如何计算网格上的顶点法线 [英] How to calculate the normal of vertices on a mesh
本文介绍了如何计算网格上的顶点法线的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我的.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: Theacos
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, checkerrno
, or enable floating point exceptions.
这篇关于如何计算网格上的顶点法线的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文