BsCameraHandler.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831
  1. #include "BsCameraHandler.h"
  2. #include "BsCameraHandlerRTTI.h"
  3. #include "BsMath.h"
  4. #include "BsMatrix3.h"
  5. #include "BsVector2.h"
  6. #include "BsAABox.h"
  7. #include "BsSphere.h"
  8. #include "BsException.h"
  9. #include "BsRenderAPI.h"
  10. #include "BsSceneObject.h"
  11. #include "BsDebug.h"
  12. #include "BsRendererManager.h"
  13. #include "BsCoreRenderer.h"
  14. #include "BsFrameAlloc.h"
  15. namespace BansheeEngine
  16. {
  17. const float CameraHandlerBase::INFINITE_FAR_PLANE_ADJUST = 0.00001f;
  18. CameraHandlerBase::CameraHandlerBase(RenderTargetPtr target, float left, float top, float width, float height)
  19. :mProjType(PT_PERSPECTIVE), mHorzFOV(Radian(Math::PI / 4.0f)), mFarDist(1000.0f),
  20. mNearDist(0.05f), mAspect(1.33333333333333f), mOrthoHeight(1000), mRecalcFrustum(true), mRecalcFrustumPlanes(true),
  21. mCustomViewMatrix(false), mCustomProjMatrix(false), mFrustumExtentsManuallySet(false), mIgnoreSceneRenderables(false),
  22. mPriority(0), mLayers(0xFFFFFFFFFFFFFFFF), mRecalcView(true)
  23. {
  24. mViewMatrix = Matrix4::ZERO;
  25. mProjMatrixRS = Matrix4::ZERO;
  26. mViewMatrixInv = Matrix4::ZERO;
  27. mProjMatrixRSInv = Matrix4::ZERO;
  28. mProjMatrixInv = Matrix4::ZERO;
  29. invalidateFrustum();
  30. }
  31. void CameraHandlerBase::setHorzFOV(const Radian& fov)
  32. {
  33. mHorzFOV = fov;
  34. invalidateFrustum();
  35. _markCoreDirty();
  36. }
  37. const Radian& CameraHandlerBase::getHorzFOV() const
  38. {
  39. return mHorzFOV;
  40. }
  41. void CameraHandlerBase::setFarClipDistance(float farPlane)
  42. {
  43. mFarDist = farPlane;
  44. invalidateFrustum();
  45. _markCoreDirty();
  46. }
  47. float CameraHandlerBase::getFarClipDistance() const
  48. {
  49. return mFarDist;
  50. }
  51. void CameraHandlerBase::setNearClipDistance(float nearPlane)
  52. {
  53. if (nearPlane <= 0)
  54. {
  55. BS_EXCEPT(InvalidParametersException, "Near clip distance must be greater than zero.");
  56. }
  57. mNearDist = nearPlane;
  58. invalidateFrustum();
  59. _markCoreDirty();
  60. }
  61. float CameraHandlerBase::getNearClipDistance() const
  62. {
  63. return mNearDist;
  64. }
  65. const Matrix4& CameraHandlerBase::getProjectionMatrix() const
  66. {
  67. updateFrustum();
  68. return mProjMatrix;
  69. }
  70. const Matrix4& CameraHandlerBase::getProjectionMatrixInv() const
  71. {
  72. updateFrustum();
  73. return mProjMatrixInv;
  74. }
  75. const Matrix4& CameraHandlerBase::getProjectionMatrixRS() const
  76. {
  77. updateFrustum();
  78. return mProjMatrixRS;
  79. }
  80. const Matrix4& CameraHandlerBase::getProjectionMatrixRSInv() const
  81. {
  82. updateFrustum();
  83. return mProjMatrixRSInv;
  84. }
  85. const Matrix4& CameraHandlerBase::getViewMatrix() const
  86. {
  87. updateView();
  88. return mViewMatrix;
  89. }
  90. const Matrix4& CameraHandlerBase::getViewMatrixInv() const
  91. {
  92. updateView();
  93. return mViewMatrixInv;
  94. }
  95. const ConvexVolume& CameraHandlerBase::getFrustum() const
  96. {
  97. // Make any pending updates to the calculated frustum planes
  98. updateFrustumPlanes();
  99. return mFrustum;
  100. }
  101. ConvexVolume CameraHandlerBase::getWorldFrustum() const
  102. {
  103. const Vector<Plane>& frustumPlanes = getFrustum().getPlanes();
  104. Matrix4 worldMatrix;
  105. worldMatrix.setTRS(mPosition, mRotation, Vector3::ONE);
  106. Vector<Plane> worldPlanes(frustumPlanes.size());
  107. UINT32 i = 0;
  108. for (auto& plane : frustumPlanes)
  109. {
  110. worldPlanes[i] = worldMatrix.multiplyAffine(plane);
  111. i++;
  112. }
  113. return ConvexVolume(worldPlanes);
  114. }
  115. void CameraHandlerBase::calcProjectionParameters(float& left, float& right, float& bottom, float& top) const
  116. {
  117. if (mCustomProjMatrix)
  118. {
  119. // Convert clipspace corners to camera space
  120. Matrix4 invProj = mProjMatrix.inverse();
  121. Vector3 topLeft(-0.5f, 0.5f, 0.0f);
  122. Vector3 bottomRight(0.5f, -0.5f, 0.0f);
  123. topLeft = invProj.multiply(topLeft);
  124. bottomRight = invProj.multiply(bottomRight);
  125. left = topLeft.x;
  126. top = topLeft.y;
  127. right = bottomRight.x;
  128. bottom = bottomRight.y;
  129. }
  130. else
  131. {
  132. if (mFrustumExtentsManuallySet)
  133. {
  134. left = mLeft;
  135. right = mRight;
  136. top = mTop;
  137. bottom = mBottom;
  138. }
  139. else if (mProjType == PT_PERSPECTIVE)
  140. {
  141. Radian thetaY(mHorzFOV * 0.5f);
  142. float tanThetaY = Math::tan(thetaY);
  143. float tanThetaX = tanThetaY * mAspect;
  144. float half_w = tanThetaX * mNearDist;
  145. float half_h = tanThetaY * mNearDist;
  146. left = -half_w;
  147. right = half_w;
  148. bottom = -half_h;
  149. top = half_h;
  150. mLeft = left;
  151. mRight = right;
  152. mTop = top;
  153. mBottom = bottom;
  154. }
  155. else
  156. {
  157. float half_w = getOrthoWindowWidth() * 0.5f;
  158. float half_h = getOrthoWindowHeight() * 0.5f;
  159. left = -half_w;
  160. right = half_w;
  161. bottom = -half_h;
  162. top = half_h;
  163. mLeft = left;
  164. mRight = right;
  165. mTop = top;
  166. mBottom = bottom;
  167. }
  168. }
  169. }
  170. void CameraHandlerBase::updateFrustum() const
  171. {
  172. if (isFrustumOutOfDate())
  173. {
  174. float left, right, bottom, top;
  175. calcProjectionParameters(left, right, bottom, top);
  176. if (!mCustomProjMatrix)
  177. {
  178. float inv_w = 1 / (right - left);
  179. float inv_h = 1 / (top - bottom);
  180. float inv_d = 1 / (mFarDist - mNearDist);
  181. if (mProjType == PT_PERSPECTIVE)
  182. {
  183. float A = 2 * mNearDist * inv_w;
  184. float B = 2 * mNearDist * inv_h;
  185. float C = (right + left) * inv_w;
  186. float D = (top + bottom) * inv_h;
  187. float q, qn;
  188. if (mFarDist == 0)
  189. {
  190. // Infinite far plane
  191. q = CameraHandlerBase::INFINITE_FAR_PLANE_ADJUST - 1;
  192. qn = mNearDist * (CameraHandlerBase::INFINITE_FAR_PLANE_ADJUST - 2);
  193. }
  194. else
  195. {
  196. q = -(mFarDist + mNearDist) * inv_d;
  197. qn = -2 * (mFarDist * mNearDist) * inv_d;
  198. }
  199. mProjMatrix = Matrix4::ZERO;
  200. mProjMatrix[0][0] = A;
  201. mProjMatrix[0][2] = C;
  202. mProjMatrix[1][1] = B;
  203. mProjMatrix[1][2] = D;
  204. mProjMatrix[2][2] = q;
  205. mProjMatrix[2][3] = qn;
  206. mProjMatrix[3][2] = -1;
  207. }
  208. else if (mProjType == PT_ORTHOGRAPHIC)
  209. {
  210. float A = 2 * inv_w;
  211. float B = 2 * inv_h;
  212. float C = -(right + left) * inv_w;
  213. float D = -(top + bottom) * inv_h;
  214. float q, qn;
  215. if (mFarDist == 0)
  216. {
  217. // Can not do infinite far plane here, avoid divided zero only
  218. q = -CameraHandlerBase::INFINITE_FAR_PLANE_ADJUST / mNearDist;
  219. qn = -CameraHandlerBase::INFINITE_FAR_PLANE_ADJUST - 1;
  220. }
  221. else
  222. {
  223. q = -2 * inv_d;
  224. qn = -(mFarDist + mNearDist) * inv_d;
  225. }
  226. mProjMatrix = Matrix4::ZERO;
  227. mProjMatrix[0][0] = A;
  228. mProjMatrix[0][3] = C;
  229. mProjMatrix[1][1] = B;
  230. mProjMatrix[1][3] = D;
  231. mProjMatrix[2][2] = q;
  232. mProjMatrix[2][3] = qn;
  233. mProjMatrix[3][3] = 1;
  234. }
  235. }
  236. RenderAPICore* renderSystem = BansheeEngine::RenderAPICore::instancePtr();
  237. renderSystem->convertProjectionMatrix(mProjMatrix, mProjMatrixRS);
  238. mProjMatrixInv = mProjMatrix.inverse();
  239. mProjMatrixRSInv = mProjMatrixRS.inverse();
  240. // Calculate bounding box (local)
  241. // Box is from 0, down -Z, max dimensions as determined from far plane
  242. // If infinite view frustum just pick a far value
  243. float farDist = (mFarDist == 0) ? 100000 : mFarDist;
  244. // Near plane bounds
  245. Vector3 min(left, bottom, -farDist);
  246. Vector3 max(right, top, 0);
  247. if (mCustomProjMatrix)
  248. {
  249. // Some custom projection matrices can have unusual inverted settings
  250. // So make sure the AABB is the right way around to start with
  251. Vector3 tmp = min;
  252. min.floor(max);
  253. max.ceil(tmp);
  254. }
  255. if (mProjType == PT_PERSPECTIVE)
  256. {
  257. // Merge with far plane bounds
  258. float radio = farDist / mNearDist;
  259. min.floor(Vector3(left * radio, bottom * radio, -farDist));
  260. max.ceil(Vector3(right * radio, top * radio, 0));
  261. }
  262. mBoundingBox.setExtents(min, max);
  263. mRecalcFrustum = false;
  264. mRecalcFrustumPlanes = true;
  265. }
  266. }
  267. bool CameraHandlerBase::isFrustumOutOfDate() const
  268. {
  269. return mRecalcFrustum;
  270. }
  271. void CameraHandlerBase::updateView() const
  272. {
  273. if (!mCustomViewMatrix && mRecalcView)
  274. {
  275. mViewMatrix.makeView(mPosition, mRotation);
  276. mViewMatrixInv = mViewMatrix.inverseAffine();
  277. mRecalcView = false;
  278. }
  279. }
  280. void CameraHandlerBase::updateFrustumPlanes() const
  281. {
  282. updateFrustum();
  283. if (mRecalcFrustumPlanes)
  284. {
  285. Vector<Plane> frustumPlanes(6);
  286. Matrix4 combo = mProjMatrix;
  287. frustumPlanes[FRUSTUM_PLANE_LEFT].normal.x = combo[3][0] + combo[0][0];
  288. frustumPlanes[FRUSTUM_PLANE_LEFT].normal.y = combo[3][1] + combo[0][1];
  289. frustumPlanes[FRUSTUM_PLANE_LEFT].normal.z = combo[3][2] + combo[0][2];
  290. frustumPlanes[FRUSTUM_PLANE_LEFT].d = combo[3][3] + combo[0][3];
  291. frustumPlanes[FRUSTUM_PLANE_RIGHT].normal.x = combo[3][0] - combo[0][0];
  292. frustumPlanes[FRUSTUM_PLANE_RIGHT].normal.y = combo[3][1] - combo[0][1];
  293. frustumPlanes[FRUSTUM_PLANE_RIGHT].normal.z = combo[3][2] - combo[0][2];
  294. frustumPlanes[FRUSTUM_PLANE_RIGHT].d = combo[3][3] - combo[0][3];
  295. frustumPlanes[FRUSTUM_PLANE_TOP].normal.x = combo[3][0] - combo[1][0];
  296. frustumPlanes[FRUSTUM_PLANE_TOP].normal.y = combo[3][1] - combo[1][1];
  297. frustumPlanes[FRUSTUM_PLANE_TOP].normal.z = combo[3][2] - combo[1][2];
  298. frustumPlanes[FRUSTUM_PLANE_TOP].d = combo[3][3] - combo[1][3];
  299. frustumPlanes[FRUSTUM_PLANE_BOTTOM].normal.x = combo[3][0] + combo[1][0];
  300. frustumPlanes[FRUSTUM_PLANE_BOTTOM].normal.y = combo[3][1] + combo[1][1];
  301. frustumPlanes[FRUSTUM_PLANE_BOTTOM].normal.z = combo[3][2] + combo[1][2];
  302. frustumPlanes[FRUSTUM_PLANE_BOTTOM].d = combo[3][3] + combo[1][3];
  303. frustumPlanes[FRUSTUM_PLANE_NEAR].normal.x = combo[3][0] + combo[2][0];
  304. frustumPlanes[FRUSTUM_PLANE_NEAR].normal.y = combo[3][1] + combo[2][1];
  305. frustumPlanes[FRUSTUM_PLANE_NEAR].normal.z = combo[3][2] + combo[2][2];
  306. frustumPlanes[FRUSTUM_PLANE_NEAR].d = combo[3][3] + combo[2][3];
  307. frustumPlanes[FRUSTUM_PLANE_FAR].normal.x = combo[3][0] - combo[2][0];
  308. frustumPlanes[FRUSTUM_PLANE_FAR].normal.y = combo[3][1] - combo[2][1];
  309. frustumPlanes[FRUSTUM_PLANE_FAR].normal.z = combo[3][2] - combo[2][2];
  310. frustumPlanes[FRUSTUM_PLANE_FAR].d = combo[3][3] - combo[2][3];
  311. for (UINT32 i = 0; i < 6; i++)
  312. {
  313. float length = frustumPlanes[i].normal.normalize();
  314. frustumPlanes[i].d /= -length;
  315. }
  316. mFrustum = ConvexVolume(frustumPlanes);
  317. mRecalcFrustumPlanes = false;
  318. }
  319. }
  320. float CameraHandlerBase::getAspectRatio(void) const
  321. {
  322. return mAspect;
  323. }
  324. void CameraHandlerBase::setAspectRatio(float r)
  325. {
  326. mAspect = r;
  327. invalidateFrustum();
  328. _markCoreDirty();
  329. }
  330. const AABox& CameraHandlerBase::getBoundingBox() const
  331. {
  332. updateFrustum();
  333. return mBoundingBox;
  334. }
  335. void CameraHandlerBase::setProjectionType(ProjectionType pt)
  336. {
  337. mProjType = pt;
  338. invalidateFrustum();
  339. _markCoreDirty();
  340. }
  341. ProjectionType CameraHandlerBase::getProjectionType() const
  342. {
  343. return mProjType;
  344. }
  345. void CameraHandlerBase::setCustomViewMatrix(bool enable, const Matrix4& viewMatrix)
  346. {
  347. mCustomViewMatrix = enable;
  348. if (enable)
  349. {
  350. assert(viewMatrix.isAffine());
  351. mViewMatrix = viewMatrix;
  352. mViewMatrixInv = mViewMatrix.inverseAffine();
  353. }
  354. _markCoreDirty();
  355. }
  356. void CameraHandlerBase::setCustomProjectionMatrix(bool enable, const Matrix4& projMatrix)
  357. {
  358. mCustomProjMatrix = enable;
  359. if (enable)
  360. mProjMatrix = projMatrix;
  361. invalidateFrustum();
  362. _markCoreDirty();
  363. }
  364. void CameraHandlerBase::setOrthoWindow(float w, float h)
  365. {
  366. mOrthoHeight = h;
  367. mAspect = w / h;
  368. invalidateFrustum();
  369. _markCoreDirty();
  370. }
  371. void CameraHandlerBase::setOrthoWindowHeight(float h)
  372. {
  373. mOrthoHeight = h;
  374. invalidateFrustum();
  375. _markCoreDirty();
  376. }
  377. void CameraHandlerBase::setOrthoWindowWidth(float w)
  378. {
  379. mOrthoHeight = w / mAspect;
  380. invalidateFrustum();
  381. _markCoreDirty();
  382. }
  383. float CameraHandlerBase::getOrthoWindowHeight() const
  384. {
  385. return mOrthoHeight;
  386. }
  387. float CameraHandlerBase::getOrthoWindowWidth() const
  388. {
  389. return mOrthoHeight * mAspect;
  390. }
  391. void CameraHandlerBase::setFrustumExtents(float left, float right, float top, float bottom)
  392. {
  393. mFrustumExtentsManuallySet = true;
  394. mLeft = left;
  395. mRight = right;
  396. mTop = top;
  397. mBottom = bottom;
  398. invalidateFrustum();
  399. _markCoreDirty();
  400. }
  401. void CameraHandlerBase::resetFrustumExtents()
  402. {
  403. mFrustumExtentsManuallySet = false;
  404. invalidateFrustum();
  405. _markCoreDirty();
  406. }
  407. void CameraHandlerBase::getFrustumExtents(float& outleft, float& outright, float& outtop, float& outbottom) const
  408. {
  409. updateFrustum();
  410. outleft = mLeft;
  411. outright = mRight;
  412. outtop = mTop;
  413. outbottom = mBottom;
  414. }
  415. void CameraHandlerBase::setPosition(const Vector3& position)
  416. {
  417. mPosition = position;
  418. mRecalcView = true;
  419. _markCoreDirty();
  420. }
  421. void CameraHandlerBase::setRotation(const Quaternion& rotation)
  422. {
  423. mRotation = rotation;
  424. mRecalcView = true;
  425. _markCoreDirty();
  426. }
  427. void CameraHandlerBase::invalidateFrustum() const
  428. {
  429. mRecalcFrustum = true;
  430. mRecalcFrustumPlanes = true;
  431. }
  432. Vector2I CameraHandlerBase::worldToScreenPoint(const Vector3& worldPoint) const
  433. {
  434. Vector2 clipPoint = worldToClipPoint(worldPoint);
  435. return clipToScreenPoint(clipPoint);
  436. }
  437. Vector2 CameraHandlerBase::worldToClipPoint(const Vector3& worldPoint) const
  438. {
  439. Vector3 viewPoint = worldToViewPoint(worldPoint);
  440. return viewToClipPoint(viewPoint);
  441. }
  442. Vector3 CameraHandlerBase::worldToViewPoint(const Vector3& worldPoint) const
  443. {
  444. return getViewMatrix().multiplyAffine(worldPoint);
  445. }
  446. Vector3 CameraHandlerBase::screenToWorldPoint(const Vector2I& screenPoint) const
  447. {
  448. Vector2 clipPoint = screenToClipPoint(screenPoint);
  449. return clipToWorldPoint(clipPoint);
  450. }
  451. Vector3 CameraHandlerBase::screenToViewPoint(const Vector2I& screenPoint) const
  452. {
  453. Vector2 clipPoint = screenToClipPoint(screenPoint);
  454. return clipToViewPoint(clipPoint);
  455. }
  456. Vector2 CameraHandlerBase::screenToClipPoint(const Vector2I& screenPoint) const
  457. {
  458. Rect2I viewport = getViewportRect();
  459. Vector2 clipPoint;
  460. clipPoint.x = (float)(((screenPoint.x - viewport.x) / (float)viewport.width) * 2.0f - 1.0f);
  461. clipPoint.y = (float)((1.0f - ((screenPoint.y - viewport.y) / (float)viewport.height)) * 2.0f - 1.0f);
  462. return clipPoint;
  463. }
  464. Vector3 CameraHandlerBase::viewToWorldPoint(const Vector3& viewPoint) const
  465. {
  466. return getViewMatrix().inverseAffine().multiplyAffine(viewPoint);
  467. }
  468. Vector2I CameraHandlerBase::viewToScreenPoint(const Vector3& viewPoint) const
  469. {
  470. Vector2 clipPoint = viewToClipPoint(viewPoint);
  471. return clipToScreenPoint(clipPoint);
  472. }
  473. Vector2 CameraHandlerBase::viewToClipPoint(const Vector3& viewPoint) const
  474. {
  475. Vector3 projPoint = projectPoint(viewPoint);
  476. return Vector2(projPoint.x, projPoint.y);
  477. }
  478. Vector3 CameraHandlerBase::clipToWorldPoint(const Vector2& clipPoint) const
  479. {
  480. Vector3 viewPoint = clipToViewPoint(clipPoint);
  481. return viewToWorldPoint(viewPoint);
  482. }
  483. Vector3 CameraHandlerBase::clipToViewPoint(const Vector2& clipPoint) const
  484. {
  485. return unprojectPoint(Vector3(clipPoint.x, clipPoint.y, 0.5f));
  486. }
  487. Vector2I CameraHandlerBase::clipToScreenPoint(const Vector2& clipPoint) const
  488. {
  489. Rect2I viewport = getViewportRect();
  490. Vector2I screenPoint;
  491. screenPoint.x = Math::roundToInt(viewport.x + ((clipPoint.x + 1.0f) * 0.5f) * viewport.width);
  492. screenPoint.y = Math::roundToInt(viewport.y + (1.0f - (clipPoint.y + 1.0f) * 0.5f) * viewport.height);
  493. return screenPoint;
  494. }
  495. Ray CameraHandlerBase::screenPointToRay(const Vector2I& screenPoint) const
  496. {
  497. Vector2 clipPoint = screenToClipPoint(screenPoint);
  498. Vector3 near = unprojectPoint(Vector3(clipPoint.x, clipPoint.y, mNearDist));
  499. Vector3 far = unprojectPoint(Vector3(clipPoint.x, clipPoint.y, mNearDist + 1.0f));
  500. Ray ray(near, Vector3::normalize(far - near));
  501. ray.transformAffine(getViewMatrix().inverseAffine());
  502. return ray;
  503. }
  504. Vector3 CameraHandlerBase::projectPoint(const Vector3& point) const
  505. {
  506. Vector4 projPoint4(point.x, point.y, point.z, 1.0f);
  507. projPoint4 = getProjectionMatrixRS().multiply(projPoint4);
  508. if (Math::abs(projPoint4.w) > 1e-7f)
  509. {
  510. float invW = 1.0f / projPoint4.w;
  511. projPoint4.x *= invW;
  512. projPoint4.y *= invW;
  513. projPoint4.z *= invW;
  514. }
  515. else
  516. {
  517. projPoint4.x = 0.0f;
  518. projPoint4.y = 0.0f;
  519. projPoint4.z = 0.0f;
  520. }
  521. return Vector3(projPoint4.x, projPoint4.y, projPoint4.z);
  522. }
  523. Vector3 CameraHandlerBase::unprojectPoint(const Vector3& point) const
  524. {
  525. Vector4 dir4(point.x, point.y, 0.95f, 1.0f); // 0.95f arbitrary
  526. dir4 = getProjectionMatrixRS().inverse().multiply(dir4);
  527. Vector3 dir;
  528. dir.x = dir4.x;
  529. dir.y = dir4.y;
  530. dir.z = dir4.z;
  531. if (Math::abs(dir4.w) > 1e-7f)
  532. {
  533. float invW = 1.0f / dir4.w;
  534. dir.x *= invW;
  535. dir.y *= invW;
  536. dir.z *= invW;
  537. // Find a point along a ray from camera origin to point on near plane we just found,
  538. // at point.z distance from the origin
  539. float distToPlane = dir.dot(-Vector3::UNIT_Z);
  540. if (distToPlane >= 0.0f)
  541. {
  542. if (mProjType == PT_PERSPECTIVE)
  543. dir *= point.z / distToPlane;
  544. else
  545. dir += Vector3::UNIT_Z * (distToPlane - point.z);
  546. }
  547. }
  548. else
  549. {
  550. dir.x = 0.0f;
  551. dir.y = 0.0f;
  552. dir.z = 0.0f;
  553. }
  554. return Vector3(dir.x, dir.y, dir.z);
  555. }
  556. CameraHandlerCore::~CameraHandlerCore()
  557. {
  558. RendererManager::instance().getActive()->_notifyCameraRemoved(this);
  559. }
  560. CameraHandlerCore::CameraHandlerCore(SPtr<RenderTargetCore> target, float left, float top, float width, float height)
  561. {
  562. mViewport = ViewportCore::create(target, left, top, width, height);
  563. }
  564. CameraHandlerCore::CameraHandlerCore(const SPtr<ViewportCore>& viewport)
  565. {
  566. mViewport = viewport;
  567. }
  568. void CameraHandlerCore::initialize()
  569. {
  570. RendererManager::instance().getActive()->_notifyCameraAdded(this);
  571. CoreObjectCore::initialize();
  572. }
  573. Rect2I CameraHandlerCore::getViewportRect() const
  574. {
  575. return mViewport->getArea();
  576. }
  577. void CameraHandlerCore::syncToCore(const CoreSyncData& data)
  578. {
  579. char* dataPtr = (char*)data.getBuffer();
  580. dataPtr = rttiReadElem(mLayers, dataPtr);
  581. dataPtr = rttiReadElem(mPosition, dataPtr);
  582. dataPtr = rttiReadElem(mRotation, dataPtr);
  583. dataPtr = rttiReadElem(mProjType, dataPtr);
  584. dataPtr = rttiReadElem(mHorzFOV, dataPtr);
  585. dataPtr = rttiReadElem(mFarDist, dataPtr);
  586. dataPtr = rttiReadElem(mNearDist, dataPtr);
  587. dataPtr = rttiReadElem(mAspect, dataPtr);
  588. dataPtr = rttiReadElem(mOrthoHeight, dataPtr);
  589. dataPtr = rttiReadElem(mPriority, dataPtr);
  590. dataPtr = rttiReadElem(mCustomViewMatrix, dataPtr);
  591. dataPtr = rttiReadElem(mCustomProjMatrix, dataPtr);
  592. dataPtr = rttiReadElem(mFrustumExtentsManuallySet, dataPtr);
  593. dataPtr = rttiReadElem(mIgnoreSceneRenderables, dataPtr);
  594. mRecalcFrustum = true;
  595. mRecalcFrustumPlanes = true;
  596. mRecalcView = true;
  597. }
  598. CameraHandler::CameraHandler(RenderTargetPtr target, float left, float top, float width, float height)
  599. {
  600. target->blockUntilCoreInitialized();
  601. mViewport = Viewport::create(target, left, top, width, height);
  602. }
  603. SPtr<CameraHandlerCore> CameraHandler::getCore() const
  604. {
  605. return std::static_pointer_cast<CameraHandlerCore>(mCoreSpecific);
  606. }
  607. CameraHandlerPtr CameraHandler::create(RenderTargetPtr target, float left, float top, float width, float height)
  608. {
  609. CameraHandler* handler = new (bs_alloc<CameraHandler>()) CameraHandler(target, left, top, width, height);
  610. CameraHandlerPtr handlerPtr = bs_core_ptr<CameraHandler, GenAlloc>(handler);
  611. handlerPtr->_setThisPtr(handlerPtr);
  612. handlerPtr->initialize();
  613. return handlerPtr;
  614. }
  615. CameraHandlerPtr CameraHandler::createEmpty()
  616. {
  617. CameraHandler* handler = new (bs_alloc<CameraHandler>()) CameraHandler();
  618. CameraHandlerPtr handlerPtr = bs_core_ptr<CameraHandler, GenAlloc>(handler);
  619. handlerPtr->_setThisPtr(handlerPtr);
  620. return handlerPtr;
  621. }
  622. SPtr<CoreObjectCore> CameraHandler::createCore() const
  623. {
  624. Rect2 normArea = mViewport->getNormArea();
  625. CameraHandlerCore* handler = new (bs_alloc<CameraHandlerCore>()) CameraHandlerCore(mViewport->getCore());
  626. SPtr<CameraHandlerCore> handlerPtr = bs_shared_ptr<CameraHandlerCore, GenAlloc>(handler);
  627. handlerPtr->_setThisPtr(handlerPtr);
  628. return handlerPtr;
  629. }
  630. Rect2I CameraHandler::getViewportRect() const
  631. {
  632. return mViewport->getArea();
  633. }
  634. CoreSyncData CameraHandler::syncToCore(FrameAlloc* allocator)
  635. {
  636. UINT32 size = 0;
  637. size += rttiGetElemSize(mLayers);
  638. size += rttiGetElemSize(mPosition);
  639. size += rttiGetElemSize(mRotation);
  640. size += rttiGetElemSize(mProjType);
  641. size += rttiGetElemSize(mHorzFOV);
  642. size += rttiGetElemSize(mFarDist);
  643. size += rttiGetElemSize(mNearDist);
  644. size += rttiGetElemSize(mAspect);
  645. size += rttiGetElemSize(mOrthoHeight);
  646. size += rttiGetElemSize(mPriority);
  647. size += rttiGetElemSize(mCustomViewMatrix);
  648. size += rttiGetElemSize(mCustomProjMatrix);
  649. size += rttiGetElemSize(mFrustumExtentsManuallySet);
  650. size += rttiGetElemSize(mIgnoreSceneRenderables);
  651. UINT8* buffer = allocator->alloc(size);
  652. char* dataPtr = (char*)buffer;
  653. dataPtr = rttiWriteElem(mLayers, dataPtr);
  654. dataPtr = rttiWriteElem(mPosition, dataPtr);
  655. dataPtr = rttiWriteElem(mRotation, dataPtr);
  656. dataPtr = rttiWriteElem(mProjType, dataPtr);
  657. dataPtr = rttiWriteElem(mHorzFOV, dataPtr);
  658. dataPtr = rttiWriteElem(mFarDist, dataPtr);
  659. dataPtr = rttiWriteElem(mNearDist, dataPtr);
  660. dataPtr = rttiWriteElem(mAspect, dataPtr);
  661. dataPtr = rttiWriteElem(mOrthoHeight, dataPtr);
  662. dataPtr = rttiWriteElem(mPriority, dataPtr);
  663. dataPtr = rttiWriteElem(mCustomViewMatrix, dataPtr);
  664. dataPtr = rttiWriteElem(mCustomProjMatrix, dataPtr);
  665. dataPtr = rttiWriteElem(mFrustumExtentsManuallySet, dataPtr);
  666. dataPtr = rttiWriteElem(mIgnoreSceneRenderables, dataPtr);
  667. return CoreSyncData(buffer, size);
  668. }
  669. void CameraHandler::_markCoreDirty()
  670. {
  671. markCoreDirty();
  672. }
  673. RTTITypeBase* CameraHandler::getRTTIStatic()
  674. {
  675. return CameraHandlerRTTI::instance();
  676. }
  677. RTTITypeBase* CameraHandler::getRTTI() const
  678. {
  679. return CameraHandler::getRTTIStatic();
  680. }
  681. }