bool boundSort(const osg::ref_ptr< osg::Node> &i, const osg::ref_ptr< osg::Node> &j) { osg::BoundingSphere bsI = i->getBound(); osg::BoundingSphere bsJ = j->getBound(); return bsI.center().x() < bsJ.center().x(); }
int main( int argc, char **argv ) { // use an ArgumentParser object to manage the program arguments. osg::ArgumentParser arguments(&argc,argv); // set up the usage document, in case we need to print out how to use this program. arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName()); arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ..."); arguments.getApplicationUsage()->addCommandLineOption("--image <filename>","Load an image and render it on a quad"); arguments.getApplicationUsage()->addCommandLineOption("--dem <filename>","Load an image/DEM and render it on a HeightField"); arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display command line parameters"); arguments.getApplicationUsage()->addCommandLineOption("--help-env","Display environmental variables available"); arguments.getApplicationUsage()->addCommandLineOption("--help-keys","Display keyboard & mouse bindings available"); arguments.getApplicationUsage()->addCommandLineOption("--help-all","Display all command line, env vars and keyboard & mouse bindings."); arguments.getApplicationUsage()->addCommandLineOption("--dragger <draggername>","Use the specified dragger for manipulation [TabPlaneDragger, TabPlaneTrackballDragger, TrackballDragger, Translate1DDragger, Translate2DDragger, TranslateAxisDragger, TabBoxDragger, TranslatePlaneDragger, Scale1DDragger, Scale2DDragger, RotateCylinderDragger, RotateSphereDragger]"); arguments.getApplicationUsage()->addCommandLineOption("--fixedDraggerSize","Fix the size of the dragger geometry in the screen space"); bool fixedSizeInScreen = false; while (arguments.read("--fixedDraggerSize")) { fixedSizeInScreen = true; } // construct the viewer. osgViewer::Viewer viewer(arguments); // add the window size toggle handler viewer.addEventHandler(new osgViewer::WindowSizeHandler); // get details on keyboard and mouse bindings used by the viewer. viewer.getUsage(*arguments.getApplicationUsage()); if (arguments.read("--test-NodeMask")) { const osg::ref_ptr<osg::Group> group = new osg::Group(); group->setNodeMask(0); const osg::ref_ptr<osgManipulator::AntiSquish> antiSquish = new osgManipulator::AntiSquish(); group->addChild(antiSquish.get()); const osg::ref_ptr<osg::Node> node = new osg::Node(); node->setInitialBound(osg::BoundingSphere(osg::Vec3(0.0, 0.0, 0.0), 1.0)); antiSquish->addChild(node.get()); group->getBound(); return 1; } // if user request help write it out to cout. bool helpAll = arguments.read("--help-all"); unsigned int helpType = ((helpAll || arguments.read("-h") || arguments.read("--help"))? osg::ApplicationUsage::COMMAND_LINE_OPTION : 0 ) | ((helpAll || arguments.read("--help-env"))? osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE : 0 ) | ((helpAll || arguments.read("--help-keys"))? osg::ApplicationUsage::KEYBOARD_MOUSE_BINDING : 0 ); if (helpType) { arguments.getApplicationUsage()->write(std::cout, helpType); return 1; } // report any errors if they have occurred when parsing the program arguments. if (arguments.errors()) { arguments.writeErrorMessages(std::cout); return 1; } std::string dragger_name = "TabBoxDragger"; arguments.read("--dragger", dragger_name); osg::Timer_t start_tick = osg::Timer::instance()->tick(); // read the scene from the list of file specified command line args. osg::ref_ptr<osg::Node> loadedModel = osgDB::readRefNodeFiles(arguments); // if no model has been successfully loaded report failure. bool tragger2Scene(true); if (!loadedModel) { //std::cout << arguments.getApplicationName() <<": No data loaded" << std::endl; //return 1; loadedModel = createDemoScene(fixedSizeInScreen); tragger2Scene=false; } // any option left unread are converted into errors to write out later. arguments.reportRemainingOptionsAsUnrecognized(); // report any errors if they have occurred when parsing the program arguments. if (arguments.errors()) { arguments.writeErrorMessages(std::cout); } osg::Timer_t end_tick = osg::Timer::instance()->tick(); std::cout << "Time to load = "<<osg::Timer::instance()->delta_s(start_tick,end_tick)<<std::endl; // optimize the scene graph, remove redundant nodes and state etc. osgUtil::Optimizer optimizer; optimizer.optimize(loadedModel); // pass the loaded scene graph to the viewer. if ( tragger2Scene ) { viewer.setSceneData(addDraggerToScene(loadedModel.get(), dragger_name, fixedSizeInScreen)); } else { viewer.setSceneData(loadedModel); } return viewer.run(); }
osg::ref_ptr<osg::Node> decorate_with_clip_node(const osg::ref_ptr<osg::Node>& subgraph) { osg::ref_ptr<osg::Group> rootnode = new osg::Group; // create wireframe view of the model so the user can see // what parts are being culled away. osg::StateSet* stateset = new osg::StateSet; //osg::Material* material = new osg::Material; osg::PolygonMode* polymode = new osg::PolygonMode; polymode->setMode(osg::PolygonMode::FRONT_AND_BACK,osg::PolygonMode::LINE); stateset->setAttributeAndModes(polymode,osg::StateAttribute::OVERRIDE|osg::StateAttribute::ON); osg::Group* wireframe_subgraph = new osg::Group; wireframe_subgraph->setStateSet(stateset); wireframe_subgraph->addChild(subgraph); rootnode->addChild(wireframe_subgraph); /* // simple approach to adding a clipnode above a subgraph. // create clipped part. osg::ClipNode* clipped_subgraph = new osg::ClipNode; osg::BoundingSphere bs = subgraph->getBound(); bs.radius()*= 0.4f; osg::BoundingBox bb; bb.expandBy(bs); clipped_subgraph->createClipBox(bb); clipped_subgraph->addChild(subgraph); rootnode->addChild(clipped_subgraph); */ // more complex approach to managing ClipNode, allowing // ClipNode node to be transformed independently from the subgraph // that it is clipping. osg::MatrixTransform* transform= new osg::MatrixTransform; osg::NodeCallback* nc = new osg::AnimationPathCallback(subgraph->getBound().center(),osg::Vec3(0.0f,0.0f,1.0f),osg::inDegrees(45.0f)); transform->setUpdateCallback(nc); osg::ClipNode* clipnode = new osg::ClipNode; osg::BoundingSphere bs = subgraph->getBound(); bs.radius()*= 0.4f; osg::BoundingBox bb; bb.expandBy(bs); clipnode->createClipBox(bb); clipnode->setCullingActive(false); transform->addChild(clipnode); rootnode->addChild(transform); // create clipped part. osg::Group* clipped_subgraph = new osg::Group; clipped_subgraph->setStateSet(clipnode->getStateSet()); clipped_subgraph->addChild(subgraph); rootnode->addChild(clipped_subgraph); return rootnode; }
//创建预渲染场景 osg::ref_ptr<osg::Node> createPreRenderSubGraph(osg::ref_ptr<osg::Node> subgraph, unsigned tex_width, unsigned tex_height, osg::Camera::RenderTargetImplementation renderImplementation, bool useImage) { if (!subgraph) return 0; //创建一个包含预渲camera的 Group 节点 osg::ref_ptr<osg::Group> parent = new osg::Group; //创建纹理,用来绑定相机渲染的结果 osg::ref_ptr<osg::Texture> texture = 0; { osg::ref_ptr<osg::Texture2D> texture2D = new osg::Texture2D; texture2D->setTextureSize(tex_width, tex_height); texture2D->setInternalFormat(GL_RGBA); texture2D->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR); texture2D->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR); texture = texture2D; } //创建一个用来浏览的四边形几何体 { osg::ref_ptr<osg::Geometry> polyGeom = new osg::Geometry(); //设置该几何体不使用显示列表 polyGeom->setSupportsDisplayList(false); float height = 100.0f; float width = 200.0f; //创建顶点数组,并添加数据 osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array; vertices->push_back( osg::Vec3(0.0f,0.0f,0.0f) ); vertices->push_back( osg::Vec3(width,0.0f,0.0f) ); vertices->push_back( osg::Vec3(width,0.0f,height) ); vertices->push_back( osg::Vec3(0.0f,0.0f,height) ); //创建纹理数组,并添加数据 osg::ref_ptr<osg::Vec2Array> texcoords = new osg::Vec2Array(); texcoords->push_back( osg::Vec2(0.0f,0.0f) ); texcoords->push_back( osg::Vec2(1.0f,0.0f) ); texcoords->push_back( osg::Vec2(1.0f,1.0f) ); texcoords->push_back( osg::Vec2(0.0f,1.0f) ); polyGeom->setVertexArray(vertices.get()); //使用vbo扩展 // { // osg::ref_ptr<osg::VertexBufferObject> vbObject = new osg::VertexBufferObject; // vertices->setVertexBufferObject(vbObject); // // polyGeom->setUseVertexBufferObjects(true); // } polyGeom->setTexCoordArray(0,texcoords.get()); //创建颜色数组,并设置绑定方式及添加数据 // osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array; // colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); // polyGeom->setColorArray(colors.get()); // polyGeom->setColorBinding(osg::Geometry::BIND_OVERALL); polyGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,vertices->size())); //现在我们需要将纹理附加到该几何体上,我们创建一个包含该纹理的StateSet osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet; stateset->setTextureAttributeAndModes(0, texture,osg::StateAttribute::ON); polyGeom->setStateSet(stateset); osg::ref_ptr<osg::Geode> geode = new osg::Geode(); geode->addDrawable(polyGeom.get()); parent->addChild(geode.get()); } // 需要创建一个相机节点,用来渲染到该纹理(RTT) { osg::ref_ptr<osg::Camera> camera = new osg::Camera; //设置背景色及清除颜色和深度缓存 camera->setClearColor(osg::Vec4(0.1f,0.1f,0.3f,1.0f)); camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //获得该节点的范围盒 const osg::BoundingSphere& bs = subgraph->getBound(); if (!bs.valid()) { return subgraph.get(); } float znear = 1.0f*bs.radius(); float zfar = 3.0f*bs.radius(); float proj_top = 0.25f*znear; float proj_right = 0.5f*znear; znear *= 0.9f; zfar *= 1.1f; //设置投影矩阵. // camera->setProjectionMatrixAsFrustum(-proj_right,proj_right,-proj_top,proj_top,znear,zfar); //将相机对准该子场景 camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF); // camera->setViewMatrixAsLookAt(bs.center()-osg::Vec3(0.0f,2.0f,0.0f)*bs.radius(),bs.center(),osg::Vec3(0.0f,0.0f,1.0f)); //设置视口 camera->setViewport(0,0,tex_width,tex_height); //设置相机的渲染序列 camera->setRenderOrder(osg::Camera::PRE_RENDER); //设置相机渲染通过 OpenGL frame buffer object 实现 camera->setRenderTargetImplementation(renderImplementation); if (useImage) { osg::ref_ptr<osg::Image> image = new osg::Image; //image->allocateImage(tex_width, tex_height, 1, GL_RGBA, GL_UNSIGNED_BYTE); image->allocateImage(tex_width, tex_height, 1, GL_RGBA, GL_FLOAT); //将Image附加到相机的COLOR_BUFFER camera->attach(osg::Camera::COLOR_BUFFER, image.get()); //添加相机的绘制后回调,修改images数据 camera->setPostDrawCallback(new MyCameraPostDrawCallback(image.get())); //这里我们不直接将相机的COLOR_BUFFER附加到该纹理上,是为了修改渲染后的图像数据 texture->setImage(0, image.get()); } else { //直接将该纹理附加到相机的颜色缓存. camera->attach(osg::Camera::COLOR_BUFFER, texture.get()); } //添加要绘制的子场景 camera->addChild(subgraph.get()); parent->addChild(camera.get()); } return parent.get(); }
osg::ref_ptr<osg::Node> createRoom(const osg::ref_ptr<osg::Node>& loadedModel) { // default scale for this model. osg::BoundingSphere bs(osg::Vec3(0.0f,0.0f,0.0f),1.0f); osg::Group* root = new osg::Group; if (loadedModel) { const osg::BoundingSphere& loaded_bs = loadedModel->getBound(); osg::PositionAttitudeTransform* pat = new osg::PositionAttitudeTransform(); pat->setPivotPoint(loaded_bs.center()); pat->setUpdateCallback(new ModelTransformCallback(loaded_bs)); pat->addChild(loadedModel); bs = pat->getBound(); root->addChild(pat); } bs.radius()*=1.5f; // create a bounding box, which we'll use to size the room. osg::BoundingBox bb; bb.expandBy(bs); // create statesets. osg::StateSet* rootStateSet = new osg::StateSet; root->setStateSet(rootStateSet); osg::StateSet* wall = new osg::StateSet; wall->setMode(GL_CULL_FACE,osg::StateAttribute::ON); osg::StateSet* floor = new osg::StateSet; floor->setMode(GL_CULL_FACE,osg::StateAttribute::ON); osg::StateSet* roof = new osg::StateSet; roof->setMode(GL_CULL_FACE,osg::StateAttribute::ON); osg::Geode* geode = new osg::Geode; // create front side. geode->addDrawable(createWall(bb.corner(0), bb.corner(4), bb.corner(1), wall)); // right side geode->addDrawable(createWall(bb.corner(1), bb.corner(5), bb.corner(3), wall)); // left side geode->addDrawable(createWall(bb.corner(2), bb.corner(6), bb.corner(0), wall)); // back side geode->addDrawable(createWall(bb.corner(3), bb.corner(7), bb.corner(2), wall)); // floor geode->addDrawable(createWall(bb.corner(0), bb.corner(1), bb.corner(2), floor)); // roof geode->addDrawable(createWall(bb.corner(6), bb.corner(7), bb.corner(4), roof)); root->addChild(geode); root->addChild(createLights(bb,rootStateSet)); return root; }