为了使用DirectX创建3D模拟,我必须以ASCII-STL格式导入大量数据集。问题是我的读者工作但表现很糟糕。我与Autodesk Inventor STL导入器进行了比较,差异很大(5秒对1.5分钟)。我非常感谢您改进我的代码的建议或想法。谢谢!
此外,STL格式的效率非常低。对于每个面,顶点单独列出。看起来像下面这样:
facet normal 0 0.999229 0.0392606
外循环
vertex -3173.54 1993.84 -23184.5
vertex -3099.94 1993.84 -23184.5
vertex -3099.94 2000 -23341.5
ENDLOOP
endfacet
结果是在处理文件期间顶点出现了几次。我试图检查双顶点,但它需要永远的大文件(迭代变得越来越长)。
到目前为止,这是我的代码:
std::ifstream stlFile;
stlFile.open(mFilename);
if(!stlFile) // check if file can be found
{
MessageBox(0, "STL file not found.", 0, 0);
return false;
}
std::string ignore;
stlFile >> ignore >> ignore; //ignore header: solid t=x.xx
UINT index = 0;
int iIndex = 0;
int vIndex = 0;
WORD indexTmp = 0;
while(1)
{
stlFile >> ignore >> ignore; // ignore "normal"
if (ignore == "CUBE")
break;
float normal[3];
stlFile >> normal[0] >> normal[1] >> normal[2]; // read and save the face normal
stlFile >> ignore >> ignore; // ignore "outer loop"
for(int i = 0; i <= 2; ++i) // read the three vertices of a face
{
VERTEX vertexTmp;
vertexTmp.Normal.x = normal[0]; vertexTmp.Normal.y = normal[1]; vertexTmp.Normal.z = normal[2];
stlFile >> ignore >> vertexTmp.Pos.x >> vertexTmp.Pos.y >> vertexTmp.Pos.z;// >> ignore >> ignore;
//if (!ContainsVertexIndex(vertexTmp, vertices, indexTmp)) // return vertex index of double
//{
mVertices.push_back(vertexTmp); //save newly created vertex
indexTmp = vIndex; // create index reference to the new vertex
vIndex++; // increment index
//}
mIndices.push_back(indexTmp);
iIndex++; // increment index
}
stlFile >> ignore >> ignore; // endloop // endfacet
}
stlFile.close();
编辑:我将矢量更改为固定数组,但性能没有显着提高。任何其他建议。
答案 0 :(得分:2)
我刚刚遇到了这个问题并对你的速度问题有了一些了解。
您不应该使用矢量来存储此类型的数据。由于您经常检查向量中是否存在顶点,因此浪费了大量时间迭代向量。
更简单的方法是创建顶点的散列图。这允许进行恒定时间查找(实际上并不需要)和插入,这是您的处理瓶颈所在。那么你的总运行时间就是O(n),其中n是处理过的三角形数。
您需要能够对VERTEX对象进行哈希处理,这可以通过创建哈希模板来完成。我发现使用Boost的散列库最容易做到这一点,但你可以编写自己的散列库。
namespace std
{
template<>
struct hash<your_namespace::VERTEX>
{
typedef your_namespace::VERTEX argument_type;
typedef size_t result_type;
result_type operator()(const argument_type &v) const
{
result_type seed = 0;
boost::hash_combine(seed, v.X);
boost::hash_combine(seed, v.Y);
boost::hash_combine(seed, v.Z);
return seed;
}
}
}
Boost的hash_combine方法根据您对变量进行散列的顺序创建唯一的散列。因此,X-> Y-> Z产生与Z-> Y-> X不同的散列(因此每个序列组合产生唯一的输出)。
最后,使用地图数据结构来存储VERTEX数据对象。
// declaration
std::map<std::size_t, VERTEX> hashmap;
// adding VERTEX object
hashmap[std::hash<VERTEX>()(vObject)] = vObject;
使用此方法,您不必担心插入每个坐标集中的多个坐标集,因为散列坐标集会推断删除重复项。因此,不再通过循环遍历矢量数据结构来检查重复项。
希望这会有所帮助。我遇到了同样的瓶颈问题,这使我的STL读取时间从几分钟缩短到几毫秒。