- Timestamp:
- 03/21/12 18:36:20 (15 months ago)
- Files:
-
- 1 modified
Legend:
- Unmodified
- Added
- Removed
-
OpenSceneGraph/trunk/src/osgPlugins/obj/ReaderWriterOBJ.cpp
r13006 r13041 9 9 * texture coord arrays, bug fixes, and support for texture mapping. 10 10 * 11 * Writing support added 2007 by Stephan Huber, http://digitalmind.de, 11 * Writing support added 2007 by Stephan Huber, http://digitalmind.de, 12 12 * some ideas taken from the dae-plugin 13 13 * 14 * The Open Scene Graph (OSG) is a cross platform C++/OpenGL library for 15 * real-time rendering of large 3D photo-realistic models. 14 * The Open Scene Graph (OSG) is a cross platform C++/OpenGL library for 15 * real-time rendering of large 3D photo-realistic models. 16 16 * The OSG homepage is http://www.openscenegraph.org/ 17 17 */ … … 79 79 80 80 virtual ReadResult readNode(std::istream& fin, const Options* options) const; 81 82 virtual WriteResult writeObject(const osg::Object& obj,const std::string& fileName,const Options* options=NULL) const 81 82 virtual WriteResult writeObject(const osg::Object& obj,const std::string& fileName,const Options* options=NULL) const 83 83 { 84 84 const osg::Node* node = dynamic_cast<const osg::Node*>(&obj); 85 85 if (node) 86 86 return writeNode(*node, fileName, options); 87 else 88 return WriteResult(WriteResult::FILE_NOT_HANDLED); 89 } 90 91 virtual WriteResult writeNode(const osg::Node& node,const std::string& fileName,const Options* options =NULL) const 92 { 87 else 88 return WriteResult(WriteResult::FILE_NOT_HANDLED); 89 } 90 91 virtual WriteResult writeNode(const osg::Node& node,const std::string& fileName,const Options* options =NULL) const 92 { 93 93 if (!acceptsExtension(osgDB::getFileExtension(fileName))) 94 return WriteResult(WriteResult::FILE_NOT_HANDLED); 95 94 return WriteResult(WriteResult::FILE_NOT_HANDLED); 95 96 96 osgDB::ofstream f(fileName.c_str()); 97 97 std::string materialFile = osgDB::getNameLessExtension(fileName) + ".mtl"; 98 98 OBJWriterNodeVisitor nv(f, osgDB::getSimpleFileName(materialFile)); 99 99 100 100 // we must cast away constness 101 101 (const_cast<osg::Node*>(&node))->accept(nv); 102 102 103 103 osgDB::ofstream mf(materialFile.c_str()); 104 104 nv.writeMaterials(mf); 105 106 return WriteResult(WriteResult::FILE_SAVED); 107 } 108 109 110 virtual WriteResult writeObject(const osg::Object& obj,std::ostream& fout,const Options* options=NULL) const 105 106 return WriteResult(WriteResult::FILE_SAVED); 107 } 108 109 110 virtual WriteResult writeObject(const osg::Object& obj,std::ostream& fout,const Options* options=NULL) const 111 111 { 112 112 const osg::Node* node = dynamic_cast<const osg::Node*>(&obj); 113 113 if (node) 114 114 return writeNode(*node, fout, options); 115 else 116 return WriteResult(WriteResult::FILE_NOT_HANDLED); 117 } 118 119 virtual WriteResult writeNode(const osg::Node& node,std::ostream& fout,const Options* =NULL) const 120 { 115 else 116 return WriteResult(WriteResult::FILE_NOT_HANDLED); 117 } 118 119 virtual WriteResult writeNode(const osg::Node& node,std::ostream& fout,const Options* =NULL) const 120 { 121 121 // writing to a stream does not support materials 122 122 123 123 OBJWriterNodeVisitor nv(fout); 124 124 125 125 // we must cast away constness 126 126 (const_cast<osg::Node*>(&node))->accept(nv); 127 128 return WriteResult(WriteResult::FILE_SAVED); 127 128 return WriteResult(WriteResult::FILE_SAVED); 129 129 } 130 130 … … 146 146 147 147 typedef std::map< std::string, osg::ref_ptr<osg::StateSet> > MaterialToStateSetMap; 148 148 149 149 void buildMaterialToStateSetMap(obj::Model& model, MaterialToStateSetMap& materialToSetSetMapObj, ObjOptionsStruct& localOptions, const Options* options) const; 150 150 151 151 osg::Geometry* convertElementListToGeometry(obj::Model& model, obj::Model::ElementList& elementList, ObjOptionsStruct& localOptions) const; 152 152 153 153 osg::Node* convertModelToSceneGraph(obj::Model& model, ObjOptionsStruct& localOptions, const Options* options) const; 154 154 155 155 inline osg::Vec3 transformVertex(const osg::Vec3& vec, const bool rotate) const ; 156 156 inline osg::Vec3 transformNormal(const osg::Vec3& vec, const bool rotate) const ; 157 157 158 158 ObjOptionsStruct parseOptions(const Options* options) const; 159 159 … … 199 199 { 200 200 osg::ref_ptr< osg::Image > image; 201 if ( !model.getDatabasePath().empty() ) 202 { 203 // first try with database path of parent. 201 if ( !model.getDatabasePath().empty() ) 202 { 203 // first try with database path of parent. 204 204 image = osgDB::readRefImageFile(model.getDatabasePath()+'/'+filename, options); 205 205 } 206 206 207 207 if ( !image.valid() ) 208 208 { … … 231 231 texture->setWrap(osg::Texture2D::WRAP_T, textureWrapMode); 232 232 stateset->setTextureAttributeAndModes( texture_unit, texture,osg::StateAttribute::ON ); 233 233 234 234 if ( map.type == obj::Material::Map::REFLECTION ) 235 235 { … … 238 238 stateset->setTextureAttributeAndModes( texture_unit,texgen,osg::StateAttribute::ON ); 239 239 } 240 240 241 241 if ( image->isImageTranslucent()) 242 242 { … … 293 293 } 294 294 } 295 295 296 296 if (numNotBlack==0 && numBlack!=0) 297 297 { … … 310 310 } 311 311 } 312 312 313 313 for(obj::Model::MaterialMap::iterator itr = model.materialMap.begin(); 314 314 itr != model.materialMap.end(); … … 316 316 { 317 317 obj::Material& material = itr->second; 318 318 319 319 osg::ref_ptr< osg::StateSet > stateset = new osg::StateSet; 320 320 … … 338 338 } 339 339 osg_material->setShininess(osg::Material::FRONT_AND_BACK,(material.Ns/1000.0f)*128.0f ); // note OBJ shiniess is 0..1000. 340 340 341 341 if (material.ambient[3]!=1.0 || 342 342 material.diffuse[3]!=1.0 || … … 348 348 } 349 349 } 350 351 // If the user has explicitly set the required texture type to unit map via the options 350 351 // If the user has explicitly set the required texture type to unit map via the options 352 352 // string, then we load ONLY those textures that are in the map. 353 353 if(localOptions.textureUnitAllocation.size()>0) … … 396 396 } 397 397 } 398 398 399 399 if (isTransparent) 400 400 { … … 409 409 osg::Geometry* ReaderWriterOBJ::convertElementListToGeometry(obj::Model& model, obj::Model::ElementList& elementList, ObjOptionsStruct& localOptions) const 410 410 { 411 411 412 412 unsigned int numVertexIndices = 0; 413 413 unsigned int numNormalIndices = 0; 414 414 unsigned int numTexCoordIndices = 0; 415 415 416 416 unsigned int numPointElements = 0; 417 417 unsigned int numPolylineElements = 0; … … 419 419 420 420 obj::Model::ElementList::iterator itr; 421 421 422 422 if (localOptions.generateFacetNormals == true) { 423 423 for(itr=elementList.begin(); … … 428 428 if (element.dataType==obj::Element::POINTS || element.dataType==obj::Element::POLYLINE) 429 429 continue; 430 430 431 431 if (element.normalIndices.size() == 0) { 432 432 // fill in the normals … … 451 451 } 452 452 } 453 454 455 453 454 455 456 456 for(itr=elementList.begin(); 457 457 itr!=elementList.end(); … … 471 471 472 472 if (numVertexIndices==0) return 0; 473 473 474 474 if (numNormalIndices!=0 && numNormalIndices!=numVertexIndices) 475 475 { … … 477 477 numNormalIndices = 0; 478 478 } 479 479 480 480 if (numTexCoordIndices!=0 && numTexCoordIndices!=numVertexIndices) 481 481 { … … 483 483 numTexCoordIndices = 0; 484 484 } 485 485 486 486 osg::Vec3Array* vertices = numVertexIndices ? new osg::Vec3Array : 0; 487 487 osg::Vec3Array* normals = numNormalIndices ? new osg::Vec3Array : 0; 488 488 osg::Vec2Array* texcoords = numTexCoordIndices ? new osg::Vec2Array : 0; 489 489 490 490 if (vertices) vertices->reserve(numVertexIndices); 491 491 if (normals) normals->reserve(numNormalIndices); 492 492 if (texcoords) texcoords->reserve(numTexCoordIndices); 493 493 494 494 osg::Geometry* geometry = new osg::Geometry; 495 495 if (vertices) geometry->setVertexArray(vertices); … … 503 503 geometry->setTexCoordArray(0,texcoords); 504 504 } 505 505 506 506 507 507 if (numPointElements>0) … … 547 547 geometry->addPrimitiveSet(drawArrays); 548 548 } 549 549 550 550 if (numPolylineElements>0) 551 551 { … … 598 598 { 599 599 unsigned int startPos = vertices->size(); 600 600 601 601 #ifdef USE_DRAWARRAYLENGTHS 602 602 osg::DrawArrayLengths* drawArrayLengths = new osg::DrawArrayLengths(GL_POLYGON,startPos); … … 612 612 { 613 613 614 614 615 615 616 616 … … 634 634 #endif 635 635 636 636 637 637 if (model.needReverse(element)) 638 638 { … … 698 698 699 699 } 700 700 701 701 return geometry; 702 702 } … … 718 718 ++itr) 719 719 { 720 720 721 721 const obj::ElementState& es = itr->first; 722 722 obj::Model::ElementList& el = itr->second; … … 734 734 osg::StateSet* stateset = materialToStateSetMap[es.materialName].get(); 735 735 geometry->setStateSet(stateset); 736 736 737 737 // tesseleate any large polygons 738 738 if (!localOptions.noTesselateLargePolygons) … … 741 741 tessellator.retessellatePolygons(*geometry); 742 742 } 743 743 744 744 // tri strip polygons to improve graphics peformance 745 745 if (!localOptions.noTriStripPolygons) … … 748 748 tsv.stripify(*geometry); 749 749 } 750 750 751 751 // if no normals present add them. 752 752 if (localOptions.generateFacetNormals==false && (!geometry->getNormalArray() || geometry->getNormalArray()->getNumElements()==0)) … … 759 759 osg::Geode* geode = new osg::Geode; 760 760 geode->addDrawable(geometry); 761 761 762 762 if (es.objectName.empty()) 763 763 { … … 805 805 pre_equals = opt.substr(0,found); 806 806 post_equals = opt.substr(found+1); 807 } 807 } 808 808 else 809 809 { … … 814 814 { 815 815 localOptions.rotate = false; 816 } 816 } 817 817 else if (pre_equals == "noTesselateLargePolygons") 818 818 { 819 819 localOptions.noTesselateLargePolygons = true; 820 } 820 } 821 821 else if (pre_equals == "noTriStripPolygons") 822 822 { … … 828 828 } 829 829 else if (post_equals.length()>0) 830 { 831 obj::Material::Map::TextureMapType type = obj::Material::Map::UNKNOWN; 830 { 831 obj::Material::Map::TextureMapType type = obj::Material::Map::UNKNOWN; 832 832 // Now we check to see if we have anything forcing a texture allocation 833 833 if (pre_equals == "DIFFUSE") type = obj::Material::Map::DIFFUSE; … … 839 839 else if (pre_equals == "DISPLACEMENT") type = obj::Material::Map::DISPLACEMENT; 840 840 else if (pre_equals == "REFLECTION") type = obj::Material::Map::REFLECTION; 841 841 842 842 if (type!=obj::Material::Map::UNKNOWN) 843 843 { … … 861 861 std::string fileName = osgDB::findDataFile( file, options ); 862 862 if (fileName.empty()) return ReadResult::FILE_NOT_FOUND; 863 864 863 864 865 865 osgDB::ifstream fin(fileName.c_str()); 866 866 if (fin) 867 867 { 868 869 // code for setting up the database path so that internally referenced file are searched for on relative paths. 868 869 // code for setting up the database path so that internally referenced file are searched for on relative paths. 870 870 osg::ref_ptr<Options> local_opt = options ? static_cast<Options*>(options->clone(osg::CopyOp::SHALLOW_COPY)) : new Options; 871 871 local_opt->setDatabasePath(osgDB::getFilePath(fileName)); … … 880 880 return node; 881 881 } 882 882 883 883 return ReadResult::FILE_NOT_HANDLED; 884 884 } … … 892 892 obj::Model model; 893 893 model.readOBJ(fin, options); 894 894 895 895 ObjOptionsStruct localOptions = parseOptions(options); 896 896 897 897 osg::Node* node = convertModelToSceneGraph(model, localOptions, options); 898 898 return node; 899 899 } 900 900 901 901 return ReadResult::FILE_NOT_HANDLED; 902 902 }
