This repository has been archived on 2025-02-27. You can view files and clone it, but cannot push or open issues or pull requests.
CnC_Renegade/Code/Tools/LevelEdit/CameraMgr.cpp

1314 lines
34 KiB
C++

/*
** 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 : LevelEdit *
* *
* $Archive:: /Commando/Code/Tools/LevelEdit/CameraMgr.cpp $*
* *
* Author:: Patrick Smith *
* *
* $Modtime:: 11/06/01 10:29a $*
* *
* $Revision:: 46 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "stdafx.h"
#include "utils.h"
#include "camera.h"
#include "cameramgr.h"
#include "mousemgr.h"
#include "leveleditdoc.h"
#include "groupmgr.h"
#include "formtoolbar.h"
#include "camerasettingsform.h"
#include "mainfrm.h"
#include "filemgr.h"
#include "editorassetmgr.h"
#include "_assetmgr.h"
#include "sceneeditor.h"
#include "node.h"
#include "quat.h"
#include "combat.h"
#include "filelocations.h"
#include "combatchunkid.h"
#include "ccamera.h"
#include "input.h"
#include "leveleditview.h"
#include "nodemgr.h"
#include "actionparams.h"
#include "soldier.h"
////////////////////////////////////////////////////////////////////////////
//
// Constants
//
////////////////////////////////////////////////////////////////////////////
const float DEF_CAMERA_DIST = 80.00F;
const float MIN_MOVE_SCALE = 30.00F;
const float WALK_THRU_VEL_FWD = 3.5F;
const float WALK_THRU_VEL_BKWD = -WALK_THRU_VEL_FWD;
const float WALK_THRU_VEL_LEFT = 0.8F;
const float WALK_THRU_VEL_RIGHT = -WALK_THRU_VEL_LEFT;
const float WALK_THRU_VEL_STRAFE = 4.5F;
////////////////////////////////////////////////////////////////////////////
//
// Static member initialization
//
////////////////////////////////////////////////////////////////////////////
CameraMgr::UPDATE_CAMERA_FN CameraMgr::_pfnUpdateMethods[CAMERA_MODE::MODE_COUNT] =
{
CameraMgr::Update_Camera_MOVE_ZOOM,
CameraMgr::Update_Camera_MOVE_PLANE,
CameraMgr::Update_Camera_FLY_THROUGH,
CameraMgr::Update_Camera_WALK_THROUGH,
CameraMgr::Update_Camera_ROTATE_FREE,
CameraMgr::Update_Camera_ROTATE_X,
CameraMgr::Update_Camera_ROTATE_Y,
CameraMgr::Update_Camera_ROTATE_Z,
CameraMgr::Update_Camera_ORBIT,
CameraMgr::Update_Camera_FLY_TO
};
bool CameraMgr::_pKeyboardState[256] = { 0 };
HHOOK CameraMgr::_hHook = NULL;
////////////////////////////////////////////////////////////////////////////
//
// CameraMgr
//
////////////////////////////////////////////////////////////////////////////
CameraMgr::CameraMgr (void)
: m_pCamera (NULL),
m_bAutoLevel (false),
m_CameraMode (MODE_MOVE_PLANE),
m_SpeedModifier (6.0F),
m_WalkThruObj (NULL),
m_WalkThruDef (NULL)
{
Init_Camera ();
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// CameraMgr
//
////////////////////////////////////////////////////////////////////////////
CameraMgr::~CameraMgr (void)
{
MEMBER_RELEASE (m_pCamera);
if (m_WalkThruObj != NULL) {
m_WalkThruObj->Set_Delete_Pending ();
m_WalkThruObj = NULL;
Input::Shutdown ();
}
if (m_WalkThruDef != NULL) {
delete m_WalkThruDef;
}
//MEMBER_RELEASE (m_pWalkThroughPhys);
// Remove our hook procedure from the chain
if (_hHook != NULL) {
::UnhookWindowsHookEx (_hHook);
_hHook = NULL;
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// fnCameraKeyboardHook
//
////////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK
fnCameraKeyboardHook
(
int code,
WPARAM wParam,
LPARAM lParam
)
{
// Should we process this message?
if (code >= 0) {
if ((wParam >= 0) && (wParam <= 255)) {
CameraMgr::_pKeyboardState[wParam] = bool((lParam & 0x80000000) != 0x80000000);
}
}
// Call the next hook procedure in the chain
return ::CallNextHookEx (CameraMgr::_hHook, code, wParam, lParam);
}
////////////////////////////////////////////////////////////////////////////
//
// Init_Camera
//
////////////////////////////////////////////////////////////////////////////
void
CameraMgr::Init_Camera (void)
{
if (m_pCamera == NULL) {
// Create a new camera object
m_pCamera = new CameraClass;
}
// Were we able to create a new object?
ASSERT (m_pCamera!= NULL);
if (m_pCamera) {
// Create a transformation matrix
Matrix3D transform_matrix (1);
transform_matrix.Translate (Vector3 (0.0F, 0.0F, DEF_CAMERA_DIST));
m_pCamera->Set_Clip_Planes (0.1F, 200.0F);
//m_pCamera->Set_Environment_Range (9000.0F, 10000.0F);
// Move the camera back along the z-axis looking at world center
Set_Transform (transform_matrix);
m_pCamera->Set_Transform (transform_matrix);
}
// Install a windows hook procedure so we know when keys are pressed
if (_hHook == NULL) {
::memset (_pKeyboardState, 0, sizeof (_pKeyboardState));
_hHook = ::SetWindowsHookEx (WH_KEYBOARD,
fnCameraKeyboardHook,
::AfxGetInstanceHandle (),
::GetCurrentThreadId ());
}
// Reset the camera mode
m_CameraMode = MODE_MOVE_PLANE;
return ;
}
double _XRot = 0;
double _YRot = 0;
////////////////////////////////////////////////////////////////////////////
//
// Set_Camera_Mode
//
////////////////////////////////////////////////////////////////////////////
void
CameraMgr::Set_Camera_Mode (CAMERA_MODE new_mode)
{
// Is this really a new mode?
if (new_mode != m_CameraMode) {
if (new_mode == MODE_WALK_THROUGH) {
::Get_Scene_Editor ()->Set_Selection (NULL);
GameInFocus = true;
if (m_WalkThruObj == NULL) {
Input::Init ();
Input::Load_Configuration (DEFAULT_INPUT_FILENAME);
Input::Set_Mouse_Invert (true);
//
// Create a commando game object and initialize it
// with the first commando preset we found
//
SoldierGameObjDef *definition = (SoldierGameObjDef *)DefinitionMgrClass::Find_Typed_Definition ("Walk-Thru", CLASSID_GAME_OBJECT_DEF_SOLDIER, false);
m_WalkThruObj = new SoldierGameObj;
m_WalkThruObj->Init (*definition);
ActionParamsStruct parameters;
m_WalkThruObj->Get_Action()->Follow_Input( parameters );
}
m_WalkThruObj->Control_Enable (true);
m_WalkThruObj->Set_Control_Owner (CombatManager::Get_My_Id ());
CombatManager::Set_I_Am_Client (true);
CombatManager::Set_The_Star (m_WalkThruObj);
//
// Give the physics object an initial transform
//
PhysClass *phys_obj = m_WalkThruObj->Peek_Physical_Object ();
if (phys_obj != NULL) {
Matrix3D transform = m_pCamera->Get_Transform ();
Matrix3D cam_to_world (Vector3 (0, 0, -1), Vector3 (-1, 0, 0), Vector3 (0, 1, 0), Vector3 (0, 0, 0));
transform = transform * cam_to_world;
phys_obj->Set_Transform (transform);
}
} else if (m_WalkThruObj != NULL) {
m_WalkThruObj->Set_Delete_Pending ();
m_WalkThruObj = NULL;
Input::Shutdown ();
}
m_CameraMode = new_mode;
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Update_Camera
//
////////////////////////////////////////////////////////////////////////////
void
CameraMgr::Update_Camera
(
float deltax,
float deltay
)
{
// State OK?
ASSERT (m_pCamera != NULL);
if (m_pCamera != NULL) {
// Call into the state table to perform the update
_pfnUpdateMethods[m_CameraMode] (*m_pCamera, deltax, deltay);
if (m_bAutoLevel) {
// If ew are auto-leveling, then reset the initial
// rotation matrix and percent
m_AutoLevelInitalMatrix = m_pCamera->Get_Transform ();
m_AutoLevelPercent = 0.00F;
}
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Level_Camera
//
////////////////////////////////////////////////////////////////////////////
void
CameraMgr::Level_Camera (void)
{
m_bAutoLevel = true;
// Reset the initial rotation matrix and percent
m_AutoLevelInitalMatrix = m_pCamera->Get_Transform ();
m_AutoLevelPercent = 0.00F;
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Auto_Level
//
////////////////////////////////////////////////////////////////////////////
void
CameraMgr::Auto_Level (void)
{
// Is there a mouse button down?
// We don't want to auto-level if the mouse button is down
BOOL mouse_down = BOOL(::GetKeyState (VK_LBUTTON) & 0xF000);
mouse_down |= BOOL(::GetKeyState (VK_RBUTTON) & 0xF000);
// Should we auto-level the camera?
if ((m_AutoLevelPercent <= 1) && (mouse_down == false)) {
// Get the camera's current transformation matrix
Matrix3D matrix = m_pCamera->Get_Transform ();
Vector3 cam_pos;
Vector3 cam_target;
// Get the camera position
matrix.Get_Translation (&cam_pos);
// Get a vector 1 meter below the camera position
cam_target = matrix * Vector3 (0.00F, 0.00F, -1.00F);
// Force the z components of the 2 vectors to be the same.
cam_target.Z = cam_pos.Z;
// Create a new transformation matrix which is positioned
// at the camera and is looking at the vector we created
Matrix3D new_matrix;
new_matrix.Look_At (cam_pos, cam_target, 0.0F);
// Build quaternions for the start and end rotation matricies
Quaternion initial_quat = ::Build_Quaternion (m_AutoLevelInitalMatrix);
Quaternion end_quat = ::Build_Quaternion (new_matrix);
// Linerally-interpolate between the 2 rotations (from 0.0 - 1.0)
Quaternion rotation_now;
::Slerp (rotation_now, initial_quat, end_quat, m_AutoLevelPercent);
// Increment the current interpolation percent
m_AutoLevelPercent += 0.04F;
// Set the rotation for the camera's transormation matrix
matrix.Set_Rotation (rotation_now);
// Set the camera's new rotation
Set_Transform (matrix);
if (m_AutoLevelPercent >= 1) {
m_bAutoLevel = false;
}
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Increase_Speed
//
////////////////////////////////////////////////////////////////////////////
void
CameraMgr::Increase_Speed (void)
{
if (m_SpeedModifier < 1.0F) {
m_SpeedModifier += 0.1F;
} else {
m_SpeedModifier += 0.75F;
}
// Normalize the speed
if (m_SpeedModifier > 25.00F) {
m_SpeedModifier = 25.00F;
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Decrease_Speed
//
////////////////////////////////////////////////////////////////////////////
void
CameraMgr::Decrease_Speed (void)
{
if (m_SpeedModifier < 2.0F) {
m_SpeedModifier -= 0.1F;
} else {
m_SpeedModifier -= 0.75F;
}
// Normalize the speed
if (m_SpeedModifier < 0.25F) {
m_SpeedModifier = 0.25F;
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// On_Frame
//
////////////////////////////////////////////////////////////////////////////
void
CameraMgr::On_Frame (void)
{
float speed_mod = CameraMgr::_pKeyboardState[VK_CONTROL] ? m_SpeedModifier : 1.0F;
if ((_pKeyboardState[VK_NUMPAD8]) ||
(_pKeyboardState[VK_NUMPAD2])) {
// Get the camera's current position
Vector3 position = m_pCamera->Get_Position ();
float orig_z = position.Z;
// Get the current direction the camera is looking at
Matrix3D matrix = m_pCamera->Get_Transform ();
float delta = _pKeyboardState[VK_NUMPAD8] ? -0.35F : 0.35F;
delta *= speed_mod;
// Should we lock the z-position?
if (::GetKeyState (VK_CAPITAL) & 0x0001) {
// Scale the position 'forward' and 'backward'
//position += (delta * matrix.Get_Z_Vector ());
//position.Z = orig_z;
Vector3 y_vector = Vector3::Cross_Product (matrix.Get_X_Vector (), Vector3 (0, 0, 1));
y_vector.Normalize ();
position += delta * y_vector;
//delta += y_vector * (-0.05F * modifier);
} else {
// Scale the position along the direction vector
position += (delta * matrix.Get_Z_Vector ());
}
// Set the camera's new position
Set_Position (position);
}
if ((_pKeyboardState[VK_NUMPAD9]) ||
(_pKeyboardState[VK_NUMPAD3])) {
// Get the camera's current transform
Matrix3D transform = m_pCamera->Get_Transform ();
// Rotate by the specified number of radians
float rotation = _pKeyboardState[VK_NUMPAD9] ? 0.0314F : -0.0314F;
rotation *= (speed_mod / 2.5F);
if (rotation > 0.045F) {
rotation = 0.045F;
} else if (rotation < -0.045F) {
rotation = -0.045F;
}
transform.Rotate_X (rotation);
// Set the camera's new transform
Set_Transform (transform);
}
if ((_pKeyboardState[VK_NUMPAD4]) ||
(_pKeyboardState[VK_NUMPAD6])) {
if (::GetKeyState (VK_MENU) < 0) {
// Get the camera's current position
Vector3 position = m_pCamera->Get_Position ();
float delta = (_pKeyboardState[VK_NUMPAD4]) ? -0.25F : 0.25F;
delta *= speed_mod;
position += (delta * m_pCamera->Get_Transform ().Get_X_Vector ());
// Set the camera's new position
Set_Position (position);
} else {
// Get the pure rotation from the transform
Matrix3D transform = m_pCamera->Get_Transform ();
Vector3 translation = transform.Get_Translation ();
transform.Set_Translation (Vector3 (0, 0, 0));
// Determine an appropriate rotation delta
float delta = (_pKeyboardState[VK_NUMPAD4]) ? 0.0314F : -0.0314F;
delta *= speed_mod;
if (delta > 0.06F) {
delta = 0.06F;
} else if (delta < -0.06F) {
delta = -0.06F;
}
Matrix3D world_rotation(1);
world_rotation.Rotate_Z (delta);
// Rotate using the world's coord system
transform = world_rotation * transform;
transform.Set_Translation (translation);
// Set the camera's new transform
Set_Transform (transform);
}
}
if ((_pKeyboardState[VK_NUMPAD7]) ||
(_pKeyboardState[VK_NUMPAD1])) {
// Get the camera's current position
Vector3 position = m_pCamera->Get_Position ();
float delta = (_pKeyboardState[VK_NUMPAD1]) ? -0.25F : 0.25F;
delta *= speed_mod;
position.Z += delta;
// Set the camera's new position
Set_Position (position);
}
// Are we currently in 'walk-thru' mode?
if (m_CameraMode == MODE_WALK_THROUGH) {
if (m_WalkThruObj != NULL) {
if (::GetAsyncKeyState (VK_ESCAPE) < 0 || ::GetAsyncKeyState (VK_F6) < 0) {
::Get_Mouse_Mgr ()->Set_Mouse_Mode (MouseMgrClass::MODE_OBJECT_MANIPULATE);
} else {
//
// Check for the VIS-Update keypress
//
static DWORD last_vis_gen = 0;
static DWORD last_static_anim_toggle = 0;
DWORD current_ticks = ::GetTickCount ();
if ((::GetAsyncKeyState (VK_RETURN) < 0) && (current_ticks - last_vis_gen) > 1000) {
Vector3 sample_point = m_WalkThruObj->Get_Transform ().Get_Translation () + Vector3 (0, 0, 1);
::Get_Scene_Editor ()->Record_Vis_Info (m_pCamera->Get_Transform (), sample_point);
last_vis_gen = current_ticks;
} else if (::GetAsyncKeyState (VK_F3) < 0) {
bool points_visible = ::Get_Scene_Editor ()->Are_Manual_Vis_Points_Visible ();
::Get_Scene_Editor ()->Show_Manual_Vis_Points (!points_visible);
} else if ( (::GetAsyncKeyState (VK_CONTROL) < 0) &&
(::GetAsyncKeyState (VK_SHIFT) < 0) &&
(::GetAsyncKeyState ('T') < 0))
{
//
// Toggle the static anims... (if necessary)
//
if ((current_ticks - last_static_anim_toggle) > 250) {
((CMainFrame *)::AfxGetMainWnd ())->Toggle_Static_Anims ();
last_static_anim_toggle = current_ticks;
}
}
//
// Allow the game object and physic object to think
//
m_WalkThruObj->Generate_Control ();
m_WalkThruObj->Think ();
PhysClass *phys_obj = m_WalkThruObj->Peek_Physical_Object ();
if (phys_obj != NULL) {
phys_obj->Timestep (TimeManager::Get_Frame_Seconds ());
}
m_WalkThruObj->Post_Think ();
CCameraClass *game_camera = CombatManager::Get_Camera ();
if (game_camera != NULL) {
//
// Update the game camera
//
Input::Update ();
CombatManager::Handle_Input ();
CombatManager::Update_Star ();
Matrix3D tm = m_WalkThruObj->Get_Transform();
game_camera->Update ();
//
// Copy the game camera's transform
//
Matrix3D camera_tm = game_camera->Get_Transform ();
m_pCamera->Set_Transform (camera_tm);
}
}
}
}
if (m_bAutoLevel) {
Auto_Level ();
}
if (m_CameraMode == MODE_FLYTO) {
Update_Fly_To ();
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Update_Camera_Animation
//
////////////////////////////////////////////////////////////////////////////
void
CameraMgr::Update_Camera_Animation (void)
{
//
// TODO - move the camera depending on the animation mode
//
return ;
}
//**************************************************************************************************************//
//
// Start of static methods
//
//**************************************************************************************************************//
////////////////////////////////////////////////////////////////////////////
//
// Update_Camera_MOVE_ZOOM
//
////////////////////////////////////////////////////////////////////////////
void
CameraMgr::Update_Camera_MOVE_ZOOM
(
CameraClass & camera,
float deltax,
float deltay
)
{
// Get the camera's current position
Vector3 position = camera.Get_Position ();
// Get the current direction the camera is looking at
Matrix3D matrix = camera.Get_Transform ();
Vector3 orientation = matrix.Get_Z_Vector ();
float scale_factor = (position.Z > MIN_MOVE_SCALE) ? position.Z : MIN_MOVE_SCALE;
// Scale the position along the direction vector
position = position - (deltay * orientation * scale_factor);
// Set the camera's new position
::Get_Camera_Mgr ()->Set_Position (position);
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Update_Camera_MOVE_PLANE
//
////////////////////////////////////////////////////////////////////////////
void
CameraMgr::Update_Camera_MOVE_PLANE
(
CameraClass & camera,
float deltax,
float deltay
)
{
// Get the camera's current position
Vector3 position = camera.Get_Position ();
// Get the vector the camera is 'sliding' up and down on
Matrix3D matrix = camera.Get_Transform ();
Vector3 orientation = matrix.Get_Y_Vector ();
float scale_factor = (position.Z > MIN_MOVE_SCALE) ? position.Z : MIN_MOVE_SCALE;
// Scale the position along the direction vector
position = position + (deltay * orientation * scale_factor);
// Scale the position along the 'left/right' vector
orientation = matrix.Get_X_Vector ();
position = position - (deltax * orientation * scale_factor);
// Set the camera's new position
::Get_Camera_Mgr ()->Set_Position (position);
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Update_Camera_FLY_THROUGH
//
////////////////////////////////////////////////////////////////////////////
void
CameraMgr::Update_Camera_FLY_THROUGH
(
CameraClass & camera,
float deltax,
float deltay
)
{
//
// TODO - update the camera
//
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Update_Camera_WALK_THROUGH
//
////////////////////////////////////////////////////////////////////////////
void
CameraMgr::Update_Camera_WALK_THROUGH
(
CameraClass & camera,
float deltax,
float deltay
)
{
//
// TODO - update the camera
//
//Matrix3D transform = camera.Get_Transform ();
//transform.Rotate_X (deltay*3.0F);
_XRot += deltay * 2.0F;
//_YRot += deltax * 3.0F;
//camera.Set_Transform (transform);
// Get the camera's current transformation matrix
//CamaraCharPhys *pcharacter = ::Get_Camera_Mgr ()->Get_Walkthru_Character ();
if (0) {//pcharacter != NULL) {
/*Matrix3D transform = pcharacter->Get_Transform ();
transform.Rotate_Z (deltax * 2.0F);
pcharacter->Set_Transform (transform);*/
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Update_Camera_ROTATE_FREE
//
void
CameraMgr::Update_Camera_ROTATE_FREE
(
CameraClass & camera,
float deltax,
float deltay
)
{
// Rotate the camera's transformation matrix based
// on the deltas
Matrix3D matrix = camera.Get_Transform ();
//matrix.Rotate_X (deltay);
//matrix.Rotate_Y (deltax);
// Restrict the rotation to the current axis
switch (::Get_Current_Document ()->Get_Axis_Restriction ()) {
case CLevelEditDoc::RESTRICT_X:
{
matrix.Rotate_X (deltay);
}
break;
case CLevelEditDoc::RESTRICT_Y:
{
matrix.Rotate_Y (deltax);
}
break;
case CLevelEditDoc::RESTRICT_Z:
{
matrix.Rotate_Z (deltay);
}
break;
default:
{
matrix.Rotate_X (deltay);
matrix.Rotate_Y (deltax);
}
break;
}
// Set the camera's new rotation
::Get_Camera_Mgr ()->Set_Transform (matrix);
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Update_Camera_ROTATE_X
//
void
CameraMgr::Update_Camera_ROTATE_X
(
CameraClass & camera,
float deltax,
float deltay
)
{
// Rotate the camera's transformation matrix based
// on the x delta
Matrix3D matrix = camera.Get_Transform ();
matrix.Rotate_X (deltay);
// Set the camera's new rotation
::Get_Camera_Mgr ()->Set_Transform (matrix);
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Update_Camera_ROTATE_Y
//
void
CameraMgr::Update_Camera_ROTATE_Y
(
CameraClass &camera,
float deltax,
float deltay
)
{
// Rotate the camera's transformation matrix based
// on the y delta
Matrix3D matrix = camera.Get_Transform ();
matrix.Rotate_Y (deltax);
// Set the camera's new rotation
::Get_Camera_Mgr ()->Set_Transform (matrix);
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Update_Camera_ROTATE_Z
//
void
CameraMgr::Update_Camera_ROTATE_Z
(
CameraClass & camera,
float deltax,
float deltay
)
{
// Rotate the camera's transformation matrix based
// on the x and y deltas, but restrict the rotation
// to Z
Matrix3D matrix = camera.Get_Transform ();
Matrix3D temp_matrix = matrix;
temp_matrix.Rotate_X (deltay);
temp_matrix.Rotate_Y (deltax);
/*Matrix3D new_matrix (1);
new_matrix.Set_Translation (matrix.Get_Translation ());
new_matrix.Rotate_X (matrix.Get_X_Rotation ());
new_matrix.Rotate_Y (matrix.Get_Y_Rotation ());
new_matrix.Rotate_Z (temp_matrix.Get_Z_Rotation ());*/
Matrix3D new_matrix = matrix;
new_matrix.Rotate_Z (deltax+deltay);
//new_matrix.Rotate_Z (deltay);
// Set the camera's new rotation
::Get_Camera_Mgr ()->Set_Transform (matrix);
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Update_Camera_FLY_TO
//
////////////////////////////////////////////////////////////////////////////
void
CameraMgr::Update_Camera_FLY_TO
(
CameraClass &camera,
float /*deltax*/,
float /*deltay*/
)
{
::Get_Camera_Mgr ()->Update_Fly_To ();
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Update_Camera_ORBIT
//
////////////////////////////////////////////////////////////////////////////
void
CameraMgr::Update_Camera_ORBIT
(
CameraClass &camera,
float /*deltax*/,
float /*deltay*/
)
{
//
// TODO - update the camera
//
MouseMgrClass *pmouse_mgr = ::Get_Mouse_Mgr ();
CPoint point = pmouse_mgr->Get_Mouse_Point ();
CPoint last_point = pmouse_mgr->Get_Last_Mouse_Point ();
Vector3 viewpos;
Vector3 last_viewpos;
camera.Device_To_View_Space (Vector2 (last_point.x, last_point.y), &last_viewpos);
camera.Device_To_View_Space (Vector2 (point.x, point.y), &viewpos);
// Rotate the camara like a trackball
Quaternion rotation = ::Trackball (last_viewpos.X, last_viewpos.Y, viewpos.X, viewpos.Y, 0.4F);
// Rotate this item about its z axis
if (::Get_Selection_Mgr ().Get_Count () > 0) {
//SphereClass bounding_sphere = ::Get_Selection_Mgr ().Get_Bounding_Sphere ();
//bounding_sphere.Center;
Matrix3D matrix = camera.Get_Transform ();
Matrix3D matrix_inv;
matrix.Get_Orthogonal_Inverse (matrix_inv);
Vector3 vector_to_object = matrix_inv * ::Get_Selection_Mgr ().Get_Center ();//bounding_sphere.Center;
matrix.Translate (vector_to_object);
Matrix3D::Multiply (matrix, ::Build_Matrix3D (rotation), &matrix);
matrix.Translate (-vector_to_object);
::Get_Camera_Mgr ()->Set_Transform (matrix);
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Set_Camera_Pos
//
////////////////////////////////////////////////////////////////////////////
void
CameraMgr::Set_Camera_Pos (CAMERA_POS position)
{
SphereClass sp = ::Get_Selection_Mgr ().Get_Bounding_Sphere ();
if (Get_Selection_Mgr ().Get_Count () == 0) {
sp.Center = Vector3 (0, 0, 0);
sp.Radius = 100.00F;
}
float distance = sp.Radius * 3.00F;
distance = (distance < 1.0F) ? 1.0F : distance;
distance = (distance > 400.0F) ? 400.0F : distance;
Matrix3D transform (1);
switch (position)
{
case CAMERA_FRONT:
{
transform.Look_At (sp.Center + Vector3 (distance, 0.00F, 0.00F), sp.Center, 0);
}
break;
case CAMERA_BACK:
{
transform.Look_At (sp.Center + Vector3 (-distance, 0.00F, 0.00F), sp.Center, 0);
}
break;
case CAMERA_LEFT:
{
transform.Look_At (sp.Center + Vector3 (0.00F, -distance, 0.00F), sp.Center, 0);
}
break;
case CAMERA_RIGHT:
{
transform.Look_At (sp.Center + Vector3 (0.00F, distance, 0.00F), sp.Center, 0);
}
break;
case CAMERA_TOP:
{
transform.Look_At (sp.Center + Vector3 (0.00F, 0.00F, distance), sp.Center, 3.1415926535F);
}
break;
case CAMERA_BOTTOM:
{
transform.Look_At (sp.Center + Vector3 (0.00F, 0.00F, -distance), sp.Center, 3.1415926535F);
}
break;
}
// Move the camera back to get a good view of the object
Set_Transform (transform);
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Goto_Node
//
////////////////////////////////////////////////////////////////////////////
void
CameraMgr::Goto_Node (NodeClass *node)
{
RenderObjClass *render_obj = node->Peek_Render_Obj ();
if (render_obj != NULL) {
//
// Get the node's position
//
SphereClass sphere = render_obj->Get_Bounding_Sphere ();
Matrix3D tm = render_obj->Get_Transform ();
tm.Set_Translation (Vector3 (0, 0, 0));
//
// Calculate an appropriate viewing distance
//
float distance = sphere.Radius * 4;
distance = (distance < 1.0F) ? 1.0F : distance;
distance = (distance > 100.0F) ? 100.0F : distance;
Matrix3D transform (1);
//transform.Look_At (sphere.Center + Vector3 (distance, distance, distance), sphere.Center, 0);
Vector3 camera_loc = (sphere.Center + Vector3 (-distance, 0, distance));
transform.Look_At (camera_loc, sphere.Center, 0);
//tranform.Set_Translation (sphere.Center);
//render_obj->
//
// Move the camera back to get a good view of the object
//
Set_Transform (transform);
// Ensure the window is updated
::Refresh_Main_View ();
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Goto_Group
//
////////////////////////////////////////////////////////////////////////////
void
CameraMgr::Goto_Group (GroupMgrClass *group)
{
// State OK?
if (group != NULL) {
// Get the node's position
SphereClass sp = group->Get_Bounding_Sphere ();
float distance = sp.Radius;
distance = (distance < 1.0F) ? 1.0F : distance;
distance = (distance > 400.0F) ? 400.0F : distance;
Matrix3D transform (1);
transform.Look_At (sp.Center + Vector3 (distance, distance, distance), sp.Center, 0);
// Move the camera back to get a good view of the object
Set_Transform (transform);
// Ensure the window is updated
::Refresh_Main_View ();
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Set_Transform
//
////////////////////////////////////////////////////////////////////////////
void
CameraMgr::Set_Transform (const Matrix3D &transform)
{
if (m_pCamera != NULL) {
// Set the camera's new location and orientation
m_pCamera->Set_Transform (transform);
// Update the the UI to reflect this new position
((CMainFrame *)::AfxGetMainWnd ())->Update_Camera_Location (transform.Get_Translation ());
Set_Modified (true);
// If the camera settings dialog is visible, update its contents
/*FormToolbarClass &toolbar = ((CMainFrame *)::AfxGetMainWnd ())->Get_Camera_Toolbar ();
if (::IsWindow (toolbar) && toolbar.IsVisible ()) {
CameraSettingsFormClass *pform = (CameraSettingsFormClass *)toolbar.Get_Form ();
if (pform != NULL) {
pform->Update_Controls ();
}
}*/
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Set_Position
//
////////////////////////////////////////////////////////////////////////////
void
CameraMgr::Set_Position (const Vector3 &position)
{
if (m_pCamera != NULL) {
// Set the camera's new location and orientation
m_pCamera->Set_Position (position);
// Update the the UI to reflect this new position
((CMainFrame *)::AfxGetMainWnd ())->Update_Camera_Location (position);
Set_Modified (true);
// If the camera settings dialog is visible, update its contents
/*FormToolbarClass &toolbar = ((CMainFrame *)::AfxGetMainWnd ())->Get_Camera_Toolbar ();
if (::IsWindow (toolbar) && toolbar.IsVisible ()) {
CameraSettingsFormClass *pform = (CameraSettingsFormClass *)toolbar.Get_Form ();
if (pform != NULL) {
pform->Update_Controls ();
}
}*/
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Fly_To_Transform
//
////////////////////////////////////////////////////////////////////////////
void
CameraMgr::Fly_To_Transform (const Matrix3D &transform)
{
m_FlyToStartTransform = m_pCamera->Get_Transform ();
m_FlyToEndTransform = transform;
Vector3 start_point = m_FlyToStartTransform.Get_Translation ();
Vector3 end_point = m_FlyToEndTransform.Get_Translation ();
Vector3 delta = end_point - start_point;
float len = delta.Length () / 2;
Vector3 middle_point = start_point + Vector3 (delta.X / 2, delta.Y / 2, delta.Z / 2 + len);
// Remove all keys from the spline
while (m_FlyToSpline.Key_Count () > 0) {
m_FlyToSpline.Remove_Key (0);
}
Vector3 looking_start = -20.0F * m_FlyToStartTransform.Get_Z_Vector ();
int index = m_FlyToSpline.Add_Key (start_point, 0);
m_FlyToSpline.Set_Tangents (index, looking_start, looking_start);
Vector3 looking_end = -20.0F * m_FlyToEndTransform.Get_Z_Vector ();
index = m_FlyToSpline.Add_Key (end_point, 1);
m_FlyToSpline.Set_Tangents (index, looking_end, looking_end);
m_FlyToStartTime = ::GetTickCount ();
Set_Camera_Mode (MODE_FLYTO);
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Update_Fly_To
//
////////////////////////////////////////////////////////////////////////////
void
CameraMgr::Update_Fly_To (void)
{
const DWORD FLY_TICKS = 5000;
float fly_ticks = (float)FLY_TICKS;
if (::GetAsyncKeyState (VK_CONTROL) < 0) {
fly_ticks = fly_ticks / m_SpeedModifier;
}
DWORD current_time = ::GetTickCount ();
float spline_time = float(current_time - m_FlyToStartTime) / fly_ticks;
spline_time = min (1.0F, spline_time);
if (m_FlyToStartTime + ((DWORD)fly_ticks) < current_time) {
m_pCamera->Set_Transform (m_FlyToEndTransform);
Set_Camera_Mode (MODE_MOVE_PLANE);
} else {
Vector3 position (0,0,0);
Vector3 next_position (0,0,0);
m_FlyToSpline.Evaluate (spline_time, &position);
m_FlyToSpline.Evaluate (spline_time + 0.05F, &next_position);
Matrix3D rot_90 (1);
rot_90.Rotate_Z ((float)DEG_TO_RAD (90));
Vector3 x_axis = next_position - position;
x_axis.Normalize ();
Vector3 y_axis = rot_90 * x_axis;
y_axis.Normalize ();
Vector3 z_axis;
Vector3::Cross_Product (x_axis, y_axis, &z_axis);
Matrix3D orientation (x_axis, y_axis, z_axis, position);
Matrix3D world_to_cam (Vector3 (0, -1, 0), Vector3 (0, 0, 1), Vector3 (-1, 0, 0), Vector3 (0, 0, 0));
Matrix3D camera_tm = orientation * world_to_cam;
if (camera_tm.Is_Orthogonal () == false) {
TRACE ("Matrix not orthogonal!\r\n");
camera_tm.Re_Orthogonalize();
}
Set_Transform (camera_tm);
}
return ;
}
////////////////////////////////////////////////////////////////////////////
//
// Get_Character_TM
//
////////////////////////////////////////////////////////////////////////////
Matrix3D
CameraMgr::Get_Character_TM (void)
{
Matrix3D tm (1);
if (m_WalkThruObj != NULL) {
tm = m_WalkThruObj->Get_Transform ();
} else {
tm = m_pCamera->Get_Transform ();
}
return tm;
}