From 6bdd83413d8ba64bdb9ff4fd852ad6edb37f5a0c Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 24 Nov 2008 14:26:04 +0000 Subject: [PATCH] From Roland Smeenk, "Overview of the Collada/dae plugin changes New features +Read and write of osg::LOD, osg::Switch, osgSim::Sequence, osgim::MultiSwitch and osgSim::DOFTransform data in +Read and write of osg::Node description data in +Plugin option "NoExtras" to prevent writing of data and only traverse the active children when saving Changes/additions +instanced_geometry and instanced_controller are now loaded in a single Geode with multiple Geometries instead of multiple geodes with a single Geometry +Changed all calls to the deprecated createAndPlace() to the new add() methods +All transformation elements , , , , , are now concatenated properly in to a single MatrixTransform. Previously this was not done in order as required by Collada and and not all elements were included. +Complete skew matrix creation +Automatically add GL_RESCALE_NORMAL if scale is non-identity +Blinn shininess remapping to [0,128] when in range [0,1] +Changes to CMake file to make it compile on Windows +Coding style and code documentation Bug fixes +Transparent texture writing fixed +Fixed bug in using osg node name as collada node ID +Fixed usage of double sided faces in GOOGLEEARTH extra +Not adding blendfunc and blendcolor when opaque TODO/Wishlist -solve differences in drawables, DAE reader should place multiple collation elements into multiple primitivesets in a single geometry where possible (only when same material) -solve differences in matrices -multitexture support -skinned mesh and generic animations using osgAnimation -profile_GLSL based on COLLADA OpenGL Effects Viewer http://ati.amd.com/developer/rendermonkey/downloads.html -handling more to more closely mimic the intended lighting" --- src/osgPlugins/dae/CMakeLists.txt | 6 +- src/osgPlugins/dae/ReaderWriterDAE.cpp | 42 +- src/osgPlugins/dae/daeRGeometry.cpp | 344 ++++++++-------- src/osgPlugins/dae/daeRMaterials.cpp | 373 ++++++++++++------ src/osgPlugins/dae/daeRSceneObjects.cpp | 320 ++++++++++++++- src/osgPlugins/dae/daeRTransforms.cpp | 504 ++++++++++++++++-------- src/osgPlugins/dae/daeReader.cpp | 426 ++++++++++---------- src/osgPlugins/dae/daeReader.h | 94 +++-- src/osgPlugins/dae/daeWGeometry.cpp | 117 +++--- src/osgPlugins/dae/daeWMaterials.cpp | 250 ++++++------ src/osgPlugins/dae/daeWSceneObjects.cpp | 329 +++++++++++++--- src/osgPlugins/dae/daeWTransforms.cpp | 132 ++++++- src/osgPlugins/dae/daeWriter.cpp | 54 ++- src/osgPlugins/dae/daeWriter.h | 27 +- 14 files changed, 2047 insertions(+), 971 deletions(-) diff --git a/src/osgPlugins/dae/CMakeLists.txt b/src/osgPlugins/dae/CMakeLists.txt index bd61a9977..ef5a4264f 100644 --- a/src/osgPlugins/dae/CMakeLists.txt +++ b/src/osgPlugins/dae/CMakeLists.txt @@ -27,9 +27,10 @@ OPTION(COLLADA_USE_STATIC "Set to ON to build OpenSceneGraph with static Collada IF (WIN32) IF (COLLADA_USE_STATIC) - SET(TARGET_EXTERNAL_LIBRARIES libcollada_dom libcollada_dae libcollada_STLDatabase libcollada_LIBXMLPlugin libcollada_stdErrPlugin libxml2 ) + SET(TARGET_EXTERNAL_LIBRARIES libxml2 pcrecpp-d pcre-d) ELSE (COLLADA_USE_STATIC) - ADD_DEFINITIONS(-DDOM_DYNAMIC) +# ADD_DEFINITIONS(-DDOM_DYNAMIC) + SET(TARGET_EXTERNAL_LIBRARIES libxml2 pcrecpp-d pcre-d) ENDIF(COLLADA_USE_STATIC) ELSE (WIN32) @@ -53,6 +54,7 @@ ELSE (WIN32) ENDIF(WIN32) SET(TARGET_LIBRARIES_VARS COLLADA_LIBRARY) +SET(TARGET_ADDED_LIBRARIES osgSim ) #### end var setup ### SETUP_PLUGIN(dae) diff --git a/src/osgPlugins/dae/ReaderWriterDAE.cpp b/src/osgPlugins/dae/ReaderWriterDAE.cpp index 3af936d0a..dc73d2b30 100644 --- a/src/osgPlugins/dae/ReaderWriterDAE.cpp +++ b/src/osgPlugins/dae/ReaderWriterDAE.cpp @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -40,7 +41,7 @@ ReaderWriterDAE::readNode(const std::string& fname, DAE* pDAE = NULL; if ( options ) - pDAE = (DAE*) options->getPluginData("DAE"); + pDAE = (DAE*)options->getPluginData("DAE"); std::string ext( osgDB::getLowerCaseFileExtension(fname) ); if( ! acceptsExtension(ext) ) return ReadResult::FILE_NOT_HANDLED; @@ -103,31 +104,32 @@ ReaderWriterDAE::writeNode( const osg::Node& node, if( ! acceptsExtension(ext) ) return WriteResult::FILE_NOT_HANDLED; // Process options - bool usePolygon(false); - bool GoogleMode(false); + 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 if( options ) { - pDAE = (DAE*) options->getPluginData("DAE"); + pDAE = (DAE*)options->getPluginData("DAE"); std::istringstream iss( options->getOptionString() ); std::string opt; - while( std::getline( iss, opt, ',' ) ) - { - if( opt == "polygon") usePolygon = true; - else if (opt == "GoogleMode") GoogleMode = true; - else + while( std::getline( iss, opt, ',' ) ) { - osg::notify(osg::WARN) - << "\n" "COLLADA dae plugin: unrecognized option \"" << opt << "\"\n" - << "comma-delimited options:\n" - << "\tpolygon = use polygons instead of polylists for element\n" - << "\tGoogleMode = write files suitable for use by Google products\n" - << "example: osgviewer -O polygon bar.dae" "\n" - << std::endl; + if( opt == "polygon") usePolygon = true; + else if (opt == "GoogleMode") GoogleMode = true; + else if (opt == "NoExtras") writeExtras = false; + else + { + osg::notify(osg::WARN) + << std::endl << "COLLADA dae plugin: unrecognized option \"" << opt << std::endl + << "comma-delimited options:" << std::endl << std::endl + << "\tpolygon = use polygons instead of polylists for element" << std::endl + << "\tGoogleMode = write files suitable for use by Google products" << std::endl + << "example: osgviewer -O polygon bar.dae" << std::endl << std::endl; + } } - } } - + if (NULL == pDAE) { bOwnDAE = true; @@ -137,7 +139,9 @@ ReaderWriterDAE::writeNode( const osg::Node& node, // Convert file name to URI std::string fileURI = ConvertFilePathToColladaCompatibleURI(fname); - osgdae::daeWriter daeWriter(pDAE, fileURI, usePolygon, GoogleMode ); + osg::NodeVisitor::TraversalMode traversalMode = writeExtras ? osg::NodeVisitor::TRAVERSE_ALL_CHILDREN : osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN; + + osgdae::daeWriter daeWriter(pDAE, fileURI, usePolygon, GoogleMode, traversalMode, writeExtras); daeWriter.setRootNode( node ); const_cast(&node)->accept( daeWriter ); diff --git a/src/osgPlugins/dae/daeRGeometry.cpp b/src/osgPlugins/dae/daeRGeometry.cpp index cd63d0705..4b759a2a8 100644 --- a/src/osgPlugins/dae/daeRGeometry.cpp +++ b/src/osgPlugins/dae/daeRGeometry.cpp @@ -18,17 +18,14 @@ #include #include #include +#include #include using namespace osgdae; -osg::Node* daeReader::processInstance_geometry( domInstance_geometry *ig ) +osg::Geode* daeReader::processInstanceGeometry( domInstance_geometry *ig ) { - //TODO: cache geometries so they don't get processed mulitple times. - //TODO: after cached need to check geometries and materials. both have to be the same for it - // to be the same instance. - daeElement *el = getElementFromURI( ig->getUrl() ); domGeometry *geom = daeSafeCast< domGeometry >( el ); if ( geom == NULL ) @@ -36,50 +33,65 @@ osg::Node* daeReader::processInstance_geometry( domInstance_geometry *ig ) osg::notify( osg::WARN ) << "Failed to locate geometry " << ig->getUrl().getURI() << std::endl; return NULL; } - //check cache if geometry already exists - osg::Node *geo; + + // Check cache if geometry already exists + osg::Geode *geode; - std::map< domGeometry*, osg::Node* >::iterator iter = geometryMap.find( geom ); + domGeometryGeodeMap::iterator iter = geometryMap.find( geom ); if ( iter != geometryMap.end() ) { - geo = iter->second; + osg::Geode* cachedGeode = iter->second; + + // Create a copy of the cached Geode with a copy of the drawables, + // because the may be using a different material. + // TODO Cloning is not necessary if the material layouts are exactly the same. + // To check this we need to compare the material bindings used by the cached Geode + // and this new instance_geometry material bindings. + geode = static_cast(cachedGeode->clone(osg::CopyOp::DEEP_COPY_DRAWABLES)); } else { - geo = processGeometry( geom ); - geometryMap.insert( std::make_pair( geom, geo ) ); + geode = processGeometry( geom ); + geometryMap.insert( std::make_pair( geom, geode ) ); } - if ( geo == NULL ) + + if ( geode == NULL ) { osg::notify( osg::WARN ) << "Failed to load geometry " << ig->getUrl().getURI() << std::endl; return NULL; } - //process material bindings + + // process material bindings if ( ig->getBind_material() != NULL ) { - processBindMaterial( ig->getBind_material(), geo ); + processBindMaterial( ig->getBind_material(), geom, geode ); } - return geo; + return geode; } -osg::Node* daeReader::processInstance_controller( domInstance_controller *ictrl ) +// +// attributes: +// id, name +// elements: +// 0..1 +// 1 , +// 0..* +osg::Geode* daeReader::processInstanceController( domInstance_controller *ictrl ) { - //TODO: cache geometries so they don't get processed mulitple times. - //TODO: after cached need to check geometries and materials. both have to be the same for it - // to be the same instance. //TODO: support skinning - - osg::notify( osg::WARN ) << "Processing . There is not skinning support but will display the base mesh." << std::endl; - daeElement *el = getElementFromURI( ictrl->getUrl() ); + daeElement *el = getElementFromURI( ictrl->getUrl()); domController *ctrl = daeSafeCast< domController >( el ); if ( ctrl == NULL ) { - osg::notify( osg::WARN ) << "Failed to locate controller " << ictrl->getUrl().getURI() << std::endl; + osg::notify( osg::WARN ) << "Failed to locate conroller " << ictrl->getUrl().getURI() << std::endl; return NULL; } + + osg::notify( osg::WARN ) << "Processing . There is not skinning support but will display the base mesh." << std::endl; + el = NULL; - //## non init + //## non init daeURI *src=NULL; if ( ctrl->getSkin() != NULL ) { @@ -91,12 +103,13 @@ osg::Node* daeReader::processInstance_controller( domInstance_controller *ictrl src = &ctrl->getSkin()->getSource(); el = getElementFromURI( ctrl->getMorph()->getSource() ); } - //non init case - if ( !src ) - { - osg::notify( osg::WARN ) << "Failed to locate geometry : URI is NULL" << std::endl; - return NULL; - } + + //non init case + if ( !src ) + { + osg::notify( osg::WARN ) << "Failed to locate geometry : URI is NULL" << std::endl; + return NULL; + } domGeometry *geom = daeSafeCast< domGeometry >( el ); if ( geom == NULL ) @@ -104,19 +117,29 @@ osg::Node* daeReader::processInstance_controller( domInstance_controller *ictrl osg::notify( osg::WARN ) << "Failed to locate geometry " << src->getURI() << std::endl; return NULL; } - osg::Node *geo; - std::map< domGeometry*, osg::Node* >::iterator iter = geometryMap.find( geom ); + // Check cache if geometry already exists + osg::Geode *geode; + + domGeometryGeodeMap::iterator iter = geometryMap.find( geom ); if ( iter != geometryMap.end() ) { - geo = iter->second; + osg::Geode* cachedGeode = iter->second; + + // Create a copy of the cached Geode with a copy of the drawables, + // because the may be using a different material. + // TODO Cloning is not necessary if the material layouts are exactly the same. + // To check this we need to compare the material bindings used by the cached Geode + // and this new instance_geometry material bindings. + geode = static_cast(cachedGeode->clone(osg::CopyOp::DEEP_COPY_DRAWABLES)); } else { - geo = processGeometry( geom ); - geometryMap.insert( std::make_pair( geom, geo ) ); + geode = processGeometry( geom ); + geometryMap.insert( std::make_pair( geom, geode ) ); } - if ( geo == NULL ) + + if ( geode == NULL ) { osg::notify( osg::WARN ) << "Failed to load geometry " << src->getURI() << std::endl; return NULL; @@ -124,13 +147,20 @@ osg::Node* daeReader::processInstance_controller( domInstance_controller *ictrl //process material bindings if ( ictrl->getBind_material() != NULL ) { - processBindMaterial( ictrl->getBind_material(), geo ); + processBindMaterial( ictrl->getBind_material(), geom, geode ); } - return geo; + return geode; } -osg::Node *daeReader::processGeometry( domGeometry *geo ) +// +// attributes: +// id, name +// elements: +// 0..1 +// 1 , , +// 0..* +osg::Geode *daeReader::processGeometry( domGeometry *geo ) { domMesh *mesh = geo->getMesh(); if ( mesh == NULL ) @@ -138,124 +168,87 @@ osg::Node *daeReader::processGeometry( domGeometry *geo ) osg::notify( osg::WARN ) << "Unsupported Geometry type loading " << geo->getId() << std::endl; return NULL; } - osg::Node *node = new osg::Group(); - if ( geo->getId() != NULL ) + osg::Geode* geode = new osg::Geode; + if (geo->getId() != NULL ) { - node->setName( geo->getId() ); + geode->setName( geo->getId() ); } - SourceMap sources; - + // + // elements: + // 1..* + // 1 + // 0..* , , , , , , + // 0..* size_t count = mesh->getContents().getCount(); - for ( size_t i = 0; i < count; i++ ) + + // 1..* + SourceMap sources; + domSource_Array sourceArray = mesh->getSource_array(); + for ( size_t i = 0; i < sourceArray.getCount(); i++) { - if ( daeSafeCast< domVertices >( mesh->getContents()[i] ) != NULL ) continue; - - domSource *s = daeSafeCast< domSource >( mesh->getContents()[i] ); - if ( s != NULL ) - { - sources.insert( std::make_pair( (daeElement*)mesh->getContents()[i], - domSourceReader( s ) ) ); - continue; - } - - osg::Node *n = NULL; - - domTriangles *t = daeSafeCast< domTriangles >( mesh->getContents()[i] ); - if ( t != NULL ) - { - n = processSinglePPrimitive( t, sources, GL_TRIANGLES ); - if ( n != NULL ) - { - node->asGroup()->addChild( n ); - } - continue; - } - - domTristrips *ts = daeSafeCast< domTristrips >( mesh->getContents()[i] ); - if ( ts != NULL ) - { - n = processMultiPPrimitive( ts, sources, GL_TRIANGLE_STRIP ); - if ( n != NULL ) - { - node->asGroup()->addChild( n ); - } - continue; - } - - domTrifans *tf = daeSafeCast< domTrifans >( mesh->getContents()[i] ); - if ( tf != NULL ) - { - n = processMultiPPrimitive( tf, sources, GL_TRIANGLE_FAN ); - if ( n != NULL ) - { - node->asGroup()->addChild( n ); - } - continue; - } - - domLines *l = daeSafeCast< domLines >( mesh->getContents()[i] ); - if ( l != NULL ) - { - n = processSinglePPrimitive( l, sources, GL_LINES ); - if ( n != NULL ) - { - node->asGroup()->addChild( n ); - } - continue; - } - - domLinestrips *ls = daeSafeCast< domLinestrips >( mesh->getContents()[i] ); - if ( ls != NULL ) - { - n = processMultiPPrimitive( ls, sources, GL_LINE_STRIP ); - if ( n != NULL ) - { - node->asGroup()->addChild( n ); - } - continue; - } - - domPolygons *p = daeSafeCast< domPolygons >( mesh->getContents()[i] ); - if ( p != NULL ) - { - n = processMultiPPrimitive( p, sources, GL_POLYGON ); - if ( n != NULL ) - { - node->asGroup()->addChild( n ); - } - continue; - } - - domPolylist *pl = daeSafeCast< domPolylist >( mesh->getContents()[i] ); - if ( pl != NULL ) - { - n = processPolylist( pl, sources ); - if ( n != NULL ) - { - node->asGroup()->addChild( n ); - } - continue; - } - - osg::notify( osg::WARN ) << "Unsupported primitive type " << mesh->getContents()[i]->getTypeName() << " in geometry " << geo->getId() << std::endl; + sources.insert( std::make_pair((daeElement*)sourceArray[i], domSourceReader( sourceArray[i] ) ) ); } - return node; + // 0..* + domLines_Array linesArray = mesh->getLines_array(); + for ( size_t i = 0; i < linesArray.getCount(); i++) + { + processSinglePPrimitive(geode, linesArray[i], sources, GL_LINES ); + } + + // 0..* + domLinestrips_Array linestripsArray = mesh->getLinestrips_array(); + for ( size_t i = 0; i < linestripsArray.getCount(); i++) + { + processMultiPPrimitive(geode, linestripsArray[i], sources, GL_LINE_STRIP ); + } + + // 0..* + domPolygons_Array polygonsArray = mesh->getPolygons_array(); + for ( size_t i = 0; i < polygonsArray.getCount(); i++) + { + processMultiPPrimitive(geode, polygonsArray[i], sources, GL_POLYGON ); + } + + // 0..* + domPolylist_Array polylistArray = mesh->getPolylist_array(); + for ( size_t i = 0; i < polylistArray.getCount(); i++) + { + processPolylist(geode, polylistArray[i], sources ); + } + + // 0..* + domTriangles_Array trianglesArray = mesh->getTriangles_array(); + for ( size_t i = 0; i < trianglesArray.getCount(); i++) + { + processSinglePPrimitive(geode, trianglesArray[i], sources, GL_TRIANGLES ); + } + + // 0..* + domTrifans_Array trifansArray = mesh->getTrifans_array(); + for ( size_t i = 0; i < trifansArray.getCount(); i++) + { + processMultiPPrimitive(geode, trifansArray[i], sources, GL_TRIANGLE_FAN ); + } + + // 0..* + domTristrips_Array tristripsArray = mesh->getTristrips_array(); + for ( size_t i = 0; i < tristripsArray.getCount(); i++) + { + processMultiPPrimitive(geode, tristripsArray[i], sources, GL_TRIANGLE_STRIP ); + } + + return geode; } -template< typename T > -osg::Node* daeReader::processSinglePPrimitive( T *group, SourceMap &sources, GLenum mode ) -{ - osg::Geode* geode = new osg::Geode(); - osg::Geometry *geometry = new osg::Geometry(); - //Setting the name of the geode to the material symbol for easy binding later - if ( group->getMaterial() != NULL ) - { - geode->setName( group->getMaterial() ); - } +template< typename T > +void daeReader::processSinglePPrimitive(osg::Geode* geode, T *group, SourceMap &sources, GLenum mode ) +{ + osg::Geometry *geometry = new osg::Geometry(); + geometry->setName(group->getMaterial()); IndexMap index_map; resolveArrays( group->getInput_array(), geometry, sources, index_map ); @@ -265,20 +258,13 @@ osg::Node* daeReader::processSinglePPrimitive( T *group, SourceMap &sources, GLe geometry->addPrimitiveSet( dal ); geode->addDrawable( geometry ); - return geode; } template< typename T > - osg::Node* daeReader::processMultiPPrimitive( T *group, SourceMap &sources, GLenum mode ) +void daeReader::processMultiPPrimitive(osg::Geode* geode, T *group, SourceMap &sources, GLenum mode ) { - osg::Geode* geode = new osg::Geode(); osg::Geometry *geometry = new osg::Geometry(); - - //Setting the name of the geode to the material symbol for easy binding later - if ( group->getMaterial() != NULL ) - { - geode->setName( group->getMaterial() ); - } + geometry->setName(group->getMaterial()); IndexMap index_map; resolveArrays( group->getInput_array(), geometry, sources, index_map ); @@ -292,19 +278,12 @@ template< typename T > geometry->addPrimitiveSet( dal ); geode->addDrawable( geometry ); - return geode; } -osg::Node* daeReader::processPolylist( domPolylist *group, SourceMap &sources ) +void daeReader::processPolylist(osg::Geode* geode, domPolylist *group, SourceMap &sources ) { - osg::Geode* geode = new osg::Geode(); osg::Geometry *geometry = new osg::Geometry(); - - //Setting the name of the geode to the material symbol for easy binding later - if ( group->getMaterial() != NULL ) - { - geode->setName( group->getMaterial() ); - } + geometry->setName(group->getMaterial()); IndexMap index_map; resolveArrays( group->getInput_array(), geometry, sources, index_map ); @@ -342,12 +321,10 @@ osg::Node* daeReader::processPolylist( domPolylist *group, SourceMap &sources ) geometry->addPrimitiveSet( dal ); geode->addDrawable( geometry ); - return geode; } void daeReader::processP( domP *p, osg::Geometry *&/*geom*/, IndexMap &index_map, osg::DrawArrayLengths* dal /*GLenum mode*/ ) { - //osg::DrawArrayLengths* dal = new osg::DrawArrayLengths( mode ); int idxcount = index_map.size(); int count = p->getValue().getCount(); count = (count/idxcount)*idxcount; @@ -360,7 +337,6 @@ void daeReader::processP( domP *p, osg::Geometry *&/*geom*/, IndexMap &index_map k->second->push_back(tmp); } } - //geom->addPrimitiveSet( dal ); } void daeReader::resolveArrays( domInputLocalOffset_Array &inputs, osg::Geometry *&geom, @@ -377,9 +353,11 @@ void daeReader::resolveArrays( domInputLocalOffset_Array &inputs, osg::Geometry daeElement *tmp_el; domInputLocalOffset *tmp_input; - if ( findInputSourceBySemantic( inputs, "VERTEX", tmp_el, &tmp_input ) ) { + if ( findInputSourceBySemantic( inputs, "VERTEX", tmp_el, &tmp_input ) ) + { vertices = daeSafeCast< domVertices >( tmp_el ); - if ( vertices == NULL ) { + if ( vertices == NULL ) + { osg::notify( osg::WARN )<<"Could not get vertices"<getInput_array(), "NORMAL", normal_source, &tmp ); findInputSourceBySemantic( vertices->getInput_array(), "TEXCOORD", texcoord_source, &tmp ); - if ( index_map[offset] == NULL ) { + if ( index_map[offset] == NULL ) + { index_map[offset] = new osg::IntArray(); } geom->setVertexIndices( index_map[offset] ); @@ -436,9 +415,8 @@ void daeReader::resolveArrays( domInputLocalOffset_Array &inputs, osg::Geometry return; } - - if ( findInputSourceBySemantic( inputs, "COLOR", color_source, &tmp_input ) ) { - + if ( findInputSourceBySemantic( inputs, "COLOR", color_source, &tmp_input )) + { offset = tmp_input->getOffset(); if ( index_map[offset] == NULL ) { index_map[offset] = new osg::IntArray(); @@ -446,32 +424,36 @@ void daeReader::resolveArrays( domInputLocalOffset_Array &inputs, osg::Geometry geom->setColorIndices( index_map[offset] ); } - if ( color_source != NULL ) { + if ( color_source != NULL ) + { geom->setColorArray( sources[color_source].getVec4Array() ); geom->setColorBinding( osg::Geometry::BIND_PER_VERTEX ); } - if ( findInputSourceBySemantic( inputs, "NORMAL", normal_source, &tmp_input ) ) { - + if ( findInputSourceBySemantic( inputs, "NORMAL", normal_source, &tmp_input ) ) + { offset = tmp_input->getOffset(); - if ( index_map[offset] == NULL ) { + if ( index_map[offset] == NULL ) + { index_map[offset] = new osg::IntArray(); } geom->setNormalIndices( index_map[offset] ); } - if ( normal_source ) { + if ( normal_source ) + { geom->setNormalArray( sources[normal_source].getVec3Array() ); geom->setNormalBinding( osg::Geometry::BIND_PER_VERTEX ); } int unit = 0; - while ( findInputSourceBySemantic( inputs, "TEXCOORD", texcoord_source, &tmp_input, unit ) ) { - + while ( findInputSourceBySemantic( inputs, "TEXCOORD", texcoord_source, &tmp_input, unit ) ) + { offset = tmp_input->getOffset(); set = tmp_input->getSet(); - if ( index_map[offset] == NULL ) { + if ( index_map[offset] == NULL ) + { index_map[offset] = new osg::IntArray(); } //this should really be set. Then when you bind_vertex_input you can adjust accordingly for the diff --git a/src/osgPlugins/dae/daeRMaterials.cpp b/src/osgPlugins/dae/daeRMaterials.cpp index f0c2b27c8..50922ce28 100644 --- a/src/osgPlugins/dae/daeRMaterials.cpp +++ b/src/osgPlugins/dae/daeRMaterials.cpp @@ -29,84 +29,120 @@ using namespace osgdae; -void daeReader::processBindMaterial( domBind_material *bm, osg::Node *geo ) + +// +// elements: +// 0..* +// name +// sid +// semantic +// type +// 1 +// 0..* +// symbol +// target +// sid +// name +// 0..* +// profile +// 0..* +// id +// name +// type +void daeReader::processBindMaterial( domBind_material *bm, domGeometry *geom, osg::Geode *geode ) { - if ( bm->getTechnique_common() == NULL ) + if (bm->getTechnique_common() == NULL ) { osg::notify( osg::WARN ) << "No COMMON technique for bind_material" << std::endl; return; } - osg::Group *group = geo->asGroup(); - if ( group == NULL ) - { - //this shouldn't happen unless something is terribly wrong - return; - } - domInstance_material_Array &ima = bm->getTechnique_common()->getInstance_material_array(); - size_t count = ima.getCount(); - for ( size_t i = 0; i < count; i++ ) - { - std::string symbol = ima[i]->getSymbol(); - domMaterial *mat = daeSafeCast< domMaterial >( getElementFromURI( ima[i]->getTarget() ) ); - if ( mat == NULL ) - { - osg::notify( osg::WARN ) << "Failed to locate material " << ima[i]->getTarget().getURI() << std::endl; - continue; - } - osg::StateSet *ss; - //check material cache if this material already exists - std::map< domMaterial*, osg::StateSet*>::iterator iter = materialMap.find( mat ); - if ( iter != materialMap.end() ) - { - ss = iter->second; - } - else - { - ss = processMaterial( mat ); - materialMap.insert( std::make_pair( mat, ss ) ); - } - if ( ss == NULL ) - { - continue; - } - //TODO: process all of the s and s that are here in the instance_material. - for ( unsigned int x = 0; x < group->getNumChildren(); x++ ) + for (size_t i =0; i < geode->getNumDrawables(); i++) + { + osg::Drawable* drawable = geode->getDrawable(i); + std::string materialName = drawable->getName(); + + domInstance_material_Array &ima = bm->getTechnique_common()->getInstance_material_array(); + std::string symbol; + bool found = false; + for ( size_t j = 0; j < ima.getCount(); j++) { - //I named the geode with the material symbol so I can do this check for binding - if ( group->getChild( x )->getName() == symbol ) - { - /*if ( group->getChild( x )->getStateSet() != NULL ) + symbol = ima[j]->getSymbol(); + if (symbol.compare(materialName) == 0) + { + found = true; + domMaterial *mat = daeSafeCast< domMaterial >(getElementFromURI( ima[j]->getTarget())); + if (mat) { - //already have a stateSet this means I am an instance so clone me. - group->replaceChild( group->getChild( x ), (osg::Node*)group->getChild( x )->cloneType() ); - }*/ - group->getChild( x )->setStateSet( ss ); + // Check material cache if this material already exists + domMaterialStateSetMap::iterator iter = materialMap.find( mat ); + if ( iter != materialMap.end() ) + { + // Reuse material + drawable->setStateSet(iter->second); + } + else + { + // Create new material + osg::StateSet* ss = new osg::StateSet; + processMaterial(ss, mat); + drawable->setStateSet(ss); + materialMap.insert(std::make_pair(mat, ss)); + } + } + else + { + osg::notify( osg::WARN ) << "Failed to locate wit id " << ima[i]->getTarget().getURI() << std::endl; + } + + break; } } + if (!found) + { + osg::notify( osg::WARN ) << "Failed to locate with symbol " << materialName << std::endl; + } } } -osg::StateSet *daeReader::processMaterial( domMaterial *mat ) +// +// attributes: +// 0..1 id +// 0..1 name +// elements: +// 0..1 +// 1 +// 0..* +void daeReader::processMaterial(osg::StateSet *ss, domMaterial *mat ) { currentInstance_effect = mat->getInstance_effect(); domEffect *effect = daeSafeCast< domEffect >( getElementFromURI( currentInstance_effect->getUrl() ) ); - if ( effect == NULL ) + if (effect) + { + processEffect(ss, effect); + + //TODO: process all of the setParams that could happen here in the material. ESP. the textures + } + else { osg::notify( osg::WARN ) << "Failed to locate effect " << mat->getInstance_effect()->getUrl().getURI() << std::endl; - return NULL; } - osg::StateSet *ss = processEffect( effect ); - - //TODO: process all of the setParams that could happen here in the material. ESP. the textures - - return ss; } -osg::StateSet *daeReader::processEffect( domEffect *effect ) +// +// attributes: +// 1 id +// 0..1 name +// elements: +// 0..1 +// 0..* +// 0..* +// 0..* +// 1..* +// 0..* +void daeReader::processEffect(osg::StateSet *ss, domEffect *effect ) { bool hasCOMMON = false; - osg::StateSet *ss = NULL; for ( size_t i = 0; i < effect->getFx_profile_abstract_array().getCount(); i++ ) { @@ -119,21 +155,28 @@ osg::StateSet *daeReader::processEffect( domEffect *effect ) continue; } currentEffect = effect; - ss = processProfileCOMMON( pc ); + processProfileCOMMON(ss, pc); hasCOMMON = true; continue; } osg::notify( osg::WARN ) << "unsupported effect profile " << effect->getFx_profile_abstract_array()[i]->getTypeName() << std::endl; } - - return ss; } -osg::StateSet *daeReader::processProfileCOMMON( domProfile_COMMON *pc ) +// +// elements: +// 0..* , +// 1 +// attributes: +// elements: +// 0..1 +// 0..* , +// 1 , , , +// 0..* +// 0..* +void daeReader::processProfileCOMMON(osg::StateSet *ss, domProfile_COMMON *pc ) { - osg::StateSet *ss = new osg::StateSet(); - domProfile_COMMON::domTechnique *teq = pc->getTechnique(); domProfile_COMMON::domTechnique::domConstant *c = teq->getConstant(); @@ -143,42 +186,53 @@ osg::StateSet *daeReader::processProfileCOMMON( domProfile_COMMON *pc ) ss->setMode( GL_CULL_FACE, GL_TRUE ); - if (m_AuthoringTool == GOOGLE_SKETCHUP) + // See if there are any extra's that are supported by OpenSceneGraph + const domExtra_Array& ExtraArray = pc->getExtra_array(); + size_t NumberOfExtras = ExtraArray.getCount(); + size_t CurrentExtra; + for (CurrentExtra = 0; CurrentExtra < NumberOfExtras; CurrentExtra++) { - const domExtra_Array& ExtraArray = pc->getExtra_array(); - size_t NumberOfExtras = ExtraArray.getCount(); - size_t CurrentExtra; - for (CurrentExtra = 0; CurrentExtra < NumberOfExtras; CurrentExtra++) + const domTechnique_Array& TechniqueArray = ExtraArray[CurrentExtra]->getTechnique_array(); + size_t NumberOfTechniques = TechniqueArray.getCount(); + size_t CurrentTechnique; + for (CurrentTechnique = 0; CurrentTechnique < NumberOfTechniques; CurrentTechnique++) { - const domTechnique_Array& TechniqueArray = ExtraArray[CurrentExtra]->getTechnique_array(); - size_t NumberOfTechniques = TechniqueArray.getCount(); - size_t CurrentTechnique; - for (CurrentTechnique = 0; CurrentTechnique < NumberOfTechniques; CurrentTechnique++) + // + // 0 + // + if (strcmp(TechniqueArray[CurrentTechnique]->getProfile(), "GOOGLEEARTH") == 0) { - if (strcmp(TechniqueArray[CurrentTechnique]->getProfile(), "GOOGLEEARTH") == 0) + const daeElementRefArray& ElementArray = TechniqueArray[CurrentTechnique]->getContents(); + size_t NumberOfElements = ElementArray.getCount(); + size_t CurrentElement; + for (CurrentElement = 0; CurrentElement < NumberOfElements; CurrentElement++) { - const daeElementRefArray& ElementArray = TechniqueArray[CurrentTechnique]->getContents(); - size_t NumberOfElements = ElementArray.getCount(); - size_t CurrentElement; - for (CurrentElement = 0; CurrentElement < NumberOfElements; CurrentElement++) + domAny* pAny = (domAny*)ElementArray[CurrentElement].cast(); + if (strcmp(pAny->getElementName(), "double_sided") == 0) { - domAny* pAny = (domAny*)ElementArray[CurrentElement].cast(); - if (strcmp(pAny->getElementName(), "double_sided") == 0) - { - daeString Value = pAny->getValue(); - if (strcmp(Value, "1") == 0) - ss->setMode( GL_CULL_FACE, GL_FALSE ); - } + daeString Value = pAny->getValue(); + if (strcmp(Value, "1") == 0) + ss->setMode( GL_CULL_FACE, GL_FALSE ); } } } } } - //ss->setMode( GL_LIGHTING, GL_FALSE ); - osg::ref_ptr< osg::Material > mat = new osg::Material(); bool insertMat = false; + // + // elements: + // 0..1 + // 0..1 + // 0..1 + // 0..1 + // 0..1 + // 0..1 + // 0..1 + // 0..1 + // 0..1 + // 0..1 if ( b != NULL ) { bool tmp; @@ -197,7 +251,7 @@ osg::StateSet *daeReader::processProfileCOMMON( domProfile_COMMON *pc ) ss->setTextureAttribute( 0, sa ); } - tmp = processColorOrTextureType( b->getSpecular(), osg::Material::SPECULAR, mat.get(), b->getShininess() ); + tmp = processColorOrTextureType( b->getSpecular(), osg::Material::SPECULAR, mat.get(), b->getShininess(), NULL, true ); insertMat = insertMat || tmp; osg::StateAttribute *sa2 = NULL; @@ -214,16 +268,33 @@ osg::StateSet *daeReader::processProfileCOMMON( domProfile_COMMON *pc ) osg::notify( osg::WARN ) << "Already have a texture in the diffuse channel" << std::endl; } } - } + // + // elements: + // 0..1 + // 0..1 + // 0..1 + // 0..1 + // 0..1 + // 0..1 + // 0..1 + // 0..1 + // 0..1 + // 0..1 else if ( p != NULL ) { bool tmp; tmp = processColorOrTextureType( p->getEmission(), osg::Material::EMISSION, mat.get() ); insertMat = insertMat || tmp; - tmp = processColorOrTextureType( p->getAmbient(), osg::Material::AMBIENT, mat.get() ); + osg::StateAttribute *sa1 = NULL; + tmp = processColorOrTextureType( p->getAmbient(), osg::Material::AMBIENT, mat.get(), NULL, &sa1 ); insertMat = insertMat || tmp; + if ( sa1 != NULL ) + { + ss->setTextureMode( 1, GL_TEXTURE_2D, GL_TRUE ); + ss->setTextureAttribute( 0, sa1 ); + } osg::StateAttribute *sa = NULL; tmp = processColorOrTextureType( p->getDiffuse(), osg::Material::DIFFUSE, mat.get(), NULL, &sa ); @@ -253,6 +324,16 @@ osg::StateSet *daeReader::processProfileCOMMON( domProfile_COMMON *pc ) } } + // + // elements: + // 0..1 + // 0..1 + // 0..1 + // 0..1 + // 0..1 + // 0..1 + // 0..1 + // 0..1 else if ( l != NULL ) { bool tmp; @@ -287,6 +368,14 @@ osg::StateSet *daeReader::processProfileCOMMON( domProfile_COMMON *pc ) } } + // + // elements: + // 0..1 + // 0..1 + // 0..1 + // 0..1 + // 0..1 + // 0..1 else if ( c != NULL ) { insertMat = processColorOrTextureType( c->getEmission(), osg::Material::EMISSION, mat.get() ); @@ -303,21 +392,32 @@ osg::StateSet *daeReader::processProfileCOMMON( domProfile_COMMON *pc ) { ss->setAttribute( mat.get() ); } - - return ss; } -bool daeReader::processColorOrTextureType( domCommon_color_or_texture_type *cot, -osg::Material::ColorMode channel, -osg::Material *mat, -domCommon_float_or_param_type *fop, -osg::StateAttribute **sa ) +// colorOrTexture +// 1 of +// +// +// attributes: +// 1 ref +// +// attributes: +// 1 texture +// 1 texcoord +// 0..* extra +bool daeReader::processColorOrTextureType( domCommon_color_or_texture_type *cot, + osg::Material::ColorMode channel, + osg::Material *mat, + domCommon_float_or_param_type *fop, + osg::StateAttribute **sa, + bool blinn) { if ( cot == NULL ) { return false; } bool retVal = false; + //osg::StateAttribute *sa = NULL; //TODO: Make all channels process type of value if ( channel == osg::Material::EMISSION ) @@ -328,7 +428,6 @@ osg::StateAttribute **sa ) mat->setEmission( osg::Material::FRONT_AND_BACK, osg::Vec4( f4[0], f4[1], f4[2], f4[3] ) ); retVal = true; } - else if (cot->getParam() != NULL) { domFloat4 f4; @@ -338,10 +437,14 @@ osg::StateAttribute **sa ) retVal = true; } } - else + else if (cot->getTexture() != NULL) { osg::notify( osg::WARN ) << "Currently no support for in Emission channel " << std::endl; } + else + { + osg::notify( osg::WARN ) << "Missing , or in Emission channel " << std::endl; + } } else if ( channel == osg::Material::AMBIENT ) { @@ -360,9 +463,14 @@ osg::StateAttribute **sa ) retVal = true; } } + else if (cot->getTexture() != NULL && sa != NULL) + { + *sa = processTexture( cot->getTexture() ); + //osg::notify( osg::WARN ) << "Currently no support for in Ambient channel " << std::endl; + } else { - osg::notify( osg::WARN ) << "Currently no support for in Ambient channel " << std::endl; + osg::notify( osg::WARN ) << "Missing , or in Ambient channel " << std::endl; } } else if ( channel == osg::Material::DIFFUSE ) @@ -377,8 +485,7 @@ osg::StateAttribute **sa ) { *sa = processTexture( cot->getTexture() ); domExtra *extra = cot->getTexture()->getExtra(); - if ( extra != NULL && extra->getType() != NULL && - strcmp( extra->getType(), "color" ) == 0 ) + if ( extra != NULL && extra->getType() != NULL && strcmp( extra->getType(), "color" ) == 0 ) { //the extra data for osg. Diffuse color can happen with a texture. for ( unsigned int i = 0; i < extra->getTechnique_array().getCount(); i++ ) @@ -406,6 +513,10 @@ osg::StateAttribute **sa ) retVal = true; } } + else + { + osg::notify( osg::WARN ) << "Missing , or in Diffuse channel " << std::endl; + } } else if ( channel == osg::Material::SPECULAR ) { @@ -415,7 +526,7 @@ osg::StateAttribute **sa ) mat->setSpecular( osg::Material::FRONT_AND_BACK, osg::Vec4( f4[0], f4[1], f4[2], f4[3] ) ); retVal = true; } - else if (cot->getParam() != NULL) + else if (cot->getParam() != NULL) { domFloat4 f4; if (GetFloat4Param(cot->getParam()->getRef(), f4)) @@ -424,13 +535,25 @@ osg::StateAttribute **sa ) retVal = true; } } - else + else if (cot->getTexture() != NULL) { osg::notify( osg::WARN ) << "Currently no support for in Specular channel " << std::endl; } + else + { + osg::notify( osg::WARN ) << "Missing , or in Specular channel " << std::endl; + } + if ( fop != NULL && fop->getFloat() != NULL ) { - mat->setShininess( osg::Material::FRONT_AND_BACK, fop->getFloat()->getValue() ); + float shininess = fop->getFloat()->getValue(); + if (blinn) + { + // If the blinn mode is in the range [0,1] rescale it to [0,128] + if (shininess < 1) + shininess *= 128.0f; + } + mat->setShininess( osg::Material::FRONT_AND_BACK, shininess ); retVal = true; } } @@ -808,6 +931,28 @@ osg::StateAttribute *daeReader::processTexture( domCommon_color_or_texture_type_ return t2D; } + +/* +Collada 1.4.1 Specification (2nd Edition) Patch Release Notes: Revision C Release notes + +In , , , and , the child element now has an +optional opaque attribute whose valid values are: +• A_ONE (the default): Takes the transparency information from the color’s alpha channel, where the value 1.0 is opaque. +• RGB_ZERO: Takes the transparency information from the color’s red, green, and blue channels, where the value 0.0 is opaque, +with each channel modulated independently. +In the Specification, this is described in the “FX Reference” chapter in the +common_color_or_texture_type entry, along with a description of how transparency works in the +“Getting Started with COLLADA FX” chapter in the “Determining Transparency” section. + + +Collada Digital Asset Schema Release 1.5.0 Release Notes + +The element’s opaque attribute now allows, in addition to A_ONE and RGB_ZERO, the following values: +• A_ZERO (the default): Takes the transparency information from the color’s alpha channel, where the value 0.0 is opaque. +• RGB_ONE: Takes the transparency information from the color’s red, green, and blue channels, where the value 1.0 is opaque, +with each channel modulated independently. +*/ + osg::StateAttribute *daeReader::processTransparencySettings( domCommon_transparent_type *ctt, domCommon_float_or_param_type *pTransparency, osg::StateSet *ss ) { if (NULL == ctt && NULL == pTransparency) @@ -881,17 +1026,6 @@ osg::StateAttribute *daeReader::processTransparencySettings( domCommon_transpare } } - osg::BlendColor *bc = new osg::BlendColor(); - bc->setConstantColor(osg::Vec4( f4[0] * Transparency, f4[1] * Transparency, f4[2] * Transparency, f4[3] * Transparency )); - ss->setAttribute( bc ); - osg::BlendFunc *bf; - if (FX_OPAQUE_ENUM_A_ONE == Opaque) - bf = new osg::BlendFunc(GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA); - else - bf = new osg::BlendFunc(GL_ONE_MINUS_CONSTANT_COLOR, GL_CONSTANT_COLOR); - ss->setAttribute( bf ); - ss->setMode( GL_BLEND, GL_TRUE ); - if (FX_OPAQUE_ENUM_A_ONE == Opaque) { if (Transparency * f4[3] > 0.99f) @@ -908,7 +1042,20 @@ osg::StateAttribute *daeReader::processTransparencySettings( domCommon_transpare return NULL; } + osg::BlendColor *bc = new osg::BlendColor(); + bc->setConstantColor(osg::Vec4( f4[0] * Transparency, f4[1] * Transparency, f4[2] * Transparency, f4[3] * Transparency )); + ss->setAttribute( bc ); + osg::BlendFunc *bf; + if (FX_OPAQUE_ENUM_A_ONE == Opaque) + bf = new osg::BlendFunc(GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA); + else + bf = new osg::BlendFunc(GL_ONE_MINUS_CONSTANT_COLOR, GL_CONSTANT_COLOR); + ss->setAttribute( bf ); + ss->setMode( GL_BLEND, GL_TRUE ); + ss->setRenderingHint( osg::StateSet::TRANSPARENT_BIN ); ss->setRenderBinDetails( 10, "DepthSortedBin" ); return NULL; } + +// 0..* \ No newline at end of file diff --git a/src/osgPlugins/dae/daeRSceneObjects.cpp b/src/osgPlugins/dae/daeRSceneObjects.cpp index f4c012d19..c02bc25c4 100644 --- a/src/osgPlugins/dae/daeRSceneObjects.cpp +++ b/src/osgPlugins/dae/daeRSceneObjects.cpp @@ -13,18 +13,316 @@ #include "daeReader.h" #include +#include #include #include #include #include -#include #include +#include +#include +#include +#include using namespace osgdae; +osg::Node* daeReader::processOsgMultiSwitch(domTechnique* teq) +{ + osgSim::MultiSwitch* msw = new osgSim::MultiSwitch; + + domAny* any = daeSafeCast(teq->getChild("ActiveSwitchSet")); + if (any) + { + msw->setActiveSwitchSet(parseString(any->getValue())); + } + else + { + osg::notify(osg::WARN) << "Expected element 'ActiveSwitchSet' not found" << std::endl; + } + + any = daeSafeCast(teq->getChild("ValueLists")); + if (any) + { + unsigned int numChildren = any->getChildren().getCount(); + for (unsigned int currChild = 0; currChild < numChildren; currChild++) + { + domAny* child = daeSafeCast(any->getChildren()[currChild]); + if (child) + { + if (strcmp(child->getElementName(), "ValueList" ) == 0 ) + { + std::list stringValues; + osgSim::MultiSwitch::ValueList values; + + cdom::tokenize(child->getValue(), " ", stringValues); + cdom::tokenIter iter = stringValues.begin(); + + while (iter != stringValues.end()) + { + values.push_back(parseString(*iter)); + ++iter; + } + + msw->setValueList(currChild, values); + } + else + { + osg::notify(osg::WARN) << "Child of element 'ValueLists' is not of type 'ValueList'" << std::endl; + } + } + else + { + osg::notify(osg::WARN) << "Element 'ValueLists' does not contain expected elements." << std::endl; + } + } + } + else + { + osg::notify(osg::WARN) << "Expected element 'ValueLists' not found" << std::endl; + } + return msw; +} + +osg::Node* daeReader::processOsgSwitch(domTechnique* teq) +{ + osg::Switch* sw = new osg::Switch; + + domAny* any = daeSafeCast< domAny >(teq->getChild("ValueList")); + if (any) + { + std::list stringValues; + + cdom::tokenize(any->getValue(), " ", stringValues); + cdom::tokenIter iter = stringValues.begin(); + + int pos = 0; + while (iter != stringValues.end()) + { + sw->setValue(pos++, parseString(*iter)); + ++iter; + } + } + else + { + osg::notify(osg::WARN) << "Expected element 'ValueList' not found" << std::endl; + } + return sw; +} + +osg::Node* daeReader::processOsgSequence(domTechnique* teq) +{ + osg::Sequence* sq = new osg::Sequence; + + domAny* any = daeSafeCast< domAny >(teq->getChild("FrameTime")); + if (any) + { + std::list stringValues; + + cdom::tokenize(any->getValue(), " ", stringValues); + cdom::tokenIter iter = stringValues.begin(); + + int frame = 0; + while (iter != stringValues.end()) + { + sq->setTime(frame++, parseString(*iter)); + ++iter; + } + } + else + { + osg::notify(osg::WARN) << "Expected element 'FrameTime' not found" << std::endl; + } + + any = daeSafeCast< domAny >(teq->getChild("LastFrameTime")); + if (any) + { + sq->setLastFrameTime(parseString(any->getValue())); + } + else + { + osg::notify(osg::WARN) << "Expected element 'LastFrameTime' not found" << std::endl; + } + + osg::Sequence::LoopMode loopmode; + any = daeSafeCast< domAny >(teq->getChild("LoopMode")); + if (any) + { + loopmode = (osg::Sequence::LoopMode)parseString(any->getValue()); + } + else + { + osg::notify(osg::WARN) << "Expected element 'LoopMode' not found" << std::endl; + } + + int begin=0; + any = daeSafeCast< domAny >(teq->getChild("IntervalBegin")); + if (any) + { + begin = parseString(any->getValue()); + } + else + { + osg::notify(osg::WARN) << "Expected element 'IntervalBegin' not found" << std::endl; + } + + int end=-1; + any = daeSafeCast< domAny >(teq->getChild("IntervalEnd")); + if (any) + { + end = parseString(any->getValue()); + } + else + { + osg::notify(osg::WARN) << "Expected element 'IntervalEnd' not found" << std::endl; + } + + sq->setInterval(loopmode, begin, end); + + float speed = 0; + any = daeSafeCast< domAny >(teq->getChild("DurationSpeed")); + if (any) + { + speed = parseString(any->getValue()); + } + else + { + osg::notify(osg::WARN) << "Expected element 'DurationSpeed' not found" << std::endl; + } + + int nreps = -1; + any = daeSafeCast< domAny >(teq->getChild("DurationNReps")); + if (any) + { + nreps = parseString(any->getValue()); + } + else + { + osg::notify(osg::WARN) << "Expected element 'DurationNReps' not found" << std::endl; + } + + sq->setDuration(speed, nreps); + + any = daeSafeCast< domAny >(teq->getChild("SequenceMode")); + if (any) + { + sq->setMode((osg::Sequence::SequenceMode)parseString(any->getValue())); + } + else + { + osg::notify(osg::WARN) << "Expected element 'SequenceMode' not found" << std::endl; + } + + return sq; +} + + +osg::Node* daeReader::processOsgLOD(domTechnique* teq) +{ + osg::LOD* lod = new osg::LOD; + + domAny* any = daeSafeCast< domAny >(teq->getChild("Center")); + if (any) + { + // If a center is specified + lod->setCenterMode(osg::LOD::USER_DEFINED_CENTER); + lod->setCenter(parseVec3String(any->getValue())); + + any = daeSafeCast< domAny >(teq->getChild("Radius")); + if (any) + { + lod->setRadius(parseString(any->getValue())); + } + else + { + osg::notify(osg::WARN) << "Expected element 'Radius' not found" << std::endl; + } + } + + any = daeSafeCast< domAny >(teq->getChild("RangeMode")); + if (any) + { + lod->setRangeMode((osg::LOD::RangeMode)parseString(any->getValue())); + } + else + { + osg::notify(osg::WARN) << "Expected element 'RangeMode' not found" << std::endl; + } + + any = daeSafeCast< domAny >(teq->getChild("RangeList")); + if (any) + { + osg::LOD::RangeList rangelist; + + unsigned int numChildren = any->getChildren().getCount(); + for (unsigned int currChild = 0; currChild < numChildren; currChild++) + { + domAny* child = daeSafeCast(any->getChildren()[currChild]); + if (child) + { + if (strcmp(child->getElementName(), "MinMax" ) == 0 ) + { + std::list stringValues; + osg::LOD::MinMaxPair minMaxPair; + + cdom::tokenize(child->getValue(), " ", stringValues); + cdom::tokenIter iter = stringValues.begin(); + + if (iter != stringValues.end()) + { + minMaxPair.first = parseString(*iter); + ++iter; + } + else + { + osg::notify(osg::WARN) << "'MinMax' does not contain a valid minimum value" << std::endl; + } + + if (iter != stringValues.end()) + { + minMaxPair.second = parseString(*iter); + } + else + { + osg::notify(osg::WARN) << "'MinMax' does not contain a valid maximum value" << std::endl; + } + + rangelist.push_back(minMaxPair); + } + else + { + osg::notify(osg::WARN) << "Child of element 'RangeList' is not of type 'MinMax'" << std::endl; + } + } + else + { + osg::notify(osg::WARN) << "Element 'RangeList' does not contain expected elements." << std::endl; + } + } + + lod->setRangeList(rangelist); + } + else + { + osg::notify(osg::WARN) << "Expected element 'RangeList' not found" << std::endl; + } + + return lod; +} + +// +// attributes: +// id, name +// elements: +// 0..1 +// 1 +// 1 , , , +// 0..* +// 0..* osg::Node* daeReader::processLight( domLight *dlight ) { + osg::Node *node = new osg::Switch(); + //do light processing here. domLight::domTechnique_common::domAmbient *ambient; domLight::domTechnique_common::domDirectional *directional; @@ -38,8 +336,6 @@ osg::Node* daeReader::processLight( domLight *dlight ) return NULL; } - osg::Node* node = new osg::Switch(); - osg::Light* light = new osg::Light(); osg::LightSource* lightsource = new osg::LightSource(); @@ -182,11 +478,25 @@ osg::Node* daeReader::processLight( domLight *dlight ) return node; } -osg::Node* daeReader::processCamera( domCamera* /*dcamera*/ ) +// +// attributes: +// id, name +// elements: +// 0..1 +// 1 +// 1 +// 1 , +// 0..* +// 0..* +// 0..* +// 1 +// 0..* +// 0..* +osg::Node* daeReader::processCamera( domCamera * dcamera ) { - //TODO: Make the camera actually make a camera to view from. Not just draw a cone. osg::Node *node = new osg::Switch(); + //TODO: Make the camera actually make a camera to view from. Not just draw a cone. osg::Cone* cone = new osg::Cone(); osg::ShapeDrawable* sd = new osg::ShapeDrawable(cone); diff --git a/src/osgPlugins/dae/daeRTransforms.cpp b/src/osgPlugins/dae/daeRTransforms.cpp index a4e266aed..6a03ab1e3 100644 --- a/src/osgPlugins/dae/daeRTransforms.cpp +++ b/src/osgPlugins/dae/daeRTransforms.cpp @@ -13,185 +13,357 @@ #include "daeReader.h" #include +#include #include -#include #include +#include using namespace osgdae; -osg::Transform* daeReader::processMatrix( domMatrix *mat ) +// Note , , , , and may appear in any order +// These transformations can be combined in any number and ordering to produce the desired +// coordinate systemfor the parent element. The COLLADA specificatin requires that the +// transformation elements are processed in order and accumulate the result as if they were +// converted to column-order matrices and concatenated using matrix post-multiplication. +osg::Node* daeReader::processOsgMatrixTransform( domNode *node ) { - osg::Transform* xform = new osg::MatrixTransform(); - xform->setDataVariance(osg::Object::STATIC); + osg::MatrixTransform* matNode = new osg::MatrixTransform; + osg::Matrix matrix; - xform->setName( mat->getSid() ? mat->getSid() : "" ); - - osg::Matrix m; - - if (mat->getValue().getCount() != 16 ) { - osg::notify(osg::WARN)<<"Data is wrong size for matrix"<getValue().getRawData()); - m.set( mat->getValue()[0], mat->getValue()[4], mat->getValue()[8], mat->getValue()[12], - mat->getValue()[1], mat->getValue()[5], mat->getValue()[9], mat->getValue()[13], - mat->getValue()[2], mat->getValue()[6], mat->getValue()[10], mat->getValue()[14], - mat->getValue()[3], mat->getValue()[7], mat->getValue()[11], mat->getValue()[15] ); - - xform->asMatrixTransform()->setMatrix(m); - - return xform; -} - -osg::Transform* daeReader::processTranslate( domTranslate *trans ) -{ - osg::Transform* xform = new osg::PositionAttitudeTransform(); - //xform->setDataVariance(osg::Object::STATIC); - - xform->setName( trans->getSid() ? trans->getSid() : "" ); - - if (trans->getValue().getCount() != 3 ) { - osg::notify(osg::WARN)<<"Data is wrong size for translate"<getValue(); - - xform->asPositionAttitudeTransform()->setPosition( - osg::Vec3(t[0],t[1],t[2])); - - return xform; -} - -osg::Transform* daeReader::processRotate( domRotate *rot ) -{ - osg::Transform* xform = new osg::PositionAttitudeTransform(); - //xform->setDataVariance(osg::Object::STATIC); - - xform->setName( rot->getSid() ? rot->getSid() : "" ); - - if (rot->getValue().getCount() != 4 ) { - osg::notify(osg::WARN)<<"Data is wrong size for rotate"<getValue(); - - osg::Vec3 axis; - axis.set(r[0],r[1],r[2]); - xform->asPositionAttitudeTransform()->setAttitude( - osg::Quat(osg::DegreesToRadians(r[3]),axis)); - - return xform; -} - -osg::Transform* daeReader::processScale( domScale *scale ) -{ - osg::Transform* xform = new osg::PositionAttitudeTransform(); - //xform->setDataVariance(osg::Object::STATIC); - - xform->setName( scale->getSid() ? scale->getSid() : "" ); - - if (scale->getValue().getCount() != 3 ) { - osg::notify(osg::WARN)<<"Data is wrong size for scale"<getValue(); - - xform->asPositionAttitudeTransform()->setScale( - osg::Vec3(s[0],s[1],s[2])); - - return xform; -} - -osg::Transform* daeReader::processLookat( domLookat *la ) -{ - osg::Transform* xform = new osg::MatrixTransform(); - xform->setDataVariance(osg::Object::STATIC); - - xform->setName( la->getSid() ? la->getSid() : "" ); - - if (la->getValue().getCount() != 9 ) { - osg::notify(osg::WARN)<<"Data is wrong size for lookat"<getValue()[0], la->getValue()[1], la->getValue()[2] ); - center.set( la->getValue()[3], la->getValue()[4], la->getValue()[5] ); - up.set( la->getValue()[6], la->getValue()[7], la->getValue()[8] ); - - m.makeLookAt( eye, center, up ); - - xform->asMatrixTransform()->setMatrix(m); - - return xform; -} - -osg::Transform* daeReader::processSkew( domSkew *skew ) -{ - osg::Transform* xform = new osg::MatrixTransform(); - xform->setDataVariance(osg::Object::STATIC); - - xform->setName( skew->getSid() ? skew->getSid() : "" ); - - if (skew->getValue().getCount() != 9 ) { - osg::notify(osg::WARN)<<"Data is wrong size for skew"<getValue(); - - float angle = s[0]; - float shear = sin(osg::DegreesToRadians(angle)); - osg::Vec3 around(s[1],s[2],s[3]); - osg::Vec3 along(s[4],s[5],s[6]); - - osg::Vec3 const x(1,0,0); - osg::Vec3 const y(0,1,0); - osg::Vec3 const z(0,0,1); - - osg::Matrix m; - - if ( along == x ) { - if ( around == y ) { - m(2,0) = shear; - } else if ( around == z ) { - m(1,0) = -shear; - } else { - //osg::notify(osg::WARN)<<"Unsupported skew around "<getContents().getCount(); + for (size_t i = 0; i < count; i++ ) + { + domRotate * rot = daeSafeCast< domRotate >( node->getContents()[i] ); + if (rot) + { + domFloat4& r = rot->getValue(); + if (r.getCount() != 4 ) + { + osg::notify(osg::WARN)<<"Data is wrong size for rotate"<( node->getContents()[i] ); + if (trans != NULL) + { + domFloat3& t = trans->getValue(); + if (t.getCount() != 3 ) + { + osg::notify(osg::WARN)<<"Data is wrong size for translate"<( node->getContents()[i] ); + if (scale != NULL) + { + domFloat3& s = scale->getValue(); + if (s.getCount() != 3 ) + { + osg::notify(osg::WARN)<<"Data is wrong size for scale"<( node->getContents()[i] ); + if (mat != NULL) + { + if (mat->getValue().getCount() != 16 ) + { + osg::notify(osg::WARN)<<"Data is wrong size for matrix"<getValue()[0], mat->getValue()[4], mat->getValue()[8], mat->getValue()[12], + mat->getValue()[1], mat->getValue()[5], mat->getValue()[9], mat->getValue()[13], + mat->getValue()[2], mat->getValue()[6], mat->getValue()[10], mat->getValue()[14], + mat->getValue()[3], mat->getValue()[7], mat->getValue()[11], mat->getValue()[15] ); + + matrix = mMat * matrix; + continue; + } + + domLookat * la = daeSafeCast< domLookat >( node->getContents()[i] ); + if (la != NULL) + { + if (la->getValue().getCount() != 9 ) + { + osg::notify(osg::WARN)<<"Data is wrong size for lookat"<getValue()[0], la->getValue()[1], la->getValue()[2]); + osg::Vec3 center(la->getValue()[3], la->getValue()[4], la->getValue()[5] ); + osg::Vec3 up( la->getValue()[6], la->getValue()[7], la->getValue()[8] ); + lookatMat.makeLookAt( eye, center, up ); + + matrix = lookatMat * matrix; + continue; + } + + domSkew * skew = daeSafeCast< domSkew >( node->getContents()[i] ); + if (skew != NULL) + { + if (skew->getValue().getCount() != 7 ) + { + osg::notify(osg::WARN)<<"Data is wrong size for skew"<getValue(); + + float shear = sin(osg::DegreesToRadians(s[0])); + // axis of rotation + osg::Vec3f around(s[1],s[2],s[3]); + // axis of translation + osg::Vec3f along(s[4],s[5],s[6]); + + along.normalize(); + osg::Vec3f a = around - (along * (around * along)); + a.normalize(); + + float an1 = around * a; + float an2 = around * along; + + float rx = an1 * cos(shear) - an2 * sin(shear); + float ry = an1 * sin(shear) + an2 * cos(shear); + + if (rx <= 0.0) + { + osg::notify(osg::WARN)<<"skew angle too large"<setMatrix(matrix); - if (angle > 0) { - //osg::notify(osg::NOTICE)<<"Skew: angle("<getOrCreateStateSet(); + ss->setMode(GL_RESCALE_NORMAL, osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE); } - xform->asMatrixTransform()->setMatrix(m); - - return xform; + return matNode; +} + +osg::Node* daeReader::processOsgDOFTransform(domTechnique* teq) +{ + osgSim::DOFTransform* dof = new osgSim::DOFTransform; + + domAny* any = daeSafeCast< domAny >(teq->getChild("MinHPR")); + if (any) + { + dof->setMinHPR(parseVec3String(any->getValue())); + } + else + { + osg::notify(osg::WARN) << "Expected element 'MinHPR' not found" << std::endl; + } + + any = daeSafeCast< domAny >(teq->getChild("MaxHPR")); + if (any) + { + dof->setMaxHPR(parseVec3String(any->getValue())); + } + else + { + osg::notify(osg::WARN) << "Expected element 'MaxHPR' not found" << std::endl; + } + + any = daeSafeCast< domAny >(teq->getChild("IncrementHPR")); + if (any) + { + dof->setIncrementHPR(parseVec3String(any->getValue())); + } + else + { + osg::notify(osg::WARN) << "Expected element 'IncrementHPR' not found" << std::endl; + } + + any = daeSafeCast< domAny >(teq->getChild("CurrentHPR")); + if (any) + { + dof->setCurrentHPR(parseVec3String(any->getValue())); + } + else + { + osg::notify(osg::WARN) << "Expected element 'CurrentHPR' not found" << std::endl; + } + + any = daeSafeCast< domAny >(teq->getChild("MinTranslate")); + if (any) + { + dof->setMinTranslate(parseVec3String(any->getValue())); + } + else + { + osg::notify(osg::WARN) << "Expected element 'MinTranslate' not found" << std::endl; + } + + any = daeSafeCast< domAny >(teq->getChild("MaxTranslate")); + if (any) + { + dof->setMaxTranslate(parseVec3String(any->getValue())); + } + else + { + osg::notify(osg::WARN) << "Expected element 'MaxTranslate' not found" << std::endl; + } + + any = daeSafeCast< domAny >(teq->getChild("IncrementTranslate")); + if (any) + { + dof->setIncrementTranslate(parseVec3String(any->getValue())); + } + else + { + osg::notify(osg::WARN) << "Expected element 'IncrementTranslate' not found" << std::endl; + } + + any = daeSafeCast< domAny >(teq->getChild("CurrentTranslate")); + if (any) + { + dof->setCurrentTranslate(parseVec3String(any->getValue())); + } + else + { + osg::notify(osg::WARN) << "Expected element 'CurrentTranslate' not found" << std::endl; + } + + any = daeSafeCast< domAny >(teq->getChild("MinScale")); + if (any) + { + dof->setMinScale(parseVec3String(any->getValue())); + } + else + { + osg::notify(osg::WARN) << "Expected element 'MinScale' not found" << std::endl; + } + + any = daeSafeCast< domAny >(teq->getChild("MaxScale")); + if (any) + { + dof->setMaxScale(parseVec3String(any->getValue())); + } + else + { + osg::notify(osg::WARN) << "Expected element 'MaxScale' not found" << std::endl; + } + + any = daeSafeCast< domAny >(teq->getChild("IncrementScale")); + if (any) + { + dof->setIncrementScale(parseVec3String(any->getValue())); + } + else + { + osg::notify(osg::WARN) << "Expected element 'IncrementScale' not found" << std::endl; + } + + any = daeSafeCast< domAny >(teq->getChild("CurrentScale")); + if (any) + { + dof->setCurrentScale(parseVec3String(any->getValue())); + } + else + { + osg::notify(osg::WARN) << "Expected element 'CurrentScale' not found" << std::endl; + } + + any = daeSafeCast< domAny >(teq->getChild("MultOrder")); + if (any) + { + dof->setHPRMultOrder((osgSim::DOFTransform::MultOrder)parseString(any->getValue())); + } + else + { + osg::notify(osg::WARN) << "Expected element 'MultOrder' not found" << std::endl; + } + + any = daeSafeCast< domAny >(teq->getChild("LimitationFlags")); + if (any) + { + dof->setLimitationFlags(parseString(any->getValue())); + } + else + { + osg::notify(osg::WARN) << "Expected element 'LimitationFlags' not found" << std::endl; + } + + any = daeSafeCast< domAny >(teq->getChild("AnimationOn")); + if (any) + { + dof->setAnimationOn(parseString(any->getValue())); + } + else + { + osg::notify(osg::WARN) << "Expected element 'AnimationOn' not found" << std::endl; + } + + any = daeSafeCast< domAny >(teq->getChild("PutMatrix")); + if (any) + { + osg::Matrix mat = parseMatrixString(any->getValue()); + dof->setPutMatrix(mat); + dof->setInversePutMatrix( osg::Matrixd::inverse( mat ) ); + } + else + { + osg::notify(osg::WARN) << "Expected element 'PutMatrix' not found" << std::endl; + } + + return dof; } diff --git a/src/osgPlugins/dae/daeReader.cpp b/src/osgPlugins/dae/daeReader.cpp index af4760a91..dfcf4af02 100644 --- a/src/osgPlugins/dae/daeReader.cpp +++ b/src/osgPlugins/dae/daeReader.cpp @@ -13,9 +13,11 @@ #include "daeReader.h" #include +#include #include #include #include +#include using namespace osgdae; @@ -86,19 +88,24 @@ bool daeReader::convert( const std::string &fileURI ) m_AssetUp_axis = document->getAsset()->getUp_axis()->getValue(); } - if (dae->getDatabase()) { + if (dae->getDatabase()) + { count = dae->getDatabase()->getElementCount(NULL, COLLADA_TYPE_INSTANCE_RIGID_BODY, NULL); // build a std::map for lookup if Group or PositionAttitudeTransform should be created, // i.e, make it easy to check if a instance_rigid_body targets a visual node - for (int i=0; igetDatabase()->getElement(&colladaElement, i, NULL, COLLADA_TYPE_INSTANCE_RIGID_BODY); - if (result == DAE_OK) { + if (result == DAE_OK) + { irb = daeSafeCast(colladaElement); - if (irb) { - domNode *node = daeSafeCast(irb->getTarget().getElement()); - if (node && node->getId()) { + if (irb) + { + domNode *node = daeSafeCast(irb->getTarget().getElement()); + if (node && node->getId()) + { _targetMap[ std::string(node->getId()) ] = true; } } @@ -121,7 +128,7 @@ bool daeReader::convert( const std::string &fileURI ) osg::Node* daeReader::processVisualScene( domVisual_scene *scene ) { osg::Node *retVal; - //### do not add an empty group if there is only one + unsigned int nbVisualSceneGroup=scene->getNode_array().getCount(); if (nbVisualSceneGroup==0) { @@ -154,231 +161,246 @@ osg::Node* daeReader::processVisualScene( domVisual_scene *scene ) } } return retVal; - } +osg::Node* daeReader::processExtras(domNode *node) +{ + // See if one of the extras contains OpenSceneGraph specific information + unsigned int numExtras = node->getExtra_array().getCount(); + for (unsigned int currExtra=0; currExtra < numExtras; currExtra++) + { + domExtra* extra = node->getExtra_array()[currExtra]; + domTechnique* teq = NULL; + + daeString extraType = extra->getType(); + if (extraType) + { + if (strcmp(extraType, "Switch") == 0) + { + teq = getOpenSceneGraphProfile(extra); + if (teq) + { + return processOsgSwitch(teq); + } + } + else if (strcmp(extraType, "MultiSwitch") == 0) + { + teq = getOpenSceneGraphProfile(extra); + if (teq) + { + return processOsgMultiSwitch(teq); + } + } + else if (strcmp(extraType, "LOD") == 0) + { + teq = getOpenSceneGraphProfile(extra); + if (teq) + { + return processOsgLOD(teq); + } + } + else if (strcmp(extraType, "DOFTransform") == 0) + { + teq = getOpenSceneGraphProfile(extra); + if (teq) + { + return processOsgDOFTransform(teq); + } + } + else if (strcmp(extraType, "Sequence") == 0) + { + teq = getOpenSceneGraphProfile(extra); + if (teq) + { + return processOsgSequence(teq); + } + } + } + } + return new osg::Group; +} + +void daeReader::processNodeExtra(osg::Node* osgNode, domNode *node) +{ + // See if one of the extras contains OpenSceneGraph specific information + unsigned int numExtras = node->getExtra_array().getCount(); + + for (unsigned int currExtra=0; currExtra < numExtras; currExtra++) + { + domExtra* extra = node->getExtra_array()[currExtra]; + + daeString extraType = extra->getType(); + if (extraType && (strcmp(extraType, "Node") == 0)) + { + domTechnique* teq = getOpenSceneGraphProfile(extra); + if (teq) + { + domAny* any = daeSafeCast< domAny >(teq->getChild("Descriptions")); + if (any) + { + osg::Node::DescriptionList descriptions; + unsigned int numChildren = any->getChildren().getCount(); + for (unsigned int currChild = 0; currChild < numChildren; currChild++) + { + domAny* child = daeSafeCast(any->getChildren()[currChild]); + if (child) + { + if (strcmp(child->getElementName(), "Description" ) == 0 ) + { + std::string value = child->getValue(); + descriptions.push_back(value); + } + else + { + osg::notify(osg::WARN) << "Child of element 'Descriptions' is not of type 'Description'" << std::endl; + } + } + else + { + osg::notify(osg::WARN) << "Element 'Descriptions' does not contain expected elements." << std::endl; + } + } + osgNode->setDescriptions(descriptions); + } + else + { + osg::notify(osg::WARN) << "Expected element 'Descriptions' not found" << std::endl; + } + } + } + } +} + +domTechnique* daeReader::getOpenSceneGraphProfile(domExtra* extra) +{ + unsigned int numTeqs = extra->getTechnique_array().getCount(); + + for ( unsigned int currTeq = 0; currTeq < numTeqs; ++currTeq ) + { + // Only interested in OpenSceneGraph technique + if (strcmp( extra->getTechnique_array()[currTeq]->getProfile(), "OpenSceneGraph" ) == 0 ) + { + return extra->getTechnique_array()[currTeq]; + } + } + return NULL; +} + + +// +// attributes: +// id, name, sid, type, layer +// child elements: +// 0..1 +// 0..* , , , , , +// 0..* +// 0..* +// 0..* +// 0..* +// 0..* +// 0..* +// 0..* osg::Node* daeReader::processNode( domNode *node ) { - osg::Node *retVal; - osg::PositionAttitudeTransform *pat; - - int patcount = node->getRotate_array().getCount() + - node->getScale_array().getCount() + - node->getTranslate_array().getCount(); + // First we need to determine what kind of OSG node we need + // If there exist any of the , , , , , elements + // or if a COLLADA_TYPE_INSTANCE_RIGID_BODY targets this node we need a MatrixTransform + int coordcount = node->getRotate_array().getCount() + + node->getScale_array().getCount() + + node->getTranslate_array().getCount() + + node->getLookat_array().getCount() + + node->getMatrix_array().getCount() + + node->getSkew_array().getCount(); + // See if it is targeted bool targeted = false; - - if (node->getId()) { + if (node->getId()) + { targeted = _targetMap[std::string(node->getId())]; } - - if (patcount > 0 || targeted ) + osg::Node *resultNode; + if (coordcount > 0 || targeted ) { - pat = new osg::PositionAttitudeTransform(); - retVal = pat; - } - else + resultNode = processOsgMatrixTransform(node); + } + else { - retVal = new osg::Group(); + // No transform data, determine node type based on it's available extra data + resultNode = processExtras(node); } - osg::Node *current = retVal; + // See if there is generic node info attached as extra + processNodeExtra(resultNode, node); - retVal->setName( node->getId() ? node->getId() : "" ); + resultNode->setName( node->getId() ? node->getId() : "" ); + osg::Group* groupNode = resultNode->asGroup(); - // Handle rotate, translate and scale first.. - // will make the hierarchy less deep - - // - osg::Quat osgRot; - for (unsigned int i=0; igetRotate_array().getCount(); i++) + if (groupNode) { - daeSmartRef rot = node->getRotate_array().get(i); - if (rot->getValue().getCount() != 4 ) { - osg::notify(osg::WARN)<<"Data is wrong size for rotate"<getValue(); - - osg::Vec3 axis; - axis.set(r[0],r[1],r[2]); - osgRot = osg::Quat(osg::DegreesToRadians(r[3]),axis) * osgRot; - pat->setAttitude(osgRot); - } - - // - osg::Vec3 osgScale = osg::Vec3(1.0, 1.0, 1.0); - for (unsigned int i=0; igetScale_array().getCount(); i++) - { - daeSmartRef scale = node->getScale_array().get(i); - - if (scale->getValue().getCount() != 3 ) { - osg::notify(osg::WARN)<<"Data is wrong size for scale"<getValue(); - - osgScale[0] *= s[0]; - osgScale[1] *= s[1]; - osgScale[2] *= s[2]; - pat->setScale(osgScale); - } - - // - osg::Vec3 osgTrans = osg::Vec3(0.0, 0.0, 0.0); - for (unsigned int i=0; igetTranslate_array().getCount(); i++) - { - daeSmartRef trans = node->getTranslate_array().get(i); - - if (trans->getValue().getCount() != 3 ) { - osg::notify(osg::WARN)<<"Data is wrong size for translate"<getValue(); - osgTrans += osg::Vec3(t[0],t[1],t[2]); - pat->setPosition(osgTrans); - } - - - - size_t count = node->getContents().getCount(); - for ( size_t i = 0; i < count; i++ ) - { - osg::Node *trans = NULL; - - //I'm using daeSafeCast to check type because the pointer comparisons are a lot faster - //than a strcmp - domTranslate * t = daeSafeCast< domTranslate >( node->getContents()[i] ); - if ( t != NULL ) + // 0..* + domInstance_camera_Array cameraInstanceArray = node->getInstance_camera_array(); + for ( size_t i = 0; i < cameraInstanceArray.getCount(); i++ ) { - continue; - } - - domRotate * r = daeSafeCast< domRotate >( node->getContents()[i] ); - if ( r != NULL ) { - continue; - } - - domScale * s = daeSafeCast< domScale >( node->getContents()[i] ); - if ( s != NULL ) { - continue; - } - - domMatrix * m = daeSafeCast< domMatrix >( node->getContents()[i] ); - if ( m != NULL ) { - trans = processMatrix( m ); - if ( trans != NULL ) - { - current->asGroup()->addChild( trans ); - current = trans; - } - continue; - } - - domSkew *sk = daeSafeCast< domSkew >( node->getContents()[i] ); - if ( sk != NULL ) { - trans = processSkew( sk ); - if ( trans != NULL ) - { - current->asGroup()->addChild( trans ); - current = trans; - } - continue; - } - - domInstance_geometry *ig = daeSafeCast< domInstance_geometry >( node->getContents()[i] ); - if ( ig != NULL ) - { - trans = processInstance_geometry( ig ); - if ( trans != NULL ) - { - current->asGroup()->addChild( trans ); - } - continue; - } - - domInstance_controller *ictrl = daeSafeCast< domInstance_controller >( node->getContents()[i] ); - if ( ictrl != NULL ) - { - trans = processInstance_controller( ictrl ); - if ( trans != NULL ) - { - current->asGroup()->addChild( trans ); - } - continue; - } - - domInstance_camera *ic = daeSafeCast< domInstance_camera >( node->getContents()[i] ); - if ( ic != NULL ) - { - daeElement *el = getElementFromURI( ic->getUrl() ); + daeElement *el = getElementFromURI( cameraInstanceArray[i]->getUrl()); domCamera *c = daeSafeCast< domCamera >( el ); - if ( c == NULL ) - { - osg::notify( osg::WARN ) << "Failed to locate camera " << ic->getUrl().getURI() << std::endl; - } - trans = processCamera( c ); - if ( trans != NULL ) - { - current->asGroup()->addChild( trans ); - } - continue; + + if (c) + groupNode->addChild( processCamera( c )); + else + osg::notify( osg::WARN ) << "Failed to locate camera " << cameraInstanceArray[i]->getUrl().getURI() << std::endl; } - - domInstance_light *il = daeSafeCast< domInstance_light >( node->getContents()[i] ); - if ( il != NULL ) + + // 0..* + domInstance_controller_Array controllerInstanceArray = node->getInstance_controller_array(); + for ( size_t i = 0; i < controllerInstanceArray.getCount(); i++ ) { - daeElement *el = getElementFromURI( il->getUrl() ); + groupNode->addChild( processInstanceController( controllerInstanceArray[i] )); + } + + // 0..* + domInstance_geometry_Array geometryInstanceArray = node->getInstance_geometry_array(); + for ( size_t i = 0; i < geometryInstanceArray.getCount(); i++ ) + { + groupNode->addChild( processInstanceGeometry( geometryInstanceArray[i] )); + } + + // 0..* + domInstance_light_Array lightInstanceArray = node->getInstance_light_array(); + for ( size_t i = 0; i < lightInstanceArray.getCount(); i++ ) + { + daeElement *el = getElementFromURI( lightInstanceArray[i]->getUrl()); domLight *l = daeSafeCast< domLight >( el ); - if ( l == NULL ) - { - osg::notify( osg::WARN ) << "Failed to locate light " << il->getUrl().getURI() << std::endl; - } - trans = processLight( l ); - if ( trans != NULL ) - { - current->asGroup()->addChild( trans ); - } - continue; + + if (l) + groupNode->addChild( processLight( l )); + else + osg::notify( osg::WARN ) << "Failed to locate light " << lightInstanceArray[i]->getUrl().getURI() << std::endl; } - domInstance_node *instn = daeSafeCast< domInstance_node >( node->getContents()[i] ); - if ( instn != NULL ) + // 0..* + domInstance_node_Array nodeInstanceArray = node->getInstance_node_array(); + for ( size_t i = 0; i < nodeInstanceArray.getCount(); i++ ) { - daeElement *el = getElementFromURI( instn->getUrl() ); + daeElement *el = getElementFromURI( nodeInstanceArray[i]->getUrl()); domNode *n = daeSafeCast< domNode >( el ); - if ( n == NULL ) - { - osg::notify( osg::WARN ) << "Failed to locate camera " << ic->getUrl().getURI() << std::endl; - } - trans = processNode( n ); - if ( trans != NULL ) - { - current->asGroup()->addChild( trans ); - } - continue; + + if (n) + // Recursive call + groupNode->addChild( processNode( n )); + else + osg::notify( osg::WARN ) << "Failed to locate node " << nodeInstanceArray[i]->getUrl().getURI() << std::endl; } - domNode *n = daeSafeCast< domNode >( node->getContents()[i] ); - if ( n != NULL ) + // 0..* + domNode_Array nodeArray = node->getNode_array(); + for ( size_t i = 0; i < nodeArray.getCount(); i++ ) { - trans = processNode( n ); - if ( trans != NULL ) - { - current->asGroup()->addChild( trans ); - } - continue; + // Recursive call + groupNode->addChild( processNode( nodeArray[i] )); } - - const char *name = node->getContents()[i]->getElementName(); - if ( name == NULL ) name = node->getContents()[i]->getTypeName(); - osg::notify( osg::WARN ) << "Unsupported element type: " << name << " in COLLADA scene!" << std::endl; - } - return retVal; + return resultNode; } diff --git a/src/osgPlugins/dae/daeReader.h b/src/osgPlugins/dae/daeReader.h index 28b38716d..2a8757591 100644 --- a/src/osgPlugins/dae/daeReader.h +++ b/src/osgPlugins/dae/daeReader.h @@ -93,6 +93,38 @@ bool findInputSourceBySemantic( TInputArray& inputs, const char* semantic, daeEl return false; } +/// Convert string to value using it's stream operator +template +T parseString(const std::string& valueAsString) { + std::stringstream str; + str << valueAsString; + T result; + str >> result; + return result; +} + +inline osg::Vec3 parseVec3String(const std::string& valueAsString) +{ + std::stringstream str; + str << valueAsString; + osg::Vec3 result; + str >> result.x() >> result.y() >> result.z(); + return result; +} + +inline osg::Matrix parseMatrixString(const std::string& valueAsString) +{ + std::stringstream str; + str << valueAsString; + osg::Matrix result; + str >> result(0,0) >> result(1,0) >> result(2,0) >> result(3,0) + >> result(0,1) >> result(1,1) >> result(2,1) >> result(3,1) + >> result(0,2) >> result(1,2) >> result(2,2) >> result(3,2) + >> result(0,3) >> result(1,3) >> result(2,3) >> result(3,3); + return result; +} + + /** @class daeReader @brief Read a OSG scene from a DAE file @@ -113,33 +145,38 @@ public: protected: //scene processing - osg::Node* processVisualScene( domVisual_scene *scene ); - osg::Node* processNode( domNode *node ); + osg::Node* processVisualScene( domVisual_scene *scene ); + osg::Node* processNode( domNode *node ); + osg::Node* processOsgMatrixTransform( domNode *node ); //osg::Node* processInstance( domInstanceWithExtra *iwe ); - //transform processing - osg::Transform* processMatrix( domMatrix *mat ); - osg::Transform* processTranslate( domTranslate *trans ); - osg::Transform* processRotate( domRotate *rot ); - osg::Transform* processScale( domScale *scale ); - osg::Transform* processLookat( domLookat *la ); - osg::Transform* processSkew( domSkew *skew ); + // Processing of OSG specific info stored in node extras + osg::Node* processExtras(domNode *node); + void processNodeExtra(osg::Node* osgNode, domNode *node); + domTechnique* getOpenSceneGraphProfile(domExtra* extra); + void processAsset( domAsset *node ); + + osg::Node* processOsgSwitch(domTechnique* teq); + osg::Node* processOsgMultiSwitch(domTechnique* teq); + osg::Node* processOsgLOD(domTechnique* teq); + osg::Node* processOsgDOFTransform(domTechnique* teq); + osg::Node* processOsgSequence(domTechnique* teq); //geometry processing - osg::Node* processInstance_geometry( domInstance_geometry *ig ); - osg::Node* processGeometry( domGeometry *geo ); - osg::Node* processInstance_controller( domInstance_controller *ictrl ); + osg::Geode* processInstanceGeometry( domInstance_geometry *ig ); + osg::Geode* processGeometry( domGeometry *geo ); + osg::Geode* processInstanceController( domInstance_controller *ictrl ); typedef std::map< daeElement*, domSourceReader > SourceMap; typedef std::map< int, osg::IntArray*, std::less > IndexMap; template< typename T > - osg::Node* processSinglePPrimitive( T *group, SourceMap &sources, GLenum mode ); + void processSinglePPrimitive(osg::Geode* geode, T *group, SourceMap &sources, GLenum mode ); template< typename T > - osg::Node* processMultiPPrimitive( T *group, SourceMap &sources, GLenum mode ); + void processMultiPPrimitive(osg::Geode* geode, T *group, SourceMap &sources, GLenum mode ); - osg::Node* processPolylist( domPolylist *group, SourceMap &sources ); + void processPolylist(osg::Geode* geode, domPolylist *group, SourceMap &sources ); void resolveArrays( domInputLocalOffset_Array &inputs, osg::Geometry *&geom, SourceMap &sources, IndexMap &index_map ); @@ -147,12 +184,16 @@ protected: void processP( domP *p, osg::Geometry *&geom, IndexMap &index_map, osg::DrawArrayLengths* dal/*GLenum mode*/ ); //material/effect processing - void processBindMaterial( domBind_material *bm, osg::Node *geo ); - osg::StateSet *processMaterial( domMaterial *mat ); - osg::StateSet *processEffect( domEffect *effect ); - osg::StateSet *processProfileCOMMON( domProfile_COMMON *pc ); + void processBindMaterial( domBind_material *bm, domGeometry *geom, osg::Geode *geode ); + void processMaterial(osg::StateSet *ss, domMaterial *mat ); + void processEffect(osg::StateSet *ss, domEffect *effect ); + void processProfileCOMMON(osg::StateSet *ss, domProfile_COMMON *pc ); bool processColorOrTextureType( domCommon_color_or_texture_type *cot, - osg::Material::ColorMode channel, osg::Material *mat, domCommon_float_or_param_type *fop = NULL, osg::StateAttribute **sa = NULL ); + osg::Material::ColorMode channel, + osg::Material *mat, + domCommon_float_or_param_type *fop = NULL, + osg::StateAttribute **sa = NULL, + bool normalizeShininess=false); osg::StateAttribute *processTransparencySettings( domCommon_transparent_type *ctt, domCommon_float_or_param_type *pTransparency, osg::StateSet *ss ); bool GetFloat4Param(xsNCName Reference, domFloat4 &f4); bool GetFloatParam(xsNCName Reference, domFloat &f); @@ -174,8 +215,17 @@ protected: domInstance_effect *currentInstance_effect; domEffect *currentEffect; - std::map< domGeometry*, osg::Node* > geometryMap; - std::map< domMaterial*, osg::StateSet* > materialMap; + typedef std::map< domGeometry*, osg::Geode*> domGeometryGeodeMap; + typedef std::map< domMaterial*, osg::StateSet*> domMaterialStateSetMap; + typedef std::map< std::string, osg::StateSet*> MaterialStateSetMap; + + /// Maps geometry to a Geode + domGeometryGeodeMap geometryMap; + // Maps material target to stateset + domMaterialStateSetMap materialMap; + // Maps material symbol to stateset + MaterialStateSetMap materialMap2; + enum AuthoringTool { UNKNOWN, diff --git a/src/osgPlugins/dae/daeWGeometry.cpp b/src/osgPlugins/dae/daeWGeometry.cpp index 6aeb431fb..fd6e15699 100644 --- a/src/osgPlugins/dae/daeWGeometry.cpp +++ b/src/osgPlugins/dae/daeWGeometry.cpp @@ -24,28 +24,33 @@ using namespace osgdae; -//GEODE void daeWriter::apply( osg::Geode &node ) { -#ifdef _DEBUG debugPrint( node ); -#endif pushStateSet(node.getStateSet()); if (NULL != node.getStateSet()) m_CurrentRenderingHint = node.getStateSet()->getRenderingHint(); + // TODO + // Write a Geode as a single instance_geometry if all drawables use the same vertex streams + // Reuse an existing Geode if only statesets differ unsigned int count = node.getNumDrawables(); for ( unsigned int i = 0; i < count; i++ ) { osg::Geometry *g = node.getDrawable( i )->asGeometry(); + if ( g != NULL ) { + // Transparency at drawable level + if (NULL != g->getStateSet()) + m_CurrentRenderingHint = g->getStateSet()->getRenderingHint(); + pushStateSet(g->getStateSet()); std::map< osg::Geometry*, domGeometry *>::iterator iter = geometryMap.find( g ); if ( iter != geometryMap.end() ) { - domInstance_geometry *ig = daeSafeCast< domInstance_geometry >( currentNode->createAndPlace( "instance_geometry" ) ); + domInstance_geometry *ig = daeSafeCast< domInstance_geometry >( currentNode->add( "instance_geometry" ) ); std::string url = "#" + std::string( iter->second->getId() ); ig->setUrl( url.c_str() ); @@ -56,13 +61,13 @@ void daeWriter::apply( osg::Geode &node ) { if ( lib_geoms == NULL ) { - lib_geoms = daeSafeCast< domLibrary_geometries >( dom->createAndPlace( COLLADA_ELEMENT_LIBRARY_GEOMETRIES ) ); + lib_geoms = daeSafeCast< domLibrary_geometries >( dom->add( COLLADA_ELEMENT_LIBRARY_GEOMETRIES ) ); } std::string name = node.getName(); if ( name.empty() ) name = "geometry"; name = uniquify( name ); - domGeometryRef geo = daeSafeCast< domGeometry >( lib_geoms->createAndPlace( COLLADA_ELEMENT_GEOMETRY ) ); + domGeometryRef geo = daeSafeCast< domGeometry >( lib_geoms->add( COLLADA_ELEMENT_GEOMETRY ) ); geo->setId( name.c_str() ); if ( !processGeometry( g, geo, name ) ) @@ -71,7 +76,7 @@ void daeWriter::apply( osg::Geode &node ) continue; } - domInstance_geometry *ig = daeSafeCast< domInstance_geometry >( currentNode->createAndPlace( "instance_geometry" ) ); + domInstance_geometry *ig = daeSafeCast< domInstance_geometry >( currentNode->add( "instance_geometry" ) ); std::string url = "#" + name; ig->setUrl( url.c_str() ); @@ -87,8 +92,6 @@ void daeWriter::apply( osg::Geode &node ) } } - lastVisited = GEODE; - popStateSet(node.getStateSet()); } @@ -130,7 +133,7 @@ void daeWriter::appendGeometryIndices(osg::Geometry *geom, bool daeWriter::processGeometry( osg::Geometry *geom, domGeometry *geo, const std::string &name ) { - domMesh *mesh = daeSafeCast< domMesh >( geo->createAndPlace( COLLADA_ELEMENT_MESH ) ); + domMesh *mesh = daeSafeCast< domMesh >( geo->add( COLLADA_ELEMENT_MESH ) ); domSource *pos = NULL; domSource *norm = NULL; domSource *color = NULL; @@ -206,12 +209,12 @@ bool daeWriter::processGeometry( osg::Geometry *geom, domGeometry *geo, const st } //create a vertices element - domVertices *vertices = daeSafeCast< domVertices >( mesh->createAndPlace( COLLADA_ELEMENT_VERTICES ) ); + domVertices *vertices = daeSafeCast< domVertices >( mesh->add( COLLADA_ELEMENT_VERTICES ) ); std::string vName = name + "-vertices"; vertices->setId( vName.c_str() ); //make a POSITION input in it - domInputLocal *il = daeSafeCast< domInputLocal >( vertices->createAndPlace( "input" ) ); + domInputLocal *il = daeSafeCast< domInputLocal >( vertices->add( "input" ) ); il->setSemantic( "POSITION" ); std::string url = "#" + std::string( pos->getId() ); il->setSource( url.c_str() ); @@ -265,7 +268,7 @@ bool daeWriter::processGeometry( osg::Geometry *geom, domGeometry *geo, const st //if NORMAL shares same indices as POSITION put it in the vertices /*if ( normalInds == vertInds && vertInds != NULL ) { - il = daeSafeCast< domInputLocal >( vertices->createAndPlace( "input" ) ); + il = daeSafeCast< domInputLocal >( vertices->add( "input" ) ); il->setSemantic( "NORMAL" ); url = "#" + std::string(md->norm->getId()); il->setSource( url.c_str() ); @@ -316,7 +319,7 @@ bool daeWriter::processGeometry( osg::Geometry *geom, domGeometry *geo, const st } //if COLOR shares same indices as POSITION put it in the vertices /*if ( colorInds == vertInds && vertInds != NULL ) { - il = daeSafeCast< domInputLocal >( vertices->createAndPlace( "input" ) ); + il = daeSafeCast< domInputLocal >( vertices->add( "input" ) ); il->setSemantic( "COLOR" ); url = "#" + std::string(md->color->getId()); il->setSource( url.c_str() ); @@ -403,7 +406,7 @@ bool daeWriter::processGeometry( osg::Geometry *geom, domGeometry *geo, const st if ( lines == NULL ) { lines = createPrimGroup( COLLADA_ELEMENT_LINES, mesh, norm, color, texcoord ); - lines->createAndPlace( COLLADA_ELEMENT_P ); + lines->add( COLLADA_ELEMENT_P ); std::string mat = name + "_material"; lines->setMaterial( mat.c_str() ); } @@ -416,7 +419,7 @@ bool daeWriter::processGeometry( osg::Geometry *geom, domGeometry *geo, const st if ( tris == NULL ) { tris = createPrimGroup( COLLADA_ELEMENT_TRIANGLES, mesh, norm, color, texcoord ); - tris->createAndPlace( COLLADA_ELEMENT_P ); + tris->add( COLLADA_ELEMENT_P ); std::string mat = name + "_material"; tris->setMaterial( mat.c_str() ); } @@ -431,7 +434,7 @@ bool daeWriter::processGeometry( osg::Geometry *geom, domGeometry *geo, const st if (usePolygons) { polys = createPrimGroup( COLLADA_ELEMENT_POLYGONS, mesh, norm, color, texcoord ); - polys->createAndPlace( COLLADA_ELEMENT_P ); + polys->add( COLLADA_ELEMENT_P ); std::string mat = name + "_material"; polys->setMaterial( mat.c_str() ); } @@ -439,8 +442,8 @@ bool daeWriter::processGeometry( osg::Geometry *geom, domGeometry *geo, const st { polylist = createPrimGroup( COLLADA_ELEMENT_POLYLIST, mesh, norm, color, texcoord ); - polylist->createAndPlace( COLLADA_ELEMENT_VCOUNT ); - polylist->createAndPlace( COLLADA_ELEMENT_P ); + polylist->add( COLLADA_ELEMENT_VCOUNT ); + polylist->add( COLLADA_ELEMENT_P ); std::string mat = name + "_material"; polylist->setMaterial( mat.c_str() ); } @@ -492,7 +495,7 @@ bool daeWriter::processGeometry( osg::Geometry *geom, domGeometry *geo, const st if (usePolygons) { polys = createPrimGroup( COLLADA_ELEMENT_POLYGONS, mesh, norm, color, texcoord ); - polys->createAndPlace( COLLADA_ELEMENT_P ); + polys->add( COLLADA_ELEMENT_P ); std::string mat = name + "_material"; polys->setMaterial( mat.c_str() ); } @@ -500,8 +503,8 @@ bool daeWriter::processGeometry( osg::Geometry *geom, domGeometry *geo, const st { polylist = createPrimGroup( COLLADA_ELEMENT_POLYLIST, mesh, norm, color, texcoord ); - polylist->createAndPlace( COLLADA_ELEMENT_VCOUNT ); - polylist->createAndPlace( COLLADA_ELEMENT_P ); + polylist->add( COLLADA_ELEMENT_VCOUNT ); + polylist->add( COLLADA_ELEMENT_P ); std::string mat = name + "_material"; polylist->setMaterial( mat.c_str() ); } @@ -549,19 +552,19 @@ bool daeWriter::processGeometry( osg::Geometry *geom, domGeometry *geo, const st } case GL_LINE_STRIP: { - p.push_back(daeSafeCast( linestrips->createAndPlace( COLLADA_ELEMENT_P ) )); + p.push_back(daeSafeCast( linestrips->add( COLLADA_ELEMENT_P ) )); linestrips->setCount( linestrips->getCount() + 1 ); break; } case GL_TRIANGLE_STRIP: { - p.push_back(daeSafeCast( tristrips->createAndPlace( COLLADA_ELEMENT_P ) )); + p.push_back(daeSafeCast( tristrips->add( COLLADA_ELEMENT_P ) )); tristrips->setCount( tristrips->getCount() + 1 ); break; } case GL_TRIANGLE_FAN: { - p.push_back(daeSafeCast( trifans->createAndPlace( COLLADA_ELEMENT_P ) )); + p.push_back(daeSafeCast( trifans->add( COLLADA_ELEMENT_P ) )); trifans->setCount( trifans->getCount() + 1 ); break; } @@ -650,19 +653,19 @@ bool daeWriter::processGeometry( osg::Geometry *geom, domGeometry *geo, const st } case GL_LINE_STRIP: { - p.push_back(daeSafeCast( linestrips->createAndPlace( COLLADA_ELEMENT_P ) )); + p.push_back(daeSafeCast( linestrips->add( COLLADA_ELEMENT_P ) )); linestrips->setCount( linestrips->getCount() + 1 ); break; } case GL_TRIANGLE_STRIP: { - p.push_back(daeSafeCast( tristrips->createAndPlace( COLLADA_ELEMENT_P ) )); + p.push_back(daeSafeCast( tristrips->add( COLLADA_ELEMENT_P ) )); tristrips->setCount( tristrips->getCount() + 1 ); break; } case GL_TRIANGLE_FAN: { - p.push_back(daeSafeCast( trifans->createAndPlace( COLLADA_ELEMENT_P ) )); + p.push_back(daeSafeCast( trifans->add( COLLADA_ELEMENT_P ) )); trifans->setCount( trifans->getCount() + 1 ); break; } @@ -744,19 +747,19 @@ bool daeWriter::processGeometry( osg::Geometry *geom, domGeometry *geo, const st } case GL_LINE_STRIP: { - p.push_back(daeSafeCast( linestrips->createAndPlace( COLLADA_ELEMENT_P ) )); + p.push_back(daeSafeCast( linestrips->add( COLLADA_ELEMENT_P ) )); linestrips->setCount( linestrips->getCount() + 1 ); break; } case GL_TRIANGLE_STRIP: { - p.push_back(daeSafeCast( tristrips->createAndPlace( COLLADA_ELEMENT_P ) )); + p.push_back(daeSafeCast( tristrips->add( COLLADA_ELEMENT_P ) )); tristrips->setCount( tristrips->getCount() + 1 ); break; } case GL_TRIANGLE_FAN: { - p.push_back(daeSafeCast( trifans->createAndPlace( COLLADA_ELEMENT_P ) )); + p.push_back(daeSafeCast( trifans->add( COLLADA_ELEMENT_P ) )); trifans->setCount( trifans->getCount() + 1 ); break; } @@ -843,19 +846,19 @@ bool daeWriter::processGeometry( osg::Geometry *geom, domGeometry *geo, const st } case GL_LINE_STRIP: { - p.push_back(daeSafeCast( linestrips->createAndPlace( COLLADA_ELEMENT_P ) )); + p.push_back(daeSafeCast( linestrips->add( COLLADA_ELEMENT_P ) )); linestrips->setCount( linestrips->getCount() + 1 ); break; } case GL_TRIANGLE_STRIP: { - p.push_back(daeSafeCast( tristrips->createAndPlace( COLLADA_ELEMENT_P ) )); + p.push_back(daeSafeCast( tristrips->add( COLLADA_ELEMENT_P ) )); tristrips->setCount( tristrips->getCount() + 1 ); break; } case GL_TRIANGLE_FAN: { - p.push_back(daeSafeCast( trifans->createAndPlace( COLLADA_ELEMENT_P ) )); + p.push_back(daeSafeCast( trifans->add( COLLADA_ELEMENT_P ) )); trifans->setCount( trifans->getCount() + 1 ); break; } @@ -944,19 +947,19 @@ bool daeWriter::processGeometry( osg::Geometry *geom, domGeometry *geo, const st } case GL_LINE_STRIP: { - p.push_back(daeSafeCast( linestrips->createAndPlace( COLLADA_ELEMENT_P ) )); + p.push_back(daeSafeCast( linestrips->add( COLLADA_ELEMENT_P ) )); linestrips->setCount( linestrips->getCount() + 1 ); break; } case GL_TRIANGLE_STRIP: { - p.push_back(daeSafeCast( tristrips->createAndPlace( COLLADA_ELEMENT_P ) )); + p.push_back(daeSafeCast( tristrips->add( COLLADA_ELEMENT_P ) )); tristrips->setCount( tristrips->getCount() + 1 ); break; } case GL_TRIANGLE_FAN: { - p.push_back(daeSafeCast( trifans->createAndPlace( COLLADA_ELEMENT_P ) )); + p.push_back(daeSafeCast( trifans->add( COLLADA_ELEMENT_P ) )); trifans->setCount( trifans->getCount() + 1 ); break; } @@ -1038,39 +1041,39 @@ bool daeWriter::processGeometry( osg::Geometry *geom, domGeometry *geo, const st domSource *daeWriter::createSource( daeElement *parent, const std::string &baseName, int size, bool color, bool uv ) { - domSource *src = daeSafeCast< domSource >( parent->createAndPlace( COLLADA_ELEMENT_SOURCE ) ); + domSource *src = daeSafeCast< domSource >( parent->add( COLLADA_ELEMENT_SOURCE ) ); if ( src == NULL ) { return NULL; } src->setId( baseName.c_str() ); - domFloat_array *fa = daeSafeCast< domFloat_array >( src->createAndPlace( COLLADA_ELEMENT_FLOAT_ARRAY ) ); + domFloat_array *fa = daeSafeCast< domFloat_array >( src->add( COLLADA_ELEMENT_FLOAT_ARRAY ) ); std::string fName = baseName + "-array"; fa->setId( fName.c_str() ); - domSource::domTechnique_common *teq = daeSafeCast< domSource::domTechnique_common >( src->createAndPlace( "technique_common" ) ); - domAccessor *acc = daeSafeCast< domAccessor >( teq->createAndPlace( COLLADA_ELEMENT_ACCESSOR ) ); + domSource::domTechnique_common *teq = daeSafeCast< domSource::domTechnique_common >( src->add( "technique_common" ) ); + domAccessor *acc = daeSafeCast< domAccessor >( teq->add( COLLADA_ELEMENT_ACCESSOR ) ); std::string url = "#" + fName; acc->setSource( url.c_str() ); domParam *param; if ( color ) { acc->setStride( size ); - param = daeSafeCast< domParam >( acc->createAndPlace( COLLADA_ELEMENT_PARAM ) ); + param = daeSafeCast< domParam >( acc->add( COLLADA_ELEMENT_PARAM ) ); param->setName( "R" ); param->setType( "float" ); - param = daeSafeCast< domParam >( acc->createAndPlace( COLLADA_ELEMENT_PARAM ) ); + param = daeSafeCast< domParam >( acc->add( COLLADA_ELEMENT_PARAM ) ); param->setName( "G" ); param->setType( "float" ); - param = daeSafeCast< domParam >( acc->createAndPlace( COLLADA_ELEMENT_PARAM ) ); + param = daeSafeCast< domParam >( acc->add( COLLADA_ELEMENT_PARAM ) ); param->setName( "B" ); param->setType( "float" ); if ( size == 4 ) { - param = daeSafeCast< domParam >( acc->createAndPlace( COLLADA_ELEMENT_PARAM ) ); + param = daeSafeCast< domParam >( acc->add( COLLADA_ELEMENT_PARAM ) ); param->setName( "A" ); param->setType( "float" ); } @@ -1079,17 +1082,17 @@ domSource *daeWriter::createSource( daeElement *parent, const std::string &baseN else if ( uv ) { acc->setStride( size ); - param = daeSafeCast< domParam >( acc->createAndPlace( COLLADA_ELEMENT_PARAM ) ); + param = daeSafeCast< domParam >( acc->add( COLLADA_ELEMENT_PARAM ) ); param->setName( "S" ); param->setType( "float" ); - param = daeSafeCast< domParam >( acc->createAndPlace( COLLADA_ELEMENT_PARAM ) ); + param = daeSafeCast< domParam >( acc->add( COLLADA_ELEMENT_PARAM ) ); param->setName( "T" ); param->setType( "float" ); if ( size >=3 ) { - param = daeSafeCast< domParam >( acc->createAndPlace( COLLADA_ELEMENT_PARAM ) ); + param = daeSafeCast< domParam >( acc->add( COLLADA_ELEMENT_PARAM ) ); param->setName( "P" ); param->setType( "float" ); } @@ -1097,23 +1100,23 @@ domSource *daeWriter::createSource( daeElement *parent, const std::string &baseN else { acc->setStride( size ); - param = daeSafeCast< domParam >( acc->createAndPlace( COLLADA_ELEMENT_PARAM ) ); + param = daeSafeCast< domParam >( acc->add( COLLADA_ELEMENT_PARAM ) ); param->setName( "X" ); param->setType( "float" ); - param = daeSafeCast< domParam >( acc->createAndPlace( COLLADA_ELEMENT_PARAM ) ); + param = daeSafeCast< domParam >( acc->add( COLLADA_ELEMENT_PARAM ) ); param->setName( "Y" ); param->setType( "float" ); if ( size >=3 ) { - param = daeSafeCast< domParam >( acc->createAndPlace( COLLADA_ELEMENT_PARAM ) ); + param = daeSafeCast< domParam >( acc->add( COLLADA_ELEMENT_PARAM ) ); param->setName( "Z" ); param->setType( "float" ); if ( size == 4 ) { - param = daeSafeCast< domParam >( acc->createAndPlace( COLLADA_ELEMENT_PARAM ) ); + param = daeSafeCast< domParam >( acc->add( COLLADA_ELEMENT_PARAM ) ); param->setName( "W" ); param->setType( "float" ); } @@ -1127,15 +1130,15 @@ template < typename Ty > Ty *daeWriter::createPrimGroup( daeString type, domMesh *mesh, domSource *norm, domSource *color, const std::vector< domSource* > &texcoord ) { unsigned int offset = 0; - Ty *retVal = daeSafeCast< Ty >( mesh->createAndPlace( type ) ); - domInputLocalOffset *ilo = daeSafeCast< domInputLocalOffset >( retVal->createAndPlace( "input" ) ); + Ty *retVal = daeSafeCast< Ty >( mesh->add( type ) ); + domInputLocalOffset *ilo = daeSafeCast< domInputLocalOffset >( retVal->add( "input" ) ); ilo->setOffset( offset++ ); ilo->setSemantic( "VERTEX" ); std::string url = "#" + std::string(mesh->getVertices()->getId()); ilo->setSource( url.c_str() ); if ( norm != NULL ) { - ilo = daeSafeCast< domInputLocalOffset >( retVal->createAndPlace( "input" ) ); + ilo = daeSafeCast< domInputLocalOffset >( retVal->add( "input" ) ); ilo->setOffset( offset++ ); ilo->setSemantic( "NORMAL" ); url = "#" + std::string( norm->getId() ); @@ -1143,7 +1146,7 @@ Ty *daeWriter::createPrimGroup( daeString type, domMesh *mesh, domSource *norm, } if ( color != NULL ) { - ilo = daeSafeCast< domInputLocalOffset >( retVal->createAndPlace( "input" ) ); + ilo = daeSafeCast< domInputLocalOffset >( retVal->add( "input" ) ); ilo->setOffset( offset++ ); ilo->setSemantic( "COLOR" ); url = "#" + std::string( color->getId() ); @@ -1151,7 +1154,7 @@ Ty *daeWriter::createPrimGroup( daeString type, domMesh *mesh, domSource *norm, } for ( unsigned int i = 0; i < texcoord.size(); i++ ) { - ilo = daeSafeCast< domInputLocalOffset >( retVal->createAndPlace( "input" ) ); + ilo = daeSafeCast< domInputLocalOffset >( retVal->add( "input" ) ); ilo->setOffset( offset++ ); ilo->setSemantic( "TEXCOORD" ); ilo->setSet( i ); diff --git a/src/osgPlugins/dae/daeWMaterials.cpp b/src/osgPlugins/dae/daeWMaterials.cpp index 4c00c7e1e..7880a76f1 100644 --- a/src/osgPlugins/dae/daeWMaterials.cpp +++ b/src/osgPlugins/dae/daeWMaterials.cpp @@ -33,9 +33,9 @@ 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 ) ); + domBind_material *bm = daeSafeCast< domBind_material >( ig->add( COLLADA_ELEMENT_BIND_MATERIAL ) ); + domBind_material::domTechnique_common *tc = daeSafeCast< domBind_material::domTechnique_common >( bm->add( "technique_common" ) ); + domInstance_material *im = daeSafeCast< domInstance_material >( tc->add( COLLADA_ELEMENT_INSTANCE_MATERIAL ) ); std::string symbol = geoName + "_material"; im->setSymbol( symbol.c_str() ); @@ -49,10 +49,10 @@ void daeWriter::processMaterial( osg::StateSet *ss, domInstance_geometry *ig, co if ( lib_mats == NULL ) { - lib_mats = daeSafeCast< domLibrary_materials >( dom->createAndPlace( COLLADA_ELEMENT_LIBRARY_MATERIALS ) ); + lib_mats = daeSafeCast< domLibrary_materials >( dom->add( COLLADA_ELEMENT_LIBRARY_MATERIALS ) ); } - domMaterial *mat = daeSafeCast< domMaterial >( lib_mats->createAndPlace( COLLADA_ELEMENT_MATERIAL ) ); + domMaterial *mat = daeSafeCast< domMaterial >( lib_mats->add( COLLADA_ELEMENT_MATERIAL ) ); std::string name = ssClean->getName(); if ( name.empty() ) { @@ -65,13 +65,13 @@ void daeWriter::processMaterial( osg::StateSet *ss, domInstance_geometry *ig, co std::string url = "#" + name; im->setTarget( url.c_str() ); - domInstance_effect *ie = daeSafeCast( mat->createAndPlace( "instance_effect" ) ); + domInstance_effect *ie = daeSafeCast( mat->add( "instance_effect" ) ); if ( lib_effects == NULL ) { - lib_effects = daeSafeCast< domLibrary_effects >( dom->createAndPlace( COLLADA_ELEMENT_LIBRARY_EFFECTS ) ); + lib_effects = daeSafeCast< domLibrary_effects >( dom->add( COLLADA_ELEMENT_LIBRARY_EFFECTS ) ); } - domEffect *effect = daeSafeCast< domEffect >( lib_effects->createAndPlace( COLLADA_ELEMENT_EFFECT ) ); + domEffect *effect = daeSafeCast< domEffect >( lib_effects->add( COLLADA_ELEMENT_EFFECT ) ); std::string efName = name + "_effect"; effect->setId( efName.c_str() ); @@ -79,10 +79,10 @@ void daeWriter::processMaterial( osg::StateSet *ss, domInstance_geometry *ig, co url = "#" + efName; ie->setUrl( url.c_str() ); - domProfile_COMMON *pc = daeSafeCast< domProfile_COMMON >( effect->createAndPlace( COLLADA_ELEMENT_PROFILE_COMMON ) ); - domProfile_COMMON::domTechnique *pc_teq = daeSafeCast< domProfile_COMMON::domTechnique >( pc->createAndPlace( "technique" ) ); + domProfile_COMMON *pc = daeSafeCast< domProfile_COMMON >( effect->add( COLLADA_ELEMENT_PROFILE_COMMON ) ); + domProfile_COMMON::domTechnique *pc_teq = daeSafeCast< domProfile_COMMON::domTechnique >( pc->add( "technique" ) ); pc_teq->setSid( "t0" ); - domProfile_COMMON::domTechnique::domPhong *phong = daeSafeCast< domProfile_COMMON::domTechnique::domPhong >( pc_teq->createAndPlace( "phong" ) ); + domProfile_COMMON::domTechnique::domPhong *phong = daeSafeCast< domProfile_COMMON::domTechnique::domPhong >( pc_teq->add( "phong" ) ); osg::Texture *tex = static_cast(ssClean->getTextureAttribute( 0, osg::StateAttribute::TEXTURE )); if ( ssClean->getTextureAttribute( 1, osg::StateAttribute::TEXTURE ) != NULL ) @@ -92,12 +92,12 @@ void daeWriter::processMaterial( osg::StateSet *ss, domInstance_geometry *ig, co if ( tex != NULL && tex->getImage( 0 ) != NULL ) { //TODO: Export all of the texture Attributes like wrap mode and all that jazz - domImage *img = daeSafeCast< domImage >( pc->createAndPlace( COLLADA_ELEMENT_IMAGE ) ); + domImage *img = daeSafeCast< domImage >( pc->add( COLLADA_ELEMENT_IMAGE ) ); std::string iName = efName + "-image"; img->setId( iName.c_str() ); osg::Image *osgimg = tex->getImage( 0 ); - domImage::domInit_from *imgif = daeSafeCast< domImage::domInit_from >( img->createAndPlace( "init_from" ) ); + domImage::domInit_from *imgif = daeSafeCast< domImage::domInit_from >( img->add( "init_from" ) ); std::string fileURI = ReaderWriterDAE::ConvertFilePathToColladaCompatibleURI(osgDB::findDataFile(osgimg->getFileName())); daeURI dd(*dae, fileURI);//fileURI.c_str() ); imgif->setValue( dd ); @@ -105,23 +105,23 @@ void daeWriter::processMaterial( osg::StateSet *ss, domInstance_geometry *ig, co imgif->getValue().makeRelativeTo(doc->getDocumentURI()); #ifndef EARTH_TEX - domCommon_newparam_type *np = daeSafeCast< domCommon_newparam_type >( pc->createAndPlace( "newparam" ) ); + domCommon_newparam_type *np = daeSafeCast< domCommon_newparam_type >( pc->add( "newparam" ) ); std::string surfName = efName + "-surface"; np->setSid( surfName.c_str() ); - domFx_surface_common *surface = daeSafeCast< domFx_surface_common >( np->createAndPlace( "surface" ) ); - domFx_surface_init_from_common *sif = daeSafeCast< domFx_surface_init_from_common >( surface->createAndPlace("init_from") ); + domFx_surface_common *surface = daeSafeCast< domFx_surface_common >( np->add( "surface" ) ); + domFx_surface_init_from_common *sif = daeSafeCast< domFx_surface_init_from_common >( surface->add("init_from") ); sif->setValue( iName.c_str() ); surface->setType( FX_SURFACE_TYPE_ENUM_2D ); - np = daeSafeCast< domCommon_newparam_type >( pc->createAndPlace( "newparam" ) ); + np = daeSafeCast< domCommon_newparam_type >( pc->add( "newparam" ) ); std::string sampName = efName + "-sampler"; np->setSid( sampName.c_str() ); - domFx_sampler2D_common *sampler = daeSafeCast< domFx_sampler2D_common >( np->createAndPlace( "sampler2D" ) ); - domFx_sampler2D_common_complexType::domSource *source = daeSafeCast< domFx_sampler2D_common_complexType::domSource >( sampler->createAndPlace( "source" ) ); + domFx_sampler2D_common *sampler = daeSafeCast< domFx_sampler2D_common >( np->add( "sampler2D" ) ); + domFx_sampler2D_common_complexType::domSource *source = daeSafeCast< domFx_sampler2D_common_complexType::domSource >( sampler->add( "source" ) ); source->setValue( surfName.c_str() ); //set sampler state - domFx_sampler2D_common_complexType::domWrap_s *wrap_s = daeSafeCast< domFx_sampler2D_common_complexType::domWrap_s >( sampler->createAndPlace( "wrap_s" ) ); + domFx_sampler2D_common_complexType::domWrap_s *wrap_s = daeSafeCast< domFx_sampler2D_common_complexType::domWrap_s >( sampler->add( "wrap_s" ) ); osg::Texture::WrapMode wrap = tex->getWrap( osg::Texture::WRAP_S ); switch( wrap ) { @@ -143,7 +143,7 @@ void daeWriter::processMaterial( osg::StateSet *ss, domInstance_geometry *ig, co break; } - domFx_sampler2D_common_complexType::domWrap_t *wrap_t = daeSafeCast< domFx_sampler2D_common_complexType::domWrap_t >( sampler->createAndPlace( "wrap_t" ) ); + domFx_sampler2D_common_complexType::domWrap_t *wrap_t = daeSafeCast< domFx_sampler2D_common_complexType::domWrap_t >( sampler->add( "wrap_t" ) ); wrap = tex->getWrap( osg::Texture::WRAP_T ); switch( wrap ) { @@ -166,13 +166,13 @@ void daeWriter::processMaterial( osg::StateSet *ss, domInstance_geometry *ig, co } const osg::Vec4 &bcol = tex->getBorderColor(); - domFx_sampler2D_common_complexType::domBorder_color *dbcol = daeSafeCast< domFx_sampler2D_common_complexType::domBorder_color >( sampler->createAndPlace( "border_color" ) ); + domFx_sampler2D_common_complexType::domBorder_color *dbcol = daeSafeCast< domFx_sampler2D_common_complexType::domBorder_color >( sampler->add( "border_color" ) ); dbcol->getValue().append( bcol.r() ); dbcol->getValue().append( bcol.g() ); dbcol->getValue().append( bcol.b() ); dbcol->getValue().append( bcol.a() ); - domFx_sampler2D_common_complexType::domMinfilter *minfilter = daeSafeCast< domFx_sampler2D_common_complexType::domMinfilter >( sampler->createAndPlace( "minfilter" ) ); + domFx_sampler2D_common_complexType::domMinfilter *minfilter = daeSafeCast< domFx_sampler2D_common_complexType::domMinfilter >( sampler->add( "minfilter" ) ); osg::Texture::FilterMode mode = tex->getFilter( osg::Texture::MIN_FILTER ); switch( mode ) { @@ -196,7 +196,7 @@ void daeWriter::processMaterial( osg::StateSet *ss, domInstance_geometry *ig, co break; } - domFx_sampler2D_common_complexType::domMagfilter *magfilter = daeSafeCast< domFx_sampler2D_common_complexType::domMagfilter >( sampler->createAndPlace( "magfilter" ) ); + domFx_sampler2D_common_complexType::domMagfilter *magfilter = daeSafeCast< domFx_sampler2D_common_complexType::domMagfilter >( sampler->add( "magfilter" ) ); mode = tex->getFilter( osg::Texture::MAG_FILTER ); switch( mode ) { @@ -221,49 +221,21 @@ void daeWriter::processMaterial( osg::StateSet *ss, domInstance_geometry *ig, co } - domCommon_color_or_texture_type *cot = daeSafeCast< domCommon_color_or_texture_type >( phong->createAndPlace( "diffuse" ) ); - domCommon_color_or_texture_type_complexType::domTexture *dtex = daeSafeCast< domCommon_color_or_texture_type_complexType::domTexture >( cot->createAndPlace( "texture" ) ); + domCommon_color_or_texture_type *cot = daeSafeCast< domCommon_color_or_texture_type >( phong->add( "diffuse" ) ); + domCommon_color_or_texture_type_complexType::domTexture *dtex = daeSafeCast< domCommon_color_or_texture_type_complexType::domTexture >( cot->add( "texture" ) ); dtex->setTexture( sampName.c_str() ); dtex->setTexcoord( "texcoord0" ); #else - domCommon_color_or_texture_type *cot = daeSafeCast< domCommon_color_or_texture_type >( phong->createAndPlace( "diffuse" ) ); - domCommon_color_or_texture_type_complexType::domTexture *dtex = daeSafeCast< domCommon_color_or_texture_type_complexType::domTexture >( cot->createAndPlace( "texture" ) ); + domCommon_color_or_texture_type *cot = daeSafeCast< domCommon_color_or_texture_type >( phong->add( "diffuse" ) ); + domCommon_color_or_texture_type_complexType::domTexture *dtex = daeSafeCast< domCommon_color_or_texture_type_complexType::domTexture >( cot->add( "texture" ) ); dtex->setTexture( iName.c_str() ); dtex->setTexcoord( "texcoord0" ); #endif - domInstance_material::domBind_vertex_input *bvi = daeSafeCast< domInstance_material::domBind_vertex_input >( im->createAndPlace( "bind_vertex_input" ) ); + domInstance_material::domBind_vertex_input *bvi = daeSafeCast< domInstance_material::domBind_vertex_input >( im->add( "bind_vertex_input" ) ); bvi->setSemantic( "texcoord0" ); bvi->setInput_semantic( "TEXCOORD" ); bvi->setInput_set( 0 ); - -/* I dont think this belongs here RFJ - //take care of blending if any - 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" ) ); - ctt->setOpaque( FX_OPAQUE_ENUM_RGB_ZERO ); - domCommon_color_or_texture_type_complexType::domColor *tcol = daeSafeCast< domCommon_color_or_texture_type_complexType::domColor >( ctt->createAndPlace( "color" ) ); - tcol->getValue().append( bc->getConstantColor().r() ); - tcol->getValue().append( bc->getConstantColor().r() ); - tcol->getValue().append( bc->getConstantColor().r() ); - tcol->getValue().append( bc->getConstantColor().r() ); - } - else if ( bf != NULL ) - { - domCommon_transparent_type *ctt = daeSafeCast< domCommon_transparent_type >( phong->createAndPlace( "transparent" ) ); - ctt->setOpaque( FX_OPAQUE_ENUM_A_ONE ); - dtex = daeSafeCast< domCommon_color_or_texture_type_complexType::domTexture >( ctt->createAndPlace( "texture" ) ); -#ifndef EARTH_TEX - dtex->setTexture( sampName.c_str() ); -#else - dtex->setTexture( iName.c_str() ); -#endif - dtex->setTexcoord( "texcoord0" ); - } -*/ } osg::Material *osgmat = static_cast(ssClean->getAttribute( osg::StateAttribute::MATERIAL )); if ( osgmat != NULL ) @@ -274,15 +246,15 @@ void daeWriter::processMaterial( osg::StateSet *ss, domInstance_geometry *ig, co const osg::Vec4 &sCol = osgmat->getSpecularFrontAndBack()?osgmat->getSpecular( osg::Material::FRONT_AND_BACK ):osgmat->getSpecular( osg::Material::FRONT ); float shininess = osgmat->getShininessFrontAndBack()?osgmat->getShininess( osg::Material::FRONT_AND_BACK ):osgmat->getShininess( osg::Material::FRONT ); - domCommon_color_or_texture_type *cot = daeSafeCast< domCommon_color_or_texture_type >( phong->createAndPlace( "emission" ) ); - domCommon_color_or_texture_type_complexType::domColor *col = daeSafeCast< domCommon_color_or_texture_type_complexType::domColor >( cot->createAndPlace( "color" ) ); + domCommon_color_or_texture_type *cot = daeSafeCast< domCommon_color_or_texture_type >( phong->add( "emission" ) ); + domCommon_color_or_texture_type_complexType::domColor *col = daeSafeCast< domCommon_color_or_texture_type_complexType::domColor >( cot->add( "color" ) ); col->getValue().append( eCol.r() ); col->getValue().append( eCol.g() ); col->getValue().append( eCol.b() ); col->getValue().append( eCol.a() ); - cot = daeSafeCast< domCommon_color_or_texture_type >( phong->createAndPlace( "ambient" ) ); - col = daeSafeCast< domCommon_color_or_texture_type_complexType::domColor >( cot->createAndPlace( "color" ) ); + cot = daeSafeCast< domCommon_color_or_texture_type >( phong->add( "ambient" ) ); + col = daeSafeCast< domCommon_color_or_texture_type_complexType::domColor >( cot->add( "color" ) ); col->getValue().append( aCol.r() ); col->getValue().append( aCol.g() ); col->getValue().append( aCol.b() ); @@ -292,8 +264,8 @@ void daeWriter::processMaterial( osg::StateSet *ss, domInstance_geometry *ig, co //### check if we really have a texture 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" ) ); + cot = daeSafeCast< domCommon_color_or_texture_type >( phong->add( "diffuse" ) ); + col = daeSafeCast< domCommon_color_or_texture_type_complexType::domColor >( cot->add( "color" ) ); col->getValue().append( dCol.r() ); col->getValue().append( dCol.g() ); col->getValue().append( dCol.b() ); @@ -303,27 +275,38 @@ void daeWriter::processMaterial( osg::StateSet *ss, domInstance_geometry *ig, co { cot = phong->getDiffuse(); - domCommon_color_or_texture_type_complexType::domTexture *dtex = cot->getTexture(); - domExtra *extra = daeSafeCast< domExtra >( dtex->createAndPlace( COLLADA_ELEMENT_EXTRA ) ); - extra->setType( "color" ); - domTechnique *teq = daeSafeCast< domTechnique >( extra->createAndPlace( COLLADA_ELEMENT_TECHNIQUE ) ); - teq->setProfile( "SCEI" ); - domAny *any = (domAny*)(daeElement*)teq->createAndPlace( "color" ); + if (writeExtras) + { + // Adds the following to a texture element - std::ostringstream colVal; - colVal << dCol.r() << " " << dCol.g() << " " << dCol.b() << " " << dCol.a(); - any->setValue( colVal.str().c_str() ); + // + // + // 1.0 1.0 1.0 1.0 + // + // + + domCommon_color_or_texture_type_complexType::domTexture *dtex = cot->getTexture(); + domExtra *extra = daeSafeCast< domExtra >( dtex->add( COLLADA_ELEMENT_EXTRA ) ); + extra->setType( "color" ); + domTechnique *teq = daeSafeCast< domTechnique >( extra->add( COLLADA_ELEMENT_TECHNIQUE ) ); + teq->setProfile( "SCEI" ); + domAny *any = (domAny*)(daeElement*)teq->add( "color" ); + + std::ostringstream colVal; + colVal << dCol.r() << " " << dCol.g() << " " << dCol.b() << " " << dCol.a(); + any->setValue( colVal.str().c_str() ); + } } - cot = daeSafeCast< domCommon_color_or_texture_type >( phong->createAndPlace( "specular" ) ); - col = daeSafeCast< domCommon_color_or_texture_type_complexType::domColor >( cot->createAndPlace( "color" ) ); + cot = daeSafeCast< domCommon_color_or_texture_type >( phong->add( "specular" ) ); + col = daeSafeCast< domCommon_color_or_texture_type_complexType::domColor >( cot->add( "color" ) ); col->getValue().append( sCol.r() ); col->getValue().append( sCol.g() ); col->getValue().append( sCol.b() ); col->getValue().append( sCol.a() ); - domCommon_float_or_param_type *fop = daeSafeCast< domCommon_float_or_param_type >( phong->createAndPlace( "shininess" ) ); - domCommon_float_or_param_type_complexType::domFloat *f = daeSafeCast< domCommon_float_or_param_type_complexType::domFloat >( fop->createAndPlace( "float" ) ); + domCommon_float_or_param_type *fop = daeSafeCast< domCommon_float_or_param_type >( phong->add( "shininess" ) ); + domCommon_float_or_param_type_complexType::domFloat *f = daeSafeCast< domCommon_float_or_param_type_complexType::domFloat >( fop->add( "float" ) ); f->setValue( shininess ); } @@ -333,65 +316,100 @@ void daeWriter::processMaterial( osg::StateSet *ss, domInstance_geometry *ig, co { osg::BlendFunc *pBlendFunc = static_cast< osg::BlendFunc * >( ssClean->getAttribute( osg::StateAttribute::BLENDFUNC ) ); osg::BlendColor *pBlendColor = static_cast< osg::BlendColor * >( ssClean->getAttribute( osg::StateAttribute::BLENDCOLOR ) ); - if ((NULL != pBlendFunc) && (NULL != pBlendColor)) + if (pBlendFunc != NULL) { - if ((GL_CONSTANT_ALPHA == pBlendFunc->getSource()) && (GL_ONE_MINUS_CONSTANT_ALPHA == pBlendFunc->getDestination())) + if (pBlendColor != NULL) { - // A_ONE opaque mode - domCommon_transparent_type *pTransparent = daeSafeCast(phong->createAndPlace("transparent")); - pTransparent->setOpaque(FX_OPAQUE_ENUM_A_ONE); - domCommon_color_or_texture_type_complexType::domColor *pColor = daeSafeCast(pTransparent->createAndPlace("color")); - domCommon_float_or_param_type *pFop = daeSafeCast(phong->createAndPlace( "transparency")); - domCommon_float_or_param_type_complexType::domFloat *pTransparency = daeSafeCast(pFop->createAndPlace("float")); - if (m_GoogleMode) + if ((GL_CONSTANT_ALPHA == pBlendFunc->getSource()) && (GL_ONE_MINUS_CONSTANT_ALPHA == pBlendFunc->getDestination())) { - pColor->getValue().append(1.0); - pColor->getValue().append(1.0); - pColor->getValue().append(1.0); - pColor->getValue().append(1.0); - pTransparency->setValue(1.0 - pBlendColor->getConstantColor().a()); + // A_ONE opaque mode + domCommon_transparent_type *pTransparent = daeSafeCast(phong->add("transparent")); + pTransparent->setOpaque(FX_OPAQUE_ENUM_A_ONE); + domCommon_color_or_texture_type_complexType::domColor *pColor = daeSafeCast(pTransparent->add("color")); + domCommon_float_or_param_type *pFop = daeSafeCast(phong->add( "transparency")); + domCommon_float_or_param_type_complexType::domFloat *pTransparency = daeSafeCast(pFop->add("float")); + if (m_GoogleMode) + { + pColor->getValue().append(1.0); + pColor->getValue().append(1.0); + pColor->getValue().append(1.0); + pColor->getValue().append(1.0); + pTransparency->setValue(1.0 - pBlendColor->getConstantColor().a()); + } + else + { + pColor->getValue().append(pBlendColor->getConstantColor().r()); + pColor->getValue().append(pBlendColor->getConstantColor().g()); + pColor->getValue().append(pBlendColor->getConstantColor().b()); + pColor->getValue().append(pBlendColor->getConstantColor().a()); + pTransparency->setValue(1.0); + } } - else + else if ((GL_ONE_MINUS_CONSTANT_COLOR == pBlendFunc->getSource()) && (GL_CONSTANT_COLOR == pBlendFunc->getDestination())) { + // RGB_ZERO opaque mode + domCommon_transparent_type *pTransparent = daeSafeCast(phong->add("transparent")); + pTransparent->setOpaque(FX_OPAQUE_ENUM_RGB_ZERO); + domCommon_color_or_texture_type_complexType::domColor *pColor = daeSafeCast(pTransparent->add("color")); pColor->getValue().append(pBlendColor->getConstantColor().r()); pColor->getValue().append(pBlendColor->getConstantColor().g()); pColor->getValue().append(pBlendColor->getConstantColor().b()); pColor->getValue().append(pBlendColor->getConstantColor().a()); + domCommon_float_or_param_type *pFop = daeSafeCast(phong->add( "transparency")); + domCommon_float_or_param_type_complexType::domFloat *pTransparency = daeSafeCast(pFop->add("float")); pTransparency->setValue(1.0); } + else + osg::notify( osg::WARN ) << "Unsupported BlendFunction parameters in transparency processing." << std::endl; } - else if ((GL_ONE_MINUS_CONSTANT_COLOR == pBlendFunc->getSource()) && (GL_CONSTANT_COLOR == pBlendFunc->getDestination())) + else if (tex != NULL && tex->getImage( 0 ) != NULL) { - // RGB_ZERO opaque mode - domCommon_transparent_type *pTransparent = daeSafeCast(phong->createAndPlace("transparent")); - pTransparent->setOpaque(FX_OPAQUE_ENUM_RGB_ZERO); - domCommon_color_or_texture_type_complexType::domColor *pColor = daeSafeCast(pTransparent->createAndPlace("color")); - pColor->getValue().append(pBlendColor->getConstantColor().r()); - pColor->getValue().append(pBlendColor->getConstantColor().g()); - pColor->getValue().append(pBlendColor->getConstantColor().b()); - pColor->getValue().append(pBlendColor->getConstantColor().a()); - domCommon_float_or_param_type *pFop = daeSafeCast(phong->createAndPlace( "transparency")); - domCommon_float_or_param_type_complexType::domFloat *pTransparency = daeSafeCast(pFop->createAndPlace("float")); - pTransparency->setValue(1.0); + domCommon_transparent_type *ctt = daeSafeCast< domCommon_transparent_type >( phong->add( "transparent" ) ); + 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( "texture" ) ); + + #ifndef EARTH_TEX + std::string sampName = efName + "-sampler"; + dtex->setTexture( sampName.c_str() ); + #else + std::string iName = efName + "-image"; + dtex->setTexture( iName.c_str() ); + #endif + dtex->setTexcoord( "texcoord0" ); } else - osg::notify( osg::WARN ) << "Unsupported BlendFunction parameters in transparency processing." << std::endl; + { + osg::notify( osg::WARN ) << "Transparency processing - No texture or BlendColor." << std::endl; + } } else - osg::notify( osg::WARN ) << "Transparency processing - BlendFunction or BlendColor not found." << std::endl; + { + osg::notify( osg::WARN ) << "Transparency processing - BlendFunction not found." << std::endl; + } } - // Process GOOGLE one sided stuff here - if (osg::StateAttribute::INHERIT != ssClean->getMode(GL_CULL_FACE)) + if (writeExtras) { - domExtra *pExtra = daeSafeCast(pc->createAndPlace(COLLADA_ELEMENT_EXTRA)); - domTechnique *pTechnique = daeSafeCast(pExtra->createAndPlace( COLLADA_ELEMENT_TECHNIQUE ) ); - pTechnique->setProfile("GOOGLEEARTH"); - domAny *pAny = (domAny*)(daeElement*)pTechnique->createAndPlace("double_sided"); - if (GL_FALSE == ssClean->getMode(GL_CULL_FACE)) - pAny->setValue("1"); - else - pAny->setValue("0"); + // Adds the following to a Profile_COMMON element + + // + // + // 0 + // + // + + // Process GOOGLE one sided stuff here + if (osg::StateAttribute::INHERIT != ssClean->getMode(GL_CULL_FACE)) + { + domExtra *pExtra = daeSafeCast(pc->add(COLLADA_ELEMENT_EXTRA)); + domTechnique *pTechnique = daeSafeCast(pExtra->add( COLLADA_ELEMENT_TECHNIQUE ) ); + pTechnique->setProfile("GOOGLEEARTH"); + domAny *pAny = (domAny*)(daeElement*)pTechnique->add("double_sided"); + if (GL_FALSE == ssClean->getMode(GL_CULL_FACE)) + pAny->setValue("1"); + else + pAny->setValue("0"); + } } materialMap.insert( std::make_pair( ssClean, mat ) ); @@ -409,7 +427,7 @@ osg::StateSet* daeWriter::CleanStateSet(osg::StateSet* pStateSet) const if (NULL != pStateSet->getAttribute(osg::StateAttribute::MATERIAL)) pCleanedStateSet->setAttribute(pStateSet->getAttribute(osg::StateAttribute::MATERIAL)); // pCleanedStateSet->setRenderingHint(pStateSet->getRenderingHint()); does not work at the moment due to stateSet::merge - if (osg::StateAttribute::INHERIT != pStateSet->getMode(GL_CULL_FACE)) + if (osg::StateAttribute::ON != pStateSet->getMode(GL_CULL_FACE)) pCleanedStateSet->setMode(GL_CULL_FACE, pStateSet->getMode(GL_CULL_FACE)); return pCleanedStateSet; } diff --git a/src/osgPlugins/dae/daeWSceneObjects.cpp b/src/osgPlugins/dae/daeWSceneObjects.cpp index e5d02dbcd..ae11cb886 100644 --- a/src/osgPlugins/dae/daeWSceneObjects.cpp +++ b/src/osgPlugins/dae/daeWSceneObjects.cpp @@ -19,19 +19,54 @@ #include #include #include - +#include //#include //#include +#include +#include +#include + using namespace osgdae; +// Write non-standard node data as extra of type "Node" with "OpenSceneGraph" technique +void daeWriter::writeNodeExtra(osg::Node &node) +{ + unsigned int numDesc = node.getDescriptions().size(); + // Only create extra if descriptions are filled in + if (writeExtras && (numDesc > 0)) + { + // Adds the following to a node + + // + // + // + // Some info + // + // + // + + domExtra *extra = daeSafeCast(currentNode->add( COLLADA_ELEMENT_EXTRA )); + extra->setType("Node"); + domTechnique *teq = daeSafeCast(extra->add( COLLADA_ELEMENT_TECHNIQUE ) ); + teq->setProfile( "OpenSceneGraph" ); + domAny *descriptions = (domAny*)teq->add( "Descriptions" ); + + for (unsigned int currDesc = 0; currDesc < numDesc; currDesc++) + { + std::string value = node.getDescription(currDesc); + if (!value.empty()) + { + domAny *description = (domAny*)descriptions->add( "Description" ); + description->setValue(value.c_str()); + } + } + } +} -//GROUP void daeWriter::apply( osg::Group &node ) { -#ifdef _DEBUG debugPrint( node ); -#endif while ( lastDepth >= _nodePath.size() ) { @@ -39,23 +74,73 @@ void daeWriter::apply( osg::Group &node ) currentNode = daeSafeCast< domNode >( currentNode->getParentElement() ); lastDepth--; } - currentNode = daeSafeCast< domNode >(currentNode->createAndPlace( COLLADA_ELEMENT_NODE ) ); + currentNode = daeSafeCast< domNode >(currentNode->add( COLLADA_ELEMENT_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) + { + // Adds the following to a node + + // + // + // 0 + // + // 1 0 + // 0 1 + // + // + // + + domExtra *extra = daeSafeCast(currentNode->add( COLLADA_ELEMENT_EXTRA )); + extra->setType("MultiSwitch"); + domTechnique *teq = daeSafeCast(extra->add( COLLADA_ELEMENT_TECHNIQUE ) ); + teq->setProfile( "OpenSceneGraph" ); + + domAny *activeSwitchSet = (domAny*)teq->add("ActiveSwitchSet" ); + activeSwitchSet->setValue(toString(multiswitch->getActiveSwitchSet()).c_str()); + + domAny *valueLists = (domAny*)teq->add( "ValueLists" ); + + unsigned int pos = 0; + const osgSim::MultiSwitch::SwitchSetList& switchset = multiswitch->getSwitchSetList(); + for(osgSim::MultiSwitch::SwitchSetList::const_iterator sitr=switchset.begin(); + sitr!=switchset.end(); + ++sitr,++pos) + { + domAny *valueList = (domAny*)valueLists->add( "ValueList" ); + std::stringstream fw; + const osgSim::MultiSwitch::ValueList& values = *sitr; + for(osgSim::MultiSwitch::ValueList::const_iterator itr=values.begin(); + itr!=values.end(); + ++itr) + { + if (itr != values.begin()) + { + fw << " "; + } + fw << *itr; + } + valueList->setValue(fw.str().c_str()); + } + currentNode->setId(getNodeName(node,"multiswitch").c_str()); + } + else + { currentNode->setId(getNodeName(node,"group").c_str()); + } + + writeNodeExtra(node); lastDepth = _nodePath.size(); - lastVisited = GROUP; - traverse( node ); } -//SWITCH void daeWriter::apply( osg::Switch &node ) { -#ifdef _DEBUG debugPrint( node ); -#endif while ( lastDepth >= _nodePath.size() ) { @@ -63,29 +148,52 @@ void daeWriter::apply( osg::Switch &node ) currentNode = daeSafeCast< domNode >( currentNode->getParentElement() ); lastDepth--; } - currentNode = daeSafeCast< domNode >(currentNode->createAndPlace( COLLADA_ELEMENT_NODE ) ); + currentNode = daeSafeCast< domNode >(currentNode->add( COLLADA_ELEMENT_NODE ) ); currentNode->setId(getNodeName(node,"switch").c_str()); + + if (writeExtras) + { + // Adds the following to a node + + // + // + // 1 0 + // + // + + domExtra *extra = daeSafeCast(currentNode->add( COLLADA_ELEMENT_EXTRA )); + extra->setType("Switch"); + domTechnique *teq = daeSafeCast(extra->add( COLLADA_ELEMENT_TECHNIQUE ) ); + teq->setProfile( "OpenSceneGraph" ); + + domAny *valueList = (domAny*)teq->add( "ValueList" ); + + std::stringstream fw; + const osg::Switch::ValueList& values = node.getValueList(); + for(osg::Switch::ValueList::const_iterator itr=values.begin(); + itr!=values.end(); + ++itr) + { + if (itr != values.begin()) + { + fw << " "; + } + fw << *itr; + } + valueList->setValue(fw.str().c_str()); + } + + writeNodeExtra(node); lastDepth = _nodePath.size(); - lastVisited = SWITCH; - - unsigned int cnt = node.getNumChildren(); - for ( unsigned int i = 0; i < cnt; i++ ) - { - if ( node.getValue( i ) ) - { - node.getChild( i )->accept( *this ); - } - } + // Process all children + traverse( node ); } -//LOD -void daeWriter::apply( osg::LOD &node ) +void daeWriter::apply( osg::Sequence &node ) { -#ifdef _DEBUG debugPrint( node ); -#endif while ( lastDepth >= _nodePath.size() ) { @@ -93,40 +201,158 @@ void daeWriter::apply( osg::LOD &node ) currentNode = daeSafeCast< domNode >( currentNode->getParentElement() ); lastDepth--; } - currentNode = daeSafeCast< domNode >(currentNode->createAndPlace( COLLADA_ELEMENT_NODE ) ); + currentNode = daeSafeCast< domNode >(currentNode->add( COLLADA_ELEMENT_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) + { + // Adds the following to a node + + // + // + // 0 0 + // 0 + // 0 + // 0 + // -1 + // 1 + // -1 + // 0 + // + // + + domExtra *extra = daeSafeCast(currentNode->add( COLLADA_ELEMENT_EXTRA )); + extra->setType("Sequence"); + domTechnique *teq = daeSafeCast(extra->add( COLLADA_ELEMENT_TECHNIQUE ) ); + teq->setProfile( "OpenSceneGraph" ); + + domAny *frameTime = (domAny*)teq->add("FrameTime"); + std::stringstream fw; + for (unsigned int i = 0; i < node.getNumChildren(); i++) + { + if (i > 0) + { + fw << " "; + } + fw << node.getTime(i); + } + frameTime->setValue(fw.str().c_str()); + + domAny *lastFrameTime = (domAny*)teq->add("LastFrameTime"); + lastFrameTime->setValue(toString(node.getLastFrameTime()).c_str()); + + // loop mode & interval + osg::Sequence::LoopMode mode; + int begin, end; + node.getInterval(mode, begin, end); + domAny *loopMode = (domAny*)teq->add("LoopMode"); + loopMode->setValue(toString(mode).c_str()); + domAny *intervalBegin = (domAny*)teq->add("IntervalBegin"); + intervalBegin->setValue(toString(begin).c_str()); + domAny *intervalEnd = (domAny*)teq->add("IntervalEnd"); + intervalEnd->setValue(toString(end).c_str()); + + // duration + float speed; + int nreps; + node.getDuration(speed, nreps); + domAny *durationSpeed = (domAny*)teq->add("DurationSpeed"); + durationSpeed->setValue(toString(speed).c_str()); + domAny *durationNReps = (domAny*)teq->add("DurationNReps"); + durationNReps->setValue(toString(nreps).c_str()); + + // sequence mode + domAny *sequenceMode = (domAny*)teq->add("SequenceMode"); + sequenceMode->setValue(toString(node.getMode()).c_str()); + } + + writeNodeExtra(node); + + lastDepth = _nodePath.size(); + + traverse( node ); +} + +void daeWriter::apply( osg::LOD &node ) +{ + debugPrint( node ); + + while ( lastDepth >= _nodePath.size() ) + { + //We are not a child of previous node + currentNode = daeSafeCast< domNode >( currentNode->getParentElement() ); + lastDepth--; + } + currentNode = daeSafeCast< domNode >(currentNode->add( COLLADA_ELEMENT_NODE ) ); lastDepth = _nodePath.size(); currentNode->setId(getNodeName(node,"LOD").c_str()); - lastVisited = LOD; - //TODO : get the most or less detailed node, not only the first one - - /*for ( unsigned int i = 0; i < node.getNumChildren(); i++ ) + if (writeExtras) { - if ( node.getChild( i ) != NULL ) + // Store LOD data as extra "LOD" data in the "OpenSceneGraph" technique + // Adds the following to a node + + // + // + //
1 2 3
(optional ) + // -1 (required if Center is available) + // 0 + // + // 0 300 + // 300 600 + // + //
+ //
+ + domExtra *extra = daeSafeCast(currentNode->add( COLLADA_ELEMENT_EXTRA )); + extra->setType("LOD"); + domTechnique *teq = daeSafeCast(extra->add( COLLADA_ELEMENT_TECHNIQUE ) ); + teq->setProfile( "OpenSceneGraph" ); + + if (node.getCenterMode()==osg::LOD::USER_DEFINED_CENTER) { - node.getChild( i )->accept( *this ); - break; + domAny *center = (domAny*)teq->add("Center"); + center->setValue(toString(node.getCenter()).c_str()); + + domAny *radius = (domAny*)teq->add("Radius"); + radius->setValue(toString(node.getRadius()).c_str()); } - }*/ - //unsigned int cnt = node.getNumChildren(); - node.getChild( 0 )->accept( *this ); + + domAny *rangeMode = (domAny*)teq->add("RangeMode"); + rangeMode->setValue(toString(node.getRangeMode()).c_str()); + + domAny *valueLists = (domAny*)teq->add("RangeList"); + + unsigned int pos = 0; + const osg::LOD::RangeList& rangelist = node.getRangeList(); + for(osg::LOD::RangeList::const_iterator sitr=rangelist.begin(); + sitr!=rangelist.end(); + ++sitr,++pos) + { + domAny *valueList = (domAny*)valueLists->add("MinMax"); + std::stringstream fw; + fw << sitr->first << " " << sitr->second; + valueList->setValue(fw.str().c_str()); + } + } + + writeNodeExtra(node); + + // Process all children + traverse( node ); } void daeWriter::apply( osg::ProxyNode &node ) { - osg::notify( osg::WARN ) << "ProxyNode. Missing " << node.getNumChildren() << " children\n"; + osg::notify( osg::WARN ) << "ProxyNode. Missing " << node.getNumChildren() << " children" << std::endl; } - - -//LIGHT void daeWriter::apply( osg::LightSource &node ) { -#ifdef _DEBUG debugPrint( node ); -#endif - domInstance_light *il = daeSafeCast< domInstance_light >( currentNode->createAndPlace( "instance_light" ) ); + domInstance_light *il = daeSafeCast< domInstance_light >( currentNode->add( "instance_light" ) ); std::string name = node.getName(); if ( name.empty() ) { @@ -137,24 +363,19 @@ void daeWriter::apply( osg::LightSource &node ) if ( lib_lights == NULL ) { - lib_lights = daeSafeCast< domLibrary_lights >( dom->createAndPlace( COLLADA_ELEMENT_LIBRARY_LIGHTS ) ); + lib_lights = daeSafeCast< domLibrary_lights >( dom->add( COLLADA_ELEMENT_LIBRARY_LIGHTS ) ); } - domLight *light = daeSafeCast< domLight >( lib_lights->createAndPlace( COLLADA_ELEMENT_LIGHT ) ); + domLight *light = daeSafeCast< domLight >( lib_lights->add( COLLADA_ELEMENT_LIGHT ) ); light->setId( name.c_str() ); - lastVisited = LIGHT; - traverse( node ); } -//CAMERA void daeWriter::apply( osg::Camera &node ) { -#ifdef _DEBUG debugPrint( node ); -#endif - domInstance_camera *ic = daeSafeCast< domInstance_camera >( currentNode->createAndPlace( "instance_camera" ) ); + domInstance_camera *ic = daeSafeCast< domInstance_camera >( currentNode->add( "instance_camera" ) ); std::string name = node.getName(); if ( name.empty() ) { @@ -165,12 +386,10 @@ void daeWriter::apply( osg::Camera &node ) if ( lib_cameras == NULL ) { - lib_cameras = daeSafeCast< domLibrary_cameras >( dom->createAndPlace( COLLADA_ELEMENT_LIBRARY_CAMERAS ) ); + lib_cameras = daeSafeCast< domLibrary_cameras >( dom->add( COLLADA_ELEMENT_LIBRARY_CAMERAS ) ); } - domCamera *cam = daeSafeCast< domCamera >( lib_cameras->createAndPlace( COLLADA_ELEMENT_CAMERA ) ); + domCamera *cam = daeSafeCast< domCamera >( lib_cameras->add( COLLADA_ELEMENT_CAMERA ) ); cam->setId( name.c_str() ); - lastVisited = CAMERA; - traverse( node ); } diff --git a/src/osgPlugins/dae/daeWTransforms.cpp b/src/osgPlugins/dae/daeWTransforms.cpp index 9ac196b6d..5ec2e25ae 100644 --- a/src/osgPlugins/dae/daeWTransforms.cpp +++ b/src/osgPlugins/dae/daeWTransforms.cpp @@ -17,6 +17,9 @@ #include #include +#include + +#include using namespace osgdae; @@ -34,10 +37,10 @@ void daeWriter::apply( osg::MatrixTransform &node ) lastDepth--; } - currentNode = daeSafeCast< domNode >(currentNode->createAndPlace( COLLADA_ELEMENT_NODE ) ); + currentNode = daeSafeCast< domNode >(currentNode->add( COLLADA_ELEMENT_NODE ) ); currentNode->setId(getNodeName(node,"matrixTransform").c_str()); - domMatrix *mat = daeSafeCast< domMatrix >(currentNode->createAndPlace( COLLADA_ELEMENT_MATRIX ) ); + domMatrix *mat = daeSafeCast< domMatrix >(currentNode->add( COLLADA_ELEMENT_MATRIX ) ); const osg::Matrix::value_type *mat_vals = node.getMatrix().ptr(); //for ( int i = 0; i < 16; i++ ) //{ @@ -60,9 +63,10 @@ void daeWriter::apply( osg::MatrixTransform &node ) mat->getValue().append( mat_vals[11] ); mat->getValue().append( mat_vals[15] ); - lastVisited = MATRIX; lastDepth = _nodePath.size(); + writeNodeExtra(node); + traverse( node ); } @@ -79,7 +83,7 @@ void daeWriter::apply( osg::PositionAttitudeTransform &node ) currentNode = daeSafeCast< domNode >( currentNode->getParentElement() ); lastDepth--; } - currentNode = daeSafeCast< domNode >(currentNode->createAndPlace( COLLADA_ELEMENT_NODE ) ); + currentNode = daeSafeCast< domNode >(currentNode->add( COLLADA_ELEMENT_NODE ) ); currentNode->setId(getNodeName(node,"positionAttitudeTransform").c_str()); const osg::Vec3 &pos = node.getPosition(); @@ -89,7 +93,7 @@ void daeWriter::apply( osg::PositionAttitudeTransform &node ) if ( s.x() != 1 || s.y() != 1 || s.z() != 1 ) { //make a scale - domScale *scale = daeSafeCast< domScale >( currentNode->createAndPlace( COLLADA_ELEMENT_SCALE ) ); + domScale *scale = daeSafeCast< domScale >( currentNode->add( COLLADA_ELEMENT_SCALE ) ); scale->getValue().append( s.x() ); scale->getValue().append( s.y() ); scale->getValue().append( s.z() ); @@ -101,7 +105,7 @@ void daeWriter::apply( osg::PositionAttitudeTransform &node ) if ( angle != 0 ) { //make a rotate - domRotate *rot = daeSafeCast< domRotate >( currentNode->createAndPlace( COLLADA_ELEMENT_ROTATE ) ); + domRotate *rot = daeSafeCast< domRotate >( currentNode->add( COLLADA_ELEMENT_ROTATE ) ); rot->getValue().append( axis.x() ); rot->getValue().append( axis.y() ); rot->getValue().append( axis.z() ); @@ -111,13 +115,14 @@ void daeWriter::apply( osg::PositionAttitudeTransform &node ) if ( pos.x() != 0 || pos.y() != 0 || pos.z() != 0 ) { //make a translate - domTranslate *trans = daeSafeCast< domTranslate >( currentNode->createAndPlace( COLLADA_ELEMENT_TRANSLATE ) ); + domTranslate *trans = daeSafeCast< domTranslate >( currentNode->add( COLLADA_ELEMENT_TRANSLATE ) ); trans->getValue().append( pos.x() ); trans->getValue().append( pos.y() ); trans->getValue().append( pos.z() ); } - lastVisited = POSATT; + writeNodeExtra(node); + lastDepth = _nodePath.size(); traverse( node ); @@ -125,10 +130,117 @@ void daeWriter::apply( osg::PositionAttitudeTransform &node ) void daeWriter::apply( osg::Transform &node ) { - osg::notify( osg::WARN ) << "some other transform type. Missing " << node.getNumChildren() << " children\n"; + debugPrint( node ); + + while ( lastDepth >= _nodePath.size() ) + { + // We are not a child of previous node + currentNode = daeSafeCast< domNode >( currentNode->getParentElement() ); + lastDepth--; + } + currentNode = daeSafeCast< domNode >(currentNode->add( COLLADA_ELEMENT_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) + { + // Adds the following to a node + + // + // + // 0 -0.174533 0 + // 0 0.872665 0 + // 0 0.0174533 0 + // 0 0 0 + // 0 0 0 + // 0 0 0 + // 0 0 0 + // 0 0 0 + // 0 0 0 + // 1 1 1 + // 0 0 0 + // 1 1 1 + // 0 + // 269964960 + // 0 + // + // 1 0 0 0 + // 0 1 0 0 + // 0 0 1 0 + // 0 0 0 1 + // + // + // + + domExtra *extra = daeSafeCast(currentNode->add( COLLADA_ELEMENT_EXTRA )); + extra->setType("DOFTransform"); + domTechnique *teq = daeSafeCast(extra->add( COLLADA_ELEMENT_TECHNIQUE ) ); + teq->setProfile( "OpenSceneGraph" ); + + domAny *minHPR = (domAny*)teq->add("MinHPR" ); + minHPR->setValue(toString(dof->getMinHPR()).c_str()); + + domAny *maxHPR = (domAny*)teq->add("MaxHPR" ); + maxHPR->setValue(toString(dof->getMaxHPR()).c_str()); + + domAny *incrementHPR = (domAny*)teq->add("IncrementHPR" ); + incrementHPR->setValue(toString(dof->getIncrementHPR()).c_str()); + + domAny *currentHPR = (domAny*)teq->add("CurrentHPR" ); + currentHPR->setValue(toString(dof->getCurrentHPR()).c_str()); + + domAny *minTranslate = (domAny*)teq->add("MinTranslate" ); + minTranslate->setValue(toString(dof->getMinTranslate()).c_str()); + + domAny *maxTranslate = (domAny*)teq->add("MaxTranslate" ); + maxTranslate->setValue(toString(dof->getMaxTranslate()).c_str()); + + domAny *incrementTranslate = (domAny*)teq->add("IncrementTranslate" ); + incrementTranslate->setValue(toString(dof->getIncrementTranslate()).c_str()); + + domAny *currentTranslate = (domAny*)teq->add("CurrentTranslate" ); + currentTranslate->setValue(toString(dof->getCurrentTranslate()).c_str()); + + domAny *minScale = (domAny*)teq->add("MinScale" ); + minScale->setValue(toString(dof->getMinScale()).c_str()); + + domAny *maxScale = (domAny*)teq->add("MaxScale" ); + maxScale->setValue(toString(dof->getMaxScale()).c_str()); + + domAny *incrementScale = (domAny*)teq->add("IncrementScale" ); + incrementScale->setValue(toString(dof->getIncrementScale()).c_str()); + + domAny *currentScale = (domAny*)teq->add("CurrentScale" ); + currentScale->setValue(toString(dof->getCurrentScale()).c_str()); + + domAny *multOrder = (domAny*)teq->add("MultOrder" ); + multOrder->setValue(toString(dof->getHPRMultOrder()).c_str()); + + domAny *limitationFlags = (domAny*)teq->add("LimitationFlags" ); + limitationFlags->setValue(toString(dof->getLimitationFlags()).c_str()); + + domAny *animationOn = (domAny*)teq->add("AnimationOn" ); + animationOn->setValue(toString(dof->getAnimationOn()).c_str()); + + domAny *putMatrix = (domAny*)teq->add("PutMatrix" ); + putMatrix->setValue(toString(dof->getPutMatrix()).c_str()); + + currentNode->setId(getNodeName(node, "doftransform").c_str()); + } + else + { + currentNode->setId(getNodeName(node, "transform").c_str()); + osg::notify( osg::WARN ) << "some other transform type. Missing " << node.getNumChildren() << " children" << std::endl; + } + + writeNodeExtra(node); + + lastDepth = _nodePath.size(); + + traverse( node ); } void daeWriter::apply( osg::CoordinateSystemNode &node ) { - osg::notify( osg::WARN ) << "CoordinateSystemNode. Missing " << node.getNumChildren() << " children\n"; + osg::notify( osg::WARN ) << "CoordinateSystemNode. Missing " << node.getNumChildren() << " children" << std::endl; } diff --git a/src/osgPlugins/dae/daeWriter.cpp b/src/osgPlugins/dae/daeWriter.cpp index 810a7cbf3..992ce09a8 100644 --- a/src/osgPlugins/dae/daeWriter.cpp +++ b/src/osgPlugins/dae/daeWriter.cpp @@ -20,13 +20,33 @@ #include -using namespace osgdae; -daeWriter::daeWriter( DAE *dae_, const std::string &fileURI, bool _usePolygons, bool GoogleMode ) : osg::NodeVisitor( TRAVERSE_ALL_CHILDREN ), +namespace osgdae { + +std::string toString(osg::Vec3 value) +{ + std::stringstream str; + str << value.x() << " " << value.y() << " " << value.z(); + return str.str(); +} + +std::string toString(osg::Matrix value) +{ + std::stringstream str; + str << value(0,0) << " " << value(1,0) << " " << value(2,0) << " " << value(3,0) << " " + << value(0,1) << " " << value(1,1) << " " << value(2,1) << " " << value(3,1) << " " + << value(0,2) << " " << value(1,2) << " " << value(2,2) << " " << value(3,2) << " " + << value(0,3) << " " << value(1,3) << " " << value(2,3) << " " << value(3,3); + return str.str(); +} + + +daeWriter::daeWriter( DAE *dae_, const std::string &fileURI, bool _usePolygons, bool GoogleMode, TraversalMode tm, bool _writeExtras) : osg::NodeVisitor( tm ), dae(dae_), rootName(*dae_), usePolygons (_usePolygons), - m_GoogleMode(GoogleMode) + m_GoogleMode(GoogleMode), + writeExtras(_writeExtras) { success = true; @@ -36,14 +56,14 @@ daeWriter::daeWriter( DAE *dae_, const std::string &fileURI, bool _usePolygons, dae->getDatabase()->createDocument( fileURI.c_str(), &doc ); dom = (domCOLLADA*)doc->getDomRoot(); //create scene and instance visual scene - domCOLLADA::domScene *scene = daeSafeCast< domCOLLADA::domScene >( dom->createAndPlace( COLLADA_ELEMENT_SCENE ) ); - domInstanceWithExtra *ivs = daeSafeCast< domInstanceWithExtra >( scene->createAndPlace( "instance_visual_scene" ) ); + domCOLLADA::domScene *scene = daeSafeCast< domCOLLADA::domScene >( dom->add( COLLADA_ELEMENT_SCENE ) ); + domInstanceWithExtra *ivs = daeSafeCast< domInstanceWithExtra >( scene->add( "instance_visual_scene" ) ); ivs->setUrl( "#defaultScene" ); //create library visual scenes and a visual scene and the root node - lib_vis_scenes = daeSafeCast( dom->createAndPlace( COLLADA_ELEMENT_LIBRARY_VISUAL_SCENES ) ); - vs = daeSafeCast< domVisual_scene >( lib_vis_scenes->createAndPlace( COLLADA_ELEMENT_VISUAL_SCENE ) ); + lib_vis_scenes = daeSafeCast( dom->add( COLLADA_ELEMENT_LIBRARY_VISUAL_SCENES ) ); + vs = daeSafeCast< domVisual_scene >( lib_vis_scenes->add( COLLADA_ELEMENT_VISUAL_SCENE ) ); vs->setId( "defaultScene" ); - currentNode = daeSafeCast< domNode >( vs->createAndPlace( COLLADA_ELEMENT_NODE ) ); + currentNode = daeSafeCast< domNode >( vs->add( COLLADA_ELEMENT_NODE ) ); currentNode->setId( "sceneRoot" ); //create Asset @@ -66,12 +86,14 @@ daeWriter::~daeWriter() void daeWriter::debugPrint( osg::Node &node ) { +#ifdef _DEBUG std::string indent = ""; for ( unsigned int i = 0; i < _nodePath.size(); i++ ) { indent += " "; } osg::notify( osg::INFO ) << indent << node.className() << std::endl; +#endif } bool daeWriter::writeFile() @@ -94,7 +116,7 @@ void daeWriter::setRootNode( const osg::Node &node ) std::string daeWriter::getNodeName(const osg::Node & node,const std::string & defaultName) { std::string nodeName; - if ((node.getName().empty()) || (node.getName()!="")) + if (node.getName().empty()) nodeName=uniquify(defaultName); else nodeName=node.getName(); @@ -104,12 +126,9 @@ std::string daeWriter::getNodeName(const osg::Node & node,const std::string & de //NODE void daeWriter::apply( osg::Node &node ) { -#ifdef _DEBUG debugPrint( node ); -#endif - osg::notify( osg::INFO ) << "generic node\n"; - lastVisited = NODE; + writeNodeExtra(node); traverse( node ); } @@ -135,10 +154,10 @@ std::string daeWriter::uniquify( const std::string &name ) void daeWriter::createAssetTag() { - domAsset *asset = daeSafeCast< domAsset >(dom->createAndPlace( COLLADA_ELEMENT_ASSET ) ); - domAsset::domCreated *c = daeSafeCast< domAsset::domCreated >( asset->createAndPlace( "created" ) ); - domAsset::domModified *m = daeSafeCast< domAsset::domModified >( asset->createAndPlace( "modified" ) ); - domAsset::domUnit *u = daeSafeCast< domAsset::domUnit >( asset->createAndPlace( "unit" ) ); + domAsset *asset = daeSafeCast< domAsset >(dom->add( COLLADA_ELEMENT_ASSET ) ); + domAsset::domCreated *c = daeSafeCast< domAsset::domCreated >(asset->add("created" )); + domAsset::domModified *m = daeSafeCast< domAsset::domModified >(asset->add("modified" )); + domAsset::domUnit *u = daeSafeCast< domAsset::domUnit >(asset->add("unit")); //TODO : set date and time c->setValue( "2006-07-25T00:00:00Z" ); @@ -179,3 +198,4 @@ void daeWriter::popStateSet(osg::StateSet* ss) } } +} // namespace osgdae \ No newline at end of file diff --git a/src/osgPlugins/dae/daeWriter.h b/src/osgPlugins/dae/daeWriter.h index 16c5d4d9c..ab833783b 100644 --- a/src/osgPlugins/dae/daeWriter.h +++ b/src/osgPlugins/dae/daeWriter.h @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -61,6 +62,17 @@ class domVisual_scene; class domP; namespace osgdae { + +/// Convert value to string using it's stream operator +template +std::string toString(T value) { + std::stringstream str; + str << value; + return str.str(); +} + +std::string toString(osg::Vec3 value); +std::string toString(osg::Matrix value); /** @class daeWriter @@ -71,9 +83,7 @@ class daeWriter : public osg::NodeVisitor protected: class ArrayNIndices; public: - enum NodeType { NODE, GEODE, GROUP, LIGHT, CAMERA, MATRIX, POSATT, SWITCH, LOD }; - - daeWriter( DAE *dae_, const std::string &fileURI, bool usePolygons=false, bool GoogleMode = false ); + daeWriter( DAE *dae_, const std::string &fileURI, bool usePolygons=false, bool GoogleMode = false,TraversalMode tm=TRAVERSE_ALL_CHILDREN, bool writeExtras = true); virtual ~daeWriter(); void setRootNode( const osg::Node &node ); @@ -90,9 +100,10 @@ public: virtual void apply( osg::MatrixTransform &node ); virtual void apply( osg::PositionAttitudeTransform &node ); virtual void apply( osg::Switch &node ); + virtual void apply( osg::Sequence &node ); virtual void apply( osg::LOD &node ); - //virtual void apply( osg::Billboard &node); + //virtual void apply( osg::Billboard &node); virtual void apply( osg::ProxyNode &node ); //virtual void apply( osg::Projection &node) virtual void apply( osg::CoordinateSystemNode &node ); @@ -100,11 +111,14 @@ public: //virtual void apply( osg::TexGenNode &node) virtual void apply( osg::Transform &node ); //virtual void apply( osg::CameraView &node) - //virtual void apply( osg::Sequence &node) //virtual void apply( osg::PagedLOD &node) //virtual void apply( osg::ClearNode &node) //virtual void apply( osg::OccluderNode &node) + void writeNodeExtra(osg::Node &node); + + + void traverse (osg::Node &node); /*protected: @@ -148,8 +162,9 @@ protected: //members domNode *currentNode; domVisual_scene *vs; + /// Write OSG specific data as extra data + bool writeExtras; bool success; - NodeType lastVisited; unsigned int lastDepth; struct CompareStateSet