1 //-----------------------------------------------------------------------------
2 // Copyright (c) 2012 GarageGames, LLC
4 // Permission is hereby granted, free of charge, to any person obtaining a copy
5 // of this software and associated documentation files (the "Software"), to
6 // deal in the Software without restriction, including without limitation the
7 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 // sell copies of the Software, and to permit persons to whom the Software is
9 // furnished to do so, subject to the following conditions:
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 //-----------------------------------------------------------------------------
23 #include "platform/platform.h"
24 #include "T3D/camera.h"
26 #include "math/mMath.h"
27 #include "core/stream/bitStream.h"
28 #include "T3D/fx/cameraFXMgr.h"
29 #include "T3D/gameBase/gameConnection.h"
30 #include "math/mathIO.h"
31 #include "gui/worldEditor/editor.h"
32 #include "console/engineAPI.h"
33 #include "console/consoleTypes.h"
34 #include "console/engineAPI.h"
35 #include "math/mathUtils.h"
36 #include "math/mTransform.h"
38 #ifdef TORQUE_EXTENDED_MOVE
39 #include "T3D/gameBase/extended/extendedMove.h"
42 S32
Camera::smExtendedMovePosRotIndex
= 0; // The ExtendedMove position/rotation index used for camera movements
44 #define MaxPitch 1.5706f
45 #define CameraRadius 0.05f;
48 ImplementEnumType( CameraMotionMode
,
49 "Movement behavior type for Camera.\n\n"
50 "@ingroup BaseCamera" )
51 { Camera::StationaryMode
, "Stationary", "Camera does not rotate or move." },
52 { Camera::FreeRotateMode
, "FreeRotate", "Camera may rotate but does not move." },
53 { Camera::FlyMode
, "Fly", "Camera may rotate and move freely." },
54 { Camera::OrbitObjectMode
, "OrbitObject", "Camera orbits about a given object. Damage flash and white out is determined by the object being orbited. See Camera::setOrbitMode() to set the orbit object and other parameters." },
55 { Camera::OrbitPointMode
, "OrbitPoint", "Camera orbits about a given point. See Camera::setOrbitMode() to set the orbit point and other parameters." },
56 { Camera::TrackObjectMode
, "TrackObject", "Camera always faces a given object. See Camera::setTrackObject() to set the object to track and a distance to remain from the object." },
57 { Camera::OverheadMode
, "Overhead", "Camera moves in the XY plane." },
58 { Camera::EditOrbitMode
, "EditOrbit", "Used by the World Editor to orbit about a point. When first activated, the camera is rotated to face the orbit point rather than move to it." }
62 //=============================================================================
64 //=============================================================================
65 // MARK: ---- CameraData ----
67 IMPLEMENT_CO_DATABLOCK_V1( CameraData
);
68 ConsoleDocClass( CameraData
,
69 "@brief A datablock that describes a camera.\n\n"
72 "datablock CameraData(Observer)\n"
74 " mode = \"Observer\";\n"
79 "@ref Datablock_Networking\n"
80 "@ingroup BaseCamera\n"
81 "@ingroup Datablocks\n"
84 //-----------------------------------------------------------------------------
86 void CameraData::initPersistFields()
88 Parent::initPersistFields();
91 //-----------------------------------------------------------------------------
93 void CameraData::packData(BitStream
* stream
)
95 Parent::packData(stream
);
98 //-----------------------------------------------------------------------------
100 void CameraData::unpackData(BitStream
* stream
)
102 Parent::unpackData(stream
);
105 //=============================================================================
107 //=============================================================================
108 // MARK: ---- Camera ----
110 IMPLEMENT_CO_NETOBJECT_V1( Camera
);
111 ConsoleDocClass( Camera
,
112 "@brief Represents a position, direction and field of view to render a scene from.\n\n"
114 "A camera is typically manipulated by a GameConnection. When set as the connection's "
115 "control object, the camera handles all movement actions ($mvForwardAction, $mvPitch, etc.) "
116 "just like a Player.\n"
119 "// Set an already created camera as the GameConnection's control object\n"
120 "%connection.setControlObject(%camera);\n"
123 "<h3>Methods of Operation</h3>\n\n"
125 "The camera has two general methods of operation. The first is the standard mode where "
126 "the camera starts and stops its motion and rotation instantly. This is the default operation "
127 "of the camera and is used by most games. It may be specifically set with Camera::setFlyMode() "
128 "for 6 DoF motion. It is also typically the method used with Camera::setOrbitMode() or one of "
129 "its helper methods to orbit about a specific object (such as the Player's dead body) or a "
130 "specific point.\n\n"
132 "The second method goes under the name of Newton as it follows Newton's 2nd law of "
133 "motion: F=ma. This provides the camera with an ease-in and ease-out feel for both movement "
134 "and rotation. To activate this method for movement, either use Camera::setNewtonFlyMode() or set "
135 "the Camera::newtonMode field to true. To activate this method for rotation, set the Camera::newtonRotation "
136 "to true. This method of operation is not typically used in games, and was developed to allow "
137 "for a smooth fly through of a game level while recording a demo video. But with the right force "
138 "and drag settings, it may give a more organic feel to the camera to games that use an overhead view, "
141 "There is a third, minor method of operation but it is not generally used for games. This is when the "
142 "camera is used with Torque's World Editor in Edit Orbit Mode. When set, this allows the camera "
143 "to rotate about a specific point in the world, and move towards and away from this point. See "
144 "Camera::setEditOrbitMode() and Camera::setEditOrbitPoint(). While in this mode, Camera::autoFitRadius() "
145 "may also be used.\n\n"
148 "// Create a camera in the level and set its position to a given spawn point.\n"
149 "// Note: The camera starts in the standard fly mode.\n"
150 "%cam = new Camera() {\n"
151 " datablock = \"Observer\";\n"
153 "MissionCleanup.add( %cam );\n"
154 "%cam.setTransform( %spawnPoint.getTransform() );\n"
158 "// Create a camera at the given spawn point for the specified\n"
159 "// GameConnection i.e. the client. Uses the standard\n"
160 "// Sim::spawnObject() function to create the camera using the\n"
161 "// defined default settings.\n"
162 "// Note: The camera starts in the standard fly mode.\n"
163 "function GameConnection::spawnCamera(%this, %spawnPoint)\n"
165 " // Set the control object to the default camera\n"
166 " if (!isObject(%this.camera))\n"
168 " if (isDefined(\"$Game::DefaultCameraClass\"))\n"
169 " %this.camera = spawnObject($Game::DefaultCameraClass, $Game::DefaultCameraDataBlock);\n"
172 " // If we have a camera then set up some properties\n"
173 " if (isObject(%this.camera))\n"
175 " // Make sure we're cleaned up when the mission ends\n"
176 " MissionCleanup.add( %this.camera );\n"
178 " // Make sure the camera is always in scope for the connection\n"
179 " %this.camera.scopeToClient(%this);\n"
181 " // Send all user input from the connection to the camera\n"
182 " %this.setControlObject(%this.camera);\n"
184 " if (isDefined(\"%spawnPoint\"))\n"
186 " // Attempt to treat %spawnPoint as an object, such as a\n"
187 " // SpawnSphere class.\n"
188 " if (getWordCount(%spawnPoint) == 1 && isObject(%spawnPoint))\n"
190 " %this.camera.setTransform(%spawnPoint.getTransform());\n"
194 " // Treat %spawnPoint as an AngleAxis transform\n"
195 " %this.camera.setTransform(%spawnPoint);\n"
202 "<h3>Motion Modes</h3>\n\n"
204 "Beyond the different operation methods, the Camera may be set to one of a number "
205 "of motion modes. These motion modes determine how the camera will respond to input "
206 "and may be used to constrain how the Camera moves. The CameraMotionMode enumeration "
207 "defines the possible set of modes and the Camera's current may be obtained by using "
210 "Some of the motion modes may be set using specific script methods. These often provide "
211 "additional parameters to set up the mode in one go. Otherwise, it is always possible to "
212 "set a Camera's motion mode using the controlMode property. Just pass in the name of the "
213 "mode enum. The following table lists the motion modes, how to set them up, and what they offer:\n\n"
215 "<table border='1' cellpadding='1'>"
216 "<tr><th>Mode</th><th>Set From Script</th><th>Input Move</th><th>Input Rotate</th><th>Can Use Newton Mode?</th></tr>"
217 "<tr><td>Stationary</td><td>controlMode property</td><td>No</td><td>No</td><td>No</td></tr>"
218 "<tr><td>FreeRotate</td><td>controlMode property</td><td>No</td><td>Yes</td><td>Rotate Only</td></tr>"
219 "<tr><td>Fly</td><td>setFlyMode()</td><td>Yes</td><td>Yes</td><td>Yes</td></tr>"
220 "<tr><td>OrbitObject</td><td>setOrbitMode()</td><td>Orbits object</td><td>Points to object</td><td>Move only</td></tr>"
221 "<tr><td>OrbitPoint</td><td>setOrbitPoint()</td><td>Orbits point</td><td>Points to location</td><td>Move only</td></tr>"
222 "<tr><td>TrackObject</td><td>setTrackObject()</td><td>No</td><td>Points to object</td><td>Yes</td></tr>"
223 "<tr><td>Overhead</td><td>controlMode property</td><td>Yes</td><td>No</td><td>Yes</td></tr>"
224 "<tr><td>EditOrbit (object selected)</td><td>setEditOrbitMode()</td><td>Orbits object</td><td>Points to object</td><td>Move only</td></tr>"
225 "<tr><td>EditOrbit (no object)</td><td>setEditOrbitMode()</td><td>Yes</td><td>Yes</td><td>Yes</td></tr>"
228 "<h3>%Trigger Input</h3>\n\n"
230 "Passing a move trigger ($mvTriggerCount0, $mvTriggerCount1, etc.) on to a Camera performs "
231 "different actions depending on which mode the camera is in. While in Fly, Overhead or "
232 "EditOrbit mode, either trigger0 or trigger1 will cause a camera to move twice its normal "
233 "movement speed. You can see this in action within the World Editor, where holding down the "
234 "left mouse button while in mouse look mode (right mouse button is also down) causes the Camera "
235 "to move faster.\n\n"
237 "Passing along trigger2 will put the camera into strafe mode. While in this mode a Fly, "
238 "FreeRotate or Overhead Camera will not rotate from the move input. Instead the yaw motion "
239 "will be applied to the Camera's x motion, and the pitch motion will be applied to the Camera's "
240 "z motion. You can see this in action within the World Editor where holding down the middle mouse "
241 "button allows the user to move the camera up, down and side-to-side.\n\n"
243 "While the camera is operating in Newton Mode, trigger0 and trigger1 behave slightly differently. "
244 "Here trigger0 activates a multiplier to the applied acceleration force as defined by speedMultiplier. "
245 "This has the affect of making the camera move up to speed faster. trigger1 has the opposite affect "
246 "by acting as a brake. When trigger1 is active a multiplier is added to the Camera's drag as "
247 "defined by brakeMultiplier.\n\n"
250 "@see CameraMotionMode\n"
251 "@see Camera::movementSpeed\n\n"
252 "@ingroup BaseCamera\n"
255 F32
Camera::smMovementSpeed
= 40.0f
;
257 //----------------------------------------------------------------------------
261 mNetFlags
.clear(Ghostable
);
262 mTypeMask
|= CameraObjectType
;
264 mDelta
.pos
= Point3F(0.0f
, 0.0f
, 100.0f
);
265 mDelta
.rot
= Point3F(0.0f
, 0.0f
, 0.0f
);
266 mDelta
.posVec
= mDelta
.rotVec
= VectorF(0.0f
, 0.0f
, 0.0f
);
267 mObjToWorld
.setColumn(3, mDelta
.pos
);
270 mOffset
.set(0.0f
, 0.0f
, 0.0f
);
272 mMinOrbitDist
= 0.0f
;
273 mMaxOrbitDist
= 0.0f
;
274 mCurOrbitDist
= 0.0f
;
276 mPosition
.set(0.0f
, 0.0f
, 0.0f
);
277 mObservingClientObject
= false;
280 mLastAbsoluteYaw
= 0.0f
;
281 mLastAbsolutePitch
= 0.0f
;
282 mLastAbsoluteRoll
= 0.0f
;
285 mNewtonRotation
= false;
286 mAngularVelocity
.set(0.0f
, 0.0f
, 0.0f
);
287 mAngularForce
= 100.0f
;
289 mVelocity
.set(0.0f
, 0.0f
, 0.0f
);
294 mSpeedMultiplier
= 2.0f
;
295 mBrakeMultiplier
= 2.0f
;
298 mValidEditOrbitPoint
= false;
299 mEditOrbitPoint
.set(0.0f
, 0.0f
, 0.0f
);
300 mCurrentEditOrbitDist
= 2.0;
305 //----------------------------------------------------------------------------
311 //----------------------------------------------------------------------------
315 if(!Parent::onAdd() || !mDataBlock
)
318 mObjBox
.maxExtents
= mObjScale
;
319 mObjBox
.minExtents
= mObjScale
;
320 mObjBox
.minExtents
.neg();
330 //----------------------------------------------------------------------------
332 void Camera::onRemove()
339 //----------------------------------------------------------------------------
341 bool Camera::onNewDataBlock( GameBaseData
*dptr
, bool reload
)
343 mDataBlock
= dynamic_cast<CameraData
*>(dptr
);
344 if ( !mDataBlock
|| !Parent::onNewDataBlock( dptr
, reload
) )
347 scriptOnNewDataBlock();
352 //----------------------------------------------------------------------------
354 void Camera::onEditorEnable()
356 mNetFlags
.set(Ghostable
);
359 //----------------------------------------------------------------------------
361 void Camera::onEditorDisable()
363 mNetFlags
.clear(Ghostable
);
366 //----------------------------------------------------------------------------
368 // check if the object needs to be observed through its own camera...
369 void Camera::getCameraTransform(F32
* pos
, MatrixF
* mat
)
371 // The camera doesn't support a third person mode,
372 // so we want to override the default ShapeBase behavior.
373 ShapeBase
* obj
= dynamic_cast<ShapeBase
*>(static_cast<SimObject
*>(mOrbitObject
));
374 if(obj
&& static_cast<ShapeBaseData
*>(obj
->getDataBlock())->observeThroughObject
)
375 obj
->getCameraTransform(pos
, mat
);
377 getRenderEyeTransform(mat
);
380 mat
->mul( gCamFXMgr
.getTrans() );
383 void Camera::getEyeCameraTransform(IDisplayDevice
*displayDevice
, U32 eyeId
, MatrixF
*outMat
)
385 // The camera doesn't support a third person mode,
386 // so we want to override the default ShapeBase behavior.
387 ShapeBase
* obj
= dynamic_cast<ShapeBase
*>(static_cast<SimObject
*>(mOrbitObject
));
388 if(obj
&& static_cast<ShapeBaseData
*>(obj
->getDataBlock())->observeThroughObject
)
389 obj
->getEyeCameraTransform(displayDevice
, eyeId
, outMat
);
392 Parent::getEyeCameraTransform(displayDevice
, eyeId
, outMat
);
396 //----------------------------------------------------------------------------
398 F32
Camera::getCameraFov()
400 ShapeBase
* obj
= dynamic_cast<ShapeBase
*>(static_cast<SimObject
*>(mOrbitObject
));
401 if(obj
&& static_cast<ShapeBaseData
*>(obj
->getDataBlock())->observeThroughObject
)
402 return(obj
->getCameraFov());
404 return(Parent::getCameraFov());
407 //----------------------------------------------------------------------------
409 F32
Camera::getDefaultCameraFov()
411 ShapeBase
* obj
= dynamic_cast<ShapeBase
*>(static_cast<SimObject
*>(mOrbitObject
));
412 if(obj
&& static_cast<ShapeBaseData
*>(obj
->getDataBlock())->observeThroughObject
)
413 return(obj
->getDefaultCameraFov());
415 return(Parent::getDefaultCameraFov());
418 //----------------------------------------------------------------------------
420 bool Camera::isValidCameraFov(F32 fov
)
422 ShapeBase
* obj
= dynamic_cast<ShapeBase
*>(static_cast<SimObject
*>(mOrbitObject
));
423 if(obj
&& static_cast<ShapeBaseData
*>(obj
->getDataBlock())->observeThroughObject
)
424 return(obj
->isValidCameraFov(fov
));
426 return(Parent::isValidCameraFov(fov
));
429 //----------------------------------------------------------------------------
431 void Camera::setCameraFov(F32 fov
)
433 ShapeBase
* obj
= dynamic_cast<ShapeBase
*>(static_cast<SimObject
*>(mOrbitObject
));
434 if(obj
&& static_cast<ShapeBaseData
*>(obj
->getDataBlock())->observeThroughObject
)
435 obj
->setCameraFov(fov
);
437 Parent::setCameraFov(fov
);
440 //----------------------------------------------------------------------------
442 void clampPitchAngle(F32
&pitch
)
444 // Clamp pitch to +/-MaxPitch, but allow pitch=PI as it is used by some editor
445 // views (bottom, front, right)
446 if ((pitch
> MaxPitch
) && !mIsEqual(pitch
, M_PI_F
, 0.001f
))
448 else if (pitch
< -MaxPitch
)
452 //----------------------------------------------------------------------------
454 void Camera::processTick(const Move
* move
)
456 Parent::processTick(move
);
460 // Update SceneContainer.
468 bool strafeMode
= move
->trigger
[2];
470 // If using editor then force camera into fly mode, unless using EditOrbitMode
471 if(gEditingMission
&& mMode
!= FlyMode
&& mMode
!= EditOrbitMode
)
474 // Massage the mode if we're in EditOrbitMode
475 CameraMotionMode virtualMode
= mMode
;
476 if(mMode
== EditOrbitMode
)
478 if(!mValidEditOrbitPoint
)
480 virtualMode
= FlyMode
;
484 // Reset any Newton camera velocities for when we switch
485 // out of EditOrbitMode.
486 mNewtonRotation
= false;
487 mVelocity
.set(0.0f
, 0.0f
, 0.0f
);
488 mAngularVelocity
.set(0.0f
, 0.0f
, 0.0f
);
492 // Update orientation
493 mDelta
.rotVec
= mRot
;
495 VectorF
rotVec(0, 0, 0);
497 bool doStandardMove
= true;
499 #ifdef TORQUE_EXTENDED_MOVE
500 GameConnection
* con
= getControllingClient();
502 // Work with an absolute rotation from the ExtendedMove class?
503 if(con
&& con
->getControlSchemeAbsoluteRotation())
505 doStandardMove
= false;
506 const ExtendedMove
* emove
= dynamic_cast<const ExtendedMove
*>(move
);
507 U32 emoveIndex
= smExtendedMovePosRotIndex
;
508 if(emoveIndex
>= ExtendedMove::MaxPositionsRotations
)
511 if(emove
->EulerBasedRotation
[emoveIndex
])
513 if(virtualMode
!= StationaryMode
&&
514 virtualMode
!= TrackObjectMode
&&
515 (!mLocked
|| virtualMode
!= OrbitObjectMode
&& virtualMode
!= OrbitPointMode
))
518 mRot
.x
+= (emove
->rotX
[emoveIndex
] - mLastAbsolutePitch
);
520 // Do we also include the relative pitch value?
521 if(con
->getControlSchemeAddPitchToAbsRot() && !strafeMode
)
530 // Constrain the range of mRot.x
531 while (mRot
.x
< -M_PI_F
)
533 while (mRot
.x
> M_PI_F
)
537 mRot
.z
+= (emove
->rotZ
[emoveIndex
] - mLastAbsoluteYaw
);
539 // Do we also include the relative yaw value?
540 if(con
->getControlSchemeAddYawToAbsRot() && !strafeMode
)
549 // Constrain the range of mRot.z
550 while (mRot
.z
< -M_PI_F
)
552 while (mRot
.z
> M_PI_F
)
555 mLastAbsoluteYaw
= emove
->rotZ
[emoveIndex
];
556 mLastAbsolutePitch
= emove
->rotX
[emoveIndex
];
557 mLastAbsoluteRoll
= emove
->rotY
[emoveIndex
];
560 mRot
.y
= emove
->rotY
[emoveIndex
];
562 // Constrain the range of mRot.y
563 while (mRot
.y
> M_PI_F
)
572 // process input/determine rotation vector
573 if(virtualMode
!= StationaryMode
&&
574 virtualMode
!= TrackObjectMode
&&
575 (!mLocked
|| ((virtualMode
!= OrbitObjectMode
) && (virtualMode
!= OrbitPointMode
))))
579 rotVec
.x
= move
->pitch
;
580 rotVec
.z
= move
->yaw
;
583 else if(virtualMode
== TrackObjectMode
&& bool(mOrbitObject
))
585 // orient the camera to face the object
587 // If this is a shapebase, use its render eye transform
588 // to avoid jittering.
589 ShapeBase
*shape
= dynamic_cast<ShapeBase
*>((GameBase
*)mOrbitObject
);
593 shape
->getRenderEyeTransform( &ret
);
594 objPos
= ret
.getPosition();
598 mOrbitObject
->getWorldBox().getCenter(&objPos
);
600 mObjToWorld
.getColumn(3,&pos
);
604 MathUtils::getAnglesFromVector(vec
, yaw
, pitch
);
605 rotVec
.x
= -pitch
- mRot
.x
;
606 rotVec
.z
= yaw
- mRot
.z
;
607 if(rotVec
.z
> M_PI_F
)
609 else if(rotVec
.z
< -M_PI_F
)
613 // apply rotation vector according to physics rules
616 const F32 force
= mAngularForce
;
617 const F32 drag
= mAngularDrag
;
619 VectorF
acc(0.0f
, 0.0f
, 0.0f
);
621 rotVec
.x
*= 2.0f
; // Assume that our -2PI to 2PI range was clamped to -PI to PI in script
622 rotVec
.z
*= 2.0f
; // Assume that our -2PI to 2PI range was clamped to -PI to PI in script
624 F32 rotVecL
= rotVec
.len();
627 acc
= (rotVec
* force
/ mMass
) * TickSec
;
631 mAngularVelocity
+= acc
;
634 mAngularVelocity
-= mAngularVelocity
* drag
* TickSec
;
637 mRot
+= mAngularVelocity
* TickSec
;
638 clampPitchAngle(mRot
.x
);
644 clampPitchAngle(mRot
.x
);
649 VectorF
posVec(0, 0, 0);
650 bool mustValidateEyePoint
= false;
651 bool serverInterpolate
= false;
653 // process input/determine translation vector
654 if(virtualMode
== OrbitObjectMode
|| virtualMode
== OrbitPointMode
)
657 if(virtualMode
== OrbitObjectMode
&& bool(mOrbitObject
))
659 // If this is a shapebase, use its render eye transform
660 // to avoid jittering.
661 GameBase
*castObj
= mOrbitObject
;
662 ShapeBase
* shape
= dynamic_cast<ShapeBase
*>(castObj
);
666 shape
->getRenderEyeTransform( &ret
);
667 mPosition
= ret
.getPosition();
671 // Hopefully this is a static object that doesn't move,
672 // because the worldbox doesn't get updated between ticks.
673 mOrbitObject
->getWorldBox().getCenter(&mPosition
);
677 posVec
= (mPosition
+ mOffset
) - pos
;
678 mustValidateEyePoint
= true;
679 serverInterpolate
= mNewtonMode
;
681 else if(virtualMode
== EditOrbitMode
&& mValidEditOrbitPoint
)
683 bool faster
= move
->trigger
[0] || move
->trigger
[1];
684 F32 scale
= smMovementSpeed
* (faster
+ 1);
685 mCurrentEditOrbitDist
-= move
->y
* TickSec
* scale
;
686 mCurrentEditOrbitDist
-= move
->roll
* TickSec
* scale
; // roll will be -Pi to Pi and we'll attempt to scale it here to be in line with the move->y calculation above
687 if(mCurrentEditOrbitDist
< 0.0f
)
688 mCurrentEditOrbitDist
= 0.0f
;
690 mPosition
= mEditOrbitPoint
;
691 _setPosition(mPosition
, mRot
);
692 _calcEditOrbitPoint(&mObjToWorld
, mRot
);
695 else if(virtualMode
== FlyMode
)
697 bool faster
= move
->trigger
[0] || move
->trigger
[1];
698 F32 scale
= smMovementSpeed
* (faster
+ 1);
700 mObjToWorld
.getColumn(3,&pos
);
701 mObjToWorld
.getColumn(0,&vec
);
702 posVec
= vec
* move
->x
* TickSec
* scale
+ vec
* (strafeMode
? move
->yaw
* 2.0f
* TickSec
* scale
: 0.0f
);
703 mObjToWorld
.getColumn(1,&vec
);
704 posVec
+= vec
* move
->y
* TickSec
* scale
+ vec
* move
->roll
* TickSec
* scale
;
705 mObjToWorld
.getColumn(2,&vec
);
706 posVec
+= vec
* move
->z
* TickSec
* scale
- vec
* (strafeMode
? move
->pitch
* 2.0f
* TickSec
* scale
: 0.0f
);
708 else if(virtualMode
== OverheadMode
)
710 bool faster
= move
->trigger
[0] || move
->trigger
[1];
711 F32 scale
= smMovementSpeed
* (faster
+ 1);
713 mObjToWorld
.getColumn(3,&pos
);
715 mObjToWorld
.getColumn(0,&vec
);
718 vec
= vec
* move
->x
* TickSec
* scale
+ (strafeMode
? vec
* move
->yaw
* 2.0f
* TickSec
* scale
: Point3F(0, 0, 0));
721 mObjToWorld
.getColumn(1,&vec
);
725 mObjToWorld
.getColumn(2,&vec
);
729 vec
= vec
* move
->y
* TickSec
* scale
- (strafeMode
? vec
* move
->pitch
* 2.0f
* TickSec
* scale
: Point3F(0, 0, 0));
731 posVec
.z
+= move
->z
* TickSec
* scale
+ move
->roll
* TickSec
* scale
;
735 mObjToWorld
.getColumn(3,&pos
);
738 // apply translation vector according to physics rules
742 bool faster
= move
->trigger
[0];
743 bool brake
= move
->trigger
[1];
745 const F32 movementSpeedMultiplier
= smMovementSpeed
/ 40.0f
; // Using the starting value as the base
746 const F32 force
= faster
? mFlyForce
* movementSpeedMultiplier
* mSpeedMultiplier
: mFlyForce
* movementSpeedMultiplier
;
747 const F32 drag
= brake
? mDrag
* mBrakeMultiplier
: mDrag
;
749 VectorF
acc(0.0f
, 0.0f
, 0.0f
);
751 F32 posVecL
= posVec
.len();
754 acc
= (posVec
* force
/ mMass
) * TickSec
;
761 mVelocity
-= mVelocity
* drag
* TickSec
;
764 pos
+= mVelocity
* TickSec
;
771 _setPosition(pos
,mRot
);
773 // If on the client, calc delta for backstepping
774 if (serverInterpolate
|| isClientObject())
778 mDelta
.posVec
= mDelta
.posVec
- mDelta
.pos
;
779 mDelta
.rotVec
= mDelta
.rotVec
- mDelta
.rot
;
780 for(U32 i
=0; i
<3; ++i
)
782 if (mDelta
.rotVec
[i
] > M_PI_F
)
783 mDelta
.rotVec
[i
] -= M_2PI_F
;
784 else if (mDelta
.rotVec
[i
] < -M_PI_F
)
785 mDelta
.rotVec
[i
] += M_2PI_F
;
789 if(mustValidateEyePoint
)
790 _validateEyePoint(1.0f
, &mObjToWorld
);
792 setMaskBits(MoveMask
);
795 // Need to calculate the orbit position for the editor so the camera position
796 // doesn't change when switching between orbit and other camera modes
797 if (isServerObject() && (mMode
== EditOrbitMode
&& mValidEditOrbitPoint
))
798 _calcEditOrbitPoint(&mObjToWorld
, mRot
);
800 if(getControllingClient() && mContainer
)
804 //----------------------------------------------------------------------------
806 void Camera::onDeleteNotify( SimObject
* obj
)
808 if( obj
== mOrbitObject
)
812 if( mMode
== OrbitObjectMode
)
813 mMode
= OrbitPointMode
;
816 Parent::onDeleteNotify( obj
);
819 //----------------------------------------------------------------------------
821 void Camera::interpolateTick(F32 dt
)
823 Parent::interpolateTick(dt
);
828 Point3F rot
= mDelta
.rot
+ mDelta
.rotVec
* dt
;
830 if((mMode
== OrbitObjectMode
|| mMode
== OrbitPointMode
) && !mNewtonMode
)
832 if(mMode
== OrbitObjectMode
&& bool(mOrbitObject
))
834 // If this is a shapebase, use its render eye transform
835 // to avoid jittering.
836 GameBase
*castObj
= mOrbitObject
;
837 ShapeBase
* shape
= dynamic_cast<ShapeBase
*>(castObj
);
841 shape
->getRenderEyeTransform( &ret
);
842 mPosition
= ret
.getPosition();
846 // Hopefully this is a static object that doesn't move,
847 // because the worldbox doesn't get updated between ticks.
848 mOrbitObject
->getWorldBox().getCenter(&mPosition
);
851 _setRenderPosition( mPosition
+ mOffset
, rot
);
852 _validateEyePoint( 1.0f
, &mRenderObjToWorld
);
854 else if(mMode
== EditOrbitMode
&& mValidEditOrbitPoint
)
856 mPosition
= mEditOrbitPoint
;
857 _setRenderPosition(mPosition
, rot
);
858 _calcEditOrbitPoint(&mRenderObjToWorld
, rot
);
860 else if(mMode
== TrackObjectMode
&& bool(mOrbitObject
) && !mNewtonRotation
)
862 // orient the camera to face the object
864 // If this is a shapebase, use its render eye transform
865 // to avoid jittering.
866 ShapeBase
*shape
= dynamic_cast<ShapeBase
*>((GameBase
*)mOrbitObject
);
870 shape
->getRenderEyeTransform( &ret
);
871 objPos
= ret
.getPosition();
875 mOrbitObject
->getWorldBox().getCenter(&objPos
);
877 Point3F pos
= mDelta
.pos
+ mDelta
.posVec
* dt
;
878 Point3F vec
= objPos
- pos
;
881 MathUtils::getAnglesFromVector(vec
, yaw
, pitch
);
884 _setRenderPosition(pos
, rot
);
888 Point3F pos
= mDelta
.pos
+ mDelta
.posVec
* dt
;
889 _setRenderPosition(pos
,rot
);
890 if(mMode
== OrbitObjectMode
|| mMode
== OrbitPointMode
)
891 _validateEyePoint(1.0f
, &mRenderObjToWorld
);
895 //----------------------------------------------------------------------------
897 void Camera::_setPosition(const Point3F
& pos
, const Point3F
& rot
)
900 xRot
.set(EulerF(rot
.x
, 0.0f
, 0.0f
));
901 zRot
.set(EulerF(0.0f
, 0.0f
, rot
.z
));
905 if(mDataBlock
&& mDataBlock
->cameraCanBank
)
907 // Take rot.y into account to bank the camera
909 imat
.mul(zRot
, xRot
);
911 ymat
.set(EulerF(0.0f
, rot
.y
, 0.0f
));
912 temp
.mul(imat
, ymat
);
916 temp
.mul(zRot
, xRot
);
919 temp
.setColumn(3, pos
);
920 Parent::setTransform(temp
);
924 //----------------------------------------------------------------------------
926 void Camera::setRotation(const Point3F
& rot
)
929 xRot
.set(EulerF(rot
.x
, 0.0f
, 0.0f
));
930 zRot
.set(EulerF(0.0f
, 0.0f
, rot
.z
));
934 if(mDataBlock
&& mDataBlock
->cameraCanBank
)
936 // Take rot.y into account to bank the camera
938 imat
.mul(zRot
, xRot
);
940 ymat
.set(EulerF(0.0f
, rot
.y
, 0.0f
));
941 temp
.mul(imat
, ymat
);
945 temp
.mul(zRot
, xRot
);
948 temp
.setColumn(3, getPosition());
949 Parent::setTransform(temp
);
953 //----------------------------------------------------------------------------
955 void Camera::_setRenderPosition(const Point3F
& pos
,const Point3F
& rot
)
958 xRot
.set(EulerF(rot
.x
, 0, 0));
959 zRot
.set(EulerF(0, 0, rot
.z
));
963 // mDataBlock may not be defined yet as this method is called during
964 // SceneObject::onAdd().
965 if(mDataBlock
&& mDataBlock
->cameraCanBank
)
967 // Take rot.y into account to bank the camera
969 imat
.mul(zRot
, xRot
);
971 ymat
.set(EulerF(0.0f
, rot
.y
, 0.0f
));
972 temp
.mul(imat
, ymat
);
976 temp
.mul(zRot
, xRot
);
979 temp
.setColumn(3, pos
);
980 Parent::setRenderTransform(temp
);
983 //----------------------------------------------------------------------------
985 void Camera::writePacketData(GameConnection
*connection
, BitStream
*bstream
)
987 // Update client regardless of status flags.
988 Parent::writePacketData(connection
, bstream
);
991 mObjToWorld
.getColumn(3,&pos
);
992 bstream
->setCompressionPoint(pos
);
993 mathWrite(*bstream
, pos
);
994 bstream
->write(mRot
.x
);
995 if(mDataBlock
&& bstream
->writeFlag(mDataBlock
->cameraCanBank
))
997 // Include mRot.y to allow for camera banking
998 bstream
->write(mRot
.y
);
1000 bstream
->write(mRot
.z
);
1002 U32 writeMode
= mMode
;
1003 Point3F writePos
= mPosition
;
1005 if(mMode
== OrbitObjectMode
)
1007 gIndex
= bool(mOrbitObject
) ? connection
->getGhostIndex(mOrbitObject
): -1;
1010 writeMode
= OrbitPointMode
;
1011 if(bool(mOrbitObject
))
1012 mOrbitObject
->getWorldBox().getCenter(&writePos
);
1015 else if(mMode
== TrackObjectMode
)
1017 gIndex
= bool(mOrbitObject
) ? connection
->getGhostIndex(mOrbitObject
): -1;
1019 writeMode
= StationaryMode
;
1021 bstream
->writeRangedU32(writeMode
, CameraFirstMode
, CameraLastMode
);
1023 if (writeMode
== OrbitObjectMode
|| writeMode
== OrbitPointMode
)
1025 bstream
->write(mMinOrbitDist
);
1026 bstream
->write(mMaxOrbitDist
);
1027 bstream
->write(mCurOrbitDist
);
1028 if(writeMode
== OrbitObjectMode
)
1030 bstream
->writeFlag(mObservingClientObject
);
1031 bstream
->writeInt(gIndex
, NetConnection::GhostIdBitSize
);
1033 if (writeMode
== OrbitPointMode
)
1034 bstream
->writeCompressedPoint(writePos
);
1036 else if(writeMode
== TrackObjectMode
)
1038 bstream
->writeInt(gIndex
, NetConnection::GhostIdBitSize
);
1041 if(bstream
->writeFlag(mNewtonMode
))
1043 bstream
->write(mVelocity
.x
);
1044 bstream
->write(mVelocity
.y
);
1045 bstream
->write(mVelocity
.z
);
1047 if(bstream
->writeFlag(mNewtonRotation
))
1049 bstream
->write(mAngularVelocity
.x
);
1050 bstream
->write(mAngularVelocity
.y
);
1051 bstream
->write(mAngularVelocity
.z
);
1054 bstream
->writeFlag(mValidEditOrbitPoint
);
1055 if(writeMode
== EditOrbitMode
)
1057 bstream
->write(mEditOrbitPoint
.x
);
1058 bstream
->write(mEditOrbitPoint
.y
);
1059 bstream
->write(mEditOrbitPoint
.z
);
1060 bstream
->write(mCurrentEditOrbitDist
);
1064 //----------------------------------------------------------------------------
1066 void Camera::readPacketData(GameConnection
*connection
, BitStream
*bstream
)
1068 Parent::readPacketData(connection
, bstream
);
1070 mathRead(*bstream
, &pos
);
1071 bstream
->setCompressionPoint(pos
);
1072 bstream
->read(&rot
.x
);
1073 if(bstream
->readFlag())
1075 // Include rot.y to allow for camera banking
1076 bstream
->read(&rot
.y
);
1078 bstream
->read(&rot
.z
);
1081 mMode
= (CameraMotionMode
)bstream
->readRangedU32(CameraFirstMode
, CameraLastMode
);
1082 mObservingClientObject
= false;
1083 if (mMode
== OrbitObjectMode
|| mMode
== OrbitPointMode
)
1085 bstream
->read(&mMinOrbitDist
);
1086 bstream
->read(&mMaxOrbitDist
);
1087 bstream
->read(&mCurOrbitDist
);
1089 if(mMode
== OrbitObjectMode
)
1091 mObservingClientObject
= bstream
->readFlag();
1092 S32 gIndex
= bstream
->readInt(NetConnection::GhostIdBitSize
);
1093 obj
= static_cast<GameBase
*>(connection
->resolveGhost(gIndex
));
1095 if (mMode
== OrbitPointMode
)
1096 bstream
->readCompressedPoint(&mPosition
);
1098 else if (mMode
== TrackObjectMode
)
1100 S32 gIndex
= bstream
->readInt(NetConnection::GhostIdBitSize
);
1101 obj
= static_cast<GameBase
*>(connection
->resolveGhost(gIndex
));
1104 if (obj
!= (GameBase
*)mOrbitObject
)
1108 clearProcessAfter();
1109 clearNotify(mOrbitObject
);
1115 processAfter(mOrbitObject
);
1116 deleteNotify(mOrbitObject
);
1120 mNewtonMode
= bstream
->readFlag();
1123 bstream
->read(&mVelocity
.x
);
1124 bstream
->read(&mVelocity
.y
);
1125 bstream
->read(&mVelocity
.z
);
1128 mNewtonRotation
= bstream
->readFlag();
1131 bstream
->read(&mAngularVelocity
.x
);
1132 bstream
->read(&mAngularVelocity
.y
);
1133 bstream
->read(&mAngularVelocity
.z
);
1136 mValidEditOrbitPoint
= bstream
->readFlag();
1137 if(mMode
== EditOrbitMode
)
1139 bstream
->read(&mEditOrbitPoint
.x
);
1140 bstream
->read(&mEditOrbitPoint
.y
);
1141 bstream
->read(&mEditOrbitPoint
.z
);
1142 bstream
->read(&mCurrentEditOrbitDist
);
1145 _setPosition(pos
,rot
);
1146 // Movement in OrbitObjectMode is not input-based - don't reset interpolation
1147 if(mMode
!= OrbitObjectMode
)
1150 mDelta
.posVec
.set(0.0f
, 0.0f
, 0.0f
);
1152 mDelta
.rotVec
.set(0.0f
, 0.0f
, 0.0f
);
1156 //----------------------------------------------------------------------------
1158 U32
Camera::packUpdate(NetConnection
*con
, U32 mask
, BitStream
*bstream
)
1160 Parent::packUpdate(con
, mask
, bstream
);
1162 if (bstream
->writeFlag(mask
& UpdateMask
))
1164 bstream
->writeFlag(mLocked
);
1165 mathWrite(*bstream
, mOffset
);
1168 if(bstream
->writeFlag(mask
& NewtonCameraMask
))
1170 bstream
->write(mAngularForce
);
1171 bstream
->write(mAngularDrag
);
1172 bstream
->write(mMass
);
1173 bstream
->write(mDrag
);
1174 bstream
->write(mFlyForce
);
1175 bstream
->write(mSpeedMultiplier
);
1176 bstream
->write(mBrakeMultiplier
);
1179 if(bstream
->writeFlag(mask
& EditOrbitMask
))
1181 bstream
->write(mEditOrbitPoint
.x
);
1182 bstream
->write(mEditOrbitPoint
.y
);
1183 bstream
->write(mEditOrbitPoint
.z
);
1184 bstream
->write(mCurrentEditOrbitDist
);
1187 // The rest of the data is part of the control object packet update.
1188 // If we're controlled by this client, we don't need to send it.
1189 if(bstream
->writeFlag(getControllingClient() == con
&& !(mask
& InitialUpdateMask
)))
1192 if (bstream
->writeFlag(mask
& MoveMask
))
1195 mObjToWorld
.getColumn(3,&pos
);
1196 bstream
->write(pos
.x
);
1197 bstream
->write(pos
.y
);
1198 bstream
->write(pos
.z
);
1199 bstream
->write(mRot
.x
);
1200 bstream
->write(mRot
.z
);
1202 // Only required if in NewtonFlyMode
1203 F32 len
= mVelocity
.len();
1204 if(bstream
->writeFlag(mNewtonMode
&& len
> 0.02f
))
1206 Point3F outVel
= mVelocity
;
1208 bstream
->writeNormalVector(outVel
, 10);
1209 len
*= 32.0f
; // 5 bits of fraction
1212 bstream
->writeInt((S32
)len
, 13);
1216 len
= mAngularVelocity
.len();
1217 if(bstream
->writeFlag(mNewtonRotation
&& len
> 0.02f
))
1219 Point3F outVel
= mAngularVelocity
;
1221 bstream
->writeNormalVector(outVel
, 10);
1222 len
*= 32.0f
; // 5 bits of fraction
1225 bstream
->writeInt((S32
)len
, 13);
1232 //----------------------------------------------------------------------------
1234 void Camera::unpackUpdate(NetConnection
*con
, BitStream
*bstream
)
1236 Parent::unpackUpdate(con
,bstream
);
1238 if (bstream
->readFlag())
1240 mLocked
= bstream
->readFlag();
1241 mathRead(*bstream
, &mOffset
);
1245 if(bstream
->readFlag())
1247 bstream
->read(&mAngularForce
);
1248 bstream
->read(&mAngularDrag
);
1249 bstream
->read(&mMass
);
1250 bstream
->read(&mDrag
);
1251 bstream
->read(&mFlyForce
);
1252 bstream
->read(&mSpeedMultiplier
);
1253 bstream
->read(&mBrakeMultiplier
);
1257 if(bstream
->readFlag())
1259 bstream
->read(&mEditOrbitPoint
.x
);
1260 bstream
->read(&mEditOrbitPoint
.y
);
1261 bstream
->read(&mEditOrbitPoint
.z
);
1262 bstream
->read(&mCurrentEditOrbitDist
);
1265 // controlled by the client?
1266 if(bstream
->readFlag())
1270 if (bstream
->readFlag())
1273 bstream
->read(&pos
.x
);
1274 bstream
->read(&pos
.y
);
1275 bstream
->read(&pos
.z
);
1276 bstream
->read(&rot
.x
);
1277 bstream
->read(&rot
.z
);
1278 _setPosition(pos
,rot
);
1281 if(bstream
->readFlag())
1283 bstream
->readNormalVector(&mVelocity
, 10);
1284 mVelocity
*= bstream
->readInt(13) / 32.0f
;
1288 mNewtonRotation
= bstream
->readFlag();
1291 bstream
->readNormalVector(&mAngularVelocity
, 10);
1292 mAngularVelocity
*= bstream
->readInt(13) / 32.0f
;
1295 if(mMode
!= OrbitObjectMode
)
1297 // New delta for client side interpolation
1300 mDelta
.posVec
= mDelta
.rotVec
= VectorF(0.0f
, 0.0f
, 0.0f
);
1305 //----------------------------------------------------------------------------
1307 void Camera::initPersistFields()
1309 addGroup( "Camera" );
1310 addProtectedField( "controlMode", TYPEID
< CameraMotionMode
>(), Offset( mMode
, Camera
),
1311 &_setModeField
, &defaultProtectedGetFn
,
1312 "The current camera control mode." );
1313 endGroup( "Camera" );
1315 addGroup( "Camera: Newton Mode" );
1316 addField( "newtonMode", TypeBool
, Offset(mNewtonMode
, Camera
),
1317 "Apply smoothing (acceleration and damping) to camera movements." );
1318 addField( "newtonRotation", TypeBool
, Offset(mNewtonRotation
, Camera
),
1319 "Apply smoothing (acceleration and damping) to camera rotations." );
1320 addProtectedField( "mass", TypeF32
, Offset(mMass
, Camera
), &_setNewtonField
, &defaultProtectedGetFn
,
1321 "The camera's mass (Newton mode only). Default value is 10." );
1322 addProtectedField( "drag", TypeF32
, Offset(mDrag
, Camera
), &_setNewtonField
, &defaultProtectedGetFn
,
1323 "Drag on camera when moving (Newton mode only). Default value is 2." );
1324 addProtectedField( "force", TypeF32
, Offset(mFlyForce
, Camera
), &_setNewtonField
, &defaultProtectedGetFn
,
1325 "Force applied on camera when asked to move (Newton mode only). Default value is 500." );
1326 addProtectedField( "angularDrag", TypeF32
, Offset(mAngularDrag
, Camera
), &_setNewtonField
, &defaultProtectedGetFn
,
1327 "Drag on camera when rotating (Newton mode only). Default value is 2." );
1328 addProtectedField( "angularForce", TypeF32
, Offset(mAngularForce
, Camera
), &_setNewtonField
, &defaultProtectedGetFn
,
1329 "Force applied on camera when asked to rotate (Newton mode only). Default value is 100." );
1330 addProtectedField( "speedMultiplier", TypeF32
, Offset(mSpeedMultiplier
, Camera
), &_setNewtonField
, &defaultProtectedGetFn
,
1331 "Speed multiplier when triggering the accelerator (Newton mode only). Default value is 2." );
1332 addProtectedField( "brakeMultiplier", TypeF32
, Offset(mBrakeMultiplier
, Camera
), &_setNewtonField
, &defaultProtectedGetFn
,
1333 "Speed multiplier when triggering the brake (Newton mode only). Default value is 2." );
1334 endGroup( "Camera: Newton Mode" );
1336 Parent::initPersistFields();
1339 //-----------------------------------------------------------------------------
1341 void Camera::consoleInit()
1343 Con::addVariable("$Camera::movementSpeed", TypeF32
, &smMovementSpeed
,
1344 "@brief Global camera movement speed in units/s (typically m/s), with a base value of 40.\n\n"
1345 "Used in the following camera modes:\n"
1346 "- Edit Orbit Mode\n"
1349 "@ingroup BaseCamera\n");
1351 // ExtendedMove support
1352 Con::addVariable("$camera::extendedMovePosRotIndex", TypeS32
, &smExtendedMovePosRotIndex
,
1353 "@brief The ExtendedMove position/rotation index used for camera movements.\n\n"
1354 "@ingroup BaseCamera\n");
1357 //-----------------------------------------------------------------------------
1359 bool Camera::_setNewtonField( void *object
, const char *index
, const char *data
)
1361 static_cast<Camera
*>(object
)->setMaskBits(NewtonCameraMask
);
1362 return true; // ok to set value
1365 //-----------------------------------------------------------------------------
1367 bool Camera::_setModeField( void *object
, const char *index
, const char *data
)
1369 Camera
*cam
= static_cast<Camera
*>( object
);
1371 if( dStricmp(data
, "Fly") == 0 )
1374 return false; // already changed mode
1377 else if( dStricmp(data
, "EditOrbit" ) == 0 )
1379 cam
->setEditOrbitMode();
1380 return false; // already changed mode
1383 else if( (dStricmp(data
, "OrbitObject") == 0 && cam
->mMode
!= OrbitObjectMode
) ||
1384 (dStricmp(data
, "TrackObject") == 0 && cam
->mMode
!= TrackObjectMode
) ||
1385 (dStricmp(data
, "OrbitPoint") == 0 && cam
->mMode
!= OrbitPointMode
) )
1387 Con::warnf("Couldn't change Camera mode to %s: required information missing. Use camera.set%s().", data
, data
);
1388 return false; // don't change the mode - not valid
1391 else if( dStricmp(data
, "OrbitObject") != 0 &&
1392 dStricmp(data
, "TrackObject") != 0 &&
1393 bool(cam
->mOrbitObject
) )
1395 cam
->clearProcessAfter();
1396 cam
->clearNotify(cam
->mOrbitObject
);
1397 cam
->mOrbitObject
= NULL
;
1400 // make sure the requested mode is supported, and set it
1401 // NOTE: The _CameraMode namespace is generated by ImplementEnumType above
1403 const EngineEnumTable
& enums
= *( TYPE
< CameraMotionMode
>()->getEnumTable() );
1404 const U32 numValues
= enums
.getNumValues();
1406 for( S32 i
= 0; i
< numValues
; ++i
)
1408 if( dStricmp(data
, enums
[i
].mName
) == 0 )
1410 cam
->mMode
= (CameraMotionMode
) enums
[i
].mInt
;
1415 Con::warnf("Unsupported camera mode: %s", data
);
1419 //-----------------------------------------------------------------------------
1421 Point3F
Camera::getPosition()
1423 static Point3F position
;
1424 mObjToWorld
.getColumn(3, &position
);
1428 //-----------------------------------------------------------------------------
1430 void Camera::setFlyMode()
1434 if (bool(mOrbitObject
))
1436 clearProcessAfter();
1437 clearNotify(mOrbitObject
);
1439 mOrbitObject
= NULL
;
1442 //-----------------------------------------------------------------------------
1444 void Camera::setNewtonFlyMode()
1450 //-----------------------------------------------------------------------------
1452 void Camera::setOrbitMode(GameBase
*obj
, const Point3F
&pos
, const Point3F
&rot
, const Point3F
& offset
, F32 minDist
, F32 maxDist
, F32 curDist
, bool ownClientObject
, bool locked
)
1454 mObservingClientObject
= ownClientObject
;
1456 if (bool(mOrbitObject
))
1458 clearProcessAfter();
1459 clearNotify(mOrbitObject
);
1463 if(bool(mOrbitObject
))
1465 processAfter(mOrbitObject
);
1466 deleteNotify(mOrbitObject
);
1467 mOrbitObject
->getWorldBox().getCenter(&mPosition
);
1468 mMode
= OrbitObjectMode
;
1472 mMode
= OrbitPointMode
;
1476 _setPosition(mPosition
, rot
);
1478 mMinOrbitDist
= minDist
;
1479 mMaxOrbitDist
= maxDist
;
1480 mCurOrbitDist
= curDist
;
1482 if (locked
!= mLocked
|| mOffset
!= offset
)
1486 setMaskBits(UpdateMask
);
1490 //-----------------------------------------------------------------------------
1492 void Camera::setTrackObject(GameBase
*obj
, const Point3F
&offset
)
1494 if(bool(mOrbitObject
))
1496 clearProcessAfter();
1497 clearNotify(mOrbitObject
);
1500 if(bool(mOrbitObject
))
1502 processAfter(mOrbitObject
);
1503 deleteNotify(mOrbitObject
);
1507 mMode
= TrackObjectMode
;
1509 setMaskBits( UpdateMask
);
1512 //-----------------------------------------------------------------------------
1514 void Camera::_validateEyePoint(F32 pos
, MatrixF
*mat
)
1518 // Use the eye transform to orient the camera
1520 mat
->getColumn(1, &dir
);
1521 if (mMaxOrbitDist
- mMinOrbitDist
> 0.0f
)
1522 pos
*= mMaxOrbitDist
- mMinOrbitDist
;
1524 // Use the camera node's pos.
1525 Point3F startPos
= getRenderPosition();
1528 // Make sure we don't extend the camera into anything solid
1530 mOrbitObject
->disableCollision();
1533 U32 mask
= TerrainObjectType
|
1535 StaticShapeObjectType
|
1540 SceneContainer
* pContainer
= isServerObject() ? &gServerContainer
: &gClientContainer
;
1541 if (!pContainer
->castRay(startPos
, startPos
- dir
* 2.5 * pos
, mask
, &collision
))
1542 endPos
= startPos
- dir
* pos
;
1545 float dot
= mDot(dir
, collision
.normal
);
1548 F32 colDist
= mDot(startPos
- collision
.point
, dir
) - (1 / dot
) * CameraRadius
;
1553 endPos
= startPos
- dir
* colDist
;
1556 endPos
= startPos
- dir
* pos
;
1558 mat
->setColumn(3, endPos
);
1561 mOrbitObject
->enableCollision();
1565 //-----------------------------------------------------------------------------
1567 void Camera::setTransform(const MatrixF
& mat
)
1569 // This method should never be called on the client.
1571 // This currently converts all rotation in the mat into
1572 // rotations around the z and x axis.
1574 mat
.getColumn(1, &vec
);
1575 mat
.getColumn(3, &pos
);
1576 Point3F
rot(-mAtan2(vec
.z
, mSqrt(vec
.x
* vec
.x
+ vec
.y
* vec
.y
)), 0.0f
, -mAtan2(-vec
.x
, vec
.y
));
1577 _setPosition(pos
,rot
);
1580 //-----------------------------------------------------------------------------
1582 void Camera::setRenderTransform(const MatrixF
& mat
)
1584 // This method should never be called on the client.
1586 // This currently converts all rotation in the mat into
1587 // rotations around the z and x axis.
1589 mat
.getColumn(1,&vec
);
1590 mat
.getColumn(3,&pos
);
1591 Point3F
rot(-mAtan2(vec
.z
, mSqrt(vec
.x
*vec
.x
+ vec
.y
*vec
.y
)),0,-mAtan2(-vec
.x
,vec
.y
));
1592 _setRenderPosition(pos
,rot
);
1595 //-----------------------------------------------------------------------------
1597 F32
Camera::getDamageFlash() const
1599 if (mMode
== OrbitObjectMode
&& isServerObject() && bool(mOrbitObject
))
1601 const GameBase
*castObj
= mOrbitObject
;
1602 const ShapeBase
* psb
= dynamic_cast<const ShapeBase
*>(castObj
);
1604 return psb
->getDamageFlash();
1607 return mDamageFlash
;
1610 //-----------------------------------------------------------------------------
1612 F32
Camera::getWhiteOut() const
1614 if (mMode
== OrbitObjectMode
&& isServerObject() && bool(mOrbitObject
))
1616 const GameBase
*castObj
= mOrbitObject
;
1617 const ShapeBase
* psb
= dynamic_cast<const ShapeBase
*>(castObj
);
1619 return psb
->getWhiteOut();
1625 //-----------------------------------------------------------------------------
1627 void Camera::setVelocity(const VectorF
& vel
)
1630 setMaskBits(MoveMask
);
1633 //-----------------------------------------------------------------------------
1635 void Camera::setAngularVelocity(const VectorF
& vel
)
1637 mAngularVelocity
= vel
;
1638 setMaskBits(MoveMask
);
1641 //-----------------------------------------------------------------------------
1643 void Camera::setEditOrbitMode()
1645 mMode
= EditOrbitMode
;
1647 if (bool(mOrbitObject
))
1649 clearProcessAfter();
1650 clearNotify(mOrbitObject
);
1652 mOrbitObject
= NULL
;
1654 // If there is a valid orbit point, then point to it
1655 // rather than move the camera.
1656 if(mValidEditOrbitPoint
)
1659 mObjToWorld
.getColumn(3,¤tPos
);
1661 Point3F dir
= mEditOrbitPoint
- currentPos
;
1662 mCurrentEditOrbitDist
= dir
.len();
1666 MathUtils::getAnglesFromVector(dir
, yaw
, pitch
);
1672 //-----------------------------------------------------------------------------
1674 void Camera::_calcOrbitPoint( MatrixF
* mat
, const Point3F
& rot
)
1678 pos
.x
= mCurOrbitDist
* mSin( rot
.x
+ mDegToRad( 90.0f
) ) * mCos( -1.0f
* ( rot
.z
+ mDegToRad( 90.0f
) ) ) + mPosition
.x
+ mOffset
.x
;
1679 pos
.y
= mCurOrbitDist
* mSin( rot
.x
+ mDegToRad( 90.0f
) ) * mSin( -1.0f
* ( rot
.z
+ mDegToRad( 90.0f
) ) ) + mPosition
.y
+ mOffset
.y
;
1680 pos
.z
= mCurOrbitDist
* mSin( rot
.x
) + mPosition
.z
+ mOffset
.z
;
1682 mat
->setColumn( 3, pos
);
1685 //-----------------------------------------------------------------------------
1687 void Camera::_calcEditOrbitPoint( MatrixF
*mat
, const Point3F
& rot
)
1690 //mat->getColumn(1, &dir);
1692 //Point3F startPos = getRenderPosition();
1693 //Point3F endPos = startPos - dir * mCurrentEditOrbitDist;
1696 pos
.x
= mCurrentEditOrbitDist
* mSin(rot
.x
+ mDegToRad(90.0f
)) * mCos(-1.0f
* (rot
.z
+ mDegToRad(90.0f
))) + mEditOrbitPoint
.x
;
1697 pos
.y
= mCurrentEditOrbitDist
* mSin(rot
.x
+ mDegToRad(90.0f
)) * mSin(-1.0f
* (rot
.z
+ mDegToRad(90.0f
))) + mEditOrbitPoint
.y
;
1698 pos
.z
= mCurrentEditOrbitDist
* mSin(rot
.x
) + mEditOrbitPoint
.z
;
1700 mat
->setColumn(3, pos
);
1703 //-----------------------------------------------------------------------------
1705 void Camera::setValidEditOrbitPoint( bool state
)
1707 mValidEditOrbitPoint
= state
;
1708 setMaskBits(EditOrbitMask
);
1711 //-----------------------------------------------------------------------------
1713 Point3F
Camera::getEditOrbitPoint() const
1715 return mEditOrbitPoint
;
1718 //-----------------------------------------------------------------------------
1720 void Camera::setEditOrbitPoint( const Point3F
& pnt
)
1722 // Change the point that we orbit in EditOrbitMode.
1723 // We'll also change the facing and distance of the
1724 // camera so that it doesn't jump around.
1726 mObjToWorld
.getColumn(3,¤tPos
);
1728 Point3F dir
= pnt
- currentPos
;
1729 mCurrentEditOrbitDist
= dir
.len();
1731 if(mMode
== EditOrbitMode
)
1736 MathUtils::getAnglesFromVector(dir
, yaw
, pitch
);
1741 mEditOrbitPoint
= pnt
;
1743 setMaskBits(EditOrbitMask
);
1746 //----------------------------------------------------------------------------
1748 void Camera::lookAt( const Point3F
& pos
)
1751 mObjToWorld
.getColumn(3, &mPosition
);
1752 vec
= pos
- mPosition
;
1753 vec
.normalizeSafe();
1755 MathUtils::getAnglesFromVector(vec
, yaw
, pitch
);
1758 _setPosition(mPosition
, mRot
);
1761 //----------------------------------------------------------------------------
1763 void Camera::autoFitRadius( F32 radius
)
1765 F32 fov
= mDegToRad( getCameraFov() );
1766 F32 viewradius
= (radius
* 2.0f
) / mTan(fov
* 0.5f
);
1768 // Be careful of infinite sized objects. Clip to 16km
1769 if(viewradius
> 16000.0f
)
1770 viewradius
= 16000.0f
;
1772 if(mMode
== EditOrbitMode
&& mValidEditOrbitPoint
)
1774 mCurrentEditOrbitDist
= viewradius
;
1776 else if(mValidEditOrbitPoint
)
1778 mCurrentEditOrbitDist
= viewradius
;
1781 mObjToWorld
.getColumn(3,¤tPos
);
1783 Point3F dir
= mEditOrbitPoint
- currentPos
;
1787 MathUtils::getAnglesFromVector(dir
, yaw
, pitch
);
1791 mPosition
= mEditOrbitPoint
;
1792 _setPosition(mPosition
, mRot
);
1793 _calcEditOrbitPoint(&mObjToWorld
, mRot
);
1797 //=============================================================================
1799 //=============================================================================
1800 // MARK: ---- Console API ----
1802 //-----------------------------------------------------------------------------
1804 DefineEngineMethod( Camera
, getMode
, Camera::CameraMotionMode
, (), ,
1805 "Returns the current camera control mode.\n\n"
1806 "@see CameraMotionMode")
1808 return object
->getMode();
1811 //-----------------------------------------------------------------------------
1813 DefineEngineMethod( Camera
, getPosition
, Point3F
, (), ,
1814 "Get the camera's position in the world.\n\n"
1815 "@returns The position in the form of \"x y z\".")
1817 return object
->getPosition();
1820 //-----------------------------------------------------------------------------
1822 DefineEngineMethod( Camera
, getRotation
, Point3F
, (), ,
1823 "Get the camera's Euler rotation in radians.\n\n"
1824 "@returns The rotation in radians in the form of \"x y z\".")
1826 return object
->getRotation();
1829 //-----------------------------------------------------------------------------
1831 DefineEngineMethod( Camera
, setRotation
, void, ( Point3F rot
), ,
1832 "Set the camera's Euler rotation in radians.\n\n"
1833 "@param rot The rotation in radians in the form of \"x y z\"."
1834 "@note Rotation around the Y axis is ignored" )
1836 return object
->setRotation( rot
);
1839 //-----------------------------------------------------------------------------
1841 DefineEngineMethod( Camera
, getOffset
, Point3F
, (), ,
1842 "Get the camera's offset from its orbit or tracking point.\n\n"
1843 "The offset is added to the camera's position when set to CameraMode::OrbitObject.\n"
1844 "@returns The offset in the form of \"x y z\".")
1846 return object
->getOffset();
1849 //-----------------------------------------------------------------------------
1851 DefineEngineMethod( Camera
, setOffset
, void, (Point3F offset
), ,
1852 "Set the camera's offset.\n\n"
1853 "The offset is added to the camera's position when set to CameraMode::OrbitObject.\n"
1854 "@param offset The distance to offset the camera by in the form of \"x y z\".")
1856 object
->setOffset(offset
);
1859 //-----------------------------------------------------------------------------
1861 DefineEngineMethod( Camera
, setOrbitMode
, void, (GameBase
* orbitObject
, TransformF orbitPoint
, F32 minDistance
, F32 maxDistance
,
1862 F32 initDistance
, bool ownClientObj
, Point3F offset
, bool locked
), (false, Point3F::Zero
, false),
1863 "Set the camera to orbit around the given object, or if none is given, around the given point.\n\n"
1864 "@param orbitObject The object to orbit around. If no object is given (0 or blank string is passed in) use the orbitPoint instead\n"
1865 "@param orbitPoint The point to orbit around when no object is given. In the form of \"x y z ax ay az aa\" such as returned by SceneObject::getTransform().\n"
1866 "@param minDistance The minimum distance allowed to the orbit object or point.\n"
1867 "@param maxDistance The maximum distance allowed from the orbit object or point.\n"
1868 "@param initDistance The initial distance from the orbit object or point.\n"
1869 "@param ownClientObj [optional] Are we orbiting an object that is owned by us? Default is false.\n"
1870 "@param offset [optional] An offset added to the camera's position. Default is no offset.\n"
1871 "@param locked [optional] Indicates the camera does not receive input from the player. Default is false.\n"
1872 "@see Camera::setOrbitObject()\n"
1873 "@see Camera::setOrbitPoint()\n")
1876 orbitPoint
.mOrientation
.setMatrix(&mat
);
1877 object
->setOrbitMode(orbitObject
, orbitPoint
.mPosition
, mat
.toEuler(), offset
,
1878 minDistance
, maxDistance
, initDistance
, ownClientObj
, locked
);
1881 //-----------------------------------------------------------------------------
1883 DefineEngineMethod( Camera
, setOrbitObject
, bool, (GameBase
* orbitObject
, VectorF rotation
, F32 minDistance
,
1884 F32 maxDistance
, F32 initDistance
, bool ownClientObject
, Point3F offset
, bool locked
),
1885 (false, Point3F::Zero
, false),
1886 "Set the camera to orbit around a given object.\n\n"
1887 "@param orbitObject The object to orbit around.\n"
1888 "@param rotation The initial camera rotation about the object in radians in the form of \"x y z\".\n"
1889 "@param minDistance The minimum distance allowed to the orbit object or point.\n"
1890 "@param maxDistance The maximum distance allowed from the orbit object or point.\n"
1891 "@param initDistance The initial distance from the orbit object or point.\n"
1892 "@param ownClientObject [optional] Are we orbiting an object that is owned by us? Default is false.\n"
1893 "@param offset [optional] An offset added to the camera's position. Default is no offset.\n"
1894 "@param locked [optional] Indicates the camera does not receive input from the player. Default is false.\n"
1895 "@returns false if the given object could not be found.\n"
1896 "@see Camera::setOrbitMode()\n")
1900 Con::errorf( "Camera::setOrbitObject - Invalid object");
1904 object
->setOrbitMode(orbitObject
, Point3F(0.0f
, 0.0f
, 0.0f
), rotation
, offset
,
1905 minDistance
, maxDistance
, initDistance
, ownClientObject
, locked
);
1909 //-----------------------------------------------------------------------------
1911 DefineEngineMethod( Camera
, setOrbitPoint
, void, (TransformF orbitPoint
, F32 minDistance
, F32 maxDistance
, F32 initDistance
,
1912 Point3F offset
, bool locked
),
1913 (Point3F::Zero
, false),
1914 "Set the camera to orbit around a given point.\n\n"
1915 "@param orbitPoint The point to orbit around. In the form of \"x y z ax ay az aa\" such as returned by SceneObject::getTransform().\n"
1916 "@param minDistance The minimum distance allowed to the orbit object or point.\n"
1917 "@param maxDistance The maximum distance allowed from the orbit object or point.\n"
1918 "@param initDistance The initial distance from the orbit object or point.\n"
1919 "@param offset [optional] An offset added to the camera's position. Default is no offset.\n"
1920 "@param locked [optional] Indicates the camera does not receive input from the player. Default is false.\n"
1921 "@see Camera::setOrbitMode()\n")
1924 orbitPoint
.mOrientation
.setMatrix(&mat
);
1925 object
->setOrbitMode(NULL
, orbitPoint
.mPosition
, mat
.toEuler(), offset
,
1926 minDistance
, maxDistance
, initDistance
, false, locked
);
1929 //-----------------------------------------------------------------------------
1931 DefineEngineMethod( Camera
, setTrackObject
, bool, (GameBase
* trackObject
, Point3F offset
), (Point3F::Zero
),
1932 "Set the camera to track a given object.\n\n"
1933 "@param trackObject The object to track.\n"
1934 "@param offset [optional] An offset added to the camera's position. Default is no offset.\n"
1935 "@returns false if the given object could not be found.\n")
1939 Con::warnf("Cannot track non-existing object.");
1943 object
->setTrackObject(trackObject
, offset
);
1947 //-----------------------------------------------------------------------------
1949 DefineEngineMethod( Camera
, setEditOrbitMode
, void, (), ,
1950 "Set the editor camera to orbit around a point set with Camera::setEditOrbitPoint().\n\n"
1951 "@note This method is generally used only within the World Editor and other tools. To "
1952 "orbit about an object or point within a game, see Camera::setOrbitMode() and its helper methods.\n")
1954 object
->setEditOrbitMode();
1957 //-----------------------------------------------------------------------------
1959 DefineEngineMethod( Camera
, setFlyMode
, void, (), ,
1960 "Set the camera to fly freely.\n\n"
1961 "Allows the camera to have 6 degrees of freedom. Provides for instantaneous motion "
1962 "and rotation unless one of the Newton fields has been set to true. See Camera::newtonMode "
1963 "and Camera::newtonRotation.\n")
1965 object
->setFlyMode();
1968 //-----------------------------------------------------------------------------
1970 DefineEngineMethod( Camera
, setNewtonFlyMode
, void, (), ,
1971 "Set the camera to fly freely, but with ease-in and ease-out.\n\n"
1972 "This method allows for the same 6 degrees of freedom as Camera::setFlyMode() but "
1973 "activates the ease-in and ease-out on the camera's movement. To also activate "
1974 "Newton mode for the camera's rotation, set Camera::newtonRotation to true.")
1976 object
->setNewtonFlyMode();
1979 //-----------------------------------------------------------------------------
1981 DefineEngineMethod( Camera
, isRotationDamped
, bool, (), ,
1982 "Is this a Newton Fly mode camera with damped rotation?\n\n"
1983 "@returns true if the camera uses a damped rotation. i.e. Camera::newtonRotation is set to true.\n")
1985 return object
->isRotationDamped();
1988 //-----------------------------------------------------------------------------
1990 DefineEngineMethod( Camera
, getAngularVelocity
, VectorF
, (), ,
1991 "Get the angular velocity for a Newton mode camera.\n\n"
1992 "@returns The angular velocity in the form of \"x y z\".\n"
1993 "@note Only returns useful results when Camera::newtonRotation is set to true.")
1995 return object
->getAngularVelocity();
1998 //-----------------------------------------------------------------------------
2000 DefineEngineMethod( Camera
, setAngularVelocity
, void, (VectorF velocity
), ,
2001 "Set the angular velocity for a Newton mode camera.\n\n"
2002 "@param velocity The angular velocity infor form of \"x y z\".\n"
2003 "@note Only takes affect when Camera::newtonRotation is set to true.")
2005 object
->setAngularVelocity(velocity
);
2008 //-----------------------------------------------------------------------------
2010 DefineEngineMethod( Camera
, setAngularForce
, void, (F32 force
), ,
2011 "Set the angular force for a Newton mode camera.\n\n"
2012 "@param force The angular force applied when attempting to rotate the camera."
2013 "@note Only takes affect when Camera::newtonRotation is set to true.")
2015 object
->setAngularForce(force
);
2018 //-----------------------------------------------------------------------------
2020 DefineEngineMethod( Camera
, setAngularDrag
, void, (F32 drag
), ,
2021 "Set the angular drag for a Newton mode camera.\n\n"
2022 "@param drag The angular drag applied while the camera is rotating."
2023 "@note Only takes affect when Camera::newtonRotation is set to true.")
2025 object
->setAngularDrag(drag
);
2028 //-----------------------------------------------------------------------------
2030 DefineEngineMethod( Camera
, setMass
, void, (F32 mass
), ,
2031 "Set the mass for a Newton mode camera.\n\n"
2032 "@param mass The mass used during ease-in and ease-out calculations."
2033 "@note Only used when Camera is in Newton mode.")
2035 object
->setMass(mass
);
2038 //-----------------------------------------------------------------------------
2040 DefineEngineMethod( Camera
, getVelocity
, VectorF
, (), ,
2041 "Get the velocity for the camera.\n\n"
2042 "@returns The camera's velocity in the form of \"x y z\"."
2043 "@note Only useful when the Camera is in Newton mode.")
2045 return object
->getVelocity();
2048 //-----------------------------------------------------------------------------
2050 DefineEngineMethod( Camera
, setVelocity
, void, (VectorF velocity
), ,
2051 "Set the velocity for the camera.\n\n"
2052 "@param velocity The camera's velocity in the form of \"x y z\"."
2053 "@note Only affects the Camera when in Newton mode.")
2055 object
->setVelocity(velocity
);
2058 //-----------------------------------------------------------------------------
2060 DefineEngineMethod( Camera
, setDrag
, void, (F32 drag
), ,
2061 "Set the drag for a Newton mode camera.\n\n"
2062 "@param drag The drag applied to the camera while moving."
2063 "@note Only used when Camera is in Newton mode.")
2065 object
->setDrag(drag
);
2068 //-----------------------------------------------------------------------------
2070 DefineEngineMethod( Camera
, setFlyForce
, void, (F32 force
), ,
2071 "Set the force applied to a Newton mode camera while moving.\n\n"
2072 "@param force The force applied to the camera while attempting to move."
2073 "@note Only used when Camera is in Newton mode.")
2075 object
->setFlyForce(force
);
2078 //-----------------------------------------------------------------------------
2080 DefineEngineMethod( Camera
, setSpeedMultiplier
, void, (F32 multiplier
), ,
2081 "Set the Newton mode camera speed multiplier when trigger[0] is active.\n\n"
2082 "@param multiplier The speed multiplier to apply."
2083 "@note Only used when Camera is in Newton mode.")
2085 object
->setSpeedMultiplier(multiplier
);
2088 //-----------------------------------------------------------------------------
2090 DefineEngineMethod( Camera
, setBrakeMultiplier
, void, (F32 multiplier
), ,
2091 "Set the Newton mode camera brake multiplier when trigger[1] is active.\n\n"
2092 "@param multiplier The brake multiplier to apply."
2093 "@note Only used when Camera is in Newton mode.")
2095 object
->setBrakeMultiplier(multiplier
);
2098 //----------------------------------------------------------------------------
2100 DefineEngineMethod( Camera
, isEditOrbitMode
, bool, (), ,
2101 "Is the camera in edit orbit mode?\n\n"
2102 "@returns true if the camera is in edit orbit mode.")
2104 return object
->isEditOrbitMode();
2107 //----------------------------------------------------------------------------
2109 DefineEngineMethod( Camera
, setValidEditOrbitPoint
, void, (bool validPoint
), ,
2110 "Set if there is a valid editor camera orbit point.\n"
2111 "When validPoint is set to false the Camera operates as if it is "
2112 "in Fly mode rather than an Orbit mode.\n\n"
2113 "@param validPoint Indicates the validity of the orbit point."
2114 "@note Only used when Camera is in Edit Orbit Mode.")
2116 object
->setValidEditOrbitPoint(validPoint
);
2119 //----------------------------------------------------------------------------
2121 DefineEngineMethod( Camera
, setEditOrbitPoint
, void, (Point3F point
), ,
2122 "Set the editor camera's orbit point.\n\n"
2123 "@param point The point the camera will orbit in the form of \"x y z\".")
2125 object
->setEditOrbitPoint(point
);
2128 //----------------------------------------------------------------------------
2130 DefineEngineMethod( Camera
, autoFitRadius
, void, (F32 radius
), ,
2131 "Move the camera to fully view the given radius.\n\n"
2132 "@note For this operation to take affect a valid edit orbit point must first be specified. See Camera::setEditOrbitPoint().\n"
2133 "@param radius The radius to view.")
2135 object
->autoFitRadius(radius
);
2138 //----------------------------------------------------------------------------
2140 DefineEngineMethod( Camera
, lookAt
, void, (Point3F point
), ,
2141 "Point the camera at the specified position. Does not work in Orbit or Track modes.\n\n"
2142 "@param point The position to point the camera at.")
2144 object
->lookAt(point
);