球体纹理和杆

时间:2014-03-04 16:06:51

标签: c# geometry directx mdx texture-mapping

我使用Managed DirectX和C#来构造一个球体(Mesh.Sphere)。

我使用以下代码计算U和V:

CustomVertex.PositionNormalTextured[] vertData = (CustomVertex.PositionNormalTextured[])tempMesh.VertexBuffer.Lock(0, typeof(CustomVertex.PositionNormalTextured), LockFlags.None, tempMesh.NumberVertices);

for (int i = 0; i < vertData.Length; ++i)
{
    vertData[i].Tu = (float)(1.0 - (double)(0.5f + Math.Atan2(vertData[i].Nz, vertData[i].Nx) / (Math.PI * 2)));
    vertData[i].Tv = (float)(0.5 - Math.Asin(vertData[i].Ny) / Math.PI);
}

现在我遇到了问题,球体的极点和纹理的极点(equirectangular投影)不匹配。Red points present the poles in my program

图片中的红点是球体的极点当前与纹理匹配的位置。

有人可以告诉我我可以做些什么来解决这个问题吗?

1 个答案:

答案 0 :(得分:1)

如果球体在原点居中并且y向上,则上面的代码可以正常工作。我将证明:

在假设极点存在于0,1,0和0,-1,0的情况下应用数学,给出以下极数。

 u = 1.0 - (0.5 + (atan2( 0, 0 ) / (2 * PI));
 => u = 1.0 - (0.5 + (0 / (2 * PI));
 => u = 1.0 - 0.5;
 => u = 0.5
 v = 0.5 - (asin( 1 ) / PI)
 => v = 0

 u = 0.5
 v = 0.5 - (asin( -1 ) / PI)
 => v = 0.5 - -0.5
 => v = 1.0

对于u和v,哪个是正确的值,即(0.5,0)和(0.5,1)。

如果您正在使用z-up,那么这将给出不正确的值(因为您需要在计算中交换y和z),但它仍然没有给出您建议的极点值:

 u = 1.0 - (0.5 + (atan2( 1, 0 ) / (2 * PI));
 => u = 1.0 - (0.5 + (PI / (2 * PI)))
 => u = 1.0 - (0.5 + 0.5);
 => u = 0
 v = 0.5 - (asin( 0 ) / PI)
 => v = 0.5 - (0 / PI)
 => v = 0.5

 u = 1.0 - (0.5 + (atan2( -1, 0 ) / (2 * PI));
 => u = 1.0 - (0.5 + (-PI / (2 * PI)))
 => u = 1.0 - (0.5 - 0.5);
 => u = 1.0
 v = 0.5 - (asin( 0 ) / PI)
 => v = 0.5 - (0 / PI)
 => v = 0.5

这样做的原因是相当明智的。在u方向上,球体完全包裹着圆形。即u的0与u的1相同。这完全发生在你发布的等式中的x-z平面上(y不考虑u)。这就是为什么它除以2 * pi或整圆的弧度数。 v方向不会缠绕。实际上它只适用于范围的一半,因此也适用于分割pi。您会注意到在计算中只使用y,因此x和z不会影响v计算。

希望有所帮助。