spotLight.cpp

Engine/source/T3D/spotLight.cpp

More...

Public Functions

ConsoleDocClass(SpotLight , "@brief Lighting object which emits conical light in <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">direction.\n\n</a>" "<a href="/coding/class/classspotlight/">SpotLight</a> is one of the two types of lighting objects that can be added " "<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> Torque 3D level, the other being PointLight. Unlike directional or " "point lights, the SpotLights emits lighting in <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> specific direction " "within <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> cone. The distance of the cone is controlled by the SpotLight::range " "<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">variable.\n\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "//Declaration of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> point light in script, or created by <a href="/coding/file/gizmo_8h/#gizmo_8h_1a10fcd3bee2ea25191e31795e36bdeba1a81f4537631c9ab219ec74de554483adc">World</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Editor\n</a>" "<a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/class/classspotlight/">SpotLight</a>(SampleSpotLight)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " range=\"10\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   innerAngle = \"40\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   outerAngle = \"45\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   isEnabled = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   color = \"1 1 1 1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   brightness = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   castShadows = \"0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   priority = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   animate = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   animationPeriod = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   animationPhase = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   flareType = \"LightFlareExample0\";\n" "   flareScale = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   attenuationRatio = \"0 1 1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   shadowType = \"Spot\";\n" "   texSize = \"512\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   overDarkFactor = \"2000 1000 500 100\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   shadowDistance = \"400\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   shadowSoftness = \"0.15\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   numSplits = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   logWeight = \"0.91\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   fadeStartDistance = \"0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   lastSplitTerrainOnly = \"0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   representedInLightmap = \"0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   shadowDarkenColor = \"0 0 0 -1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   includeLightmappedGeometryInShadow = \"0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   position = \"-29.4362 -5.86289 5.58602\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   rotation = \"1 0 0 0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "};\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">LightBase\n\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">PointLight\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Lighting\n</a>" )

Detailed Description

Public Functions

ConsoleDocClass(SpotLight , "@brief Lighting object which emits conical light in <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">direction.\n\n</a>" "<a href="/coding/class/classspotlight/">SpotLight</a> is one of the two types of lighting objects that can be added " "<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> Torque 3D level, the other being PointLight. Unlike directional or " "point lights, the SpotLights emits lighting in <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> specific direction " "within <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> cone. The distance of the cone is controlled by the SpotLight::range " "<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">variable.\n\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "//Declaration of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> point light in script, or created by <a href="/coding/file/gizmo_8h/#gizmo_8h_1a10fcd3bee2ea25191e31795e36bdeba1a81f4537631c9ab219ec74de554483adc">World</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Editor\n</a>" "<a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/class/classspotlight/">SpotLight</a>(SampleSpotLight)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " range=\"10\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   innerAngle = \"40\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   outerAngle = \"45\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   isEnabled = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   color = \"1 1 1 1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   brightness = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   castShadows = \"0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   priority = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   animate = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   animationPeriod = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   animationPhase = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   flareType = \"LightFlareExample0\";\n" "   flareScale = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   attenuationRatio = \"0 1 1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   shadowType = \"Spot\";\n" "   texSize = \"512\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   overDarkFactor = \"2000 1000 500 100\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   shadowDistance = \"400\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   shadowSoftness = \"0.15\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   numSplits = \"1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   logWeight = \"0.91\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   fadeStartDistance = \"0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   lastSplitTerrainOnly = \"0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   representedInLightmap = \"0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   shadowDarkenColor = \"0 0 0 -1\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   includeLightmappedGeometryInShadow = \"0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   position = \"-29.4362 -5.86289 5.58602\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   rotation = \"1 0 0 0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "};\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">LightBase\n\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">PointLight\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Lighting\n</a>" )

IMPLEMENT_CO_NETOBJECT_V1(SpotLight )

  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#include "T3D/spotLight.h"
 26
 27#include "console/consoleTypes.h"
 28#include "core/stream/bitStream.h"
 29#include "gfx/gfxDrawUtil.h"
 30
 31
 32IMPLEMENT_CO_NETOBJECT_V1( SpotLight );
 33
 34ConsoleDocClass( SpotLight,
 35   "@brief Lighting object which emits conical light in a direction.\n\n"
 36
 37   "SpotLight is one of the two types of lighting objects that can be added "
 38   "to a Torque 3D level, the other being PointLight. Unlike directional or "
 39   "point lights, the SpotLights emits lighting in a specific direction "
 40   "within a cone. The distance of the cone is controlled by the SpotLight::range "
 41   "variable.\n\n"
 42
 43   "@tsexample\n"
 44   "// Declaration of a point light in script, or created by World Editor\n"
 45   "new SpotLight(SampleSpotLight)\n"
 46   "{\n"
 47   "   range = \"10\";\n"
 48   "   innerAngle = \"40\";\n"
 49   "   outerAngle = \"45\";\n"
 50   "   isEnabled = \"1\";\n"
 51   "   color = \"1 1 1 1\";\n"
 52   "   brightness = \"1\";\n"
 53   "   castShadows = \"0\";\n"
 54   "   priority = \"1\";\n"
 55   "   animate = \"1\";\n"
 56   "   animationPeriod = \"1\";\n"
 57   "   animationPhase = \"1\";\n"
 58   "   flareType = \"LightFlareExample0\";\n"
 59   "   flareScale = \"1\";\n"
 60   "   attenuationRatio = \"0 1 1\";\n"
 61   "   shadowType = \"Spot\";\n"
 62   "   texSize = \"512\";\n"
 63   "   overDarkFactor = \"2000 1000 500 100\";\n"
 64   "   shadowDistance = \"400\";\n"
 65   "   shadowSoftness = \"0.15\";\n"
 66   "   numSplits = \"1\";\n"
 67   "   logWeight = \"0.91\";\n"
 68   "   fadeStartDistance = \"0\";\n"
 69   "   lastSplitTerrainOnly = \"0\";\n"
 70   "   representedInLightmap = \"0\";\n"
 71   "   shadowDarkenColor = \"0 0 0 -1\";\n"
 72   "   includeLightmappedGeometryInShadow = \"0\";\n"
 73   "   position = \"-29.4362 -5.86289 5.58602\";\n"
 74   "   rotation = \"1 0 0 0\";\n"
 75   "};\n"
 76   "@endtsexample\n\n"
 77
 78   "@see LightBase\n\n"
 79   "@see PointLight\n\n"
 80   "@ingroup Lighting\n"
 81);
 82
 83SpotLight::SpotLight()
 84   :  mRange( 10.0f ),
 85      mInnerConeAngle( 40.0f ),
 86      mOuterConeAngle( 45.0f )
 87{
 88   // We set the type here to ensure the extended
 89   // parameter validation works when setting fields.
 90   mLight->setType( LightInfo::Spot );
 91}
 92
 93SpotLight::~SpotLight()
 94{
 95}
 96
 97void SpotLight::initPersistFields()
 98{
 99   addGroup( "Light" );
100      
101      addField( "range", TypeF32, Offset( mRange, SpotLight ) );
102      addField( "innerAngle", TypeF32, Offset( mInnerConeAngle, SpotLight ) );
103      addField( "outerAngle", TypeF32, Offset( mOuterConeAngle, SpotLight ) );
104
105   endGroup( "Light" );
106
107   // We do the parent fields at the end so that
108   // they show up that way in the inspector.
109   Parent::initPersistFields();
110
111   // Remove the scale field... it's already 
112   // defined by the range and angle.
113   removeField( "scale" );
114
115   //These are particular fields for PSSM, so useless for point lights
116   removeField("numSplits");
117   removeField("logWeight");
118   removeField("lastSplitTerrainOnly");
119}
120
121void SpotLight::_conformLights()
122{
123   mLight->setTransform( getTransform() );
124
125   mRange = getMax( mRange, 0.05f );
126   mLight->setRange( mRange );
127
128   mLight->setColor( mColor );
129   mLight->setBrightness( mBrightness );
130   mLight->setCastShadows( mCastShadows );
131   mLight->setStaticRefreshFreq(mStaticRefreshFreq);
132   mLight->setDynamicRefreshFreq(mDynamicRefreshFreq);
133   mLight->setPriority( mPriority );
134
135   mOuterConeAngle = getMax( 0.01f, mOuterConeAngle );
136   mInnerConeAngle = getMin( mInnerConeAngle, mOuterConeAngle );
137
138   mLight->setInnerConeAngle( mInnerConeAngle );
139   mLight->setOuterConeAngle( mOuterConeAngle );
140
141   // Update the bounds and scale to fit our spotlight.
142   F32 radius = mRange * mSin( mDegToRad( mOuterConeAngle ) * 0.5f );
143   Point3F objectScale(radius, mRange, radius);
144   Point3F objectBoxMin(-1, 0, -1);
145
146   if (mAnimationData && mAnimationData->mRot.keyLen[0] > 0)
147   {
148      objectBoxMin.set(-1, -1, -1);
149      objectScale.set(mRange, mRange, mRange);
150   }
151
152   mObjBox.minExtents.set(objectBoxMin);
153   mObjBox.maxExtents.set(1, 1, 1);
154   mObjScale.set(objectScale);
155
156   // Skip our transform... it just dirties mask bits.
157   Parent::setTransform( mObjToWorld );
158}
159
160U32 SpotLight::packUpdate(NetConnection *conn, U32 mask, BitStream *stream )
161{
162   if ( stream->writeFlag( mask & UpdateMask ) )
163   {
164      stream->write( mRange );
165      stream->write( mInnerConeAngle );
166      stream->write( mOuterConeAngle );
167   }
168   
169   return Parent::packUpdate( conn, mask, stream );
170}
171
172void SpotLight::unpackUpdate( NetConnection *conn, BitStream *stream )
173{
174   if ( stream->readFlag() ) // UpdateMask
175   {   
176      stream->read( &mRange );
177      stream->read( &mInnerConeAngle );
178      stream->read( &mOuterConeAngle );
179   }
180   
181   Parent::unpackUpdate( conn, stream );
182}
183
184void SpotLight::setScale( const VectorF &scale )
185{
186   // The y coord is the spotlight range.
187   mRange = getMax( scale.y, 0.05f );
188
189   // Use the average of the x and z to get a radius.  This
190   // is the best method i've found to make the manipulation
191   // from the WorldEditor gizmo to feel right.
192   F32 radius = mClampF( ( scale.x + scale.z ) * 0.5f, 0.05f, mRange );
193   mOuterConeAngle = mRadToDeg( mAsin( radius / mRange ) ) * 2.0f;
194
195   // Make sure the inner angle is less than the outer.
196   //
197   // TODO: Maybe we should make the inner angle a scale
198   // and not an absolute angle?
199   //
200   mInnerConeAngle = getMin( mInnerConeAngle, mOuterConeAngle );
201
202   // We changed a bunch of our settings 
203   // so notify the client.
204   setMaskBits( UpdateMask );
205
206   // Let the parent do the final scale.
207   Parent::setScale( VectorF( radius, mRange, radius ) );
208}
209
210void SpotLight::_renderViz( SceneRenderState *state )
211{
212   GFXDrawUtil *draw = GFX->getDrawUtil();
213
214   GFXStateBlockDesc desc;
215   desc.setZReadWrite( true, false );
216   desc.setCullMode( GFXCullNone );
217   desc.setBlend( true );
218
219   // Base the color on the light color.
220   ColorI color = mColor.toColorI();
221   color.alpha = 16;
222
223   F32 radius = mRange * mSin( mDegToRad( mOuterConeAngle * 0.5f ) );
224   draw->drawCone(   desc, 
225                     getPosition() + ( getTransform().getForwardVector() * mRange ),
226                     getPosition(),
227                     radius,
228                     color );
229}
230