BsCamera.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793
  1. /*
  2. -----------------------------------------------------------------------------
  3. This source file is part of OGRE
  4. (Object-oriented Graphics Rendering Engine)
  5. For the latest info, see http://www.ogre3d.org
  6. Copyright (c) 2000-2011 Torus Knot Software Ltd
  7. Permission is hereby granted, free of charge, to any person obtaining a copy
  8. of this software and associated documentation files (the "Software"), to deal
  9. in the Software without restriction, including without limitation the rights
  10. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. copies of the Software, and to permit persons to whom the Software is
  12. furnished to do so, subject to the following conditions:
  13. The above copyright notice and this permission notice shall be included in
  14. all copies or substantial portions of the Software.
  15. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. THE SOFTWARE.
  22. -----------------------------------------------------------------------------
  23. */
  24. #include "BsCamera.h"
  25. #include "BsCameraRTTI.h"
  26. #include "CmMath.h"
  27. #include "CmMatrix3.h"
  28. #include "CmVector2.h"
  29. #include "CmAABox.h"
  30. #include "CmSphere.h"
  31. #include "CmHardwareBufferManager.h"
  32. #include "CmVertexBuffer.h"
  33. #include "CmIndexBuffer.h"
  34. #include "CmException.h"
  35. #include "CmRenderSystem.h"
  36. #include "CmSceneObject.h"
  37. using namespace CamelotFramework;
  38. namespace BansheeEngine
  39. {
  40. const float Camera::INFINITE_FAR_PLANE_ADJUST = 0.00001f;
  41. //-----------------------------------------------------------------------
  42. Camera::Camera(const HSceneObject& parent)
  43. : Component(parent),
  44. mProjType(PT_PERSPECTIVE),
  45. mHorzFOV(Radian(Math::PI/4.0f)),
  46. mFarDist(100000.0f),
  47. mNearDist(100.0f),
  48. mAspect(1.33333333333333f),
  49. mOrthoHeight(1000),
  50. mFrustumOffset(Vector2::ZERO),
  51. mFocalLength(1.0f),
  52. mLastParentOrientation(Quaternion::IDENTITY),
  53. mLastParentPosition(Vector3::ZERO),
  54. mRecalcFrustum(true),
  55. mRecalcFrustumPlanes(true),
  56. mRecalcWorldSpaceCorners(true),
  57. mRecalcVertexData(true),
  58. mCustomViewMatrix(false),
  59. mCustomProjMatrix(false),
  60. mFrustumExtentsManuallySet(false),
  61. mIgnoreSceneRenderables(false),
  62. mPriority(0),
  63. mLayers(0xFFFFFFFFFFFFFFFF)
  64. {
  65. setName("Camera");
  66. updateView();
  67. updateFrustum();
  68. // Reasonable defaults to camera params
  69. mHorzFOV = Radian(Math::PI/4.0f);
  70. mNearDist = 100.0f;
  71. mFarDist = 100000.0f;
  72. mAspect = 1.33333333333333f;
  73. mProjType = PT_PERSPECTIVE;
  74. invalidateFrustum();
  75. // Init matrices
  76. mViewMatrix = Matrix4::ZERO;
  77. mProjMatrixRS = Matrix4::ZERO;
  78. }
  79. //-----------------------------------------------------------------------
  80. Camera::~Camera()
  81. {
  82. }
  83. void Camera::initialize(RenderTargetPtr target, float left, float top, float width, float height)
  84. {
  85. target->synchronize();
  86. mViewport = cm_shared_ptr<Viewport, PoolAlloc>(target, left, top, width, height);
  87. }
  88. //-----------------------------------------------------------------------
  89. void Camera::setHorzFOV(const Radian& fov)
  90. {
  91. mHorzFOV = fov;
  92. invalidateFrustum();
  93. }
  94. //-----------------------------------------------------------------------
  95. const Radian& Camera::getHorzFOV(void) const
  96. {
  97. return mHorzFOV;
  98. }
  99. //-----------------------------------------------------------------------
  100. void Camera::setFarClipDistance(float farPlane)
  101. {
  102. mFarDist = farPlane;
  103. invalidateFrustum();
  104. }
  105. //-----------------------------------------------------------------------
  106. float Camera::getFarClipDistance(void) const
  107. {
  108. return mFarDist;
  109. }
  110. //-----------------------------------------------------------------------
  111. void Camera::setNearClipDistance(float nearPlane)
  112. {
  113. if (nearPlane <= 0)
  114. {
  115. CM_EXCEPT(InvalidParametersException, "Near clip distance must be greater than zero.");
  116. }
  117. mNearDist = nearPlane;
  118. invalidateFrustum();
  119. }
  120. //-----------------------------------------------------------------------
  121. float Camera::getNearClipDistance(void) const
  122. {
  123. return mNearDist;
  124. }
  125. //---------------------------------------------------------------------
  126. void Camera::setFrustumOffset(const Vector2& offset)
  127. {
  128. mFrustumOffset = offset;
  129. invalidateFrustum();
  130. }
  131. //---------------------------------------------------------------------
  132. void Camera::setFrustumOffset(float horizontal, float vertical)
  133. {
  134. setFrustumOffset(Vector2(horizontal, vertical));
  135. }
  136. //---------------------------------------------------------------------
  137. const Vector2& Camera::getFrustumOffset() const
  138. {
  139. return mFrustumOffset;
  140. }
  141. //---------------------------------------------------------------------
  142. void Camera::setFocalLength(float focalLength)
  143. {
  144. if (focalLength <= 0)
  145. {
  146. CM_EXCEPT(InvalidParametersException,
  147. "Focal length must be greater than zero.");
  148. }
  149. mFocalLength = focalLength;
  150. invalidateFrustum();
  151. }
  152. //---------------------------------------------------------------------
  153. float Camera::getFocalLength() const
  154. {
  155. return mFocalLength;
  156. }
  157. //-----------------------------------------------------------------------
  158. const Matrix4& Camera::getProjectionMatrix(void) const
  159. {
  160. updateFrustum();
  161. return mProjMatrix;
  162. }
  163. //-----------------------------------------------------------------------
  164. const Matrix4& Camera::getProjectionMatrixWithRSDepth(void) const
  165. {
  166. updateFrustum();
  167. return mProjMatrixRSDepth;
  168. }
  169. //-----------------------------------------------------------------------
  170. const Matrix4& Camera::getProjectionMatrixRS(void) const
  171. {
  172. updateFrustum();
  173. return mProjMatrixRS;
  174. }
  175. //-----------------------------------------------------------------------
  176. const Matrix4& Camera::getViewMatrix(void) const
  177. {
  178. updateView();
  179. return mViewMatrix;
  180. }
  181. //-----------------------------------------------------------------------
  182. const Plane* Camera::getFrustumPlanes(void) const
  183. {
  184. // Make any pending updates to the calculated frustum planes
  185. updateFrustumPlanes();
  186. return mFrustumPlanes;
  187. }
  188. //-----------------------------------------------------------------------
  189. const Plane& Camera::getFrustumPlane(unsigned short plane) const
  190. {
  191. // Make any pending updates to the calculated frustum planes
  192. updateFrustumPlanes();
  193. return mFrustumPlanes[plane];
  194. }
  195. //-----------------------------------------------------------------------
  196. bool Camera::isVisible(const AABox& bound, FrustumPlane* culledBy) const
  197. {
  198. // Make any pending updates to the calculated frustum planes
  199. updateFrustumPlanes();
  200. // For each plane, see if all points are on the negative side
  201. // If so, object is not visible
  202. for (int plane = 0; plane < 6; ++plane)
  203. {
  204. // Skip far plane if infinite view frustum
  205. if (plane == FRUSTUM_PLANE_FAR && mFarDist == 0)
  206. continue;
  207. Plane::Side side = mFrustumPlanes[plane].getSide(bound);
  208. if (side == Plane::NEGATIVE_SIDE)
  209. {
  210. // ALL corners on negative side therefore out of view
  211. if (culledBy)
  212. *culledBy = (FrustumPlane)plane;
  213. return false;
  214. }
  215. }
  216. return true;
  217. }
  218. //-----------------------------------------------------------------------
  219. bool Camera::isVisible(const Vector3& vert, FrustumPlane* culledBy) const
  220. {
  221. // Make any pending updates to the calculated frustum planes
  222. updateFrustumPlanes();
  223. // For each plane, see if all points are on the negative side
  224. // If so, object is not visible
  225. for (int plane = 0; plane < 6; ++plane)
  226. {
  227. // Skip far plane if infinite view frustum
  228. if (plane == FRUSTUM_PLANE_FAR && mFarDist == 0)
  229. continue;
  230. if (mFrustumPlanes[plane].getSide(vert) == Plane::NEGATIVE_SIDE)
  231. {
  232. // ALL corners on negative side therefore out of view
  233. if (culledBy)
  234. *culledBy = (FrustumPlane)plane;
  235. return false;
  236. }
  237. }
  238. return true;
  239. }
  240. //-----------------------------------------------------------------------
  241. bool Camera::isVisible(const Sphere& sphere, FrustumPlane* culledBy) const
  242. {
  243. // Make any pending updates to the calculated frustum planes
  244. updateFrustumPlanes();
  245. // For each plane, see if sphere is on negative side
  246. // If so, object is not visible
  247. for (int plane = 0; plane < 6; ++plane)
  248. {
  249. // Skip far plane if infinite view frustum
  250. if (plane == FRUSTUM_PLANE_FAR && mFarDist == 0)
  251. continue;
  252. // If the distance from sphere center to plane is negative, and 'more negative'
  253. // than the radius of the sphere, sphere is outside frustum
  254. if (mFrustumPlanes[plane].getDistance(sphere.getCenter()) < -sphere.getRadius())
  255. {
  256. // ALL corners on negative side therefore out of view
  257. if (culledBy)
  258. *culledBy = (FrustumPlane)plane;
  259. return false;
  260. }
  261. }
  262. return true;
  263. }
  264. //-----------------------------------------------------------------------
  265. void Camera::calcProjectionParameters(float& left, float& right, float& bottom, float& top) const
  266. {
  267. if (mCustomProjMatrix)
  268. {
  269. // Convert clipspace corners to camera space
  270. Matrix4 invProj = mProjMatrix.inverse();
  271. Vector3 topLeft(-0.5f, 0.5f, 0.0f);
  272. Vector3 bottomRight(0.5f, -0.5f, 0.0f);
  273. topLeft = invProj.multiply(topLeft);
  274. bottomRight = invProj.multiply(bottomRight);
  275. left = topLeft.x;
  276. top = topLeft.y;
  277. right = bottomRight.x;
  278. bottom = bottomRight.y;
  279. }
  280. else
  281. {
  282. if (mFrustumExtentsManuallySet)
  283. {
  284. left = mLeft;
  285. right = mRight;
  286. top = mTop;
  287. bottom = mBottom;
  288. }
  289. // Calculate general projection parameters
  290. else if (mProjType == PT_PERSPECTIVE)
  291. {
  292. Radian thetaY (mHorzFOV * 0.5f);
  293. float tanThetaY = Math::tan(thetaY);
  294. float tanThetaX = tanThetaY * mAspect;
  295. float nearFocal = mNearDist / mFocalLength;
  296. float nearOffsetX = mFrustumOffset.x * nearFocal;
  297. float nearOffsetY = mFrustumOffset.y * nearFocal;
  298. float half_w = tanThetaX * mNearDist;
  299. float half_h = tanThetaY * mNearDist;
  300. left = - half_w + nearOffsetX;
  301. right = + half_w + nearOffsetX;
  302. bottom = - half_h + nearOffsetY;
  303. top = + half_h + nearOffsetY;
  304. mLeft = left;
  305. mRight = right;
  306. mTop = top;
  307. mBottom = bottom;
  308. }
  309. else
  310. {
  311. // Unknown how to apply frustum offset to orthographic camera, just ignore here
  312. float half_w = getOrthoWindowWidth() * 0.5f;
  313. float half_h = getOrthoWindowHeight() * 0.5f;
  314. left = - half_w;
  315. right = + half_w;
  316. bottom = - half_h;
  317. top = + half_h;
  318. mLeft = left;
  319. mRight = right;
  320. mTop = top;
  321. mBottom = bottom;
  322. }
  323. }
  324. }
  325. //-----------------------------------------------------------------------
  326. void Camera::updateFrustumImpl(void) const
  327. {
  328. // Common calcs
  329. float left, right, bottom, top;
  330. calcProjectionParameters(left, right, bottom, top);
  331. if (!mCustomProjMatrix)
  332. {
  333. // The code below will dealing with general projection
  334. // parameters, similar glFrustum and glOrtho.
  335. // Doesn't optimise manually except division operator, so the
  336. // code more self-explaining.
  337. float inv_w = 1 / (right - left);
  338. float inv_h = 1 / (top - bottom);
  339. float inv_d = 1 / (mFarDist - mNearDist);
  340. // Recalc if frustum params changed
  341. if (mProjType == PT_PERSPECTIVE)
  342. {
  343. // Calc matrix elements
  344. float A = 2 * mNearDist * inv_w;
  345. float B = 2 * mNearDist * inv_h;
  346. float C = (right + left) * inv_w;
  347. float D = (top + bottom) * inv_h;
  348. float q, qn;
  349. if (mFarDist == 0)
  350. {
  351. // Infinite far plane
  352. q = Camera::INFINITE_FAR_PLANE_ADJUST - 1;
  353. qn = mNearDist * (Camera::INFINITE_FAR_PLANE_ADJUST - 2);
  354. }
  355. else
  356. {
  357. q = - (mFarDist + mNearDist) * inv_d;
  358. qn = -2 * (mFarDist * mNearDist) * inv_d;
  359. }
  360. // NB: This creates 'uniform' perspective projection matrix,
  361. // which depth range [-1,1], right-handed rules
  362. //
  363. // [ A 0 C 0 ]
  364. // [ 0 B D 0 ]
  365. // [ 0 0 q qn ]
  366. // [ 0 0 -1 0 ]
  367. //
  368. // A = 2 * near / (right - left)
  369. // B = 2 * near / (top - bottom)
  370. // C = (right + left) / (right - left)
  371. // D = (top + bottom) / (top - bottom)
  372. // q = - (far + near) / (far - near)
  373. // qn = - 2 * (far * near) / (far - near)
  374. mProjMatrix = Matrix4::ZERO;
  375. mProjMatrix[0][0] = A;
  376. mProjMatrix[0][2] = C;
  377. mProjMatrix[1][1] = B;
  378. mProjMatrix[1][2] = D;
  379. mProjMatrix[2][2] = q;
  380. mProjMatrix[2][3] = qn;
  381. mProjMatrix[3][2] = -1;
  382. } // perspective
  383. else if (mProjType == PT_ORTHOGRAPHIC)
  384. {
  385. float A = 2 * inv_w;
  386. float B = 2 * inv_h;
  387. float C = - (right + left) * inv_w;
  388. float D = - (top + bottom) * inv_h;
  389. float q, qn;
  390. if (mFarDist == 0)
  391. {
  392. // Can not do infinite far plane here, avoid divided zero only
  393. q = - Camera::INFINITE_FAR_PLANE_ADJUST / mNearDist;
  394. qn = - Camera::INFINITE_FAR_PLANE_ADJUST - 1;
  395. }
  396. else
  397. {
  398. q = - 2 * inv_d;
  399. qn = - (mFarDist + mNearDist) * inv_d;
  400. }
  401. // NB: This creates 'uniform' orthographic projection matrix,
  402. // which depth range [-1,1], right-handed rules
  403. //
  404. // [ A 0 0 C ]
  405. // [ 0 B 0 D ]
  406. // [ 0 0 q qn ]
  407. // [ 0 0 0 1 ]
  408. //
  409. // A = 2 * / (right - left)
  410. // B = 2 * / (top - bottom)
  411. // C = - (right + left) / (right - left)
  412. // D = - (top + bottom) / (top - bottom)
  413. // q = - 2 / (far - near)
  414. // qn = - (far + near) / (far - near)
  415. mProjMatrix = Matrix4::ZERO;
  416. mProjMatrix[0][0] = A;
  417. mProjMatrix[0][3] = C;
  418. mProjMatrix[1][1] = B;
  419. mProjMatrix[1][3] = D;
  420. mProjMatrix[2][2] = q;
  421. mProjMatrix[2][3] = qn;
  422. mProjMatrix[3][3] = 1;
  423. } // ortho
  424. } // !mCustomProjMatrix
  425. RenderSystem* renderSystem = CamelotFramework::RenderSystem::instancePtr();
  426. // API specific
  427. renderSystem->convertProjectionMatrix(mProjMatrix, mProjMatrixRS);
  428. // API specific for Gpu Programs
  429. renderSystem->convertProjectionMatrix(mProjMatrix, mProjMatrixRSDepth, true);
  430. // Calculate bounding box (local)
  431. // Box is from 0, down -Z, max dimensions as determined from far plane
  432. // If infinite view frustum just pick a far value
  433. float farDist = (mFarDist == 0) ? 100000 : mFarDist;
  434. // Near plane bounds
  435. Vector3 min(left, bottom, -farDist);
  436. Vector3 max(right, top, 0);
  437. if (mCustomProjMatrix)
  438. {
  439. // Some custom projection matrices can have unusual inverted settings
  440. // So make sure the AABB is the right way around to start with
  441. Vector3 tmp = min;
  442. min.floor(max);
  443. max.ceil(tmp);
  444. }
  445. if (mProjType == PT_PERSPECTIVE)
  446. {
  447. // Merge with far plane bounds
  448. float radio = farDist / mNearDist;
  449. min.floor(Vector3(left * radio, bottom * radio, -farDist));
  450. max.ceil(Vector3(right * radio, top * radio, 0));
  451. }
  452. mBoundingBox.setExtents(min, max);
  453. mRecalcFrustum = false;
  454. // Signal to update frustum clipping planes
  455. mRecalcFrustumPlanes = true;
  456. }
  457. //-----------------------------------------------------------------------
  458. void Camera::updateFrustum(void) const
  459. {
  460. if (isFrustumOutOfDate())
  461. {
  462. updateFrustumImpl();
  463. }
  464. }
  465. //-----------------------------------------------------------------------
  466. bool Camera::isFrustumOutOfDate(void) const
  467. {
  468. return mRecalcFrustum;
  469. }
  470. //-----------------------------------------------------------------------
  471. void Camera::updateView(void) const
  472. {
  473. if (!mCustomViewMatrix)
  474. {
  475. Matrix3 rot;
  476. const Quaternion& orientation = sceneObject()->getWorldRotation();
  477. const Vector3& position = sceneObject()->getWorldPosition();
  478. mViewMatrix.makeView(position, orientation);
  479. }
  480. }
  481. //-----------------------------------------------------------------------
  482. void Camera::updateFrustumPlanesImpl(void) const
  483. {
  484. // -------------------------
  485. // Update the frustum planes
  486. // -------------------------
  487. Matrix4 combo = mProjMatrix * mViewMatrix;
  488. mFrustumPlanes[FRUSTUM_PLANE_LEFT].normal.x = combo[3][0] + combo[0][0];
  489. mFrustumPlanes[FRUSTUM_PLANE_LEFT].normal.y = combo[3][1] + combo[0][1];
  490. mFrustumPlanes[FRUSTUM_PLANE_LEFT].normal.z = combo[3][2] + combo[0][2];
  491. mFrustumPlanes[FRUSTUM_PLANE_LEFT].d = combo[3][3] + combo[0][3];
  492. mFrustumPlanes[FRUSTUM_PLANE_RIGHT].normal.x = combo[3][0] - combo[0][0];
  493. mFrustumPlanes[FRUSTUM_PLANE_RIGHT].normal.y = combo[3][1] - combo[0][1];
  494. mFrustumPlanes[FRUSTUM_PLANE_RIGHT].normal.z = combo[3][2] - combo[0][2];
  495. mFrustumPlanes[FRUSTUM_PLANE_RIGHT].d = combo[3][3] - combo[0][3];
  496. mFrustumPlanes[FRUSTUM_PLANE_TOP].normal.x = combo[3][0] - combo[1][0];
  497. mFrustumPlanes[FRUSTUM_PLANE_TOP].normal.y = combo[3][1] - combo[1][1];
  498. mFrustumPlanes[FRUSTUM_PLANE_TOP].normal.z = combo[3][2] - combo[1][2];
  499. mFrustumPlanes[FRUSTUM_PLANE_TOP].d = combo[3][3] - combo[1][3];
  500. mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].normal.x = combo[3][0] + combo[1][0];
  501. mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].normal.y = combo[3][1] + combo[1][1];
  502. mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].normal.z = combo[3][2] + combo[1][2];
  503. mFrustumPlanes[FRUSTUM_PLANE_BOTTOM].d = combo[3][3] + combo[1][3];
  504. mFrustumPlanes[FRUSTUM_PLANE_NEAR].normal.x = combo[3][0] + combo[2][0];
  505. mFrustumPlanes[FRUSTUM_PLANE_NEAR].normal.y = combo[3][1] + combo[2][1];
  506. mFrustumPlanes[FRUSTUM_PLANE_NEAR].normal.z = combo[3][2] + combo[2][2];
  507. mFrustumPlanes[FRUSTUM_PLANE_NEAR].d = combo[3][3] + combo[2][3];
  508. mFrustumPlanes[FRUSTUM_PLANE_FAR].normal.x = combo[3][0] - combo[2][0];
  509. mFrustumPlanes[FRUSTUM_PLANE_FAR].normal.y = combo[3][1] - combo[2][1];
  510. mFrustumPlanes[FRUSTUM_PLANE_FAR].normal.z = combo[3][2] - combo[2][2];
  511. mFrustumPlanes[FRUSTUM_PLANE_FAR].d = combo[3][3] - combo[2][3];
  512. // Renormalise any normals which were not unit length
  513. for(int i=0; i<6; i++ )
  514. {
  515. float length = mFrustumPlanes[i].normal.normalize();
  516. mFrustumPlanes[i].d /= length;
  517. }
  518. mRecalcFrustumPlanes = false;
  519. }
  520. //-----------------------------------------------------------------------
  521. void Camera::updateFrustumPlanes(void) const
  522. {
  523. updateView();
  524. updateFrustum();
  525. if (mRecalcFrustumPlanes)
  526. {
  527. updateFrustumPlanesImpl();
  528. }
  529. }
  530. //-----------------------------------------------------------------------
  531. void Camera::updateWorldSpaceCornersImpl(void) const
  532. {
  533. Matrix4 eyeToWorld = mViewMatrix.inverseAffine();
  534. // Note: Even though we can dealing with general projection matrix here,
  535. // but because it's incompatibly with infinite far plane, thus, we
  536. // still need to working with projection parameters.
  537. // Calc near plane corners
  538. float nearLeft, nearRight, nearBottom, nearTop;
  539. calcProjectionParameters(nearLeft, nearRight, nearBottom, nearTop);
  540. // Treat infinite fardist as some arbitrary far value
  541. float farDist = (mFarDist == 0) ? 100000 : mFarDist;
  542. // Calc far palne corners
  543. float radio = mProjType == PT_PERSPECTIVE ? farDist / mNearDist : 1;
  544. float farLeft = nearLeft * radio;
  545. float farRight = nearRight * radio;
  546. float farBottom = nearBottom * radio;
  547. float farTop = nearTop * radio;
  548. // near
  549. mWorldSpaceCorners[0] = eyeToWorld.multiply3x4(Vector3(nearRight, nearTop, -mNearDist));
  550. mWorldSpaceCorners[1] = eyeToWorld.multiply3x4(Vector3(nearLeft, nearTop, -mNearDist));
  551. mWorldSpaceCorners[2] = eyeToWorld.multiply3x4(Vector3(nearLeft, nearBottom, -mNearDist));
  552. mWorldSpaceCorners[3] = eyeToWorld.multiply3x4(Vector3(nearRight, nearBottom, -mNearDist));
  553. // far
  554. mWorldSpaceCorners[4] = eyeToWorld.multiply3x4(Vector3(farRight, farTop, -farDist));
  555. mWorldSpaceCorners[5] = eyeToWorld.multiply3x4(Vector3(farLeft, farTop, -farDist));
  556. mWorldSpaceCorners[6] = eyeToWorld.multiply3x4(Vector3(farLeft, farBottom, -farDist));
  557. mWorldSpaceCorners[7] = eyeToWorld.multiply3x4(Vector3(farRight, farBottom, -farDist));
  558. mRecalcWorldSpaceCorners = false;
  559. }
  560. //-----------------------------------------------------------------------
  561. void Camera::updateWorldSpaceCorners(void) const
  562. {
  563. updateView();
  564. if (mRecalcWorldSpaceCorners)
  565. {
  566. updateWorldSpaceCornersImpl();
  567. }
  568. }
  569. //-----------------------------------------------------------------------
  570. float Camera::getAspectRatio(void) const
  571. {
  572. return mAspect;
  573. }
  574. //-----------------------------------------------------------------------
  575. void Camera::setAspectRatio(float r)
  576. {
  577. mAspect = r;
  578. invalidateFrustum();
  579. }
  580. //-----------------------------------------------------------------------
  581. const AABox& Camera::getBoundingBox(void) const
  582. {
  583. return mBoundingBox;
  584. }
  585. // -------------------------------------------------------------------
  586. const Vector3* Camera::getWorldSpaceCorners(void) const
  587. {
  588. updateWorldSpaceCorners();
  589. return mWorldSpaceCorners;
  590. }
  591. //-----------------------------------------------------------------------
  592. void Camera::setProjectionType(ProjectionType pt)
  593. {
  594. mProjType = pt;
  595. invalidateFrustum();
  596. }
  597. //-----------------------------------------------------------------------
  598. ProjectionType Camera::getProjectionType(void) const
  599. {
  600. return mProjType;
  601. }
  602. //---------------------------------------------------------------------
  603. void Camera::setCustomViewMatrix(bool enable, const Matrix4& viewMatrix)
  604. {
  605. mCustomViewMatrix = enable;
  606. if (enable)
  607. {
  608. assert(viewMatrix.isAffine());
  609. mViewMatrix = viewMatrix;
  610. }
  611. }
  612. //---------------------------------------------------------------------
  613. void Camera::setCustomProjectionMatrix(bool enable, const Matrix4& projMatrix)
  614. {
  615. mCustomProjMatrix = enable;
  616. if (enable)
  617. {
  618. mProjMatrix = projMatrix;
  619. }
  620. invalidateFrustum();
  621. }
  622. //---------------------------------------------------------------------
  623. void Camera::setOrthoWindow(float w, float h)
  624. {
  625. mOrthoHeight = h;
  626. mAspect = w / h;
  627. invalidateFrustum();
  628. }
  629. //---------------------------------------------------------------------
  630. void Camera::setOrthoWindowHeight(float h)
  631. {
  632. mOrthoHeight = h;
  633. invalidateFrustum();
  634. }
  635. //---------------------------------------------------------------------
  636. void Camera::setOrthoWindowWidth(float w)
  637. {
  638. mOrthoHeight = w / mAspect;
  639. invalidateFrustum();
  640. }
  641. //---------------------------------------------------------------------
  642. float Camera::getOrthoWindowHeight() const
  643. {
  644. return mOrthoHeight;
  645. }
  646. //---------------------------------------------------------------------
  647. float Camera::getOrthoWindowWidth() const
  648. {
  649. return mOrthoHeight * mAspect;
  650. }
  651. //---------------------------------------------------------------------
  652. void Camera::setFrustumExtents(float left, float right, float top, float bottom)
  653. {
  654. mFrustumExtentsManuallySet = true;
  655. mLeft = left;
  656. mRight = right;
  657. mTop = top;
  658. mBottom = bottom;
  659. invalidateFrustum();
  660. }
  661. //---------------------------------------------------------------------
  662. void Camera::resetFrustumExtents()
  663. {
  664. mFrustumExtentsManuallySet = false;
  665. invalidateFrustum();
  666. }
  667. //---------------------------------------------------------------------
  668. void Camera::getFrustumExtents(float& outleft, float& outright, float& outtop, float& outbottom) const
  669. {
  670. updateFrustum();
  671. outleft = mLeft;
  672. outright = mRight;
  673. outtop = mTop;
  674. outbottom = mBottom;
  675. }
  676. // -------------------------------------------------------------------
  677. void Camera::invalidateFrustum(void) const
  678. {
  679. mRecalcFrustumPlanes = true;
  680. mRecalcWorldSpaceCorners = true;
  681. mRecalcVertexData = true;
  682. }
  683. // -------------------------------------------------------------------
  684. float Camera::getBoundingRadius(void) const
  685. {
  686. // return a little bigger than the near distance
  687. // just to keep things just outside
  688. return mNearDist * 1.5f;
  689. }
  690. RTTITypeBase* Camera::getRTTIStatic()
  691. {
  692. return CameraRTTI::instance();
  693. }
  694. RTTITypeBase* Camera::getRTTI() const
  695. {
  696. return Camera::getRTTIStatic();
  697. }
  698. } // namespace CamelotFramework