BsCamera.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "Renderer/BsCamera.h"
  4. #include "RTTI/BsCameraRTTI.h"
  5. #include "Math/BsMath.h"
  6. #include "Math/BsMatrix3.h"
  7. #include "Math/BsVector2.h"
  8. #include "Math/BsAABox.h"
  9. #include "Math/BsSphere.h"
  10. #include "Error/BsException.h"
  11. #include "RenderAPI/BsRenderAPI.h"
  12. #include "Scene/BsSceneObject.h"
  13. #include "Renderer/BsRendererManager.h"
  14. #include "Renderer/BsRenderer.h"
  15. #include "Allocators/BsFrameAlloc.h"
  16. #include "Scene/BsSceneManager.h"
  17. namespace bs
  18. {
  19. const float CameraBase::INFINITE_FAR_PLANE_ADJUST = 0.00001f;
  20. CameraBase::CameraBase()
  21. : mLayers(0xFFFFFFFFFFFFFFFF), mProjType(PT_PERSPECTIVE), mHorzFOV(Degree(90.0f)), mFarDist(1000.0f)
  22. , mNearDist(0.05f), mAspect(1.33333333333333f), mOrthoHeight(5), mPriority(0), mCustomViewMatrix(false)
  23. , mCustomProjMatrix(false), mMSAA(1), mFrustumExtentsManuallySet(false), mProjMatrixRS(BsZero), mProjMatrix(BsZero)
  24. , mViewMatrix(BsZero), mProjMatrixRSInv(BsZero), mProjMatrixInv(BsZero), mViewMatrixInv(BsZero)
  25. , mRecalcFrustum(true), mRecalcFrustumPlanes(true), mRecalcView(true)
  26. {
  27. mRenderSettings = bs_shared_ptr_new<RenderSettings>();
  28. invalidateFrustum();
  29. }
  30. void CameraBase::setHorzFOV(const Radian& fov)
  31. {
  32. mHorzFOV = fov;
  33. invalidateFrustum();
  34. _markCoreDirty();
  35. }
  36. const Radian& CameraBase::getHorzFOV() const
  37. {
  38. return mHorzFOV;
  39. }
  40. void CameraBase::setFarClipDistance(float farPlane)
  41. {
  42. mFarDist = farPlane;
  43. invalidateFrustum();
  44. _markCoreDirty();
  45. }
  46. float CameraBase::getFarClipDistance() const
  47. {
  48. return mFarDist;
  49. }
  50. void CameraBase::setNearClipDistance(float nearPlane)
  51. {
  52. if (nearPlane <= 0)
  53. {
  54. LOGERR("Near clip distance must be greater than zero.");
  55. return;
  56. }
  57. mNearDist = nearPlane;
  58. invalidateFrustum();
  59. _markCoreDirty();
  60. }
  61. float CameraBase::getNearClipDistance() const
  62. {
  63. return mNearDist;
  64. }
  65. const Matrix4& CameraBase::getProjectionMatrix() const
  66. {
  67. updateFrustum();
  68. return mProjMatrix;
  69. }
  70. const Matrix4& CameraBase::getProjectionMatrixInv() const
  71. {
  72. updateFrustum();
  73. return mProjMatrixInv;
  74. }
  75. const Matrix4& CameraBase::getProjectionMatrixRS() const
  76. {
  77. updateFrustum();
  78. return mProjMatrixRS;
  79. }
  80. const Matrix4& CameraBase::getProjectionMatrixRSInv() const
  81. {
  82. updateFrustum();
  83. return mProjMatrixRSInv;
  84. }
  85. const Matrix4& CameraBase::getViewMatrix() const
  86. {
  87. updateView();
  88. return mViewMatrix;
  89. }
  90. const Matrix4& CameraBase::getViewMatrixInv() const
  91. {
  92. updateView();
  93. return mViewMatrixInv;
  94. }
  95. const ConvexVolume& CameraBase::getFrustum() const
  96. {
  97. // Make any pending updates to the calculated frustum planes
  98. updateFrustumPlanes();
  99. return mFrustum;
  100. }
  101. ConvexVolume CameraBase::getWorldFrustum() const
  102. {
  103. const Vector<Plane>& frustumPlanes = getFrustum().getPlanes();
  104. const Transform& tfrm = getTransform();
  105. Matrix4 worldMatrix;
  106. worldMatrix.setTRS(tfrm.getPosition(), tfrm.getRotation(), Vector3::ONE);
  107. Vector<Plane> worldPlanes(frustumPlanes.size());
  108. UINT32 i = 0;
  109. for (auto& plane : frustumPlanes)
  110. {
  111. worldPlanes[i] = worldMatrix.multiplyAffine(plane);
  112. i++;
  113. }
  114. return ConvexVolume(worldPlanes);
  115. }
  116. void CameraBase::calcProjectionParameters(float& left, float& right, float& bottom, float& top) const
  117. {
  118. if (mCustomProjMatrix)
  119. {
  120. // Convert clipspace corners to camera space
  121. Matrix4 invProj = mProjMatrix.inverse();
  122. Vector3 topLeft(-0.5f, 0.5f, 0.0f);
  123. Vector3 bottomRight(0.5f, -0.5f, 0.0f);
  124. topLeft = invProj.multiply(topLeft);
  125. bottomRight = invProj.multiply(bottomRight);
  126. left = topLeft.x;
  127. top = topLeft.y;
  128. right = bottomRight.x;
  129. bottom = bottomRight.y;
  130. }
  131. else
  132. {
  133. if (mFrustumExtentsManuallySet)
  134. {
  135. left = mLeft;
  136. right = mRight;
  137. top = mTop;
  138. bottom = mBottom;
  139. }
  140. else if (mProjType == PT_PERSPECTIVE)
  141. {
  142. Radian thetaX(mHorzFOV * 0.5f);
  143. float tanThetaX = Math::tan(thetaX);
  144. float tanThetaY = tanThetaX / mAspect;
  145. float half_w = tanThetaX * mNearDist;
  146. float half_h = tanThetaY * mNearDist;
  147. left = -half_w;
  148. right = half_w;
  149. bottom = -half_h;
  150. top = half_h;
  151. mLeft = left;
  152. mRight = right;
  153. mTop = top;
  154. mBottom = bottom;
  155. }
  156. else
  157. {
  158. float half_w = getOrthoWindowWidth() * 0.5f;
  159. float half_h = getOrthoWindowHeight() * 0.5f;
  160. left = -half_w;
  161. right = half_w;
  162. bottom = -half_h;
  163. top = half_h;
  164. mLeft = left;
  165. mRight = right;
  166. mTop = top;
  167. mBottom = bottom;
  168. }
  169. }
  170. }
  171. void CameraBase::updateFrustum() const
  172. {
  173. if (isFrustumOutOfDate())
  174. {
  175. float left, right, bottom, top;
  176. calcProjectionParameters(left, right, bottom, top);
  177. if (!mCustomProjMatrix)
  178. {
  179. float inv_w = 1 / (right - left);
  180. float inv_h = 1 / (top - bottom);
  181. float inv_d = 1 / (mFarDist - mNearDist);
  182. if (mProjType == PT_PERSPECTIVE)
  183. {
  184. float A = 2 * mNearDist * inv_w;
  185. float B = 2 * mNearDist * inv_h;
  186. float C = (right + left) * inv_w;
  187. float D = (top + bottom) * inv_h;
  188. float q, qn;
  189. if (mFarDist == 0)
  190. {
  191. // Infinite far plane
  192. q = CameraBase::INFINITE_FAR_PLANE_ADJUST - 1;
  193. qn = mNearDist * (CameraBase::INFINITE_FAR_PLANE_ADJUST - 2);
  194. }
  195. else
  196. {
  197. q = -(mFarDist + mNearDist) * inv_d;
  198. qn = -2 * (mFarDist * mNearDist) * inv_d;
  199. }
  200. mProjMatrix = Matrix4::ZERO;
  201. mProjMatrix[0][0] = A;
  202. mProjMatrix[0][2] = C;
  203. mProjMatrix[1][1] = B;
  204. mProjMatrix[1][2] = D;
  205. mProjMatrix[2][2] = q;
  206. mProjMatrix[2][3] = qn;
  207. mProjMatrix[3][2] = -1;
  208. }
  209. else if (mProjType == PT_ORTHOGRAPHIC)
  210. {
  211. float A = 2 * inv_w;
  212. float B = 2 * inv_h;
  213. float C = -(right + left) * inv_w;
  214. float D = -(top + bottom) * inv_h;
  215. float q, qn;
  216. if (mFarDist == 0)
  217. {
  218. // Can not do infinite far plane here, avoid divided zero only
  219. q = -CameraBase::INFINITE_FAR_PLANE_ADJUST / mNearDist;
  220. qn = -CameraBase::INFINITE_FAR_PLANE_ADJUST - 1;
  221. }
  222. else
  223. {
  224. q = -2 * inv_d;
  225. qn = -(mFarDist + mNearDist) * inv_d;
  226. }
  227. mProjMatrix = Matrix4::ZERO;
  228. mProjMatrix[0][0] = A;
  229. mProjMatrix[0][3] = C;
  230. mProjMatrix[1][1] = B;
  231. mProjMatrix[1][3] = D;
  232. mProjMatrix[2][2] = q;
  233. mProjMatrix[2][3] = qn;
  234. mProjMatrix[3][3] = 1;
  235. }
  236. }
  237. ct::RenderAPI* renderAPI = ct::RenderAPI::instancePtr();
  238. renderAPI->convertProjectionMatrix(mProjMatrix, mProjMatrixRS);
  239. mProjMatrixInv = mProjMatrix.inverse();
  240. mProjMatrixRSInv = mProjMatrixRS.inverse();
  241. // Calculate bounding box (local)
  242. // Box is from 0, down -Z, max dimensions as determined from far plane
  243. // If infinite view frustum just pick a far value
  244. float farDist = (mFarDist == 0) ? 100000 : mFarDist;
  245. // Near plane bounds
  246. Vector3 min(left, bottom, -farDist);
  247. Vector3 max(right, top, 0);
  248. if (mCustomProjMatrix)
  249. {
  250. // Some custom projection matrices can have unusual inverted settings
  251. // So make sure the AABB is the right way around to start with
  252. Vector3 tmp = min;
  253. min.floor(max);
  254. max.ceil(tmp);
  255. }
  256. if (mProjType == PT_PERSPECTIVE)
  257. {
  258. // Merge with far plane bounds
  259. float radio = farDist / mNearDist;
  260. min.floor(Vector3(left * radio, bottom * radio, -farDist));
  261. max.ceil(Vector3(right * radio, top * radio, 0));
  262. }
  263. mBoundingBox.setExtents(min, max);
  264. mRecalcFrustum = false;
  265. mRecalcFrustumPlanes = true;
  266. }
  267. }
  268. bool CameraBase::isFrustumOutOfDate() const
  269. {
  270. return mRecalcFrustum;
  271. }
  272. void CameraBase::updateView() const
  273. {
  274. if (!mCustomViewMatrix && mRecalcView)
  275. {
  276. mViewMatrix.makeView(mTransform.getPosition(), mTransform.getRotation());
  277. mViewMatrixInv = mViewMatrix.inverseAffine();
  278. mRecalcView = false;
  279. }
  280. }
  281. void CameraBase::updateFrustumPlanes() const
  282. {
  283. updateFrustum();
  284. if (mRecalcFrustumPlanes)
  285. {
  286. mFrustum = ConvexVolume(mProjMatrix);
  287. mRecalcFrustumPlanes = false;
  288. }
  289. }
  290. float CameraBase::getAspectRatio() const
  291. {
  292. return mAspect;
  293. }
  294. void CameraBase::setAspectRatio(float r)
  295. {
  296. mAspect = r;
  297. invalidateFrustum();
  298. _markCoreDirty();
  299. }
  300. const AABox& CameraBase::getBoundingBox() const
  301. {
  302. updateFrustum();
  303. return mBoundingBox;
  304. }
  305. void CameraBase::setProjectionType(ProjectionType pt)
  306. {
  307. mProjType = pt;
  308. invalidateFrustum();
  309. _markCoreDirty();
  310. }
  311. ProjectionType CameraBase::getProjectionType() const
  312. {
  313. return mProjType;
  314. }
  315. void CameraBase::setCustomViewMatrix(bool enable, const Matrix4& viewMatrix)
  316. {
  317. mCustomViewMatrix = enable;
  318. if (enable)
  319. {
  320. BS_ASSERT(viewMatrix.isAffine());
  321. mViewMatrix = viewMatrix;
  322. mViewMatrixInv = mViewMatrix.inverseAffine();
  323. }
  324. _markCoreDirty();
  325. }
  326. void CameraBase::setCustomProjectionMatrix(bool enable, const Matrix4& projMatrix)
  327. {
  328. mCustomProjMatrix = enable;
  329. if (enable)
  330. mProjMatrix = projMatrix;
  331. invalidateFrustum();
  332. _markCoreDirty();
  333. }
  334. void CameraBase::setOrthoWindow(float w, float h)
  335. {
  336. mOrthoHeight = h;
  337. mAspect = w / h;
  338. invalidateFrustum();
  339. _markCoreDirty();
  340. }
  341. void CameraBase::setOrthoWindowHeight(float h)
  342. {
  343. mOrthoHeight = h;
  344. invalidateFrustum();
  345. _markCoreDirty();
  346. }
  347. void CameraBase::setOrthoWindowWidth(float w)
  348. {
  349. mOrthoHeight = w / mAspect;
  350. invalidateFrustum();
  351. _markCoreDirty();
  352. }
  353. float CameraBase::getOrthoWindowHeight() const
  354. {
  355. return mOrthoHeight;
  356. }
  357. float CameraBase::getOrthoWindowWidth() const
  358. {
  359. return mOrthoHeight * mAspect;
  360. }
  361. void CameraBase::setFrustumExtents(float left, float right, float top, float bottom)
  362. {
  363. mFrustumExtentsManuallySet = true;
  364. mLeft = left;
  365. mRight = right;
  366. mTop = top;
  367. mBottom = bottom;
  368. invalidateFrustum();
  369. _markCoreDirty();
  370. }
  371. void CameraBase::resetFrustumExtents()
  372. {
  373. mFrustumExtentsManuallySet = false;
  374. invalidateFrustum();
  375. _markCoreDirty();
  376. }
  377. void CameraBase::getFrustumExtents(float& outleft, float& outright, float& outtop, float& outbottom) const
  378. {
  379. updateFrustum();
  380. outleft = mLeft;
  381. outright = mRight;
  382. outtop = mTop;
  383. outbottom = mBottom;
  384. }
  385. void CameraBase::setTransform(const Transform& transform)
  386. {
  387. SceneActor::setTransform(transform);
  388. mRecalcView = true;
  389. }
  390. void CameraBase::invalidateFrustum() const
  391. {
  392. mRecalcFrustum = true;
  393. mRecalcFrustumPlanes = true;
  394. }
  395. Vector2I CameraBase::worldToScreenPoint(const Vector3& worldPoint) const
  396. {
  397. Vector2 ndcPoint = worldToNdcPoint(worldPoint);
  398. return ndcToScreenPoint(ndcPoint);
  399. }
  400. Vector2 CameraBase::worldToNdcPoint(const Vector3& worldPoint) const
  401. {
  402. Vector3 viewPoint = worldToViewPoint(worldPoint);
  403. return viewToNdcPoint(viewPoint);
  404. }
  405. Vector3 CameraBase::worldToViewPoint(const Vector3& worldPoint) const
  406. {
  407. return getViewMatrix().multiplyAffine(worldPoint);
  408. }
  409. Vector3 CameraBase::screenToWorldPoint(const Vector2I& screenPoint, float depth) const
  410. {
  411. Vector2 ndcPoint = screenToNdcPoint(screenPoint);
  412. return ndcToWorldPoint(ndcPoint, depth);
  413. }
  414. Vector3 CameraBase::screenToWorldPointDeviceDepth(const Vector2I& screenPoint, float deviceDepth) const
  415. {
  416. Vector2 ndcPoint = screenToNdcPoint(screenPoint);
  417. Vector4 worldPoint(ndcPoint.x, ndcPoint.y, deviceDepth, 1.0f);
  418. worldPoint = getProjectionMatrixRS().inverse().multiply(worldPoint);
  419. Vector3 worldPoint3D;
  420. if (Math::abs(worldPoint.w) > 1e-7f)
  421. {
  422. float invW = 1.0f / worldPoint.w;
  423. worldPoint3D.x = worldPoint.x * invW;
  424. worldPoint3D.y = worldPoint.y * invW;
  425. worldPoint3D.z = worldPoint.z * invW;
  426. }
  427. return viewToWorldPoint(worldPoint3D);
  428. }
  429. Vector3 CameraBase::screenToViewPoint(const Vector2I& screenPoint, float depth) const
  430. {
  431. Vector2 ndcPoint = screenToNdcPoint(screenPoint);
  432. return ndcToViewPoint(ndcPoint, depth);
  433. }
  434. Vector2 CameraBase::screenToNdcPoint(const Vector2I& screenPoint) const
  435. {
  436. Rect2I viewport = getViewportRect();
  437. Vector2 ndcPoint;
  438. ndcPoint.x = (float)(((screenPoint.x - viewport.x) / (float)viewport.width) * 2.0f - 1.0f);
  439. const RenderAPIInfo& info = RenderAPI::getAPIInfo();
  440. if(info.isFlagSet(RenderAPIFeatureFlag::NDCYAxisDown))
  441. ndcPoint.y = (float)(((screenPoint.y - viewport.y) / (float)viewport.height) * 2.0f - 1.0f);
  442. else
  443. ndcPoint.y = (float)((1.0f - ((screenPoint.y - viewport.y) / (float)viewport.height)) * 2.0f - 1.0f);
  444. return ndcPoint;
  445. }
  446. Vector3 CameraBase::viewToWorldPoint(const Vector3& viewPoint) const
  447. {
  448. return getViewMatrix().inverseAffine().multiplyAffine(viewPoint);
  449. }
  450. Vector2I CameraBase::viewToScreenPoint(const Vector3& viewPoint) const
  451. {
  452. Vector2 ndcPoint = viewToNdcPoint(viewPoint);
  453. return ndcToScreenPoint(ndcPoint);
  454. }
  455. Vector2 CameraBase::viewToNdcPoint(const Vector3& viewPoint) const
  456. {
  457. Vector3 projPoint = projectPoint(viewPoint);
  458. return Vector2(projPoint.x, projPoint.y);
  459. }
  460. Vector3 CameraBase::ndcToWorldPoint(const Vector2& ndcPoint, float depth) const
  461. {
  462. Vector3 viewPoint = ndcToViewPoint(ndcPoint, depth);
  463. return viewToWorldPoint(viewPoint);
  464. }
  465. Vector3 CameraBase::ndcToViewPoint(const Vector2& ndcPoint, float depth) const
  466. {
  467. return unprojectPoint(Vector3(ndcPoint.x, ndcPoint.y, depth));
  468. }
  469. Vector2I CameraBase::ndcToScreenPoint(const Vector2& ndcPoint) const
  470. {
  471. Rect2I viewport = getViewportRect();
  472. Vector2I screenPoint;
  473. screenPoint.x = Math::roundToInt(viewport.x + ((ndcPoint.x + 1.0f) * 0.5f) * viewport.width);
  474. screenPoint.y = Math::roundToInt(viewport.y + (1.0f - (ndcPoint.y + 1.0f) * 0.5f) * viewport.height);
  475. return screenPoint;
  476. }
  477. Ray CameraBase::screenPointToRay(const Vector2I& screenPoint) const
  478. {
  479. Vector2 ndcPoint = screenToNdcPoint(screenPoint);
  480. Vector3 near = unprojectPoint(Vector3(ndcPoint.x, ndcPoint.y, mNearDist));
  481. Vector3 far = unprojectPoint(Vector3(ndcPoint.x, ndcPoint.y, mNearDist + 1.0f));
  482. Ray ray(near, Vector3::normalize(far - near));
  483. ray.transformAffine(getViewMatrix().inverseAffine());
  484. return ray;
  485. }
  486. Vector3 CameraBase::projectPoint(const Vector3& point) const
  487. {
  488. Vector4 projPoint4(point.x, point.y, point.z, 1.0f);
  489. projPoint4 = getProjectionMatrixRS().multiply(projPoint4);
  490. if (Math::abs(projPoint4.w) > 1e-7f)
  491. {
  492. float invW = 1.0f / projPoint4.w;
  493. projPoint4.x *= invW;
  494. projPoint4.y *= invW;
  495. projPoint4.z *= invW;
  496. }
  497. else
  498. {
  499. projPoint4.x = 0.0f;
  500. projPoint4.y = 0.0f;
  501. projPoint4.z = 0.0f;
  502. }
  503. return Vector3(projPoint4.x, projPoint4.y, projPoint4.z);
  504. }
  505. Vector3 CameraBase::unprojectPoint(const Vector3& point) const
  506. {
  507. // Point.z is expected to be in view space, so we need to do some extra work to get the proper coordinates
  508. // (as opposed to if point.z was in device coordinates, in which case we could just inverse project)
  509. // Get world position for a point near the far plane (0.95f)
  510. Vector4 farAwayPoint(point.x, point.y, 0.95f, 1.0f);
  511. farAwayPoint = getProjectionMatrixRS().inverse().multiply(farAwayPoint);
  512. // Can't proceed if w is too small
  513. if (Math::abs(farAwayPoint.w) > 1e-7f)
  514. {
  515. // Perspective divide, to get the values that make sense in 3D space
  516. float invW = 1.0f / farAwayPoint.w;
  517. Vector3 farAwayPoint3D;
  518. farAwayPoint3D.x = farAwayPoint.x * invW;
  519. farAwayPoint3D.y = farAwayPoint.y * invW;
  520. farAwayPoint3D.z = farAwayPoint.z * invW;
  521. // Find the distance to the far point along the camera's viewing axis
  522. float distAlongZ = farAwayPoint3D.dot(-Vector3::UNIT_Z);
  523. // Do nothing if point is behind the camera
  524. if (distAlongZ >= 0.0f)
  525. {
  526. if (mProjType == PT_PERSPECTIVE)
  527. {
  528. // Direction from origin to our point
  529. Vector3 dir = farAwayPoint3D; // Camera is at (0, 0, 0) so it's the same vector
  530. // Our view space depth (point.z) is distance along the camera's viewing axis. Since our direction
  531. // vector is not parallel to the viewing axis, instead of normalizing it with its own length, we
  532. // "normalize" with the length projected along the camera's viewing axis.
  533. dir /= distAlongZ;
  534. // And now we just find the final position along the direction
  535. return dir * point.z;
  536. }
  537. else // Ortographic
  538. {
  539. // Depth difference between our arbitrary point and actual depth
  540. float depthDiff = distAlongZ - point.z;
  541. // Depth difference along viewing direction
  542. Vector3 depthDiffVec = depthDiff * -Vector3::UNIT_Z;
  543. // Return point that is depthDiff closer than our arbitrary point
  544. return farAwayPoint3D - depthDiffVec;
  545. }
  546. }
  547. }
  548. return Vector3(0.0f, 0.0f, 0.0f);
  549. }
  550. Camera::Camera(SPtr<RenderTarget> target, float left, float top, float width, float height)
  551. :mMain(false)
  552. {
  553. if (target != nullptr)
  554. target->blockUntilCoreInitialized();
  555. mViewport = Viewport::create(target, left, top, width, height);
  556. }
  557. SPtr<ct::Camera> Camera::getCore() const
  558. {
  559. return std::static_pointer_cast<ct::Camera>(mCoreSpecific);
  560. }
  561. SPtr<Camera> Camera::create(SPtr<RenderTarget> target, float left, float top, float width, float height)
  562. {
  563. Camera* handler = new (bs_alloc<Camera>()) Camera(target, left, top, width, height);
  564. SPtr<Camera> handlerPtr = bs_core_ptr<Camera>(handler);
  565. handlerPtr->_setThisPtr(handlerPtr);
  566. handlerPtr->initialize();
  567. return handlerPtr;
  568. }
  569. SPtr<Camera> Camera::createEmpty()
  570. {
  571. Camera* handler = new (bs_alloc<Camera>()) Camera();
  572. SPtr<Camera> handlerPtr = bs_core_ptr<Camera>(handler);
  573. handlerPtr->_setThisPtr(handlerPtr);
  574. return handlerPtr;
  575. }
  576. SPtr<ct::CoreObject> Camera::createCore() const
  577. {
  578. ct::Camera* handler = new (bs_alloc<ct::Camera>()) ct::Camera(mViewport->getCore());
  579. SPtr<ct::Camera> handlerPtr = bs_shared_ptr<ct::Camera>(handler);
  580. handlerPtr->_setThisPtr(handlerPtr);
  581. return handlerPtr;
  582. }
  583. void Camera::initialize()
  584. {
  585. CoreObject::initialize();
  586. gSceneManager()._registerCamera(std::static_pointer_cast<Camera>(getThisPtr()));
  587. }
  588. void Camera::destroy()
  589. {
  590. gSceneManager()._unregisterCamera(std::static_pointer_cast<Camera>(getThisPtr()));
  591. CoreObject::destroy();
  592. }
  593. Rect2I Camera::getViewportRect() const
  594. {
  595. return mViewport->getPixelArea();
  596. }
  597. CoreSyncData Camera::syncToCore(FrameAlloc* allocator)
  598. {
  599. UINT32 dirtyFlag = getCoreDirtyFlags();
  600. UINT32 size = getActorSyncDataSize();
  601. size += rttiGetElemSize(dirtyFlag);
  602. UINT32 ppSize = 0;
  603. if (dirtyFlag != (UINT32)ActorDirtyFlag::Transform)
  604. {
  605. size += rttiGetElemSize(mLayers);
  606. size += rttiGetElemSize(mProjType);
  607. size += rttiGetElemSize(mHorzFOV);
  608. size += rttiGetElemSize(mFarDist);
  609. size += rttiGetElemSize(mNearDist);
  610. size += rttiGetElemSize(mAspect);
  611. size += rttiGetElemSize(mOrthoHeight);
  612. size += rttiGetElemSize(mPriority);
  613. size += rttiGetElemSize(mCustomViewMatrix);
  614. size += rttiGetElemSize(mCustomProjMatrix);
  615. size += rttiGetElemSize(mFrustumExtentsManuallySet);
  616. size += rttiGetElemSize(mMSAA);
  617. size += sizeof(UINT32);
  618. if(mRenderSettings != nullptr)
  619. {
  620. mRenderSettings->_getSyncData(nullptr, ppSize);
  621. size += ppSize;
  622. }
  623. }
  624. UINT8* buffer = allocator->alloc(size);
  625. char* dataPtr = (char*)buffer;
  626. dataPtr = syncActorTo(dataPtr);
  627. dataPtr = rttiWriteElem(dirtyFlag, dataPtr);
  628. if (dirtyFlag != (UINT32)ActorDirtyFlag::Transform)
  629. {
  630. dataPtr = rttiWriteElem(mLayers, dataPtr);
  631. dataPtr = rttiWriteElem(mProjType, dataPtr);
  632. dataPtr = rttiWriteElem(mHorzFOV, dataPtr);
  633. dataPtr = rttiWriteElem(mFarDist, dataPtr);
  634. dataPtr = rttiWriteElem(mNearDist, dataPtr);
  635. dataPtr = rttiWriteElem(mAspect, dataPtr);
  636. dataPtr = rttiWriteElem(mOrthoHeight, dataPtr);
  637. dataPtr = rttiWriteElem(mPriority, dataPtr);
  638. dataPtr = rttiWriteElem(mCustomViewMatrix, dataPtr);
  639. dataPtr = rttiWriteElem(mCustomProjMatrix, dataPtr);
  640. dataPtr = rttiWriteElem(mFrustumExtentsManuallySet, dataPtr);
  641. dataPtr = rttiWriteElem(mMSAA, dataPtr);
  642. dataPtr = rttiWriteElem(ppSize, dataPtr);
  643. if(mRenderSettings != nullptr)
  644. mRenderSettings->_getSyncData((UINT8*)dataPtr, ppSize);
  645. dataPtr += ppSize;
  646. }
  647. return CoreSyncData(buffer, size);
  648. }
  649. void Camera::getCoreDependencies(Vector<CoreObject*>& dependencies)
  650. {
  651. dependencies.push_back(mViewport.get());
  652. }
  653. void Camera::_markCoreDirty(ActorDirtyFlag flag)
  654. {
  655. markCoreDirty((UINT32)flag);
  656. }
  657. RTTITypeBase* Camera::getRTTIStatic()
  658. {
  659. return CameraRTTI::instance();
  660. }
  661. RTTITypeBase* Camera::getRTTI() const
  662. {
  663. return Camera::getRTTIStatic();
  664. }
  665. namespace ct
  666. {
  667. Camera::~Camera()
  668. {
  669. RendererManager::instance().getActive()->notifyCameraRemoved(this);
  670. }
  671. Camera::Camera(SPtr<RenderTarget> target, float left, float top, float width, float height)
  672. : mRendererId(0)
  673. {
  674. mViewport = Viewport::create(target, left, top, width, height);
  675. }
  676. Camera::Camera(const SPtr<Viewport>& viewport)
  677. : mRendererId(0)
  678. {
  679. mViewport = viewport;
  680. }
  681. void Camera::initialize()
  682. {
  683. RendererManager::instance().getActive()->notifyCameraAdded(this);
  684. CoreObject::initialize();
  685. }
  686. Rect2I Camera::getViewportRect() const
  687. {
  688. return mViewport->getPixelArea();
  689. }
  690. void Camera::syncToCore(const CoreSyncData& data)
  691. {
  692. char* dataPtr = (char*)data.getBuffer();
  693. UINT32 dirtyFlag;
  694. dataPtr = syncActorFrom(dataPtr);
  695. dataPtr = rttiReadElem(dirtyFlag, dataPtr);
  696. mRecalcFrustum = true;
  697. mRecalcFrustumPlanes = true;
  698. mRecalcView = true;
  699. if (dirtyFlag != (UINT32)ActorDirtyFlag::Transform)
  700. {
  701. dataPtr = rttiReadElem(mLayers, dataPtr);
  702. dataPtr = rttiReadElem(mProjType, dataPtr);
  703. dataPtr = rttiReadElem(mHorzFOV, dataPtr);
  704. dataPtr = rttiReadElem(mFarDist, dataPtr);
  705. dataPtr = rttiReadElem(mNearDist, dataPtr);
  706. dataPtr = rttiReadElem(mAspect, dataPtr);
  707. dataPtr = rttiReadElem(mOrthoHeight, dataPtr);
  708. dataPtr = rttiReadElem(mPriority, dataPtr);
  709. dataPtr = rttiReadElem(mCustomViewMatrix, dataPtr);
  710. dataPtr = rttiReadElem(mCustomProjMatrix, dataPtr);
  711. dataPtr = rttiReadElem(mFrustumExtentsManuallySet, dataPtr);
  712. dataPtr = rttiReadElem(mMSAA, dataPtr);
  713. UINT32 ppSize = 0;
  714. dataPtr = rttiReadElem(ppSize, dataPtr);
  715. if(ppSize > 0)
  716. {
  717. if (mRenderSettings == nullptr)
  718. mRenderSettings = bs_shared_ptr_new<RenderSettings>();
  719. mRenderSettings->_setSyncData((UINT8*)dataPtr, ppSize);
  720. dataPtr += ppSize;
  721. }
  722. }
  723. RendererManager::instance().getActive()->notifyCameraUpdated(this, (UINT32)dirtyFlag);
  724. }
  725. }
  726. }