spotLight.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  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. addGroup( "Light" );
  88. addField( "range", TypeF32, Offset( mRange, SpotLight ) );
  89. addField( "innerAngle", TypeF32, Offset( mInnerConeAngle, SpotLight ) );
  90. addField( "outerAngle", TypeF32, Offset( mOuterConeAngle, SpotLight ) );
  91. endGroup( "Light" );
  92. // We do the parent fields at the end so that
  93. // they show up that way in the inspector.
  94. Parent::initPersistFields();
  95. // Remove the scale field... it's already
  96. // defined by the range and angle.
  97. removeField( "scale" );
  98. }
  99. void SpotLight::_conformLights()
  100. {
  101. mLight->setTransform( getTransform() );
  102. mRange = getMax( mRange, 0.05f );
  103. mLight->setRange( mRange );
  104. mLight->setColor( mColor );
  105. mLight->setBrightness( mBrightness );
  106. mLight->setCastShadows( mCastShadows );
  107. mLight->setStaticRefreshFreq(mStaticRefreshFreq);
  108. mLight->setDynamicRefreshFreq(mDynamicRefreshFreq);
  109. mLight->setPriority( mPriority );
  110. mOuterConeAngle = getMax( 0.01f, mOuterConeAngle );
  111. mInnerConeAngle = getMin( mInnerConeAngle, mOuterConeAngle );
  112. mLight->setInnerConeAngle( mInnerConeAngle );
  113. mLight->setOuterConeAngle( mOuterConeAngle );
  114. // Update the bounds and scale to fit our spotlight.
  115. F32 radius = mRange * mSin( mDegToRad( mOuterConeAngle ) * 0.5f );
  116. Point3F objectScale(radius, mRange, radius);
  117. Point3F objectBoxMin(-1, 0, -1);
  118. if (mAnimationData && mAnimationData->mRot.keyLen > 0)
  119. {
  120. objectBoxMin.set(-1, -1, -1);
  121. objectScale.set(mRange, mRange, mRange);
  122. }
  123. mObjBox.minExtents.set(objectBoxMin);
  124. mObjBox.maxExtents.set(1, 1, 1);
  125. mObjScale.set(objectScale);
  126. // Skip our transform... it just dirties mask bits.
  127. Parent::setTransform( mObjToWorld );
  128. }
  129. U32 SpotLight::packUpdate(NetConnection *conn, U32 mask, BitStream *stream )
  130. {
  131. if ( stream->writeFlag( mask & UpdateMask ) )
  132. {
  133. stream->write( mRange );
  134. stream->write( mInnerConeAngle );
  135. stream->write( mOuterConeAngle );
  136. }
  137. return Parent::packUpdate( conn, mask, stream );
  138. }
  139. void SpotLight::unpackUpdate( NetConnection *conn, BitStream *stream )
  140. {
  141. if ( stream->readFlag() ) // UpdateMask
  142. {
  143. stream->read( &mRange );
  144. stream->read( &mInnerConeAngle );
  145. stream->read( &mOuterConeAngle );
  146. }
  147. Parent::unpackUpdate( conn, stream );
  148. }
  149. void SpotLight::setScale( const VectorF &scale )
  150. {
  151. // The y coord is the spotlight range.
  152. mRange = getMax( scale.y, 0.05f );
  153. // Use the average of the x and z to get a radius. This
  154. // is the best method i've found to make the manipulation
  155. // from the WorldEditor gizmo to feel right.
  156. F32 radius = mClampF( ( scale.x + scale.z ) * 0.5f, 0.05f, mRange );
  157. mOuterConeAngle = mRadToDeg( mAsin( radius / mRange ) ) * 2.0f;
  158. // Make sure the inner angle is less than the outer.
  159. //
  160. // TODO: Maybe we should make the inner angle a scale
  161. // and not an absolute angle?
  162. //
  163. mInnerConeAngle = getMin( mInnerConeAngle, mOuterConeAngle );
  164. // We changed a bunch of our settings
  165. // so notify the client.
  166. setMaskBits( UpdateMask );
  167. // Let the parent do the final scale.
  168. Parent::setScale( VectorF( radius, mRange, radius ) );
  169. }
  170. void SpotLight::_renderViz( SceneRenderState *state )
  171. {
  172. GFXDrawUtil *draw = GFX->getDrawUtil();
  173. GFXStateBlockDesc desc;
  174. desc.setZReadWrite( true, false );
  175. desc.setCullMode( GFXCullNone );
  176. desc.setBlend( true );
  177. // Base the color on the light color.
  178. ColorI color = mColor.toColorI();
  179. color.alpha = 16;
  180. F32 radius = mRange * mSin( mDegToRad( mOuterConeAngle * 0.5f ) );
  181. draw->drawCone( desc,
  182. getPosition() + ( getTransform().getForwardVector() * mRange ),
  183. getPosition(),
  184. radius,
  185. color );
  186. }