我正在尝试编写一个加载 .obj 文件的程序。出于某种原因,我的模型只在计算错误的法 vector 时亮起。我无法在网上找到任何解释此异常的信息。
这就是我计算法线的方式,我认为这是正确的方式。
vector<float> Vertex::findNormal(Vertex v2, Vertex v3)
{
float va[3], vb[3], vr[3], val;
/* Calculate 1st Vector */
va[0] = v2.getX() - x;
va[1] = v2.getY() - y;
va[2] = v2.getZ() - z;
/* Calculate 2nd Vector */
vb[0] = v3.getX() - v2.getX();
vb[1] = v3.getY() - v2.getY();
vb[2] = v3.getZ() - v2.getZ();
/* Cross Product */
vr[0] = va[1] * vb[2] - vb[1] * va[2];
vr[1] = vb[0] * va[2] - va[0] * vb[2];
vr[2] = va[0] * vb[1] - vb[0] * va[1];
/* Normalization Factor */
val = sqrt(vr[0]*vr[0] + vr[1]*vr[1] + vr[2]*vr[2]);
normal.push_back(vr[0]/val);
normal.push_back(vr[1]/val);
normal.push_back(vr[2]/val);
return normal;
}
但这是结果: Correct Normals
Angel 数据集由 U.C. 提供伯克利计算机动画和建模小组。
(不允许我发布图片,因为 <10 声望)
如果我切换其中一个 vector 的方向,例如:
/* Calculate 1st Vector */
va[0] = x - v2.getX();
va[1] = y - v2.getY();
va[2] = z - v2.getZ();
然后它正确呈现:
但它不应该,因为顶点的方向是逆时针的。所以根据右手法则,第一次计算应该产生正确的、向外的法 vector 。
我试过通过,反转绕组,
glFrontFace(GL_CW);
我对我的代码进行了单元测试,以确保从文件中按逆时针顺序读取顶点,我对照明设置进行了无数次修改,但都无济于事。
谁能解释为什么会这样?我的顶点计算中是否存在我遗漏的错误?或者关于可能出错的任何其他想法?
最佳答案
问题在于您如何计算 a 和 b vector 。看看这张显示右手定则的图片:
vector a 和 b 都起源于同一点并指向不同的方向。 vector b不是从 vector a的尖端开始的。
但是在您的代码中,就好像中指的根部( vector b)从食指的指尖( vector a)开始,因为您要绕三角形而不是选择从同一三角形发出的两个 vector 顶点。这相当于使用 vector a 的尖端作为公共(public)顶点,但是 vector a 指向错误的方向
用顺时针编号的顶点画一个覆盖在图像上的三角形:
(您可以用 3 种不同的方式对顶点进行编号,但我选择了与您的代码的工作版本相匹配的编号。)
要获得从顶点 2 到顶点 1 的 vector a,从顶点 1 减去顶点 2:
/* Calculate 1st Vector */
va[0] = x - v2.getX();
va[1] = y - v2.getY();
va[2] = z - v2.getZ();
要获得从顶点 2 到顶点 3 的 vector b,从顶点 3 减去顶点 2:
/* Calculate 2nd Vector */
vb[0] = v3.getX() - v2.getX();
vb[1] = v3.getY() - v2.getY();
vb[2] = v3.getZ() - v2.getZ();
关于c++ - OpenGL .obj 加载程序 : Model only lit correctly with incorrect normal vectors?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31397662/