From c44ef1bfd9ff9cf1409c5e0a4900754010b4298b Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 16 May 2011 10:07:20 +0000 Subject: [PATCH] From Sukender, I wrapped my change about non-empty texture units in an off-by-default option, so that it doesn't break any existing code. But AFAIK, other readers (except OSGx) generate contiguous texture units, so I guess this option to be useful for users. Other changes in this sumbission include the added ability to tessellate polygons in Collada reader, with appropriate options. - No tessellation - Tessellate as triangle fan (previous behaviour, kept as default for backward-compatibility) - Full tessellation I also put auto_ptr<> for RAII of DAE structure (as discussed), and moved reader options in a structure, as for the writer. Code also make use of osgDB::ExternalFileWriter I submitted, so please merge this submission after the PluginImageWriter one. --- src/osgPlugins/dae/ReaderWriterDAE.cpp | 69 +++++++----- src/osgPlugins/dae/ReaderWriterDAE.h | 5 + src/osgPlugins/dae/daeRGeometry.cpp | 137 ++++++++++++++++++------ src/osgPlugins/dae/daeRMaterials.cpp | 128 ++++++++++++---------- src/osgPlugins/dae/daeReader.cpp | 15 ++- src/osgPlugins/dae/daeReader.h | 31 ++++-- src/osgPlugins/dae/daeWAnimations.cpp | 4 +- src/osgPlugins/dae/daeWGeometry.cpp | 14 +-- src/osgPlugins/dae/daeWMaterials.cpp | 69 +++--------- src/osgPlugins/dae/daeWSceneObjects.cpp | 10 +- src/osgPlugins/dae/daeWTransforms.cpp | 2 +- src/osgPlugins/dae/daeWriter.cpp | 38 +++---- src/osgPlugins/dae/daeWriter.h | 52 ++++----- 13 files changed, 320 insertions(+), 254 deletions(-) diff --git a/src/osgPlugins/dae/ReaderWriterDAE.cpp b/src/osgPlugins/dae/ReaderWriterDAE.cpp index c1151d664..dae70e9a1 100644 --- a/src/osgPlugins/dae/ReaderWriterDAE.cpp +++ b/src/osgPlugins/dae/ReaderWriterDAE.cpp @@ -41,9 +41,28 @@ ReaderWriterDAE::readNode(const std::string& fname, bool bOwnDAE = false; DAE* pDAE = NULL; - if ( options ) + // Process options + osgDAE::daeReader::Options pluginOptions; + if( options ) + { pDAE = (DAE*)options->getPluginData("DAE"); + pluginOptions.precisionHint = options->getPrecisionHint(); + + std::istringstream iss( options->getOptionString() ); + std::string opt; + while (iss >> opt) + { + if( opt == "StrictTransparency") pluginOptions.strictTransparency = true; + else if (opt == "daeTessellateNone") pluginOptions.tessellateMode = osgDAE::daeReader::TESSELLATE_NONE; + else if (opt == "daeTessellatePolygonsAsTriFans") pluginOptions.tessellateMode = osgDAE::daeReader::TESSELLATE_POLYGONS_AS_TRIFAN; + else if (opt == "daeTessellatePolygons") pluginOptions.tessellateMode = osgDAE::daeReader::TESSELLATE_POLYGONS; + else if (opt == "daeUsePredefinedTextureUnits") pluginOptions.usePredefinedTextureUnits = true; + else if (opt == "daeUseSequencedTextureUnits") pluginOptions.usePredefinedTextureUnits = false; + } + } + + std::string ext( osgDB::getLowerCaseFileExtension(fname) ); if( ! acceptsExtension(ext) ) return ReadResult::FILE_NOT_HANDLED; @@ -57,10 +76,9 @@ ReaderWriterDAE::readNode(const std::string& fname, bOwnDAE = true; pDAE = new DAE; } + std::auto_ptr scopedDae(bOwnDAE ? pDAE : NULL); // Deallocates locally created structure at scope exit - osgDAE::daeReader daeReader(pDAE, - options && options->getOptionString().find("StrictTransparency") != std::string::npos, - options ? options->getPrecisionHint() : 0 ) ; + osgDAE::daeReader daeReader(pDAE, &pluginOptions); // Convert file name to URI std::string fileURI = ConvertFilePathToColladaCompatibleURI(fileName); @@ -85,9 +103,6 @@ ReaderWriterDAE::readNode(const std::string& fname, *(domUpAxisType*)options->getPluginData("DAE-AssetUp_axis") = daeReader.getAssetUpAxis(); } - if (bOwnDAE) - delete pDAE; - osg::Node* rootNode( daeReader.getRootNode() ); return rootNode; } @@ -107,14 +122,7 @@ ReaderWriterDAE::writeNode( const osg::Node& node, if( ! acceptsExtension(ext) ) return WriteResult::FILE_NOT_HANDLED; // Process options - bool usePolygon(false); // Use plugin option "polygon" to enable - bool googleMode(false); // Use plugin option "GoogleMode" to enable - bool writeExtras(true); // Use plugin option "NoExtras" to disable - bool earthTex(false); // Use plugin option "daeEarthTex" to enable - bool zUpAxis(false); // Use plugin option "daeZUpAxis" to enable - bool linkOrignialTextures(false); - bool forceTexture(false); - bool namesUseCodepage(false); + osgDAE::daeWriter::Options pluginOptions; std::string srcDirectory( osgDB::getFilePath(node.getName().empty() ? fname : node.getName()) ); // Base dir when relativising images paths if( options ) { @@ -123,6 +131,12 @@ ReaderWriterDAE::writeNode( const osg::Node& node, const std::string & baseDir = options->getPluginStringData("baseImageDir"); // Rename "srcModelPath" (and call getFilePath() on it)? if (!baseDir.empty()) srcDirectory = baseDir; + const std::string & relativiseImagesPathNbUpDirs = options->getPluginStringData("DAE-relativiseImagesPathNbUpDirs"); + if (!relativiseImagesPathNbUpDirs.empty()) { + std::istringstream iss(relativiseImagesPathNbUpDirs); + iss >> pluginOptions.relativiseImagesPathNbUpDirs; + } + // Sukender's note: I don't know why DAE seems to accept comma-sparated options instead of space-separated options as other ReaderWriters. However, to avoid breaking compatibility, here's a workaround: std::string optString( options->getOptionString() ); for(std::string::iterator it=optString.begin(); it!=optString.end(); ++it) { @@ -134,14 +148,14 @@ ReaderWriterDAE::writeNode( const osg::Node& node, //while (iss >> opt) while( std::getline( iss, opt, ',' ) ) { - if( opt == "polygon") usePolygon = true; - else if (opt == "GoogleMode") googleMode = true; - else if (opt == "NoExtras") writeExtras = false; - else if (opt == "daeEarthTex") earthTex = true; - else if (opt == "daeZUpAxis") zUpAxis = true; - else if (opt == "daeLinkOriginalTexturesNoForce") { linkOrignialTextures = true; forceTexture = false; } - else if (opt == "daeLinkOriginalTexturesForce") { linkOrignialTextures = true; forceTexture = true; } - else if (opt == "daeNamesUseCodepage") namesUseCodepage = true; + if( opt == "polygon") pluginOptions.usePolygons = true; + else if (opt == "GoogleMode") pluginOptions.googleMode = true; + else if (opt == "NoExtras") pluginOptions.writeExtras = false; + else if (opt == "daeEarthTex") pluginOptions.earthTex = true; + else if (opt == "daeZUpAxis") {} // Nothing (old option) + else if (opt == "daeLinkOriginalTexturesNoForce") { pluginOptions.linkOrignialTextures = true; pluginOptions.forceTexture = false; } + else if (opt == "daeLinkOriginalTexturesForce") { pluginOptions.linkOrignialTextures = true; pluginOptions.forceTexture = true; } + else if (opt == "daeNamesUseCodepage") pluginOptions.namesUseCodepage = true; else if (!opt.empty()) { OSG_NOTICE << std::endl << "COLLADA dae plugin: unrecognized option \"" << opt << std::endl; @@ -154,13 +168,14 @@ ReaderWriterDAE::writeNode( const osg::Node& node, bOwnDAE = true; pDAE = new DAE; } + std::auto_ptr scopedDae(bOwnDAE ? pDAE : NULL); // Deallocates locally created structure at scope exit // Convert file name to URI std::string fileURI = ConvertFilePathToColladaCompatibleURI(fname); - osg::NodeVisitor::TraversalMode traversalMode = writeExtras ? osg::NodeVisitor::TRAVERSE_ALL_CHILDREN : osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN; + osg::NodeVisitor::TraversalMode traversalMode = pluginOptions.writeExtras ? osg::NodeVisitor::TRAVERSE_ALL_CHILDREN : osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN; - osgDAE::daeWriter daeWriter(pDAE, fileURI, osgDB::getFilePath(fname), srcDirectory, options, usePolygon, googleMode, traversalMode, writeExtras, earthTex, zUpAxis, linkOrignialTextures, forceTexture, namesUseCodepage); + osgDAE::daeWriter daeWriter(pDAE, fileURI, osgDB::getFilePath(fname), srcDirectory, options, traversalMode, &pluginOptions); daeWriter.setRootNode( node ); const_cast(&node)->accept( daeWriter ); @@ -182,9 +197,6 @@ ReaderWriterDAE::writeNode( const osg::Node& node, } } - if (bOwnDAE) - delete pDAE; - return retVal; } @@ -246,7 +258,6 @@ std::string ReaderWriterDAE::ConvertFilePathToColladaCompatibleURI(const std::st std::string ReaderWriterDAE::ConvertColladaCompatibleURIToFilePath(const std::string& uri) { // Reciprocal of ConvertFilePathToColladaCompatibleURI() - #ifdef OSG_USE_UTF8_FILENAME std::string path( cdom::uriToNativePath( uri ) ); #else diff --git a/src/osgPlugins/dae/ReaderWriterDAE.h b/src/osgPlugins/dae/ReaderWriterDAE.h index 5bf4ec8f7..523c9a1b9 100644 --- a/src/osgPlugins/dae/ReaderWriterDAE.h +++ b/src/osgPlugins/dae/ReaderWriterDAE.h @@ -28,6 +28,11 @@ public: supportsOption("daeNamesUseCodepage", "(Write option) All names except filenames (materials, animation, geometries...) should be considered as encoded using current codepage (UTF8 if not). Filenames follow OSG_USE_UTF8_FILENAME."); supportsOption("StrictTransparency", "(Read option) Undocumented"); + supportsOption("daeTessellateNone", "(Read option) Do not tessellate at all (Polygons are stored as GL_POLYGON - not suitable for concave polygons)"); + supportsOption("daeTessellatePolygonsAsTriFans", "(Read option) Tessellate the old way (default), interpreting polygons as triangle fans (faster, but does not work for concave polygons)"); + supportsOption("daeTessellatePolygons", "(Read option) Use full tessellation of polygons (slower, works for concave polygons)"); + supportsOption("daeUsePredefinedTextureUnits", "(Read option) Texture units have fixed uses (0: ambient occlusion, 1: main texture...). May create non contiguous units (default)."); + supportsOption("daeUsePredefinedTextureUnits", "(Read option) Texture units are created in sequence (contiguous units)."); } const char* className() const { return "COLLADA 1.4.x DAE reader/writer"; } diff --git a/src/osgPlugins/dae/daeRGeometry.cpp b/src/osgPlugins/dae/daeRGeometry.cpp index 3c4cfa1ed..9d457f0fd 100644 --- a/src/osgPlugins/dae/daeRGeometry.cpp +++ b/src/osgPlugins/dae/daeRGeometry.cpp @@ -23,6 +23,8 @@ #include #include +#include + #include #include #include @@ -375,14 +377,14 @@ osg::Geode *daeReader::processMesh(domMesh* pDomMesh) domPolygons_Array polygonsArray = pDomMesh->getPolygons_array(); for ( size_t i = 0; i < polygonsArray.getCount(); i++) { - processPolygons(pOsgGeode, pDomMesh, polygonsArray[i], sources); + processPolygons(pOsgGeode, pDomMesh, polygonsArray[i], sources, GL_POLYGON, _pluginOptions.tessellateMode); } // 0..* domPolylist_Array polylistArray = pDomMesh->getPolylist_array(); for ( size_t i = 0; i < polylistArray.getCount(); i++) { - processPolylist(pOsgGeode, pDomMesh, polylistArray[i], sources); + processPolylist(pOsgGeode, pDomMesh, polylistArray[i], sources, _pluginOptions.tessellateMode); } // 0..* @@ -396,7 +398,7 @@ osg::Geode *daeReader::processMesh(domMesh* pDomMesh) domTrifans_Array trifansArray = pDomMesh->getTrifans_array(); for ( size_t i = 0; i < trifansArray.getCount(); i++) { - processPolygons(pOsgGeode, pDomMesh, trifansArray[i], sources); + processPolygons(pOsgGeode, pDomMesh, trifansArray[i], sources, GL_TRIANGLE_FAN, TESSELLATE_NONE); } // 0..* @@ -494,7 +496,7 @@ void daeReader::processMultiPPrimitive(osg::Geode* geode, } } -void daeReader::processPolylist(osg::Geode* geode, const domMesh* pDomMesh, const domPolylist *group, SourceMap &sources) +void daeReader::processPolylist(osg::Geode* geode, const domMesh* pDomMesh, const domPolylist *group, SourceMap &sources, TessellateMode tessellateMode) { const domPolylist::domVcount* pDomVcount = group->getVcount(); if (!pDomVcount) @@ -515,52 +517,119 @@ void daeReader::processPolylist(osg::Geode* geode, const domMesh* pDomMesh, cons const std::vector& vertexList = vertexLists.front(); - osg::DrawElementsUInt* pDrawTriangles = new osg::DrawElementsUInt(GL_TRIANGLES); - geometry->addPrimitiveSet(pDrawTriangles); - - const domListOfUInts& vCount = pDomVcount->getValue(); - for (size_t i = 0, j = 0; i < vCount.getCount(); ++i) + osg::DrawElementsUInt* pDrawTriangles(NULL); + if (tessellateMode == TESSELLATE_POLYGONS_AS_TRIFAN) { - size_t primitiveLength = vCount[i]; - if (j + primitiveLength > vertexList.size()) + // Produce triangles, interpreting polygons as fans (old way) + pDrawTriangles = new osg::DrawElementsUInt(GL_TRIANGLES); + geometry->addPrimitiveSet(pDrawTriangles); + + const domListOfUInts& vCount = pDomVcount->getValue(); + for (size_t i = 0, j = 0; i < vCount.getCount(); ++i) { - OSG_WARN << "Error: vertex counts are greater than the number of indices." << std::endl; - return; + size_t primitiveLength = vCount[i]; + if (j + primitiveLength > vertexList.size()) + { + OSG_WARN << "Error: vertex counts are greater than the number of indices." << std::endl; + return; + } + for (size_t k = 2; k < primitiveLength; ++k) + { + pDrawTriangles->push_back(vertexList[j]); + pDrawTriangles->push_back(vertexList[j+k-1]); + pDrawTriangles->push_back(vertexList[j+k]); + } + j += primitiveLength; } - for (size_t k = 2; k < primitiveLength; ++k) + } + else + { + // Produce polygons or well-tessellated polygons + const domListOfUInts& vCount = pDomVcount->getValue(); + for (size_t i = 0, j = 0; i < vCount.getCount(); ++i) { - pDrawTriangles->push_back(vertexList[j]); - pDrawTriangles->push_back(vertexList[j+k-1]); - pDrawTriangles->push_back(vertexList[j+k]); + size_t primitiveLength = vCount[i]; + if (j + primitiveLength > vertexList.size()) + { + OSG_WARN << "Error: vertex counts are greater than the number of indices." << std::endl; + return; + } + + osg::DrawElementsUInt* pDrawElements = new osg::DrawElementsUInt(GL_POLYGON); + geometry->addPrimitiveSet(pDrawElements); + for (size_t k = 0; k < primitiveLength; ++k) + { + pDrawElements->push_back(vertexList[k+j]); + } + + j += primitiveLength; + } + + if (tessellateMode == TESSELLATE_POLYGONS) + { + osgUtil::Tessellator tessellator; + tessellator.setTessellationType(osgUtil::Tessellator::TESS_TYPE_POLYGONS); + tessellator.setWindingType(osgUtil::Tessellator::TESS_WINDING_POSITIVE); + tessellator.retessellatePolygons(*geometry); } - j += primitiveLength; } } -template +template< typename T > void daeReader::processPolygons(osg::Geode* geode, - const domMesh* pDomMesh, const T *group, SourceMap& sources) + const domMesh* pDomMesh, const T *group, SourceMap& sources, GLenum mode, TessellateMode tessellateMode) { osg::Geometry *geometry = new osg::Geometry(); geometry->setName(group->getMaterial()); geode->addDrawable(geometry); - osg::DrawElementsUInt* pDrawElements = new osg::DrawElementsUInt(GL_TRIANGLES); - geometry->addPrimitiveSet(pDrawElements); - std::vector > indexLists; resolveMeshArrays(group->getP_array(), group->getInput_array(), pDomMesh, geometry, sources, indexLists); - for ( size_t i = 0; i < indexLists.size(); ++i) + if (tessellateMode == TESSELLATE_POLYGONS_AS_TRIFAN) { - const std::vector& indices = indexLists[i]; + // Produce triangles, interpreting polygons as fans (old way) + osg::DrawElementsUInt* pDrawElements = new osg::DrawElementsUInt(GL_TRIANGLES); + geometry->addPrimitiveSet(pDrawElements); - for (size_t j = 2; j < indices.size(); ++j) + std::vector > indexLists; + resolveMeshArrays(group->getP_array(), group->getInput_array(), pDomMesh, + geometry, sources, indexLists); + + for ( size_t i = 0; i < indexLists.size(); ++i) { - pDrawElements->push_back(indices.front()); - pDrawElements->push_back(indices[j - 1]); - pDrawElements->push_back(indices[j]); + const std::vector& indices = indexLists[i]; + + for (size_t j = 2; j < indices.size(); ++j) + { + pDrawElements->push_back(indices.front()); + pDrawElements->push_back(indices[j - 1]); + pDrawElements->push_back(indices[j]); + } + } + } + else + { + // Produce polygons or well-tessellated polygons + for ( size_t i = 0; i < indexLists.size(); ++i) + { + const std::vector& indices = indexLists[i]; + + osg::DrawElementsUInt* pDrawElements = new osg::DrawElementsUInt(mode); + geometry->addPrimitiveSet(pDrawElements); + for (size_t j = 0; j < indices.size(); ++j) + { + pDrawElements->push_back(indices[j]); + } + } + + if (tessellateMode == TESSELLATE_POLYGONS) + { + osgUtil::Tessellator tessellator; + tessellator.setTessellationType(osgUtil::Tessellator::TESS_TYPE_POLYGONS); + tessellator.setWindingType(osgUtil::Tessellator::TESS_WINDING_POSITIVE); + tessellator.retessellatePolygons(*geometry); } } } @@ -840,10 +909,10 @@ void daeReader::resolveMeshArrays(const domP_Array& domPArray, } } - const bool readDoubleVertices = (_precisionHint & osgDB::Options::DOUBLE_PRECISION_VERTEX) != 0; - const bool readDoubleColors = (_precisionHint & osgDB::Options::DOUBLE_PRECISION_COLOR) != 0; - const bool readDoubleNormals = (_precisionHint & osgDB::Options::DOUBLE_PRECISION_NORMAL) != 0; - const bool readDoubleTexcoords = (_precisionHint & osgDB::Options::DOUBLE_PRECISION_TEX_COORD) != 0; + const bool readDoubleVertices = (_pluginOptions.precisionHint & osgDB::Options::DOUBLE_PRECISION_VERTEX) != 0; + const bool readDoubleColors = (_pluginOptions.precisionHint & osgDB::Options::DOUBLE_PRECISION_COLOR) != 0; + const bool readDoubleNormals = (_pluginOptions.precisionHint & osgDB::Options::DOUBLE_PRECISION_NORMAL) != 0; + const bool readDoubleTexcoords = (_pluginOptions.precisionHint & osgDB::Options::DOUBLE_PRECISION_TEX_COORD) != 0; // Vertices { @@ -893,6 +962,4 @@ void daeReader::resolveMeshArrays(const domP_Array& domPArray, } } } - -#undef FOREACH_INDEX } diff --git a/src/osgPlugins/dae/daeRMaterials.cpp b/src/osgPlugins/dae/daeRMaterials.cpp index 7cb0e5cf7..f8bb81276 100644 --- a/src/osgPlugins/dae/daeRMaterials.cpp +++ b/src/osgPlugins/dae/daeRMaterials.cpp @@ -170,9 +170,10 @@ void daeReader::processBindMaterial( domBind_material *bm, domGeometry *geom, os // 2. For each possible texture unit find the correct texcoord array and // indices from the cached drawable and place in the cloned drawable // in the correct texture unit slot - copyTextureCoordinateSet(ss, cachedGeometry, clonedGeometry, ima[j], AMBIENT_OCCLUSION_UNIT); - copyTextureCoordinateSet(ss, cachedGeometry, clonedGeometry, ima[j], MAIN_TEXTURE_UNIT); - copyTextureCoordinateSet(ss, cachedGeometry, clonedGeometry, ima[j], TRANSPARENCY_MAP_UNIT); + unsigned int textureUnit(0); + if (copyTextureCoordinateSet(ss, cachedGeometry, clonedGeometry, ima[j], AMBIENT_OCCLUSION_UNIT, textureUnit)) ++textureUnit; + if (copyTextureCoordinateSet(ss, cachedGeometry, clonedGeometry, ima[j], MAIN_TEXTURE_UNIT , textureUnit)) ++textureUnit; + if (copyTextureCoordinateSet(ss, cachedGeometry, clonedGeometry, ima[j], TRANSPARENCY_MAP_UNIT , textureUnit)) ++textureUnit; } else { @@ -339,13 +340,15 @@ void daeReader::processProfileCOMMON(osg::StateSet *ss, domProfile_COMMON *pc ) mat->setAmbient( osg::Material::FRONT_AND_BACK, osg::Vec4( 1.0f, 1.0f, 1.0f, 1.0f ) ); mat->setDiffuse( osg::Material::FRONT_AND_BACK, osg::Vec4( 1.0f, 1.0f, 1.0f, 1.0f ) ); // Use the ambient texture map as an occlusion map. - ss->setTextureMode( AMBIENT_OCCLUSION_UNIT, GL_TEXTURE_2D, GL_TRUE ); - ss->setTextureAttribute(AMBIENT_OCCLUSION_UNIT, new osg::TexEnv(osg::TexEnv::MODULATE) ); - ss->setTextureAttribute( AMBIENT_OCCLUSION_UNIT, AmbientStateAttribute ); + unsigned int textureUnit( _pluginOptions.usePredefinedTextureUnits ? AMBIENT_OCCLUSION_UNIT : 0); + ss->setTextureMode( textureUnit, GL_TEXTURE_2D, GL_TRUE ); + ss->setTextureAttribute( textureUnit, new osg::TexEnv(osg::TexEnv::MODULATE) ); + ss->setTextureAttribute( textureUnit, AmbientStateAttribute ); // Modulate in the diffuse texture - ss->setTextureMode( MAIN_TEXTURE_UNIT, GL_TEXTURE_2D, GL_TRUE ); - ss->setTextureAttribute(MAIN_TEXTURE_UNIT, new osg::TexEnv(osg::TexEnv::MODULATE) ); - ss->setTextureAttribute( MAIN_TEXTURE_UNIT, DiffuseStateAttribute ); + textureUnit = _pluginOptions.usePredefinedTextureUnits ? MAIN_TEXTURE_UNIT : 1; + ss->setTextureMode( textureUnit, GL_TEXTURE_2D, GL_TRUE ); + ss->setTextureAttribute( textureUnit, new osg::TexEnv(osg::TexEnv::MODULATE) ); + ss->setTextureAttribute( textureUnit, DiffuseStateAttribute ); } else { @@ -353,9 +356,10 @@ void daeReader::processProfileCOMMON(osg::StateSet *ss, domProfile_COMMON *pc ) // plus any constant ambient contribution after the lighting calculation. This means that I am modulating the the // ambient with the texture as well but I cannot see a way of avoiding that. mat->setDiffuse( osg::Material::FRONT_AND_BACK, osg::Vec4( 1.0f, 1.0f, 1.0f, 1.0f ) ); - ss->setTextureMode( MAIN_TEXTURE_UNIT, GL_TEXTURE_2D, GL_TRUE ); - ss->setTextureAttribute(MAIN_TEXTURE_UNIT, new osg::TexEnv(osg::TexEnv::MODULATE) ); - ss->setTextureAttribute( MAIN_TEXTURE_UNIT, DiffuseStateAttribute ); + unsigned int textureUnit( _pluginOptions.usePredefinedTextureUnits ? MAIN_TEXTURE_UNIT : 0); + ss->setTextureMode( textureUnit, GL_TEXTURE_2D, GL_TRUE ); + ss->setTextureAttribute( textureUnit, new osg::TexEnv(osg::TexEnv::MODULATE) ); + ss->setTextureAttribute( textureUnit, DiffuseStateAttribute ); } // Save the texture name for later @@ -413,13 +417,15 @@ void daeReader::processProfileCOMMON(osg::StateSet *ss, domProfile_COMMON *pc ) mat->setAmbient( osg::Material::FRONT_AND_BACK, osg::Vec4( 1.0f, 1.0f, 1.0f, 1.0f ) ); mat->setDiffuse( osg::Material::FRONT_AND_BACK, osg::Vec4( 1.0f, 1.0f, 1.0f, 1.0f ) ); // Use the ambient texture map as an occlusion map. - ss->setTextureMode( AMBIENT_OCCLUSION_UNIT, GL_TEXTURE_2D, GL_TRUE ); - ss->setTextureAttribute(AMBIENT_OCCLUSION_UNIT, new osg::TexEnv(osg::TexEnv::MODULATE) ); - ss->setTextureAttribute( AMBIENT_OCCLUSION_UNIT, AmbientStateAttribute ); + unsigned int textureUnit( _pluginOptions.usePredefinedTextureUnits ? AMBIENT_OCCLUSION_UNIT : 0); + ss->setTextureMode( textureUnit, GL_TEXTURE_2D, GL_TRUE ); + ss->setTextureAttribute( textureUnit, new osg::TexEnv(osg::TexEnv::MODULATE) ); + ss->setTextureAttribute( textureUnit, AmbientStateAttribute ); // Modulate in the diffuse texture - ss->setTextureMode( MAIN_TEXTURE_UNIT, GL_TEXTURE_2D, GL_TRUE ); - ss->setTextureAttribute(MAIN_TEXTURE_UNIT, new osg::TexEnv(osg::TexEnv::MODULATE) ); - ss->setTextureAttribute( MAIN_TEXTURE_UNIT, DiffuseStateAttribute ); + textureUnit = _pluginOptions.usePredefinedTextureUnits ? MAIN_TEXTURE_UNIT : 1; + ss->setTextureMode( textureUnit, GL_TEXTURE_2D, GL_TRUE ); + ss->setTextureAttribute( textureUnit, new osg::TexEnv(osg::TexEnv::MODULATE) ); + ss->setTextureAttribute( textureUnit, DiffuseStateAttribute ); } else { @@ -427,9 +433,10 @@ void daeReader::processProfileCOMMON(osg::StateSet *ss, domProfile_COMMON *pc ) // plus any constant ambient contribution after the lighting calculation. This means that I am modulating the the // ambient with the texture as well but I cannot see a way of avoiding that. mat->setDiffuse( osg::Material::FRONT_AND_BACK, osg::Vec4( 1.0f, 1.0f, 1.0f, 1.0f ) ); - ss->setTextureMode( MAIN_TEXTURE_UNIT, GL_TEXTURE_2D, GL_TRUE ); - ss->setTextureAttribute(MAIN_TEXTURE_UNIT, new osg::TexEnv(osg::TexEnv::MODULATE) ); - ss->setTextureAttribute( MAIN_TEXTURE_UNIT, DiffuseStateAttribute ); + unsigned int textureUnit( _pluginOptions.usePredefinedTextureUnits ? MAIN_TEXTURE_UNIT : 0); + ss->setTextureMode( textureUnit, GL_TEXTURE_2D, GL_TRUE ); + ss->setTextureAttribute( textureUnit, new osg::TexEnv(osg::TexEnv::MODULATE) ); + ss->setTextureAttribute( textureUnit, DiffuseStateAttribute ); } // Save the texture name for later @@ -485,13 +492,15 @@ void daeReader::processProfileCOMMON(osg::StateSet *ss, domProfile_COMMON *pc ) mat->setAmbient( osg::Material::FRONT_AND_BACK, osg::Vec4( 1.0f, 1.0f, 1.0f, 1.0f ) ); mat->setDiffuse( osg::Material::FRONT_AND_BACK, osg::Vec4( 1.0f, 1.0f, 1.0f, 1.0f ) ); // Use the ambient texture map as an occlusion map. - ss->setTextureMode( AMBIENT_OCCLUSION_UNIT, GL_TEXTURE_2D, GL_TRUE ); - ss->setTextureAttribute(AMBIENT_OCCLUSION_UNIT, new osg::TexEnv(osg::TexEnv::MODULATE) ); - ss->setTextureAttribute( AMBIENT_OCCLUSION_UNIT, AmbientStateAttribute ); + unsigned int textureUnit( _pluginOptions.usePredefinedTextureUnits ? AMBIENT_OCCLUSION_UNIT : 0); + ss->setTextureMode( textureUnit, GL_TEXTURE_2D, GL_TRUE ); + ss->setTextureAttribute( textureUnit, new osg::TexEnv(osg::TexEnv::MODULATE) ); + ss->setTextureAttribute( textureUnit, AmbientStateAttribute ); // Modulate in the diffuse texture - ss->setTextureMode( MAIN_TEXTURE_UNIT, GL_TEXTURE_2D, GL_TRUE ); - ss->setTextureAttribute(MAIN_TEXTURE_UNIT, new osg::TexEnv(osg::TexEnv::MODULATE) ); - ss->setTextureAttribute( MAIN_TEXTURE_UNIT, DiffuseStateAttribute ); + textureUnit = _pluginOptions.usePredefinedTextureUnits ? MAIN_TEXTURE_UNIT : 1; + ss->setTextureMode( textureUnit, GL_TEXTURE_2D, GL_TRUE ); + ss->setTextureAttribute( textureUnit, new osg::TexEnv(osg::TexEnv::MODULATE) ); + ss->setTextureAttribute( textureUnit, DiffuseStateAttribute ); } else { @@ -499,9 +508,10 @@ void daeReader::processProfileCOMMON(osg::StateSet *ss, domProfile_COMMON *pc ) // plus any constant ambient contribution after the lighting calculation. This means that I am modulating the the // ambient with the texture as well but I cannot see a way of avoiding that. mat->setDiffuse( osg::Material::FRONT_AND_BACK, osg::Vec4( 1.0f, 1.0f, 1.0f, 1.0f ) ); - ss->setTextureMode( MAIN_TEXTURE_UNIT, GL_TEXTURE_2D, GL_TRUE ); - ss->setTextureAttribute(MAIN_TEXTURE_UNIT, new osg::TexEnv(osg::TexEnv::MODULATE) ); - ss->setTextureAttribute( MAIN_TEXTURE_UNIT, DiffuseStateAttribute ); + unsigned int textureUnit( _pluginOptions.usePredefinedTextureUnits ? MAIN_TEXTURE_UNIT : 0); + ss->setTextureMode( textureUnit, GL_TEXTURE_2D, GL_TRUE ); + ss->setTextureAttribute( textureUnit, new osg::TexEnv(osg::TexEnv::MODULATE) ); + ss->setTextureAttribute( textureUnit, DiffuseStateAttribute ); } // Save the texture name for later @@ -529,9 +539,10 @@ void daeReader::processProfileCOMMON(osg::StateSet *ss, domProfile_COMMON *pc ) processColorOrTextureType(ss, c->getEmission(), osg::Material::EMISSION, mat.get(), NULL, &sa ); if (sa != NULL ) { - ss->setTextureMode( MAIN_TEXTURE_UNIT, GL_TEXTURE_2D, GL_TRUE ); - ss->setTextureAttribute(MAIN_TEXTURE_UNIT, new osg::TexEnv(osg::TexEnv::REPLACE) ); - ss->setTextureAttribute( MAIN_TEXTURE_UNIT, sa ); + unsigned int textureUnit( _pluginOptions.usePredefinedTextureUnits ? MAIN_TEXTURE_UNIT : 0); + ss->setTextureMode( textureUnit, GL_TEXTURE_2D, GL_TRUE ); + ss->setTextureAttribute( textureUnit, new osg::TexEnv(osg::TexEnv::REPLACE) ); + ss->setTextureAttribute( textureUnit, sa ); } // Use the emission colour as the main colour in transparency calculations @@ -1241,7 +1252,7 @@ void daeReader::processTransparencySettings( domCommon_transparent_type *ctt, } else { - bool strictTransparency = _strictTransparency; + bool strictTransparency = _pluginOptions.strictTransparency; if (!strictTransparency) { const osg::Texture* pMainTexture = dynamic_cast( @@ -1270,40 +1281,41 @@ void daeReader::processTransparencySettings( domCommon_transparent_type *ctt, ss->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); } -void daeReader::copyTextureCoordinateSet(const osg::StateSet* ss, const osg::Geometry* cachedGeometry, osg::Geometry* clonedGeometry, const domInstance_material* im, TextureUnitUsage tuu) +bool daeReader::copyTextureCoordinateSet(const osg::StateSet* ss, const osg::Geometry* cachedGeometry, osg::Geometry* clonedGeometry, const domInstance_material* im, TextureUnitUsage tuu, unsigned int textureUnit) { - if (!ss->getTextureAttribute(tuu, osg::StateAttribute::TEXTURE)) - return; + unsigned int localTextureUnit( _pluginOptions.usePredefinedTextureUnits ? tuu : textureUnit); + if (!ss->getTextureAttribute(localTextureUnit, osg::StateAttribute::TEXTURE)) + return false; const std::string& texCoordSetName = _texCoordSetMap [TextureToCoordSetMap::key_type(ss, tuu)]; - if (!texCoordSetName.empty()) + if (texCoordSetName.empty()) return false; + + const domInstance_material::domBind_vertex_input_Array &bvia = im->getBind_vertex_input_array(); + size_t k; + for (k = 0; k < bvia.getCount(); k++) { - const domInstance_material::domBind_vertex_input_Array &bvia = im->getBind_vertex_input_array(); - size_t k; - for (k = 0; k < bvia.getCount(); k++) + if (!strcmp(bvia[k]->getSemantic(), texCoordSetName.c_str()) && !strcmp(bvia[k]->getInput_semantic(), COMMON_PROFILE_INPUT_TEXCOORD)) { - if (!strcmp(bvia[k]->getSemantic(), texCoordSetName.c_str()) && !strcmp(bvia[k]->getInput_semantic(), COMMON_PROFILE_INPUT_TEXCOORD)) + unsigned set = bvia[k]->getInput_set(); + if (set < cachedGeometry->getNumTexCoordArrays()) { - unsigned set = bvia[k]->getInput_set(); - if (set < cachedGeometry->getNumTexCoordArrays()) - { - clonedGeometry->setTexCoordData(tuu, cachedGeometry->getTexCoordData(set)); - } - else - { - OSG_WARN << "Texture coordinate set " << set << " not found." << std::endl; - } - break; + clonedGeometry->setTexCoordData(localTextureUnit, cachedGeometry->getTexCoordData(set)); } - } - if (k == bvia.getCount()) - { - OSG_WARN << "Failed to find matching for " << texCoordSetName << std::endl; - if (cachedGeometry->getNumTexCoordArrays()) + else { - clonedGeometry->setTexCoordData(tuu, cachedGeometry->getTexCoordData(0)); + OSG_WARN << "Texture coordinate set " << set << " not found." << std::endl; } + break; } } + if (k == bvia.getCount()) + { + OSG_WARN << "Failed to find matching for " << texCoordSetName << std::endl; + if (cachedGeometry->getNumTexCoordArrays()) + { + clonedGeometry->setTexCoordData(localTextureUnit, cachedGeometry->getTexCoordData(0)); + } + } + return true; } diff --git a/src/osgPlugins/dae/daeReader.cpp b/src/osgPlugins/dae/daeReader.cpp index f7b463ffa..f2d4947b0 100644 --- a/src/osgPlugins/dae/daeReader.cpp +++ b/src/osgPlugins/dae/daeReader.cpp @@ -22,7 +22,15 @@ using namespace osgDAE; -daeReader::daeReader(DAE *dae_, bool strictTransparency, int precisionHint) : +daeReader::Options::Options() : + strictTransparency(false), + precisionHint(0), + tessellateMode(TESSELLATE_POLYGONS_AS_TRIFAN), // Use old tessellation behaviour as default + usePredefinedTextureUnits(true) +{ +} + +daeReader::daeReader(DAE *dae_, const Options * pluginOptions) : _dae(dae_), _rootNode(NULL), _visualScene(NULL), @@ -30,12 +38,11 @@ daeReader::daeReader(DAE *dae_, bool strictTransparency, int precisionHint) : _currentInstance_effect(NULL), _currentEffect(NULL), _authoringTool(UNKNOWN), - _strictTransparency(strictTransparency), _invertTransparency(false), - _precisionHint(precisionHint), _assetUnitName("meter"), _assetUnitMeter(1.0), - _assetUp_axis(UPAXISTYPE_Y_UP) + _assetUp_axis(UPAXISTYPE_Y_UP), + _pluginOptions(pluginOptions ? *pluginOptions : Options()) { } diff --git a/src/osgPlugins/dae/daeReader.h b/src/osgPlugins/dae/daeReader.h index d342cbc85..07d5de0ad 100644 --- a/src/osgPlugins/dae/daeReader.h +++ b/src/osgPlugins/dae/daeReader.h @@ -133,7 +133,23 @@ inline osg::Matrix parseMatrixString(const std::string& valueAsString) */ class daeReader { public: - daeReader(DAE *dae_, bool strictTransparency, int precisionHint); + enum TessellateMode + { + TESSELLATE_NONE, ///< Do not tessellate at all (Polygons are stored as GL_POLYGON - not suitable for concave polygons) + TESSELLATE_POLYGONS_AS_TRIFAN, ///< Tessellate the old way, interpreting polygons as triangle fans (faster, but does not work for concave polygons) + TESSELLATE_POLYGONS ///< Use full tessellation of polygons (slower, works for concave polygons) + }; + + struct Options + { + Options(); + bool strictTransparency; + int precisionHint; ///< Precision hint flags, as specified in osgDB::Options::PrecisionHint + bool usePredefinedTextureUnits; + TessellateMode tessellateMode; + }; + + daeReader(DAE *dae_, const Options * pluginOptions); virtual ~daeReader(); bool convert( const std::string &fileURI ); @@ -305,11 +321,10 @@ private: template< typename T > void processMultiPPrimitive(osg::Geode* geode, const domMesh* pDomMesh, const T* group, SourceMap& sources, GLenum mode); - template - void processPolygons(osg::Geode* geode, const domMesh* pDomMesh, const T *group, SourceMap& sources); + void processPolylist(osg::Geode* geode, const domMesh* pDomMesh, const domPolylist *group, SourceMap &sources, TessellateMode tessellateMode); - void processPolylist(osg::Geode* geode, const domMesh* pDomMesh, const domPolylist *group, SourceMap &sources); - void processPolygons(osg::Geode* geode, const domMesh* pDomMesh, const domPolygons *group, SourceMap &sources); + template< typename T > + void processPolygons(osg::Geode* geode, const domMesh* pDomMesh, const T *group, SourceMap &sources, GLenum mode, TessellateMode tessellateMode); void resolveMeshArrays(const domP_Array&, const domInputLocalOffset_Array& inputs, const domMesh* pDomMesh, @@ -339,7 +354,7 @@ private: std::string processImagePath(const domImage*) const; osg::Image* processImageTransparency(const osg::Image*, domFx_opaque_enum, float transparency) const; osg::Texture2D* processTexture( domCommon_color_or_texture_type_complexType::domTexture *tex, const osg::StateSet*, TextureUnitUsage, domFx_opaque_enum = FX_OPAQUE_ENUM_A_ONE, float transparency = 1.0f); - void copyTextureCoordinateSet(const osg::StateSet* ss, const osg::Geometry* cachedGeometry, osg::Geometry* clonedGeometry, const domInstance_material* im, TextureUnitUsage); + bool copyTextureCoordinateSet(const osg::StateSet* ss, const osg::Geometry* cachedGeometry, osg::Geometry* clonedGeometry, const domInstance_material* im, TextureUnitUsage tuu, unsigned int textureUnit); //scene objects osg::Node* processLight( domLight *dlight ); @@ -392,8 +407,8 @@ private: OldToNewIndexMap _oldToNewIndexMap; AuthoringTool _authoringTool; - bool _strictTransparency, _invertTransparency; - int _precisionHint; ///< Precision hint flags, as specified in osgDB::Options::PrecisionHint + bool _invertTransparency; + Options _pluginOptions; // Additional Information std::string _assetUnitName; diff --git a/src/osgPlugins/dae/daeWAnimations.cpp b/src/osgPlugins/dae/daeWAnimations.cpp index 0b88788b4..2f9540a85 100644 --- a/src/osgPlugins/dae/daeWAnimations.cpp +++ b/src/osgPlugins/dae/daeWAnimations.cpp @@ -36,7 +36,7 @@ using namespace osgDAE; void daeWriter::writeAnimations( osg::Node &node ) { - const std::string nodeNameUTF( _namesUseCodepage ? osgDB::convertStringFromCurrentCodePageToUTF8(node.getName()) : node.getName() ); + const std::string nodeNameUTF( _pluginOptions.namesUseCodepage ? osgDB::convertStringFromCurrentCodePageToUTF8(node.getName()) : node.getName() ); osg::NodeCallback* ncb = node.getUpdateCallback(); if (ncb) { @@ -68,7 +68,7 @@ void daeWriter::writeAnimations( osg::Node &node ) { osgAnimation::Channel* channel = animationChannels[j].get(); std::string channelName( channel->getName() ); - std::string channelNameUTF( _namesUseCodepage ? osgDB::convertStringFromCurrentCodePageToUTF8(channelName) : channelName ); + std::string channelNameUTF( _pluginOptions.namesUseCodepage ? osgDB::convertStringFromCurrentCodePageToUTF8(channelName) : channelName ); // Wrap each animation channel into it's own child when more than 1 channel if (animationChannels.size() > 1) diff --git a/src/osgPlugins/dae/daeWGeometry.cpp b/src/osgPlugins/dae/daeWGeometry.cpp index dce7c3606..5e01c8508 100644 --- a/src/osgPlugins/dae/daeWGeometry.cpp +++ b/src/osgPlugins/dae/daeWGeometry.cpp @@ -749,7 +749,7 @@ bool daeWriter::processGeometry( osg::Geometry *geom, domGeometry *geo, const st { if ( polys == NULL ) { - if (usePolygons) + if (_pluginOptions.usePolygons) { polys = createPrimGroup( COLLADA_ELEMENT_POLYGONS, mesh, norm, color, texcoord ); polys->add( COLLADA_ELEMENT_P ); @@ -810,7 +810,7 @@ bool daeWriter::processGeometry( osg::Geometry *geom, domGeometry *geo, const st { if ( polys == NULL ) { - if (usePolygons) + if (_pluginOptions.usePolygons) { polys = createPrimGroup( COLLADA_ELEMENT_POLYGONS, mesh, norm, color, texcoord ); polys->add( COLLADA_ELEMENT_P ); @@ -890,7 +890,7 @@ bool daeWriter::processGeometry( osg::Geometry *geom, domGeometry *geo, const st { //TODO : test this case unsigned int nbPolygons=drawArray->getCount()/primLength; - if (usePolygons) + if (_pluginOptions.usePolygons) { //for( unsigned int idx = 0; idx < nbPolygons; ++idx ) p.push_back(polys->getP_array()[0]); @@ -990,7 +990,7 @@ bool daeWriter::processGeometry( osg::Geometry *geom, domGeometry *geo, const st default: { - if (usePolygons) + if (_pluginOptions.usePolygons) { //for( unsigned int idx = 0; idx < nbPolygons; ++idx ) p.push_back(polys->getP_array()[0]); @@ -1084,7 +1084,7 @@ bool daeWriter::processGeometry( osg::Geometry *geom, domGeometry *geo, const st default: { unsigned int nbPolygons=drawElements->size()/primLength; - if (usePolygons) + if (_pluginOptions.usePolygons) { //for( unsigned int idx = 0; idx < nbPolygons; ++idx ) /*idx*/ //huh ? why only one ? @@ -1183,7 +1183,7 @@ bool daeWriter::processGeometry( osg::Geometry *geom, domGeometry *geo, const st default: { unsigned int nbPolygons=drawElements->size()/primLength; - if (usePolygons) + if (_pluginOptions.usePolygons) { //for( unsigned int idx = 0; idx < nbPolygons; ++idx ) /*idx*/ //huh ? why only one ? @@ -1284,7 +1284,7 @@ bool daeWriter::processGeometry( osg::Geometry *geom, domGeometry *geo, const st default: { unsigned int nbPolygons=drawElements->size()/primLength; - if (usePolygons) + if (_pluginOptions.usePolygons) { //for( unsigned int idx = 0; idx < nbPolygons; ++idx ) /*idx*/ //huh ? why only one ? diff --git a/src/osgPlugins/dae/daeWMaterials.cpp b/src/osgPlugins/dae/daeWMaterials.cpp index 3b77433e5..e3c4d439e 100644 --- a/src/osgPlugins/dae/daeWMaterials.cpp +++ b/src/osgPlugins/dae/daeWMaterials.cpp @@ -33,12 +33,13 @@ using namespace osgDAE; + void daeWriter::processMaterial( osg::StateSet *ss, domBind_material *pDomBindMaterial, 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::domTechnique_common *tc = daeSafeCast< domBind_material::domTechnique_common >( pDomBindMaterial->add( COLLADA_ELEMENT_TECHNIQUE_COMMON ) ); domInstance_material *pDomInstanceMaterial = daeSafeCast< domInstance_material >( tc->add( COLLADA_ELEMENT_INSTANCE_MATERIAL ) ); - const std::string symbol( _namesUseCodepage ? osgDB::convertStringFromCurrentCodePageToUTF8(geoName + "_material") : (geoName + "_material") ); + const std::string symbol( _pluginOptions.namesUseCodepage ? osgDB::convertStringFromCurrentCodePageToUTF8(geoName + "_material") : (geoName + "_material") ); pDomInstanceMaterial->setSymbol( symbol.c_str() ); // See if material already exists in cache @@ -104,65 +105,19 @@ void daeWriter::processMaterial( osg::StateSet *ss, domBind_material *pDomBindMa domImage::domInit_from *imgif = daeSafeCast< domImage::domInit_from >( img->add( COLLADA_ELEMENT_INIT_FROM ) ); std::string fileURI; - if (m_linkOrignialTextures) + if (_pluginOptions.linkOrignialTextures) { // We link to orignial images (not the ones in memory). fileURI = osgDB::findDataFile(osgimg->getFileName()); - if (fileURI=="" && m_ForceTexture) + if (fileURI=="" && _pluginOptions.forceTexture) { fileURI = osgDB::getRealPath(osgimg->getFileName()); } } else { - // We do not link to orignial images but to the ones in memory. Then must ensure to write the images. - // Following code block is borrowed from FBX's WriterNodeVisitor::Material::Material(). - ImageSet::iterator it = _imageSet.find(osgimg); - if (it != _imageSet.end()) - { - fileURI = it->second; - } - else - { - fileURI = osgDB::getRealPath(osgDB::convertFileNameToNativeStyle(osgimg->getFileName())); - std::string destPath; - std::string relativePath; - if (fileURI.empty()) - { - static const unsigned int MAX_IMAGE_NUMBER = UINT_MAX-1; // -1 to allow doing +1 without an overflow - unsigned int imageNumber; - for (imageNumber=_lastGeneratedImageFileName+1; imageNumbersetValue( dd ); // The document URI should contain the canonical path it was created with - if (m_linkOrignialTextures) imgif->getValue().makeRelativeTo(doc->getDocumentURI()); + if (_pluginOptions.linkOrignialTextures) imgif->getValue().makeRelativeTo(doc->getDocumentURI()); - if (!m_EarthTex) + if (!_pluginOptions.earthTex) { domCommon_newparam_type *np = daeSafeCast< domCommon_newparam_type >( pc->add(COLLADA_ELEMENT_NEWPARAM) ); std::string surfName = efName + "-surface"; @@ -347,7 +302,7 @@ void daeWriter::processMaterial( osg::StateSet *ss, domBind_material *pDomBindMa { cot = phong->getDiffuse(); - if (writeExtras) + if (_pluginOptions.writeExtras) { // Adds the following to a texture element @@ -400,7 +355,7 @@ void daeWriter::processMaterial( osg::StateSet *ss, domBind_material *pDomBindMa domCommon_color_or_texture_type_complexType::domColor *pColor = daeSafeCast(pTransparent->add(COLLADA_ELEMENT_COLOR)); domCommon_float_or_param_type *pFop = daeSafeCast(phong->add(COLLADA_ELEMENT_TRANSPARENCY)); domCommon_float_or_param_type_complexType::domFloat *pTransparency = daeSafeCast(pFop->add(COLLADA_ELEMENT_FLOAT)); - if (m_GoogleMode) + if (_pluginOptions.googleMode) { pColor->getValue().append(1.0); pColor->getValue().append(1.0); @@ -440,7 +395,7 @@ void daeWriter::processMaterial( osg::StateSet *ss, domBind_material *pDomBindMa ctt->setOpaque( FX_OPAQUE_ENUM_A_ONE ); domCommon_color_or_texture_type_complexType::domTexture * dtex = daeSafeCast< domCommon_color_or_texture_type_complexType::domTexture >( ctt->add(COLLADA_ELEMENT_TEXTURE) ); - if (!m_EarthTex) + if (!_pluginOptions.earthTex) { std::string sampName = efName + "-sampler"; dtex->setTexture( sampName.c_str() ); @@ -463,7 +418,7 @@ void daeWriter::processMaterial( osg::StateSet *ss, domBind_material *pDomBindMa } } - if (writeExtras) + if (_pluginOptions.writeExtras) { // Adds the following to a Profile_COMMON element diff --git a/src/osgPlugins/dae/daeWSceneObjects.cpp b/src/osgPlugins/dae/daeWSceneObjects.cpp index 77ca97fab..fa05bcc17 100644 --- a/src/osgPlugins/dae/daeWSceneObjects.cpp +++ b/src/osgPlugins/dae/daeWSceneObjects.cpp @@ -35,7 +35,7 @@ void daeWriter::writeNodeExtra(osg::Node &node) { unsigned int numDesc = node.getDescriptions().size(); // Only create extra if descriptions are filled in - if (writeExtras && (numDesc > 0)) + if (_pluginOptions.writeExtras && (numDesc > 0)) { // Adds the following to a node @@ -73,7 +73,7 @@ void daeWriter::apply( osg::Group &node ) // If a multiswitch node, store it's data as extra "MultiSwitch" data in the "OpenSceneGraph" technique osgSim::MultiSwitch* multiswitch = dynamic_cast(&node); - if (writeExtras && multiswitch) + if (_pluginOptions.writeExtras && multiswitch) { // Adds the following to a node @@ -142,7 +142,7 @@ void daeWriter::apply( osg::Switch &node ) currentNode = daeSafeCast< domNode >(currentNode->add( COLLADA_ELEMENT_NODE ) ); currentNode->setId(getNodeName(node,"switch").c_str()); - if (writeExtras) + if (_pluginOptions.writeExtras) { // Adds the following to a node @@ -190,7 +190,7 @@ void daeWriter::apply( osg::Sequence &node ) currentNode->setId(getNodeName(node,"sequence").c_str()); // If a sequence node, store it's data as extra "Sequence" data in the "OpenSceneGraph" technique - if (writeExtras) + if (_pluginOptions.writeExtras) { // Adds the following to a node @@ -267,7 +267,7 @@ void daeWriter::apply( osg::LOD &node ) currentNode = daeSafeCast< domNode >(currentNode->add( COLLADA_ELEMENT_NODE ) ); currentNode->setId(getNodeName(node,"LOD").c_str()); - if (writeExtras) + if (_pluginOptions.writeExtras) { // Store LOD data as extra "LOD" data in the "OpenSceneGraph" technique // Adds the following to a node diff --git a/src/osgPlugins/dae/daeWTransforms.cpp b/src/osgPlugins/dae/daeWTransforms.cpp index 5ae55eb2e..80b284fa2 100644 --- a/src/osgPlugins/dae/daeWTransforms.cpp +++ b/src/osgPlugins/dae/daeWTransforms.cpp @@ -184,7 +184,7 @@ void daeWriter::apply( osg::Transform &node ) // If a DOFTransform node store it's data as extra "DOFTransform" data in the "OpenSceneGraph" technique osgSim::DOFTransform* dof = dynamic_cast(&node); - if (writeExtras && dof) + if (_pluginOptions.writeExtras && dof) { // Adds the following to a node diff --git a/src/osgPlugins/dae/daeWriter.cpp b/src/osgPlugins/dae/daeWriter.cpp index 314a51172..c281001e3 100644 --- a/src/osgPlugins/dae/daeWriter.cpp +++ b/src/osgPlugins/dae/daeWriter.cpp @@ -96,23 +96,25 @@ std::string toString(const osg::Matrix& value) } -daeWriter::daeWriter( DAE *dae_, const std::string & fileURI, const std::string & directory, const std::string & srcDirectory, const osgDB::ReaderWriter::Options * options, bool _usePolygons, bool googleMode, TraversalMode tm, bool _writeExtras, bool earthTex, bool zUpAxis, bool linkOrignialTextures, bool forceTexture, bool namesUseCodepage) : osg::NodeVisitor( tm ), - dae(dae_), - _domLibraryAnimations(NULL), - writeExtras(_writeExtras), - rootName(*dae_), - usePolygons (_usePolygons), - m_GoogleMode(googleMode), - m_EarthTex(earthTex), - m_ZUpAxis(zUpAxis), - m_linkOrignialTextures(linkOrignialTextures), - m_ForceTexture(forceTexture), - m_CurrentRenderingHint(osg::StateSet::DEFAULT_BIN), - _lastGeneratedImageFileName(0), - _directory(directory), - _srcDirectory(srcDirectory), - _options(options), - _namesUseCodepage(namesUseCodepage) +daeWriter::Options::Options() + : usePolygons(false), + googleMode(false), + writeExtras(true), + earthTex(false), + linkOrignialTextures(false), + forceTexture(false), + namesUseCodepage(false), + relativiseImagesPathNbUpDirs(0) +{} + +daeWriter::daeWriter( DAE *dae_, const std::string & fileURI, const std::string & directory, const std::string & srcDirectory, const osgDB::ReaderWriter::Options * options, TraversalMode tm, const Options * pluginOptions) : osg::NodeVisitor( tm ), + dae(dae_), + _domLibraryAnimations(NULL), + rootName(*dae_), + m_CurrentRenderingHint(osg::StateSet::DEFAULT_BIN), + _options(options), + _pluginOptions(pluginOptions ? *pluginOptions : Options()), + _externalWriter(srcDirectory, directory, true, pluginOptions ? pluginOptions->relativiseImagesPathNbUpDirs : 0) { success = true; @@ -209,7 +211,7 @@ void daeWriter::updateCurrentDaeNode() std::string daeWriter::uniquify( const std::string &_name ) { - const std::string name( _namesUseCodepage ? osgDB::convertStringFromCurrentCodePageToUTF8(_name) : _name ); + const std::string name( _pluginOptions.namesUseCodepage ? osgDB::convertStringFromCurrentCodePageToUTF8(_name) : _name ); std::map< std::string, int >::iterator iter = uniqueNames.find( name ); if ( iter != uniqueNames.end() ) { diff --git a/src/osgPlugins/dae/daeWriter.h b/src/osgPlugins/dae/daeWriter.h index 177bd3b46..c6cf19d18 100644 --- a/src/osgPlugins/dae/daeWriter.h +++ b/src/osgPlugins/dae/daeWriter.h @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -136,7 +137,25 @@ class daeWriter : public osg::NodeVisitor protected: class ArrayNIndices; public: - daeWriter( DAE *dae_, const std::string &fileURI, const std::string & directory, const std::string & srcDirectory, const osgDB::ReaderWriter::Options * options, bool usePolygons=false, bool googleMode = false, TraversalMode tm=TRAVERSE_ALL_CHILDREN, bool writeExtras = true, bool earthTex = false, bool zUpAxis=false, bool linkOrignialTextures=false, bool forceTexture=false, bool namesUseCodepage=false); + struct Options + { + Options(); + + bool usePolygons; + /** work in Google compatibility mode. In daeWMaterials, change transparency color. And in daeWGeometry, replace tristrip and trifans by triangles*/ + bool googleMode; + /** Write OSG specific data as extra data. */ + bool writeExtras; + /** work in Google compatibility mode for textures*/ + bool earthTex; + /** link to original images instead of exporting */ + bool linkOrignialTextures; + /** force the use an image for a texture, even if the file is not found (when m_linkOrignialTextures). */ + bool forceTexture; + bool namesUseCodepage; + unsigned int relativiseImagesPathNbUpDirs; + }; + daeWriter(DAE *dae_, const std::string &fileURI, const std::string & directory, const std::string & srcDirectory, const osgDB::ReaderWriter::Options * options, TraversalMode tm=TRAVERSE_ALL_CHILDREN, const Options * pluginOptions=NULL); virtual ~daeWriter(); void setRootNode( const osg::Node &node ); @@ -216,8 +235,6 @@ protected: //members domNode *currentNode; domVisual_scene *vs; - /// Write OSG specific data as extra data - bool writeExtras; bool success; unsigned int lastDepth; @@ -249,8 +266,6 @@ protected: //members daeURI rootName; - bool usePolygons; - osg::StateSet* CleanStateSet(osg::StateSet* pStateSet) const; void updateCurrentDaeNode(); @@ -305,38 +320,15 @@ private: //members /** provide an unique name */ std::string uniquify( const std::string &name ); - /** work in Google compatibility mode. In daeWMaterials, change transparency color. And in daeWGeometry, replace tristrip and trifans by triangles*/ - bool m_GoogleMode; - - /** work in Google compatibility mode for textures*/ - bool m_EarthTex; - - /** indicates if the up axis is on Z axis*/ - bool m_ZUpAxis; - - /** link to original images instead of exporting */ - bool m_linkOrignialTextures; - - /** force the use an image for a texture, even if the file is not found (when m_linkOrignialTextures). */ - bool m_ForceTexture; - /** Current RenderingHint */ /** This are needed because the stateSet merge code currently does not handle it */ int m_CurrentRenderingHint; FindAnimatedNodeVisitor _animatedNodeCollector; - /** Number used when writing images with no name, to generate a file name. */ - unsigned int _lastGeneratedImageFileName; - std::string _directory; - std::string _srcDirectory; const osgDB::ReaderWriter::Options * _options; - bool _namesUseCodepage; - - typedef std::map ImageSet; - typedef std::set ImageFilenameSet; // Sub-optimal because strings are doubled (in ImageSet). Moreover, an unordered_set (= hashset) would be more efficient (Waiting for unordered_set to be included in C++ standard ;) ). - ImageSet _imageSet; - ImageFilenameSet _imageFilenameSet; + Options _pluginOptions; + osgDB::ExternalFileWriter _externalWriter; }; }