本书示例代码"introduction to 3d game programming with directx 11"
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的成员Vertices和Indices是STL的vector。
在我看来,这个函数调用了那一系列函数后,meshData.Vertices.push_back,在循环的下一次迭代中,一些顶点可能会被重复存储。
任何人都可以回答
- 不管我错了,
- 为什么作者要这样写代码,
- 或者如果我的想法是对的,有没有更高效的方法
感谢所有阅读我拙劣英语的人。
- 如果v1-v2边还有一个三角形,那么v1,v2,m1会相加两次,依此类推
- 谁知道呢?也许在此之后还有一个额外的去重过程。
- 可以使用几何着色器或直接曲面细分在 GPU 上执行此操作。参见 this example。
whether I am wrong
我很确定你是对的,尤其是关于重复的顶点!
why the author make the codes like this
除了作者本人,没有人能回答这个问题。我 猜测 he/she 只是监督了重复问题...
or whether there is more efficient way if my thought is right.
只要算法不正确!
,我就不会关心效率
首先,我们需要避免顶点重复。我只是将现有的顶点保留原样(因此只有 clear
索引)并在末尾附加新的顶点。为此,我会将 edges 存储在临时 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);
// ...
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的成员Vertices和Indices是STL的vector。
在我看来,这个函数调用了那一系列函数后,meshData.Vertices.push_back,在循环的下一次迭代中,一些顶点可能会被重复存储。
任何人都可以回答
- 不管我错了,
- 为什么作者要这样写代码,
- 或者如果我的想法是对的,有没有更高效的方法
感谢所有阅读我拙劣英语的人。
- 如果v1-v2边还有一个三角形,那么v1,v2,m1会相加两次,依此类推
- 谁知道呢?也许在此之后还有一个额外的去重过程。
- 可以使用几何着色器或直接曲面细分在 GPU 上执行此操作。参见 this example。
whether I am wrong
我很确定你是对的,尤其是关于重复的顶点!
why the author make the codes like this
除了作者本人,没有人能回答这个问题。我 猜测 he/she 只是监督了重复问题...
or whether there is more efficient way if my thought is right.
只要算法不正确!
,我就不会关心效率首先,我们需要避免顶点重复。我只是将现有的顶点保留原样(因此只有 clear
索引)并在末尾附加新的顶点。为此,我会将 edges 存储在临时 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);
// ...