camerashakesystem.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : WWPhys *
  23. * *
  24. * $Archive:: /Commando/Code/wwphys/camerashakesystem.cpp $*
  25. * *
  26. * Original Author:: Greg Hjelstrom *
  27. * *
  28. * $Author:: Greg_h $*
  29. * *
  30. * $Modtime:: 6/12/01 10:25a $*
  31. * *
  32. * $Revision:: 3 $*
  33. * *
  34. *---------------------------------------------------------------------------------------------*
  35. * Functions: *
  36. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  37. #include "camerashakesystem.h"
  38. #include "camera.h"
  39. #include "wwmemlog.h"
  40. /*
  41. ** (gth) According to my "research" the artists say that there are several factors that
  42. ** go into a good camera shake.
  43. ** - The motion should be sinusoidal.
  44. ** - Camera rotation is more effective than camera motion (good, I won't use any translation)
  45. ** - The camera should pitch up and down a lot more than it yaws left and right.
  46. */
  47. DEFINE_AUTO_POOL(CameraShakeSystemClass::CameraShakerClass,256);
  48. const float MIN_OMEGA = DEG_TO_RADF(12.5f*360.0f);
  49. const float MAX_OMEGA = DEG_TO_RADF(15.0f*360.0f);
  50. const float END_OMEGA = DEG_TO_RADF(360.0f);
  51. const float MIN_PHI = DEG_TO_RADF(0.0f);
  52. const float MAX_PHI = DEG_TO_RADF(360.0f);
  53. const Vector3 AXIS_ROTATION = Vector3(DEG_TO_RADF(7.5f),DEG_TO_RADF(15.0f),DEG_TO_RADF(5.0f));
  54. /************************************************************************************************
  55. **
  56. ** CameraShakeSystemClass::CameraShakerClass Implementation
  57. **
  58. ************************************************************************************************/
  59. CameraShakeSystemClass::CameraShakerClass::CameraShakerClass
  60. (
  61. const Vector3 & position,
  62. float radius,
  63. float duration,
  64. float intensity
  65. ) :
  66. Position(position),
  67. Radius(radius),
  68. Duration(duration),
  69. Intensity(intensity),
  70. ElapsedTime(0.0f)
  71. {
  72. /*
  73. ** Initialize random sinusoid values
  74. */
  75. Omega.X = WWMath::Random_Float(MIN_OMEGA,MAX_OMEGA);
  76. Omega.Y = WWMath::Random_Float(MIN_OMEGA,MAX_OMEGA);
  77. Omega.Z = WWMath::Random_Float(MIN_OMEGA,MAX_OMEGA);
  78. Phi.X = WWMath::Random_Float(MIN_PHI,MAX_PHI);
  79. Phi.Y = WWMath::Random_Float(MIN_PHI,MAX_PHI);
  80. Phi.Z = WWMath::Random_Float(MIN_PHI,MAX_PHI);
  81. }
  82. CameraShakeSystemClass::CameraShakerClass::~CameraShakerClass(void)
  83. {
  84. }
  85. void CameraShakeSystemClass::CameraShakerClass::Compute_Rotations(const Vector3 & camera_position, Vector3 * set_angles)
  86. {
  87. WWASSERT(set_angles != NULL);
  88. /*
  89. ** We want several different sinusiods, each with a different phase shift and
  90. ** frequency. The frequency is a function of time as well, stretching the
  91. ** sine wave out. These waves are modulated based on the distance from the
  92. ** center of the "shake", the intensity of the shake, and based on the axis
  93. ** being affected. The vertical axis should have about 3x the amplitude of
  94. ** the horizontal axis.
  95. */
  96. float len2 = (camera_position - Position).Length2();
  97. if (len2 > Radius*Radius) {
  98. return;
  99. }
  100. /*
  101. ** f(t) = intensity(t,pos) * sin( omega(t) * t + phi );
  102. ** intensity(t,pos) = intensity * (radius/distance) * timeremaing/totaltime
  103. ** omega(t) = start_omega + (end_omega - start_omega) * t
  104. ** phi = random(0..start_omega)
  105. */
  106. float intensity = Intensity * (1.0f - WWMath::Sqrt(len2) / Radius) * (1.0f - ElapsedTime / Duration);
  107. for (int i=0; i<3; i++) {
  108. float omega = Omega[i] + (END_OMEGA - Omega[i]) * ElapsedTime;
  109. (*set_angles)[i] += AXIS_ROTATION[i] * intensity * WWMath::Sin(omega * ElapsedTime + Phi[i]);
  110. }
  111. }
  112. /************************************************************************************************
  113. **
  114. ** CameraShakeSystemClass Implementation
  115. **
  116. ************************************************************************************************/
  117. CameraShakeSystemClass::CameraShakeSystemClass(void)
  118. {
  119. }
  120. CameraShakeSystemClass::~CameraShakeSystemClass(void)
  121. {
  122. /*
  123. ** delete all of the objects out of the list
  124. */
  125. while (!CameraShakerList.Is_Empty()) {
  126. CameraShakerClass * obj = CameraShakerList.Remove_Head();
  127. CameraShakerList.Remove(obj);
  128. delete obj;
  129. }
  130. }
  131. void CameraShakeSystemClass::Add_Camera_Shake
  132. (
  133. const Vector3 & position,
  134. float radius,
  135. float duration,
  136. float power
  137. )
  138. {
  139. WWMEMLOG(MEM_PHYSICSDATA);
  140. /*
  141. ** Allocate a new camera shaker object. Note that these are mem-pooled so the allocation
  142. ** is very cheap.
  143. */
  144. CameraShakerClass * shaker = new CameraShakerClass(position,radius,duration,power);
  145. CameraShakerList.Add(shaker);
  146. }
  147. void CameraShakeSystemClass::Timestep(float dt)
  148. {
  149. /*
  150. ** Allow each camera shaker to timestep. Any that expire are added to a temporary
  151. ** list for deletion.
  152. */
  153. MultiListClass<CameraShakerClass> deletelist;
  154. MultiListIterator<CameraShakerClass> iterator(&CameraShakerList);
  155. for (iterator.First(); !iterator.Is_Done(); iterator.Next()) {
  156. CameraShakerClass * obj = iterator.Peek_Obj();
  157. obj->Timestep(dt);
  158. if (obj->Is_Expired()) {
  159. deletelist.Add(obj);
  160. }
  161. }
  162. /*
  163. ** Remove and delete all the ones that expired
  164. */
  165. while (!deletelist.Is_Empty()) {
  166. CameraShakerClass * obj = deletelist.Remove_Head();
  167. CameraShakerList.Remove(obj);
  168. delete obj;
  169. }
  170. }
  171. void CameraShakeSystemClass::Update_Camera(CameraClass & camera)
  172. {
  173. MultiListIterator<CameraShakerClass> iterator(&CameraShakerList);
  174. Vector3 angles(0,0,0);
  175. Vector3 camera_position;
  176. Matrix3D camera_transform;
  177. camera_transform = camera.Get_Transform();
  178. camera_transform.Get_Translation(&camera_position);
  179. /*
  180. ** Accumulate the effects of any active camera shakers
  181. */
  182. for (iterator.First(); !iterator.Is_Done(); iterator.Next()) {
  183. iterator.Peek_Obj()->Compute_Rotations(camera_position,&angles);
  184. }
  185. /*
  186. ** Clamp the result
  187. */
  188. for (int i=0; i<3; i++) {
  189. WWMath::Clamp(angles[i],-AXIS_ROTATION[i],AXIS_ROTATION[i]);
  190. }
  191. /*
  192. ** Apply to the camera
  193. */
  194. camera_transform.Rotate_X(angles.X);
  195. camera_transform.Rotate_Y(angles.Y);
  196. camera_transform.Rotate_Z(angles.Z);
  197. camera.Set_Transform(camera_transform);
  198. }