欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Assimp加载较大的OBJ模型

程序员文章站 2022-03-26 16:03:20
...

  最近用Assimp加载较大OBJ模型时发现内存会爆满,看了下源码,问题在于解析OBJ文件时是一次解析全部 开辟的内存没有及时的释放 。

这是解析的源码

void ObjFileParser::parseFile( IOStreamBuffer<char> &streamBuffer ) {
    // only update every 100KB or it'll be too slow
    //const unsigned int updateProgressEveryBytes = 100 * 1024;
    unsigned int progressCounter = 0;
    const unsigned int bytesToProcess = static_cast<unsigned int>(streamBuffer.size());
    const unsigned int progressTotal = bytesToProcess;
    unsigned int processed = 0;
    size_t lastFilePos( 0 );

    std::vector<char> buffer;
    while ( streamBuffer.getNextDataLine( buffer, '\0' ) ) {
        m_DataIt = buffer.begin();
        m_DataItEnd = buffer.end();

        // Handle progress reporting
        const size_t filePos( streamBuffer.getFilePos() );
        if ( lastFilePos < filePos ) {
            processed = static_cast<unsigned int>(filePos);
            lastFilePos = filePos;
            progressCounter++;
            m_progress->UpdateFileRead( processed, progressTotal );
        }

        // parse line
        switch (*m_DataIt) {
        case 'v': // Parse a vertex texture coordinate
            {
			
                ++m_DataIt;
                if (*m_DataIt == ' ' || *m_DataIt == '\t') {
                    size_t numComponents = getNumComponentsInDataDefinition();
                    if (numComponents == 3) {
                        // read in vertex definition
						m_isVN = false;
                        getVector3(m_pModel->m_Vertices);
                    } else if (numComponents == 4) {
                        // read in vertex definition (homogeneous coords)
                        getHomogeneousVector3(m_pModel->m_Vertices);
                    } else if (numComponents == 6) {
                        // read vertex and vertex-color
                        getTwoVectors3(m_pModel->m_Vertices, m_pModel->m_VertexColors);
                    }
                } else if (*m_DataIt == 't') {
                    // read in texture coordinate ( 2D or 3D )
                    ++m_DataIt;
                    getVector( m_pModel->m_TextureCoord );
                } else if (*m_DataIt == 'n') {
                    // Read in normal vector definition
                    ++m_DataIt;
					m_isVN = true;
                    getVector3( m_pModel->m_Normals );
                }
            }
            break;

        case 'p': // Parse a face, line or point statement
        case 'l':
        case 'f':
            {
                getFace(*m_DataIt == 'f' ? aiPrimitiveType_POLYGON : (*m_DataIt == 'l'
                    ? aiPrimitiveType_LINE : aiPrimitiveType_POINT));
            }
            break;

        case '#': // Parse a comment
            {
                getComment();
            }
            break;

        case 'u': // Parse a material desc. setter
            {
                std::string name;

                getNameNoSpace(m_DataIt, m_DataItEnd, name);

                size_t nextSpace = name.find(" ");
                if (nextSpace != std::string::npos)
                    name = name.substr(0, nextSpace);

                if(name == "usemtl")
                {
                    getMaterialDesc();
                }
            }
            break;

        case 'm': // Parse a material library or merging group ('mg')
            {
                std::string name;

                getNameNoSpace(m_DataIt, m_DataItEnd, name);

                size_t nextSpace = name.find(" ");
                if (nextSpace != std::string::npos)
                    name = name.substr(0, nextSpace);

                if (name == "mg")
                    getGroupNumberAndResolution();
                else if(name == "mtllib")
                    getMaterialLib();
				else
					goto pf_skip_line;
            }
            break;

        case 'g': // Parse group name
            {
                getGroupName();
            }
            break;

        case 's': // Parse group number
            {
                getGroupNumber();
            }
            break;

        case 'o': // Parse object name
            {
                getObjectName();
            }
            break;

        default:
            {
pf_skip_line:
                m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
            }
            break;
        }
    }
	m_filePath.push_back(m_curPath);
}

会在解析f的时候new出Face类型 直到文件读完 由于OJB文件较大所以会内存爆满

 ObjFile::Face *face = new ObjFile::Face( type );

暂时优化的方案 按块现将face的数据写入文件里面保存 face直接释放  

挡块多的时候要管理好路径,后面的赋值也方便

读出来直接从这个CreateDataFromImport(parser.GetModel(), pScene, pParser);函数里面赋值

这个函数也是按照块来赋值 ,在下面循环里读取并赋值给pModel->m_Meshes[index]->m_Faces。 也可以直接赋值个pScene 这样做比较麻烦要改大量代码

  for (size_t index = 0; index < pModel->m_Objects.size(); ++index) 

经过这个函数createNodes(pModel, pModel->m_Objects[index], pScene->mRootNode, pScene, MeshArray);之后要把之前赋值的pModel->m_Meshes[index]->m_Faces全部释放掉。

 

相关标签: Assimp OBJ