DecalSet.h 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. // Copyright (c) 2008-2023 the Urho3D project
  2. // License: MIT
  3. #pragma once
  4. #include "../Container/List.h"
  5. #include "../Graphics/Drawable.h"
  6. #include "../Graphics/Skeleton.h"
  7. #include "../Math/Frustum.h"
  8. namespace Urho3D
  9. {
  10. class IndexBuffer;
  11. class VertexBuffer;
  12. /// %Decal vertex.
  13. struct DecalVertex
  14. {
  15. /// Construct with defaults.
  16. DecalVertex() = default;
  17. /// Construct with position and normal.
  18. DecalVertex(const Vector3& position, const Vector3& normal) :
  19. position_(position),
  20. normal_(normal)
  21. {
  22. }
  23. /// Construct with position, normal and skinning information.
  24. DecalVertex(const Vector3& position, const Vector3& normal, const float* blendWeights, const unsigned char* blendIndices) :
  25. position_(position),
  26. normal_(normal)
  27. {
  28. for (unsigned i = 0; i < 4; ++i)
  29. {
  30. blendWeights_[i] = blendWeights[i];
  31. blendIndices_[i] = blendIndices[i];
  32. }
  33. }
  34. /// Position.
  35. Vector3 position_;
  36. /// Normal.
  37. Vector3 normal_;
  38. /// Texture coordinates.
  39. Vector2 texCoord_;
  40. /// Tangent.
  41. Vector4 tangent_;
  42. /// Blend weights.
  43. float blendWeights_[4]{};
  44. /// Blend indices.
  45. unsigned char blendIndices_[4]{};
  46. };
  47. /// One decal in a decal set.
  48. struct Decal
  49. {
  50. /// Construct with defaults.
  51. Decal() :
  52. timer_(0.0f),
  53. timeToLive_(0.0f)
  54. {
  55. }
  56. /// Add a vertex.
  57. void AddVertex(const DecalVertex& vertex);
  58. /// Calculate local-space bounding box.
  59. void CalculateBoundingBox();
  60. /// Decal age timer.
  61. float timer_;
  62. /// Maximum time to live in seconds (0 = infinite).
  63. float timeToLive_;
  64. /// Local-space bounding box.
  65. BoundingBox boundingBox_;
  66. /// Decal vertices.
  67. Vector<DecalVertex> vertices_;
  68. /// Decal indices.
  69. Vector<unsigned short> indices_;
  70. };
  71. /// %Decal renderer component.
  72. class URHO3D_API DecalSet : public Drawable
  73. {
  74. URHO3D_OBJECT(DecalSet, Drawable);
  75. public:
  76. /// Construct.
  77. explicit DecalSet(Context* context);
  78. /// Destruct.
  79. ~DecalSet() override;
  80. /// Register object factory.
  81. /// @nobind
  82. static void RegisterObject(Context* context);
  83. /// Apply attribute changes that can not be applied immediately. Called after scene load or a network update.
  84. void ApplyAttributes() override;
  85. /// Handle enabled/disabled state change.
  86. void OnSetEnabled() override;
  87. /// Process octree raycast. May be called from a worker thread.
  88. void ProcessRayQuery(const RayOctreeQuery& query, Vector<RayQueryResult>& results) override;
  89. /// Calculate distance and prepare batches for rendering. May be called from worker thread(s), possibly re-entrantly.
  90. void UpdateBatches(const FrameInfo& frame) override;
  91. /// Prepare geometry for rendering. Called from a worker thread if possible (no GPU update).
  92. void UpdateGeometry(const FrameInfo& frame) override;
  93. /// Return whether a geometry update is necessary, and if it can happen in a worker thread.
  94. UpdateGeometryType GetUpdateGeometryType() override;
  95. /// Set material. The material should use a small negative depth bias to avoid Z-fighting.
  96. /// @property
  97. void SetMaterial(Material* material);
  98. /// Set maximum number of decal vertices.
  99. /// @property
  100. void SetMaxVertices(unsigned num);
  101. /// Set maximum number of decal vertex indices.
  102. /// @property
  103. void SetMaxIndices(unsigned num);
  104. /// Set whether to optimize GPU buffer sizes according to current amount of decals. Default false, which will size the buffers according to the maximum vertices/indices. When true, buffers will be reallocated whenever decals are added/removed, which can be worse for performance.
  105. /// @property
  106. void SetOptimizeBufferSize(bool enable);
  107. /// Add a decal at world coordinates, using a target drawable's geometry for reference. If the decal needs to move with the target, the decal component should be created to the target's node. Return true if successful.
  108. bool AddDecal(Drawable* target, const Vector3& worldPosition, const Quaternion& worldRotation, float size, float aspectRatio,
  109. float depth, const Vector2& topLeftUV, const Vector2& bottomRightUV, float timeToLive = 0.0f, float normalCutoff = 0.1f,
  110. unsigned subGeometry = M_MAX_UNSIGNED);
  111. /// Remove n oldest decals.
  112. void RemoveDecals(unsigned num);
  113. /// Remove all decals.
  114. void RemoveAllDecals();
  115. /// Return material.
  116. /// @property
  117. Material* GetMaterial() const;
  118. /// Return number of decals.
  119. /// @property
  120. unsigned GetNumDecals() const { return decals_.Size(); }
  121. /// Retur number of vertices in the decals.
  122. /// @property
  123. unsigned GetNumVertices() const { return numVertices_; }
  124. /// Retur number of vertex indices in the decals.
  125. /// @property
  126. unsigned GetNumIndices() const { return numIndices_; }
  127. /// Return maximum number of decal vertices.
  128. /// @property
  129. unsigned GetMaxVertices() const { return maxVertices_; }
  130. /// Return maximum number of decal vertex indices.
  131. /// @property
  132. unsigned GetMaxIndices() const { return maxIndices_; }
  133. /// Return whether is optimizing GPU buffer sizes according to current amount of decals.
  134. /// @property
  135. bool GetOptimizeBufferSize() const { return optimizeBufferSize_; }
  136. /// Set material attribute.
  137. void SetMaterialAttr(const ResourceRef& value);
  138. /// Set decals attribute.
  139. void SetDecalsAttr(const Vector<byte>& value);
  140. /// Return material attribute.
  141. ResourceRef GetMaterialAttr() const;
  142. /// Return decals attribute.
  143. Vector<byte> GetDecalsAttr() const;
  144. protected:
  145. /// Recalculate the world-space bounding box.
  146. void OnWorldBoundingBoxUpdate() override;
  147. /// Handle node transform being dirtied.
  148. void OnMarkedDirty(Node* node) override;
  149. private:
  150. /// Get triangle faces from the target geometry.
  151. void GetFaces(Vector<Vector<DecalVertex>>& faces, Drawable* target, unsigned batchIndex, const Frustum& frustum,
  152. const Vector3& decalNormal, float normalCutoff);
  153. /// Get triangle face from the target geometry.
  154. void GetFace
  155. (Vector<Vector<DecalVertex>>& faces, Drawable* target, unsigned batchIndex, unsigned i0, unsigned i1, unsigned i2,
  156. const byte* positionData, const byte* normalData, const byte* skinningData,
  157. unsigned positionStride, unsigned normalStride, unsigned skinningStride, const Frustum& frustum,
  158. const Vector3& decalNormal, float normalCutoff);
  159. /// Get bones referenced by skinning data and remap the skinning indices. Return true if successful.
  160. bool GetBones(Drawable* target, unsigned batchIndex, const float* blendWeights, const unsigned char* blendIndices,
  161. unsigned char* newBlendIndices);
  162. /// Calculate UV coordinates for the decal.
  163. void CalculateUVs
  164. (Decal& decal, const Matrix3x4& view, const Matrix4& projection, const Vector2& topLeftUV, const Vector2& bottomRightUV);
  165. /// Transform decal's vertices from the target geometry to the decal set local space.
  166. void TransformVertices(Decal& decal, const Matrix3x4& transform);
  167. /// Remove a decal by iterator and return iterator to the next decal.
  168. List<Decal>::Iterator RemoveDecal(List<Decal>::Iterator i);
  169. /// Mark decals and the bounding box dirty.
  170. void MarkDecalsDirty();
  171. /// Recalculate the local-space bounding box.
  172. void CalculateBoundingBox();
  173. /// Rewrite decal vertex and index buffers.
  174. void UpdateBuffers();
  175. /// Recalculate skinning.
  176. void UpdateSkinning();
  177. /// Update the batch (geometry type, shader data).
  178. void UpdateBatch();
  179. /// Find bones after loading.
  180. void AssignBoneNodes();
  181. /// Subscribe/unsubscribe from scene post-update as necessary.
  182. void UpdateEventSubscription(bool checkAllDecals);
  183. /// Handle scene post-update event.
  184. void HandleScenePostUpdate(StringHash eventType, VariantMap& eventData);
  185. /// Geometry.
  186. SharedPtr<Geometry> geometry_;
  187. /// Vertex buffer.
  188. SharedPtr<VertexBuffer> vertexBuffer_;
  189. /// Index buffer.
  190. SharedPtr<IndexBuffer> indexBuffer_;
  191. /// Decals.
  192. List<Decal> decals_;
  193. /// Bones used for skinned decals.
  194. Vector<Bone> bones_;
  195. /// Skinning matrices.
  196. Vector<Matrix3x4> skinMatrices_;
  197. /// Vertices in the current decals.
  198. unsigned numVertices_;
  199. /// Indices in the current decals.
  200. unsigned numIndices_;
  201. /// Maximum vertices.
  202. unsigned maxVertices_;
  203. /// Maximum indices.
  204. unsigned maxIndices_;
  205. /// Optimize buffer sizes flag.
  206. bool optimizeBufferSize_;
  207. /// Skinned mode flag.
  208. bool skinned_;
  209. /// Vertex buffer needs rewrite / resizing flag.
  210. bool bufferDirty_;
  211. /// Bounding box needs update flag.
  212. bool boundingBoxDirty_;
  213. /// Skinning dirty flag.
  214. bool skinningDirty_;
  215. /// Bone nodes assignment pending flag.
  216. bool assignBonesPending_;
  217. /// Subscribed to scene post update event flag.
  218. bool subscribed_;
  219. };
  220. }