diff --git a/src/osgPlugins/dae/daeRMaterials.cpp b/src/osgPlugins/dae/daeRMaterials.cpp index f0818f472..a7007fa6f 100644 --- a/src/osgPlugins/dae/daeRMaterials.cpp +++ b/src/osgPlugins/dae/daeRMaterials.cpp @@ -25,6 +25,8 @@ #include #include +#include + using namespace osgdae; void daeReader::processBindMaterial( domBind_material *bm, osg::Node *geo ) @@ -333,20 +335,8 @@ osg::StateAttribute **sa ) { osg::Vec4 col; domAny *dcol = (domAny*)(daeElement*)teq->getContents()[0]; - char *val = (char *)dcol->getValue(); - int cnt = 0; - while ( cnt < 4 && strlen( val ) != 0 ) - { - char *space = strchr( val, ' ' ); - if ( space != NULL ) - { - *space = 0; - } - int tmp = atoi( val ); - col[cnt] = tmp; - cnt++; - val = space + 1; - } + std::istringstream diffuse_colour((const char *)dcol->getValue()); + diffuse_colour >> col.r() >> col.g() >> col.b() >> col.a(); mat->setDiffuse( osg::Material::FRONT_AND_BACK, col ); retVal = true; break; diff --git a/src/osgPlugins/dae/daeWGeometry.cpp b/src/osgPlugins/dae/daeWGeometry.cpp index d4511b35f..bf02ca23d 100644 --- a/src/osgPlugins/dae/daeWGeometry.cpp +++ b/src/osgPlugins/dae/daeWGeometry.cpp @@ -31,12 +31,15 @@ void daeWriter::apply( osg::Geode &node ) debugPrint( node ); #endif + pushStateSet(node.getStateSet()); + unsigned int count = node.getNumDrawables(); for ( unsigned int i = 0; i < count; i++ ) { osg::Geometry *g = node.getDrawable( i )->asGeometry(); if ( g != NULL ) { + pushStateSet(g->getStateSet()); std::map< osg::Geometry*, domGeometry *>::iterator iter = geometryMap.find( g ); if ( iter != geometryMap.end() ) { @@ -44,11 +47,8 @@ void daeWriter::apply( osg::Geode &node ) std::string url = "#" + std::string( iter->second->getId() ); ig->setUrl( url.c_str() ); - //osg::notify( osg::WARN ) << "Found a duplicate Geometry " << url << std::endl; - if ( node.getStateSet() != NULL ) - { - processMaterial( node.getStateSet(), ig, iter->second->getId() ); - } + if (!stateSetStack.empty()) + processMaterial( currentStateSet.get(), ig, iter->second->getId() ); } else { @@ -78,17 +78,16 @@ void daeWriter::apply( osg::Geode &node ) geometryMap.insert( std::make_pair( g, geo ) ); #endif - if ( node.getStateSet() != NULL ) - { - processMaterial( node.getStateSet(), ig, name ); - } + if (!stateSetStack.empty()) + processMaterial( currentStateSet.get(), ig, name ); } + popStateSet(g->getStateSet()); } } lastVisited = GEODE; - traverse( node ); + popStateSet(node.getStateSet()); } /** append elements (verts, normals, colors and texcoord) for file write */ diff --git a/src/osgPlugins/dae/daeWMaterials.cpp b/src/osgPlugins/dae/daeWMaterials.cpp index 9c84c7e31..aeb198897 100644 --- a/src/osgPlugins/dae/daeWMaterials.cpp +++ b/src/osgPlugins/dae/daeWMaterials.cpp @@ -27,13 +27,14 @@ using namespace osgdae; void daeWriter::processMaterial( osg::StateSet *ss, domInstance_geometry *ig, const std::string &geoName ) { + osg::ref_ptr ssClean = CleanStateSet(ss); // Need to hold a ref to this or the materialMap.find() will delete it domBind_material *bm = daeSafeCast< domBind_material >( ig->createAndPlace( COLLADA_ELEMENT_BIND_MATERIAL ) ); domBind_material::domTechnique_common *tc = daeSafeCast< domBind_material::domTechnique_common >( bm->createAndPlace( "technique_common" ) ); domInstance_material *im = daeSafeCast< domInstance_material >( tc->createAndPlace( COLLADA_ELEMENT_INSTANCE_MATERIAL ) ); std::string symbol = geoName + "_material"; im->setSymbol( symbol.c_str() ); - std::map< osg::StateSet*, domMaterial* >::iterator iter = materialMap.find( ss ); + MaterialMap::iterator iter = materialMap.find( ssClean ); if ( iter != materialMap.end() ) { std::string url = "#" + std::string( iter->second->getId() ); @@ -47,7 +48,7 @@ void daeWriter::processMaterial( osg::StateSet *ss, domInstance_geometry *ig, co } domMaterial *mat = daeSafeCast< domMaterial >( lib_mats->createAndPlace( COLLADA_ELEMENT_MATERIAL ) ); - std::string name = ss->getName(); + std::string name = ssClean->getName(); if ( name.empty() ) { name = "material"; @@ -78,10 +79,10 @@ void daeWriter::processMaterial( osg::StateSet *ss, domInstance_geometry *ig, co pc_teq->setSid( "t0" ); domProfile_COMMON::domTechnique::domPhong *phong = daeSafeCast< domProfile_COMMON::domTechnique::domPhong >( pc_teq->createAndPlace( "phong" ) ); - osg::Texture *tex = static_cast(ss->getTextureAttribute( 0, osg::StateAttribute::TEXTURE )); - if ( ss->getTextureAttribute( 1, osg::StateAttribute::TEXTURE ) != NULL ) + osg::Texture *tex = static_cast(ssClean->getTextureAttribute( 0, osg::StateAttribute::TEXTURE )); + if ( ssClean->getTextureAttribute( 1, osg::StateAttribute::TEXTURE ) != NULL ) { - tex = static_cast(ss->getTextureAttribute( 1, osg::StateAttribute::TEXTURE )); + tex = static_cast(ssClean->getTextureAttribute( 1, osg::StateAttribute::TEXTURE )); } if ( tex != NULL && tex->getImage( 0 ) != NULL ) { @@ -93,12 +94,23 @@ void daeWriter::processMaterial( osg::StateSet *ss, domInstance_geometry *ig, co osg::Image *osgimg = tex->getImage( 0 ); domImage::domInit_from *imgif = daeSafeCast< domImage::domInit_from >( img->createAndPlace( "init_from" ) ); std::string imgstr = "/" + osgDB::convertFileNameToUnixStyle( osgDB::findDataFile( osgimg->getFileName() ) ); +#ifdef WIN32 + daeURI uri( _strlwr( (char *)imgstr.c_str() ) ); +#else daeURI uri( imgstr.c_str() ); +#endif uri.validate(); imgif->setValue( uri.getURI() ); //imgif->setValue( imgstr.c_str() ); //imgif->getValue().validate(); +#ifdef WIN32 + std::string docUriString = doc->getDocumentURI()->getFilepath(); + docUriString += doc->getDocumentURI()->getFile(); + daeURI docUri( _strlwr( (char *)docUriString.c_str() ) ); + imgif->getValue().makeRelativeTo( &docUri ); +#else imgif->getValue().makeRelativeTo( doc->getDocumentURI() ); +#endif //imgif->setValue( osgimg->getFileName().c_str() ); //osg::notify( osg::WARN ) << "original img filename " << osgimg->getFileName() << std::endl; //osg::notify( osg::WARN ) << "init_from filename " << imgstr << std::endl; @@ -237,8 +249,8 @@ void daeWriter::processMaterial( osg::StateSet *ss, domInstance_geometry *ig, co bvi->setInput_set( 0 ); //take care of blending if any - osg::BlendFunc *bf = static_cast< osg::BlendFunc * >( ss->getAttribute( osg::StateAttribute::BLENDFUNC ) ); - osg::BlendColor *bc = static_cast< osg::BlendColor * >( ss->getAttribute( osg::StateAttribute::BLENDCOLOR ) ); + osg::BlendFunc *bf = static_cast< osg::BlendFunc * >( ssClean->getAttribute( osg::StateAttribute::BLENDFUNC ) ); + osg::BlendColor *bc = static_cast< osg::BlendColor * >( ssClean->getAttribute( osg::StateAttribute::BLENDCOLOR ) ); if ( bc != NULL ) { domCommon_transparent_type *ctt = daeSafeCast< domCommon_transparent_type >( phong->createAndPlace( "transparent" ) ); @@ -263,7 +275,7 @@ void daeWriter::processMaterial( osg::StateSet *ss, domInstance_geometry *ig, co } } - osg::Material *osgmat = static_cast(ss->getAttribute( osg::StateAttribute::MATERIAL )); + osg::Material *osgmat = static_cast(ssClean->getAttribute( osg::StateAttribute::MATERIAL )); if ( osgmat != NULL ) { const osg::Vec4 &eCol = osgmat->getEmissionFrontAndBack()?osgmat->getEmission( osg::Material::FRONT_AND_BACK ):osgmat->getEmission( osg::Material::FRONT ); @@ -288,7 +300,7 @@ void daeWriter::processMaterial( osg::StateSet *ss, domInstance_geometry *ig, co //### check if we really have a texture - if ((tex == NULL) || (!cot->getTexture())) + if ( phong->getDiffuse() == NULL ) { cot = daeSafeCast< domCommon_color_or_texture_type >( phong->createAndPlace( "diffuse" ) ); col = daeSafeCast< domCommon_color_or_texture_type_complexType::domColor >( cot->createAndPlace( "color" ) ); @@ -309,7 +321,7 @@ void daeWriter::processMaterial( osg::StateSet *ss, domInstance_geometry *ig, co domAny *any = (domAny*)(daeElement*)teq->createAndPlace( "color" ); std::ostringstream colVal; - colVal << std::dec << " " << int(dCol[0]) << " " << int(dCol[1]) << " " << int(dCol[2]) << " " << int(dCol[3]); + colVal << dCol.r() << " " << dCol.g() << " " << dCol.b() << " " << dCol.a(); any->setValue( colVal.str().c_str() ); } @@ -325,5 +337,22 @@ void daeWriter::processMaterial( osg::StateSet *ss, domInstance_geometry *ig, co f->setValue( shininess ); } - materialMap.insert( std::make_pair( ss, mat ) ); + materialMap.insert( std::make_pair( ssClean, mat ) ); } + +osg::StateSet* daeWriter::CleanStateSet(osg::StateSet* pStateSet) const +{ + // TODO - clean out all the the attributes and modes not used to define materials + osg::StateSet* pCleanedStateSet = new osg::StateSet; + pCleanedStateSet->setTextureAttributeList(pStateSet->getTextureAttributeList()); + if (NULL != pStateSet->getAttribute(osg::StateAttribute::BLENDFUNC)) + pCleanedStateSet->setAttribute(pStateSet->getAttribute(osg::StateAttribute::BLENDFUNC)); + if (NULL != pStateSet->getAttribute(osg::StateAttribute::BLENDCOLOR)) + pCleanedStateSet->setAttribute(pStateSet->getAttribute(osg::StateAttribute::BLENDCOLOR)); + if (NULL != pStateSet->getAttribute(osg::StateAttribute::MATERIAL)) + pCleanedStateSet->setAttribute(pStateSet->getAttribute(osg::StateAttribute::MATERIAL)); + + return pCleanedStateSet; +} + + diff --git a/src/osgPlugins/dae/daeWriter.cpp b/src/osgPlugins/dae/daeWriter.cpp index f3fc4bb1a..29b37a423 100644 --- a/src/osgPlugins/dae/daeWriter.cpp +++ b/src/osgPlugins/dae/daeWriter.cpp @@ -23,8 +23,8 @@ using namespace osgdae; daeWriter::daeWriter( DAE *dae_, const std::string &fname,bool _usePolygons ) : osg::NodeVisitor( TRAVERSE_ALL_CHILDREN ), - dae(dae_), - usePolygons (_usePolygons) + dae(dae_), + usePolygons (_usePolygons) { success = true; @@ -54,6 +54,8 @@ daeWriter::daeWriter( DAE *dae_, const std::string &fname,bool _usePolygons ) : lib_mats = NULL; lastDepth = 0; + + currentStateSet = new osg::StateSet(); } daeWriter::~daeWriter() @@ -143,3 +145,35 @@ void daeWriter::createAssetTag() u->setName( "meter" ); u->setMeter( 1 ); } + +void daeWriter::traverse (osg::Node &node) +{ + pushStateSet(node.getStateSet()); + + osg::NodeVisitor::traverse( node ); + + popStateSet(node.getStateSet()); +} + +void daeWriter::pushStateSet(osg::StateSet* ss) +{ + if (NULL!=ss) { + // Save our current stateset + stateSetStack.push(currentStateSet.get()); + + // merge with node stateset + currentStateSet = static_cast(currentStateSet->clone(osg::CopyOp::SHALLOW_COPY)); + currentStateSet->merge(*ss); + } +} + + +void daeWriter::popStateSet(osg::StateSet* ss) +{ + if (NULL!=ss) { + // restore the previous stateset + currentStateSet = stateSetStack.top(); + stateSetStack.pop(); + } +} + diff --git a/src/osgPlugins/dae/daeWriter.h b/src/osgPlugins/dae/daeWriter.h index d8752cfdf..360ce3a72 100644 --- a/src/osgPlugins/dae/daeWriter.h +++ b/src/osgPlugins/dae/daeWriter.h @@ -15,6 +15,7 @@ #define _DAE_WRITER_H_ #include +#include #include #include @@ -106,6 +107,8 @@ public: //virtual void apply( osg::ClearNode &node) //virtual void apply( osg::OccluderNode &node) + void traverse (osg::Node &node); + /*protected: struct MeshData { domMesh *mesh; @@ -130,6 +133,10 @@ protected: //methods void createAssetTag(); + void pushStateSet(osg::StateSet* ss); + + void popStateSet(osg::StateSet* ss); + protected: //members DAE *dae; daeDocument *doc; @@ -147,15 +154,37 @@ protected: //members NodeType lastVisited; unsigned int lastDepth; + struct CompareStateSet + { + bool operator()(const osg::ref_ptr& ss1, const osg::ref_ptr& ss2) const + { + //std::cout << "CompareStateSet: " << ss1->compare(*ss2, false) << " " << ss1 << " " << ss2 << std::endl; + return ss1->compare(*ss2, true) < 0; + } + }; + + + std::map< std::string, int > uniqueNames; std::map< osg::Geometry*, domGeometry * > geometryMap; - std::map< osg::StateSet*, domMaterial * > materialMap; + + typedef std::map< osg::ref_ptr, domMaterial *, CompareStateSet> MaterialMap; + + MaterialMap materialMap; + + typedef std::stack > StateSetStack; + + StateSetStack stateSetStack; + + osg::ref_ptr currentStateSet; daeURI rootName; bool usePolygons; + osg::StateSet* CleanStateSet(osg::StateSet* pStateSet) const; + protected: //inner classes class ArrayNIndices {