afxCamera.cpp
Engine/source/afx/afxCamera.cpp
Public Defines
define
CameraRadius() 0.05f;
define
MaxPitch() 1.3962f
Public Functions
ConsoleDocClass(afxCamera , "@brief A 3rd person camera <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">afxMisc\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">AFX\n</a>" )
ConsoleDocClass(afxCameraData , "@brief A datablock that describes an <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">afxCamera.\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">afxMisc\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">AFX\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Datablocks\n</a>" )
DefineEngineMethod(afxCamera , getMode , const char * , () , "" )
DefineEngineMethod(afxCamera , getPosition , Point3F , () , "@brief Get the position of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">camera.\n\n</a>" "@returns The position of the camera." )
DefineEngineMethod(afxCamera , getThirdPersonAngle , F32 , () , "" )
DefineEngineMethod(afxCamera , getThirdPersonCOIOffset , Point3F , () , "" )
DefineEngineMethod(afxCamera , getThirdPersonDistance , F32 , () , "" )
DefineEngineMethod(afxCamera , getThirdPersonOffset , Point3F , () , "" )
DefineEngineMethod(afxCamera , setCameraSubject , bool , (SceneObject *subject) , "" )
DefineEngineMethod(afxCamera , setFlyMode , void , () , "@brief Set the camera <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be able <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> fly freely." )
DefineEngineMethod(afxCamera , setThirdPersonAngle , bool , (F32 distance) , "" )
DefineEngineMethod(afxCamera , setThirdPersonDistance , bool , (F32 distance) , "" )
DefineEngineMethod(afxCamera , setThirdPersonMode , void , () , "" )
DefineEngineMethod(afxCamera , setThirdPersonOffset , void , (Point3F offset, Point3F coi_offset) , (Point3F::Max) , "" )
DefineEngineMethod(afxCamera , setThirdPersonSnap , void , () , "" )
DefineEngineStringlyVariadicMethod(afxCamera , setOrbitMode , void , 7 , 8 , "(GameBase orbitObject, <a href="/coding/class/classtransformf/">TransformF</a> mat, float minDistance, float maxDistance, float curDistance, bool ownClientObject)" "Set the camera <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> orbit around some given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n\n</a>" "@param orbitObject <a href="/coding/file/gizmo_8h/#gizmo_8h_1a10fcd3bee2ea25191e31795e36bdeba1a5df911aaca43421a25e32c3002befbc4">Object</a> we want <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">orbit.\n</a>" "@param mat A set of fields: posX posY posZ aaX aaY aaZ <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">aaTheta\n</a>" "@param minDistance Minimum distance <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> keep from <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param maxDistance Maximum distance <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> keep from <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param curDistance Distance <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set initially from <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param ownClientObj Are we observing an object owned by us?" )
Detailed Description
Public Defines
CameraRadius() 0.05f;
MaxPitch() 1.3962f
Public Functions
ConsoleDocClass(afxCamera , "@brief A 3rd person camera <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">afxMisc\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">AFX\n</a>" )
ConsoleDocClass(afxCameraData , "@brief A datablock that describes an <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">afxCamera.\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">afxMisc\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">AFX\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Datablocks\n</a>" )
DefineEngineMethod(afxCamera , getMode , const char * , () , "" )
DefineEngineMethod(afxCamera , getPosition , Point3F , () , "@brief Get the position of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">camera.\n\n</a>" "@returns The position of the camera." )
DefineEngineMethod(afxCamera , getThirdPersonAngle , F32 , () , "" )
DefineEngineMethod(afxCamera , getThirdPersonCOIOffset , Point3F , () , "" )
DefineEngineMethod(afxCamera , getThirdPersonDistance , F32 , () , "" )
DefineEngineMethod(afxCamera , getThirdPersonOffset , Point3F , () , "" )
DefineEngineMethod(afxCamera , setCameraSubject , bool , (SceneObject *subject) , "" )
DefineEngineMethod(afxCamera , setFlyMode , void , () , "@brief Set the camera <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be able <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> fly freely." )
DefineEngineMethod(afxCamera , setThirdPersonAngle , bool , (F32 distance) , "" )
DefineEngineMethod(afxCamera , setThirdPersonDistance , bool , (F32 distance) , "" )
DefineEngineMethod(afxCamera , setThirdPersonMode , void , () , "" )
DefineEngineMethod(afxCamera , setThirdPersonOffset , void , (Point3F offset, Point3F coi_offset) , (Point3F::Max) , "" )
DefineEngineMethod(afxCamera , setThirdPersonSnap , void , () , "" )
DefineEngineStringlyVariadicMethod(afxCamera , setOrbitMode , void , 7 , 8 , "(GameBase orbitObject, <a href="/coding/class/classtransformf/">TransformF</a> mat, float minDistance, float maxDistance, float curDistance, bool ownClientObject)" "Set the camera <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> orbit around some given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n\n</a>" "@param orbitObject <a href="/coding/file/gizmo_8h/#gizmo_8h_1a10fcd3bee2ea25191e31795e36bdeba1a5df911aaca43421a25e32c3002befbc4">Object</a> we want <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">orbit.\n</a>" "@param mat A set of fields: posX posY posZ aaX aaY aaZ <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">aaTheta\n</a>" "@param minDistance Minimum distance <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> keep from <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param maxDistance Maximum distance <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> keep from <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param curDistance Distance <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set initially from <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">object.\n</a>" "@param ownClientObj Are we observing an object owned by us?" )
IMPLEMENT_CO_DATABLOCK_V1(afxCameraData )
IMPLEMENT_CO_NETOBJECT_V1(afxCamera )
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 25// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames 26// Copyright (C) 2015 Faust Logic, Inc. 27// 28// afxCamera implements a modified camera for demonstrating a third person camera style 29// which is more common to RPG games than the standard FPS style camera. For the most part, 30// it is a hybrid of the standard TGE camera and the third person mode of the Advanced Camera 31// resource, authored by Thomas "Man of Ice" Lund. This camera implements the bare minimum 32// required for demonstrating an RPG style camera and leaves tons of room for improvement. 33// It should be replaced with a better camera if possible. 34// 35// Advanced Camera Resource by Thomas "Man of Ice" Lund: 36// http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=5471 37// 38//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 39 40#include "afx/arcaneFX.h" 41 42#include "math/mathUtils.h" 43#include "math/mathIO.h" 44#include "T3D/gameBase/gameConnection.h" 45#include "T3D/camera.h" 46#include "T3D/player.h" 47#include "T3D/sfx/sfx3DWorld.h" 48 49#include "afx/afxCamera.h" 50 51#define MaxPitch 1.3962f 52#define CameraRadius 0.05f; 53 54//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 55// afxCameraData 56 57IMPLEMENT_CO_DATABLOCK_V1(afxCameraData); 58 59ConsoleDocClass( afxCameraData, 60 "@brief A datablock that describes an afxCamera.\n\n" 61 62 "@ingroup afxMisc\n" 63 "@ingroup AFX\n" 64 "@ingroup Datablocks\n" 65); 66 67U32 afxCameraData::sCameraCollisionMask = TerrainObjectType | InteriorLikeObjectType | TerrainLikeObjectType; 68 69void afxCameraData::initPersistFields() 70{ 71 Con::addVariable("pref::afxCamera::collisionMask", TypeS32, &sCameraCollisionMask); 72 73 Parent::initPersistFields(); 74} 75 76void afxCameraData::packData(BitStream* stream) 77{ 78 Parent::packData(stream); 79} 80 81void afxCameraData::unpackData(BitStream* stream) 82{ 83 Parent::unpackData(stream); 84} 85 86//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 87//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 88// afxCamera 89 90IMPLEMENT_CO_NETOBJECT_V1(afxCamera); 91 92ConsoleDocClass( afxCamera, 93 "@brief A 3rd person camera object.\n\n" 94 95 "@ingroup afxMisc\n" 96 "@ingroup AFX\n" 97); 98 99afxCamera::afxCamera() 100{ 101 mNetFlags.clear(Ghostable); 102 mTypeMask |= CameraObjectType; 103 mDelta.pos = Point3F(0,0,100); 104 mDelta.rot = Point3F(0,0,0); 105 mDelta.posVec = mDelta.rotVec = VectorF(0,0,0); 106 mObjToWorld.setColumn(3, mDelta.pos); 107 mRot = mDelta.rot; 108 109 mMinOrbitDist = 0; 110 mMaxOrbitDist = 0; 111 mCurOrbitDist = 0; 112 mOrbitObject = NULL; 113 mPosition.set(0.f, 0.f, 0.f); 114 mObservingClientObject = false; 115 mMode = FlyMode; 116 117 mCam_subject = NULL; 118 mCoi_offset.set(0, 0, 2); 119 mCam_offset.set(0, 0, 0); 120 mCam_distance = 0.0f; 121 mCam_angle = 0.0f; 122 mCam_dirty = false; 123 124 mFlymode_saved = false; 125 mThird_person_snap_s = 1; 126 mThird_person_snap_c = 1; 127 mFlymode_saved_pos.zero(); 128 129 mDamageState = Disabled; 130} 131 132afxCamera::~afxCamera() 133{ 134} 135 136//---------------------------------------------------------------------------- 137 138void afxCamera::cam_update(F32 dt, bool on_server) 139{ 140 if (mMode == ThirdPersonMode && mCam_subject) 141 cam_update_3pov(dt, on_server); 142} 143 144void afxCamera::set_cam_pos(const Point3F& pos,const Point3F& rot) 145{ 146 MatrixF xRot, zRot; 147 xRot.set(EulerF(rot.x, 0, 0)); 148 zRot.set(EulerF(0, 0, rot.z)); 149 MatrixF temp; 150 temp.mul(zRot, xRot); 151 temp.setColumn(3, pos); 152 Parent::setTransform(temp); 153 mRot = rot; 154} 155 156 157//---------------------------------------------------------------------------- 158 159 160 161//---------------------------------------------------------------------------- 162 163Point3F &afxCamera::getPosition() 164{ 165 static Point3F position; 166 mObjToWorld.getColumn(3, &position); 167 return position; 168} 169 170//---------------------------------------------------------------------------- 171 172 173//---------------------------------------------------------------------------- 174//---------------------------------------------------------------------------- 175// NEW Observer Code 176//---------------------------------------------------------------------------- 177//---------------------------------------------------------------------------- 178void afxCamera::setFlyMode() 179{ 180 mMode = FlyMode; 181 if (mFlymode_saved) 182 snapToPosition(mFlymode_saved_pos); 183 184 if (bool(mOrbitObject)) 185 { 186 clearProcessAfter(); 187 clearNotify(mOrbitObject); 188 } 189 mOrbitObject = NULL; 190} 191 192void afxCamera::setOrbitMode(GameBase *obj, Point3F &pos, AngAxisF &rot, F32 minDist, F32 maxDist, F32 curDist, bool ownClientObject) 193{ 194 mObservingClientObject = ownClientObject; 195 196 if(bool(mOrbitObject)) { 197 clearProcessAfter(); 198 clearNotify(mOrbitObject); 199 } 200 mOrbitObject = obj; 201 if(bool(mOrbitObject)) 202 { 203 processAfter(mOrbitObject); 204 deleteNotify(mOrbitObject); 205 mOrbitObject->getWorldBox().getCenter(&mPosition); 206 mMode = OrbitObjectMode; 207 } 208 else 209 { 210 mMode = OrbitPointMode; 211 mPosition = pos; 212 } 213 214 QuatF q(rot); 215 MatrixF tempMat(true); 216 q.setMatrix(&tempMat); 217 Point3F dir; 218 tempMat.getColumn(1, &dir); 219 220 set_cam_pos(mPosition, dir); 221 222 mMinOrbitDist = minDist; 223 mMaxOrbitDist = maxDist; 224 mCurOrbitDist = curDist; 225} 226 227 228void afxCamera::validateEyePoint(F32 pos, MatrixF *mat) 229{ 230 if (pos != 0) { 231 // Use the eye transform to orient the camera 232 Point3F dir; 233 mat->getColumn(1, &dir); 234 pos *= mMaxOrbitDist - mMinOrbitDist; 235 // Use the camera node's pos. 236 Point3F startPos; 237 Point3F endPos; 238 mObjToWorld.getColumn(3,&startPos); 239 240 // Make sure we don't extend the camera into anything solid 241 if(mOrbitObject) 242 mOrbitObject->disableCollision(); 243 disableCollision(); 244 RayInfo collision; 245 246 SceneContainer* pContainer = isServerObject() ? &gServerContainer : &gClientContainer; 247 if (!pContainer->castRay(startPos, startPos - dir * 2.5 * pos, afxCameraData::sCameraCollisionMask, &collision)) 248 endPos = startPos - dir * pos; 249 else 250 { 251 float dot = mDot(dir, collision.normal); 252 if(dot > 0.01) 253 { 254 float colDist = mDot(startPos - collision.point, dir) - (1 / dot) * CameraRadius; 255 if(colDist > pos) 256 colDist = pos; 257 if(colDist < 0) 258 colDist = 0; 259 endPos = startPos - dir * colDist; 260 } 261 else 262 endPos = startPos - dir * pos; 263 } 264 mat->setColumn(3,endPos); 265 enableCollision(); 266 if(mOrbitObject) 267 mOrbitObject->enableCollision(); 268 } 269} 270 271//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 272 273 274 275 276 277// Sets the position and calculates rotation 278void afxCamera::snapToPosition(const Point3F& tPos) 279{ 280 MatrixF transMat; 281 282 if (mCam_subject) 283 { 284 // get the subject's transform 285 MatrixF objToWorld = mCam_subject->getRenderTransform(); 286 287 // transform the center-of-interest to world-space 288 Point3F objPos; 289 objToWorld.mulP(mCoi_offset, &objPos); 290 291 // find normalized direction vector looking from camera to coi 292 VectorF dirVec = objPos - tPos; 293 dirVec.normalize(); 294 295 MathUtils::getAnglesFromVector(dirVec, mRot.z, mRot.x); 296 mRot.x = 0 - mRot.x; 297 298 transMat = MathUtils::createOrientFromDir(dirVec); 299 } 300 else 301 { 302 transMat.identity(); 303 } 304 305 transMat.setColumn(3, tPos); 306 Parent::setTransform(transMat); 307} 308 309void afxCamera::setCameraSubject(SceneObject* new_subject) 310{ 311 // cleanup any existing chase subject 312 if (mCam_subject) 313 { 314 if (dynamic_cast<GameBase*>(mCam_subject)) 315 clearProcessAfter(); 316 clearNotify(mCam_subject); 317 } 318 319 mCam_subject = new_subject; 320 321 // set associations with new chase subject 322 if (mCam_subject) 323 { 324 if (dynamic_cast<GameBase*>(mCam_subject)) 325 processAfter((GameBase*)mCam_subject); 326 deleteNotify(mCam_subject); 327 } 328 329 mMode = (mCam_subject) ? ThirdPersonMode : FlyMode; 330 setMaskBits(SubjectMask); 331} 332 333void afxCamera::setThirdPersonOffset(const Point3F& offset) 334{ 335 // new method 336 if (mCam_distance > 0.0f) 337 { 338 if (isClientObject()) 339 { 340 GameConnection* conn = GameConnection::getConnectionToServer(); 341 if (conn) 342 { 343 // this auto switches to/from first person 344 if (conn->isFirstPerson()) 345 { 346 if (mCam_distance >= 1.0f) 347 conn->setFirstPerson(false); 348 } 349 else 350 { 351 if (mCam_distance < 1.0f) 352 conn->setFirstPerson(true); 353 } 354 } 355 } 356 357 mCam_offset = offset; 358 mCam_dirty = true; 359 360 return; 361 } 362 363 // old backwards-compatible method 364 if (offset.y != mCam_offset.y && isClientObject()) 365 { 366 GameConnection* conn = GameConnection::getConnectionToServer(); 367 if (conn) 368 { 369 // this auto switches to/from first person 370 if (conn->isFirstPerson()) 371 { 372 if (offset.y <= -1.0f) 373 conn->setFirstPerson(false); 374 } 375 else 376 { 377 if (offset.y > -1.0f) 378 conn->setFirstPerson(true); 379 } 380 } 381 } 382 383 mCam_offset = offset; 384 mCam_dirty = true; 385} 386 387void afxCamera::setThirdPersonOffset(const Point3F& offset, const Point3F& coi_offset) 388{ 389 mCoi_offset = coi_offset; 390 setThirdPersonOffset(offset); 391} 392 393void afxCamera::setThirdPersonDistance(F32 distance) 394{ 395 mCam_distance = distance; 396 mCam_dirty = true; 397} 398 399F32 afxCamera::getThirdPersonDistance() 400{ 401 return mCam_distance; 402} 403 404void afxCamera::setThirdPersonAngle(F32 angle) 405{ 406 mCam_angle = angle; 407 mCam_dirty = true; 408} 409 410F32 afxCamera::getThirdPersonAngle() 411{ 412 return mCam_angle; 413} 414 415void afxCamera::setThirdPersonMode() 416{ 417 mMode = ThirdPersonMode; 418 mFlymode_saved_pos = getPosition(); 419 mFlymode_saved = true; 420 mCam_dirty = true; 421 mThird_person_snap_s++; 422} 423 424void afxCamera::setThirdPersonSnap() 425{ 426 if (mMode == ThirdPersonMode) 427 mThird_person_snap_s += 2; 428} 429 430void afxCamera::setThirdPersonSnapClient() 431{ 432 if (mMode == ThirdPersonMode) 433 mThird_person_snap_c++; 434} 435 436const char* afxCamera::getMode() 437{ 438 switch (mMode) 439 { 440 case ThirdPersonMode: 441 return "ThirdPerson"; 442 case FlyMode: 443 return "Fly"; 444 case OrbitObjectMode: 445 return "Orbit"; 446 } 447 448 return "Unknown"; 449} 450 451//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 452// Console Methods 453 454DefineEngineStringlyVariadicMethod(afxCamera, setOrbitMode, void, 7, 8, 455 "(GameBase orbitObject, TransformF mat, float minDistance, float maxDistance, float curDistance, bool ownClientObject)" 456 "Set the camera to orbit around some given object.\n\n" 457 "@param orbitObject Object we want to orbit.\n" 458 "@param mat A set of fields: posX posY posZ aaX aaY aaZ aaTheta\n" 459 "@param minDistance Minimum distance to keep from object.\n" 460 "@param maxDistance Maximum distance to keep from object.\n" 461 "@param curDistance Distance to set initially from object.\n" 462 "@param ownClientObj Are we observing an object owned by us?") 463{ 464 Point3F pos; 465 AngAxisF aa; 466 F32 minDis, maxDis, curDis; 467 468 GameBase *orbitObject = NULL; 469 if(Sim::findObject(argv[2],orbitObject) == false) 470 { 471 Con::warnf("Cannot orbit non-existing object."); 472 object->setFlyMode(); 473 return; 474 } 475 476 dSscanf(argv[3],"%f %f %f %f %f %f %f", 477 &pos.x,&pos.y,&pos.z,&aa.axis.x,&aa.axis.y,&aa.axis.z,&aa.angle); 478 minDis = dAtof(argv[4]); 479 maxDis = dAtof(argv[5]); 480 curDis = dAtof(argv[6]); 481 482 object->setOrbitMode(orbitObject, pos, aa, minDis, maxDis, curDis, (argc == 8) ? dAtob(argv[7]) : false); 483} 484 485DefineEngineMethod(afxCamera, setFlyMode, void, (),, 486 "@brief Set the camera to be able to fly freely.") 487{ 488 object->setFlyMode(); 489} 490 491DefineEngineMethod(afxCamera, getPosition, Point3F, (),, 492 "@brief Get the position of the camera.\n\n" 493 "@returns The position of the camera.") 494{ 495 return object->getPosition(); 496} 497 498DefineEngineMethod(afxCamera, setCameraSubject, bool, (SceneObject* subject),, "") 499{ 500 if (!subject) 501 { 502 Con::errorf("Camera subject not found."); 503 return false; 504 } 505 506 object->setCameraSubject(subject); 507 508 return true; 509} 510 511DefineEngineMethod(afxCamera, setThirdPersonDistance, bool, (F32 distance),, "") 512{ 513 object->setThirdPersonDistance(distance); 514 515 return true; 516} 517 518DefineEngineMethod(afxCamera, getThirdPersonDistance, F32, (),, "") 519{ 520 return object->getThirdPersonDistance(); 521} 522 523DefineEngineMethod(afxCamera, setThirdPersonAngle, bool, (F32 distance),, "") 524{ 525 object->setThirdPersonAngle(distance); 526 527 return true; 528} 529 530DefineEngineMethod(afxCamera, getThirdPersonAngle, F32, (),, "") 531{ 532 return object->getThirdPersonAngle(); 533} 534 535DefineEngineMethod(afxCamera, setThirdPersonOffset, void, (Point3F offset, Point3F coi_offset), (Point3F::Max), "") 536{ 537 if (coi_offset == Point3F::Max) 538 { 539 object->setThirdPersonOffset(offset); 540 } 541 else 542 { 543 object->setThirdPersonOffset(offset, coi_offset); 544 } 545} 546 547DefineEngineMethod(afxCamera, getThirdPersonOffset, Point3F, (),, "") 548{ 549 return object->getThirdPersonOffset(); 550} 551 552DefineEngineMethod(afxCamera, getThirdPersonCOIOffset, Point3F, (),, "") 553{ 554 return object->getThirdPersonCOIOffset(); 555} 556 557DefineEngineMethod(afxCamera, setThirdPersonMode, void, (),, "") 558{ 559 object->setThirdPersonMode(); 560} 561 562DefineEngineMethod(afxCamera, setThirdPersonSnap, void, (),, "") 563{ 564 object->setThirdPersonSnap(); 565} 566 567DefineEngineMethod(afxCamera, getMode, const char*, (),, "") 568{ 569 return object->getMode(); 570} 571 572//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 573 574// 3POV SECTION 575 576void afxCamera::cam_update_3pov(F32 dt, bool on_server) 577{ 578 Point3F goal_pos; 579 Point3F curr_pos = getRenderPosition(); 580 MatrixF xfm = mCam_subject->getRenderTransform(); 581 Point3F coi = mCam_subject->getRenderPosition() + mCoi_offset; 582 583 // for player subjects, pitch is adjusted 584 Player* player_subj = dynamic_cast<Player*>(mCam_subject); 585 if (player_subj) 586 { 587 if (mCam_distance > 0.0f) 588 { 589 // rotate xfm by amount of cam_angle 590 F32 look_yaw = player_subj->getHeadRotation().z + mDegToRad(-mCam_angle); 591 MatrixF look_yaw_mtx(EulerF(0,0,look_yaw)); 592 xfm.mul(look_yaw_mtx); 593 594 // rotate xfm by amount of head pitch in player 595 F32 head_pitch = player_subj->getHeadRotation().x; 596 MatrixF head_pitch_mtx(EulerF(head_pitch,0,0)); 597 xfm.mul(head_pitch_mtx); 598 599 VectorF behind_vec(0, -mCam_distance, 0); 600 xfm.mulP(behind_vec, &goal_pos); 601 goal_pos += mCam_offset; 602 } 603 else // old backwards-compatible method 604 { 605 // rotate xfm by amount of head pitch in player 606 F32 head_pitch = player_subj->getHeadRotation().x; 607 MatrixF head_pitch_mtx(EulerF(head_pitch,0,0)); 608 xfm.mul(head_pitch_mtx); 609 610 VectorF behind_vec(0, mCam_offset.y, 0); 611 xfm.mulP(behind_vec, &goal_pos); 612 goal_pos.z += mCam_offset.z; 613 } 614 } 615 // for non-player subjects, camera will follow, but pitch won't adjust. 616 else 617 { 618 xfm.mulP(mCam_offset, &goal_pos); 619 } 620 621 // avoid view occlusion 622 if (avoid_blocked_view(coi, goal_pos, goal_pos) && !on_server) 623 { 624 // snap to final position if path to goal is blocked 625 if (test_blocked_line(curr_pos, goal_pos)) 626 mThird_person_snap_c++; 627 } 628 629 // place camera into its final position 630 631 // speed factor values 632 // 15 -- tight 633 // 10 -- normal 634 // 5 -- loose 635 // 1 -- very loose 636 F32 speed_factor = 8.0f; 637 F32 time_inc = 1.0f/speed_factor; 638 639 // snap to final position 640 if (on_server || (mThird_person_snap_c > 0 || dt > time_inc)) 641 { 642 snapToPosition(goal_pos); 643 if (!on_server && mThird_person_snap_c > 0) 644 mThird_person_snap_c--; 645 return; 646 } 647 // interpolate to final position 648 else 649 { 650 // interpretation: always move a proportion of the distance 651 // from current location to destination that would cover the 652 // entire distance in time_inc duration at constant velocity. 653 F32 t = (dt >= time_inc) ? 1.0f : dt*speed_factor; 654 snapToPosition(goal_pos*t + curr_pos*(1.0-t)); 655 } 656} 657 658// See if the camera view is occluded by certain objects, 659// and move the camera closer to the subject in that case 660bool afxCamera::avoid_blocked_view(const Point3F& startpos, const Point3F& endpos, Point3F& newpos) 661{ 662 // cast ray to check for intersection with potential blocker objects 663 RayInfo hit_info; 664 if (!getContainer()->castRay(startpos, endpos, afxCameraData::sCameraCollisionMask, &hit_info)) 665 { 666 // no hit: just return original endpos 667 newpos = endpos; 668 return false; 669 } 670 671 // did hit: return the hit location nudged forward slightly 672 // to avoid seeing clipped portions of blocking object. 673 Point3F sight_line = startpos - hit_info.point; 674 sight_line.normalize(); 675 newpos = hit_info.point + sight_line*0.4f; 676 677 return true; 678} 679 680bool afxCamera::test_blocked_line(const Point3F& startpos, const Point3F& endpos) 681{ 682 RayInfo hit_info; 683 return getContainer()->castRay(startpos, endpos, afxCameraData::sCameraCollisionMask, &hit_info); 684} 685 686//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 687 688// STD OVERRIDES SECTION 689 690bool afxCamera::onAdd() 691{ 692 if(!Parent::onAdd()) 693 return false; 694 695 mObjBox.maxExtents = mObjScale; 696 mObjBox.minExtents = mObjScale; 697 mObjBox.minExtents.neg(); 698 699 resetWorldBox(); 700 701 addToScene(); 702 703 return true; 704} 705 706void afxCamera::onRemove() 707{ 708 removeFromScene(); 709 Parent::onRemove(); 710} 711 712void afxCamera::onDeleteNotify(SimObject *obj) 713{ 714 Parent::onDeleteNotify(obj); 715 716 if (obj == (SimObject*)mOrbitObject) 717 { 718 mOrbitObject = NULL; 719 if (mMode == OrbitObjectMode) 720 mMode = OrbitPointMode; 721 } 722 723 if (obj == mCam_subject) 724 { 725 mCam_subject = NULL; 726 } 727} 728 729void afxCamera::advanceTime(F32 dt) 730{ 731 Parent::advanceTime(dt); 732 733 if (gSFX3DWorld) 734 { 735 if (mMode == ThirdPersonMode && mCam_subject) 736 { 737 if (gSFX3DWorld->getListener() != mCam_subject) 738 gSFX3DWorld->setListener(mCam_subject); 739 } 740 else if (mMode == FlyMode) 741 { 742 if (gSFX3DWorld->getListener() != this) 743 gSFX3DWorld->setListener(this); 744 } 745 } 746 747 cam_update(dt, false); 748} 749 750void afxCamera::processTick(const Move* move) 751{ 752 Parent::processTick(move); 753 Point3F vec,pos; 754 755 // move will be NULL unless camera becomes the control object as in FlyMode 756 if (move) 757 { 758 // UPDATE ORIENTATION // 759 mDelta.rotVec = mRot; 760 mObjToWorld.getColumn(3, &mDelta.posVec); 761 mRot.x = mClampF(mRot.x + move->pitch, -MaxPitch, MaxPitch); 762 mRot.z += move->yaw; 763 764 // ORBIT MODE // 765 if (mMode == OrbitObjectMode || mMode == OrbitPointMode) 766 { 767 if(mMode == OrbitObjectMode && bool(mOrbitObject)) 768 { 769 // If this is a shapebase, use its render eye transform 770 // to avoid jittering. 771 GameBase *castObj = mOrbitObject; 772 ShapeBase* shape = dynamic_cast<ShapeBase*>(castObj); 773 if( shape != NULL ) { 774 MatrixF ret; 775 shape->getRenderEyeTransform( &ret ); 776 mPosition = ret.getPosition(); 777 } 778 else 779 { 780 // Hopefully this is a static object that doesn't move, 781 // because the worldbox doesn't get updated between ticks. 782 mOrbitObject->getWorldBox().getCenter(&mPosition); 783 } 784 } 785 set_cam_pos(mPosition, mRot); 786 validateEyePoint(1.0f, &mObjToWorld); 787 pos = mPosition; 788 } 789 790 // NON-ORBIT MODE (FLY MODE) // 791 else // if (mode == FlyMode) 792 { 793 // Update pos 794 bool faster = move->trigger[0] || move->trigger[1]; 795 F32 scale = Camera::getMovementSpeed() * (faster + 1); 796 797 mObjToWorld.getColumn(3,&pos); 798 mObjToWorld.getColumn(0,&vec); 799 pos += vec * move->x * TickSec * scale; 800 mObjToWorld.getColumn(1,&vec); 801 pos += vec * move->y * TickSec * scale; 802 mObjToWorld.getColumn(2,&vec); 803 pos += vec * move->z * TickSec * scale; 804 set_cam_pos(pos,mRot); 805 } 806 807 // If on the client, calc delta for backstepping 808 if (isClientObject()) 809 { 810 mDelta.pos = pos; 811 mDelta.rot = mRot; 812 mDelta.posVec = mDelta.posVec - mDelta.pos; 813 mDelta.rotVec = mDelta.rotVec - mDelta.rot; 814 } 815 else 816 { 817 setMaskBits(MoveMask); 818 } 819 } 820 else // if (!move) 821 { 822 if (isServerObject()) 823 cam_update(1.0/32.0, true); 824 } 825 826 if (getControllingClient() && mContainer) 827 updateContainer(); 828} 829 830void afxCamera::interpolateTick(F32 dt) 831{ 832 Parent::interpolateTick(dt); 833 834 if (mMode == ThirdPersonMode) 835 return; 836 837 Point3F rot = mDelta.rot + mDelta.rotVec * dt; 838 839 if(mMode == OrbitObjectMode || mMode == OrbitPointMode) 840 { 841 if(mMode == OrbitObjectMode && bool(mOrbitObject)) 842 { 843 // If this is a shapebase, use its render eye transform 844 // to avoid jittering. 845 GameBase *castObj = mOrbitObject; 846 ShapeBase* shape = dynamic_cast<ShapeBase*>(castObj); 847 if( shape != NULL ) 848 { 849 MatrixF ret; 850 shape->getRenderEyeTransform( &ret ); 851 mPosition = ret.getPosition(); 852 } 853 else 854 { 855 // Hopefully this is a static object that doesn't move, 856 // because the worldbox doesn't get updated between ticks. 857 mOrbitObject->getWorldBox().getCenter(&mPosition); 858 } 859 } 860 set_cam_pos(mPosition, rot); 861 validateEyePoint(1.0f, &mObjToWorld); 862 } 863 else 864 { 865 // NOTE - posVec is 0,0,0 unless cam is control-object and process tick is 866 // updating the delta 867 Point3F pos = mDelta.pos + mDelta.posVec * dt; 868 set_cam_pos(pos,rot); 869 } 870} 871 872void afxCamera::writePacketData(GameConnection *connection, BitStream *bstream) 873{ 874 // Update client regardless of status flags. 875 Parent::writePacketData(connection, bstream); 876 877 Point3F pos; mObjToWorld.getColumn(3, &pos); 878 bstream->setCompressionPoint(pos); // SET COMPRESSION POINT 879 mathWrite(*bstream, pos); // SND POS 880 bstream->write(mRot.x); // SND X ROT 881 bstream->write(mRot.z); // SND Z ROT 882 883 if (bstream->writeFlag(mCam_dirty)) 884 { 885 mathWrite(*bstream, mCam_offset); // SND CAM_OFFSET 886 mathWrite(*bstream, mCoi_offset); // SND COI_OFFSET 887 bstream->write(mCam_distance); 888 bstream->write(mCam_angle); 889 mCam_dirty = false; 890 } 891 892 U32 writeMode = mMode; 893 Point3F writePos = mPosition; 894 S32 gIndex = -1; 895 if (mMode == OrbitObjectMode) 896 { 897 gIndex = bool(mOrbitObject) ? connection->getGhostIndex(mOrbitObject): -1; 898 if(gIndex == -1) 899 { 900 writeMode = OrbitPointMode; 901 mOrbitObject->getWorldBox().getCenter(&writePos); 902 } 903 } 904 905 bstream->writeRangedU32(writeMode, CameraFirstMode, CameraLastMode); // SND MODE 906 if (writeMode == ThirdPersonMode) 907 { 908 bstream->write(mThird_person_snap_s > 0); // SND SNAP 909 if (mThird_person_snap_s > 0) 910 mThird_person_snap_s--; 911 } 912 913 if (writeMode == OrbitObjectMode || writeMode == OrbitPointMode) 914 { 915 bstream->write(mMinOrbitDist); // SND ORBIT MIN DIST 916 bstream->write(mMaxOrbitDist); // SND ORBIT MAX DIST 917 bstream->write(mCurOrbitDist); // SND ORBIT CURR DIST 918 if(writeMode == OrbitObjectMode) 919 { 920 bstream->writeFlag(mObservingClientObject); // SND OBSERVING CLIENT OBJ 921 bstream->writeInt(gIndex, NetConnection::GhostIdBitSize); // SND ORBIT OBJ 922 } 923 if (writeMode == OrbitPointMode) 924 bstream->writeCompressedPoint(writePos); // WRITE COMPRESSION POINT 925 } 926} 927 928void afxCamera::readPacketData(GameConnection *connection, BitStream *bstream) 929{ 930 Parent::readPacketData(connection, bstream); 931 932 Point3F pos,rot; 933 mathRead(*bstream, &pos); // RCV POS 934 bstream->setCompressionPoint(pos); 935 bstream->read(&rot.x); // RCV X ROT 936 bstream->read(&rot.z); // RCV Z ROT 937 938 if (bstream->readFlag()) 939 { 940 Point3F new_cam_offset, new_coi_offset; 941 mathRead(*bstream, &new_cam_offset); // RCV CAM_OFFSET 942 mathRead(*bstream, &new_coi_offset); // RCV COI_OFFSET 943 bstream->read(&mCam_distance); 944 bstream->read(&mCam_angle); 945 setThirdPersonOffset(new_cam_offset, new_coi_offset); 946 } 947 948 GameBase* obj = 0; 949 mMode = bstream->readRangedU32(CameraFirstMode, // RCV MODE 950 CameraLastMode); 951 if (mMode == ThirdPersonMode) 952 { 953 bool snap; bstream->read(&snap); 954 if (snap) 955 mThird_person_snap_c++; 956 } 957 958 mObservingClientObject = false; 959 if (mMode == OrbitObjectMode || mMode == OrbitPointMode) { 960 bstream->read(&mMinOrbitDist); 961 bstream->read(&mMaxOrbitDist); 962 bstream->read(&mCurOrbitDist); 963 964 if(mMode == OrbitObjectMode) 965 { 966 mObservingClientObject = bstream->readFlag(); 967 S32 gIndex = bstream->readInt(NetConnection::GhostIdBitSize); 968 obj = static_cast<GameBase*>(connection->resolveGhost(gIndex)); 969 } 970 if (mMode == OrbitPointMode) 971 bstream->readCompressedPoint(&mPosition); 972 } 973 if (obj != (GameBase*)mOrbitObject) { 974 if (mOrbitObject) { 975 clearProcessAfter(); 976 clearNotify(mOrbitObject); 977 } 978 mOrbitObject = obj; 979 if (mOrbitObject) { 980 processAfter(mOrbitObject); 981 deleteNotify(mOrbitObject); 982 } 983 } 984 985 if (mMode == ThirdPersonMode) 986 return; 987 988 set_cam_pos(pos,rot); 989 mDelta.pos = pos; 990 mDelta.rot = rot; 991 mDelta.rotVec.set(0,0,0); 992 mDelta.posVec.set(0,0,0); 993} 994 995U32 afxCamera::packUpdate(NetConnection* conn, U32 mask, BitStream *bstream) 996{ 997 U32 retMask = Parent::packUpdate(conn,mask,bstream); 998 999 // The rest of the data is part of the control object packet update. 1000 // If we're controlled by this client, we don't need to send it. 1001 //if(bstream->writeFlag(getControllingClient() == conn && !(mask & InitialUpdateMask))) 1002 // return 0; 1003 1004 if (bstream->writeFlag(mask & MoveMask)) { 1005 Point3F pos; 1006 mObjToWorld.getColumn(3,&pos); 1007 bstream->write(pos.x); 1008 bstream->write(pos.y); 1009 bstream->write(pos.z); 1010 bstream->write(mRot.x); 1011 bstream->write(mRot.z); 1012 } 1013 1014 if (bstream->writeFlag(mask & SubjectMask)) 1015 { 1016 S32 ghost_id = (mCam_subject) ? conn->getGhostIndex(mCam_subject) : -1; 1017 if (bstream->writeFlag(ghost_id != -1)) 1018 bstream->writeRangedU32(U32(ghost_id), 0, NetConnection::MaxGhostCount); 1019 else if (mCam_subject) 1020 retMask |= SubjectMask; 1021 } 1022 1023 return retMask; 1024} 1025 1026void afxCamera::unpackUpdate(NetConnection *conn, BitStream *bstream) 1027{ 1028 Parent::unpackUpdate(conn,bstream); 1029 1030 // controlled by the client? 1031 //if(bstream->readFlag()) 1032 // return; 1033 1034 if (bstream->readFlag()) { 1035 Point3F pos,rot; 1036 bstream->read(&pos.x); 1037 bstream->read(&pos.y); 1038 bstream->read(&pos.z); 1039 bstream->read(&rot.x); 1040 bstream->read(&rot.z); 1041 set_cam_pos(pos,rot); 1042 1043 // New delta for client side interpolation 1044 mDelta.pos = pos; 1045 mDelta.rot = rot; 1046 mDelta.posVec = mDelta.rotVec = VectorF(0,0,0); 1047 } 1048 1049 if (bstream->readFlag()) 1050 { 1051 if (bstream->readFlag()) 1052 { 1053 S32 ghost_id = bstream->readRangedU32(0, NetConnection::MaxGhostCount); 1054 mCam_subject = dynamic_cast<GameBase*>(conn->resolveGhost(ghost_id)); 1055 } 1056 else 1057 mCam_subject = NULL; 1058 } 1059} 1060 1061// Override to ensure both are kept in scope 1062void afxCamera::onCameraScopeQuery(NetConnection* conn, CameraScopeQuery* query) 1063{ 1064 if (mCam_subject) 1065 conn->objectInScope(mCam_subject); 1066 Parent::onCameraScopeQuery(conn, query); 1067} 1068 1069//---------------------------------------------------------------------------- 1070// check if the object needs to be observed through its own camera... 1071void afxCamera::getCameraTransform(F32* pos, MatrixF* mat) 1072{ 1073 // The camera doesn't support a third person mode, 1074 // so we want to override the default ShapeBase behavior. 1075 ShapeBase * obj = dynamic_cast<ShapeBase*>(static_cast<SimObject*>(mOrbitObject)); 1076 if (obj && static_cast<ShapeBaseData*>(obj->getDataBlock())->observeThroughObject) 1077 obj->getCameraTransform(pos, mat); 1078 else 1079 getEyeTransform(mat); 1080} 1081 1082void afxCamera::setTransform(const MatrixF& mat) 1083{ 1084 // This method should never be called on the client. 1085 1086 // This currently converts all rotation in the mat into 1087 // rotations around the z and x axis. 1088 Point3F pos,vec; 1089 mat.getColumn(1,&vec); 1090 mat.getColumn(3,&pos); 1091 Point3F rot(-mAtan2(vec.z, mSqrt(vec.x*vec.x + vec.y*vec.y)),0,-mAtan2(-vec.x,vec.y)); 1092 set_cam_pos(pos,rot); 1093} 1094 1095void afxCamera::onEditorEnable() 1096{ 1097 mNetFlags.set(Ghostable); 1098} 1099 1100void afxCamera::onEditorDisable() 1101{ 1102 mNetFlags.clear(Ghostable); 1103} 1104 1105F32 afxCamera::getCameraFov() 1106{ 1107 ShapeBase * obj = dynamic_cast<ShapeBase*>(static_cast<SimObject*>(mOrbitObject)); 1108 if(obj && static_cast<ShapeBaseData*>(obj->getDataBlock())->observeThroughObject) 1109 return(obj->getCameraFov()); 1110 else 1111 return(Parent::getCameraFov()); 1112} 1113 1114F32 afxCamera::getDefaultCameraFov() 1115{ 1116 ShapeBase * obj = dynamic_cast<ShapeBase*>(static_cast<SimObject*>(mOrbitObject)); 1117 if(obj && static_cast<ShapeBaseData*>(obj->getDataBlock())->observeThroughObject) 1118 return(obj->getDefaultCameraFov()); 1119 else 1120 return(Parent::getDefaultCameraFov()); 1121} 1122 1123bool afxCamera::isValidCameraFov(F32 fov) 1124{ 1125 ShapeBase * obj = dynamic_cast<ShapeBase*>(static_cast<SimObject*>(mOrbitObject)); 1126 if(obj && static_cast<ShapeBaseData*>(obj->getDataBlock())->observeThroughObject) 1127 return(obj->isValidCameraFov(fov)); 1128 else 1129 return(Parent::isValidCameraFov(fov)); 1130} 1131 1132void afxCamera::setCameraFov(F32 fov) 1133{ 1134 ShapeBase * obj = dynamic_cast<ShapeBase*>(static_cast<SimObject*>(mOrbitObject)); 1135 if(obj && static_cast<ShapeBaseData*>(obj->getDataBlock())->observeThroughObject) 1136 obj->setCameraFov(fov); 1137 else 1138 Parent::setCameraFov(fov); 1139} 1140 1141F32 afxCamera::getDamageFlash() const 1142{ 1143 if (mMode == OrbitObjectMode && isServerObject() && bool(mOrbitObject)) 1144 { 1145 const GameBase *castObj = mOrbitObject; 1146 const ShapeBase* psb = dynamic_cast<const ShapeBase*>(castObj); 1147 if (psb) 1148 return psb->getDamageFlash(); 1149 } 1150 1151 return mDamageFlash; 1152} 1153 1154F32 afxCamera::getWhiteOut() const 1155{ 1156 if (mMode == OrbitObjectMode && isServerObject() && bool(mOrbitObject)) 1157 { 1158 const GameBase *castObj = mOrbitObject; 1159 const ShapeBase* psb = dynamic_cast<const ShapeBase*>(castObj); 1160 if (psb) 1161 return psb->getWhiteOut(); 1162 } 1163 1164 return mWhiteOut; 1165} 1166 1167//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 1168 1169void afxCamera::setControllingClient( GameConnection* client ) 1170{ 1171 GameBase::setControllingClient( client ); 1172} 1173 1174//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~// 1175