camera.cpp 74 KB

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