DirectX 重新计算内部/外部实现

问题描述

对于我的游戏,我添加了“画笔”,它是用于创建关卡几何体的 3D 盒子。我想添加将画笔从里到外翻转的功能,让外部变成内部等等。我很确定我知道如何做到这一点,但我想确保这实际上是标准做法。首先,这是我在引擎中的 BrushVolume 的图片

enter image description here

我通过以下代码生成这个 BrushVolume:

public void Rebuild()
        {
            /**
             * No faces are present; empty the StaticBrushVolume
             */
            if (this.FaceVisibility == BrushVolumeFaceVisibility.None)
            {
                if (_bufferBinding.Buffer != null)
                {
                    _bufferBinding.Buffer.dispose();
                }
                this.FaceCount = 0;
                _drawCount = 0;
                return;
            }
            this.FaceCount = CountVisibleFaces(this.FaceVisibility);
            Vertex[] vertices = new Vertex[this.FaceCount * 6];
            float width = this.Width;
            float height = this.Height;
            float depth = this.Depth;
            float uvX = width / (float)this.DiffuseMaterial.Width;
            float uvY = height / (float)this.DiffuseMaterial.Height;
            float uvZ = depth / (float)this.DiffuseMaterial.Width;
            // Generate Front Face
            int index = 0;
            if (this.FaceVisibility.HasFlag(BrushVolumeFaceVisibility.Front))
            {
                Vector3 normal = new Vector3(0,-1);
                vertices[index++] = new Vertex(new Vector3(-width,height,-depth),new Vector2(uvX,0),normal);
                vertices[index++] = new Vertex(new Vector3(width,new Vector2(0,-height,uvY),normal);
                vertices[index++] = new Vertex(new Vector3(-width,normal);
            }
            // Generate East Face
            if (this.FaceVisibility.HasFlag(BrushVolumeFaceVisibility.Left))
            {
                Vector3 normal = new Vector3(1,0);
                vertices[index++] = new Vertex(new Vector3(width,depth),new Vector2(uvZ,normal);

                vertices[index++] = new Vertex(new Vector3(width,normal);
            }
            // Generate South Face
            if (this.FaceVisibility.HasFlag(BrushVolumeFaceVisibility.Back))
            {
                Vector3 normal = new Vector3(0,1);
                vertices[index++] = new Vertex(new Vector3(width,normal);
            }
            // Generate West Face
            if (this.FaceVisibility.HasFlag(BrushVolumeFaceVisibility.Right))
            {
                Vector3 normal = new Vector3(-1,0);

                // Clockwise

                vertices[index++] = new Vertex(new Vector3(-width,normal);

                vertices[index++] = new Vertex(new Vector3(-width,normal);

                // Counter Clockwise

                //vertices[index++] = new Vertex(new Vector3(-width,normal);
                //vertices[index++] = new Vertex(new Vector3(-width,normal);

                //vertices[index++] = new Vertex(new Vector3(-width,normal);
            }
            // Generate Top Face
            if (this.FaceVisibility.HasFlag(BrushVolumeFaceVisibility.Top))
            {
                Vector3 normal = new Vector3(0,1,uvZ),normal);
            }
            // Generate Bottom Face
            if (this.FaceVisibility.HasFlag(BrushVolumeFaceVisibility.Bottom))
            {
                Vector3 normal = new Vector3(0,-1,0);
                vertices[index++] = new Vertex(new Vector3(-width,normal);
            }
            if (this._bufferBinding.Buffer != null)
            {
                this._bufferBinding.Buffer.dispose();
            }
            this._drawCount = vertices.Length;
            Buffer vertexBuffer = Buffer.Create(Device,BindFlags.VertexBuffer,vertices);
            this._bufferBinding = new VertexBufferBinding(vertexBuffer,32,0); // 32 is Vertex Size In Bytes
        }

我在那里留下了一张便条,显示了我目前对如何将一张脸从内部翻转到外部的想法。很简单,我想只是反转缠绕顺序。我的引擎认使用顺时针缠绕,所以如果我将每个面的缠绕反转为逆时针,它会在发动机中显示为内部。这也有效。然而,这可能是一个愚蠢的问题。但这是标准吗?我尝试谷歌搜索 Blender 如何实现“重新计算内部”,但我在网上找不到任何讨论实际实现细节的内容

有谁知道从外到内翻转面的标准做法是否像反转缠绕顺序一样简单?

解决方法

我相当肯定,反转缠绕顺序是实现这一目标的方式。我还必须反转纹理坐标和法线,以便正确显示纹理。这是一个 gif,显示了我的实施结果:

enter image description here

在那个 gif 中,我只是按一个键来循环切换笔刷体积的“船体模式”。

此示例的源位于 on my pastebin

这是我如何从外部反转到内部等的简短示例。

if (this.FaceVisibility.HasFlag(BrushVolumeFaceVisibility.Front))
            {
                if (this.HullMode == BrushVolumeHullMode.Interior)
                {
                    Vector3 normal = new Vector3(0,1);
                    vertices[index++] = new Vertex(new Vector3(-width,height,-depth),new Vector2(0,0),normal);
                    vertices[index++] = new Vertex(new Vector3(width,new Vector2(uvX,-height,uvY),normal);
                    vertices[index++] = new Vertex(new Vector3(-width,normal);
                }
                else
                {
                    Vector3 normal = new Vector3(0,-1);
                    vertices[index++] = new Vertex(new Vector3(width,normal);
                }
            }

应该注意的是,我的实现一点也不优雅,因为我将翻转状态硬编码到 if 分支中,具体取决于外壳模式。像 Blender 这样的软件可能有一种更奢侈的方式来做到这一点,因为它们必须迭代更大(和动态)的三角形集。可能有一种奇特的算法来反转缠绕顺序和纹理坐标。但是,我不知道它可能是什么,因为网上没有相关资料。

如果有人知道更好的方法,我真的很想看看。