RuntimeMeshCore.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. // Copyright 2016 Chris Conway (Koderz). All Rights Reserved.
  2. #pragma once
  3. #include "Engine.h"
  4. #include "Components/MeshComponent.h"
  5. #include "RuntimeMeshProfiling.h"
  6. #include "RuntimeMeshVersion.h"
  7. #include "Runtime/Launch/Resources/Version.h"
  8. #include "RuntimeMeshCore.generated.h"
  9. class FRuntimeMeshVertexFactory;
  10. template<typename T>
  11. struct FRuntimeMeshVertexTraits
  12. {
  13. private:
  14. template<typename C, C> struct ChT;
  15. struct FallbackPosition { FVector Position; };
  16. struct DerivedPosition : T, FallbackPosition { };
  17. template<typename C> static char(&PositionCheck(ChT<FVector FallbackPosition::*, &C::Position>*))[1];
  18. template<typename C> static char(&PositionCheck(...))[2];
  19. struct FallbackNormal { FPackedRGBA16N Normal; };
  20. struct DerivedNormal : T, FallbackNormal { };
  21. template<typename C> static char(&NormalCheck(ChT<FPackedRGBA16N FallbackNormal::*, &C::Normal>*))[1];
  22. template<typename C> static char(&NormalCheck(...))[2];
  23. struct FallbackTangent { FPackedRGBA16N Tangent; };
  24. struct DerivedTangent : T, FallbackTangent { };
  25. template<typename C> static char(&TangentCheck(ChT<FPackedRGBA16N FallbackTangent::*, &C::Tangent>*))[1];
  26. template<typename C> static char(&TangentCheck(...))[2];
  27. struct FallbackColor { FColor Color; };
  28. struct DerivedColor : T, FallbackColor { };
  29. template<typename C> static char(&ColorCheck(ChT<FColor FallbackColor::*, &C::Color>*))[1];
  30. template<typename C> static char(&ColorCheck(...))[2];
  31. struct FallbackUV0 { FVector2D UV0; };
  32. struct DerivedUV0 : T, FallbackUV0 { };
  33. template<typename C> static char(&UV0Check(ChT<FVector2D FallbackUV0::*, &C::UV0>*))[1];
  34. template<typename C> static char(&UV0Check(...))[2];
  35. struct FallbackUV1 { FVector2D UV1; };
  36. struct DerivedUV1 : T, FallbackUV1 { };
  37. template<typename C> static char(&UV1Check(ChT<FVector2D FallbackUV1::*, &C::UV1>*))[1];
  38. template<typename C> static char(&UV1Check(...))[2];
  39. struct FallbackUV2 { FVector2D UV2; };
  40. struct DerivedUV2 : T, FallbackUV2 { };
  41. template<typename C> static char(&UV2Check(ChT<FVector2D FallbackUV2::*, &C::UV2>*))[1];
  42. template<typename C> static char(&UV2Check(...))[2];
  43. struct FallbackUV3 { FVector2D UV3; };
  44. struct DerivedUV3 : T, FallbackUV3 { };
  45. template<typename C> static char(&UV3Check(ChT<FVector2D FallbackUV3::*, &C::UV3>*))[1];
  46. template<typename C> static char(&UV3Check(...))[2];
  47. struct FallbackUV4 { FVector2D UV4; };
  48. struct DerivedUV4 : T, FallbackUV4 { };
  49. template<typename C> static char(&UV4Check(ChT<FVector2D FallbackUV4::*, &C::UV4>*))[1];
  50. template<typename C> static char(&UV4Check(...))[2];
  51. struct FallbackUV5 { FVector2D UV5; };
  52. struct DerivedUV5 : T, FallbackUV5 { };
  53. template<typename C> static char(&UV5Check(ChT<FVector2D FallbackUV5::*, &C::UV5>*))[1];
  54. template<typename C> static char(&UV5Check(...))[2];
  55. struct FallbackUV6 { FVector2D UV6; };
  56. struct DerivedUV6 : T, FallbackUV6 { };
  57. template<typename C> static char(&UV6Check(ChT<FVector2D FallbackUV6::*, &C::UV6>*))[1];
  58. template<typename C> static char(&UV6Check(...))[2];
  59. struct FallbackUV7 { FVector2D UV7; };
  60. struct DerivedUV7 : T, FallbackUV7 { };
  61. template<typename C> static char(&UV7Check(ChT<FVector2D FallbackUV7::*, &C::UV7>*))[1];
  62. template<typename C> static char(&UV7Check(...))[2];
  63. template<typename A, typename B>
  64. struct IsSameType
  65. {
  66. static const bool Value = false;
  67. };
  68. template<typename A>
  69. struct IsSameType<A, A>
  70. {
  71. static const bool Value = true;
  72. };
  73. template<bool HasNormal, bool HasTangent, typename Type>
  74. struct TangentBasisHighPrecisionDetector
  75. {
  76. static const bool Value = false;
  77. };
  78. template<typename Type>
  79. struct TangentBasisHighPrecisionDetector<true, false, Type>
  80. {
  81. static const bool Value = IsSameType<decltype(DeclVal<T>().Normal), FPackedRGBA16N>::Value;
  82. };
  83. template<bool HasNormal, typename Type>
  84. struct TangentBasisHighPrecisionDetector<HasNormal, true, Type>
  85. {
  86. static const bool Value = IsSameType<decltype(DeclVal<T>().Tangent), FPackedRGBA16N>::Value;
  87. };
  88. template<bool HasUV0, typename Type>
  89. struct UVChannelHighPrecisionDetector
  90. {
  91. static const bool Value = false;
  92. };
  93. template<typename Type>
  94. struct UVChannelHighPrecisionDetector<true, Type>
  95. {
  96. static const bool Value = IsSameType<decltype(DeclVal<T>().UV0), FVector2D>::Value;
  97. };
  98. public:
  99. static const bool HasPosition = sizeof(PositionCheck<DerivedPosition>(0)) == 2;
  100. static const bool HasNormal = sizeof(NormalCheck<DerivedNormal>(0)) == 2;
  101. static const bool HasTangent = sizeof(TangentCheck<DerivedTangent>(0)) == 2;
  102. static const bool HasColor = sizeof(ColorCheck<DerivedColor>(0)) == 2;
  103. static const bool HasUV0 = sizeof(UV0Check<DerivedUV0>(0)) == 2;
  104. static const bool HasUV1 = sizeof(UV1Check<DerivedUV1>(0)) == 2;
  105. static const bool HasUV2 = sizeof(UV2Check<DerivedUV2>(0)) == 2;
  106. static const bool HasUV3 = sizeof(UV3Check<DerivedUV3>(0)) == 2;
  107. static const bool HasUV4 = sizeof(UV4Check<DerivedUV4>(0)) == 2;
  108. static const bool HasUV5 = sizeof(UV5Check<DerivedUV5>(0)) == 2;
  109. static const bool HasUV6 = sizeof(UV6Check<DerivedUV6>(0)) == 2;
  110. static const bool HasUV7 = sizeof(UV7Check<DerivedUV7>(0)) == 2;
  111. static const int32 NumUVChannels =
  112. (HasUV0 ? 1 : 0) +
  113. (HasUV1 ? 1 : 0) +
  114. (HasUV2 ? 1 : 0) +
  115. (HasUV3 ? 1 : 0) +
  116. (HasUV4 ? 1 : 0) +
  117. (HasUV5 ? 1 : 0) +
  118. (HasUV6 ? 1 : 0) +
  119. (HasUV7 ? 1 : 0);
  120. static const bool HasHighPrecisionNormals = TangentBasisHighPrecisionDetector<HasNormal, HasTangent, T>::Value;
  121. static const bool HasHighPrecisionUVs = UVChannelHighPrecisionDetector<HasUV0, T>::Value;
  122. };
  123. #if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION >= 12
  124. /** Structure definition of a vertex */
  125. using RuntimeMeshVertexStructure = FLocalVertexFactory::FDataType;
  126. #else
  127. /** Structure definition of a vertex */
  128. using RuntimeMeshVertexStructure = FLocalVertexFactory::DataType;
  129. #endif
  130. #define RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, VertexType, Member, MemberType) \
  131. STRUCTMEMBER_VERTEXSTREAMCOMPONENT(&VertexBuffer, VertexType, Member, MemberType)
  132. /* Update frequency for a section. Used to optimize for update or render speed*/
  133. UENUM(BlueprintType)
  134. enum class EUpdateFrequency : uint8
  135. {
  136. /* Tries to skip recreating the scene proxy if possible. */
  137. Average UMETA(DisplayName = "Average"),
  138. /* Tries to skip recreating the scene proxy if possible and optimizes the buffers for frequent updates. */
  139. Frequent UMETA(DisplayName = "Frequent"),
  140. /* If the component is static it will try to use the static rendering path (this will force a recreate of the scene proxy) */
  141. Infrequent UMETA(DisplayName = "Infrequent")
  142. };
  143. /* Control flags for update actions */
  144. enum class ESectionUpdateFlags
  145. {
  146. None = 0x0,
  147. /**
  148. * This will use move-assignment when copying the supplied vertices/triangles into the section.
  149. * This is faster as it doesn't require copying the data.
  150. *
  151. * CAUTION: This means that your copy of the arrays will be cleared!
  152. */
  153. MoveArrays = 0x1,
  154. /**
  155. * Should the normals and tangents be calculated automatically?
  156. * To do this manually see RuntimeMeshLibrary::CalculateTangentsForMesh()
  157. */
  158. CalculateNormalTangent = 0x2,
  159. /**
  160. * Should the tessellation indices be calculated to support tessellation?
  161. * To do this manually see RuntimeMeshLibrary::GenerateTessellationIndexBuffer()
  162. */
  163. CalculateTessellationIndices = 0x4,
  164. };
  165. ENUM_CLASS_FLAGS(ESectionUpdateFlags)
  166. /**
  167. * Struct used to specify a tangent vector for a vertex
  168. * The Y tangent is computed from the cross product of the vertex normal (Tangent Z) and the TangentX member.
  169. */
  170. USTRUCT(BlueprintType)
  171. struct FRuntimeMeshTangent
  172. {
  173. GENERATED_USTRUCT_BODY()
  174. /** Direction of X tangent for this vertex */
  175. UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Tangent)
  176. FVector TangentX;
  177. /** Bool that indicates whether we should flip the Y tangent when we compute it using cross product */
  178. UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Tangent)
  179. bool bFlipTangentY;
  180. FRuntimeMeshTangent()
  181. : TangentX(1.f, 0.f, 0.f)
  182. , bFlipTangentY(false)
  183. {}
  184. FRuntimeMeshTangent(float X, float Y, float Z, bool bInFlipTangentY = false)
  185. : TangentX(X, Y, Z)
  186. , bFlipTangentY(bInFlipTangentY)
  187. {}
  188. FRuntimeMeshTangent(FVector InTangentX, bool bInFlipTangentY = false)
  189. : TangentX(InTangentX)
  190. , bFlipTangentY(bInFlipTangentY)
  191. {}
  192. void AdjustNormal(FPackedNormal& Normal) const
  193. {
  194. Normal.Vector.W = bFlipTangentY ? 0 : 255;
  195. }
  196. void AdjustNormal(FPackedRGBA16N& Normal) const
  197. {
  198. Normal.W = bFlipTangentY ? 0 : 65535;
  199. }
  200. };
  201. /*
  202. * Configuration flag for the collision cooking to prioritize cooking speed or collision performance.
  203. */
  204. UENUM(BlueprintType)
  205. enum class ERuntimeMeshCollisionCookingMode : uint8
  206. {
  207. /*
  208. * Favors runtime collision performance of cooking speed.
  209. * This means that cooking a new mesh will be slower, but collision will be faster.
  210. */
  211. CollisionPerformance UMETA(DisplayName = "Collision Performance"),
  212. /*
  213. * Favors cooking speed over collision performance.
  214. * This means that cooking a new mesh will be faster, but collision will be slower.
  215. */
  216. CookingPerformance UMETA(DisplayName = "Cooking Performance"),
  217. };
  218. /* The different buffers within the Runtime Mesh Component */
  219. enum class ERuntimeMeshBuffer
  220. {
  221. None = 0x0,
  222. Vertices = 0x1,
  223. Triangles = 0x2,
  224. Positions = 0x4
  225. };
  226. ENUM_CLASS_FLAGS(ERuntimeMeshBuffer)
  227. USTRUCT()
  228. struct FRuntimeMeshCollisionSection
  229. {
  230. GENERATED_BODY()
  231. UPROPERTY()
  232. TArray<FVector> VertexBuffer;
  233. UPROPERTY()
  234. TArray<int32> IndexBuffer;
  235. void Reset()
  236. {
  237. VertexBuffer.Empty();
  238. IndexBuffer.Empty();
  239. }
  240. friend FArchive& operator <<(FArchive& Ar, FRuntimeMeshCollisionSection& Section)
  241. {
  242. Ar << Section.VertexBuffer;
  243. Ar << Section.IndexBuffer;
  244. return Ar;
  245. }
  246. };
  247. USTRUCT()
  248. struct FRuntimeConvexCollisionSection
  249. {
  250. GENERATED_BODY()
  251. UPROPERTY()
  252. TArray<FVector> VertexBuffer;
  253. UPROPERTY()
  254. FBox BoundingBox;
  255. void Reset()
  256. {
  257. VertexBuffer.Empty();
  258. BoundingBox.Init();
  259. }
  260. friend FArchive& operator <<(FArchive& Ar, FRuntimeConvexCollisionSection& Section)
  261. {
  262. Ar << Section.VertexBuffer;
  263. Ar << Section.BoundingBox;
  264. return Ar;
  265. }
  266. };
  267. struct RUNTIMEMESHCOMPONENT_API FRuntimeMeshVertexTypeInfo
  268. {
  269. const FString TypeName;
  270. const FGuid TypeGuid;
  271. FRuntimeMeshVertexTypeInfo(FString Name, FGuid Guid) : TypeName(Name), TypeGuid(Guid) { }
  272. virtual bool Equals(const FRuntimeMeshVertexTypeInfo* Other) const
  273. {
  274. return TypeGuid == Other->TypeGuid;
  275. }
  276. template<typename Type>
  277. void EnsureEquals() const
  278. {
  279. if (!Equals(&Type::TypeInfo))
  280. {
  281. ThrowMismatchException(Type::TypeInfo.TypeName);
  282. }
  283. }
  284. virtual class FRuntimeMeshSectionInterface* CreateSection(bool bInNeedsPositionOnlyBuffer) const = 0;
  285. protected:
  286. void ThrowMismatchException(const FString& OtherName) const
  287. {
  288. UE_LOG(RuntimeMeshLog, Fatal, TEXT("Vertex Type Mismatch: %s and %s"), *TypeName, *OtherName);
  289. }
  290. };
  291. /*
  292. * Internal container used to track known vertex types, for serialization and other purposes.
  293. */
  294. class RUNTIMEMESHCOMPONENT_API FRuntimeMeshVertexTypeRegistrationContainer
  295. {
  296. struct VertexRegistration
  297. {
  298. const FRuntimeMeshVertexTypeInfo* const TypeInfo;
  299. uint32 ReferenceCount;
  300. VertexRegistration(const FRuntimeMeshVertexTypeInfo* const InTypeInfo)
  301. : TypeInfo(InTypeInfo), ReferenceCount(1) { }
  302. };
  303. TMap<FGuid, VertexRegistration> Registrations;
  304. public:
  305. static FRuntimeMeshVertexTypeRegistrationContainer& GetInstance();
  306. void Register(const FRuntimeMeshVertexTypeInfo* InType);
  307. void UnRegister(const FRuntimeMeshVertexTypeInfo* InType);
  308. const FRuntimeMeshVertexTypeInfo* GetVertexType(FGuid Key) const;
  309. };
  310. template<typename VertexType>
  311. class FRuntimeMeshVertexTypeRegistration : FNoncopyable
  312. {
  313. public:
  314. FRuntimeMeshVertexTypeRegistration()
  315. {
  316. FRuntimeMeshVertexTypeRegistrationContainer::GetInstance().Register(&VertexType::TypeInfo);
  317. }
  318. ~FRuntimeMeshVertexTypeRegistration()
  319. {
  320. FRuntimeMeshVertexTypeRegistrationContainer::GetInstance().UnRegister(&VertexType::TypeInfo);
  321. }
  322. };
  323. #define DECLARE_RUNTIMEMESH_CUSTOMVERTEX_TYPEINFO(TypeName, Guid) \
  324. struct FRuntimeMeshVertexTypeInfo_##TypeName : public FRuntimeMeshVertexTypeInfo \
  325. { \
  326. FRuntimeMeshVertexTypeInfo_##TypeName() : FRuntimeMeshVertexTypeInfo(TEXT(#TypeName), Guid) { } \
  327. }; \
  328. static const FRuntimeMeshVertexTypeInfo_##TypeName TypeInfo;
  329. #define DEFINE_RUNTIMEMESH_CUSTOMVERTEX_TYPEINFO(TypeName) \
  330. const TypeName::FRuntimeMeshVertexTypeInfo_##TypeName TypeName::TypeInfo = TypeName::FRuntimeMeshVertexTypeInfo_##TypeName(); \
  331. FRuntimeMeshVertexTypeRegistration<##TypeName> FRuntimeMeshVertexTypeInfoRegistration_##TypeName(&##TypeName::TypeInfo);