BsCameraHandler.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637
  1. #pragma once
  2. #include "BsPrerequisites.h"
  3. #include "BsIReflectable.h"
  4. #include "BsMatrix4.h"
  5. #include "BsVector3.h"
  6. #include "BsVector2.h"
  7. #include "BsVector2I.h"
  8. #include "BsAABox.h"
  9. #include "BsQuaternion.h"
  10. #include "BsRay.h"
  11. #include "BsCoreObject.h"
  12. #include "BsConvexVolume.h"
  13. namespace BansheeEngine
  14. {
  15. /**
  16. * @brief Specified projection type to use by the camera.
  17. */
  18. enum ProjectionType
  19. {
  20. PT_ORTHOGRAPHIC,
  21. PT_PERSPECTIVE
  22. };
  23. /**
  24. * @brief Clip planes that form the camera frustum (visible area).
  25. */
  26. enum FrustumPlane
  27. {
  28. FRUSTUM_PLANE_NEAR = 0,
  29. FRUSTUM_PLANE_FAR = 1,
  30. FRUSTUM_PLANE_LEFT = 2,
  31. FRUSTUM_PLANE_RIGHT = 3,
  32. FRUSTUM_PLANE_TOP = 4,
  33. FRUSTUM_PLANE_BOTTOM = 5
  34. };
  35. /**
  36. * @brief Camera determines how is world geometry projected onto a 2D surface. You may
  37. * position and orient it in space, set options like aspect ratio and field or view
  38. * and it outputs view and projection matrices required for rendering.
  39. */
  40. class BS_EXPORT CameraHandlerBase
  41. {
  42. public:
  43. virtual ~CameraHandlerBase() { }
  44. /**
  45. * @brief Sets the camera horizontal field of view. This determines how wide the camera
  46. * viewing angle is along the horizontal axis. Vertical FOV is calculated from the
  47. * horizontal FOV and the aspect.
  48. */
  49. virtual void setHorzFOV(const Radian& fovy);
  50. /**
  51. * @brief Retrieves the camera horizontal field of view.
  52. */
  53. virtual const Radian& getHorzFOV() const;
  54. /**
  55. * @brief Sets the distance from the frustum to the near clipping plane. Anything
  56. * closer than the near clipping plane will not be rendered. Decreasing this value
  57. * decreases depth buffer precision.
  58. */
  59. virtual void setNearClipDistance(float nearDist);
  60. /**
  61. * @brief Retrieves the distance from the frustum to the near clipping plane. Anything
  62. * closer than the near clipping plane will not be rendered. Decreasing this value
  63. * decreases depth buffer precision.
  64. */
  65. virtual float getNearClipDistance() const;
  66. /**
  67. * @brief Sets the distance from the frustum to the far clipping plane. Anything
  68. * farther than the far clipping plane will not be rendered. Increasing this value
  69. * decreases depth buffer precision.
  70. */
  71. virtual void setFarClipDistance(float farDist);
  72. /**
  73. * @brief Retrieves the distance from the frustum to the far clipping plane. Anything
  74. * farther than the far clipping plane will not be rendered. Increasing this value
  75. * decreases depth buffer precision.
  76. */
  77. virtual float getFarClipDistance() const;
  78. /**
  79. * @brief Sets the current viewport aspect ratio (width / height).
  80. */
  81. virtual void setAspectRatio(float ratio);
  82. /**
  83. * @brief Returns current viewport aspect ratio (width / height).
  84. */
  85. virtual float getAspectRatio() const;
  86. /**
  87. * @brief Sets camera world space position.
  88. */
  89. virtual void setPosition(const Vector3& position);
  90. /**
  91. * @brief Retrieves camera world space position.
  92. */
  93. virtual Vector3 getPosition() const { return mPosition; }
  94. /**
  95. * @brief Gets the Z (forward) axis of the object, in world space.
  96. *
  97. * @return Forward axis of the object.
  98. */
  99. Vector3 getForward() const { return getRotation().rotate(-Vector3::UNIT_Z); }
  100. /**
  101. * @brief Sets camera world space rotation.
  102. */
  103. virtual void setRotation(const Quaternion& rotation);
  104. /**
  105. * @brief Retrieves camera world space rotation.
  106. */
  107. virtual Quaternion getRotation() const { return mRotation; }
  108. /** @brief Manually set the extents of the frustum that will be used when calculating the
  109. * projection matrix. This will prevents extents for being automatically calculated
  110. * from aspect and near plane so it is up to the caller to keep these values
  111. * accurate.
  112. *
  113. * @param left The position where the left clip plane intersect the near clip plane, in view space.
  114. * @param right The position where the right clip plane intersect the near clip plane, in view space.
  115. * @param top The position where the top clip plane intersect the near clip plane, in view space.
  116. * @param bottom The position where the bottom clip plane intersect the near clip plane, in view space.
  117. */
  118. virtual void setFrustumExtents(float left, float right, float top, float bottom);
  119. /**
  120. * @brief Resets frustum extents so they are automatically derived from other values.
  121. * This is only relevant if you have previously set custom extents.
  122. */
  123. virtual void resetFrustumExtents();
  124. /**
  125. * @brief Returns the extents of the frustum in view space at the near plane.
  126. */
  127. virtual void getFrustumExtents(float& outleft, float& outright, float& outtop, float& outbottom) const;
  128. /**
  129. * @brief Returns the standard projection matrix that determines how are 3D points
  130. * projected to two dimensions. The layout of this matrix depends on currently
  131. * used render system.
  132. *
  133. * @note You should use this matrix when sending the matrix to the render system to remain
  134. * everything works consistently when other render systems are used.
  135. */
  136. virtual const Matrix4& getProjectionMatrixRS() const;
  137. /**
  138. * @brief Returns the inverse of the render-system specific projection matrix.
  139. *
  140. * @see getProjectionMatrixRS
  141. */
  142. virtual const Matrix4& getProjectionMatrixRSInv() const;
  143. /**
  144. * @brief Returns the standard projection matrix that determines how are 3D points
  145. * projected to two dimensions. Returned matrix is standard following right-hand
  146. * rules and depth range of [-1, 1].
  147. *
  148. * @note Different render systems will expect different projection matrix layouts, in which
  149. * case use getProjectionMatrixRS.
  150. */
  151. virtual const Matrix4& getProjectionMatrix() const;
  152. /**
  153. * @brief Returns the inverse of the projection matrix.
  154. *
  155. * @see getProjectionMatrix
  156. */
  157. virtual const Matrix4& getProjectionMatrixInv() const;
  158. /**
  159. * @brief Gets the camera view matrix. Used for positioning/orienting the camera.
  160. */
  161. virtual const Matrix4& getViewMatrix() const;
  162. /**
  163. * @brief Returns the inverse of the view matrix.
  164. *
  165. * @see getViewMatrix
  166. */
  167. virtual const Matrix4& getViewMatrixInv() const;
  168. /**
  169. * @brief Sets whether the camera should use the custom view matrix.
  170. * When this is enabled camera will no longer calculate its view matrix
  171. * based on position/orientation and caller will be resonsible to keep
  172. * the view matrix up to date.
  173. */
  174. virtual void setCustomViewMatrix(bool enable, const Matrix4& viewMatrix = Matrix4::IDENTITY);
  175. /**
  176. * @brief Returns true if a custom view matrix is used.
  177. */
  178. virtual bool isCustomViewMatrixEnabled() const { return mCustomViewMatrix; }
  179. /**
  180. * @brief Sets whether the camera should use the custom projection matrix.
  181. * When this is enabled camera will no longer calculate its projection matrix
  182. * based on field of view, aspect and other parameters and caller will be
  183. * resonsible to keep the projection matrix up to date.
  184. */
  185. virtual void setCustomProjectionMatrix(bool enable, const Matrix4& projectionMatrix = Matrix4::IDENTITY);
  186. /**
  187. * @brief Returns true if a custom projection matrix is used.
  188. */
  189. virtual bool isCustomProjectionMatrixEnabled() const { return mCustomProjMatrix; }
  190. /**
  191. * @brief Returns a convex volume representing the visible area of the camera,
  192. * in local space.
  193. */
  194. virtual const ConvexVolume& getFrustum() const;
  195. /**
  196. * @brief Returns a convex volume representing the visible area of the camera,
  197. * in world space.
  198. */
  199. virtual ConvexVolume getWorldFrustum() const;
  200. /**
  201. * @brief Returns the bounding of the frustum.
  202. */
  203. const AABox& getBoundingBox() const;
  204. /**
  205. * @brief Sets the type of projection used by the camera.
  206. */
  207. virtual void setProjectionType(ProjectionType pt);
  208. /**
  209. * @brief Returns the type of projection used by the camera.
  210. */
  211. virtual ProjectionType getProjectionType() const;
  212. /**
  213. * @brief Sets the orthographic window height, for use with orthographic rendering only.
  214. *
  215. * @param w Width of the window in world units.
  216. * @param h Height of the window in world units.
  217. *
  218. * @note Calling this method will recalculate the aspect ratio, use setOrthoWindowHeight or
  219. * setOrthoWindowWidth alone if you wish to preserve the aspect ratio but just fit one
  220. * or other dimension to a particular size.
  221. */
  222. virtual void setOrthoWindow(float w, float h);
  223. /**
  224. * @brief Sets the orthographic window height, for use with orthographic rendering only.
  225. *
  226. * @param h Height of the window in world units.
  227. *
  228. * @note The width of the window will be calculated from the aspect ratio.
  229. */
  230. virtual void setOrthoWindowHeight(float h);
  231. /**
  232. * @brief Sets the orthographic window width, for use with orthographic rendering only.
  233. *
  234. * @param w Width of the window in world units.
  235. *
  236. * @note The height of the window will be calculated from the aspect ratio.
  237. */
  238. virtual void setOrthoWindowWidth(float w);
  239. /**
  240. * @brief Gets the orthographic window width in world units, for use with orthographic rendering only.
  241. */
  242. virtual float getOrthoWindowHeight() const;
  243. /**
  244. * @brief Gets the orthographic window width in world units, for use with orthographic rendering only.
  245. *
  246. * @note This is calculated from the orthographic height and the aspect ratio.
  247. */
  248. virtual float getOrthoWindowWidth() const;
  249. /**
  250. * @brief This option tells the renderer that this camera should ignore any renderable components.
  251. */
  252. void setIgnoreSceneRenderables(bool value) { mIgnoreSceneRenderables = true; _markCoreDirty(); }
  253. /**
  254. * @brief This option tells the renderer that this camera should ignore any renderable components.
  255. */
  256. bool getIgnoreSceneRenderables() const { return mIgnoreSceneRenderables; }
  257. /**
  258. * @brief Gets a priority that determines in which orders the cameras are rendered.
  259. * This only applies to cameras rendering to the same render target.
  260. */
  261. INT32 getPriority() const { return mPriority; }
  262. /**
  263. * @brief Sets a priority that determines in which orders the cameras are rendered.
  264. * This only applies to cameras rendering to the same render target.
  265. *
  266. * @param priority The priority. Higher value means the camera will be rendered sooner.
  267. */
  268. void setPriority(INT32 priority) { mPriority = priority; _markCoreDirty(); }
  269. /**
  270. * @brief Retrieves layer bitfield that is used when determining which object should the camera render.
  271. */
  272. UINT64 getLayers() const { return mLayers; }
  273. /**
  274. * @brief Sets layer bitfield that is used when determining which object should the camera render.
  275. */
  276. void setLayers(UINT64 layers) { mLayers = layers; _markCoreDirty(); }
  277. /**
  278. * @brief Converts a point in world space to screen coordinates (in pixels
  279. * corresponding to the render target attached to the camera).
  280. */
  281. Vector2I worldToScreenPoint(const Vector3& worldPoint) const;
  282. /**
  283. * @brief Converts a point in world space to normalized clip coordinates
  284. * (in [0, 1] range).
  285. */
  286. Vector2 worldToClipPoint(const Vector3& worldPoint) const;
  287. /**
  288. * @brief Converts a point in world space to point relative to camera's
  289. * coordinate system (view space).
  290. */
  291. Vector3 worldToViewPoint(const Vector3& worldPoint) const;
  292. /**
  293. * @brief Converts a point in screen space (pixels corresponding to
  294. * render target attached to the camera) to a point in world space.
  295. *
  296. * @param screenPoint Point to transform.
  297. * @param depth Depth to place the world point at. The depth is applied
  298. * to the vector going from camera origin to the point on
  299. * the near plane.
  300. */
  301. Vector3 screenToWorldPoint(const Vector2I& screenPoint, float depth = 0.5f) const;
  302. /**
  303. * @brief Converts a point in screen space (pixels corresponding to
  304. * render target attached to the camera) to a point relative to
  305. * camera's coordinate system (view space).
  306. *
  307. * @param screenPoint Point to transform.
  308. * @param depth Depth to place the world point at. The depth is applied
  309. * to the vector going from camera origin to the point on
  310. * the near plane.
  311. */
  312. Vector3 screenToViewPoint(const Vector2I& screenPoint, float depth = 0.5f) const;
  313. /**
  314. * @brief Converts a point in screen space (pixels corresponding to
  315. * render target attached to the camera) to normalized clip
  316. * coordinates (in [0, 1] range).
  317. */
  318. Vector2 screenToClipPoint(const Vector2I& screenPoint) const;
  319. /**
  320. * @brief Converts a point relative to camera's coordinate system (view space)
  321. * into a point in world space.
  322. */
  323. Vector3 viewToWorldPoint(const Vector3& viewPoint) const;
  324. /**
  325. * @brief Converts a point relative to camera's coordinate system (view space)
  326. * into a point in screen space (pixels corresponding to render target
  327. * attached to the camera.
  328. */
  329. Vector2I viewToScreenPoint(const Vector3& viewPoint) const;
  330. /**
  331. * @brief Converts a point relative to camera's coordinate system (view space)
  332. * into normalized clip coordinates (in [0, 1] range).
  333. */
  334. Vector2 viewToClipPoint(const Vector3& viewPoint) const;
  335. /**
  336. * @brief Converts a point in normalized clip coordinates ([0, 1] range) to
  337. * a point in world space.
  338. *
  339. * @param clipPoint Point to transform.
  340. * @param depth Depth to place the world point at. The depth is applied
  341. * to the vector going from camera origin to the point on
  342. * the near plane.
  343. */
  344. Vector3 clipToWorldPoint(const Vector2& clipPoint, float depth = 0.5f) const;
  345. /**
  346. * @brief Converts a point in normalized clip coordinates ([0, 1] range) to
  347. * a point relative to camera's coordinate system (view space).
  348. *
  349. * @param clipPoint Point to transform.
  350. * @param depth Depth to place the world point at. The depth is applied
  351. * to the vector going from camera origin to the point on
  352. * the near plane.
  353. */
  354. Vector3 clipToViewPoint(const Vector2& clipPoint, float depth = 0.5f) const;
  355. /**
  356. * @brief Converts a point in normalized clip coordinates ([0, 1] range) to
  357. * a point in screen space (pixels corresponding to render target attached
  358. * to the camera)
  359. */
  360. Vector2I clipToScreenPoint(const Vector2& clipPoint) const;
  361. /**
  362. * @brief Converts a point in screen space (pixels corresponding to
  363. * render target attached to the camera) to a ray in world space
  364. * originating at the selected point on the camera near plane.
  365. */
  366. Ray screenPointToRay(const Vector2I& screenPoint) const;
  367. /**
  368. * @brief Projects a point from view to clip space.
  369. */
  370. Vector3 projectPoint(const Vector3& point) const;
  371. /**
  372. * @brief Un-projects a point in clip space to view space.
  373. */
  374. Vector3 unprojectPoint(const Vector3& point) const;
  375. static const float INFINITE_FAR_PLANE_ADJUST; /**< Small constant used to reduce far plane projection to avoid inaccuracies. */
  376. protected:
  377. CameraHandlerBase(RenderTargetPtr target = nullptr,
  378. float left = 0.0f, float top = 0.0f, float width = 1.0f, float height = 1.0f);
  379. /**
  380. * @brief Calculate projection parameters that are used when constructing the projection matrix.
  381. */
  382. virtual void calcProjectionParameters(float& left, float& right, float& bottom, float& top) const;
  383. /**
  384. * @brief Recalculate frustum if dirty.
  385. */
  386. virtual void updateFrustum() const;
  387. /**
  388. * @brief Recalculate frustum planes if dirty.
  389. */
  390. virtual void updateFrustumPlanes() const;
  391. /**
  392. * @brief Update view matrix from parent position/orientation.
  393. *
  394. * @note Does nothing when custom view matrix is set.
  395. */
  396. virtual void updateView() const;
  397. /**
  398. * @brief Checks if the frustum requires updating.
  399. */
  400. virtual bool isFrustumOutOfDate() const;
  401. /**
  402. * @brief Notify camera that the frustum requires to be updated.
  403. */
  404. virtual void invalidateFrustum() const;
  405. /**
  406. * @brief Returns a rectangle that defines the viewport position and size, in pixels.
  407. */
  408. virtual Rect2I getViewportRect() const = 0;
  409. /**
  410. * @copydoc CoreObject::markCoreDirty
  411. */
  412. virtual void _markCoreDirty() { }
  413. protected:
  414. UINT64 mLayers; /**< Bitfield that can be used for filtering what objects the camera sees. */
  415. Vector3 mPosition; /**< World space position. */
  416. Quaternion mRotation; /**< World space rotation. */
  417. ProjectionType mProjType; /**< Type of camera projection. */
  418. Radian mHorzFOV; /**< Horizontal field of view represents how wide is the camera angle. */
  419. float mFarDist; /**< Clip any objects further than this. Larger value decreases depth precision at smaller depths. */
  420. float mNearDist; /**< Clip any objects close than this. Smaller value decreases depth precision at larger depths. */
  421. float mAspect; /**< Width/height viewport ratio. */
  422. float mOrthoHeight; /**< Height in world units used for orthographic cameras. */
  423. INT32 mPriority; /**< Determines in what order will the camera be rendered. Higher priority means the camera will be rendered sooner. */
  424. bool mCustomViewMatrix; /**< Is custom view matrix set. */
  425. bool mCustomProjMatrix; /**< Is custom projection matrix set. */
  426. bool mFrustumExtentsManuallySet; /**< Are frustum extents manually set. */
  427. bool mIgnoreSceneRenderables; /**< Should the camera ignore renderable components. */
  428. mutable Matrix4 mProjMatrixRS; /**< Cached render-system specific projection matrix. */
  429. mutable Matrix4 mProjMatrix; /**< Cached projection matrix that determines how are 3D points projected to a 2D viewport. */
  430. mutable Matrix4 mViewMatrix; /**< Cached view matrix that determines camera position/orientation. */
  431. mutable Matrix4 mProjMatrixRSInv;
  432. mutable Matrix4 mProjMatrixInv;
  433. mutable Matrix4 mViewMatrixInv;
  434. mutable ConvexVolume mFrustum; /**< Main clipping planes describing cameras visible area. */
  435. mutable bool mRecalcFrustum; /**< Should frustum be recalculated. */
  436. mutable bool mRecalcFrustumPlanes; /**< Should frustum planes be recalculated. */
  437. mutable bool mRecalcView; /**< Should view matrix be recalculated. */
  438. mutable float mLeft, mRight, mTop, mBottom; /**< Frustum extents. */
  439. mutable AABox mBoundingBox; /**< Frustum bounding box. */
  440. };
  441. /**
  442. * @copydoc CameraHandlerBase
  443. */
  444. class BS_EXPORT CameraHandlerCore : public CoreObjectCore, public CameraHandlerBase
  445. {
  446. public:
  447. ~CameraHandlerCore();
  448. /**
  449. * @brief Returns the viewport used by the camera.
  450. */
  451. SPtr<ViewportCore> getViewport() const { return mViewport; }
  452. protected:
  453. friend class CameraHandler;
  454. CameraHandlerCore(SPtr<RenderTargetCore> target = nullptr,
  455. float left = 0.0f, float top = 0.0f, float width = 1.0f, float height = 1.0f);
  456. CameraHandlerCore(const SPtr<ViewportCore>& viewport);
  457. /**
  458. * @copydoc CoreObjectCore::initialize
  459. */
  460. void initialize() override;
  461. /**
  462. * @copydoc CameraHandlerBase
  463. */
  464. virtual Rect2I getViewportRect() const override;
  465. /**
  466. * @copydoc CoreObject::syncToCore
  467. */
  468. void syncToCore(const CoreSyncData& data) override;
  469. SPtr<ViewportCore> mViewport;
  470. };
  471. /**
  472. * @copydoc CameraHandlerBase
  473. */
  474. class BS_EXPORT CameraHandler : public IReflectable, public CoreObject, public CameraHandlerBase
  475. {
  476. public:
  477. /**
  478. * @brief Returns the viewport used by the camera.
  479. */
  480. ViewportPtr getViewport() const { return mViewport; }
  481. /**
  482. * @brief Retrieves an implementation of a camera handler usable only from the
  483. * core thread.
  484. */
  485. SPtr<CameraHandlerCore> getCore() const;
  486. /**
  487. * @brief Returns the hash value that can be used to identify if the internal data needs an update.
  488. */
  489. UINT32 _getLastModifiedHash() const { return mLastUpdateHash; }
  490. /**
  491. * @brief Sets the hash value that can be used to identify if the internal data needs an update.
  492. */
  493. void _setLastModifiedHash(UINT32 hash) { mLastUpdateHash = hash; }
  494. /**
  495. * @brief Creates a new camera that renders to the specified portion of the provided render target.
  496. */
  497. static CameraHandlerPtr create(RenderTargetPtr target = nullptr,
  498. float left = 0.0f, float top = 0.0f, float width = 1.0f, float height = 1.0f);
  499. protected:
  500. CameraHandler(RenderTargetPtr target = nullptr,
  501. float left = 0.0f, float top = 0.0f, float width = 1.0f, float height = 1.0f);
  502. /**
  503. * @copydoc CameraHandlerBase
  504. */
  505. virtual Rect2I getViewportRect() const override;
  506. /**
  507. * @copydoc CoreObject::createCore
  508. */
  509. SPtr<CoreObjectCore> createCore() const override;
  510. /**
  511. * @copydoc CoreObject::markCoreDirty
  512. */
  513. void _markCoreDirty() override;
  514. /**
  515. * @copydoc CoreObject::syncToCore
  516. */
  517. CoreSyncData syncToCore(FrameAlloc* allocator) override;
  518. /**
  519. * @copydoc CoreObject::getCoreDependencies
  520. */
  521. void getCoreDependencies(Vector<SPtr<CoreObject>>& dependencies) override;
  522. /**
  523. * @brief Creates a new camera without initializing it.
  524. */
  525. static CameraHandlerPtr createEmpty();
  526. ViewportPtr mViewport; /**< Viewport that describes 2D rendering surface. */
  527. UINT32 mLastUpdateHash;
  528. /************************************************************************/
  529. /* RTTI */
  530. /************************************************************************/
  531. public:
  532. friend class CameraHandlerRTTI;
  533. static RTTITypeBase* getRTTIStatic();
  534. virtual RTTITypeBase* getRTTI() const;
  535. };
  536. }