如何在非托管的DirectX中将纹理映射到圆柱体?

3
在C#.net中,我有一个动态直径和长度的网格圆柱,并尝试将纹理映射到它上面。我已经花了大部分时间试图找出如何做到这一点,但在Google上没有找到任何信息。
圆柱体的纹理具有jpg文件的顶部区域和侧面的其余部分。 我需要将jpg图像边缘沿着圆柱体的顶部边缘定位。例如,使用一张图片,在顶部放置红色,在侧面放置绿色。
有人能帮我将VertexBuffer点映射到纹理吗?
C#.Net 2008 DirectX 9(非托管) 我已经发布了我的解决方案

只需计算纹理坐标。这看起来很简单。你遇到了什么确切的问题?你能发布一些失败的结果吗? - Stephen Chung
我现在已经弄清楚了。问题在于我不擅长数学,并且使用DirectX自动生成网格,因此我不知道网格是如何创建或布局的 ;) 我已经在答案中发布了我的新工作代码。 - Craig White
这就对了!如果你想从事图形编程,你真的需要提高数学水平——这是绕不过去的问题。 - Stephen Chung
2个回答

1

好的,我终于搞清楚了。我之前有一些代码是有效的,但不完全是我想要的,来自http://channel9.msdn.com/coding4fun/articles/Ask-the-ZMan-Applying-Textures-Part-3

无论如何,我刚刚对它进行了一些修改。

供参考,也为那些通过谷歌到达此处的人提供帮助。

public static float ComputeBoundingSphere(Mesh mesh, out Microsoft.DirectX.Vector3 center)
    {
        // Lock the vertex buffer
        Microsoft.DirectX.GraphicsStream data = null;
        try
        {
            data = mesh.LockVertexBuffer(LockFlags.ReadOnly);
            // Now compute the bounding sphere
            return Geometry.ComputeBoundingSphere(data, mesh.NumberVertices, 
                mesh.VertexFormat, out center);
        }
        finally
        {
            // Make sure to unlock the vertex buffer
            if (data != null)
                mesh.UnlockVertexBuffer();
        }
    }

    private static Mesh SetSphericalTexture(Mesh mesh)
    {
        Microsoft.DirectX.Vector3 vertexRay;
        Microsoft.DirectX.Vector3 meshCenter;
        double phi;
        float u;


        Microsoft.DirectX.Vector3 north = new Microsoft.DirectX.Vector3(0f, 0f, 1f);
        Microsoft.DirectX.Vector3 equator = new Microsoft.DirectX.Vector3(0f, 1f, 0f);
        Microsoft.DirectX.Vector3 northEquatorCross = Microsoft.DirectX.Vector3.Cross(north, equator);

        ComputeBoundingSphere(mesh, out meshCenter);

        using (VertexBuffer vb = mesh.VertexBuffer)
        {
            CustomVertex.PositionNormalTextured[] verts = (CustomVertex.PositionNormalTextured[])vb.Lock(0, typeof(CustomVertex.PositionNormalTextured), LockFlags.None, mesh.NumberVertices);
            try
            {
                for (int i = 0; i < verts.Length; i++)
                {
                    //For each vertex take a ray from the centre of the mesh to the vertex and normalize so the dot products work.
                    vertexRay = Microsoft.DirectX.Vector3.Normalize(verts[i].Position - meshCenter);

                    phi = Math.Acos((double)vertexRay.Z);
                    if (vertexRay.Z > -0.9)
                    {
                        verts[i].Tv = 0.121f; //percentage of the image being the top side
                    }
                    else
                        verts[i].Tv = (float)(phi / Math.PI);

                    if (vertexRay.Z == 1.0f || vertexRay.Z == -1.0f)
                    {
                        verts[i].Tu = 0.5f;
                    }
                    else
                    {
                        u = (float)(Math.Acos(Math.Max(Math.Min((double)vertexRay.Y / Math.Sin(phi), 1.0), -1.0)) / (2.0 * Math.PI));
                        //Since the cross product is just giving us (1,0,0) i.e. the xaxis 
                        //and the dot product was giving us a +ve or -ve angle, we can just compare the x value with 0
                        verts[i].Tu = (vertexRay.X > 0f) ? u : 1 - u;
                    }
                }
            }
            finally
            {
                vb.Unlock();
            }
        }
        return mesh;
    }

1

尽管这个教程是用VB编写的,但它清楚地解释了这个过程。

计算纹理坐标可能需要相当多的工作;这就是为什么通常由3D建模软件来完成,这样你就可以轻松地、更重要的是,直观地调整映射。

如果您有任何问题,请告诉我。

编辑

要将纹理坐标添加到DirectX生成的圆柱体中,请参见此处


顺便问一下,您所说的非托管DirectX是什么意思?您是创建了自己的包装器还是使用了像SlimDX这样的库? - Emond
哦,这个教程是关于将纹理附加到一个空心圆柱体上的。我的圆柱体有顶部和底部。我正在使用 Microsoft.DirectX.Direct3D.Mesh.Cylinder 来创建它。 Unmanaged 是指我们正在使用原始的 DirectX 库,而不是 .Net 托管版本。 - Craig White
我添加了另一个链接,可能会帮助你使用Microsoft.DirectX.Direct3D.Mesh.Cylinder。那么你是如何包装未托管的库的?使用PInvoke吗? - Emond
嗯,“辐射”是什么意思? - Emond
所有的图像都被扭曲成指向圆柱侧面的位置。我需要将其显示为在学校制作纸圆柱时的样子,即将矩形弯成圆柱形,并在顶部和底部留有一个翻盖。 - Craig White
显示剩余5条评论

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