[osg-submissions] some changes to osgdb_dae (Collada plugin)
Mattias Linde
linde at acc.umu.se
Thu Sep 6 02:15:37 PDT 2007
Hi Robert,
Have made the updates now. Added a std::map for easy lookup if a visual node
is targeted by a rigid body which is the reason why the .h-file was changed too.
So now there'll be Group as often as possible, otherwise PostitionAttitudeTransform.
/ Mattias
-------------- next part --------------
/*
* 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.
*/
#ifndef _DAE_CONV_H_
#define _DAE_CONV_H_
#include <string>
#include <dae.h>
#include <dae/daeURI.h>
#include <dae/daeElement.h>
#include <dom/domCommon_color_or_texture_type.h>
#include <osg/Node>
#include <osg/Transform>
#include <osg/Notify>
#include <osg/PositionAttitudeTransform>
#include <osgDB/ReaderWriter>
#include <osgDB/FileNameUtils>
#include <osgDB/FileUtils>
#include <osgDB/Registry>
#include <osg/Material>
class domBind_material;
class domCamera;
//class domCommon_color_or_texture_type;
class domCommon_float_or_param_type;
class domGeometry;
class domInstance_controller;
class domInstance_geometry;
class domInstanceWithExtra;
class domLight;
class domLookat;
class domMatrix;
class domNode;
class domP;
class domProfile_COMMON;
class domScale;
class domSkew;
class domTranslate;
class domRotate;
class domVisual_scene;
#include <dom/domInputLocalOffset.h>
namespace osgdae {
class domSourceReader;
inline daeElement *getElementFromURI( daeURI &uri )
{
if ( uri.getState() == daeURI::uri_loaded || uri.getState() == daeURI::uri_pending ) {
uri.resolveElement();
}
return uri.getElement();
}
inline daeElement *getElementFromIDRef( daeIDRef &idref )
{
if ( idref.getState() == daeIDRef::id_loaded || idref.getState() == daeIDRef::id_pending ) {
idref.resolveElement();
}
return idref.getElement();
}
template< typename TInputArray, typename TInputType >
bool findInputSourceBySemantic( TInputArray& inputs, const char* semantic, daeElement *& element,
TInputType ** input = NULL, int unit = 0 )
{
element = NULL;
int count = 0;
for ( size_t i = 0; i < inputs.getCount(); i++ ) {
if ( !strcmp(semantic, inputs[i]->getSemantic()) ) {
if ( count == unit )
{
element = getElementFromURI( inputs[i]->getSource() );
*input = (TInputType*)inputs[i];
return true;
}
count++;
}
}
return false;
}
/**
@class daeReader
@brief Read a OSG scene from a DAE file
*/
class daeReader {
public:
daeReader(DAE *dae_);
virtual ~daeReader();
bool convert( const std::string &fileURI );
osg::Node* getRootNode() { return rootNode; }
protected:
//scene processing
osg::Node* processVisualScene( domVisual_scene *scene );
osg::Node* processNode( 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 );
//geometry processing
osg::Node* processInstance_geometry( domInstance_geometry *ig );
osg::Node* processGeometry( domGeometry *geo );
osg::Node* processInstance_controller( domInstance_controller *ictrl );
typedef std::map< daeElement*, domSourceReader > SourceMap;
typedef std::map< int, osg::IntArray*, std::less<int> > IndexMap;
template< typename T >
osg::Node* processSinglePPrimitive( T *group, SourceMap &sources, GLenum mode );
template< typename T >
osg::Node* processMultiPPrimitive( T *group, SourceMap &sources, GLenum mode );
osg::Node* processPolylist( domPolylist *group, SourceMap &sources );
void resolveArrays( domInputLocalOffset_Array &inputs, osg::Geometry *&geom,
SourceMap &sources, IndexMap &index_map );
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 );
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::StateAttribute *processTransparencySettings( domCommon_transparent_type *ctt, domCommon_float_or_param_type *pTransparency, osg::StateSet *ss );
osg::StateAttribute *processTexture( domCommon_color_or_texture_type_complexType::domTexture *tex );
//scene objects
osg::Node* processLight( domLight *dlight );
osg::Node* processCamera( domCamera *dcamera );
protected:
DAE *dae;
osg::Node* rootNode;
std::map<std::string,bool> _targetMap;
int m_numlights;
domEffect *currentEffect;
std::map< domGeometry*, osg::Node* > geometryMap;
std::map< domMaterial*, osg::StateSet* > materialMap;
enum AuthoringTool
{
UNKNOWN,
GOOGLE_SKETCHUP
};
AuthoringTool m_AuthoringTool;
};
};
#endif
-------------- next part --------------
/*
* 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 "daeReader.h"
#include <dae.h>
#include <dom/domCOLLADA.h>
#include <dom/domInstanceWithExtra.h>
#include <dom/domConstants.h>
using namespace osgdae;
daeReader::daeReader(DAE *dae_) : dae(dae_),
rootNode(NULL),
m_numlights(0),
currentEffect(NULL),
geometryMap(),
materialMap(),
m_AuthoringTool(UNKNOWN)
{
}
daeReader::~daeReader()
{
}
bool daeReader::convert( const std::string &fileURI )
{
daeElement *colladaElement;
domInstance_rigid_body *irb;
daeInt count, result;
std::string fURI;
if ( fileURI[1] == ':' )
{
fURI = "/" + fileURI;
}
else
{
fURI = fileURI;
}
daeInt res = dae->load( fURI.c_str() );
if( res != DAE_OK && res != DAE_ERR_COLLECTION_ALREADY_EXISTS)
{
osg::notify( osg::WARN ) << "Load failed in COLLADA DOM" << std::endl;
return false;
}
osg::notify( osg::INFO ) << "URI loaded: " << fURI << std::endl;
domCOLLADA* document = dae->getDom( fURI.c_str() );
if ( !document->getScene() || !document->getScene()->getInstance_visual_scene() )
{
osg::notify( osg::WARN ) << "No scene found!" << std::endl;
return false;
}
if (document->getAsset())
{
const domAsset::domContributor_Array& ContributorArray = document->getAsset()->getContributor_array();
size_t NumberOfContributors = ContributorArray.getCount();
size_t CurrentContributor;
for (CurrentContributor = 0; CurrentContributor < NumberOfContributors; CurrentContributor++)
{
if (ContributorArray[CurrentContributor]->getAuthoring_tool())
{
xsString Tool = ContributorArray[CurrentContributor]->getAuthoring_tool()->getValue();
if (strncmp(Tool, "Google SketchUp", 15) == 0)
m_AuthoringTool = GOOGLE_SKETCHUP;
}
}
}
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; i<count; i++) {
result = dae->getDatabase()->getElement(&colladaElement, i, NULL, COLLADA_TYPE_INSTANCE_RIGID_BODY);
if (result == DAE_OK) {
irb = daeSafeCast<domInstance_rigid_body>(colladaElement);
if (irb) {
domNode *node = daeSafeCast<domNode>(irb->getTarget().getElement());
if (node && node->getId()) {
_targetMap[ std::string(node->getId()) ] = true;
}
}
}
}
}
domInstanceWithExtra *ivs = document->getScene()->getInstance_visual_scene();
domVisual_scene *vs = daeSafeCast< domVisual_scene >( getElementFromURI( ivs->getUrl() ) );
if ( vs == NULL )
{
osg::notify( osg::WARN ) << "Unable to locate visual scene!" << std::endl;
return false;
}
rootNode = processVisualScene( vs );
return true;
}
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)
{
osg::notify( osg::WARN ) << "No visual scene group found !" << std::endl;
retVal = new osg::Group();
retVal->setName("Empty Collada scene");
}
else if (nbVisualSceneGroup==1)
{
osg::Node *node = processNode( scene->getNode_array()[0] );
if ( node != NULL )
retVal = node;
else
{
retVal = new osg::Group();
retVal->setName("Empty Collada scene (import failure)");
}
}
else
{
retVal = new osg::Group();
retVal->setName("Collada visual scene group");
for ( size_t i = 0; i < scene->getNode_array().getCount(); i++ )
{
osg::Node *node = processNode( scene->getNode_array()[i] );
if ( node != NULL )
{
retVal->asGroup()->addChild( node );
}
}
}
return retVal;
}
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();
bool targeted = false;
if (node->getId()) {
targeted = _targetMap[std::string(node->getId())];
}
if (patcount > 0 || targeted )
{
pat = new osg::PositionAttitudeTransform();
retVal = pat;
}
else
{
retVal = new osg::Group();
}
osg::Node *current = retVal;
retVal->setName( node->getId() ? node->getId() : "" );
// Handle rotate, translate and scale first..
// will make the hierarchy less deep
// <rotate>
osg::Quat osgRot;
for (int i=0; i<node->getRotate_array().getCount(); i++)
{
daeSmartRef<domRotate> rot = node->getRotate_array().get(i);
if (rot->getValue().getCount() != 4 ) {
osg::notify(osg::WARN)<<"Data is wrong size for rotate"<<std::endl;
continue;
}
domFloat4& r = rot->getValue();
osg::Vec3 axis;
axis.set(r[0],r[1],r[2]);
osgRot = osg::Quat(osg::DegreesToRadians(r[3]),axis) * osgRot;
pat->setAttitude(osgRot);
}
// <scale>
osg::Vec3 osgScale = osg::Vec3(1.0, 1.0, 1.0);
for (int i=0; i<node->getScale_array().getCount(); i++)
{
daeSmartRef<domScale> scale = node->getScale_array().get(i);
if (scale->getValue().getCount() != 3 ) {
osg::notify(osg::WARN)<<"Data is wrong size for scale"<<std::endl;
continue;
}
domFloat3& s = scale->getValue();
osgScale[0] *= s[0];
osgScale[1] *= s[1];
osgScale[2] *= s[2];
pat->setScale(osgScale);
}
// <translate>
osg::Vec3 osgTrans = osg::Vec3(0.0, 0.0, 0.0);
for (int i=0; i<node->getTranslate_array().getCount(); i++)
{
daeSmartRef<domTranslate> trans = node->getTranslate_array().get(i);
if (trans->getValue().getCount() != 3 ) {
osg::notify(osg::WARN)<<"Data is wrong size for translate"<<std::endl;
continue;
}
domFloat3& t = trans->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 )
{
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() );
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;
}
domInstance_light *il = daeSafeCast< domInstance_light >( node->getContents()[i] );
if ( il != NULL )
{
daeElement *el = getElementFromURI( il->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;
}
domInstance_node *instn = daeSafeCast< domInstance_node >( node->getContents()[i] );
if ( instn != NULL )
{
daeElement *el = getElementFromURI( instn->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;
}
domNode *n = daeSafeCast< domNode >( node->getContents()[i] );
if ( n != NULL )
{
trans = processNode( n );
if ( trans != NULL )
{
current->asGroup()->addChild( trans );
}
continue;
}
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;
}
More information about the osg-submissions
mailing list