lightAnimData.cpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  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 "lightAnimData.h"
  24. #include "console/consoleTypes.h"
  25. #include "T3D/lightBase.h"
  26. #include "math/mRandom.h"
  27. #include "math/mathIO.h"
  28. #include "T3D/gameBase/processList.h"
  29. #include "core/stream/bitStream.h"
  30. LightAnimData::LightAnimData()
  31. {
  32. }
  33. LightAnimData::~LightAnimData()
  34. {
  35. }
  36. IMPLEMENT_CO_DATABLOCK_V1( LightAnimData );
  37. ConsoleDocClass( LightAnimData,
  38. "@brief A datablock which defines and performs light animation, such as rotation, brightness fade, and colorization.\n\n"
  39. "@tsexample\n"
  40. "datablock LightAnimData( SubtlePulseLightAnim )\n"
  41. "{\n"
  42. " brightnessA = 0.5;\n"
  43. " brightnessZ = 1;\n"
  44. " brightnessPeriod = 1;\n"
  45. " brightnessKeys = \"aza\";\n"
  46. " brightnessSmooth = true;\n"
  47. "};\n"
  48. "@endtsexample\n\n"
  49. "@see LightBase\n\n"
  50. "@see LightDescription\n\n"
  51. "@ingroup FX\n"
  52. "@ingroup Lighting\n"
  53. );
  54. void LightAnimData::initPersistFields()
  55. {
  56. addGroup( "Offset",
  57. "The XYZ translation animation state relative to the light position." );
  58. addField( "offsetA", TypeF32, Offset( mOffset.value1, LightAnimData ), 3,
  59. "The value of the A key in the keyframe sequence." );
  60. addField( "offsetZ", TypeF32, Offset( mOffset.value2, LightAnimData ), 3,
  61. "The value of the Z key in the keyframe sequence." );
  62. addField( "offsetPeriod", TypeF32, Offset( mOffset.period, LightAnimData ), 3,
  63. "The animation time for keyframe sequence." );
  64. addField( "offsetKeys", TypeString, Offset( mOffset.keys, LightAnimData ), 3,
  65. "The keyframe sequence encoded into a string where characters from A to Z define "
  66. "a position between the two animation values." );
  67. addField( "offsetSmooth", TypeBool, Offset( mOffset.smooth, LightAnimData ), 3,
  68. "If true the transition between keyframes will be smooth." );
  69. endGroup( "Offset" );
  70. addGroup( "Rotation",
  71. "The XYZ rotation animation state relative to the light orientation." );
  72. addField( "rotA", TypeF32, Offset( mRot.value1, LightAnimData ), 3,
  73. "The value of the A key in the keyframe sequence." );
  74. addField( "rotZ", TypeF32, Offset( mRot.value2, LightAnimData ), 3,
  75. "The value of the Z key in the keyframe sequence." );
  76. addField( "rotPeriod", TypeF32, Offset( mRot.period, LightAnimData ), 3,
  77. "The animation time for keyframe sequence." );
  78. addField( "rotKeys", TypeString, Offset( mRot.keys, LightAnimData ), 3,
  79. "The keyframe sequence encoded into a string where characters from A to Z define "
  80. "a position between the two animation values." );
  81. addField( "rotSmooth", TypeBool, Offset( mRot.smooth, LightAnimData ), 3,
  82. "If true the transition between keyframes will be smooth." );
  83. endGroup( "Rotation" );
  84. addGroup( "Color",
  85. "The RGB color animation state." );
  86. addField( "colorA", TypeF32, Offset( mColor.value1, LightAnimData ), 3,
  87. "The value of the A key in the keyframe sequence." );
  88. addField( "colorZ", TypeF32, Offset( mColor.value2, LightAnimData ), 3,
  89. "The value of the Z key in the keyframe sequence." );
  90. addField( "colorPeriod", TypeF32, Offset( mColor.period, LightAnimData ), 3,
  91. "The animation time for keyframe sequence." );
  92. addField( "colorKeys", TypeString, Offset( mColor.keys, LightAnimData ), 3,
  93. "The keyframe sequence encoded into a string where characters from A to Z define "
  94. "a position between the two animation values." );
  95. addField( "colorSmooth", TypeBool, Offset( mColor.smooth, LightAnimData ), 3,
  96. "If true the transition between keyframes will be smooth." );
  97. endGroup( "Color" );
  98. addGroup( "Brightness",
  99. "The brightness animation state." );
  100. addField( "brightnessA", TypeF32, Offset( mBrightness.value1, LightAnimData ),
  101. "The value of the A key in the keyframe sequence." );
  102. addField( "brightnessZ", TypeF32, Offset( mBrightness.value2, LightAnimData ),
  103. "The value of the Z key in the keyframe sequence." );
  104. addField( "brightnessPeriod", TypeF32, Offset( mBrightness.period, LightAnimData ),
  105. "The animation time for keyframe sequence." );
  106. addField( "brightnessKeys", TypeString, Offset( mBrightness.keys, LightAnimData ),
  107. "The keyframe sequence encoded into a string where characters from A to Z define "
  108. "a position between the two animation values." );
  109. addField( "brightnessSmooth", TypeBool, Offset( mBrightness.smooth, LightAnimData ),
  110. "If true the transition between keyframes will be smooth." );
  111. endGroup( "Brightness" );
  112. Parent::initPersistFields();
  113. }
  114. bool LightAnimData::preload( bool server, String &errorStr )
  115. {
  116. if ( !Parent::preload( server, errorStr ) )
  117. return false;
  118. _updateKeys();
  119. return true;
  120. }
  121. void LightAnimData::inspectPostApply()
  122. {
  123. Parent::inspectPostApply();
  124. _updateKeys();
  125. }
  126. void LightAnimData::_updateKeys()
  127. {
  128. mOffset.updateKey();
  129. mRot.updateKey();
  130. mColor.updateKey();
  131. mBrightness.updateKey();
  132. }
  133. template<U32 COUNT>
  134. void LightAnimData::AnimValue<COUNT>::updateKey()
  135. {
  136. for ( U32 i=0; i < COUNT; i++ )
  137. {
  138. timeScale[i] = 0.0f;
  139. keyLen[i] = 0.0f;
  140. if ( keys[i] && keys[i][0] && period[i] > 0.0f )
  141. {
  142. keyLen[i] = dStrlen( keys[i] );
  143. timeScale[i] = (F32)( keyLen[i] - 1 ) / period[i];
  144. }
  145. }
  146. }
  147. template<U32 COUNT>
  148. bool LightAnimData::AnimValue<COUNT>::animate( F32 time, F32 *output )
  149. {
  150. F32 scaledTime, lerpFactor, valueRange, keyFrameLerp;
  151. U32 posFrom, posTo;
  152. S32 keyFrameFrom, keyFrameTo;
  153. F32 initialValue = *output;
  154. bool wasAnimated = false;
  155. for ( U32 i=0; i < COUNT; i++ )
  156. {
  157. if ( mIsZero( timeScale[i] ) )
  158. continue;
  159. wasAnimated = true;
  160. scaledTime = mFmod( time, period[i] ) * timeScale[i];
  161. posFrom = mFloor( scaledTime );
  162. posTo = mCeil( scaledTime );
  163. keyFrameFrom = dToupper( keys[i][posFrom] ) - 65;
  164. keyFrameTo = dToupper( keys[i][posTo] ) - 65;
  165. valueRange = ( value2[i] - value1[i] ) / 25.0f;
  166. if ( !smooth[i] )
  167. output[i] = (value1[i] + (keyFrameFrom * valueRange)) * initialValue;
  168. else
  169. {
  170. lerpFactor = scaledTime - posFrom;
  171. keyFrameLerp = ( keyFrameTo - keyFrameFrom ) * lerpFactor;
  172. output[i] = (value1[i] + ((keyFrameFrom + keyFrameLerp) * valueRange)) * initialValue;
  173. }
  174. }
  175. return wasAnimated;
  176. }
  177. template<U32 COUNT>
  178. void LightAnimData::AnimValue<COUNT>::write( BitStream *stream ) const
  179. {
  180. for ( U32 i=0; i < COUNT; i++ )
  181. {
  182. stream->write( value1[i] );
  183. stream->write( value2[i] );
  184. stream->write( period[i] );
  185. stream->writeString( keys[i] );
  186. }
  187. }
  188. template<U32 COUNT>
  189. void LightAnimData::AnimValue<COUNT>::read( BitStream *stream )
  190. {
  191. for ( U32 i=0; i < COUNT; i++ )
  192. {
  193. stream->read( &value1[i] );
  194. stream->read( &value2[i] );
  195. stream->read( &period[i] );
  196. keys[i] = stream->readSTString();
  197. }
  198. }
  199. void LightAnimData::packData( BitStream *stream )
  200. {
  201. Parent::packData( stream );
  202. mOffset.write( stream );
  203. mRot.write( stream );
  204. mColor.write( stream );
  205. mBrightness.write( stream );
  206. }
  207. void LightAnimData::unpackData( BitStream *stream )
  208. {
  209. Parent::unpackData( stream );
  210. mOffset.read( stream );
  211. mRot.read( stream );
  212. mColor.read( stream );
  213. mBrightness.read( stream );
  214. }
  215. void LightAnimData::animate( LightInfo *lightInfo, LightAnimState *state )
  216. {
  217. PROFILE_SCOPE( LightAnimData_animate );
  218. // Calculate the input time for animation.
  219. F32 time = state->animationPhase +
  220. ( (F32)Sim::getCurrentTime() * 0.001f ) /
  221. state->animationPeriod;
  222. MatrixF transform( state->transform );
  223. EulerF euler( Point3F::Zero );
  224. if ( mRot.animate( time, euler ) )
  225. {
  226. euler.x = mDegToRad( euler.x );
  227. euler.y = mDegToRad( euler.y );
  228. euler.z = mDegToRad( euler.z );
  229. MatrixF rot( euler );
  230. transform.mul( rot );
  231. }
  232. Point3F offset( Point3F::Zero );
  233. if ( mOffset.animate( time, offset ) )
  234. transform.displace( offset );
  235. lightInfo->setTransform( transform );
  236. ColorF color = state->color;
  237. mColor.animate( time, color );
  238. lightInfo->setColor( color );
  239. F32 brightness = state->brightness;
  240. mBrightness.animate( time, &brightness );
  241. lightInfo->setBrightness( brightness );
  242. }