2
0

lightAnimData.cpp 10 KB

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