osg网格划分

来源:互联网 发布:化妆品扫码软件 编辑:程序博客网 时间:2024/04/28 08:26
创建结构体,用于储存三角形顶点和重心信息struct TriangleSelf {public:osg::Vec3f _p0;osg::Vec3f _p1;osg::Vec3f _p2;osg::Vec3f _centre;TriangleSelf(osg::Vec3f p0,osg::Vec3f p1,osg::Vec3f p2,osg::Vec3f centre){_p0 = p0;_p1 = p1;_p2 = p2;_centre = centre;}TriangleSelf(){}};//创建结构体,用于储存格子编号和三角形struct Classification{public:int _gridIndex;std::vector<TriangleSelf> _triangleselfList;Classification(int &gridIndex){_gridIndex=gridIndex;}};//创建nodevisitor,用于遍历节点,得到所有三角形的顶点class MeshNodeVisitor : public osg::NodeVisitor{public://构造函数MeshNodeVisitor():osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN){m_TriPoints=new osg::Vec3Array;         //定义数组,用于保存索引号对应的顶点}//重载MatrixTransform节点的apply函数virtual void apply(osg::MatrixTransform &node){traverse(node);}//重载group的apply()函数virtual void apply(osg::Group &group){traverse(group);}//重载Geode的apply()函数,获取对应索引号的顶点数组m_TriPoints,三角形索引数组triangle和三角形中心数组centerPointvirtual void apply(osg::Geode &geode){unsigned int drwnum = geode.getNumDrawables();for ( unsigned int i = 0; i < drwnum; i++ ){osg::ref_ptr<osg::Geometry>geometry= geode.getDrawable( i )->asGeometry();if ( !geometry )continue;for ( unsigned int n = 0; n < geometry->getNumPrimitiveSets(); ++n ){osg::PrimitiveSet* ps =geometry->getPrimitiveSet( n );if ( !ps ) continue;osg::ref_ptr<osg::Vec3Array> va = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());//获取顶点数组if((osg::PrimitiveSet::DrawElementsUIntPrimitiveType==ps->getType())&&(osg::PrimitiveSet::TRIANGLES==ps->getMode())){osg::ref_ptr<osg::DrawElementsUInt>deui = new osg::DrawElementsUInt;  //定义deui用于接收索引数组deui = dynamic_cast<osg::DrawElementsUInt*>(ps);const unsigned indexNum = deui->getNumIndices(); //indexNum获取了索引的个数for (unsigned int m=0; m<indexNum; m++) {m_TriPoints->push_back(va->at(deui->at(m)));//获取索引位置的顶点}}else{std::cout<<"模型绘制方式不是三角形!!"<<std::endl;}}}traverse(geode);}public://创建函数用于将m_TriPoints传出去osg::ref_ptr<osg::Vec3Array> getTriPoints(){return m_TriPoints.release();}private:osg::ref_ptr<osg::DrawElementsUInt>deui;osg::ref_ptr<osg::Vec3Array> m_TriPoints;};//创建函数,用于绘制划分网格osg::ref_ptr<osg::Group>CreateGrids(const osg::Vec3f oriPoint,float lengthx,float lengthy,int &row, int &col, int&pace){//申请一个叶子节点osg::ref_ptr<osg::Group>pGroup =new osg::Group();//申请变量用于表示各顶点所在的行、列以及顶点之间的间隔row=0;col=0;pace=0;//输出模型包围盒的大小,便于设置行列数。std::cout<<"包围盒x方向大小为:"<<lengthx<<", "<<"y方向的大小为:"<<lengthy<<std::endl;std::cout<<"enter the col,row and the pace : "<<std::endl;std::cin>>col>>row>>pace;for(int i=0;i<row;i++){//获取起始点坐标且赋值float x_ori = oriPoint.x();float y_ori = oriPoint.y();float z_ori = oriPoint.z();for(int j=0;j<col;j++){osg::ref_ptr<osg::Vec3Array>vertexs = new osg::Vec3Array;//计算出任意一个四边形顶点的坐标值vertexs->push_back(osg::Vec3f(x_ori+j*pace,y_ori-i*pace,z_ori));vertexs->push_back(osg::Vec3f(x_ori+(j+1)*pace,y_ori-i*pace,z_ori));vertexs->push_back(osg::Vec3f(x_ori+(j+1)*pace,y_ori-(i+1)*pace,z_ori));vertexs->push_back(osg::Vec3f(x_ori+j*pace,y_ori-(i+1)*pace,z_ori));//绘制格子osg::ref_ptr<osg::Geode> geode = new osg::Geode;osg::ref_ptr<osg::Geometry>geom=new osg::Geometry();geom->setVertexArray(vertexs);geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4));osg::ref_ptr<osg::Vec4Array> colors2 = new osg::Vec4Array;colors2->push_back(osg::Vec4(0,0,0,0.1));geom->setColorArray(colors2);geom->setColorBinding(osg::Geometry::BIND_OVERALL);geode->addDrawable(geom.get());geode->getOrCreateStateSet()->setMode(GL_BLEND,osg::StateAttribute::ON);int gridIndex = i*col+j;std::ostringstream oss;//创建一个流oss<<gridIndex;//把值传递如流中std::string gridName = oss.str();geode->setName(gridName);osg::ref_ptr<osg::Geode> geode2 = new osg::Geode;osg::ref_ptr<osg::Geometry>geom2=new osg::Geometry();geom2->setVertexArray(vertexs);osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array;colors->push_back(osg::Vec4(1,1,1,1));geom2->setColorArray(colors);geom2->setColorBinding(osg::Geometry::BIND_OVERALL);geom2->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP,0,4));geode2->addDrawable(geom2.get());osg::LineWidth* lw = new osg::LineWidth;lw->setWidth(1);geode2->getOrCreateStateSet()->setAttributeAndModes(lw,osg::StateAttribute::ON);pGroup->addChild(geode);pGroup->addChild(geode2);}}//函数返回geodereturn pGroup.release();}//创建函数,用于绘制包围盒,从而获取划分网格的参考位置以及参考大小osg::ref_ptr<osg::Geode> createboundingbox(osg::Node *node,osg::Vec3f &oriPoint,float &lengthx,float &lengthy){osg::ref_ptr<osg::Geode> geode = new osg::Geode;osg::ComputeBoundsVisitor boundvisitor ;  node->accept(boundvisitor); osg::BoundingBox bb = boundvisitor.getBoundingBox(); //获取包围盒的长宽高和中点lengthx = bb.xMax()-bb.xMin();  lengthy = bb.yMax()-bb.yMin();  float lengthz = bb.zMax()-bb.zMin(); osg::Vec3f pcenter=bb.center();//获取包围盒左后上方顶点oriPoint.set(bb.xMin(),bb.yMax(),bb.zMin());//绘制包围盒osg::ref_ptr<osg::ShapeDrawable>drawable = new osg::ShapeDrawable(new osg::Box(pcenter,lengthx,lengthy,lengthz)); //设置包围盒样式osg::ref_ptr<osg::StateSet>stateset = new osg::StateSet;  stateset= drawable->getOrCreateStateSet();osg::ref_ptr<osg::PolygonMode>polygon = new osg::PolygonMode(osg::PolygonMode::FRONT_AND_BACK,osg::PolygonMode::LINE);  stateset->setAttributeAndModes(polygon); //设置线宽osg::ref_ptr<osg::LineWidth>linewidth = new osg::LineWidth(3.0);  stateset->setAttribute(linewidth);//设置包围盒颜色drawable->setColor(osg::Vec4(1.0,1.0,0.0,1.0));geode->addDrawable(drawable);return geode.get();}//创建函数,用于判断一个点是否在矩形内部bool isPointinPolygon(osg::Vec2f p,osg::ref_ptr<osg::Vec2Array> pPoly){float xMin=pPoly->at(3).x();//此处顶点的编号与后续本程序中网格顶点顺序有关float xMax=pPoly->at(1).x();float yMin=pPoly->at(3).y();float yMax=pPoly->at(1).y();if(xMin<=p.x()&&p.x()<xMax&&yMin<=p.y()&&p.y()<yMax)return true;elsereturn false;}//创建PickHandler类,用于编写自定义的事件响应器class PickHandler : public osgGA::GUIEventHandler{public:PickHandler(osgViewer::Viewer*viewer,std::vector<Classification> classFications):mViewer(viewer),lastselect(0){mClassifications = classFications;pRoot = viewer->getSceneData()->asSwitch();pTriGeode = new osg::Geode();}//定义构造函数,有两个参数,mViewer和lastselect,分别初始化为viewer和0//在handle中实现的功能有双击鼠标左键调用pick函数virtual bool handle(const osgGA::GUIEventAdapter&ea,osgGA::GUIActionAdapter& aa){osg::ref_ptr<osgViewer::Viewer>viewer=dynamic_cast<osgViewer::Viewer*>(&aa);if(viewer=NULL)return false;switch(ea.getEventType()){case(osgGA::GUIEventAdapter::DOUBLECLICK):{if(ea.getButton()==1)Pick(ea.getX(),ea.getY());}return true;}return false;}private://pick函数用于选择对象void Pick(float x,float y){osg::ref_ptr<osg::Node>node=new osg::Node;osg::ref_ptr<osg::Group>parent=new osg::Group;/*** 进行相交测试,几种测试方法见osgUtil::LineSegmentIntersector,结果保留在lsi里面***/osgUtil::LineSegmentIntersector* lsi=new osgUtil::LineSegmentIntersector(osgUtil::LineSegmentIntersector::WINDOW,x,y);osgUtil::IntersectionVisitor ivsec(lsi);mViewer->getCamera()->accept(ivsec);if (lsi->containsIntersections()){if (!(lsi->getFirstIntersection().nodePath.empty())){osg::NodePath np= lsi->getFirstIntersection().nodePath;osg::ref_ptr<osg::Geode> pGeode = dynamic_cast<osg::Geode*>(np[np.size()-1]);if(pGeode.valid()){std::string gridName = pGeode->getName();int num = atoi(gridName.c_str());std::vector<TriangleSelf> triList = mClassifications[num]._triangleselfList;//更新三角形if(pTriGeode->getNumDrawables()>0){pRoot->removeChild(pTriGeode);pTriGeode->removeDrawables(0,pTriGeode->getNumDrawables());}for (int j = 0 ;j<triList.size();j++){TriangleSelf tri = triList[j];osg::ref_ptr<osg::Geometry> pTriGeom = new osg::Geometry;osg::ref_ptr<osg::Vec3Array> pTriVerts = new osg::Vec3Array;pTriVerts->push_back(osg::Vec3(tri._p0));pTriVerts->push_back(osg::Vec3(tri._p1));pTriVerts->push_back(osg::Vec3(tri._p2));pTriGeom->setVertexArray(pTriVerts);pTriGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES,0,pTriVerts->size()));pTriGeode->addDrawable(pTriGeom);}pRoot->addChild(pTriGeode);}} }return;}osgViewer::Viewer *mViewer;osg::Node *lastselect;std::vector<Classification> mClassifications;osg::ref_ptr<osg::Switch> pRoot;osg::ref_ptr<osg::Geode> pTriGeode;};int main (){osg::ref_ptr<osgViewer::Viewer>viewer=new osgViewer::Viewer;osg::ref_ptr<osg::Switch>root=new osg::Switch;osg::ref_ptr<osg::Node>mesh=osgDB::readNodeFile("mesh_2.osg");MeshNodeVisitor mnv;mesh->accept(mnv);//获取模型三角形信息osg::ref_ptr<osg::Vec3Array>pVerts = mnv.getTriPoints();std::vector<TriangleSelf> triangleVector;for (unsigned int i = 0;i<pVerts->size();i+=3){osg::Vec3f p0 = pVerts->at(i);osg::Vec3f p1 = pVerts->at(i+1);osg::Vec3f p2 = pVerts->at(i+2);osg::Vec3f centre = (p0+p1+p2)/3.0;TriangleSelf _triangle(p0,p1,p2,centre);triangleVector.push_back(_triangle);}//调用函数createboundingbox()和CreateGrids(),用于绘制网格osg::Vec3f oriPoint;float lengthx,lengthy;int row,col,pace;osg::ref_ptr<osg::Node> node = createboundingbox(mesh,oriPoint,lengthx,lengthy);osg::ref_ptr<osg::Group> geode=CreateGrids(oriPoint,lengthx,lengthy,row,col,pace);//判断三角形和网格的关系,将三角形进行按网格划分std::vector<Classification> classification;int gridNum = (col) * (row);for (int i = 0 ;i<gridNum;++i){Classification _classfi(i);classification.push_back(_classfi);}bool isNextTri = false;for(unsigned int n=0,k = 0;n<pVerts->size();++k,n+=3){for(int i=0;i<row;++i){if(isNextTri){isNextTri = false;break;}for(int j=0;j<col;++j){osg::Vec2 p(triangleVector[k]._centre.x(),triangleVector[k]._centre.y());osg::ref_ptr<osg::Vec2Array> pPoly = new osg::Vec2Array;pPoly->push_back(osg::Vec2f(oriPoint.x()+j*pace,oriPoint.y()-i*pace));pPoly->push_back(osg::Vec2f(oriPoint.x()+(j+1)*pace,oriPoint.y()-i*pace));pPoly->push_back(osg::Vec2f(oriPoint.x()+(j+1)*pace,oriPoint.y()-(i+1)*pace));pPoly->push_back(osg::Vec2f(oriPoint.x()+j*pace,oriPoint.y()-(i+1)*pace));if(isPointinPolygon(p,pPoly)){int gridIndex=i*col+j;classification[gridIndex]._triangleselfList.push_back(triangleVector[k]);isNextTri = true;break;}}}}//输出每个格子内有多少三角形for(int i=0;i<gridNum;i++){int selTriCount=classification[i]._triangleselfList.size();std::cout<<"第"<<i<<"个格子里有"<<selTriCount<<"个三角形"<<std::endl;}//输出每个格子的三角形(输出为osg格式)for(int m=0;m<gridNum;m++){osg::Group*triGroup=new osg::Group;for(int n=0;n<classification[m]._triangleselfList.size();n++){osg::ref_ptr<osg::Vec3Array>griVertex=new osg::Vec3Array;griVertex->push_back(classification[m]._triangleselfList[n]._p0);griVertex->push_back(classification[m]._triangleselfList[n]._p1);griVertex->push_back(classification[m]._triangleselfList[n]._p2);osg::ref_ptr<osg::Geometry>triGeometry=new osg::Geometry;triGeometry->setVertexArray(griVertex);triGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLES,0,3));osg::ref_ptr<osg::Geode>triGeode=new osg::Geode;triGeode->addDrawable(triGeometry);triGroup->addChild(triGeode.get());}std::ostringstream oss;//创建一个流oss<<m;//把值传递如流中std::string fileName = oss.str() + ".osg";osg::Node* triNode=dynamic_cast<osg::Node*>(triGroup);//在使用writeNodeFile时,节点始终是Node指针,故需要将其转换成NodeosgDB::writeNodeFile(*triNode,fileName);}root->addChild(geode.get());//root->addChild(mesh.get(),true);viewer->setSceneData(root);viewer->addEventHandler(new PickHandler(viewer,classification));//viewer->setUpViewInWindow(500,500,800,600);return viewer->run();}

0 0
原创粉丝点击