XNA顶点法线计算无法为立方体工作

3

我有一个函数可以为大多数基本图形计算顶点法线。但是它似乎无法处理立方体。

当我尝试使用漫反射光着色器时,它给我这个结果(右侧相同)

Cube Diffuse Light Shader

这是我的计算法线的代码:

public virtual void GenerateNormals()
    {
        for (int i = 0; i < vertices.Length; i++)
            vertices[i].Normal = new Vector3(0, 0, 0);

        for (int i = 0; i < indices.Length / 3; i++)
        {
            Vector3 firstvec = vertices[indices[i * 3 + 1]].Position - vertices[indices[i * 3]].Position;
            Vector3 secondvec = vertices[indices[i * 3]].Position - vertices[indices[i * 3 + 2]].Position;
            Vector3 normal = Vector3.Cross(firstvec, secondvec);
            normal.Normalize();
            vertices[indices[i * 3]].Normal += normal;
            vertices[indices[i * 3 + 1]].Normal += normal;
            vertices[indices[i * 3 + 2]].Normal += normal;
        }

        for (int i = 0; i < vertices.Length; i++)
            if (vertices[i].Normal != Vector3.Zero) vertices[i].Normal.Normalize();
    }

魔方的顶点是这样生成的:
Vector3[] vectors = new Vector3[8];

        vectors[0] = new Vector3(-1, 1, -1);
        vectors[1] = new Vector3(1, 1, -1);
        vectors[2] = new Vector3(-1, 1, 1);
        vectors[3] = new Vector3(1, 1, 1);
        vectors[4] = new Vector3(-1, -1, -1);
        vectors[5] = new Vector3(1, -1, -1);
        vectors[6] = new Vector3(-1, -1, 1);
        vectors[7] = new Vector3(1, -1, 1);


        vertices = new VertexPositionNormalColored[24];

        //Top
        vertices[0].Position = vectors[0];
        vertices[0].Color = TopColor;
        vertices[1].Position = vectors[1];
        vertices[1].Color = TopColor;
        vertices[2].Position = vectors[2];
        vertices[2].Color = TopColor;
        vertices[3].Position = vectors[3];
        vertices[3].Color = TopColor;

        //Bottom
        vertices[4].Position = vectors[4];
        vertices[4].Color = BottomColor;
        vertices[5].Position = vectors[5];
        vertices[5].Color = BottomColor;
        vertices[6].Position = vectors[6];
        vertices[6].Color = BottomColor;
        vertices[7].Position = vectors[7];
        vertices[7].Color = BottomColor;

        //Left
        vertices[8].Position = vectors[2];
        vertices[8].Color = LeftColor;
        vertices[9].Position = vectors[0];
        vertices[9].Color = LeftColor;
        vertices[10].Position = vectors[6];
        vertices[10].Color = LeftColor;
        vertices[11].Position = vectors[4];
        vertices[11].Color = LeftColor;

        //Right
        vertices[12].Position = vectors[3];
        vertices[12].Color = RightColor;
        vertices[13].Position = vectors[1];
        vertices[13].Color = RightColor;
        vertices[14].Position = vectors[7];
        vertices[14].Color = RightColor;
        vertices[15].Position = vectors[5];
        vertices[15].Color = RightColor;

        //Back
        vertices[16].Position = vectors[0];
        vertices[16].Color = BackColor;
        vertices[17].Position = vectors[1];
        vertices[17].Color = BackColor;
        vertices[18].Position = vectors[4];
        vertices[18].Color = BackColor;
        vertices[19].Position = vectors[5];
        vertices[19].Color = BackColor;

        //Front
        vertices[20].Position = vectors[2];
        vertices[20].Color = FrontColor;
        vertices[21].Position = vectors[3];
        vertices[21].Color = FrontColor;
        vertices[22].Position = vectors[6];
        vertices[22].Color = FrontColor;
        vertices[23].Position = vectors[7];
        vertices[23].Color = FrontColor;

并且索引就像这样:

indices = new int[36];

        //Top
        indices[0] = 0;
        indices[1] = 1;
        indices[2] = 2;
        indices[3] = 2;
        indices[4] = 3;
        indices[5] = 1;

        //Back
        indices[6] = 16;
        indices[7] = 17;
        indices[8] = 18;
        indices[9] = 18;
        indices[10] = 19;
        indices[11] = 17;
        //Left
        indices[12] = 8;
        indices[13] = 9;
        indices[14] = 10;
        indices[15] = 10;
        indices[16] = 11;
        indices[17] = 9;
        //Front
        indices[18] = 20;
        indices[19] = 21;
        indices[20] = 22;
        indices[21] = 22;
        indices[22] = 23;
        indices[23] = 21;
        //Right
        indices[24] = 12;
        indices[25] = 13;
        indices[26] = 14;
        indices[27] = 14;
        indices[28] = 15;
        indices[29] = 13;
        //Bottom
        indices[30] = 4;
        indices[31] = 5;
        indices[32] = 6;
        indices[33] = 6;
        indices[34] = 7;
        indices[35] = 5;

我希望专家们能够帮助我找到解决方案。提前感谢!

2个回答

2
你得到这个结果是因为两个不同三角形的顶点顺序不同。
在一个右手坐标系中,你的第一个三角形{(-1,1,-1), (1,1,-1) , (-1,1,1)}按逆时针顺序排列,而第二个{(-1,1,1), (1,1,1) , (1,1,-1)}按顺时针顺序排列。
这些三角形的法线方向将有所不同。

我知道会是这样的。现在问题的解决方案出来了。就像不断尝试直到达到好的结果一样。我想我会通过剔除来解决它。无论如何,谢谢你的回答!现在我知道魔方是问题所在,而不是我计算法线的方式。 - Daniel Sharp

0

嗯,看起来你在计算(并求和)某些顶点的法线两次(因为你正在遍历索引数组,并且每个面重用一些顶点)。虽然法线应该是相同的,而且归一化应该会解决这个问题。我怀疑计算出的法线在第一次运行时朝一个方向,在下一次运行时朝相反方向,导致法线为(0,0,0)。

尝试跳过索引数组,直接通过顶点数组进行遍历,仅计算每个顶点的法线一次。


我使用索引数组来获得更平滑的结果。我在互联网上查过,所以那不可能是问题。 - Daniel Sharp
啊,我明白了。但在这种情况下,我认为这不会有任何影响,因为唯一共享顶点的三角形是完全平行的。 - Chris
我知道,但我不仅用这种方法来处理立方体,而且用于其他所有形状。 - Daniel Sharp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接