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;
};

 

posted @ 2015-06-19 09:48  酷熊  阅读(1114)  评论(0编辑  收藏  举报