BsGizmoManager.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #pragma once
  4. #include "BsEditorPrerequisites.h"
  5. #include "Utility/BsModule.h"
  6. #include "Image/BsColor.h"
  7. #include "Math/BsVector2I.h"
  8. #include "Math/BsMatrix4.h"
  9. #include "RenderAPI/BsGpuParam.h"
  10. #include "Utility/BsDrawHelper.h"
  11. #include "Renderer/BsParamBlocks.h"
  12. #include "Renderer/BsRendererExtension.h"
  13. namespace bs
  14. {
  15. /** @addtogroup Scene-Editor
  16. * @{
  17. */
  18. namespace ct { class GizmoRenderer; }
  19. /** Type of mesh that can be drawn by the gizmo renderer. */
  20. enum class GizmoMeshType
  21. {
  22. Solid, Line, Wire, Text, Count
  23. };
  24. /**
  25. * Handles the rendering and picking of gizmo elements. Gizmos are icons and 3D objects usually rendered in scene view
  26. * for various visualization purposes (for example a Camera component will have a gizmo that draws a Camera icon since
  27. * otherwise it has no visual representation). Aside from being rendered, gizmos can also be selected by the user as if
  28. * they were normal scene elements.
  29. */
  30. class BS_ED_EXPORT GizmoManager : public Module<GizmoManager>
  31. {
  32. public:
  33. GizmoManager();
  34. ~GizmoManager();
  35. /**
  36. * Starts gizmo creation. All further call will be referencing this gizmo. Must be followed by a matching
  37. * endGizmo().
  38. *
  39. * @param gizmoParent Scene object this gizmo is attached to. Selecting the gizmo will select this scene object.
  40. */
  41. void startGizmo(const HSceneObject& gizmoParent);
  42. /** Ends gizmo creation. Must be called after a matching startGizmo(). */
  43. void endGizmo();
  44. /** Changes the color of any further gizmo draw calls. */
  45. void setColor(const Color& color);
  46. /** Changes the transform that will be applied to meshes of any further gizmo draw calls. */
  47. void setTransform(const Matrix4& transform);
  48. /**
  49. * If pickable is set to true, gizmo can be selected by the user, otherwise it will be drawn but cannot be
  50. * interacted with.
  51. *
  52. * @note Must be called between startGizmo/endGizmo calls.
  53. */
  54. void setPickable(bool pickable) { mPickable = pickable; }
  55. /** Returns the currently set gizmo color. */
  56. Color getColor() const { return mColor; }
  57. /** Returns the currently set gizmo transform. */
  58. Matrix4 getTransform() const { return mTransform; }
  59. /**
  60. * Draws an axis aligned cuboid.
  61. *
  62. * @param[in] position Center of the cuboid.
  63. * @param[in] extents Radius of the cuboid in each axis.
  64. *
  65. * @note Must be called between startGizmo/endGizmo calls.
  66. */
  67. void drawCube(const Vector3& position, const Vector3& extents);
  68. /**
  69. * Draws a sphere.
  70. *
  71. * @note Must be called between startGizmo/endGizmo calls.
  72. */
  73. void drawSphere(const Vector3& position, float radius);
  74. /**
  75. * Draws a solid cone.
  76. *
  77. * @param[in] base Position of the center of the base of the cone.
  78. * @param[in] normal Orientation of the cone, pointing from center base to the tip of the cone.
  79. * @param[in] height Height of the cone (along the normal).
  80. * @param[in] radius Radius of the base of the cone.
  81. * @param[in] scale Scale applied to cone's disc width & height. Allows you to create elliptical cones.
  82. */
  83. void drawCone(const Vector3& base, const Vector3& normal, float height, float radius,
  84. const Vector2& scale = Vector2::ONE);
  85. /**
  86. * Draws a solid disc.
  87. *
  88. * @param[in] position Center of the disc.
  89. * @param[in] normal Orientation of the disc, pointing in the direction the disc is visible in.
  90. * @param[in] radius Radius of the disc.
  91. */
  92. void drawDisc(const Vector3& position, const Vector3& normal, float radius);
  93. /**
  94. * Draws a wireframe axis aligned cuboid.
  95. *
  96. * @param[in] position Center of the cuboid.
  97. * @param[in] extents Radius of the cuboid in each axis.
  98. *
  99. * @note Must be called between startGizmo/endGizmo calls.
  100. */
  101. void drawWireCube(const Vector3& position, const Vector3& extents);
  102. /**
  103. * Draws a wireframe sphere represented by three discs.
  104. *
  105. * @note Must be called between startGizmo/endGizmo calls.
  106. */
  107. void drawWireSphere(const Vector3& position, float radius);
  108. /**
  109. * Draws a wireframe hemisphere represented by three arcs.
  110. *
  111. * @note Must be called between startGizmo/endGizmo calls.
  112. */
  113. void drawWireHemisphere(const Vector3& position, float radius);
  114. /**
  115. * Draws a wireframe capsule.
  116. *
  117. * @param[in] position World coordinates of the center of the capsule.
  118. * @param[in] height Distance between the centers of the capsule's hemispheres.
  119. * @param[in] radius Distance of each point from the capsule's center-line.
  120. */
  121. void drawWireCapsule(const Vector3& position, float height, float radius);
  122. /**
  123. * Draws a wireframe cone.
  124. *
  125. * @param[in] base Position of the center of the base of the cone.
  126. * @param[in] normal Orientation of the cone, pointing from center base to the tip of the cone.
  127. * @param[in] height Height of the cone (along the normal).
  128. * @param[in] radius Radius of the base of the cone.
  129. * @param[in] scale Scale applied to cone's disc width & height. Allows you to create elliptical cones.
  130. */
  131. void drawWireCone(const Vector3& base, const Vector3& normal, float height, float radius,
  132. const Vector2& scale = Vector2::ONE);
  133. /**
  134. * Draws a line between two points.
  135. *
  136. * @note Must be called between startGizmo/endGizmo calls.
  137. */
  138. void drawLine(const Vector3& start, const Vector3& end);
  139. /**
  140. * Draws a list of lines. Provided array must contain pairs of the line start point followed by an end point.
  141. *
  142. * @note Must be called between startGizmo/endGizmo calls.
  143. */
  144. void drawLineList(const Vector<Vector3>& linePoints);
  145. /**
  146. * Draws a wireframe disc.
  147. *
  148. * @param[in] position Center of the disc.
  149. * @param[in] normal Orientation of the disc, pointing in the direction the disc is visible in.
  150. * @param[in] radius Radius of the disc.
  151. */
  152. void drawWireDisc(const Vector3& position, const Vector3& normal, float radius);
  153. /**
  154. * Draws a wireframe arc.
  155. *
  156. * @param[in] position Center of the arc.
  157. * @param[in] normal Orientation of the arc, pointing in the direction the arc is visible in.
  158. * @param[in] radius Radius of the arc.
  159. * @param[in] startAngle Angle at which to start the arc.
  160. * @param[in] amountAngle Length of the arc.
  161. */
  162. void drawWireArc(const Vector3& position, const Vector3& normal, float radius, Degree startAngle, Degree amountAngle);
  163. /**
  164. * Draws a wireframe mesh.
  165. *
  166. * @param[in] meshData Object containing mesh vertices and indices. Vertices must be Vertex3 and indices
  167. * 32-bit.
  168. */
  169. void drawWireMesh(const SPtr<MeshData>& meshData);
  170. /**
  171. * Draws a wireframe frustum.
  172. *
  173. * @param[in] position Origin of the frustum, or the eye point.
  174. * @param[in] aspect Ratio of frustum width over frustum height.
  175. * @param[in] FOV Horizontal field of view in degrees.
  176. * @param[in] near Distance to the near frustum plane.
  177. * @param[in] far Distance to the far frustum plane.
  178. *
  179. * @note Must be called between startGizmo/endGizmo calls.
  180. */
  181. void drawFrustum(const Vector3& position, float aspect, Degree FOV, float near, float far);
  182. /**
  183. * Draws an icon that always faces the camera.
  184. *
  185. * @param[in] position Position of the center of the icon.
  186. * @param[in] image Sprite image for the icon to draw.
  187. * @param[in] fixedScale If true then the icon will remain the same size regardless of the distance from camera.
  188. *
  189. * @note Must be called between startGizmo/endGizmo calls.
  190. */
  191. void drawIcon(Vector3 position, HSpriteTexture image, bool fixedScale);
  192. /**
  193. * Draws a mesh representing 2D text with the specified properties.
  194. *
  195. * @param[in] position Position to render the text at. Text will be centered around this point.
  196. * @param[in] text Text to draw.
  197. * @param[in] font Font to use for rendering the text's characters.
  198. * @param[in] fontSize Size of the characters, in points.
  199. */
  200. void drawText(const Vector3& position, const String& text, const HFont& font, UINT32 fontSize = 16);
  201. /**
  202. * Clears all gizmo data, but doesn't update the meshes or the render data. (Calling update would create empty
  203. * meshes, but before calling update gizmos will still be drawn).
  204. */
  205. void clearGizmos();
  206. /**
  207. * Clears gizmo render data like meshes, but doesn't clear the original gizmo data (Calling update would just
  208. * recreate the render data).
  209. */
  210. void clearRenderData();
  211. /**
  212. * Returns a scene object that was attached to a specific gizmo.
  213. *
  214. * @param[in] gizmoIdx Index of the gizmo to look for.
  215. */
  216. HSceneObject getSceneObject(UINT32 gizmoIdx);
  217. /** @name Internal
  218. * @{
  219. */
  220. /**
  221. * Updates all the gizmo meshes to reflect all draw calls submitted since clearGizmos().
  222. *
  223. * @note Internal method.
  224. */
  225. void update(const SPtr<Camera>& camera);
  226. /**
  227. * Queues all gizmos to be rendered for picking. Each gizmo is draw with a separate color so we can identify them
  228. * later.
  229. *
  230. * @param[in] camera Camera to draw the gizmos on.
  231. * @param[in] idxToColorCallback Callback that assigns a unique color to each gizmo index.
  232. *
  233. * @note Internal method.
  234. */
  235. void renderForPicking(const SPtr<Camera>& camera, std::function<Color(UINT32)> idxToColorCallback);
  236. /** @} */
  237. private:
  238. friend class ct::GizmoRenderer;
  239. /** Supported types of gizmo materials (shaders) */
  240. enum class GizmoMaterial
  241. {
  242. Solid, Wire, Line, Picking, PickingAlpha, Text
  243. };
  244. /** Common data shared by all gizmo types. */
  245. struct CommonData
  246. {
  247. UINT32 idx;
  248. Color color;
  249. Matrix4 transform;
  250. HSceneObject sceneObject;
  251. bool pickable;
  252. };
  253. /** Data required for rendering a cuboid gizmo. */
  254. struct CubeData : CommonData
  255. {
  256. Vector3 position;
  257. Vector3 extents;
  258. };
  259. /** Data required for rendering a sphere gizmo. */
  260. struct SphereData : CommonData
  261. {
  262. Vector3 position;
  263. float radius;
  264. };
  265. /** Data required for rendering a cone gizmo. */
  266. struct ConeData : CommonData
  267. {
  268. Vector3 base;
  269. Vector3 normal;
  270. float radius;
  271. float height;
  272. Vector2 scale;
  273. };
  274. /** Data required for rendering a line gizmo. */
  275. struct LineData : CommonData
  276. {
  277. Vector3 start;
  278. Vector3 end;
  279. };
  280. /** Data required for rendering a list of lines. */
  281. struct LineListData : CommonData
  282. {
  283. Vector<Vector3> linePoints;
  284. };
  285. /** Data required for rendering a disc gizmo. */
  286. struct DiscData : CommonData
  287. {
  288. Vector3 position;
  289. Vector3 normal;
  290. float radius;
  291. };
  292. /** Data required for rendering a wireframe arc gizmo. */
  293. struct WireArcData : CommonData
  294. {
  295. Vector3 position;
  296. Vector3 normal;
  297. float radius;
  298. Degree startAngle;
  299. Degree amountAngle;
  300. };
  301. /** Data required for rendering a wireframe mesh gizmo. */
  302. struct WireMeshData : CommonData
  303. {
  304. SPtr<MeshData> meshData;
  305. };
  306. /** Data required for rendering a frustum gizmo. */
  307. struct FrustumData : CommonData
  308. {
  309. Vector3 position;
  310. float aspect;
  311. Degree FOV;
  312. float near;
  313. float far;
  314. };
  315. /** Data required for rendering an icon gizmo. */
  316. struct IconData : CommonData
  317. {
  318. Vector3 position;
  319. bool fixedScale;
  320. HSpriteTexture texture;
  321. };
  322. /** Data required for rendering text. */
  323. struct TextData : CommonData
  324. {
  325. Vector3 position;
  326. String text;
  327. HFont font;
  328. UINT32 fontSize;
  329. };
  330. /** Stores how many icons use a specific texture. */
  331. struct IconRenderData
  332. {
  333. UINT32 count;
  334. SPtr<ct::Texture> texture;
  335. UINT32 paramsIdx;
  336. };
  337. /** Data about a mesh rendered by the draw manager. */
  338. struct MeshRenderData
  339. {
  340. MeshRenderData(const SPtr<ct::Mesh>& mesh, const SubMesh& subMesh, SPtr<ct::Texture> texture, GizmoMeshType type)
  341. :mesh(mesh), subMesh(subMesh), texture(texture), type(type), paramsIdx(0)
  342. { }
  343. SPtr<ct::Mesh> mesh;
  344. SubMesh subMesh;
  345. SPtr<ct::Texture> texture;
  346. GizmoMeshType type;
  347. UINT32 paramsIdx;
  348. };
  349. /** Data used for initializing the core thread equivalent of the gizmo manager. */
  350. struct CoreInitData
  351. {
  352. SPtr<ct::Material> solidMat;
  353. SPtr<ct::Material> wireMat;
  354. SPtr<ct::Material> lineMat;
  355. SPtr<ct::Material> iconMat;
  356. SPtr<ct::Material> textMat;
  357. SPtr<ct::Material> pickingMat;
  358. SPtr<ct::Material> alphaPickingMat;
  359. };
  360. typedef Vector<IconRenderData> IconRenderDataVec;
  361. typedef SPtr<IconRenderDataVec> IconRenderDataVecPtr;
  362. /**
  363. * Builds a brand new mesh that can be used for rendering all icon gizmos.
  364. *
  365. * @param[in] camera Camera the mesh will be rendered to.
  366. * @param[in] iconData A list of all icons and their properties.
  367. * @param[in] forPicking Whether the icons will be rendered normally, or with a special material for picking.
  368. * @param[in] renderData Output data that outlines the structure of the returned mesh. It tells us which portions
  369. * of the mesh use which icon texture.
  370. *
  371. * @return A mesh containing all of the visible icons.
  372. */
  373. SPtr<Mesh> buildIconMesh(const SPtr<Camera>& camera, const Vector<IconData>& iconData, bool forPicking,
  374. IconRenderDataVecPtr& renderData);
  375. /** Resizes the icon width/height so it is always scaled to optimal size (with preserved aspect). */
  376. void limitIconSize(UINT32& width, UINT32& height);
  377. /** Converts mesh data from DrawHelper into mesh data usable by the gizmo renderer. */
  378. Vector<MeshRenderData> createMeshProxyData(const Vector<DrawHelper::ShapeMeshData>& meshData);
  379. /**
  380. * Calculates colors for an icon based on its position in the camera. For example icons too close to too far might
  381. * be faded.
  382. *
  383. * @param[in] tint Primary tint for the icon.
  384. * @param[in] camera Camera in which the icon will be rendered in.
  385. * @param[in] iconHeight Height of the icon in pixels.
  386. * @param[in] fixedScale Whether the icon size changes depending on distance from the camera.
  387. * @param[in] normalColor Normal color of the icon.
  388. * @param[in] fadedColor Faded color to be used when icon is occluded by geometry.
  389. */
  390. void calculateIconColors(const Color& tint, const SPtr<Camera>& camera, UINT32 iconHeight, bool fixedScale,
  391. Color& normalColor, Color& fadedColor);
  392. static const UINT32 VERTEX_BUFFER_GROWTH;
  393. static const UINT32 INDEX_BUFFER_GROWTH;
  394. static const UINT32 SPHERE_QUALITY;
  395. static const UINT32 WIRE_SPHERE_QUALITY;
  396. static const float MAX_ICON_RANGE;
  397. static const UINT32 OPTIMAL_ICON_SIZE;
  398. static const float ICON_TEXEL_WORLD_SIZE;
  399. typedef Set<IconData, std::function<bool(const IconData&, const IconData&)>> IconSet;
  400. Color mColor;
  401. Matrix4 mTransform;
  402. HSceneObject mActiveSO;
  403. bool mPickable;
  404. UINT32 mCurrentIdx;
  405. bool mTransformDirty;
  406. bool mColorDirty;
  407. DrawHelper* mDrawHelper;
  408. DrawHelper* mPickingDrawHelper;
  409. Vector<CubeData> mSolidCubeData;
  410. Vector<CubeData> mWireCubeData;
  411. Vector<SphereData> mSolidSphereData;
  412. Vector<SphereData> mWireSphereData;
  413. Vector<SphereData> mWireHemisphereData;
  414. Vector<ConeData> mSolidConeData;
  415. Vector<ConeData> mWireConeData;
  416. Vector<LineData> mLineData;
  417. Vector<LineListData> mLineListData;
  418. Vector<DiscData> mSolidDiscData;
  419. Vector<DiscData> mWireDiscData;
  420. Vector<WireArcData> mWireArcData;
  421. Vector<WireMeshData> mWireMeshData;
  422. Vector<FrustumData> mFrustumData;
  423. Vector<IconData> mIconData;
  424. Vector<TextData> mTextData;
  425. Map<UINT32, HSceneObject> mIdxToSceneObjectMap;
  426. Vector<DrawHelper::ShapeMeshData> mActiveMeshes;
  427. SPtr<Mesh> mIconMesh;
  428. SPtr<ct::GizmoRenderer> mGizmoRenderer;
  429. // Immutable
  430. SPtr<VertexDataDesc> mIconVertexDesc;
  431. // Transient
  432. struct SortedIconData
  433. {
  434. float distance;
  435. Vector2I screenPosition;
  436. UINT32 iconIdx;
  437. };
  438. Vector<SortedIconData> mSortedIconData;
  439. };
  440. /** @} */
  441. namespace ct
  442. {
  443. /** @addtogroup Scene-Editor-Internal
  444. * @{
  445. */
  446. BS_PARAM_BLOCK_BEGIN(GizmoParamBlockDef)
  447. BS_PARAM_BLOCK_ENTRY(Matrix4, gMatViewProj)
  448. BS_PARAM_BLOCK_ENTRY(Vector4, gViewDir)
  449. BS_PARAM_BLOCK_ENTRY(float, gInvViewportWidth)
  450. BS_PARAM_BLOCK_ENTRY(float, gInvViewportHeight)
  451. BS_PARAM_BLOCK_ENTRY(float, gViewportYFlip)
  452. BS_PARAM_BLOCK_END
  453. extern GizmoParamBlockDef gGizmoParamBlockDef;
  454. BS_PARAM_BLOCK_BEGIN(GizmoPickingParamBlockDef)
  455. BS_PARAM_BLOCK_ENTRY(Matrix4, gMatViewProj)
  456. BS_PARAM_BLOCK_ENTRY(float, gAlphaCutoff)
  457. BS_PARAM_BLOCK_END
  458. extern GizmoPickingParamBlockDef gGizmoPickingParamBlockDef;
  459. /** Performs rendering of gizmos on the core thread, as managed by the GizmoManager. */
  460. class GizmoRenderer : public RendererExtension
  461. {
  462. friend class bs::GizmoManager;
  463. public:
  464. GizmoRenderer();
  465. private:
  466. /** @copydoc RendererExtension::initialize */
  467. void initialize(const Any& data) override;
  468. /** @copydoc RendererExtension::check */
  469. bool check(const Camera& camera) override;
  470. /** @copydoc RendererExtension::render */
  471. void render(const Camera& camera) override;
  472. /**
  473. * Renders all provided meshes using the provided camera.
  474. *
  475. * @param[in] camera Sets the camera all rendering will be performed to.
  476. * @param[in] meshes Meshes to render.
  477. * @param[in] iconMesh Mesh containing icon meshes.
  478. * @param[in] iconRenderData Icon render data outlining which parts of the icon mesh use which textures.
  479. * @param[in] usePickingMaterial If true, meshes will be rendered using a special picking materials, otherwise
  480. * they'll be rendered using normal drawing materials.
  481. */
  482. void renderData(const SPtr<Camera>& camera, Vector<GizmoManager::MeshRenderData>& meshes,
  483. const SPtr<MeshBase>& iconMesh, const GizmoManager::IconRenderDataVecPtr& iconRenderData,
  484. bool usePickingMaterial);
  485. /**
  486. * Renders the icon gizmo mesh using the provided parameters.
  487. *
  488. * @param[in] screenArea Area of the viewport to render the gizmos in, in pixels.
  489. * @param[in] mesh Mesh containing the icons.
  490. * @param[in] renderData Icon render data outlining which parts of the icon mesh use which textures.
  491. * @param[in] usePickingMaterial Should the icons be rendered normally or for picking.
  492. */
  493. void renderIconGizmos(Rect2I screenArea, SPtr<MeshBase> mesh, GizmoManager::IconRenderDataVecPtr renderData,
  494. bool usePickingMaterial);
  495. /**
  496. * Updates the internal data that is used for rendering. Normally you would call this after updating the camera or
  497. * meshes on the sim thread.
  498. *
  499. * @param[in] camera Sets the camera all rendering will be performed to.
  500. * @param[in] meshes Meshes to render.
  501. * @param[in] iconMesh Mesh containing icon meshes.
  502. * @param[in] iconRenderData Icon render data outlining which parts of the icon mesh use which textures.
  503. */
  504. void updateData(const SPtr<Camera>& camera, const Vector<GizmoManager::MeshRenderData>& meshes,
  505. const SPtr<MeshBase>& iconMesh, const GizmoManager::IconRenderDataVecPtr& iconRenderData);
  506. static const float PICKING_ALPHA_CUTOFF;
  507. SPtr<Camera> mCamera;
  508. Vector<GizmoManager::MeshRenderData> mMeshes;
  509. SPtr<MeshBase> mIconMesh;
  510. GizmoManager::IconRenderDataVecPtr mIconRenderData;
  511. Vector<SPtr<GpuParamsSet>> mMeshParamSets[(UINT32)GizmoMeshType::Count];
  512. Vector<SPtr<GpuParamsSet>> mIconParamSets;
  513. Vector<SPtr<GpuParamsSet>> mPickingParamSets[2];
  514. SPtr<GpuParamBlockBuffer> mMeshGizmoBuffer;
  515. SPtr<GpuParamBlockBuffer> mIconGizmoBuffer;
  516. SPtr<GpuParamBlockBuffer> mMeshPickingParamBuffer;
  517. SPtr<GpuParamBlockBuffer> mIconPickingParamBuffer;
  518. // Immutable
  519. SPtr<Material> mMeshMaterials[(UINT32)GizmoMeshType::Count];
  520. SPtr<Material> mIconMaterial;
  521. SPtr<Material> mPickingMaterials[2];
  522. };
  523. /** @} */
  524. }
  525. }