// Copyright 2016 Chris Conway (Koderz). All Rights Reserved. #pragma once #include "RuntimeMeshCore.h" ////////////////////////////////////////////////////////////////////////// // // This file contains a generic vertex structure capable of efficiently representing a vertex // with any combination of position, normal, tangent, color, and 0-8 uv channels. // // To get around an issue with MSVC and potentially other compilers not performing // empty base class optimizations (EBO) to children in multiple inheritance, // this vertex is built via a tree of inheritance using partial specializations. // // At each tier of this tree partial specialization will choose which components // we need to add in, thereby removing entire inherited classes when we don't need them. // // Structure: // FRuntimeMeshVertex // / \ // FRuntimeMeshPositionNormalTangentComponentCombiner FRuntimeMeshColorUVComponentCombiner // / \ / \ // FRuntimeMeshPositionComponent \ FRuntimeMeshColorComponent \ // \ \ // FRuntimeMeshNormalTangentComponents FRuntimeMeshUVComponents // // // // // // Example use: (This defines a vertex with all components and 1 UV with default precision for normal/tangent and UV) // // using MyVertex = FRuntimeMeshVertex; // // MyVertex Vertex; // Vertex.Position = FVector(0,0,0); // Vertex.Normal = FVector(0,0,0); // Vertex.UV0 = FVector2D(0,0); // // ////////////////////////////////////////////////////////////////////////// template RuntimeMeshVertexStructure CreateVertexStructure(const FVertexBuffer& VertexBuffer); ////////////////////////////////////////////////////////////////////////// // Texture Component Type Selector ////////////////////////////////////////////////////////////////////////// enum class ERuntimeMeshVertexUVType { Default = 1, HighPrecision = 2, }; template struct FRuntimeMeshVertexUVsTypeSelector; template<> struct FRuntimeMeshVertexUVsTypeSelector { typedef FVector2DHalf UVsType; static const EVertexElementType VertexElementType1Channel = VET_Half2; static const EVertexElementType VertexElementType2Channel = VET_Half4; }; template<> struct FRuntimeMeshVertexUVsTypeSelector { typedef FVector2D UVsType; static const EVertexElementType VertexElementType1Channel = VET_Float2; static const EVertexElementType VertexElementType2Channel = VET_Float4; }; ////////////////////////////////////////////////////////////////////////// // Texture Component ////////////////////////////////////////////////////////////////////////// /* Defines the UV coordinates for a vertex (Defaulted to 0 channels) */ template struct FRuntimeMeshUVComponents { static_assert(TextureChannels >= 0 && TextureChannels <= 8, "You must have between 0 and 8 (inclusive) UV channels"); }; /* Defines the UV coordinates for a vertex (Specialized to 0 channels) */ template struct FRuntimeMeshUVComponents<0, UVType> { FRuntimeMeshUVComponents() { } FRuntimeMeshUVComponents(EForceInit) { } }; /* Defines the UV coordinates for a vertex (Specialized to 1 channels) */ template struct FRuntimeMeshUVComponents<1, UVType> { UVType UV0; FRuntimeMeshUVComponents() { } FRuntimeMeshUVComponents(EForceInit) : UV0(0, 0) { } FRuntimeMeshUVComponents(const FVector2D& InUV0) : UV0(InUV0) { } }; /* Defines the UV coordinates for a vertex (Specialized to 2 channels) */ template struct FRuntimeMeshUVComponents<2, UVType> { UVType UV0; UVType UV1; FRuntimeMeshUVComponents() { } FRuntimeMeshUVComponents(EForceInit) : UV0(0, 0), UV1(0, 0) { } FRuntimeMeshUVComponents(const FVector2D& InUV0) : UV0(InUV0), UV1(0, 0) { } FRuntimeMeshUVComponents(const FVector2D& InUV0, const FVector2D& InUV1) : UV0(InUV0), UV1(InUV1) { } }; /* Defines the UV coordinates for a vertex (Specialized to 3 channels) */ template struct FRuntimeMeshUVComponents<3, UVType> { UVType UV0; UVType UV1; UVType UV2; FRuntimeMeshUVComponents() { } FRuntimeMeshUVComponents(EForceInit) : UV0(0, 0), UV1(0, 0), UV2(0, 0) { } FRuntimeMeshUVComponents(const FVector2D& InUV0) : UV0(InUV0), UV1(0, 0), UV2(0, 0) { } FRuntimeMeshUVComponents(const FVector2D& InUV0, const FVector2D& InUV1) : UV0(InUV0), UV1(InUV1), UV2(0, 0) { } FRuntimeMeshUVComponents(const FVector2D& InUV0, const FVector2D& InUV1, const FVector2D& InUV2) : UV0(InUV0), UV1(InUV1), UV2(InUV2) { } }; /* Defines the UV coordinates for a vertex (Specialized to 4 channels) */ template struct FRuntimeMeshUVComponents<4, UVType> { UVType UV0; UVType UV1; UVType UV2; UVType UV3; FRuntimeMeshUVComponents() { } FRuntimeMeshUVComponents(EForceInit) : UV0(0, 0), UV1(0, 0), UV2(0, 0), UV3(0, 0) { } FRuntimeMeshUVComponents(const FVector2D& InUV0) : UV0(InUV0), UV1(0, 0), UV2(0, 0), UV3(0, 0) { } FRuntimeMeshUVComponents(const FVector2D& InUV0, const FVector2D& InUV1) : UV0(InUV0), UV1(InUV1), UV2(0, 0), UV3(0, 0) { } FRuntimeMeshUVComponents(const FVector2D& InUV0, const FVector2D& InUV1, const FVector2D& InUV2) : UV0(InUV0), UV1(InUV1), UV2(InUV2), UV3(0, 0) { } FRuntimeMeshUVComponents(const FVector2D& InUV0, const FVector2D& InUV1, const FVector2D& InUV2, const FVector2D& InUV3) : UV0(InUV0), UV1(InUV1), UV2(InUV2), UV3(InUV3) { } }; /* Defines the UV coordinates for a vertex (Specialized to 5 channels) */ template struct FRuntimeMeshUVComponents<5, UVType> { UVType UV0; UVType UV1; UVType UV2; UVType UV3; UVType UV4; FRuntimeMeshUVComponents() { } FRuntimeMeshUVComponents(EForceInit) : UV0(0, 0), UV1(0, 0), UV2(0, 0), UV3(0, 0), UV4(0, 0) { } FRuntimeMeshUVComponents(const FVector2D& InUV0) : UV0(InUV0), UV1(0, 0), UV2(0, 0), UV3(0, 0), UV4(0, 0) { } FRuntimeMeshUVComponents(const FVector2D& InUV0, const FVector2D& InUV1) : UV0(InUV0), UV1(InUV1), UV2(0, 0), UV3(0, 0), UV4(0, 0) { } FRuntimeMeshUVComponents(const FVector2D& InUV0, const FVector2D& InUV1, const FVector2D& InUV2) : UV0(InUV0), UV1(InUV1), UV2(InUV2), UV3(0, 0), UV4(0, 0) { } FRuntimeMeshUVComponents(const FVector2D& InUV0, const FVector2D& InUV1, const FVector2D& InUV2, const FVector2D& InUV3) : UV0(InUV0), UV1(InUV1), UV2(InUV2), UV3(InUV3), UV4(0, 0) { } FRuntimeMeshUVComponents(const FVector2D& InUV0, const FVector2D& InUV1, const FVector2D& InUV2, const FVector2D& InUV3, const FVector2D& InUV4) : UV0(InUV0), UV1(InUV1), UV2(InUV2), UV3(InUV3), UV4(InUV4) { } }; /* Defines the UV coordinates for a vertex (Specialized to 6 channels, Half Precision) */ template struct FRuntimeMeshUVComponents<6, UVType> { UVType UV0; UVType UV1; UVType UV2; UVType UV3; UVType UV4; UVType UV5; FRuntimeMeshUVComponents() { } FRuntimeMeshUVComponents(EForceInit) : UV0(0, 0), UV1(0, 0), UV2(0, 0), UV3(0, 0), UV4(0, 0), UV5(0, 0) { } FRuntimeMeshUVComponents(const FVector2D& InUV0) : UV0(InUV0), UV1(0, 0), UV2(0, 0), UV3(0, 0), UV4(0, 0), UV5(0, 0) { } FRuntimeMeshUVComponents(const FVector2D& InUV0, const FVector2D& InUV1) : UV0(InUV0), UV1(InUV1), UV2(0, 0), UV3(0, 0), UV4(0, 0), UV5(0, 0) { } FRuntimeMeshUVComponents(const FVector2D& InUV0, const FVector2D& InUV1, const FVector2D& InUV2) : UV0(InUV0), UV1(InUV1), UV2(InUV2), UV3(0, 0), UV4(0, 0), UV5(0, 0) { } FRuntimeMeshUVComponents(const FVector2D& InUV0, const FVector2D& InUV1, const FVector2D& InUV2, const FVector2D& InUV3) : UV0(InUV0), UV1(InUV1), UV2(InUV2), UV3(InUV3), UV4(0, 0), UV5(0, 0) { } FRuntimeMeshUVComponents(const FVector2D& InUV0, const FVector2D& InUV1, const FVector2D& InUV2, const FVector2D& InUV3, const FVector2D& InUV4) : UV0(InUV0), UV1(InUV1), UV2(InUV2), UV3(InUV3), UV4(InUV4), UV5(0, 0) { } FRuntimeMeshUVComponents(const FVector2D& InUV0, const FVector2D& InUV1, const FVector2D& InUV2, const FVector2D& InUV3, const FVector2D& InUV4, const FVector2D& InUV5) : UV0(InUV0), UV1(InUV1), UV2(InUV2), UV3(InUV3), UV4(InUV4), UV5(InUV5) { } }; /* Defines the UV coordinates for a vertex (Specialized to 7 channels) */ template struct FRuntimeMeshUVComponents<7, UVType> { UVType UV0; UVType UV1; UVType UV2; UVType UV3; UVType UV4; UVType UV5; UVType UV6; FRuntimeMeshUVComponents() { } FRuntimeMeshUVComponents(EForceInit) : UV0(0, 0), UV1(0, 0), UV2(0, 0), UV3(0, 0), UV4(0, 0), UV5(0, 0), UV6(0, 0) { } FRuntimeMeshUVComponents(const FVector2D& InUV0) : UV0(InUV0), UV1(0, 0), UV2(0, 0), UV3(0, 0), UV4(0, 0), UV5(0, 0), UV6(0, 0) { } FRuntimeMeshUVComponents(const FVector2D& InUV0, const FVector2D& InUV1) : UV0(InUV0), UV1(InUV1), UV2(0, 0), UV3(0, 0), UV4(0, 0), UV5(0, 0), UV6(0, 0) { } FRuntimeMeshUVComponents(const FVector2D& InUV0, const FVector2D& InUV1, const FVector2D& InUV2) : UV0(InUV0), UV1(InUV1), UV2(InUV2), UV3(0, 0), UV4(0, 0), UV5(0, 0), UV6(0, 0) { } FRuntimeMeshUVComponents(const FVector2D& InUV0, const FVector2D& InUV1, const FVector2D& InUV2, const FVector2D& InUV3) : UV0(InUV0), UV1(InUV1), UV2(InUV2), UV3(InUV3), UV4(0, 0), UV5(0, 0), UV6(0, 0) { } FRuntimeMeshUVComponents(const FVector2D& InUV0, const FVector2D& InUV1, const FVector2D& InUV2, const FVector2D& InUV3, const FVector2D& InUV4) : UV0(InUV0), UV1(InUV1), UV2(InUV2), UV3(InUV3), UV4(InUV4), UV5(0, 0), UV6(0, 0) { } FRuntimeMeshUVComponents(const FVector2D& InUV0, const FVector2D& InUV1, const FVector2D& InUV2, const FVector2D& InUV3, const FVector2D& InUV4, const FVector2D& InUV5) : UV0(InUV0), UV1(InUV1), UV2(InUV2), UV3(InUV3), UV4(InUV4), UV5(InUV5), UV6(0, 0) { } FRuntimeMeshUVComponents(const FVector2D& InUV0, const FVector2D& InUV1, const FVector2D& InUV2, const FVector2D& InUV3, const FVector2D& InUV4, const FVector2D& InUV5, const FVector2D& InUV6) : UV0(InUV0), UV1(InUV1), UV2(InUV2), UV3(InUV3), UV4(InUV4), UV5(InUV5), UV6(InUV6) { } }; /* Defines the UV coordinates for a vertex (Specialized to 8 channels) */ template struct FRuntimeMeshUVComponents<8, UVType> { UVType UV0; UVType UV1; UVType UV2; UVType UV3; UVType UV4; UVType UV5; UVType UV6; UVType UV7; FRuntimeMeshUVComponents() { } FRuntimeMeshUVComponents(EForceInit) : UV0(0, 0), UV1(0, 0), UV2(0, 0), UV3(0, 0), UV4(0, 0), UV5(0, 0), UV6(0, 0), UV7(0, 0) { } FRuntimeMeshUVComponents(const FVector2D& InUV0) : UV0(InUV0), UV1(0, 0), UV2(0, 0), UV3(0, 0), UV4(0, 0), UV5(0, 0), UV6(0, 0), UV7(0, 0) { } FRuntimeMeshUVComponents(const FVector2D& InUV0, const FVector2D& InUV1) : UV0(InUV0), UV1(InUV1), UV2(0, 0), UV3(0, 0), UV4(0, 0), UV5(0, 0), UV6(0, 0), UV7(0, 0) { } FRuntimeMeshUVComponents(const FVector2D& InUV0, const FVector2D& InUV1, const FVector2D& InUV2) : UV0(InUV0), UV1(InUV1), UV2(InUV2), UV3(0, 0), UV4(0, 0), UV5(0, 0), UV6(0, 0), UV7(0, 0) { } FRuntimeMeshUVComponents(const FVector2D& InUV0, const FVector2D& InUV1, const FVector2D& InUV2, const FVector2D& InUV3) : UV0(InUV0), UV1(InUV1), UV2(InUV2), UV3(InUV3), UV4(0, 0), UV5(0, 0), UV6(0, 0), UV7(0, 0) { } FRuntimeMeshUVComponents(const FVector2D& InUV0, const FVector2D& InUV1, const FVector2D& InUV2, const FVector2D& InUV3, const FVector2D& InUV4) : UV0(InUV0), UV1(InUV1), UV2(InUV2), UV3(InUV3), UV4(InUV4), UV5(0, 0), UV6(0, 0), UV7(0, 0) { } FRuntimeMeshUVComponents(const FVector2D& InUV0, const FVector2D& InUV1, const FVector2D& InUV2, const FVector2D& InUV3, const FVector2D& InUV4, const FVector2D& InUV5) : UV0(InUV0), UV1(InUV1), UV2(InUV2), UV3(InUV3), UV4(InUV4), UV5(InUV5), UV6(0, 0), UV7(0, 0) { } FRuntimeMeshUVComponents(const FVector2D& InUV0, const FVector2D& InUV1, const FVector2D& InUV2, const FVector2D& InUV3, const FVector2D& InUV4, const FVector2D& InUV5, const FVector2D& InUV6) : UV0(InUV0), UV1(InUV1), UV2(InUV2), UV3(InUV3), UV4(InUV4), UV5(InUV5), UV6(InUV6), UV7(0, 0) { } FRuntimeMeshUVComponents(const FVector2D& InUV0, const FVector2D& InUV1, const FVector2D& InUV2, const FVector2D& InUV3, const FVector2D& InUV4, const FVector2D& InUV5, const FVector2D& InUV6, const FVector2D& InUV7) : UV0(InUV0), UV1(InUV1), UV2(InUV2), UV3(InUV3), UV4(InUV4), UV5(InUV5), UV6(InUV6), UV7(InUV7) { } }; ////////////////////////////////////////////////////////////////////////// // Tangent Basis Component Type Selector ////////////////////////////////////////////////////////////////////////// enum class ERuntimeMeshVertexTangentBasisType { Default = 1, HighPrecision = 2, }; template struct FRuntimeMeshVertexTangentTypeSelector; template<> struct FRuntimeMeshVertexTangentTypeSelector { typedef FPackedNormal TangentType; static const EVertexElementType VertexElementType = VET_PackedNormal; }; template<> struct FRuntimeMeshVertexTangentTypeSelector { typedef FPackedRGBA16N TangentType; static const EVertexElementType VertexElementType = VET_UShort4N; }; ////////////////////////////////////////////////////////////////////////// // Tangent Basis Components ////////////////////////////////////////////////////////////////////////// template struct FRuntimeMeshNormalTangentComponents; struct RuntimeMeshNormalUtil { static void SetNormalW(FPackedNormal& Target, float Determinant) { Target.Vector.W = Determinant < 0.0f ? 0 : 255; } static void SetNormalW(FPackedRGBA16N& Target, float Determinant) { Target.W = Determinant < 0.0f ? 0 : 65535; } }; template struct FRuntimeMeshNormalTangentComponents { TangentType Normal; FRuntimeMeshNormalTangentComponents() { } FRuntimeMeshNormalTangentComponents(EForceInit) : Normal(FVector4(0.0f, 0.0f, 1.0f, 1.0f)) { } void SetNormalAndTangent(const FVector& InNormal, const FRuntimeMeshTangent& InTangent) { Normal = InNormal; InTangent.AdjustNormal(Normal); } void SetNormalAndTangent(const FVector& InTangentX, const FVector& InTangentY, const FVector& InTangentZ) { Normal = InTangentZ; // store determinant of basis in w component of normal vector RuntimeMeshNormalUtil::SetNormalW(Normal, GetBasisDeterminantSign(InTangentX, InTangentY, InTangentZ)); } }; template struct FRuntimeMeshNormalTangentComponents { TangentType Tangent; FRuntimeMeshNormalTangentComponents() { } FRuntimeMeshNormalTangentComponents(EForceInit) : Tangent(FVector(1.0f, 0.0f, 0.0f)) { } void SetNormalAndTangent(const FVector& InNormal, const FRuntimeMeshTangent& InTangent) { Tangent = InTangent.TangentX; } void SetNormalAndTangent(const FVector& InTangentX, const FVector& InTangentY, const FVector& InTangentZ) { Tangent = InTangentX; } }; template struct FRuntimeMeshNormalTangentComponents { TangentType Normal; TangentType Tangent; FRuntimeMeshNormalTangentComponents() { } FRuntimeMeshNormalTangentComponents(EForceInit) : Normal(FVector4(0.0f, 0.0f, 1.0f, 1.0f)), Tangent(FVector(1.0f, 0.0f, 0.0f)) { } void SetNormalAndTangent(const FVector& InNormal, const FRuntimeMeshTangent& InTangent) { Normal = InNormal; Tangent = InTangent.TangentX; InTangent.AdjustNormal(Normal); } void SetNormalAndTangent(const FVector& InTangentX, const FVector& InTangentY, const FVector& InTangentZ) { Normal = InTangentZ; Tangent = InTangentX; // store determinant of basis in w component of normal vector RuntimeMeshNormalUtil::SetNormalW(Normal, GetBasisDeterminantSign(InTangentX, InTangentY, InTangentZ)); } }; ////////////////////////////////////////////////////////////////////////// // Position Component ////////////////////////////////////////////////////////////////////////// template struct FRuntimeMeshPositionComponent; template<> struct FRuntimeMeshPositionComponent { FVector Position; FRuntimeMeshPositionComponent() { } FRuntimeMeshPositionComponent(EForceInit) : Position(0.0f, 0.0f, 0.0f) { } }; ////////////////////////////////////////////////////////////////////////// // Color Component ////////////////////////////////////////////////////////////////////////// template struct FRuntimeMeshColorComponent; template<> struct FRuntimeMeshColorComponent { FColor Color; FRuntimeMeshColorComponent() { } FRuntimeMeshColorComponent(EForceInit) : Color(FColor::White) { } }; ////////////////////////////////////////////////////////////////////////// // Position Normal Tangent Combiner ////////////////////////////////////////////////////////////////////////// template struct FRuntimeMeshPositionNormalTangentComponentCombiner : public FRuntimeMeshPositionComponent, public FRuntimeMeshNormalTangentComponents { FRuntimeMeshPositionNormalTangentComponentCombiner() { } FRuntimeMeshPositionNormalTangentComponentCombiner(EForceInit) : FRuntimeMeshPositionComponent(EForceInit::ForceInit) , FRuntimeMeshNormalTangentComponents(EForceInit::ForceInit) { } }; template struct FRuntimeMeshPositionNormalTangentComponentCombiner : public FRuntimeMeshPositionComponent { FRuntimeMeshPositionNormalTangentComponentCombiner() { } FRuntimeMeshPositionNormalTangentComponentCombiner(EForceInit) : FRuntimeMeshPositionComponent(EForceInit::ForceInit) { } }; template struct FRuntimeMeshPositionNormalTangentComponentCombiner : public FRuntimeMeshNormalTangentComponents { FRuntimeMeshPositionNormalTangentComponentCombiner() { } FRuntimeMeshPositionNormalTangentComponentCombiner(EForceInit) : FRuntimeMeshNormalTangentComponents(EForceInit::ForceInit) { } }; template struct FRuntimeMeshPositionNormalTangentComponentCombiner; ////////////////////////////////////////////////////////////////////////// // Color UV Combiner ////////////////////////////////////////////////////////////////////////// template struct FRuntimeMeshColorUVComponentCombiner : public FRuntimeMeshColorComponent, public FRuntimeMeshUVComponents { FRuntimeMeshColorUVComponentCombiner() { } FRuntimeMeshColorUVComponentCombiner(EForceInit) : FRuntimeMeshColorComponent(EForceInit::ForceInit) , FRuntimeMeshUVComponents(EForceInit::ForceInit) { } }; template struct FRuntimeMeshColorUVComponentCombiner : public FRuntimeMeshUVComponents { FRuntimeMeshColorUVComponentCombiner() { } FRuntimeMeshColorUVComponentCombiner(EForceInit) : FRuntimeMeshUVComponents(EForceInit::ForceInit) { } }; template struct FRuntimeMeshColorUVComponentCombiner : public FRuntimeMeshColorComponent { FRuntimeMeshColorUVComponentCombiner() { } FRuntimeMeshColorUVComponentCombiner(EForceInit) : FRuntimeMeshColorComponent(EForceInit::ForceInit) { } }; template struct FRuntimeMeshColorUVComponentCombiner; ////////////////////////////////////////////////////////////////////////// // Template Vertex Type Info Structure ////////////////////////////////////////////////////////////////////////// template struct FRuntimeMeshVertexTypeInfo_GenericVertex : public FRuntimeMeshVertexTypeInfo { FRuntimeMeshVertexTypeInfo_GenericVertex(FString VertexName) : FRuntimeMeshVertexTypeInfo( FString::Printf(TEXT("RuntimeMeshVertex<%d, %d, %d, %d, %d, %d, %d>"), WantsPosition, WantsNormal, WantsTangent, WantsColor, NumWantedUVChannels, (int32)NormalTangentType, (int32)UVType), GetVertexGuid(VertexName)) { } static FGuid GetVertexGuid(FString VertexName) { uint32 TypeID = 0; TypeID = (TypeID << 1) | (WantsPosition ? 1 : 0); TypeID = (TypeID << 1) | (WantsNormal ? 1 : 0); TypeID = (TypeID << 1) | (WantsTangent ? 1 : 0); TypeID = (TypeID << 3) | (uint32)NormalTangentType; TypeID = (TypeID << 1) | (WantsColor ? 1 : 0); TypeID = (TypeID << 6) | (NumWantedUVChannels & 0xFF); TypeID = (TypeID << 3) | (uint32)UVType; FGuid Guid = FGuid(0x00FFEB44, 0x31094597, /*0x93918032*/ GetTypeHash(VertexName), (0x78C3 << 16) | TypeID); return Guid; } }; ////////////////////////////////////////////////////////////////////////// // Macros to create a custom vertex type based on the generic vertex and implement some common constructors ////////////////////////////////////////////////////////////////////////// #define RUNTIMEMESH_VERTEX_DEFAULTINIT_POSITION_true Position = FVector(0.0f, 0.0f, 0.0f); #define RUNTIMEMESH_VERTEX_DEFAULTINIT_POSITION_false #define RUNTIMEMESH_VERTEX_DEFAULTINIT_POSITION(HasPosition) RUNTIMEMESH_VERTEX_DEFAULTINIT_POSITION_##HasPosition #define RUNTIMEMESH_VERTEX_DEFAULTINIT_NORMAL_true Normal = FVector4(0.0f, 0.0f, 1.0f, 1.0f); #define RUNTIMEMESH_VERTEX_DEFAULTINIT_NORMAL_false #define RUNTIMEMESH_VERTEX_DEFAULTINIT_NORMAL(HasNormal) RUNTIMEMESH_VERTEX_DEFAULTINIT_NORMAL_##HasNormal #define RUNTIMEMESH_VERTEX_DEFAULTINIT_TANGENT_true Tangent = FVector(1.0f, 0.0f, 0.0f); #define RUNTIMEMESH_VERTEX_DEFAULTINIT_TANGENT_false #define RUNTIMEMESH_VERTEX_DEFAULTINIT_TANGENT(HasTangent) RUNTIMEMESH_VERTEX_DEFAULTINIT_TANGENT_##HasTangent #define RUNTIMEMESH_VERTEX_DEFAULTINIT_COLOR_true Color = FColor::White; #define RUNTIMEMESH_VERTEX_DEFAULTINIT_COLOR_false #define RUNTIMEMESH_VERTEX_DEFAULTINIT_COLOR(HasColor) RUNTIMEMESH_VERTEX_DEFAULTINIT_COLOR_##HasColor #define RUNTIMEMESH_VERTEX_DEFAULTINIT_UVCHANNEL_0 #define RUNTIMEMESH_VERTEX_DEFAULTINIT_UVCHANNEL_1 \ UV0 = FVector2D(0.0f, 0.0f); #define RUNTIMEMESH_VERTEX_DEFAULTINIT_UVCHANNEL_2 \ RUNTIMEMESH_VERTEX_DEFAULTINIT_UVCHANNEL_1 \ UV1 = FVector2D(0.0f, 0.0f); #define RUNTIMEMESH_VERTEX_DEFAULTINIT_UVCHANNEL_3 \ RUNTIMEMESH_VERTEX_DEFAULTINIT_UVCHANNEL_2 \ UV2 = FVector2D(0.0f, 0.0f); #define RUNTIMEMESH_VERTEX_DEFAULTINIT_UVCHANNEL_4 \ RUNTIMEMESH_VERTEX_DEFAULTINIT_UVCHANNEL_3 \ UV3 = FVector2D(0.0f, 0.0f); #define RUNTIMEMESH_VERTEX_DEFAULTINIT_UVCHANNEL_5 \ RUNTIMEMESH_VERTEX_DEFAULTINIT_UVCHANNEL_4 \ UV4 = FVector2D(0.0f, 0.0f); #define RUNTIMEMESH_VERTEX_DEFAULTINIT_UVCHANNEL_6 \ RUNTIMEMESH_VERTEX_DEFAULTINIT_UVCHANNEL_5 \ UV5 = FVector2D(0.0f, 0.0f); #define RUNTIMEMESH_VERTEX_DEFAULTINIT_UVCHANNEL_7 \ RUNTIMEMESH_VERTEX_DEFAULTINIT_UVCHANNEL_6 \ UV6 = FVector2D(0.0f, 0.0f); #define RUNTIMEMESH_VERTEX_DEFAULTINIT_UVCHANNEL_8 \ RUNTIMEMESH_VERTEX_DEFAULTINIT_UVCHANNEL_7 \ UV7 = FVector2D(0.0f, 0.0f); #define RUNTIMEMESH_VERTEX_DEFAULTINIT_UVCHANNELS(NumChannels) RUNTIMEMESH_VERTEX_DEFAULTINIT_UVCHANNEL_##NumChannels #define RUNTIMEMESH_VERTEX_PARAMETER_UVCHANNEL_0 #define RUNTIMEMESH_VERTEX_PARAMETER_UVCHANNEL_1 , const FVector2D& InUV0 = FVector2D::ZeroVector #define RUNTIMEMESH_VERTEX_PARAMETER_UVCHANNEL_2 RUNTIMEMESH_VERTEX_PARAMETER_UVCHANNEL_1 , const FVector2D& InUV1 = FVector2D::ZeroVector #define RUNTIMEMESH_VERTEX_PARAMETER_UVCHANNEL_3 RUNTIMEMESH_VERTEX_PARAMETER_UVCHANNEL_2 , const FVector2D& InUV2 = FVector2D::ZeroVector #define RUNTIMEMESH_VERTEX_PARAMETER_UVCHANNEL_4 RUNTIMEMESH_VERTEX_PARAMETER_UVCHANNEL_3 , const FVector2D& InUV3 = FVector2D::ZeroVector #define RUNTIMEMESH_VERTEX_PARAMETER_UVCHANNEL_5 RUNTIMEMESH_VERTEX_PARAMETER_UVCHANNEL_4 , const FVector2D& InUV4 = FVector2D::ZeroVector #define RUNTIMEMESH_VERTEX_PARAMETER_UVCHANNEL_6 RUNTIMEMESH_VERTEX_PARAMETER_UVCHANNEL_5 , const FVector2D& InUV5 = FVector2D::ZeroVector #define RUNTIMEMESH_VERTEX_PARAMETER_UVCHANNEL_7 RUNTIMEMESH_VERTEX_PARAMETER_UVCHANNEL_6 , const FVector2D& InUV6 = FVector2D::ZeroVector #define RUNTIMEMESH_VERTEX_PARAMETER_UVCHANNEL_8 RUNTIMEMESH_VERTEX_PARAMETER_UVCHANNEL_7 , const FVector2D& InUV7 = FVector2D::ZeroVector #define RUNTIMEMESH_VERTEX_PARAMETER_UVCHANNELS(NumChannels) RUNTIMEMESH_VERTEX_PARAMETER_UVCHANNEL_##NumChannels #define RUNTIMEMESH_VERTEX_INIT_UVCHANNEL_0 #define RUNTIMEMESH_VERTEX_INIT_UVCHANNEL_1 \ UV0 = InUV0; #define RUNTIMEMESH_VERTEX_INIT_UVCHANNEL_2 \ RUNTIMEMESH_VERTEX_INIT_UVCHANNEL_1 \ UV1 = InUV1; #define RUNTIMEMESH_VERTEX_INIT_UVCHANNEL_3 \ RUNTIMEMESH_VERTEX_INIT_UVCHANNEL_2 \ UV2 = InUV2; #define RUNTIMEMESH_VERTEX_INIT_UVCHANNEL_4 \ RUNTIMEMESH_VERTEX_INIT_UVCHANNEL_3 \ UV3 = InUV3; #define RUNTIMEMESH_VERTEX_INIT_UVCHANNEL_5 \ RUNTIMEMESH_VERTEX_INIT_UVCHANNEL_4 \ UV4 = InUV4; #define RUNTIMEMESH_VERTEX_INIT_UVCHANNEL_6 \ RUNTIMEMESH_VERTEX_INIT_UVCHANNEL_5 \ UV5 = InUV5; #define RUNTIMEMESH_VERTEX_INIT_UVCHANNEL_7 \ RUNTIMEMESH_VERTEX_INIT_UVCHANNEL_6 \ UV6 = InUV6; #define RUNTIMEMESH_VERTEX_INIT_UVCHANNEL_8 \ RUNTIMEMESH_VERTEX_INIT_UVCHANNEL_7 \ UV7 = InUV7; #define RUNTIMEMESH_VERTEX_INIT_UVCHANNELS(NumChannels) RUNTIMEMESH_VERTEX_INIT_UVCHANNEL_##NumChannels #define RUNTIMEMESH_VERTEX_PARAMETER_POSITION_true const FVector& InPosition, #define RUNTIMEMESH_VERTEX_PARAMETER_POSITION_false #define RUNTIMEMESH_VERTEX_PARAMETER_POSITION(NeedsPosition) RUNTIMEMESH_VERTEX_PARAMETER_POSITION_##NeedsPosition #define RUNTIMEMESH_VERTEX_INIT_POSITION_true Position = InPosition; #define RUNTIMEMESH_VERTEX_INIT_POSITION_false #define RUNTIMEMESH_VERTEX_INIT_POSITION(NeedsPosition) RUNTIMEMESH_VERTEX_INIT_POSITION_##NeedsPosition // PreProcessor IF with pass through for all the constructor arguments #define RUNTIMEMESH_VERTEX_CONSTRUCTOR_DEFINITION_IF(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType, Condition, IfTrue) \ RUNTIMEMESH_VERTEX_CONSTRUCTOR_DEFINITION_IF_##Condition(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType, IfTrue) #define RUNTIMEMESH_VERTEX_CONSTRUCTOR_DEFINITION_IF_false(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType, IfTrue) #define RUNTIMEMESH_VERTEX_CONSTRUCTOR_DEFINITION_IF_true(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType, IfTrue) IfTrue // Implementation of Position only Constructor #define RUNTIMEMESH_VERTEX_CONSTRUCTOR_POSITION_IMPLEMENTATION(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType) \ VertexName(const FVector& InPosition) \ { \ RUNTIMEMESH_VERTEX_INIT_POSITION(NeedsPosition) \ RUNTIMEMESH_VERTEX_DEFAULTINIT_NORMAL(NeedsNormal) \ RUNTIMEMESH_VERTEX_DEFAULTINIT_TANGENT(NeedsTangent) \ RUNTIMEMESH_VERTEX_DEFAULTINIT_COLOR(NeedsColor) \ RUNTIMEMESH_VERTEX_DEFAULTINIT_UVCHANNELS(UVChannelCount) \ } // Defines the Position Constuctor if it's wanted #define RUNTIMEMESH_VERTEX_CONSTRUCTOR_POSITION(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType) \ RUNTIMEMESH_VERTEX_CONSTRUCTOR_DEFINITION_IF(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType, NeedsPosition, \ RUNTIMEMESH_VERTEX_CONSTRUCTOR_POSITION_IMPLEMENTATION(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType) \ ) // Implementation of Position/Normal Constructor #define RUNTIMEMESH_VERTEX_CONSTRUCTOR_POSITION_NORMAL_IMPLEMENTATION(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType) \ VertexName(RUNTIMEMESH_VERTEX_PARAMETER_POSITION(NeedsPosition) const FVector& InNormal) \ { \ RUNTIMEMESH_VERTEX_INIT_POSITION(NeedsPosition) \ Normal = InNormal; \ RUNTIMEMESH_VERTEX_DEFAULTINIT_TANGENT(NeedsTangent) \ RUNTIMEMESH_VERTEX_DEFAULTINIT_COLOR(NeedsColor) \ RUNTIMEMESH_VERTEX_DEFAULTINIT_UVCHANNELS(UVChannelCount) \ } // Defines the Position/Normal Constuctor if it's wanted #define RUNTIMEMESH_VERTEX_CONSTRUCTOR_POSITION_NORMAL(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType) \ RUNTIMEMESH_VERTEX_CONSTRUCTOR_DEFINITION_IF(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType, NeedsNormal, \ RUNTIMEMESH_VERTEX_CONSTRUCTOR_POSITION_NORMAL_IMPLEMENTATION(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType) \ ) // Implementation of Position/Color Constructor #define RUNTIMEMESH_VERTEX_CONSTRUCTOR_POSITION_COLOR_IMPLEMENTATION(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType) \ VertexName(RUNTIMEMESH_VERTEX_PARAMETER_POSITION(NeedsPosition) const FColor& InColor) \ { \ RUNTIMEMESH_VERTEX_INIT_POSITION(NeedsPosition) \ RUNTIMEMESH_VERTEX_DEFAULTINIT_NORMAL(NeedsNormal) \ RUNTIMEMESH_VERTEX_DEFAULTINIT_TANGENT(NeedsTangent) \ Color = InColor; \ RUNTIMEMESH_VERTEX_DEFAULTINIT_UVCHANNELS(UVChannelCount) \ } // Defines the Position/Color Constructor if it's wanted #define RUNTIMEMESH_VERTEX_CONSTRUCTOR_POSITION_COLOR(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType) \ RUNTIMEMESH_VERTEX_CONSTRUCTOR_DEFINITION_IF(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType, NeedsColor, \ RUNTIMEMESH_VERTEX_CONSTRUCTOR_POSITION_COLOR_IMPLEMENTATION(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType) \ ) // Implementation of Position/Normal/Tangent Constructor #define RUNTIMEMESH_VERTEX_CONSTRUCTOR_POSITION_NORMAL_TANGENT_IMPLEMENTATION(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType) \ VertexName(RUNTIMEMESH_VERTEX_PARAMETER_POSITION(NeedsPosition) const FVector& InNormal, const FRuntimeMeshTangent& InTangent RUNTIMEMESH_VERTEX_PARAMETER_UVCHANNELS(UVChannelCount)) \ { \ RUNTIMEMESH_VERTEX_INIT_POSITION(NeedsPosition) \ Normal = InNormal; \ Tangent = InTangent.TangentX; \ InTangent.AdjustNormal(Normal); \ RUNTIMEMESH_VERTEX_DEFAULTINIT_COLOR(NeedsColor) \ RUNTIMEMESH_VERTEX_INIT_UVCHANNELS(UVChannelCount) \ } // Defines the Position/Normal/Tangent Constructor if it's wanted #define RUNTIMEMESH_VERTEX_CONSTRUCTOR_POSITION_NORMAL_TANGENT(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType) \ RUNTIMEMESH_VERTEX_CONSTRUCTOR_DEFINITION_IF(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType, NeedsNormal, \ RUNTIMEMESH_VERTEX_CONSTRUCTOR_DEFINITION_IF(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType, NeedsTangent, \ RUNTIMEMESH_VERTEX_CONSTRUCTOR_POSITION_NORMAL_TANGENT_IMPLEMENTATION(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType) \ ) \ ) // Implementation of Position/TangentX/TangentY/TangentZ Constructor #define RUNTIMEMESH_VERTEX_CONSTRUCTOR_POSITION_TANGENTX_TANGENTY_TANGENTZ_IMPLEMENTATION(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType) \ VertexName(RUNTIMEMESH_VERTEX_PARAMETER_POSITION(NeedsPosition) const FVector& InTangentX, const FVector& InTangentY, const FVector& InTangentZ RUNTIMEMESH_VERTEX_PARAMETER_UVCHANNELS(UVChannelCount)) \ { \ RUNTIMEMESH_VERTEX_INIT_POSITION(NeedsPosition) \ SetNormalAndTangent(InTangentX, InTangentY, InTangentZ); \ RUNTIMEMESH_VERTEX_DEFAULTINIT_COLOR(NeedsColor) \ RUNTIMEMESH_VERTEX_INIT_UVCHANNELS(UVChannelCount) \ } // Defines the Position/TangentX/TangentY/TangentZ Constructor if it's wanted #define RUNTIMEMESH_VERTEX_CONSTRUCTOR_POSITION_TANGENTX_TANGENTY_TANGENTZ(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType) \ RUNTIMEMESH_VERTEX_CONSTRUCTOR_DEFINITION_IF(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType, NeedsNormal, \ RUNTIMEMESH_VERTEX_CONSTRUCTOR_DEFINITION_IF(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType, NeedsTangent, \ RUNTIMEMESH_VERTEX_CONSTRUCTOR_POSITION_TANGENTX_TANGENTY_TANGENTZ_IMPLEMENTATION(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType) \ ) \ ) // Implementation of Position/Normal/Tangent Constructor #define RUNTIMEMESH_VERTEX_CONSTRUCTOR_POSITION_NORMAL_TANGENT_COLOR_IMPLEMENTATION(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType) \ VertexName(RUNTIMEMESH_VERTEX_PARAMETER_POSITION(NeedsPosition) const FVector& InNormal, const FRuntimeMeshTangent& InTangent, const FColor& InColor RUNTIMEMESH_VERTEX_PARAMETER_UVCHANNELS(UVChannelCount)) \ { \ RUNTIMEMESH_VERTEX_INIT_POSITION(NeedsPosition) \ Normal = InNormal; \ Tangent = InTangent.TangentX; \ InTangent.AdjustNormal(Normal); \ Color = InColor; \ RUNTIMEMESH_VERTEX_INIT_UVCHANNELS(UVChannelCount) \ } // Defines the Position/Normal/Tangent Constructor if it's wanted #define RUNTIMEMESH_VERTEX_CONSTRUCTOR_POSITION_NORMAL_TANGENT_COLOR(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType) \ RUNTIMEMESH_VERTEX_CONSTRUCTOR_DEFINITION_IF(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType, NeedsNormal, \ RUNTIMEMESH_VERTEX_CONSTRUCTOR_DEFINITION_IF(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType, NeedsTangent, \ RUNTIMEMESH_VERTEX_CONSTRUCTOR_DEFINITION_IF(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType, NeedsColor, \ RUNTIMEMESH_VERTEX_CONSTRUCTOR_POSITION_NORMAL_TANGENT_COLOR_IMPLEMENTATION(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType) \ ) \ ) \ ) // Implementation of Position/TangentX/TangentY/TangentZ Constructor #define RUNTIMEMESH_VERTEX_CONSTRUCTOR_POSITION_TANGENTX_TANGENTY_TANGENTZ_COLOR_IMPLEMENTATION(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType) \ VertexName(RUNTIMEMESH_VERTEX_PARAMETER_POSITION(NeedsPosition) const FVector& InTangentX, const FVector& InTangentY, const FVector& InTangentZ, const FColor& InColor RUNTIMEMESH_VERTEX_PARAMETER_UVCHANNELS(UVChannelCount)) \ { \ RUNTIMEMESH_VERTEX_INIT_POSITION(NeedsPosition) \ SetNormalAndTangent(InTangentX, InTangentY, InTangentZ); \ Color = InColor; \ RUNTIMEMESH_VERTEX_INIT_UVCHANNELS(UVChannelCount) \ } // Defines the Position/TangentX/TangentY/TangentZ Constructor if it's wanted #define RUNTIMEMESH_VERTEX_CONSTRUCTOR_POSITION_TANGENTX_TANGENTY_TANGENTZ_COLOR(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType) \ RUNTIMEMESH_VERTEX_CONSTRUCTOR_DEFINITION_IF(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType, NeedsNormal, \ RUNTIMEMESH_VERTEX_CONSTRUCTOR_DEFINITION_IF(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType, NeedsTangent, \ RUNTIMEMESH_VERTEX_CONSTRUCTOR_DEFINITION_IF(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType, NeedsColor, \ RUNTIMEMESH_VERTEX_CONSTRUCTOR_POSITION_TANGENTX_TANGENTY_TANGENTZ_COLOR_IMPLEMENTATION(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType) \ ) \ ) \ ) #define RUNTIMEMESH_VERTEX_SERIALIZATION_POSITION_true Ar << V.Position; #define RUNTIMEMESH_VERTEX_SERIALIZATION_POSITION_false #define RUNTIMEMESH_VERTEX_SERIALIZATION_POSITION(NeedsPosition) RUNTIMEMESH_VERTEX_SERIALIZATION_POSITION_##NeedsPosition #define RUNTIMEMESH_VERTEX_SERIALIZATION_NORMAL_true Ar << V.Normal; #define RUNTIMEMESH_VERTEX_SERIALIZATION_NORMAL_false #define RUNTIMEMESH_VERTEX_SERIALIZATION_NORMAL(NeedsNormal) RUNTIMEMESH_VERTEX_SERIALIZATION_NORMAL_##NeedsNormal #define RUNTIMEMESH_VERTEX_SERIALIZATION_TANGENT_true Ar << V.Tangent; #define RUNTIMEMESH_VERTEX_SERIALIZATION_TANGENT_false #define RUNTIMEMESH_VERTEX_SERIALIZATION_TANGENT(NeedsTangent) RUNTIMEMESH_VERTEX_SERIALIZATION_TANGENT_##NeedsTangent #define RUNTIMEMESH_VERTEX_SERIALIZATION_COLOR_true Ar << V.Color; #define RUNTIMEMESH_VERTEX_SERIALIZATION_COLOR_false #define RUNTIMEMESH_VERTEX_SERIALIZATION_COLOR(NeedsColor) RUNTIMEMESH_VERTEX_SERIALIZATION_COLOR_##NeedsColor #define RUNTIMEMESH_VERTEX_SERIALIZATION_UVCHANNEL_0 #define RUNTIMEMESH_VERTEX_SERIALIZATION_UVCHANNEL_1 \ Ar << V.UV0; #define RUNTIMEMESH_VERTEX_SERIALIZATION_UVCHANNEL_2 \ RUNTIMEMESH_VERTEX_SERIALIZATION_UVCHANNEL_1 \ Ar << V.UV1; #define RUNTIMEMESH_VERTEX_SERIALIZATION_UVCHANNEL_3 \ RUNTIMEMESH_VERTEX_SERIALIZATION_UVCHANNEL_2 \ Ar << V.UV2; #define RUNTIMEMESH_VERTEX_SERIALIZATION_UVCHANNEL_4 \ RUNTIMEMESH_VERTEX_SERIALIZATION_UVCHANNEL_3 \ Ar << V.UV3; #define RUNTIMEMESH_VERTEX_SERIALIZATION_UVCHANNEL_5 \ RUNTIMEMESH_VERTEX_SERIALIZATION_UVCHANNEL_4 \ Ar << V.UV4; #define RUNTIMEMESH_VERTEX_SERIALIZATION_UVCHANNEL_6 \ RUNTIMEMESH_VERTEX_SERIALIZATION_UVCHANNEL_5 \ Ar << V.UV5; #define RUNTIMEMESH_VERTEX_SERIALIZATION_UVCHANNEL_7 \ RUNTIMEMESH_VERTEX_SERIALIZATION_UVCHANNEL_6 \ Ar << V.UV6; #define RUNTIMEMESH_VERTEX_SERIALIZATION_UVCHANNEL_8 \ RUNTIMEMESH_VERTEX_SERIALIZATION_UVCHANNEL_7 \ Ar << V.UV7; #define RUNTIMEMESH_VERTEX_SERIALIZATION_UVCHANNELS(NumChannels) RUNTIMEMESH_VERTEX_SERIALIZATION_UVCHANNEL_##NumChannels #define RUNTIMEMESH_VERTEX_SERIALIZER(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount) \ friend FArchive& operator<<(FArchive& Ar, VertexName & V) \ { \ RUNTIMEMESH_VERTEX_SERIALIZATION_POSITION(NeedsPosition) \ RUNTIMEMESH_VERTEX_SERIALIZATION_NORMAL(NeedsNormal) \ RUNTIMEMESH_VERTEX_SERIALIZATION_TANGENT(NeedsTangent) \ RUNTIMEMESH_VERTEX_SERIALIZATION_COLOR(NeedsColor) \ RUNTIMEMESH_VERTEX_SERIALIZATION_UVCHANNELS(UVChannelCount) \ return Ar; \ } #define DECLARE_RUNTIME_MESH_VERTEXINTERNAL(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType, APIQUALIFIER) \ struct APIQUALIFIER FRuntimeMeshVertexTypeInfo_##VertexName \ : public FRuntimeMeshVertexTypeInfo_GenericVertex \ { \ FRuntimeMeshVertexTypeInfo_##VertexName() \ : FRuntimeMeshVertexTypeInfo_GenericVertex(TEXT("")) { } \ \ virtual class FRuntimeMeshSectionInterface* CreateSection(bool bInNeedsPositionOnlyBuffer) const override; \ }; \ struct APIQUALIFIER VertexName : public FRuntimeMeshVertex \ { \ static const FRuntimeMeshVertexTypeInfo_##VertexName TypeInfo; \ \ typedef FRuntimeMeshVertex Super; \ \ VertexName() { } \ \ VertexName(EForceInit) : Super(EForceInit::ForceInit) { } \ \ RUNTIMEMESH_VERTEX_CONSTRUCTOR_POSITION(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType) \ \ RUNTIMEMESH_VERTEX_CONSTRUCTOR_POSITION_NORMAL(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType) \ \ RUNTIMEMESH_VERTEX_CONSTRUCTOR_POSITION_COLOR(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType) \ \ RUNTIMEMESH_VERTEX_CONSTRUCTOR_POSITION_NORMAL_TANGENT(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType) \ \ RUNTIMEMESH_VERTEX_CONSTRUCTOR_POSITION_TANGENTX_TANGENTY_TANGENTZ(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType) \ \ RUNTIMEMESH_VERTEX_CONSTRUCTOR_POSITION_NORMAL_TANGENT_COLOR(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType) \ \ RUNTIMEMESH_VERTEX_CONSTRUCTOR_POSITION_TANGENTX_TANGENTY_TANGENTZ_COLOR(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType) \ \ RUNTIMEMESH_VERTEX_SERIALIZER(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount) \ }; #define DECLARE_RUNTIME_MESH_VERTEX(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType) \ DECLARE_RUNTIME_MESH_VERTEXINTERNAL(VertexName, NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType, /**/) /* Used only for the generic vertex to create the type registration */ #define DEFINE_RUNTIME_MESH_VERTEX(VertexName) \ const FRuntimeMeshVertexTypeInfo_##VertexName VertexName::TypeInfo; \ FRuntimeMeshVertexTypeRegistration< VertexName > FRuntimeMeshVertexTypeInfoRegistration_##VertexName; \ FRuntimeMeshSectionInterface* FRuntimeMeshVertexTypeInfo_##VertexName::CreateSection(bool bInNeedsPositionOnlyBuffer) const \ { \ return new FRuntimeMeshSection< VertexName >(bInNeedsPositionOnlyBuffer); \ } ////////////////////////////////////////////////////////////////////////// // Template Vertex ////////////////////////////////////////////////////////////////////////// // This version uses both sub combiners since there's at least 1 thing we need from both. template struct FRuntimeMeshVertex : public FRuntimeMeshPositionNormalTangentComponentCombiner::TangentType>, public FRuntimeMeshColorUVComponentCombiner::UVsType> { // Make sure something is enabled static_assert((WantsPosition || WantsNormal || WantsTangent || WantsColor || NumWantedUVChannels > 0), "Invalid configuration... You must have at least 1 component enabled."); // Get vertex structure static RuntimeMeshVertexStructure GetVertexStructure(const FVertexBuffer& VertexBuffer); FRuntimeMeshVertex() { } FRuntimeMeshVertex(EForceInit) : FRuntimeMeshPositionNormalTangentComponentCombiner::TangentType>(EForceInit::ForceInit) , FRuntimeMeshColorUVComponentCombiner::UVsType>(EForceInit::ForceInit) { } }; // This version only uses the position/normal/tangent combiner as we don't need anything from the other template struct FRuntimeMeshVertex : public FRuntimeMeshPositionNormalTangentComponentCombiner::TangentType> { // Get vertex structure static RuntimeMeshVertexStructure GetVertexStructure(const FVertexBuffer& VertexBuffer); FRuntimeMeshVertex() { } FRuntimeMeshVertex(EForceInit) : FRuntimeMeshPositionNormalTangentComponentCombiner::TangentType>(EForceInit::ForceInit) { } }; // This version only uses the color/uv combiner as we don't need anything from the other template struct FRuntimeMeshVertex : public FRuntimeMeshColorUVComponentCombiner::UVsType> { // Get vertex structure static RuntimeMeshVertexStructure GetVertexStructure(const FVertexBuffer& VertexBuffer); FRuntimeMeshVertex() { } FRuntimeMeshVertex(EForceInit) : FRuntimeMeshColorUVComponentCombiner::UVsType>(EForceInit::ForceInit) { } }; ////////////////////////////////////////////////////////////////////////// // Vertex Structure Generator ////////////////////////////////////////////////////////////////////////// struct FRuntimeMeshVertexUtilities { ////////////////////////////////////////////////////////////////////////// // Position Component ////////////////////////////////////////////////////////////////////////// template struct FRuntimeMeshPositionComponentUtilities { static void AddComponent(const FVertexBuffer& VertexBuffer, RuntimeMeshVertexStructure& VertexStructure) { VertexStructure.PositionComponent = RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, Position, VET_Float3); } }; template struct FRuntimeMeshPositionComponentUtilities { static void AddComponent(const FVertexBuffer& VertexBuffer, RuntimeMeshVertexStructure& VertexStructure) { } }; ////////////////////////////////////////////////////////////////////////// // Normal/Tangent Components ////////////////////////////////////////////////////////////////////////// template struct FRuntimeMeshNormalTangentComponentVertexStructure { static void AddComponent(const FVertexBuffer& VertexBuffer, RuntimeMeshVertexStructure& VertexStructure) { VertexStructure.TangentBasisComponents[1] = RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, Normal, FRuntimeMeshVertexTangentTypeSelector::VertexElementType); VertexStructure.TangentBasisComponents[0] = RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, Tangent, FRuntimeMeshVertexTangentTypeSelector::VertexElementType); } }; template struct FRuntimeMeshNormalTangentComponentVertexStructure { static void AddComponent(const FVertexBuffer& VertexBuffer, RuntimeMeshVertexStructure& VertexStructure) { VertexStructure.TangentBasisComponents[1] = RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, Normal, FRuntimeMeshVertexTangentTypeSelector::VertexElementType); } }; template struct FRuntimeMeshNormalTangentComponentVertexStructure { static void AddComponent(const FVertexBuffer& VertexBuffer, RuntimeMeshVertexStructure& VertexStructure) { VertexStructure.TangentBasisComponents[0] = RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, Tangent, FRuntimeMeshVertexTangentTypeSelector::VertexElementType); } }; template struct FRuntimeMeshNormalTangentComponentVertexStructure { static void AddComponent(const FVertexBuffer& VertexBuffer, RuntimeMeshVertexStructure& VertexStructure) { } }; ////////////////////////////////////////////////////////////////////////// // Color Component ////////////////////////////////////////////////////////////////////////// template struct FRuntimeMeshColorComponentVertexStructure { static void AddComponent(const FVertexBuffer& VertexBuffer, RuntimeMeshVertexStructure& VertexStructure) { VertexStructure.ColorComponent = RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, Color, VET_Color); } }; template struct FRuntimeMeshColorComponentVertexStructure { static void AddComponent(const FVertexBuffer& VertexBuffer, RuntimeMeshVertexStructure& VertexStructure) { } }; ////////////////////////////////////////////////////////////////////////// // UV Components ////////////////////////////////////////////////////////////////////////// template struct FRuntimeMeshTextureChannelsVertexStructure { static void AddChannels(const FVertexBuffer& VertexBuffer, RuntimeMeshVertexStructure& VertexStructure) { } }; template struct FRuntimeMeshTextureChannelsVertexStructure { static void AddChannels(const FVertexBuffer& VertexBuffer, RuntimeMeshVertexStructure& VertexStructure) { VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV0, FRuntimeMeshVertexUVsTypeSelector::VertexElementType1Channel)); } }; template struct FRuntimeMeshTextureChannelsVertexStructure { static void AddChannels(const FVertexBuffer& VertexBuffer, RuntimeMeshVertexStructure& VertexStructure) { VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV0, FRuntimeMeshVertexUVsTypeSelector::VertexElementType2Channel)); } }; template struct FRuntimeMeshTextureChannelsVertexStructure { static void AddChannels(const FVertexBuffer& VertexBuffer, RuntimeMeshVertexStructure& VertexStructure) { VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV0, FRuntimeMeshVertexUVsTypeSelector::VertexElementType2Channel)); VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV2, FRuntimeMeshVertexUVsTypeSelector::VertexElementType1Channel)); } }; template struct FRuntimeMeshTextureChannelsVertexStructure { static void AddChannels(const FVertexBuffer& VertexBuffer, RuntimeMeshVertexStructure& VertexStructure) { VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV0, FRuntimeMeshVertexUVsTypeSelector::VertexElementType2Channel)); VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV2, FRuntimeMeshVertexUVsTypeSelector::VertexElementType2Channel)); } }; template struct FRuntimeMeshTextureChannelsVertexStructure { static void AddChannels(const FVertexBuffer& VertexBuffer, RuntimeMeshVertexStructure& VertexStructure) { VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV0, FRuntimeMeshVertexUVsTypeSelector::VertexElementType2Channel)); VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV2, FRuntimeMeshVertexUVsTypeSelector::VertexElementType2Channel)); VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV4, FRuntimeMeshVertexUVsTypeSelector::VertexElementType1Channel)); } }; template struct FRuntimeMeshTextureChannelsVertexStructure { static void AddChannels(const FVertexBuffer& VertexBuffer, RuntimeMeshVertexStructure& VertexStructure) { VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV0, FRuntimeMeshVertexUVsTypeSelector::VertexElementType2Channel)); VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV2, FRuntimeMeshVertexUVsTypeSelector::VertexElementType2Channel)); VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV4, FRuntimeMeshVertexUVsTypeSelector::VertexElementType2Channel)); } }; template struct FRuntimeMeshTextureChannelsVertexStructure { static void AddChannels(const FVertexBuffer& VertexBuffer, RuntimeMeshVertexStructure& VertexStructure) { VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV0, FRuntimeMeshVertexUVsTypeSelector::VertexElementType2Channel)); VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV2, FRuntimeMeshVertexUVsTypeSelector::VertexElementType2Channel)); VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV4, FRuntimeMeshVertexUVsTypeSelector::VertexElementType2Channel)); VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV6, FRuntimeMeshVertexUVsTypeSelector::VertexElementType1Channel)); } }; template struct FRuntimeMeshTextureChannelsVertexStructure { static void AddChannels(const FVertexBuffer& VertexBuffer, RuntimeMeshVertexStructure& VertexStructure) { VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV0, FRuntimeMeshVertexUVsTypeSelector::VertexElementType2Channel)); VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV2, FRuntimeMeshVertexUVsTypeSelector::VertexElementType2Channel)); VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV4, FRuntimeMeshVertexUVsTypeSelector::VertexElementType2Channel)); VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV6, FRuntimeMeshVertexUVsTypeSelector::VertexElementType2Channel)); } }; ////////////////////////////////////////////////////////////////////////// // Vertex Structure Helper ////////////////////////////////////////////////////////////////////////// template static RuntimeMeshVertexStructure CreateVertexStructure(const FVertexBuffer& VertexBuffer) { typedef FRuntimeMeshVertex RuntimeVertexType; RuntimeMeshVertexStructure VertexStructure; // Add Position component if necessary FRuntimeMeshPositionComponentUtilities::AddComponent(VertexBuffer, VertexStructure); // Add normal and tangent components if necessary FRuntimeMeshNormalTangentComponentVertexStructure::AddComponent(VertexBuffer, VertexStructure); // Add color component if necessary FRuntimeMeshColorComponentVertexStructure::AddComponent(VertexBuffer, VertexStructure); // Add all texture channels FRuntimeMeshTextureChannelsVertexStructure::AddChannels(VertexBuffer, VertexStructure); return VertexStructure; } }; // These need to be declared after FRuntimemeshVertexStructureHelper and RuntimeMeshVertexStructure to fix circular dependencies between the two template RuntimeMeshVertexStructure FRuntimeMeshVertex::GetVertexStructure(const FVertexBuffer& VertexBuffer) { return FRuntimeMeshVertexUtilities::CreateVertexStructure(VertexBuffer); } template RuntimeMeshVertexStructure FRuntimeMeshVertex::GetVertexStructure(const FVertexBuffer& VertexBuffer) { return FRuntimeMeshVertexUtilities::CreateVertexStructure(VertexBuffer); } template RuntimeMeshVertexStructure FRuntimeMeshVertex::GetVertexStructure(const FVertexBuffer& VertexBuffer) { return FRuntimeMeshVertexUtilities::CreateVertexStructure(VertexBuffer); } ////////////////////////////////////////////////////////////////////////// // Name Vertex Configurations ////////////////////////////////////////////////////////////////////////// /** Simple vertex with 1 UV channel */ DECLARE_RUNTIME_MESH_VERTEXINTERNAL(FRuntimeMeshVertexSimple, true, true, true, true, 1, ERuntimeMeshVertexTangentBasisType::Default, ERuntimeMeshVertexUVType::HighPrecision, RUNTIMEMESHCOMPONENT_API) /** Simple vertex with 2 UV channels */ DECLARE_RUNTIME_MESH_VERTEXINTERNAL(FRuntimeMeshVertexDualUV, true, true, true, true, 2, ERuntimeMeshVertexTangentBasisType::Default, ERuntimeMeshVertexUVType::HighPrecision, RUNTIMEMESHCOMPONENT_API) /** Simple vertex with 3 UV channels */ DECLARE_RUNTIME_MESH_VERTEXINTERNAL(FRuntimeMeshVertexTripleUV, true, true, true, true, 3, ERuntimeMeshVertexTangentBasisType::Default, ERuntimeMeshVertexUVType::HighPrecision, RUNTIMEMESHCOMPONENT_API) /** Simple vertex with 1 UV channel and NO position component (Meant to be used with separate position buffer) */ DECLARE_RUNTIME_MESH_VERTEXINTERNAL(FRuntimeMeshVertexNoPosition, false, true, true, true, 1, ERuntimeMeshVertexTangentBasisType::Default, ERuntimeMeshVertexUVType::HighPrecision, RUNTIMEMESHCOMPONENT_API) /** Simple vertex with 2 UV channels and NO position component (Meant to be used with separate position buffer) */ DECLARE_RUNTIME_MESH_VERTEXINTERNAL(FRuntimeMeshVertexNoPositionDualUV, false, true, true, true, 2, ERuntimeMeshVertexTangentBasisType::Default, ERuntimeMeshVertexUVType::HighPrecision, RUNTIMEMESHCOMPONENT_API) /** Simple vertex with 1 UV channel */ DECLARE_RUNTIME_MESH_VERTEXINTERNAL(FRuntimeMeshVertexHiPrecisionNormals, true, true, true, true, 1, ERuntimeMeshVertexTangentBasisType::HighPrecision, ERuntimeMeshVertexUVType::HighPrecision, RUNTIMEMESHCOMPONENT_API) /** Simple vertex with 2 UV channels */ DECLARE_RUNTIME_MESH_VERTEXINTERNAL(FRuntimeMeshVertexDualUVHiPrecisionNormals, true, true, true, true, 2, ERuntimeMeshVertexTangentBasisType::HighPrecision, ERuntimeMeshVertexUVType::HighPrecision, RUNTIMEMESHCOMPONENT_API) /** Simple vertex with 1 UV channel and NO position component (Meant to be used with separate position buffer) */ DECLARE_RUNTIME_MESH_VERTEXINTERNAL(FRuntimeMeshVertexNoPositionHiPrecisionNormals, false, true, true, true, 1, ERuntimeMeshVertexTangentBasisType::HighPrecision, ERuntimeMeshVertexUVType::HighPrecision, RUNTIMEMESHCOMPONENT_API) /** Simple vertex with 2 UV channels and NO position component (Meant to be used with separate position buffer) */ DECLARE_RUNTIME_MESH_VERTEXINTERNAL(FRuntimeMeshVertexNoPositionDualUVHiPrecisionNormals, false, true, true, true, 2, ERuntimeMeshVertexTangentBasisType::HighPrecision, ERuntimeMeshVertexUVType::HighPrecision, RUNTIMEMESHCOMPONENT_API)