簡體   English   中英

在“使用DirectX 11進行3D游戲編程介紹”一書的示例代碼中

[英]In an example code of the book “introduction to 3d game programming with directx 11”

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'文件中,並且可以細分網格。 在調用此功能之前,將創建一個二十面體並將其作為參數meshData進行傳輸。 MeshData,頂點和索引的成員是STL的向量。

在我看來,在此函數調用了一系列函數meshData.Vertices.push_back之后,在循環的下一次迭代中,可能會重復存儲一些頂點。

任何人都可以回答

  • 我是否有錯
  • 為什么作者編寫這樣的代碼,
  • 或者如果我的想法正確,是否有更有效的方法。

謝謝所有讀我英語不好的人。

  • 如果在v1-v2邊附近還有另一個三角形,則將v1,v2和m1相加兩次,依此類推。
  • 誰知道? 在此之后,也許還有額外的重復數據刪除通道。
  • 可以使用幾何着色器或直線細分在GPU上執行此操作。 請參閱此示例

我是否錯

我很確定你是對的 ,尤其是關於重復的頂點!

為什么作者制作這樣的代碼

除了作者本人之外,沒有人可以回答這個問題。 他/她只是監督了重復問題...

或者如果我的想法正確,是否有更有效的方法。

只要算法不正確,我就不會在乎效率!

首先,我們需要避免頂點重復。 我只是將現有的頂點保持不變(因此僅clear索引),並在最后附加新的頂點。 為此,我將邊緣存儲在臨時std :: map中,將一對索引(邊緣)映射到新創建的索引(始終先使用較小的索引,以避免(10,12)(12,10) ,它標識同一條邊...)。

然后對於v0,v1,v2,我將使用索引,而不是頂點本身。 首先在地圖上查找m0,m1,m2,如果找到,請使用,否則,創建一個新頂點,將其添加到頂點向量中,然后在我們的地圖中添加一個條目。

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);

// ...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM