码迷,mamicode.com
首页 > 其他好文 > 详细

3D打印技术之切片引擎(3)

时间:2015-03-02 22:29:25      阅读:313      评论:0      收藏:0      [点我收藏+]

标签:3d打印   切片引擎   图形学   

【此系列文章基于熔融沉积( fused depostion modeling, FDM )成形工艺

从这一篇文章开始,我讲一下实体切片方面的一些技术。

切片引擎,实体部分大致包括:

提取边界矢量——>添加多边——>生成填充矢量集合。

其中最难的是生成填充矢量集合,也是整个切片引擎技术的核心,因为衡量一款引擎的好坏的四个核心要素——稳固性;与原始模型的相似度;用了多少材料;打印快慢,都是主要取决于填充矢量的生成技术。目前生成填充矢量的算法还有很多未知的问题有待攻克,对于这一块技术我将在最后与大家讨论,在这一篇文章里,我主要的说一下提取边界矢量的技术。

提取边界矢量,就是在对模型分层的时候,获得模型与某一层(z平面)相交的矢量集合,并且以特定顺序(一般规定顺着Z轴负方向看为正向)首尾相接。

其中难点主要是要所有的层都以特定顺序首尾相接,看下图:

技术分享

这是某一模型在skeinforge下生成的某一层的矢量集合。看它的边界矢量,就是如上所述,按照某一特定顺序,首尾相接。

这里求三角面片和z平面的交线这是高中解析几何的东西,而首尾相接只需略懂数据结构就非常容易做到的。在这里就不赘述了。

我就只说如何让所有的交线按照某一特定方向来生成边界矢量

算法步骤如下:

第一步,求出来的三角面片和z平面交线段的两个端点:beginPoint和endPoint,把它假设成为我们想要的符合特定顺序的矢量:phasor。开始节点:beginPoint,结束节点:endPoint。

第二步,就是判断该矢量是否符合我们的要求的,如果不符合就对它做反转。

步骤如下:

1,做beginPoint和endPoint的差vectorDiff。

2,对vectorDiff和该三角面片的法向量normal做叉积cross。

3,beginPoint和cross相加得到vectorAdd。

4,做三个向量(1,1,z),(1,0,z),(0,1,z).这三个向量的第三个元素都是z,要保证线性无关(三个线性无关的向量确定一个平面)。

5,对这三个向量以及vectorAdd做四点行列式,如果行列式的值小于0,反转,否则不反转。

可能对于初学者,四点行列式有些难以理解,对此,请参看我的另一篇博文: Devillers & Guigue算法

为什么要这样做,有一点点算法功底的同学容易理解,这样做的目的主要是充分利用法向量来判断二维矢量的合理方向,因为对传统的多边形面片离散化的3D模型,法向量唯一标识3D模型面的方向,要使得提取的边界矢量方向规范就必须充分利用法向量信息。

至于我所做的三个向量,是为了标定z平面,只需找到这个平面三个不相关的向量就可以了。

讲这么多,上述算法应该就不难理解了。

下面呈上该算法的代码。

//矢量
struct Phasor
{
	float3 beginPoint,endPoint;

	int status;
	
	int material;

	int tri_index;

	void reversal()
	{
		float3 temp;

		memcpy(temp,beginPoint,sizeof(float)*3);

		memcpy(beginPoint,endPoint,sizeof(float)*3);

		memcpy(endPoint,temp,sizeof(float)*3);
	}

	void copy(Phasor *p)
	{
		memcpy(beginPoint,p->beginPoint,sizeof(float)*3);

		memcpy(endPoint,p->endPoint,sizeof(float)*3);

		status=p->status;

		material=p->material;

		tri_index=p->tri_index;
	}
};

void get_vector_diff( float3& aimV, const float3 a, const float3 b )
{
    aimV[0] = b[0] - a[0];
	
    aimV[1] = b[1] - a[1];
	
    aimV[2] = b[2] - a[2];
}

void cross_product(float3 &result,float3 a, float3 b)
{
	result[0] = a[1]*b[2] - a[2]*b[1];
	result[1] = a[2]*b[0] - a[0]*b[2];
	result[2] = a[0]*b[1] - a[1]*b[0];
}


void get_vector_sum( float3& aimV, const float3 a, const float3 b )
{
    aimV[0] = a[0] + b[0];
	
    aimV[1] = a[1] + b[1];
	
    aimV[2] = a[2] + b[2];
}

//获得四点的行列式
float get_vector4_det( float3 v1, float3 v2, float3 v3, float3 v4 )
{
	
    float a[3][3];
    for ( int i = 0; i != 3; ++i )
    {
        a[0][i] = v1[i] - v4[i];
        a[1][i] = v2[i] - v4[i];
        a[2][i] = v3[i] - v4[i];
    }
	
    return a[0][0] * a[1][1] * a[2][2] + 
		a[0][1] * a[1][2] * a[2][0] + 
		a[0][2] * a[1][0] * a[2][1] - 
		a[0][2] * a[1][1] * a[2][0] - 
		a[0][1] * a[1][0] * a[2][2] - 
		a[0][0] * a[1][2] * a[2][1];
}




/// <summary>   
/// 如果边界矢量不符合要求,改变矢量方向
/// </summary>     
/// <param name="phasor">矢量</param> 
/// <param name="normal">法向</param>
/// <param name="z">z坐标</param>
void STLDelamination::rectifyDirection(Phasor *phasor,float3 normal,float z)
{
	float3 cross;

	float3 vectorDiff;

	float3 vectorAdd;

	float3 a,b,c,temp;

	a[0]=1;
	a[1]=1;
	a[2]=z;

	b[0]=1;
	b[1]=0;
	b[2]=z;

	c[0]=0;
	c[1]=1;
	c[2]=z;

	get_vector_diff(vectorDiff,phasor->beginPoint,phasor->endPoint);

	cross_product(cross,normal,vectorDiff);

	get_vector_sum(vectorAdd,phasor->beginPoint,cross);


	if(get_vector4_det(a, b, c, vectorAdd )<0)
	{
		memcpy(temp,phasor->beginPoint,sizeof(float)*3);
		
		memcpy(phasor->beginPoint,phasor->endPoint,sizeof(float)*3);
		
		memcpy(phasor->endPoint,temp,sizeof(float)*3);
	}
}






3D打印技术之切片引擎(3)

标签:3d打印   切片引擎   图形学   

原文地址:http://blog.csdn.net/fourierfeng/article/details/44004459

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!