DecalSet.h 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. //
  2. // Copyright (c) 2008-2017 the Urho3D project.
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #pragma once
  23. #include "../Container/List.h"
  24. #include "../Graphics/Drawable.h"
  25. #include "../Graphics/Skeleton.h"
  26. #include "../Math/Frustum.h"
  27. namespace Atomic
  28. {
  29. class IndexBuffer;
  30. class VertexBuffer;
  31. /// %Decal vertex.
  32. struct DecalVertex
  33. {
  34. /// Construct with defaults.
  35. DecalVertex()
  36. {
  37. }
  38. /// Construct with position and normal.
  39. DecalVertex(const Vector3& position, const Vector3& normal) :
  40. position_(position),
  41. normal_(normal)
  42. {
  43. }
  44. /// Construct with position, normal and skinning information.
  45. DecalVertex(const Vector3& position, const Vector3& normal, const float* blendWeights, const unsigned char* blendIndices) :
  46. position_(position),
  47. normal_(normal)
  48. {
  49. for (unsigned i = 0; i < 4; ++i)
  50. {
  51. blendWeights_[i] = blendWeights[i];
  52. blendIndices_[i] = blendIndices[i];
  53. }
  54. }
  55. /// Position.
  56. Vector3 position_;
  57. /// Normal.
  58. Vector3 normal_;
  59. /// Texture coordinates.
  60. Vector2 texCoord_;
  61. /// Tangent.
  62. Vector4 tangent_;
  63. /// Blend weights.
  64. float blendWeights_[4];
  65. /// Blend indices.
  66. unsigned char blendIndices_[4];
  67. };
  68. /// One decal in a decal set.
  69. struct Decal
  70. {
  71. /// Construct with defaults.
  72. Decal() :
  73. timer_(0.0f),
  74. timeToLive_(0.0f)
  75. {
  76. }
  77. /// Add a vertex.
  78. void AddVertex(const DecalVertex& vertex);
  79. /// Calculate local-space bounding box.
  80. void CalculateBoundingBox();
  81. /// Decal age timer.
  82. float timer_;
  83. /// Maximum time to live in seconds (0 = infinite)
  84. float timeToLive_;
  85. /// Local-space bounding box.
  86. BoundingBox boundingBox_;
  87. /// Decal vertices.
  88. PODVector<DecalVertex> vertices_;
  89. /// Decal indices.
  90. PODVector<unsigned short> indices_;
  91. };
  92. /// %Decal renderer component.
  93. class ATOMIC_API DecalSet : public Drawable
  94. {
  95. ATOMIC_OBJECT(DecalSet, Drawable);
  96. public:
  97. /// Construct.
  98. DecalSet(Context* context);
  99. /// Destruct.
  100. virtual ~DecalSet();
  101. /// Register object factory.
  102. static void RegisterObject(Context* context);
  103. /// Apply attribute changes that can not be applied immediately. Called after scene load or a network update.
  104. virtual void ApplyAttributes();
  105. /// Handle enabled/disabled state change.
  106. virtual void OnSetEnabled();
  107. /// Process octree raycast. May be called from a worker thread.
  108. virtual void ProcessRayQuery(const RayOctreeQuery& query, PODVector<RayQueryResult>& results);
  109. /// Calculate distance and prepare batches for rendering. May be called from worker thread(s), possibly re-entrantly.
  110. virtual void UpdateBatches(const FrameInfo& frame);
  111. /// Prepare geometry for rendering. Called from a worker thread if possible (no GPU update.)
  112. virtual void UpdateGeometry(const FrameInfo& frame);
  113. /// Return whether a geometry update is necessary, and if it can happen in a worker thread.
  114. virtual UpdateGeometryType GetUpdateGeometryType();
  115. /// Set material. The material should use a small negative depth bias to avoid Z-fighting.
  116. void SetMaterial(Material* material);
  117. /// Set maximum number of decal vertices.
  118. void SetMaxVertices(unsigned num);
  119. /// Set maximum number of decal vertex indices.
  120. void SetMaxIndices(unsigned num);
  121. /// 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.
  122. void SetOptimizeBufferSize(bool enable);
  123. /// 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.
  124. bool AddDecal(Drawable* target, const Vector3& worldPosition, const Quaternion& worldRotation, float size, float aspectRatio,
  125. float depth, const Vector2& topLeftUV, const Vector2& bottomRightUV, float timeToLive = 0.0f, float normalCutoff = 0.1f,
  126. unsigned subGeometry = M_MAX_UNSIGNED);
  127. /// Remove n oldest decals.
  128. void RemoveDecals(unsigned num);
  129. /// Remove all decals.
  130. void RemoveAllDecals();
  131. /// Return material.
  132. Material* GetMaterial() const;
  133. /// Return number of decals.
  134. unsigned GetNumDecals() const { return decals_.Size(); }
  135. /// Retur number of vertices in the decals.
  136. unsigned GetNumVertices() const { return numVertices_; }
  137. /// Retur number of vertex indices in the decals.
  138. unsigned GetNumIndices() const { return numIndices_; }
  139. /// Return maximum number of decal vertices.
  140. unsigned GetMaxVertices() const { return maxVertices_; }
  141. /// Return maximum number of decal vertex indices.
  142. unsigned GetMaxIndices() const { return maxIndices_; }
  143. /// Return whether is optimizing GPU buffer sizes according to current amount of decals.
  144. bool GetOptimizeBufferSize() const { return optimizeBufferSize_; }
  145. /// Set material attribute.
  146. void SetMaterialAttr(const ResourceRef& value);
  147. /// Set decals attribute.
  148. void SetDecalsAttr(const PODVector<unsigned char>& value);
  149. /// Return material attribute.
  150. ResourceRef GetMaterialAttr() const;
  151. /// Return decals attribute.
  152. PODVector<unsigned char> GetDecalsAttr() const;
  153. protected:
  154. /// Recalculate the world-space bounding box.
  155. virtual void OnWorldBoundingBoxUpdate();
  156. /// Handle node transform being dirtied.
  157. virtual void OnMarkedDirty(Node* node);
  158. private:
  159. /// Get triangle faces from the target geometry.
  160. void GetFaces(Vector<PODVector<DecalVertex> >& faces, Drawable* target, unsigned batchIndex, const Frustum& frustum,
  161. const Vector3& decalNormal, float normalCutoff);
  162. /// Get triangle face from the target geometry.
  163. void GetFace
  164. (Vector<PODVector<DecalVertex> >& faces, Drawable* target, unsigned batchIndex, unsigned i0, unsigned i1, unsigned i2,
  165. const unsigned char* positionData, const unsigned char* normalData, const unsigned char* skinningData,
  166. unsigned positionStride, unsigned normalStride, unsigned skinningStride, const Frustum& frustum,
  167. const Vector3& decalNormal, float normalCutoff);
  168. /// Get bones referenced by skinning data and remap the skinning indices. Return true if successful.
  169. bool GetBones(Drawable* target, unsigned batchIndex, const float* blendWeights, const unsigned char* blendIndices,
  170. unsigned char* newBlendIndices);
  171. /// Calculate UV coordinates for the decal.
  172. void CalculateUVs
  173. (Decal& decal, const Matrix3x4& view, const Matrix4& projection, const Vector2& topLeftUV, const Vector2& bottomRightUV);
  174. /// Transform decal's vertices from the target geometry to the decal set local space.
  175. void TransformVertices(Decal& decal, const Matrix3x4& transform);
  176. /// Remove a decal by iterator and return iterator to the next decal.
  177. List<Decal>::Iterator RemoveDecal(List<Decal>::Iterator i);
  178. /// Mark decals and the bounding box dirty.
  179. void MarkDecalsDirty();
  180. /// Recalculate the local-space bounding box.
  181. void CalculateBoundingBox();
  182. /// Rewrite decal vertex and index buffers.
  183. void UpdateBuffers();
  184. /// Recalculate skinning.
  185. void UpdateSkinning();
  186. /// Update the batch (geometry type, shader data.)
  187. void UpdateBatch();
  188. /// Find bones after loading.
  189. void AssignBoneNodes();
  190. /// Subscribe/unsubscribe from scene post-update as necessary.
  191. void UpdateEventSubscription(bool checkAllDecals);
  192. /// Handle scene post-update event.
  193. void HandleScenePostUpdate(StringHash eventType, VariantMap& eventData);
  194. /// Geometry.
  195. SharedPtr<Geometry> geometry_;
  196. /// Vertex buffer.
  197. SharedPtr<VertexBuffer> vertexBuffer_;
  198. /// Index buffer.
  199. SharedPtr<IndexBuffer> indexBuffer_;
  200. /// Decals.
  201. List<Decal> decals_;
  202. /// Bones used for skinned decals.
  203. Vector<Bone> bones_;
  204. /// Skinning matrices.
  205. PODVector<Matrix3x4> skinMatrices_;
  206. /// Vertices in the current decals.
  207. unsigned numVertices_;
  208. /// Indices in the current decals.
  209. unsigned numIndices_;
  210. /// Maximum vertices.
  211. unsigned maxVertices_;
  212. /// Maximum indices.
  213. unsigned maxIndices_;
  214. /// Optimize buffer sizes flag.
  215. bool optimizeBufferSize_;
  216. /// Skinned mode flag.
  217. bool skinned_;
  218. /// Vertex buffer needs rewrite / resizing flag.
  219. bool bufferDirty_;
  220. /// Bounding box needs update flag.
  221. bool boundingBoxDirty_;
  222. /// Skinning dirty flag.
  223. bool skinningDirty_;
  224. /// Bone nodes assignment pending flag.
  225. bool assignBonesPending_;
  226. /// Subscribed to scene post update event flag.
  227. bool subscribed_;
  228. };
  229. }