mirror of
https://github.com/electronicarts/CnC_Renegade.git
synced 2025-12-15 23:21:40 -05:00
Initial commit of Command & Conquer Renegade source code.
This commit is contained in:
223
Code/wwphys/camerashakesystem.cpp
Normal file
223
Code/wwphys/camerashakesystem.cpp
Normal file
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***********************************************************************************************
|
||||
*** 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 ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : WWPhys *
|
||||
* *
|
||||
* $Archive:: /Commando/Code/wwphys/camerashakesystem.cpp $*
|
||||
* *
|
||||
* Original Author:: Greg Hjelstrom *
|
||||
* *
|
||||
* $Author:: Greg_h $*
|
||||
* *
|
||||
* $Modtime:: 6/12/01 10:25a $*
|
||||
* *
|
||||
* $Revision:: 3 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#include "camerashakesystem.h"
|
||||
#include "camera.h"
|
||||
#include "wwmemlog.h"
|
||||
|
||||
/*
|
||||
** (gth) According to my "research" the artists say that there are several factors that
|
||||
** go into a good camera shake.
|
||||
** - The motion should be sinusoidal.
|
||||
** - Camera rotation is more effective than camera motion (good, I won't use any translation)
|
||||
** - The camera should pitch up and down a lot more than it yaws left and right.
|
||||
*/
|
||||
|
||||
DEFINE_AUTO_POOL(CameraShakeSystemClass::CameraShakerClass,256);
|
||||
|
||||
const float MIN_OMEGA = DEG_TO_RADF(12.5f*360.0f);
|
||||
const float MAX_OMEGA = DEG_TO_RADF(15.0f*360.0f);
|
||||
const float END_OMEGA = DEG_TO_RADF(360.0f);
|
||||
const float MIN_PHI = DEG_TO_RADF(0.0f);
|
||||
const float MAX_PHI = DEG_TO_RADF(360.0f);
|
||||
const Vector3 AXIS_ROTATION = Vector3(DEG_TO_RADF(7.5f),DEG_TO_RADF(15.0f),DEG_TO_RADF(5.0f));
|
||||
|
||||
/************************************************************************************************
|
||||
**
|
||||
** CameraShakeSystemClass::CameraShakerClass Implementation
|
||||
**
|
||||
************************************************************************************************/
|
||||
CameraShakeSystemClass::CameraShakerClass::CameraShakerClass
|
||||
(
|
||||
const Vector3 & position,
|
||||
float radius,
|
||||
float duration,
|
||||
float intensity
|
||||
) :
|
||||
Position(position),
|
||||
Radius(radius),
|
||||
Duration(duration),
|
||||
Intensity(intensity),
|
||||
ElapsedTime(0.0f)
|
||||
{
|
||||
/*
|
||||
** Initialize random sinusoid values
|
||||
*/
|
||||
Omega.X = WWMath::Random_Float(MIN_OMEGA,MAX_OMEGA);
|
||||
Omega.Y = WWMath::Random_Float(MIN_OMEGA,MAX_OMEGA);
|
||||
Omega.Z = WWMath::Random_Float(MIN_OMEGA,MAX_OMEGA);
|
||||
Phi.X = WWMath::Random_Float(MIN_PHI,MAX_PHI);
|
||||
Phi.Y = WWMath::Random_Float(MIN_PHI,MAX_PHI);
|
||||
Phi.Z = WWMath::Random_Float(MIN_PHI,MAX_PHI);
|
||||
}
|
||||
|
||||
CameraShakeSystemClass::CameraShakerClass::~CameraShakerClass(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void CameraShakeSystemClass::CameraShakerClass::Compute_Rotations(const Vector3 & camera_position, Vector3 * set_angles)
|
||||
{
|
||||
WWASSERT(set_angles != NULL);
|
||||
|
||||
/*
|
||||
** We want several different sinusiods, each with a different phase shift and
|
||||
** frequency. The frequency is a function of time as well, stretching the
|
||||
** sine wave out. These waves are modulated based on the distance from the
|
||||
** center of the "shake", the intensity of the shake, and based on the axis
|
||||
** being affected. The vertical axis should have about 3x the amplitude of
|
||||
** the horizontal axis.
|
||||
*/
|
||||
float len2 = (camera_position - Position).Length2();
|
||||
if (len2 > Radius*Radius) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
** f(t) = intensity(t,pos) * sin( omega(t) * t + phi );
|
||||
** intensity(t,pos) = intensity * (radius/distance) * timeremaing/totaltime
|
||||
** omega(t) = start_omega + (end_omega - start_omega) * t
|
||||
** phi = random(0..start_omega)
|
||||
*/
|
||||
float intensity = Intensity * (1.0f - WWMath::Sqrt(len2) / Radius) * (1.0f - ElapsedTime / Duration);
|
||||
for (int i=0; i<3; i++) {
|
||||
float omega = Omega[i] + (END_OMEGA - Omega[i]) * ElapsedTime;
|
||||
(*set_angles)[i] += AXIS_ROTATION[i] * intensity * WWMath::Sin(omega * ElapsedTime + Phi[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************************************
|
||||
**
|
||||
** CameraShakeSystemClass Implementation
|
||||
**
|
||||
************************************************************************************************/
|
||||
CameraShakeSystemClass::CameraShakeSystemClass(void)
|
||||
{
|
||||
}
|
||||
|
||||
CameraShakeSystemClass::~CameraShakeSystemClass(void)
|
||||
{
|
||||
/*
|
||||
** delete all of the objects out of the list
|
||||
*/
|
||||
while (!CameraShakerList.Is_Empty()) {
|
||||
CameraShakerClass * obj = CameraShakerList.Remove_Head();
|
||||
CameraShakerList.Remove(obj);
|
||||
delete obj;
|
||||
}
|
||||
}
|
||||
|
||||
void CameraShakeSystemClass::Add_Camera_Shake
|
||||
(
|
||||
const Vector3 & position,
|
||||
float radius,
|
||||
float duration,
|
||||
float power
|
||||
)
|
||||
{
|
||||
WWMEMLOG(MEM_PHYSICSDATA);
|
||||
/*
|
||||
** Allocate a new camera shaker object. Note that these are mem-pooled so the allocation
|
||||
** is very cheap.
|
||||
*/
|
||||
CameraShakerClass * shaker = new CameraShakerClass(position,radius,duration,power);
|
||||
CameraShakerList.Add(shaker);
|
||||
}
|
||||
|
||||
void CameraShakeSystemClass::Timestep(float dt)
|
||||
{
|
||||
/*
|
||||
** Allow each camera shaker to timestep. Any that expire are added to a temporary
|
||||
** list for deletion.
|
||||
*/
|
||||
MultiListClass<CameraShakerClass> deletelist;
|
||||
MultiListIterator<CameraShakerClass> iterator(&CameraShakerList);
|
||||
for (iterator.First(); !iterator.Is_Done(); iterator.Next()) {
|
||||
CameraShakerClass * obj = iterator.Peek_Obj();
|
||||
obj->Timestep(dt);
|
||||
if (obj->Is_Expired()) {
|
||||
deletelist.Add(obj);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Remove and delete all the ones that expired
|
||||
*/
|
||||
while (!deletelist.Is_Empty()) {
|
||||
CameraShakerClass * obj = deletelist.Remove_Head();
|
||||
CameraShakerList.Remove(obj);
|
||||
delete obj;
|
||||
}
|
||||
}
|
||||
|
||||
void CameraShakeSystemClass::Update_Camera(CameraClass & camera)
|
||||
{
|
||||
MultiListIterator<CameraShakerClass> iterator(&CameraShakerList);
|
||||
|
||||
Vector3 angles(0,0,0);
|
||||
Vector3 camera_position;
|
||||
Matrix3D camera_transform;
|
||||
|
||||
camera_transform = camera.Get_Transform();
|
||||
camera_transform.Get_Translation(&camera_position);
|
||||
|
||||
/*
|
||||
** Accumulate the effects of any active camera shakers
|
||||
*/
|
||||
for (iterator.First(); !iterator.Is_Done(); iterator.Next()) {
|
||||
iterator.Peek_Obj()->Compute_Rotations(camera_position,&angles);
|
||||
}
|
||||
|
||||
/*
|
||||
** Clamp the result
|
||||
*/
|
||||
for (int i=0; i<3; i++) {
|
||||
WWMath::Clamp(angles[i],-AXIS_ROTATION[i],AXIS_ROTATION[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
** Apply to the camera
|
||||
*/
|
||||
camera_transform.Rotate_X(angles.X);
|
||||
camera_transform.Rotate_Y(angles.Y);
|
||||
camera_transform.Rotate_Z(angles.Z);
|
||||
camera.Set_Transform(camera_transform);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user