colladaLights.cpp
Engine/source/ts/collada/colladaLights.cpp
Public Functions
DefineEngineFunction(loadColladaLights , bool , (const char *filename, const char *parentGroup, const char *baseObject) , ("", "") , "(string filename, <a href="/coding/class/classsimgroup/">SimGroup</a> parentGroup=<a href="/coding/class/classscene/">Scene</a>, <a href="/coding/class/classsimobject/">SimObject</a> baseObject=-1)" "Load all light instances from <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> COLLADA (.dae) <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> and add <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">scene.\n</a>" "@param filename COLLADA filename <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> load lights <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">from\n</a>" "@param parentGroup (optional) name of an existing simgroup <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> add the <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> " "lights <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> (defaults <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> root <a href="/coding/class/classscene/">Scene</a>)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@param baseObject (optional) name of an object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> use as the origin (useful " "<a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> you are loading the lights <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> collada scene and have moved or rotated " "the geometry)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@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\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "//load the lights in <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">room.dae\n</a>" "loadColladaLights(\"art/shapes/collada/room.dae\" );\n\n" "// load the lights in room.dae and add them <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the RoomLights <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">group\n</a>" "loadColladaLights( \"art/shapes/collada/room.dae\", \"RoomLights\" );\n\n" "// load the lights in room.dae and use the transform of the \"Room\"\n" "object as the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">origin\n</a>" "loadColladaLights( \"art/shapes/collada/room.dae\", \"\", \"Room\" );\n" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" "@note Currently <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> editor use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">only\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Editors\n</a>" "@internal" )
resolveLightAttenuation(T * light, Point3F & attenuationRatio)
resolveLightColor(T * light, LinearColorF & color)
Detailed Description
Public Functions
DefineEngineFunction(loadColladaLights , bool , (const char *filename, const char *parentGroup, const char *baseObject) , ("", "") , "(string filename, <a href="/coding/class/classsimgroup/">SimGroup</a> parentGroup=<a href="/coding/class/classscene/">Scene</a>, <a href="/coding/class/classsimobject/">SimObject</a> baseObject=-1)" "Load all light instances from <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> COLLADA (.dae) <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> and add <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">scene.\n</a>" "@param filename COLLADA filename <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> load lights <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">from\n</a>" "@param parentGroup (optional) name of an existing simgroup <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> add the <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> " "lights <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> (defaults <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> root <a href="/coding/class/classscene/">Scene</a>)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@param baseObject (optional) name of an object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> use as the origin (useful " "<a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> you are loading the lights <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> collada scene and have moved or rotated " "the geometry)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@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\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "//load the lights in <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">room.dae\n</a>" "loadColladaLights(\"art/shapes/collada/room.dae\" );\n\n" "// load the lights in room.dae and add them <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the RoomLights <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">group\n</a>" "loadColladaLights( \"art/shapes/collada/room.dae\", \"RoomLights\" );\n\n" "// load the lights in room.dae and use the transform of the \"Room\"\n" "object as the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">origin\n</a>" "loadColladaLights( \"art/shapes/collada/room.dae\", \"\", \"Room\" );\n" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" "@note Currently <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> editor use <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">only\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Editors\n</a>" "@internal" )
processNodeLights(AppNode * appNode, const MatrixF & offset, SimGroup * group)
resolveLightAttenuation(T * light, Point3F & attenuationRatio)
resolveLightColor(T * light, LinearColorF & color)
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 "console/engineAPI.h" 25#include "platform/platform.h" 26 27#include "ts/collada/colladaUtils.h" 28#include "ts/collada/colladaAppNode.h" 29#include "ts/collada/colladaShapeLoader.h" 30 31#include "T3D/pointLight.h" 32#include "T3D/spotLight.h" 33 34#include "T3D/Scene.h" 35 36//----------------------------------------------------------------------------- 37// Collada <light> elements are very similar, but are arranged as separate, unrelated 38// classes. These template functions are used to provide a simple way to access the 39// common elements. 40template<class T> static void resolveLightColor(T* light, LinearColorF& color) 41{ 42 if (light->getColor()) 43 { 44 color.red = light->getColor()->getValue()[0]; 45 color.green = light->getColor()->getValue()[1]; 46 color.blue = light->getColor()->getValue()[2]; 47 } 48} 49 50template<class T> static void resolveLightAttenuation(T* light, Point3F& attenuationRatio) 51{ 52 if (light->getConstant_attenuation()) 53 attenuationRatio.x = light->getConstant_attenuation()->getValue(); 54 if (light->getLinear_attenuation()) 55 attenuationRatio.y = light->getLinear_attenuation()->getValue(); 56 if (light->getQuadratic_attenuation()) 57 attenuationRatio.z = light->getQuadratic_attenuation()->getValue(); 58} 59 60//----------------------------------------------------------------------------- 61// Recurse through the collada scene to add <light>s to the Torque scene 62static void processNodeLights(AppNode* appNode, const MatrixF& offset, SimGroup* group) 63{ 64 const domNode* node = dynamic_cast<ColladaAppNode*>(appNode)->getDomNode(); 65 66 for (S32 iLight = 0; iLight < node->getInstance_light_array().getCount(); iLight++) { 67 68 domInstance_light* instLight = node->getInstance_light_array()[iLight]; 69 domLight* p_domLight = daeSafeCast<domLight>(instLight->getUrl().getElement()); 70 if (!p_domLight) { 71 Con::warnf("Failed to find light for URL \"%s\"", instLight->getUrl().getOriginalURI()); 72 continue; 73 } 74 75 String lightName = Sim::getUniqueName(_GetNameOrId(node)); 76 const char* lightType = ""; 77 78 domLight::domTechnique_common* technique = p_domLight->getTechnique_common(); 79 if (!technique) { 80 Con::warnf("No <technique_common> for light \"%s\"", lightName.c_str()); 81 continue; 82 } 83 84 LightBase* pLight = 0; 85 LinearColorF color(LinearColorF::WHITE); 86 Point3F attenuation(0, 1, 1); 87 88 if (technique->getAmbient()) { 89 domLight::domTechnique_common::domAmbient* ambient = technique->getAmbient(); 90 // No explicit support for ambient lights, so use a PointLight instead 91 lightType = "ambient"; 92 pLight = new PointLight; 93 resolveLightColor(ambient, color); 94 } 95 else if (technique->getDirectional()) { 96 domLight::domTechnique_common::domDirectional* directional = technique->getDirectional(); 97 // No explicit support for directional lights, so use a SpotLight instead 98 lightType = "directional"; 99 pLight = new SpotLight; 100 resolveLightColor(directional, color); 101 } 102 else if (technique->getPoint()) { 103 domLight::domTechnique_common::domPoint* point = technique->getPoint(); 104 lightType = "point"; 105 pLight = new PointLight; 106 resolveLightColor(point, color); 107 resolveLightAttenuation(point, attenuation); 108 } 109 else if (technique->getSpot()) { 110 domLight::domTechnique_common::domSpot* spot = technique->getSpot(); 111 lightType = "spot"; 112 pLight = new SpotLight; 113 resolveLightColor(spot, color); 114 resolveLightAttenuation(spot, attenuation); 115 } 116 else 117 continue; 118 119 Con::printf("Adding <%s> light \"%s\" as a %s", lightType, lightName.c_str(), pLight->getClassName()); 120 121 MatrixF mat(offset); 122 mat.mul(appNode->getNodeTransform(TSShapeLoader::DefaultTime)); 123 124 pLight->setDataField(StringTable->insert("color"), 0, 125 avar("%f %f %f %f", color.red, color.green, color.blue, color.alpha)); 126 pLight->setDataField(StringTable->insert("attenuationRatio"), 0, 127 avar("%f %f %f", attenuation.x, attenuation.y, attenuation.z)); 128 pLight->setTransform(mat); 129 130 if (!pLight->registerObject(lightName)) { 131 Con::errorf(ConsoleLogEntry::General, "Failed to register light for \"%s\"", lightName.c_str()); 132 delete pLight; 133 } 134 else if (group) 135 group->addObject(pLight); 136 } 137 138 // Recurse child nodes 139 for (S32 iChild = 0; iChild < appNode->getNumChildNodes(); iChild++) 140 processNodeLights(appNode->getChildNode(iChild), offset, group); 141} 142 143// Load lights from a collada file and add to the scene. 144DefineEngineFunction( loadColladaLights, bool, (const char * filename, const char * parentGroup, const char * baseObject), ("", ""), 145 "(string filename, SimGroup parentGroup=Scene, SimObject baseObject=-1)" 146 "Load all light instances from a COLLADA (.dae) file and add to the scene.\n" 147 "@param filename COLLADA filename to load lights from\n" 148 "@param parentGroup (optional) name of an existing simgroup to add the new " 149 "lights to (defaults to root Scene)\n" 150 "@param baseObject (optional) name of an object to use as the origin (useful " 151 "if you are loading the lights for a collada scene and have moved or rotated " 152 "the geometry)\n" 153 "@return true if successful, false otherwise\n\n" 154 "@tsexample\n" 155 "// load the lights in room.dae\n" 156 "loadColladaLights( \"art/shapes/collada/room.dae\" );\n\n" 157 "// load the lights in room.dae and add them to the RoomLights group\n" 158 "loadColladaLights( \"art/shapes/collada/room.dae\", \"RoomLights\" );\n\n" 159 "// load the lights in room.dae and use the transform of the \"Room\"\n" 160 "object as the origin\n" 161 "loadColladaLights( \"art/shapes/collada/room.dae\", \"\", \"Room\" );\n" 162 "@endtsexample\n\n" 163 "@note Currently for editor use only\n" 164 "@ingroup Editors\n" 165 "@internal") 166{ 167 Torque::Path path(filename); 168 169 // Optional group to add the lights to. Create if it does not exist, and use 170 // the root Scene if not specified. 171 Scene* scene = Scene::getRootScene(); 172 SimGroup* group = 0; 173 if (!String::isEmpty(parentGroup)){ 174 if (!Sim::findObject(parentGroup, group)) { 175 // Create the group if it could not be found 176 group = new SimGroup; 177 if (group->registerObject(parentGroup)) { 178 if (scene) 179 scene->addObject(group); 180 } 181 else { 182 delete group; 183 group = 0; 184 } 185 } 186 } 187 if (!group) 188 group = scene; 189 190 // Optional object to provide the base transform 191 MatrixF offset(true); 192 if (!String::isEmpty(baseObject)){ 193 SceneObject *obj; 194 if (Sim::findObject(baseObject, obj)) 195 offset = obj->getTransform(); 196 } 197 198 // Load the Collada file into memory 199 domCOLLADA* root = ColladaShapeLoader::getDomCOLLADA(path); 200 if (!root) { 201 TSShapeLoader::updateProgress(TSShapeLoader::Load_Complete, "Load complete"); 202 return false; 203 } 204 205 // Extract the global scale and up_axis from the top level <asset> element, 206 F32 unit = 1.0f; 207 domUpAxisType upAxis = UPAXISTYPE_Z_UP; 208 if (root->getAsset()) { 209 if (root->getAsset()->getUnit()) 210 unit = root->getAsset()->getUnit()->getMeter(); 211 if (root->getAsset()->getUp_axis()) 212 upAxis = root->getAsset()->getUp_axis()->getValue(); 213 } 214 215 ColladaUtils::getOptions().unit = unit; 216 ColladaUtils::getOptions().upAxis = upAxis; 217 218 // First grab all of the top-level nodes 219 Vector<ColladaAppNode*> sceneNodes; 220 for (S32 iSceneLib = 0; iSceneLib < root->getLibrary_visual_scenes_array().getCount(); iSceneLib++) { 221 const domLibrary_visual_scenes* libScenes = root->getLibrary_visual_scenes_array()[iSceneLib]; 222 for (S32 iScene = 0; iScene < libScenes->getVisual_scene_array().getCount(); iScene++) { 223 const domVisual_scene* visualScene = libScenes->getVisual_scene_array()[iScene]; 224 for (S32 iNode = 0; iNode < visualScene->getNode_array().getCount(); iNode++) 225 sceneNodes.push_back(new ColladaAppNode(visualScene->getNode_array()[iNode])); 226 } 227 } 228 229 // Recurse the scene tree looking for <instance_light>s 230 for (S32 iNode = 0; iNode < sceneNodes.size(); iNode++) { 231 processNodeLights(sceneNodes[iNode], offset, group); 232 delete sceneNodes[iNode]; 233 } 234 235 TSShapeLoader::updateProgress(TSShapeLoader::Load_Complete, "Load complete"); 236 237 return true; 238} 239