查看: 2906|回复: 9

求助:如何简化ive模型?

[复制链接]

该用户从未签到

发表于 2012-8-28 17:09:29 来自手机 | 显示全部楼层 |阅读模式
我用osgutil:simplifier发现只能简化osg模型,怎么才能减少ive模型的顶点数?

该用户从未签到

发表于 2012-8-28 18:40:24 | 显示全部楼层
简化难道不减少顶点数?

该用户从未签到

 楼主| 发表于 2012-8-29 08:52:26 来自手机 | 显示全部楼层
smash 发表于 2012-8-28 18:40
简化难道不减少顶点数?

就是问如何简化啊

该用户从未签到

发表于 2012-8-29 10:24:12 | 显示全部楼层
llxiaocha 发表于 2012-8-29 08:52
就是问如何简化啊

ive模型跟osg模型读到内存里都是一样的,怎么会osg能简化ive不能简化?

该用户从未签到

 楼主| 发表于 2012-8-29 11:25:21 | 显示全部楼层
smash 发表于 2012-8-29 10:24
ive模型跟osg模型读到内存里都是一样的,怎么会osg能简化ive不能简化?

我也奇怪呢,我设化简参数是0.1,读cow.osg化简前顶点数是7772,化简后是三百多,读一个ive文件,化简前后顶点数没有变化



[code


//节点纹理访问器
class TextureVisitor : public osg::NodeVisitor
{
public:

        osg::ref_ptr<osg::Vec3Array> extracted_verts;
        //构造函数,遍历所有子节点
        TextureVisitor( ):
          osg::NodeVisitor( osg::NodeVisitor::TRAVERSE_ALL_CHILDREN )
          {
                  //
                  extracted_verts=new osg::Vec3Array;
          }

          //重载apply方法
          virtual void apply( osg::Node& node )
          {
                  if( node.getStateSet() )
                  {
                          apply( node.getStateSet() );
                          //node.setStateSet(NULL);
                  }

                  //实现继续遍历节点
                  traverse(node);
          }

          //重载apply方法
          virtual void apply( osg::Geode& geode )
          {
                  if( geode.getStateSet() )
                  {
                          apply( geode.getStateSet() );
                         // geode.setStateSet(NULL);


                  }

                  unsigned int cnt = geode.getNumDrawables();

                  for( unsigned int i = 0; i < cnt; i++ )
                  {
                          apply(geode.getDrawable(i)->getStateSet());
                          //geode.getDrawable(i)->setStateSet(NULL);
                          //得到绘制体
                          osg::Geometry * geom=dynamic_cast<osg::Geometry*>(geode.getDrawable(i));
                          if (!geom)
                          {
                                  continue;
                          }
                          //得到顶点
                          osg::Vec3Array *verts= dynamic_cast<osg::Vec3Array*>(geom->getVertexArray());
                          if (!verts)
                          {
                                 continue;
                          }
                          //将顶点插入到顶点列表
                          extracted_verts->insert(extracted_verts->end(),verts->begin(),verts->end());

                  }


                  traverse(geode);
          }

          //得到贴图列表
          void apply( osg::StateSet* state )
          {
                  //得到纹理属性列表
                  osg::StateSet::TextureAttributeList& texAttribList = state->getTextureAttributeList();
                  for( unsigned int i = 0; i < texAttribList.size(); i++ )
                  {
                          //得到纹理
                          osg::Texture2D* tex2D = NULL;
                          if( tex2D = dynamic_cast<osg::Texture2D*>(state->getTextureAttribute(i, osg::StateAttribute::TEXTURE)) )
                          {
                                  //得到贴图
                                  if( tex2D->getImage() )
                                  {
                                          //简化贴图
                                          scale(tex2D->getImage(),minimage);

                                  }
                          }
                  }
          }
        void setminimage(float m)
        {
                minimage=m;
        }
          

protected:

        float minimage;//贴图简化大小
       
};
void SimplifierTexture(osg::Node* node,float minverts,float minimage)
{


        //样本比率越小,简化越多
        float sampleRatio = 0.1f;
        //设置点的最大误差
        float maxError = 4.0f;
        //计算顶点数
        unsigned int num;
        //深拷贝模型到nodedeep节点
        osg::ref_ptr<osg::Node> nodedeep = (osg::Node*)node->clone(osg::CopyOp:EEP_COPY_ALL);

        //创建纹理访问器
        TextureVisitor textureTV;
        textureTV.setminimage(minimage);
        //启动访问器,执行遍历
        nodedeep->accept( textureTV );

        //得到模型的顶点数
        num=textureTV.extracted_verts->size();

        //得到化简样本比率
        sampleRatio=minverts/(float)num;
        std::cout<<num;
        //创建简化对象
        osgUtil::Simplifier simplifier(sampleRatio, maxError);
        //利用simplifier简化nodedeep
        nodedeep->accept(simplifier);

        return ;

}

int main()
{
        //创建Viewer对象,场景浏览器
        osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();

        osg::ref_ptr<osg::Group> root = new osg::Group();

        //创建一个节点并读取模型
        osg::ref_ptr<osg::Node> node = osgDB::readNodeFile("cow.osg");

        float minverts=1000;
        float minimage=256;

        SimplifierTexture(node,minverts,minimage);


       

        root->addChild(node.get());
        ////优化场景数据
        //osgUtil::Optimizer optimizer ;
        //optimizer.optimize(root.get()) ;

        viewer->setSceneData(root.get());

        viewer->realize();

        viewer->run();

        return 0 ;
}[/code]

该用户从未签到

 楼主| 发表于 2012-8-29 15:15:15 来自手机 | 显示全部楼层
求助求助等消息

该用户从未签到

 楼主| 发表于 2012-8-30 14:44:08 | 显示全部楼层
这几天研究了下simplifier这个工具,发现简化osg模型的时候顶点数会减少,文件会变小,简化ive模型时,顶点数会增加,重新保存为ive文件会变大,而且输出顶点数发现简化后的模型是在简化前模型的基础上增加了好多顶点,但是用网格显示效果的时候,发现确实根据边塌陷算法少了好多三角形,不懂。。。

该用户从未签到

发表于 2012-9-6 17:04:23 | 显示全部楼层
不是这样的,OSG简化算法是在经典边塌陷基础上做了限制,即所有的边界边和与边界边相邻的边都不参与塌陷,因此这些边对应的面也不会被简化掉。这样可以最大限度地保证简化后模型的边界不变
但是要注意的是,简化并不会自动合并重合的顶点和边,因为这些重合的点可能具有不同的顶点属性(纹理坐标等),此时这些边可能都会被认为是边界而无法简化掉。因此,如果您知道这些边是可以合并的,那么需要自己提前合并掉,然后简化算法才能够发挥性能

该用户从未签到

 楼主| 发表于 2012-9-7 09:28:06 | 显示全部楼层
array 发表于 2012-9-6 17:04
不是这样的,OSG简化算法是在经典边塌陷基础上做了限制,即所有的边界边和与边界边相邻的边都不参与塌陷,因 ...

我添加的模型是任意的,不是特定的,请问如何能确定哪些边是不必要的?
这种情况下如何简化?
谢谢array

该用户从未签到

发表于 2012-9-12 11:04:05 | 显示全部楼层
简单的原则,完全是建模过程中的:尽量使用索引,避免使用重合的顶点
您需要登录后才可以回帖 登录 | 注册

本版积分规则

OSG中国官方论坛-有您OSG在中国才更好

网站简介:osgChina是国内首个三维相关技术开源社区,旨在为国内更多的技术开发人员提供最前沿的技术资讯,为更多的三维从业者提供一个学习、交流的技术平台。

联系我们

  • 工作时间:09:00--18:00
  • 反馈邮箱:1315785073@qq.com
快速回复 返回顶部 返回列表