123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2012 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #include "platform/platform.h"
- #include "lightAnimData.h"
- #include "console/consoleTypes.h"
- #include "T3D/lightBase.h"
- #include "math/mRandom.h"
- #include "math/mathIO.h"
- #include "T3D/gameBase/processList.h"
- #include "core/stream/bitStream.h"
- LightAnimData::LightAnimData()
- {
- }
- LightAnimData::~LightAnimData()
- {
- }
- IMPLEMENT_CO_DATABLOCK_V1( LightAnimData );
- ConsoleDocClass( LightAnimData,
- "@brief A datablock which defines and performs light animation, such as rotation, brightness fade, and colorization.\n\n"
- "@tsexample\n"
- "datablock LightAnimData( SubtlePulseLightAnim )\n"
- "{\n"
- " brightnessA = 0.5;\n"
- " brightnessZ = 1;\n"
- " brightnessPeriod = 1;\n"
- " brightnessKeys = \"aza\";\n"
- " brightnessSmooth = true;\n"
- "};\n"
- "@endtsexample\n\n"
- "@see LightBase\n\n"
- "@see LightDescription\n\n"
- "@ingroup FX\n"
- "@ingroup Lighting\n"
- );
- void LightAnimData::initPersistFields()
- {
- docsURL;
- addGroup( "Offset",
- "The XYZ translation animation state relative to the light position." );
- addField( "offsetA", TypeF32, Offset( mOffset.value1, LightAnimData ), 3,
- "The value of the A key in the keyframe sequence." );
- addField( "offsetZ", TypeF32, Offset( mOffset.value2, LightAnimData ), 3,
- "The value of the Z key in the keyframe sequence." );
- addField( "offsetPeriod", TypeF32, Offset( mOffset.period, LightAnimData ), 3,
- "The animation time for keyframe sequence." );
- addField( "offsetKeys", TypeString, Offset( mOffset.keys, LightAnimData ), 3,
- "The keyframe sequence encoded into a string where characters from A to Z define "
- "a position between the two animation values." );
- addField( "offsetSmooth", TypeBool, Offset( mOffset.smooth, LightAnimData ), 3,
- "If true the transition between keyframes will be smooth." );
- endGroup( "Offset" );
- addGroup( "Rotation",
- "The XYZ rotation animation state relative to the light orientation." );
- addField( "rotA", TypeF32, Offset( mRot.value1, LightAnimData ), 3,
- "The value of the A key in the keyframe sequence." );
- addField( "rotZ", TypeF32, Offset( mRot.value2, LightAnimData ), 3,
- "The value of the Z key in the keyframe sequence." );
- addField( "rotPeriod", TypeF32, Offset( mRot.period, LightAnimData ), 3,
- "The animation time for keyframe sequence." );
- addField( "rotKeys", TypeString, Offset( mRot.keys, LightAnimData ), 3,
- "The keyframe sequence encoded into a string where characters from A to Z define "
- "a position between the two animation values." );
- addField( "rotSmooth", TypeBool, Offset( mRot.smooth, LightAnimData ), 3,
- "If true the transition between keyframes will be smooth." );
- endGroup( "Rotation" );
- addGroup( "Color",
- "The RGB color animation state." );
- addField( "colorA", TypeF32, Offset( mColor.value1, LightAnimData ), 3,
- "The value of the A key in the keyframe sequence." );
- addField( "colorZ", TypeF32, Offset( mColor.value2, LightAnimData ), 3,
- "The value of the Z key in the keyframe sequence." );
- addField( "colorPeriod", TypeF32, Offset( mColor.period, LightAnimData ), 3,
- "The animation time for keyframe sequence." );
- addField( "colorKeys", TypeString, Offset( mColor.keys, LightAnimData ), 3,
- "The keyframe sequence encoded into a string where characters from A to Z define "
- "a position between the two animation values." );
- addField( "colorSmooth", TypeBool, Offset( mColor.smooth, LightAnimData ), 3,
- "If true the transition between keyframes will be smooth." );
- endGroup( "Color" );
- addGroup( "Brightness",
- "The brightness animation state." );
- addField( "brightnessA", TypeF32, Offset( mBrightness.value1, LightAnimData ),
- "The value of the A key in the keyframe sequence." );
- addField( "brightnessZ", TypeF32, Offset( mBrightness.value2, LightAnimData ),
- "The value of the Z key in the keyframe sequence." );
- addField( "brightnessPeriod", TypeF32, Offset( mBrightness.period, LightAnimData ),
- "The animation time for keyframe sequence." );
- addField( "brightnessKeys", TypeString, Offset( mBrightness.keys, LightAnimData ),
- "The keyframe sequence encoded into a string where characters from A to Z define "
- "a position between the two animation values." );
- addField( "brightnessSmooth", TypeBool, Offset( mBrightness.smooth, LightAnimData ),
- "If true the transition between keyframes will be smooth." );
- endGroup( "Brightness" );
- Parent::initPersistFields();
- }
- bool LightAnimData::preload( bool server, String &errorStr )
- {
- if ( !Parent::preload( server, errorStr ) )
- return false;
- _updateKeys();
- return true;
- }
- void LightAnimData::inspectPostApply()
- {
- Parent::inspectPostApply();
- _updateKeys();
- }
- void LightAnimData::_updateKeys()
- {
- mOffset.updateKey();
- mRot.updateKey();
- mColor.updateKey();
- mBrightness.updateKey();
- }
- template<U32 COUNT>
- void LightAnimData::AnimValue<COUNT>::updateKey()
- {
- for ( U32 i=0; i < COUNT; i++ )
- {
- timeScale[i] = 0.0f;
- keyLen[i] = 0.0f;
-
- if ( keys[i] && keys[i][0] && period[i] > 0.0f )
- {
- keyLen[i] = dStrlen( keys[i] );
- timeScale[i] = (F32)( keyLen[i] - 1 ) / period[i];
- }
- }
- }
- template<U32 COUNT>
- bool LightAnimData::AnimValue<COUNT>::animate(F32 time, F32 *output, bool multiply)
- {
- F32 scaledTime, lerpFactor, valueRange, keyFrameLerp;
- U32 posFrom, posTo;
- S32 keyFrameFrom, keyFrameTo;
- F32 initialValue = *output;
- if (!multiply)
- initialValue = 1;
- bool wasAnimated = false;
- for ( U32 i=0; i < COUNT; i++ )
- {
- if ( mIsZero( timeScale[i] ) )
- continue;
- wasAnimated = true;
- scaledTime = mFmod( time, period[i] ) * timeScale[i];
- posFrom = mFloor( scaledTime );
- posTo = mCeil( scaledTime );
- keyFrameFrom = dToupper( keys[i][posFrom] ) - 65;
- keyFrameTo = dToupper( keys[i][posTo] ) - 65;
- valueRange = ( value2[i] - value1[i] ) / 25.0f;
- if ( !smooth[i] )
- output[i] = (value1[i] + (keyFrameFrom * valueRange)) * initialValue;
- else
- {
- lerpFactor = scaledTime - posFrom;
- keyFrameLerp = ( keyFrameTo - keyFrameFrom ) * lerpFactor;
- output[i] = (value1[i] + ((keyFrameFrom + keyFrameLerp) * valueRange)) * initialValue;
- }
- }
- return wasAnimated;
- }
- template<U32 COUNT>
- void LightAnimData::AnimValue<COUNT>::write( BitStream *stream ) const
- {
- for ( U32 i=0; i < COUNT; i++ )
- {
- stream->write( value1[i] );
- stream->write( value2[i] );
- stream->write( period[i] );
- stream->writeString( keys[i] );
- }
- }
- template<U32 COUNT>
- void LightAnimData::AnimValue<COUNT>::read( BitStream *stream )
- {
- for ( U32 i=0; i < COUNT; i++ )
- {
- stream->read( &value1[i] );
- stream->read( &value2[i] );
- stream->read( &period[i] );
- keys[i] = stream->readSTString();
- }
- }
- void LightAnimData::packData( BitStream *stream )
- {
- Parent::packData( stream );
- mOffset.write( stream );
- mRot.write( stream );
- mColor.write( stream );
- mBrightness.write( stream );
- }
- void LightAnimData::unpackData( BitStream *stream )
- {
- Parent::unpackData( stream );
- mOffset.read( stream );
- mRot.read( stream );
- mColor.read( stream );
- mBrightness.read( stream );
- }
- void LightAnimData::animate( LightInfo *lightInfo, LightAnimState *state )
- {
- PROFILE_SCOPE( LightAnimData_animate );
- // Calculate the input time for animation.
- F32 time = state->animationPhase +
- ( (F32)Sim::getCurrentTime() * 0.001f ) /
- state->animationPeriod;
- MatrixF transform( state->transform );
- EulerF euler( Point3F::Zero );
- if ( mRot.animate( time, euler ) )
- {
- euler.x = mDegToRad( euler.x );
- euler.y = mDegToRad( euler.y );
- euler.z = mDegToRad( euler.z );
- MatrixF rot( euler );
- transform.mul( rot );
- }
- Point3F offset( Point3F::Zero );
- if ( mOffset.animate( time, offset ) )
- transform.displace( offset );
- lightInfo->setTransform( transform );
- LinearColorF color = state->color;
- mColor.animate( time, color );
- lightInfo->setColor( color );
- F32 brightness = state->brightness;
- mBrightness.animate( time, &brightness, true );
- lightInfo->setBrightness( brightness );
- }
|