我的代码读取STL文件(c++)的改进



为了用DirectX创建3D模拟,我必须导入ASCII-STL格式的巨大数据集。问题是,我的读者正在工作,但表现很糟糕。我与Autodesk Inventor STL导入程序进行了比较,两者的差异非常显著(5秒与1.5分钟)。我非常感谢为改进我的代码而提出的建议或想法。非常感谢。

此外,STL格式的效率非常低。对于每个面,顶点都单独列出。看起来如下:

刻面法线0 0.999229 0.0392606

外环

顶点-3173.54 1993.84-23184.5

顶点-3099.94 1993.84-23184.5

顶点-3099.94 2000-23341.5

端环

端面

结果是,在处理文件的过程中会出现多次顶点。我试着检查双顶点,但对于巨大的文件来说,这需要很长时间(迭代越来越长)。

这是我到目前为止的代码:

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

编辑:我将矢量更改为固定数组,但性能没有显著提高。任何其他建议。

我刚刚遇到这个问题,对您的速度问题有了一些了解。

您不应该将矢量用于这种类型的数据存储。由于您一直在检查向量中是否存在顶点,因此在向量上迭代会浪费大量时间。

一种更简单的方法是创建顶点的哈希图。这允许恒定的时间查找(这不是真正需要的)和插入,这是你的处理瓶颈所在。然后你的总运行时间将是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读取时间从几分钟减少到了几毫秒。

相关内容

  • 没有找到相关文章

最新更新