如何计算网格上的顶点法线 [英] How to calculate the normal of vertices on a mesh

查看:160
本文介绍了如何计算网格上的顶点法线的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的.obj文件不包含vn(顶点的法线),所以我尝试自己计算它们。我的代码是:

My .obj file do not contain vn(normal of vertices), so I try to calculate them myself. My here was my code:

using namespace cv;
typedef struct vet_data 
{
	Vec3f vn;
	double total_angle;

} vet_data;
long v_num = mesh.vertices.size();
vet_data v_data[v_num];

for(int i = 0; i < v_num; ++i) {
	v_data[i].vn = Vec3f(0,0,0);
	v_data[i].total_angle = 0;
}
std::ofstream test_out("/home/sar/Desktop/test_out.txt");
for(auto&& v : mesh.tvi) {           //traverse all the triangles 
//here v is a triangle that contains 3 points
//so v[0], v[1], v[2] are the index of points of the triangle
	Vec3f v0 = Vec3f(mesh.vertices[v[0]][0], mesh.vertices[v[0]][1], mesh.vertices[v[0]][2]),
		  v1 = Vec3f(mesh.vertices[v[1]][0], mesh.vertices[v[1]][1], mesh.vertices[v[1]][2]),
		  v2 = Vec3f(mesh.vertices[v[2]][0], mesh.vertices[v[2]][1], mesh.vertices[v[2]][2]);

	Vec3f e1 = v1 - v0;
	Vec3f e2 = v2 - v1;
	Vec3f vn = normalize(e1.cross(e2));

	double angle[3] = { 0.0, 0.0, 0.0 };
	double t1, t2, t3;
	t1 = (v1 - v0).dot(v2 - v0) * CV_PI / 180.0;
	t2 = (v0 - v1).dot(v2 - v1) * CV_PI / 180.0;
	t3 = (v0 - v2).dot(v1 - v2) * CV_PI / 180.0;
	angle[0] = acos(t1);
	angle[1] = acos(t2);
	angle[2] = acos(t3);
	for(int i = 0; i < 3; ++i) {
		v_data[v[i]].vn += vn * angle[i];
		v_data[v[i]].total_angle += angle[i];
	}
}
obj_file << "--vn--" << std::endl;
for(int i = 0; i < v_num; ++i) {
	Vec3f vn = v_data[i].vn / v_data[i].total_angle;
	obj_file << "vn" << " " << vn[0] << " " << vn[1] << " " << vn[2] << std::endl;
}







然而,有些vns是:vn nan nan nan

我无法弄明白为什么。



我尝试过的事情:



我尝试写入文件以找出问题所在。但我还是不知道。

而且,即使我在.obj文件中写错了vns,它仍然可以显示。为什么?

如果有人能给我一些提示,我将不胜感激。




However, some vns are :vn nan nan nan
I can not figure out why.

What I have tried:

and I tried to wrote into a file to figure out what was wrong. But I still do not know.
And, even I wrote wrong vns in my .obj file, it can still display. Why?
I would appreciate if anyone can give some hints to me.

推荐答案

如前所述,这需要调试你的代码。您也可以通过使用 isnan 检查中间值来使用穷人的调试[ ^ ]。因此,您可以检测到NAN的分配位置。



但是有一个候选者可以生成NAN: acos 函数。通过舍入错误可能会使参数略高于1。然后返回NAN,这将影响所有后续计算。



要检查和/或处理此问题,您可以插入代码将参数限制为1,检查 errno ,或启用浮点异常。
As already mentioned this requires debugging your code. You might also use poor man's debugging by checking intermediate values with isnan[^]. So you can detect where NANs are assigned.

But there is a candidate for generating NANs: The acos function. It might happen that the argument is slightly above 1 by rounding errors. Then a NAN is returned which affects all following calculations.

To check and/or handle this you might insert code to limit the argument to 1, check errno, or enable floating point exceptions.


这篇关于如何计算网格上的顶点法线的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆