camera.cpp 73 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  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:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  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
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "platform/platform.h"
  23. #include "T3D/camera.h"
  24. #include "math/mMath.h"
  25. #include "core/stream/bitStream.h"
  26. #include "T3D/fx/cameraFXMgr.h"
  27. #include "T3D/gameBase/gameConnection.h"
  28. #include "math/mathIO.h"
  29. #include "gui/worldEditor/editor.h"
  30. #include "console/engineAPI.h"
  31. #include "console/consoleTypes.h"
  32. #include "console/engineAPI.h"
  33. #include "math/mathUtils.h"
  34. #include "math/mTransform.h"
  35. #ifdef TORQUE_EXTENDED_MOVE
  36. #include "T3D/gameBase/extended/extendedMove.h"
  37. #endif
  38. S32 Camera::smExtendedMovePosRotIndex = 0; // The ExtendedMove position/rotation index used for camera movements
  39. #define MaxPitch 1.5706f
  40. #define CameraRadius 0.05f;
  41. ImplementEnumType( CameraMotionMode,
  42. "Movement behavior type for Camera.\n\n"
  43. "@ingroup BaseCamera" )
  44. { Camera::StationaryMode, "Stationary", "Camera does not rotate or move." },
  45. { Camera::FreeRotateMode, "FreeRotate", "Camera may rotate but does not move." },
  46. { Camera::FlyMode, "Fly", "Camera may rotate and move freely." },
  47. { 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." },
  48. { Camera::OrbitPointMode, "OrbitPoint", "Camera orbits about a given point. See Camera::setOrbitMode() to set the orbit point and other parameters." },
  49. { 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." },
  50. { Camera::OverheadMode, "Overhead", "Camera moves in the XY plane." },
  51. { 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." }
  52. EndImplementEnumType;
  53. //=============================================================================
  54. // CameraData.
  55. //=============================================================================
  56. // MARK: ---- CameraData ----
  57. IMPLEMENT_CO_DATABLOCK_V1( CameraData );
  58. ConsoleDocClass( CameraData,
  59. "@brief A datablock that describes a camera.\n\n"
  60. "@tsexample\n"
  61. "datablock CameraData(Observer)\n"
  62. "{\n"
  63. " mode = \"Observer\";\n"
  64. "};\n"
  65. "@endtsexample\n"
  66. "@see Camera\n\n"
  67. "@ref Datablock_Networking\n"
  68. "@ingroup BaseCamera\n"
  69. "@ingroup Datablocks\n"
  70. );
  71. //-----------------------------------------------------------------------------
  72. void CameraData::initPersistFields()
  73. {
  74. docsURL;
  75. Parent::initPersistFields();
  76. }
  77. //-----------------------------------------------------------------------------
  78. void CameraData::packData(BitStream* stream)
  79. {
  80. Parent::packData(stream);
  81. }
  82. //-----------------------------------------------------------------------------
  83. void CameraData::unpackData(BitStream* stream)
  84. {
  85. Parent::unpackData(stream);
  86. }
  87. //=============================================================================
  88. // Camera.
  89. //=============================================================================
  90. // MARK: ---- Camera ----
  91. IMPLEMENT_CO_NETOBJECT_V1( Camera );
  92. ConsoleDocClass( Camera,
  93. "@brief Represents a position, direction and field of view to render a scene from.\n\n"
  94. "A camera is typically manipulated by a GameConnection. When set as the connection's "
  95. "control object, the camera handles all movement actions ($mvForwardAction, $mvPitch, etc.) "
  96. "just like a Player.\n"
  97. "@tsexample\n"
  98. "// Set an already created camera as the GameConnection's control object\n"
  99. "%connection.setControlObject(%camera);\n"
  100. "@endtsexample\n\n"
  101. "<h3>Methods of Operation</h3>\n\n"
  102. "The camera has two general methods of operation. The first is the standard mode where "
  103. "the camera starts and stops its motion and rotation instantly. This is the default operation "
  104. "of the camera and is used by most games. It may be specifically set with Camera::setFlyMode() "
  105. "for 6 DoF motion. It is also typically the method used with Camera::setOrbitMode() or one of "
  106. "its helper methods to orbit about a specific object (such as the Player's dead body) or a "
  107. "specific point.\n\n"
  108. "The second method goes under the name of Newton as it follows Newton's 2nd law of "
  109. "motion: F=ma. This provides the camera with an ease-in and ease-out feel for both movement "
  110. "and rotation. To activate this method for movement, either use Camera::setNewtonFlyMode() or set "
  111. "the Camera::newtonMode field to true. To activate this method for rotation, set the Camera::newtonRotation "
  112. "to true. This method of operation is not typically used in games, and was developed to allow "
  113. "for a smooth fly through of a game level while recording a demo video. But with the right force "
  114. "and drag settings, it may give a more organic feel to the camera to games that use an overhead view, "
  115. "such as a RTS.\n\n"
  116. "There is a third, minor method of operation but it is not generally used for games. This is when the "
  117. "camera is used with Torque's World Editor in Edit Orbit Mode. When set, this allows the camera "
  118. "to rotate about a specific point in the world, and move towards and away from this point. See "
  119. "Camera::setEditOrbitMode() and Camera::setEditOrbitPoint(). While in this mode, Camera::autoFitRadius() "
  120. "may also be used.\n\n"
  121. "@tsexample\n"
  122. "// Create a camera in the level and set its position to a given spawn point.\n"
  123. "// Note: The camera starts in the standard fly mode.\n"
  124. "%cam = new Camera() {\n"
  125. " datablock = \"Observer\";\n"
  126. "};\n"
  127. "MissionCleanup.add( %cam );\n"
  128. "%cam.setTransform( %spawnPoint.getTransform() );\n"
  129. "@endtsexample\n\n"
  130. "@tsexample\n"
  131. "// Create a camera at the given spawn point for the specified\n"
  132. "// GameConnection i.e. the client. Uses the standard\n"
  133. "// Sim::spawnObject() function to create the camera using the\n"
  134. "// defined default settings.\n"
  135. "// Note: The camera starts in the standard fly mode.\n"
  136. "function GameConnection::spawnCamera(%this, %spawnPoint)\n"
  137. "{\n"
  138. " // Set the control object to the default camera\n"
  139. " if (!isObject(%this.camera))\n"
  140. " {\n"
  141. " if (isDefined(\"$Game::DefaultCameraClass\"))\n"
  142. " %this.camera = spawnObject($Game::DefaultCameraClass, $Game::DefaultCameraDataBlock);\n"
  143. " }\n"
  144. "\n"
  145. " // If we have a camera then set up some properties\n"
  146. " if (isObject(%this.camera))\n"
  147. " {\n"
  148. " // Make sure we're cleaned up when the mission ends\n"
  149. " MissionCleanup.add( %this.camera );\n"
  150. "\n"
  151. " // Make sure the camera is always in scope for the connection\n"
  152. " %this.camera.scopeToClient(%this);\n"
  153. "\n"
  154. " // Send all user input from the connection to the camera\n"
  155. " %this.setControlObject(%this.camera);\n"
  156. "\n"
  157. " if (isDefined(\"%spawnPoint\"))\n"
  158. " {\n"
  159. " // Attempt to treat %spawnPoint as an object, such as a\n"
  160. " // SpawnSphere class.\n"
  161. " if (getWordCount(%spawnPoint) == 1 && isObject(%spawnPoint))\n"
  162. " {\n"
  163. " %this.camera.setTransform(%spawnPoint.getTransform());\n"
  164. " }\n"
  165. " else\n"
  166. " {\n"
  167. " // Treat %spawnPoint as an AngleAxis transform\n"
  168. " %this.camera.setTransform(%spawnPoint);\n"
  169. " }\n"
  170. " }\n"
  171. " }\n"
  172. "}\n"
  173. "@endtsexample\n\n"
  174. "<h3>Motion Modes</h3>\n\n"
  175. "Beyond the different operation methods, the Camera may be set to one of a number "
  176. "of motion modes. These motion modes determine how the camera will respond to input "
  177. "and may be used to constrain how the Camera moves. The CameraMotionMode enumeration "
  178. "defines the possible set of modes and the Camera's current may be obtained by using "
  179. "getMode().\n\n"
  180. "Some of the motion modes may be set using specific script methods. These often provide "
  181. "additional parameters to set up the mode in one go. Otherwise, it is always possible to "
  182. "set a Camera's motion mode using the controlMode property. Just pass in the name of the "
  183. "mode enum. The following table lists the motion modes, how to set them up, and what they offer:\n\n"
  184. "<table border='1' cellpadding='1'>"
  185. "<tr><th>Mode</th><th>Set From Script</th><th>Input Move</th><th>Input Rotate</th><th>Can Use Newton Mode?</th></tr>"
  186. "<tr><td>Stationary</td><td>controlMode property</td><td>No</td><td>No</td><td>No</td></tr>"
  187. "<tr><td>FreeRotate</td><td>controlMode property</td><td>No</td><td>Yes</td><td>Rotate Only</td></tr>"
  188. "<tr><td>Fly</td><td>setFlyMode()</td><td>Yes</td><td>Yes</td><td>Yes</td></tr>"
  189. "<tr><td>OrbitObject</td><td>setOrbitMode()</td><td>Orbits object</td><td>Points to object</td><td>Move only</td></tr>"
  190. "<tr><td>OrbitPoint</td><td>setOrbitPoint()</td><td>Orbits point</td><td>Points to location</td><td>Move only</td></tr>"
  191. "<tr><td>TrackObject</td><td>setTrackObject()</td><td>No</td><td>Points to object</td><td>Yes</td></tr>"
  192. "<tr><td>Overhead</td><td>controlMode property</td><td>Yes</td><td>No</td><td>Yes</td></tr>"
  193. "<tr><td>EditOrbit (object selected)</td><td>setEditOrbitMode()</td><td>Orbits object</td><td>Points to object</td><td>Move only</td></tr>"
  194. "<tr><td>EditOrbit (no object)</td><td>setEditOrbitMode()</td><td>Yes</td><td>Yes</td><td>Yes</td></tr>"
  195. "</table>\n\n"
  196. "<h3>%Trigger Input</h3>\n\n"
  197. "Passing a move trigger ($mvTriggerCount0, $mvTriggerCount1, etc.) on to a Camera performs "
  198. "different actions depending on which mode the camera is in. While in Fly, Overhead or "
  199. "EditOrbit mode, either trigger0 or trigger1 will cause a camera to move twice its normal "
  200. "movement speed. You can see this in action within the World Editor, where holding down the "
  201. "left mouse button while in mouse look mode (right mouse button is also down) causes the Camera "
  202. "to move faster.\n\n"
  203. "Passing along trigger2 will put the camera into strafe mode. While in this mode a Fly, "
  204. "FreeRotate or Overhead Camera will not rotate from the move input. Instead the yaw motion "
  205. "will be applied to the Camera's x motion, and the pitch motion will be applied to the Camera's "
  206. "z motion. You can see this in action within the World Editor where holding down the middle mouse "
  207. "button allows the user to move the camera up, down and side-to-side.\n\n"
  208. "While the camera is operating in Newton Mode, trigger0 and trigger1 behave slightly differently. "
  209. "Here trigger0 activates a multiplier to the applied acceleration force as defined by speedMultiplier. "
  210. "This has the affect of making the camera move up to speed faster. trigger1 has the opposite affect "
  211. "by acting as a brake. When trigger1 is active a multiplier is added to the Camera's drag as "
  212. "defined by brakeMultiplier.\n\n"
  213. "@see CameraData\n"
  214. "@see CameraMotionMode\n"
  215. "@see Camera::movementSpeed\n\n"
  216. "@ingroup BaseCamera\n"
  217. );
  218. F32 Camera::smMovementSpeed = 40.0f;
  219. //----------------------------------------------------------------------------
  220. Camera::Camera()
  221. {
  222. mNetFlags.clear(Ghostable);
  223. mTypeMask |= CameraObjectType;
  224. mDataBlock = 0;
  225. mDelta.pos = Point3F(0.0f, 0.0f, 100.0f);
  226. mDelta.rot = Point3F(0.0f, 0.0f, 0.0f);
  227. mDelta.posVec = mDelta.rotVec = VectorF(0.0f, 0.0f, 0.0f);
  228. mObjToWorld.setColumn(3, mDelta.pos);
  229. mRot = mDelta.rot;
  230. mOffset.set(0.0f, 0.0f, 0.0f);
  231. mMinOrbitDist = 0.0f;
  232. mMaxOrbitDist = 0.0f;
  233. mCurOrbitDist = 0.0f;
  234. mOrbitObject = NULL;
  235. mPosition.set(0.0f, 0.0f, 0.0f);
  236. mObservingClientObject = false;
  237. mMode = FlyMode;
  238. mLastAbsoluteYaw = 0.0f;
  239. mLastAbsolutePitch = 0.0f;
  240. mLastAbsoluteRoll = 0.0f;
  241. // For NewtonFlyMode
  242. mNewtonRotation = false;
  243. mAngularVelocity.set(0.0f, 0.0f, 0.0f);
  244. mAngularForce = 100.0f;
  245. mAngularDrag = 2.0f;
  246. mVelocity.set(0.0f, 0.0f, 0.0f);
  247. mNewtonMode = false;
  248. mMass = 10.0f;
  249. mDrag = 2.0;
  250. mFlyForce = 500.0f;
  251. mSpeedMultiplier = 2.0f;
  252. mBrakeMultiplier = 2.0f;
  253. // For EditOrbitMode
  254. mValidEditOrbitPoint = false;
  255. mEditOrbitPoint.set(0.0f, 0.0f, 0.0f);
  256. mCurrentEditOrbitDist = 2.0;
  257. mLocked = false;
  258. }
  259. //----------------------------------------------------------------------------
  260. Camera::~Camera()
  261. {
  262. }
  263. //----------------------------------------------------------------------------
  264. bool Camera::onAdd()
  265. {
  266. if(!Parent::onAdd() || !mDataBlock)
  267. return false;
  268. mObjBox.maxExtents = mObjScale;
  269. mObjBox.minExtents = mObjScale;
  270. mObjBox.minExtents.neg();
  271. resetWorldBox();
  272. addToScene();
  273. scriptOnAdd();
  274. return true;
  275. }
  276. //----------------------------------------------------------------------------
  277. void Camera::onRemove()
  278. {
  279. scriptOnRemove();
  280. removeFromScene();
  281. Parent::onRemove();
  282. }
  283. //----------------------------------------------------------------------------
  284. bool Camera::onNewDataBlock( GameBaseData *dptr, bool reload )
  285. {
  286. mDataBlock = dynamic_cast<CameraData*>(dptr);
  287. if ( !mDataBlock || !Parent::onNewDataBlock( dptr, reload ) )
  288. return false;
  289. scriptOnNewDataBlock();
  290. return true;
  291. }
  292. //----------------------------------------------------------------------------
  293. void Camera::onEditorEnable()
  294. {
  295. mNetFlags.set(Ghostable);
  296. }
  297. //----------------------------------------------------------------------------
  298. void Camera::onEditorDisable()
  299. {
  300. mNetFlags.clear(Ghostable);
  301. }
  302. //----------------------------------------------------------------------------
  303. // check if the object needs to be observed through its own camera...
  304. void Camera::getCameraTransform(F32* pos, MatrixF* mat)
  305. {
  306. // The camera doesn't support a third person mode,
  307. // so we want to override the default ShapeBase behavior.
  308. ShapeBase * obj = dynamic_cast<ShapeBase*>(static_cast<SimObject*>(mOrbitObject));
  309. if(obj && static_cast<ShapeBaseData*>(obj->getDataBlock())->observeThroughObject)
  310. obj->getCameraTransform(pos, mat);
  311. else
  312. getRenderEyeTransform(mat);
  313. // Apply Camera FX.
  314. mat->mul( gCamFXMgr.getTrans() );
  315. }
  316. void Camera::getEyeCameraTransform(IDisplayDevice *displayDevice, U32 eyeId, MatrixF *outMat)
  317. {
  318. // The camera doesn't support a third person mode,
  319. // so we want to override the default ShapeBase behavior.
  320. ShapeBase * obj = dynamic_cast<ShapeBase*>(static_cast<SimObject*>(mOrbitObject));
  321. if(obj && static_cast<ShapeBaseData*>(obj->getDataBlock())->observeThroughObject)
  322. obj->getEyeCameraTransform(displayDevice, eyeId, outMat);
  323. else
  324. {
  325. Parent::getEyeCameraTransform(displayDevice, eyeId, outMat);
  326. }
  327. }
  328. //----------------------------------------------------------------------------
  329. F32 Camera::getCameraFov()
  330. {
  331. ShapeBase * obj = dynamic_cast<ShapeBase*>(static_cast<SimObject*>(mOrbitObject));
  332. if(obj && static_cast<ShapeBaseData*>(obj->getDataBlock())->observeThroughObject)
  333. return(obj->getCameraFov());
  334. else
  335. return(Parent::getCameraFov());
  336. }
  337. //----------------------------------------------------------------------------
  338. F32 Camera::getDefaultCameraFov()
  339. {
  340. ShapeBase * obj = dynamic_cast<ShapeBase*>(static_cast<SimObject*>(mOrbitObject));
  341. if(obj && static_cast<ShapeBaseData*>(obj->getDataBlock())->observeThroughObject)
  342. return(obj->getDefaultCameraFov());
  343. else
  344. return(Parent::getDefaultCameraFov());
  345. }
  346. //----------------------------------------------------------------------------
  347. bool Camera::isValidCameraFov(F32 fov)
  348. {
  349. ShapeBase * obj = dynamic_cast<ShapeBase*>(static_cast<SimObject*>(mOrbitObject));
  350. if(obj && static_cast<ShapeBaseData*>(obj->getDataBlock())->observeThroughObject)
  351. return(obj->isValidCameraFov(fov));
  352. else
  353. return(Parent::isValidCameraFov(fov));
  354. }
  355. //----------------------------------------------------------------------------
  356. void Camera::setCameraFov(F32 fov)
  357. {
  358. ShapeBase * obj = dynamic_cast<ShapeBase*>(static_cast<SimObject*>(mOrbitObject));
  359. if(obj && static_cast<ShapeBaseData*>(obj->getDataBlock())->observeThroughObject)
  360. obj->setCameraFov(fov);
  361. else
  362. Parent::setCameraFov(fov);
  363. }
  364. //----------------------------------------------------------------------------
  365. void clampPitchAngle(F32 &pitch)
  366. {
  367. // Clamp pitch to +/-MaxPitch, but allow pitch=PI as it is used by some editor
  368. // views (bottom, front, right)
  369. if ((pitch > MaxPitch) && !mIsEqual(pitch, M_PI_F, 0.001f))
  370. pitch = MaxPitch;
  371. else if (pitch < -MaxPitch)
  372. pitch = -MaxPitch;
  373. }
  374. //----------------------------------------------------------------------------
  375. void Camera::processTick(const Move* move)
  376. {
  377. Parent::processTick(move);
  378. if ( isMounted() )
  379. {
  380. // Update SceneContainer.
  381. updateContainer();
  382. return;
  383. }
  384. Point3F vec,pos;
  385. if (move)
  386. {
  387. bool strafeMode = move->trigger[2];
  388. // If using editor then force camera into fly mode, unless using EditOrbitMode
  389. if(gEditingMission && mMode != FlyMode && mMode != EditOrbitMode)
  390. setFlyMode();
  391. // Massage the mode if we're in EditOrbitMode
  392. CameraMotionMode virtualMode = mMode;
  393. if(mMode == EditOrbitMode)
  394. {
  395. if(!mValidEditOrbitPoint)
  396. {
  397. virtualMode = FlyMode;
  398. }
  399. else
  400. {
  401. // Reset any Newton camera velocities for when we switch
  402. // out of EditOrbitMode.
  403. mNewtonRotation = false;
  404. mVelocity.set(0.0f, 0.0f, 0.0f);
  405. mAngularVelocity.set(0.0f, 0.0f, 0.0f);
  406. }
  407. }
  408. // Update orientation
  409. mDelta.rotVec = mRot;
  410. VectorF rotVec(0, 0, 0);
  411. bool doStandardMove = true;
  412. #ifdef TORQUE_EXTENDED_MOVE
  413. GameConnection* con = getControllingClient();
  414. // Work with an absolute rotation from the ExtendedMove class?
  415. if(con && con->getControlSchemeAbsoluteRotation())
  416. {
  417. doStandardMove = false;
  418. const ExtendedMove* emove = dynamic_cast<const ExtendedMove*>(move);
  419. U32 emoveIndex = smExtendedMovePosRotIndex;
  420. if(emoveIndex >= ExtendedMove::MaxPositionsRotations)
  421. emoveIndex = 0;
  422. if(emove->EulerBasedRotation[emoveIndex])
  423. {
  424. if(virtualMode != StationaryMode &&
  425. virtualMode != TrackObjectMode &&
  426. (!mLocked || virtualMode != OrbitObjectMode && virtualMode != OrbitPointMode))
  427. {
  428. // Pitch
  429. mRot.x += (emove->rotX[emoveIndex] - mLastAbsolutePitch);
  430. // Do we also include the relative pitch value?
  431. if(con->getControlSchemeAddPitchToAbsRot() && !strafeMode)
  432. {
  433. F32 x = move->pitch;
  434. if (x > M_PI_F)
  435. x -= M_2PI_F;
  436. mRot.x += x;
  437. }
  438. // Constrain the range of mRot.x
  439. while (mRot.x < -M_PI_F)
  440. mRot.x += M_2PI_F;
  441. while (mRot.x > M_PI_F)
  442. mRot.x -= M_2PI_F;
  443. // Yaw
  444. mRot.z += (emove->rotZ[emoveIndex] - mLastAbsoluteYaw);
  445. // Do we also include the relative yaw value?
  446. if(con->getControlSchemeAddYawToAbsRot() && !strafeMode)
  447. {
  448. F32 z = move->yaw;
  449. if (z > M_PI_F)
  450. z -= M_2PI_F;
  451. mRot.z += z;
  452. }
  453. // Constrain the range of mRot.z
  454. while (mRot.z < -M_PI_F)
  455. mRot.z += M_2PI_F;
  456. while (mRot.z > M_PI_F)
  457. mRot.z -= M_2PI_F;
  458. mLastAbsoluteYaw = emove->rotZ[emoveIndex];
  459. mLastAbsolutePitch = emove->rotX[emoveIndex];
  460. mLastAbsoluteRoll = emove->rotY[emoveIndex];
  461. // Bank
  462. mRot.y = emove->rotY[emoveIndex];
  463. // Constrain the range of mRot.y
  464. while (mRot.y > M_PI_F)
  465. mRot.y -= M_2PI_F;
  466. }
  467. }
  468. }
  469. #endif
  470. if(doStandardMove)
  471. {
  472. // process input/determine rotation vector
  473. if(virtualMode != StationaryMode &&
  474. virtualMode != TrackObjectMode &&
  475. (!mLocked || ((virtualMode != OrbitObjectMode) && (virtualMode != OrbitPointMode))))
  476. {
  477. if(!strafeMode)
  478. {
  479. rotVec.x = move->pitch;
  480. rotVec.z = move->yaw;
  481. }
  482. }
  483. else if(virtualMode == TrackObjectMode && bool(mOrbitObject))
  484. {
  485. // orient the camera to face the object
  486. Point3F objPos;
  487. // If this is a shapebase, use its render eye transform
  488. // to avoid jittering.
  489. ShapeBase *shape = dynamic_cast<ShapeBase*>((GameBase*)mOrbitObject);
  490. if( shape != NULL )
  491. {
  492. MatrixF ret;
  493. shape->getRenderEyeTransform( &ret );
  494. objPos = ret.getPosition();
  495. }
  496. else
  497. {
  498. mOrbitObject->getWorldBox().getCenter(&objPos);
  499. }
  500. mObjToWorld.getColumn(3,&pos);
  501. vec = objPos - pos;
  502. vec.normalizeSafe();
  503. F32 pitch, yaw;
  504. MathUtils::getAnglesFromVector(vec, yaw, pitch);
  505. rotVec.x = -pitch - mRot.x;
  506. rotVec.z = yaw - mRot.z;
  507. if(rotVec.z > M_PI_F)
  508. rotVec.z -= M_2PI_F;
  509. else if(rotVec.z < -M_PI_F)
  510. rotVec.z += M_2PI_F;
  511. }
  512. // apply rotation vector according to physics rules
  513. if(mNewtonRotation)
  514. {
  515. const F32 force = mAngularForce;
  516. const F32 drag = mAngularDrag;
  517. VectorF acc(0.0f, 0.0f, 0.0f);
  518. rotVec.x *= 2.0f; // Assume that our -2PI to 2PI range was clamped to -PI to PI in script
  519. rotVec.z *= 2.0f; // Assume that our -2PI to 2PI range was clamped to -PI to PI in script
  520. F32 rotVecL = rotVec.len();
  521. if(rotVecL > 0)
  522. {
  523. acc = (rotVec * force / mMass) * TickSec;
  524. }
  525. // Accelerate
  526. mAngularVelocity += acc;
  527. // Drag
  528. mAngularVelocity -= mAngularVelocity * drag * TickSec;
  529. // Rotate
  530. mRot += mAngularVelocity * TickSec;
  531. clampPitchAngle(mRot.x);
  532. }
  533. else
  534. {
  535. mRot.x += rotVec.x;
  536. mRot.z += rotVec.z;
  537. clampPitchAngle(mRot.x);
  538. }
  539. }
  540. // Update position
  541. VectorF posVec(0, 0, 0);
  542. bool mustValidateEyePoint = false;
  543. bool serverInterpolate = false;
  544. // process input/determine translation vector
  545. if(virtualMode == OrbitObjectMode || virtualMode == OrbitPointMode)
  546. {
  547. pos = mDelta.pos;
  548. if(virtualMode == OrbitObjectMode && bool(mOrbitObject))
  549. {
  550. // If this is a shapebase, use its render eye transform
  551. // to avoid jittering.
  552. GameBase *castObj = mOrbitObject;
  553. ShapeBase* shape = dynamic_cast<ShapeBase*>(castObj);
  554. if( shape != NULL )
  555. {
  556. MatrixF ret;
  557. shape->getRenderEyeTransform( &ret );
  558. mPosition = ret.getPosition();
  559. }
  560. else
  561. {
  562. // Hopefully this is a static object that doesn't move,
  563. // because the worldbox doesn't get updated between ticks.
  564. mOrbitObject->getWorldBox().getCenter(&mPosition);
  565. }
  566. }
  567. posVec = (mPosition + mOffset) - pos;
  568. mustValidateEyePoint = true;
  569. serverInterpolate = mNewtonMode;
  570. }
  571. else if(virtualMode == EditOrbitMode && mValidEditOrbitPoint)
  572. {
  573. bool faster = move->trigger[0] || move->trigger[1];
  574. F32 scale = smMovementSpeed * (faster + 1);
  575. mCurrentEditOrbitDist -= move->y * TickSec * scale;
  576. 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
  577. if(mCurrentEditOrbitDist < 0.0f)
  578. mCurrentEditOrbitDist = 0.0f;
  579. mPosition = mEditOrbitPoint;
  580. _setPosition(mPosition, mRot);
  581. _calcEditOrbitPoint(&mObjToWorld, mRot);
  582. pos = mPosition;
  583. }
  584. else if(virtualMode == FlyMode)
  585. {
  586. bool faster = move->trigger[0] || move->trigger[1];
  587. F32 scale = smMovementSpeed * (faster + 1);
  588. mObjToWorld.getColumn(3,&pos);
  589. mObjToWorld.getColumn(0,&vec);
  590. posVec = vec * move->x * TickSec * scale + vec * (strafeMode ? move->yaw * 2.0f * TickSec * scale : 0.0f);
  591. mObjToWorld.getColumn(1,&vec);
  592. posVec += vec * move->y * TickSec * scale + vec * move->roll * TickSec * scale;
  593. mObjToWorld.getColumn(2,&vec);
  594. posVec += vec * move->z * TickSec * scale - vec * (strafeMode ? move->pitch * 2.0f * TickSec * scale : 0.0f);
  595. }
  596. else if(virtualMode == OverheadMode)
  597. {
  598. bool faster = move->trigger[0] || move->trigger[1];
  599. F32 scale = smMovementSpeed * (faster + 1);
  600. mObjToWorld.getColumn(3,&pos);
  601. mObjToWorld.getColumn(0,&vec);
  602. vec.z = 0;
  603. vec.normalizeSafe();
  604. vec = vec * move->x * TickSec * scale + (strafeMode ? vec * move->yaw * 2.0f * TickSec * scale : Point3F(0, 0, 0));
  605. posVec = vec;
  606. mObjToWorld.getColumn(1,&vec);
  607. vec.z = 0;
  608. if (vec.isZero())
  609. {
  610. mObjToWorld.getColumn(2,&vec);
  611. vec.z = 0;
  612. }
  613. vec.normalizeSafe();
  614. vec = vec * move->y * TickSec * scale - (strafeMode ? vec * move->pitch * 2.0f * TickSec * scale : Point3F(0, 0, 0));
  615. posVec += vec;
  616. posVec.z += move->z * TickSec * scale + move->roll * TickSec * scale;
  617. }
  618. else // ignore input
  619. {
  620. mObjToWorld.getColumn(3,&pos);
  621. }
  622. // apply translation vector according to physics rules
  623. mDelta.posVec = pos;
  624. if(mNewtonMode)
  625. {
  626. bool faster = move->trigger[0];
  627. bool brake = move->trigger[1];
  628. const F32 movementSpeedMultiplier = smMovementSpeed / 40.0f; // Using the starting value as the base
  629. const F32 force = faster ? mFlyForce * movementSpeedMultiplier * mSpeedMultiplier : mFlyForce * movementSpeedMultiplier;
  630. const F32 drag = brake ? mDrag * mBrakeMultiplier : mDrag;
  631. VectorF acc(0.0f, 0.0f, 0.0f);
  632. F32 posVecL = posVec.len();
  633. if(posVecL > 0)
  634. {
  635. acc = (posVec * force / mMass) * TickSec;
  636. }
  637. // Accelerate
  638. mVelocity += acc;
  639. // Drag
  640. mVelocity -= mVelocity * drag * TickSec;
  641. // Move
  642. pos += mVelocity * TickSec;
  643. }
  644. else
  645. {
  646. pos += posVec;
  647. }
  648. _setPosition(pos,mRot);
  649. // If on the client, calc delta for backstepping
  650. if (serverInterpolate || isClientObject())
  651. {
  652. mDelta.pos = pos;
  653. mDelta.rot = mRot;
  654. mDelta.posVec = mDelta.posVec - mDelta.pos;
  655. mDelta.rotVec = mDelta.rotVec - mDelta.rot;
  656. for(U32 i=0; i<3; ++i)
  657. {
  658. if (mDelta.rotVec[i] > M_PI_F)
  659. mDelta.rotVec[i] -= M_2PI_F;
  660. else if (mDelta.rotVec[i] < -M_PI_F)
  661. mDelta.rotVec[i] += M_2PI_F;
  662. }
  663. }
  664. if(mustValidateEyePoint)
  665. _validateEyePoint(1.0f, &mObjToWorld);
  666. setMaskBits(MoveMask);
  667. }
  668. // Need to calculate the orbit position for the editor so the camera position
  669. // doesn't change when switching between orbit and other camera modes
  670. if (isServerObject() && (mMode == EditOrbitMode && mValidEditOrbitPoint))
  671. _calcEditOrbitPoint(&mObjToWorld, mRot);
  672. if(getControllingClient() && mContainer)
  673. updateContainer();
  674. }
  675. //----------------------------------------------------------------------------
  676. void Camera::onDeleteNotify( SimObject* obj )
  677. {
  678. if( obj == mOrbitObject )
  679. {
  680. mOrbitObject = NULL;
  681. if( mMode == OrbitObjectMode )
  682. mMode = OrbitPointMode;
  683. }
  684. Parent::onDeleteNotify( obj );
  685. }
  686. //----------------------------------------------------------------------------
  687. void Camera::interpolateTick(F32 dt)
  688. {
  689. Parent::interpolateTick(dt);
  690. if ( isMounted() )
  691. return;
  692. Point3F rot = mDelta.rot + mDelta.rotVec * dt;
  693. if((mMode == OrbitObjectMode || mMode == OrbitPointMode) && !mNewtonMode)
  694. {
  695. if(mMode == OrbitObjectMode && bool(mOrbitObject))
  696. {
  697. // If this is a shapebase, use its render eye transform
  698. // to avoid jittering.
  699. GameBase *castObj = mOrbitObject;
  700. ShapeBase* shape = dynamic_cast<ShapeBase*>(castObj);
  701. if( shape != NULL )
  702. {
  703. MatrixF ret;
  704. shape->getRenderEyeTransform( &ret );
  705. mPosition = ret.getPosition();
  706. }
  707. else
  708. {
  709. // Hopefully this is a static object that doesn't move,
  710. // because the worldbox doesn't get updated between ticks.
  711. mOrbitObject->getWorldBox().getCenter(&mPosition);
  712. }
  713. }
  714. _setRenderPosition( mPosition + mOffset, rot );
  715. _validateEyePoint( 1.0f, &mRenderObjToWorld );
  716. }
  717. else if(mMode == EditOrbitMode && mValidEditOrbitPoint)
  718. {
  719. mPosition = mEditOrbitPoint;
  720. _setRenderPosition(mPosition, rot);
  721. _calcEditOrbitPoint(&mRenderObjToWorld, rot);
  722. }
  723. else if(mMode == TrackObjectMode && bool(mOrbitObject) && !mNewtonRotation)
  724. {
  725. // orient the camera to face the object
  726. Point3F objPos;
  727. // If this is a shapebase, use its render eye transform
  728. // to avoid jittering.
  729. ShapeBase *shape = dynamic_cast<ShapeBase*>((GameBase*)mOrbitObject);
  730. if( shape != NULL )
  731. {
  732. MatrixF ret;
  733. shape->getRenderEyeTransform( &ret );
  734. objPos = ret.getPosition();
  735. }
  736. else
  737. {
  738. mOrbitObject->getWorldBox().getCenter(&objPos);
  739. }
  740. Point3F pos = mDelta.pos + mDelta.posVec * dt;
  741. Point3F vec = objPos - pos;
  742. vec.normalizeSafe();
  743. F32 pitch, yaw;
  744. MathUtils::getAnglesFromVector(vec, yaw, pitch);
  745. rot.x = -pitch;
  746. rot.z = yaw;
  747. _setRenderPosition(pos, rot);
  748. }
  749. else
  750. {
  751. Point3F pos = mDelta.pos + mDelta.posVec * dt;
  752. _setRenderPosition(pos,rot);
  753. if(mMode == OrbitObjectMode || mMode == OrbitPointMode)
  754. _validateEyePoint(1.0f, &mRenderObjToWorld);
  755. }
  756. }
  757. //----------------------------------------------------------------------------
  758. void Camera::_setPosition(const Point3F& pos, const Point3F& rot)
  759. {
  760. MatrixF xRot, zRot;
  761. xRot.set(EulerF(rot.x, 0.0f, 0.0f));
  762. zRot.set(EulerF(0.0f, 0.0f, rot.z));
  763. MatrixF temp;
  764. if(mDataBlock && mDataBlock->cameraCanBank)
  765. {
  766. // Take rot.y into account to bank the camera
  767. MatrixF imat;
  768. imat.mul(zRot, xRot);
  769. MatrixF ymat;
  770. ymat.set(EulerF(0.0f, rot.y, 0.0f));
  771. temp.mul(imat, ymat);
  772. }
  773. else
  774. {
  775. temp.mul(zRot, xRot);
  776. }
  777. temp.setColumn(3, pos);
  778. Parent::setTransform(temp);
  779. mRot = rot;
  780. }
  781. //----------------------------------------------------------------------------
  782. void Camera::setRotation(const Point3F& rot)
  783. {
  784. MatrixF xRot, zRot;
  785. xRot.set(EulerF(rot.x, 0.0f, 0.0f));
  786. zRot.set(EulerF(0.0f, 0.0f, rot.z));
  787. MatrixF temp;
  788. if(mDataBlock && mDataBlock->cameraCanBank)
  789. {
  790. // Take rot.y into account to bank the camera
  791. MatrixF imat;
  792. imat.mul(zRot, xRot);
  793. MatrixF ymat;
  794. ymat.set(EulerF(0.0f, rot.y, 0.0f));
  795. temp.mul(imat, ymat);
  796. }
  797. else
  798. {
  799. temp.mul(zRot, xRot);
  800. }
  801. temp.setColumn(3, getPosition());
  802. Parent::setTransform(temp);
  803. mRot = rot;
  804. }
  805. //----------------------------------------------------------------------------
  806. void Camera::_setRenderPosition(const Point3F& pos,const Point3F& rot)
  807. {
  808. MatrixF xRot, zRot;
  809. xRot.set(EulerF(rot.x, 0, 0));
  810. zRot.set(EulerF(0, 0, rot.z));
  811. MatrixF temp;
  812. // mDataBlock may not be defined yet as this method is called during
  813. // SceneObject::onAdd().
  814. if(mDataBlock && mDataBlock->cameraCanBank)
  815. {
  816. // Take rot.y into account to bank the camera
  817. MatrixF imat;
  818. imat.mul(zRot, xRot);
  819. MatrixF ymat;
  820. ymat.set(EulerF(0.0f, rot.y, 0.0f));
  821. temp.mul(imat, ymat);
  822. }
  823. else
  824. {
  825. temp.mul(zRot, xRot);
  826. }
  827. temp.setColumn(3, pos);
  828. Parent::setRenderTransform(temp);
  829. }
  830. //----------------------------------------------------------------------------
  831. void Camera::writePacketData(GameConnection *connection, BitStream *bstream)
  832. {
  833. // Update client regardless of status flags.
  834. Parent::writePacketData(connection, bstream);
  835. Point3F pos;
  836. mObjToWorld.getColumn(3,&pos);
  837. bstream->setCompressionPoint(pos);
  838. mathWrite(*bstream, pos);
  839. bstream->write(mRot.x);
  840. if(mDataBlock && bstream->writeFlag(mDataBlock->cameraCanBank))
  841. {
  842. // Include mRot.y to allow for camera banking
  843. bstream->write(mRot.y);
  844. }
  845. bstream->write(mRot.z);
  846. U32 writeMode = mMode;
  847. Point3F writePos = mPosition;
  848. S32 gIndex = -1;
  849. if(mMode == OrbitObjectMode)
  850. {
  851. gIndex = bool(mOrbitObject) ? connection->getGhostIndex(mOrbitObject): -1;
  852. if(gIndex == -1)
  853. {
  854. writeMode = OrbitPointMode;
  855. if(bool(mOrbitObject))
  856. mOrbitObject->getWorldBox().getCenter(&writePos);
  857. }
  858. }
  859. else if(mMode == TrackObjectMode)
  860. {
  861. gIndex = bool(mOrbitObject) ? connection->getGhostIndex(mOrbitObject): -1;
  862. if(gIndex == -1)
  863. writeMode = StationaryMode;
  864. }
  865. bstream->writeRangedU32(writeMode, CameraFirstMode, CameraLastMode);
  866. if (writeMode == OrbitObjectMode || writeMode == OrbitPointMode)
  867. {
  868. bstream->write(mMinOrbitDist);
  869. bstream->write(mMaxOrbitDist);
  870. bstream->write(mCurOrbitDist);
  871. if(writeMode == OrbitObjectMode)
  872. {
  873. bstream->writeFlag(mObservingClientObject);
  874. bstream->writeInt(gIndex, NetConnection::GhostIdBitSize);
  875. }
  876. if (writeMode == OrbitPointMode)
  877. bstream->writeCompressedPoint(writePos);
  878. }
  879. else if(writeMode == TrackObjectMode)
  880. {
  881. bstream->writeInt(gIndex, NetConnection::GhostIdBitSize);
  882. }
  883. if(bstream->writeFlag(mNewtonMode))
  884. {
  885. bstream->write(mVelocity.x);
  886. bstream->write(mVelocity.y);
  887. bstream->write(mVelocity.z);
  888. }
  889. if(bstream->writeFlag(mNewtonRotation))
  890. {
  891. bstream->write(mAngularVelocity.x);
  892. bstream->write(mAngularVelocity.y);
  893. bstream->write(mAngularVelocity.z);
  894. }
  895. bstream->writeFlag(mValidEditOrbitPoint);
  896. if(writeMode == EditOrbitMode)
  897. {
  898. bstream->write(mEditOrbitPoint.x);
  899. bstream->write(mEditOrbitPoint.y);
  900. bstream->write(mEditOrbitPoint.z);
  901. bstream->write(mCurrentEditOrbitDist);
  902. }
  903. }
  904. //----------------------------------------------------------------------------
  905. void Camera::readPacketData(GameConnection *connection, BitStream *bstream)
  906. {
  907. Parent::readPacketData(connection, bstream);
  908. Point3F pos,rot;
  909. mathRead(*bstream, &pos);
  910. bstream->setCompressionPoint(pos);
  911. bstream->read(&rot.x);
  912. if(bstream->readFlag())
  913. {
  914. // Include rot.y to allow for camera banking
  915. bstream->read(&rot.y);
  916. }
  917. bstream->read(&rot.z);
  918. GameBase* obj = 0;
  919. mMode = (CameraMotionMode)bstream->readRangedU32(CameraFirstMode, CameraLastMode);
  920. mObservingClientObject = false;
  921. if (mMode == OrbitObjectMode || mMode == OrbitPointMode)
  922. {
  923. bstream->read(&mMinOrbitDist);
  924. bstream->read(&mMaxOrbitDist);
  925. bstream->read(&mCurOrbitDist);
  926. if(mMode == OrbitObjectMode)
  927. {
  928. mObservingClientObject = bstream->readFlag();
  929. S32 gIndex = bstream->readInt(NetConnection::GhostIdBitSize);
  930. obj = static_cast<GameBase*>(connection->resolveGhost(gIndex));
  931. }
  932. if (mMode == OrbitPointMode)
  933. bstream->readCompressedPoint(&mPosition);
  934. }
  935. else if (mMode == TrackObjectMode)
  936. {
  937. S32 gIndex = bstream->readInt(NetConnection::GhostIdBitSize);
  938. obj = static_cast<GameBase*>(connection->resolveGhost(gIndex));
  939. }
  940. if (obj != (GameBase*)mOrbitObject)
  941. {
  942. if (mOrbitObject)
  943. {
  944. clearProcessAfter();
  945. clearNotify(mOrbitObject);
  946. }
  947. mOrbitObject = obj;
  948. if (mOrbitObject)
  949. {
  950. processAfter(mOrbitObject);
  951. deleteNotify(mOrbitObject);
  952. }
  953. }
  954. mNewtonMode = bstream->readFlag();
  955. if(mNewtonMode)
  956. {
  957. bstream->read(&mVelocity.x);
  958. bstream->read(&mVelocity.y);
  959. bstream->read(&mVelocity.z);
  960. }
  961. mNewtonRotation = bstream->readFlag();
  962. if(mNewtonRotation)
  963. {
  964. bstream->read(&mAngularVelocity.x);
  965. bstream->read(&mAngularVelocity.y);
  966. bstream->read(&mAngularVelocity.z);
  967. }
  968. mValidEditOrbitPoint = bstream->readFlag();
  969. if(mMode == EditOrbitMode)
  970. {
  971. bstream->read(&mEditOrbitPoint.x);
  972. bstream->read(&mEditOrbitPoint.y);
  973. bstream->read(&mEditOrbitPoint.z);
  974. bstream->read(&mCurrentEditOrbitDist);
  975. }
  976. _setPosition(pos,rot);
  977. // Movement in OrbitObjectMode is not input-based - don't reset interpolation
  978. if(mMode != OrbitObjectMode)
  979. {
  980. mDelta.pos = pos;
  981. mDelta.posVec.set(0.0f, 0.0f, 0.0f);
  982. mDelta.rot = rot;
  983. mDelta.rotVec.set(0.0f, 0.0f, 0.0f);
  984. }
  985. }
  986. //----------------------------------------------------------------------------
  987. U32 Camera::packUpdate(NetConnection *con, U32 mask, BitStream *bstream)
  988. {
  989. Parent::packUpdate(con, mask, bstream);
  990. if (bstream->writeFlag(mask & UpdateMask))
  991. {
  992. bstream->writeFlag(mLocked);
  993. mathWrite(*bstream, mOffset);
  994. }
  995. if(bstream->writeFlag(mask & NewtonCameraMask))
  996. {
  997. bstream->write(mAngularForce);
  998. bstream->write(mAngularDrag);
  999. bstream->write(mMass);
  1000. bstream->write(mDrag);
  1001. bstream->write(mFlyForce);
  1002. bstream->write(mSpeedMultiplier);
  1003. bstream->write(mBrakeMultiplier);
  1004. }
  1005. if(bstream->writeFlag(mask & EditOrbitMask))
  1006. {
  1007. bstream->write(mEditOrbitPoint.x);
  1008. bstream->write(mEditOrbitPoint.y);
  1009. bstream->write(mEditOrbitPoint.z);
  1010. bstream->write(mCurrentEditOrbitDist);
  1011. }
  1012. // The rest of the data is part of the control object packet update.
  1013. // If we're controlled by this client, we don't need to send it.
  1014. if(bstream->writeFlag(getControllingClient() == con && !(mask & InitialUpdateMask)))
  1015. return 0;
  1016. if (bstream->writeFlag(mask & MoveMask))
  1017. {
  1018. Point3F pos;
  1019. mObjToWorld.getColumn(3,&pos);
  1020. bstream->write(pos.x);
  1021. bstream->write(pos.y);
  1022. bstream->write(pos.z);
  1023. bstream->write(mRot.x);
  1024. bstream->write(mRot.z);
  1025. // Only required if in NewtonFlyMode
  1026. F32 len = mVelocity.len();
  1027. if(bstream->writeFlag(mNewtonMode && len > 0.02f))
  1028. {
  1029. Point3F outVel = mVelocity;
  1030. outVel *= 1.0f/len;
  1031. bstream->writeNormalVector(outVel, 10);
  1032. len *= 32.0f; // 5 bits of fraction
  1033. if(len > 8191)
  1034. len = 8191;
  1035. bstream->writeInt((S32)len, 13);
  1036. }
  1037. // Rotation
  1038. len = mAngularVelocity.len();
  1039. if(bstream->writeFlag(mNewtonRotation && len > 0.02f))
  1040. {
  1041. Point3F outVel = mAngularVelocity;
  1042. outVel *= 1.0f/len;
  1043. bstream->writeNormalVector(outVel, 10);
  1044. len *= 32.0f; // 5 bits of fraction
  1045. if(len > 8191)
  1046. len = 8191;
  1047. bstream->writeInt((S32)len, 13);
  1048. }
  1049. }
  1050. return 0;
  1051. }
  1052. //----------------------------------------------------------------------------
  1053. void Camera::unpackUpdate(NetConnection *con, BitStream *bstream)
  1054. {
  1055. Parent::unpackUpdate(con,bstream);
  1056. if (bstream->readFlag())
  1057. {
  1058. mLocked = bstream->readFlag();
  1059. mathRead(*bstream, &mOffset);
  1060. }
  1061. // NewtonCameraMask
  1062. if(bstream->readFlag())
  1063. {
  1064. bstream->read(&mAngularForce);
  1065. bstream->read(&mAngularDrag);
  1066. bstream->read(&mMass);
  1067. bstream->read(&mDrag);
  1068. bstream->read(&mFlyForce);
  1069. bstream->read(&mSpeedMultiplier);
  1070. bstream->read(&mBrakeMultiplier);
  1071. }
  1072. // EditOrbitMask
  1073. if(bstream->readFlag())
  1074. {
  1075. bstream->read(&mEditOrbitPoint.x);
  1076. bstream->read(&mEditOrbitPoint.y);
  1077. bstream->read(&mEditOrbitPoint.z);
  1078. bstream->read(&mCurrentEditOrbitDist);
  1079. }
  1080. // controlled by the client?
  1081. if(bstream->readFlag())
  1082. return;
  1083. // MoveMask
  1084. if (bstream->readFlag())
  1085. {
  1086. Point3F pos,rot;
  1087. bstream->read(&pos.x);
  1088. bstream->read(&pos.y);
  1089. bstream->read(&pos.z);
  1090. bstream->read(&rot.x);
  1091. bstream->read(&rot.z);
  1092. rot.y = 0.0f;
  1093. _setPosition(pos,rot);
  1094. // NewtonMode
  1095. if(bstream->readFlag())
  1096. {
  1097. bstream->readNormalVector(&mVelocity, 10);
  1098. mVelocity *= bstream->readInt(13) / 32.0f;
  1099. }
  1100. // NewtonRotation
  1101. mNewtonRotation = bstream->readFlag();
  1102. if(mNewtonRotation)
  1103. {
  1104. bstream->readNormalVector(&mAngularVelocity, 10);
  1105. mAngularVelocity *= bstream->readInt(13) / 32.0f;
  1106. }
  1107. if(mMode != OrbitObjectMode)
  1108. {
  1109. // New delta for client side interpolation
  1110. mDelta.pos = pos;
  1111. mDelta.rot = rot;
  1112. mDelta.posVec = mDelta.rotVec = VectorF(0.0f, 0.0f, 0.0f);
  1113. }
  1114. }
  1115. }
  1116. //----------------------------------------------------------------------------
  1117. void Camera::initPersistFields()
  1118. {
  1119. docsURL;
  1120. addGroup( "Camera" );
  1121. addProtectedField( "controlMode", TYPEID< CameraMotionMode >(), Offset( mMode, Camera ),
  1122. &_setModeField, &defaultProtectedGetFn,
  1123. "The current camera control mode." );
  1124. endGroup( "Camera" );
  1125. addGroup( "Camera: Newton Mode" );
  1126. addField( "newtonMode", TypeBool, Offset(mNewtonMode, Camera),
  1127. "Apply smoothing (acceleration and damping) to camera movements." );
  1128. addField( "newtonRotation", TypeBool, Offset(mNewtonRotation, Camera),
  1129. "Apply smoothing (acceleration and damping) to camera rotations." );
  1130. addProtectedField( "mass", TypeF32, Offset(mMass, Camera), &_setNewtonField, &defaultProtectedGetFn,
  1131. "The camera's mass (Newton mode only). Default value is 10." );
  1132. addProtectedField( "drag", TypeF32, Offset(mDrag, Camera), &_setNewtonField, &defaultProtectedGetFn,
  1133. "Drag on camera when moving (Newton mode only). Default value is 2." );
  1134. addProtectedField( "force", TypeF32, Offset(mFlyForce, Camera), &_setNewtonField, &defaultProtectedGetFn,
  1135. "Force applied on camera when asked to move (Newton mode only). Default value is 500." );
  1136. addProtectedField( "angularDrag", TypeF32, Offset(mAngularDrag, Camera), &_setNewtonField, &defaultProtectedGetFn,
  1137. "Drag on camera when rotating (Newton mode only). Default value is 2." );
  1138. addProtectedField( "angularForce", TypeF32, Offset(mAngularForce, Camera), &_setNewtonField, &defaultProtectedGetFn,
  1139. "Force applied on camera when asked to rotate (Newton mode only). Default value is 100." );
  1140. addProtectedField( "speedMultiplier", TypeF32, Offset(mSpeedMultiplier, Camera), &_setNewtonField, &defaultProtectedGetFn,
  1141. "Speed multiplier when triggering the accelerator (Newton mode only). Default value is 2." );
  1142. addProtectedField( "brakeMultiplier", TypeF32, Offset(mBrakeMultiplier, Camera), &_setNewtonField, &defaultProtectedGetFn,
  1143. "Speed multiplier when triggering the brake (Newton mode only). Default value is 2." );
  1144. endGroup( "Camera: Newton Mode" );
  1145. Parent::initPersistFields();
  1146. }
  1147. //-----------------------------------------------------------------------------
  1148. void Camera::consoleInit()
  1149. {
  1150. Con::addVariable("$Camera::movementSpeed", TypeF32, &smMovementSpeed,
  1151. "@brief Global camera movement speed in units/s (typically m/s), with a base value of 40.\n\n"
  1152. "Used in the following camera modes:\n"
  1153. "- Edit Orbit Mode\n"
  1154. "- Fly Mode\n"
  1155. "- Overhead Mode\n"
  1156. "@ingroup BaseCamera\n");
  1157. // ExtendedMove support
  1158. Con::addVariable("$camera::extendedMovePosRotIndex", TypeS32, &smExtendedMovePosRotIndex,
  1159. "@brief The ExtendedMove position/rotation index used for camera movements.\n\n"
  1160. "@ingroup BaseCamera\n");
  1161. }
  1162. //-----------------------------------------------------------------------------
  1163. bool Camera::_setNewtonField( void *object, const char *index, const char *data )
  1164. {
  1165. static_cast<Camera*>(object)->setMaskBits(NewtonCameraMask);
  1166. return true; // ok to set value
  1167. }
  1168. //-----------------------------------------------------------------------------
  1169. bool Camera::_setModeField( void *object, const char *index, const char *data )
  1170. {
  1171. Camera *cam = static_cast<Camera*>( object );
  1172. if( dStricmp(data, "Fly") == 0 )
  1173. {
  1174. cam->setFlyMode();
  1175. return false; // already changed mode
  1176. }
  1177. else if( dStricmp(data, "EditOrbit" ) == 0 )
  1178. {
  1179. cam->setEditOrbitMode();
  1180. return false; // already changed mode
  1181. }
  1182. else if( (dStricmp(data, "OrbitObject") == 0 && cam->mMode != OrbitObjectMode) ||
  1183. (dStricmp(data, "TrackObject") == 0 && cam->mMode != TrackObjectMode) ||
  1184. (dStricmp(data, "OrbitPoint") == 0 && cam->mMode != OrbitPointMode) )
  1185. {
  1186. Con::warnf("Couldn't change Camera mode to %s: required information missing. Use camera.set%s().", data, data);
  1187. return false; // don't change the mode - not valid
  1188. }
  1189. else if( dStricmp(data, "OrbitObject") != 0 &&
  1190. dStricmp(data, "TrackObject") != 0 &&
  1191. bool(cam->mOrbitObject) )
  1192. {
  1193. cam->clearProcessAfter();
  1194. cam->clearNotify(cam->mOrbitObject);
  1195. cam->mOrbitObject = NULL;
  1196. }
  1197. // make sure the requested mode is supported, and set it
  1198. // NOTE: The _CameraMode namespace is generated by ImplementEnumType above
  1199. const EngineEnumTable& enums = *( TYPE< CameraMotionMode >()->getEnumTable() );
  1200. const U32 numValues = enums.getNumValues();
  1201. for( S32 i = 0; i < numValues; ++i)
  1202. {
  1203. if( dStricmp(data, enums[i].mName) == 0 )
  1204. {
  1205. cam->mMode = (CameraMotionMode) enums[i].mInt;
  1206. return false;
  1207. }
  1208. }
  1209. Con::warnf("Unsupported camera mode: %s", data);
  1210. return false;
  1211. }
  1212. //-----------------------------------------------------------------------------
  1213. Point3F Camera::getPosition()
  1214. {
  1215. static Point3F position;
  1216. mObjToWorld.getColumn(3, &position);
  1217. return position;
  1218. }
  1219. //-----------------------------------------------------------------------------
  1220. void Camera::setFlyMode()
  1221. {
  1222. mMode = FlyMode;
  1223. if (bool(mOrbitObject))
  1224. {
  1225. clearProcessAfter();
  1226. clearNotify(mOrbitObject);
  1227. }
  1228. mOrbitObject = NULL;
  1229. }
  1230. //-----------------------------------------------------------------------------
  1231. void Camera::setNewtonFlyMode()
  1232. {
  1233. mNewtonMode = true;
  1234. setFlyMode();
  1235. }
  1236. //-----------------------------------------------------------------------------
  1237. void Camera::setOrbitMode(GameBase *obj, const Point3F &pos, const Point3F &rot, const Point3F& offset, F32 minDist, F32 maxDist, F32 curDist, bool ownClientObject, bool locked)
  1238. {
  1239. mObservingClientObject = ownClientObject;
  1240. if (bool(mOrbitObject))
  1241. {
  1242. clearProcessAfter();
  1243. clearNotify(mOrbitObject);
  1244. }
  1245. mOrbitObject = obj;
  1246. if(bool(mOrbitObject))
  1247. {
  1248. processAfter(mOrbitObject);
  1249. deleteNotify(mOrbitObject);
  1250. mOrbitObject->getWorldBox().getCenter(&mPosition);
  1251. mMode = OrbitObjectMode;
  1252. }
  1253. else
  1254. {
  1255. mMode = OrbitPointMode;
  1256. mPosition = pos;
  1257. }
  1258. _setPosition(mPosition, rot);
  1259. mMinOrbitDist = minDist;
  1260. mMaxOrbitDist = maxDist;
  1261. mCurOrbitDist = curDist;
  1262. if (locked != mLocked || mOffset != offset)
  1263. {
  1264. mLocked = locked;
  1265. mOffset = offset;
  1266. setMaskBits(UpdateMask);
  1267. }
  1268. }
  1269. //-----------------------------------------------------------------------------
  1270. void Camera::setTrackObject(GameBase *obj, const Point3F &offset)
  1271. {
  1272. if(bool(mOrbitObject))
  1273. {
  1274. clearProcessAfter();
  1275. clearNotify(mOrbitObject);
  1276. }
  1277. mOrbitObject = obj;
  1278. if(bool(mOrbitObject))
  1279. {
  1280. processAfter(mOrbitObject);
  1281. deleteNotify(mOrbitObject);
  1282. }
  1283. mOffset = offset;
  1284. mMode = TrackObjectMode;
  1285. setMaskBits( UpdateMask );
  1286. }
  1287. //-----------------------------------------------------------------------------
  1288. void Camera::_validateEyePoint(F32 pos, MatrixF *mat)
  1289. {
  1290. if (pos != 0)
  1291. {
  1292. // Use the eye transform to orient the camera
  1293. Point3F dir;
  1294. mat->getColumn(1, &dir);
  1295. if (mMaxOrbitDist - mMinOrbitDist > 0.0f)
  1296. pos *= mMaxOrbitDist - mMinOrbitDist;
  1297. // Use the camera node's pos.
  1298. Point3F startPos = getRenderPosition();
  1299. Point3F endPos;
  1300. // Make sure we don't extend the camera into anything solid
  1301. if(mOrbitObject)
  1302. mOrbitObject->disableCollision();
  1303. disableCollision();
  1304. RayInfo collision;
  1305. U32 mask = TerrainObjectType |
  1306. WaterObjectType |
  1307. StaticShapeObjectType |
  1308. PlayerObjectType |
  1309. ItemObjectType |
  1310. VehicleObjectType;
  1311. SceneContainer* pContainer = isServerObject() ? &gServerContainer : &gClientContainer;
  1312. if (!pContainer->castRay(startPos, startPos - dir * 2.5 * pos, mask, &collision))
  1313. endPos = startPos - dir * pos;
  1314. else
  1315. {
  1316. float dot = mDot(dir, collision.normal);
  1317. if (dot > 0.01f)
  1318. {
  1319. F32 colDist = mDot(startPos - collision.point, dir) - (1 / dot) * CameraRadius;
  1320. if (colDist > pos)
  1321. colDist = pos;
  1322. if (colDist < 0.0f)
  1323. colDist = 0.0f;
  1324. endPos = startPos - dir * colDist;
  1325. }
  1326. else
  1327. endPos = startPos - dir * pos;
  1328. }
  1329. mat->setColumn(3, endPos);
  1330. enableCollision();
  1331. if(mOrbitObject)
  1332. mOrbitObject->enableCollision();
  1333. }
  1334. }
  1335. //-----------------------------------------------------------------------------
  1336. void Camera::setTransform(const MatrixF& mat)
  1337. {
  1338. // This method should never be called on the client.
  1339. // This currently converts all rotation in the mat into
  1340. // rotations around the z and x axis.
  1341. Point3F pos,vec;
  1342. mat.getColumn(1, &vec);
  1343. mat.getColumn(3, &pos);
  1344. Point3F rot(-mAtan2(vec.z, mSqrt(vec.x * vec.x + vec.y * vec.y)), 0.0f, -mAtan2(-vec.x, vec.y));
  1345. _setPosition(pos,rot);
  1346. }
  1347. //-----------------------------------------------------------------------------
  1348. void Camera::setRenderTransform(const MatrixF& mat)
  1349. {
  1350. // This method should never be called on the client.
  1351. // This currently converts all rotation in the mat into
  1352. // rotations around the z and x axis.
  1353. Point3F pos,vec;
  1354. mat.getColumn(1,&vec);
  1355. mat.getColumn(3,&pos);
  1356. Point3F rot(-mAtan2(vec.z, mSqrt(vec.x*vec.x + vec.y*vec.y)),0,-mAtan2(-vec.x,vec.y));
  1357. _setRenderPosition(pos,rot);
  1358. }
  1359. //-----------------------------------------------------------------------------
  1360. F32 Camera::getDamageFlash() const
  1361. {
  1362. if (mMode == OrbitObjectMode && isServerObject() && bool(mOrbitObject))
  1363. {
  1364. const GameBase *castObj = mOrbitObject;
  1365. const ShapeBase* psb = dynamic_cast<const ShapeBase*>(castObj);
  1366. if (psb)
  1367. return psb->getDamageFlash();
  1368. }
  1369. return mDamageFlash;
  1370. }
  1371. //-----------------------------------------------------------------------------
  1372. F32 Camera::getWhiteOut() const
  1373. {
  1374. if (mMode == OrbitObjectMode && isServerObject() && bool(mOrbitObject))
  1375. {
  1376. const GameBase *castObj = mOrbitObject;
  1377. const ShapeBase* psb = dynamic_cast<const ShapeBase*>(castObj);
  1378. if (psb)
  1379. return psb->getWhiteOut();
  1380. }
  1381. return mWhiteOut;
  1382. }
  1383. //-----------------------------------------------------------------------------
  1384. void Camera::setVelocity(const VectorF& vel)
  1385. {
  1386. mVelocity = vel;
  1387. setMaskBits(MoveMask);
  1388. }
  1389. //-----------------------------------------------------------------------------
  1390. void Camera::setAngularVelocity(const VectorF& vel)
  1391. {
  1392. mAngularVelocity = vel;
  1393. setMaskBits(MoveMask);
  1394. }
  1395. //-----------------------------------------------------------------------------
  1396. void Camera::setEditOrbitMode()
  1397. {
  1398. mMode = EditOrbitMode;
  1399. if (bool(mOrbitObject))
  1400. {
  1401. clearProcessAfter();
  1402. clearNotify(mOrbitObject);
  1403. }
  1404. mOrbitObject = NULL;
  1405. // If there is a valid orbit point, then point to it
  1406. // rather than move the camera.
  1407. if(mValidEditOrbitPoint)
  1408. {
  1409. Point3F currentPos;
  1410. mObjToWorld.getColumn(3,&currentPos);
  1411. Point3F dir = mEditOrbitPoint - currentPos;
  1412. mCurrentEditOrbitDist = dir.len();
  1413. dir.normalize();
  1414. F32 yaw, pitch;
  1415. MathUtils::getAnglesFromVector(dir, yaw, pitch);
  1416. mRot.x = -pitch;
  1417. mRot.z = yaw;
  1418. }
  1419. }
  1420. //-----------------------------------------------------------------------------
  1421. void Camera::_calcOrbitPoint( MatrixF* mat, const Point3F& rot )
  1422. {
  1423. Point3F pos;
  1424. pos.x = mCurOrbitDist * mSin( rot.x + mDegToRad( 90.0f ) ) * mCos( -1.0f * ( rot.z + mDegToRad( 90.0f ) ) ) + mPosition.x + mOffset.x;
  1425. pos.y = mCurOrbitDist * mSin( rot.x + mDegToRad( 90.0f ) ) * mSin( -1.0f * ( rot.z + mDegToRad( 90.0f ) ) ) + mPosition.y + mOffset.y;
  1426. pos.z = mCurOrbitDist * mSin( rot.x ) + mPosition.z + mOffset.z;
  1427. mat->setColumn( 3, pos );
  1428. }
  1429. //-----------------------------------------------------------------------------
  1430. void Camera::_calcEditOrbitPoint( MatrixF *mat, const Point3F& rot )
  1431. {
  1432. //Point3F dir;
  1433. //mat->getColumn(1, &dir);
  1434. //Point3F startPos = getRenderPosition();
  1435. //Point3F endPos = startPos - dir * mCurrentEditOrbitDist;
  1436. Point3F pos;
  1437. pos.x = mCurrentEditOrbitDist * mSin(rot.x + mDegToRad(90.0f)) * mCos(-1.0f * (rot.z + mDegToRad(90.0f))) + mEditOrbitPoint.x;
  1438. pos.y = mCurrentEditOrbitDist * mSin(rot.x + mDegToRad(90.0f)) * mSin(-1.0f * (rot.z + mDegToRad(90.0f))) + mEditOrbitPoint.y;
  1439. pos.z = mCurrentEditOrbitDist * mSin(rot.x) + mEditOrbitPoint.z;
  1440. mat->setColumn(3, pos);
  1441. }
  1442. //-----------------------------------------------------------------------------
  1443. void Camera::setValidEditOrbitPoint( bool state )
  1444. {
  1445. mValidEditOrbitPoint = state;
  1446. setMaskBits(EditOrbitMask);
  1447. }
  1448. //-----------------------------------------------------------------------------
  1449. Point3F Camera::getEditOrbitPoint() const
  1450. {
  1451. return mEditOrbitPoint;
  1452. }
  1453. //-----------------------------------------------------------------------------
  1454. void Camera::setEditOrbitPoint( const Point3F& pnt )
  1455. {
  1456. // Change the point that we orbit in EditOrbitMode.
  1457. // We'll also change the facing and distance of the
  1458. // camera so that it doesn't jump around.
  1459. Point3F currentPos;
  1460. mObjToWorld.getColumn(3,&currentPos);
  1461. Point3F dir = pnt - currentPos;
  1462. mCurrentEditOrbitDist = dir.len();
  1463. if(mMode == EditOrbitMode)
  1464. {
  1465. dir.normalize();
  1466. F32 yaw, pitch;
  1467. MathUtils::getAnglesFromVector(dir, yaw, pitch);
  1468. mRot.x = -pitch;
  1469. mRot.z = yaw;
  1470. }
  1471. mEditOrbitPoint = pnt;
  1472. setMaskBits(EditOrbitMask);
  1473. }
  1474. //----------------------------------------------------------------------------
  1475. void Camera::lookAt( const Point3F& pos )
  1476. {
  1477. Point3F vec;
  1478. mObjToWorld.getColumn(3, &mPosition);
  1479. vec = pos - mPosition;
  1480. vec.normalizeSafe();
  1481. F32 pitch, yaw;
  1482. MathUtils::getAnglesFromVector(vec, yaw, pitch);
  1483. mRot.x = -pitch;
  1484. mRot.z = yaw;
  1485. _setPosition(mPosition, mRot);
  1486. }
  1487. //----------------------------------------------------------------------------
  1488. void Camera::autoFitRadius( F32 radius )
  1489. {
  1490. F32 fov = mDegToRad( getCameraFov() );
  1491. F32 viewradius = (radius * 2.0f) / mTan(fov * 0.5f);
  1492. // Be careful of infinite sized objects. Clip to 16km
  1493. if(viewradius > 16000.0f)
  1494. viewradius = 16000.0f;
  1495. if(mMode == EditOrbitMode && mValidEditOrbitPoint)
  1496. {
  1497. mCurrentEditOrbitDist = viewradius;
  1498. }
  1499. else if(mValidEditOrbitPoint)
  1500. {
  1501. mCurrentEditOrbitDist = viewradius;
  1502. Point3F currentPos;
  1503. mObjToWorld.getColumn(3,&currentPos);
  1504. Point3F dir = mEditOrbitPoint - currentPos;
  1505. dir.normalize();
  1506. F32 yaw, pitch;
  1507. MathUtils::getAnglesFromVector(dir, yaw, pitch);
  1508. mRot.x = -pitch;
  1509. mRot.z = yaw;
  1510. mPosition = mEditOrbitPoint;
  1511. _setPosition(mPosition, mRot);
  1512. _calcEditOrbitPoint(&mObjToWorld, mRot);
  1513. }
  1514. }
  1515. //=============================================================================
  1516. // Console API.
  1517. //=============================================================================
  1518. // MARK: ---- Console API ----
  1519. //-----------------------------------------------------------------------------
  1520. DefineEngineMethod( Camera, getMode, Camera::CameraMotionMode, (), ,
  1521. "Returns the current camera control mode.\n\n"
  1522. "@see CameraMotionMode")
  1523. {
  1524. return object->getMode();
  1525. }
  1526. //-----------------------------------------------------------------------------
  1527. DefineEngineMethod( Camera, getPosition, Point3F, (), ,
  1528. "Get the camera's position in the world.\n\n"
  1529. "@returns The position in the form of \"x y z\".")
  1530. {
  1531. return object->getPosition();
  1532. }
  1533. //-----------------------------------------------------------------------------
  1534. DefineEngineMethod( Camera, getRotation, Point3F, (), ,
  1535. "Get the camera's Euler rotation in radians.\n\n"
  1536. "@returns The rotation in radians in the form of \"x y z\".")
  1537. {
  1538. return object->getRotation();
  1539. }
  1540. //-----------------------------------------------------------------------------
  1541. DefineEngineMethod( Camera, setRotation, void, ( Point3F rot ), ,
  1542. "Set the camera's Euler rotation in radians.\n\n"
  1543. "@param rot The rotation in radians in the form of \"x y z\"."
  1544. "@note Rotation around the Y axis is ignored" )
  1545. {
  1546. return object->setRotation( rot );
  1547. }
  1548. //-----------------------------------------------------------------------------
  1549. DefineEngineMethod( Camera, getOffset, Point3F, (), ,
  1550. "Get the camera's offset from its orbit or tracking point.\n\n"
  1551. "The offset is added to the camera's position when set to CameraMode::OrbitObject.\n"
  1552. "@returns The offset in the form of \"x y z\".")
  1553. {
  1554. return object->getOffset();
  1555. }
  1556. //-----------------------------------------------------------------------------
  1557. DefineEngineMethod( Camera, setOffset, void, (Point3F offset), ,
  1558. "Set the camera's offset.\n\n"
  1559. "The offset is added to the camera's position when set to CameraMode::OrbitObject.\n"
  1560. "@param offset The distance to offset the camera by in the form of \"x y z\".")
  1561. {
  1562. object->setOffset(offset);
  1563. }
  1564. //-----------------------------------------------------------------------------
  1565. DefineEngineMethod( Camera, setOrbitMode, void, (GameBase* orbitObject, TransformF orbitPoint, F32 minDistance, F32 maxDistance,
  1566. F32 initDistance, bool ownClientObj, Point3F offset, bool locked), (false, Point3F::Zero, false),
  1567. "Set the camera to orbit around the given object, or if none is given, around the given point.\n\n"
  1568. "@param orbitObject The object to orbit around. If no object is given (0 or blank string is passed in) use the orbitPoint instead\n"
  1569. "@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"
  1570. "@param minDistance The minimum distance allowed to the orbit object or point.\n"
  1571. "@param maxDistance The maximum distance allowed from the orbit object or point.\n"
  1572. "@param initDistance The initial distance from the orbit object or point.\n"
  1573. "@param ownClientObj [optional] Are we orbiting an object that is owned by us? Default is false.\n"
  1574. "@param offset [optional] An offset added to the camera's position. Default is no offset.\n"
  1575. "@param locked [optional] Indicates the camera does not receive input from the player. Default is false.\n"
  1576. "@see Camera::setOrbitObject()\n"
  1577. "@see Camera::setOrbitPoint()\n")
  1578. {
  1579. MatrixF mat;
  1580. orbitPoint.mOrientation.setMatrix(&mat);
  1581. object->setOrbitMode(orbitObject, orbitPoint.mPosition, mat.toEuler(), offset,
  1582. minDistance, maxDistance, initDistance, ownClientObj, locked);
  1583. }
  1584. //-----------------------------------------------------------------------------
  1585. DefineEngineMethod( Camera, setOrbitObject, bool, (GameBase* orbitObject, VectorF rotation, F32 minDistance,
  1586. F32 maxDistance, F32 initDistance, bool ownClientObject, Point3F offset, bool locked),
  1587. (false, Point3F::Zero, false),
  1588. "Set the camera to orbit around a given object.\n\n"
  1589. "@param orbitObject The object to orbit around.\n"
  1590. "@param rotation The initial camera rotation about the object in radians in the form of \"x y z\".\n"
  1591. "@param minDistance The minimum distance allowed to the orbit object or point.\n"
  1592. "@param maxDistance The maximum distance allowed from the orbit object or point.\n"
  1593. "@param initDistance The initial distance from the orbit object or point.\n"
  1594. "@param ownClientObject [optional] Are we orbiting an object that is owned by us? Default is false.\n"
  1595. "@param offset [optional] An offset added to the camera's position. Default is no offset.\n"
  1596. "@param locked [optional] Indicates the camera does not receive input from the player. Default is false.\n"
  1597. "@returns false if the given object could not be found.\n"
  1598. "@see Camera::setOrbitMode()\n")
  1599. {
  1600. if( !orbitObject )
  1601. {
  1602. Con::errorf( "Camera::setOrbitObject - Invalid object");
  1603. return false;
  1604. }
  1605. object->setOrbitMode(orbitObject, Point3F(0.0f, 0.0f, 0.0f), rotation, offset,
  1606. minDistance, maxDistance, initDistance, ownClientObject, locked);
  1607. return true;
  1608. }
  1609. //-----------------------------------------------------------------------------
  1610. DefineEngineMethod( Camera, setOrbitPoint, void, (TransformF orbitPoint, F32 minDistance, F32 maxDistance, F32 initDistance,
  1611. Point3F offset, bool locked),
  1612. (Point3F::Zero, false),
  1613. "Set the camera to orbit around a given point.\n\n"
  1614. "@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"
  1615. "@param minDistance The minimum distance allowed to the orbit object or point.\n"
  1616. "@param maxDistance The maximum distance allowed from the orbit object or point.\n"
  1617. "@param initDistance The initial distance from the orbit object or point.\n"
  1618. "@param offset [optional] An offset added to the camera's position. Default is no offset.\n"
  1619. "@param locked [optional] Indicates the camera does not receive input from the player. Default is false.\n"
  1620. "@see Camera::setOrbitMode()\n")
  1621. {
  1622. MatrixF mat;
  1623. orbitPoint.mOrientation.setMatrix(&mat);
  1624. object->setOrbitMode(NULL, orbitPoint.mPosition, mat.toEuler(), offset,
  1625. minDistance, maxDistance, initDistance, false, locked);
  1626. }
  1627. //-----------------------------------------------------------------------------
  1628. DefineEngineMethod( Camera, setTrackObject, bool, (GameBase* trackObject, Point3F offset), (Point3F::Zero),
  1629. "Set the camera to track a given object.\n\n"
  1630. "@param trackObject The object to track.\n"
  1631. "@param offset [optional] An offset added to the camera's position. Default is no offset.\n"
  1632. "@returns false if the given object could not be found.\n")
  1633. {
  1634. if(!trackObject)
  1635. {
  1636. Con::warnf("Cannot track non-existing object.");
  1637. return false;
  1638. }
  1639. object->setTrackObject(trackObject, offset);
  1640. return true;
  1641. }
  1642. //-----------------------------------------------------------------------------
  1643. DefineEngineMethod( Camera, setEditOrbitMode, void, (), ,
  1644. "Set the editor camera to orbit around a point set with Camera::setEditOrbitPoint().\n\n"
  1645. "@note This method is generally used only within the World Editor and other tools. To "
  1646. "orbit about an object or point within a game, see Camera::setOrbitMode() and its helper methods.\n")
  1647. {
  1648. object->setEditOrbitMode();
  1649. }
  1650. //-----------------------------------------------------------------------------
  1651. DefineEngineMethod( Camera, setFlyMode, void, (), ,
  1652. "Set the camera to fly freely.\n\n"
  1653. "Allows the camera to have 6 degrees of freedom. Provides for instantaneous motion "
  1654. "and rotation unless one of the Newton fields has been set to true. See Camera::newtonMode "
  1655. "and Camera::newtonRotation.\n")
  1656. {
  1657. object->setFlyMode();
  1658. }
  1659. //-----------------------------------------------------------------------------
  1660. DefineEngineMethod( Camera, setNewtonFlyMode, void, (), ,
  1661. "Set the camera to fly freely, but with ease-in and ease-out.\n\n"
  1662. "This method allows for the same 6 degrees of freedom as Camera::setFlyMode() but "
  1663. "activates the ease-in and ease-out on the camera's movement. To also activate "
  1664. "Newton mode for the camera's rotation, set Camera::newtonRotation to true.")
  1665. {
  1666. object->setNewtonFlyMode();
  1667. }
  1668. //-----------------------------------------------------------------------------
  1669. DefineEngineMethod( Camera, isRotationDamped, bool, (), ,
  1670. "Is this a Newton Fly mode camera with damped rotation?\n\n"
  1671. "@returns true if the camera uses a damped rotation. i.e. Camera::newtonRotation is set to true.\n")
  1672. {
  1673. return object->isRotationDamped();
  1674. }
  1675. //-----------------------------------------------------------------------------
  1676. DefineEngineMethod( Camera, getAngularVelocity, VectorF, (), ,
  1677. "Get the angular velocity for a Newton mode camera.\n\n"
  1678. "@returns The angular velocity in the form of \"x y z\".\n"
  1679. "@note Only returns useful results when Camera::newtonRotation is set to true.")
  1680. {
  1681. return object->getAngularVelocity();
  1682. }
  1683. //-----------------------------------------------------------------------------
  1684. DefineEngineMethod( Camera, setAngularVelocity, void, (VectorF velocity), ,
  1685. "Set the angular velocity for a Newton mode camera.\n\n"
  1686. "@param velocity The angular velocity infor form of \"x y z\".\n"
  1687. "@note Only takes affect when Camera::newtonRotation is set to true.")
  1688. {
  1689. object->setAngularVelocity(velocity);
  1690. }
  1691. //-----------------------------------------------------------------------------
  1692. DefineEngineMethod( Camera, setAngularForce, void, (F32 force), ,
  1693. "Set the angular force for a Newton mode camera.\n\n"
  1694. "@param force The angular force applied when attempting to rotate the camera."
  1695. "@note Only takes affect when Camera::newtonRotation is set to true.")
  1696. {
  1697. object->setAngularForce(force);
  1698. }
  1699. //-----------------------------------------------------------------------------
  1700. DefineEngineMethod( Camera, setAngularDrag, void, (F32 drag), ,
  1701. "Set the angular drag for a Newton mode camera.\n\n"
  1702. "@param drag The angular drag applied while the camera is rotating."
  1703. "@note Only takes affect when Camera::newtonRotation is set to true.")
  1704. {
  1705. object->setAngularDrag(drag);
  1706. }
  1707. //-----------------------------------------------------------------------------
  1708. DefineEngineMethod( Camera, setMass, void, (F32 mass), ,
  1709. "Set the mass for a Newton mode camera.\n\n"
  1710. "@param mass The mass used during ease-in and ease-out calculations."
  1711. "@note Only used when Camera is in Newton mode.")
  1712. {
  1713. object->setMass(mass);
  1714. }
  1715. //-----------------------------------------------------------------------------
  1716. DefineEngineMethod( Camera, getVelocity, VectorF, (), ,
  1717. "Get the velocity for the camera.\n\n"
  1718. "@returns The camera's velocity in the form of \"x y z\"."
  1719. "@note Only useful when the Camera is in Newton mode.")
  1720. {
  1721. return object->getVelocity();
  1722. }
  1723. //-----------------------------------------------------------------------------
  1724. DefineEngineMethod( Camera, setVelocity, void, (VectorF velocity), ,
  1725. "Set the velocity for the camera.\n\n"
  1726. "@param velocity The camera's velocity in the form of \"x y z\"."
  1727. "@note Only affects the Camera when in Newton mode.")
  1728. {
  1729. object->setVelocity(velocity);
  1730. }
  1731. //-----------------------------------------------------------------------------
  1732. DefineEngineMethod( Camera, setDrag, void, (F32 drag), ,
  1733. "Set the drag for a Newton mode camera.\n\n"
  1734. "@param drag The drag applied to the camera while moving."
  1735. "@note Only used when Camera is in Newton mode.")
  1736. {
  1737. object->setDrag(drag);
  1738. }
  1739. //-----------------------------------------------------------------------------
  1740. DefineEngineMethod( Camera, setFlyForce, void, (F32 force), ,
  1741. "Set the force applied to a Newton mode camera while moving.\n\n"
  1742. "@param force The force applied to the camera while attempting to move."
  1743. "@note Only used when Camera is in Newton mode.")
  1744. {
  1745. object->setFlyForce(force);
  1746. }
  1747. //-----------------------------------------------------------------------------
  1748. DefineEngineMethod( Camera, setSpeedMultiplier, void, (F32 multiplier), ,
  1749. "Set the Newton mode camera speed multiplier when trigger[0] is active.\n\n"
  1750. "@param multiplier The speed multiplier to apply."
  1751. "@note Only used when Camera is in Newton mode.")
  1752. {
  1753. object->setSpeedMultiplier(multiplier);
  1754. }
  1755. //-----------------------------------------------------------------------------
  1756. DefineEngineMethod( Camera, setBrakeMultiplier, void, (F32 multiplier), ,
  1757. "Set the Newton mode camera brake multiplier when trigger[1] is active.\n\n"
  1758. "@param multiplier The brake multiplier to apply."
  1759. "@note Only used when Camera is in Newton mode.")
  1760. {
  1761. object->setBrakeMultiplier(multiplier);
  1762. }
  1763. //----------------------------------------------------------------------------
  1764. DefineEngineMethod( Camera, isEditOrbitMode, bool, (), ,
  1765. "Is the camera in edit orbit mode?\n\n"
  1766. "@returns true if the camera is in edit orbit mode.")
  1767. {
  1768. return object->isEditOrbitMode();
  1769. }
  1770. //----------------------------------------------------------------------------
  1771. DefineEngineMethod( Camera, setValidEditOrbitPoint, void, (bool validPoint), ,
  1772. "Set if there is a valid editor camera orbit point.\n"
  1773. "When validPoint is set to false the Camera operates as if it is "
  1774. "in Fly mode rather than an Orbit mode.\n\n"
  1775. "@param validPoint Indicates the validity of the orbit point."
  1776. "@note Only used when Camera is in Edit Orbit Mode.")
  1777. {
  1778. object->setValidEditOrbitPoint(validPoint);
  1779. }
  1780. //----------------------------------------------------------------------------
  1781. DefineEngineMethod( Camera, setEditOrbitPoint, void, (Point3F point), ,
  1782. "Set the editor camera's orbit point.\n\n"
  1783. "@param point The point the camera will orbit in the form of \"x y z\".")
  1784. {
  1785. object->setEditOrbitPoint(point);
  1786. }
  1787. //----------------------------------------------------------------------------
  1788. DefineEngineMethod( Camera, autoFitRadius, void, (F32 radius), ,
  1789. "Move the camera to fully view the given radius.\n\n"
  1790. "@note For this operation to take affect a valid edit orbit point must first be specified. See Camera::setEditOrbitPoint().\n"
  1791. "@param radius The radius to view.")
  1792. {
  1793. object->autoFitRadius(radius);
  1794. }
  1795. //----------------------------------------------------------------------------
  1796. DefineEngineMethod( Camera, lookAt, void, (Point3F point), ,
  1797. "Point the camera at the specified position. Does not work in Orbit or Track modes.\n\n"
  1798. "@param point The position to point the camera at.")
  1799. {
  1800. object->lookAt(point);
  1801. }