Torque3D Documentation / _generateds / colladaImport.cpp

colladaImport.cpp

Engine/source/ts/collada/colladaImport.cpp

More...

Classes:

Public Functions

DefineEngineFunction(enumColladaForImport , bool , (const char *shapePath, const char *ctrl, bool loadCachedDts) , ("", "", true) , "(string shapePath, <a href="/coding/class/classguitreeviewctrl/">GuiTreeViewCtrl</a> ctrl) Collect scene information from " "<a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> COLLADA <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> and store it in <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> GuiTreeView control. This function is " "used by the COLLADA import gui <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> show <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> preview of the scene contents " "prior <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> import, and is probably not much use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> anything <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">else.\n</a>" " @param shapePath COLLADA <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">filename\n</a>" " @param ctrl GuiTreeView <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> add elements <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">to\n</a>" " @param loadCachedDts dictates <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> it should try and load the cached dts <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> it exists" " @return true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> successful, false <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">otherwise\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Editors\n</a>" " @internal" )
processNode(GuiTreeViewCtrl * tree, domNode * node, S32 parentID, SceneStats & stats)

Detailed Description

Public Functions

DefineEngineFunction(enumColladaForImport , bool , (const char *shapePath, const char *ctrl, bool loadCachedDts) , ("", "", true) , "(string shapePath, <a href="/coding/class/classguitreeviewctrl/">GuiTreeViewCtrl</a> ctrl) Collect scene information from " "<a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> COLLADA <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> and store it in <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> GuiTreeView control. This function is " "used by the COLLADA import gui <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> show <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> preview of the scene contents " "prior <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> import, and is probably not much use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> anything <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">else.\n</a>" " @param shapePath COLLADA <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">filename\n</a>" " @param ctrl GuiTreeView <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> add elements <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">to\n</a>" " @param loadCachedDts dictates <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> it should try and load the cached dts <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> it exists" " @return true <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> successful, false <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">otherwise\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Editors\n</a>" " @internal" )

processNode(GuiTreeViewCtrl * tree, domNode * node, S32 parentID, SceneStats & stats)

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#include "platform/platform.h"
 25
 26#include "console/engineAPI.h"
 27#include "core/volume.h"
 28#include "ts/collada/colladaUtils.h"
 29#include "ts/collada/colladaAppNode.h"
 30#include "ts/collada/colladaShapeLoader.h"
 31
 32#include "gui/controls/guiTreeViewCtrl.h"
 33
 34// Helper struct for counting nodes, meshes and polygons down through the scene
 35// hierarchy
 36struct SceneStats
 37{
 38   S32 numNodes;
 39   S32 numMeshes;
 40   S32 numPolygons;
 41   S32 numMaterials;
 42   S32 numLights;
 43   S32 numClips;
 44
 45   SceneStats() : numNodes(0), numMeshes(0), numPolygons(0), numMaterials(0), numLights(0), numClips(0) { }
 46};
 47
 48// Recurse through the <visual_scene> adding nodes and geometry to the GuiTreeView control
 49static void processNode(GuiTreeViewCtrl* tree, domNode* node, S32 parentID, SceneStats& stats)
 50{
 51   stats.numNodes++;
 52   S32 nodeID = tree->insertItem(parentID, _GetNameOrId(node), "node", "", 0, 0);
 53
 54   // Update mesh and poly counts
 55   for (S32 i = 0; i < node->getContents().getCount(); i++)
 56   {
 57      domGeometry* geom = 0;
 58      const char* elemName = "";
 59
 60      daeElement* child = node->getContents()[i];
 61      switch (child->getElementType())
 62      {
 63         case COLLADA_TYPE::INSTANCE_GEOMETRY:
 64         {
 65            domInstance_geometry* instgeom = daeSafeCast<domInstance_geometry>(child);
 66            if (instgeom)
 67            {
 68               geom = daeSafeCast<domGeometry>(instgeom->getUrl().getElement());
 69               elemName = _GetNameOrId(geom);
 70            }
 71            break;
 72         }
 73
 74         case COLLADA_TYPE::INSTANCE_CONTROLLER:
 75         {
 76            domInstance_controller* instctrl = daeSafeCast<domInstance_controller>(child);
 77            if (instctrl)
 78            {
 79               domController* ctrl = daeSafeCast<domController>(instctrl->getUrl().getElement());
 80               elemName = _GetNameOrId(ctrl);
 81               if (ctrl && ctrl->getSkin())
 82                  geom = daeSafeCast<domGeometry>(ctrl->getSkin()->getSource().getElement());
 83               else if (ctrl && ctrl->getMorph())
 84                  geom = daeSafeCast<domGeometry>(ctrl->getMorph()->getSource().getElement());
 85            }
 86            break;
 87         }
 88
 89         case COLLADA_TYPE::INSTANCE_LIGHT:
 90            stats.numLights++;
 91            tree->insertItem(nodeID, _GetNameOrId(node), "light", "", 0, 0);
 92            break;
 93      }
 94
 95      if (geom && geom->getMesh())
 96      {
 97         const char* name = _GetNameOrId(node);
 98         if ( dStrEqual( name, "null" ) || dStrEndsWith( name, "PIVOT" ) )
 99            name = _GetNameOrId( daeSafeCast<domNode>(node->getParent()) );
100
101         stats.numMeshes++;
102         tree->insertItem(nodeID, name, "mesh", "", 0, 0);
103
104         for (S32 j = 0; j < geom->getMesh()->getTriangles_array().getCount(); j++)
105            stats.numPolygons += geom->getMesh()->getTriangles_array()[j]->getCount();
106         for (S32 j = 0; j < geom->getMesh()->getTristrips_array().getCount(); j++)
107            stats.numPolygons += geom->getMesh()->getTristrips_array()[j]->getCount();
108         for (S32 j = 0; j < geom->getMesh()->getTrifans_array().getCount(); j++)
109            stats.numPolygons += geom->getMesh()->getTrifans_array()[j]->getCount();
110         for (S32 j = 0; j < geom->getMesh()->getPolygons_array().getCount(); j++)
111            stats.numPolygons += geom->getMesh()->getPolygons_array()[j]->getCount();
112         for (S32 j = 0; j < geom->getMesh()->getPolylist_array().getCount(); j++)
113            stats.numPolygons += geom->getMesh()->getPolylist_array()[j]->getCount();
114      }
115   }
116
117   // Recurse into child nodes
118   for (S32 i = 0; i < node->getNode_array().getCount(); i++)
119      processNode(tree, node->getNode_array()[i], nodeID, stats);
120
121   for (S32 i = 0; i < node->getInstance_node_array().getCount(); i++)
122   {
123      domInstance_node* instnode = node->getInstance_node_array()[i];
124      domNode* dNode = daeSafeCast<domNode>(instnode->getUrl().getElement());
125      if (dNode)
126         processNode(tree, dNode, nodeID, stats);
127   }
128}
129
130DefineEngineFunction( enumColladaForImport, bool, (const char * shapePath, const char * ctrl, bool loadCachedDts), ("", "", true),
131   "(string shapePath, GuiTreeViewCtrl ctrl) Collect scene information from "
132   "a COLLADA file and store it in a GuiTreeView control. This function is "
133   "used by the COLLADA import gui to show a preview of the scene contents "
134   "prior to import, and is probably not much use for anything else.\n"
135   "@param shapePath COLLADA filename\n"
136   "@param ctrl GuiTreeView control to add elements to\n"
137   "@param loadCachedDts dictates if it should try and load the cached dts file if it exists"
138   "@return true if successful, false otherwise\n"
139   "@ingroup Editors\n"
140   "@internal")
141{
142   GuiTreeViewCtrl* tree;
143   if (!Sim::findObject(ctrl, tree))
144   {
145      Con::errorf("enumColladaScene::Could not find GuiTreeViewCtrl '%s'", ctrl);
146      return false;
147   }
148
149   // Check if a cached DTS is available => no need to import the collada file
150   // if we can load the DTS instead
151   Torque::Path path(shapePath);
152   if (loadCachedDts && ColladaShapeLoader::canLoadCachedDTS(path))
153      return false;
154
155   // Check if this is a Sketchup file (.kmz) and if so, mount the zip filesystem
156   // and get the path to the DAE file.
157   String mountPoint;
158   Torque::Path daePath;
159   bool isSketchup = ColladaShapeLoader::checkAndMountSketchup(path, mountPoint, daePath);
160
161   // Load the Collada file into memory
162   domCOLLADA* root = ColladaShapeLoader::getDomCOLLADA(daePath);
163   if (!root)
164   {
165      TSShapeLoader::updateProgress(TSShapeLoader::Load_Complete, "Load complete");
166      return false;
167   }
168
169   if (isSketchup)
170   {
171      // Unmount the zip if we mounted it
172      Torque::FS::Unmount(mountPoint);
173   }
174
175   // Initialize tree
176   tree->removeItem(0);
177   S32 nodesID = tree->insertItem(0, "Shape", "", "", 0, 0);
178   S32 matsID = tree->insertItem(0, "Materials", "", "", 0, 0);
179   S32 animsID = tree->insertItem(0, "Animations", "", "", 0, 0);
180
181   SceneStats stats;
182
183   // Query DOM for shape summary details
184   for (S32 i = 0; i < root->getLibrary_visual_scenes_array().getCount(); i++)
185   {
186      const domLibrary_visual_scenes* libScenes = root->getLibrary_visual_scenes_array()[i];
187      for (S32 j = 0; j < libScenes->getVisual_scene_array().getCount(); j++)
188      {
189         const domVisual_scene* visualScene = libScenes->getVisual_scene_array()[j];
190         for (S32 k = 0; k < visualScene->getNode_array().getCount(); k++)
191            processNode(tree, visualScene->getNode_array()[k], nodesID, stats);
192      }
193   }
194
195   // Get material count
196   for (S32 i = 0; i < root->getLibrary_materials_array().getCount(); i++)
197   {
198      const domLibrary_materials* libraryMats = root->getLibrary_materials_array()[i];
199      stats.numMaterials += libraryMats->getMaterial_array().getCount();
200      for (S32 j = 0; j < libraryMats->getMaterial_array().getCount(); j++)
201      {
202         domMaterial* mat = libraryMats->getMaterial_array()[j];
203         tree->insertItem(matsID, _GetNameOrId(mat), "", "", 0, 0);
204      }
205   }
206
207   // Get images count
208   for (S32 i = 0; i < root->getLibrary_images_array().getCount(); i++)
209   {
210      const domLibrary_images* libraryImages = root->getLibrary_images_array()[i];
211
212      for (S32 j = 0; j < libraryImages->getImage_array().getCount(); j++)
213      {
214         domImage* img = libraryImages->getImage_array()[j];
215
216         S32 materialID = tree->findItemByName(_GetNameOrId(img));
217
218         if (materialID == 0)
219            continue;
220
221         tree->setItemValue(materialID, img->getInit_from()->getValue().str().c_str());
222      }
223   }
224
225   // Get animation count
226   for (S32 i = 0; i < root->getLibrary_animation_clips_array().getCount(); i++)
227   {
228      const domLibrary_animation_clips* libraryClips = root->getLibrary_animation_clips_array()[i];
229      stats.numClips += libraryClips->getAnimation_clip_array().getCount();
230      for (S32 j = 0; j < libraryClips->getAnimation_clip_array().getCount(); j++)
231      {
232         domAnimation_clip* clip = libraryClips->getAnimation_clip_array()[j];
233         tree->insertItem(animsID, _GetNameOrId(clip), "animation", "", 0, 0);
234      }
235   }
236   if (stats.numClips == 0)
237   {
238      // No clips => check if there are any animations (these will be added to a default clip)
239      for (S32 i = 0; i < root->getLibrary_animations_array().getCount(); i++)
240      {
241         const domLibrary_animations* libraryAnims = root->getLibrary_animations_array()[i];
242         if (libraryAnims->getAnimation_array().getCount())
243         {
244            stats.numClips = 1;
245            tree->insertItem(animsID, "ambient", "animation", "", 0, 0);
246            break;
247         }
248      }
249   }
250
251   // Extract the global scale and up_axis from the top level <asset> element,
252   F32 unit = 1.0f;
253   domUpAxisType upAxis = UPAXISTYPE_Z_UP;
254   if (root->getAsset()) {
255      if (root->getAsset()->getUnit())
256         unit = root->getAsset()->getUnit()->getMeter();
257      if (root->getAsset()->getUp_axis())
258         upAxis = root->getAsset()->getUp_axis()->getValue();
259   }
260
261   TSShapeLoader::updateProgress(TSShapeLoader::Load_Complete, "Load complete");
262
263   // Store shape information in the tree control
264   tree->setDataField(StringTable->insert("_nodeCount"), 0, avar("%d", stats.numNodes));
265   tree->setDataField(StringTable->insert("_meshCount"), 0, avar("%d", stats.numMeshes));
266   tree->setDataField(StringTable->insert("_polygonCount"), 0, avar("%d", stats.numPolygons));
267   tree->setDataField(StringTable->insert("_materialCount"), 0, avar("%d", stats.numMaterials));
268   tree->setDataField(StringTable->insert("_lightCount"), 0, avar("%d", stats.numLights));
269   tree->setDataField(StringTable->insert("_animCount"), 0, avar("%d", stats.numClips));
270   tree->setDataField(StringTable->insert("_unit"), 0, avar("%g", unit));
271
272   if (upAxis == UPAXISTYPE_X_UP)
273      tree->setDataField(StringTable->insert("_upAxis"), 0, "X_AXIS");
274   else if (upAxis == UPAXISTYPE_Y_UP)
275      tree->setDataField(StringTable->insert("_upAxis"), 0, "Y_AXIS");
276   else
277      tree->setDataField(StringTable->insert("_upAxis"), 0, "Z_AXIS");
278
279   char shapesStr[16];
280   dSprintf(shapesStr, 16, "%i", stats.numMeshes);
281   char materialsStr[16];
282   dSprintf(materialsStr, 16, "%i", stats.numMaterials);
283   char animationsStr[16];
284   dSprintf(animationsStr, 16, "%i", stats.numClips);
285
286   tree->setItemValue(nodesID, StringTable->insert(shapesStr));
287   tree->setItemValue(matsID, StringTable->insert(materialsStr));
288   tree->setItemValue(animsID, StringTable->insert(animationsStr));
289
290   return true;
291}
292