诊断背面剔除问题

时间:2011-10-18 04:56:52

标签: c# graphics xna 3d

设置:我正在使用立方体贴图投影来创建一个块状的行星。立方体贴图投影非常简单:将矢量从立方体的中心移动到该立方体上的任何点,对其进行标准化,然后将其乘以球体的半径,并获得坐标的新位置。以下是2D中的快速说明:

diagram of cubemap projection

[link]

现在,正如我所说,我创造了这个,所以它是由块组成的。所以在实践中,我将我的立方体划分为相等的方形细分(如rubik的立方体)。我使用自定义坐标:( Face,X,Y,Shell)。面指的是点所在的立方体上的哪个面。 X和Y指的是它在脸上的位置。壳牌指的是它的“高度”。在实践中,这转化为我投射点的球体的半径。如果我没有很好地解释它,希望图像会有所帮助:

image of a rendered planet

[link]

- 这是一个用完全随机的高度图生成的行星,关闭了背面剔除。无论如何,既然你已经了解我正在使用的东西 -

我的问题是我无法以可预测的方式进行背面剔除。我目前的系统工作原理如下:

  • 计算块的中心
  • 通过取三角形两边的叉积来获得块的每个三角形顶点的法线
  • 从三角形的中心(三角形顶点的平均值)获取矢量到块的中心,将其标准化。
  • 取三角形法线和法线中心的点积
  • 如果点积为> = 0,则翻转三角形的第一个和最后一个索引

这是代码中的内容:

public bool CheckIndices(Quad q, Vector3 centerOfBlock)
    {
        Vector3[] vertices = new Vector3[3];
        for (int v = 0; v < 3; v++)
            vertices[v] = q.Corners[indices[v]].Position;

        Vector3 center = (vertices[0] + vertices[1] + vertices[2]) / 3f;
        Vector3 normal = Vector3.Cross(vertices[1] - vertices[0], vertices[2] - vertices[0]);
        Vector3 position = center - centerOfBlock;

        position.Normalize();
        normal.Normalize();
        float dotProduct = Vector3.Dot(position, normal);

        if (dotProduct >= 0)
        {
            int swap = indices[0];
            indices[0] = indices[2];
            indices[2] = swap;
            return false;
        }
        return true;
    }

我使用Quad类来保存三角形和其他一些数据。三角形存储int [3],用于索引,这些索引对应于存储在Quad中的顶点。

但是,当我使用此方法时,至少有一半的面部绘制方向错误。我注意到问题中存在两种模式:

  • 从行星中心向外指向的面孔始终是正确的
  • 指向行星中心的面部始终不正确

这让我相信我计算出的区块中心是不正确的,实际上位于区块和行星中心之间。但是,改变我对块中心的计算是无效的。

我使用了两种不同的方法来计算块的中心。第一个是从块的位置找到一个坐标的投影位置,该坐标具有+ 0.5 X,+ 5 Y和+5 Shell(Z)。因为我使用左下角的角来定义块位置,所以这个新坐标自然会位于块的中心。我使用的另一种方法是计算块的每个角的实际位置,然后平均这些向量。这种方法对我来说似乎非常简单,但它没有成功。

由于这个原因,我开始怀疑上面粘贴的代码,它确定是否必须翻转三角形。我不记得某些逻辑背后的所有推理,特别是在&gt; = 0语句之后。我只需要另一双眼睛:这里有什么问题吗?

1 个答案:

答案 0 :(得分:0)

问题在于,当我得到立方体上任意点的位置时,我的立方体贴图投影过于笼统。将GetCorrectedCubePosition方法here与同一方法here进行比较,以查看所做的改进。我在帖子中提到的顺时针索引顺序检查的方法在效果上应该是未知的,因为我将不再使用它们。使用正确的投影意味着我可以在生成方法本身中将我的顶点硬定义为顺时针方向,而不必猜测。