/* * Copyright 2006 Sony Computer Entertainment Inc. * * Licensed under the SCEA Shared Source License, Version 1.0 (the "License"); you may not use this * file except in compliance with the License. You may obtain a copy of the License at: * http://research.scea.com/scea_shared_source_license.html * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing permissions and limitations under the * License. */ #include "daeWriter.h" #include #include #include #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()); } } } } void daeWriter::apply( osg::Group &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 ) ); // 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 { writeAnimations(node); currentNode->setId(getNodeName(node,"group").c_str()); } writeNodeExtra(node); lastDepth = _nodePath.size(); traverse( node ); } void daeWriter::apply( osg::Switch &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 ) ); 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(); // Process all children traverse( node ); } void daeWriter::apply( osg::Sequence &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 ) ); 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()); if (writeExtras) { // 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) { 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()); } 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" << std::endl; } void daeWriter::apply( osg::LightSource &node ) { debugPrint( node ); domInstance_light *il = daeSafeCast< domInstance_light >( currentNode->add( COLLADA_ELEMENT_INSTANCE_LIGHT ) ); std::string name = node.getName(); if ( name.empty() ) { name = uniquify( "light" ); } std::string url = "#" + name; il->setUrl( url.c_str() ); if ( lib_lights == NULL ) { lib_lights = daeSafeCast< domLibrary_lights >( dom->add( COLLADA_ELEMENT_LIBRARY_LIGHTS ) ); } domLight *light = daeSafeCast< domLight >( lib_lights->add( COLLADA_ELEMENT_LIGHT ) ); light->setId( name.c_str() ); osg::Light* pOsgLight = node.getLight(); domLight *pDomLight = daeSafeCast< domLight >( lib_lights->add( COLLADA_ELEMENT_LIGHT ) ); pDomLight->setId( name.c_str() ); domLight::domTechnique_common *domTechniqueCommon = daeSafeCast(pDomLight->add(COLLADA_ELEMENT_TECHNIQUE_COMMON)); osg::Vec4 position = pOsgLight->getPosition(); osg::Vec3 direction = pOsgLight->getDirection(); osg::Vec4 ambientColor = pOsgLight->getAmbient(); osg::Vec4 diffuseColor = pOsgLight->getDiffuse(); osg::Vec4 specularColor = pOsgLight->getSpecular(); if (position.w() == 0) { // Directional light domLight::domTechnique_common::domDirectional *domDirectional = daeSafeCast(domTechniqueCommon->add(COLLADA_ELEMENT_DIRECTIONAL)); if ((position.x() != 0) || (position.y() != 0) || (position.z() != 0)) { osg::Vec3 dir(-position.x(), -position.y(), -position.z()); // TODO wrap instance_light in a rotating node to translate default light [0,0,-1] into proper direction } domFloat3 color; color.append3(diffuseColor.r(), diffuseColor.g(), diffuseColor.b()); domDirectional->add(COLLADA_ELEMENT_COLOR); domDirectional->getColor()->setValue(color); } else if (direction.length() == 0) { // Omni/point light domLight::domTechnique_common::domPoint *domPoint = daeSafeCast(domTechniqueCommon->add(COLLADA_ELEMENT_POINT)); domPoint->add(COLLADA_ELEMENT_CONSTANT_ATTENUATION); domPoint->getConstant_attenuation()->setValue(pOsgLight->getConstantAttenuation()); domPoint->add(COLLADA_ELEMENT_LINEAR_ATTENUATION); domPoint->getLinear_attenuation()->setValue(pOsgLight->getLinearAttenuation()); domPoint->add(COLLADA_ELEMENT_QUADRATIC_ATTENUATION); domPoint->getQuadratic_attenuation()->setValue(pOsgLight->getQuadraticAttenuation()); if ((position.x() != 0) || (position.y() != 0) || (position.z() != 0)) { // TODO wrap instance_light in a transforming node to translate default light [0,0,0] into proper position } domFloat3 color; color.append3(diffuseColor.r(), diffuseColor.g(), diffuseColor.b()); domPoint->add(COLLADA_ELEMENT_COLOR); domPoint->getColor()->setValue(color); } else { // Spot light domLight::domTechnique_common::domSpot *domSpot = daeSafeCast(domTechniqueCommon->add(COLLADA_ELEMENT_SPOT)); domSpot->add(COLLADA_ELEMENT_CONSTANT_ATTENUATION); domSpot->getConstant_attenuation()->setValue(pOsgLight->getConstantAttenuation()); domSpot->add(COLLADA_ELEMENT_LINEAR_ATTENUATION); domSpot->getLinear_attenuation()->setValue(pOsgLight->getLinearAttenuation()); domSpot->add(COLLADA_ELEMENT_QUADRATIC_ATTENUATION); domSpot->getQuadratic_attenuation()->setValue(pOsgLight->getQuadraticAttenuation()); if ((position.x() != 0) || (position.y() != 0) || (position.z() != 0)) { // TODO wrap instance_light in a transforming node to translate default light [0,0,0] into proper position // and rotate default direction [0,0,-1] into proper dir } domFloat3 color; color.append3(diffuseColor.r(), diffuseColor.g(), diffuseColor.b()); domSpot->add(COLLADA_ELEMENT_COLOR); domSpot->getColor()->setValue(color); domSpot->add(COLLADA_ELEMENT_FALLOFF_ANGLE); domSpot->getFalloff_angle()->setValue(pOsgLight->getSpotCutoff()); domSpot->add(COLLADA_ELEMENT_FALLOFF_EXPONENT); domSpot->getFalloff_exponent()->setValue(pOsgLight->getSpotExponent()); } // Write ambient as a separate Collada light if ((ambientColor.r() != 0) || (ambientColor.g() != 0) || (ambientColor.b() != 0)) { domInstance_light *ambientDomInstanceLight = daeSafeCast< domInstance_light >(currentNode->add( COLLADA_ELEMENT_INSTANCE_LIGHT )); std::string name = node.getName(); if (name.empty()) { name = uniquify( "light-ambient" ); } else { name += "-ambient"; } std::string url = "#" + name; ambientDomInstanceLight->setUrl( url.c_str() ); domLight *ambientDomLight = daeSafeCast< domLight >( lib_lights->add( COLLADA_ELEMENT_LIGHT ) ); ambientDomLight->setId(name.c_str()); domLight::domTechnique_common *ambientDomTechniqueCommon = daeSafeCast(ambientDomLight->add(COLLADA_ELEMENT_TECHNIQUE_COMMON)); // Ambient light domLight::domTechnique_common::domAmbient *domAmbient = daeSafeCast(ambientDomTechniqueCommon->add(COLLADA_ELEMENT_AMBIENT)); domFloat3 color; color.append3(ambientColor.r(), ambientColor.g(), ambientColor.b()); domAmbient->add(COLLADA_ELEMENT_COLOR); domAmbient->getColor()->setValue(color); } traverse( node ); } void daeWriter::apply( osg::Camera &node ) { debugPrint( node ); domInstance_camera *ic = daeSafeCast< domInstance_camera >( currentNode->add( COLLADA_ELEMENT_INSTANCE_CAMERA ) ); std::string name = node.getName(); if ( name.empty() ) { name = uniquify( "camera" ); } std::string url = "#" + name; ic->setUrl( url.c_str() ); if ( lib_cameras == NULL ) { lib_cameras = daeSafeCast< domLibrary_cameras >( dom->add( COLLADA_ELEMENT_LIBRARY_CAMERAS ) ); } domCamera *cam = daeSafeCast< domCamera >( lib_cameras->add( COLLADA_ELEMENT_CAMERA ) ); cam->setId( name.c_str() ); traverse( node ); } void daeWriter::apply( osg::CameraView &node) { debugPrint( node ); domInstance_camera *ic = daeSafeCast< domInstance_camera >( currentNode->add(COLLADA_ELEMENT_INSTANCE_CAMERA)); std::string name = node.getName(); if ( name.empty() ) { name = uniquify( "camera" ); } std::string url = "#" + name; ic->setUrl( url.c_str() ); if ( lib_cameras == NULL ) { lib_cameras = daeSafeCast< domLibrary_cameras >( dom->add( COLLADA_ELEMENT_LIBRARY_CAMERAS ) ); } domCamera *cam = daeSafeCast< domCamera >( lib_cameras->add( COLLADA_ELEMENT_CAMERA ) ); cam->setId( name.c_str() ); domCamera::domOptics *optics = daeSafeCast< domCamera::domOptics >( cam->add( COLLADA_ELEMENT_OPTICS ) ); domCamera::domOptics::domTechnique_common *techniqueCommon = daeSafeCast< domCamera::domOptics::domTechnique_common >( optics->add( COLLADA_ELEMENT_TECHNIQUE_COMMON ) ); domCamera::domOptics::domTechnique_common::domPerspective *pDomPerspective = daeSafeCast< domCamera::domOptics::domTechnique_common::domPerspective >( techniqueCommon->add( COLLADA_ELEMENT_PERSPECTIVE ) ); domTargetableFloat *pXfov = NULL; domTargetableFloat *pYfov = NULL; switch(node.getFieldOfViewMode()) { case(osg::CameraView::UNCONSTRAINED): pXfov = daeSafeCast< domTargetableFloat >( pDomPerspective->add( COLLADA_ELEMENT_XFOV ) ); pXfov->setValue(node.getFieldOfView()); break; case(osg::CameraView::HORIZONTAL): pXfov = daeSafeCast< domTargetableFloat >( pDomPerspective->add( COLLADA_ELEMENT_XFOV ) ); pXfov->setValue(node.getFieldOfView()); break; case(osg::CameraView::VERTICAL): pYfov = daeSafeCast< domTargetableFloat >( pDomPerspective->add( COLLADA_ELEMENT_YFOV ) ); pYfov->setValue(node.getFieldOfView()); break; } // Using hardcoded values for , and domTargetableFloat *pAspectRatio = daeSafeCast< domTargetableFloat >( pDomPerspective->add( COLLADA_ELEMENT_ASPECT_RATIO ) ); pAspectRatio->setValue(1.0); domTargetableFloat *pNear = daeSafeCast< domTargetableFloat >( pDomPerspective->add( COLLADA_ELEMENT_ZNEAR ) ); pNear->setValue(1); domTargetableFloat *pFar = daeSafeCast< domTargetableFloat >( pDomPerspective->add( COLLADA_ELEMENT_ZFAR ) ); pFar->setValue(1000); }