colladaImport.cpp
Engine/source/ts/collada/colladaImport.cpp
Classes:
class
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