PageRenderTime 27ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/Core/Dependencies/OgreCollada/FCollada/ColladaMaya/DaeDoc.cpp

https://bitbucket.org/barakianc/nvidia-physx-and-apex-in-gge
C++ | 459 lines | 328 code | 59 blank | 72 comment | 73 complexity | 0c4fab3a143b53086ba72ea54fd989bf MD5 | raw file
  1. /*
  2. Copyright (C) 2005-2007 Feeling Software Inc.
  3. Portions of the code are:
  4. Copyright (C) 2005-2007 Sony Computer Entertainment America
  5. Copyright (C) 2004-2005 Alias Systems Corp.
  6. MIT License: http://www.opensource.org/licenses/mit-license.php
  7. */
  8. #include "StdAfx.h"
  9. #include <time.h>
  10. #include <maya/MAnimControl.h>
  11. #include <maya/MAnimUtil.h>
  12. #include <maya/MEulerRotation.h>
  13. #include <maya/MFileIO.h>
  14. #include <maya/MFnCamera.h>
  15. #include <maya/MItDependencyNodes.h>
  16. #include <maya/MQuaternion.h>
  17. #include <maya/MSelectionList.h>
  18. #include <maya/MFnStringArrayData.h>
  19. #include "DaeDocNode.h"
  20. #include "DaeTransform.h"
  21. #include "DaeTranslator.h"
  22. #include "CExportOptions.h"
  23. #include "CReferenceManager.h"
  24. #include "DaeAnimClipLibrary.h"
  25. #include "MFnPluginNoEntry.h"
  26. #include "TranslatorHelpers/CAnimationHelper.h"
  27. #include "TranslatorHelpers/CShaderHelper.h"
  28. #include "TranslatorHelpers/CDagHelper.h"
  29. #include "TranslatorHelpers/HIAnimCache.h"
  30. #include "FCDocument/FCDocument.h"
  31. #include "FCDocument/FCDocumentTools.h"
  32. #include "FCDocument/FCDAsset.h"
  33. #include "FCDocument/FCDCamera.h"
  34. #include "FCDocument/FCDController.h"
  35. #include "FCDocument/FCDEmitter.h"
  36. #include "FCDocument/FCDForceField.h"
  37. #include "FCDocument/FCDGeometry.h"
  38. #include "FCDocument/FCDLight.h"
  39. #include "FCDocument/FCDSceneNode.h"
  40. #include "FCDocument/FCDPhysicsScene.h"
  41. #include "FUtils/FUFileManager.h"
  42. #ifdef _WIN32
  43. #pragma warning(disable: 4355)
  44. #endif
  45. // Constructor / Destructor
  46. DaeDoc::DaeDoc(DaeDocNode* _colladaNode, const MString& documentFilename, uint _logicalIndex)
  47. : animCache(NULL), ageiaPhysicsScene(NULL), animationLibrary(NULL), animClipLibrary(NULL), cameraLibrary(NULL)
  48. , controllerLibrary(NULL), emitterLibrary(NULL), forceFieldLibrary(NULL)
  49. , geometryLibrary(NULL), lightLibrary(NULL), materialLibrary(NULL), nativePhysicsScene(NULL), textureLibrary(NULL)
  50. , physicsMaterialLibrary(NULL), physicsModelLibrary(NULL)
  51. , physicsSceneLibrary(NULL), sceneGraph(NULL), uiUnitFactor(1.0f), isImport(true)
  52. , colladaNode(_colladaNode), filename(documentFilename), logicalIndex(_logicalIndex)
  53. {
  54. FCollada::SetDereferenceFlag(false);
  55. colladaDocument = FCollada::NewTopDocument();
  56. colladaDocument->SetFileUrl(MConvert::ToFChar(documentFilename));
  57. entityManager = new DaeEntityManager(this);
  58. }
  59. DaeDoc::~DaeDoc()
  60. {
  61. ReleaseLibraries(); // The libraries should already have been released
  62. SAFE_DELETE(entityManager);
  63. SAFE_DELETE(colladaDocument); // We want to release the document after the libraries, in case they point to FCollada objects.
  64. }
  65. // Create the parsing libraries: we want access to the libraries only during import/export time.
  66. void DaeDoc::CreateLibraries()
  67. {
  68. ReleaseLibraries();
  69. // Create the basic elements
  70. animCache = new CAnimCache(this);
  71. sceneGraph = new DaeSceneGraph(this);
  72. geometryLibrary = new DaeGeometryLibrary(this);
  73. controllerLibrary = new DaeControllerLibrary(this);
  74. animationLibrary = new DaeAnimationLibrary(this, isImport);
  75. materialLibrary = new DaeMaterialLibrary(this);
  76. textureLibrary = new DaeTextureLibrary(this);
  77. lightLibrary = new DaeLightLibrary(this);
  78. cameraLibrary = new DaeCameraLibrary(this);
  79. physicsMaterialLibrary = new DaePhysicsMaterialLibrary(this);
  80. physicsModelLibrary = new DaePhysicsModelLibrary(this);
  81. physicsSceneLibrary = new DaePhysicsSceneLibrary(this);
  82. nativePhysicsScene = new DaeNativePhysicsScene(this);
  83. ageiaPhysicsScene = new DaeAgeiaPhysicsScene(this);
  84. animClipLibrary = new DaeAnimClipLibrary(this);
  85. emitterLibrary = new DaeEmitterLibrary(this);
  86. forceFieldLibrary = new DaeForceFieldLibrary(this);
  87. }
  88. void DaeDoc::ReleaseLibraries()
  89. {
  90. SAFE_DELETE(animCache);
  91. SAFE_DELETE(geometryLibrary);
  92. SAFE_DELETE(controllerLibrary);
  93. SAFE_DELETE(animationLibrary);
  94. SAFE_DELETE(materialLibrary);
  95. SAFE_DELETE(textureLibrary);
  96. SAFE_DELETE(lightLibrary);
  97. SAFE_DELETE(cameraLibrary);
  98. SAFE_DELETE(physicsMaterialLibrary);
  99. SAFE_DELETE(physicsModelLibrary);
  100. SAFE_DELETE(physicsSceneLibrary);
  101. SAFE_DELETE(nativePhysicsScene);
  102. SAFE_DELETE(ageiaPhysicsScene);
  103. SAFE_DELETE(sceneGraph);
  104. SAFE_DELETE(animClipLibrary);
  105. SAFE_DELETE(emitterLibrary);
  106. SAFE_DELETE(forceFieldLibrary);
  107. }
  108. // Import a COLLADA document
  109. //
  110. void DaeDoc::Import(bool isCOLLADAReference)
  111. {
  112. // Create the import/export library helpers
  113. entityManager->Clear();
  114. isImport = true;
  115. CreateLibraries();
  116. // Parse in the COLLADA document
  117. FUErrorSimpleHandler* errorHandler = NULL;
  118. if (!isCOLLADAReference) errorHandler = new FUErrorSimpleHandler();
  119. FCollada::LoadDocumentFromFile(colladaDocument, MConvert::ToFChar(filename));
  120. if (errorHandler != NULL && !errorHandler->IsSuccessful())
  121. {
  122. MGlobal::displayInfo(errorHandler->GetErrorString());
  123. CImportOptions::SetErrorFlag();
  124. return;
  125. }
  126. // Read in the document asset information
  127. ImportAsset();
  128. // Import the DAG entity libraries
  129. materialLibrary->Import();
  130. cameraLibrary->Import();
  131. lightLibrary->Import();
  132. geometryLibrary->Import();
  133. controllerLibrary->Import();
  134. sceneGraph->Import();
  135. // Instantiate the main visual scene when importing/opening a document
  136. FCDSceneNode* visualScene = colladaDocument->GetVisualSceneInstance();
  137. if (!isCOLLADAReference && visualScene != NULL)
  138. {
  139. sceneGraph->InstantiateVisualScene(visualScene);
  140. // don't bother if no real physics... it will also show rigid bodies
  141. // from previous load if import create the solver.
  142. FCDPhysicsScene* pScene = colladaDocument->GetPhysicsSceneInstance();
  143. if (pScene && !pScene->GetPhysicsModelInstances().empty())
  144. {
  145. MObject nima = MFnPlugin::findPlugin("physx");
  146. if (nima != MObject::kNullObj)
  147. {
  148. physicsSceneLibrary->Import();
  149. sceneGraph->InstantiatePhysicsScene(pScene);
  150. }
  151. else
  152. {
  153. MGlobal::displayWarning("physX plugin not detected. Skipping Physics.");
  154. }
  155. }
  156. }
  157. // When everything is loaded and created, connect the driven key inputs
  158. animationLibrary->ConnectDrivers();
  159. // Since we are keeping all FCollada objects around: reduce the memory usage of
  160. // some well-known memory hogging objects.
  161. controllerLibrary->LeanMemory();
  162. geometryLibrary->LeanMemory();
  163. // Release the import/export library helpers
  164. ReleaseLibraries();
  165. colladaNode->ReleaseAllEntityNodes();
  166. SAFE_DELETE(errorHandler);
  167. }
  168. DaeEntity* DaeDoc::Import(FCDEntity* colladaEntity)
  169. {
  170. // Import whatever this is.
  171. DaeEntity* e = (DaeEntity*) colladaEntity->GetUserHandle();
  172. if (e != NULL) return e;
  173. if (colladaEntity->GetObjectType().Includes(FCDSceneNode::GetClassType()))
  174. {
  175. return sceneGraph->ImportNode((FCDSceneNode*) colladaEntity);
  176. }
  177. else if (colladaEntity->GetObjectType().Includes(FCDLight::GetClassType()))
  178. {
  179. return lightLibrary->ImportLight((FCDLight*) colladaEntity);
  180. }
  181. else if (colladaEntity->GetObjectType().Includes(FCDCamera::GetClassType()))
  182. {
  183. return cameraLibrary->ImportCamera((FCDCamera*) colladaEntity);
  184. }
  185. else if (colladaEntity->GetObjectType().Includes(FCDGeometry::GetClassType()))
  186. {
  187. return geometryLibrary->ImportGeometry((FCDGeometry*) colladaEntity);
  188. }
  189. else if (colladaEntity->GetObjectType().Includes(FCDController::GetClassType()))
  190. {
  191. return controllerLibrary->ImportController((FCDController*) colladaEntity);
  192. }
  193. return NULL;
  194. }
  195. void DaeDoc::ImportAsset()
  196. {
  197. // Up_axis
  198. if (MGlobal::mayaState() != MGlobal::kBatch)
  199. {
  200. if (CImportOptions::IsOpenMode() && CImportOptions::ImportUpAxis())
  201. {
  202. fchar upAxis = 'y';
  203. const FMVector3& colladaUpAxis = colladaDocument->GetAsset()->GetUpAxis();
  204. if (IsEquivalent(colladaUpAxis, FMVector3::YAxis)) upAxis = 'y';
  205. else if (IsEquivalent(colladaUpAxis, FMVector3::ZAxis)) upAxis = 'z';
  206. else if (IsEquivalent(colladaUpAxis, FMVector3::XAxis)) MGlobal::displayWarning("An up_axis of 'X' is not supported by Maya.");
  207. else MGlobal::displayWarning("Unknown up_axis value.");
  208. // Use the MEL commands to set the up_axis. Currently resets the view, if the axis must change..
  209. FUStringBuilder command(FC("string $currentAxis = `upAxis -q -ax`; if ($currentAxis != \""));
  210. command.append(upAxis); command.append(FC("\") { upAxis -ax \"")); command.append(upAxis);
  211. command.append(FC("\"; viewSet -home persp; }"));
  212. MGlobal::executeCommand(command.ToCharPtr());
  213. }
  214. }
  215. // Retrieve Maya's current up-axis.
  216. MString result;
  217. FMVector3 mayaUpAxis = FMVector3::Zero;
  218. if (CImportOptions::ImportUpAxis())
  219. {
  220. mayaUpAxis = FMVector3::YAxis;
  221. MGlobal::executeCommand(FC("upAxis -q -ax;"), result, false, false);
  222. if (IsEquivalent(MConvert::ToFChar(result), FC("z"))) mayaUpAxis = FMVector3::ZAxis;
  223. }
  224. float mayaUnit = 0.0f;
  225. if (CImportOptions::ImportUnits()) mayaUnit = 0.01f;
  226. // Standardize the COLLADA document on this up-axis and units (centimeters).
  227. FCDocumentTools::StandardizeUpAxisAndLength(colladaDocument, mayaUpAxis, mayaUnit);
  228. // Get the UI unit factor, for parts of Maya that don't handle variable lengths correctly
  229. MDistance testDistance(1.0f, MDistance::uiUnit());
  230. uiUnitFactor = (float) testDistance.as(MDistance::kCentimeters);
  231. }
  232. void DaeDoc::Export(bool selectionOnly)
  233. {
  234. // Create the import/export library helpers.
  235. isImport = false;
  236. CreateLibraries();
  237. // Get the UI unit type (internal units are centimeter)
  238. MDistance testDistance(1.0f, MDistance::uiUnit());
  239. float conversionFactor = (float) testDistance.as(MDistance::kMeters);
  240. uiUnitFactor = 1.0f / conversionFactor;
  241. // Export the document asset information.
  242. ExportAsset();
  243. // Export all the non-XRef materials
  244. if (!selectionOnly) GetMaterialLibrary()->Export();
  245. // Find all the nodes to export, and recurse through the scene to export.
  246. sceneGraph->FindForcedNodes(selectionOnly);
  247. sceneGraph->Export(selectionOnly);
  248. // Export rigid constraints if required.
  249. if (CExportOptions::ExportPhysics())
  250. {
  251. // save non physics animation library in case want to use again
  252. DaeAnimationLibrary* nonPhysAnimationLibrary = animationLibrary;
  253. animationLibrary = new DaeAnimationLibrary(this, false);
  254. nativePhysicsScene->finalize();
  255. ageiaPhysicsScene->finalize();
  256. // animationLibrary->ExportAnimations();
  257. SAFE_DELETE(animationLibrary);
  258. animationLibrary = nonPhysAnimationLibrary;
  259. }
  260. // Retrieve the unit name and set the asset's unit information
  261. MString unitName;
  262. MGlobal::executeCommand("currentUnit -q -linear -fullName;", unitName);
  263. colladaDocument->GetAsset()->SetUnitName(MConvert::ToFChar(unitName));
  264. FCDocumentTools::StandardizeUpAxisAndLength(colladaDocument, FMVector3::Origin, conversionFactor);
  265. // Write out the FCollada document.
  266. colladaDocument->GetFileManager()->SetForceAbsoluteFlag(!CExportOptions::RelativePaths());
  267. FCollada::SaveDocument(colladaDocument, MConvert::ToFChar(filename));
  268. // Release the import/export library helpers
  269. ReleaseLibraries();
  270. colladaNode->ReleaseAllEntityNodes();
  271. }
  272. void DaeDoc::ExportAsset()
  273. {
  274. FCDAsset* asset = colladaDocument->GetAsset();
  275. // Clone any previous document's asset.
  276. if (GetCOLLADANode()->GetDocumentCount() > 0)
  277. {
  278. DaeDoc* previousDocument = GetCOLLADANode()->GetDocument(0);
  279. if (previousDocument != NULL && previousDocument->GetCOLLADADocument() != NULL)
  280. {
  281. previousDocument->GetCOLLADADocument()->GetAsset()->Clone(asset);
  282. }
  283. }
  284. FCDAssetContributor* contributor = asset->AddContributor();
  285. const char* userName = getenv("USER");
  286. if (userName == NULL) userName = getenv("USERNAME");
  287. if (userName != NULL) contributor->SetAuthor(TO_FSTRING(userName));
  288. FUStringBuilder authoringTool(FC("Maya"));
  289. authoringTool.append(MConvert::ToFChar(MGlobal::mayaVersion()));
  290. authoringTool.append(FC(" | ColladaMaya v"));
  291. uint32 version = FCOLLADA_VERSION & 0x0000FFFF;
  292. authoringTool.append(FCOLLADA_VERSION >> 16); authoringTool.append((fchar) '.');
  293. authoringTool.append(version / 10); authoringTool.append(version % 10);
  294. authoringTool.append(TO_FSTRING(FCOLLADA_BUILDSTR));
  295. contributor->SetAuthoringTool(authoringTool.ToCharPtr());
  296. // comments
  297. MString optstr = MString("ColladaMaya export options: bakeTransforms=") + CExportOptions::BakeTransforms()
  298. + ";exportPolygonMeshes=" + CExportOptions::ExportPolygonMeshes() + ";bakeLighting=" + CExportOptions::BakeLighting()
  299. + ";isSampling=" + CExportOptions::IsSampling() + ";\ncurveConstrainSampling=" + CExportOptions::CurveConstrainSampling()
  300. + ";removeStaticCurves=" + CExportOptions::RemoveStaticCurves() + ";exportCameraAsLookat=" + CExportOptions::ExportCameraAsLookat()
  301. + ";\nexportLights=" + CExportOptions::ExportLights() + ";exportCameras=" + CExportOptions::ExportCameras()
  302. + ";exportJointsAndSkin=" + CExportOptions::ExportJointsAndSkin() + ";\nexportAnimations=" + CExportOptions::ExportAnimations()
  303. + ";exportTriangles=" + CExportOptions::ExportTriangles() + ";exportInvisibleNodes=" + CExportOptions::ExportInvisibleNodes()
  304. + ";\nexportNormals=" + CExportOptions::ExportNormals() + ";exportTexCoords=" + CExportOptions::ExportTexCoords()
  305. + ";\nexportVertexColors=" + CExportOptions::ExportVertexColors()
  306. + ";exportVertexColorsAnimation=" + CExportOptions::ExportVertexColorAnimations()
  307. + ";exportTangents=" + CExportOptions::ExportTangents()
  308. + ";\nexportTexTangents=" + CExportOptions::ExportTexTangents() + ";exportConstraints=" + CExportOptions::ExportConstraints()
  309. + ";exportPhysics=" + CExportOptions::ExportPhysics() + ";exportXRefs=" + CExportOptions::ExportXRefs()
  310. + ";\ndereferenceXRefs=" + CExportOptions::DereferenceXRefs() + ";cameraXFov=" + CExportOptions::CameraXFov()
  311. + ";cameraYFov=" + CExportOptions::CameraYFov();
  312. contributor->SetComments(MConvert::ToFChar(optstr));
  313. // source is the scene we have exported from
  314. MString currentScene = MFileIO::currentFile();
  315. if (currentScene.length() != 0)
  316. {
  317. // Intentionally not relative
  318. FUUri uri(colladaDocument->GetFileManager()->GetCurrentUri().MakeAbsolute(MConvert::ToFChar(currentScene)));
  319. fstring sourceDocumentPath = uri.GetAbsolutePath();
  320. contributor->SetSourceData(sourceDocumentPath);
  321. }
  322. // Leave this as centimeters, it will be modified later.
  323. asset->SetUnitConversionFactor(0.01f);
  324. // Up axis
  325. if (MGlobal::isYAxisUp()) asset->SetUpAxis(FMVector3::YAxis);
  326. else if (MGlobal::isZAxisUp()) asset->SetUpAxis(FMVector3::ZAxis);
  327. }
  328. // Replace characters that are supported in Maya,
  329. // but not supported in collada names
  330. MString DaeDoc::MayaNameToColladaName(const MString& str, bool removeNamespace)
  331. {
  332. // NathanM: Strip off namespace prefixes
  333. // TODO: Should really be exposed as an option in the Exporter
  334. MString mayaName;
  335. if (removeNamespace)
  336. {
  337. int prefixIndex = str.rindex(':');
  338. mayaName = (prefixIndex < 0) ? str : str.substring(prefixIndex + 1, str.length());
  339. }
  340. else mayaName = str;
  341. uint length = mayaName.length();
  342. FUStringBuilder builder;
  343. builder.reserve(length);
  344. const fchar* c = MConvert::ToFChar(mayaName);
  345. // Replace offending characters by some
  346. // that are supported within xml:
  347. // ':', '|' are replaced by '_'.
  348. // [claforte] Ideally, these should be encoded
  349. // as '%3A' for ':', etc. and decoded at import time.
  350. //
  351. for (uint i = 0; i < length; i++)
  352. {
  353. fchar d = c[i];
  354. if (d == '|' || d == ':' || d == '/' || d == '\\' || d == '(' || d == ')' || d == '[' || d == ']')
  355. d = '_';
  356. builder.append(d);
  357. }
  358. return builder.ToCharPtr();
  359. }
  360. //
  361. // Make an unique COLLADA Id from a dagPath
  362. // We are free to use anything we want for Ids. For now use
  363. // a honking unique name for readability - but in future we
  364. // could just use an incrementing integer
  365. //
  366. MString DaeDoc::DagPathToColladaId(const MDagPath& dagPath)
  367. {
  368. return MayaNameToColladaName(dagPath.partialPathName(), false);
  369. }
  370. //
  371. // Get a COLLADA suitable node name from a DAG path
  372. // For import/export symmetry, this should be exactly the
  373. // Maya node name. If we include any more of the path, we'll
  374. // get viral node names after repeated import/export.
  375. //
  376. MString DaeDoc::DagPathToColladaName(const MDagPath& dagPath)
  377. {
  378. MFnDependencyNode node(dagPath.node());
  379. return MayaNameToColladaName(node.name(), true);
  380. }
  381. //
  382. // Make a COLLADA name suitable for a DAG name
  383. //
  384. MString DaeDoc::ColladaNameToDagName(const MString& dagPath)
  385. {
  386. int length = dagPath.length();
  387. char* tmp = new char[length + 1];
  388. const char* c = dagPath.asChar();
  389. for (int i = 0; i <= length; i++)
  390. {
  391. if ((tmp[i] = c[i]) == '.')
  392. {
  393. tmp[i] = '_';
  394. }
  395. }
  396. MString rv(tmp, length);
  397. SAFE_DELETE_ARRAY(tmp);
  398. return rv;
  399. }