afxEA_CameraShake.cpp
Engine/source/afx/ea/afxEA_CameraShake.cpp
Classes:
class
Detailed Description
1 2 3//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 4// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames 5// Copyright (C) 2015 Faust Logic, Inc. 6// 7// Permission is hereby granted, free of charge, to any person obtaining a copy 8// of this software and associated documentation files (the "Software"), to 9// deal in the Software without restriction, including without limitation the 10// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 11// sell copies of the Software, and to permit persons to whom the Software is 12// furnished to do so, subject to the following conditions: 13// 14// The above copyright notice and this permission notice shall be included in 15// all copies or substantial portions of the Software. 16// 17// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23// IN THE SOFTWARE. 24// 25//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 26 27#include <typeinfo> 28#include "afx/arcaneFX.h" 29 30#include "T3D/fx/cameraFXMgr.h" 31 32#include "afx/afxEffectDefs.h" 33#include "afx/afxEffectWrapper.h" 34#include "afx/afxChoreographer.h" 35#include "afx/ce/afxCameraShake.h" 36 37//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 38// afxEA_CameraShake 39 40class afxEA_CameraShake : public afxEffectWrapper 41{ 42 typedef afxEffectWrapper Parent; 43 44 afxCameraShakeData* shake_data; 45 CameraShake* camera_shake; 46 47 void do_runtime_substitutions(); 48 49public: 50 /*C*/ afxEA_CameraShake(); 51 /*D*/ ~afxEA_CameraShake(); 52 53 virtual void ea_set_datablock(SimDataBlock*); 54 virtual bool ea_start(); 55 virtual bool ea_update(F32 dt); 56 virtual void ea_finish(bool was_stopped); 57}; 58 59//~~~~~~~~~~~~~~~~~~~~// 60 61afxEA_CameraShake::afxEA_CameraShake() 62{ 63 shake_data = 0; 64 camera_shake = 0; 65} 66 67afxEA_CameraShake::~afxEA_CameraShake() 68{ 69 delete camera_shake; 70 if (shake_data && shake_data->isTempClone()) 71 delete shake_data; 72 shake_data = 0; 73} 74 75void afxEA_CameraShake::ea_set_datablock(SimDataBlock* db) 76{ 77 shake_data = dynamic_cast<afxCameraShakeData*>(db); 78} 79 80bool afxEA_CameraShake::ea_start() 81{ 82 if (!shake_data) 83 { 84 Con::errorf("afxEA_CameraShake::ea_start() -- missing or incompatible datablock."); 85 return false; 86 } 87 88 do_runtime_substitutions(); 89 90 afxConstraint* pos_constraint = getPosConstraint(); 91 afxConstraint* aim_constraint = getAimConstraint(); 92 93 if (aim_constraint && pos_constraint) 94 { 95 if (mFull_lifetime <= 0 || mFull_lifetime == INFINITE_LIFETIME) 96 { 97 Con::errorf("afxEA_CameraShake::ea_start() -- effect requires a finite lifetime."); 98 return false; 99 } 100 101 SceneObject* shaken = aim_constraint->getSceneObject(); 102 if (shaken) 103 { 104 Point3F pos; pos_constraint->getPosition(pos); 105 VectorF diff = shaken->getPosition() - pos; 106 F32 dist = diff.len(); 107 if (dist < shake_data->camShakeRadius) 108 { 109 camera_shake = new CameraShake; 110 camera_shake->setDuration(mFull_lifetime); 111 camera_shake->setFrequency(shake_data->camShakeFreq); 112 113 F32 falloff = dist/shake_data->camShakeRadius; 114 falloff = 1 + falloff*10.0; 115 falloff = 1.0 / (falloff*falloff); 116 117 VectorF shakeAmp = shake_data->camShakeAmp*falloff; 118 camera_shake->setAmplitude(shakeAmp); 119 camera_shake->setFalloff(shake_data->camShakeFalloff); 120 camera_shake->init(); 121 } 122 } 123 } 124 125 return true; 126} 127 128bool afxEA_CameraShake::ea_update(F32 dt) 129{ 130 afxConstraint* aim_constraint = getAimConstraint(); 131 if (camera_shake && aim_constraint) 132 { 133 camera_shake->update(dt); 134 135 SceneObject* shaken = aim_constraint->getSceneObject(); 136 if (shaken) 137 { 138 MatrixF fxTrans = camera_shake->getTrans(); 139 MatrixF curTrans = shaken->getRenderTransform(); 140 curTrans.mul(fxTrans); 141 142 Point3F cameraPosWorld; 143 curTrans.getColumn(3,&cameraPosWorld); 144 shaken->setPosition(cameraPosWorld); 145 } 146 } 147 148 return true; 149} 150 151void afxEA_CameraShake::ea_finish(bool was_stopped) 152{ 153 delete camera_shake; 154 camera_shake = 0; 155} 156 157void afxEA_CameraShake::do_runtime_substitutions() 158{ 159 // only clone the datablock if there are substitutions 160 if (shake_data->getSubstitutionCount() > 0) 161 { 162 // clone the datablock and perform substitutions 163 afxCameraShakeData* orig_db = shake_data; 164 shake_data = new afxCameraShakeData(*orig_db, true); 165 orig_db->performSubstitutions(shake_data, mChoreographer, mGroup_index); 166 } 167} 168 169//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 170 171class afxEA_CameraShakeDesc : public afxEffectAdapterDesc, public afxEffectDefs 172{ 173 static afxEA_CameraShakeDesc desc; 174 175public: 176 virtual bool testEffectType(const SimDataBlock*) const; 177 virtual bool requiresStop(const afxEffectWrapperData*, const afxEffectTimingData&) const; 178 virtual bool runsOnServer(const afxEffectWrapperData*) const { return false; } 179 virtual bool runsOnClient(const afxEffectWrapperData*) const { return true; } 180 virtual bool isPositional(const afxEffectWrapperData*) const { return false; } 181 182 virtual afxEffectWrapper* create() const { return new afxEA_CameraShake; } 183}; 184 185afxEA_CameraShakeDesc afxEA_CameraShakeDesc::desc; 186 187bool afxEA_CameraShakeDesc::testEffectType(const SimDataBlock* db) const 188{ 189 return (typeid(afxCameraShakeData) == typeid(*db)); 190} 191 192bool afxEA_CameraShakeDesc::requiresStop(const afxEffectWrapperData* ew, const afxEffectTimingData& timing) const 193{ 194 return (timing.lifetime < 0); 195} 196 197//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 198