PageRenderTime 39ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/COLLADAMax/src/COLLADAMaxSceneGraphCreator.cpp

https://bitbucket.org/ZhangJingGuo/opencollada
C++ | 406 lines | 277 code | 69 blank | 60 comment | 31 complexity | 736f211cac12f938c3cf219b8a7cb396 MD5 | raw file
  1. /*
  2. Copyright (c) 2008-2009 NetAllied Systems GmbH
  3. This file is part of COLLADAMax.
  4. Portions of the code are:
  5. Copyright (c) 2005-2007 Feeling Software Inc.
  6. Copyright (c) 2005-2007 Sony Computer Entertainment America
  7. Based on the 3dsMax COLLADASW Tools:
  8. Copyright (c) 2005-2006 Autodesk Media Entertainment
  9. Licensed under the MIT Open Source License,
  10. for details please see LICENSE file or the website
  11. http://www.opensource.org/licenses/mit-license.php
  12. */
  13. #include "COLLADAMaxStableHeaders.h"
  14. #include "COLLADAMaxSceneGraphCreator.h"
  15. #include "COLLADAFWVisualScene.h"
  16. #include "dummy.h"
  17. namespace COLLADAMax
  18. {
  19. SceneGraphCreator::SceneGraphCreator( DocumentImporter* documentImporter, const COLLADAFW::VisualScene* visualScene, COLLADABU::Math::Matrix4 upAxisRotation )
  20. : ImporterBase( documentImporter )
  21. , mVisualScene( visualScene )
  22. , mUpAxisRotation( upAxisRotation )
  23. {}
  24. //------------------------------
  25. SceneGraphCreator::~SceneGraphCreator()
  26. {
  27. }
  28. //------------------------------
  29. void SceneGraphCreator::setNodeProperties( const COLLADAFW::Node* node, ImpNode* importNode )
  30. {
  31. const String& newNodeName = node->getName();
  32. if ( !newNodeName.empty() )
  33. {
  34. #ifdef UNICODE
  35. WideString wideNodeName = COLLADABU::StringUtils::toWideString(newNodeName.c_str());
  36. importNode->SetName(wideNodeName.c_str());
  37. #else
  38. importNode->SetName(newNodeName.c_str());
  39. #endif
  40. }
  41. // set transform. we always do this. If there is an animation, the controller will be changed
  42. COLLADABU::Math::Matrix4 transformationMatrix;
  43. node->getTransformationMatrix(transformationMatrix);
  44. Matrix3 maxTransformationMatrix;
  45. Matrix4ToMaxMatrix3(maxTransformationMatrix, transformationMatrix);
  46. importNode->SetTransform(0, maxTransformationMatrix);
  47. }
  48. //------------------------------
  49. bool SceneGraphCreator::create()
  50. {
  51. if ( !mVisualScene )
  52. return false;
  53. INode* rootNode = getMaxInterface()->GetRootNode();
  54. //why does this not work: setting rotation on root node
  55. // Matrix3 maxTransformationMatrix;
  56. // Matrix4ToMaxMatrix3(maxTransformationMatrix, mUpAxisRotation);
  57. // rootNode->SetNodeTM(0, maxTransformationMatrix);
  58. //
  59. // Matrix3 x = rootNode->GetNodeTM(0);
  60. if( COLLADABU::Math::Matrix4::IDENTITY != mUpAxisRotation )
  61. {
  62. ImpNode* upAxisCorrectionNode = getMaxImportInterface()->CreateNode();
  63. Matrix3 maxTransformationMatrix;
  64. Matrix4ToMaxMatrix3( maxTransformationMatrix, mUpAxisRotation );
  65. upAxisCorrectionNode->SetName(__T("upaxis"));
  66. upAxisCorrectionNode->SetTransform(0, maxTransformationMatrix);
  67. INode* iNode = upAxisCorrectionNode->GetINode();
  68. upAxisCorrectionNode->Reference( getDummyObject() );
  69. rootNode->AttachChild(iNode, FALSE);
  70. importNodes(mVisualScene->getRootNodes(), iNode);
  71. }
  72. else
  73. importNodes(mVisualScene->getRootNodes(), rootNode);
  74. return true;
  75. }
  76. //------------------------------
  77. ImpNode* SceneGraphCreator::importNode( const COLLADAFW::Node* node, INode* parentINode )
  78. {
  79. bool singleInstance = (node->getInstanceGeometries().getCount() +
  80. node->getInstanceControllers().getCount() +
  81. node->getInstanceCameras().getCount() +
  82. node->getInstanceLights().getCount() ) == 1;
  83. ImpNode* newImportNode = 0;
  84. const COLLADAFW::UniqueId& nodeUniqueId = node->getUniqueId();
  85. if ( !singleInstance )
  86. {
  87. newImportNode = getMaxImportInterface()->CreateNode();
  88. setNodeProperties(node, newImportNode);
  89. getMaxImportInterface()->AddNodeToScene(newImportNode);
  90. RefResult res = newImportNode->Reference(getDummyObject());
  91. if ( node->getType() == COLLADAFW::Node::JOINT )
  92. {
  93. newImportNode->GetINode()->ShowBone(1);
  94. }
  95. importInstanceGeometries(node->getInstanceGeometries(), newImportNode);
  96. importInstanceControllers(node->getInstanceControllers(), newImportNode);
  97. importInstanceCameras(node->getInstanceCameras(), newImportNode);
  98. importInstanceLights(node->getInstanceLights(), newImportNode);
  99. }
  100. else
  101. {
  102. newImportNode = importInstanceGeometry( node, parentINode );
  103. if ( !newImportNode )
  104. newImportNode = importInstanceController( node, parentINode );
  105. if ( !newImportNode )
  106. newImportNode = importInstanceCamera( node, parentINode );
  107. if ( !newImportNode )
  108. newImportNode = importInstanceLight( node, parentINode );
  109. assert(newImportNode);
  110. }
  111. INode* childNode = newImportNode->GetINode();
  112. importNodes(node->getChildNodes(), childNode);
  113. // Append all nodes that are referenced by this node.
  114. importInstanceNodes(node->getInstanceNodes(), newImportNode);
  115. /** Store the unique id of the created node, to resolve references, when ever necessary.*/
  116. addUniqueIdINodePair( nodeUniqueId, newImportNode->GetINode());
  117. parentINode->AttachChild(childNode, FALSE);
  118. #if 0
  119. /* if there are nodes that reference the just created node, clone this node
  120. and append it to the referencing node.*/
  121. ImpNode* referencingImpNode = 0;
  122. while ( referencingImpNode = getReferencingImpNodesByUniqueId(nodeUniqueId) )
  123. {
  124. removeUniqueIdReferencingImpNodePair( nodeUniqueId, referencingImpNode);
  125. recursivelyCloneINode( referencingImpNode, newImportNode->GetINode() );
  126. }
  127. #endif
  128. return newImportNode;
  129. }
  130. //------------------------------
  131. bool SceneGraphCreator::importNodes( const COLLADAFW::NodePointerArray& nodeArray, INode* parentINode )
  132. {
  133. for ( size_t i = 0, count = nodeArray.getCount(); i < count; ++i)
  134. {
  135. ImpNode* newNode = importNode(nodeArray[i], parentINode);
  136. }
  137. return true;
  138. }
  139. //------------------------------
  140. template<class Instance,
  141. void (SceneGraphCreator::*postProcess)( INode*, Instance* )>
  142. bool SceneGraphCreator::importInstances( const COLLADAFW::PointerArray<Instance>& instanceArray, ImpNode* parentImportNode )
  143. {
  144. for ( size_t i = 0, count = instanceArray.getCount(); i < count; ++i)
  145. {
  146. Instance* instance = instanceArray[i];
  147. ImpNode* newImportNode = getMaxImportInterface()->CreateNode();
  148. INode* newNode = newImportNode->GetINode();
  149. const COLLADAFW::UniqueId& uniqueId = instance->getInstanciatedObjectId();
  150. Object* object = getObjectByUniqueId(uniqueId);
  151. if ( object )
  152. {
  153. newImportNode->Reference(object);
  154. }
  155. else
  156. {
  157. newImportNode->Reference( getDummyObject() );
  158. }
  159. const COLLADAFW::UniqueId& instanceUniqueId = instance->getInstanciatedObjectId();
  160. // Store mapping between unique ids and nodes referencing the corresponding object.
  161. // Used to clone nodes
  162. addObjectINodeUniqueIdPair(newNode, instanceUniqueId);
  163. // Used to resolve instancing of objects
  164. addUniqueIdObjectINodePair(instanceUniqueId, newNode);
  165. INode* parentNode = parentImportNode->GetINode();
  166. parentNode->AttachChild(newNode, FALSE);
  167. // post process the creation
  168. if ( postProcess )
  169. (this->*postProcess)(newNode, instance);
  170. }
  171. return true;
  172. }
  173. //------------------------------
  174. bool SceneGraphCreator::importInstanceGeometries( const COLLADAFW::InstanceGeometryPointerArray& instanceGeometryArray, ImpNode* parentImportNode )
  175. {
  176. return importInstances<COLLADAFW::InstanceGeometry, &SceneGraphCreator::storeMaterialBindings<COLLADAFW::COLLADA_TYPE::INSTANCE_GEOMETRY> >(instanceGeometryArray, parentImportNode);
  177. }
  178. //------------------------------
  179. bool SceneGraphCreator::importInstanceControllers( const COLLADAFW::InstanceControllerPointerArray& instanceControllerArray, ImpNode* parentImportNode )
  180. {
  181. return importInstances<COLLADAFW::InstanceController, &SceneGraphCreator::postProcessInstanceController>(instanceControllerArray, parentImportNode);
  182. }
  183. //------------------------------
  184. bool SceneGraphCreator::importInstanceCameras( const COLLADAFW::InstanceCameraPointerArray& instanceCameraArray, ImpNode* parentImportNode )
  185. {
  186. return importInstances<COLLADAFW::InstanceCamera, 0>(instanceCameraArray, parentImportNode);
  187. }
  188. //------------------------------
  189. bool SceneGraphCreator::importInstanceLights( const COLLADAFW::InstanceLightPointerArray& instanceLightArray, ImpNode* parentImportNode )
  190. {
  191. return importInstances<COLLADAFW::InstanceLight, 0>(instanceLightArray, parentImportNode);
  192. }
  193. //------------------------------
  194. template<class Instance,
  195. const COLLADAFW::PointerArray<Instance>& (COLLADAFW::Node::*getInstances)()const,
  196. void (SceneGraphCreator::*postProcess)( INode*, Instance* )>
  197. ImpNode* SceneGraphCreator::importInstance( const COLLADAFW::Node* node, INode* parentINode )
  198. {
  199. const COLLADAFW::PointerArray<Instance>& instances = (node->*getInstances)();
  200. if ( instances.getCount() != 1 )
  201. return 0;
  202. ImpNode* newImportNode = getMaxImportInterface()->CreateNode();
  203. setNodeProperties(node, newImportNode);
  204. INode* newNode = newImportNode->GetINode();
  205. Instance* instance = instances[0];
  206. const COLLADAFW::UniqueId& uniqueId = instance->getInstanciatedObjectId();
  207. Object* object = getObjectByUniqueId(uniqueId);
  208. if ( object )
  209. {
  210. newImportNode->Reference(object);
  211. const String& objectName = getObjectNameByObject(object);
  212. if ( node->getName().empty() && !objectName.empty() )
  213. {
  214. #ifdef UNICODE
  215. WideString wideObjectName = COLLADABU::StringUtils::toWideString(objectName.c_str());
  216. newImportNode->SetName( wideObjectName.c_str() );
  217. #else
  218. newImportNode->SetName( objectName.c_str() );
  219. #endif
  220. }
  221. }
  222. else
  223. {
  224. newImportNode->Reference( getDummyObject() );
  225. }
  226. const COLLADAFW::UniqueId& instanceGeometryUniqueId = instance->getInstanciatedObjectId();
  227. // Store mapping between unique ids and nodes referencing the corresponding object.
  228. // Used to clone nodes
  229. addObjectINodeUniqueIdPair(newNode, instanceGeometryUniqueId);
  230. // Used to resolve instancing of objects
  231. addUniqueIdObjectINodePair(instanceGeometryUniqueId, newNode);
  232. parentINode->AttachChild(newNode, FALSE);
  233. // post process the creation
  234. if ( postProcess )
  235. (this->*postProcess)(newNode, instance);
  236. return newImportNode;
  237. }
  238. //------------------------------
  239. ImpNode* SceneGraphCreator::importInstanceGeometry( const COLLADAFW::Node* node, INode* parentINode )
  240. {
  241. return importInstance<COLLADAFW::InstanceGeometry, &COLLADAFW::Node::getInstanceGeometries, &SceneGraphCreator::storeMaterialBindings<COLLADAFW::COLLADA_TYPE::INSTANCE_GEOMETRY> >(node, parentINode);
  242. }
  243. //------------------------------
  244. ImpNode* SceneGraphCreator::importInstanceController( const COLLADAFW::Node* node, INode* parentINode )
  245. {
  246. return importInstance<COLLADAFW::InstanceController, &COLLADAFW::Node::getInstanceControllers, &SceneGraphCreator::postProcessInstanceController>(node, parentINode);
  247. }
  248. //------------------------------
  249. ImpNode* SceneGraphCreator::importInstanceCamera( const COLLADAFW::Node* node, INode* parentINode )
  250. {
  251. return importInstance<COLLADAFW::InstanceCamera, &COLLADAFW::Node::getInstanceCameras, 0>(node, parentINode);
  252. }
  253. //------------------------------
  254. ImpNode* SceneGraphCreator::importInstanceLight( const COLLADAFW::Node* node, INode* parentINode )
  255. {
  256. return importInstance<COLLADAFW::InstanceLight, &COLLADAFW::Node::getInstanceLights, 0>(node, parentINode);
  257. }
  258. //------------------------------
  259. bool SceneGraphCreator::importInstanceNodes( const COLLADAFW::InstanceNodePointerArray& instanceNodeArray, ImpNode* parentImportNode )
  260. {
  261. for ( size_t i = 0, count = instanceNodeArray.getCount(); i < count; ++i)
  262. {
  263. COLLADAFW::InstanceNode* instanceNode = instanceNodeArray[i];
  264. const COLLADAFW::UniqueId& uniqueId = instanceNode->getInstanciatedObjectId();
  265. INode* instanciatedINode = getINodeByUniqueId(uniqueId);
  266. // check if the referenced node is already in the max scene graph
  267. if ( instanciatedINode )
  268. {
  269. if ( !recursivelyCloneINode(parentImportNode, instanciatedINode) )
  270. return false;;
  271. }
  272. else
  273. {
  274. const COLLADAFW::Node* instanciatedFWNode = getFWNodeByUniqueId( uniqueId );
  275. // check if the referenced node is in one of the already received library nodes
  276. if ( instanciatedFWNode )
  277. {
  278. importNode( instanciatedFWNode, parentImportNode->GetINode() );
  279. }
  280. #if 0
  281. else
  282. {
  283. // If the referenced node has not been imported, store which node is referenced
  284. // to clone the nodes as the referenced nodes gets imported
  285. addUniqueIdReferencingImpNodePair(instanceNode->getInstanciatedObjectId(), parentImportNode );
  286. }
  287. #endif
  288. }
  289. }
  290. return true;
  291. }
  292. //------------------------------
  293. bool SceneGraphCreator::recursivelyCloneINode( ImpNode* parentImportNode, INode* nodeToClone )
  294. {
  295. ImpNode* newImportNode = getMaxImportInterface()->CreateNode();
  296. getMaxImportInterface()->AddNodeToScene(newImportNode);
  297. INode* newNode = newImportNode->GetINode();
  298. Object* object = nodeToClone->GetObjectRef();
  299. newImportNode->Reference(object);
  300. newNode->SetTMController(nodeToClone->GetTMController());
  301. newImportNode->SetName(nodeToClone->GetName());
  302. //used to assign material
  303. addClonedINodeOriginalINodePair(newNode, nodeToClone);
  304. INode* parentNode = parentImportNode->GetINode();
  305. parentNode->AttachChild(newNode, TRUE);
  306. /* If the node to clone references an object, the cloned one must references the same object.*/
  307. COLLADAFW::UniqueId id = getUniqueIdByObjectINode(nodeToClone);
  308. if ( id.isValid() )
  309. {
  310. addUniqueIdObjectINodePair(id, newNode);
  311. addObjectINodeUniqueIdPair(newNode, id);
  312. }
  313. // Clone the children
  314. for ( int i = 0, count = nodeToClone->NumberOfChildren(); i < count; ++i)
  315. recursivelyCloneINode(newImportNode, nodeToClone->GetChildNode(i));
  316. return true;
  317. }
  318. //------------------------------
  319. void SceneGraphCreator::postProcessInstanceController( INode* node, COLLADAFW::InstanceController* instanceController )
  320. {
  321. storeMaterialBindings<COLLADAFW::COLLADA_TYPE::INSTANCE_CONTROLLER>( node, instanceController );
  322. const COLLADAFW::UniqueId& controllerUniqueId = instanceController->getInstanciatedObjectId();
  323. const COLLADAFW::SkinController* skinController = getSkinControllerByUniqueId( controllerUniqueId );
  324. if ( skinController )
  325. {
  326. const COLLADAFW::UniqueId& skinSource = skinController->getSource();
  327. if ( skinSource.getClassId() == COLLADAFW::MorphController::ID() )
  328. {
  329. addMorphControllerINodePair( skinSource, node);
  330. }
  331. }
  332. }
  333. } // namespace COLLADAMax