我正在尝试编写一个加载.obj文件的程序。出于某种原因,我的模型只会用错误计算的法向量点亮。我无法在网上找到解释这种异常现象的任何内容。
这就是我计算法线的方法,我认为这是正确的方法。
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
天使数据集由联合国提供。伯克利计算机动画与建模组。
(不会让我发布图片,因为&lt; 10声誉)
如果我切换其中一个向量的方向,例如:
/* Calculate 1st Vector */
va[0] = x - v2.getX();
va[1] = y - v2.getY();
va[2] = z - v2.getZ();
然后它呈现正确:
但它不应该,因为顶点的方向是逆时针的。因此,通过右手规则,第一次计算应产生正确的,面向外的法向量。
我试图扭转绕组,
glFrontFace(GL_CW);
我已经对我的代码进行了单元测试,以确保从文件中按逆时针顺序读取顶点,我对照明设置进行了无数次修改无济于事。
任何人都可以解释为什么会这样吗?我遗漏的顶点计算中是否有错误?或者关于可能出现什么问题的任何其他想法?
答案 0 :(得分:2)
问题在于你如何计算a和b向量。看一下显示右手规则的图像:
矢量a和b都来自同一个点并指向不同的方向。矢量b不是从矢量a的尖端开始的。
然而在你的代码中,好像中指的基部(矢量b)从食指的尖端(矢量a)开始,因为你绕着三角形而不是选择从它发出的两个矢量顶点。这相当于使用向量a的尖端作为您的公共顶点,但使用向量指向错误的方式
将图像上的三角形覆盖在顺时针编号的顶点上:
(你可以用3种不同的方式对顶点进行编号,但我选择的编号与代码的工作版本相匹配。)
要获得从顶点2到顶点1的向量a,从顶点1减去顶点2:
/* Calculate 1st Vector */
va[0] = x - v2.getX();
va[1] = y - v2.getY();
va[2] = z - v2.getZ();
要获得从顶点2到顶点3的向量b,从顶点3中减去顶点2:
/* Calculate 2nd Vector */
vb[0] = v3.getX() - v2.getX();
vb[1] = v3.getY() - v2.getY();
vb[2] = v3.getZ() - v2.getZ();