/COLLADAMax/src/COLLADAMaxSceneGraphCreator.cpp
C++ | 406 lines | 277 code | 69 blank | 60 comment | 31 complexity | 736f211cac12f938c3cf219b8a7cb396 MD5 | raw file
- /*
- Copyright (c) 2008-2009 NetAllied Systems GmbH
- This file is part of COLLADAMax.
- Portions of the code are:
- Copyright (c) 2005-2007 Feeling Software Inc.
- Copyright (c) 2005-2007 Sony Computer Entertainment America
- Based on the 3dsMax COLLADASW Tools:
- Copyright (c) 2005-2006 Autodesk Media Entertainment
- Licensed under the MIT Open Source License,
- for details please see LICENSE file or the website
- http://www.opensource.org/licenses/mit-license.php
- */
- #include "COLLADAMaxStableHeaders.h"
- #include "COLLADAMaxSceneGraphCreator.h"
- #include "COLLADAFWVisualScene.h"
- #include "dummy.h"
- namespace COLLADAMax
- {
- SceneGraphCreator::SceneGraphCreator( DocumentImporter* documentImporter, const COLLADAFW::VisualScene* visualScene, COLLADABU::Math::Matrix4 upAxisRotation )
- : ImporterBase( documentImporter )
- , mVisualScene( visualScene )
- , mUpAxisRotation( upAxisRotation )
- {}
- //------------------------------
- SceneGraphCreator::~SceneGraphCreator()
- {
- }
- //------------------------------
- void SceneGraphCreator::setNodeProperties( const COLLADAFW::Node* node, ImpNode* importNode )
- {
- const String& newNodeName = node->getName();
- if ( !newNodeName.empty() )
- {
- #ifdef UNICODE
- WideString wideNodeName = COLLADABU::StringUtils::toWideString(newNodeName.c_str());
- importNode->SetName(wideNodeName.c_str());
- #else
- importNode->SetName(newNodeName.c_str());
- #endif
- }
- // set transform. we always do this. If there is an animation, the controller will be changed
- COLLADABU::Math::Matrix4 transformationMatrix;
- node->getTransformationMatrix(transformationMatrix);
- Matrix3 maxTransformationMatrix;
- Matrix4ToMaxMatrix3(maxTransformationMatrix, transformationMatrix);
- importNode->SetTransform(0, maxTransformationMatrix);
- }
- //------------------------------
- bool SceneGraphCreator::create()
- {
- if ( !mVisualScene )
- return false;
- INode* rootNode = getMaxInterface()->GetRootNode();
- //why does this not work: setting rotation on root node
- // Matrix3 maxTransformationMatrix;
- // Matrix4ToMaxMatrix3(maxTransformationMatrix, mUpAxisRotation);
- // rootNode->SetNodeTM(0, maxTransformationMatrix);
- //
- // Matrix3 x = rootNode->GetNodeTM(0);
- if( COLLADABU::Math::Matrix4::IDENTITY != mUpAxisRotation )
- {
- ImpNode* upAxisCorrectionNode = getMaxImportInterface()->CreateNode();
- Matrix3 maxTransformationMatrix;
- Matrix4ToMaxMatrix3( maxTransformationMatrix, mUpAxisRotation );
- upAxisCorrectionNode->SetName(__T("upaxis"));
- upAxisCorrectionNode->SetTransform(0, maxTransformationMatrix);
- INode* iNode = upAxisCorrectionNode->GetINode();
- upAxisCorrectionNode->Reference( getDummyObject() );
- rootNode->AttachChild(iNode, FALSE);
- importNodes(mVisualScene->getRootNodes(), iNode);
- }
- else
- importNodes(mVisualScene->getRootNodes(), rootNode);
- return true;
- }
- //------------------------------
- ImpNode* SceneGraphCreator::importNode( const COLLADAFW::Node* node, INode* parentINode )
- {
- bool singleInstance = (node->getInstanceGeometries().getCount() +
- node->getInstanceControllers().getCount() +
- node->getInstanceCameras().getCount() +
- node->getInstanceLights().getCount() ) == 1;
- ImpNode* newImportNode = 0;
- const COLLADAFW::UniqueId& nodeUniqueId = node->getUniqueId();
- if ( !singleInstance )
- {
- newImportNode = getMaxImportInterface()->CreateNode();
- setNodeProperties(node, newImportNode);
- getMaxImportInterface()->AddNodeToScene(newImportNode);
- RefResult res = newImportNode->Reference(getDummyObject());
- if ( node->getType() == COLLADAFW::Node::JOINT )
- {
- newImportNode->GetINode()->ShowBone(1);
- }
- importInstanceGeometries(node->getInstanceGeometries(), newImportNode);
- importInstanceControllers(node->getInstanceControllers(), newImportNode);
- importInstanceCameras(node->getInstanceCameras(), newImportNode);
- importInstanceLights(node->getInstanceLights(), newImportNode);
- }
- else
- {
- newImportNode = importInstanceGeometry( node, parentINode );
- if ( !newImportNode )
- newImportNode = importInstanceController( node, parentINode );
- if ( !newImportNode )
- newImportNode = importInstanceCamera( node, parentINode );
- if ( !newImportNode )
- newImportNode = importInstanceLight( node, parentINode );
- assert(newImportNode);
- }
- INode* childNode = newImportNode->GetINode();
- importNodes(node->getChildNodes(), childNode);
- // Append all nodes that are referenced by this node.
- importInstanceNodes(node->getInstanceNodes(), newImportNode);
- /** Store the unique id of the created node, to resolve references, when ever necessary.*/
- addUniqueIdINodePair( nodeUniqueId, newImportNode->GetINode());
- parentINode->AttachChild(childNode, FALSE);
- #if 0
- /* if there are nodes that reference the just created node, clone this node
- and append it to the referencing node.*/
- ImpNode* referencingImpNode = 0;
- while ( referencingImpNode = getReferencingImpNodesByUniqueId(nodeUniqueId) )
- {
- removeUniqueIdReferencingImpNodePair( nodeUniqueId, referencingImpNode);
- recursivelyCloneINode( referencingImpNode, newImportNode->GetINode() );
- }
- #endif
- return newImportNode;
- }
- //------------------------------
- bool SceneGraphCreator::importNodes( const COLLADAFW::NodePointerArray& nodeArray, INode* parentINode )
- {
- for ( size_t i = 0, count = nodeArray.getCount(); i < count; ++i)
- {
- ImpNode* newNode = importNode(nodeArray[i], parentINode);
- }
- return true;
- }
- //------------------------------
- template<class Instance,
- void (SceneGraphCreator::*postProcess)( INode*, Instance* )>
- bool SceneGraphCreator::importInstances( const COLLADAFW::PointerArray<Instance>& instanceArray, ImpNode* parentImportNode )
- {
- for ( size_t i = 0, count = instanceArray.getCount(); i < count; ++i)
- {
- Instance* instance = instanceArray[i];
- ImpNode* newImportNode = getMaxImportInterface()->CreateNode();
- INode* newNode = newImportNode->GetINode();
- const COLLADAFW::UniqueId& uniqueId = instance->getInstanciatedObjectId();
- Object* object = getObjectByUniqueId(uniqueId);
- if ( object )
- {
- newImportNode->Reference(object);
- }
- else
- {
- newImportNode->Reference( getDummyObject() );
- }
- const COLLADAFW::UniqueId& instanceUniqueId = instance->getInstanciatedObjectId();
- // Store mapping between unique ids and nodes referencing the corresponding object.
- // Used to clone nodes
- addObjectINodeUniqueIdPair(newNode, instanceUniqueId);
- // Used to resolve instancing of objects
- addUniqueIdObjectINodePair(instanceUniqueId, newNode);
- INode* parentNode = parentImportNode->GetINode();
- parentNode->AttachChild(newNode, FALSE);
- // post process the creation
- if ( postProcess )
- (this->*postProcess)(newNode, instance);
- }
- return true;
- }
- //------------------------------
- bool SceneGraphCreator::importInstanceGeometries( const COLLADAFW::InstanceGeometryPointerArray& instanceGeometryArray, ImpNode* parentImportNode )
- {
- return importInstances<COLLADAFW::InstanceGeometry, &SceneGraphCreator::storeMaterialBindings<COLLADAFW::COLLADA_TYPE::INSTANCE_GEOMETRY> >(instanceGeometryArray, parentImportNode);
- }
- //------------------------------
- bool SceneGraphCreator::importInstanceControllers( const COLLADAFW::InstanceControllerPointerArray& instanceControllerArray, ImpNode* parentImportNode )
- {
- return importInstances<COLLADAFW::InstanceController, &SceneGraphCreator::postProcessInstanceController>(instanceControllerArray, parentImportNode);
- }
- //------------------------------
- bool SceneGraphCreator::importInstanceCameras( const COLLADAFW::InstanceCameraPointerArray& instanceCameraArray, ImpNode* parentImportNode )
- {
- return importInstances<COLLADAFW::InstanceCamera, 0>(instanceCameraArray, parentImportNode);
- }
- //------------------------------
- bool SceneGraphCreator::importInstanceLights( const COLLADAFW::InstanceLightPointerArray& instanceLightArray, ImpNode* parentImportNode )
- {
- return importInstances<COLLADAFW::InstanceLight, 0>(instanceLightArray, parentImportNode);
- }
- //------------------------------
- template<class Instance,
- const COLLADAFW::PointerArray<Instance>& (COLLADAFW::Node::*getInstances)()const,
- void (SceneGraphCreator::*postProcess)( INode*, Instance* )>
- ImpNode* SceneGraphCreator::importInstance( const COLLADAFW::Node* node, INode* parentINode )
- {
- const COLLADAFW::PointerArray<Instance>& instances = (node->*getInstances)();
- if ( instances.getCount() != 1 )
- return 0;
- ImpNode* newImportNode = getMaxImportInterface()->CreateNode();
- setNodeProperties(node, newImportNode);
- INode* newNode = newImportNode->GetINode();
- Instance* instance = instances[0];
- const COLLADAFW::UniqueId& uniqueId = instance->getInstanciatedObjectId();
- Object* object = getObjectByUniqueId(uniqueId);
- if ( object )
- {
- newImportNode->Reference(object);
- const String& objectName = getObjectNameByObject(object);
- if ( node->getName().empty() && !objectName.empty() )
- {
- #ifdef UNICODE
- WideString wideObjectName = COLLADABU::StringUtils::toWideString(objectName.c_str());
- newImportNode->SetName( wideObjectName.c_str() );
- #else
- newImportNode->SetName( objectName.c_str() );
- #endif
- }
- }
- else
- {
- newImportNode->Reference( getDummyObject() );
- }
- const COLLADAFW::UniqueId& instanceGeometryUniqueId = instance->getInstanciatedObjectId();
- // Store mapping between unique ids and nodes referencing the corresponding object.
- // Used to clone nodes
- addObjectINodeUniqueIdPair(newNode, instanceGeometryUniqueId);
- // Used to resolve instancing of objects
- addUniqueIdObjectINodePair(instanceGeometryUniqueId, newNode);
- parentINode->AttachChild(newNode, FALSE);
- // post process the creation
- if ( postProcess )
- (this->*postProcess)(newNode, instance);
- return newImportNode;
- }
- //------------------------------
- ImpNode* SceneGraphCreator::importInstanceGeometry( const COLLADAFW::Node* node, INode* parentINode )
- {
- return importInstance<COLLADAFW::InstanceGeometry, &COLLADAFW::Node::getInstanceGeometries, &SceneGraphCreator::storeMaterialBindings<COLLADAFW::COLLADA_TYPE::INSTANCE_GEOMETRY> >(node, parentINode);
- }
- //------------------------------
- ImpNode* SceneGraphCreator::importInstanceController( const COLLADAFW::Node* node, INode* parentINode )
- {
- return importInstance<COLLADAFW::InstanceController, &COLLADAFW::Node::getInstanceControllers, &SceneGraphCreator::postProcessInstanceController>(node, parentINode);
- }
- //------------------------------
- ImpNode* SceneGraphCreator::importInstanceCamera( const COLLADAFW::Node* node, INode* parentINode )
- {
- return importInstance<COLLADAFW::InstanceCamera, &COLLADAFW::Node::getInstanceCameras, 0>(node, parentINode);
- }
- //------------------------------
- ImpNode* SceneGraphCreator::importInstanceLight( const COLLADAFW::Node* node, INode* parentINode )
- {
- return importInstance<COLLADAFW::InstanceLight, &COLLADAFW::Node::getInstanceLights, 0>(node, parentINode);
- }
- //------------------------------
- bool SceneGraphCreator::importInstanceNodes( const COLLADAFW::InstanceNodePointerArray& instanceNodeArray, ImpNode* parentImportNode )
- {
- for ( size_t i = 0, count = instanceNodeArray.getCount(); i < count; ++i)
- {
- COLLADAFW::InstanceNode* instanceNode = instanceNodeArray[i];
- const COLLADAFW::UniqueId& uniqueId = instanceNode->getInstanciatedObjectId();
- INode* instanciatedINode = getINodeByUniqueId(uniqueId);
- // check if the referenced node is already in the max scene graph
- if ( instanciatedINode )
- {
- if ( !recursivelyCloneINode(parentImportNode, instanciatedINode) )
- return false;;
- }
- else
- {
- const COLLADAFW::Node* instanciatedFWNode = getFWNodeByUniqueId( uniqueId );
- // check if the referenced node is in one of the already received library nodes
- if ( instanciatedFWNode )
- {
- importNode( instanciatedFWNode, parentImportNode->GetINode() );
- }
- #if 0
- else
- {
- // If the referenced node has not been imported, store which node is referenced
- // to clone the nodes as the referenced nodes gets imported
- addUniqueIdReferencingImpNodePair(instanceNode->getInstanciatedObjectId(), parentImportNode );
- }
- #endif
- }
- }
- return true;
- }
- //------------------------------
- bool SceneGraphCreator::recursivelyCloneINode( ImpNode* parentImportNode, INode* nodeToClone )
- {
- ImpNode* newImportNode = getMaxImportInterface()->CreateNode();
- getMaxImportInterface()->AddNodeToScene(newImportNode);
- INode* newNode = newImportNode->GetINode();
- Object* object = nodeToClone->GetObjectRef();
- newImportNode->Reference(object);
- newNode->SetTMController(nodeToClone->GetTMController());
- newImportNode->SetName(nodeToClone->GetName());
- //used to assign material
- addClonedINodeOriginalINodePair(newNode, nodeToClone);
- INode* parentNode = parentImportNode->GetINode();
- parentNode->AttachChild(newNode, TRUE);
- /* If the node to clone references an object, the cloned one must references the same object.*/
- COLLADAFW::UniqueId id = getUniqueIdByObjectINode(nodeToClone);
- if ( id.isValid() )
- {
- addUniqueIdObjectINodePair(id, newNode);
- addObjectINodeUniqueIdPair(newNode, id);
- }
- // Clone the children
- for ( int i = 0, count = nodeToClone->NumberOfChildren(); i < count; ++i)
- recursivelyCloneINode(newImportNode, nodeToClone->GetChildNode(i));
- return true;
- }
- //------------------------------
- void SceneGraphCreator::postProcessInstanceController( INode* node, COLLADAFW::InstanceController* instanceController )
- {
- storeMaterialBindings<COLLADAFW::COLLADA_TYPE::INSTANCE_CONTROLLER>( node, instanceController );
- const COLLADAFW::UniqueId& controllerUniqueId = instanceController->getInstanciatedObjectId();
- const COLLADAFW::SkinController* skinController = getSkinControllerByUniqueId( controllerUniqueId );
- if ( skinController )
- {
- const COLLADAFW::UniqueId& skinSource = skinController->getSource();
- if ( skinSource.getClassId() == COLLADAFW::MorphController::ID() )
- {
- addMorphControllerINodePair( skinSource, node);
- }
- }
- }
- } // namespace COLLADAMax