spotLight.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platform/platform.h"
  23. #include "T3D/spotLight.h"
  24. #include "console/consoleTypes.h"
  25. #include "core/stream/bitStream.h"
  26. #include "gfx/gfxDrawUtil.h"
  27. IMPLEMENT_CO_NETOBJECT_V1( SpotLight );
  28. ConsoleDocClass( SpotLight,
  29. "@brief Lighting object which emits conical light in a direction.\n\n"
  30. "SpotLight is one of the two types of lighting objects that can be added "
  31. "to a Torque 3D level, the other being PointLight. Unlike directional or "
  32. "point lights, the SpotLights emits lighting in a specific direction "
  33. "within a cone. The distance of the cone is controlled by the SpotLight::range "
  34. "variable.\n\n"
  35. "@tsexample\n"
  36. "// Declaration of a point light in script, or created by World Editor\n"
  37. "new SpotLight(SampleSpotLight)\n"
  38. "{\n"
  39. " range = \"10\";\n"
  40. " innerAngle = \"40\";\n"
  41. " outerAngle = \"45\";\n"
  42. " isEnabled = \"1\";\n"
  43. " color = \"1 1 1 1\";\n"
  44. " brightness = \"1\";\n"
  45. " castShadows = \"0\";\n"
  46. " priority = \"1\";\n"
  47. " animate = \"1\";\n"
  48. " animationPeriod = \"1\";\n"
  49. " animationPhase = \"1\";\n"
  50. " flareType = \"LightFlareExample0\";\n"
  51. " flareScale = \"1\";\n"
  52. " attenuationRatio = \"0 1 1\";\n"
  53. " shadowType = \"Spot\";\n"
  54. " texSize = \"512\";\n"
  55. " overDarkFactor = \"2000 1000 500 100\";\n"
  56. " shadowDistance = \"400\";\n"
  57. " shadowSoftness = \"0.15\";\n"
  58. " numSplits = \"1\";\n"
  59. " logWeight = \"0.91\";\n"
  60. " fadeStartDistance = \"0\";\n"
  61. " lastSplitTerrainOnly = \"0\";\n"
  62. " representedInLightmap = \"0\";\n"
  63. " shadowDarkenColor = \"0 0 0 -1\";\n"
  64. " includeLightmappedGeometryInShadow = \"0\";\n"
  65. " position = \"-29.4362 -5.86289 5.58602\";\n"
  66. " rotation = \"1 0 0 0\";\n"
  67. "};\n"
  68. "@endtsexample\n\n"
  69. "@see LightBase\n\n"
  70. "@see PointLight\n\n"
  71. "@ingroup Lighting\n"
  72. );
  73. SpotLight::SpotLight()
  74. : mRange( 10.0f ),
  75. mInnerConeAngle( 40.0f ),
  76. mOuterConeAngle( 45.0f )
  77. {
  78. // We set the type here to ensure the extended
  79. // parameter validation works when setting fields.
  80. mLight->setType( LightInfo::Spot );
  81. }
  82. SpotLight::~SpotLight()
  83. {
  84. }
  85. void SpotLight::initPersistFields()
  86. {
  87. docsURL;
  88. addGroup( "Light" );
  89. addField( "range", TypeF32, Offset( mRange, SpotLight ) );
  90. addField( "innerAngle", TypeF32, Offset( mInnerConeAngle, SpotLight ) );
  91. addField( "outerAngle", TypeF32, Offset( mOuterConeAngle, SpotLight ) );
  92. endGroup( "Light" );
  93. // We do the parent fields at the end so that
  94. // they show up that way in the inspector.
  95. Parent::initPersistFields();
  96. // Remove the scale field... it's already
  97. // defined by the range and angle.
  98. removeField( "scale" );
  99. //These are particular fields for PSSM, so useless for point lights
  100. removeField("numSplits");
  101. removeField("logWeight");
  102. removeField("lastSplitTerrainOnly");
  103. }
  104. void SpotLight::_conformLights()
  105. {
  106. mLight->setTransform( getTransform() );
  107. mRange = getMax( mRange, 0.05f );
  108. mLight->setRange( mRange );
  109. mLight->setColor( mColor );
  110. mLight->setBrightness( mBrightness );
  111. mLight->setCastShadows( mCastShadows );
  112. mLight->setStaticRefreshFreq(mStaticRefreshFreq);
  113. mLight->setDynamicRefreshFreq(mDynamicRefreshFreq);
  114. mLight->setPriority( mPriority );
  115. mOuterConeAngle = getMax( 0.01f, mOuterConeAngle );
  116. mInnerConeAngle = getMin( mInnerConeAngle, mOuterConeAngle );
  117. mLight->setInnerConeAngle( mInnerConeAngle );
  118. mLight->setOuterConeAngle( mOuterConeAngle );
  119. // Update the bounds and scale to fit our spotlight.
  120. F32 radius = mRange * mSin( mDegToRad( mOuterConeAngle ) * 0.5f );
  121. Point3F objectScale(radius, mRange, radius);
  122. Point3F objectBoxMin(-1, 0, -1);
  123. if (mAnimationData && mAnimationData->mRot.keyLen[0] > 0)
  124. {
  125. objectBoxMin.set(-1, -1, -1);
  126. objectScale.set(mRange, mRange, mRange);
  127. }
  128. mObjBox.minExtents.set(objectBoxMin);
  129. mObjBox.maxExtents.set(1, 1, 1);
  130. mObjScale.set(objectScale);
  131. // Skip our transform... it just dirties mask bits.
  132. Parent::setTransform( mObjToWorld );
  133. }
  134. U32 SpotLight::packUpdate(NetConnection *conn, U32 mask, BitStream *stream )
  135. {
  136. if ( stream->writeFlag( mask & UpdateMask ) )
  137. {
  138. stream->write( mRange );
  139. stream->write( mInnerConeAngle );
  140. stream->write( mOuterConeAngle );
  141. }
  142. return Parent::packUpdate( conn, mask, stream );
  143. }
  144. void SpotLight::unpackUpdate( NetConnection *conn, BitStream *stream )
  145. {
  146. if ( stream->readFlag() ) // UpdateMask
  147. {
  148. stream->read( &mRange );
  149. stream->read( &mInnerConeAngle );
  150. stream->read( &mOuterConeAngle );
  151. }
  152. Parent::unpackUpdate( conn, stream );
  153. }
  154. void SpotLight::setScale( const VectorF &scale )
  155. {
  156. // The y coord is the spotlight range.
  157. mRange = getMax( scale.y, 0.05f );
  158. // Use the average of the x and z to get a radius. This
  159. // is the best method i've found to make the manipulation
  160. // from the WorldEditor gizmo to feel right.
  161. F32 radius = mClampF( ( scale.x + scale.z ) * 0.5f, 0.05f, mRange );
  162. mOuterConeAngle = mRadToDeg( mAsin( radius / mRange ) ) * 2.0f;
  163. // Make sure the inner angle is less than the outer.
  164. //
  165. // TODO: Maybe we should make the inner angle a scale
  166. // and not an absolute angle?
  167. //
  168. mInnerConeAngle = getMin( mInnerConeAngle, mOuterConeAngle );
  169. // We changed a bunch of our settings
  170. // so notify the client.
  171. setMaskBits( UpdateMask );
  172. // Let the parent do the final scale.
  173. Parent::setScale( VectorF( radius, mRange, radius ) );
  174. }
  175. void SpotLight::_renderViz( SceneRenderState *state )
  176. {
  177. GFXDrawUtil *draw = GFX->getDrawUtil();
  178. GFXStateBlockDesc desc;
  179. desc.setZReadWrite( true, false );
  180. desc.setCullMode( GFXCullNone );
  181. desc.setBlend( true );
  182. // Base the color on the light color.
  183. ColorI color = mColor.toColorI();
  184. color.alpha = 16;
  185. F32 radius = mRange * mSin( mDegToRad( mOuterConeAngle * 0.5f ) );
  186. draw->drawCone( desc,
  187. getPosition() + ( getTransform().getForwardVector() * mRange ),
  188. getPosition(),
  189. radius,
  190. color );
  191. }