lightAnimData.cpp 9.6 KB

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