/* ** 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 . */ /*********************************************************************************************** *** 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; }