我使用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投影)不匹配。
图片中的红点是球体的极点当前与纹理匹配的位置。
有人可以告诉我我可以做些什么来解决这个问题吗?
答案 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计算。
希望有所帮助。