Polygon 3D(三维平面多边形)的法向量的计算(MeshLab默认的计算)

目的:网格法向量的计算

最近发现一个非常有意思的东西,网上的资料较少,所以记下来供大家查阅,
就是在网格化三维polygon 3d的时候,对于polygon 3d的法向量和网格化为三角形的时候。生成obj文件的时候三角面片的方向只和三角形的顶点顺序有关。如果三角面片上进行顶点的normal设置,可能毫无效果。在meshlab中只和顶点的顺序有关。polygon 3d的法向量和三角面片的法向量一致。

三角面片的法向量:
测试它是左手坐标系还是右手坐标系生成的法向量?从顶点的顺序(也是半面结构)来看它是左手坐标系生成的法向量。

为了测试我们要了解向量叉乘的几何意义,如果左乘的话,它是右手坐标系下做的(可以这样规定)。它的几何意义如下:
在这里插入图片描述
可以看出来,在 a × b a × b a×b 是左乘的角度可以看出来,右手坐标系,从 a a a b b b的方向。
对于三角形的面片的方向,可能不一样。它规定了一个顺序。如果 p 0 , p 1 , p 2 p0, p1, p2 p0,p1,p2三个顶点的顺序,然后我们需要计算它是哪个方向为主。需要看一下方向。在测试的途中,
v 0.0 0.0 0.0
v 0.0 1.0 0.0
v 1.0 0.0 0.0
f 3 2 1
从这个可以看到,
p 0 = ( 1 , 0 , 0 ) ; p 1 = ( 0 , 1 , 0 ) ; p 3 = ( 0 , 0 , 0 ) p0=(1,0,0); p1=(0,1,0); p3=(0,0,0) p0=(1,0,0);p1=(0,1,0);p3=(0,0,0),它的顺序,
在这里插入图片描述
可以得到normal =(0,0,1),
如果从顶点的顺序来看的话。
在这里插入图片描述
它是典型的左手坐标系。如果用数学中的向量来算的话,可能需要改变一下思路,需要计算两个向量的叉乘。会得到 a = ( p 1 − p 0 ) ; b = ( p 2 − p 0 ) a=(p1 - p0); b = (p2-p0) a=(p1p0);b=(p2p0),然后叉乘 a × b a × b a×b可以得到。就是那种从它其实和逻辑是自洽的,因为我们如果用 ( p 1 − p 0 ) × ( p 2 − p 1 ) (p1-p0)×(p2-p1) (p1p0)×(p2p1)这个不是三角形的夹角,而是180-夹角,。所以叉乘可能需要变化一下,对夹角的计算。代码如下:

Eigen::Vector3f GetNormalFrom3Points(Eigen::Vector3f& a, Eigen::Vector3f& b, Eigen::Vector3f& c)
	{
    
    
		Eigen::Vector3f e1 = b - a;
		Eigen::Vector3f e2 = c - a;
		
		Eigen::Vector3f e1_(e1.x, e1.y, e1.z), e2_(e2.x, e2.y, e2.z);
		Eigen::Vector3f normal = e1.cross(e2);
		if (normal.norm() < 0.0001) {
    
    	//如果太小了,可以返回(0,0,0)
#ifdef LIULINGFEI
			printf("result = %f, %f, %f\n", 0, 0, 0);
#endif
			return Eigen::Vector3f(0, 0, 0);
		}
		else {
    
    
			Eigen::Vector3f temp = normal.normalized();
#ifdef LIULINGFEI
			printf("result = %f, %f, %f\n", temp(0), temp(1), temp(2));
#endif
			return normal.normalized();
		}
	}

网上可能对于三角面片的法向量有一些资料,但是对于polygon 面片的法向量可能需要一些,可能不一样。它需要对每一个顶点计算法向量(邻近的顶点构成三角形,然后计算这个三角形的法向量然后计算这个顶点的反向量),然后区平均值。但是也可以计算polygon的法向量了。代码如下:

Eigen::Vector3f GetPolygonNormalFrom3Points(std::vector<Eigen::Vector3f>& poly_pnts)
{
    
    
	Eigen::Vector3f sum(0,0,0);
	for(int i = 0; i < poly_pnts.size(); ++i)
	{
    
    
		Eigen::Vector3f pre_pnt = poly_pnts[(i-1)%poly_pnts.size()];
		Eigen::Vector3f pnt = poly_pnts[(i)%poly_pnts.size()];
		Eigen::Vector3f next_pnt = poly_pnts[(i+1)%poly_pnts.size()];
		Eigen::Vector3f tmp_normal = GetNormalFrom3Points(pre_pnt, pnt, next_pnt);
		//对于其中的tmp_normal 不一样,可能不同的权重,但是我都归一化了,得到相应的法向量。
		sum += tmp_normal;
	}
	if(poly_pnts.empty())
	{
    
    
		return sum;
	}
	else
	{
    
    
		return sum.normal();
	}
}

感悟:测试这个polygon的法向量得到。

猜你喜欢

转载自blog.csdn.net/weixin_43851636/article/details/122132622