camerashakesystem.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. /*
  2. ** Command & Conquer Generals Zero Hour(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 <stdio.h>
  38. #include <stdlib.h>
  39. #include <string.h>
  40. #include <assetmgr.h>
  41. #include <texture.h>
  42. #include <tri.h>
  43. #include <colmath.h>
  44. #include <coltest.h>
  45. #include <rinfo.h>
  46. #include <camera.h>
  47. #include <d3dx8core.h>
  48. #include "Common/GlobalData.h"
  49. #include "Common/PerfTimer.h"
  50. #include "GameClient/TerrainVisual.h"
  51. #include "GameClient/View.h"
  52. #include "GameClient/Water.h"
  53. #include "GameLogic/AIPathfind.h"
  54. #include "GameLogic/TerrainLogic.h"
  55. #include "W3DDevice/GameClient/TerrainTex.h"
  56. #include "W3DDevice/GameClient/W3DDynamicLight.h"
  57. #include "W3DDevice/GameClient/W3DScene.h"
  58. #include "W3DDevice/GameClient/W3DTerrainTracks.h"
  59. #include "W3DDevice/GameClient/W3DBibBuffer.h"
  60. #include "W3DDevice/GameClient/W3DTreeBuffer.h"
  61. #include "W3DDevice/GameClient/W3DRoadBuffer.h"
  62. #include "W3DDevice/GameClient/W3DBridgeBuffer.h"
  63. #include "W3DDevice/GameClient/W3DWaypointBuffer.h"
  64. #include "W3DDevice/GameClient/W3DCustomEdging.h"
  65. #include "W3DDevice/GameClient/WorldHeightMap.h"
  66. #include "W3DDevice/GameClient/W3DShaderManager.h"
  67. #include "W3DDevice/GameClient/W3DShadow.h"
  68. #include "W3DDevice/GameClient/W3DWater.h"
  69. #include "W3DDevice/GameClient/W3DShroud.h"
  70. #include "WW3D2/DX8Wrapper.h"
  71. #include "WW3D2/Light.h"
  72. #include "WW3D2/Scene.h"
  73. #include "W3DDevice/GameClient/W3DPoly.h"
  74. #include "W3DDevice/GameClient/W3DCustomScene.h"
  75. #include "W3DDevice/GameClient/camerashakesystem.h"
  76. #include "WW3D2/Camera.h"
  77. //#include "W3DDevice/GameClient/camera.h"
  78. //#include "W3DDevice/GameClient/wwmemlog.h"
  79. /*
  80. ** (gth) According to my "research" the artists say that there are several factors that
  81. ** go into a good camera shake.
  82. ** - The motion should be sinusoidal.
  83. ** - Camera rotation is more effective than camera motion (good, I won't use any translation)
  84. ** - The camera should pitch up and down a lot more than it yaws left and right.
  85. */
  86. DEFINE_AUTO_POOL(CameraShakeSystemClass::CameraShakerClass,256);
  87. const float MIN_OMEGA = DEG_TO_RADF(12.5f*360.0f);
  88. const float MAX_OMEGA = DEG_TO_RADF(15.0f*360.0f);
  89. const float END_OMEGA = DEG_TO_RADF(360.0f);
  90. const float MIN_PHI = DEG_TO_RADF(0.0f);
  91. const float MAX_PHI = DEG_TO_RADF(360.0f);
  92. const Vector3 AXIS_ROTATION = Vector3(DEG_TO_RADF(7.5f),DEG_TO_RADF(15.0f),DEG_TO_RADF(5.0f));
  93. /************************************************************************************************
  94. **
  95. ** CameraShakeSystemClass::CameraShakerClass Implementation
  96. **
  97. ************************************************************************************************/
  98. CameraShakeSystemClass::CameraShakerClass::CameraShakerClass
  99. (
  100. const Vector3 & position,
  101. float radius,
  102. float duration,
  103. float intensity
  104. ) :
  105. Position(position),
  106. Radius(radius),
  107. Duration(duration),
  108. Intensity(intensity),
  109. ElapsedTime(0.0f)
  110. {
  111. /*
  112. ** Initialize random sinusoid values
  113. */
  114. Omega.X = WWMath::Random_Float(MIN_OMEGA,MAX_OMEGA);
  115. Omega.Y = WWMath::Random_Float(MIN_OMEGA,MAX_OMEGA);
  116. Omega.Z = WWMath::Random_Float(MIN_OMEGA,MAX_OMEGA);
  117. Phi.X = WWMath::Random_Float(MIN_PHI,MAX_PHI);
  118. Phi.Y = WWMath::Random_Float(MIN_PHI,MAX_PHI);
  119. Phi.Z = WWMath::Random_Float(MIN_PHI,MAX_PHI);
  120. }
  121. CameraShakeSystemClass::CameraShakerClass::~CameraShakerClass(void)
  122. {
  123. }
  124. void CameraShakeSystemClass::CameraShakerClass::Compute_Rotations(const Vector3 & camera_position, Vector3 * set_angles)
  125. {
  126. WWASSERT(set_angles != NULL);
  127. /*
  128. ** We want several different sinusiods, each with a different phase shift and
  129. ** frequency. The frequency is a function of time as well, stretching the
  130. ** sine wave out. These waves are modulated based on the distance from the
  131. ** center of the "shake", the intensity of the shake, and based on the axis
  132. ** being affected. The vertical axis should have about 3x the amplitude of
  133. ** the horizontal axis.
  134. */
  135. float len2 = (camera_position - Position).Length2();
  136. if (len2 > Radius*Radius) {
  137. return;
  138. }
  139. /*
  140. ** f(t) = intensity(t,pos) * sin( omega(t) * t + phi );
  141. ** intensity(t,pos) = intensity * (radius/distance) * timeremaing/totaltime
  142. ** omega(t) = start_omega + (end_omega - start_omega) * t
  143. ** phi = random(0..start_omega)
  144. */
  145. float intensity = Intensity * (1.0f - WWMath::Sqrt(len2) / Radius) * (1.0f - ElapsedTime / Duration);
  146. for (int i=0; i<3; i++) {
  147. float omega = Omega[i] + (END_OMEGA - Omega[i]) * ElapsedTime;
  148. (*set_angles)[i] += AXIS_ROTATION[i] * intensity * WWMath::Sin(omega * ElapsedTime + Phi[i]);
  149. //WST 11/14/2002. Add in additional random fudge. There seems to be a too mathematical pattern of shake with the above
  150. Vector3 secondary_angles;
  151. float minor_intensity = intensity * 0.5f;
  152. secondary_angles.X = WWMath::Random_Float(-minor_intensity,minor_intensity);
  153. secondary_angles.Y = WWMath::Random_Float(-minor_intensity,minor_intensity);
  154. secondary_angles.Z = WWMath::Random_Float(-minor_intensity,minor_intensity);
  155. (*set_angles) += secondary_angles;
  156. }
  157. }
  158. /************************************************************************************************
  159. **
  160. ** CameraShakeSystemClass Implementation
  161. **
  162. ************************************************************************************************/
  163. CameraShakeSystemClass::CameraShakeSystemClass(void)
  164. {
  165. }
  166. CameraShakeSystemClass::~CameraShakeSystemClass(void)
  167. {
  168. /*
  169. ** delete all of the objects out of the list
  170. */
  171. while (!CameraShakerList.Is_Empty()) {
  172. CameraShakerClass * obj = CameraShakerList.Remove_Head();
  173. CameraShakerList.Remove(obj);
  174. delete obj;
  175. }
  176. }
  177. void CameraShakeSystemClass::Add_Camera_Shake
  178. (
  179. const Vector3 & position,
  180. float radius,
  181. float duration,
  182. float power
  183. )
  184. {
  185. //WWMEMLOG(MEM_PHYSICSDATA);
  186. /*
  187. ** Allocate a new camera shaker object. Note that these are mem-pooled so the allocation
  188. ** is very cheap.
  189. */
  190. //Power is in degrees of amplitude.
  191. power = power * PI/180.0f;
  192. CameraShakerClass * shaker = new CameraShakerClass(position,radius,duration,power);
  193. CameraShakerList.Add(shaker);
  194. }
  195. bool CameraShakeSystemClass::IsCameraShaking(void)
  196. {
  197. /*
  198. ** Loop through to find if there is any active camera shakers
  199. */
  200. MultiListIterator<CameraShakerClass> iterator(&CameraShakerList);
  201. for (iterator.First(); !iterator.Is_Done(); iterator.Next()) {
  202. CameraShakerClass * obj = iterator.Peek_Obj();
  203. if (obj){
  204. return (true);
  205. }
  206. }
  207. return(false);
  208. }
  209. void CameraShakeSystemClass::Timestep(float dt)
  210. {
  211. /*
  212. ** Allow each camera shaker to timestep. Any that expire are added to a temporary
  213. ** list for deletion.
  214. */
  215. MultiListClass<CameraShakerClass> deletelist;
  216. MultiListIterator<CameraShakerClass> iterator(&CameraShakerList);
  217. for (iterator.First(); !iterator.Is_Done(); iterator.Next()) {
  218. CameraShakerClass * obj = iterator.Peek_Obj();
  219. obj->Timestep(dt);
  220. if (obj->Is_Expired()) {
  221. deletelist.Add(obj);
  222. }
  223. }
  224. /*
  225. ** Remove and delete all the ones that expired
  226. */
  227. while (!deletelist.Is_Empty()) {
  228. CameraShakerClass * obj = deletelist.Remove_Head();
  229. CameraShakerList.Remove(obj);
  230. delete obj;
  231. }
  232. }
  233. void CameraShakeSystemClass::Update_Camera_Shaker(Vector3 camera_position, Vector3 *shaker_angle)
  234. {
  235. MultiListIterator<CameraShakerClass> iterator(&CameraShakerList);
  236. Vector3 angles(0,0,0);
  237. Matrix3D camera_transform;
  238. //camera_transform = camera.Get_Transform();
  239. //camera_transform.Get_Translation(&camera_position);
  240. /*
  241. ** Accumulate the effects of any active camera shakers
  242. */
  243. for (iterator.First(); !iterator.Is_Done(); iterator.Next()) {
  244. iterator.Peek_Obj()->Compute_Rotations(camera_position,&angles);
  245. }
  246. /*
  247. ** Clamp the result
  248. */
  249. for (int i=0; i<3; i++) {
  250. WWMath::Clamp(angles[i],-AXIS_ROTATION[i],AXIS_ROTATION[i]);
  251. }
  252. *shaker_angle = angles;
  253. /*
  254. ** Apply to the camera
  255. */
  256. /*
  257. camera_transform.Rotate_X(angles.X);
  258. camera_transform.Rotate_Y(angles.Y);
  259. camera_transform.Rotate_Z(angles.Z);
  260. camera.Set_Transform(camera_transform);
  261. */
  262. }
  263. // The Instance of the system
  264. CameraShakeSystemClass CameraShakerSystem; //WST 11/12/2002 This is the new Camera Shaker system upgrade