123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2012 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #include "platform/platform.h"
- #include "console/engineAPI.h"
- #include "core/volume.h"
- #include "ts/collada/colladaUtils.h"
- #include "ts/collada/colladaAppNode.h"
- #include "ts/collada/colladaShapeLoader.h"
- #include "gui/controls/guiTreeViewCtrl.h"
- // Helper struct for counting nodes, meshes and polygons down through the scene
- // hierarchy
- struct SceneStats
- {
- S32 numNodes;
- S32 numMeshes;
- S32 numPolygons;
- S32 numMaterials;
- S32 numLights;
- S32 numClips;
- SceneStats() : numNodes(0), numMeshes(0), numPolygons(0), numMaterials(0), numLights(0), numClips(0) { }
- };
- // Recurse through the <visual_scene> adding nodes and geometry to the GuiTreeView control
- static void processNode(GuiTreeViewCtrl* tree, domNode* node, S32 parentID, SceneStats& stats)
- {
- stats.numNodes++;
- S32 nodeID = tree->insertItem(parentID, _GetNameOrId(node), "node", "", 0, 0);
- // Update mesh and poly counts
- for (S32 i = 0; i < node->getContents().getCount(); i++)
- {
- domGeometry* geom = 0;
- const char* elemName = "";
- daeElement* child = node->getContents()[i];
- switch (child->getElementType())
- {
- case COLLADA_TYPE::INSTANCE_GEOMETRY:
- {
- domInstance_geometry* instgeom = daeSafeCast<domInstance_geometry>(child);
- if (instgeom)
- {
- geom = daeSafeCast<domGeometry>(instgeom->getUrl().getElement());
- elemName = _GetNameOrId(geom);
- }
- break;
- }
- case COLLADA_TYPE::INSTANCE_CONTROLLER:
- {
- domInstance_controller* instctrl = daeSafeCast<domInstance_controller>(child);
- if (instctrl)
- {
- domController* ctrl = daeSafeCast<domController>(instctrl->getUrl().getElement());
- elemName = _GetNameOrId(ctrl);
- if (ctrl && ctrl->getSkin())
- geom = daeSafeCast<domGeometry>(ctrl->getSkin()->getSource().getElement());
- else if (ctrl && ctrl->getMorph())
- geom = daeSafeCast<domGeometry>(ctrl->getMorph()->getSource().getElement());
- }
- break;
- }
- case COLLADA_TYPE::INSTANCE_LIGHT:
- stats.numLights++;
- tree->insertItem(nodeID, _GetNameOrId(node), "light", "", 0, 0);
- break;
- }
- if (geom && geom->getMesh())
- {
- const char* name = _GetNameOrId(node);
- if ( dStrEqual( name, "null" ) || dStrEndsWith( name, "PIVOT" ) )
- name = _GetNameOrId( daeSafeCast<domNode>(node->getParent()) );
- stats.numMeshes++;
- tree->insertItem(nodeID, name, "mesh", "", 0, 0);
- for (S32 j = 0; j < geom->getMesh()->getTriangles_array().getCount(); j++)
- stats.numPolygons += geom->getMesh()->getTriangles_array()[j]->getCount();
- for (S32 j = 0; j < geom->getMesh()->getTristrips_array().getCount(); j++)
- stats.numPolygons += geom->getMesh()->getTristrips_array()[j]->getCount();
- for (S32 j = 0; j < geom->getMesh()->getTrifans_array().getCount(); j++)
- stats.numPolygons += geom->getMesh()->getTrifans_array()[j]->getCount();
- for (S32 j = 0; j < geom->getMesh()->getPolygons_array().getCount(); j++)
- stats.numPolygons += geom->getMesh()->getPolygons_array()[j]->getCount();
- for (S32 j = 0; j < geom->getMesh()->getPolylist_array().getCount(); j++)
- stats.numPolygons += geom->getMesh()->getPolylist_array()[j]->getCount();
- }
- }
- // Recurse into child nodes
- for (S32 i = 0; i < node->getNode_array().getCount(); i++)
- processNode(tree, node->getNode_array()[i], nodeID, stats);
- for (S32 i = 0; i < node->getInstance_node_array().getCount(); i++)
- {
- domInstance_node* instnode = node->getInstance_node_array()[i];
- domNode* dNode = daeSafeCast<domNode>(instnode->getUrl().getElement());
- if (dNode)
- processNode(tree, dNode, nodeID, stats);
- }
- }
- DefineEngineFunction( enumColladaForImport, bool, (const char * shapePath, const char * ctrl, bool loadCachedDts), ("", "", true),
- "(string shapePath, GuiTreeViewCtrl ctrl) Collect scene information from "
- "a COLLADA file and store it in a GuiTreeView control. This function is "
- "used by the COLLADA import gui to show a preview of the scene contents "
- "prior to import, and is probably not much use for anything else.\n"
- "@param shapePath COLLADA filename\n"
- "@param ctrl GuiTreeView control to add elements to\n"
- "@param loadCachedDts dictates if it should try and load the cached dts file if it exists"
- "@return true if successful, false otherwise\n"
- "@ingroup Editors\n"
- "@internal")
- {
- GuiTreeViewCtrl* tree;
- if (!Sim::findObject(ctrl, tree))
- {
- Con::errorf("enumColladaScene::Could not find GuiTreeViewCtrl '%s'", ctrl);
- return false;
- }
- // Check if a cached DTS is available => no need to import the collada file
- // if we can load the DTS instead
- Torque::Path path(shapePath);
- if (loadCachedDts && ColladaShapeLoader::canLoadCachedDTS(path))
- return false;
- // Check if this is a Sketchup file (.kmz) and if so, mount the zip filesystem
- // and get the path to the DAE file.
- String mountPoint;
- Torque::Path daePath;
- bool isSketchup = ColladaShapeLoader::checkAndMountSketchup(path, mountPoint, daePath);
- // Load the Collada file into memory
- domCOLLADA* root = ColladaShapeLoader::getDomCOLLADA(daePath);
- if (!root)
- {
- TSShapeLoader::updateProgress(TSShapeLoader::Load_Complete, "Load complete");
- return false;
- }
- if (isSketchup)
- {
- // Unmount the zip if we mounted it
- Torque::FS::Unmount(mountPoint);
- }
- // Initialize tree
- tree->removeItem(0);
- S32 nodesID = tree->insertItem(0, "Shape", "", "", 0, 0);
- S32 matsID = tree->insertItem(0, "Materials", "", "", 0, 0);
- S32 animsID = tree->insertItem(0, "Animations", "", "", 0, 0);
- SceneStats stats;
- // Query DOM for shape summary details
- for (S32 i = 0; i < root->getLibrary_visual_scenes_array().getCount(); i++)
- {
- const domLibrary_visual_scenes* libScenes = root->getLibrary_visual_scenes_array()[i];
- for (S32 j = 0; j < libScenes->getVisual_scene_array().getCount(); j++)
- {
- const domVisual_scene* visualScene = libScenes->getVisual_scene_array()[j];
- for (S32 k = 0; k < visualScene->getNode_array().getCount(); k++)
- processNode(tree, visualScene->getNode_array()[k], nodesID, stats);
- }
- }
- // Get material count
- for (S32 i = 0; i < root->getLibrary_materials_array().getCount(); i++)
- {
- const domLibrary_materials* libraryMats = root->getLibrary_materials_array()[i];
- stats.numMaterials += libraryMats->getMaterial_array().getCount();
- for (S32 j = 0; j < libraryMats->getMaterial_array().getCount(); j++)
- {
- domMaterial* mat = libraryMats->getMaterial_array()[j];
- tree->insertItem(matsID, _GetNameOrId(mat), "", "", 0, 0);
- }
- }
- // Get images count
- for (S32 i = 0; i < root->getLibrary_images_array().getCount(); i++)
- {
- const domLibrary_images* libraryImages = root->getLibrary_images_array()[i];
- for (S32 j = 0; j < libraryImages->getImage_array().getCount(); j++)
- {
- domImage* img = libraryImages->getImage_array()[j];
- S32 materialID = tree->findItemByName(_GetNameOrId(img));
- if (materialID == 0)
- continue;
- tree->setItemValue(materialID, img->getInit_from()->getValue().str().c_str());
- }
- }
- // Get animation count
- for (S32 i = 0; i < root->getLibrary_animation_clips_array().getCount(); i++)
- {
- const domLibrary_animation_clips* libraryClips = root->getLibrary_animation_clips_array()[i];
- stats.numClips += libraryClips->getAnimation_clip_array().getCount();
- for (S32 j = 0; j < libraryClips->getAnimation_clip_array().getCount(); j++)
- {
- domAnimation_clip* clip = libraryClips->getAnimation_clip_array()[j];
- tree->insertItem(animsID, _GetNameOrId(clip), "animation", "", 0, 0);
- }
- }
- if (stats.numClips == 0)
- {
- // No clips => check if there are any animations (these will be added to a default clip)
- for (S32 i = 0; i < root->getLibrary_animations_array().getCount(); i++)
- {
- const domLibrary_animations* libraryAnims = root->getLibrary_animations_array()[i];
- if (libraryAnims->getAnimation_array().getCount())
- {
- stats.numClips = 1;
- tree->insertItem(animsID, "ambient", "animation", "", 0, 0);
- break;
- }
- }
- }
- // Extract the global scale and up_axis from the top level <asset> element,
- F32 unit = 1.0f;
- domUpAxisType upAxis = UPAXISTYPE_Z_UP;
- if (root->getAsset()) {
- if (root->getAsset()->getUnit())
- unit = root->getAsset()->getUnit()->getMeter();
- if (root->getAsset()->getUp_axis())
- upAxis = root->getAsset()->getUp_axis()->getValue();
- }
- TSShapeLoader::updateProgress(TSShapeLoader::Load_Complete, "Load complete");
- // Store shape information in the tree control
- tree->setDataField(StringTable->insert("_nodeCount"), 0, avar("%d", stats.numNodes));
- tree->setDataField(StringTable->insert("_meshCount"), 0, avar("%d", stats.numMeshes));
- tree->setDataField(StringTable->insert("_polygonCount"), 0, avar("%d", stats.numPolygons));
- tree->setDataField(StringTable->insert("_materialCount"), 0, avar("%d", stats.numMaterials));
- tree->setDataField(StringTable->insert("_lightCount"), 0, avar("%d", stats.numLights));
- tree->setDataField(StringTable->insert("_animCount"), 0, avar("%d", stats.numClips));
- tree->setDataField(StringTable->insert("_unit"), 0, avar("%g", unit));
- if (upAxis == UPAXISTYPE_X_UP)
- tree->setDataField(StringTable->insert("_upAxis"), 0, "X_AXIS");
- else if (upAxis == UPAXISTYPE_Y_UP)
- tree->setDataField(StringTable->insert("_upAxis"), 0, "Y_AXIS");
- else
- tree->setDataField(StringTable->insert("_upAxis"), 0, "Z_AXIS");
- char shapesStr[16];
- dSprintf(shapesStr, 16, "%i", stats.numMeshes);
- char materialsStr[16];
- dSprintf(materialsStr, 16, "%i", stats.numMaterials);
- char animationsStr[16];
- dSprintf(animationsStr, 16, "%i", stats.numClips);
- tree->setItemValue(nodesID, StringTable->insert(shapesStr));
- tree->setItemValue(matsID, StringTable->insert(materialsStr));
- tree->setItemValue(animsID, StringTable->insert(animationsStr));
- return true;
- }
|