| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180 |
- /*
- ** 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/Mover.cpp $*
- * *
- * Author:: Patrick Smith *
- * *
- * $Modtime:: 2/15/01 10:15a $*
- * *
- * $Revision:: 15 $*
- * *
- *---------------------------------------------------------------------------------------------*
- * Functions: *
- * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
- #include "stdafx.h"
- #include "mover.h"
- #include "utils.h"
- #include "cameramgr.h"
- #include "leveleditdoc.h"
- #include "leveleditview.h"
- #include "node.h"
- #include "phys3.h"
- ///////////////////////////////////////////////////////////////////////////
- //
- // Clip_Point
- //
- ///////////////////////////////////////////////////////////////////////////
- static inline bool
- Clip_Point (Vector3 *point, const AABoxClass &box)
- {
- Vector3 temp_point = *point;
- //
- // Clip the temporary point
- //
- temp_point.X = max (temp_point.X, box.Center.X - box.Extent.X);
- temp_point.Y = max (temp_point.Y, box.Center.Y - box.Extent.Y);
- temp_point.Z = max (temp_point.Z, box.Center.Z - box.Extent.Z);
- temp_point.X = min (temp_point.X, box.Center.X + box.Extent.X);
- temp_point.Y = min (temp_point.Y, box.Center.Y + box.Extent.Y);
- temp_point.Z = min (temp_point.Z, box.Center.Z + box.Extent.Z);
- //
- // Did the clip change the point?
- //
- bool retval = (point->X != temp_point.X);
- retval |= (point->Y != temp_point.Y);
- retval |= (point->Z != temp_point.Z);
-
- //
- // Pass the new point back to the caller
- //
- (*point) = temp_point;
-
- return retval;
- }
- ///////////////////////////////////////////////////////////////////////
- //
- // Get_Mouse_Ray
- //
- ///////////////////////////////////////////////////////////////////////
- void
- MoverClass::Get_Mouse_Ray
- (
- const POINT & mouse_pos,
- float length,
- Vector3 & start,
- Vector3 & end
- )
- {
- // The start of the ray is simply the camera's position
- start = ::Get_Camera_Mgr ()->Get_Camera ()->Get_Transform ().Get_Translation ();
- //
- // Ensure the 'point' is correct for this mode (fullscreen/windowed)
- //
- float xpos = mouse_pos.x;
- float ypos = mouse_pos.y;
- ::Constrain_Point_To_Aspect_Ratio (xpos, ypos);
-
- // The 'end' of the ray is the world coordinates of the supplied point
- ::Get_Camera_Mgr ()->Get_Camera ()->Device_To_World_Space (Vector2 (xpos, ypos), &end);
- //
- // Recalculate the length of the ray
- //
- end = start + ((end - start) * length);
- return ;
- }
- ///////////////////////////////////////////////////////////////////////
- //
- // Get_Mouse_Ray
- //
- ///////////////////////////////////////////////////////////////////////
- void
- MoverClass::Get_Mouse_Ray
- (
- float length,
- Vector3 &start,
- Vector3 &end
- )
- {
- //
- // Ensure the 'point' is correct for this mode (fullscreen/windowed)
- //
- CPoint point;
- ::GetCursorPos (&point);
- ::Get_Main_View ()->ScreenToClient (&point);
- Get_Mouse_Ray (point, length, start, end);
- return ;
- }
- ///////////////////////////////////////////////////////////////////////
- //
- // Get_LOS_Ray
- //
- ///////////////////////////////////////////////////////////////////////
- void
- MoverClass::Get_LOS_Ray
- (
- const POINT & mouse_pos,
- float length,
- Vector3 & start,
- Vector3 & end
- )
- {
- // Get the transformation matrix for the camera
- Matrix3D camera_tm = ::Get_Camera_Mgr ()->Get_Camera ()->Get_Transform ();
-
- //
- // The start and end's of the ray are the camera's position
- // and 'length' down the camera's -z axis.
- //
- start = camera_tm.Get_Translation ();
- end = camera_tm * Vector3 (0, 0, -length);
- return ;
- }
- ///////////////////////////////////////////////////////////////////////
- //
- // Get_LOS_Ray
- //
- ///////////////////////////////////////////////////////////////////////
- void
- MoverClass::Get_LOS_Ray
- (
- float length,
- Vector3 &start,
- Vector3 &end
- )
- {
- //
- // Ensure the 'point' is correct for this mode (fullscreen/windowed)
- //
- CPoint point;
- ::GetCursorPos (&point);
- ::Get_Main_View ()->ScreenToClient (&point);
- Get_LOS_Ray (point, length, start, end);
- return ;
- }
- ///////////////////////////////////////////////////////////////////////
- //
- // Position_Node
- //
- ///////////////////////////////////////////////////////////////////////
- void
- MoverClass::Position_Node (NodeClass *node)
- {
- float distance = 1000.0F;
- //
- // Determine what ray to cast the node along
- //
- Vector3 ray_start;
- Vector3 ray_end;
- Get_LOS_Ray (distance, ray_start, ray_end);
- Position_Node_Along_Ray (node, ray_start, ray_end);
- return ;
- }
- ///////////////////////////////////////////////////////////////////////
- //
- // Position_Node_Along_Ray
- //
- ///////////////////////////////////////////////////////////////////////
- void
- MoverClass::Position_Node_Along_Ray (NodeClass *node)
- {
- //
- // Determine what ray to cast the node along
- //
- Vector3 ray_start;
- Vector3 ray_end;
- Get_Mouse_Ray (350.00F, ray_start, ray_end);
- Position_Node_Along_Ray (node, ray_start, ray_end);
- return ;
- }
- ///////////////////////////////////////////////////////////////////////
- //
- // Position_Nodes_Along_Ray
- //
- ///////////////////////////////////////////////////////////////////////
- void
- MoverClass::Position_Nodes_Along_Ray (void)
- {
- //
- // Determine what ray to cast the node along
- //
- Vector3 ray_start;
- Vector3 ray_end;
- Get_Mouse_Ray (350.00F, ray_start, ray_end);
- Position_Nodes_Along_Ray (ray_start, ray_end);
- return ;
- }
- ///////////////////////////////////////////////////////////////////////
- //
- // Position_Nodes_Along_Ray
- //
- ///////////////////////////////////////////////////////////////////////
- void
- MoverClass::Position_Nodes_Along_Ray (const Vector3 &start, const Vector3 &end)
- {
- NODE_LIST list;
- Vector3 center = ::Get_Scene_Editor ()->Build_Node_List (list);
- if (list.Count () == 1) {
- Position_Node_Along_Ray (list[0], start, end);
- } else {
- Position_Nodes_Along_Ray (list, center, start, end);
- }
- return ;
- }
- ///////////////////////////////////////////////////////////////////////
- //
- // Position_Nodes_Along_Ray
- //
- ///////////////////////////////////////////////////////////////////////
- Vector3
- MoverClass::Position_Nodes_Along_Ray
- (
- NODE_LIST & list,
- const Vector3 &tracking_pt,
- const Vector3 &start,
- const Vector3 &end
- )
- {
- if (list.Count () == 1) {
- return Position_Node_Along_Ray (list[0], start, end);
- }
- Vector3 position (tracking_pt);
- //
- // Turn off collision detection
- //
- for (int index = 0; index < list.Count (); index ++) {
- PhysClass *phys_obj = list[index]->Peek_Physics_Obj ();
- if (phys_obj != NULL) {
- phys_obj->Inc_Ignore_Counter();
- }
- }
- //
- // Cast the ray into the world so we can stop the objects at whatever it hits
- //
- CastResultStruct res;
- if (Cast_Ray (res, start, end, GAME_COLLISION_GROUP) != NULL) {
- position = start + (end - start) * res.Fraction;
- }
- // Calculate a delta to move each object
- Vector3 delta = position - tracking_pt;
- //
- // Re-position the nodes
- //
- for (index = 0; index < list.Count (); index ++) {
- NodeClass *node = list[index];
- PhysClass *phys_obj = node->Peek_Physics_Obj ();
- if (phys_obj != NULL) {
-
- //
- // Move the node and turn collision back on
- //
- node->Translate (delta);
- phys_obj->Dec_Ignore_Counter();
- }
- }
- ::Set_Modified ();
- return position;
- }
- ///////////////////////////////////////////////////////////////////////
- //
- // Position_Node_Along_Ray
- //
- ///////////////////////////////////////////////////////////////////////
- Vector3
- MoverClass::Position_Node_Along_Ray
- (
- NodeClass * node,
- const Vector3 &start,
- const Vector3 &end
- )
- {
- Vector3 position (0, 0, 0);
- PhysClass *phys_obj = node->Peek_Physics_Obj ();
- if (phys_obj != NULL) {
- position = node->Get_Transform ().Get_Translation ();
- // Don't include this node in the collision test
- phys_obj->Inc_Ignore_Counter();
- //
- // Cast the ray into the world so we can stop the object at whatever it hits
- //
- CastResultStruct res;
- if (Cast_Ray (res, start, end, GAME_COLLISION_GROUP) != NULL) {
- //
- // Determine the new position based on whether or not the
- // ray-cast hit anything.
- //
- position = start + (end - start) * res.Fraction;
-
- //
- // Get the collision box for this render obj
- //
- AABoxClass box;
- RenderObjClass *model = phys_obj->Peek_Model ();
- RenderObjClass *world_box = model->Get_Sub_Object_By_Name ("WORLDBOX");
- if (world_box != NULL) {
- world_box->Get_Obj_Space_Bounding_Box (box);
- MEMBER_RELEASE (world_box);
- } else {
- model->Get_Obj_Space_Bounding_Box (box);
- }
- box.Extent.Z = WWMATH_EPSILON;
-
- //
- // Move the object so its not embedded in the surface
- //
- Vector3 temp_pt = box.Center - res.Normal;
- ::Clip_Point (&temp_pt, box);
- float len = (temp_pt - box.Center).Length () + WWMATH_EPSILON;
- position += (res.Normal * len);
- //
- // Move the node
- //
- node->Translate (position - node->Get_Transform ().Get_Translation ());
- }
- phys_obj->Dec_Ignore_Counter();
- ::Set_Modified ();
- }
- return position;
- }
- ///////////////////////////////////////////////////////////////////////
- //
- // Calc_Ray_Intersection_XY
- //
- ///////////////////////////////////////////////////////////////////////
- bool
- MoverClass::Calc_Ray_Intersection_XY
- (
- float plane,
- const Vector3 &ray_start,
- const Vector3 &ray_end,
- Vector3 & result
- )
- {
- // Assume no intersection
- bool intersected = false;
- if ((ray_end.Z - ray_start.Z) != 0.00F) {
- // Calculate the fraction of the distance along the ray where the
- // Z value of the ray is the same as the Z value of the plane.
- // This simulates an intersection of the ray with the x-y plane at depth 'z'.
- double fraction = double(plane - ray_start.Z) / double(ray_end.Z - ray_start.Z);
- // If the fraction is between 0 and 1, then the ray intersects the plane
- if ((fraction >= 0) && (fraction <= 1.0F)) {
- // Now calcuate the intersection point based on this fraction.
- // To do this we use the parameterized form of a line equation:
- // P = P1 + (P2 - P1) * t
- // (Where t is a percentage between 0 and 1)
- result = ray_start + ((ray_end - ray_start) * fraction);
- // Success!
- intersected = true;
- }
- }
- // Return the true/false result code
- return intersected;
- }
- ///////////////////////////////////////////////////////////////////////
- //
- // Calc_Ray_Intersection_XZ
- //
- ///////////////////////////////////////////////////////////////////////
- bool
- MoverClass::Calc_Ray_Intersection_XZ
- (
- float plane,
- const Vector3 &ray_start,
- const Vector3 &ray_end,
- Vector3 & result
- )
- {
- // Assume no intersection
- bool intersected = false;
- if ((ray_end.Y - ray_start.Y) != 0.00F) {
- // Calculate the fraction of the distance along the ray where the
- // Y value of the ray is the same as the Y value of the plane.
- // This simulates an intersection of the ray with the x-z plane at depth 'y'.
- double fraction = double(plane - ray_start.Y) / double(ray_end.Y - ray_start.Y);
- // If the fraction is between 0 and 1, then the ray intersects the plane
- if ((fraction >= 0) && (fraction <= 1.0F)) {
- // Now calcuate the intersection point based on this fraction.
- // To do this we use the parameterized form of a line equation:
- // P = P1 + (P2 - P1) * t
- // (Where t is a percentage between 0 and 1)
- result = ray_start + ((ray_end - ray_start) * fraction);
- // Success!
- intersected = true;
- }
- }
- // Return the true/false result code
- return intersected;
- }
- ///////////////////////////////////////////////////////////////////////
- //
- // Calc_Ray_Intersection_YZ
- //
- ///////////////////////////////////////////////////////////////////////
- bool
- MoverClass::Calc_Ray_Intersection_YZ
- (
- float plane,
- const Vector3 &ray_start,
- const Vector3 &ray_end,
- Vector3 & result
- )
- {
- // Assume no intersection
- bool intersected = false;
- if ((ray_end.X - ray_start.X) != 0.00F) {
- // Calculate the fraction of the distance along the ray where the
- // X value of the ray is the same as the X value of the plane.
- // This simulates an intersection of the ray with the y-z plane at depth 'x'.
- double fraction = double(plane - ray_start.X) / double(ray_end.X - ray_start.X);
- // If the fraction is between 0 and 1, then the ray intersects the plane
- if ((fraction >= 0) && (fraction <= 1.0F)) {
- // Now calcuate the intersection point based on this fraction.
- // To do this we use the parameterized form of a line equation:
- // P = P1 + (P2 - P1) * t
- // (Where t is a percentage between 0 and 1)
- result = ray_start + ((ray_end - ray_start) * fraction);
- // Success!
- intersected = true;
- }
- }
- // Return the true/false result code
- return intersected;
- }
- ///////////////////////////////////////////////////////////////////////
- //
- // Transform_Node
- //
- ///////////////////////////////////////////////////////////////////////
- void
- MoverClass::Transform_Node
- (
- NodeClass * node,
- const Matrix3D & transform
- )
- {
- //
- // Move this node by the translation delta
- //
- Matrix3D curr_transform = node->Get_Transform ();
- Move_Node (node, transform.Get_Translation () - curr_transform.Get_Translation ());
-
- //
- // Determine a rotation matrix that is relative to the node's current transform
- //
- Matrix3D relative_transform;
- curr_transform.Get_Orthogonal_Inverse (relative_transform);
- Matrix3D rotation_matrix = relative_transform * transform;
- rotation_matrix.Set_Translation (Vector3 (0, 0, 0));
-
- //
- // Rotate the node by this matrix, centered about the new position.
- //
- Matrix3D coord_system (transform.Get_Translation ());
- Rotate_Node (node, rotation_matrix, coord_system);
- return ;
- }
- ///////////////////////////////////////////////////////////////////////
- //
- // Transform_Nodes
- //
- ///////////////////////////////////////////////////////////////////////
- void
- MoverClass::Transform_Nodes
- (
- NodeClass * node,
- const Matrix3D & transform
- )
- {
- NODE_LIST list;
- ::Get_Scene_Editor ()->Build_Node_List (list);
- Transform_Nodes (list, node, transform);
- return ;
- }
- ///////////////////////////////////////////////////////////////////////
- //
- // Transform_Nodes
- //
- ///////////////////////////////////////////////////////////////////////
- void
- MoverClass::Transform_Nodes
- (
- NODE_LIST & list,
- NodeClass * node,
- const Matrix3D & transform
- )
- {
- Matrix3D curr_transform = node->Get_Transform ();
- //
- // Move this list of nodes by the translation delta
- //
- Move_Nodes (list, transform.Get_Translation () - curr_transform.Get_Translation ());
- //
- // Determine a rotation matrix that is relative to the node's current transform
- //
- Matrix3D relative_transform;
- curr_transform.Get_Orthogonal_Inverse (relative_transform);
- Matrix3D rotation_matrix = relative_transform * transform;
- rotation_matrix.Set_Translation (Vector3 (0, 0, 0));
-
- //
- // Rotate the list of nodes by this matrix, centered about the new position.
- //
- Rotate_Nodes (list, rotation_matrix, transform.Get_Translation ());
- return ;
- }
- ///////////////////////////////////////////////////////////////////////
- //
- // Move_Node
- //
- ///////////////////////////////////////////////////////////////////////
- void
- MoverClass::Move_Node (NodeClass *node, const Vector3 &translation)
- {
- node->Translate (translation);
- ::Set_Modified ();
- return ;
- }
- ///////////////////////////////////////////////////////////////////////
- //
- // Move_Nodes
- //
- ///////////////////////////////////////////////////////////////////////
- void
- MoverClass::Simple_Move_Nodes (NODE_LIST &list, const Vector3 &translation)
- {
- for (int index = 0; index < list.Count (); index ++) {
- NodeClass *node = list[index];
- node->Translate (translation);
- }
- return ;
- }
- ///////////////////////////////////////////////////////////////////////
- //
- // Move_Nodes
- //
- ///////////////////////////////////////////////////////////////////////
- void
- MoverClass::Move_Nodes (const Vector3 &translation)
- {
- NODE_LIST list;
- ::Get_Scene_Editor ()->Build_Node_List (list);
- Simple_Move_Nodes (list, translation);
- return ;
- }
- ///////////////////////////////////////////////////////////////////////
- //
- // Move_Nodes
- //
- ///////////////////////////////////////////////////////////////////////
- Vector3
- MoverClass::Move_Nodes (NODE_LIST &list, const Vector3 &tracking_point)
- {
- //
- // Calculate the new position for the group
- //
- Matrix3D coord_system (1);
- Vector3 new_pos = Calc_New_Position (coord_system, tracking_point);
- //
- // Loop through all the nodes and move them by the calculated delta
- //
- for (int index = 0; index < list.Count (); index ++) {
- NodeClass *node = list[index];
-
- //
- // Move the node
- //
- if (node != NULL) {
- node->Translate (new_pos - tracking_point);
- }
- }
- Set_Modified ();
- return new_pos;
- }
- ///////////////////////////////////////////////////////////////////////
- //
- // Calc_New_Position
- //
- ///////////////////////////////////////////////////////////////////////
- Vector3
- MoverClass::Calc_New_Position
- (
- const Matrix3D & coord_system,
- const Vector3 & start_in_world_coords,
- LPPOINT mouse_pos
- )
- {
- Vector3 return_point = start_in_world_coords;
- Vector3 start_point = start_in_world_coords;
- //
- // The start of the ray is simply the camera's position
- //
- Vector3 ray_start = ::Get_Camera_Mgr ()->Get_Camera ()->Get_Transform ().Get_Translation ();
- //
- // Ensure the 'mouse-point' is correct for this mode (fullscreen/windowed)
- //
- CPoint point;
- if (mouse_pos == NULL) {
- ::GetCursorPos (&point);
- ::Get_Main_View()->ScreenToClient (&point);
- } else {
- point = (*mouse_pos);
- }
-
- float xpos = point.x;
- float ypos = point.y;
- ::Constrain_Point_To_Aspect_Ratio (xpos, ypos);
-
- //
- // The 'end' of the ray is the world coordinates of the mouse point
- //
- Vector3 ray_end;
- ::Get_Camera_Mgr ()->Get_Camera ()->Device_To_World_Space (Vector2 (xpos, ypos), &ray_end);
- //
- // However, now we must transform all our coords into the coordinate system we were passed.
- //
- Matrix3D coord_system_inv;
- coord_system.Get_Orthogonal_Inverse (coord_system_inv);
- ray_start = coord_system_inv * ray_start;
- ray_end = coord_system_inv * ray_end;
- start_point = coord_system_inv * start_point;
- return_point = coord_system_inv * return_point;
-
- //
- // Move the ray's endpoint along the line 1000 meters
- //
- ray_end = ray_start + ((ray_end - ray_start) * 1000.00F);
- //
- // Should we restrict movement to the z-axis?
- //
- if ((::GetKeyState (VK_SHIFT) < 0) ||
- (::Get_Current_Document ()->Get_Axis_Restriction () == CLevelEditDoc::RESTRICT_Z)) {
- // Determine which plane (y-z or x-z) to base the movement on
- float deltax = ::fabs (ray_end.X - ray_start.X);
- float deltay = ::fabs (ray_end.Y - ray_start.Y);
-
- // Determine where the ray intersects this plane
- if (deltax > deltay) {
- // Determine where the ray intersects the YZ plane
- Vector3 result;
- if (Calc_Ray_Intersection_YZ (start_point.X, ray_start, ray_end, result)) {
- return_point.Z = result.Z;
- }
-
- } else {
- // Determine where the ray intersects the XZ plane
- Vector3 result;
- if (Calc_Ray_Intersection_XZ (start_point.Y, ray_start, ray_end, result)) {
- return_point.Z = result.Z;
- }
- }
- } else {
-
- // Determine where the ray intersects the XY plane
- Vector3 result;
- if (Calc_Ray_Intersection_XY (start_point.Z, ray_start, ray_end, result)) {
-
- //
- // Now apply the axis restrictions
- //
- if (::Get_Current_Document ()->Get_Axis_Restriction () == CLevelEditDoc::RESTRICT_X) {
- return_point.X = result.X;
- } else if (::Get_Current_Document ()->Get_Axis_Restriction () == CLevelEditDoc::RESTRICT_Y) {
- return_point.Y = result.Y;
- } else {
- return_point = result;
- }
- }
- }
-
- //
- // Now convert the return value to world coords
- //
- return_point = coord_system * return_point;
- // Return the new point
- return return_point;
- }
- ///////////////////////////////////////////////////////////////////////
- //
- // Rotate_Nodes
- //
- ///////////////////////////////////////////////////////////////////////
- void
- MoverClass::Rotate_Nodes
- (
- float deltax,
- float deltay,
- const Quaternion & rotation
- )
- {
- NODE_LIST list;
- Vector3 center = ::Get_Scene_Editor ()->Build_Node_List (list);
- Rotate_Nodes (list, center, deltax, deltay, rotation);
- return ;
- }
- ///////////////////////////////////////////////////////////////////////
- //
- // Rotate_Nodes
- //
- ///////////////////////////////////////////////////////////////////////
- void
- MoverClass::Rotate_Nodes
- (
- NODE_LIST & list,
- const Vector3 & center,
- float deltax,
- float deltay,
- const Quaternion & rotation
- )
- {
- Matrix3D rotation_matrix (1);
- //
- // Are we restricting movement to a specific axis?
- //
- switch (::Get_Current_Document ()->Get_Axis_Restriction ()) {
-
- case CLevelEditDoc::RESTRICT_X:
- rotation_matrix.Rotate_X (deltax * 3.0F);
- break;
- case CLevelEditDoc::RESTRICT_Y:
- rotation_matrix.Rotate_Y (deltay * 3.0F);
- break;
- case CLevelEditDoc::RESTRICT_Z:
- rotation_matrix.Rotate_Z (deltay * 3.0F);
- break;
- case CLevelEditDoc::RESTRICT_NONE:
- rotation_matrix.Set_Rotation (rotation);
- break;
- }
- Rotate_Nodes (list, rotation_matrix, center);
- return ;
- }
- ///////////////////////////////////////////////////////////////////////
- //
- // Rotate_Nodes
- //
- ///////////////////////////////////////////////////////////////////////
- void
- MoverClass::Rotate_Nodes
- (
- NODE_LIST & list,
- const Matrix3D & rotation_matrix,
- const Vector3 & center
- )
- {
- //
- // Setup the rotation
- //
- Matrix3D coord_system (1);
- coord_system.Set_Translation (center);
- //
- // Determine if we should restrict rotation or not
- //
- bool restrict_rotation = false;
- for (int index = 0; index < list.Count (); index ++) {
- restrict_rotation |= list[index]->Is_Rotation_Restricted ();
- }
- //
- // Loop through all the nodes and rotate them
- //
- for (index = 0; index < list.Count (); index ++) {
- NodeClass *node = list[index];
- //
- // Rotate the node
- //
- if (restrict_rotation == false) {
- Rotate_Node_Freely (node, rotation_matrix, coord_system);
- } else {
- Rotate_Node_Z90 (node, rotation_matrix, coord_system);
- }
- }
- Set_Modified ();
- return ;
- }
- ///////////////////////////////////////////////////////////////////////
- //
- // Rotate_Nodes_Z
- //
- ///////////////////////////////////////////////////////////////////////
- void
- MoverClass::Rotate_Nodes_Z (float multiplier)
- {
- NODE_LIST list;
- Vector3 center = ::Get_Scene_Editor ()->Build_Node_List (list);
- Rotate_Nodes_Z (list, center, multiplier);
- return ;
- }
- ///////////////////////////////////////////////////////////////////////
- //
- // Rotate_Nodes_Z
- //
- ///////////////////////////////////////////////////////////////////////
- void
- MoverClass::Rotate_Nodes_Z
- (
- NODE_LIST & list,
- const Vector3 & center,
- float multiplier
- )
- {
- Matrix3D coord_system (1);
- coord_system.Set_Translation (center);
- //
- // Determine if we should restrict rotation or not
- //
- bool restrict_rotation = false;
- for (int index = 0; index < list.Count (); index ++) {
- restrict_rotation |= list[index]->Is_Rotation_Restricted ();
- }
- //
- // Loop through all the nodes and rotate them
- //
- for (index = 0; index < list.Count (); index ++) {
- NodeClass *node = list[index];
- //
- // Determine which rotation matrix to use (Z90 lock, or normal)
- //
- Matrix3D rotation_matrix (1);
- if (restrict_rotation == false) {
- rotation_matrix.Rotate_Z (DEG_TO_RAD (5.0F) * multiplier);
- } else if (multiplier > 0.0F) {
- rotation_matrix.Rotate_Z ((float)DEG_TO_RAD (-90));
- } else {
- rotation_matrix.Rotate_Z ((float)DEG_TO_RAD (90));
- }
- // Rotate the node
- node->Rotate (rotation_matrix, coord_system);
- }
- Set_Modified ();
- return ;
- }
- ///////////////////////////////////////////////////////////////////////
- //
- // Rotate_Node_Z90
- //
- ///////////////////////////////////////////////////////////////////////
- void
- MoverClass::Rotate_Node_Z90
- (
- NodeClass * node,
- const Matrix3D & rotation_matrix,
- const Matrix3D & coord_system
- )
- {
- if (node->Is_Locked () == false) {
- //
- // Get the transformation matrix
- //
- Matrix3D transform = node->Get_Transform ();
- Vector3 translation = transform.Get_Translation ();
- bool allow_translation = bool(coord_system.Get_Translation () != translation);
- Quaternion orientation = node->Get_Orientation ();
- transform.Set_Rotation (orientation);
- //
- // Rotate the transformation matrix in the provided coordinate system
- //
- ::Rotate_Matrix (transform, rotation_matrix, coord_system, &transform);
- //
- // Remember the orientation of the new matrix
- //
- orientation = ::Build_Quaternion (transform);
- node->Set_Orientation (orientation);
- double new_z_rot = transform.Get_Z_Rotation ();
- if (new_z_rot < 0) {
- new_z_rot += DEG_TO_RAD (360);
- }
- if (allow_translation) {
- translation = transform.Get_Translation ();
- }
- // Restrict translation if necessary
- transform.Make_Identity ();
- // Based on the z oomponent of the rotation, determine which
- // direction the object should be facing
- if ((new_z_rot > DEG_TO_RAD (45)) && (new_z_rot <= DEG_TO_RAD (135))) {
- transform = Matrix3D::RotateZ90;
- } else if ((new_z_rot > DEG_TO_RAD (135)) && (new_z_rot <= DEG_TO_RAD (225))) {
- transform = Matrix3D::RotateZ180;
- } else if ((new_z_rot > DEG_TO_RAD (225)) && (new_z_rot <= DEG_TO_RAD (315))) {
- transform = Matrix3D::RotateZ270;
- }
- //
- // Translate the matrix as necessary
- //
- transform.Set_Translation (translation);
- //
- // Pass the new transformation matrix onto the object
- //
- node->Set_Transform (transform);
- node->On_Rotate ();
- }
- return ;
- }
- ///////////////////////////////////////////////////////////////////////
- //
- // Rotate_Node_Freely
- //
- ///////////////////////////////////////////////////////////////////////
- void
- MoverClass::Rotate_Node_Freely
- (
- NodeClass * node,
- const Matrix3D & rotation_matrix,
- const Matrix3D & coord_system
- )
- {
- if (node->Is_Locked () == false) {
- Matrix3D tm = node->Get_Transform ();
- //
- // Translate this node in the specified coordinate system
- //
- Matrix3D coord_inv;
- Matrix3D coord_to_obj;
-
- coord_system.Get_Orthogonal_Inverse (coord_inv);
- Matrix3D::Multiply (coord_inv, tm, &coord_to_obj);
- Matrix3D::Multiply (coord_system, rotation_matrix, &tm);
- Matrix3D::Multiply (tm, coord_to_obj, &tm);
- if (!tm.Is_Orthogonal ()) {
- tm.Re_Orthogonalize ();
- TRACE ("Matrix wasn't orthogonal.\n");
- }
- //
- // Rotate the object and do post processing
- //
- node->Set_Transform (tm);
- node->On_Rotate ();
- }
- return ;
- }
- ///////////////////////////////////////////////////////////////////////
- //
- // Rotate_Node
- //
- ///////////////////////////////////////////////////////////////////////
- void
- MoverClass::Rotate_Node
- (
- NodeClass * node,
- const Matrix3D & rotation_matrix,
- const Matrix3D & coord_system
- )
- {
- //
- // Determine whether the node can be rotated free-form or
- // is restricted to 90 deg rotations about the Z axis.
- //
- if (node->Is_Rotation_Restricted () == false) {
- Rotate_Node_Freely (node, rotation_matrix, coord_system);
- } else {
- Rotate_Node_Z90 (node, rotation_matrix, coord_system);
- }
- return ;
- }
- ///////////////////////////////////////////////////////////////////////
- //
- // Translate_Node
- //
- ///////////////////////////////////////////////////////////////////////
- void
- MoverClass::Translate_Node (NodeClass *node, const Vector3 &vector)
- {
- if (node->Is_Locked () == false) {
-
- //
- // Move the physics object by the requested amount
- //
- Matrix3D tm = node->Get_Transform ();
- tm.Set_Translation (tm.Get_Translation () + vector);
- node->Set_Transform (tm);
- //phys_obj->Set_Position (tm.Get_Translation () + vector);
- /*Phys3Class *phys3_obj = phys_obj->As_Phys3Class ();
- if (phys3_obj != NULL) {
- phys3_obj->Set_Velocity (vector);
- }*/
- // Notify the node
- node->On_Translate ();
- }
- return ;
- }
|