- Timestamp:
- 03/21/12 18:36:20 (15 months ago)
- Files:
-
- 1 modified
Legend:
- Unmodified
- Added
- Removed
-
OpenSceneGraph/trunk/src/osgPlugins/obj/OBJWriterNodeVisitor.cpp
r12292 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 */ … … 19 19 #include <osg/io_utils> 20 20 #include "OBJWriterNodeVisitor.h" 21 21 22 22 23 23 … … 25 25 class ValueVisitor : public osg::ValueVisitor { 26 26 public: 27 ValueVisitor(std::ostream& fout, const osg::Matrix& m = osg::Matrix::identity(), bool isNormal = false) : 28 osg::ValueVisitor(), 29 _fout(fout), 30 _m(m), 27 ValueVisitor(std::ostream& fout, const osg::Matrix& m = osg::Matrix::identity(), bool isNormal = false) : 28 osg::ValueVisitor(), 29 _fout(fout), 30 _m(m), 31 31 _isNormal(isNormal) 32 { 32 { 33 33 _applyMatrix = (_m != osg::Matrix::identity()); 34 34 if (_isNormal) _origin = osg::Vec3(0,0,0) * _m; 35 35 } 36 37 virtual void apply (osg::Vec2 & inv) 38 { 39 _fout << inv[0] << ' ' << inv[1]; 40 } 41 42 virtual void apply (osg::Vec3 & inv) 43 { 36 37 virtual void apply (osg::Vec2 & inv) 38 { 39 _fout << inv[0] << ' ' << inv[1]; 40 } 41 42 virtual void apply (osg::Vec3 & inv) 43 { 44 44 osg::Vec3 v(inv); 45 45 if (_applyMatrix) v = (_isNormal) ? (v * _m) - _origin : v * _m; 46 _fout << v[0] << ' ' << v[1] << ' ' << v[2]; 47 } 48 46 _fout << v[0] << ' ' << v[1] << ' ' << v[2]; 47 } 48 49 49 virtual void apply (osg::Vec2b & inv) 50 { 51 _fout << inv[0] << ' ' << inv[1]; 52 } 53 54 virtual void apply (osg::Vec3b & inv) 55 { 50 { 51 _fout << inv[0] << ' ' << inv[1]; 52 } 53 54 virtual void apply (osg::Vec3b & inv) 55 { 56 56 osg::Vec3 v(inv[0], inv[1], inv[2]); 57 57 if (_applyMatrix) v = (_isNormal) ? (v * _m) - _origin : v * _m; 58 _fout << v[0] << ' ' << v[1] << ' ' << v[2]; 59 } 60 61 virtual void apply (osg::Vec2s & inv) 62 { 63 _fout << inv[0] << ' ' << inv[1]; 64 } 65 66 virtual void apply (osg::Vec3s & inv) 67 { 58 _fout << v[0] << ' ' << v[1] << ' ' << v[2]; 59 } 60 61 virtual void apply (osg::Vec2s & inv) 62 { 63 _fout << inv[0] << ' ' << inv[1]; 64 } 65 66 virtual void apply (osg::Vec3s & inv) 67 { 68 68 osg::Vec3 v(inv[0], inv[1], inv[2]); 69 69 if (_applyMatrix) v = (_isNormal) ? (v * _m) - _origin : v * _m; 70 _fout << v[0] << ' ' << v[1] << ' ' << v[2]; 70 _fout << v[0] << ' ' << v[1] << ' ' << v[2]; 71 71 } 72 72 private: … … 82 82 /** writes all primitives of a primitive-set out to a stream, decomposes quads to triangles, line-strips to lines etc */ 83 83 class ObjPrimitiveIndexWriter : public osg::PrimitiveIndexFunctor { 84 84 85 85 public: 86 ObjPrimitiveIndexWriter(std::ostream& fout,osg::Geometry* geo, unsigned int normalIndex, unsigned int lastVertexIndex, unsigned int lastNormalIndex, unsigned int lastTexIndex) : 87 osg::PrimitiveIndexFunctor(), 86 ObjPrimitiveIndexWriter(std::ostream& fout,osg::Geometry* geo, unsigned int normalIndex, unsigned int lastVertexIndex, unsigned int lastNormalIndex, unsigned int lastTexIndex) : 87 osg::PrimitiveIndexFunctor(), 88 88 _fout(fout), 89 89 _lastVertexIndex(lastVertexIndex), … … 96 96 { 97 97 } 98 98 99 99 virtual void setVertexArray(unsigned int,const osg::Vec2*) {} 100 100 … … 102 102 103 103 virtual void setVertexArray(unsigned int,const osg::Vec4* ) {} 104 104 105 105 virtual void setVertexArray(unsigned int,const osg::Vec2d*) {} 106 106 … … 108 108 109 109 virtual void setVertexArray(unsigned int,const osg::Vec4d* ) {} 110 111 void write(unsigned int i) 110 111 void write(unsigned int i) 112 112 { 113 113 _fout << (i + _lastVertexIndex) << "/"; 114 115 if (_hasTexCoords || _hasNormalCoords) 114 115 if (_hasTexCoords || _hasNormalCoords) 116 116 { 117 117 if (_hasTexCoords) 118 118 _fout << (i + _lastTexIndex); 119 119 _fout << "/"; 120 if (_hasNormalCoords) 120 if (_hasNormalCoords) 121 121 { 122 122 if (_geo->getNormalBinding() == osg::Geometry::BIND_PER_VERTEX) … … 128 128 _fout << " "; 129 129 } 130 130 131 131 // operator for triangles 132 132 void writeTriangle(unsigned int i1, unsigned int i2, unsigned int i3) … … 140 140 if(_geo->getNormalBinding() && _geo->getNormalBinding() == osg::Geometry::BIND_PER_PRIMITIVE) ++_normalIndex; 141 141 } 142 142 143 143 // operator for lines 144 void writeLine(unsigned int i1, unsigned int i2) 144 void writeLine(unsigned int i1, unsigned int i2) 145 145 { 146 146 _fout << "l "; … … 151 151 if(_geo->getNormalBinding() && _geo->getNormalBinding() == osg::Geometry::BIND_PER_PRIMITIVE) ++_normalIndex; 152 152 } 153 153 154 154 // operator for points 155 void writePoint(unsigned int i1) 155 void writePoint(unsigned int i1) 156 156 { 157 157 _fout << "p "; … … 181 181 } 182 182 183 virtual void drawArrays(GLenum mode,GLint first,GLsizei count); 184 183 virtual void drawArrays(GLenum mode,GLint first,GLsizei count); 184 185 185 virtual void drawElements(GLenum mode,GLsizei count,const GLubyte* indices) 186 186 { … … 190 190 { 191 191 drawElementsImplementation<GLushort>(mode, count, indices); 192 } 192 } 193 193 194 194 virtual void drawElements(GLenum mode,GLsizei count,const GLuint* indices) 195 195 { 196 196 drawElementsImplementation<GLuint>(mode, count, indices); 197 } 197 } 198 198 199 199 protected: 200 201 template<typename T>void drawElementsImplementation(GLenum mode, GLsizei count, const T* indices) 200 201 template<typename T>void drawElementsImplementation(GLenum mode, GLsizei count, const T* indices) 202 202 { 203 203 if (indices==0 || count==0) return; 204 204 205 205 typedef const T* IndexPointer; 206 206 207 207 switch(mode) 208 208 { … … 212 212 for(IndexPointer iptr=indices;iptr<ilast;iptr+=3) 213 213 writeTriangle(*iptr,*(iptr+1),*(iptr+2)); 214 214 215 215 break; 216 216 } … … 261 261 IndexPointer ilast = &indices[count]; 262 262 for(IndexPointer iptr=indices;iptr<ilast;++iptr) 263 263 264 264 { 265 265 writePoint(*iptr); … … 279 279 case(GL_LINE_STRIP): 280 280 { 281 281 282 282 IndexPointer ilast = &indices[count]; 283 283 for(IndexPointer iptr=indices+1;iptr<ilast;iptr+=2) … … 303 303 break; 304 304 } 305 } 306 305 } 306 307 307 private: 308 308 … … 374 374 case(GL_POINTS): 375 375 { 376 376 377 377 for(GLsizei i=0;i<count;++i) 378 378 { … … 408 408 } 409 409 default: 410 OSG_WARN << "OBJWriterNodeVisitor :: can't handle mode " << mode << std::endl; 411 break; 412 } 413 } 414 410 OSG_WARN << "OBJWriterNodeVisitor :: can't handle mode " << mode << std::endl; 411 break; 412 } 413 } 414 415 415 416 416 OBJWriterNodeVisitor::OBJMaterial::OBJMaterial(osg::Material* mat, osg::Texture* tex) : … … 422 422 static unsigned int s_objmaterial_id = 0; 423 423 ++s_objmaterial_id; 424 std::stringstream ss; 424 std::stringstream ss; 425 425 ss << "material_" << s_objmaterial_id; 426 426 name = ss.str(); 427 427 428 428 if (mat) { 429 429 diffuse = mat->getDiffuse(osg::Material::FRONT); … … 431 431 specular = mat->getSpecular(osg::Material::FRONT); 432 432 } 433 433 434 434 if (tex) { 435 435 osg::Image* img = tex->getImage(0); 436 436 if ((img) && (!img->getFileName().empty())) 437 437 image = img->getFileName(); 438 439 } 440 438 439 } 440 441 441 } 442 442 443 443 std::ostream& operator<<(std::ostream& fout, const OBJWriterNodeVisitor::OBJMaterial& mat) { 444 444 445 445 fout << "newmtl " << mat.name << std::endl; 446 446 fout << " " << "Ka " << mat.ambient << std::endl; 447 447 fout << " " << "Kd " << mat.diffuse << std::endl; 448 448 fout << " " << "Ks " << mat.specular << std::endl; 449 449 450 450 if(!mat.image.empty()) 451 451 fout << " " << "map_Kd " << mat.image << std::endl; 452 452 453 453 return fout; 454 455 } 456 457 void OBJWriterNodeVisitor::writeMaterials(std::ostream& fout) 454 455 } 456 457 void OBJWriterNodeVisitor::writeMaterials(std::ostream& fout) 458 458 { 459 459 for(MaterialMap::iterator i = _materialMap.begin(); i != _materialMap.end(); ++i) … … 465 465 466 466 std::string OBJWriterNodeVisitor::getUniqueName(const std::string& defaultvalue) { 467 467 468 468 std::string name = ""; 469 469 for(std::list<std::string>::iterator i = _nameStack.begin(); i != _nameStack.end(); ++i) { … … 471 471 name += (*i); 472 472 } 473 473 474 474 if (!defaultvalue.empty()) 475 475 name += "_" +defaultvalue; 476 476 477 477 if (_nameMap.find(name) == _nameMap.end()) 478 478 _nameMap.insert(std::make_pair(name, 0u)); 479 479 480 480 std::stringstream ss; 481 481 ss << name << "_" << _nameMap[name]; … … 489 489 if (array == NULL) 490 490 return; 491 491 492 492 ValueVisitor vv(_fout, m, isNormal); 493 493 _fout << std::endl; … … 497 497 _fout << std::endl; 498 498 } 499 499 500 500 _fout << "# " << array->getNumElements() << " elements written" << std::endl; 501 502 } 503 504 void OBJWriterNodeVisitor::processStateSet(osg::StateSet* ss) 501 502 } 503 504 void OBJWriterNodeVisitor::processStateSet(osg::StateSet* ss) 505 505 { 506 506 if (_materialMap.find(ss) != _materialMap.end()) { … … 508 508 return; 509 509 } 510 510 511 511 osg::Material* mat = dynamic_cast<osg::Material*>(ss->getAttribute(osg::StateAttribute::MATERIAL)); 512 512 osg::Texture* tex = dynamic_cast<osg::Texture*>(ss->getTextureAttribute(0, osg::StateAttribute::TEXTURE)); 513 514 if (mat || tex) 513 514 if (mat || tex) 515 515 { 516 516 _materialMap.insert(std::make_pair(osg::ref_ptr<osg::StateSet>(ss), OBJMaterial(mat, tex))); 517 517 _fout << "usemtl " << _materialMap[ss].name << std::endl; 518 518 } 519 519 520 520 } 521 521 … … 524 524 _fout << std::endl; 525 525 _fout << "o " << getUniqueName( geo->getName().empty() ? geo->className() : geo->getName() ) << std::endl; 526 526 527 527 processStateSet(_currentStateSet.get()); 528 528 529 529 processArray("v", geo->getVertexArray(), m, false); 530 530 processArray("vn", geo->getNormalArray(), m, true); 531 531 processArray("vt", geo->getTexCoordArray(0)); // we support only tex-unit 0 532 532 unsigned int normalIndex = 0; 533 for(unsigned int i = 0; i < geo->getNumPrimitiveSets(); ++i) 533 for(unsigned int i = 0; i < geo->getNumPrimitiveSets(); ++i) 534 534 { 535 535 osg::PrimitiveSet* ps = geo->getPrimitiveSet(i); 536 536 537 537 ObjPrimitiveIndexWriter pif(_fout, geo, normalIndex, _lastVertexIndex, _lastNormalIndex, _lastTexIndex); 538 538 ps->accept(pif); 539 539 540 540 if(geo->getNormalArray() && geo->getNormalBinding() == osg::Geometry::BIND_PER_PRIMITIVE_SET) 541 541 ++normalIndex; 542 542 } 543 if (geo->getVertexArray()) 543 if (geo->getVertexArray()) 544 544 _lastVertexIndex += geo->getVertexArray()->getNumElements(); 545 545 if (geo->getNormalArray()) … … 547 547 if(geo->getTexCoordArray(0)) 548 548 _lastTexIndex += geo->getTexCoordArray(0)->getNumElements(); 549 549 550 550 } 551 551 … … 563 563 { 564 564 pushStateSet(g->getStateSet()); 565 565 566 566 processGeometry(g,m); 567 567 568 568 popStateSet(g->getStateSet()); 569 569 }
