NodeVisitor的使用-遍历Geode节点下的Geometry并获取顶点、法向量等数据
struct Subset { std::vector<float> vertexs;//位置 std::vector<float> normals;//法向 std::vector<float> texCoords;//纹理 std::vector<unsigned int> indices;//索引下标 std::vector<unsigned int> faceMtrls;//面材质索引 }; class GetSimplifySTLDataVisitor : public osg::NodeVisitor { public: GetSimplifySTLDataVisitor(Subset &s):dstSubset(s), osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) { } virtual void apply(osg::Geode& geode) { unsigned int count = geode.getNumDrawables(); for ( unsigned int i = 0; i < count; i++ ) { osg::Geometry *geometry = geode.getDrawable( i )->asGeometry(); if ( !geometry ) continue; // 顶点数据 osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray()); int vertexlNum = vertices->size(); for ( int i=0; i<vertexlNum; i++) { dstSubset.vertexs.push_back( vertices->at(i).x() ); dstSubset.vertexs.push_back( vertices->at(i).y() ); dstSubset.vertexs.push_back( vertices->at(i).z() ); } // 法向量 osg::Vec3Array* normals = dynamic_cast<osg::Vec3Array*>(geometry->getNormalArray()); int normalNum = normals->size(); for (int i=0; i<normalNum; i++) { dstSubset.normals.push_back( normals->at(i).x() ); dstSubset.normals.push_back( normals->at(i).y() ); dstSubset.normals.push_back( normals->at(i).z() ); } normalBindKinds.insert(geometry->getNormalBinding()); if(osg::Geometry::BIND_PER_VERTEX != geometry->getNormalBinding() ) { std::string msg="未处理的法向量绑定方式"; MessageBox(0, LPCTSTR(msg.c_str()), "警告", MB_OK); } // 索引数组 for ( unsigned int i = 0; i < geometry->getNumPrimitiveSets(); ++i ) { osg::PrimitiveSet* ps = geometry->getPrimitiveSet( i ); if ( !ps ) continue; pts.insert(ps->getType()); modes.insert(ps->getMode()); switch( ps->getType() ) { case osg::PrimitiveSet::DrawElementsUIntPrimitiveType : { osg::DrawElementsUInt* deui = dynamic_cast<osg::DrawElementsUInt*>(ps); const unsigned indexNum = deui->getNumIndices(); switch( deui->getMode() ) { case osg::PrimitiveSet::TRIANGLES : { for (unsigned int i=0; i<indexNum; i++) { dstSubset.indices.push_back( deui->at(i) ); } break; } default: { std::string msg="未处理的绘制模式"; MessageBox(0, LPCTSTR(msg.c_str()), "警告", MB_OK); } } break; } case osg::PrimitiveSet::DrawElementsUShortPrimitiveType : { osg::DrawElementsUShort* de = dynamic_cast<osg::DrawElementsUShort*>(ps); const unsigned indexNum = de->getNumIndices(); switch( de->getMode() ) { case osg::PrimitiveSet::TRIANGLES : { for (unsigned int i=0; i<indexNum; i++) { dstSubset.indices.push_back( de->at(i) ); } break; } case osg::PrimitiveSet::TRIANGLE_STRIP : { for (unsigned int i=0; i<indexNum-2; i++) { //此处索引为何与基数偶数有关,可百度GL_TRIANGLE_STRIP if (i%2==0) { dstSubset.indices.push_back( de->at(i) ); dstSubset.indices.push_back( de->at(i+1) ); dstSubset.indices.push_back( de->at(i+2) ); } else { dstSubset.indices.push_back( de->at(i) ); dstSubset.indices.push_back( de->at(i+2) ); dstSubset.indices.push_back( de->at(i+1) ); } } break; } default: { std::string msg="未处理的绘制模式"; MessageBox(0, LPCTSTR(msg.c_str()), "警告", MB_OK); } } break; } case osg::PrimitiveSet::DrawArraysPrimitiveType : { osg::DrawArrays* da = dynamic_cast<osg::DrawArrays*>(ps); int first=da->getFirst(); int count=da->getCount(); switch( da->getMode() ) { case osg::PrimitiveSet::TRIANGLES : { for ( int i=first; i<first+count; i++) { dstSubset.indices.push_back( i ); } break; } case osg::PrimitiveSet::TRIANGLE_STRIP : { for ( int i=first; i<first+count-2; i++) { if(i%2==0) { dstSubset.indices.push_back( i ); dstSubset.indices.push_back( i+1 ); dstSubset.indices.push_back( i+2 ); } else { dstSubset.indices.push_back( i ); dstSubset.indices.push_back( i+2 ); dstSubset.indices.push_back( i+1 ); } } break; } default: { std::string msg="未处理的绘制模式"; MessageBox(0, LPCTSTR(msg.c_str()), "警告", MB_OK); } } break; } default: { std::string msg="未处理的图元类型"; MessageBox(0, LPCTSTR(msg.c_str()), "警告", MB_OK); } } } } } private: Subset &dstSubset; //以下三个数组用来测试 std::set<osg::Geometry::AttributeBinding> normalBindKinds; std::set<osg::PrimitiveSet::Type> pts; std::set<GLenum> modes; };