c++ - 在书中的示例代码 "introduction to 3d game programming with directx 11"

标签 c++ directx directx-11 direct3d direct3d11

void GeometryGenerator::Subdivide(MeshData& meshData)
{
    // Save a copy of the input geometry.
    MeshData inputCopy = meshData;


    meshData.Vertices.resize(0);
    meshData.Indices.resize(0);

    //       v1
    //       *
    //      / \
    //     /   \
    //  m0*-----*m1
    //   / \   / \
    //  /   \ /   \
    // *-----*-----*
    // v0    m2     v2

    UINT numTris = inputCopy.Indices.size()/3;
    for(UINT i = 0; i < numTris; ++i)
    {
        Vertex v0 = inputCopy.Vertices[ inputCopy.Indices[i*3+0] ];
        Vertex v1 = inputCopy.Vertices[ inputCopy.Indices[i*3+1] ];
        Vertex v2 = inputCopy.Vertices[ inputCopy.Indices[i*3+2] ];

        //
        // Generate the midpoints.
        //

        Vertex m0, m1, m2;

        // For subdivision, we just care about the position component.  We 
        // derive the other
        // vertex components in CreateGeosphere.

        m0.Position = XMFLOAT3(
            0.5f*(v0.Position.x + v1.Position.x),
            0.5f*(v0.Position.y + v1.Position.y),
            0.5f*(v0.Position.z + v1.Position.z));

        m1.Position = XMFLOAT3(
            0.5f*(v1.Position.x + v2.Position.x),
            0.5f*(v1.Position.y + v2.Position.y),
            0.5f*(v1.Position.z + v2.Position.z));

        m2.Position = XMFLOAT3(
            0.5f*(v0.Position.x + v2.Position.x),
            0.5f*(v0.Position.y + v2.Position.y),
            0.5f*(v0.Position.z + v2.Position.z));

        //
        // Add new geometry.
        //

        meshData.Vertices.push_back(v0); // 0
        meshData.Vertices.push_back(v1); // 1
        meshData.Vertices.push_back(v2); // 2
        meshData.Vertices.push_back(m0); // 3
        meshData.Vertices.push_back(m1); // 4
        meshData.Vertices.push_back(m2); // 5

        meshData.Indices.push_back(i*6+0);
        meshData.Indices.push_back(i*6+3);
        meshData.Indices.push_back(i*6+5);

        meshData.Indices.push_back(i*6+3);
        meshData.Indices.push_back(i*6+4);
        meshData.Indices.push_back(i*6+5);

        meshData.Indices.push_back(i*6+5);
        meshData.Indices.push_back(i*6+4);
        meshData.Indices.push_back(i*6+2);

        meshData.Indices.push_back(i*6+3);
        meshData.Indices.push_back(i*6+1);
        meshData.Indices.push_back(i*6+4);
    }
}

此函数位于“GeometryGenerator.cpp”文件中,用于 segmentation 网格。 在调用此函数之前,创建一个二十面体并将其作为参数 meshData 传输。 MeshData的成员Vertices和Indices是STL的 vector 。

在我看来,在这个函数调用了这一系列函数meshData.Vertices.push_back之后,在循环的下一次迭代中,一些顶点可能会被重复存储。

谁都能回答

  • 我是否错了,
  • 为什么作者要这样写代码,
  • 或者如果我的想法是正确的,是否有更有效的方法。

感谢所有阅读我拙劣英语的人。

最佳答案

whether I am wrong

我很确定您是对的,尤其是关于重复的顶点!

why the author make the codes like this

除了作者本人,没有人能回答这个问题。我会猜测他/她只是监督了重复问题...

or whether there is more efficient way if my thought is right.

只要算法不正确,我就不会关心效率!

首先,我们需要避免顶点重复。我只是将现有的顶点保留原样(因此只清除索引)并在末尾附加新的顶点。为此,我会将 edges 存储在临时 std::map 中,将一对索引(边缘)映射到新创建的索引(总是首先使用较小的索引以避免 出现问题(10,12)(12,10),它们标识相同的边...)。

然后对于 v0、v1、v2,我将使用索引,而不是顶点本身。首先在 map 中查找 m0、m1、m2,如果找到,则使用,否则创建一个新顶点,将其添加到顶点 vector 中,并在我们的 map 中添加一个条目。

UINT v0 = copiedIndices[i*3+0];
// ...

UINT m0;
auto key = std::make_pair(v0, v1); // TODO: order indices!!!
auto entry = myMap.find(key); 
if(entry != myMap.end())
{
    m0 = entry->second;
}
else
{
    meshData.Vertices.push_back(newVertex);
    m0 = meshData.Vertices.size() - 1;
    myMap.insert(key, m0);
}

然后您将添加新的三角形,只需按原样使用索引即可:

meshdata.indices.pushback(v0); // one of the original indices
meshdata.indices.pushback(m0); // one of the new ones
meshdata.indices.pushback(m2);

// ...

关于c++ - 在书中的示例代码 "introduction to 3d game programming with directx 11",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45231807/

相关文章:

c++ - 创建一个类来访问和指定 vector 类型,并构建一个获取位置并为其分配区域的类

windows - Directx 11.1 中 D3DXCOLOR 结构的新等效项?

c++ - DirectX 11 向后兼容性

c++ - DXGI EnumOutputs - 无 DXGI_OUTPUT_DESC 和空显示模式数组

c++ - 在 Visual Studio 2012 中使用 DirectX 11

c++ - 编程语言开发实践,如何将golang风格的接口(interface)编译为c++?

c++ - Call by pointer 变成 call by reference to pointer

c++ - C++ 标准库必须支持对 friend 是谁挑剔的类吗?

c# - 使用 C# 在托管 DirectX 中在视频上绘制文本

c++ - 类成员函数地址