/*===========================================================================*\ * * * OpenMesh * * Copyright (C) 2001-2015 by Computer Graphics Group, RWTH Aachen * * www.openmesh.org * * * *---------------------------------------------------------------------------* * This file is part of OpenMesh. * * * * OpenMesh is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of * * the License, or (at your option) any later version with the * * following exceptions: * * * * If other files instantiate templates or use macros * * or inline functions from this file, or you compile this file and * * link it with other files to produce an executable, this file does * * not by itself cause the resulting executable to be covered by the * * GNU Lesser General Public License. This exception does not however * * invalidate any other reasons why the executable file might be * * covered by the GNU Lesser General Public License. * * * * OpenMesh is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU LesserGeneral Public * * License along with OpenMesh. If not, * * see . * * * \*===========================================================================*/ /*===========================================================================*\ * * * $Revision$ * * $Date$ * * * \*===========================================================================*/ // -------------------- STL #include #include #include #include // -------------------- OpenSG #include #include #include #include #include #include #include // -------------------- OpenMesh #include // always before kernel type #include #include #include #include // -------------------- #include // ----------------------------------------------------------- namespace ----- OSG_USING_NAMESPACE // ------------------------------------------------------------- OpenMesh ---- struct MeshTraits : public OpenMesh::Kernel_OSG::Traits { HalfedgeAttributes( OpenMesh::Attributes::PrevHalfedge); VertexAttributes ( OpenMesh::Attributes::Normal | OpenMesh::Attributes::Color ); FaceAttributes ( OpenMesh::Attributes::Normal ); }; typedef OpenMesh::Kernel_OSG::TriMesh_OSGArrayKernelT mesh_t; typedef OpenMesh::Subdivider::Uniform::LoopT< mesh_t > loop_t; typedef OpenMesh::Smoother::JacobiLaplaceSmootherT< mesh_t > smoother_t; // --------------------------------------------------------------- globals ---- class MeshContainer { public: typedef std::vector meshbag_t; const size_t InvalidIndex; public: MeshContainer() : InvalidIndex(size_t(-1)) { } ~MeshContainer() { meshbag_t::iterator it = meshes_.begin(); for(;it != meshes_.end(); ++it) delete *it; } size_t size() const { return meshes_.size(); } mesh_t& operator [] ( size_t idx ) { if (idx < meshes_.size()) return *(meshes_[idx]); throw std::range_error("Invalid index"); } const mesh_t& operator [] ( size_t idx ) const { if (idx < meshes_.size()) return *(meshes_[idx]); throw std::range_error("Invalid index"); } bool bind( osg::GeometryPtr geo ) { std::auto_ptr obj(new mesh_t); return (OpenMesh::Kernel_OSG::bind< mesh_t >( *obj, geo)) ? (meshes_.push_back(obj.release()), true) : false; } private: meshbag_t meshes_; private: // non-copyable MeshContainer( const MeshContainer& ); MeshContainer& operator = ( const MeshContainer& ); }; struct Globals { // OpenSG specific entities SimpleSceneManager* mgr; GLUTWindowPtr gwin; NodePtr root; std::vector geos; size_t sel; bool statistics; // OpenMesh specific entities MeshContainer meshes; } g; // -------------------------------------------------------------- forwards ---- void display(void); void reshape(int width, int height); void mouse(int button, int state, int x, int y); void keyboard(unsigned char key, int x, int y); void motion(int x, int y); // ---------------------------------------------------------------- helper ---- // setup the GLUT library which handles the windows for us int setupGLUT(int *argc, char *argv[]) { glutInit(argc, argv); glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE); int winid = glutCreateWindow("OpenMesh within OpenSG"); glutReshapeFunc(reshape); glutDisplayFunc(display); glutMouseFunc(mouse); glutMotionFunc(motion); glutKeyboardFunc(keyboard); return winid; } // -------------------------------------------------- locate geometry node ---- /* This function uses the fact that ::dcast() acts like dynamic_cast. It tries to dcast the core to a GeometryPtr, and tests the result to see if it actually was derived from Geometry. */ Action::ResultE bindGeo(NodePtr& node) { GeometryPtr geo = GeometryPtr::dcast(node->getCore()); if (geo!=NullFC) { if ( g.meshes.bind( geo ) ) { std::cout << " Geometry connected to OpenMesh object\n"; g.geos.push_back(geo); g.sel = g.meshes.size()-1; assert( g.geos.size() == g.meshes.size() ); } else std::cerr << " Warning! Could not bind the OpenMesh" << " object to the geometry!\n"; } return Action::Continue; } // ------------------------------------------------------------------ main ---- int main(int argc, char **argv) { // OSG init osgInit(argc,argv); int winid = setupGLUT(&argc, argv); // the connection between GLUT and OpenSG g.gwin = GLUTWindow::create(); g.gwin->setId(winid); g.gwin->init(); // -------------------- create root node with core std::cout << "Create root node with core\n"; g.root = Node::create(); NodeCorePtr core = Group::create(); osg::beginEditCP(g.root); { g.root->setCore(core); } osg::endEditCP(g.root); // -------------------- load the scene std::cout << "Load a scene from '" << argv[1] << "'\n"; NodePtr node = SceneFileHandler::the().read( argv[1] ); if ( node != NullFC ) { osg::beginEditCP(g.root); { g.root->addChild(node); } osg::endEditCP(g.root); } else return 1; // -------------------- bind all geometry nodes to an OpenMesh std::cout << "Bind all geometry nodes\n"; traverse(g.root, osgTypedFunctionFunctor1CPtrRef(bindGeo)); if (!g.meshes.size()) { std::cerr << " No geometry found. Nothing to do!\n"; return 1; } else std::cout << " Number of bound geometry: " << g.meshes.size() << std::endl; // -------------------- create the SimpleSceneManager helper std::cout << "Create simple scene manager\n"; g.mgr = new SimpleSceneManager; // tell the manager what to manage g.mgr->setWindow(g.gwin); g.mgr->setRoot (g.root); // g.mgr->useOpenSGLogo(); g.mgr->setStatistics(false); // -------------------- show the whole scene std::cout << "Display everything\n"; g.mgr->showAll(); glutMainLoop(); return 0; } // --------------------------------------------------------------- display ---- void display(void) { g.mgr->redraw(); } // --------------------------------------------------------------- reshape ---- void reshape(int w, int h) { g.mgr->resize(w, h); glutPostRedisplay(); } // ----------------------------------------------------------------- mouse ---- void mouse(int button, int state, int x, int y) { if (state) { g.mgr->mouseButtonRelease(button, x, y); // if ( g.mode & FLYMODE ) // glutIdleFunc(NULL); } else { g.mgr->mouseButtonPress(button, x, y); // if ( g.mode & FLYMODE ) // glutIdleFunc(idle); } glutPostRedisplay(); } // -------------------------------------------------------------- keyboard ---- void keyboard(unsigned char key, int x, int y) { #define MESH g.meshes[g.sel] #define GEO g.geos[g.sel] #define YN(b) (b?"yes":"no") OpenMesh::Utils::Timer t; using namespace std; switch(key) { case 27: // escape exit(0); break; case 'i': { cout << "OpenMesh information for obj #" << g.sel << ":\n"; cout << " #Vertices: " << MESH.n_vertices() << endl; cout << " #Faces: " << MESH.n_faces() << endl; cout << " #Edges: " << MESH.n_edges() << endl; cout << " v. normal: " << YN(MESH.has_vertex_normals()) << endl; cout << " v. color: " << YN(MESH.has_vertex_colors()) << endl; cout << "v. texcoord: " << YN(MESH.has_vertex_texcoords()) << endl; cout << " f. normal: " << YN(MESH.has_face_normals()) << endl; cout << " f. color: " << YN(MESH.has_face_colors()) << endl; break; } case 'I': cout << "Geometry information for obj #" << g.sel << ":\n"; cout << " #Types: " << GEO->getTypes()->size() << endl; cout << " #Lengths: " << GEO->getLengths()->size() << endl; cout << " #Indices: " << GEO->getIndices()->size() << endl; cout << "#Positions: " << GEO->getPositions()->size() << endl; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if ((size_t(key)-size_t('0')) < g.meshes.size()) { g.sel = (size_t(key)-size_t('0')); cout << "Selected geometry #" << g.sel << endl; } break; case '+': g.sel = ++g.sel % g.meshes.size(); cout << "Selected geometry #" << g.sel << endl; break; case '-': g.sel = (g.sel + g.meshes.size()-1) % g.meshes.size(); cout << "Selected geometry #" << g.sel << endl; break; case 'S': g.mgr->setStatistics( g.statistics=!g.statistics ); g.statistics ? cout << "Statistics enabled.\n" : cout << "Statistics disabled.\n"; glutPostRedisplay(); break; case 'w': { OpenMesh::IO::Options opt; if (MESH.has_vertex_colors()) opt += OpenMesh::IO::Options::VertexColor; if (MESH.has_face_colors()) opt += OpenMesh::IO::Options::FaceColor; if (MESH.has_vertex_normals()) opt += OpenMesh::IO::Options::VertexNormal; std::string ofname; { std::stringstream ostr; ostr << "object-" << g.sel << ".om"; ofname = ostr.str(); } cout << "Writing OpenMesh of geometry #" << g.sel << " to " << ofname << std::endl; t.start(); bool rc = OpenMesh::IO::write_mesh( MESH, ofname, opt); t.stop(); rc ? cout << " Done (" << t.as_string() << ")\n" : cout << " Failed to store OpenMesh\n"; break; } case 's': { cout << "Appyling two smoothing steps on selected geometry.."; t.start(); smoother_t smoother( g.meshes[g.sel] ); smoother.initialize( smoother_t::Tangential, smoother_t::C1 ); beginEditCP(g.geos[g.sel]); smoother.smooth(2); endEditCP(g.geos[g.sel]); t.stop(); cout << "done. " << t.as_string() << endl; glutPostRedisplay(); break; } case 't': { cout << "Applying two smoothing steps on all bound geometry.."; t.start(); for(size_t i = 0; i < g.meshes.size(); ++i) { smoother_t smoother( g.meshes[i] ); smoother.initialize( smoother_t::Tangential, smoother_t::C1 ); beginEditCP(g.geos[i]); smoother.smooth(2); endEditCP(g.geos[i]); } t.stop(); cout << "done. " << t.as_string() << endl; glutPostRedisplay(); break; } case 'c': { OpenMesh::IO::Options opt; if (MESH.has_vertex_colors()) opt += OpenMesh::IO::Options::VertexColor; if (MESH.has_face_colors()) opt += OpenMesh::IO::Options::FaceColor; if (MESH.has_vertex_normals()) opt += OpenMesh::IO::Options::VertexNormal; mesh_t m(MESH); std::string ofname; { std::stringstream ostr; ostr << "copy-" << g.sel << ".om"; ofname = ostr.str(); } cout << "Writing copy of geometry #" << g.sel << " to " << ofname << std::endl; t.start(); bool rc = OpenMesh::IO::write_mesh( MESH, ofname, opt); t.stop(); rc ? cout << " Done (" << t.as_string() << ")\n" : cout << " Failed to store OpenMesh\n"; OpenMesh::IO::write_mesh( m, ofname ); break; } case 'u': { cout << "Applying one step of loop subdivision.."; t.start(); loop_t loop; beginEditCP( GEO ); loop( MESH, 1 ); MESH.update_normals(); endEditCP( GEO ); t.stop(); cout << "done. " << t.as_string() << endl; glutPostRedisplay(); break; } default: cout << "key [0x" << setw(4) << hex << key << dec << "]\n"; } #undef YN #undef MESH } //----------------------------------------------------------------- motion ---- void motion(int x, int y) { g.mgr->mouseMove(x, y); glutPostRedisplay(); }