Commit 6d94c9d3 by Martin Turski

added EditorCameraControls class, an example of interpolated camera movement…

added EditorCameraControls class, an example of interpolated camera movement management + various changes
parent fe1bee7a
......@@ -35,6 +35,9 @@ public:
math::Frustum GetSimpleFrustum( void ) const;
math::Quader GetComplexFrustum( void ) const;
rw::Frame* GetRWFrame( void ) { return this->camFrame; }
rw::Camera* GetRWCamera( void ) { return this->rwCamera; }
private:
bool isRendering;
void *rendering_context;
......
#pragma once
#include "Camera.h"
#include "sys/Timer.h"
namespace krt
{
struct EditorCameraControls
{
EditorCameraControls( void );
~EditorCameraControls( void );
void OnFrame( Camera *camera );
void SetAccelerationTime( unsigned int time );
// Velocity manipulation functions.
void AddRightVelocity( float velo ) { this->right_velo.GiveVelocity( this->right_velo.GetCurrent() + velo ); }
void SetRightVelocity( float velo ) { this->right_velo.GiveVelocity( velo ); }
float GetRightVelocity( void ) { return this->right_velo.GetCurrent(); }
void StopRightVelocity( void ) { this->right_velo.StopMovement(); }
void AddFrontVelocity( float velo ) { this->front_velo.GiveVelocity( this->front_velo.GetCurrent() + velo ); }
void SetFrontVelocity( float velo ) { this->front_velo.GiveVelocity( velo ); }
float GetFrontVelocity( void ) { return this->front_velo.GetCurrent(); }
void StopFrontVelocity( void ) { this->front_velo.StopMovement(); }
void AddUpVelocity( float velo ) { this->up_velo.GiveVelocity( this->up_velo.GetCurrent() + velo ); }
void SetUpVelocity( float velo ) { this->up_velo.GiveVelocity( velo ); }
float GetUpVelocity( void ) { return this->up_velo.GetCurrent(); }
void StopUpVelocity( void ) { this->up_velo.StopMovement(); }
void AddPitchVelocity( float velo ) { this->pitch_velo.GiveVelocity( this->pitch_velo.GetCurrent() + velo ); }
void SetPitchVelocity( float velo ) { this->pitch_velo.GiveVelocity( velo ); }
float GetPitchVelocity( void ) { return this->pitch_velo.GetCurrent(); }
void StopPitchVelocity( void ) { this->pitch_velo.StopMovement(); }
void AddYawVelocity( float velo ) { this->yaw_velo.GiveVelocity( this->yaw_velo.GetCurrent() + velo ); }
void SetYawVelocity( float velo ) { this->yaw_velo.GiveVelocity( velo ); }
float GetYawVelocity( void ) { return this->yaw_velo.GetCurrent(); }
void StopYawVelocity( void ) { this->yaw_velo.StopMovement(); }
void StopVelocity( void )
{
this->right_velo.StopMovement();
this->front_velo.StopMovement();
this->up_velo.StopMovement();
this->yaw_velo.StopMovement();
this->pitch_velo.StopMovement();
}
private:
typedef uint64_t timer_t;
template <typename numberType>
struct InterpolatedVelocity
{
inline InterpolatedVelocity( void )
{
this->isMoving = false;
this->isStopping = false;
this->acceleration_time = 1000;
}
inline void GiveVelocity( float speed )
{
timer_t cur_milli = sys::Milliseconds();
this->velocity_at_start_request = this->GetAtTime( cur_milli );
this->start_velocity = cur_milli;
this->isStopping = false;
this->isMoving = true;
this->requested_velocity = speed;
}
inline void StopMovement( void )
{
if ( this->isMoving )
{
// Update current status.
timer_t cur_milli = sys::Milliseconds();
this->velocity_at_start_request = this->GetAtTime( cur_milli );
this->start_velocity = cur_milli;
this->isStopping = true;
this->isMoving = false;
}
}
inline void SetAccelerationInterval( timer_t interval_ms )
{
assert( isMoving == false && isStopping == false );
this->acceleration_time = interval_ms;
// TODO: update the current velocity.
}
inline numberType GetCurrent( void )
{
timer_t cur_milli = sys::Milliseconds();
numberType currentVelo = this->GetAtTime( cur_milli );
return currentVelo;
}
private:
inline numberType GetElapsedInterval( timer_t milli ) const
{
return std::min( (numberType)1.0, ( (numberType)( milli - this->start_velocity ) / (numberType)acceleration_time ) );
}
inline numberType GetAtTime( timer_t cur_milli )
{
if ( this->isMoving )
{
const numberType elapsed_interval = GetElapsedInterval( cur_milli );
numberType velocity_to_add = ( this->requested_velocity - this->velocity_at_start_request ) * elapsed_interval;
return ( this->velocity_at_start_request + velocity_to_add );
}
else if ( this->isStopping )
{
const numberType elapsed_interval = GetElapsedInterval( cur_milli );
return ( this->velocity_at_start_request * ( (numberType)1.0 - elapsed_interval ) );
}
return 0;
}
numberType velocity_at_start_request;
numberType requested_velocity;
bool isMoving;
bool isStopping;
timer_t start_velocity;
timer_t acceleration_time;
};
InterpolatedVelocity <float> right_velo;
InterpolatedVelocity <float> front_velo;
InterpolatedVelocity <float> up_velo;
InterpolatedVelocity <float> yaw_velo;
InterpolatedVelocity <float> pitch_velo;
};
}
\ No newline at end of file
......@@ -51,6 +51,9 @@ class Game
Camera& GetWorldCamera(void) { return this->worldCam; }
void SetActiveCamera( Camera *theCamera ) { this->activeCam = theCamera; }
Camera* GetActiveCamera( void ) { return this->activeCam; }
private:
void MountUserDirectory();
......@@ -81,6 +84,8 @@ class Game
Camera worldCam; // camera to render the main world in
Camera *activeCam;
private:
std::unique_ptr<ConVar<int>> maxFPSVariable;
......
#include "StdInc.h"
#include "Camera.h"
#include "Game.h"
// Camera is responsible for setting up the rendering context.
#include <windows.h>
#include <d3d9.h>
......@@ -94,6 +96,11 @@ void Camera::BeginUpdate( void *gpuContext )
if ( this->isRendering )
return;
// Make sure no other camera is active.
assert( theGame->GetActiveCamera() == NULL );
theGame->SetActiveCamera( this );
// perform rendering
IDirect3DDevice9* device = reinterpret_cast<IDirect3DDevice9*>(gpuContext);
......@@ -138,6 +145,10 @@ void Camera::EndUpdate( void )
if ( !this->isRendering )
return;
assert( theGame->GetActiveCamera() == this );
// TODO: maybe we want to make this more beautiful.
// Finish rendering and present.
IDirect3DDevice9* device = reinterpret_cast<IDirect3DDevice9*>( this->rendering_context );
......@@ -150,6 +161,8 @@ void Camera::EndUpdate( void )
this->rendering_context = NULL;
this->isRendering = false;
theGame->SetActiveCamera( NULL );
}
void Camera::SetFOV( float fov_radians )
......
#include "StdInc.h"
#include "CameraControls.h"
#include "Game.h"
// Simple camera movement classes for map viewer and things.
namespace krt
{
EditorCameraControls::EditorCameraControls( void )
{
// Do some tests.
}
EditorCameraControls::~EditorCameraControls( void )
{
return;
}
static float normalize_angle( float angle )
{
if ( isnan( angle ) || isinf( angle ) )
return 0;
while ( angle < 0 )
{
angle += 360;
}
while ( angle >= 360 )
{
angle -= 360;
}
return angle;
}
// A little messy but hopefully it works.
inline void matrix_get_yaw_pitch( const rw::Matrix& viewMat, float& yaw_out, float& pitch_out )
{
float xy_length = rw::length( rw::V3d( viewMat.at.x, viewMat.at.y, 0.0f ) );
float z_front = viewMat.at.z;
if ( z_front > 0.99999 )
{
pitch_out = 90;
}
else if ( z_front < -0.99999 )
{
pitch_out = -90;
}
else
{
pitch_out = (float)RAD2DEG( atan2( z_front, xy_length ) );
}
if ( abs(z_front) > 0.99999 )
{
if ( viewMat.up.y < 0 )
{
yaw_out = 270 - (float)RAD2DEG( atan2( viewMat.up.y, viewMat.up.x ) );
}
else
{
yaw_out = 270 - (float)RAD2DEG( atan2( viewMat.up.y, viewMat.up.x ) );
}
}
else
{
if ( viewMat.at.y < 0 )
{
yaw_out = 90 - (float)RAD2DEG( atan2( viewMat.at.y, viewMat.at.x ) );
}
else
{
yaw_out = 90 - (float)RAD2DEG( atan2( viewMat.at.y, viewMat.at.x ) );
}
}
yaw_out = normalize_angle( yaw_out );
}
inline void matrix_from_yaw_pitch( rw::Matrix& matOut, float yaw, float pitch )
{
double yaw_rad = DEG2RAD( yaw );
double pitch_rad = DEG2RAD( pitch );
float at_vec_x_pos = (float)sin( yaw_rad );
float at_vec_y_pos = (float)cos( yaw_rad );
float at_vec_height = (float)sin( pitch_rad );
float at_xy_vec_length = (float)cos( pitch_rad );
rw::V3d at_vector = rw::normalize( rw::V3d( at_vec_x_pos * at_xy_vec_length, at_vec_y_pos * at_xy_vec_length, at_vec_height ) );
rw::V3d up_vector;
rw::V3d right_vector;
if ( at_vector.z == 1 )
{
up_vector = rw::V3d( -at_vec_x_pos, -at_vec_y_pos, 0 );
right_vector = rw::normalize( rw::cross( at_vector, up_vector ) );
}
else if ( at_vector.z == -1 )
{
up_vector = rw::V3d( at_vec_x_pos, at_vec_y_pos, 0 );
right_vector = rw::normalize( rw::cross( at_vector, up_vector ) );
}
else
{
rw::V3d normalizator( 0, 0, 1 );
right_vector = rw::normalize( rw::cross( normalizator, at_vector ) );
up_vector = rw::normalize( rw::cross( at_vector, right_vector ) );
}
matOut.right = right_vector;
matOut.rightw = 0;
matOut.up = up_vector;
matOut.upw = 0;
matOut.at = at_vector;
matOut.atw = 0;
}
void EditorCameraControls::OnFrame( Camera *camera )
{
// Move the camera.
rw::Matrix camView = camera->GetViewMatrix();
float frame_delta = theGame->GetDelta();
// Linear velocity.
rw::V3d linear_velo( this->right_velo.GetCurrent(), this->up_velo.GetCurrent(), this->front_velo.GetCurrent() );
rw::V3d frame_linear_velo = rw::scale( linear_velo, frame_delta );
rw::V3d new_cam_pos = camView.transPoint( frame_linear_velo );
camView.pos = new_cam_pos;
// Linear turn velocity, based on euler angles.
{
double yaw_velo_val = this->yaw_velo.GetCurrent() * frame_delta;
double pitch_velo_val = this->pitch_velo.GetCurrent() * frame_delta;
if ( yaw_velo_val != 0 || pitch_velo_val != 0 )
{
rw::Matrix cur_frame_rotate;
cur_frame_rotate.setIdentity();
float cur_yaw, cur_pitch;
matrix_get_yaw_pitch( camView, cur_yaw, cur_pitch );
// Make sure we do not go overboard, so limit pitch.
float new_pitch = std::max( -90.0f, std::min( 90.0f, (float)( cur_pitch + pitch_velo_val ) ) );
matrix_from_yaw_pitch( camView, cur_yaw + yaw_velo_val, new_pitch );
}
}
camera->SetViewMatrix( camView );
}
void EditorCameraControls::SetAccelerationTime( unsigned int time )
{
this->front_velo.SetAccelerationInterval( time );
this->right_velo.SetAccelerationInterval( time );
this->up_velo.SetAccelerationInterval( time );
}
};
\ No newline at end of file
......@@ -49,6 +49,9 @@ Game::Game(const std::vector<std::pair<std::string, std::string>>& setList) : st
gta::attachPlugins();
// Keep track of the active camera, because only one camera can be active at a time in our engine.
this->activeCam = NULL;
// Prepare main world camera. (NOT FINAL).
worldCam.Initialize();
......@@ -77,6 +80,8 @@ Game::Game(const std::vector<std::pair<std::string, std::string>>& setList) : st
Game::~Game(void)
{
assert( this->activeCam == NULL );
// Delete important RW resources owned by the game.
worldCam.Shutdown();
......
......@@ -8,6 +8,9 @@
#include "Console.CommandHelpers.h"
#include "Camera.h"
#include "CameraControls.h"
#include "sys/Timer.h"
namespace krt
{
......@@ -34,8 +37,6 @@ World::~World( void )
// TODO: add more cool world stuff.
#define DEG2RAD( x ) (x*3.14159265/180)
inline rw::V3d corvec( rw::V3d rwvec )
{
return rwvec;
......@@ -105,19 +106,50 @@ void World::RenderWorld( void *gfxDevice )
rw::V3d objectPosition(0.0f, 0.0f, 0.0f);
#endif
rw::V3d forward = rw::normalize(rw::sub(objectPosition, cameraPosition));
rw::V3d left = rw::normalize(rw::cross(rw::V3d(0.0f, 0.0f, 1.0f), forward));
rw::V3d up = rw::cross(forward, left);
static bool hasInitializedWorldCam = false;
if ( !hasInitializedWorldCam )
{
worldCam.SetFarClip( 1150 );
rw::V3d forward = rw::normalize(rw::sub(objectPosition, cameraPosition));
rw::V3d left = rw::normalize(rw::cross(rw::V3d(0.0f, 0.0f, 1.0f), forward));
rw::V3d up = rw::cross(forward, left);
rw::Matrix viewMat;
viewMat.setIdentity();
viewMat.right = left;
viewMat.up = up;
viewMat.at = forward;
viewMat.pos = cameraPosition;
worldCam.SetViewMatrix( viewMat );
hasInitializedWorldCam = true;
}
rw::Matrix viewMat;
viewMat.setIdentity();
#if 1
// Do a little test, meow.
uint64_t cur_time = sys::Milliseconds();
viewMat.right = left;
viewMat.up = up;
viewMat.at = forward;
viewMat.pos = cameraPosition;
worldCam.SetViewMatrix( viewMat );
unsigned int cur_divisor = ( ( cur_time / 500 ) % 2 );
static EditorCameraControls editorControls;
editorControls.SetYawVelocity( 40 );
if ( cur_divisor == 0 )
{
editorControls.SetPitchVelocity( 40 );
}
else if ( cur_divisor == 1 )
{
editorControls.SetPitchVelocity( -40 );
}
editorControls.OnFrame( &worldCam );
#endif
}
// Begin the rendering.
......
......@@ -2199,7 +2199,7 @@ void MatrixToEulerRad( const rw::Matrix& mat, float& x_rad, float& y_rad, float&
void EulerToMatrix( rw::Matrix& mat, float x_angle, float y_angle, float z_angle )
{
EulerRadToMatrix( mat, DEG2RAD( x_angle ), DEG2RAD( y_angle ), DEG2RAD( z_angle ) );
EulerRadToMatrix( mat, (float)DEG2RAD( x_angle ), (float)DEG2RAD( y_angle ), (float)DEG2RAD( z_angle ) );
}
void MatrixToEuler( const rw::Matrix& mat, float& x_angle, float& y_angle, float& z_angle )
......@@ -2208,9 +2208,9 @@ void MatrixToEuler( const rw::Matrix& mat, float& x_angle, float& y_angle, float
MatrixToEulerRad( mat, x_rad, y_rad, z_rad );
x_angle = RAD2DEG( x_rad );
y_angle = RAD2DEG( y_rad );
z_angle = RAD2DEG( z_rad );
x_angle = (float)RAD2DEG( x_rad );
y_angle = (float)RAD2DEG( y_rad );
z_angle = (float)RAD2DEG( z_rad );
}
void EulerRadToMatrix( rw::Matrix& mat, float x_rad, float y_rad, float z_rad )
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment