Эх сурвалжийг харах

[ue4] Removed RuntimeMeshComponent. We use ProceduralMeshComponent now. Currently does not support two color tinting.

badlogic 7 жил өмнө
parent
commit
fbd8fa5bea
42 өөрчлөгдсөн 12 нэмэгдсэн , 11142 устгасан
  1. 0 58
      spine-ue4/Plugins/RuntimeMeshComponentPlugin/.gitignore
  2. 0 21
      spine-ue4/Plugins/RuntimeMeshComponentPlugin/LICENSE
  3. 0 50
      spine-ue4/Plugins/RuntimeMeshComponentPlugin/README.md
  4. BIN
      spine-ue4/Plugins/RuntimeMeshComponentPlugin/Resources/Icon128.png
  5. 0 29
      spine-ue4/Plugins/RuntimeMeshComponentPlugin/RuntimeMeshComponent.uplugin
  6. 0 2134
      spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Private/RuntimeMeshComponent.cpp
  7. 0 38
      spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Private/RuntimeMeshComponentPlugin.cpp
  8. 0 14
      spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Private/RuntimeMeshComponentPluginPrivatePCH.h
  9. 0 51
      spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Private/RuntimeMeshCore.cpp
  10. 0 32
      spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Private/RuntimeMeshGenericVertex.cpp
  11. 0 561
      spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Private/RuntimeMeshLibrary.cpp
  12. 0 156
      spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Private/TessellationUtilities.cpp
  13. 0 178
      spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Private/TessellationUtilities.h
  14. 0 1215
      spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Public/RuntimeMeshAsync.h
  15. 0 983
      spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Public/RuntimeMeshBuilder.h
  16. 0 1308
      spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Public/RuntimeMeshComponent.h
  17. 0 38
      spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Public/RuntimeMeshComponentPlugin.h
  18. 0 423
      spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Public/RuntimeMeshCore.h
  19. 0 1273
      spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Public/RuntimeMeshGenericVertex.h
  20. 0 129
      spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Public/RuntimeMeshLibrary.h
  21. 0 74
      spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Public/RuntimeMeshProfiling.h
  22. 0 187
      spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Public/RuntimeMeshRendering.h
  23. 0 812
      spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Public/RuntimeMeshSection.h
  24. 0 228
      spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Public/RuntimeMeshSectionProxy.h
  25. 0 257
      spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Public/RuntimeMeshUpdateCommands.h
  26. 0 27
      spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Public/RuntimeMeshVersion.h
  27. 0 24
      spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/RuntimeMeshComponent.Build.cs
  28. 0 269
      spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponentEditor/Private/RuntimeMeshComponentDetails.cpp
  29. 0 27
      spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponentEditor/Private/RuntimeMeshComponentDetails.h
  30. 0 31
      spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponentEditor/Private/RuntimeMeshComponentEditorPlugin.cpp
  31. 0 15
      spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponentEditor/Private/RuntimeMeshComponentEditorPrivatePCH.h
  32. 0 36
      spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponentEditor/Public/IRuntimeMeshComponentEditorPlugin.h
  33. 0 33
      spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponentEditor/RuntimeMeshComponentEditor.Build.cs
  34. 0 1
      spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpinePluginPrivatePCH.h
  35. 6 12
      spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonRendererComponent.cpp
  36. 0 311
      spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonRendererComponentPMC.cpp
  37. 2 2
      spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonRendererComponent.h
  38. 0 97
      spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonRendererComponentPMC.h
  39. 2 2
      spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/SpinePlugin.Build.cs
  40. 0 4
      spine-ue4/Plugins/SpinePlugin/SpinePlugin.uplugin
  41. 1 1
      spine-ue4/Source/SpineUE4/SpineUE4.Build.cs
  42. 1 1
      spine-ue4/SpineUE4.uproject

+ 0 - 58
spine-ue4/Plugins/RuntimeMeshComponentPlugin/.gitignore

@@ -1,58 +0,0 @@
-# Compiled Object files
-*.slo
-*.lo
-*.o
-*.obj
-
-# Precompiled Headers
-*.gch
-*.pch
-
-# Compiled Dynamic libraries
-*.so
-*.dylib
-*.dll
-
-# Fortran module files
-*.mod
-
-# Compiled Static libraries
-*.lai
-*.la
-*.a
-*.lib
-
-# Executables
-*.exe
-*.out
-*.app
-*.ipa
-
-# These project files can be generated by the engine
-*.xcodeproj
-*.sln
-*.suo
-*.opensdf
-*.sdf
-
-# Precompiled Assets
-SourceArt/**/*.png
-SourceArt/**/*.tga
-
-# Binary Files
-Binaries/*
-
-# Builds
-Build/*
-
-# Don't ignore icon files in Build
-!Build/**/*.ico
-
-# Configuration files generated by the Editor
-Saved/*
-
-# Compiled source files for the engine to use
-Intermediate/*
-
-# Cache files for the editor to use
-DerivedDataCache/*

+ 0 - 21
spine-ue4/Plugins/RuntimeMeshComponentPlugin/LICENSE

@@ -1,21 +0,0 @@
-The MIT License (MIT)
-
-Copyright (c) 2016 Chris Conway (Koderz)
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.

+ 0 - 50
spine-ue4/Plugins/RuntimeMeshComponentPlugin/README.md

@@ -1,50 +0,0 @@
-# UE4 Runtime Mesh Component
-
-**Branch with Slicer Support can be found here https://github.com/Koderz/UnrealEngine/tree/RMC_With_Slicer**
-**Examples project can be found here https://github.com/Koderz/UE4RuntimeMeshComponentExamples**
-
-
-**The RuntimeMeshComponent, or RMC for short, is a component designed specifically to support rendering and collision on meshes generated at runtime. This could be anything from voxel engines like Minecraft, to custom model viewers, or just supporting loading user models for things like modding. It has numerous different features to support most of the normal rendering needs of a game, as well as ability to support both static collision for things such as terrain, as well as dynamic collision for things that need to be able to move and bounce around!**
-
-**Now, the RMC is very similar in purpose to the ProceduralMeshComponent or CustomMeshComponent currently found in UE4, but it far surpasses both in features, and efficiency! It on average uses half the memory of the ProceduralMeshComponent, while also being more efficient to render, and far faster to update mesh data. This is shown by the ability to update a 600k+ vertex mesh in real time! The RMC is also nearly 100% compatible with the ProceduralMeshComponent, while adding many features above what the PMC offers.**
-
-
-*Current list of features in the RMC*
-* Slicer Support!!  You can now use
-* Collision cooking speed improvements.** (new)
-* High precision normals support (new)
-* Tessellation support (new)
-* Navigation mesh support (new)
-* Fully configurable vertex structure (new)
-* Ability to save individual sections or the entire RMC to disk (new)
-* RMC <-> StaticMesHComponent conversions.  SMC -> RMC at runtime or in editor.  RMC -> SMC in editor.  (new)
-* Normal/Tangent calculation. (new) (will be getting speed improvements soon)
-* Multiple UV channel support (up to 8 channels) 
-* Fast path updates for meshes that need to update as fast as frame-by-frame
-* Static render path for meshes that don't update frequently, this provides a slightly faster rendering performance.
-* Collision only mesh sections.
-* 50%+ memory reduction over the ProceduralMeshComponent and CustomMeshComponent
-* Visibility and shadowing are configurable per section.
-* Separate vertex positions for cases of only needing to update the position.
-* Collision has lower overhead compared to ProceduralMeshComponent
-
-**The RMC has picked up the collision cooking improvements done in UE4.14. This means that by default you'll see far faster collision updates, but at the cost of a little lower performance collision. You do however have the option to prioritize quality, which will slow down updates, but make actual collision detection a little faster**
-
-**As a part of V2, there has also been some preliminary work done on threaded cooking. This can help to unblock the game thread from collision with large meshes. This is still a very new part, and not heavily tested or complete. To use this you'll have to use a source build of the engine. More information to come.**
-
-For information on installation, usage and everything else, [please read the Wiki](https://github.com/Koderz/UE4RuntimeMeshComponent/wiki/)
-
-**Some requested features that I'm looking into: (These aren't guaranteed to be added)**
-* LOD (Potentially with dithering support)
-* Dithered transitions for mesh updates.
-* Mesh sharing, to allow multiple RMCs to have the same copy of the mesh to reduce memory overhead. This is much like how the StaticMeshComponent works.
-* Instancing support.
-* Multiple vertex buffer (In Addition to the current separate position vertex buffer)
-* Mesh replication
-
-**Supported Engine Versions:**
-v1.2 supports engine versions 4.10+
-v2.0 supports engine versions 4.12+
-
-*The Runtime Mesh Component should support all UE4 platforms.*
-*Collision MAY NOT be available on some platforms (HTML5, Mobile)*

BIN
spine-ue4/Plugins/RuntimeMeshComponentPlugin/Resources/Icon128.png


+ 0 - 29
spine-ue4/Plugins/RuntimeMeshComponentPlugin/RuntimeMeshComponent.uplugin

@@ -1,29 +0,0 @@
-{
-  "FileVersion": 3,
-  "Version": 2,
-  "VersionName": "2.0",
-  "FriendlyName": "Runtime Mesh Component",
-  "Description": "A renderable component with utilities for creating and modifying mesh geometry procedurally at runtime.",
-  "Category": "Rendering",
-	"CreatedBy" : "Chris Conway (Koderz)",
-	"CreatedByURL" : "https://forums.unrealengine.com/member.php?141752-Koderz",
-  "DocsURL": "https://github.com/Koderz/UE4RuntimeMeshComponent/wiki",
-  "MarketplaceURL": "com.epicgames.launcher://ue/marketplace/content/ad0b45a6a31e462aba7cf7c790a9c125",
-  "SupportURL": "https://github.com/Koderz/UE4RuntimeMeshComponent/issues",
-  "EnabledByDefault": true,
-  "CanContainContent": false,
-  "IsBetaVersion": false,
-  "Installed": false,
-  "Modules": [
-    {
-      "Name": "RuntimeMeshComponent",
-      "Type": "Runtime",
-      "LoadingPhase": "Default"
-    },
-		{
-			"Name" : "RuntimeMeshComponentEditor",
-			"Type" : "Editor",
-			"LoadingPhase" : "Default"
-		}
-  ]
-}

+ 0 - 2134
spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Private/RuntimeMeshComponent.cpp

@@ -1,2134 +0,0 @@
-// Copyright 2016 Chris Conway (Koderz). All Rights Reserved.
-
-#include "RuntimeMeshComponentPluginPrivatePCH.h"
-#include "RuntimeMeshComponent.h"
-#include "RuntimeMeshCore.h"
-#include "RuntimeMeshGenericVertex.h"
-#include "RuntimeMeshVersion.h"
-#include "PhysicsEngine/PhysicsSettings.h"
-
-
-/** Runtime mesh scene proxy */
-class FRuntimeMeshSceneProxy : public FPrimitiveSceneProxy
-{
-private:
-	// Temporarily holds all section creation data until this proxy is passsed to the RT.
-	// After this data is applied this array is cleared.
-	TArray<FRuntimeMeshSectionCreateDataInterface*> SectionCreationData;
-
-public:
-
-	FRuntimeMeshSceneProxy(URuntimeMeshComponent* Component)
-		: FPrimitiveSceneProxy(Component)
-		, BodySetup(Component->GetBodySetup())
-	{
-		bStaticElementsAlwaysUseProxyPrimitiveUniformBuffer = true;
-
-
-		// Get the proxy for all mesh sections
-
-		const int32 NumSections = Component->MeshSections.Num();
-		Sections.AddDefaulted(NumSections);
-
-		for (int32 SectionIdx = 0; SectionIdx < NumSections; SectionIdx++)
-		{
-			RuntimeMeshSectionPtr& SourceSection = Component->MeshSections[SectionIdx];
-			if (SourceSection.IsValid())
-			{
-				UMaterialInterface* Material = Component->GetMaterial(SectionIdx);
-				if (Material == nullptr)
-				{
-					Material = UMaterial::GetDefaultMaterial(MD_Surface);
-				}
-
-
-				// Get the section creation data
-				auto* SectionData = SourceSection->GetSectionCreationData(&GetScene(), Material);
-				SectionData->SetTargetSection(SectionIdx);
-				SectionCreationData.Add(SectionData);
-
-			}
-		}
-
-		// Update material relevancy information needed to control the rendering.
-		UpdateMaterialRelevance();
-	}
-
-	virtual ~FRuntimeMeshSceneProxy()
-	{
-		for (FRuntimeMeshSectionProxyInterface* Section : Sections)
-		{
-			if (Section)
-			{
-				delete Section;
-			}
-		}
-	}
-
-	void CreateRenderThreadResources() override
-	{
-		FPrimitiveSceneProxy::CreateRenderThreadResources();
-
-		for (auto Section : SectionCreationData)
-		{
-			CreateSection_RenderThread(Section);
-		}
-		// The individual items are deleted by CreateSection_RenderThread so just clear the array.
-		SectionCreationData.Empty();
-	}
-
-	/** Called on render thread to create a new dynamic section. (Static sections are handled differently) */
-	void CreateSection_RenderThread(FRuntimeMeshSectionCreateDataInterface* SectionData)
-	{
-		SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_CreateSection_RenderThread);
-
-		check(IsInRenderingThread());
-		check(SectionData);
-
-		int32 SectionIndex = SectionData->GetTargetSection();
-
-		// Make sure the array is big enough
-		if (SectionIndex >= Sections.Num())
-		{
-			Sections.SetNum(SectionIndex + 1, false);
-		}
-		
-		// If a section already exists... destroy it!
-		if (FRuntimeMeshSectionProxyInterface* Section = Sections[SectionIndex])
-		{			
-			delete Section;
-		}
-		
-		// Get the proxy and finish the creation here on the render thread.
-		FRuntimeMeshSectionProxyInterface* Section = SectionData->NewProxy;
-		Section->FinishCreate_RenderThread(SectionData);		
-
-		// Save ref to new section
-		Sections[SectionIndex] = Section;
-		
-		delete SectionData;
-		
-		// Update material relevancy information needed to control the rendering.
-		UpdateMaterialRelevance();
-	}
-
-	/** Called on render thread to assign new dynamic data */
-  	void UpdateSection_RenderThread(FRuntimeMeshRenderThreadCommandInterface* SectionData)
-  	{
-		SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_UpdateSection_RenderThread);
-
-  		check(IsInRenderingThread());
-		check(SectionData);
-
-		if (SectionData->GetTargetSection() < Sections.Num() && Sections[SectionData->GetTargetSection()] != nullptr)
-		{
-			Sections[SectionData->GetTargetSection()]->FinishUpdate_RenderThread(SectionData);
-		}
-
-		delete SectionData;
- 	}
-
-	void UpdateSectionPositionOnly_RenderThread(FRuntimeMeshRenderThreadCommandInterface* SectionData)
-	{
-		SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_UpdateSectionPositionOnly_RenderThread);
-
-		check(IsInRenderingThread());
-		check(SectionData);
-
-		if (SectionData->GetTargetSection() < Sections.Num() && Sections[SectionData->GetTargetSection()] != nullptr)
-		{
-			Sections[SectionData->GetTargetSection()]->FinishPositionUpdate_RenderThread(SectionData);
-		}
-
-		delete SectionData;
-	}
-
-	void UpdateSectionProperties_RenderThread(FRuntimeMeshRenderThreadCommandInterface* SectionData)
-	{
-		SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_UpdateSectionProperties_RenderThread);
-
-		check(IsInRenderingThread());
-		check(SectionData);
-
-		int32 SectionIndex = SectionData->GetTargetSection();
-
-		if (SectionIndex < Sections.Num() && Sections[SectionIndex] != nullptr)
-		{
-			Sections[SectionIndex]->FinishPropertyUpdate_RenderThread(SectionData);
-		}
-	}
-
-
-	void DestroySection_RenderThread(int32 SectionIndex)
-	{
-		check(IsInRenderingThread());
-
-		if (SectionIndex < Sections.Num() && Sections[SectionIndex] != nullptr)
-		{
-			delete Sections[SectionIndex];
-			Sections[SectionIndex] = nullptr;
-		}
-		
-		// Update material relevancy information needed to control the rendering.
-		UpdateMaterialRelevance();
-	}
-
-	void ApplyBatchUpdate_RenderThread(FRuntimeMeshBatchUpdateData* BatchUpdateData)
-	{
-		SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_ApplyBatchUpdate_RenderThread);
-
-		check(IsInRenderingThread());
-		check(BatchUpdateData);
-
-		// Destroy flagged sections
-		for (auto& SectionIndex : BatchUpdateData->DestroySections)
-		{
-			DestroySection_RenderThread(SectionIndex);
-		}
-
-		// Create new sections
-		for (auto& SectionToCreate : BatchUpdateData->CreateSections)
-		{
-			CreateSection_RenderThread(static_cast<FRuntimeMeshSectionCreateDataInterface*>(SectionToCreate));
-		}
-
-		// Update sections
-		for (auto& SectionToUpdate : BatchUpdateData->UpdateSections)
-		{
-			UpdateSection_RenderThread(SectionToUpdate);
-		}		
-
-		// Apply section property updates
-		for (auto& SectionToUpdate : BatchUpdateData->PropertyUpdateSections)
-		{
-			UpdateSectionProperties_RenderThread(SectionToUpdate);
-		}
-
-		delete BatchUpdateData;
-
-	}
-
-
-	bool HasDynamicSections() const
-	{
-		for (FRuntimeMeshSectionProxyInterface* Section : Sections)
-		{
-			if (Section && !Section->WantsToRenderInStaticPath())
-			{
-				return true;
-			}
-		}
-		return false;
-	}
-
-	bool HasStaticSections() const 
-	{
-		for (FRuntimeMeshSectionProxyInterface* Section : Sections)
-		{
-			if (Section && Section->WantsToRenderInStaticPath())
-			{
-				return true;
-			}
-		}
-		return false;
-	}
-
-#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION >= 11
-	virtual FPrimitiveViewRelevance GetViewRelevance(const FSceneView* View) const override
-#else
-	virtual FPrimitiveViewRelevance GetViewRelevance(const FSceneView* View) override
-#endif
-	{
-		FPrimitiveViewRelevance Result;
-		Result.bDrawRelevance = IsShown(View);
-		Result.bShadowRelevance = IsShadowCast(View);
-
-		bool bForceDynamicPath = IsRichView(*View->Family) || View->Family->EngineShowFlags.Wireframe || IsSelected() || !IsStaticPathAvailable();
-		Result.bStaticRelevance = !bForceDynamicPath && HasStaticSections();
-		Result.bDynamicRelevance =  bForceDynamicPath || HasDynamicSections();
-		
-		Result.bRenderInMainPass = ShouldRenderInMainPass();
-#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION >= 11
-		Result.bUsesLightingChannels = GetLightingChannelMask() != GetDefaultLightingChannelMask();
-#endif
-		Result.bRenderCustomDepth = ShouldRenderCustomDepth();
-		MaterialRelevance.SetPrimitiveViewRelevance(Result);
-		return Result;
-	}
-
-	void CreateMeshBatch(FMeshBatch& MeshBatch, FRuntimeMeshSectionProxyInterface* Section, FMaterialRenderProxy* WireframeMaterial) const
-	{
-		Section->CreateMeshBatch(MeshBatch, WireframeMaterial, IsSelected());
-
-		MeshBatch.ReverseCulling = IsLocalToWorldDeterminantNegative();
-		MeshBatch.bCanApplyViewModeOverrides = true;
-		
-		FMeshBatchElement& BatchElement = MeshBatch.Elements[0];
-		BatchElement.PrimitiveUniformBufferResource = &GetUniformBuffer();
-	}
-	
-	virtual void DrawStaticElements(FStaticPrimitiveDrawInterface* PDI) override
-	{
-		SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_DrawStaticElements);
-
-		for (FRuntimeMeshSectionProxyInterface* Section : Sections)
-		{
-			if (Section && Section->ShouldRender() && Section->WantsToRenderInStaticPath())
-			{
-				FMeshBatch MeshBatch;
-				CreateMeshBatch(MeshBatch, Section, nullptr);
-				PDI->DrawMesh(MeshBatch, FLT_MAX);
-			}
-		}
-	}
-
-	virtual void GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector) const override
-	{
-		SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_GetDynamicMeshElements);
-
-		// Set up wireframe material (if needed)
-		const bool bWireframe = AllowDebugViewmodes() && ViewFamily.EngineShowFlags.Wireframe;
-
-		FColoredMaterialRenderProxy* WireframeMaterialInstance = nullptr;
-		if (bWireframe)
-		{
-			WireframeMaterialInstance = new FColoredMaterialRenderProxy(
-				GEngine->WireframeMaterial ? GEngine->WireframeMaterial->GetRenderProxy(IsSelected()) : nullptr,
-				FLinearColor(0, 0.5f, 1.f)
-				);
-
-			Collector.RegisterOneFrameMaterialProxy(WireframeMaterialInstance);
-		}
-
-		// Iterate over sections
-		for (FRuntimeMeshSectionProxyInterface* Section : Sections)
-		{
-			if (Section && Section->ShouldRender())
-			{
-				// Add the mesh batch to every view it's visible in
-				for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
-				{
-					if (VisibilityMap & (1 << ViewIndex))
-					{
-						bool bForceDynamicPath = IsRichView(*Views[ViewIndex]->Family) || Views[ViewIndex]->Family->EngineShowFlags.Wireframe || IsSelected() || !IsStaticPathAvailable();
-
-						if (bForceDynamicPath || !Section->WantsToRenderInStaticPath())
-						{
-							FMeshBatch& MeshBatch = Collector.AllocateMesh();
-							CreateMeshBatch(MeshBatch, Section, WireframeMaterialInstance);
-
-							Collector.AddMesh(ViewIndex, MeshBatch);
-						}
-					}
-				}
-			}			
-		}
-
-		// Draw bounds
-#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
-		for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
-		{
-			if (VisibilityMap & (1 << ViewIndex))
-			{				
-#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION >= 13
-				// Draw simple collision as wireframe if 'show collision', and collision is enabled, and we are not using the complex as the simple
-				if (ViewFamily.EngineShowFlags.Collision && IsCollisionEnabled() && BodySetup->GetCollisionTraceFlag() != ECollisionTraceFlag::CTF_UseComplexAsSimple)
-				{
-					FTransform GeomTransform(GetLocalToWorld());
-					BodySetup->AggGeom.GetAggGeom(GeomTransform, GetSelectionColor(FColor(157, 149, 223, 255), IsSelected(), IsHovered()).ToFColor(true), NULL, false, false, UseEditorDepthTest(), ViewIndex, Collector);
-				}
-#endif
-
-				// Render bounds
-				RenderBounds(Collector.GetPDI(ViewIndex), ViewFamily.EngineShowFlags, GetBounds(), IsSelected());
-			}
-		}
-#endif
-	}
-
-
-	virtual bool CanBeOccluded() const override
-	{
-		return !MaterialRelevance.bDisableDepthTest;
-	}
-
-	virtual uint32 GetMemoryFootprint(void) const
-	{
-		return(sizeof(*this) + GetAllocatedSize());
-	}
-
-	uint32 GetAllocatedSize(void) const
-	{
-		return(FPrimitiveSceneProxy::GetAllocatedSize());
-	}
-
-	void UpdateMaterialRelevance()
-	{
-		FMaterialRelevance NewMaterialRelevance;
-		for (FRuntimeMeshSectionProxyInterface* Section : Sections)
-		{
-			if (Section)
-			{
-				NewMaterialRelevance |= Section->GetMaterialRelevance();
-			}
-		}
-		MaterialRelevance = NewMaterialRelevance;
-	}
-
-private:
-	/** Array of sections */
-	TArray<FRuntimeMeshSectionProxyInterface*> Sections;
-	UBodySetup* BodySetup;
-	FMaterialRelevance MaterialRelevance;
-};
-
-
-
-
-void FRuntimeMeshComponentPrePhysicsTickFunction::ExecuteTick( float DeltaTime, ELevelTick TickType, ENamedThreads::Type CurrentThread, const FGraphEventRef& MyCompletionGraphEvent)
-{
-	/* Ensure target still exists */
-
-#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION >= 11
-	bool bIsValid = Target && !Target->IsPendingKillOrUnreachable();
-#else
-	bool bIsValid = Target && !Target->HasAnyFlags(RF_PendingKill | RF_Unreachable);
-#endif
-
-	if (bIsValid)
-	{
-		FScopeCycleCounterUObject ActorScope(Target);
-		Target->BakeCollision();
-	}
-}
-
-FString FRuntimeMeshComponentPrePhysicsTickFunction::DiagnosticMessage()
-{
-	return Target->GetFullName() + TEXT("[PrePhysicsTick]");
-}
-
-
-
-/* Helper for converting an array of FLinearColor to an array of FColors*/
-void ConvertLinearColorToFColor(const TArray<FLinearColor>& LinearColors, TArray<FColor>& Colors)
-{
-	Colors.SetNumUninitialized(LinearColors.Num());
-	for (int32 Index = 0; Index < LinearColors.Num(); Index++)
-	{
-		Colors[Index] = LinearColors[Index].ToFColor(false);
-	}
-}
-
-
-
-
-URuntimeMeshComponent::URuntimeMeshComponent(const FObjectInitializer& ObjectInitializer)
-	: Super(ObjectInitializer)
-	, bUseComplexAsSimpleCollision(true)
-	, bShouldSerializeMeshData(true)
-	, bCollisionDirty(true)
-	, CollisionMode(ERuntimeMeshCollisionCookingMode::CookingPerformance)
-{
-	// Setup the collision update ticker
-	PrePhysicsTick.TickGroup = TG_PrePhysics;
-	PrePhysicsTick.bCanEverTick = true;
-	PrePhysicsTick.bStartWithTickEnabled = true;
-
-	// Reset the batch state
-	BatchState.ResetBatch();
-
-	SetNetAddressable();
-}
-
-TSharedPtr<FRuntimeMeshSectionInterface> URuntimeMeshComponent::CreateOrResetSectionLegacyType(int32 SectionIndex, int32 NumUVChannels)
-{
-	if (NumUVChannels == 1)
-	{
-		return CreateOrResetSection<FRuntimeMeshSection<FRuntimeMeshVertexSimple>>(SectionIndex, false, true);
-	}
-	else if (NumUVChannels == 2)
-	{
-		return CreateOrResetSection<FRuntimeMeshSection<FRuntimeMeshVertexDualUV>>(SectionIndex, false, true);
-	}
-	else
-	{
-		check(false && "Legacy sections only support standard vertex formats wit 1 or 2 uv channels");
-		return nullptr;
-	}
-}
-
-
-void URuntimeMeshComponent::CreateSectionInternal(int32 SectionIndex, ESectionUpdateFlags UpdateFlags)
-{
-	RuntimeMeshSectionPtr Section = MeshSections[SectionIndex];
-	check(Section.IsValid());
-
-	// Update normal/tangents if requested...
-	if (!!(UpdateFlags & ESectionUpdateFlags::CalculateNormalTangent))
-	{
-		Section->GenerateNormalTangent();
-	}
-
-	// calculate tessellation if requested...
-	if (!!(UpdateFlags & ESectionUpdateFlags::CalculateTessellationIndices))
-	{
-		Section->GenerateTessellationIndices();
-	}
-
-	// Use the batch update if one is running
-	if (BatchState.IsBatchPending())
-	{
-		// Mark section created
-		BatchState.MarkSectionCreated(SectionIndex, Section->UpdateFrequency == EUpdateFrequency::Infrequent);
-
-		// Flag collision if this section affects it
-		if (Section->CollisionEnabled)
-		{
-			BatchState.MarkCollisionDirty();
-		}
-		
-		// Flag bounds update
-		BatchState.MarkBoundsDirty();
-
-		// bail since we don't update directly in this case.
-		return;
-	}
-
-	// Enqueue the RT command if we already have a SceneProxy
-	if (SceneProxy && Section->UpdateFrequency != EUpdateFrequency::Infrequent)
-	{
-		// Gather all needed update info
-		auto* SectionData = Section->GetSectionCreationData(GetScene(), GetSectionMaterial(SectionIndex));
-		SectionData->SetTargetSection(SectionIndex);
-
-		// Enqueue update on RT
-		ENQUEUE_UNIQUE_RENDER_COMMAND_TWOPARAMETER(
-			FRuntimeMeshSectionCreate,
-			FRuntimeMeshSceneProxy*, RuntimeMeshSceneProxy, (FRuntimeMeshSceneProxy*)SceneProxy,
-			FRuntimeMeshSectionCreateDataInterface*, SectionData, SectionData,
-			{
-				RuntimeMeshSceneProxy->CreateSection_RenderThread(SectionData);
-			}
-		);
-	}
-	else
-	{
-		// Mark the render state dirty so it's recreated when necessary.
-		MarkRenderStateDirty();
-	}
-
-	// Mark collision dirty so it's re-baked at the end of this frame
-	if (Section->CollisionEnabled)
-	{
-		MarkCollisionDirty();
-	}
-
-	// Update overall bounds
-	UpdateLocalBounds();
-
-}
-
-void URuntimeMeshComponent::UpdateSectionInternal(int32 SectionIndex, bool bHadVertexPositionsUpdate, bool bHadVertexUpdates, bool bHadIndexUpdates, bool bNeedsBoundsUpdate, ESectionUpdateFlags UpdateFlags)
-{
-	// Ensure that something was updated
-	check(bHadVertexPositionsUpdate || bHadVertexUpdates || bHadIndexUpdates || bNeedsBoundsUpdate);
-
-	check(SectionIndex < MeshSections.Num() && MeshSections[SectionIndex].IsValid());	
-	RuntimeMeshSectionPtr Section = MeshSections[SectionIndex];
-	
-	// Update normal/tangents if requested...
-	if (!!(UpdateFlags & ESectionUpdateFlags::CalculateNormalTangent))
-	{
-		Section->GenerateNormalTangent();
-	}
-
-	// calculate tessellation if requested...
-	if (!!(UpdateFlags & ESectionUpdateFlags::CalculateTessellationIndices))
-	{
-		Section->GenerateTessellationIndices();
-	}
-
-	/* Make sure this is only flagged if the section is dual buffer */
-	bHadVertexPositionsUpdate = Section->IsDualBufferSection() && bHadVertexPositionsUpdate;
-	bool bNeedsCollisionUpdate = Section->CollisionEnabled && (bHadVertexPositionsUpdate || (!Section->IsDualBufferSection() && bHadVertexUpdates));
-	
-	// Use the batch update if one is running
-	if (BatchState.IsBatchPending())
-	{
-		// Mark update for section or promote to proxy recreate if static section
-		if (Section->UpdateFrequency == EUpdateFrequency::Infrequent)
-		{
-			BatchState.MarkRenderStateDirty();
-		}
-		else
-		{
-			ERuntimeMeshSectionBatchUpdateType UpdateType = ERuntimeMeshSectionBatchUpdateType::None;
-			UpdateType |= bHadVertexPositionsUpdate ? ERuntimeMeshSectionBatchUpdateType::PositionsUpdate : ERuntimeMeshSectionBatchUpdateType::None;
-			UpdateType |= bHadVertexUpdates ? ERuntimeMeshSectionBatchUpdateType::VerticesUpdate : ERuntimeMeshSectionBatchUpdateType::None;
-			UpdateType |= bHadIndexUpdates ? ERuntimeMeshSectionBatchUpdateType::IndicesUpdate : ERuntimeMeshSectionBatchUpdateType::None;
-
-			BatchState.MarkUpdateForSection(SectionIndex, UpdateType);
-		}
-
-		// Flag collision if this section affects it
-		if (bNeedsCollisionUpdate)
-		{
-			BatchState.MarkCollisionDirty();
-		}
-
-		// Flag bounds update if needed.
-		if (bNeedsBoundsUpdate)
-		{
-			BatchState.MarkBoundsDirty();
-		}
-
-		// bail since we don't update directly in this case.
-		return;
-	}
-
-
-	// Send the update to the render thread if the scene proxy exists
-	if (SceneProxy && Section->UpdateFrequency != EUpdateFrequency::Infrequent)
-	{
-		auto* SectionData = Section->GetSectionUpdateData(bHadVertexPositionsUpdate, bHadVertexUpdates, bHadIndexUpdates);
-		SectionData->SetTargetSection(SectionIndex);
-
-		// Enqueue update on RT
-		ENQUEUE_UNIQUE_RENDER_COMMAND_TWOPARAMETER(
-			FRuntimeMeshSectionUpdate,
-			FRuntimeMeshSceneProxy*, RuntimeMeshSceneProxy, (FRuntimeMeshSceneProxy*)SceneProxy,
-			FRuntimeMeshRenderThreadCommandInterface*, SectionData, SectionData,
-			{
-				RuntimeMeshSceneProxy->UpdateSection_RenderThread(SectionData);
-			}
-		);
-	}
-	else
-	{
-		// Mark the renderstate dirty so it's recreated when necessary.
-		MarkRenderStateDirty();
-	}
-
-	// Mark collision dirty so it's re-baked at the end of this frame
-	if (bNeedsCollisionUpdate)
-	{
-		MarkCollisionDirty();
-	}
-
-	// Update overall bounds if needed
-	if (bNeedsBoundsUpdate)
-	{
-		UpdateLocalBounds();
-	}
-}
-
-void URuntimeMeshComponent::UpdateSectionVertexPositionsInternal(int32 SectionIndex, bool bNeedsBoundsUpdate)
-{
-	check(SectionIndex < MeshSections.Num() && MeshSections[SectionIndex].IsValid());
-	RuntimeMeshSectionPtr Section = MeshSections[SectionIndex];
-
-	if (SceneProxy)
-	{
-		auto SectionData = Section->GetSectionPositionUpdateData();
-		SectionData->SetTargetSection(SectionIndex);
-
-		// Enqueue command to modify render thread info
-		ENQUEUE_UNIQUE_RENDER_COMMAND_TWOPARAMETER(
-			FRuntimeMeshSectionPositionUpdate,
-			FRuntimeMeshSceneProxy*, RuntimeMeshSceneProxy, (FRuntimeMeshSceneProxy*)SceneProxy,
-			FRuntimeMeshRenderThreadCommandInterface*, SectionData, SectionData,
-			{
-				RuntimeMeshSceneProxy->UpdateSectionPositionOnly_RenderThread(SectionData);
-			}
-		);
-	}
-	else
-	{
-		MarkRenderStateDirty();
-	}
-
-	if (bNeedsBoundsUpdate)
-	{
-		UpdateLocalBounds();
-	}
-}
-
-void URuntimeMeshComponent::UpdateSectionPropertiesInternal(int32 SectionIndex, bool bUpdateRequiresProxyRecreateIfStatic)
-{
-	check(SectionIndex < MeshSections.Num() && MeshSections[SectionIndex].IsValid());
-	RuntimeMeshSectionPtr Section = MeshSections[SectionIndex];
-
-	bool bRequiresRecreate = bUpdateRequiresProxyRecreateIfStatic && Section->UpdateFrequency == EUpdateFrequency::Infrequent;
-
-	// Use the batch update if one is running
-	if (BatchState.IsBatchPending())
-	{
-		if (bRequiresRecreate)
-		{
-			BatchState.MarkRenderStateDirty();
-		}
-		else
-		{
-			BatchState.MarkUpdateForSection(SectionIndex, ERuntimeMeshSectionBatchUpdateType::PropertyUpdate);
-		}
-
-		// bail since we don't update directly in this case.
-		return;
-	}
-
-
-
-	if (SceneProxy && !bRequiresRecreate)
-	{
-		auto SectionData = new FRuntimeMeshSectionPropertyUpdateData();
-		SectionData->SetTargetSection(SectionIndex);
-		SectionData->bIsVisible = Section->bIsVisible;
-		SectionData->bCastsShadow = Section->bCastsShadow;
-
-
-		// Enqueue command to modify render thread info
-		ENQUEUE_UNIQUE_RENDER_COMMAND_TWOPARAMETER(
-			FRuntimeMeshSectionPropertyUpdate,
-			FRuntimeMeshSceneProxy*, RuntimeMeshSceneProxy, (FRuntimeMeshSceneProxy*)SceneProxy,
-			FRuntimeMeshRenderThreadCommandInterface*, SectionData, SectionData,
-			{
-				RuntimeMeshSceneProxy->UpdateSectionProperties_RenderThread(SectionData);
-			}
-		);
-	}
-	else
-	{
-		MarkRenderStateDirty();
-	}
-}
-
-
-void URuntimeMeshComponent::UpdateMeshSectionPositionsImmediate(int32 SectionIndex, TArray<FVector>& VertexPositions, ESectionUpdateFlags UpdateFlags)
-{
-	SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_UpdateMeshSectionPositionsImmediate);
-
-	// Validate all update parameters
-	RMC_VALIDATE_UPDATEPARAMETERS_DUALBUFFER(SectionIndex, /*VoidReturn*/);
-
-	// Get section
-	RuntimeMeshSectionPtr& Section = MeshSections[SectionIndex];
-
-	// Check dual buffer section status
-	if (VertexPositions.Num() != Section->PositionVertexBuffer.Num())
-	{
-		Log(TEXT("UpdateMeshSection() - Positions cannot change length unless the vertexdata is updated as well."), true);
-		return;
-	}
-
-	bool bShouldUseMove = (UpdateFlags & ESectionUpdateFlags::MoveArrays) != ESectionUpdateFlags::None;
-	bool bNeedsBoundsUpdate = false;
-
-	// Update vertex positions if supplied
-	bool bUpdatedVertexPositions = false;
-	if (VertexPositions.Num() > 0)
-	{
-		bNeedsBoundsUpdate = Section->UpdateVertexPositionBuffer(VertexPositions, nullptr, bShouldUseMove);
-		bUpdatedVertexPositions = true;
-	}
-	else
-	{
-		Log(TEXT("UpdatemeshSection() - Vertex positions empty. They will not be updated."));
-	}
-
-	// Finalize section update if we have anything to apply
-	if (bUpdatedVertexPositions)
-	{
-		UpdateSectionVertexPositionsInternal(SectionIndex, bNeedsBoundsUpdate);
-	}
-}
-
-void URuntimeMeshComponent::UpdateMeshSectionPositionsImmediate(int32 SectionIndex, TArray<FVector>& VertexPositions, const FBox& BoundingBox, ESectionUpdateFlags UpdateFlags)
-{
-	SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_UpdateMeshSectionPositionsImmediate_WithBoundinBox);
-
-	// Validate all update parameters
-	RMC_VALIDATE_UPDATEPARAMETERS_DUALBUFFER(SectionIndex, /*VoidReturn*/);
-
-	// Get section
-	RuntimeMeshSectionPtr& Section = MeshSections[SectionIndex];
-
-	// Check dual buffer section status
-	if (VertexPositions.Num() != Section->PositionVertexBuffer.Num())
-	{
-		Log(TEXT("UpdateMeshSection() - Positions cannot change length unless the vertexdata is updated as well."), true);
-		return;
-	}
-
-	bool bShouldUseMove = (UpdateFlags & ESectionUpdateFlags::MoveArrays) != ESectionUpdateFlags::None;
-	bool bNeedsBoundsUpdate = false;
-
-	// Update vertex positions if supplied
-	bool bUpdatedVertexPositions = false;
-	if (VertexPositions.Num() > 0)
-	{
-		bNeedsBoundsUpdate = Section->UpdateVertexPositionBuffer(VertexPositions, &BoundingBox, bShouldUseMove);
-		bUpdatedVertexPositions = true;
-	}
-	else
-	{
-		Log(TEXT("UpdatemeshSection() - Vertex positions empty. They will not be updated."));
-	}
-
-	// Finalize section update if we have anything to apply
-	if (bUpdatedVertexPositions)
-	{
-		UpdateSectionVertexPositionsInternal(SectionIndex, bNeedsBoundsUpdate);
-	}
-}
-
-
-TArray<FVector>* URuntimeMeshComponent::BeginMeshSectionPositionUpdate(int32 SectionIndex)
-{
-	// Validate all update parameters
-	RMC_VALIDATE_UPDATEPARAMETERS_DUALBUFFER(SectionIndex, nullptr);
-
-	// Get section
-	RuntimeMeshSectionPtr& Section = MeshSections[SectionIndex];
-	
-	return &Section->PositionVertexBuffer;
-}
-
-void URuntimeMeshComponent::EndMeshSectionPositionUpdate(int32 SectionIndex)
-{
-	// Validate all update parameters
-	RMC_VALIDATE_UPDATEPARAMETERS_DUALBUFFER(SectionIndex, /*VoidReturn*/);
-	
-	// TODO: Validate that the position buffer is still the same length
-
-	UpdateSectionVertexPositionsInternal(SectionIndex, true);
-}
-
-void URuntimeMeshComponent::EndMeshSectionPositionUpdate(int32 SectionIndex, const FBox& BoundingBox)
-{
-	// Validate all update parameters
-	RMC_VALIDATE_UPDATEPARAMETERS_DUALBUFFER(SectionIndex, /*VoidReturn*/);
-
-	RuntimeMeshSectionPtr& Section = MeshSections[SectionIndex];
-	
-	bool bNeedsBoundingBoxUpdate = !(Section->LocalBoundingBox == BoundingBox);
-	if (bNeedsBoundingBoxUpdate)
-	{
-		Section->LocalBoundingBox = BoundingBox;
-	}
-	
-	// TODO: Validate that the position buffer is still the same length
-
-	UpdateSectionVertexPositionsInternal(SectionIndex, bNeedsBoundingBoxUpdate);
-}
-
-
-
-
-void URuntimeMeshComponent::EndMeshSectionUpdate(int32 SectionIndex, ERuntimeMeshBuffer UpdatedBuffers, ESectionUpdateFlags UpdateFlags)
-{
-	// Bail if we have no buffers to update.
-	if (UpdatedBuffers == ERuntimeMeshBuffer::None)
-	{
-		return;
-	}
-
-	// Validate all update parameters
-	RMC_VALIDATE_UPDATEPARAMETERS(SectionIndex, /*VoidReturn*/);
-
-	// Get section and update bounding box
-	RuntimeMeshSectionPtr& Section = MeshSections[SectionIndex];
-	Section->RecalculateBoundingBox();
-
-	// Finalize section update
-	UpdateSectionInternal(SectionIndex, 
-		!!(UpdatedBuffers & ERuntimeMeshBuffer::Positions), 
-		!!(UpdatedBuffers & ERuntimeMeshBuffer::Vertices), 
-		!!(UpdatedBuffers & ERuntimeMeshBuffer::Triangles), true, UpdateFlags);
-}
-
-
-void URuntimeMeshComponent::EndMeshSectionUpdate(int32 SectionIndex, ERuntimeMeshBuffer UpdatedBuffers, const FBox& BoundingBox, ESectionUpdateFlags UpdateFlags)
-{
-	// Bail if we have no buffers to update.
-	if (UpdatedBuffers == ERuntimeMeshBuffer::None)
-	{
-		return;
-	}
-
-	// Validate all update parameters
-	RMC_VALIDATE_UPDATEPARAMETERS(SectionIndex, /*VoidReturn*/);
-
-	// Get section and update bounding box
-	RuntimeMeshSectionPtr& Section = MeshSections[SectionIndex];
-	Section->LocalBoundingBox = BoundingBox;
-
-	// Finalize section update
-	UpdateSectionInternal(SectionIndex,
-		!!(UpdatedBuffers & ERuntimeMeshBuffer::Positions),
-		!!(UpdatedBuffers & ERuntimeMeshBuffer::Vertices),
-		!!(UpdatedBuffers & ERuntimeMeshBuffer::Triangles), true, UpdateFlags);
-}
-
-
-
-void URuntimeMeshComponent::CreateMeshSection(int32 SectionIndex, const TArray<FVector>& Vertices, const TArray<int32>& Triangles, const TArray<FVector>& Normals,
-	const TArray<FVector2D>& UV0, const TArray<FColor>& Colors, const TArray<FRuntimeMeshTangent>& Tangents, bool bCreateCollision,	EUpdateFrequency UpdateFrequency, 
-	ESectionUpdateFlags UpdateFlags)
-{
-	SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_CreateMeshSection);
-
-	// Validate all creation parameters
-	RMC_VALIDATE_CREATIONPARAMETERS(SectionIndex, Vertices, Triangles, /*VoidReturn*/);
-
-	// Create the section
-	auto NewSection = CreateOrResetSectionLegacyType(SectionIndex, 1);
-
-	// Update the mesh data in the section
-	NewSection->UpdateVertexBufferInternal(Vertices, Normals, Tangents, UV0, TArray<FVector2D>(), Colors);
-
-	TArray<int32>& TrianglesRef = const_cast<TArray<int32>&>(Triangles);
-	NewSection->UpdateIndexBuffer(TrianglesRef, false);
-
-	// Track collision status and update collision information if necessary
-	NewSection->CollisionEnabled = bCreateCollision;
-	NewSection->UpdateFrequency = UpdateFrequency;
-
-	// Finalize section.
-	CreateSectionInternal(SectionIndex, UpdateFlags);
-}
-
-void URuntimeMeshComponent::CreateMeshSection(int32 SectionIndex, const TArray<FVector>& Vertices, const TArray<int32>& Triangles, const TArray<FVector>& Normals,
-	const TArray<FVector2D>& UV0, const TArray<FVector2D>& UV1, const TArray<FColor>& Colors, const TArray<FRuntimeMeshTangent>& Tangents,
-	bool bCreateCollision, EUpdateFrequency UpdateFrequency, ESectionUpdateFlags UpdateFlags)
-{
-	SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_CreateMeshSection_DualUV);
-
-	// Validate all creation parameters
-	RMC_VALIDATE_CREATIONPARAMETERS(SectionIndex, Vertices, Triangles, /*VoidReturn*/);
-
-	// Create the section
-	auto NewSection = CreateOrResetSectionLegacyType(SectionIndex, 2);
-
-	// Update the mesh data in the section
-	NewSection->UpdateVertexBufferInternal(Vertices, Normals, Tangents, UV0, UV1, Colors);
-
-	TArray<int32>& TrianglesRef = const_cast<TArray<int32>&>(Triangles);
-	NewSection->UpdateIndexBuffer(TrianglesRef, false);
-
-	// Track collision status and update collision information if necessary
-	NewSection->CollisionEnabled = bCreateCollision;
-	NewSection->UpdateFrequency = UpdateFrequency;
-
-	// Finalize section.
-	CreateSectionInternal(SectionIndex, UpdateFlags);
-}
-
-
-
-void URuntimeMeshComponent::UpdateMeshSection(int32 SectionIndex, const TArray<FVector>& Vertices, const TArray<FVector>& Normals, const TArray<FVector2D>& UV0,
-	const TArray<FColor>& Colors, const TArray<FRuntimeMeshTangent>& Tangents, ESectionUpdateFlags UpdateFlags)
-{
-	UpdateMeshSection(SectionIndex, Vertices, TArray<int32>(), Normals, UV0, Colors, Tangents, UpdateFlags);
-}
-
-void URuntimeMeshComponent::UpdateMeshSection(int32 SectionIndex, const TArray<FVector>& Vertices, const TArray<FVector>& Normals, const TArray<FVector2D>& UV0,
-	const TArray<FVector2D>& UV1, const TArray<FColor>& Colors, const TArray<FRuntimeMeshTangent>& Tangents, ESectionUpdateFlags UpdateFlags)
-{
-	UpdateMeshSection(SectionIndex, Vertices, TArray<int32>(), Normals, UV0, UV1, Colors, Tangents, UpdateFlags);
-}
-
-void URuntimeMeshComponent::UpdateMeshSection(int32 SectionIndex, const TArray<FVector>& Vertices, const TArray<int32>& Triangles, const TArray<FVector>& Normals,
-	const TArray<FVector2D>& UV0, const TArray<FColor>& Colors, const TArray<FRuntimeMeshTangent>& Tangents, ESectionUpdateFlags UpdateFlags)
-{
-	SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_UpdateMeshSection);
-
-	// Validate all update parameters
-	RMC_VALIDATE_UPDATEPARAMETERS_INTERNALSECTION(SectionIndex, /*VoidReturn*/);
-
-	// Validate section type
-	MeshSections[SectionIndex]->GetVertexType()->EnsureEquals<FRuntimeMeshVertexSimple>();
-
-	// Get section
-	RuntimeMeshSectionPtr& Section = MeshSections[SectionIndex];
-	
-	// Tell the section to update the vertex buffer
-	bool bHadVertexUpdates = Section->UpdateVertexBufferInternal(Vertices, Normals, Tangents, UV0, TArray<FVector2D>(), Colors);
-
-	bool bHadTriangleUpdates = Triangles.Num() > 0;
-	if (bHadTriangleUpdates)
-	{
-		TArray<int32>& TrianglesRef = const_cast<TArray<int32>&>(Triangles);
-
-		Section->UpdateIndexBuffer(TrianglesRef, false);
-	}
-
-	UpdateSectionInternal(SectionIndex, false, bHadVertexUpdates, bHadTriangleUpdates, true, UpdateFlags);
-}
-
-void URuntimeMeshComponent::UpdateMeshSection(int32 SectionIndex, const TArray<FVector>& Vertices, const TArray<int32>& Triangles, const TArray<FVector>& Normals,
-	const TArray<FVector2D>& UV0, const TArray<FVector2D>& UV1, const TArray<FColor>& Colors, const TArray<FRuntimeMeshTangent>& Tangents, ESectionUpdateFlags UpdateFlags)
-{
-	SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_UpdateMeshSection_DualUV);
-
-	// Validate all update parameters
-	RMC_VALIDATE_UPDATEPARAMETERS_INTERNALSECTION(SectionIndex, /*VoidReturn*/);
-
-	// Validate section type
-	MeshSections[SectionIndex]->GetVertexType()->EnsureEquals<FRuntimeMeshVertexDualUV>();
-
-	// Get section
-	RuntimeMeshSectionPtr& Section = MeshSections[SectionIndex];
-	
-	// Tell the section to update the vertex buffer
-	bool bHadVertexUpdates = Section->UpdateVertexBufferInternal(Vertices, Normals, Tangents, UV0, UV1, Colors);
-
-	bool bHadTriangleUpdates = Triangles.Num() > 0;
-	if (bHadTriangleUpdates)
-	{
-		TArray<int32>& TrianglesRef = const_cast<TArray<int32>&>(Triangles);
-
-		Section->UpdateIndexBuffer(TrianglesRef, false);
-	}
-
-	UpdateSectionInternal(SectionIndex, false, bHadVertexUpdates, bHadTriangleUpdates, true, UpdateFlags);
-}
-
-
-void URuntimeMeshComponent::CreateMeshSection_Blueprint(int32 SectionIndex, const TArray<FVector>& Vertices, const TArray<int32>& Triangles, const TArray<FVector>& Normals, const TArray<FRuntimeMeshTangent>& Tangents,
-	const TArray<FVector2D>& UV0, const TArray<FVector2D>& UV1, const TArray<FLinearColor>& VertexColors, bool bCreateCollision, bool bCalculateNormalTangent, bool bGenerateTessellationTriangles, EUpdateFrequency UpdateFrequency)
-{	
-	// Convert vertex colors to FColor
-	TArray<FColor> Colors;
-	ConvertLinearColorToFColor(VertexColors, Colors);
-
-	ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None;
-	UpdateFlags |= bCalculateNormalTangent ? ESectionUpdateFlags::CalculateNormalTangent : ESectionUpdateFlags::None;
-	UpdateFlags |= bGenerateTessellationTriangles ? ESectionUpdateFlags::CalculateTessellationIndices : ESectionUpdateFlags::None;
-
-	// Create section
-	CreateMeshSection(SectionIndex, Vertices, Triangles, Normals, UV0, UV1, Colors, Tangents, bCreateCollision, UpdateFrequency, UpdateFlags);
-}
-
-void URuntimeMeshComponent::UpdateMeshSection_Blueprint(int32 SectionIndex, const TArray<FVector>& Vertices, const TArray<int32>& Triangles, const TArray<FVector>& Normals, const TArray<FRuntimeMeshTangent>& Tangents,
-	const TArray<FVector2D>& UV0, const TArray<FVector2D>& UV1, const TArray<FLinearColor>& VertexColors, bool bCalculateNormalTangent, bool bGenerateTessellationTriangles)
-{
-	// Convert vertex colors to FColor
-	TArray<FColor> Colors;
-	ConvertLinearColorToFColor(VertexColors, Colors);
-
-	ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None;
-	UpdateFlags |= bCalculateNormalTangent ? ESectionUpdateFlags::CalculateNormalTangent : ESectionUpdateFlags::None;
-	UpdateFlags |= bGenerateTessellationTriangles ? ESectionUpdateFlags::CalculateTessellationIndices : ESectionUpdateFlags::None;
-
-	// Update section
-	UpdateMeshSection(SectionIndex, Vertices, Triangles, Normals, UV0, UV1, Colors, Tangents, UpdateFlags);
-}
-
-
-
-void URuntimeMeshComponent::CreateMeshSection(int32 SectionIndex, IRuntimeMeshVerticesBuilder& Vertices, FRuntimeMeshIndicesBuilder& Triangles, bool bCreateCollision,
-	EUpdateFrequency UpdateFrequency, ESectionUpdateFlags UpdateFlags)
-{
-	RMC_CHECKINGAME_LOGINEDITOR((SectionIndex >= 0), "SectionIndex cannot be negative.", /**/);
-	RMC_CHECKINGAME_LOGINEDITOR((Vertices.Length() > 0), "Vertices length must not be 0.", /**/);
-	RMC_CHECKINGAME_LOGINEDITOR((Triangles.Length() > 0), "Triangles length must not be 0", /**/);
-
-	// First we need to create the new section
-	TSharedPtr<FRuntimeMeshSectionInterface> Section = MakeShareable(Vertices.GetVertexType()->CreateSection(Vertices.WantsSeparatePositionBuffer()));
-
-	// Ensure sections array is long enough
-	if (SectionIndex >= MeshSections.Num())
-	{
-		MeshSections.SetNum(SectionIndex + 1, false);
-	}
-
-	// Set the new section
-	MeshSections[SectionIndex] = Section;
-
-	// Set vertex/index buffers
-	Section->UpdateVertexBuffer(Vertices, nullptr, !!(UpdateFlags & ESectionUpdateFlags::MoveArrays));
-	Section->UpdateIndexBuffer(Triangles, !!(UpdateFlags & ESectionUpdateFlags::MoveArrays));
-	
-
-	// Track collision status and update collision information if necessary
-	Section->CollisionEnabled = bCreateCollision;
-	Section->UpdateFrequency = UpdateFrequency;
-
-	// Finalize section.
-	CreateSectionInternal(SectionIndex, UpdateFlags);
-}
-
-void URuntimeMeshComponent::UpdateMeshSection(int32 SectionIndex, IRuntimeMeshVerticesBuilder& Vertices, FRuntimeMeshIndicesBuilder& Triangles, ESectionUpdateFlags UpdateFlags)
-{	
-	// Validate all update parameters
-	RMC_VALIDATE_UPDATEPARAMETERS_INTERNALSECTION(SectionIndex, /*VoidReturn*/);
-
-	// Get section
-	RuntimeMeshSectionPtr& Section = MeshSections[SectionIndex];
-
-	// Set vertex/index buffers
-	Section->UpdateVertexBuffer(Vertices, nullptr, !!(UpdateFlags & ESectionUpdateFlags::MoveArrays));
-	Section->UpdateIndexBuffer(Triangles, !!(UpdateFlags & ESectionUpdateFlags::MoveArrays));
-
-	UpdateSectionInternal(SectionIndex, Vertices.WantsSeparatePositionBuffer(), true, true, true, UpdateFlags);
-}
-
-
-
-void URuntimeMeshComponent::ClearMeshSection(int32 SectionIndex)
-{
-	SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_ClearMeshSection);
-
- 	if (SectionIndex < MeshSections.Num() && MeshSections[SectionIndex].IsValid())
- 	{
-		// Did this section have collision
-		bool HadCollision = MeshSections[SectionIndex]->CollisionEnabled;
-		bool bWasStaticSection = MeshSections[SectionIndex]->UpdateFrequency == EUpdateFrequency::Infrequent;
-
-		// Clear the section
-		MeshSections[SectionIndex].Reset();
-		
-		// Use the batch update if one is running
-		if (BatchState.IsBatchPending())
-		{
-			// Mark section created
-			BatchState.MarkSectionDestroyed(SectionIndex, bWasStaticSection);
-
-			// Flag collision if this section affects it
-			if (HadCollision)
-			{
-				BatchState.MarkCollisionDirty();
-			}
-
-			// Flag bounds update
-			BatchState.MarkBoundsDirty();
-			
-			// bail since we don't update directly in this case.
-			return;
-		}
-
-
-		if (SceneProxy && !bWasStaticSection)
-		{			
-			// Enqueue update on RT
-			ENQUEUE_UNIQUE_RENDER_COMMAND_TWOPARAMETER(
-				FRuntimeMeshSectionUpdate,
-				FRuntimeMeshSceneProxy*, RuntimeMeshSceneProxy, (FRuntimeMeshSceneProxy*)SceneProxy,
-				int32, SectionIndex, SectionIndex,
-				{
-					RuntimeMeshSceneProxy->DestroySection_RenderThread(SectionIndex);
-				}
-			);
-		}
-		else
-		{
-			MarkRenderStateDirty();
-		}
-
-		// Update our collision info only if this section had any influence on it
-		if (HadCollision)
-		{
-			MarkCollisionDirty();
-		}
-		
-		UpdateLocalBounds();
-
- 	}
-}
-
-void URuntimeMeshComponent::ClearAllMeshSections()
-{
- 	MeshSections.Empty();
-
-	// Use the batch update if one is running
-	if (BatchState.IsBatchPending())
-	{
-		// Mark render state dirty
-		BatchState.MarkRenderStateDirty();
-
-		// Flag collision
-		BatchState.MarkCollisionDirty();
-
-		// Flag bounds update
-		BatchState.MarkBoundsDirty();
-
-		// bail since we don't update directly in this case.
-		return;
-	}
-	
- 	MarkRenderStateDirty();
-	MarkCollisionDirty();
-	UpdateLocalBounds();
-}
-
-void URuntimeMeshComponent::SetSectionTessellationTriangles(int32 SectionIndex, const TArray<int32>& TessellationTriangles, bool bShouldMoveArray)
-{
-	// Validate all update parameters
-	RMC_VALIDATE_UPDATEPARAMETERS_INTERNALSECTION(SectionIndex, /*VoidReturn*/);
-	
-	// Get section
-	RuntimeMeshSectionPtr& Section = MeshSections[SectionIndex];
-
-	// Tell the section to update the tessellation index buffer
-	Section->UpdateTessellationIndexBuffer(const_cast<TArray<int32>&>(TessellationTriangles), bShouldMoveArray);
-
-	UpdateSectionInternal(SectionIndex, false, false, true, false, ESectionUpdateFlags::None);
-}
-
-
-
-
-bool URuntimeMeshComponent::GetSectionBoundingBox(int32 SectionIndex, FBox& OutBoundingBox)
-{
-	if (SectionIndex < MeshSections.Num() && MeshSections[SectionIndex].IsValid())
-	{
-		OutBoundingBox = MeshSections[SectionIndex]->LocalBoundingBox;
-		return true;
-	}
-	return false;
-}
-
-void URuntimeMeshComponent::SetMeshSectionVisible(int32 SectionIndex, bool bNewVisibility)
-{
- 	if (SectionIndex < MeshSections.Num() && MeshSections[SectionIndex].IsValid())
- 	{
- 		// Set game thread state
- 		MeshSections[SectionIndex]->bIsVisible = bNewVisibility;
-
-		// Finish the update
-		UpdateSectionPropertiesInternal(SectionIndex, false);
- 	}
-}
-
-bool URuntimeMeshComponent::IsMeshSectionVisible(int32 SectionIndex) const
-{
-	return SectionIndex < MeshSections.Num() && MeshSections[SectionIndex].IsValid() && MeshSections[SectionIndex]->bIsVisible;
-}
-
-void URuntimeMeshComponent::SetMeshSectionCastsShadow(int32 SectionIndex, bool bNewCastsShadow)
-{
-	if (SectionIndex < MeshSections.Num() && MeshSections[SectionIndex].IsValid())
-	{
-		// Set game thread state
-		MeshSections[SectionIndex]->bCastsShadow = bNewCastsShadow;
-
-		// Finish the update
-		UpdateSectionPropertiesInternal(SectionIndex, true);
-	}
-}
-
-bool URuntimeMeshComponent::IsMeshSectionCastingShadows(int32 SectionIndex) const
-{
-	return SectionIndex < MeshSections.Num() && MeshSections[SectionIndex].IsValid() && MeshSections[SectionIndex]->bCastsShadow;
-}
-
-void URuntimeMeshComponent::SetMeshSectionCollisionEnabled(int32 SectionIndex, bool bNewCollisionEnabled)
-{
-	if (SectionIndex < MeshSections.Num() && MeshSections[SectionIndex].IsValid())
-	{
-		auto& Section = MeshSections[SectionIndex];
-		if (Section->CollisionEnabled != bNewCollisionEnabled)
-		{
-			Section->CollisionEnabled = bNewCollisionEnabled;
-			
-			// Use the batch update if one is running
-			if (BatchState.IsBatchPending())
-			{
-				// Mark render state dirty
-				BatchState.MarkCollisionDirty();
-			}
-			else
-			{
-				MarkCollisionDirty();
-			}
-		}
-	}
-}
-
-bool URuntimeMeshComponent::IsMeshSectionCollisionEnabled(int32 SectionIndex)
-{
-	return SectionIndex < MeshSections.Num() && MeshSections[SectionIndex].IsValid() && MeshSections[SectionIndex]->CollisionEnabled;
-}
-
-
-
-int32 URuntimeMeshComponent::GetNumSections() const
-{
-	int32 SectionCount = 0;
-	for (int32 Index = 0; Index < MeshSections.Num(); Index++)
-	{
-		if (MeshSections[Index].IsValid())
-		{
-			SectionCount++;
-		}
-	}
-
-	return SectionCount;
-}
-
-bool URuntimeMeshComponent::DoesSectionExist(int32 SectionIndex) const
-{
-	return SectionIndex < MeshSections.Num() && MeshSections[SectionIndex].IsValid();
-}
-
-int32 URuntimeMeshComponent::FirstAvailableMeshSectionIndex() const
-{
-	for (int32 Index = 0; Index < MeshSections.Num(); Index++)
-	{
-		if (!MeshSections[Index].IsValid())
-		{
-			return Index;
-		}
-	}
-	return MeshSections.Num();
-}
-
-int32 URuntimeMeshComponent::GetLastSectionIndex() const
-{
-	for (int32 Index = MeshSections.Num() - 1; Index >= 0; Index--)
-	{
-		if (MeshSections[Index].IsValid())
-		{
-			return Index;
-		}
-	}
-
-	return -1;
-}
-
-
-void URuntimeMeshComponent::SetMeshCollisionSection(int32 CollisionSectionIndex, const TArray<FVector>& Vertices, const TArray<int32>& Triangles)
-{
-	SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_SetMeshCollisionSection);
-
-	if (MeshCollisionSections.Num() <= CollisionSectionIndex)
-	{
-		MeshCollisionSections.SetNum(CollisionSectionIndex + 1, false);
-	}
-
-	auto& Section = MeshCollisionSections[CollisionSectionIndex];
-	Section.VertexBuffer = Vertices;
-	Section.IndexBuffer = Triangles;
-
-	// Use the batch update if one is running
-	if (BatchState.IsBatchPending())
-	{
-		// Mark render state dirty
-		BatchState.MarkCollisionDirty();
-	}
-	else
-	{
-		MarkCollisionDirty();
-	}
-}
-
-void URuntimeMeshComponent::ClearMeshCollisionSection(int32 CollisionSectionIndex)
-{
-	SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_ClearMeshCollisionSection);
-
-	if (MeshCollisionSections.Num() <= CollisionSectionIndex)
-		return;
-
-	MeshCollisionSections[CollisionSectionIndex].Reset();
-
-	// Use the batch update if one is running
-	if (BatchState.IsBatchPending())
-	{
-		// Mark render state dirty
-		BatchState.MarkCollisionDirty();
-	}
-	else
-	{
-		MarkCollisionDirty();
-	}
-}
-
-void URuntimeMeshComponent::ClearAllMeshCollisionSections()
-{
-	SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_ClearAllMeshCollisionSections);
-
-	MeshCollisionSections.Empty();
-
-	// Use the batch update if one is running
-	if (BatchState.IsBatchPending())
-	{
-		// Mark render state dirty
-		BatchState.MarkCollisionDirty();
-	}
-	else
-	{
-		MarkCollisionDirty();
-	}
-}
-
-
-void URuntimeMeshComponent::AddCollisionConvexMesh(TArray<FVector> ConvexVerts)
-{
-	SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_AddCollisionConvexMesh);
-
-	if (ConvexVerts.Num() >= 4)
-	{
-		FRuntimeConvexCollisionSection ConvexSection;
-		ConvexSection.VertexBuffer = ConvexVerts;
-		ConvexSection.BoundingBox = FBox(ConvexVerts);
-		ConvexCollisionSections.Add(ConvexSection);
-		
-
-		// Use the batch update if one is running
-		if (BatchState.IsBatchPending())
-		{
-			// Mark render state dirty
-			BatchState.MarkCollisionDirty();
-		}
-		else
-		{
-			MarkCollisionDirty();
-		}
-	}
-}
-
-void URuntimeMeshComponent::ClearCollisionConvexMeshes()
-{
-	SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_ClearCollisionConvexMeshes);
-
-	// Empty simple collision info
-	ConvexCollisionSections.Empty();
-
-
-	// Use the batch update if one is running
-	if (BatchState.IsBatchPending())
-	{
-		// Mark render state dirty
-		BatchState.MarkCollisionDirty();
-	}
-	else
-	{
-		MarkCollisionDirty();
-	}
-}
-
-void URuntimeMeshComponent::SetCollisionConvexMeshes(const TArray< TArray<FVector> >& ConvexMeshes)
-{
-	SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_SetCollisionConvexMeshes);
-
-	ConvexCollisionSections.Empty(ConvexMeshes.Num());
-
-	// Create element for each convex mesh
-	for (int32 ConvexIndex = 0; ConvexIndex < ConvexMeshes.Num(); ConvexIndex++)
-	{
-		FRuntimeConvexCollisionSection ConvexSection;
-		ConvexSection.VertexBuffer = ConvexMeshes[ConvexIndex];
-		ConvexSection.BoundingBox = FBox(ConvexSection.VertexBuffer);
-		ConvexCollisionSections.Add(ConvexSection);
-	}
-
-
-	// Use the batch update if one is running
-	if (BatchState.IsBatchPending())
-	{
-		// Mark render state dirty
-		BatchState.MarkCollisionDirty();
-	}
-	else
-	{
-		MarkCollisionDirty();
-	}
-}
-
-
-void URuntimeMeshComponent::UpdateLocalBounds(bool bMarkRenderTransform)
-{
-	SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_UpdateLocalBounds);
-	
-	FBox LocalBox(EForceInit::ForceInitToZero);
-
-	for (const RuntimeMeshSectionPtr& Section : MeshSections)
-	{
-		if (Section.IsValid() && Section->bIsVisible)
-		{
-			LocalBox += Section->LocalBoundingBox;
-		}
-	}
-
-	LocalBounds = LocalBox.IsValid ? FBoxSphereBounds(LocalBox) : FBoxSphereBounds(FVector(0, 0, 0), FVector(0, 0, 0), 0); // fallback to reset box sphere bounds
-
-	// Update global bounds
-	UpdateBounds();
-
-	if (bMarkRenderTransform)
-	{
-		// Need to send to render thread
-		MarkRenderTransformDirty();
-	}
-}
-
-FPrimitiveSceneProxy* URuntimeMeshComponent::CreateSceneProxy()
-{
-	SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_CreateSceneProxy);
-
-	return new FRuntimeMeshSceneProxy(this);
-}
-
-int32 URuntimeMeshComponent::GetNumMaterials() const
-{
-	return MeshSections.Num();
-}
-
-FBoxSphereBounds URuntimeMeshComponent::CalcBounds(const FTransform& LocalToWorld) const
-{
-	return LocalBounds.TransformBy(LocalToWorld);
-}
-
-
-
-
-
-void URuntimeMeshComponent::EndBatchUpdates()
-{
-	// Bail if we have no pending updates
-	if (!BatchState.IsBatchPending())
-		return;
-
-	// Handle all pending rendering updates..
-	if (BatchState.RequiresSceneProxyRecreate())
-	{
-		MarkRenderStateDirty();
-	}
-	else
-	{
-		auto* BatchUpdateData = new FRuntimeMeshBatchUpdateData;
-
-		for (int32 Index = 0; Index <= BatchState.GetMaxSection(); Index++)
-		{
-			// Skip this section if it has no updates.
-			if (!BatchState.HasAnyFlagSet(Index))
-			{
-				continue;
-			}
-
-			// Check that we don't have both create and destroy flagged
-			check(!(BatchState.HasFlagSet(Index, ERuntimeMeshSectionBatchUpdateType::Create) && BatchState.HasFlagSet(Index, ERuntimeMeshSectionBatchUpdateType::Destroy)));
-
-			// Handle section created
-			if (BatchState.HasFlagSet(Index, ERuntimeMeshSectionBatchUpdateType::Create))
-			{
-				// Validate section exists
-				check(MeshSections.Num() >= Index && MeshSections[Index].IsValid());
-				
-				UMaterialInterface* Material = GetMaterial(Index);
-				if (Material == nullptr)
-				{
-					Material = UMaterial::GetDefaultMaterial(MD_Surface);
-				}
-
-				// Get the section create data and add it to the list
-				auto SectionCreateData = MeshSections[Index]->GetSectionCreationData(GetScene(), Material);
-				SectionCreateData->SetTargetSection(Index);
-
-				BatchUpdateData->CreateSections.Add(SectionCreateData);
-			}
-			// Handle destroy
-			else if (BatchState.HasFlagSet(Index, ERuntimeMeshSectionBatchUpdateType::Destroy))
-			{
-				BatchUpdateData->DestroySections.Add(Index);
-			}
-			// Handle vertex/index updates
-			else if (BatchState.HasFlagSet(Index, ERuntimeMeshSectionBatchUpdateType::VerticesUpdate) || BatchState.HasFlagSet(Index, ERuntimeMeshSectionBatchUpdateType::IndicesUpdate))
-			{
-				// Validate section exists
-				check(MeshSections.Num() >= Index && MeshSections[Index].IsValid());
-
-				// Get the section update data and add it to the list.
-				bool bHadPositionUpdates = BatchState.HasFlagSet(Index, ERuntimeMeshSectionBatchUpdateType::PositionsUpdate);
-				bool bHadVertexUpdates = BatchState.HasFlagSet(Index, ERuntimeMeshSectionBatchUpdateType::VerticesUpdate);
-				bool bHadIndexUpdates = BatchState.HasFlagSet(Index, ERuntimeMeshSectionBatchUpdateType::IndicesUpdate);
-				auto SectionUpdateData = MeshSections[Index]->GetSectionUpdateData(bHadPositionUpdates, bHadVertexUpdates, bHadIndexUpdates);
-				SectionUpdateData->SetTargetSection(Index);
-
-				BatchUpdateData->UpdateSections.Add(SectionUpdateData);
-			}
-			// Handle property updates
-			else if (BatchState.HasFlagSet(Index, ERuntimeMeshSectionBatchUpdateType::PropertyUpdate))
-			{
-				// Validate section exists
-				check(MeshSections.Num() >= Index && MeshSections[Index].IsValid());
-
-				auto SectionProperties = new(BatchUpdateData->PropertyUpdateSections) FRuntimeMeshSectionPropertyUpdateData;
-
-				auto& Section = MeshSections[Index];
-
-				SectionProperties->SetTargetSection(Index);
-				SectionProperties->bIsVisible = Section->bIsVisible;
-				SectionProperties->bCastsShadow = Section->bCastsShadow;
-			}
-			else
-			{
-				// Unknown update type.
-				checkNoEntry();
-			}
-		}
-
-
-
-		// Enqueue update on RT
-		ENQUEUE_UNIQUE_RENDER_COMMAND_TWOPARAMETER(
-			FRuntimeMeshBatchUpdateCommand,
-			FRuntimeMeshSceneProxy*, RuntimeMeshSceneProxy, (FRuntimeMeshSceneProxy*)SceneProxy,
-			FRuntimeMeshBatchUpdateData*, BatchUpdateData, BatchUpdateData,
-			{
-				RuntimeMeshSceneProxy->ApplyBatchUpdate_RenderThread(BatchUpdateData);
-			}
-		);
-
-
-	}
-
-	// Update collision if necessary
-	if (BatchState.RequiresCollisionUpdate())
-	{
-		MarkCollisionDirty();
-	}
-
-	// Update local bounds if necessary
-	if (BatchState.RequiresBoundsUpdate())
-	{
-		UpdateLocalBounds(!BatchState.RequiresSceneProxyRecreate());
-	}
-
-	// Clear batch info
-	BatchState.ResetBatch();
-}
-
-
-
-
-void URuntimeMeshComponent::GetSectionMesh(int32 SectionIndex, const IRuntimeMeshVerticesBuilder*& Vertices, const FRuntimeMeshIndicesBuilder*& Indices)
-{
-	RMC_VALIDATE_UPDATEPARAMETERS(SectionIndex, /*VoidReturn*/);
-
-	IRuntimeMeshVerticesBuilder* TempVertices;
-	FRuntimeMeshIndicesBuilder* TempIndices;
-
-	MeshSections[SectionIndex]->GetSectionMesh(TempVertices, TempIndices);
-
-	Vertices = TempVertices;
-	Indices = TempIndices;
-}
-
-void URuntimeMeshComponent::BeginMeshSectionUpdate(int32 SectionIndex, IRuntimeMeshVerticesBuilder*& Vertices, FRuntimeMeshIndicesBuilder*& Indices)
-{
-	RMC_VALIDATE_UPDATEPARAMETERS(SectionIndex, /*VoidReturn*/);
-
-	// Get mesh
-	MeshSections[SectionIndex]->GetSectionMesh(Vertices, Indices);
-}
-
-bool URuntimeMeshComponent::GetPhysicsTriMeshData(struct FTriMeshCollisionData* CollisionData, bool InUseAllTriData)
-{
-	SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_GetPhysicsTriMeshData);
- 	int32 VertexBase = 0; // Base vertex index for current section
- 
-	bool HadCollision = false;
-
-#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION >= 13
-	// See if we should copy UVs
-	bool bCopyUVs = UPhysicsSettings::Get()->bSupportUVFromHitResults;
-	if (bCopyUVs)
-	{
-		CollisionData->UVs.AddZeroed(1); // only one UV channel
-	}
-#endif
-
-	// For each section..
-	for (int32 SectionIdx = 0; SectionIdx < MeshSections.Num(); SectionIdx++)
-	{ 
-		const RuntimeMeshSectionPtr& Section = MeshSections[SectionIdx];
-
-		if (Section.IsValid() && Section->CollisionEnabled)
-		{
-			// Copy vertex data
-#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION >= 13
-			Section->GetCollisionInformation(CollisionData->Vertices, CollisionData->UVs, bCopyUVs);
-#else
-			Section->GetCollisionInformation(CollisionData->Vertices);
-#endif
-
-			// Copy indices
-			const int32 NumTriangles = Section->IndexBuffer.Num() / 3;
-			for (int32 TriIdx = 0; TriIdx < NumTriangles; TriIdx++)
-			{
-				// Add the triangle
-				FTriIndices& Triangle = *new (CollisionData->Indices) FTriIndices;
-				Triangle.v0 = Section->IndexBuffer[(TriIdx * 3) + 0] + VertexBase;
-				Triangle.v1 = Section->IndexBuffer[(TriIdx * 3) + 1] + VertexBase;
-				Triangle.v2 = Section->IndexBuffer[(TriIdx * 3) + 2] + VertexBase;
-
-				// Add material info
-				CollisionData->MaterialIndices.Add(SectionIdx);
-			}
-
-			// Update the vertex base index
-			VertexBase = CollisionData->Vertices.Num();
-			HadCollision = true;
-		}
-	}
-
-	for (int32 SectionIdx = 0; SectionIdx < MeshCollisionSections.Num(); SectionIdx++)
-	{
-		auto& Section = MeshCollisionSections[SectionIdx];
-		if (Section.VertexBuffer.Num() > 0 && Section.IndexBuffer.Num() > 0)
-		{
-			CollisionData->Vertices.Append(Section.VertexBuffer);
-
-			const int32 NumTriangles = Section.IndexBuffer.Num() / 3;
-			for (int32 TriIdx = 0; TriIdx < NumTriangles; TriIdx++)
-			{
-				// Add the triangle
-				FTriIndices& Triangle = *new (CollisionData->Indices) FTriIndices;
-				Triangle.v0 = Section.IndexBuffer[(TriIdx * 3) + 0] + VertexBase;
-				Triangle.v1 = Section.IndexBuffer[(TriIdx * 3) + 1] + VertexBase;
-				Triangle.v2 = Section.IndexBuffer[(TriIdx * 3) + 2] + VertexBase;
-
-				// Add material info
-				CollisionData->MaterialIndices.Add(SectionIdx);
-			}
-
-
-			VertexBase = CollisionData->Vertices.Num();
-			HadCollision = true;
-		}
-	}
- 
- 	CollisionData->bFlipNormals = true;
-
-#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION >= 14
-	if (CollisionMode == ERuntimeMeshCollisionCookingMode::CookingPerformance)
-	{
-		CollisionData->bFlipNormals = true;
-	}
-#endif
- 
- 	return HadCollision;
- }
-
- bool URuntimeMeshComponent::ContainsPhysicsTriMeshData(bool InUseAllTriData) const
- {
- 	for (const RuntimeMeshSectionPtr& Section : MeshSections)
- 	{
- 		if (Section.IsValid() && Section->IndexBuffer.Num() >= 3 && Section->CollisionEnabled)
- 		{
- 			return true;
- 		}
- 	}
-
-	for (const auto& Section : MeshCollisionSections)
-	{
-		if (Section.VertexBuffer.Num() > 0 && Section.IndexBuffer.Num() > 0)
-		{
-			return true;
-		}
-	}
- 
- 	return false;
- }
-
-
-void URuntimeMeshComponent::EnsureBodySetupCreated()
-{
-	if (BodySetup == nullptr)
-	{
-		BodySetup = NewObject<UBodySetup>(this, NAME_None, (IsTemplate() ? RF_Public : RF_NoFlags));
-		BodySetup->BodySetupGuid = FGuid::NewGuid();
-
-		BodySetup->bGenerateMirroredCollision = false;
-		BodySetup->bDoubleSidedGeometry = true;
-	}
-}
-
-void URuntimeMeshComponent::UpdateCollision()
-{
-	SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_UpdateCollision);
-
-	bool NeedsNewPhysicsState = false;
-
-	// Destroy physics state if it exists
-	if (bPhysicsStateCreated)
-	{
-		DestroyPhysicsState();
-		NeedsNewPhysicsState = true;
-	}
-
-	// Ensure we have a BodySetup
-	EnsureBodySetupCreated();
-
-	// Fill in simple collision convex elements
-	BodySetup->AggGeom.ConvexElems.SetNum(ConvexCollisionSections.Num());
-	for (int32 Index = 0; Index < ConvexCollisionSections.Num(); Index++)
-	{
-		FKConvexElem& NewConvexElem = BodySetup->AggGeom.ConvexElems[Index];
-
-		NewConvexElem.VertexData = ConvexCollisionSections[Index].VertexBuffer;
-		NewConvexElem.ElemBox = FBox(NewConvexElem.VertexData);
-	} 
-
-	// Set trace flag
-	BodySetup->CollisionTraceFlag = bUseComplexAsSimpleCollision ? CTF_UseComplexAsSimple : CTF_UseDefault;
-
-	// New GUID as collision has changed
-	BodySetup->BodySetupGuid = FGuid::NewGuid();
-
-
-#if WITH_RUNTIME_PHYSICS_COOKING || WITH_PHYSX || WITH_EDITOR
-	// Clear current mesh data
-	BodySetup->InvalidatePhysicsData();
-	// Create new mesh data
-	BodySetup->CreatePhysicsMeshes();
-#endif // WITH_RUNTIME_PHYSICS_COOKING || WITH_EDITOR
-
-	// Recreate physics state if necessary
-	if (NeedsNewPhysicsState)
-	{
-		CreatePhysicsState();
-	}
-
-	UpdateNavigation();
-}
-
-UBodySetup* URuntimeMeshComponent::GetBodySetup()
-{
-	EnsureBodySetupCreated();
-	return BodySetup;
-}
-
-void URuntimeMeshComponent::MarkCollisionDirty()
-{
-	if (!bCollisionDirty)
-	{
-		bCollisionDirty = true;
-		PrePhysicsTick.SetTickFunctionEnable(true);
-	}
-}
-
-void URuntimeMeshComponent::CookCollisionNow()
-{
-	if (bCollisionDirty)
-	{
-		BakeCollision();
-	}
-}
-
-
-void URuntimeMeshComponent::BakeCollision()
-{
-	// Bake the collision
-	UpdateCollision();
-
-	bCollisionDirty = false;
-	PrePhysicsTick.SetTickFunctionEnable(false);
-}
-
-
-void URuntimeMeshComponent::UpdateNavigation()
-{
-	if (UNavigationSystem::ShouldUpdateNavOctreeOnComponentChange() && IsRegistered())
-	{
-		UWorld* MyWorld = GetWorld();
-
-#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION >= 13
-		if (MyWorld != nullptr && MyWorld->GetNavigationSystem() != nullptr &&
-			(MyWorld->GetNavigationSystem()->ShouldAllowClientSideNavigation() || !MyWorld->IsNetMode(ENetMode::NM_Client)))
-#else
-
-		if (MyWorld != nullptr && MyWorld->IsGameWorld() && MyWorld->GetNetMode() < ENetMode::NM_Client)
-#endif
-		{
-			UNavigationSystem::UpdateComponentInNavOctree(*this);
-		}
-	}
-}
-
-void URuntimeMeshComponent::RegisterComponentTickFunctions(bool bRegister)
-{
-	Super::RegisterComponentTickFunctions(bRegister);
-
-	if (bRegister)
-	{
-		if (SetupActorComponentTickFunction(&PrePhysicsTick))
-		{
-			PrePhysicsTick.Target = this;
-			PrePhysicsTick.SetTickFunctionEnable(bCollisionDirty);
-		}
-	}
-	else
-	{
-		if (PrePhysicsTick.IsTickFunctionRegistered())
-		{
-			PrePhysicsTick.UnRegisterTickFunction();
-		}
-	}
-}
-
-void URuntimeMeshComponent::SerializeLegacy(FArchive& Ar)
-{
-	if (Ar.CustomVer(FRuntimeMeshVersion::GUID) >= FRuntimeMeshVersion::Initial)
-	{
-		int32 SectionsCount = bShouldSerializeMeshData ? MeshSections.Num() : 0;
-		Ar << SectionsCount;
-		if (Ar.IsLoading() && MeshSections.Num() < SectionsCount)
-		{
-			MeshSections.SetNum(SectionsCount);
-		}
-
-		for (int32 Index = 0; Index < SectionsCount; Index++)
-		{
-			bool IsSectionValid = MeshSections[Index].IsValid();
-
-			// WE can only load/save internal types (we don't know how to serialize arbitrary vertex types.
-			if (Ar.IsSaving() && (IsSectionValid && !MeshSections[Index]->bIsLegacySectionType))
-			{
-				IsSectionValid = false;
-			}
-
-			Ar << IsSectionValid;
-
-			if (IsSectionValid)
-			{
-				if (Ar.CustomVer(FRuntimeMeshVersion::GUID) >= FRuntimeMeshVersion::TemplatedVertexFix)
-				{
-					int32 NumUVChannels;
-					bool WantsHalfPrecisionUVs;
-
-					if (Ar.IsSaving())
-					{
-						MeshSections[Index]->GetInternalVertexComponents(NumUVChannels, WantsHalfPrecisionUVs);
-					}
-
-					Ar << NumUVChannels;
-					Ar << WantsHalfPrecisionUVs;
-
-					if (Ar.IsLoading())
-					{
-						CreateOrResetSectionLegacyType(Index, NumUVChannels);
-					}
-
-				}
-				else
-				{
-					bool bWantsNormal;
-					bool bWantsTangent;
-					bool bWantsColor;
-					int32 TextureChannels;
-
-					Ar << bWantsNormal;
-					Ar << bWantsTangent;
-					Ar << bWantsColor;
-					Ar << TextureChannels;
-
-					if (Ar.IsLoading())
-					{
-						CreateOrResetSectionLegacyType(Index, TextureChannels);
-					}
-				}
-
-				FRuntimeMeshSectionInterface& SectionPtr = *MeshSections[Index].Get();
-				SectionPtr.Serialize(Ar);
-
-			}
-		}
-	}
-
-	if (Ar.CustomVer(FRuntimeMeshVersion::GUID) >= FRuntimeMeshVersion::SerializationOptional)
-	{
-
-		if (bShouldSerializeMeshData || Ar.IsLoading())
-		{
-			// Serialize the real data if we want it, also use this path for loading to get anything that was in the last save
-
-			// Serialize the collision data
-			Ar << MeshCollisionSections;
-			Ar << ConvexCollisionSections;
-		}
-		else
-		{
-			// serialize empty arrays if we don't want serialization
-			TArray<FRuntimeMeshCollisionSection> NullCollisionSections;
-			Ar << NullCollisionSections;
-			TArray<FRuntimeConvexCollisionSection> NullConvexBodies;
-			Ar << NullConvexBodies;
-		}
-	}
-}
-
-void URuntimeMeshComponent::Serialize(FArchive& Ar)
-{	
-	Super::Serialize(Ar);
-
-	SerializeInternal(Ar);
-}	
-
-void URuntimeMeshComponent::SerializeInternal(FArchive& Ar, bool bForceSaveAll)
-{
-	SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_Serialize);
-
-	Ar.UsingCustomVersion(FRuntimeMeshVersion::GUID);
-
-	// Handle old serialization
-	if (Ar.CustomVer(FRuntimeMeshVersion::GUID) < FRuntimeMeshVersion::SerializationV2)
-	{
-		SerializeLegacy(Ar);
-		return;
-	}
-
-	bool bSerializeMeshData = bShouldSerializeMeshData || bForceSaveAll;
-
-	// Serialize basic settings
-	Ar << bSerializeMeshData;
-	Ar << bUseComplexAsSimpleCollision;
-
-	// Serialize the number of sections...
-	int32 NumSections = bSerializeMeshData ? MeshSections.Num() : 0;
-	Ar << NumSections;
-
-	// Resize the section array if we're loading.
-	if (Ar.IsLoading())
-	{
-		MeshSections.Reset(NumSections);
-		MeshSections.SetNum(NumSections);
-	}
-
-	// Next serialize all the sections...
-	for (int32 Index = 0; Index < NumSections; Index++)
-	{
-		SerializeRMCSection(Ar, Index);
-	}
-
-	if (bSerializeMeshData || Ar.IsLoading())
-	{
-		// Serialize the real data if we want it, also use this path for loading to get anything that was in the last save
-
-		// Serialize the collision data
-		Ar << MeshCollisionSections;
-		Ar << ConvexCollisionSections;
-	}
-	else
-	{
-		// serialize empty arrays if we don't want serialization
-		TArray<FRuntimeMeshCollisionSection> NullCollisionSections;
-		Ar << NullCollisionSections;
-		TArray<FRuntimeConvexCollisionSection> NullConvexBodies;
-		Ar << NullConvexBodies;
-	}
-}
-
-
-void URuntimeMeshComponent::SerializeRMC(FArchive& Ar)
-{
-	SerializeInternal(Ar, true);
-}
-
-void URuntimeMeshComponent::SerializeRMCSection(FArchive& Ar, int32 SectionIndex)
-{
-	if (Ar.IsLoading() && MeshSections.Num() <= SectionIndex)
-	{
-		MeshSections.SetNum(SectionIndex + 1);
-	}
-
-	// Serialize the section validity (default it to section valid + type known for saving reasons)
-	bool bSectionIsValid = MeshSections[SectionIndex].IsValid();
-	bool bSectionTypeFound = bSectionIsValid ? FRuntimeMeshVertexTypeRegistrationContainer::GetInstance().GetVertexType(MeshSections[SectionIndex]->GetVertexType()->TypeGuid) != nullptr : true;
-	bSectionIsValid = bSectionIsValid && bSectionTypeFound;
-	Ar << bSectionIsValid;
-
-	// If section is invalid, skip
-	if (!bSectionIsValid)
-	{
-		if (!bSectionTypeFound)
-		{
-			UE_LOG(RuntimeMeshLog, Error, TEXT("Attempted to serialize a vertex of unknown type %s"), *MeshSections[SectionIndex]->GetVertexType()->TypeGuid.ToString());
-		}
-		return;
-	}
-
-	// Serialize section type info
-	FGuid TypeGuid;
-	bool bHasSeparatePositionBuffer;
-
-	if (Ar.IsSaving())
-	{
-		TypeGuid = MeshSections[SectionIndex]->GetVertexType()->TypeGuid;
-		bHasSeparatePositionBuffer = MeshSections[SectionIndex]->IsDualBufferSection();
-	}
-
-	Ar << TypeGuid;
-	Ar << bHasSeparatePositionBuffer;
-
-	if (Ar.IsLoading())
-	{
-		auto VertexTypeRegistration = FRuntimeMeshVertexTypeRegistrationContainer::GetInstance().GetVertexType(TypeGuid);
-
-		if (VertexTypeRegistration == nullptr)
-		{
-			UE_LOG(RuntimeMeshLog, Error, TEXT("Attempted to serialize a vertex of unknown type %s"), *MeshSections[SectionIndex]->GetVertexType()->TypeGuid.ToString());
-			bSectionIsValid = false;
-		}
-		else
-		{
-			auto NewSection = VertexTypeRegistration->CreateSection(bHasSeparatePositionBuffer);
-			MeshSections[SectionIndex] = MakeShareable(NewSection);
-		}
-	}
-
-	// Now we save the section data to a separate archive and then write in into the main. 
-	// This way we can recover from unknown types or mismatch sizes
-
-
-	TArray<uint8> SectionData;
-
-	if (Ar.IsSaving())
-	{
-		FMemoryWriter SectionAr(SectionData, true);
-		SectionAr.UsingCustomVersion(FRuntimeMeshVersion::GUID);
-
-		MeshSections[SectionIndex]->Serialize(SectionAr);
-	}
-
-	Ar << SectionData;
-
-	if (Ar.IsLoading() && bSectionIsValid)
-	{
-		FMemoryReader SectionAr(SectionData, true);
-		SectionAr.Seek(0);
-		SectionAr.UsingCustomVersion(FRuntimeMeshVersion::GUID);
-
-		MeshSections[SectionIndex]->Serialize(SectionAr);
-
-		// Was this section loaded correctly?
-		if (SectionAr.IsError())
-		{
-			MeshSections[SectionIndex].Reset();
-			UE_LOG(RuntimeMeshLog, Log, TEXT("Unable to load section %d of type %s. This is most likely caused by a reconfigured vertex type."),
-				SectionIndex, *MeshSections[SectionIndex]->GetVertexType()->TypeName);
-		}
-	}
-}
-
-
-
-
-
-
-
-
-void URuntimeMeshComponent::PostLoad()
-{
-	Super::PostLoad();
-
-	// Rebuild collision and local bounds.
-	MarkCollisionDirty();
-	UpdateLocalBounds();
-
-	if (BodySetup && IsTemplate())
-	{
-		BodySetup->SetFlags(RF_Public);
-	}
-}

+ 0 - 38
spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Private/RuntimeMeshComponentPlugin.cpp

@@ -1,38 +0,0 @@
-// Copyright 2016 Chris Conway (Koderz). All Rights Reserved.
-
-#include "RuntimeMeshComponentPluginPrivatePCH.h"
-#include "RuntimeMeshVersion.h"
-#include "RuntimeMeshComponentPlugin.h"
-
-
-// Register the custom version with core
-FCustomVersionRegistration GRegisterRuntimeMeshCustomVersion(FRuntimeMeshVersion::GUID, FRuntimeMeshVersion::LatestVersion, TEXT("RuntimeMesh"));
-
-
-
-
-class FRuntimeMeshComponentPlugin : public IRuntimeMeshComponentPlugin
-{
-	/** IModuleInterface implementation */
-	virtual void StartupModule() override;
-	virtual void ShutdownModule() override;
-};
-
-IMPLEMENT_MODULE(FRuntimeMeshComponentPlugin, RuntimeMeshComponent)
-
-
-
-void FRuntimeMeshComponentPlugin::StartupModule()
-{
-
-}
-
-
-void FRuntimeMeshComponentPlugin::ShutdownModule()
-{
-
-}
-
-
-
-DEFINE_LOG_CATEGORY(RuntimeMeshLog);

+ 0 - 14
spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Private/RuntimeMeshComponentPluginPrivatePCH.h

@@ -1,14 +0,0 @@
-// Copyright 2016 Chris Conway (Koderz). All Rights Reserved.
-
-
-#pragma once
-
-#include "CoreUObject.h"
-#include "Engine.h"
-
-#include "RuntimeMeshComponentPlugin.h"
-
-
-#include "RuntimeMeshComponent.h"
-#include "PhysicsEngine/BodySetup.h"
-

+ 0 - 51
spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Private/RuntimeMeshCore.cpp

@@ -1,51 +0,0 @@
-// Copyright 2016 Chris Conway (Koderz). All Rights Reserved.
-
-#include "RuntimeMeshComponentPluginPrivatePCH.h"
-#include "RuntimeMeshCore.h"
-
-
-FRuntimeMeshVertexTypeRegistrationContainer& FRuntimeMeshVertexTypeRegistrationContainer::GetInstance()
-{
-	static FRuntimeMeshVertexTypeRegistrationContainer Instance;
-	return Instance;
-}
-
-void FRuntimeMeshVertexTypeRegistrationContainer::Register(const FRuntimeMeshVertexTypeInfo* InType)
-{
-	if (auto ExistingRegistration = Registrations.Find(InType->TypeGuid))
-	{
-		// This path only exists to support hotreload
-
-		// If you hit this then you've probably either:
-		// * Changed registration details during hotreload.
-		// * Accidentally copy-and-pasted an FRuntimeMeshVertexTypeRegistration object.
-		ensureMsgf(ExistingRegistration->TypeInfo->TypeName == InType->TypeName,
-			TEXT("Runtime mesh vertex registrations cannot change between hotreloads - \"%s\" is being reregistered as \"%s\""),
-			*ExistingRegistration->TypeInfo->TypeName, *InType->TypeName);
-
-		ExistingRegistration->ReferenceCount++;
-	}
-	else
-	{
-		Registrations.Add(InType->TypeGuid, VertexRegistration(InType));
-	}
-}
-
-void FRuntimeMeshVertexTypeRegistrationContainer::UnRegister(const FRuntimeMeshVertexTypeInfo* InType)
-{
-	auto ExistingRegistration = Registrations.Find(InType->TypeGuid);
-
-	check(ExistingRegistration);
-
-	ExistingRegistration->ReferenceCount--;
-	if (ExistingRegistration->ReferenceCount == 0)
-	{
-		Registrations.Remove(InType->TypeGuid);
-	}
-}
-
-const FRuntimeMeshVertexTypeInfo* FRuntimeMeshVertexTypeRegistrationContainer::GetVertexType(FGuid Key) const
-{
-	auto Registration = Registrations.Find(Key);
-	return (Registration ? Registration->TypeInfo : nullptr);
-}

+ 0 - 32
spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Private/RuntimeMeshGenericVertex.cpp

@@ -1,32 +0,0 @@
-// Copyright 2016 Chris Conway (Koderz). All Rights Reserved.
-
-#include "RuntimeMeshComponentPluginPrivatePCH.h"
-#include "RuntimeMeshGenericVertex.h"
-#include "RuntimeMeshBuilder.h"
-
-// Finish all the built in vertex types.
-DEFINE_RUNTIME_MESH_VERTEX(FRuntimeMeshVertexSimple);
-DEFINE_RUNTIME_MESH_VERTEX(FRuntimeMeshVertexDualUV);
-DEFINE_RUNTIME_MESH_VERTEX(FRuntimeMeshVertexTripleUV);
-DEFINE_RUNTIME_MESH_VERTEX(FRuntimeMeshVertexNoPosition);
-DEFINE_RUNTIME_MESH_VERTEX(FRuntimeMeshVertexNoPositionDualUV);
-DEFINE_RUNTIME_MESH_VERTEX(FRuntimeMeshVertexHiPrecisionNormals);
-DEFINE_RUNTIME_MESH_VERTEX(FRuntimeMeshVertexDualUVHiPrecisionNormals);
-DEFINE_RUNTIME_MESH_VERTEX(FRuntimeMeshVertexNoPositionHiPrecisionNormals);
-DEFINE_RUNTIME_MESH_VERTEX(FRuntimeMeshVertexNoPositionDualUVHiPrecisionNormals);
-
-
-
-
-const FRuntimeMeshVertexTypeInfo* FRuntimeMeshComponentVerticesBuilder::GetVertexType() const
-{
-	if (HasUVComponent(1))
-	{
-		if (HasUVComponent(2)) return &FRuntimeMeshVertexTripleUV::TypeInfo;
-		else return &FRuntimeMeshVertexDualUV::TypeInfo;
-	}
-	else
-	{
-		return &FRuntimeMeshVertexSimple::TypeInfo;
-	}
-}

+ 0 - 561
spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Private/RuntimeMeshLibrary.cpp

@@ -1,561 +0,0 @@
-// Copyright 2016 Chris Conway (Koderz). All Rights Reserved.
-
-#include "RuntimeMeshComponentPluginPrivatePCH.h"
-#include "RuntimeMeshLibrary.h"
-#include "MessageLog.h"
-#include "UObjectToken.h"
-#include "StaticMeshResources.h"
-#include "TessellationUtilities.h"
-#include "RuntimeMeshBuilder.h"
-#include "RuntimeMeshComponent.h"
-
-#define LOCTEXT_NAMESPACE "RuntimeMeshLibrary"
-
-
-URuntimeMeshLibrary::URuntimeMeshLibrary(const FObjectInitializer& ObjectInitializer)
-	: Super(ObjectInitializer)
-{
-
-}
-
-void URuntimeMeshLibrary::ConvertQuadToTriangles(TArray<int32>& Triangles, int32 Vert0, int32 Vert1, int32 Vert2, int32 Vert3)
-{
-	Triangles.Add(Vert0);
-	Triangles.Add(Vert1);
-	Triangles.Add(Vert3);
-
-	Triangles.Add(Vert1);
-	Triangles.Add(Vert2);
-	Triangles.Add(Vert3);
-}
-
-void URuntimeMeshLibrary::CreateGridMeshTriangles(int32 NumX, int32 NumY, bool bWinding, TArray<int32>& Triangles)
-{
-	Triangles.Reset();
-
-	if (NumX >= 2 && NumY >= 2)
-	{
-		// Build Quads
-		for (int XIdx = 0; XIdx < NumX - 1; XIdx++)
-		{
-			for (int YIdx = 0; YIdx < NumY - 1; YIdx++)
-			{
-				const int32 I0 = (XIdx + 0)*NumY + (YIdx + 0);
-				const int32 I1 = (XIdx + 1)*NumY + (YIdx + 0);
-				const int32 I2 = (XIdx + 1)*NumY + (YIdx + 1);
-				const int32 I3 = (XIdx + 0)*NumY + (YIdx + 1);
-
-				if (bWinding)
-				{
-					ConvertQuadToTriangles(Triangles, I0, I1, I2, I3);
-				}
-				else
-				{
-					ConvertQuadToTriangles(Triangles, I0, I3, I2, I1);
-				}
-			}
-		}
-	}
-}
-
-void URuntimeMeshLibrary::CreateBoxMesh(FVector BoxRadius, TArray<FVector>& Vertices, TArray<int32>& Triangles, TArray<FVector>& Normals, TArray<FVector2D>& UVs, TArray<FRuntimeMeshTangent>& Tangents)
-{
-	// Generate verts
-	FVector BoxVerts[8];
-	BoxVerts[0] = FVector(-BoxRadius.X, BoxRadius.Y, BoxRadius.Z);
-	BoxVerts[1] = FVector(BoxRadius.X, BoxRadius.Y, BoxRadius.Z);
-	BoxVerts[2] = FVector(BoxRadius.X, -BoxRadius.Y, BoxRadius.Z);
-	BoxVerts[3] = FVector(-BoxRadius.X, -BoxRadius.Y, BoxRadius.Z);
-
-	BoxVerts[4] = FVector(-BoxRadius.X, BoxRadius.Y, -BoxRadius.Z);
-	BoxVerts[5] = FVector(BoxRadius.X, BoxRadius.Y, -BoxRadius.Z);
-	BoxVerts[6] = FVector(BoxRadius.X, -BoxRadius.Y, -BoxRadius.Z);
-	BoxVerts[7] = FVector(-BoxRadius.X, -BoxRadius.Y, -BoxRadius.Z);
-
-	// Generate triangles (from quads)
-	Triangles.Reset();
-
-	const int32 NumVerts = 24; // 6 faces x 4 verts per face
-
-	Vertices.Reset();
-	Vertices.AddUninitialized(NumVerts);
-
-	Normals.Reset();
-	Normals.AddUninitialized(NumVerts);
-
-	Tangents.Reset();
-	Tangents.AddUninitialized(NumVerts);
-
-	Vertices[0] = BoxVerts[0];
-	Vertices[1] = BoxVerts[1];
-	Vertices[2] = BoxVerts[2];
-	Vertices[3] = BoxVerts[3];
-	ConvertQuadToTriangles(Triangles, 0, 1, 2, 3);
-	Normals[0] = Normals[1] = Normals[2] = Normals[3] = FVector(0, 0, 1);
-	Tangents[0] = Tangents[1] = Tangents[2] = Tangents[3] = FRuntimeMeshTangent(0.f, -1.f, 0.f);
-
-	Vertices[4] = BoxVerts[4];
-	Vertices[5] = BoxVerts[0];
-	Vertices[6] = BoxVerts[3];
-	Vertices[7] = BoxVerts[7];
-	ConvertQuadToTriangles(Triangles, 4, 5, 6, 7);
-	Normals[4] = Normals[5] = Normals[6] = Normals[7] = FVector(-1, 0, 0);
-	Tangents[4] = Tangents[5] = Tangents[6] = Tangents[7] = FRuntimeMeshTangent(0.f, -1.f, 0.f);
-
-	Vertices[8] = BoxVerts[5];
-	Vertices[9] = BoxVerts[1];
-	Vertices[10] = BoxVerts[0];
-	Vertices[11] = BoxVerts[4];
-	ConvertQuadToTriangles(Triangles, 8, 9, 10, 11);
-	Normals[8] = Normals[9] = Normals[10] = Normals[11] = FVector(0, 1, 0);
-	Tangents[8] = Tangents[9] = Tangents[10] = Tangents[11] = FRuntimeMeshTangent(-1.f, 0.f, 0.f);
-
-	Vertices[12] = BoxVerts[6];
-	Vertices[13] = BoxVerts[2];
-	Vertices[14] = BoxVerts[1];
-	Vertices[15] = BoxVerts[5];
-	ConvertQuadToTriangles(Triangles, 12, 13, 14, 15);
-	Normals[12] = Normals[13] = Normals[14] = Normals[15] = FVector(1, 0, 0);
-	Tangents[12] = Tangents[13] = Tangents[14] = Tangents[15] = FRuntimeMeshTangent(0.f, 1.f, 0.f);
-
-	Vertices[16] = BoxVerts[7];
-	Vertices[17] = BoxVerts[3];
-	Vertices[18] = BoxVerts[2];
-	Vertices[19] = BoxVerts[6];
-	ConvertQuadToTriangles(Triangles, 16, 17, 18, 19);
-	Normals[16] = Normals[17] = Normals[18] = Normals[19] = FVector(0, -1, 0);
-	Tangents[16] = Tangents[17] = Tangents[18] = Tangents[19] = FRuntimeMeshTangent(1.f, 0.f, 0.f);
-
-	Vertices[20] = BoxVerts[7];
-	Vertices[21] = BoxVerts[6];
-	Vertices[22] = BoxVerts[5];
-	Vertices[23] = BoxVerts[4];
-	ConvertQuadToTriangles(Triangles, 20, 21, 22, 23);
-	Normals[20] = Normals[21] = Normals[22] = Normals[23] = FVector(0, 0, -1);
-	Tangents[20] = Tangents[21] = Tangents[22] = Tangents[23] = FRuntimeMeshTangent(0.f, 1.f, 0.f);
-
-	// UVs
-	UVs.Reset();
-	UVs.AddUninitialized(NumVerts);
-
-	UVs[0] = UVs[4] = UVs[8] = UVs[12] = UVs[16] = UVs[20] = FVector2D(0.f, 0.f);
-	UVs[1] = UVs[5] = UVs[9] = UVs[13] = UVs[17] = UVs[21] = FVector2D(0.f, 1.f);
-	UVs[2] = UVs[6] = UVs[10] = UVs[14] = UVs[18] = UVs[22] = FVector2D(1.f, 1.f);
-	UVs[3] = UVs[7] = UVs[11] = UVs[15] = UVs[19] = UVs[23] = FVector2D(1.f, 0.f);
-}
-
-
-
-
-
-void FindVertOverlaps(int32 TestVertIndex, const IRuntimeMeshVerticesBuilder* Vertices, TArray<int32>& VertOverlaps)
-{
-	// Check if Verts is empty or test is outside range
-	if (TestVertIndex < Vertices->Length())
-	{
-		const FVector TestVert = Vertices->GetPosition(TestVertIndex);
-
-		for (int32 VertIdx = 0; VertIdx < Vertices->Length(); VertIdx++)
-		{
-			// First see if we overlap, and smoothing groups are the same
-			if (TestVert.Equals(Vertices->GetPosition(VertIdx)))
-			{
-				// If it, so we are at least considered an 'overlap' for normal gen
-				VertOverlaps.Add(VertIdx);
-			}
-		}
-	}
-}
-
-void URuntimeMeshLibrary::CalculateTangentsForMesh(IRuntimeMeshVerticesBuilder* Vertices, const FRuntimeMeshIndicesBuilder* Triangles)
-{
-	if (Vertices->Length() == 0) return;
-
-	// Number of triangles
-	const int32 NumTris = Triangles->TriangleLength();
-	// Number of verts
-	const int32 NumVerts = Vertices->Length();
-
-	// Map of vertex to triangles in Triangles array
-	TMultiMap<int32, int32> VertToTriMap;
-	// Map of vertex to triangles to consider for normal calculation
-	TMultiMap<int32, int32> VertToTriSmoothMap;
-
-	// Normal/tangents for each face
-	TArray<FVector> FaceTangentX, FaceTangentY, FaceTangentZ;
-	FaceTangentX.AddUninitialized(NumTris);
-	FaceTangentY.AddUninitialized(NumTris);
-	FaceTangentZ.AddUninitialized(NumTris);
-
-	// Iterate over triangles
-	for (int TriIdx = 0; TriIdx < NumTris; TriIdx++)
-	{
-		int32 CornerIndex[3];
-		FVector P[3];
-
-		for (int32 CornerIdx = 0; CornerIdx < 3; CornerIdx++)
-		{
-			// Find vert index (clamped within range)
-			int32 VertIndex = FMath::Min(Triangles->GetIndex((TriIdx * 3) + CornerIdx), NumVerts - 1);
-
-			CornerIndex[CornerIdx] = VertIndex;
-			P[CornerIdx] = Vertices->GetPosition(VertIndex);
-
-			// Find/add this vert to index buffer
-			TArray<int32> VertOverlaps;
-			FindVertOverlaps(VertIndex, Vertices, VertOverlaps);
-
-			// Remember which triangles map to this vert
-			VertToTriMap.AddUnique(VertIndex, TriIdx);
-			VertToTriSmoothMap.AddUnique(VertIndex, TriIdx);
-
-			// Also update map of triangles that 'overlap' this vert (ie don't match UV, but do match smoothing) and should be considered when calculating normal
-			for (int32 OverlapIdx = 0; OverlapIdx < VertOverlaps.Num(); OverlapIdx++)
-			{
-				// For each vert we overlap..
-				int32 OverlapVertIdx = VertOverlaps[OverlapIdx];
-
-				// Add this triangle to that vert
-				VertToTriSmoothMap.AddUnique(OverlapVertIdx, TriIdx);
-
-				// And add all of its triangles to us
-				TArray<int32> OverlapTris;
-				VertToTriMap.MultiFind(OverlapVertIdx, OverlapTris);
-				for (int32 OverlapTriIdx = 0; OverlapTriIdx < OverlapTris.Num(); OverlapTriIdx++)
-				{
-					VertToTriSmoothMap.AddUnique(VertIndex, OverlapTris[OverlapTriIdx]);
-				}
-			}
-		}
-
-		// Calculate triangle edge vectors and normal
-		const FVector Edge21 = P[1] - P[2];
-		const FVector Edge20 = P[0] - P[2];
-		const FVector TriNormal = (Edge21 ^ Edge20).GetSafeNormal();
-
-		// If we have UVs, use those to calc 
-		if (Vertices->HasUVComponent(0))
-		{
-			const FVector2D T1 = Vertices->GetUV(CornerIndex[0]);
-			const FVector2D T2 = Vertices->GetUV(CornerIndex[1]);
-			const FVector2D T3 = Vertices->GetUV(CornerIndex[2]);
-
-			FMatrix	ParameterToLocal(
-				FPlane(P[1].X - P[0].X, P[1].Y - P[0].Y, P[1].Z - P[0].Z, 0),
-				FPlane(P[2].X - P[0].X, P[2].Y - P[0].Y, P[2].Z - P[0].Z, 0),
-				FPlane(P[0].X, P[0].Y, P[0].Z, 0),
-				FPlane(0, 0, 0, 1)
-			);
-
-			FMatrix ParameterToTexture(
-				FPlane(T2.X - T1.X, T2.Y - T1.Y, 0, 0),
-				FPlane(T3.X - T1.X, T3.Y - T1.Y, 0, 0),
-				FPlane(T1.X, T1.Y, 1, 0),
-				FPlane(0, 0, 0, 1)
-			);
-
-			// Use InverseSlow to catch singular matrices.  Inverse can miss this sometimes.
-			const FMatrix TextureToLocal = ParameterToTexture.Inverse() * ParameterToLocal;
-
-			FaceTangentX[TriIdx] = TextureToLocal.TransformVector(FVector(1, 0, 0)).GetSafeNormal();
-			FaceTangentY[TriIdx] = TextureToLocal.TransformVector(FVector(0, 1, 0)).GetSafeNormal();
-		}
-		else
-		{
-			FaceTangentX[TriIdx] = Edge20.GetSafeNormal();
-			FaceTangentY[TriIdx] = (FaceTangentX[TriIdx] ^ TriNormal).GetSafeNormal();
-		}
-
-		FaceTangentZ[TriIdx] = TriNormal;
-	}
-
-
-	// Arrays to accumulate tangents into
-	TArray<FVector> VertexTangentXSum, VertexTangentYSum, VertexTangentZSum;
-	VertexTangentXSum.AddZeroed(NumVerts);
-	VertexTangentYSum.AddZeroed(NumVerts);
-	VertexTangentZSum.AddZeroed(NumVerts);
-
-	// For each vertex..
-	for (int VertxIdx = 0; VertxIdx < Vertices->Length(); VertxIdx++)
-	{
-		// Find relevant triangles for normal
-		TArray<int32> SmoothTris;
-		VertToTriSmoothMap.MultiFind(VertxIdx, SmoothTris);
-
-		for (int i = 0; i < SmoothTris.Num(); i++)
-		{
-			int32 TriIdx = SmoothTris[i];
-			VertexTangentZSum[VertxIdx] += FaceTangentZ[TriIdx];
-		}
-
-		// Find relevant triangles for tangents
-		TArray<int32> TangentTris;
-		VertToTriMap.MultiFind(VertxIdx, TangentTris);
-
-		for (int i = 0; i < TangentTris.Num(); i++)
-		{
-			int32 TriIdx = TangentTris[i];
-			VertexTangentXSum[VertxIdx] += FaceTangentX[TriIdx];
-			VertexTangentYSum[VertxIdx] += FaceTangentY[TriIdx];
-		}
-	}
-
-	// Finally, normalize tangents and build output arrays
-	
-	for (int VertxIdx = 0; VertxIdx < NumVerts; VertxIdx++)
-	{
-		FVector& TangentX = VertexTangentXSum[VertxIdx];
-		FVector& TangentY = VertexTangentYSum[VertxIdx];
-		FVector& TangentZ = VertexTangentZSum[VertxIdx];
-
-		TangentX.Normalize();
-		TangentZ.Normalize();
-
-		// Use Gram-Schmidt orthogonalization to make sure X is orth with Z
-		TangentX -= TangentZ * (TangentZ | TangentX);
-		TangentX.Normalize();
-
-		Vertices->SetTangents(VertxIdx, TangentX, TangentY, TangentZ);
-	}
-}
-
-void URuntimeMeshLibrary::CalculateTangentsForMesh(const TArray<FVector>& Vertices, const TArray<int32>& Triangles, const TArray<FVector2D>& UVs, TArray<FVector>& Normals, TArray<FRuntimeMeshTangent>& Tangents)
-{
-	FRuntimeMeshComponentVerticesBuilder VerticesBuilder(const_cast<TArray<FVector>*>(&Vertices), &Normals, &Tangents, nullptr, const_cast<TArray<FVector2D>*>(&UVs));
-	FRuntimeMeshIndicesBuilder IndicesBuilder(const_cast<TArray<int32>*>(&Triangles));
-
-	CalculateTangentsForMesh(&VerticesBuilder, &IndicesBuilder);
-}
-
-
-
-
-
-void URuntimeMeshLibrary::GenerateTessellationIndexBuffer(const IRuntimeMeshVerticesBuilder* Vertices, const FRuntimeMeshIndicesBuilder* Indices, FRuntimeMeshIndicesBuilder* OutTessellationIndices)
-{
-	TessellationUtilities::CalculateTessellationIndices(Vertices, Indices, OutTessellationIndices);
-}
-
-void URuntimeMeshLibrary::GenerateTessellationIndexBuffer(const TArray<FVector>& Vertices, const TArray<int32>& Triangles, const TArray<FVector2D>& UVs, TArray<FVector>& Normals, TArray<FRuntimeMeshTangent>& Tangents, TArray<int32>& OutTessTriangles)
-{
-	FRuntimeMeshComponentVerticesBuilder VerticesBuilder(const_cast<TArray<FVector>*>(&Vertices), &Normals, &Tangents, nullptr, const_cast<TArray<FVector2D>*>(&UVs));
-	FRuntimeMeshIndicesBuilder IndicesBuilder(const_cast<TArray<int32>*>(&Triangles));
-	FRuntimeMeshIndicesBuilder OutIndicesBuilder(&OutTessTriangles);
-
-	GenerateTessellationIndexBuffer(&VerticesBuilder, &IndicesBuilder, &OutIndicesBuilder);
-}
-
-
-
-
-
-static int32 GetNewIndexForOldVertIndex(int32 MeshVertIndex, TMap<int32, int32>& MeshToSectionVertMap, const FPositionVertexBuffer* PosBuffer, const FStaticMeshVertexBuffer* VertBuffer, const FColorVertexBuffer* ColorBuffer, IRuntimeMeshVerticesBuilder* Vertices)
-{
-	int32* NewIndexPtr = MeshToSectionVertMap.Find(MeshVertIndex);
-	if (NewIndexPtr != nullptr)
-	{
-		return *NewIndexPtr;
-	}
-	else
-	{
-		// Copy position
-		int32 SectionVertIndex = Vertices->MoveNextOrAdd();
-
-		Vertices->SetPosition(PosBuffer->VertexPosition(MeshVertIndex));
-		Vertices->SetNormal(VertBuffer->VertexTangentZ(MeshVertIndex));
-		Vertices->SetTangent(VertBuffer->VertexTangentX(MeshVertIndex));
-		if (ColorBuffer && ColorBuffer->GetNumVertices())
-		{
-			Vertices->SetColor(ColorBuffer->VertexColor(MeshVertIndex));
-		}
-
-		// copy all uv channels
-		for (uint32 Index = 0; Index < VertBuffer->GetNumTexCoords(); Index++)
-		{
-			Vertices->SetUV(Index, VertBuffer->GetVertexUV(MeshVertIndex, Index));
-		}
-
-		MeshToSectionVertMap.Add(MeshVertIndex, SectionVertIndex);
-
-		return SectionVertIndex;
-	}
-}
-
-void URuntimeMeshLibrary::GetSectionFromStaticMesh(UStaticMesh* InMesh, int32 LODIndex, int32 SectionIndex,
-	IRuntimeMeshVerticesBuilder* Vertices, FRuntimeMeshIndicesBuilder* Triangles, FRuntimeMeshIndicesBuilder* AdjacencyTriangles)
-{
-	if (InMesh)
-	{
-#if !WITH_EDITOR && (ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION >= 13)
-		if (!InMesh->bAllowCPUAccess)
-		{
-			FMessageLog("PIE").Warning()
-				->AddToken(FTextToken::Create(LOCTEXT("GetSectionFromStaticMeshStart", "Calling GetSectionFromStaticMesh on")))
-				->AddToken(FUObjectToken::Create(InMesh))
-				->AddToken(FTextToken::Create(LOCTEXT("GetSectionFromStaticMeshEnd", "but 'Allow CPU Access' is not enabled. This is required for converting StaticMesh to RuntimeMeshComponent in cooked builds.")));
-		}
-		else 
-#endif
-#if WITH_EDITOR || (ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION >= 13)
-		if (InMesh->RenderData != nullptr && InMesh->RenderData->LODResources.IsValidIndex(LODIndex))
-		{
-			const FStaticMeshLODResources& LOD = InMesh->RenderData->LODResources[LODIndex];
-			if (LOD.Sections.IsValidIndex(SectionIndex))
-			{
-				// Empty output buffers
-				Vertices->Reset();
-				Triangles->Reset();
-
-				// Map from vert buffer for whole mesh to vert buffer for section of interest
-				TMap<int32, int32> MeshToSectionVertMap;
-
-				const FStaticMeshSection& Section = LOD.Sections[SectionIndex];
-				const uint32 OnePastLastIndex = Section.FirstIndex + Section.NumTriangles * 3;
-				FIndexArrayView Indices = LOD.IndexBuffer.GetArrayView();
-
-
-				// Iterate over section index buffer, copying verts as needed
-				for (uint32 i = Section.FirstIndex; i < OnePastLastIndex; i++)
-				{
-					uint32 MeshVertIndex = Indices[i];
-
-					// See if we have this vert already in our section vert buffer, and copy vert in if not 
-					int32 SectionVertIndex = GetNewIndexForOldVertIndex(MeshVertIndex, MeshToSectionVertMap, &LOD.PositionVertexBuffer, &LOD.VertexBuffer, &LOD.ColorVertexBuffer, Vertices);
-
-					// Add to index buffer
-					Triangles->AddIndex(SectionVertIndex);
-				}
-
-				if (AdjacencyTriangles != nullptr)
-				{
-					AdjacencyTriangles->Reset();
-
-					// Adjacency indices use 12 per triangle instead of 3. So start position and length both need to be multiplied by 4
-					const uint32 SectionAdjacencyFirstIndex = Section.FirstIndex * 4;
-					const uint32 SectionAdjacencyOnePastLastIndex = SectionAdjacencyFirstIndex + Section.NumTriangles * (3 * 4);
-					FIndexArrayView AdjacencyIndices = LOD.AdjacencyIndexBuffer.GetArrayView();
-
-					// Iterate over section adjacency index buffer, copying any new verts as needed
-					for (uint32 i = SectionAdjacencyFirstIndex; i < SectionAdjacencyOnePastLastIndex; i++)
-					{
-						uint32 MeshVertIndex = AdjacencyIndices[i];
-
-						// See if we have this vert already in our section vert buffer, and copy vert in if not 
-						int32 SectionVertIndex = GetNewIndexForOldVertIndex(MeshVertIndex, MeshToSectionVertMap, &LOD.PositionVertexBuffer, &LOD.VertexBuffer, &LOD.ColorVertexBuffer, Vertices);
-
-						// Add to index buffer
-						AdjacencyTriangles->AddIndex(SectionVertIndex);
-					}
-				}
-			}
-		}
-#endif
-	}
-}
-
-void URuntimeMeshLibrary::GetSectionFromStaticMesh(UStaticMesh* InMesh, int32 LODIndex, int32 SectionIndex, TArray<FVector>& Vertices,
-	TArray<int32>& Triangles, TArray<FVector>& Normals, TArray<FVector2D>& UVs, TArray<FRuntimeMeshTangent>& Tangents)
-{
-	FRuntimeMeshComponentVerticesBuilder VerticesBuilder(&Vertices, &Normals, &Tangents, nullptr, &UVs);
-	FRuntimeMeshIndicesBuilder IndicesBuilder(&Triangles);
-
-	GetSectionFromStaticMesh(InMesh, LODIndex, SectionIndex, &VerticesBuilder, &IndicesBuilder, nullptr);
-}
-
-void URuntimeMeshLibrary::CopyRuntimeMeshFromStaticMeshComponent(UStaticMeshComponent* StaticMeshComp, int32 LODIndex,
-	URuntimeMeshComponent* RuntimeMeshComp, bool bShouldCreateCollision)
-{
-#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION >= 14
-	UStaticMesh* StaticMesh = StaticMeshComp->GetStaticMesh();
-#else
-	UStaticMesh* StaticMesh = StaticMeshComp->StaticMesh;
-#endif
-
-	if (StaticMeshComp != nullptr && StaticMesh != nullptr && RuntimeMeshComp != nullptr)
-	{
-		//// MESH DATA
-
-		// Make sure LOD index is valid
-		if (StaticMesh->RenderData == nullptr || !StaticMesh->RenderData->LODResources.IsValidIndex(LODIndex))
-		{
-			return;
-		}
-
-		// Get specified LOD
-		const FStaticMeshLODResources& LOD = StaticMesh->RenderData->LODResources[LODIndex];
-
-#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION >= 13
-		int32 NumSections = StaticMesh->GetNumSections(LODIndex);
-#else
-		int32 NumSections = LOD.Sections.Num();
-#endif
-		for (int32 SectionIndex = 0; SectionIndex < NumSections; SectionIndex++)
-		{
-			// Buffers for copying geom data
-			if (LOD.Sections.IsValidIndex(SectionIndex))
-			{
-				int32 NumUVChannels = LOD.GetNumTexCoords();
-
-				FRuntimeMeshIndicesBuilder AdjacencyTriangles;
-
-				if (NumUVChannels <= 1)
-				{
-					FRuntimeMeshPackedVerticesBuilder<FRuntimeMeshVertexSimple> Vertices;
-					FRuntimeMeshIndicesBuilder Triangles;
-
-					// Get geom data from static mesh
-					GetSectionFromStaticMesh(StaticMesh, LODIndex, SectionIndex, &Vertices, &Triangles, &AdjacencyTriangles);
-
-					// Create section using data
-					RuntimeMeshComp->CreateMeshSection(SectionIndex, *Vertices.GetVertices(), *Triangles.GetIndices(),
-						bShouldCreateCollision, EUpdateFrequency::Infrequent, ESectionUpdateFlags::MoveArrays);
-				}
-				else
-				{
-					FRuntimeMeshPackedVerticesBuilder<FRuntimeMeshVertexDualUV> Vertices;
-					FRuntimeMeshIndicesBuilder Triangles;
-
-					// Get geom data from static mesh
-					GetSectionFromStaticMesh(StaticMesh, LODIndex, SectionIndex, &Vertices, &Triangles, &AdjacencyTriangles);
-
-					// Create section using data
-					RuntimeMeshComp->CreateMeshSection(SectionIndex, *Vertices.GetVertices(), *Triangles.GetIndices(),
-						bShouldCreateCollision, EUpdateFrequency::Infrequent, ESectionUpdateFlags::MoveArrays);
-
-				}
-
-			}
-		}
-
-		//// SIMPLE COLLISION
-
-		// Clear any existing collision hulls
-		RuntimeMeshComp->ClearCollisionConvexMeshes();
-
-		if (StaticMesh->BodySetup != nullptr)
-		{
-			// Iterate over all convex hulls on static mesh..
-			const int32 NumConvex = StaticMesh->BodySetup->AggGeom.ConvexElems.Num();
-			for (int ConvexIndex = 0; ConvexIndex < NumConvex; ConvexIndex++)
-			{
-				// Copy convex verts to ProcMesh
-				FKConvexElem& MeshConvex = StaticMesh->BodySetup->AggGeom.ConvexElems[ConvexIndex];
-				RuntimeMeshComp->AddCollisionConvexMesh(MeshConvex.VertexData);
-			}
-		}
-
-		//// MATERIALS
-
-		for (int32 MatIndex = 0; MatIndex < StaticMeshComp->GetNumMaterials(); MatIndex++)
-		{
-			RuntimeMeshComp->SetMaterial(MatIndex, StaticMeshComp->GetMaterial(MatIndex));
-		}
-	}
-}
-
-
-
-
-
-#undef LOCTEXT_NAMESPACE

+ 0 - 156
spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Private/TessellationUtilities.cpp

@@ -1,156 +0,0 @@
-// Copyright 2016 Chris Conway (Koderz). All Rights Reserved.
-
-#include "RuntimeMeshComponentPluginPrivatePCH.h"
-#include "TessellationUtilities.h"
-
-const uint32 EdgesPerTriangle = 3;
-const uint32 IndicesPerTriangle = 3;
-const uint32 VerticesPerTriangle = 3;
-const uint32 DuplicateIndexCount = 3;
-
-const uint32 PnAenDomCorner_IndicesPerPatch = 12;
-
-
-void TessellationUtilities::AddIfLeastUV(PositionDictionary& PosDict, const Vertex& Vert, uint32 Index)
-{
-	auto* Pos = PosDict.Find(Vert.Position);
-	if (Pos == nullptr)
-	{
-		PosDict.Add(Vert.Position, Corner(Index, Vert.TexCoord));
-	}
-	else if (Vert.TexCoord < Pos->TexCoord)
-	{
-		PosDict[Vert.Position] = Corner(Index, Vert.TexCoord);
-	}
-}
-
-
-void TessellationUtilities::CalculateTessellationIndices(const IRuntimeMeshVerticesBuilder* Vertices, const FRuntimeMeshIndicesBuilder* Indices, FRuntimeMeshIndicesBuilder* TessellationIndices)
-{
-	EdgeDictionary EdgeDict;
-	EdgeDict.Reserve(Indices->Length());
-	PositionDictionary PosDict;
-	PosDict.Reserve(Indices->Length());
-
-	TessellationIndices->Reset(PnAenDomCorner_IndicesPerPatch * Indices->Length() / IndicesPerTriangle);
-	
-	ExpandIB(Vertices, Indices, EdgeDict, PosDict, TessellationIndices);
-
-	ReplacePlaceholderIndices(Vertices, Indices, EdgeDict, PosDict, TessellationIndices);
-}
-
-
-void TessellationUtilities::ExpandIB(const IRuntimeMeshVerticesBuilder* Vertices, const FRuntimeMeshIndicesBuilder* Indices,
-	EdgeDictionary& OutEdgeDict, PositionDictionary& OutPosDict, FRuntimeMeshIndicesBuilder* OutIndices)
-{
-	const uint32 TriangleCount = Indices->Length() / IndicesPerTriangle;
-
-	for (uint32 U = 0; U < TriangleCount; U++)
-	{
-		const uint32 StartInIndex = U * IndicesPerTriangle;
-		const uint32 StartOutIndex = U * PnAenDomCorner_IndicesPerPatch;
-
-		Indices->Seek(StartInIndex);
-		const uint32 Index0 = Indices->ReadOne();
-		const uint32 Index1 = Indices->ReadOne();
-		const uint32 Index2 = Indices->ReadOne();
-
-		Vertices->Seek(Index0);
-		const Vertex Vertex0(Vertices->GetPosition(), Vertices->GetUV(0));
-		Vertices->Seek(Index1);
-		const Vertex Vertex1(Vertices->GetPosition(), Vertices->GetUV(0));
-		Vertices->Seek(Index2);
-		const Vertex Vertex2(Vertices->GetPosition(), Vertices->GetUV(0));
-
-		Triangle Tri(Index0, Index1, Index2, Vertex0, Vertex1, Vertex2);
-
-		OutIndices->Seek(StartOutIndex);
-		OutIndices->AddTriangle(Tri.GetIndex(0), Tri.GetIndex(1), Tri.GetIndex(2));
-
-		OutIndices->AddIndex(Tri.GetIndex(0));
-		OutIndices->AddIndex(Tri.GetIndex(1));
-
-		OutIndices->AddIndex(Tri.GetIndex(1));
-		OutIndices->AddIndex(Tri.GetIndex(2));
-
-		OutIndices->AddIndex(Tri.GetIndex(2));
-		OutIndices->AddIndex(Tri.GetIndex(0));
-
-		OutIndices->AddTriangle(Tri.GetIndex(0), Tri.GetIndex(1), Tri.GetIndex(2));
-
-		
-		Edge Rev0 = Tri.GetEdge(0).GetReverse();
-		Edge Rev1 = Tri.GetEdge(1).GetReverse();
-		Edge Rev2 = Tri.GetEdge(2).GetReverse();
-
-		OutEdgeDict.Add(Rev0, Rev0);
-		OutEdgeDict.Add(Rev1, Rev1);
-		OutEdgeDict.Add(Rev2, Rev2);
-
-		AddIfLeastUV(OutPosDict, Vertex0, Index0);
-		AddIfLeastUV(OutPosDict, Vertex1, Index1);
-		AddIfLeastUV(OutPosDict, Vertex2, Index2);
-	}
-}
-
-
-
-void TessellationUtilities::ReplacePlaceholderIndices(const IRuntimeMeshVerticesBuilder* Vertices, const FRuntimeMeshIndicesBuilder* Indices,
-	EdgeDictionary& EdgeDict, PositionDictionary& PosDict, FRuntimeMeshIndicesBuilder* OutIndices)
-{
-	const uint32 TriangleCount = Indices->Length() / PnAenDomCorner_IndicesPerPatch;
-
-	for (uint32 U = 0; U < TriangleCount; U++)
-	{
-		const uint32 StartOutIndex = U * PnAenDomCorner_IndicesPerPatch;
-
-		OutIndices->Seek(StartOutIndex);
-		const uint32 Index0 = OutIndices->ReadOne();
-		const uint32 Index1 = OutIndices->ReadOne();
-		const uint32 Index2 = OutIndices->ReadOne();
-
-		Vertices->Seek(Index0);
-		const Vertex Vertex0(Vertices->GetPosition(), Vertices->GetUV(0));
-		Vertices->Seek(Index1);
-		const Vertex Vertex1(Vertices->GetPosition(), Vertices->GetUV(0));
-		Vertices->Seek(Index2);
-		const Vertex Vertex2(Vertices->GetPosition(), Vertices->GetUV(0));
-
-		Triangle Tri(Index0, Index1, Index2, Vertex0, Vertex1, Vertex2);
-
-		Edge* Ed = EdgeDict.Find(Tri.GetEdge(0));
-		if (Ed != nullptr)
-		{
-			OutIndices->Seek(StartOutIndex + 3);
-			OutIndices->AddIndex(Ed->GetIndex(0));
-			OutIndices->AddIndex(Ed->GetIndex(1));
-		}
-
-		Ed = EdgeDict.Find(Tri.GetEdge(1));
-		if (Ed != nullptr)
-		{
-			OutIndices->Seek(StartOutIndex + 5);
-			OutIndices->AddIndex(Ed->GetIndex(0));
-			OutIndices->AddIndex(Ed->GetIndex(1));
-		}
-
-		Ed = EdgeDict.Find(Tri.GetEdge(2));
-		if (Ed != nullptr)
-		{
-			OutIndices->Seek(StartOutIndex + 7);
-			OutIndices->AddIndex(Ed->GetIndex(0));
-			OutIndices->AddIndex(Ed->GetIndex(1));
-		}
-		
-		// Deal with dominant positions.
-		for (uint32 V = 0; V < VerticesPerTriangle; V++)
-		{
-			Corner* Corn = PosDict.Find(Tri.GetEdge(V).GetVertex(0).Position);
-			if (Corn != nullptr)
-			{
-				OutIndices->Seek(StartOutIndex + 9 + V);
-				OutIndices->AddIndex(Corn->Index);
-			}
-		}
-	}
-}

+ 0 - 178
spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Private/TessellationUtilities.h

@@ -1,178 +0,0 @@
-// Copyright 2016 Chris Conway (Koderz). All Rights Reserved.
-
-#pragma once
-#include "RuntimeMeshBuilder.h"
-
-
-
-/**
- * 
- */
-class TessellationUtilities
-{
-public:
-	static void CalculateTessellationIndices(const IRuntimeMeshVerticesBuilder* Vertices, const FRuntimeMeshIndicesBuilder* Indices, FRuntimeMeshIndicesBuilder* TessellationIndices);
-
-
-
-
-private:
-	struct Vertex
-	{
-		FVector Position;
-		FVector2D TexCoord;
-
-		Vertex() { }
-		Vertex(const FVector& InPosition, const FVector2D& InTexCoord)
-			: Position(InPosition), TexCoord(InTexCoord)
-		{ }
-
-		FORCEINLINE bool operator==(const Vertex& Other) const
-		{
-			return Position == Other.Position;
-		}
-		FORCEINLINE bool operator<(const Vertex& Other) const
-		{
-			return Position.X < Other.Position.X
-				|| Position.Y < Other.Position.Y
-				|| Position.Z < Other.Position.Z;
-		}
-	};
-
-	static FORCEINLINE uint32 HashValue(const FVector& Vec)
-	{
-		return 31337 * GetTypeHash(Vec.X) + 13 * GetTypeHash(Vec.Y) + 3 * GetTypeHash(Vec.Z);
-	}
-
-	static FORCEINLINE uint32 HashValue(const Vertex& Vert)
-	{
-		return HashValue(Vert.Position);
-	}
-
-	struct Edge
-	{
-	private:
-		uint32 IndexFrom;
-		uint32 IndexTo;
-
-		Vertex VertexFrom;
-		Vertex VertexTo;
-
-		uint32 CachedHash;
-
-	public:
-		Edge() : CachedHash(0) { }
-		Edge(uint32 InIndexFrom, uint32 InIndexTo, const Vertex& InVertexFrom, const Vertex& InVertexTo)
-			: IndexFrom(InIndexFrom), IndexTo(InIndexTo), VertexFrom(InVertexFrom), VertexTo(InVertexTo)
-		{
-			// Hash should only consider position, not index. 
-			// We want values with different indices to compare true.
-			CachedHash = 7 * HashValue(VertexFrom) + 2 * HashValue(VertexTo);
-		}
-
-		Vertex GetVertex(uint32 I) const
-		{
-			switch (I)
-			{
-			case 0:
-				return VertexFrom;
-			case 1:
-				return VertexTo;
-			default:
-				checkNoEntry();
-				return Vertex();
-			}
-		}
-
-		uint32 GetIndex(uint32 I) const
-		{
-			switch (I)
-			{
-			case 0:
-				return IndexFrom;
-			case 1:
-				return IndexTo;
-			default:
-				checkNoEntry();
-				return 0;
-			}
-		}
-
-		Edge GetReverse() const
-		{
-			return Edge(IndexTo, IndexFrom, VertexTo, VertexFrom);
-		}
-
-		FORCEINLINE bool operator<(const Edge& Other) const
-		{
-			// Quick out, otherwise we have to compare vertices
-			if (IndexFrom == Other.IndexFrom && IndexTo == Other.IndexTo)
-			{
-				return false;
-			}
-
-			return VertexFrom < Other.VertexFrom || VertexTo < Other.VertexTo;
-		}
-
-		FORCEINLINE bool operator==(const Edge& Other) const
-		{
-			return (IndexFrom == Other.IndexFrom && IndexTo == Other.IndexTo) ||
-				(VertexFrom == Other.VertexFrom && VertexTo == Other.VertexTo);
-		}
-
-		friend FORCEINLINE uint32 GetTypeHash(const Edge& E)
-		{
-			return E.CachedHash;
-		}
-	};
-
-	struct Corner
-	{
-		uint32 Index;
-		FVector2D TexCoord;
-
-		Corner() : Index(0) { }
-		Corner(uint32 InIndex, FVector2D InTexCoord)
-			: Index(InIndex), TexCoord(InTexCoord)
-		{ }
-	};
-
-	class Triangle
-	{
-		Edge Edge0;
-		Edge Edge1;
-		Edge Edge2;
-
-	public:
-		Triangle(uint32 Index0, uint32 Index1, uint32 Index2, const Vertex& Vertex0, const Vertex& Vertex1, const Vertex& Vertex2)
-			: Edge0(Index0, Index1, Vertex0, Vertex1)
-			, Edge1(Index1, Index2, Vertex1, Vertex2)
-			, Edge2(Index2, Index0, Vertex2, Vertex0)
-		{ }
-
-		FORCEINLINE bool operator<(const Triangle& Other) const
-		{
-			return Edge0 < Other.Edge0 || Edge1 < Other.Edge1 || Edge2 < Other.Edge2;
-		}
-
-		FORCEINLINE const Edge& GetEdge(uint32 I)
-		{
-			return ((Edge*)&Edge0)[I];
-		}
-		FORCEINLINE uint32 GetIndex(uint32 I)
-		{
-			return GetEdge(I).GetIndex(0);
-		}
-
-	};
-	using EdgeDictionary = TMap<Edge, Edge>;
-	using PositionDictionary = TMap<FVector, Corner>;
-
-	static void AddIfLeastUV(PositionDictionary& PosDict, const Vertex& Vert, uint32 Index);
-
-	static void ReplacePlaceholderIndices(const IRuntimeMeshVerticesBuilder* Vertices, const FRuntimeMeshIndicesBuilder* Indices,
-		EdgeDictionary& EdgeDict, PositionDictionary& PosDict, FRuntimeMeshIndicesBuilder* OutIndices);
-
-	static void ExpandIB(const IRuntimeMeshVerticesBuilder* Vertices, const FRuntimeMeshIndicesBuilder* Indices,
-		EdgeDictionary& OutEdgeDict, PositionDictionary& OutPosDict, FRuntimeMeshIndicesBuilder* OutIndices);
-};

+ 0 - 1215
spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Public/RuntimeMeshAsync.h

@@ -1,1215 +0,0 @@
-// Copyright 2016 Chris Conway (Koderz). All Rights Reserved.
-
-#pragma once
-
-#include "RuntimeMeshCore.h"
-#include "RuntimeMeshComponent.h"
-
-#define RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(TaskType, DataType, DataPtr, RuntimeMesh, Code)														\
-	class FParallelRuntimeMeshComponentTask_##TaskType																							\
-	{																																			\
-		TWeakObjectPtr<URuntimeMeshComponent> RuntimeMeshComponent;																				\
-		DataType* RMCCallData;																															\
-	public:																																		\
-		FParallelRuntimeMeshComponentTask_##TaskType(TWeakObjectPtr<URuntimeMeshComponent> InRMC, DataType* InData)			\
-			: RuntimeMeshComponent(InRMC), RMCCallData(InData)																		\
-		{																																		\
-		}																																		\
-																																				\
-		~FParallelRuntimeMeshComponentTask_##TaskType()																							\
-		{																																		\
-			if (RMCCallData != nullptr)																											\
-			{																																	\
-				delete RMCCallData;																												\
-			}																																	\
-		}																																		\
-																																				\
-		FORCEINLINE TStatId GetStatId() const																									\
-		{																																		\
-			RETURN_QUICK_DECLARE_CYCLE_STAT(FParallelRuntimeMeshComponentTask_##TaskType, STATGROUP_TaskGraphTasks);							\
-		}																																		\
-																																				\
-		static ENamedThreads::Type GetDesiredThread()																							\
-		{																																		\
-			return ENamedThreads::GameThread;																									\
-		}																																		\
-																																				\
-		static ESubsequentsMode::Type GetSubsequentsMode()																						\
-		{																																		\
-			return ESubsequentsMode::FireAndForget;																								\
-		}																																		\
-																																				\
-		void DoTask(ENamedThreads::Type CurrentThread, const FGraphEventRef& MyCompletionGraphEvent)											\
-		{																																		\
-			DataType* Data = RMCCallData;																										\
-			if (URuntimeMeshComponent* Mesh = RuntimeMeshComponent.Get())																		\
-			{																																	\
-				Code																															\
-			}																																	\
-		}																																		\
-	};																																			\
-	TGraphTask<FParallelRuntimeMeshComponentTask_##TaskType>::CreateTask().ConstructAndDispatchWhenReady(RuntimeMesh, DataPtr);
-
-
-
-
-class RUNTIMEMESHCOMPONENT_API FRuntimeMeshAsync
-{
-
-
-
-public:
-
-	/**
-	*	Create/replace a section.
-	*	@param	SectionIndex		Index of the section to create or replace.
-	*	@param	Vertices			Vertex buffer all vertex data for this section.
-	*	@param	Triangles			Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
-	*	@param	bCreateCollision	Indicates whether collision should be created for this section. This adds significant cost.
-	*	@param	UpdateFrequency		Indicates how frequently the section will be updated. Allows the RMC to optimize itself to a particular use.
-	*	@param	UpdateFlags			Flags pertaining to this particular update.
-	*/
-	template<typename VertexType>
-	static void CreateMeshSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex, TArray<VertexType>& Vertices, TArray<int32>& Triangles, 
-		bool bCreateCollision = false, EUpdateFrequency UpdateFrequency = EUpdateFrequency::Average, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
-	{
-		struct FRMCAsyncData
-		{
-			int32 SectionIndex;
-			TArray<VertexType> Vertices;
-			TArray<int32> Triangles;
-			bool bCreateCollision;
-			EUpdateFrequency UpdateFrequency;
-			ESectionUpdateFlags UpdateFlags;
-		};
-
-		FRMCAsyncData* CallData = new FRMCAsyncData;
-		CallData->SectionIndex = SectionIndex;
-
-		if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
-		{
-			CallData->Vertices = MoveTemp(Vertices);
-			CallData->Triangles = MoveTemp(Triangles);
-		}
-		else
-		{
-			CallData->Vertices = Vertices;
-			CallData->Triangles = Triangles;
-		}
-		CallData->bCreateCollision = bCreateCollision;
-		CallData->UpdateFrequency = UpdateFrequency;
-		CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
-
-		RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(CreateMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
-		{
-			Mesh->CreateMeshSection(Data->SectionIndex, Data->Vertices, Data->Triangles, Data->bCreateCollision, Data->UpdateFrequency, Data->UpdateFlags);
-		});
-	}
-
-
-	/**
-	*	Create/replace a section.
-	*	@param	SectionIndex		Index of the section to create or replace.
-	*	@param	Vertices			Vertex buffer all vertex data for this section.
-	*	@param	Triangles			Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
-	*	@param	BoundingBox			The bounds of this section. Faster than the RMC automatically calculating it.
-	*	@param	bCreateCollision	Indicates whether collision should be created for this section. This adds significant cost.
-	*	@param	UpdateFrequency		Indicates how frequently the section will be updated. Allows the RMC to optimize itself to a particular use.
-	*	@param	UpdateFlags			Flags pertaining to this particular update.
-	*/
-	template<typename VertexType>
-	static void CreateMeshSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex, TArray<VertexType>& Vertices, TArray<int32>& Triangles,
-		const FBox& BoundingBox, bool bCreateCollision = false, EUpdateFrequency UpdateFrequency = EUpdateFrequency::Average, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
-	{
-		struct FRMCAsyncData
-		{
-			int32 SectionIndex;
-			TArray<VertexType> Vertices;
-			TArray<int32> Triangles;
-			FBox BoundingBox;
-			bool bCreateCollision;
-			EUpdateFrequency UpdateFrequency;
-			ESectionUpdateFlags UpdateFlags;
-		};
-
-		FRMCAsyncData* CallData = new FRMCAsyncData;
-		CallData->SectionIndex = SectionIndex;
-
-		if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
-		{
-			CallData->Vertices = MoveTemp(Vertices);
-			CallData->Triangles = MoveTemp(Triangles);
-		}
-		else
-		{
-			CallData->Vertices = Vertices;
-			CallData->Triangles = Triangles;
-		}
-		CallData->BoundingBox = BoundingBox;
-		CallData->bCreateCollision = bCreateCollision;
-		CallData->UpdateFrequency = UpdateFrequency;
-		CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
-
-		RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(CreateMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
-		{
-			Mesh->CreateMeshSection(Data->SectionIndex, Data->Vertices, Data->Triangles, Data->BoundingBox, Data->bCreateCollision, Data->UpdateFrequency, Data->UpdateFlags);
-		});
-	}
-
-	/**
-	*	Create/replace a section using 2 vertex buffers. One contains positions only, the other contains all other data. This allows for very efficient updates of the positions of a mesh.
-	*	@param	SectionIndex		Index of the section to create or replace.
-	*	@param	VertexPositions		Vertex buffer containing only the position information for each vertex.
-	*	@param	VertexData			Vertex buffer containing everything except position for each vertex.
-	*	@param	Triangles			Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
-	*	@param	bCreateCollision	Indicates whether collision should be created for this section. This adds significant cost.
-	*	@param	UpdateFrequency		Indicates how frequently the section will be updated. Allows the RMC to optimize itself to a particular use.
-	*	@param	UpdateFlags			Flags pertaining to this particular update.
-	*/
-	template<typename VertexType>
-	static void CreateMeshSectionDualBuffer(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex, TArray<FVector>& VertexPositions,
-		TArray<VertexType>& VertexData, TArray<int32>& Triangles, bool bCreateCollision = false,
-		EUpdateFrequency UpdateFrequency = EUpdateFrequency::Average, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
-	{
-		struct FRMCAsyncData
-		{
-			int32 SectionIndex;
-			TArray<FVector> VertexPositions;
-			TArray<VertexType> Vertices;
-			TArray<int32> Triangles;
-			bool bCreateCollision;
-			EUpdateFrequency UpdateFrequency;
-			ESectionUpdateFlags UpdateFlags;
-		};
-
-		FRMCAsyncData* CallData = new FRMCAsyncData;
-		CallData->SectionIndex = SectionIndex;
-
-		if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
-		{
-			CallData->VertexPositions = MoveTemp(VertexPositions);
-			CallData->Vertices = MoveTemp(VertexData);
-			CallData->Triangles = MoveTemp(Triangles);
-		}
-		else
-		{
-			CallData->VertexPositions = VertexPositions;
-			CallData->Vertices = VertexData;
-			CallData->Triangles = Triangles;
-		}
-		CallData->bCreateCollision = bCreateCollision;
-		CallData->UpdateFrequency = UpdateFrequency;
-		CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
-
-		RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(CreateMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
-		{
-			Mesh->CreateMeshSection(Data->SectionIndex, Data->VertexPositions, Data->Vertices, Data->Triangles, Data->bCreateCollision, Data->UpdateFrequency, Data->UpdateFlags);
-		});
-	}
-
-	/**
-	*	Create/replace a section using 2 vertex buffers. One contains positions only, the other contains all other data. This allows for very efficient updates of the positions of a mesh.
-	*	@param	SectionIndex		Index of the section to create or replace.
-	*	@param	VertexPositions		Vertex buffer containing only the position information for each vertex.
-	*	@param	VertexData			Vertex buffer containing everything except position for each vertex.
-	*	@param	Triangles			Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
-	*	@param	BoundingBox			The bounds of this section. Faster than the RMC automatically calculating it.
-	*	@param	bCreateCollision	Indicates whether collision should be created for this section. This adds significant cost.
-	*	@param	UpdateFrequency		Indicates how frequently the section will be updated. Allows the RMC to optimize itself to a particular use.
-	*	@param	UpdateFlags			Flags pertaining to this particular update.
-	*/
-	template<typename VertexType>
-	static void CreateMeshSectionDualBuffer(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex, TArray<FVector>& VertexPositions,
-		TArray<VertexType>& VertexData, TArray<int32>& Triangles, const FBox& BoundingBox,
-		bool bCreateCollision = false, EUpdateFrequency UpdateFrequency = EUpdateFrequency::Average, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
-	{
-		struct FRMCAsyncData
-		{
-			int32 SectionIndex;
-			TArray<FVector> VertexPositions;
-			TArray<VertexType> Vertices;
-			TArray<int32> Triangles;
-			FBox BoundingBox;
-			bool bCreateCollision;
-			EUpdateFrequency UpdateFrequency;
-			ESectionUpdateFlags UpdateFlags;
-		};
-
-		FRMCAsyncData* CallData = new FRMCAsyncData;
-		CallData->SectionIndex = SectionIndex;
-
-		if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
-		{
-			CallData->VertexPositions = MoveTemp(VertexPositions);
-			CallData->Vertices = MoveTemp(VertexData);
-			CallData->Triangles = MoveTemp(Triangles);
-		}
-		else
-		{
-			CallData->VertexPositions = VertexPositions;
-			CallData->Vertices = VertexData;
-			CallData->Triangles = Triangles;
-		}
-		CallData->BoundingBox = BoundingBox;
-		CallData->bCreateCollision = bCreateCollision;
-		CallData->UpdateFrequency = UpdateFrequency;
-		CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
-
-		RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(CreateMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
-		{
-			Mesh->CreateMeshSection(Data->SectionIndex, Data->VertexPositions, Data->Vertices, Data->Triangles, Data->BoundingBox, Data->bCreateCollision, Data->UpdateFrequency, Data->UpdateFlags);
-		});
-	}
-
-
-	/**
-	*	Updates a section. This is faster than CreateMeshSection. If this is a dual buffer section, you cannot change the length of the vertices.
-	*	@param	SectionIndex		Index of the section to update.
-	*	@param	Vertices			Vertex buffer all vertex data for this section, or in the case of dual buffer section it contains everything but position.
-	*	@param	UpdateFlags			Flags pertaining to this particular update.
-	*/
-	template<typename VertexType>
-	static void UpdateMeshSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex, TArray<VertexType>& Vertices,
-		ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
-	{
-		struct FRMCAsyncData
-		{
-			int32 SectionIndex;
-			TArray<VertexType> Vertices;
-			ESectionUpdateFlags UpdateFlags;
-		};
-
-		FRMCAsyncData* CallData = new FRMCAsyncData;
-		CallData->SectionIndex = SectionIndex;
-
-		if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
-		{
-			CallData->Vertices = MoveTemp(Vertices);
-		}
-		else
-		{
-			CallData->Vertices = Vertices;
-		}
-
-		CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
-
-		RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(UpdateMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
-		{
-			Mesh->UpdateMeshSection(Data->SectionIndex, Data->Vertices, Data->UpdateFlags);
-		});
-	}
-
-	/**
-	*	Updates a section. This is faster than CreateMeshSection. If this is a dual buffer section, you cannot change the length of the vertices.
-	*	@param	SectionIndex		Index of the section to update.
-	*	@param	Vertices			Vertex buffer all vertex data for this section, or in the case of dual buffer section it contains everything but position.
-	*	@param	BoundingBox			The bounds of this section. Faster than the RMC automatically calculating it.
-	*	@param	UpdateFlags			Flags pertaining to this particular update.
-	*/
-	template<typename VertexType>
-	static void UpdateMeshSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex, TArray<VertexType>& Vertices,
-		const FBox& BoundingBox, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
-	{
-		struct FRMCAsyncData
-		{
-			int32 SectionIndex;
-			TArray<VertexType> Vertices;
-			FBox BoundingBox;
-			ESectionUpdateFlags UpdateFlags;
-		};
-
-		FRMCAsyncData* CallData = new FRMCAsyncData;
-		CallData->SectionIndex = SectionIndex;
-
-		if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
-		{
-			CallData->Vertices = MoveTemp(Vertices);
-		}
-		else
-		{
-			CallData->Vertices = Vertices;
-		}
-		
-		CallData->BoundingBox = BoundingBox;
-		CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
-
-		RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(UpdateMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
-		{
-			Mesh->UpdateMeshSection(Data->SectionIndex, Data->Vertices, Data->BoundingBox, Data->UpdateFlags);
-		});
-	}
-
-	/**
-	*	Updates a section. This is faster than CreateMeshSection. If this is a dual buffer section, you cannot change the length of the vertices.
-	*	@param	SectionIndex		Index of the section to update.
-	*	@param	Vertices			Vertex buffer all vertex data for this section, or in the case of dual buffer section it contains everything but position.
-	*	@param	Triangles			Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
-	*	@param	UpdateFlags			Flags pertaining to this particular update.
-	*/
-	template<typename VertexType>
-	static void UpdateMeshSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex, TArray<VertexType>& Vertices,
-		TArray<int32>& Triangles, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
-	{
-		struct FRMCAsyncData
-		{
-			int32 SectionIndex;
-			TArray<VertexType> Vertices;
-			TArray<int32> Triangles;
-			ESectionUpdateFlags UpdateFlags;
-		};
-
-		FRMCAsyncData* CallData = new FRMCAsyncData;
-		CallData->SectionIndex = SectionIndex;
-
-		if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
-		{
-			CallData->Vertices = MoveTemp(Vertices);
-			CallData->Triangles = MoveTemp(Triangles);
-		}
-		else
-		{
-			CallData->Vertices = Vertices;
-			CallData->Triangles = Triangles;
-		}
-
-		CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
-
-		RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(UpdateMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
-		{
-			Mesh->UpdateMeshSection(Data->SectionIndex, Data->Vertices, Data->Triangles, Data->UpdateFlags);
-		});
-	}
-
-	/**
-	*	Updates a section. This is faster than CreateMeshSection. If this is a dual buffer section, you cannot change the length of the vertices.
-	*	@param	SectionIndex		Index of the section to update.
-	*	@param	Vertices			Vertex buffer all vertex data for this section, or in the case of dual buffer section it contains everything but position.
-	*	@param	Triangles			Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
-	*	@param	BoundingBox			The bounds of this section. Faster than the RMC automatically calculating it.
-	*	@param	UpdateFlags			Flags pertaining to this particular update.
-	*/
-	template<typename VertexType>
-	static void UpdateMeshSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex, TArray<VertexType>& Vertices,
-		TArray<int32>& Triangles, const FBox& BoundingBox, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
-	{
-		struct FRMCAsyncData
-		{
-			int32 SectionIndex;
-			TArray<VertexType> Vertices;
-			TArray<int32> Triangles;
-			FBox BoundingBox;
-			ESectionUpdateFlags UpdateFlags;
-		};
-
-		FRMCAsyncData* CallData = new FRMCAsyncData;
-		CallData->SectionIndex = SectionIndex;
-
-		if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
-		{
-			CallData->Vertices = MoveTemp(Vertices);
-			CallData->Triangles = MoveTemp(Triangles);
-		}
-		else
-		{
-			CallData->Vertices = Vertices;
-			CallData->Triangles = Triangles;
-		}
-
-		CallData->BoundingBox = BoundingBox;
-		CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
-
-		RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(UpdateMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
-		{
-			Mesh->UpdateMeshSection(Data->SectionIndex, Data->Vertices, Data->Triangles, Data->BoundingBox, Data->UpdateFlags);
-		});
-	}
-
-
-	/**
-	*	Updates a section. This is faster than CreateMeshSection. This is only for dual buffer sections. You cannot change the length of positions or vertex data unless you specify both together.
-	*	@param	SectionIndex		Index of the section to update.
-	*	@param	VertexPositions		Vertex buffer containing only the position information for each vertex.
-	*	@param	Vertices			Vertex buffer containing everything except position for each vertex.
-	*	@param	UpdateFlags			Flags pertaining to this particular update.
-	*/
-	template<typename VertexType>
-	static void UpdateMeshSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex, TArray<FVector>& VertexPositions,
-		TArray<VertexType>& Vertices, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
-	{
-		struct FRMCAsyncData
-		{
-			int32 SectionIndex;
-			TArray<FVector> VertexPositions;
-			TArray<VertexType> Vertices;
-			ESectionUpdateFlags UpdateFlags;
-		};
-
-		FRMCAsyncData* CallData = new FRMCAsyncData;
-		CallData->SectionIndex = SectionIndex;
-
-		if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
-		{
-			CallData->VertexPositions = MoveTemp(VertexPositions);
-			CallData->Vertices = MoveTemp(Vertices);
-		}
-		else
-		{
-			CallData->VertexPositions = VertexPositions;
-			CallData->Vertices = Vertices;
-		}
-
-		CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
-
-		RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(UpdateMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
-		{
-			Mesh->UpdateMeshSection(Data->SectionIndex, Data->VertexPositions, Data->Vertices, Data->UpdateFlags);
-		});
-	}
-
-	/**
-	*	Updates a section. This is faster than CreateMeshSection. This is only for dual buffer sections. You cannot change the length of positions or vertex data unless you specify both together.
-	*	@param	SectionIndex		Index of the section to update.
-	*	@param	VertexPositions		Vertex buffer containing only the position information for each vertex.
-	*	@param	Vertices			Vertex buffer containing everything except position for each vertex.
-	*	@param	BoundingBox			The bounds of this section. Faster than the RMC automatically calculating it.
-	*	@param	UpdateFlags			Flags pertaining to this particular update.
-	*/
-	template<typename VertexType>
-	static void UpdateMeshSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex, TArray<FVector>& VertexPositions,
-		TArray<VertexType>& Vertices, const FBox& BoundingBox, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
-	{
-		struct FRMCAsyncData
-		{
-			int32 SectionIndex;
-			TArray<FVector> VertexPositions;
-			TArray<VertexType> Vertices;
-			FBox BoundingBox;
-			ESectionUpdateFlags UpdateFlags;
-		};
-
-		FRMCAsyncData* CallData = new FRMCAsyncData;
-		CallData->SectionIndex = SectionIndex;
-
-		if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
-		{
-			CallData->VertexPositions = MoveTemp(VertexPositions);
-			CallData->Vertices = MoveTemp(Vertices);
-		}
-		else
-		{
-			CallData->VertexPositions = VertexPositions;
-			CallData->Vertices = Vertices;
-		}
-
-		CallData->BoundingBox = BoundingBox;
-		CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
-
-		RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(UpdateMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
-		{
-			Mesh->UpdateMeshSection(Data->SectionIndex, Data->VertexPositions, Data->Vertices, Data->BoundingBox, Data->UpdateFlags);
-		});
-	}
-
-	/**
-	*	Updates a section. This is faster than CreateMeshSection. This is only for dual buffer sections. You cannot change the length of positions or vertex data unless you specify both together.
-	*	@param	SectionIndex		Index of the section to update.
-	*	@param	VertexPositions		Vertex buffer containing only the position information for each vertex.
-	*	@param	Vertices			Vertex buffer containing everything except position for each vertex.
-	*	@param	Triangles			Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
-	*	@param	UpdateFlags			Flags pertaining to this particular update.
-	*/
-	template<typename VertexType>
-	static void UpdateMeshSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex, TArray<FVector>& VertexPositions,
-		TArray<VertexType>& Vertices, TArray<int32>& Triangles, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
-	{
-		struct FRMCAsyncData
-		{
-			int32 SectionIndex;
-			TArray<FVector> VertexPositions;
-			TArray<VertexType> Vertices;
-			TArray<int32> Triangles;
-			ESectionUpdateFlags UpdateFlags;
-		};
-
-		FRMCAsyncData* CallData = new FRMCAsyncData;
-		CallData->SectionIndex = SectionIndex;
-
-		if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
-		{
-			CallData->VertexPositions = MoveTemp(VertexPositions);
-			CallData->Vertices = MoveTemp(Vertices);
-			CallData->Triangles = MoveTemp(Triangles);
-		}
-		else
-		{
-			CallData->VertexPositions = VertexPositions;
-			CallData->Vertices = Vertices;
-			CallData->Triangles = Triangles;
-		}
-
-		CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
-
-		RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(UpdateMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
-		{
-			Mesh->UpdateMeshSection(Data->SectionIndex, Data->VertexPositions, Data->Vertices, Data->Triangles, Data->UpdateFlags);
-		});
-	}
-
-	/**
-	*	Updates a section. This is faster than CreateMeshSection. This is only for dual buffer sections. You cannot change the length of positions or vertex data unless you specify both together.
-	*	@param	SectionIndex		Index of the section to update.
-	*	@param	VertexPositions		Vertex buffer containing only the position information for each vertex.
-	*	@param	Vertices			Vertex buffer containing everything except position for each vertex.
-	*	@param	Triangles			Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
-	*	@param	BoundingBox			The bounds of this section. Faster than the RMC automatically calculating it.
-	*	@param	UpdateFlags			Flags pertaining to this particular update.
-	*/
-	template<typename VertexType>
-	static void UpdateMeshSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex, TArray<FVector>& VertexPositions,
-		TArray<VertexType>& Vertices, TArray<int32>& Triangles, const FBox& BoundingBox, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
-	{
-		struct FRMCAsyncData
-		{
-			int32 SectionIndex;
-			TArray<FVector> VertexPositions;
-			TArray<VertexType> Vertices;
-			TArray<int32> Triangles;
-			FBox BoundingBox;
-			ESectionUpdateFlags UpdateFlags;
-		};
-
-		FRMCAsyncData* CallData = new FRMCAsyncData;
-		CallData->SectionIndex = SectionIndex;
-
-		if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
-		{
-			CallData->VertexPositions = MoveTemp(VertexPositions);
-			CallData->Vertices = MoveTemp(Vertices);
-			CallData->Triangles = MoveTemp(Triangles);
-		}
-		else
-		{
-			CallData->VertexPositions = VertexPositions;
-			CallData->Vertices = Vertices;
-			CallData->Triangles = Triangles;
-		}
-
-		CallData->BoundingBox = BoundingBox;
-		CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
-
-		RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(UpdateMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
-		{
-			Mesh->UpdateMeshSection(Data->SectionIndex, Data->VertexPositions, Data->Vertices, Data->Triangles, Data->BoundingBox, Data->UpdateFlags);
-		});
-	}
-
-
-	/**
-	*	Updates a sections position buffer only. This cannot be used on a non-dual buffer section. You cannot change the length of the vertex position buffer with this function.
-	*	@param	SectionIndex		Index of the section to update.
-	*	@param	VertexPositions		Vertex buffer containing only the position information for each vertex.
-	*	@param	UpdateFlags			Flags pertaining to this particular update.
-	*/
-	static void UpdateMeshSectionPositionsImmediate(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex,
-		TArray<FVector>& VertexPositions, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
-	{
-		struct FRMCAsyncData
-		{
-			int32 SectionIndex;
-			TArray<FVector> VertexPositions;
-			ESectionUpdateFlags UpdateFlags;
-		};
-
-		FRMCAsyncData* CallData = new FRMCAsyncData;
-		CallData->SectionIndex = SectionIndex;
-
-		if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
-		{
-			CallData->VertexPositions = MoveTemp(VertexPositions);
-		}
-		else
-		{
-			CallData->VertexPositions = VertexPositions;
-		}
-
-		CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
-
-		RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(UpdateMeshSectionPositionsImmediate, FRMCAsyncData, CallData, InRuntimeMeshComponent,
-		{
-			Mesh->UpdateMeshSectionPositionsImmediate(Data->SectionIndex, Data->VertexPositions, Data->UpdateFlags);
-		});
-	}
-
-	/**
-	*	Updates a sections position buffer only. This cannot be used on a non-dual buffer section. You cannot change the length of the vertex position buffer with this function.
-	*	@param	SectionIndex		Index of the section to update.
-	*	@param	VertexPositions		Vertex buffer containing only the position information for each vertex.
-	*	@param	BoundingBox			The bounds of this section. Faster than the RMC automatically calculating it.
-	*	@param	UpdateFlags			Flags pertaining to this particular update.
-	*/
-	static void UpdateMeshSectionPositionsImmediate(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex,
-		TArray<FVector>& VertexPositions, const FBox& BoundingBox, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
-	{
-		struct FRMCAsyncData
-		{
-			int32 SectionIndex;
-			TArray<FVector> VertexPositions;
-			FBox BoundingBox;
-			ESectionUpdateFlags UpdateFlags;
-		};
-
-		FRMCAsyncData* CallData = new FRMCAsyncData;
-		CallData->SectionIndex = SectionIndex;
-
-		if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
-		{
-			CallData->VertexPositions = MoveTemp(VertexPositions);
-		}
-		else
-		{
-			CallData->VertexPositions = VertexPositions;
-		}
-		
-		CallData->BoundingBox = BoundingBox;
-		CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
-
-		RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(UpdateMeshSectionPositionsImmediate, FRMCAsyncData, CallData, InRuntimeMeshComponent,
-		{
-			Mesh->UpdateMeshSectionPositionsImmediate(Data->SectionIndex, Data->VertexPositions, Data->BoundingBox, Data->UpdateFlags);
-		});
-	}
-
-
-
-
-
-	/**
-	*	Create/replace a section.
-	*	@param	SectionIndex		Index of the section to create or replace.
-	*	@param	Vertices			Vertex buffer of all vertex positions to use for this mesh section.
-	*	@param	Triangles			Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
-	*	@param	Normals				Optional array of normal vectors for each vertex. If supplied, must be same length as Vertices array.
-	*	@param	UV0					Optional array of texture co-ordinates for each vertex (UV Channel 0). If supplied, must be same length as Vertices array.
-	*	@param	Colors				Optional array of colors for each vertex. If supplied, must be same length as Vertices array.
-	*	@param	Tangents			Optional array of tangent vector for each vertex. If supplied, must be same length as Vertices array.
-	*	@param	bCreateCollision	Indicates whether collision should be created for this section. This adds significant cost.
-	*	@param	UpdateFrequency		Indicates how frequently the section will be updated. Allows the RMC to optimize itself to a particular use.
-	*/
-	static void CreateMeshSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex, const TArray<FVector>& Vertices,
-		const TArray<int32>& Triangles, const TArray<FVector>& Normals, const TArray<FVector2D>& UV0, const TArray<FColor>& Colors,
-		const TArray<FRuntimeMeshTangent>& Tangents, bool bCreateCollision = false,
-		EUpdateFrequency UpdateFrequency = EUpdateFrequency::Average, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
-	{
-		struct FRMCAsyncData
-		{
-			int32 SectionIndex;
-			TArray<FVector> Vertices;
-			TArray<int32> Triangles;
-			TArray<FVector> Normals;
-			TArray<FVector2D> UV0;
-			TArray<FColor> Colors;
-			TArray<FRuntimeMeshTangent> Tangents;
-			bool bCreateCollision = false;
-			EUpdateFrequency UpdateFrequency;
-			ESectionUpdateFlags UpdateFlags;
-		};
-
-		FRMCAsyncData* CallData = new FRMCAsyncData;
-		CallData->SectionIndex = SectionIndex;
-
-		if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
-		{
-			CallData->Vertices = MoveTemp(Vertices);
-			CallData->Triangles = MoveTemp(Triangles);
-			CallData->Normals = MoveTemp(Normals);
-			CallData->UV0 = MoveTemp(UV0);
-			CallData->Colors = MoveTemp(Colors);
-			CallData->Tangents = MoveTemp(Tangents);
-		}
-		else
-		{
-			CallData->Vertices = Vertices;
-			CallData->Triangles = Triangles;
-			CallData->Normals = Normals;
-			CallData->UV0 = UV0;
-			CallData->Colors = Colors;
-			CallData->Tangents = Tangents;
-		}
-
-		CallData->bCreateCollision = bCreateCollision;
-		CallData->UpdateFrequency = UpdateFrequency;
-		CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
-
-		RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(CreateMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
-		{
-			Mesh->CreateMeshSection(Data->SectionIndex, Data->Vertices, Data->Triangles, Data->Normals, Data->UV0, Data->Colors, 
-			Data->Tangents, Data->bCreateCollision, Data->UpdateFrequency, Data->UpdateFlags);
-		});
-	}
-
-	/**
-	*	Create/replace a section.
-	*	@param	SectionIndex		Index of the section to create or replace.
-	*	@param	Vertices			Vertex buffer of all vertex positions to use for this mesh section.
-	*	@param	Triangles			Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
-	*	@param	Normals				Optional array of normal vectors for each vertex. If supplied, must be same length as Vertices array.
-	*	@param	UV0					Optional array of texture co-ordinates for each vertex (UV Channel 0). If supplied, must be same length as Vertices array.
-	*	@param	UV1					Optional array of texture co-ordinates for each vertex (UV Channel 1). If supplied, must be same length as Vertices array.
-	*	@param	Colors				Optional array of colors for each vertex. If supplied, must be same length as Vertices array.
-	*	@param	Tangents			Optional array of tangent vector for each vertex. If supplied, must be same length as Vertices array.
-	*	@param	bCreateCollision	Indicates whether collision should be created for this section. This adds significant cost.
-	*	@param	UpdateFrequency		Indicates how frequently the section will be updated. Allows the RMC to optimize itself to a particular use.
-	*/
-	static void CreateMeshSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex, const TArray<FVector>& Vertices,
-		const TArray<int32>& Triangles, const TArray<FVector>& Normals,	const TArray<FVector2D>& UV0, const TArray<FVector2D>& UV1, 
-		const TArray<FColor>& Colors, const TArray<FRuntimeMeshTangent>& Tangents,
-		bool bCreateCollision = false, EUpdateFrequency UpdateFrequency = EUpdateFrequency::Average, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
-	{
-		struct FRMCAsyncData
-		{
-			int32 SectionIndex;
-			TArray<FVector> Vertices;
-			TArray<int32> Triangles;
-			TArray<FVector> Normals;
-			TArray<FVector2D> UV0;
-			TArray<FVector2D> UV1;
-			TArray<FColor> Colors;
-			TArray<FRuntimeMeshTangent> Tangents;
-			bool bCreateCollision = false;
-			EUpdateFrequency UpdateFrequency;
-			ESectionUpdateFlags UpdateFlags;
-		};
-
-		FRMCAsyncData* CallData = new FRMCAsyncData;
-		CallData->SectionIndex = SectionIndex;
-
-		if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
-		{
-			CallData->Vertices = MoveTemp(Vertices);
-			CallData->Triangles = MoveTemp(Triangles);
-			CallData->Normals = MoveTemp(Normals);
-			CallData->UV0 = MoveTemp(UV0);
-			CallData->UV1 = MoveTemp(UV1);
-			CallData->Colors = MoveTemp(Colors);
-			CallData->Tangents = MoveTemp(Tangents);
-		}
-		else
-		{
-			CallData->Vertices = Vertices;
-			CallData->Triangles = Triangles;
-			CallData->Normals = Normals;
-			CallData->UV0 = UV0;
-			CallData->UV1 = UV1;
-			CallData->Colors = Colors;
-			CallData->Tangents = Tangents;
-		}
-
-		CallData->bCreateCollision = bCreateCollision;
-		CallData->UpdateFrequency = UpdateFrequency;
-		CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
-
-		RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(CreateMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
-		{
-			Mesh->CreateMeshSection(Data->SectionIndex, Data->Vertices, Data->Triangles, Data->Normals, Data->UV0, Data->UV1, Data->Colors,
-			Data->Tangents, Data->bCreateCollision, Data->UpdateFrequency, Data->UpdateFlags);
-		});
-	}
-
-
-	/**
-	*	Updates a section. This is faster than CreateMeshSection.
-	*	@param	SectionIndex		Index of the section to update.
-	*	@param	Vertices			Vertex buffer of all vertex positions to use for this mesh section.
-	*	@param	Normals				Optional array of normal vectors for each vertex. If supplied, must be same length as Vertices array.
-	*	@param	UV1					Optional array of texture co-ordinates for each vertex (UV Channel 1). If supplied, must be same length as Vertices array.
-	*	@param	Colors				Optional array of colors for each vertex. If supplied, must be same length as Vertices array.
-	*	@param	Tangents			Optional array of tangent vector for each vertex. If supplied, must be same length as Vertices array.
-	*/
-	static void UpdateMeshSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex, const TArray<FVector>& Vertices,
-		const TArray<FVector>& Normals, const TArray<FVector2D>& UV0, const TArray<FColor>& Colors, const TArray<FRuntimeMeshTangent>& Tangents, 
-		ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
-	{
-		struct FRMCAsyncData
-		{
-			int32 SectionIndex;
-			TArray<FVector> Vertices;
-			TArray<FVector> Normals;
-			TArray<FVector2D> UV0;
-			TArray<FVector2D> UV1;
-			TArray<FColor> Colors;
-			TArray<FRuntimeMeshTangent> Tangents;
-			bool bCreateCollision = false;
-			EUpdateFrequency UpdateFrequency;
-			ESectionUpdateFlags UpdateFlags;
-		};
-
-		FRMCAsyncData* CallData = new FRMCAsyncData;
-		CallData->SectionIndex = SectionIndex;
-
-		if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
-		{
-			CallData->Vertices = MoveTemp(Vertices);
-			CallData->Normals = MoveTemp(Normals);
-			CallData->UV0 = MoveTemp(UV0);
-			CallData->Colors = MoveTemp(Colors);
-			CallData->Tangents = MoveTemp(Tangents);
-		}
-		else
-		{
-			CallData->Vertices = Vertices;
-			CallData->Normals = Normals;
-			CallData->UV0 = UV0;
-			CallData->Colors = Colors;
-			CallData->Tangents = Tangents;
-		}
-
-		CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
-
-		RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(UpdateMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
-		{
-			Mesh->UpdateMeshSection(Data->SectionIndex, Data->Vertices, Data->Normals, Data->UV0, Data->Colors,	Data->Tangents, Data->UpdateFlags);
-		});
-	}
-
-	/**
-	*	Updates a section. This is faster than CreateMeshSection.
-	*	@param	SectionIndex		Index of the section to update.
-	*	@param	Vertices			Vertex buffer of all vertex positions to use for this mesh section.
-	*	@param	Normals				Optional array of normal vectors for each vertex. If supplied, must be same length as Vertices array.
-	*	@param	UV0					Optional array of texture co-ordinates for each vertex (UV Channel 0). If supplied, must be same length as Vertices array.
-	*	@param	UV1					Optional array of texture co-ordinates for each vertex (UV Channel 1). If supplied, must be same length as Vertices array.
-	*	@param	Colors				Optional array of colors for each vertex. If supplied, must be same length as Vertices array.
-	*	@param	Tangents			Optional array of tangent vector for each vertex. If supplied, must be same length as Vertices array.
-	*/
-	static void UpdateMeshSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex, const TArray<FVector>& Vertices,
-		const TArray<FVector>& Normals, const TArray<FVector2D>& UV0, const TArray<FVector2D>& UV1, const TArray<FColor>& Colors, 
-		const TArray<FRuntimeMeshTangent>& Tangents, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
-	{
-		struct FRMCAsyncData
-		{
-			int32 SectionIndex;
-			TArray<FVector> Vertices;
-			TArray<FVector> Normals;
-			TArray<FVector2D> UV0;
-			TArray<FVector2D> UV1;
-			TArray<FColor> Colors;
-			TArray<FRuntimeMeshTangent> Tangents;
-			bool bCreateCollision = false;
-			EUpdateFrequency UpdateFrequency;
-			ESectionUpdateFlags UpdateFlags;
-		};
-
-		FRMCAsyncData* CallData = new FRMCAsyncData;
-		CallData->SectionIndex = SectionIndex;
-
-		if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
-		{
-			CallData->Vertices = MoveTemp(Vertices);
-			CallData->Normals = MoveTemp(Normals);
-			CallData->UV0 = MoveTemp(UV0);
-			CallData->UV1 = MoveTemp(UV1);
-			CallData->Colors = MoveTemp(Colors);
-			CallData->Tangents = MoveTemp(Tangents);
-		}
-		else
-		{
-			CallData->Vertices = Vertices;
-			CallData->Normals = Normals;
-			CallData->UV0 = UV0;
-			CallData->UV1 = UV1;
-			CallData->Colors = Colors;
-			CallData->Tangents = Tangents;
-		}
-
-		CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
-
-		RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(UpdateMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
-		{
-			Mesh->UpdateMeshSection(Data->SectionIndex, Data->Vertices, Data->Normals, Data->UV0, Data->UV1, Data->Colors, Data->Tangents, Data->UpdateFlags);
-		});
-	}
-
-	/**
-	*	Updates a section. This is faster than CreateMeshSection.
-	*	@param	SectionIndex		Index of the section to update.
-	*	@param	Vertices			Vertex buffer of all vertex positions to use for this mesh section.
-	*	@param	Triangles			Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
-	*	@param	Normals				Optional array of normal vectors for each vertex. If supplied, must be same length as Vertices array.
-	*	@param	UV0					Optional array of texture co-ordinates for each vertex (UV Channel 0). If supplied, must be same length as Vertices array.
-	*	@param	Colors				Optional array of colors for each vertex. If supplied, must be same length as Vertices array.
-	*	@param	Tangents			Optional array of tangent vector for each vertex. If supplied, must be same length as Vertices array.
-	*/
-	static void UpdateMeshSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex, const TArray<FVector>& Vertices,
-		const TArray<int32>& Triangles, const TArray<FVector>& Normals,	const TArray<FVector2D>& UV0, const TArray<FColor>& Colors, 
-		const TArray<FRuntimeMeshTangent>& Tangents, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
-	{
-		struct FRMCAsyncData
-		{
-			int32 SectionIndex;
-			TArray<FVector> Vertices;
-			TArray<int32> Triangles;
-			TArray<FVector> Normals;
-			TArray<FVector2D> UV0;
-			TArray<FColor> Colors;
-			TArray<FRuntimeMeshTangent> Tangents;
-			bool bCreateCollision = false;
-			EUpdateFrequency UpdateFrequency;
-			ESectionUpdateFlags UpdateFlags;
-		};
-
-		FRMCAsyncData* CallData = new FRMCAsyncData;
-		CallData->SectionIndex = SectionIndex;
-
-		if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
-		{
-			CallData->Vertices = MoveTemp(Vertices);
-			CallData->Triangles = MoveTemp(Triangles);
-			CallData->Normals = MoveTemp(Normals);
-			CallData->UV0 = MoveTemp(UV0);
-			CallData->Colors = MoveTemp(Colors);
-			CallData->Tangents = MoveTemp(Tangents);
-		}
-		else
-		{
-			CallData->Vertices = Vertices;
-			CallData->Triangles = Triangles;
-			CallData->Normals = Normals;
-			CallData->UV0 = UV0;
-			CallData->Colors = Colors;
-			CallData->Tangents = Tangents;
-		}
-
-		CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
-
-		RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(UpdateMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
-		{
-			Mesh->UpdateMeshSection(Data->SectionIndex, Data->Vertices, Data->Triangles, Data->Normals, Data->UV0, Data->Colors, Data->Tangents, Data->UpdateFlags);
-		});
-	}
-
-	/**
-	*	Updates a section. This is faster than CreateMeshSection.
-	*	@param	SectionIndex		Index of the section to update.
-	*	@param	Vertices			Vertex buffer of all vertex positions to use for this mesh section.
-	*	@param	Triangles			Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
-	*	@param	Normals				Optional array of normal vectors for each vertex. If supplied, must be same length as Vertices array.
-	*	@param	UV0					Optional array of texture co-ordinates for each vertex (UV Channel 0). If supplied, must be same length as Vertices array.
-	*	@param	UV1					Optional array of texture co-ordinates for each vertex (UV Channel 1). If supplied, must be same length as Vertices array.
-	*	@param	Colors				Optional array of colors for each vertex. If supplied, must be same length as Vertices array.
-	*	@param	Tangents			Optional array of tangent vector for each vertex. If supplied, must be same length as Vertices array.
-	*/
-	static void UpdateMeshSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex, const TArray<FVector>& Vertices,
-		const TArray<int32>& Triangles, const TArray<FVector>& Normals,	const TArray<FVector2D>& UV0, const TArray<FVector2D>& UV1, 
-		const TArray<FColor>& Colors, const TArray<FRuntimeMeshTangent>& Tangents, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
-	{
-		struct FRMCAsyncData
-		{
-			int32 SectionIndex;
-			TArray<FVector> Vertices;
-			TArray<int32> Triangles;
-			TArray<FVector> Normals;
-			TArray<FVector2D> UV0;
-			TArray<FVector2D> UV1;
-			TArray<FColor> Colors;
-			TArray<FRuntimeMeshTangent> Tangents;
-			bool bCreateCollision = false;
-			EUpdateFrequency UpdateFrequency;
-			ESectionUpdateFlags UpdateFlags;
-		};
-
-		FRMCAsyncData* CallData = new FRMCAsyncData;
-		CallData->SectionIndex = SectionIndex;
-
-		if (!!(UpdateFlags & ESectionUpdateFlags::MoveArrays))
-		{
-			CallData->Vertices = MoveTemp(Vertices);
-			CallData->Triangles = MoveTemp(Triangles);
-			CallData->Normals = MoveTemp(Normals);
-			CallData->UV0 = MoveTemp(UV0);
-			CallData->UV1 = MoveTemp(UV1);
-			CallData->Colors = MoveTemp(Colors);
-			CallData->Tangents = MoveTemp(Tangents);
-		}
-		else
-		{
-			CallData->Vertices = Vertices;
-			CallData->Triangles = Triangles;
-			CallData->Normals = Normals;
-			CallData->UV0 = UV0;
-			CallData->UV1 = UV1;
-			CallData->Colors = Colors;
-			CallData->Tangents = Tangents;
-		}
-
-		CallData->UpdateFlags = UpdateFlags | ESectionUpdateFlags::MoveArrays; // We can always use move arrays here since we either just copied it, or moved it from the original
-
-		RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(UpdateMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
-		{
-			Mesh->UpdateMeshSection(Data->SectionIndex, Data->Vertices, Data->Triangles, Data->Normals, Data->UV0, Data->UV1, Data->Colors,	Data->Tangents, Data->UpdateFlags);
-		});
-	}
-
-
-
-	/** Clear a section of the procedural mesh. */
-	static void ClearMeshSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex)
-	{
-		struct FRMCAsyncData
-		{
-			int32 SectionIndex;
-		};
-
-		FRMCAsyncData* CallData = new FRMCAsyncData;
-		CallData->SectionIndex = SectionIndex;
-
-		RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(ClearMeshSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
-		{
-			Mesh->ClearMeshSection(Data->SectionIndex);
-		});
-	}
-
-	/** Clear all mesh sections and reset to empty state */
-	static void ClearAllMeshSections(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent)
-	{
-		struct FRMCAsyncData
-		{
-			int32 SectionIndex;
-		};
-		FRMCAsyncData* CallData = new FRMCAsyncData;
-
-		RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(ClearAllMeshSections, FRMCAsyncData, CallData, InRuntimeMeshComponent,
-		{
-			Mesh->ClearAllMeshSections();
-		});
-	}
-
-
-	/** Sets the tessellation triangles needed to correctly support tessellation on a section. */
-	static void SetSectionTessellationTriangles(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 SectionIndex,
-		const TArray<int32>& TessellationTriangles, bool bShouldMoveArray = false)
-	{
-		struct FRMCAsyncData
-		{
-			int32 SectionIndex;
-			TArray<int32> TessellationTriangles;
-		};
-		FRMCAsyncData* CallData = new FRMCAsyncData;
-		CallData->SectionIndex = SectionIndex;
-
-		if (bShouldMoveArray)
-		{
-			CallData->TessellationTriangles = MoveTemp(TessellationTriangles);
-		}
-		else
-		{
-			CallData->TessellationTriangles = TessellationTriangles;
-		}
-
-
-		RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(SetSectionTessellationTriangles, FRMCAsyncData, CallData, InRuntimeMeshComponent,
-		{
-			Mesh->SetSectionTessellationTriangles(Data->SectionIndex, Data->TessellationTriangles, true);
-		});
-	}
-
-
-	/** Sets the geometry for a collision only section */
-	static void SetMeshCollisionSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 CollisionSectionIndex,
-		const TArray<FVector>& Vertices, const TArray<int32>& Triangles)
-	{
-		struct FRMCAsyncData
-		{
-			int32 CollisionSectionIndex;
-			TArray<FVector> Vertices;
-			TArray<int32> Triangles;
-		};
-		FRMCAsyncData* CallData = new FRMCAsyncData;
-		CallData->CollisionSectionIndex = CollisionSectionIndex;
-		CallData->Vertices = Vertices;
-		CallData->Triangles = Triangles;
-
-		RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(SetMeshCollisionSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
-		{
-			Mesh->SetMeshCollisionSection(Data->CollisionSectionIndex, Data->Vertices, Data->Triangles);
-		});
-	}
-
-	/** Clears the geometry for a collision only section */
-	static void ClearMeshCollisionSection(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, int32 CollisionSectionIndex)
-	{
-		struct FRMCAsyncData
-		{
-			int32 CollisionSectionIndex;
-		};
-		FRMCAsyncData* CallData = new FRMCAsyncData;
-		CallData->CollisionSectionIndex = CollisionSectionIndex;
-
-		RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(ClearMeshCollisionSection, FRMCAsyncData, CallData, InRuntimeMeshComponent,
-		{
-			Mesh->ClearMeshCollisionSection(Data->CollisionSectionIndex);
-		});
-	}
-
-	/** Clears the geometry for ALL collision only sections */
-	static void ClearAllMeshCollisionSections(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent)
-	{
-		struct FRMCAsyncData
-		{
-			int32 CollisionSectionIndex;
-		};
-		FRMCAsyncData* CallData = new FRMCAsyncData;
-
-		RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(ClearAllMeshCollisionSections, FRMCAsyncData, CallData, InRuntimeMeshComponent,
-		{
-			Mesh->ClearAllMeshCollisionSections();
-		});
-	}
-
-
-	/** Add simple collision convex to this component */
-	static void AddCollisionConvexMesh(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, TArray<FVector> ConvexVerts)
-	{
-		struct FRMCAsyncData
-		{
-			TArray<FVector> ConvexVerts;
-		};
-		FRMCAsyncData* CallData = new FRMCAsyncData;
-		CallData->ConvexVerts = ConvexVerts;
-
-		RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(AddCollisionConvexMesh, FRMCAsyncData, CallData, InRuntimeMeshComponent,
-		{
-			Mesh->AddCollisionConvexMesh(Data->ConvexVerts);
-		});
-	}
-
-	/** Add simple collision convex to this component */
-	static void ClearCollisionConvexMeshes(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent)
-	{
-		struct FRMCAsyncData
-		{
-			int32 CollisionSectionIndex;
-		};
-		FRMCAsyncData* CallData = new FRMCAsyncData;
-
-		RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(ClearCollisionConvexMeshes, FRMCAsyncData, CallData, InRuntimeMeshComponent,
-		{
-			Mesh->ClearCollisionConvexMeshes();
-		});
-	}
-
-	/** Function to replace _all_ simple collision in one go */
-	static void SetCollisionConvexMeshes(TWeakObjectPtr<URuntimeMeshComponent> InRuntimeMeshComponent, const TArray< TArray<FVector> >& ConvexMeshes)
-	{
-		struct FRMCAsyncData
-		{
-			TArray<TArray<FVector>> ConvexMeshes;
-		};
-		FRMCAsyncData* CallData = new FRMCAsyncData;
-		CallData->ConvexMeshes = ConvexMeshes;
-
-		RUNTIMEMESHCOMPONENTASYNC_ENQUEUETASK(SetCollisionConvexMeshes, FRMCAsyncData, CallData, InRuntimeMeshComponent,
-		{
-			Mesh->SetCollisionConvexMeshes(Data->ConvexMeshes);
-		});
-	}
-};

+ 0 - 983
spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Public/RuntimeMeshBuilder.h

@@ -1,983 +0,0 @@
-// Copyright 2016 Chris Conway (Koderz). All Rights Reserved.
-
-#pragma once
-
-#include "RuntimeMeshCore.h"
-#include "RuntimeMeshGenericVertex.h"
-
-//////////////////////////////////////////////////////////////////////////
-//	This is a work in progress, it's functional, but could use some improvement
-//////////////////////////////////////////////////////////////////////////
-
-enum class ERuntimeMeshVerticesBuilderType : uint8
-{
-	Component,
-	Packed
-};
-
-
-class IRuntimeMeshVerticesBuilder
-{
-public:
-	IRuntimeMeshVerticesBuilder() { }
-	IRuntimeMeshVerticesBuilder(const IRuntimeMeshVerticesBuilder& Other) = delete;
-	IRuntimeMeshVerticesBuilder& operator=(const IRuntimeMeshVerticesBuilder& Other) = delete;
-	virtual ~IRuntimeMeshVerticesBuilder() { }
-
-	virtual ERuntimeMeshVerticesBuilderType GetBuilderType() const = 0;
-	virtual const FRuntimeMeshVertexTypeInfo* GetVertexType() const = 0;
-
-	virtual bool HasPositionComponent() const = 0;
-	virtual bool HasNormalComponent() const = 0;
-	virtual bool HasTangentComponent() const = 0;
-	virtual bool HasColorComponent() const = 0;
-	virtual bool HasUVComponent(int32 Index) const = 0;
-	virtual bool HasHighPrecisionNormals() const = 0;
-	virtual bool HasHighPrecisionUVs() const = 0;
-
-	virtual void SetPosition(const FVector& InPosition) = 0;
-	virtual void SetNormal(const FVector4& InNormal) = 0;
-	virtual void SetTangent(const FVector& InTangent) = 0;
-	virtual void SetColor(const FColor& InColor) = 0;
-	virtual void SetUV(int32 Index, const FVector2D& InUV) = 0;
-
-	virtual void SetPosition(int32 VertexIndex, const FVector& InPosition) = 0;
-	virtual void SetNormal(int32 VertexIndex, const FVector4& InNormal) = 0;
-	virtual void SetTangent(int32 VertexIndex, const FVector& InTangent) = 0;
-	virtual void SetColor(int32 VertexIndex, const FColor& InColor) = 0;
-	virtual void SetUV(int32 VertexIndex, int32 Index, const FVector2D& InUV) = 0;
-	
-	void SetTangents(const FVector& InTangentX, const FVector& InTangentY, const FVector& InTangentZ)
-	{
-		SetNormal(FVector4(InTangentZ, GetBasisDeterminantSign(InTangentX, InTangentY, InTangentZ)));
-		SetTangent(InTangentX);
-	}
-	void SetTangents(int32 VertexIndex, const FVector& InTangentX, const FVector& InTangentY, const FVector& InTangentZ)
-	{
-		Seek(VertexIndex);
-		SetNormal(FVector4(InTangentZ, GetBasisDeterminantSign(InTangentX, InTangentY, InTangentZ)));
-		SetTangent(InTangentX);
-	}
-
-	virtual FVector GetPosition() const = 0;
-	virtual FVector4 GetNormal() const = 0;
-	virtual FVector GetTangent() const = 0;
-	virtual FColor GetColor() const = 0;
-	virtual FVector2D GetUV(int32 Index) const = 0;
-
-	virtual FVector GetPosition(int32 VertexIndex) const = 0;
-	virtual FVector4 GetNormal(int32 VertexIndex) const = 0;
-	virtual FVector GetTangent(int32 VertexIndex) const = 0;
-	virtual FColor GetColor(int32 VertexIndex) const = 0;
-	virtual FVector2D GetUV(int32 VertexIndex, int32 Index) const = 0;
-
-	virtual int32 Length() const = 0;
-	virtual void Seek(int32 Position) const = 0;
-	void SeekEnd() const
-	{
-		Seek(Length() - 1);
-	}
-	virtual int32 MoveNext() const = 0;
-	virtual int32 MoveNextOrAdd() = 0;
-
-	virtual void Reset() = 0;
-
-	virtual IRuntimeMeshVerticesBuilder* Clone(bool bIncludeData = true) const = 0;
-
-	virtual bool WantsSeparatePositionBuffer() const
-	{
-		return false;
-	}
-};
-
-
-template<typename VertexType>
-class FRuntimeMeshPackedVerticesBuilder : public IRuntimeMeshVerticesBuilder
-{
-private:
-	TArray<VertexType>* Vertices;
-	TArray<FVector>* Positions;
-	int32 CurrentPosition;
-	bool bOwnsVertexArray;
-public:
-
-	FRuntimeMeshPackedVerticesBuilder(bool bWantsSeparatePositions = false)
-		: Vertices(new TArray<VertexType>())
-		, Positions(bWantsSeparatePositions? new TArray<FVector>() : nullptr)
-		, CurrentPosition(-1)
-		, bOwnsVertexArray(true)
-	{ }
-	FRuntimeMeshPackedVerticesBuilder(TArray<VertexType>* InVertices, TArray<FVector>* InPositions = nullptr)
-		: Vertices(InVertices)
-		, Positions(InPositions)
-		, CurrentPosition(-1)
-		, bOwnsVertexArray(false)
-	{ }
-	FRuntimeMeshPackedVerticesBuilder(const FRuntimeMeshPackedVerticesBuilder& Other) = delete;
-	FRuntimeMeshPackedVerticesBuilder& operator=(const FRuntimeMeshPackedVerticesBuilder& Other) = delete;
-	virtual ~FRuntimeMeshPackedVerticesBuilder() override
-	{
-		if (bOwnsVertexArray)
-		{
-			delete Vertices;
-
-			if (Positions)
-			{
-				delete Positions;
-			}
-		}
-	}
-
-
-	virtual ERuntimeMeshVerticesBuilderType GetBuilderType() const
-	{
-		return ERuntimeMeshVerticesBuilderType::Packed;
-	}
-	virtual const FRuntimeMeshVertexTypeInfo* GetVertexType() const
-	{
-		return &VertexType::TypeInfo;
-	}
-
-
-	virtual bool HasPositionComponent() const override { return Positions != nullptr || FRuntimeMeshVertexTraits<VertexType>::HasPosition; }
-	virtual bool HasNormalComponent() const override { return FRuntimeMeshVertexTraits<VertexType>::HasNormal; }
-	virtual bool HasTangentComponent() const override { return FRuntimeMeshVertexTraits<VertexType>::HasTangent; }
-	virtual bool HasColorComponent() const override { return FRuntimeMeshVertexTraits<VertexType>::HasColor; }
-	virtual bool HasUVComponent(int32 Index) const override
-	{
-		switch (Index)
-		{
-		case 0:
-			return FRuntimeMeshVertexTraits<VertexType>::HasUV0;
-		case 1:
-			return FRuntimeMeshVertexTraits<VertexType>::HasUV1;
-		case 2:
-			return FRuntimeMeshVertexTraits<VertexType>::HasUV2;
-		case 3:
-			return FRuntimeMeshVertexTraits<VertexType>::HasUV3;
-		case 4:
-			return FRuntimeMeshVertexTraits<VertexType>::HasUV4;
-		case 5:
-			return FRuntimeMeshVertexTraits<VertexType>::HasUV5;
-		case 6:
-			return FRuntimeMeshVertexTraits<VertexType>::HasUV6;
-		case 7:
-			return FRuntimeMeshVertexTraits<VertexType>::HasUV7;
-		}
-		return false;
-	}
-	virtual bool HasHighPrecisionNormals() const override { return FRuntimeMeshVertexTraits<VertexType>::HasHighPrecisionNormals; }
-	virtual bool HasHighPrecisionUVs() const override { return FRuntimeMeshVertexTraits<VertexType>::HasHighPrecisionUVs; }
-
-	virtual void SetPosition(const FVector& InPosition) override 
-	{ 
-		if (Positions)
-		{
-			(*Positions)[CurrentPosition] = InPosition;
-		}
-		else
-		{
-			SetPositionInternal<VertexType>((*Vertices)[CurrentPosition], InPosition);
-		}		
-	}
-	virtual void SetNormal(const FVector4& InNormal) override { SetNormalInternal<VertexType>((*Vertices)[CurrentPosition], InNormal); }
-	virtual void SetTangent(const FVector& InTangent) override { SetTangentInternal<VertexType>((*Vertices)[CurrentPosition], InTangent); }
-	virtual void SetColor(const FColor& InColor) override { SetColorInternal<VertexType>((*Vertices)[CurrentPosition], InColor); }
-	virtual void SetUV(int32 Index, const FVector2D& InUV)
-	{
-		switch (Index)
-		{
-		case 0:
-			SetUV0Internal<VertexType>((*Vertices)[CurrentPosition], InUV);
-			return;
-		case 1:
-			SetUV1Internal<VertexType>((*Vertices)[CurrentPosition], InUV);
-			return;
-		case 2:
-			SetUV2Internal<VertexType>((*Vertices)[CurrentPosition], InUV);
-			return;
-		case 3:
-			SetUV3Internal<VertexType>((*Vertices)[CurrentPosition], InUV);
-			return;
-		case 4:
-			SetUV4Internal<VertexType>((*Vertices)[CurrentPosition], InUV);
-			return;
-		case 5:
-			SetUV5Internal<VertexType>((*Vertices)[CurrentPosition], InUV);
-			return;
-		case 6:
-			SetUV6Internal<VertexType>((*Vertices)[CurrentPosition], InUV);
-			return;
-		case 7:
-			SetUV7Internal<VertexType>((*Vertices)[CurrentPosition], InUV);
-			return;
-		}
-	}
-
-
-	virtual void SetPosition(int32 VertexIndex, const FVector& InPosition) override
-	{
-		Seek(VertexIndex);
-		if (Positions)
-		{
-			(*Positions)[CurrentPosition] = InPosition;
-		}
-		else
-		{
-			SetPositionInternal<VertexType>((*Vertices)[CurrentPosition], InPosition);
-		}
-	}
-	virtual void SetNormal(int32 VertexIndex, const FVector4& InNormal) override { Seek(VertexIndex); SetNormalInternal<VertexType>((*Vertices)[CurrentPosition], InNormal); }
-	virtual void SetTangent(int32 VertexIndex, const FVector& InTangent) override { Seek(VertexIndex); SetTangentInternal<VertexType>((*Vertices)[CurrentPosition], InTangent); }
-	virtual void SetColor(int32 VertexIndex, const FColor& InColor) override { Seek(VertexIndex); SetColorInternal<VertexType>((*Vertices)[CurrentPosition], InColor); }
-	virtual void SetUV(int32 VertexIndex, int32 Index, const FVector2D& InUV)
-	{
-		Seek(VertexIndex);
-		switch (Index)
-		{
-		case 0:
-			SetUV0Internal<VertexType>((*Vertices)[CurrentPosition], InUV);
-			return;
-		case 1:
-			SetUV1Internal<VertexType>((*Vertices)[CurrentPosition], InUV);
-			return;
-		case 2:
-			SetUV2Internal<VertexType>((*Vertices)[CurrentPosition], InUV);
-			return;
-		case 3:
-			SetUV3Internal<VertexType>((*Vertices)[CurrentPosition], InUV);
-			return;
-		case 4:
-			SetUV4Internal<VertexType>((*Vertices)[CurrentPosition], InUV);
-			return;
-		case 5:
-			SetUV5Internal<VertexType>((*Vertices)[CurrentPosition], InUV);
-			return;
-		case 6:
-			SetUV6Internal<VertexType>((*Vertices)[CurrentPosition], InUV);
-			return;
-		case 7:
-			SetUV7Internal<VertexType>((*Vertices)[CurrentPosition], InUV);
-			return;
-		}
-	}
-
-
-	virtual FVector GetPosition() const override 
-	{ 
-		if (Positions)
-		{
-			return (*Positions)[CurrentPosition];
-		}
-		else
-		{
-			return GetPositionInternal<VertexType>((*Vertices)[CurrentPosition]);
-		}
-	}
-	virtual FVector4 GetNormal() const override { return GetNormalInternal<VertexType>((*Vertices)[CurrentPosition]); }
-	virtual FVector GetTangent() const override { return GetTangentInternal<VertexType>((*Vertices)[CurrentPosition]); }
-	virtual FColor GetColor() const override { return GetColorInternal<VertexType>((*Vertices)[CurrentPosition]); }
-	virtual FVector2D GetUV(int32 Index) const override
-	{
-		switch (Index)
-		{
-		case 0:
-			return GetUV0Internal<VertexType>((*Vertices)[CurrentPosition]);
-		case 1:
-			return GetUV1Internal<VertexType>((*Vertices)[CurrentPosition]);
-		case 2:
-			return GetUV2Internal<VertexType>((*Vertices)[CurrentPosition]);
-		case 3:
-			return GetUV3Internal<VertexType>((*Vertices)[CurrentPosition]);
-		case 4:
-			return GetUV4Internal<VertexType>((*Vertices)[CurrentPosition]);
-		case 5:
-			return GetUV5Internal<VertexType>((*Vertices)[CurrentPosition]);
-		case 6:
-			return GetUV6Internal<VertexType>((*Vertices)[CurrentPosition]);
-		case 7:
-			return GetUV7Internal<VertexType>((*Vertices)[CurrentPosition]);
-		}
-		return FVector2D::ZeroVector;
-	}
-
-
-	virtual FVector GetPosition(int32 VertexIndex) const override
-	{
-		Seek(VertexIndex);
-		if (Positions)
-		{
-			return (*Positions)[CurrentPosition];
-		}
-		else
-		{
-			return GetPositionInternal<VertexType>((*Vertices)[CurrentPosition]);
-		}
-	}
-	virtual FVector4 GetNormal(int32 VertexIndex) const override { Seek(VertexIndex); return GetNormalInternal<VertexType>((*Vertices)[CurrentPosition]); }
-	virtual FVector GetTangent(int32 VertexIndex) const override { Seek(VertexIndex); return GetTangentInternal<VertexType>((*Vertices)[CurrentPosition]); }
-	virtual FColor GetColor(int32 VertexIndex) const override { Seek(VertexIndex); return GetColorInternal<VertexType>((*Vertices)[CurrentPosition]); }
-	virtual FVector2D GetUV(int32 VertexIndex, int32 Index) const override
-	{
-		Seek(VertexIndex);
-		switch (Index)
-		{
-		case 0:
-			return GetUV0Internal<VertexType>((*Vertices)[CurrentPosition]);
-		case 1:
-			return GetUV1Internal<VertexType>((*Vertices)[CurrentPosition]);
-		case 2:
-			return GetUV2Internal<VertexType>((*Vertices)[CurrentPosition]);
-		case 3:
-			return GetUV3Internal<VertexType>((*Vertices)[CurrentPosition]);
-		case 4:
-			return GetUV4Internal<VertexType>((*Vertices)[CurrentPosition]);
-		case 5:
-			return GetUV5Internal<VertexType>((*Vertices)[CurrentPosition]);
-		case 6:
-			return GetUV6Internal<VertexType>((*Vertices)[CurrentPosition]);
-		case 7:
-			return GetUV7Internal<VertexType>((*Vertices)[CurrentPosition]);
-		}
-		return FVector2D::ZeroVector;
-	}
-
-	virtual int32 Length() const override { return Vertices->Num(); }
-	virtual void Seek(int32 Position) const override 
-	{ 
-		const_cast<FRuntimeMeshPackedVerticesBuilder<VertexType>*>(this)->CurrentPosition = Position;
-	}
-	virtual int32 MoveNext() const override
-	{
-		return ++const_cast<FRuntimeMeshPackedVerticesBuilder<VertexType>*>(this)->CurrentPosition;
-	}
-	virtual int32 MoveNextOrAdd() override
-	{
-		CurrentPosition++;
-		if (CurrentPosition >= Vertices->Num())
-		{
-			Vertices->SetNumZeroed(CurrentPosition + 1, false);
-			if (Positions)
-			{
-				Positions->SetNumZeroed(CurrentPosition + 1, false);
-			}
-		}
-		return CurrentPosition;
-	}
-
-	virtual void Reset() override
-	{
-		Vertices->Reset();
-		if (Positions)
-		{
-			Positions->Reset();
-		}
-		CurrentPosition = -1;
-	}
-
-	virtual IRuntimeMeshVerticesBuilder* Clone(bool bIncludeData = true) const override
-	{
-		FRuntimeMeshPackedVerticesBuilder<VertexType>* NewBuilder = new FRuntimeMeshPackedVerticesBuilder(Positions != nullptr);
-
-		if (bIncludeData)
-		{
-			*NewBuilder->Vertices = *Vertices;
-			*NewBuilder->Positions = *Positions;
-			NewBuilder->Seek(0);
-		}
-
-		return NewBuilder;
-	}
-
-	TArray<VertexType>* GetVertices()
-	{
-		return Vertices;
-	}
-
-	TArray<FVector>* GetPositions()
-	{
-		return Positions;
-	}
-
-
-	virtual bool WantsSeparatePositionBuffer() const
-	{
-		return Positions != nullptr;
-	}
-
-private:
-	template<typename Type>
-	FORCEINLINE static typename TEnableIf<FRuntimeMeshVertexTraits<Type>::HasPosition>::Type SetPositionInternal(Type& Vertex, const FVector& Position)
-	{
-		Vertex.Position = Position;
-	}
-	template<typename Type>
-	FORCEINLINE static typename TEnableIf<!FRuntimeMeshVertexTraits<Type>::HasPosition>::Type SetPositionInternal(Type& Vertex, const FVector& Position)
-	{
-
-	}	
-	template<typename Type>
-	FORCEINLINE static typename TEnableIf<FRuntimeMeshVertexTraits<Type>::HasPosition, FVector>::Type GetPositionInternal(const Type& Vertex)
-	{
-		return Vertex.Position;
-	}
-	template<typename Type>
-	FORCEINLINE static typename TEnableIf<!FRuntimeMeshVertexTraits<Type>::HasPosition, FVector>::Type GetPositionInternal(const Type& Vertex)
-	{
-		return FVector::ZeroVector;
-	}
-
-
-	template<typename Type>
-	FORCEINLINE static typename TEnableIf<FRuntimeMeshVertexTraits<Type>::HasNormal>::Type SetNormalInternal(Type& Vertex, const FVector4& Normal)
-	{
-		Vertex.Normal = Normal;
-	}
-	template<typename Type>
-	FORCEINLINE static typename TEnableIf<!FRuntimeMeshVertexTraits<Type>::HasNormal>::Type SetNormalInternal(Type& Vertex, const FVector4& Normal)
-	{
-
-	}
-	template<typename Type>
-	FORCEINLINE static typename TEnableIf<FRuntimeMeshVertexTraits<Type>::HasNormal, FVector4>::Type GetNormalInternal(const Type& Vertex)
-	{
-		return Vertex.Normal;
-	}
-	template<typename Type>
-	FORCEINLINE static typename TEnableIf<!FRuntimeMeshVertexTraits<Type>::HasNormal, FVector4>::Type GetNormalInternal(const Type& Vertex)
-	{
-		return FVector::ZeroVector;
-	}
-
-
-	template<typename Type>
-	FORCEINLINE static typename TEnableIf<FRuntimeMeshVertexTraits<Type>::HasTangent>::Type SetTangentInternal(Type& Vertex, const FVector4& Tangent)
-	{
-		Vertex.Tangent = Tangent;
-	}
-	template<typename Type>
-	FORCEINLINE static typename TEnableIf<!FRuntimeMeshVertexTraits<Type>::HasTangent>::Type SetTangentInternal(Type& Vertex, const FVector4& Tangent)
-	{
-
-	}
-	template<typename Type>
-	FORCEINLINE static typename TEnableIf<FRuntimeMeshVertexTraits<Type>::HasTangent, FVector4>::Type GetTangentInternal(const Type& Vertex)
-	{
-		return Vertex.Tangent;
-	}
-	template<typename Type>
-	FORCEINLINE static typename TEnableIf<!FRuntimeMeshVertexTraits<Type>::HasTangent, FVector4>::Type GetTangentInternal(const Type& Vertex)
-	{
-		return FVector::ZeroVector;
-	}
-
-
-	template<typename Type>
-	FORCEINLINE static typename TEnableIf<FRuntimeMeshVertexTraits<Type>::HasColor>::Type SetColorInternal(Type& Vertex, const FColor& Color)
-	{
-		Vertex.Color = Color;
-	}
-	template<typename Type>
-	FORCEINLINE static typename TEnableIf<!FRuntimeMeshVertexTraits<Type>::HasColor>::Type SetColorInternal(Type& Vertex, const FColor& Color)
-	{
-
-	}
-	template<typename Type>
-	FORCEINLINE static typename TEnableIf<FRuntimeMeshVertexTraits<Type>::HasColor, FColor>::Type GetColorInternal(const Type& Vertex)
-	{
-		return Vertex.Color;
-	}
-	template<typename Type>
-	FORCEINLINE static typename TEnableIf<!FRuntimeMeshVertexTraits<Type>::HasColor, FColor>::Type GetColorInternal(const Type& Vertex)
-	{
-		return FColor::Transparent;
-	}
-
-
-
-#define CreateUVChannelGetSetPair(Index)																											\
-	template<typename Type>																															\
-	FORCEINLINE static typename TEnableIf<FRuntimeMeshVertexTraits<Type>::HasUV##Index>::Type SetUV##Index##Internal(Type& Vertex, const FVector2D& UV##Index)			\
-	{																																				\
-		Vertex.UV##Index = UV##Index;																												\
-	}																																				\
-	template<typename Type>																															\
-	FORCEINLINE static typename TEnableIf<!FRuntimeMeshVertexTraits<Type>::HasUV##Index>::Type SetUV##Index##Internal(Type& Vertex, const FVector2D& UV##Index)			\
-	{																																				\
-	}																																				\
-	template<typename Type>																															\
-	FORCEINLINE static typename TEnableIf<FRuntimeMeshVertexTraits<Type>::HasUV##Index, FVector2D>::Type GetUV##Index##Internal(const Type& Vertex)						\
-	{																																				\
-		return Vertex.UV##Index;																													\
-	}																																				\
-	template<typename Type>																															\
-	FORCEINLINE static typename TEnableIf<!FRuntimeMeshVertexTraits<Type>::HasUV##Index, FVector2D>::Type GetUV##Index##Internal(const Type& Vertex)					\
-	{																																				\
-		return FVector2D::ZeroVector;																												\
-	}																																				
-
-
-CreateUVChannelGetSetPair(0);
-CreateUVChannelGetSetPair(1);
-CreateUVChannelGetSetPair(2);
-CreateUVChannelGetSetPair(3);
-CreateUVChannelGetSetPair(4);
-CreateUVChannelGetSetPair(5);
-CreateUVChannelGetSetPair(6);
-CreateUVChannelGetSetPair(7);
-
-
-#undef CreateUVChannelGetSetPair
-};
-
-class RUNTIMEMESHCOMPONENT_API FRuntimeMeshComponentVerticesBuilder : public IRuntimeMeshVerticesBuilder
-{
-private:
-	TArray<FVector>* Positions;
-	TArray<FVector>* Normals;
-	TArray<FRuntimeMeshTangent>* Tangents;
-	TArray<FColor>* Colors;
-	TArray<FVector2D>* UV0s;
-	TArray<FVector2D>* UV1s;
-	int32 CurrentPosition;
-	bool bOwnsBuffers;
-public:
-
-	FRuntimeMeshComponentVerticesBuilder(bool bInWantsNormal, bool bInWantsTangent, bool bInWantsColor, bool bInWantsUV0, bool bInWantsUV1)
-		: Positions(new TArray<FVector>())
-		, Normals(bInWantsNormal ? new TArray<FVector>() : nullptr)
-		, Tangents(bInWantsTangent ? new TArray<FRuntimeMeshTangent>() : nullptr)
-		, Colors(bInWantsColor ? new TArray<FColor>() : nullptr)
-		, UV0s(bInWantsUV0 ? new TArray<FVector2D>() : nullptr)
-		, UV1s(bInWantsUV1 ? new TArray<FVector2D>() : nullptr)
-		, CurrentPosition(-1)
-		, bOwnsBuffers(true)		
-	{ }
-	FRuntimeMeshComponentVerticesBuilder(TArray<FVector>* InPositions, TArray<FVector>* InNormals, TArray<FRuntimeMeshTangent>* InTangents,
-		TArray<FColor>* InColors, TArray<FVector2D>* InUV0s, TArray<FVector2D>* InUV1s = nullptr)
-		: Positions(InPositions)
-		, Normals(InNormals)
-		, Tangents(InTangents)
-		, Colors(InColors)
-		, UV0s(InUV0s)
-		, UV1s(InUV1s)
-		, CurrentPosition(-1)
-		, bOwnsBuffers(false)
-	{ }
-	FRuntimeMeshComponentVerticesBuilder(const FRuntimeMeshComponentVerticesBuilder& Other) = delete;
-	FRuntimeMeshComponentVerticesBuilder& operator=(const FRuntimeMeshComponentVerticesBuilder& Other) = delete;
-	virtual ~FRuntimeMeshComponentVerticesBuilder() override
-	{
-		if (bOwnsBuffers)
-		{			
-			if (Positions) delete Positions;
-			if (Normals) delete Normals;
-			if (Tangents) delete Tangents;
-			if (Colors) delete Colors;
-			if (UV0s) delete UV0s;
-			if (UV1s) delete UV1s;
-		}
-	}
-
-
-	virtual ERuntimeMeshVerticesBuilderType GetBuilderType() const { return ERuntimeMeshVerticesBuilderType::Packed; }
-	virtual const FRuntimeMeshVertexTypeInfo* GetVertexType() const;
-
-
-	virtual bool HasPositionComponent() const override { return Positions != nullptr; }
-	virtual bool HasNormalComponent() const override { return Normals != nullptr; }
-	virtual bool HasTangentComponent() const override { return Tangents != nullptr; }
-	virtual bool HasColorComponent() const override { return Colors != nullptr; }
-	virtual bool HasUVComponent(int32 Index) const override
-	{
-		switch (Index)
-		{
-		case 0:
-			return UV0s != nullptr;
-		case 1:
-			return UV1s != nullptr;
-		default:
-			return false;
-		}
-	}
-	virtual bool HasHighPrecisionNormals() const override { return false; }
-	virtual bool HasHighPrecisionUVs() const override { return true; }
-
-	virtual void SetPosition(const FVector& InPosition) override 
-	{
-		if (CurrentPosition >= Positions->Num())
-		{
-			Positions->SetNumZeroed(CurrentPosition + 1, false);
-		}
-		(*Positions)[CurrentPosition] = InPosition;
-	}
-	virtual void SetNormal(const FVector4& InNormal) override
-	{
-		if (Normals)
-		{
-			if (CurrentPosition >= Normals->Num())
-			{
-				Normals->SetNumZeroed(CurrentPosition + 1, false);
-			}
-			(*Normals)[CurrentPosition] = InNormal;
-			(*Tangents)[CurrentPosition].bFlipTangentY = InNormal.W < 0.0f;
-		}
-	}
-	virtual void SetTangent(const FVector& InTangent) override
-	{
-		if (Tangents)
-		{
-			if (CurrentPosition >= Tangents->Num())
-			{
-				Tangents->SetNumZeroed(CurrentPosition + 1, false);
-			}
-			(*Tangents)[CurrentPosition].TangentX = InTangent;
-		}
-	}
-	virtual void SetColor(const FColor& InColor) override
-	{
-		if (Colors)
-		{
-			if (CurrentPosition >= Colors->Num())
-			{
-				Colors->SetNumZeroed(CurrentPosition + 1, false);
-			}
-			(*Colors)[CurrentPosition] = InColor;
-		}
-	}
-	virtual void SetUV(int32 Index, const FVector2D& InUV)
-	{
-		switch (Index)
-		{
-		case 0:
-		{
-			if (UV0s)
-			{
-				if (CurrentPosition >= UV0s->Num())
-				{
-					UV0s->SetNumZeroed(CurrentPosition + 1, false);
-				}
-				(*UV0s)[CurrentPosition] = InUV;
-			}
-		}
-		case 1:
-		{
-			if (UV1s)
-			{
-				if (CurrentPosition >= UV1s->Num())
-				{
-					UV1s->SetNumZeroed(CurrentPosition + 1, false);
-				}
-				(*UV1s)[CurrentPosition] = InUV;
-			}
-		}
-		default:
-			return;
-		}
-	}
-
-	virtual void SetPosition(int32 VertexIndex, const FVector& InPosition) override
-	{
-		Seek(VertexIndex);
-		if (CurrentPosition >= Positions->Num())
-		{
-			Positions->SetNumZeroed(CurrentPosition + 1, false);
-		}
-		(*Positions)[CurrentPosition] = InPosition;
-	}
-	virtual void SetNormal(int32 VertexIndex, const FVector4& InNormal) override
-	{
-		Seek(VertexIndex);
-		if (Normals)
-		{
-			if (CurrentPosition >= Normals->Num())
-			{
-				Normals->SetNumZeroed(CurrentPosition + 1, false);
-			}
-			(*Normals)[CurrentPosition] = InNormal;
-			(*Tangents)[CurrentPosition].bFlipTangentY = InNormal.W < 0.0f;
-		}
-	}
-	virtual void SetTangent(int32 VertexIndex, const FVector& InTangent) override
-	{
-		Seek(VertexIndex);
-		if (Tangents)
-		{
-			if (CurrentPosition >= Tangents->Num())
-			{
-				Tangents->SetNumZeroed(CurrentPosition + 1, false);
-			}
-			(*Tangents)[CurrentPosition].TangentX = InTangent;
-		}
-	}
-	virtual void SetColor(int32 VertexIndex, const FColor& InColor) override
-	{
-		Seek(VertexIndex);
-		if (Colors)
-		{
-			if (CurrentPosition >= Colors->Num())
-			{
-				Colors->SetNumZeroed(CurrentPosition + 1, false);
-			}
-			(*Colors)[CurrentPosition] = InColor;
-		}
-	}
-	virtual void SetUV(int32 VertexIndex, int32 Index, const FVector2D& InUV)
-	{
-		Seek(VertexIndex);
-		switch (Index)
-		{
-		case 0:
-		{
-			if (UV0s)
-			{
-				if (CurrentPosition >= UV0s->Num())
-				{
-					UV0s->SetNumZeroed(CurrentPosition + 1, false);
-				}
-				(*UV0s)[CurrentPosition] = InUV;
-			}
-		}
-		case 1:
-		{
-			if (UV1s)
-			{
-				if (CurrentPosition >= UV1s->Num())
-				{
-					UV1s->SetNumZeroed(CurrentPosition + 1, false);
-				}
-				(*UV1s)[CurrentPosition] = InUV;
-			}
-		}
-		default:
-			return;
-		}
-	}
-
-	virtual FVector GetPosition() const override
-	{
-		check(Positions && Positions->Num() > CurrentPosition);
-		return (*Positions)[CurrentPosition];
-	}
-	virtual FVector4 GetNormal() const override
-	{
-		check(Normals && Normals->Num() > CurrentPosition);
-		float W = (Tangents && Tangents->Num() > CurrentPosition) ? ((*Tangents)[CurrentPosition].bFlipTangentY ? -1.0f : 1.0f) : 1.0f;
-		return FVector4((*Normals)[CurrentPosition], W);
-	}
-	virtual FVector GetTangent() const override
-	{
-		check(Tangents && Tangents->Num() > CurrentPosition);
-		return (*Tangents)[CurrentPosition].TangentX;
-	}
-	virtual FColor GetColor() const override
-	{
-		check(Colors && Colors->Num() > CurrentPosition);
-		return (*Colors)[CurrentPosition];
-	}
-	virtual FVector2D GetUV(int32 Index) const override
-	{
-		switch (Index)
-		{
-		case 0:
-			check(UV0s && UV0s->Num() > CurrentPosition);
-			return (*UV0s)[CurrentPosition];
-		case 1:
-			check(UV1s && UV1s->Num() > CurrentPosition);
-			return (*UV1s)[CurrentPosition];
-		}
-		return FVector2D::ZeroVector;
-	}
-
-	virtual FVector GetPosition(int32 VertexIndex) const override
-	{
-		Seek(VertexIndex);
-		check(Positions && Positions->Num() > CurrentPosition);
-		return (*Positions)[CurrentPosition];
-	}
-	virtual FVector4 GetNormal(int32 VertexIndex) const override
-	{
-		Seek(VertexIndex);
-		check(Normals && Normals->Num() > CurrentPosition);
-		float W = (Tangents && Tangents->Num() > CurrentPosition) ? ((*Tangents)[CurrentPosition].bFlipTangentY ? -1.0f : 1.0f) : 1.0f;
-		return FVector4((*Normals)[CurrentPosition], W);
-	}
-	virtual FVector GetTangent(int32 VertexIndex) const override
-	{
-		Seek(VertexIndex);
-		check(Tangents && Tangents->Num() > CurrentPosition);
-		return (*Tangents)[CurrentPosition].TangentX;
-	}
-	virtual FColor GetColor(int32 VertexIndex) const override
-	{
-		Seek(VertexIndex);
-		check(Colors && Colors->Num() > CurrentPosition);
-		return (*Colors)[CurrentPosition];
-	}
-	virtual FVector2D GetUV(int32 VertexIndex, int32 Index) const override
-	{
-		Seek(VertexIndex);
-		switch (Index)
-		{
-		case 0:
-			check(UV0s && UV0s->Num() > CurrentPosition);
-			return (*UV0s)[CurrentPosition];
-		case 1:
-			check(UV1s && UV1s->Num() > CurrentPosition);
-			return (*UV1s)[CurrentPosition];
-		}
-		return FVector2D::ZeroVector;
-	}
-
-
-	virtual int32 Length() const override { return Positions->Num(); }
-	virtual void Seek(int32 Position) const override
-	{
-		const_cast<FRuntimeMeshComponentVerticesBuilder*>(this)->CurrentPosition = Position;
-	}
-	virtual int32 MoveNext() const override
-	{
-		return ++const_cast<FRuntimeMeshComponentVerticesBuilder*>(this)->CurrentPosition;
-	}
-	virtual int32 MoveNextOrAdd() override
-	{
-		return ++CurrentPosition;
-	}
-
-	
-	TArray<FVector>* GetPositions() const { return Positions; }
-	TArray<FVector>* GetNormals() const { return Normals; }
-	TArray<FRuntimeMeshTangent>* GetTangents() const { return Tangents; }
-	TArray<FColor>* GetColors() const { return Colors; }
-	TArray<FVector2D>* GetUV0s() const { return UV0s; }
-	TArray<FVector2D>* GetUV1s() const { return UV1s; }
-
-	virtual void Reset() override
-	{
-		Positions->Reset();
-		Normals->Reset();
-		Tangents->Reset();
-		Colors->Reset();
-		UV0s->Reset();
-		UV1s->Reset();
-		CurrentPosition = -1;
-	}
-
-	virtual IRuntimeMeshVerticesBuilder* Clone(bool bIncludeData = true) const override
-	{
-		FRuntimeMeshComponentVerticesBuilder* NewBuilder = new FRuntimeMeshComponentVerticesBuilder(Normals != nullptr, Tangents != nullptr, Colors != nullptr, UV0s != nullptr, UV1s != nullptr);
-
-		if (bIncludeData)
-		{
-			*NewBuilder->Positions = *Positions;
-			*NewBuilder->Normals = *Normals;
-			*NewBuilder->Tangents = *Tangents;
-			*NewBuilder->Colors = *Colors;
-			*NewBuilder->UV0s = *UV0s;
-			*NewBuilder->UV1s = *UV1s;
-			NewBuilder->Seek(0);
-		}
-
-		return NewBuilder;
-	}
-};
-
-
-
-class FRuntimeMeshIndicesBuilder
-{
-	bool bOwnsIndexArray;
-	TArray<int32>* Indices;
-	int32 CurrentPosition;
-public:
-
-	FRuntimeMeshIndicesBuilder()
-		: bOwnsIndexArray(true), Indices(new TArray<int32>()), CurrentPosition(0)
-	{ }
-	FRuntimeMeshIndicesBuilder(TArray<int32>* InVertices)
-		: bOwnsIndexArray(false), Indices(InVertices), CurrentPosition(0)
-	{ }
-	FRuntimeMeshIndicesBuilder(const FRuntimeMeshIndicesBuilder& Other) = delete;
-	FRuntimeMeshIndicesBuilder& operator=(const FRuntimeMeshIndicesBuilder& Other) = delete;
-	virtual ~FRuntimeMeshIndicesBuilder()
-	{
-		if (bOwnsIndexArray)
-		{
-			delete Indices;
-		}
-	}
-
-	virtual ERuntimeMeshVerticesBuilderType GetBuilderType() const { return ERuntimeMeshVerticesBuilderType::Component; }
-
-
-	void AddTriangle(int32 Index0, int32 Index1, int32 Index2)
-	{
-		if ((CurrentPosition + 3) >= Indices->Num())
-		{
-			Indices->SetNum(CurrentPosition + 3);
-		}
-
-		(*Indices)[CurrentPosition++] = Index0;
-		(*Indices)[CurrentPosition++] = Index1;
-		(*Indices)[CurrentPosition++] = Index2;
-	}
-
-	void AddIndex(int32 Index)
-	{
-		if ((CurrentPosition + 1) >= Indices->Num())
-		{
-			Indices->SetNum(CurrentPosition + 1);
-		}
-		(*Indices)[CurrentPosition++] = Index;
-	}
-	int32 ReadOne() const
-	{
-		return (*Indices)[const_cast<FRuntimeMeshIndicesBuilder*>(this)->CurrentPosition++];
-	}
-
-	int32 GetIndex(int32 Position) const
-	{
-		const_cast<FRuntimeMeshIndicesBuilder*>(this)->CurrentPosition = Position;
-		return (*Indices)[CurrentPosition];
-	}
-
-	int32 TriangleLength() const { return Length() / 3; }
-	int32 Length() const { return Indices->Num(); }
-
-	bool HasRemaining() const { return CurrentPosition < Indices->Num(); }
-	
-	void Seek(int32 Position) const
-	{
-		const_cast<FRuntimeMeshIndicesBuilder*>(this)->CurrentPosition = Position;
-	}
-	void SeekEnd() const
-	{
-		Seek(Length());
-	}
-	void Reset(int32 NewSize = 0)
-	{
-		Indices->Reset(NewSize);
-		CurrentPosition = 0;
-	}
-	void SetNum(int32 NewSize)
-	{
-		Indices->SetNum(NewSize);
-	}
-	
-	FRuntimeMeshIndicesBuilder* Clone(bool bIncludeData = true) const
-	{
-		FRuntimeMeshIndicesBuilder* NewBuilder = new FRuntimeMeshIndicesBuilder();
-
-		if (bIncludeData)
-		{
-			*NewBuilder->Indices = *Indices;
-		}
-		
-		return NewBuilder;
-	}
-
-	TArray<int32>* GetIndices()
-	{
-		return Indices;
-	}
-};

+ 0 - 1308
spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Public/RuntimeMeshComponent.h

@@ -1,1308 +0,0 @@
-// Copyright 2016 Chris Conway (Koderz). All Rights Reserved.
-
-#pragma once
-
-#include "Components/MeshComponent.h"
-#include "RuntimeMeshCore.h"
-#include "RuntimeMeshSection.h"
-#include "RuntimeMeshGenericVertex.h"
-#include "RuntimeMeshBuilder.h"
-#include "PhysicsEngine/ConvexElem.h"
-#include "RuntimeMeshComponent.generated.h"
-
-// This set of macros is only meant for argument validation as it will return out of whatever scope.
-#if WITH_EDITOR
-#define RMC_CHECKINGAME_LOGINEDITOR(Condition, Message, RetVal) \
-	{ if (!(Condition)) \
-	{ \
-		Log(TEXT(Message), true); \
-		return RetVal; \
-	} }
-#else
-#define RMC_CHECKINGAME_LOGINEDITOR(Condition, Message, RetVal) \
-	check(Condition && Message);
-#endif
-
-
-#define RMC_VALIDATE_CREATIONPARAMETERS(SectionIndex, Vertices, Triangles, RetVal) \
-		RMC_CHECKINGAME_LOGINEDITOR((SectionIndex >= 0), "SectionIndex cannot be negative.", RetVal); \
-		RMC_CHECKINGAME_LOGINEDITOR((Vertices.Num() > 0), "Vertices length must not be 0.", RetVal); \
-		RMC_CHECKINGAME_LOGINEDITOR((Triangles.Num() > 0), "Triangles length must not be 0", RetVal);
-
-#define RMC_VALIDATE_CREATIONPARAMETERS_DUALBUFFER(SectionIndex, Vertices, Triangles, Positions, RetVal) \
-		RMC_VALIDATE_CREATIONPARAMETERS(SectionIndex, Vertices, Triangles, RetVal) \
-		RMC_CHECKINGAME_LOGINEDITOR((Positions.Num() == Vertices.Num()), "Positions must be the same length as Vertices", RetVal);
-
-#define RMC_VALIDATE_BOUNDINGBOX(BoundingBox, RetVal) \
-		RMC_CHECKINGAME_LOGINEDITOR(BoundingBox.IsValid, "BoundingBox must be valid.", RetVal);
-
-#define RMC_VALIDATE_UPDATEPARAMETERS(SectionIndex, RetVal) \
-		RMC_CHECKINGAME_LOGINEDITOR((SectionIndex >= 0), "SectionIndex cannot be negative.", RetVal); \
-		RMC_CHECKINGAME_LOGINEDITOR((SectionIndex < MeshSections.Num() && MeshSections[SectionIndex].IsValid()), "Invalid SectionIndex.", RetVal);
-
-#define RMC_VALIDATE_UPDATEPARAMETERS_INTERNALSECTION(SectionIndex, RetVal) \
-		RMC_VALIDATE_UPDATEPARAMETERS(SectionIndex, RetVal) \
-		RMC_CHECKINGAME_LOGINEDITOR((MeshSections[SectionIndex]->bIsLegacySectionType), "Section is not of legacy type.", RetVal);
-		
-#define RMC_VALIDATE_UPDATEPARAMETERS_DUALBUFFER(SectionIndex, RetVal) \
-		RMC_VALIDATE_UPDATEPARAMETERS(SectionIndex, RetVal) \
-		RMC_CHECKINGAME_LOGINEDITOR((MeshSections[SectionIndex]->IsDualBufferSection()), "Section is not dual buffer.", RetVal);
-
-
-
-/* 
-*	This tick function is used to drive the collision cooker. It is enabled for one frame when we need to update collision. 
-*	This keeps from cooking on each individual create/update section as the original PMC did
-*/
-USTRUCT()
-struct RUNTIMEMESHCOMPONENT_API FRuntimeMeshComponentPrePhysicsTickFunction : public FTickFunction
-{
-	GENERATED_USTRUCT_BODY()
-
-	/* Target RMC to tick */
-	class URuntimeMeshComponent* Target;
-
-	virtual void ExecuteTick(float DeltaTime, ELevelTick TickType, ENamedThreads::Type CurrentThread,
-		const FGraphEventRef& MyCompletionGraphEvent) override;
-
-	virtual FString DiagnosticMessage() override;
-};
-
-template<>
-#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION <= 15
-struct TStructOpsTypeTraits<FRuntimeMeshComponentPrePhysicsTickFunction> : public TStructOpsTypeTraitsBase
-#else
-struct TStructOpsTypeTraits<FRuntimeMeshComponentPrePhysicsTickFunction> : public TStructOpsTypeTraitsBase2<FRuntimeMeshComponentPrePhysicsTickFunction>
-#endif
-{
-	enum
-	{
-		WithCopy = false
-	};
-};
-
-/**
-*	Component that allows you to specify custom triangle mesh geometry for rendering and collision.
-*/
-UCLASS(HideCategories = (Object, LOD), Meta = (BlueprintSpawnableComponent))
-class RUNTIMEMESHCOMPONENT_API URuntimeMeshComponent : public UMeshComponent, public IInterface_CollisionDataProvider
-{
-	GENERATED_BODY()
-
-private:
-	
-	/* Creates an mesh section of a specified type at the specified index. */
-	template<typename SectionType>
-	TSharedPtr<SectionType> CreateOrResetSection(int32 SectionIndex, bool bWantsSeparatePositionBuffer, bool bInIsLegacySectionType = false)
-	{
-		// Ensure sections array is long enough
-		if (SectionIndex >= MeshSections.Num())
-		{
-			MeshSections.SetNum(SectionIndex + 1, false);
-		}
-
-		// Create new section
-		TSharedPtr<SectionType> NewSection = MakeShareable(new SectionType(bWantsSeparatePositionBuffer));
-		NewSection->bIsLegacySectionType = bInIsLegacySectionType;
-
-		// Store section at index
-		MeshSections[SectionIndex] = NewSection;
-
-		return NewSection;
-	}
-		
-	/* Creates a mesh section of an internal type meant for the generic vertex and the old PMC style API */
-	TSharedPtr<FRuntimeMeshSectionInterface> CreateOrResetSectionLegacyType(int32 SectionIndex, int32 NumUVChannels);
-
-	/* Gets the material for a section or the default material if one's not provided. */
-	UMaterialInterface* GetSectionMaterial(int32 Index)
-	{
-		auto Material = GetMaterial(Index);
-		return Material ? Material : UMaterial::GetDefaultMaterial(MD_Surface);
-	}
-
-
-	/* Finishes creating a section, including entering it for batch updating, or updating the RT directly */
-	void CreateSectionInternal(int32 SectionIndex, ESectionUpdateFlags UpdateFlags);
-
-	/* Finishes updating a section, including entering it for batch updating, or updating the RT directly */
-	void UpdateSectionInternal(int32 SectionIndex, bool bHadVertexPositionsUpdate, bool bHadVertexUpdates, bool bHadIndexUpdates, bool bNeedsBoundsUpdate, ESectionUpdateFlags UpdateFlags);
-
-	/* Finishes updating a sections positions (Only used if section is dual vertex buffer), including entering it for batch updating, or updating the RT directly */
-	void UpdateSectionVertexPositionsInternal(int32 SectionIndex, bool bNeedsBoundsUpdate);
-
-	/* Finishes updating a sections properties, like visible/casts shadow, a*/
-	void UpdateSectionPropertiesInternal(int32 SectionIndex, bool bUpdateRequiresProxyRecreateIfStatic);
-	
-	/* Internal log helper for the templates to be able to use the internal logger */
-	static void Log(FString Text, bool bIsError = false)
-	{
-		if (bIsError)
-		{
-			UE_LOG(RuntimeMeshLog, Error, TEXT("%s"), *Text);
-		}
-		else
-		{
-			UE_LOG(RuntimeMeshLog, Warning, TEXT("%s"), *Text);
-		}
-	}
-
-public:
-	URuntimeMeshComponent(const FObjectInitializer& ObjectInitializer);
-
-	/**
-	*	Create/replace a section.
-	*	@param	SectionIndex		Index of the section to create or replace.
-	*	@param	Vertices			Vertex buffer all vertex data for this section.
-	*	@param	Triangles			Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
-	*	@param	bCreateCollision	Indicates whether collision should be created for this section. This adds significant cost.
-	*	@param	UpdateFrequency		Indicates how frequently the section will be updated. Allows the RMC to optimize itself to a particular use.
-	*	@param	UpdateFlags			Flags pertaining to this particular update.
-	*/
-	template<typename VertexType>
-	void CreateMeshSection(int32 SectionIndex, TArray<VertexType>& Vertices, TArray<int32>& Triangles, bool bCreateCollision = false, 
-		EUpdateFrequency UpdateFrequency = EUpdateFrequency::Average, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
-	{
-		// It is only safe to call these functions from the game thread.
-		check(IsInGameThread());
-
-		SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_CreateMeshSection_VertexType);
-
-		// Validate all creation parameters
-		RMC_VALIDATE_CREATIONPARAMETERS(SectionIndex, Vertices, Triangles, /*VoidReturn*/);
-
-		// Create the section
-		TSharedPtr<FRuntimeMeshSection<VertexType>> Section = CreateOrResetSection<FRuntimeMeshSection<VertexType>>(SectionIndex, false);
-		
-		// Set the vertex and index buffers
-		bool bShouldUseMove = (UpdateFlags & ESectionUpdateFlags::MoveArrays) != ESectionUpdateFlags::None;
-		Section->UpdateVertexBuffer(Vertices, nullptr, bShouldUseMove);
-		Section->UpdateIndexBuffer(Triangles, bShouldUseMove);
-
-		// Track collision status and update collision information if necessary
-		Section->CollisionEnabled = bCreateCollision;
-		Section->UpdateFrequency = UpdateFrequency;
-
-		// Finalize section.
-		CreateSectionInternal(SectionIndex, UpdateFlags);
-	}
-
-	/**
-	*	Create/replace a section.
-	*	@param	SectionIndex		Index of the section to create or replace.
-	*	@param	Vertices			Vertex buffer all vertex data for this section.
-	*	@param	Triangles			Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
-	*	@param	BoundingBox			The bounds of this section. Faster than the RMC automatically calculating it.
-	*	@param	bCreateCollision	Indicates whether collision should be created for this section. This adds significant cost.
-	*	@param	UpdateFrequency		Indicates how frequently the section will be updated. Allows the RMC to optimize itself to a particular use.
-	*	@param	UpdateFlags			Flags pertaining to this particular update.
-	*/
-	template<typename VertexType>
-	void CreateMeshSection(int32 SectionIndex, TArray<VertexType>& Vertices, TArray<int32>& Triangles, const FBox& BoundingBox, bool bCreateCollision = false,
-		EUpdateFrequency UpdateFrequency = EUpdateFrequency::Average, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
-	{
-		// It is only safe to call these functions from the game thread.
-		check(IsInGameThread());
-
-		SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_CreateMeshSection_VertexType_WithBoundingBox);
-
-		// Validate all creation parameters
-		RMC_VALIDATE_CREATIONPARAMETERS(SectionIndex, Vertices, Triangles, /*VoidReturn*/);
-		RMC_VALIDATE_BOUNDINGBOX(BoundingBox, /*VoidReturn*/);
-
-		// Create the section
-		TSharedPtr<FRuntimeMeshSection<VertexType>> Section = CreateOrResetSection<FRuntimeMeshSection<VertexType>>(SectionIndex, false);
-
-		// Set the vertex and index buffers
-		bool bShouldUseMove = (UpdateFlags & ESectionUpdateFlags::MoveArrays) != ESectionUpdateFlags::None;
-		Section->UpdateVertexBuffer(Vertices, &BoundingBox, bShouldUseMove);
-		Section->UpdateIndexBuffer(Triangles, bShouldUseMove);
-
-		// Track collision status and update collision information if necessary
-		Section->CollisionEnabled = bCreateCollision;
-		Section->UpdateFrequency = UpdateFrequency;
-
-		// Finalize section.
-		CreateSectionInternal(SectionIndex, UpdateFlags);
-	}
-
-	/**
-	*	Create/replace a section using 2 vertex buffers. One contains positions only, the other contains all other data. This allows for very efficient updates of the positions of a mesh.
-	*	@param	SectionIndex		Index of the section to create or replace.
-	*	@param	VertexPositions		Vertex buffer containing only the position information for each vertex.
-	*	@param	VertexData			Vertex buffer containing everything except position for each vertex.
-	*	@param	Triangles			Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
-	*	@param	bCreateCollision	Indicates whether collision should be created for this section. This adds significant cost.
-	*	@param	UpdateFrequency		Indicates how frequently the section will be updated. Allows the RMC to optimize itself to a particular use.
-	*	@param	UpdateFlags			Flags pertaining to this particular update.
-	*/
-	template<typename VertexType>
-	void CreateMeshSectionDualBuffer(int32 SectionIndex, TArray<FVector>& VertexPositions, TArray<VertexType>& VertexData, TArray<int32>& Triangles, bool bCreateCollision = false,
-		EUpdateFrequency UpdateFrequency = EUpdateFrequency::Average, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
-	{
-		SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_CreateMeshSectionDualBuffer_VertexType);
-
-		// Validate all creation parameters
-		RMC_VALIDATE_CREATIONPARAMETERS_DUALBUFFER(SectionIndex, VertexData, Triangles, VertexPositions, /*VoidReturn*/);
-
-		TSharedPtr<FRuntimeMeshSection<VertexType>> Section = CreateOrResetSection<FRuntimeMeshSection<VertexType>>(SectionIndex, true);
-
-		bool bShouldUseMove = (UpdateFlags & ESectionUpdateFlags::MoveArrays) != ESectionUpdateFlags::None;
-		Section->UpdateVertexPositionBuffer(VertexPositions, nullptr, bShouldUseMove);
-		Section->UpdateVertexBuffer(VertexData, nullptr, bShouldUseMove);
-		Section->UpdateIndexBuffer(Triangles, bShouldUseMove);
-
-		// Track collision status and update collision information if necessary
-		Section->CollisionEnabled = bCreateCollision;
-		Section->UpdateFrequency = UpdateFrequency;
-
-		// Finalize section.
-		CreateSectionInternal(SectionIndex, UpdateFlags);
-	}
-
-	/**
-	*	Create/replace a section using 2 vertex buffers. One contains positions only, the other contains all other data. This allows for very efficient updates of the positions of a mesh.
-	*	@param	SectionIndex		Index of the section to create or replace.
-	*	@param	VertexPositions		Vertex buffer containing only the position information for each vertex.
-	*	@param	VertexData			Vertex buffer containing everything except position for each vertex.
-	*	@param	Triangles			Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
-	*	@param	BoundingBox			The bounds of this section. Faster than the RMC automatically calculating it.
-	*	@param	bCreateCollision	Indicates whether collision should be created for this section. This adds significant cost.
-	*	@param	UpdateFrequency		Indicates how frequently the section will be updated. Allows the RMC to optimize itself to a particular use.
-	*	@param	UpdateFlags			Flags pertaining to this particular update.
-	*/
-	template<typename VertexType>
-	void CreateMeshSectionDualBuffer(int32 SectionIndex, TArray<FVector>& VertexPositions, TArray<VertexType>& VertexData, TArray<int32>& Triangles, const FBox& BoundingBox,
-		bool bCreateCollision = false, EUpdateFrequency UpdateFrequency = EUpdateFrequency::Average, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
-	{
-		SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_CreateMeshSectionDualBuffer_VertexType_WithBoundingBox);
-
-		// Validate all creation parameters
-		RMC_VALIDATE_CREATIONPARAMETERS_DUALBUFFER(SectionIndex, VertexData, Triangles, VertexPositions, /*VoidReturn*/);
-		RMC_VALIDATE_BOUNDINGBOX(BoundingBox, /*VoidReturn*/);
-
-		TSharedPtr<FRuntimeMeshSection<VertexType>> Section = CreateOrResetSection<FRuntimeMeshSection<VertexType>>(SectionIndex, true);
-
-		bool bShouldUseMove = (UpdateFlags & ESectionUpdateFlags::MoveArrays) != ESectionUpdateFlags::None;
-		Section->UpdateVertexPositionBuffer(VertexPositions, &BoundingBox, bShouldUseMove);
-		Section->UpdateVertexBuffer(VertexData, nullptr, bShouldUseMove);
-		Section->UpdateIndexBuffer(Triangles, bShouldUseMove);
-
-		// Track collision status and update collision information if necessary
-		Section->CollisionEnabled = bCreateCollision;
-		Section->UpdateFrequency = UpdateFrequency;
-
-		// Finalize section.
-		CreateSectionInternal(SectionIndex, UpdateFlags);
-	}
-	
-
-	/**
-	*	Updates a section. This is faster than CreateMeshSection. If this is a dual buffer section, you cannot change the length of the vertices.
-	*	@param	SectionIndex		Index of the section to update.
-	*	@param	Vertices			Vertex buffer all vertex data for this section, or in the case of dual buffer section it contains everything but position.
-	*	@param	UpdateFlags			Flags pertaining to this particular update.
-	*/
-	template<typename VertexType>
-	void UpdateMeshSection(int32 SectionIndex, TArray<VertexType>& Vertices, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
-	{
-		SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_UpdateMeshSection_VertexType);
-
-		// Validate all update parameters
-		RMC_VALIDATE_UPDATEPARAMETERS(SectionIndex, /*VoidReturn*/);
-		
-		// Validate section type
-		MeshSections[SectionIndex]->GetVertexType()->EnsureEquals<VertexType>();
-
-		// Cast section to correct type
-		TSharedPtr<FRuntimeMeshSection<VertexType>> Section = StaticCastSharedPtr<FRuntimeMeshSection<VertexType>>(MeshSections[SectionIndex]);
-		
-		// Check dual buffer section status
-		if (Section->IsDualBufferSection() && Vertices.Num() != Section->VertexBuffer.Num())
-		{
-			Log(TEXT("UpdateMeshSection() - Vertices cannot change length unless the positions are updated as well."), true);
-			return;
-		}
-
-		bool bShouldUseMove = (UpdateFlags & ESectionUpdateFlags::MoveArrays) != ESectionUpdateFlags::None;
-		bool bNeedsBoundsUpdate = false;
-
-		// Update vertices if supplied
-		bool bUpdatedVertices = false;
-		if (Vertices.Num() > 0)
-		{
-			bNeedsBoundsUpdate = Section->UpdateVertexBuffer(Vertices, nullptr, bShouldUseMove);
-			bUpdatedVertices = true;
-		}
-		else
-		{
-			Log(TEXT("UpdateMeshSection() - Vertices empty. They will not be updated."));
-		}
-		
-		// Finalize section update if we have anything to apply
-		if (bUpdatedVertices)
-		{
-			UpdateSectionInternal(SectionIndex, false, bUpdatedVertices, false, bNeedsBoundsUpdate, UpdateFlags);
-		}
-	}
-
-	/**
-	*	Updates a section. This is faster than CreateMeshSection. If this is a dual buffer section, you cannot change the length of the vertices.
-	*	@param	SectionIndex		Index of the section to update.
-	*	@param	Vertices			Vertex buffer all vertex data for this section, or in the case of dual buffer section it contains everything but position.
-	*	@param	BoundingBox			The bounds of this section. Faster than the RMC automatically calculating it.
-	*	@param	UpdateFlags			Flags pertaining to this particular update.
-	*/
-	template<typename VertexType>
-	void UpdateMeshSection(int32 SectionIndex, TArray<VertexType>& Vertices, const FBox& BoundingBox, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
-	{
-		SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_UpdateMeshSection_VertexType_WithBoundingBox);
-
-		// Validate all update parameters
-		RMC_VALIDATE_UPDATEPARAMETERS(SectionIndex, /*VoidReturn*/);
-		RMC_VALIDATE_BOUNDINGBOX(BoundingBox, /*VoidReturn*/);
-
-		// Validate section type
-		MeshSections[SectionIndex]->GetVertexType()->EnsureEquals<VertexType>();
-
-		// Cast section to correct type
-		TSharedPtr<FRuntimeMeshSection<VertexType>> Section = StaticCastSharedPtr<FRuntimeMeshSection<VertexType>>(MeshSections[SectionIndex]);
-
-		// Check dual buffer section status
-		if (Section->IsDualBufferSection() && Vertices.Num() != Section->VertexBuffer.Num())
-		{
-			Log(TEXT("UpdateMeshSection() - Vertices cannot change length unless the positions are updated as well."), true);
-			return;
-		}
-
-		bool bShouldUseMove = (UpdateFlags & ESectionUpdateFlags::MoveArrays) != ESectionUpdateFlags::None;
-		bool bNeedsBoundsUpdate = false;
-
-		// Update vertices if supplied
-		bool bUpdatedVertices = false;
-		if (Vertices.Num() > 0)
-		{
-			bNeedsBoundsUpdate = Section->UpdateVertexBuffer(Vertices, &BoundingBox, bShouldUseMove);
-			bUpdatedVertices = true;
-		}
-		else
-		{
-			Log(TEXT("UpdateMeshSection() - Vertices empty. They will not be updated."));
-		}
-
-		// Finalize section update if we have anything to apply
-		if (bUpdatedVertices)
-		{
-			UpdateSectionInternal(SectionIndex, false, bUpdatedVertices, false, bNeedsBoundsUpdate, UpdateFlags);
-		}
-	}
-
-	/**
-	*	Updates a section. This is faster than CreateMeshSection. If this is a dual buffer section, you cannot change the length of the vertices.
-	*	@param	SectionIndex		Index of the section to update.
-	*	@param	Vertices			Vertex buffer all vertex data for this section, or in the case of dual buffer section it contains everything but position.
-	*	@param	Triangles			Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
-	*	@param	UpdateFlags			Flags pertaining to this particular update.
-	*/
-	template<typename VertexType>
-	void UpdateMeshSection(int32 SectionIndex, TArray<VertexType>& Vertices, TArray<int32>& Triangles, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
-	{
-		SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_UpdateMeshSection_VertexType_WithTriangles);
-
-		// Validate all update parameters
-		RMC_VALIDATE_UPDATEPARAMETERS(SectionIndex, /*VoidReturn*/);
-
-		// Validate section type
-		MeshSections[SectionIndex]->GetVertexType()->EnsureEquals<VertexType>();
-
-		// Cast section to correct type
-		TSharedPtr<FRuntimeMeshSection<VertexType>> Section = StaticCastSharedPtr<FRuntimeMeshSection<VertexType>>(MeshSections[SectionIndex]);
-
-		// Check dual buffer section status
-		if (Section->IsDualBufferSection() && Vertices.Num() != Section->VertexBuffer.Num())
-		{
-			Log(TEXT("UpdateMeshSection() - Vertices cannot change length unless the positions are updated as well."), true);
-			return;
-		}
-
-		bool bShouldUseMove = (UpdateFlags & ESectionUpdateFlags::MoveArrays) != ESectionUpdateFlags::None;
-		bool bNeedsBoundsUpdate = false;
-
-		// Update vertices if supplied
-		bool bUpdatedVertices = false;
-		if (Vertices.Num() > 0)
-		{
-			bNeedsBoundsUpdate = Section->UpdateVertexBuffer(Vertices, nullptr, bShouldUseMove);
-			bUpdatedVertices = true;
-		}
-		else
-		{
-			Log(TEXT("UpdateMeshSection() - Vertices empty. They will not be updated."));
-		}
-
-		// Update triangles if supplied
-		bool bUpdatedIndices = false;
-		if (Triangles.Num() > 0)
-		{
-			Section->UpdateIndexBuffer(Triangles, bShouldUseMove);
-			bUpdatedIndices = true;
-		}
-		else
-		{
-			Log(TEXT("UpdateMeshSection() - Triangles empty. They will not be updated."));
-		}
-
-		// Finalize section update if we have anything to apply
-		if (bUpdatedVertices || bUpdatedIndices)
-		{
-			UpdateSectionInternal(SectionIndex, false, bUpdatedVertices, bUpdatedIndices, bNeedsBoundsUpdate, UpdateFlags);
-		}
-	}
-
-	/**
-	*	Updates a section. This is faster than CreateMeshSection. If this is a dual buffer section, you cannot change the length of the vertices.
-	*	@param	SectionIndex		Index of the section to update.
-	*	@param	Vertices			Vertex buffer all vertex data for this section, or in the case of dual buffer section it contains everything but position.
-	*	@param	Triangles			Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
-	*	@param	BoundingBox			The bounds of this section. Faster than the RMC automatically calculating it.
-	*	@param	UpdateFlags			Flags pertaining to this particular update.
-	*/
-	template<typename VertexType>
-	void UpdateMeshSection(int32 SectionIndex, TArray<VertexType>& Vertices, TArray<int32>& Triangles, const FBox& BoundingBox, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
-	{
-		SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_UpdateMeshSection_VertexType_WithTrianglesAndBoundinBox);
-
-		// Validate all update parameters
-		RMC_VALIDATE_UPDATEPARAMETERS(SectionIndex, /*VoidReturn*/);
-		RMC_VALIDATE_BOUNDINGBOX(BoundingBox, /*VoidReturn*/);
-
-		// Validate section type
-		MeshSections[SectionIndex]->GetVertexType()->EnsureEquals<VertexType>();
-
-		// Cast section to correct type
-		TSharedPtr<FRuntimeMeshSection<VertexType>> Section = StaticCastSharedPtr<FRuntimeMeshSection<VertexType>>(MeshSections[SectionIndex]);
-
-		// Check dual buffer section status
-		if (Section->IsDualBufferSection() && Vertices.Num() != Section->VertexBuffer.Num())
-		{
-			Log(TEXT("UpdateMeshSection() - Vertices cannot change length unless the positions are updated as well."), true);
-			return;
-		}
-
-		bool bShouldUseMove = (UpdateFlags & ESectionUpdateFlags::MoveArrays) != ESectionUpdateFlags::None;
-		bool bNeedsBoundsUpdate = false;
-
-		// Update vertices if supplied
-		bool bUpdatedVertices = false;
-		if (Vertices.Num() > 0)
-		{
-			bNeedsBoundsUpdate = Section->UpdateVertexBuffer(Vertices, &BoundingBox, bShouldUseMove);
-			bUpdatedVertices = true;
-		}
-		else
-		{
-			Log(TEXT("UpdateMeshSection() - Vertices empty. They will not be updated."));
-		}
-
-		// Update indices if supplied
-		bool bUpdatedIndices = false;
-		if (Triangles.Num() > 0)
-		{
-			Section->UpdateIndexBuffer(Triangles, bShouldUseMove);
-			bUpdatedIndices = true;
-		}
-		else
-		{
-			Log(TEXT("UpdateMeshSection() - Triangles empty. They will not be updated."));
-		}
-
-		// Finalize section update if we have anything to apply
-		if (bUpdatedVertices || bUpdatedIndices)
-		{
-			UpdateSectionInternal(SectionIndex, false, bUpdatedVertices, bUpdatedIndices, bNeedsBoundsUpdate, UpdateFlags);
-		}
-	}
-
-	
-	/**
-	*	Updates a section. This is faster than CreateMeshSection. This is only for dual buffer sections. You cannot change the length of positions or vertex data unless you specify both together.
-	*	@param	SectionIndex		Index of the section to update.	
-	*	@param	VertexPositions		Vertex buffer containing only the position information for each vertex.
-	*	@param	VertexData			Vertex buffer containing everything except position for each vertex.
-	*	@param	UpdateFlags			Flags pertaining to this particular update.
-	*/
-	template<typename VertexType>
-	void UpdateMeshSection(int32 SectionIndex, TArray<FVector>& VertexPositions, TArray<VertexType>& VertexData, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
-	{
-		SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_UpdateMeshSection_Dual_VertexType);
-
-		// Validate all update parameters
-		RMC_VALIDATE_UPDATEPARAMETERS_DUALBUFFER(SectionIndex, /*VoidReturn*/);
-
-		// Validate section type
-		MeshSections[SectionIndex]->GetVertexType()->EnsureEquals<VertexType>();
-
-		// Cast section to correct type
-		TSharedPtr<FRuntimeMeshSection<VertexType>> Section = StaticCastSharedPtr<FRuntimeMeshSection<VertexType>>(MeshSections[SectionIndex]);
-
-		// Check dual buffer section status
-		if (Section->IsDualBufferSection() && 
-			VertexData.Num() != Section->VertexBuffer.Num() &&
-			VertexPositions.Num() != VertexData.Num())
-		{
-			Log(TEXT("UpdateMeshSection() - Vertices cannot change length unless the positions are updated as well."), true);
-			return;
-		}
-
-		bool bShouldUseMove = (UpdateFlags & ESectionUpdateFlags::MoveArrays) != ESectionUpdateFlags::None;
-		bool bNeedsBoundsUpdate = false;
-
-		// Update vertex positions if supplied
-		bool bUpdatedVertexPositions = false;
-		if (VertexPositions.Num() > 0)
-		{
-			bNeedsBoundsUpdate = Section->UpdateVertexPositionBuffer(VertexPositions, nullptr, bShouldUseMove);
-			bUpdatedVertexPositions = true;
-		}
-		else
-		{
-			Log(TEXT("UpdatemeshSection() - Vertex positions empty. They will not be updated."));
-		}
-
-		// Update vertices if supplied
-		bool bUpdatedVertices = false;
-		if (VertexData.Num() > 0)
-		{
-			Section->UpdateVertexBuffer(VertexData, nullptr, bShouldUseMove);
-			bUpdatedVertices = true;
-		}
-		else
-		{
-			Log(TEXT("UpdateMeshSection() - Vertices empty. They will not be updated."));
-		}
-
-		// Finalize section update if we have anything to apply
-		if (bUpdatedVertexPositions || bUpdatedVertices)
-		{
-			UpdateSectionInternal(SectionIndex, bUpdatedVertexPositions, bUpdatedVertices, false, bNeedsBoundsUpdate, UpdateFlags);
-		}
-	}
-
-	/**
-	*	Updates a section. This is faster than CreateMeshSection. This is only for dual buffer sections. You cannot change the length of positions or vertex data unless you specify both together.
-	*	@param	SectionIndex		Index of the section to update.
-	*	@param	VertexPositions		Vertex buffer containing only the position information for each vertex.
-	*	@param	VertexData			Vertex buffer containing everything except position for each vertex.
-	*	@param	BoundingBox			The bounds of this section. Faster than the RMC automatically calculating it.
-	*	@param	UpdateFlags			Flags pertaining to this particular update.
-	*/
-	template<typename VertexType>
-	void UpdateMeshSection(int32 SectionIndex, TArray<FVector>& VertexPositions, TArray<VertexType>& VertexData, const FBox& BoundingBox, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
-	{
-		SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_UpdateMeshSection_Dual_VertexType_WithBoundingBox);
-
-		// Validate all update parameters
-		RMC_VALIDATE_UPDATEPARAMETERS_DUALBUFFER(SectionIndex, /*VoidReturn*/);
-		RMC_VALIDATE_BOUNDINGBOX(BoundingBox, /*VoidReturn*/);
-
-		// Validate section type
-		MeshSections[SectionIndex]->GetVertexType()->EnsureEquals<VertexType>();
-
-		// Cast section to correct type
-		TSharedPtr<FRuntimeMeshSection<VertexType>> Section = StaticCastSharedPtr<FRuntimeMeshSection<VertexType>>(MeshSections[SectionIndex]);
-
-		// Check dual buffer section status
-		if (Section->IsDualBufferSection() &&
-			VertexData.Num() != Section->VertexBuffer.Num() &&
-			VertexPositions.Num() != VertexData.Num())
-		{
-			Log(TEXT("UpdateMeshSection() - Vertices cannot change length unless the positions are updated as well."), true);
-			return;
-		}
-
-		bool bShouldUseMove = (UpdateFlags & ESectionUpdateFlags::MoveArrays) != ESectionUpdateFlags::None;
-		bool bNeedsBoundsUpdate = false;
-
-		// Update vertex positions if supplied
-		bool bUpdatedVertexPositions = false;
-		if (VertexPositions.Num() > 0)
-		{
-			bNeedsBoundsUpdate = Section->UpdateVertexPositionBuffer(VertexPositions, &BoundingBox, bShouldUseMove);
-			bUpdatedVertexPositions = true;
-		}
-		else
-		{
-			Log(TEXT("UpdatemeshSection() - Vertex positions empty. They will not be updated."));
-		}
-
-		// Update vertices if supplied
-		bool bUpdatedVertices = false;
-		if (VertexData.Num() > 0)
-		{
-			Section->UpdateVertexBuffer(VertexData, nullptr, bShouldUseMove);
-			bUpdatedVertices = true;
-		}
-		else
-		{
-			Log(TEXT("UpdateMeshSection() - Vertices empty. They will not be updated."));
-		}
-
-		// Finalize section update if we have anything to apply
-		if (bUpdatedVertexPositions || bUpdatedVertices)
-		{
-			UpdateSectionInternal(SectionIndex, bUpdatedVertexPositions, bUpdatedVertices, false, bNeedsBoundsUpdate, UpdateFlags);
-		}
-	}
-
-	/**
-	*	Updates a section. This is faster than CreateMeshSection. This is only for dual buffer sections. You cannot change the length of positions or vertex data unless you specify both together.
-	*	@param	SectionIndex		Index of the section to update.
-	*	@param	VertexPositions		Vertex buffer containing only the position information for each vertex.
-	*	@param	VertexData			Vertex buffer containing everything except position for each vertex.
-	*	@param	Triangles			Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
-	*	@param	UpdateFlags			Flags pertaining to this particular update.
-	*/
-	template<typename VertexType>
-	void UpdateMeshSection(int32 SectionIndex, TArray<FVector>& VertexPositions, TArray<VertexType>& VertexData, TArray<int32>& Triangles, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
-	{
-		SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_UpdateMeshSection_Dual_VertexType_WithTriangles);
-
-		// Validate all update parameters
-		RMC_VALIDATE_UPDATEPARAMETERS_DUALBUFFER(SectionIndex, /*VoidReturn*/);
-
-		// Validate section type
-		MeshSections[SectionIndex]->GetVertexType()->EnsureEquals<VertexType>();
-
-		// Cast section to correct type
-		TSharedPtr<FRuntimeMeshSection<VertexType>> Section = StaticCastSharedPtr<FRuntimeMeshSection<VertexType>>(MeshSections[SectionIndex]);
-
-		// Check dual buffer section status
-		if (Section->IsDualBufferSection() &&
-			VertexData.Num() != Section->VertexBuffer.Num() &&
-			VertexPositions.Num() != VertexData.Num())
-		{
-			Log(TEXT("UpdateMeshSection() - Vertices cannot change length unless the positions are updated as well."), true);
-			return;
-		}
-
-		bool bShouldUseMove = (UpdateFlags & ESectionUpdateFlags::MoveArrays) != ESectionUpdateFlags::None;
-		bool bNeedsBoundsUpdate = false;
-
-		// Update vertex positions if supplied
-		bool bUpdatedVertexPositions = false;
-		if (VertexPositions.Num() > 0)
-		{
-			bNeedsBoundsUpdate = Section->UpdateVertexPositionBuffer(VertexPositions, nullptr, bShouldUseMove);
-			bUpdatedVertexPositions = true;
-		}
-		else
-		{
-			Log(TEXT("UpdatemeshSection() - Vertex positions empty. They will not be updated."));
-		}
-
-		// Update vertices if supplied
-		bool bUpdatedVertices = false;
-		if (VertexData.Num() > 0)
-		{
-			Section->UpdateVertexBuffer(VertexData, nullptr, bShouldUseMove);
-			bUpdatedVertices = true;
-		}
-		else
-		{
-			Log(TEXT("UpdateMeshSection() - Vertices empty. They will not be updated."));
-		}
-
-		// Update triangles if supplied
-		bool bUpdatedIndices = false;
-		if (Triangles.Num() > 0)
-		{
-			Section->UpdateIndexBuffer(Triangles, bShouldUseMove);
-			bUpdatedIndices = true;
-		}
-		else
-		{
-			Log(TEXT("UpdateMeshSection() - Triangles empty. They will not be updated."));
-		}
-
-		// Finalize section update if we have anything to apply
-		if (bUpdatedVertexPositions || bUpdatedVertices || bUpdatedIndices)
-		{
-			UpdateSectionInternal(SectionIndex, bUpdatedVertexPositions, bUpdatedVertices, bUpdatedIndices, bNeedsBoundsUpdate, UpdateFlags);
-		}
-	}
-
-	/**
-	*	Updates a section. This is faster than CreateMeshSection. This is only for dual buffer sections. You cannot change the length of positions or vertex data unless you specify both together.
-	*	@param	SectionIndex		Index of the section to update.
-	*	@param	VertexPositions		Vertex buffer containing only the position information for each vertex.
-	*	@param	VertexData			Vertex buffer containing everything except position for each vertex.
-	*	@param	Triangles			Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
-	*	@param	BoundingBox			The bounds of this section. Faster than the RMC automatically calculating it.
-	*	@param	UpdateFlags			Flags pertaining to this particular update.
-	*/
-	template<typename VertexType>
-	void UpdateMeshSection(int32 SectionIndex, TArray<FVector>& VertexPositions, TArray<VertexType>& VertexData, TArray<int32>& Triangles, const FBox& BoundingBox, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None)
-	{
-		SCOPE_CYCLE_COUNTER(STAT_RuntimeMesh_UpdateMeshSection_Dual_VertexType_WithTrianglesAndBoundinBox);
-
-		// Validate all update parameters
-		RMC_VALIDATE_UPDATEPARAMETERS_DUALBUFFER(SectionIndex, /*VoidReturn*/);
-		RMC_VALIDATE_BOUNDINGBOX(BoundingBox, /*VoidReturn*/);
-
-		// Validate section type
-		MeshSections[SectionIndex]->GetVertexType()->EnsureEquals<VertexType>();
-
-		// Cast section to correct type
-		TSharedPtr<FRuntimeMeshSection<VertexType>> Section = StaticCastSharedPtr<FRuntimeMeshSection<VertexType>>(MeshSections[SectionIndex]);
-
-		// Check dual buffer section status
-		if (Section->IsDualBufferSection() &&
-			VertexData.Num() != Section->VertexBuffer.Num() &&
-			VertexPositions.Num() != VertexData.Num())
-		{
-			Log(TEXT("UpdateMeshSection() - Vertices cannot change length unless the positions are updated as well."), true);
-			return;
-		}
-
-		bool bShouldUseMove = (UpdateFlags & ESectionUpdateFlags::MoveArrays) != ESectionUpdateFlags::None;
-		bool bNeedsBoundsUpdate = false;
-
-		// Update vertex positions if supplied
-		bool bUpdatedVertexPositions = false;
-		if (VertexPositions.Num() > 0)
-		{
-			bNeedsBoundsUpdate = Section->UpdateVertexPositionBuffer(VertexPositions, &BoundingBox, bShouldUseMove);
-			bUpdatedVertexPositions = true;
-		}
-		else
-		{
-			Log(TEXT("UpdatemeshSection() - Vertex positions empty. They will not be updated."));
-		}
-
-		// Update vertices if supplied
-		bool bUpdatedVertices = false;
-		if (VertexData.Num() > 0)
-		{
-			Section->UpdateVertexBuffer(VertexData, nullptr, bShouldUseMove);
-			bUpdatedVertices = true;
-		}
-		else
-		{
-			Log(TEXT("UpdateMeshSection() - Vertices empty. They will not be updated."));
-		}
-
-		// Update indices if supplied
-		bool bUpdatedIndices = false;
-		if (Triangles.Num() > 0)
-		{
-			Section->UpdateIndexBuffer(Triangles, bShouldUseMove);
-			bUpdatedIndices = true;
-		}
-		else
-		{
-			Log(TEXT("UpdateMeshSection() - Triangles empty. They will not be updated."));
-		}
-
-		// Finalize section update if we have anything to apply
-		if (bUpdatedVertexPositions || bUpdatedVertices || bUpdatedIndices)
-		{
-			UpdateSectionInternal(SectionIndex, bUpdatedVertexPositions, bUpdatedVertices, bUpdatedIndices, bNeedsBoundsUpdate, UpdateFlags);
-		}
-	}
-
-	
-	/**
-	*	Updates a sections position buffer only. This cannot be used on a non-dual buffer section. You cannot change the length of the vertex position buffer with this function.
-	*	@param	SectionIndex		Index of the section to update.
-	*	@param	VertexPositions		Vertex buffer containing only the position information for each vertex.
-	*	@param	UpdateFlags			Flags pertaining to this particular update.
-	*/
-	void UpdateMeshSectionPositionsImmediate(int32 SectionIndex, TArray<FVector>& VertexPositions, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None);
-
-	/**
-	*	Updates a sections position buffer only. This cannot be used on a non-dual buffer section. You cannot change the length of the vertex position buffer with this function.
-	*	@param	SectionIndex		Index of the section to update.
-	*	@param	VertexPositions		Vertex buffer containing only the position information for each vertex.
-	*	@param	BoundingBox			The bounds of this section. Faster than the RMC automatically calculating it.
-	*	@param	UpdateFlags			Flags pertaining to this particular update.
-	*/
-	void UpdateMeshSectionPositionsImmediate(int32 SectionIndex, TArray<FVector>& VertexPositions, const FBox& BoundingBox, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None);
-	
-
-	/**
-	*	Starts an in place update of vertex positions. 
-	*	@param	SectionIndex		Index of the section to update.
-	*/
-	TArray<FVector>* BeginMeshSectionPositionUpdate(int32 SectionIndex);
-
-	/**
-	*	Finishes an in place update of vertex positions.
-	*	This will push the update to the GPU and calculate the new Bounding Box
-	*	@param	SectionIndex		Index of the section to update.
-	*/
-	void EndMeshSectionPositionUpdate(int32 SectionIndex);
-
-	/**
-	*	Finishes an in place update of vertex positions.
-	*	This will push the update to the GPU
-	*	@param	SectionIndex		Index of the section to update.
-	*	@param	BoundingBox			The bounds of this section. Faster than the RMC automatically calculating it.
-	*/
-	void EndMeshSectionPositionUpdate(int32 SectionIndex, const FBox& BoundingBox);
-
-
-	template<typename VertexType>
-	void BeginMeshSectionUpdate(int32 SectionIndex, TArray<VertexType>*& Vertices)
-	{
-		RMC_VALIDATE_UPDATEPARAMETERS(SectionIndex, /*VoidReturn*/);
-
-		// Validate section type
-		MeshSections[SectionIndex]->GetVertexType()->EnsureEquals<VertexType>();
-
-		// Cast section to correct type
-		TSharedPtr<FRuntimeMeshSection<VertexType>> Section = StaticCastSharedPtr<FRuntimeMeshSection<VertexType>>(MeshSections[SectionIndex]);
-
-		Vertices = &Section->VertexBuffer;
-	}
-
-	template<typename VertexType>
-	void BeginMeshSectionUpdate(int32 SectionIndex, TArray<VertexType>*& Vertices, TArray<int32>*& Triangles)
-	{
-		RMC_VALIDATE_UPDATEPARAMETERS(SectionIndex, /*VoidReturn*/);
-
-		// Validate section type
-		MeshSections[SectionIndex]->GetVertexType()->EnsureEquals<VertexType>();
-
-		// Cast section to correct type
-		TSharedPtr<FRuntimeMeshSection<VertexType>> Section = StaticCastSharedPtr<FRuntimeMeshSection<VertexType>>(MeshSections[SectionIndex]);
-
-		Vertices = &Section->VertexBuffer;
-		Triangles = &Section->IndexBuffer;
-	}
-
-	template<typename VertexType>
-	void BeginMeshSectionUpdate(int32 SectionIndex, TArray<FVector>*& Positions, TArray<VertexType>*& Vertices)
-	{
-		RMC_VALIDATE_UPDATEPARAMETERS(SectionIndex, /*VoidReturn*/);
-
-		// Validate section type
-		MeshSections[SectionIndex]->GetVertexType()->EnsureEquals<VertexType>();
-
-		// Cast section to correct type
-		TSharedPtr<FRuntimeMeshSection<VertexType>> Section = StaticCastSharedPtr<FRuntimeMeshSection<VertexType>>(MeshSections[SectionIndex]);
-
-		Positions = &Section->PositionVertexBuffer;
-		Vertices = &Section->VertexBuffer;
-	}
-
-	template<typename VertexType>
-	void BeginMeshSectionUpdate(int32 SectionIndex, TArray<FVector>*& Positions, TArray<VertexType>*& Vertices, TArray<int32>*& Triangles)
-	{
-		RMC_VALIDATE_UPDATEPARAMETERS(SectionIndex, /*VoidReturn*/);
-
-		// Validate section type
-		MeshSections[SectionIndex]->GetVertexType()->EnsureEquals<VertexType>();
-
-		// Cast section to correct type
-		TSharedPtr<FRuntimeMeshSection<VertexType>> Section = StaticCastSharedPtr<FRuntimeMeshSection<VertexType>>(MeshSections[SectionIndex]);
-
-		Positions = &Section->PositionVertexBuffer;
-		Vertices = &Section->VertexBuffer;
-		Triangles = &Section->IndexBuffer;
-	}
-
-
-	void BeginMeshSectionUpdate(int32 SectionIndex, IRuntimeMeshVerticesBuilder*& Vertices, FRuntimeMeshIndicesBuilder*& Indices);
-
-	void EndMeshSectionUpdate(int32 SectionIndex, ERuntimeMeshBuffer UpdatedBuffers, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None);
-
-	void EndMeshSectionUpdate(int32 SectionIndex, ERuntimeMeshBuffer UpdatedBuffers, const FBox& BoundingBox, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None);
-	
-
-	/*
-	*	Gets a readonly pointer to the sections mesh data.
-	*	To be able to edit the section data use BegineMeshSectionUpdate()
-	*/
-	void GetSectionMesh(int32 SectionIndex, const IRuntimeMeshVerticesBuilder*& Vertices, const FRuntimeMeshIndicesBuilder*& Indices);
-
-
-
-
-
-	/**
-	*	Create/replace a section.
-	*	@param	SectionIndex		Index of the section to create or replace.
-	*	@param	Vertices			Vertex buffer of all vertex positions to use for this mesh section.
-	*	@param	Triangles			Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
-	*	@param	Normals				Optional array of normal vectors for each vertex. If supplied, must be same length as Vertices array.
-	*	@param	UV0					Optional array of texture co-ordinates for each vertex (UV Channel 0). If supplied, must be same length as Vertices array.
-	*	@param	Colors				Optional array of colors for each vertex. If supplied, must be same length as Vertices array.
-	*	@param	Tangents			Optional array of tangent vector for each vertex. If supplied, must be same length as Vertices array.
-	*	@param	bCreateCollision	Indicates whether collision should be created for this section. This adds significant cost.
-	*	@param	UpdateFrequency		Indicates how frequently the section will be updated. Allows the RMC to optimize itself to a particular use.
-	*/
-	void CreateMeshSection(int32 SectionIndex, const TArray<FVector>& Vertices, const TArray<int32>& Triangles, const TArray<FVector>& Normals,
-		const TArray<FVector2D>& UV0, const TArray<FColor>& Colors, const TArray<FRuntimeMeshTangent>& Tangents, bool bCreateCollision = false,
-		EUpdateFrequency UpdateFrequency = EUpdateFrequency::Average, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None);
-
-	/**
-	*	Create/replace a section.
-	*	@param	SectionIndex		Index of the section to create or replace.
-	*	@param	Vertices			Vertex buffer of all vertex positions to use for this mesh section.
-	*	@param	Triangles			Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
-	*	@param	Normals				Optional array of normal vectors for each vertex. If supplied, must be same length as Vertices array.
-	*	@param	UV0					Optional array of texture co-ordinates for each vertex (UV Channel 0). If supplied, must be same length as Vertices array.
-	*	@param	UV1					Optional array of texture co-ordinates for each vertex (UV Channel 1). If supplied, must be same length as Vertices array.
-	*	@param	Colors				Optional array of colors for each vertex. If supplied, must be same length as Vertices array.
-	*	@param	Tangents			Optional array of tangent vector for each vertex. If supplied, must be same length as Vertices array.
-	*	@param	bCreateCollision	Indicates whether collision should be created for this section. This adds significant cost.
-	*	@param	UpdateFrequency		Indicates how frequently the section will be updated. Allows the RMC to optimize itself to a particular use.
-	*/
-	void CreateMeshSection(int32 SectionIndex, const TArray<FVector>& Vertices, const TArray<int32>& Triangles, const TArray<FVector>& Normals,
-		const TArray<FVector2D>& UV0, const TArray<FVector2D>& UV1, const TArray<FColor>& Colors, const TArray<FRuntimeMeshTangent>& Tangents,
-		bool bCreateCollision = false, EUpdateFrequency UpdateFrequency = EUpdateFrequency::Average, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None);
-
-
-	/**
-	*	Updates a section. This is faster than CreateMeshSection. 
-	*	@param	SectionIndex		Index of the section to update.
-	*	@param	Vertices			Vertex buffer of all vertex positions to use for this mesh section.
-	*	@param	Normals				Optional array of normal vectors for each vertex. If supplied, must be same length as Vertices array.
-	*	@param	UV1					Optional array of texture co-ordinates for each vertex (UV Channel 1). If supplied, must be same length as Vertices array.
-	*	@param	Colors				Optional array of colors for each vertex. If supplied, must be same length as Vertices array.
-	*	@param	Tangents			Optional array of tangent vector for each vertex. If supplied, must be same length as Vertices array.
-	*/
-	void UpdateMeshSection(int32 SectionIndex, const TArray<FVector>& Vertices, const TArray<FVector>& Normals, const TArray<FVector2D>& UV0, 
-		const TArray<FColor>& Colors, const TArray<FRuntimeMeshTangent>& Tangents, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None);
-
-	/**
-	*	Updates a section. This is faster than CreateMeshSection.
-	*	@param	SectionIndex		Index of the section to update.
-	*	@param	Vertices			Vertex buffer of all vertex positions to use for this mesh section.
-	*	@param	Normals				Optional array of normal vectors for each vertex. If supplied, must be same length as Vertices array.
-	*	@param	UV0					Optional array of texture co-ordinates for each vertex (UV Channel 0). If supplied, must be same length as Vertices array.
-	*	@param	UV1					Optional array of texture co-ordinates for each vertex (UV Channel 1). If supplied, must be same length as Vertices array.
-	*	@param	Colors				Optional array of colors for each vertex. If supplied, must be same length as Vertices array.
-	*	@param	Tangents			Optional array of tangent vector for each vertex. If supplied, must be same length as Vertices array.
-	*/
-	void UpdateMeshSection(int32 SectionIndex, const TArray<FVector>& Vertices, const TArray<FVector>& Normals, const TArray<FVector2D>& UV0, 
-		const TArray<FVector2D>& UV1, const TArray<FColor>& Colors, const TArray<FRuntimeMeshTangent>& Tangents, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None);
-
-	/**
-	*	Updates a section. This is faster than CreateMeshSection.
-	*	@param	SectionIndex		Index of the section to update.
-	*	@param	Vertices			Vertex buffer of all vertex positions to use for this mesh section.
-	*	@param	Triangles			Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
-	*	@param	Normals				Optional array of normal vectors for each vertex. If supplied, must be same length as Vertices array.
-	*	@param	UV0					Optional array of texture co-ordinates for each vertex (UV Channel 0). If supplied, must be same length as Vertices array.
-	*	@param	Colors				Optional array of colors for each vertex. If supplied, must be same length as Vertices array.
-	*	@param	Tangents			Optional array of tangent vector for each vertex. If supplied, must be same length as Vertices array.
-	*/
-	void UpdateMeshSection(int32 SectionIndex, const TArray<FVector>& Vertices, const TArray<int32>& Triangles, const TArray<FVector>& Normals, 
-		const TArray<FVector2D>& UV0, const TArray<FColor>& Colors, const TArray<FRuntimeMeshTangent>& Tangents, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None);
-
-	/**
-	*	Updates a section. This is faster than CreateMeshSection.
-	*	@param	SectionIndex		Index of the section to update.
-	*	@param	Vertices			Vertex buffer of all vertex positions to use for this mesh section.
-	*	@param	Triangles			Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
-	*	@param	Normals				Optional array of normal vectors for each vertex. If supplied, must be same length as Vertices array.
-	*	@param	UV0					Optional array of texture co-ordinates for each vertex (UV Channel 0). If supplied, must be same length as Vertices array.
-	*	@param	UV1					Optional array of texture co-ordinates for each vertex (UV Channel 1). If supplied, must be same length as Vertices array.
-	*	@param	Colors				Optional array of colors for each vertex. If supplied, must be same length as Vertices array.
-	*	@param	Tangents			Optional array of tangent vector for each vertex. If supplied, must be same length as Vertices array.
-	*/
-	void UpdateMeshSection(int32 SectionIndex, const TArray<FVector>& Vertices, const TArray<int32>& Triangles, const TArray<FVector>& Normals,
-		const TArray<FVector2D>& UV0, const TArray<FVector2D>& UV1, const TArray<FColor>& Colors, const TArray<FRuntimeMeshTangent>& Tangents, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None);
-
-	
-
-	/**
-	*	Create/replace a section.
-	*	@param	SectionIndex		Index of the section to create or replace.
-	*	@param	Vertices			Vertex buffer of all vertex positions to use for this mesh section.
-	*	@param	Triangles			Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
-	*	@param	Normals				Optional array of normal vectors for each vertex. If supplied, must be same length as Vertices array.
-	*	@param	Tangents			Optional array of tangent vector for each vertex. If supplied, must be same length as Vertices array.
-	*	@param	UV0					Optional array of texture co-ordinates for each vertex (UV Channel 0). If supplied, must be same length as Vertices array.
-	*	@param	UV1					Optional array of texture co-ordinates for each vertex (UV Channel 1). If supplied, must be same length as Vertices array.
-	*	@param	Colors				Optional array of colors for each vertex. If supplied, must be same length as Vertices array.
-	*	@param	bCreateCollision	Indicates whether collision should be created for this section. This adds significant cost.
-	*	@param	bCalculateNormalTangent	Indicates whether normal/tangent information should be calculated automatically. This can add significant cost.
-	*	@param	bGenerateTessellationTriangles	Indicates whether tessellation supporting triangles should be calculated. This can add significant cost.
-	*	@param	UpdateFrequency		Indicates how frequently the section will be updated. Allows the RMC to optimize itself to a particular use.
-	*/
-	UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh", meta = (DisplayName = "Create Mesh Section", AutoCreateRefTerm = "Normals,Tangents,UV0,UV1,Colors"))
-	void CreateMeshSection_Blueprint(int32 SectionIndex, const TArray<FVector>& Vertices, const TArray<int32>& Triangles, const TArray<FVector>& Normals, 
-		const TArray<FRuntimeMeshTangent>& Tangents, const TArray<FVector2D>& UV0, const TArray<FVector2D>& UV1, const TArray<FLinearColor>& Colors, 
-		bool bCreateCollision, bool bCalculateNormalTangent, bool bGenerateTessellationTriangles, EUpdateFrequency UpdateFrequency = EUpdateFrequency::Average);
-
-	/**
-	*	Updates a section. This is faster than CreateMeshSection. If you change the vertices count, you must update the other components.
-	*	@param	SectionIndex		Index of the section to update.
-	*	@param	Vertices			Vertex buffer of all vertex positions to use for this mesh section.
-	*	@param	Triangles			Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
-	*	@param	Normals				Optional array of normal vectors for each vertex. If supplied, must be same length as Vertices array.
-	*	@param	Tangents			Optional array of tangent vector for each vertex. If supplied, must be same length as Vertices array.
-	*	@param	UV0					Optional array of texture co-ordinates for each vertex (UV Channel 0). If supplied, must be same length as Vertices array.
-	*	@param	UV1					Optional array of texture co-ordinates for each vertex (UV Channel 1). If supplied, must be same length as Vertices array.
-	*	@param	Colors		Optional array of colors for each vertex. If supplied, must be same length as Vertices array.
-	*	@param	bCalculateNormalTangent	Indicates whether normal/tangent information should be calculated automatically. This can add significant cost.
-	*	@param	bGenerateTessellationTriangles	Indicates whether tessellation supporting triangles should be calculated. This can add significant cost.
-	*/
-	UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh", meta = (DisplayName = "Update Mesh Section", AutoCreateRefTerm = "Triangles,Normals,Tangents,UV0,UV1,Colors"))
-	void UpdateMeshSection_Blueprint(int32 SectionIndex, const TArray<FVector>& Vertices, const TArray<int32>& Triangles, const TArray<FVector>& Normals, 
-		const TArray<FRuntimeMeshTangent>& Tangents, const TArray<FVector2D>& UV0, const TArray<FVector2D>& UV1, const TArray<FLinearColor>& Colors, bool bCalculateNormalTangent, bool bGenerateTessellationTriangles);
-	
-
-
-	/**
-	*	Create/replace a section.
-	*	@param	SectionIndex		Index of the section to create or replace.
-	*	@param	Vertices			Vertex buffer all vertex data for this section.
-	*	@param	Triangles			Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
-	*	@param	bCreateCollision	Indicates whether collision should be created for this section. This adds significant cost.
-	*	@param	UpdateFrequency		Indicates how frequently the section will be updated. Allows the RMC to optimize itself to a particular use.
-	*	@param	UpdateFlags			Flags pertaining to this particular update.
-	*/
-	void CreateMeshSection(int32 SectionIndex, IRuntimeMeshVerticesBuilder& Vertices, FRuntimeMeshIndicesBuilder& Indices, bool bCreateCollision = false,
-		EUpdateFrequency UpdateFrequency = EUpdateFrequency::Average, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None);
-
-
-	/**
-	*	Updates a section. This is faster than CreateMeshSection. If this is a dual buffer section, you cannot change the length of the vertices.
-	*	@param	SectionIndex		Index of the section to update.
-	*	@param	Vertices			Vertex buffer all vertex data for this section, or in the case of dual buffer section it contains everything but position.
-	*	@param	Triangles			Index buffer indicating which vertices make up each triangle. Length must be a multiple of 3.
-	*	@param	UpdateFlags			Flags pertaining to this particular update.
-	*/
-	void UpdateMeshSection(int32 SectionIndex, IRuntimeMeshVerticesBuilder& Vertices, FRuntimeMeshIndicesBuilder& Indices, ESectionUpdateFlags UpdateFlags = ESectionUpdateFlags::None);
-
-
-
-
-	/** Clear a section of the procedural mesh. */
-	UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
-	void ClearMeshSection(int32 SectionIndex);
-
-	/** Clear all mesh sections and reset to empty state */
-	UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
-	void ClearAllMeshSections();
-
-
-	/** Sets the tessellation triangles needed to correctly support tessellation on a section. */
-	UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
-	void SetSectionTessellationTriangles(int32 SectionIndex, const TArray<int32>& TessellationTriangles, bool bShouldMoveArray = false);
-
-
-
-
-
-
-	/** Gets the bounding box of a specific section */
-	bool GetSectionBoundingBox(int32 SectionIndex, FBox& OutBoundingBox);
-
-
-	/** Control visibility of a particular section */
-	UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
-	void SetMeshSectionVisible(int32 SectionIndex, bool bNewVisibility);
-
-	/** Returns whether a particular section is currently visible */
-	UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
-	bool IsMeshSectionVisible(int32 SectionIndex) const;
-
-
-	/** Control whether a particular section casts a shadow */
-	UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
-	void SetMeshSectionCastsShadow(int32 SectionIndex, bool bNewCastsShadow);
-
-	/** Returns whether a particular section is currently casting shadows */
-	UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
-	bool IsMeshSectionCastingShadows(int32 SectionIndex) const;
-
-
-	/** Control whether a particular section has collision */
-	UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
-	void SetMeshSectionCollisionEnabled(int32 SectionIndex, bool bNewCollisionEnabled);
-
-	/** Returns whether a particular section has collision */
-	UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
-	bool IsMeshSectionCollisionEnabled(int32 SectionIndex);
-
-
-	/** Returns number of sections currently created for this component */
-	UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
-	int32 GetNumSections() const;
-
-	/** Returns whether a particular section currently exists */
-	UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
-	bool DoesSectionExist(int32 SectionIndex) const;
-
-	/** Returns first available section index */
-	UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
-	int32 FirstAvailableMeshSectionIndex() const;
-	
-	/** Returns the last in use section index */
-	UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
-	int32 GetLastSectionIndex() const;
-
-
-	/** Sets the geometry for a collision only section */
-	UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
-	void SetMeshCollisionSection(int32 CollisionSectionIndex, const TArray<FVector>& Vertices, const TArray<int32>& Triangles);
-
-	/** Clears the geometry for a collision only section */
-	UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
-	void ClearMeshCollisionSection(int32 CollisionSectionIndex);
-
-	/** Clears the geometry for ALL collision only sections */
-	UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
-	void ClearAllMeshCollisionSections();
-
-
-
-	/** Add simple collision convex to this component */
-	UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
-	void AddCollisionConvexMesh(TArray<FVector> ConvexVerts);
-
-	/** Add simple collision convex to this component */
-	UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
-	void ClearCollisionConvexMeshes();
-
-	/** Function to replace _all_ simple collision in one go */
-	void SetCollisionConvexMeshes(const TArray< TArray<FVector> >& ConvexMeshes);
-
-
-	/** Begins a batch of updates, delays updates until you call EndBatchUpdates() */
-	UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
-	void BeginBatchUpdates()
-	{
-		BatchState.StartBatch();
-	}
-
-	/** Ends a batch of updates started with BeginBatchUpdates() */
-	UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
-	void EndBatchUpdates();
-
-	/** Runs any pending collision cook (Not required to call this. This is only if you need to make sure all changes are cooked before doing something)*/
-	UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
-	void CookCollisionNow();
-
-
-
-	/**
-	*	Controls whether the complex (Per poly) geometry should be treated as 'simple' collision.
-	*	Should be set to false if this component is going to be given simple collision and simulated.
-	*/
-	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "RuntimeMesh")
-	bool bUseComplexAsSimpleCollision;
-
-	/**
-	*	Controls whether the mesh data should be serialized with the component.
-	*/
-	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "RuntimeMesh")
-	bool bShouldSerializeMeshData;
-	
-	/* 
-	*	The current mode of the collision cooker 
-	*	WARNING: This feature will only work in engine version 4.14 or above!
-	*/
-	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "RuntimeMesh")
-	ERuntimeMeshCollisionCookingMode CollisionMode;
-	
-	/** Collision data */
-	UPROPERTY(Instanced)
-	class UBodySetup* BodySetup;
-
-	/* Serialize the entire RMC to the supplied archive. */
-	void SerializeRMC(FArchive& Ar);
-
-	/* Serialize the designated section into the supplied archive. */
-	void SerializeRMCSection(FArchive& Ar, int32 SectionIndex);
-
-private:
-
-
-	//~ Begin Interface_CollisionDataProvider Interface
-	virtual bool GetPhysicsTriMeshData(struct FTriMeshCollisionData* CollisionData, bool InUseAllTriData) override;
-	virtual bool ContainsPhysicsTriMeshData(bool InUseAllTriData) const override;
-	virtual bool WantsNegXTriMesh() override { return false; }
-	//~ End Interface_CollisionDataProvider Interface
-
-
-	//~ Begin USceneComponent Interface.
-	virtual FBoxSphereBounds CalcBounds(const FTransform& LocalToWorld) const override;
-	virtual bool IsSupportedForNetworking() const override
-	{
-		return true;
-	}
-	//~ Begin USceneComponent Interface.
-
-	//~ Begin UPrimitiveComponent Interface.
-	virtual FPrimitiveSceneProxy* CreateSceneProxy() override;
-	virtual class UBodySetup* GetBodySetup() override;
-	//~ End UPrimitiveComponent Interface.
-
-	//~ Begin UMeshComponent Interface.
-	virtual int32 GetNumMaterials() const override;
-	//~ End UMeshComponent Interface.
-
-
-
-	/** Update LocalBounds member from the local box of each section */
-	void UpdateLocalBounds(bool bMarkRenderTransform = true);
-	/** Ensure ProcMeshBodySetup is allocated and configured */
-	void EnsureBodySetupCreated();
-	/** Mark collision data as dirty, and re-create on instance if necessary */
-	void UpdateCollision();
-
-	/* Marks the collision for an end of frame update */
-	void MarkCollisionDirty();
-
-	/* Cooks the new collision mesh updating the body */
-	void BakeCollision();
-
-	void UpdateNavigation();
-
-
-	/* Serializes this component */
-	virtual void Serialize(FArchive& Ar) override;
-	void SerializeInternal(FArchive& Ar, bool bForceSaveAll = false);
-	void SerializeLegacy(FArchive& Ar);
-
-	/* Does post load fixups */
-	virtual void PostLoad() override;
-
-	/* Registers the pre-physics tick function used to cook new meshes when necessary */
-	virtual void RegisterComponentTickFunctions(bool bRegister) override;
-
-
-	/* Current state of a batch update. */
-	FRuntimeMeshBatchUpdateState BatchState;
-
-	/* Is the collision in need of a recook? */
-	bool bCollisionDirty;
-
-	/** Array of sections of mesh */	
-	TArray<RuntimeMeshSectionPtr> MeshSections;
-
-	/* Array of collision only mesh sections*/
-	UPROPERTY(Transient)
-	TArray<FRuntimeMeshCollisionSection> MeshCollisionSections;
-
-	/** Convex shapes used for simple collision */
-	UPROPERTY(Transient)
-	TArray<FRuntimeConvexCollisionSection> ConvexCollisionSections;
-
-	/** Local space bounds of mesh */
-	UPROPERTY(Transient)
-	FBoxSphereBounds LocalBounds;
-
-	/* Tick function used to cook collision when needed*/
-	UPROPERTY(Transient)
-	FRuntimeMeshComponentPrePhysicsTickFunction PrePhysicsTick;
-
-
-	friend class FRuntimeMeshSceneProxy;
-	friend struct FRuntimeMeshComponentPrePhysicsTickFunction;
-};

+ 0 - 38
spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Public/RuntimeMeshComponentPlugin.h

@@ -1,38 +0,0 @@
-// Copyright 2016 Chris Conway (Koderz). All Rights Reserved.
-
-#pragma once
-
-#include "ModuleManager.h"
-
-/**
-* The public interface to this module
-*/
-class IRuntimeMeshComponentPlugin : public IModuleInterface
-{
-
-public:
-
-	/**
-	* Singleton-like access to this module's interface.  This is just for convenience!
-	* Beware of calling this during the shutdown phase, though.  Your module might have been unloaded already.
-	*
-	* @return Returns singleton instance, loading the module on demand if needed
-	*/
-	static inline IRuntimeMeshComponentPlugin& Get()
-	{
-		return FModuleManager::LoadModuleChecked< IRuntimeMeshComponentPlugin >("RuntimeMeshComponentPlugin");
-	}
-
-	/**
-	* Checks to see if this module is loaded and ready.  It is only valid to call Get() if IsAvailable() returns true.
-	*
-	* @return True if the module is loaded and ready to use
-	*/
-	static inline bool IsAvailable()
-	{
-		return FModuleManager::Get().IsModuleLoaded("RuntimeMeshComponentPlugin");
-	}
-};
-
-
-DECLARE_LOG_CATEGORY_EXTERN(RuntimeMeshLog, Log, All);

+ 0 - 423
spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Public/RuntimeMeshCore.h

@@ -1,423 +0,0 @@
-// Copyright 2016 Chris Conway (Koderz). All Rights Reserved.
-
-#pragma once
-
-#include "Engine.h"
-#include "Components/MeshComponent.h"
-#include "RuntimeMeshProfiling.h"
-#include "RuntimeMeshVersion.h"
-#include "Runtime/Launch/Resources/Version.h"
-#include "RuntimeMeshCore.generated.h"
-
-class FRuntimeMeshVertexFactory;
-
-#pragma warning( disable : 4265 )
-
-template<typename T>
-struct FRuntimeMeshVertexTraits
-{
-private:
-	template<typename C, C> struct ChT;
-
-	struct FallbackPosition { FVector Position; };
-	struct DerivedPosition : T, FallbackPosition { };
-	template<typename C> static char(&PositionCheck(ChT<FVector FallbackPosition::*, &C::Position>*))[1];
-	template<typename C> static char(&PositionCheck(...))[2];
-
-	struct FallbackNormal { FPackedRGBA16N Normal; };
-	struct DerivedNormal : T, FallbackNormal { };
-	template<typename C> static char(&NormalCheck(ChT<FPackedRGBA16N FallbackNormal::*, &C::Normal>*))[1];
-	template<typename C> static char(&NormalCheck(...))[2];
-
-	struct FallbackTangent { FPackedRGBA16N Tangent; };
-	struct DerivedTangent : T, FallbackTangent { };
-	template<typename C> static char(&TangentCheck(ChT<FPackedRGBA16N FallbackTangent::*, &C::Tangent>*))[1];
-	template<typename C> static char(&TangentCheck(...))[2];
-
-	struct FallbackColor { FColor Color; };
-	struct DerivedColor : T, FallbackColor { };
-	template<typename C> static char(&ColorCheck(ChT<FColor FallbackColor::*, &C::Color>*))[1];
-	template<typename C> static char(&ColorCheck(...))[2];
-
-	struct FallbackUV0 { FVector2D UV0; };
-	struct DerivedUV0 : T, FallbackUV0 { };
-	template<typename C> static char(&UV0Check(ChT<FVector2D FallbackUV0::*, &C::UV0>*))[1];
-	template<typename C> static char(&UV0Check(...))[2];
-
-	struct FallbackUV1 { FVector2D UV1; };
-	struct DerivedUV1 : T, FallbackUV1 { };
-	template<typename C> static char(&UV1Check(ChT<FVector2D FallbackUV1::*, &C::UV1>*))[1];
-	template<typename C> static char(&UV1Check(...))[2];
-
-	struct FallbackUV2 { FVector2D UV2; };
-	struct DerivedUV2 : T, FallbackUV2 { };
-	template<typename C> static char(&UV2Check(ChT<FVector2D FallbackUV2::*, &C::UV2>*))[1];
-	template<typename C> static char(&UV2Check(...))[2];
-
-	struct FallbackUV3 { FVector2D UV3; };
-	struct DerivedUV3 : T, FallbackUV3 { };
-	template<typename C> static char(&UV3Check(ChT<FVector2D FallbackUV3::*, &C::UV3>*))[1];
-	template<typename C> static char(&UV3Check(...))[2];
-
-	struct FallbackUV4 { FVector2D UV4; };
-	struct DerivedUV4 : T, FallbackUV4 { };
-	template<typename C> static char(&UV4Check(ChT<FVector2D FallbackUV4::*, &C::UV4>*))[1];
-	template<typename C> static char(&UV4Check(...))[2];
-
-	struct FallbackUV5 { FVector2D UV5; };
-	struct DerivedUV5 : T, FallbackUV5 { };
-	template<typename C> static char(&UV5Check(ChT<FVector2D FallbackUV5::*, &C::UV5>*))[1];
-	template<typename C> static char(&UV5Check(...))[2];
-
-	struct FallbackUV6 { FVector2D UV6; };
-	struct DerivedUV6 : T, FallbackUV6 { };
-	template<typename C> static char(&UV6Check(ChT<FVector2D FallbackUV6::*, &C::UV6>*))[1];
-	template<typename C> static char(&UV6Check(...))[2];
-
-	struct FallbackUV7 { FVector2D UV7; };
-	struct DerivedUV7 : T, FallbackUV7 { };
-	template<typename C> static char(&UV7Check(ChT<FVector2D FallbackUV7::*, &C::UV7>*))[1];
-	template<typename C> static char(&UV7Check(...))[2];
-
-	template<typename A, typename B>
-	struct IsSameType
-	{
-		static const bool Value = false;
-	};
-
-	template<typename A>
-	struct IsSameType<A, A>
-	{
-		static const bool Value = true;
-	};
-
-	template<bool HasNormal, bool HasTangent, typename Type>
-	struct TangentBasisHighPrecisionDetector
-	{
-		static const bool Value = false;
-	};
-
-	template<typename Type>
-	struct TangentBasisHighPrecisionDetector<true, false, Type>
-	{
-		static const bool Value = IsSameType<decltype(DeclVal<T>().Normal), FPackedRGBA16N>::Value;
-	};
-
-	template<bool HasNormal, typename Type>
-	struct TangentBasisHighPrecisionDetector<HasNormal, true, Type>
-	{
-		static const bool Value = IsSameType<decltype(DeclVal<T>().Tangent), FPackedRGBA16N>::Value;
-	};
-
-	template<bool HasUV0, typename Type>
-	struct UVChannelHighPrecisionDetector
-	{
-		static const bool Value = false;
-	};
-
-	template<typename Type>
-	struct UVChannelHighPrecisionDetector<true, Type>
-	{
-		static const bool Value = IsSameType<decltype(DeclVal<T>().UV0), FVector2D>::Value;
-	};
-	
-
-public:
-	static const bool HasPosition = sizeof(PositionCheck<DerivedPosition>(0)) == 2;
-	static const bool HasNormal = sizeof(NormalCheck<DerivedNormal>(0)) == 2;
-	static const bool HasTangent = sizeof(TangentCheck<DerivedTangent>(0)) == 2;
-	static const bool HasColor = sizeof(ColorCheck<DerivedColor>(0)) == 2;
-	static const bool HasUV0 = sizeof(UV0Check<DerivedUV0>(0)) == 2;
-	static const bool HasUV1 = sizeof(UV1Check<DerivedUV1>(0)) == 2;
-	static const bool HasUV2 = sizeof(UV2Check<DerivedUV2>(0)) == 2;
-	static const bool HasUV3 = sizeof(UV3Check<DerivedUV3>(0)) == 2;
-	static const bool HasUV4 = sizeof(UV4Check<DerivedUV4>(0)) == 2;
-	static const bool HasUV5 = sizeof(UV5Check<DerivedUV5>(0)) == 2;
-	static const bool HasUV6 = sizeof(UV6Check<DerivedUV6>(0)) == 2;
-	static const bool HasUV7 = sizeof(UV7Check<DerivedUV7>(0)) == 2;
-	static const int32 NumUVChannels = 
-		(HasUV0 ? 1 : 0) +
-		(HasUV1 ? 1 : 0) +
-		(HasUV2 ? 1 : 0) +
-		(HasUV3 ? 1 : 0) +
-		(HasUV4 ? 1 : 0) +
-		(HasUV5 ? 1 : 0) +
-		(HasUV6 ? 1 : 0) +
-		(HasUV7 ? 1 : 0);
-
-
-	
-	static const bool HasHighPrecisionNormals = TangentBasisHighPrecisionDetector<HasNormal, HasTangent, T>::Value;
-	static const bool HasHighPrecisionUVs = UVChannelHighPrecisionDetector<HasUV0, T>::Value;
-};
-
-
-
-#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION >= 12
-/** Structure definition of a vertex */
-using RuntimeMeshVertexStructure = FLocalVertexFactory::FDataType;
-#else
-/** Structure definition of a vertex */
-using RuntimeMeshVertexStructure = FLocalVertexFactory::DataType;
-#endif
-
-#define RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, VertexType, Member, MemberType) \
-	STRUCTMEMBER_VERTEXSTREAMCOMPONENT(&VertexBuffer, VertexType, Member, MemberType)
-
-/* Update frequency for a section. Used to optimize for update or render speed*/
-UENUM(BlueprintType)
-enum class EUpdateFrequency : uint8
-{
-	/* Tries to skip recreating the scene proxy if possible. */
-	Average UMETA(DisplayName = "Average"),
-	/* Tries to skip recreating the scene proxy if possible and optimizes the buffers for frequent updates. */
-	Frequent UMETA(DisplayName = "Frequent"),
-	/* If the component is static it will try to use the static rendering path (this will force a recreate of the scene proxy) */
-	Infrequent UMETA(DisplayName = "Infrequent")
-};
-
-/* Control flags for update actions */
-enum class ESectionUpdateFlags
-{
-	None = 0x0,
-
-	/** 
-	*	This will use move-assignment when copying the supplied vertices/triangles into the section.
-	*	This is faster as it doesn't require copying the data.
-	*
-	*	CAUTION: This means that your copy of the arrays will be cleared!
-	*/
-	MoveArrays = 0x1,
-
-	/**
-	*	Should the normals and tangents be calculated automatically?
-	*	To do this manually see RuntimeMeshLibrary::CalculateTangentsForMesh()
-	*/
-	CalculateNormalTangent = 0x2,
-
-	/**
-	*	Should the tessellation indices be calculated to support tessellation?
-	*	To do this manually see RuntimeMeshLibrary::GenerateTessellationIndexBuffer()
-	*/
-	CalculateTessellationIndices = 0x4,
-	
-};
-ENUM_CLASS_FLAGS(ESectionUpdateFlags)
-
-/**
-*	Struct used to specify a tangent vector for a vertex
-*	The Y tangent is computed from the cross product of the vertex normal (Tangent Z) and the TangentX member.
-*/
-USTRUCT(BlueprintType)
-struct FRuntimeMeshTangent
-{
-	GENERATED_USTRUCT_BODY()
-
-	/** Direction of X tangent for this vertex */
-	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Tangent)
-	FVector TangentX;
-
-	/** Bool that indicates whether we should flip the Y tangent when we compute it using cross product */
-	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Tangent)
-	bool bFlipTangentY;
-
-	FRuntimeMeshTangent()
-		: TangentX(1.f, 0.f, 0.f)
-		, bFlipTangentY(false)
-	{}
-
-	FRuntimeMeshTangent(float X, float Y, float Z, bool bInFlipTangentY = false)
-		: TangentX(X, Y, Z)
-		, bFlipTangentY(bInFlipTangentY)
-	{}
-
-	FRuntimeMeshTangent(FVector InTangentX, bool bInFlipTangentY = false)
-		: TangentX(InTangentX)
-		, bFlipTangentY(bInFlipTangentY)
-	{}
-
-	void AdjustNormal(FPackedNormal& Normal) const
-	{
-		Normal.Vector.W = bFlipTangentY ? 0 : 255;
-	}
-
-	void AdjustNormal(FPackedRGBA16N& Normal) const
-	{
-		Normal.W = bFlipTangentY ? 0 : 65535;
-	}
-};
-
-/*
-*	Configuration flag for the collision cooking to prioritize cooking speed or collision performance.
-*/
-UENUM(BlueprintType)
-enum class ERuntimeMeshCollisionCookingMode : uint8
-{
-	/*
-	*	Favors runtime collision performance of cooking speed. 
-	*	This means that cooking a new mesh will be slower, but collision will be faster.
-	*/
-	CollisionPerformance UMETA(DisplayName = "Collision Performance"),
-
-	/*
-	*	Favors cooking speed over collision performance.
-	*	This means that cooking a new mesh will be faster, but collision will be slower.
-	*/
-	CookingPerformance UMETA(DisplayName = "Cooking Performance"),
-};
-
-/* The different buffers within the Runtime Mesh Component */
-enum class ERuntimeMeshBuffer
-{
-	None = 0x0,
-	Vertices = 0x1,
-	Triangles = 0x2,
-	Positions = 0x4
-};
-ENUM_CLASS_FLAGS(ERuntimeMeshBuffer)
-
-
-USTRUCT()
-struct FRuntimeMeshCollisionSection
-{
-	GENERATED_BODY()
-
-	UPROPERTY()
-	TArray<FVector> VertexBuffer;
-
-	UPROPERTY()
-	TArray<int32> IndexBuffer;
-
-	void Reset()
-	{
-		VertexBuffer.Empty();
-		IndexBuffer.Empty();
-	}
-
-	friend FArchive& operator <<(FArchive& Ar, FRuntimeMeshCollisionSection& Section)
-	{
-		Ar << Section.VertexBuffer;
-		Ar << Section.IndexBuffer;
-		return Ar;
-	}
-}; 
-
-USTRUCT()
-struct FRuntimeConvexCollisionSection
-{
-	GENERATED_BODY()
-
-	UPROPERTY()
-	TArray<FVector> VertexBuffer;
-
-	UPROPERTY()
-	FBox BoundingBox;
-
-	void Reset()
-	{
-		VertexBuffer.Empty();
-		BoundingBox.Init();
-	}
-
-	friend FArchive& operator <<(FArchive& Ar, FRuntimeConvexCollisionSection& Section)
-	{
-		Ar << Section.VertexBuffer;
-		Ar << Section.BoundingBox;
-		return Ar;
-	}
-};
-
-
-
-
-
-
-struct RUNTIMEMESHCOMPONENT_API FRuntimeMeshVertexTypeInfo
-{
-	const FString TypeName;
-	const FGuid TypeGuid;
-
-	FRuntimeMeshVertexTypeInfo(FString Name, FGuid Guid) : TypeName(Name), TypeGuid(Guid) { }
-
-	virtual bool Equals(const FRuntimeMeshVertexTypeInfo* Other) const
-	{
-		return TypeGuid == Other->TypeGuid;
-	}
-
-	template<typename Type>
-	void EnsureEquals() const
-	{
-		if (!Equals(&Type::TypeInfo))
-		{
-			ThrowMismatchException(Type::TypeInfo.TypeName);
-		}
-	}
-
-	virtual class FRuntimeMeshSectionInterface* CreateSection(bool bInNeedsPositionOnlyBuffer) const = 0;
-protected:
-
-	void ThrowMismatchException(const FString& OtherName) const
-	{
-		UE_LOG(RuntimeMeshLog, Fatal, TEXT("Vertex Type Mismatch: %s  and  %s"), *TypeName, *OtherName);
-	}
-};
-
-
-/*
-*  Internal container used to track known vertex types, for serialization and other purposes.
-*/
-class RUNTIMEMESHCOMPONENT_API FRuntimeMeshVertexTypeRegistrationContainer
-{
-	struct VertexRegistration
-	{
-		const FRuntimeMeshVertexTypeInfo* const TypeInfo;
-		uint32 ReferenceCount;
-		
-		VertexRegistration(const FRuntimeMeshVertexTypeInfo* const InTypeInfo)
-			: TypeInfo(InTypeInfo), ReferenceCount(1) { }
-	};
-	TMap<FGuid, VertexRegistration> Registrations;
-
-public:
-
-	static FRuntimeMeshVertexTypeRegistrationContainer& GetInstance();
-
-	void Register(const FRuntimeMeshVertexTypeInfo* InType);
-
-	void UnRegister(const FRuntimeMeshVertexTypeInfo* InType);
-
-	const FRuntimeMeshVertexTypeInfo* GetVertexType(FGuid Key) const;
-
-};
-
-
-template<typename VertexType>
-class FRuntimeMeshVertexTypeRegistration : FNoncopyable
-{
-public:
-	FRuntimeMeshVertexTypeRegistration()
-	{ 
-		FRuntimeMeshVertexTypeRegistrationContainer::GetInstance().Register(&VertexType::TypeInfo);
-	}
-
-	~FRuntimeMeshVertexTypeRegistration()
-	{
-		FRuntimeMeshVertexTypeRegistrationContainer::GetInstance().UnRegister(&VertexType::TypeInfo);
-	}
-};
-
-
-
-
-#define DECLARE_RUNTIMEMESH_CUSTOMVERTEX_TYPEINFO(TypeName, Guid) \
-	struct FRuntimeMeshVertexTypeInfo_##TypeName : public FRuntimeMeshVertexTypeInfo \
-	{ \
-		FRuntimeMeshVertexTypeInfo_##TypeName() : FRuntimeMeshVertexTypeInfo(TEXT(#TypeName), Guid) { } \
-	}; \
-	static const FRuntimeMeshVertexTypeInfo_##TypeName TypeInfo;
-
-#define DEFINE_RUNTIMEMESH_CUSTOMVERTEX_TYPEINFO(TypeName) \
-	const  TypeName::FRuntimeMeshVertexTypeInfo_##TypeName TypeName::TypeInfo = TypeName::FRuntimeMeshVertexTypeInfo_##TypeName(); \
-    FRuntimeMeshVertexTypeRegistration<##TypeName> FRuntimeMeshVertexTypeInfoRegistration_##TypeName(&##TypeName::TypeInfo);
-
-

+ 0 - 1273
spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Public/RuntimeMeshGenericVertex.h

@@ -1,1273 +0,0 @@
-// 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<true, true, true, true, 1, ERuntimeMeshVertexTangentBasisType::Default, ERuntimeMeshVertexUVType::Default>;
-//
-//	MyVertex Vertex;
-//	Vertex.Position = FVector(0,0,0);
-//	Vertex.Normal = FVector(0,0,0);
-//	Vertex.UV0 = FVector2D(0,0);
-//
-//
-//////////////////////////////////////////////////////////////////////////
-
-
-template<int32 TextureChannels, bool HalfPrecisionUVs, bool HasPositionComponent>
-RuntimeMeshVertexStructure CreateVertexStructure(const FVertexBuffer& VertexBuffer);
-
-
-//////////////////////////////////////////////////////////////////////////
-// Texture Component Type Selector
-//////////////////////////////////////////////////////////////////////////
-
-enum class ERuntimeMeshVertexUVType
-{
-	Default = 1,
-	HighPrecision = 2,
-};
-
-template<ERuntimeMeshVertexUVType UVType>
-struct FRuntimeMeshVertexUVsTypeSelector;
-
-template<>
-struct FRuntimeMeshVertexUVsTypeSelector<ERuntimeMeshVertexUVType::Default>
-{
-	typedef FVector2DHalf UVsType;
-	static const EVertexElementType VertexElementType1Channel = VET_Half2;
-	static const EVertexElementType VertexElementType2Channel = VET_Half4;
-
-};
-
-template<>
-struct FRuntimeMeshVertexUVsTypeSelector<ERuntimeMeshVertexUVType::HighPrecision>
-{
-	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<int32 TextureChannels, typename UVType> 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<typename UVType> struct FRuntimeMeshUVComponents<0, UVType>
-{
-	FRuntimeMeshUVComponents() { }
-	FRuntimeMeshUVComponents(EForceInit) { }
-};
-
-/* Defines the UV coordinates for a vertex (Specialized to 1 channels) */
-template<typename UVType> 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<typename UVType> 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<typename UVType> 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<typename UVType> 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<typename UVType> 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<typename UVType> 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<typename UVType> 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<typename UVType> 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<ERuntimeMeshVertexTangentBasisType TangentBasisType>
-struct FRuntimeMeshVertexTangentTypeSelector;
-
-template<>
-struct FRuntimeMeshVertexTangentTypeSelector<ERuntimeMeshVertexTangentBasisType::Default>
-{
-	typedef FPackedNormal TangentType;
-	static const EVertexElementType VertexElementType = VET_PackedNormal;
-};
-
-template<>
-struct FRuntimeMeshVertexTangentTypeSelector<ERuntimeMeshVertexTangentBasisType::HighPrecision>
-{
-	typedef FPackedRGBA16N TangentType;
-	static const EVertexElementType VertexElementType = VET_UShort4N;
-};
-
-
-//////////////////////////////////////////////////////////////////////////
-// Tangent Basis Components
-//////////////////////////////////////////////////////////////////////////
-
-template<bool WantsNormal, bool WantsTangent, typename TangentType>
-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<typename TangentType>
-struct FRuntimeMeshNormalTangentComponents<true, false, TangentType>
-{
-	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<typename TangentType>
-struct FRuntimeMeshNormalTangentComponents<false, true, TangentType>
-{
-	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<typename TangentType>
-struct FRuntimeMeshNormalTangentComponents<true, true, TangentType>
-{
-	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<bool WantsPosition>
-struct FRuntimeMeshPositionComponent;
-
-template<>
-struct FRuntimeMeshPositionComponent<true>
-{
-	FVector Position;
-
-	FRuntimeMeshPositionComponent() { }
-	FRuntimeMeshPositionComponent(EForceInit) : Position(0.0f, 0.0f, 0.0f) { }
-};
-
-
-
-//////////////////////////////////////////////////////////////////////////
-// Color Component
-//////////////////////////////////////////////////////////////////////////
-
-template<bool WantsColor>
-struct FRuntimeMeshColorComponent;
-
-template<>
-struct FRuntimeMeshColorComponent<true>
-{
-	FColor Color;
-
-	FRuntimeMeshColorComponent() { }
-	FRuntimeMeshColorComponent(EForceInit) : Color(FColor::White) { }
-};
-
-
-
-
-//////////////////////////////////////////////////////////////////////////
-// Position Normal Tangent Combiner
-//////////////////////////////////////////////////////////////////////////
-
-template<bool WantsPosition, bool WantsNormal, bool WantsTangent, typename TangentBasisType>
-struct FRuntimeMeshPositionNormalTangentComponentCombiner :
-	public FRuntimeMeshPositionComponent<WantsPosition>,
-	public FRuntimeMeshNormalTangentComponents<WantsNormal, WantsTangent, TangentBasisType>
-{
-	FRuntimeMeshPositionNormalTangentComponentCombiner() { }
-	FRuntimeMeshPositionNormalTangentComponentCombiner(EForceInit)
-		: FRuntimeMeshPositionComponent<WantsPosition>(EForceInit::ForceInit)
-		, FRuntimeMeshNormalTangentComponents<WantsNormal, WantsTangent, TangentBasisType>(EForceInit::ForceInit)
-	{ }
-};
-
-template<bool WantsPosition, typename TangentBasisType>
-struct FRuntimeMeshPositionNormalTangentComponentCombiner<WantsPosition, false, false, TangentBasisType> :
-	public FRuntimeMeshPositionComponent<WantsPosition>
-{
-	FRuntimeMeshPositionNormalTangentComponentCombiner() { }
-	FRuntimeMeshPositionNormalTangentComponentCombiner(EForceInit)
-		: FRuntimeMeshPositionComponent<WantsPosition>(EForceInit::ForceInit)
-	{ }
-};
-
-template<bool WantsNormal, bool WantsTangent, typename TangentBasisType>
-struct FRuntimeMeshPositionNormalTangentComponentCombiner<false, WantsNormal, WantsTangent, TangentBasisType> :
-	public FRuntimeMeshNormalTangentComponents<WantsNormal, WantsTangent, TangentBasisType>
-{
-	FRuntimeMeshPositionNormalTangentComponentCombiner() { }
-	FRuntimeMeshPositionNormalTangentComponentCombiner(EForceInit)
-		: FRuntimeMeshNormalTangentComponents<WantsNormal, WantsTangent, TangentBasisType>(EForceInit::ForceInit)
-	{ }
-};
-
-template<typename TangentBasisType>
-struct FRuntimeMeshPositionNormalTangentComponentCombiner<false, false, false, TangentBasisType>;
-
-
-
-//////////////////////////////////////////////////////////////////////////
-// Color UV Combiner
-//////////////////////////////////////////////////////////////////////////
-
-template<bool WantsColor, int32 NumWantedUVChannels, typename UVType>
-struct FRuntimeMeshColorUVComponentCombiner :
-	public FRuntimeMeshColorComponent<WantsColor>,
-	public FRuntimeMeshUVComponents<NumWantedUVChannels, UVType>
-{
-	FRuntimeMeshColorUVComponentCombiner() { }
-	FRuntimeMeshColorUVComponentCombiner(EForceInit)
-		: FRuntimeMeshColorComponent<WantsColor>(EForceInit::ForceInit)
-		, FRuntimeMeshUVComponents<NumWantedUVChannels, UVType>(EForceInit::ForceInit)
-	{ }
-};
-
-template<int32 NumWantedUVChannels, typename UVType>
-struct FRuntimeMeshColorUVComponentCombiner<false, NumWantedUVChannels, UVType> :
-	public FRuntimeMeshUVComponents<NumWantedUVChannels, UVType>
-{
-	FRuntimeMeshColorUVComponentCombiner() { }
-	FRuntimeMeshColorUVComponentCombiner(EForceInit)
-		: FRuntimeMeshUVComponents<NumWantedUVChannels, UVType>(EForceInit::ForceInit)
-	{ }
-};
-
-template<bool WantsColor, typename UVType>
-struct FRuntimeMeshColorUVComponentCombiner<WantsColor, 0, UVType> :
-	public FRuntimeMeshColorComponent<WantsColor>
-{
-	FRuntimeMeshColorUVComponentCombiner() { }
-	FRuntimeMeshColorUVComponentCombiner(EForceInit)
-		: FRuntimeMeshColorComponent<WantsColor>(EForceInit::ForceInit)
-	{ }
-};
-
-template<typename UVType>
-struct FRuntimeMeshColorUVComponentCombiner<false, 0, UVType>;
-
-
-
-
-
-
-
-//////////////////////////////////////////////////////////////////////////
-// Template Vertex Type Info Structure
-//////////////////////////////////////////////////////////////////////////
-
-template<bool WantsPosition, bool WantsNormal, bool WantsTangent, bool WantsColor, int32 NumWantedUVChannels,
-	ERuntimeMeshVertexTangentBasisType NormalTangentType, ERuntimeMeshVertexUVType UVType>
-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<NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType>										\
-	{																																																\
-		FRuntimeMeshVertexTypeInfo_##VertexName()																																					\
-			: FRuntimeMeshVertexTypeInfo_GenericVertex<NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType>(TEXT("")) { }								\
-																																																	\
-		virtual class FRuntimeMeshSectionInterface* CreateSection(bool bInNeedsPositionOnlyBuffer) const override;																					\
-	};																																																\
-	struct APIQUALIFIER VertexName : public FRuntimeMeshVertex<NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType>						\
-	{																																																\
-		static const FRuntimeMeshVertexTypeInfo_##VertexName TypeInfo;																																\
-																																																	\
-		typedef FRuntimeMeshVertex<NeedsPosition, NeedsNormal, NeedsTangent, NeedsColor, UVChannelCount, TangentsType, UVChannelType> 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<bool WantsPosition, bool WantsNormal, bool WantsTangent, bool WantsColor, int32 NumWantedUVChannels,
-ERuntimeMeshVertexTangentBasisType NormalTangentType = ERuntimeMeshVertexTangentBasisType::Default, ERuntimeMeshVertexUVType UVType = ERuntimeMeshVertexUVType::Default>
-struct FRuntimeMeshVertex :
-	public FRuntimeMeshPositionNormalTangentComponentCombiner<WantsPosition, WantsNormal, WantsTangent, typename FRuntimeMeshVertexTangentTypeSelector<NormalTangentType>::TangentType>,
-	public FRuntimeMeshColorUVComponentCombiner<WantsColor, NumWantedUVChannels, typename FRuntimeMeshVertexUVsTypeSelector<UVType>::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<WantsPosition, WantsNormal, WantsTangent, typename FRuntimeMeshVertexTangentTypeSelector<NormalTangentType>::TangentType>(EForceInit::ForceInit)
-    , FRuntimeMeshColorUVComponentCombiner<WantsColor, NumWantedUVChannels, typename FRuntimeMeshVertexUVsTypeSelector<UVType>::UVsType>(EForceInit::ForceInit)
-    { }
-};
-
-// This version only uses the position/normal/tangent combiner as we don't need anything from the other
-template<bool WantsPosition, bool WantsNormal, bool WantsTangent, ERuntimeMeshVertexTangentBasisType NormalTangentType, ERuntimeMeshVertexUVType UVType>
-struct FRuntimeMeshVertex<WantsPosition, WantsNormal, WantsTangent, false, 0, NormalTangentType, UVType> :
-	public FRuntimeMeshPositionNormalTangentComponentCombiner<WantsPosition, WantsNormal, WantsTangent, typename FRuntimeMeshVertexTangentTypeSelector<NormalTangentType>::TangentType>
-{
-    // Get vertex structure
-    static RuntimeMeshVertexStructure GetVertexStructure(const FVertexBuffer& VertexBuffer);
-    
-    FRuntimeMeshVertex() { }
-    FRuntimeMeshVertex(EForceInit)
-    : FRuntimeMeshPositionNormalTangentComponentCombiner<WantsPosition, WantsNormal, WantsTangent, typename FRuntimeMeshVertexTangentTypeSelector<NormalTangentType>::TangentType>(EForceInit::ForceInit)
-    { }
-};
-
-// This version only uses the color/uv combiner as we don't need anything from the other
-template<bool WantsColor, int32 NumWantedUVChannels, ERuntimeMeshVertexTangentBasisType NormalTangentType, ERuntimeMeshVertexUVType UVType>
-struct FRuntimeMeshVertex<false, false, false, WantsColor, NumWantedUVChannels, NormalTangentType, UVType> :
-	public FRuntimeMeshColorUVComponentCombiner<WantsColor, NumWantedUVChannels, typename FRuntimeMeshVertexUVsTypeSelector<UVType>::UVsType>
-{
-    // Get vertex structure
-    static RuntimeMeshVertexStructure GetVertexStructure(const FVertexBuffer& VertexBuffer);
-    
-    FRuntimeMeshVertex() { }
-    FRuntimeMeshVertex(EForceInit)
-    : FRuntimeMeshColorUVComponentCombiner<WantsColor, NumWantedUVChannels, typename FRuntimeMeshVertexUVsTypeSelector<UVType>::UVsType>(EForceInit::ForceInit)
-    { }
-};
-
-
-
-//////////////////////////////////////////////////////////////////////////
-// Vertex Structure Generator
-//////////////////////////////////////////////////////////////////////////
-
-struct FRuntimeMeshVertexUtilities
-{
-    //////////////////////////////////////////////////////////////////////////
-    // Position Component
-    //////////////////////////////////////////////////////////////////////////
-    template<typename RuntimeVertexType, bool WantsPosition>
-    struct FRuntimeMeshPositionComponentUtilities
-    {
-        static void AddComponent(const FVertexBuffer& VertexBuffer, RuntimeMeshVertexStructure& VertexStructure)
-        {
-            VertexStructure.PositionComponent = RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, Position, VET_Float3);
-        }
-
-    };
-    
-    template<typename RuntimeVertexType>
-    struct FRuntimeMeshPositionComponentUtilities<RuntimeVertexType, false>
-    {
-        static void AddComponent(const FVertexBuffer& VertexBuffer, RuntimeMeshVertexStructure& VertexStructure)
-        {
-        }
-    };
-    
-    //////////////////////////////////////////////////////////////////////////
-    // Normal/Tangent Components
-    //////////////////////////////////////////////////////////////////////////
-    template<typename RuntimeVertexType, bool WantsNormal, bool WantsTangent, ERuntimeMeshVertexTangentBasisType NormalTangentType>
-    struct FRuntimeMeshNormalTangentComponentVertexStructure
-    {
-        static void AddComponent(const FVertexBuffer& VertexBuffer, RuntimeMeshVertexStructure& VertexStructure)
-        {
-            VertexStructure.TangentBasisComponents[1] = RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, Normal,
-                                                                                    FRuntimeMeshVertexTangentTypeSelector<NormalTangentType>::VertexElementType);
-            VertexStructure.TangentBasisComponents[0] = RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, Tangent,
-                                                                                    FRuntimeMeshVertexTangentTypeSelector<NormalTangentType>::VertexElementType);
-        }
-    };
-    
-    template<typename RuntimeVertexType, ERuntimeMeshVertexTangentBasisType NormalTangentType>
-    struct FRuntimeMeshNormalTangentComponentVertexStructure<RuntimeVertexType, true, false, NormalTangentType>
-    {
-        static void AddComponent(const FVertexBuffer& VertexBuffer, RuntimeMeshVertexStructure& VertexStructure)
-        {
-            VertexStructure.TangentBasisComponents[1] = RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, Normal,
-                                                                                    FRuntimeMeshVertexTangentTypeSelector<NormalTangentType>::VertexElementType);
-        }
-    };
-    
-    template<typename RuntimeVertexType, ERuntimeMeshVertexTangentBasisType NormalTangentType>
-    struct FRuntimeMeshNormalTangentComponentVertexStructure<RuntimeVertexType, false, true, NormalTangentType>
-    {
-        static void AddComponent(const FVertexBuffer& VertexBuffer, RuntimeMeshVertexStructure& VertexStructure)
-        {
-            VertexStructure.TangentBasisComponents[0] = RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, Tangent,
-                                                                                    FRuntimeMeshVertexTangentTypeSelector<NormalTangentType>::VertexElementType);
-        }
-    };
-    
-    template<typename RuntimeVertexType, ERuntimeMeshVertexTangentBasisType NormalTangentType>
-    struct FRuntimeMeshNormalTangentComponentVertexStructure<RuntimeVertexType, false, false, NormalTangentType>
-    {
-        static void AddComponent(const FVertexBuffer& VertexBuffer, RuntimeMeshVertexStructure& VertexStructure)
-        {
-        }
-    };
-    
-    //////////////////////////////////////////////////////////////////////////
-    // Color Component
-    //////////////////////////////////////////////////////////////////////////
-    template<typename RuntimeVertexType, bool WantsColor>
-    struct FRuntimeMeshColorComponentVertexStructure
-    {
-        static void AddComponent(const FVertexBuffer& VertexBuffer, RuntimeMeshVertexStructure& VertexStructure)
-        {
-            VertexStructure.ColorComponent = RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, Color, VET_Color);
-        }
-    };
-    
-    template<typename RuntimeVertexType>
-    struct FRuntimeMeshColorComponentVertexStructure<RuntimeVertexType, false>
-    {
-        static void AddComponent(const FVertexBuffer& VertexBuffer, RuntimeMeshVertexStructure& VertexStructure)
-        {
-        }
-    };
-    
-    
-    //////////////////////////////////////////////////////////////////////////
-    // UV Components
-    //////////////////////////////////////////////////////////////////////////
-    template<typename RuntimeVertexType, int32 NumWantedUVChannels, ERuntimeMeshVertexUVType UVType>
-    struct FRuntimeMeshTextureChannelsVertexStructure
-    {
-        static void AddChannels(const FVertexBuffer& VertexBuffer, RuntimeMeshVertexStructure& VertexStructure)
-        {
-        }
-    };
-    
-    template<typename RuntimeVertexType, ERuntimeMeshVertexUVType UVType>
-    struct FRuntimeMeshTextureChannelsVertexStructure<RuntimeVertexType, 1, UVType>
-    {
-        static void AddChannels(const FVertexBuffer& VertexBuffer, RuntimeMeshVertexStructure& VertexStructure)
-        {
-            VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV0, FRuntimeMeshVertexUVsTypeSelector<UVType>::VertexElementType1Channel));
-        }
-    };
-    
-    template<typename RuntimeVertexType, ERuntimeMeshVertexUVType UVType>
-    struct FRuntimeMeshTextureChannelsVertexStructure<RuntimeVertexType, 2, UVType>
-    {
-        static void AddChannels(const FVertexBuffer& VertexBuffer, RuntimeMeshVertexStructure& VertexStructure)
-        {
-            VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV0, FRuntimeMeshVertexUVsTypeSelector<UVType>::VertexElementType2Channel));
-        }
-    };
-    
-    template<typename RuntimeVertexType, ERuntimeMeshVertexUVType UVType>
-    struct FRuntimeMeshTextureChannelsVertexStructure<RuntimeVertexType, 3, UVType>
-    {
-        static void AddChannels(const FVertexBuffer& VertexBuffer, RuntimeMeshVertexStructure& VertexStructure)
-        {
-            
-            VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV0, FRuntimeMeshVertexUVsTypeSelector<UVType>::VertexElementType2Channel));
-            VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV2, FRuntimeMeshVertexUVsTypeSelector<UVType>::VertexElementType1Channel));
-        }
-    };
-    
-    template<typename RuntimeVertexType, ERuntimeMeshVertexUVType UVType>
-    struct FRuntimeMeshTextureChannelsVertexStructure<RuntimeVertexType, 4, UVType>
-    {
-        static void AddChannels(const FVertexBuffer& VertexBuffer, RuntimeMeshVertexStructure& VertexStructure)
-        {
-            VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV0, FRuntimeMeshVertexUVsTypeSelector<UVType>::VertexElementType2Channel));
-            VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV2, FRuntimeMeshVertexUVsTypeSelector<UVType>::VertexElementType2Channel));
-        }
-    };
-    
-    template<typename RuntimeVertexType, ERuntimeMeshVertexUVType UVType>
-    struct FRuntimeMeshTextureChannelsVertexStructure<RuntimeVertexType, 5, UVType>
-    {
-        static void AddChannels(const FVertexBuffer& VertexBuffer, RuntimeMeshVertexStructure& VertexStructure)
-        {
-            VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV0, FRuntimeMeshVertexUVsTypeSelector<UVType>::VertexElementType2Channel));
-            VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV2, FRuntimeMeshVertexUVsTypeSelector<UVType>::VertexElementType2Channel));
-            VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV4, FRuntimeMeshVertexUVsTypeSelector<UVType>::VertexElementType1Channel));
-        }
-    };
-    
-    template<typename RuntimeVertexType, ERuntimeMeshVertexUVType UVType>
-    struct FRuntimeMeshTextureChannelsVertexStructure<RuntimeVertexType, 6, UVType>
-    {
-        static void AddChannels(const FVertexBuffer& VertexBuffer, RuntimeMeshVertexStructure& VertexStructure)
-        {
-            VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV0, FRuntimeMeshVertexUVsTypeSelector<UVType>::VertexElementType2Channel));
-            VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV2, FRuntimeMeshVertexUVsTypeSelector<UVType>::VertexElementType2Channel));
-            VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV4, FRuntimeMeshVertexUVsTypeSelector<UVType>::VertexElementType2Channel));
-        }
-    };
-    
-    template<typename RuntimeVertexType, ERuntimeMeshVertexUVType UVType>
-    struct FRuntimeMeshTextureChannelsVertexStructure<RuntimeVertexType, 7, UVType>
-    {
-        static void AddChannels(const FVertexBuffer& VertexBuffer, RuntimeMeshVertexStructure& VertexStructure)
-        {
-            VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV0, FRuntimeMeshVertexUVsTypeSelector<UVType>::VertexElementType2Channel));
-            VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV2, FRuntimeMeshVertexUVsTypeSelector<UVType>::VertexElementType2Channel));
-            VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV4, FRuntimeMeshVertexUVsTypeSelector<UVType>::VertexElementType2Channel));
-            VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV6, FRuntimeMeshVertexUVsTypeSelector<UVType>::VertexElementType1Channel));
-        }
-    };
-    
-    template<typename RuntimeVertexType, ERuntimeMeshVertexUVType UVType>
-    struct FRuntimeMeshTextureChannelsVertexStructure<RuntimeVertexType, 8, UVType>
-    {
-        static void AddChannels(const FVertexBuffer& VertexBuffer, RuntimeMeshVertexStructure& VertexStructure)
-        {
-            VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV0, FRuntimeMeshVertexUVsTypeSelector<UVType>::VertexElementType2Channel));
-            VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV2, FRuntimeMeshVertexUVsTypeSelector<UVType>::VertexElementType2Channel));
-            VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV4, FRuntimeMeshVertexUVsTypeSelector<UVType>::VertexElementType2Channel));
-            VertexStructure.TextureCoordinates.Add(RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, RuntimeVertexType, UV6, FRuntimeMeshVertexUVsTypeSelector<UVType>::VertexElementType2Channel));
-        }
-    };
-    
-    
-    
-    //////////////////////////////////////////////////////////////////////////
-    // Vertex Structure Helper
-    //////////////////////////////////////////////////////////////////////////
-    template<bool WantsPosition, bool WantsNormal, bool WantsTangent, bool WantsColor, int32 NumWantedUVChannels,
-    ERuntimeMeshVertexTangentBasisType NormalTangentType, ERuntimeMeshVertexUVType UVType>
-    static RuntimeMeshVertexStructure CreateVertexStructure(const FVertexBuffer& VertexBuffer)
-    {
-        typedef FRuntimeMeshVertex<WantsPosition, WantsNormal, WantsTangent, WantsColor, NumWantedUVChannels, NormalTangentType, UVType> RuntimeVertexType;
-        
-        RuntimeMeshVertexStructure VertexStructure;
-        
-        // Add Position component if necessary
-        FRuntimeMeshPositionComponentUtilities<RuntimeVertexType, WantsPosition>::AddComponent(VertexBuffer, VertexStructure);
-        
-        // Add normal and tangent components if necessary
-        FRuntimeMeshNormalTangentComponentVertexStructure<RuntimeVertexType, WantsNormal, WantsTangent, NormalTangentType>::AddComponent(VertexBuffer, VertexStructure);
-        
-        // Add color component if necessary
-        FRuntimeMeshColorComponentVertexStructure<RuntimeVertexType, WantsColor>::AddComponent(VertexBuffer, VertexStructure);
-        
-        // Add all texture channels
-        FRuntimeMeshTextureChannelsVertexStructure<RuntimeVertexType, NumWantedUVChannels, UVType>::AddChannels(VertexBuffer, VertexStructure);
-        
-        return VertexStructure;
-    }
-};
-
-
-
-
-
-
-
-
-
-
-
-
-// These need to be declared after FRuntimemeshVertexStructureHelper and RuntimeMeshVertexStructure to fix circular dependencies between the two
-template<bool WantsPosition, bool WantsNormal, bool WantsTangent, bool WantsColor, int32 NumWantedUVChannels, ERuntimeMeshVertexTangentBasisType NormalTangentType, ERuntimeMeshVertexUVType UVType>
-RuntimeMeshVertexStructure FRuntimeMeshVertex<WantsPosition, WantsNormal, WantsTangent, WantsColor, NumWantedUVChannels, NormalTangentType, UVType>::GetVertexStructure(const FVertexBuffer& VertexBuffer)
-{
-    return FRuntimeMeshVertexUtilities::CreateVertexStructure<WantsPosition, WantsNormal, WantsTangent, WantsColor, NumWantedUVChannels, NormalTangentType, UVType>(VertexBuffer);
-}
-
-template<bool WantsPosition, bool WantsNormal, bool WantsTangent, ERuntimeMeshVertexTangentBasisType NormalTangentType, ERuntimeMeshVertexUVType UVType>
-RuntimeMeshVertexStructure FRuntimeMeshVertex<WantsPosition, WantsNormal, WantsTangent, false, 0, NormalTangentType, UVType>::GetVertexStructure(const FVertexBuffer& VertexBuffer)
-{
-    return FRuntimeMeshVertexUtilities::CreateVertexStructure<WantsPosition, WantsNormal, WantsTangent, false, 0, NormalTangentType, UVType>(VertexBuffer);
-}
-
-template<bool WantsColor, int32 NumWantedUVChannels, ERuntimeMeshVertexTangentBasisType NormalTangentType, ERuntimeMeshVertexUVType UVType>
-RuntimeMeshVertexStructure FRuntimeMeshVertex<false, false, false, WantsColor, NumWantedUVChannels, NormalTangentType, UVType>::GetVertexStructure(const FVertexBuffer& VertexBuffer)
-{
-    return FRuntimeMeshVertexUtilities::CreateVertexStructure<false, false, false, WantsColor, NumWantedUVChannels, NormalTangentType, UVType>(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)
-
-

+ 0 - 129
spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Public/RuntimeMeshLibrary.h

@@ -1,129 +0,0 @@
-// Copyright 2016 Chris Conway (Koderz). All Rights Reserved.
-
-#pragma once
-
-#include "Kismet/BlueprintFunctionLibrary.h"
-#include "RuntimeMeshComponent.h"
-#include "RuntimeMeshLibrary.generated.h"
-
-class RuntimeMeshComponent;
-
-UCLASS()
-class RUNTIMEMESHCOMPONENT_API URuntimeMeshLibrary : public UBlueprintFunctionLibrary
-{
-	GENERATED_UCLASS_BODY()
-
-	/** Add a quad, specified by four indices, to a triangle index buffer as two triangles. */
-	UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
-	static void ConvertQuadToTriangles(UPARAM(ref) TArray<int32>& Triangles, int32 Vert0, int32 Vert1, int32 Vert2, int32 Vert3);
-
-	/**
-	*	Generate an index buffer for a grid of quads.
-	*	@param	NumX			Number of vertices in X direction (must be >= 2)
-	*	@param	NumY			Number of vertices in y direction (must be >= 2)
-	*	@param	bWinding		Reverses winding of indices generated for each quad
-	*	@out	Triangles		Output index buffer
-	*/
-	UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
-	static void CreateGridMeshTriangles(int32 NumX, int32 NumY, bool bWinding, TArray<int32>& Triangles);
-
-	/** Generate vertex and index buffer for a simple box, given the supplied dimensions. Normals, UVs and tangents are also generated for each vertex. */
-	UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
-	static void CreateBoxMesh(FVector BoxRadius, TArray<FVector>& Vertices, TArray<int32>& Triangles, TArray<FVector>& Normals, TArray<FVector2D>& UVs, TArray<FRuntimeMeshTangent>& Tangents);
-
-
-
-	/**
-	*	Automatically generate normals and tangent vectors for a mesh
-	*	UVs are required for correct tangent generation.
-	*/
-	static void CalculateTangentsForMesh(IRuntimeMeshVerticesBuilder* Vertices, const FRuntimeMeshIndicesBuilder* Triangles);
-
-	/**
-	*	Automatically generate normals and tangent vectors for a mesh
-	*	UVs are required for correct tangent generation.
-	*/
-	template <typename VertexType>
-	static void CalculateTangentsForMesh(TArray<VertexType>& Vertices, const TArray<int32>& Triangles)
-	{
-		FRuntimeMeshPackedVerticesBuilder<VertexType> VerticesBuilder(&Vertices);
-		FRuntimeMeshIndicesBuilder IndicesBuilder(const_cast<TArray<int32>*>(&Triangles));
-
-		CalculateTangentsForMesh(&VerticesBuilder, &IndicesBuilder);
-	}
-
-	/**
-	*	Automatically generate normals and tangent vectors for a mesh
-	*	UVs are required for correct tangent generation.
-	*/
-	template <typename VertexType>
-	static void CalculateTangentsForMesh(TArray<FVector>& Positions, TArray<VertexType>& Vertices, const TArray<int32>& Triangles)
-	{
-		FRuntimeMeshPackedVerticesBuilder<VertexType> VerticesBuilder(&Vertices, &Positions);
-		FRuntimeMeshIndicesBuilder IndicesBuilder(const_cast<TArray<int32>*>(&Triangles));
-
-		CalculateTangentsForMesh(&VerticesBuilder, &IndicesBuilder);
-	}
-
-	/**
-	*	Automatically generate normals and tangent vectors for a mesh
-	*	UVs are required for correct tangent generation.
-	*/
-	UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh", meta = (AutoCreateRefTerm = "UVs"))
-	static void CalculateTangentsForMesh(const TArray<FVector>& Vertices, const TArray<int32>& Triangles, const TArray<FVector2D>& UVs, TArray<FVector>& Normals, TArray<FRuntimeMeshTangent>& Tangents);
-
-
-
-	/**
-	*	Generates the tessellation indices needed to support tessellation in materials
-	*/
-	static void GenerateTessellationIndexBuffer(const IRuntimeMeshVerticesBuilder* Vertices, const FRuntimeMeshIndicesBuilder* Indices, FRuntimeMeshIndicesBuilder* OutTessellationIndices);
-
-	/**
-	*	Generates the tessellation indices needed to support tessellation in materials
-	*/
-	template <typename VertexType>
-	static void GenerateTessellationIndexBuffer(TArray<VertexType>& Vertices, const TArray<int32>& Triangles, TArray<int32>& OutTessTriangles)
-	{
-		FRuntimeMeshPackedVerticesBuilder<VertexType> VerticesBuilder(&Vertices);
-		FRuntimeMeshIndicesBuilder IndicesBuilder(const_cast<TArray<int32>*>(&Triangles));
-		FRuntimeMeshIndicesBuilder OutIndicesBuilder(&OutTessTriangles);
-
-		GenerateTessellationIndexBuffer(&VerticesBuilder, &IndicesBuilder, &OutIndicesBuilder);
-	}
-
-	/**
-	*	Generates the tessellation indices needed to support tessellation in materials
-	*/
-	template <typename VertexType>
-	static void GenerateTessellationIndexBuffer(TArray<FVector>& Positions, TArray<VertexType>& Vertices, const TArray<int32>& Triangles, TArray<int32>& OutTessTriangles)
-	{
-		FRuntimeMeshPackedVerticesBuilder<VertexType> VerticesBuilder(&Vertices, &Positions);
-		FRuntimeMeshIndicesBuilder IndicesBuilder(const_cast<TArray<int32>*>(&Triangles));
-		FRuntimeMeshIndicesBuilder OutIndicesBuilder(&OutTessTriangles);
-
-		GenerateTessellationIndexBuffer(&VerticesBuilder, &IndicesBuilder, &OutIndicesBuilder);
-	}
-
-	/**
-	*	Generates the tessellation indices needed to support tessellation in materials
-	*/
-	UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh", meta = (AutoCreateRefTerm = "UVs"))
-	static void GenerateTessellationIndexBuffer(const TArray<FVector>& Vertices, const TArray<int32>& Triangles, const TArray<FVector2D>& UVs, TArray<FVector>& Normals, TArray<FRuntimeMeshTangent>& Tangents, TArray<int32>& OutTessTriangles);
-
-	
-
-	/** Grab geometry data from a StaticMesh asset. */
-	static void GetSectionFromStaticMesh(UStaticMesh* InMesh, int32 LODIndex, int32 SectionIndex,
-		IRuntimeMeshVerticesBuilder* Vertices, FRuntimeMeshIndicesBuilder* Triangles, FRuntimeMeshIndicesBuilder* AdjacencyTriangles);
-
-	/** Grab geometry data from a StaticMesh asset. */
-	UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
-	static void GetSectionFromStaticMesh(UStaticMesh* InMesh, int32 LODIndex, int32 SectionIndex, TArray<FVector>& Vertices, TArray<int32>& Triangles, TArray<FVector>& Normals, TArray<FVector2D>& UVs, TArray<FRuntimeMeshTangent>& Tangents);
-	
-	/* Copies an entire Static Mesh to a Runtime Mesh. Includes all materials, and sections.*/
-	UFUNCTION(BlueprintCallable, Category = "Components|RuntimeMesh")
-	static void CopyRuntimeMeshFromStaticMeshComponent(UStaticMeshComponent* StaticMeshComp, int32 LODIndex, URuntimeMeshComponent* RuntimeMeshComp, bool bShouldCreateCollision);
-	
-
-};

+ 0 - 74
spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Public/RuntimeMeshProfiling.h

@@ -1,74 +0,0 @@
-// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
-
-#pragma once
-
-#include "RuntimeMeshComponent.h"
-
-DECLARE_STATS_GROUP(TEXT("RuntimeMesh"), STATGROUP_RuntimeMesh, STATCAT_Advanced);
-
-// Scene Proxy Profiling
-DECLARE_CYCLE_STAT(TEXT("Create Section (RT)"), STAT_RuntimeMesh_CreateSection_RenderThread, STATGROUP_RuntimeMesh);
-DECLARE_CYCLE_STAT(TEXT("Update Section (RT)"), STAT_RuntimeMesh_UpdateSection_RenderThread, STATGROUP_RuntimeMesh);
-DECLARE_CYCLE_STAT(TEXT("Update Section - Position Only (RT)"), STAT_RuntimeMesh_UpdateSectionPositionOnly_RenderThread, STATGROUP_RuntimeMesh);
-DECLARE_CYCLE_STAT(TEXT("Update Section Properties (RT)"), STAT_RuntimeMesh_UpdateSectionProperties_RenderThread, STATGROUP_RuntimeMesh);
-
-DECLARE_CYCLE_STAT(TEXT("Apply Batch Update (RT)"), STAT_RuntimeMesh_ApplyBatchUpdate_RenderThread, STATGROUP_RuntimeMesh);
-
-DECLARE_CYCLE_STAT(TEXT("On Transform Changed (RT)"), STAT_RuntimeMesh_OnTransformChanged, STATGROUP_RuntimeMesh);
-DECLARE_CYCLE_STAT(TEXT("Draw Static Elements (RT)"), STAT_RuntimeMesh_DrawStaticElements, STATGROUP_RuntimeMesh);
-DECLARE_CYCLE_STAT(TEXT("Get Dynamic Mesh Elements (RT)"), STAT_RuntimeMesh_GetDynamicMeshElements, STATGROUP_RuntimeMesh);
-
-// RuntimeMeshComponent Profiling
-
-DECLARE_CYCLE_STAT(TEXT("CreateMeshSection<VertexType> (GT)"), STAT_RuntimeMesh_CreateMeshSection_VertexType, STATGROUP_RuntimeMesh);
-DECLARE_CYCLE_STAT(TEXT("CreateMeshSection<VertexType> (With Bounding Box) (GT)"), STAT_RuntimeMesh_CreateMeshSection_VertexType_WithBoundingBox, STATGROUP_RuntimeMesh);
-DECLARE_CYCLE_STAT(TEXT("CreateMeshSectionDualBuffer<VertexType> (GT)"), STAT_RuntimeMesh_CreateMeshSectionDualBuffer_VertexType, STATGROUP_RuntimeMesh);
-DECLARE_CYCLE_STAT(TEXT("CreateMeshSectionDualBuffer<VertexType> (With Bounding Box) (GT)"), STAT_RuntimeMesh_CreateMeshSectionDualBuffer_VertexType_WithBoundingBox, STATGROUP_RuntimeMesh);
-DECLARE_CYCLE_STAT(TEXT("CreateMeshSection<VertexType> (From Mesh Builder) (GT)"), STAT_RuntimeMesh_CreateMeshSection_VertexType_FromMeshBuilder, STATGROUP_RuntimeMesh);
-
-
-
-DECLARE_CYCLE_STAT(TEXT("CreateMeshSection (GT)"), STAT_RuntimeMesh_CreateMeshSection, STATGROUP_RuntimeMesh);
-DECLARE_CYCLE_STAT(TEXT("CreateMeshSection (GT)"), STAT_RuntimeMesh_CreateMeshSection_DualUV, STATGROUP_RuntimeMesh);
-
-DECLARE_CYCLE_STAT(TEXT("UpdateMeshSection<VertexType> (GT)"), STAT_RuntimeMesh_UpdateMeshSection_VertexType, STATGROUP_RuntimeMesh);
-DECLARE_CYCLE_STAT(TEXT("UpdateMeshSection<VertexType> (With Bounding Box) (GT)"), STAT_RuntimeMesh_UpdateMeshSection_VertexType_WithBoundingBox, STATGROUP_RuntimeMesh);
-DECLARE_CYCLE_STAT(TEXT("UpdateMeshSection<VertexType> (With Triangles) (GT)"), STAT_RuntimeMesh_UpdateMeshSection_VertexType_WithTriangles, STATGROUP_RuntimeMesh);
-DECLARE_CYCLE_STAT(TEXT("UpdateMeshSection<VertexType> (With Triangles and Bounding Box) (GT)"), STAT_RuntimeMesh_UpdateMeshSection_VertexType_WithTrianglesAndBoundinBox, STATGROUP_RuntimeMesh);
-
-DECLARE_CYCLE_STAT(TEXT("UpdateMeshSection<VertexType> (Dual) (GT)"), STAT_RuntimeMesh_UpdateMeshSection_Dual_VertexType, STATGROUP_RuntimeMesh);
-DECLARE_CYCLE_STAT(TEXT("UpdateMeshSection<VertexType> (Dual) (With Bounding Box) (GT)"), STAT_RuntimeMesh_UpdateMeshSection_Dual_VertexType_WithBoundingBox, STATGROUP_RuntimeMesh);
-DECLARE_CYCLE_STAT(TEXT("UpdateMeshSection<VertexType> (Dual) (With Triangles) (GT)"), STAT_RuntimeMesh_UpdateMeshSection_Dual_VertexType_WithTriangles, STATGROUP_RuntimeMesh);
-DECLARE_CYCLE_STAT(TEXT("UpdateMeshSection<VertexType> (Dual) (With Triangles and Bounding Box) (GT)"), STAT_RuntimeMesh_UpdateMeshSection_Dual_VertexType_WithTrianglesAndBoundinBox, STATGROUP_RuntimeMesh);
-
-DECLARE_CYCLE_STAT(TEXT("UpdateMeshSection (GT)"), STAT_RuntimeMesh_UpdateMeshSection, STATGROUP_RuntimeMesh);
-DECLARE_CYCLE_STAT(TEXT("UpdateMeshSection (GT)"), STAT_RuntimeMesh_UpdateMeshSection_DualUV, STATGROUP_RuntimeMesh);
-
-
-
-
-
-
-
-DECLARE_CYCLE_STAT(TEXT("UpdateMeshSectionPositionsImmediate (GT)"), STAT_RuntimeMesh_UpdateMeshSectionPositionsImmediate, STATGROUP_RuntimeMesh);
-DECLARE_CYCLE_STAT(TEXT("UpdateMeshSectionPositionsImmediate (With Bounding Box) (GT)"), STAT_RuntimeMesh_UpdateMeshSectionPositionsImmediate_WithBoundinBox, STATGROUP_RuntimeMesh);
-
-DECLARE_CYCLE_STAT(TEXT("Finish Create Section (GT)"), STAT_RuntimeMesh_FinishCreateSectionInternal, STATGROUP_RuntimeMesh);
-DECLARE_CYCLE_STAT(TEXT("Finish Update Section (GT)"), STAT_RuntimeMesh_FinishUpdateSectionInternal, STATGROUP_RuntimeMesh);
-DECLARE_CYCLE_STAT(TEXT("Clear Mesh Section (GT)"), STAT_RuntimeMesh_ClearMeshSection, STATGROUP_RuntimeMesh);
-
-
-DECLARE_CYCLE_STAT(TEXT("Set Mesh Collision Section (GT)"), STAT_RuntimeMesh_SetMeshCollisionSection, STATGROUP_RuntimeMesh);
-DECLARE_CYCLE_STAT(TEXT("Clear Mesh Collision Section (GT)"), STAT_RuntimeMesh_ClearMeshCollisionSection, STATGROUP_RuntimeMesh);
-DECLARE_CYCLE_STAT(TEXT("Clear All Mesh Collision Sections (GT)"), STAT_RuntimeMesh_ClearAllMeshCollisionSections, STATGROUP_RuntimeMesh);
-DECLARE_CYCLE_STAT(TEXT("Add Collision Convex Mesh (GT)"), STAT_RuntimeMesh_AddCollisionConvexMesh, STATGROUP_RuntimeMesh);
-DECLARE_CYCLE_STAT(TEXT("Clear Collision Convex Mesh (GT)"), STAT_RuntimeMesh_ClearCollisionConvexMeshes, STATGROUP_RuntimeMesh);
-DECLARE_CYCLE_STAT(TEXT("Set Collision Convex Meshes (GT)"), STAT_RuntimeMesh_SetCollisionConvexMeshes, STATGROUP_RuntimeMesh);
-DECLARE_CYCLE_STAT(TEXT("Create Scene Proxy (GT)"), STAT_RuntimeMesh_CreateSceneProxy, STATGROUP_RuntimeMesh);
-DECLARE_CYCLE_STAT(TEXT("Get Physics TriMesh Data (GT)"), STAT_RuntimeMesh_GetPhysicsTriMeshData, STATGROUP_RuntimeMesh);
-DECLARE_CYCLE_STAT(TEXT("Update Collision (GT)"), STAT_RuntimeMesh_UpdateCollision, STATGROUP_RuntimeMesh);
-DECLARE_CYCLE_STAT(TEXT("Update Local Bounds (GT)"), STAT_RuntimeMesh_UpdateLocalBounds, STATGROUP_RuntimeMesh);
-DECLARE_CYCLE_STAT(TEXT("Serialize"), STAT_RuntimeMesh_Serialize, STATGROUP_RuntimeMesh);
-
-
-

+ 0 - 187
spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Public/RuntimeMeshRendering.h

@@ -1,187 +0,0 @@
-// Copyright 2016 Chris Conway (Koderz). All Rights Reserved.
-
-#pragma once
-
-#include "Engine.h"
-#include "RuntimeMeshCore.h"
-
-
-#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION >= 12
-/** Structure definition of a vertex */
-using RuntimeMeshVertexStructure = FLocalVertexFactory::FDataType;
-#else
-/** Structure definition of a vertex */
-using RuntimeMeshVertexStructure = FLocalVertexFactory::DataType;
-#endif
-
-#define RUNTIMEMESH_VERTEXCOMPONENT(VertexBuffer, VertexType, Member, MemberType) \
-	STRUCTMEMBER_VERTEXSTREAMCOMPONENT(&VertexBuffer, VertexType, Member, MemberType)
-
-
-/* 
- *	Defines an interface for the proxy sections so that 
- *	the vertex factory can query for section visibility 
- */
-class FRuntimeMeshVisibilityInterface
-{
-public:
-	virtual bool ShouldRender() = 0;
-};
-
-
-/** Vertex Buffer for one section. Templated to support different vertex types */
-template<typename VertexType>
-class FRuntimeMeshVertexBuffer : public FVertexBuffer
-{
-public:
-
-	FRuntimeMeshVertexBuffer(EUpdateFrequency SectionUpdateFrequency) : VertexCount(0)
-	{
-		UsageFlags = SectionUpdateFrequency == EUpdateFrequency::Frequent ? BUF_Dynamic : BUF_Static;
-	}
-
-	virtual void InitRHI() override
-	{
-		// Create the vertex buffer
-		FRHIResourceCreateInfo CreateInfo;
-		VertexBufferRHI = RHICreateVertexBuffer(sizeof(VertexType) * VertexCount, UsageFlags, CreateInfo);
-	}
-
-	/* Get the size of the vertex buffer */
-	int32 Num() { return VertexCount; }
-	
-	/* Set the size of the vertex buffer */
-	void SetNum(int32 NewVertexCount)
-	{
-		check(NewVertexCount != 0);
-
-		// Make sure we're not already the right size
-		if (NewVertexCount != VertexCount)
-		{
-			VertexCount = NewVertexCount;
-			
-			// Rebuild resource
-			ReleaseResource();
-			InitResource();
-		}
-	}
-
-	/* Set the data for the vertex buffer */
-	void SetData(const TArray<VertexType>& Data)
-	{
-		check(Data.Num() == VertexCount);
-
-		// Lock the vertex buffer
- 		void* Buffer = RHILockVertexBuffer(VertexBufferRHI, 0, Data.Num() * sizeof(VertexType), RLM_WriteOnly);
- 		 
- 		// Write the vertices to the vertex buffer
- 		FMemory::Memcpy(Buffer, Data.GetData(), Data.Num() * sizeof(VertexType));
-
-		// Unlock the vertex buffer
- 		RHIUnlockVertexBuffer(VertexBufferRHI);
-	}
-
-private:
-
-	/* The number of vertices this buffer is currently allocated to hold */
-	int32 VertexCount;
-	/* The buffer configuration to use */
-	EBufferUsageFlags UsageFlags;
-};
-
-/** Index Buffer */
-class FRuntimeMeshIndexBuffer : public FIndexBuffer
-{
-public:
-
-	FRuntimeMeshIndexBuffer(EUpdateFrequency SectionUpdateFrequency) : IndexCount(0)
-	{
-		UsageFlags = SectionUpdateFrequency == EUpdateFrequency::Frequent ? BUF_Dynamic : BUF_Static;
-	}
-
-	virtual void InitRHI() override
-	{
-		// Create the index buffer
-		FRHIResourceCreateInfo CreateInfo;
-		IndexBufferRHI = RHICreateIndexBuffer(sizeof(int32), IndexCount * sizeof(int32), BUF_Dynamic, CreateInfo);
-	}
-
-	/* Get the size of the index buffer */
-	int32 Num() { return IndexCount; }
-
-	/* Set the size of the index buffer */
-	void SetNum(int32 NewIndexCount)
-	{
-		check(NewIndexCount != 0);
-
-		// Make sure we're not already the right size
-		if (NewIndexCount != IndexCount)
-		{
-			IndexCount = NewIndexCount;
-
-			// Rebuild resource
-			ReleaseResource();
-			InitResource();
-		}
-	}
-
-	/* Set the data for the index buffer */
-	void SetData(const TArray<int32>& Data)
-	{
-		check(Data.Num() == IndexCount);
-
-		// Lock the index buffer
-		void* Buffer = RHILockIndexBuffer(IndexBufferRHI, 0, IndexCount * sizeof(int32), RLM_WriteOnly);
-
-		// Write the indices to the vertex buffer	
-		FMemory::Memcpy(Buffer, Data.GetData(), Data.Num() * sizeof(int32));
-
-		// Unlock the index buffer
-		RHIUnlockIndexBuffer(IndexBufferRHI);
-	}
-
-private:
-
-	/* The number of indices this buffer is currently allocated to hold */
-	int32 IndexCount;
-	/* The buffer configuration to use */
-	EBufferUsageFlags UsageFlags;
-};
-
-/** Vertex Factory */
-class FRuntimeMeshVertexFactory : public FLocalVertexFactory
-{
-public:
-
-	FRuntimeMeshVertexFactory(FRuntimeMeshVisibilityInterface* InSectionParent) : SectionParent(InSectionParent) { }
-		
-	/** Init function that can be called on any thread, and will do the right thing (enqueue command if called on main thread) */
-	void Init(const RuntimeMeshVertexStructure VertexStructure)
-	{
-		if (IsInRenderingThread())
-		{
-			SetData(VertexStructure);
-		}
-		else
-		{
-			// Send the command to the render thread
-			ENQUEUE_UNIQUE_RENDER_COMMAND_TWOPARAMETER(
-				InitRuntimeMeshVertexFactory,
-				FRuntimeMeshVertexFactory*, VertexFactory, this,
-				const RuntimeMeshVertexStructure, VertexStructure, VertexStructure,
-				{
-					VertexFactory->Init(VertexStructure);
-				});
-		}
-	}
-
-	/* Gets the section visibility for static sections */
-	virtual uint64 GetStaticBatchElementVisibility(const class FSceneView& View, const struct FMeshBatch* Batch) const override
-	{
-		return SectionParent->ShouldRender();
-	}
-
-private:
-	/* Interface to the parent section for checking visibility.*/
-	FRuntimeMeshVisibilityInterface* SectionParent;
-};

+ 0 - 812
spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Public/RuntimeMeshSection.h

@@ -1,812 +0,0 @@
-// Copyright 2016 Chris Conway (Koderz). All Rights Reserved.
-
-#pragma once
-
-#include "Engine.h"
-#include "Components/MeshComponent.h"
-#include "RuntimeMeshProfiling.h"
-#include "RuntimeMeshVersion.h"
-#include "RuntimeMeshSectionProxy.h"
-#include "RuntimeMeshBuilder.h"
-#include "RuntimeMeshLibrary.h"
-
-/** Interface class for a single mesh section */
-class FRuntimeMeshSectionInterface
-{
-protected:
-	const bool bNeedsPositionOnlyBuffer;
-
-public:
-	/** Position only vertex buffer for this section */
-	TArray<FVector> PositionVertexBuffer;
-
-	/** Index buffer for this section */
-	TArray<int32> IndexBuffer;
-
-	/** Index buffer used for tessellation containing the needed adjacency info */
-	TArray<int32> TessellationIndexBuffer;
-
-	/** Local bounding box of section */
-	FBox LocalBoundingBox;
-
-	/** Should we build collision data for triangles in this section */
-	bool CollisionEnabled;
-
-	/** Should we display this section */
-	bool bIsVisible;
-
-	/** Should this section cast a shadow */
-	bool bCastsShadow;
-
-	/** If this section is currently using an adjacency index buffer */
-	bool bShouldUseAdjacencyIndexBuffer;
-
-	/** Update frequency of this section */
-	EUpdateFrequency UpdateFrequency;
-
-	FRuntimeMeshSectionInterface(bool bInNeedsPositionOnlyBuffer) : 
-		bNeedsPositionOnlyBuffer(bInNeedsPositionOnlyBuffer),
-		LocalBoundingBox(EForceInit::ForceInitToZero),
-		CollisionEnabled(false),
-		bIsVisible(true),
-		bCastsShadow(true),
-		bIsLegacySectionType(false)
-	{}
-
-	virtual ~FRuntimeMeshSectionInterface() { }
-
-protected:
-
-	/** Is this an internal section type. */
-	bool bIsLegacySectionType;
-
-	bool IsDualBufferSection() const { return bNeedsPositionOnlyBuffer; }
-
-	/* Updates the vertex position buffer,   returns whether we have a new bounding box */
-	bool UpdateVertexPositionBuffer(TArray<FVector>& Positions, const FBox* BoundingBox, bool bShouldMoveArray)
-	{
-		// Holds the new bounding box after this update.
-		FBox NewBoundingBox(EForceInit::ForceInitToZero);
-
-		if (bShouldMoveArray)
-		{
-			// Move buffer data
-			PositionVertexBuffer = MoveTemp(Positions);
-
-			// Calculate the bounding box if one doesn't exist.
-			if (BoundingBox == nullptr)
-			{
-				for (int32 VertexIdx = 0; VertexIdx < PositionVertexBuffer.Num(); VertexIdx++)
-				{
-					NewBoundingBox += PositionVertexBuffer[VertexIdx];
-				}
-			}
-			else
-			{
-				// Copy the supplied bounding box instead of calculating it.
-				NewBoundingBox = *BoundingBox;
-			}
-		}
-		else
-		{
-			if (BoundingBox == nullptr)
-			{
-				// Copy the buffer and calculate the bounding box at the same time
-				int32 NumVertices = Positions.Num();
-				PositionVertexBuffer.SetNumUninitialized(NumVertices);
-				for (int32 VertexIdx = 0; VertexIdx < NumVertices; VertexIdx++)
-				{
-					NewBoundingBox += Positions[VertexIdx];
-					PositionVertexBuffer[VertexIdx] = Positions[VertexIdx];
-				}
-			}
-			else
-			{
-				// Copy the buffer
-				PositionVertexBuffer = Positions;
-
-				// Copy the supplied bounding box instead of calculating it.
-				NewBoundingBox = *BoundingBox;
-			}
-		}
-
-		// Update the bounding box if necessary and alert our caller if we did
-		if (!(LocalBoundingBox == NewBoundingBox))
-		{
-			LocalBoundingBox = NewBoundingBox;
-			return true;
-		}
-
-		return false;
-	}
-
-	virtual void UpdateVertexBuffer(IRuntimeMeshVerticesBuilder& Vertices, const FBox* BoundingBox, bool bShouldMoveArray) = 0;
-
-	void UpdateIndexBuffer(TArray<int32>& Triangles, bool bShouldMoveArray)
-	{
-		if (bShouldMoveArray)
-		{
-			IndexBuffer = MoveTemp(Triangles);
-		}
-		else
-		{
-			IndexBuffer = Triangles;
-		}
-	}
-
-	void UpdateIndexBuffer(FRuntimeMeshIndicesBuilder& Triangles, bool bShouldMoveArray)
-	{
-		if (bShouldMoveArray)
-		{
-			IndexBuffer = MoveTemp(*Triangles.GetIndices());
-			Triangles.Reset();
-		}
-		else
-		{
-			IndexBuffer = *Triangles.GetIndices();
-		}
-	}
-
-	void UpdateTessellationIndexBuffer(TArray<int32>& Triangles, bool bShouldMoveArray)
-	{
-		if (bShouldMoveArray)
-		{
-			TessellationIndexBuffer = MoveTemp(Triangles);
-		}
-		else
-		{
-			TessellationIndexBuffer = Triangles;
-		}
-	}
-
-	virtual FRuntimeMeshSectionCreateDataInterface* GetSectionCreationData(FSceneInterface* InScene, UMaterialInterface* InMaterial) const = 0;
-
-	virtual FRuntimeMeshRenderThreadCommandInterface* GetSectionUpdateData(bool bIncludePositionVertices, bool bIncludeVertices, bool bIncludeIndices) const = 0;
-
-	virtual FRuntimeMeshRenderThreadCommandInterface* GetSectionPositionUpdateData() const = 0;
-
-	virtual void RecalculateBoundingBox() = 0;
-
-#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION >= 13
-	virtual int32 GetCollisionInformation(TArray<FVector>& Positions, TArray<TArray<FVector2D>>& UVs, bool bIncludeUVs) = 0;
-#else
-	virtual int32 GetCollisionInformation(TArray<FVector>& Positions) = 0;
-#endif
-
-	virtual void GetInternalVertexComponents(int32& NumUVChannels, bool& WantsHalfPrecisionUVs) { }
-
-	// This is only meant for internal use for supporting the old style create/update sections
-	virtual bool UpdateVertexBufferInternal(const TArray<FVector>& Positions, const TArray<FVector>& Normals, const TArray<FRuntimeMeshTangent>& Tangents, const TArray<FVector2D>& UV0, const TArray<FVector2D>& UV1, const TArray<FColor>& Colors) { return false; }
-	
-	virtual void GetSectionMesh(IRuntimeMeshVerticesBuilder*& Vertices, FRuntimeMeshIndicesBuilder*& Indices) = 0;
-
-	virtual const FRuntimeMeshVertexTypeInfo* GetVertexType() const = 0;
-
-	virtual void GenerateNormalTangent() = 0;
-
-	virtual void GenerateTessellationIndices() = 0;
-
-
-	virtual void Serialize(FArchive& Ar)
-	{
-		if (Ar.CustomVer(FRuntimeMeshVersion::GUID) >= FRuntimeMeshVersion::SerializationV2)
-		{
-			if (bNeedsPositionOnlyBuffer)
-			{
-				Ar << PositionVertexBuffer;
-			}
-			Ar << IndexBuffer;
-			Ar << TessellationIndexBuffer;
-			Ar << LocalBoundingBox;
-			Ar << CollisionEnabled;
-			Ar << bIsVisible;
-			Ar << bCastsShadow;
-			Ar << bShouldUseAdjacencyIndexBuffer;
-
-			// Serialize the update frequency as an int32
-			int32 UpdateFreq = (int32)UpdateFrequency;
-			Ar << UpdateFreq;
-			UpdateFrequency = (EUpdateFrequency)UpdateFreq;
-
-			Ar << bIsLegacySectionType;
-		}
-		else
-		{
-			if (Ar.CustomVer(FRuntimeMeshVersion::GUID) >= FRuntimeMeshVersion::DualVertexBuffer)
-			{
-				Ar << PositionVertexBuffer;
-			}
-			Ar << IndexBuffer;
-			Ar << LocalBoundingBox;
-			Ar << CollisionEnabled;
-			Ar << bIsVisible;
-			int32 UpdateFreq = (int32)UpdateFrequency;
-			Ar << UpdateFreq;
-			UpdateFrequency = (EUpdateFrequency)UpdateFreq;
-		}
-	}
-
-	
-
-	friend class FRuntimeMeshSceneProxy;
-	friend class URuntimeMeshComponent;
-};
-
-namespace RuntimeMeshSectionInternal
-{
-	template<typename Type>
-	static typename TEnableIf<FRuntimeMeshVertexTraits<Type>::HasPosition, int32>::Type
-		GetAllVertexPositions(const TArray<Type>& VertexBuffer, const TArray<FVector>& PositionVertexBuffer, TArray<FVector>& Positions)
-	{
-		int32 VertexCount = VertexBuffer.Num();
-		for (int32 VertIdx = 0; VertIdx < VertexCount; VertIdx++)
-		{
-			Positions.Add(VertexBuffer[VertIdx].Position);
-		}
-		return VertexCount;
-	}
-
-	template<typename Type>
-	static typename TEnableIf<!FRuntimeMeshVertexTraits<Type>::HasPosition, int32>::Type
-		GetAllVertexPositions(const TArray<Type>& VertexBuffer, const TArray<FVector>& PositionVertexBuffer, TArray<FVector>& Positions)
-	{
-		Positions.Append(PositionVertexBuffer);
-		return PositionVertexBuffer.Num();
-	}
-
-
-
-	template<typename Type>
-	static typename TEnableIf<FRuntimeMeshVertexTraits<Type>::HasPosition, bool>::Type
-		UpdateVertexBufferInternal(TArray<Type>& VertexBuffer, FBox& LocalBoundingBox, TArray<Type>& Vertices, const FBox* BoundingBox, bool bShouldMoveArray)
-	{
-		// Holds the new bounding box after this update.
-		FBox NewBoundingBox(EForceInit::ForceInitToZero);
-
-		if (bShouldMoveArray)
-		{
-			// Move buffer data
-			VertexBuffer = MoveTemp(Vertices);
-
-			// Calculate the bounding box if one doesn't exist.
-			if (BoundingBox == nullptr)
-			{
-				for (int32 VertexIdx = 0; VertexIdx < VertexBuffer.Num(); VertexIdx++)
-				{
-					NewBoundingBox += VertexBuffer[VertexIdx].Position;
-				}
-			}
-			else
-			{
-				// Copy the supplied bounding box instead of calculating it.
-				NewBoundingBox = *BoundingBox;
-			}
-		}
-		else
-		{
-			if (BoundingBox == nullptr)
-			{
-				// Copy the buffer and calculate the bounding box at the same time
-				int32 NumVertices = Vertices.Num();
-				VertexBuffer.SetNumUninitialized(NumVertices);
-				for (int32 VertexIdx = 0; VertexIdx < NumVertices; VertexIdx++)
-				{
-					NewBoundingBox += Vertices[VertexIdx].Position;
-					VertexBuffer[VertexIdx] = Vertices[VertexIdx];
-				}
-			}
-			else
-			{
-				// Copy the buffer
-				VertexBuffer = Vertices;
-
-				// Copy the supplied bounding box instead of calculating it.
-				NewBoundingBox = *BoundingBox;
-			}
-		}
-
-		// Update the bounding box if necessary and alert our caller if we did
-		if (!(LocalBoundingBox == NewBoundingBox))
-		{
-			LocalBoundingBox = NewBoundingBox;
-			return true;
-		}
-
-		return false;
-	}
-
-	template<typename Type>
-	static typename TEnableIf<!FRuntimeMeshVertexTraits<Type>::HasPosition, bool>::Type
-		UpdateVertexBufferInternal(TArray<Type>& VertexBuffer, FBox& LocalBoundingBox, TArray<Type>& Vertices, const FBox* BoundingBox, bool bShouldMoveArray)
-	{
-		if (bShouldMoveArray)
-		{
-			VertexBuffer = MoveTemp(Vertices);
-		}
-		else
-		{
-			VertexBuffer = Vertices;
-		}
-		return false;
-	}
-
-
-	template<typename Type>
-	static typename TEnableIf<FRuntimeMeshVertexTraits<Type>::HasPosition>::Type RecalculateBoundingBox(TArray<Type>& VertexBuffer, FBox& BoundingBox)
-	{
-		for (int32 Index = 0; Index < VertexBuffer.Num(); Index++)
-		{
-			BoundingBox += VertexBuffer[Index].Position;
-		}
-	}
-
-	template<typename Type>
-	static typename TEnableIf<!FRuntimeMeshVertexTraits<Type>::HasPosition>::Type RecalculateBoundingBox(TArray<Type>& VertexBuffer, FBox& BoundingBox)
-	{
-	}
-
-}
-
-/** Templated class for a single mesh section */
-template<typename VertexType>
-class FRuntimeMeshSection : public FRuntimeMeshSectionInterface
-{
-
-public:
-	/** Vertex buffer for this section */
-	TArray<VertexType> VertexBuffer;
-
-	FRuntimeMeshSection(bool bInNeedsPositionOnlyBuffer) : FRuntimeMeshSectionInterface(bInNeedsPositionOnlyBuffer) { }
-	virtual ~FRuntimeMeshSection() override { }
-
-
-protected:
-	bool UpdateVertexBuffer(TArray<VertexType>& Vertices, const FBox* BoundingBox, bool bShouldMoveArray)
-	{
-		return RuntimeMeshSectionInternal::UpdateVertexBufferInternal<VertexType>(VertexBuffer, LocalBoundingBox, Vertices, BoundingBox, bShouldMoveArray);
-	}
-
-	virtual void UpdateVertexBuffer(IRuntimeMeshVerticesBuilder& Vertices, const FBox* BoundingBox, bool bShouldMoveArray) override
-	{
-		if (Vertices.GetBuilderType() == ERuntimeMeshVerticesBuilderType::Component)
-		{
-			FRuntimeMeshComponentVerticesBuilder* VerticesBuilder = static_cast<FRuntimeMeshComponentVerticesBuilder*>(&Vertices);
-
-			TArray<FVector>* Positions = VerticesBuilder->GetPositions();
-			TArray<FVector>* Normals = VerticesBuilder->GetNormals();
-			TArray<FRuntimeMeshTangent>* Tangents = VerticesBuilder->GetTangents();
-			TArray<FColor>* Colors = VerticesBuilder->GetColors();
-			TArray<FVector2D>* UV0s = VerticesBuilder->GetUV0s();
-			TArray<FVector2D>* UV1s = VerticesBuilder->GetUV1s();
-					
-
-			UpdateVertexBufferInternal(
-				Positions ? *Positions : TArray<FVector>(),
-				Normals ? *Normals : TArray<FVector>(),
-				Tangents ? *Tangents : TArray<FRuntimeMeshTangent>(),
-				UV0s ? *UV0s : TArray<FVector2D>(),
-				UV1s ? *UV1s : TArray<FVector2D>(),
-				Colors ? *Colors : TArray<FColor>());
-
-			if (BoundingBox)
-			{
-				LocalBoundingBox = *BoundingBox;
-			}
-			else
-			{
-				LocalBoundingBox = FBox(*Positions);
-			}
-
-			if (bShouldMoveArray)
-			{
-				// This is just to keep similar behavior to the packed vertices builder.
-				Vertices.Reset();
-			}
-		}
-		else
-		{
-			// Make sure section type is the same
-			Vertices.GetVertexType()->EnsureEquals<VertexType>();
-
-			FRuntimeMeshPackedVerticesBuilder<VertexType>* VerticesBuilder = static_cast<FRuntimeMeshPackedVerticesBuilder<VertexType>*>(&Vertices);
-
-			RuntimeMeshSectionInternal::UpdateVertexBufferInternal<VertexType>(VertexBuffer, LocalBoundingBox, *VerticesBuilder->GetVertices(), BoundingBox, bShouldMoveArray);
-
-			if (BoundingBox == nullptr && VerticesBuilder->WantsSeparatePositionBuffer())
-			{
-				LocalBoundingBox = FBox(*VerticesBuilder->GetPositions());
-			}
-		}	
-	}
-
-	virtual FRuntimeMeshSectionCreateDataInterface* GetSectionCreationData(FSceneInterface* InScene, UMaterialInterface* InMaterial) const override
-	{
-		auto UpdateData = new FRuntimeMeshSectionCreateData<VertexType>();
-
-		FMaterialRelevance MaterialRelevance = (InMaterial != nullptr) 
-			? InMaterial->GetRelevance(InScene->GetFeatureLevel()) 
-			: UMaterial::GetDefaultMaterial(MD_Surface)->GetRelevance(InScene->GetFeatureLevel());
-
-		// Create new section proxy based on whether we need separate position buffer
-		if (IsDualBufferSection())
-		{
-			UpdateData->NewProxy = new FRuntimeMeshSectionProxy<VertexType, true>(InScene, UpdateFrequency, bIsVisible, bCastsShadow, InMaterial, MaterialRelevance);
-			UpdateData->PositionVertexBuffer = PositionVertexBuffer;
-		}
-		else
-		{
-			UpdateData->NewProxy = new FRuntimeMeshSectionProxy<VertexType, false>(InScene, UpdateFrequency, bIsVisible, bCastsShadow, InMaterial, MaterialRelevance);
-		}
-		const_cast<FRuntimeMeshSection*>(this)->bShouldUseAdjacencyIndexBuffer = UpdateData->NewProxy->ShouldUseAdjacencyIndexBuffer();
-
-		UpdateData->VertexBuffer = VertexBuffer;
-
-		// Switch between normal/tessellation indices
-
-		if (bShouldUseAdjacencyIndexBuffer && TessellationIndexBuffer.Num() > 0)
-		{
-			UpdateData->IndexBuffer = TessellationIndexBuffer;
-			UpdateData->bIsAdjacencyIndexBuffer = true;
-		}
-		else
-		{
-			UpdateData->IndexBuffer = IndexBuffer;
-			UpdateData->bIsAdjacencyIndexBuffer = false;
-		}
-
-		return UpdateData;
-	}
-
-	virtual FRuntimeMeshRenderThreadCommandInterface* GetSectionUpdateData(bool bIncludePositionVertices, bool bIncludeVertices, bool bIncludeIndices) const override
-	{
-		auto UpdateData = new FRuntimeMeshSectionUpdateData<VertexType>();
-		UpdateData->bIncludeVertexBuffer = bIncludeVertices;
-		UpdateData->bIncludePositionBuffer = bIncludePositionVertices;
-		UpdateData->bIncludeIndices = bIncludeIndices;
-
-		if (bIncludePositionVertices)
-		{
-			UpdateData->PositionVertexBuffer = PositionVertexBuffer;
-		}
-
-		if (bIncludeVertices)
-		{
-			UpdateData->VertexBuffer = VertexBuffer;
-		}
-
-		if (bIncludeIndices)
-		{
-			if (bShouldUseAdjacencyIndexBuffer && TessellationIndexBuffer.Num() > 0)
-			{
-				UpdateData->IndexBuffer = TessellationIndexBuffer;
-				UpdateData->bIsAdjacencyIndexBuffer = true;
-			}
-			else
-			{
-				UpdateData->IndexBuffer = IndexBuffer;
-				UpdateData->bIsAdjacencyIndexBuffer = false;
-			}
-		}
-
-		return UpdateData;
-	}
-
-	virtual FRuntimeMeshRenderThreadCommandInterface* GetSectionPositionUpdateData() const override
-	{
-		auto UpdateData = new FRuntimeMeshSectionPositionOnlyUpdateData<VertexType>();
-
-		UpdateData->PositionVertexBuffer = PositionVertexBuffer;
-
-		return UpdateData;
-	}
-
-#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION >= 13
-	virtual int32 GetCollisionInformation(TArray<FVector>& Positions, TArray<TArray<FVector2D>>& UVs, bool bIncludeUVs) override
-#else
-	virtual int32 GetCollisionInformation(TArray<FVector>& Positions) override
-#endif
-	{
-		FRuntimeMeshPackedVerticesBuilder<VertexType> VerticesBuilder(&VertexBuffer, bNeedsPositionOnlyBuffer ? &PositionVertexBuffer : nullptr);
-
-		int32 PositionStart = Positions.Num();
-		Positions.SetNum(PositionStart + VerticesBuilder.Length());
-
-#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION >= 13
-		if (bIncludeUVs)
-		{
-			UVs[0].SetNumZeroed(PositionStart + VerticesBuilder.Length());
-		}
-#endif
-
-		for (int VertexIdx = 0; VertexIdx < VerticesBuilder.Length(); VertexIdx++)
-		{
-			Positions[PositionStart + VertexIdx] = VerticesBuilder.GetPosition(VertexIdx);
-
-#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION >= 13
-			if (bIncludeUVs && VerticesBuilder.HasUVComponent(0))
-			{
-				UVs[0][PositionStart + VertexIdx] = VerticesBuilder.GetUV(0);
-			}
-#endif
-		}
-
-		return VerticesBuilder.Length();
-	}
-
-	virtual void GetSectionMesh(IRuntimeMeshVerticesBuilder*& Vertices, FRuntimeMeshIndicesBuilder*& Indices) override
-	{
-		Vertices = new FRuntimeMeshPackedVerticesBuilder<VertexType>(&VertexBuffer);
-		Indices = new FRuntimeMeshIndicesBuilder(&IndexBuffer);
-	}
-
-	virtual const FRuntimeMeshVertexTypeInfo* GetVertexType() const { return &VertexType::TypeInfo; }
-
-	virtual void GenerateNormalTangent()
-	{
-		if (IsDualBufferSection())
-		{
-			URuntimeMeshLibrary::CalculateTangentsForMesh<VertexType>(PositionVertexBuffer, VertexBuffer, IndexBuffer);
-		}
-		else
-		{
-			URuntimeMeshLibrary::CalculateTangentsForMesh<VertexType>(VertexBuffer, IndexBuffer);
-		}
-	}
-
-	virtual void GenerateTessellationIndices()
-	{
-		TArray<int32> TessellationIndices;
-		if (IsDualBufferSection())
-		{
-			URuntimeMeshLibrary::GenerateTessellationIndexBuffer<VertexType>(PositionVertexBuffer, VertexBuffer, IndexBuffer, TessellationIndices);
-		}
-		else
-		{
-			URuntimeMeshLibrary::GenerateTessellationIndexBuffer<VertexType>(VertexBuffer, IndexBuffer, TessellationIndices);
-		}
-		UpdateTessellationIndexBuffer(TessellationIndices, true);
-	}
-
-	virtual void RecalculateBoundingBox() override
-	{
-		LocalBoundingBox.Init();
-
-		if (IsDualBufferSection())
-		{
-			for (int32 Index = 0; Index < PositionVertexBuffer.Num(); Index++)
-			{
-				LocalBoundingBox += PositionVertexBuffer[Index];
-			}
-		}
-		else
-		{
-			RuntimeMeshSectionInternal::RecalculateBoundingBox<VertexType>(VertexBuffer, LocalBoundingBox);
-		}
-	}
-
-	virtual void GetInternalVertexComponents(int32& NumUVChannels, bool& WantsHalfPrecisionUVs) override
-	{
-		NumUVChannels = FRuntimeMeshVertexTraits<VertexType>::NumUVChannels;
-		WantsHalfPrecisionUVs = !FRuntimeMeshVertexTraits<VertexType>::HasHighPrecisionUVs;
-	}
-
-	virtual bool UpdateVertexBufferInternal(const TArray<FVector>& Positions, const TArray<FVector>& Normals, const TArray<FRuntimeMeshTangent>& Tangents, const TArray<FVector2D>& UV0, const TArray<FVector2D>& UV1, const TArray<FColor>& Colors) override
-	{
-		// Check existence of data components
-		const bool HasPositions = Positions.Num() > 0;
-
-		int32 NewVertexCount = HasPositions ? Positions.Num() : VertexBuffer.Num();
-		int32 OldVertexCount = FMath::Min(VertexBuffer.Num(), NewVertexCount);
-
-		// Size the vertex buffer correctly
-		if (NewVertexCount != VertexBuffer.Num())
-		{
-			VertexBuffer.SetNumZeroed(NewVertexCount);
-		}
-
-		// Clear the bounding box if we have new positions
-		if (HasPositions)
-		{
-			LocalBoundingBox.Init();
-		}
-
-		FRuntimeMeshPackedVerticesBuilder<VertexType> VerticesBuilder(&VertexBuffer);
-				
-		// Loop through existing range to update data
-		for (int32 VertexIdx = 0; VertexIdx < OldVertexCount; VertexIdx++)
-		{
-			VerticesBuilder.Seek(VertexIdx);
-
-			// Update position and bounding box
-			if (HasPositions)
-			{
-				VerticesBuilder.SetPosition(Positions[VertexIdx]);
-				LocalBoundingBox += Positions[VertexIdx];
-			}
-			
-			// see if we have a new normal and/or tangent
-			bool HasNormal = Normals.Num() > VertexIdx;
-			bool HasTangent = Tangents.Num() > VertexIdx;
-
-			// Update normal and tangent together
-			if (HasNormal && HasTangent)
-			{
-				FVector4 NewNormal(Normals[VertexIdx], Tangents[VertexIdx].bFlipTangentY ? -1.0f : 1.0f);
-				VerticesBuilder.SetNormal(NewNormal);
-				VerticesBuilder.SetTangent(Tangents[VertexIdx].TangentX);
-			}
-			// Else update only normal keeping the W component 
-			else if (HasNormal)
-			{
-				float W = VerticesBuilder.GetNormal().W;
-				VerticesBuilder.SetNormal(FVector4(Normals[VertexIdx], W));
-			}
-			// Else update tangent updating the normals W component
-			else if (HasTangent)
-			{
-				FVector4 Normal = VerticesBuilder.GetNormal();
-				Normal.W = Tangents[VertexIdx].bFlipTangentY ? -1.0f : 1.0f;
-				VerticesBuilder.SetNormal(Normal);
-				VerticesBuilder.SetTangent(Tangents[VertexIdx].TangentX);
-			}
-
-			// Update color
-			if (Colors.Num() > VertexIdx)
-			{
-				VerticesBuilder.SetColor(Colors[VertexIdx]);
-			}
-
-			// Update UV0
-			if (UV0.Num() > VertexIdx)
-			{
-				VerticesBuilder.SetUV(0, UV0[VertexIdx]);
-			}
-
-			// Update UV1 if needed
-			if (UV1.Num() > VertexIdx && VerticesBuilder.HasUVComponent(1))
-			{
-				VerticesBuilder.SetUV(1, UV1[VertexIdx]);
-			}
-		}
-
-		// Loop through additional range to add new data
-		for (int32 VertexIdx = OldVertexCount; VertexIdx < NewVertexCount; VertexIdx++)
-		{
-			VerticesBuilder.Seek(VertexIdx);
-
-			// Set position
-			VerticesBuilder.SetPosition(Positions[VertexIdx]);
-
-			// Update bounding box
-			LocalBoundingBox += Positions[VertexIdx];
-
-			// see if we have a new normal and/or tangent
-			bool HasNormal = Normals.Num() > VertexIdx;
-			bool HasTangent = Tangents.Num() > VertexIdx;
-
-			// Set normal and tangent both
-			if (HasNormal && HasTangent)
-			{
-				FVector4 NewNormal(Normals[VertexIdx], Tangents[VertexIdx].bFlipTangentY ? -1.0f : 1.0f);
-				VerticesBuilder.SetNormal(NewNormal);
-				VerticesBuilder.SetTangent(Tangents[VertexIdx].TangentX);
-			}
-			// Set normal and default tangent
-			else if (HasNormal)
-			{
-				VerticesBuilder.SetNormal(FVector4(Normals[VertexIdx], 1.0f));
-				VerticesBuilder.SetTangent(FVector(1.0f, 0.0f, 0.0f));
-			}
-			// Default normal and set tangent
-			else if (HasTangent)
-			{
-				VerticesBuilder.SetNormal(FVector4(0.0f, 0.0f, 1.0f, Tangents[VertexIdx].bFlipTangentY ? -1.0f : 1.0f));
-				VerticesBuilder.SetTangent(Tangents[VertexIdx].TangentX);
-			}
-			// Default normal and tangent
-			else
-			{
-				VerticesBuilder.SetNormal(FVector4(0.0f, 0.0f, 1.0f, 1.0f));
-				VerticesBuilder.SetTangent(FVector(1.0f, 0.0f, 0.0f));
-			}
-
-			// Set color or default 
-			VerticesBuilder.SetColor(Colors.Num() > VertexIdx ? Colors[VertexIdx] : FColor::White);
-
-			// Update UV0
-			VerticesBuilder.SetUV(0, UV0.Num() > VertexIdx ? UV0[VertexIdx] : FVector2D::ZeroVector);
-
-			// Update UV1 if needed
-			if (VerticesBuilder.HasUVComponent(1))
-			{
-				VerticesBuilder.SetUV(1, UV1.Num() > VertexIdx ? UV1[VertexIdx] : FVector2D::ZeroVector);
-			}
-		}
-
-		return true;
-	}
-
-private:
-	void SerializeLegacy(FArchive& Ar)
-	{
-		int32 VertexBufferLength = VertexBuffer.Num();
-		Ar << VertexBufferLength;
-
-		if (Ar.IsLoading())
-		{
-			VertexBuffer.SetNum(VertexBufferLength);
-			FRuntimeMeshPackedVerticesBuilder<VertexType> VerticesBuilder(&VertexBuffer);
-
-			for (int32 Index = 0; Index < VertexBufferLength; Index++)
-			{
-				VerticesBuilder.Seek(Index);
-
-				FVector TempPosition;
-				Ar << TempPosition;
-				VerticesBuilder.SetPosition(TempPosition);
-
-				FPackedNormal TempNormal;
-				Ar << TempNormal;
-				VerticesBuilder.SetNormal(TempNormal);
-
-				Ar << TempNormal;
-				VerticesBuilder.SetTangent(TempNormal);
-
-				FColor TempColor;
-				Ar << TempColor;
-				VerticesBuilder.SetColor(TempColor);
-
-				if (FRuntimeMeshVertexTraits<VertexType>::HasHighPrecisionUVs)
-				{
-					FVector2D TempUV;
-					Ar << TempUV;
-					VerticesBuilder.SetUV(0, TempUV);
-
-					if (FRuntimeMeshVertexTraits<VertexType>::NumUVChannels > 1)
-					{
-						Ar << TempUV;
-						VerticesBuilder.SetUV(1, TempUV);
-					}
-				}
-				else
-				{
-					FVector2DHalf TempUV;
-					Ar << TempUV;
-					VerticesBuilder.SetUV(0, TempUV);
-
-					if (FRuntimeMeshVertexTraits<VertexType>::NumUVChannels > 1)
-					{
-						Ar << TempUV;
-						VerticesBuilder.SetUV(1, TempUV);
-					}
-				}
-			}
-		}
-		else
-		{
-			check(false && "Cannot use legacy save.");
-		}
-	}
-
-public:
-	virtual void Serialize(FArchive& Ar) override
-	{
-
-		if (Ar.CustomVer(FRuntimeMeshVersion::GUID) >= FRuntimeMeshVersion::SerializationV2)
-		{
-			Ar << VertexBuffer;
-			FRuntimeMeshSectionInterface::Serialize(Ar);
-		}
-		else
-		{
-			FRuntimeMeshSectionInterface::Serialize(Ar);
-			SerializeLegacy(Ar);
-		}
-	}
-
-	friend class URuntimeMeshComponent;
-};
-
-
-/** Smart pointer to a Runtime Mesh Section */
-using RuntimeMeshSectionPtr = TSharedPtr<FRuntimeMeshSectionInterface>;

+ 0 - 228
spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Public/RuntimeMeshSectionProxy.h

@@ -1,228 +0,0 @@
-// Copyright 2016 Chris Conway (Koderz). All Rights Reserved.
-
-#pragma once
-
-#include "Engine.h"
-#include "Components/MeshComponent.h"
-#include "RuntimeMeshProfiling.h"
-#include "RuntimeMeshVersion.h"
-#include "RuntimeMeshCore.h"
-#include "RuntimeMeshRendering.h"
-#include "RuntimeMeshUpdateCommands.h"
-
-
-/** Interface class for the RT proxy of a single mesh section */
-class FRuntimeMeshSectionProxyInterface : public FRuntimeMeshVisibilityInterface
-{
-public:
-
-	FRuntimeMeshSectionProxyInterface() {}
-	virtual ~FRuntimeMeshSectionProxyInterface() {}
-
-	virtual bool ShouldRender() = 0;
-	virtual bool WantsToRenderInStaticPath() const = 0;
-
-	virtual bool ShouldUseAdjacencyIndexBuffer() const = 0;
-
-	virtual FMaterialRelevance GetMaterialRelevance() const = 0;
-
-	virtual void CreateMeshBatch(FMeshBatch& MeshBatch, FMaterialRenderProxy* WireframeMaterial, bool bIsSelected) = 0;
-
-
-	virtual void FinishCreate_RenderThread(FRuntimeMeshSectionCreateDataInterface* UpdateData) = 0;
-	virtual void FinishUpdate_RenderThread(FRuntimeMeshRenderThreadCommandInterface* UpdateData) = 0;
-	virtual void FinishPositionUpdate_RenderThread(FRuntimeMeshRenderThreadCommandInterface* UpdateData) = 0;
-	virtual void FinishPropertyUpdate_RenderThread(FRuntimeMeshRenderThreadCommandInterface* UpdateData) = 0;
-
-};
-
-/** Templated class for the RT proxy of a single mesh section */
-template <typename VertexType, bool NeedsPositionOnlyBuffer>
-class FRuntimeMeshSectionProxy : public FRuntimeMeshSectionProxyInterface
-{
-protected:
-	/** Whether this section is currently visible */
-	bool bIsVisible;
-
-	/** Should this section cast a shadow */
-	bool bCastsShadow;
-
-	/** Whether this section should be using an adjacency index buffer */
-	bool bShouldUseAdjacency;
-
-	/** Whether this section is using a tessellation adjacency index buffer */
-	bool bIsUsingAdjacency;
-
-	/** Update frequency of this section */
-	const EUpdateFrequency UpdateFrequency;
-
-	/** Material applied to this section */
-	UMaterialInterface* Material;
-
-	FMaterialRelevance MaterialRelevance;
-
-	FRuntimeMeshVertexBuffer<FVector>* PositionVertexBuffer;
-
-	/** Vertex buffer for this section */
-	FRuntimeMeshVertexBuffer<VertexType> VertexBuffer;
-
-	/** Index buffer for this section */
-	FRuntimeMeshIndexBuffer IndexBuffer;
-
-	/** Vertex factory for this section */
-	FRuntimeMeshVertexFactory VertexFactory;
-
-public:
-	FRuntimeMeshSectionProxy(FSceneInterface* InScene, EUpdateFrequency InUpdateFrequency, bool bInIsVisible, bool bInCastsShadow, UMaterialInterface* InMaterial, FMaterialRelevance InMaterialRelevance) :
-		bIsVisible(bInIsVisible), bCastsShadow(bInCastsShadow), UpdateFrequency(InUpdateFrequency), Material(InMaterial), MaterialRelevance(InMaterialRelevance),
-		PositionVertexBuffer(nullptr), VertexBuffer(InUpdateFrequency), IndexBuffer(InUpdateFrequency), VertexFactory(this) 
-	{ 
-		bShouldUseAdjacency = RequiresAdjacencyInformation(InMaterial, VertexFactory.GetType(), InScene->GetFeatureLevel());
-	}
-
-	virtual ~FRuntimeMeshSectionProxy() override
-	{
-		VertexBuffer.ReleaseResource();
-		IndexBuffer.ReleaseResource();
-		VertexFactory.ReleaseResource();
-
-		if (PositionVertexBuffer)
-		{
-			PositionVertexBuffer->ReleaseResource();
-			delete PositionVertexBuffer;
-		}
-	}
-
-
-	virtual bool ShouldRender() override { return bIsVisible && VertexBuffer.Num() > 0 && IndexBuffer.Num() > 0; }
-
-	virtual bool WantsToRenderInStaticPath() const override { return UpdateFrequency == EUpdateFrequency::Infrequent; }
-	
-	virtual bool ShouldUseAdjacencyIndexBuffer() const override { return bShouldUseAdjacency; }
-
-	virtual FMaterialRelevance GetMaterialRelevance() const { return MaterialRelevance; }
-	
-	virtual void CreateMeshBatch(FMeshBatch& MeshBatch, FMaterialRenderProxy* WireframeMaterial, bool bIsSelected) override
-	{
-		MeshBatch.VertexFactory = &VertexFactory;
-		MeshBatch.bWireframe = WireframeMaterial != nullptr;
-		MeshBatch.MaterialRenderProxy = MeshBatch.bWireframe ? WireframeMaterial : Material->GetRenderProxy(bIsSelected);
-		
-		if (bIsUsingAdjacency && WireframeMaterial == nullptr)
-		{
-			MeshBatch.Type = PT_12_ControlPointPatchList;
-		}
-		else
-		{
-			MeshBatch.Type = PT_TriangleList;
-		}
-
-		MeshBatch.DepthPriorityGroup = SDPG_World;
-		MeshBatch.CastShadow = bCastsShadow;
-
-		FMeshBatchElement& BatchElement = MeshBatch.Elements[0];
-		BatchElement.IndexBuffer = &IndexBuffer;
-		BatchElement.FirstIndex = 0;
-		BatchElement.NumPrimitives = bIsUsingAdjacency? IndexBuffer.Num() / 12 : IndexBuffer.Num() / 3;
-		BatchElement.MinVertexIndex = 0;
-		BatchElement.MaxVertexIndex = VertexBuffer.Num() - 1;
-	}
-
-
-	virtual void FinishCreate_RenderThread(FRuntimeMeshSectionCreateDataInterface* UpdateData) override
-	{
- 		check(IsInRenderingThread());
-
-		auto* SectionUpdateData = UpdateData->As<FRuntimeMeshSectionCreateData<VertexType>>();
-		check(SectionUpdateData);
-		
-		if (NeedsPositionOnlyBuffer)
-		{
-			// Initialize the position buffer
-			PositionVertexBuffer = new FRuntimeMeshVertexBuffer<FVector>(UpdateFrequency);
-
-			// Get and adjust the vertex structure
-			auto VertexStructure = VertexType::GetVertexStructure(VertexBuffer);
-			VertexStructure.PositionComponent = FVertexStreamComponent(PositionVertexBuffer, 0, sizeof(FVector), VET_Float3);
-			VertexFactory.Init(VertexStructure);
-		}
-		else
-		{
-			// Get and submit the vertex structure
-			auto VertexStructure = VertexType::GetVertexStructure(VertexBuffer);
-			VertexFactory.Init(VertexStructure);
-		}
-		
-		// Initialize the vertex factory
-		VertexFactory.InitResource();
-
-		auto& Vertices = SectionUpdateData->VertexBuffer;
-		VertexBuffer.SetNum(Vertices.Num());
-		VertexBuffer.SetData(Vertices);
-
-		if (NeedsPositionOnlyBuffer)
-		{
-			auto& PositionVertices = SectionUpdateData->PositionVertexBuffer;
-			PositionVertexBuffer->SetNum(PositionVertices.Num());
-			PositionVertexBuffer->SetData(PositionVertices);
-		}
-		
-		auto& Indices = SectionUpdateData->IndexBuffer;
-		IndexBuffer.SetNum(Indices.Num());
-		IndexBuffer.SetData(Indices);
-		bIsUsingAdjacency = SectionUpdateData->bIsAdjacencyIndexBuffer;
-	}
-	
-	virtual void FinishUpdate_RenderThread(FRuntimeMeshRenderThreadCommandInterface* UpdateData) override
-	{
-		check(IsInRenderingThread());
-
-		auto* SectionUpdateData = UpdateData->As<FRuntimeMeshSectionUpdateData<VertexType>>();
-		check(SectionUpdateData);
-
-		if (SectionUpdateData->bIncludeVertexBuffer)
-		{
-			auto& VertexBufferData = SectionUpdateData->VertexBuffer;
-			VertexBuffer.SetNum(VertexBufferData.Num());
-			VertexBuffer.SetData(VertexBufferData);
-		}
-
-		if (NeedsPositionOnlyBuffer && SectionUpdateData->bIncludePositionBuffer)
-		{
-			auto& PositionVertices = SectionUpdateData->PositionVertexBuffer;
-			PositionVertexBuffer->SetNum(PositionVertices.Num());
-			PositionVertexBuffer->SetData(PositionVertices);
-		}
-
-		if (SectionUpdateData->bIncludeIndices)
-		{
-			auto& IndexBufferData = SectionUpdateData->IndexBuffer;
-			IndexBuffer.SetNum(IndexBufferData.Num());
-			IndexBuffer.SetData(IndexBufferData);
-			bIsUsingAdjacency = SectionUpdateData->bIsAdjacencyIndexBuffer;
-		}
-	}
-
-	virtual void FinishPositionUpdate_RenderThread(FRuntimeMeshRenderThreadCommandInterface* UpdateData) override 
-	{
-		check(IsInRenderingThread());
-
-		// Get the Position Only update data
-		auto* SectionUpdateData = UpdateData->As<FRuntimeMeshSectionPositionOnlyUpdateData<VertexType>>();
-		check(SectionUpdateData);
-		
-		// Copy the new data to the gpu
-		PositionVertexBuffer->SetData(SectionUpdateData->PositionVertexBuffer);
-	}
-
-	virtual void FinishPropertyUpdate_RenderThread(FRuntimeMeshRenderThreadCommandInterface* UpdateData) override
-	{
-		auto* SectionUpdateData = UpdateData->As<FRuntimeMeshSectionPropertyUpdateData>();
-		check(SectionUpdateData);
-
-		// Copy visibility/shadow
-		bIsVisible = SectionUpdateData->bIsVisible;
-		bCastsShadow = SectionUpdateData->bCastsShadow;
-	}
-
-};

+ 0 - 257
spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Public/RuntimeMeshUpdateCommands.h

@@ -1,257 +0,0 @@
-// Copyright 2016 Chris Conway (Koderz). All Rights Reserved.
-
-#pragma once
-
-#include "Engine.h"
-#include "Components/MeshComponent.h"
-#include "RuntimeMeshProfiling.h"
-#include "RuntimeMeshVersion.h"
-
-
-
-
-/* Base class for all render thread command information */
-class FRuntimeMeshRenderThreadCommandInterface
-{
-public:
-
-	FRuntimeMeshRenderThreadCommandInterface() { }
-	virtual ~FRuntimeMeshRenderThreadCommandInterface() { }
-	
-	virtual void SetTargetSection(int32 InTargetSection) { TargetSection = InTargetSection; }
-	virtual int32 GetTargetSection() { return TargetSection; }
-	
-	/* Cast the update data to the specific type of update data */
-	template <typename Type>
-	Type* As()
-	{
-		return static_cast<Type*>(this);
-	}
-
-private:
-	/* Section index that this creation data applies to */
-	int32 TargetSection;
-};
-
-/* Base class for section creation data. Allows the non templated SceneProxy to get the section proxy;*/
-class FRuntimeMeshSectionCreateDataInterface : public FRuntimeMeshRenderThreadCommandInterface
-{
-public:
-	/* The new proxy to be used for section creation */
-	class FRuntimeMeshSectionProxyInterface* NewProxy;
-
-
-	FRuntimeMeshSectionCreateDataInterface() { }
-	virtual ~FRuntimeMeshSectionCreateDataInterface() override { }
-
-};
-
-/** Templated class for update data sent to the RT for updating a single mesh section */
-template<typename VertexType>
-class FRuntimeMeshSectionCreateData : public FRuntimeMeshSectionCreateDataInterface
-{
-public:
-	/* Updated position vertex buffer for the section */
-	TArray<FVector> PositionVertexBuffer;
-
-	/* Updated vertex buffer for the section */
-	TArray<VertexType> VertexBuffer;
-
-	/* Whether the supplied index buffer contains adjacency info */
-	bool bIsAdjacencyIndexBuffer;
-
-	/* Updated index buffer for the section */
-	TArray<int32> IndexBuffer;
-
-
-	FRuntimeMeshSectionCreateData() {}
-	virtual ~FRuntimeMeshSectionCreateData() override { }
-
-};
-
-/** Templated class for update data sent to the RT for updating a single mesh section */
-template<typename VertexType>
-class FRuntimeMeshSectionUpdateData : public FRuntimeMeshRenderThreadCommandInterface
-{
-public:
-	/* Updated position vertex buffer for the section */
-	TArray<FVector> PositionVertexBuffer;
-
-	/* Updated vertex buffer for the section */
-	TArray<VertexType> VertexBuffer;
-
-	/* Updated index buffer for the section */
-	TArray<int32> IndexBuffer;
-
-	/* Should we apply the position buffer */
-	bool bIncludePositionBuffer;
-
-	/* Should we apply the vertex buffer */
-	bool bIncludeVertexBuffer;
-
-	/* Should we apply the indices as an update */
-	bool bIncludeIndices;
-
-	/* Whether the supplied index buffer contains adjacency info */
-	bool bIsAdjacencyIndexBuffer;
-
-	FRuntimeMeshSectionUpdateData() {}
-	virtual ~FRuntimeMeshSectionUpdateData() override { }
-};
-
-/** Templated class for update data sent to the RT for updating a single mesh section */
-template<typename VertexType>
-class FRuntimeMeshSectionPositionOnlyUpdateData : public FRuntimeMeshRenderThreadCommandInterface
-{
-public:
-	/* Updated position vertex buffer for the section */
-	TArray<FVector> PositionVertexBuffer;
-
-	FRuntimeMeshSectionPositionOnlyUpdateData() {}
-	virtual ~FRuntimeMeshSectionPositionOnlyUpdateData() override { }
-};
-
-/** Property update for a single section */
-class FRuntimeMeshSectionPropertyUpdateData : public FRuntimeMeshRenderThreadCommandInterface
-{
-public:
-	/* Is this section visible */
-	bool bIsVisible;
-
-	/* Is this section casting shadows */
-	bool bCastsShadow;
-
-	FRuntimeMeshSectionPropertyUpdateData() {}
-	virtual ~FRuntimeMeshSectionPropertyUpdateData() override { }
-};
-
-enum class ERuntimeMeshSectionBatchUpdateType
-{
-	None = 0x0,
-	Create = 0x1,
-	Destroy = 0x2,
-	PositionsUpdate = 0x4,
-	VerticesUpdate = 0x8,
-	IndicesUpdate = 0x10,
-	PropertyUpdate = 0x20,
-};
-
-ENUM_CLASS_FLAGS(ERuntimeMeshSectionBatchUpdateType)
-
-
-/* Struct carrying all update data for a batch update sent to the render thread */
-struct FRuntimeMeshBatchUpdateData
-{
-	TArray<FRuntimeMeshSectionCreateDataInterface*> CreateSections;
-	TArray<int32> DestroySections;
-	TArray<FRuntimeMeshRenderThreadCommandInterface*> UpdateSections;
-	TArray<FRuntimeMeshSectionPropertyUpdateData*> PropertyUpdateSections;
-};
-
-
-
-struct FRuntimeMeshBatchUpdateState
-{
-	void StartBatch() { bIsPending = true; }
-
-	void ResetBatch() 
-	{
-		bIsPending = false;
-		bRequiresSceneProxyReCreate = false;
-		bRequiresBoundsUpdate = false;
-		bRequiresCollisionUpdate = false;
-
-		SectionUpdates.Empty();
-	}
-
-	
-
-
-	bool IsBatchPending() { return bIsPending; }
-
-	void MarkSectionCreated(int32 SectionIndex, bool bPromoteToProxyRecreate)
-	{
-		// Flag recreate instead of individual section
-		if (bPromoteToProxyRecreate)
-		{
-			bRequiresSceneProxyReCreate = true;
-			return;
-		}
-
-		EnsureUpdateLength(SectionIndex);
-
-		// Clear destroyed flag and set created
-		SectionUpdates[SectionIndex] &= ~ERuntimeMeshSectionBatchUpdateType::Destroy;
-		SectionUpdates[SectionIndex] |= ERuntimeMeshSectionBatchUpdateType::Create;
-	}
-
-	void MarkUpdateForSection(int32 SectionIndex, ERuntimeMeshSectionBatchUpdateType UpdateType)
-	{
-		EnsureUpdateLength(SectionIndex);
-		
-		// Add update type
-		SectionUpdates[SectionIndex] |= UpdateType;
-	}
-
-	void MarkSectionDestroyed(int32 SectionIndex, bool bPromoteToProxyRecreate)
-	{
-		// Flag recreate instead of individual section
-		if (bPromoteToProxyRecreate)
-		{
-			bRequiresSceneProxyReCreate = true;
-			return;
-		}
-
-		EnsureUpdateLength(SectionIndex);
-
-		// Clear destroyed flag and set created
-		SectionUpdates[SectionIndex] &= ~ERuntimeMeshSectionBatchUpdateType::Create;
-		SectionUpdates[SectionIndex] |= ERuntimeMeshSectionBatchUpdateType::Destroy;
-	}
-
-	void MarkRenderStateDirty() { bRequiresSceneProxyReCreate = true; }
-
-	void MarkCollisionDirty() { bRequiresCollisionUpdate = true; }
-
-	void MarkBoundsDirty() { bRequiresBoundsUpdate = true; }
-
-
-
-	bool HasAnyFlagSet(int32 SectionIndex) { return SectionUpdates[SectionIndex] != ERuntimeMeshSectionBatchUpdateType::None; }
-
-	bool HasFlagSet(int32 SectionIndex, ERuntimeMeshSectionBatchUpdateType UpdateType)
-	{
-		return (SectionUpdates[SectionIndex] & UpdateType) == UpdateType;
-	}
-
-	bool RequiresSceneProxyRecreate() { return bRequiresSceneProxyReCreate; }
-
-	bool RequiresBoundsUpdate() { return bRequiresBoundsUpdate; }
-
-	bool RequiresCollisionUpdate() { return bRequiresCollisionUpdate; }
-
-	int32 GetMaxSection() { return SectionUpdates.Num() - 1; }
-
-private:
-
-	void EnsureUpdateLength(int32 SectionIndex)
-	{
-		if (SectionIndex < SectionUpdates.Num())
-		{
-			return;
-		}
-
-		SectionUpdates.AddZeroed((SectionIndex + 1) - SectionUpdates.Num());
-	}
-
-
-	bool bIsPending;
-	bool bRequiresSceneProxyReCreate;
-	bool bRequiresBoundsUpdate;
-	bool bRequiresCollisionUpdate;
-	TArray<ERuntimeMeshSectionBatchUpdateType> SectionUpdates;
-	
-
-
-
-};

+ 0 - 27
spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/Public/RuntimeMeshVersion.h

@@ -1,27 +0,0 @@
-// Copyright 2016 Chris Conway (Koderz). All Rights Reserved.
-
-#pragma once
-
-#include "RuntimeMeshComponentPlugin.h"
-
-
-// Custom version for runtime mesh serialization
-namespace FRuntimeMeshVersion
-{
-	enum Type
-	{
-		Initial = 0,
-		TemplatedVertexFix = 1,
-		SerializationOptional = 2,
-		DualVertexBuffer = 3,
-
-		SerializationV2 = 4,
-
-		// -----<new versions can be added above this line>-------------------------------------------------
-		VersionPlusOne,
-		LatestVersion = VersionPlusOne - 1
-	};
-
-	// The GUID for this custom version
-	const static FGuid GUID = FGuid(0xEE48714B, 0x8A2C4652, 0x98BE40E6, 0xCB7EF0E6);
-};

+ 0 - 24
spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponent/RuntimeMeshComponent.Build.cs

@@ -1,24 +0,0 @@
-// Copyright 2016 Chris Conway (Koderz). All Rights Reserved.
-
-using UnrealBuildTool;
-
-public class RuntimeMeshComponent : ModuleRules
-{
-	public RuntimeMeshComponent(ReadOnlyTargetRules Target) : base(Target)
-	{
-        PrivateIncludePaths.Add("RuntimeMeshComponent/Private");
-        PublicIncludePaths.Add("RuntimeMeshComponent/Public");
-
-        PublicDependencyModuleNames.AddRange(
-                new string[]
-                {
-                        "Core",
-                        "CoreUObject",
-                        "Engine",
-                        "RenderCore",
-                        "ShaderCore",
-                        "RHI"
-                }
-            );
-    }
-}

+ 0 - 269
spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponentEditor/Private/RuntimeMeshComponentDetails.cpp

@@ -1,269 +0,0 @@
-// Copyright 2016 Chris Conway (Koderz). All Rights Reserved.
-
-#include "RuntimeMeshComponentEditorPrivatePCH.h"
-#include "RuntimeMeshComponentDetails.h"
-#include "RuntimeMeshComponent.h"
-
-#include "DlgPickAssetPath.h"
-#include "IAssetTools.h"
-#include "AssetToolsModule.h"
-#include "AssetRegistryModule.h"
-#include "PhysicsEngine/PhysicsSettings.h"
-#include "PhysicsEngine/BodySetup.h"
-
-#define LOCTEXT_NAMESPACE "RuntimeMeshComponentDetails"
-
-TSharedRef<IDetailCustomization> FRuntimeMeshComponentDetails::MakeInstance()
-{
-	return MakeShareable(new FRuntimeMeshComponentDetails);
-}
-
-void FRuntimeMeshComponentDetails::CustomizeDetails( IDetailLayoutBuilder& DetailBuilder )
-{
-	IDetailCategoryBuilder& RuntimeMeshCategory = DetailBuilder.EditCategory("RuntimeMesh");
-
-	const FText ConvertToStaticMeshText = LOCTEXT("ConvertToStaticMesh", "Create StaticMesh");
-
-	// Cache set of selected things
-#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION < 18 
-	SelectedObjectsList = DetailBuilder.GetDetailsView().GetSelectedObjects();
-#else
-	SelectedObjectsList = DetailBuilder.GetDetailsView()->GetSelectedObjects();
-#endif
-
-	RuntimeMeshCategory.AddCustomRow(ConvertToStaticMeshText, false)
-	.NameContent()
-	[
-		SNullWidget::NullWidget
-	]
-	.ValueContent()
-	.VAlign(VAlign_Center)
-	.MaxDesiredWidth(250)
-	[
-		SNew(SButton)
-		.VAlign(VAlign_Center)
-		.ToolTipText(LOCTEXT("ConvertToStaticMeshTooltip", "Create a new StaticMesh asset using current geometry from this RuntimeMeshComponent. Does not modify instance."))
-		.OnClicked(this, &FRuntimeMeshComponentDetails::ClickedOnConvertToStaticMesh)
-		.IsEnabled(this, &FRuntimeMeshComponentDetails::ConvertToStaticMeshEnabled)
-		.Content()
-		[
-			SNew(STextBlock)
-			.Text(ConvertToStaticMeshText)
-		]
-	];
-}
-
-URuntimeMeshComponent* FRuntimeMeshComponentDetails::GetFirstSelectedRuntimeMeshComp() const
-{
-	// Find first selected valid RuntimeMeshComp
-	URuntimeMeshComponent* RuntimeMeshComp = nullptr;
-	for (const TWeakObjectPtr<UObject>& Object : SelectedObjectsList)
-	{
-		URuntimeMeshComponent* TestRuntimeComp = Cast<URuntimeMeshComponent>(Object.Get());
-		// See if this one is good
-		if (TestRuntimeComp != nullptr && !TestRuntimeComp->IsTemplate())
-		{
-			RuntimeMeshComp = TestRuntimeComp;
-			break;
-		}
-	}
-
-	return RuntimeMeshComp;
-}
-
-
-bool FRuntimeMeshComponentDetails::ConvertToStaticMeshEnabled() const
-{
-	return GetFirstSelectedRuntimeMeshComp() != nullptr;
-}
-
-
-FReply FRuntimeMeshComponentDetails::ClickedOnConvertToStaticMesh()
-{
- 	// Find first selected RuntimeMeshComp
- 	URuntimeMeshComponent* RuntimeMeshComp = GetFirstSelectedRuntimeMeshComp();
- 	if (RuntimeMeshComp != nullptr)
- 	{
- 		FString NewNameSuggestion = FString(TEXT("RuntimeMeshComp"));
- 		FString PackageName = FString(TEXT("/Game/Meshes/")) + NewNameSuggestion;
- 		FString Name;
- 		FAssetToolsModule& AssetToolsModule = FModuleManager::LoadModuleChecked<FAssetToolsModule>("AssetTools");
- 		AssetToolsModule.Get().CreateUniqueAssetName(PackageName, TEXT(""), PackageName, Name);
- 
- 		TSharedPtr<SDlgPickAssetPath> PickAssetPathWidget =
- 			SNew(SDlgPickAssetPath)
- 			.Title(LOCTEXT("ConvertToStaticMeshPickName", "Choose New StaticMesh Location"))
- 			.DefaultAssetPath(FText::FromString(PackageName));
- 
- 		if (PickAssetPathWidget->ShowModal() == EAppReturnType::Ok)
- 		{
- 			// Get the full name of where we want to create the physics asset.
- 			FString UserPackageName = PickAssetPathWidget->GetFullAssetPath().ToString();
- 			FName MeshName(*FPackageName::GetLongPackageAssetName(UserPackageName));
- 
- 			// Check if the user inputed a valid asset name, if they did not, give it the generated default name
- 			if (MeshName == NAME_None)
- 			{
- 				// Use the defaults that were already generated.
- 				UserPackageName = PackageName;
- 				MeshName = *Name;
- 			}
- 
- 			// Raw mesh data we are filling in
- 			FRawMesh RawMesh;
- 					
-			// Unique Materials to apply to new mesh
-#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION >= 14
-			TArray<FStaticMaterial> Materials;
-#else
-			TArray<UMaterialInterface*> Materials;
-#endif
- 
-			bool bUseHighPrecisionTangents = false;
-			bool bUseFullPrecisionUVs = false;
-
- 			const int32 NumSections = RuntimeMeshComp->GetNumSections();
- 			int32 VertexBase = 0;
- 			for (int32 SectionIdx = 0; SectionIdx < NumSections; SectionIdx++)
- 			{
-				const IRuntimeMeshVerticesBuilder* Vertices;
-				const FRuntimeMeshIndicesBuilder* Indices;
-				RuntimeMeshComp->GetSectionMesh(SectionIdx, Vertices, Indices);
-
-				if (Vertices->HasHighPrecisionNormals())
-				{
-					bUseHighPrecisionTangents = true;
-				}
-				if (Vertices->HasHighPrecisionUVs())
-				{
-					bUseFullPrecisionUVs = true;
-				}
- 
- 				// Copy verts
-				Vertices->Seek(-1);
-				while (Vertices->MoveNext() < Vertices->Length())
-				{
-					RawMesh.VertexPositions.Add(Vertices->GetPosition());
-				}
- 
- 				// Copy 'wedge' info
-				Indices->Seek(0);
-				while (Indices->HasRemaining())
- 				{
-					int32 Index = Indices->ReadOne();
- 
- 					RawMesh.WedgeIndices.Add(Index + VertexBase);
- 
-
-					Vertices->Seek(Index);
- 
-					FVector TangentX = Vertices->GetTangent();
-					FVector TangentZ = Vertices->GetNormal();
- 					FVector TangentY = (TangentX ^ TangentZ).GetSafeNormal() * Vertices->GetNormal().W;
- 
- 					RawMesh.WedgeTangentX.Add(TangentX);
- 					RawMesh.WedgeTangentY.Add(TangentY);
- 					RawMesh.WedgeTangentZ.Add(TangentZ);
- 
-					for (int UVIndex = 0; UVIndex < 8; UVIndex++)
-					{
-						if (!Vertices->HasUVComponent(UVIndex))
-						{
-							break;
-						}
-						RawMesh.WedgeTexCoords[UVIndex].Add(Vertices->GetUV(UVIndex));
-					}
-
- 					RawMesh.WedgeColors.Add(Vertices->GetColor());
- 				}
- 
-				// Find a material index for this section.
-				UMaterialInterface* Material = RuntimeMeshComp->GetMaterial(SectionIdx);
-
-#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION >= 14
-				int32 MaterialIndex = Materials.AddUnique(FStaticMaterial(Material));
-#else
-				int32 MaterialIndex = Materials.AddUnique(Material);
-#endif
-				
-
- 				// copy face info
- 				int32 NumTris = Indices->Length() / 3;
- 				for (int32 TriIdx=0; TriIdx < NumTris; TriIdx++)
- 				{
-					// Set the face material
-					RawMesh.FaceMaterialIndices.Add(MaterialIndex);
-
- 					RawMesh.FaceSmoothingMasks.Add(0); // Assume this is ignored as bRecomputeNormals is false
- 				}
- 
- 				// Update offset for creating one big index/vertex buffer
-				VertexBase += Vertices->Length();
- 			}
- 
- 			// If we got some valid data.
- 			if (RawMesh.VertexPositions.Num() >= 3 && RawMesh.WedgeIndices.Num() >= 3)
- 			{
- 				// Then find/create it.
- 				UPackage* Package = CreatePackage(NULL, *UserPackageName);
- 				check(Package);
- 
- 				// Create StaticMesh object
- 				UStaticMesh* StaticMesh = NewObject<UStaticMesh>(Package, MeshName, RF_Public | RF_Standalone);
- 				StaticMesh->InitResources();
- 
- 				StaticMesh->LightingGuid = FGuid::NewGuid();
- 
- 				// Add source to new StaticMesh
- 				FStaticMeshSourceModel* SrcModel = new (StaticMesh->SourceModels) FStaticMeshSourceModel();
- 				SrcModel->BuildSettings.bRecomputeNormals = false;
- 				SrcModel->BuildSettings.bRecomputeTangents = false;
- 				SrcModel->BuildSettings.bRemoveDegenerates = false;
- 				SrcModel->BuildSettings.bUseHighPrecisionTangentBasis = bUseHighPrecisionTangents;
-				SrcModel->BuildSettings.bUseFullPrecisionUVs = bUseFullPrecisionUVs;
- 				SrcModel->BuildSettings.bGenerateLightmapUVs = true;
- 				SrcModel->BuildSettings.SrcLightmapIndex = 0;
- 				SrcModel->BuildSettings.DstLightmapIndex = 1;
- 				SrcModel->RawMeshBulkData->SaveRawMesh(RawMesh);
- 
-				// Set the materials used for this static mesh
-#if ENGINE_MAJOR_VERSION == 4 && ENGINE_MINOR_VERSION >= 14
-				StaticMesh->StaticMaterials = Materials;
-				int32 NumMaterials = StaticMesh->StaticMaterials.Num();
-#else
-				StaticMesh->Materials = Materials;
-				int32 NumMaterials = StaticMesh->Materials.Num();
-#endif
-
-				// Set up the SectionInfoMap to enable collision
-				for (int32 SectionIdx = 0; SectionIdx < NumMaterials; SectionIdx++)
-				{
-					FMeshSectionInfo Info = StaticMesh->SectionInfoMap.Get(0, SectionIdx);
-					Info.MaterialIndex = SectionIdx;
-					Info.bEnableCollision = true;
-					StaticMesh->SectionInfoMap.Set(0, SectionIdx, Info);
-				}
-
-				// Configure body setup for working collision.
-				StaticMesh->CreateBodySetup();
-				StaticMesh->BodySetup->CollisionTraceFlag = CTF_UseComplexAsSimple;
-
- 				// Build mesh from source
- 				StaticMesh->Build(false);
-
-				// Make package dirty.
-				StaticMesh->MarkPackageDirty();
-
- 				StaticMesh->PostEditChange();
- 
- 				// Notify asset registry of new asset
- 				FAssetRegistryModule::AssetCreated(StaticMesh);
- 			}
- 		}
- 	}
-
-	return FReply::Handled();
-}
-
-
-#undef LOCTEXT_NAMESPACE

+ 0 - 27
spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponentEditor/Private/RuntimeMeshComponentDetails.h

@@ -1,27 +0,0 @@
-// Copyright 2016 Chris Conway (Koderz). All Rights Reserved.
-
-#pragma once
-#include "IDetailCustomization.h"
-#include "DetailLayoutBuilder.h"
-
-class FRuntimeMeshComponentDetails : public IDetailCustomization
-{
-public:
-	/** Makes a new instance of this detail layout class for a specific detail view requesting it */
-	static TSharedRef<IDetailCustomization> MakeInstance();
-
-	/** IDetailCustomization interface */
-	virtual void CustomizeDetails( IDetailLayoutBuilder& DetailBuilder ) override;
-
-	/** Handle clicking the convert button */
-	FReply ClickedOnConvertToStaticMesh();
-
-	/** Is the convert button enabled */
-	bool ConvertToStaticMeshEnabled() const;
-
-	/** Util to get the RuntimeMeshComponent we want to convert */
-	class URuntimeMeshComponent* GetFirstSelectedRuntimeMeshComp() const;
-
-	/** Cached array of selected objects */
-	TArray< TWeakObjectPtr<UObject> > SelectedObjectsList;
-};

+ 0 - 31
spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponentEditor/Private/RuntimeMeshComponentEditorPlugin.cpp

@@ -1,31 +0,0 @@
-// Copyright 2016 Chris Conway (Koderz). All Rights Reserved.
-
-#include "RuntimeMeshComponentEditorPrivatePCH.h"
-
-
-
-
-class FRuntimeMeshComponentEditorPlugin : public IRuntimeMeshComponentEditorPlugin
-{
-	/** IModuleInterface implementation */
-	virtual void StartupModule() override;
-	virtual void ShutdownModule() override;
-};
-
-IMPLEMENT_MODULE( FRuntimeMeshComponentEditorPlugin, RuntimeMeshComponentEditor )
-
-
-
-void FRuntimeMeshComponentEditorPlugin::StartupModule()
-{
-	{
-		FPropertyEditorModule& PropertyModule = FModuleManager::LoadModuleChecked<FPropertyEditorModule>("PropertyEditor");
-		PropertyModule.RegisterCustomClassLayout(URuntimeMeshComponent::StaticClass()->GetFName(), FOnGetDetailCustomizationInstance::CreateStatic(&FRuntimeMeshComponentDetails::MakeInstance));
-	}
-}
-
-
-void FRuntimeMeshComponentEditorPlugin::ShutdownModule()
-{
-	
-}

+ 0 - 15
spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponentEditor/Private/RuntimeMeshComponentEditorPrivatePCH.h

@@ -1,15 +0,0 @@
-// Copyright 2016 Chris Conway (Koderz). All Rights Reserved.
-
-#include "UnrealEd.h"
-#include "PropertyEditorModule.h"
-#include "DetailLayoutBuilder.h"
-#include "DetailCategoryBuilder.h"
-#include "DetailWidgetRow.h"
-#include "IDetailsView.h"
-#include "PhysicsEngine/ConvexElem.h"
-#include "RuntimeMeshComponent.h"
-#include "Engine/StaticMesh.h"
-#include "RawMesh.h"
-
-#include "IRuntimeMeshComponentEditorPlugin.h"
-#include "RuntimeMeshComponentDetails.h"

+ 0 - 36
spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponentEditor/Public/IRuntimeMeshComponentEditorPlugin.h

@@ -1,36 +0,0 @@
-// Copyright 2016 Chris Conway (Koderz). All Rights Reserved.
-
-#pragma once
-
-#include "ModuleManager.h"
-
-
-/**
-* The public interface to this module
-*/
-class IRuntimeMeshComponentEditorPlugin : public IModuleInterface
-{
-
-public:
-
-	/**
-	* Singleton-like access to this module's interface.  This is just for convenience!
-	* Beware of calling this during the shutdown phase, though.  Your module might have been unloaded already.
-	*
-	* @return Returns singleton instance, loading the module on demand if needed
-	*/
-	static inline IRuntimeMeshComponentEditorPlugin& Get()
-	{
-		return FModuleManager::LoadModuleChecked< IRuntimeMeshComponentEditorPlugin >("RuntimeMeshComponentEditorPlugin");
-	}
-
-	/**
-	* Checks to see if this module is loaded and ready.  It is only valid to call Get() if IsAvailable() returns true.
-	*
-	* @return True if the module is loaded and ready to use
-	*/
-	static inline bool IsAvailable()
-	{
-		return FModuleManager::Get().IsModuleLoaded("RuntimeMeshComponentEditorPlugin");
-	}
-};

+ 0 - 33
spine-ue4/Plugins/RuntimeMeshComponentPlugin/Source/RuntimeMeshComponentEditor/RuntimeMeshComponentEditor.Build.cs

@@ -1,33 +0,0 @@
-// Copyright 2016 Chris Conway (Koderz). All Rights Reserved.
-
-namespace UnrealBuildTool.Rules
-{
-	public class RuntimeMeshComponentEditor : ModuleRules
-	{
-        public RuntimeMeshComponentEditor(ReadOnlyTargetRules Target) : base(Target)
-		{
-			PrivateIncludePaths.Add("RuntimeMeshComponentEditor/Private");
-            PublicIncludePaths.Add("RuntimeMeshComponentEditor/Public");
-
-			PublicDependencyModuleNames.AddRange(
-				new string[]
-				{
-					"Core",
-					"CoreUObject",
-                    "Slate",
-                    "SlateCore",
-                    "Engine",
-                    "UnrealEd",
-                    "PropertyEditor",
-                    "RenderCore",
-                    "ShaderCore",
-                    "RHI",
-                    "RuntimeMeshComponent",
-                    "RawMesh",
-                    "AssetTools",
-                    "AssetRegistry"
-                }
-				);
-		}
-	}
-}

+ 0 - 1
spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpinePluginPrivatePCH.h

@@ -34,7 +34,6 @@
 #include "SpineSkeletonComponent.h"
 #include "SpineSkeletonAnimationComponent.h"
 #include "SpineSkeletonRendererComponent.h"
-#include "SpineSkeletonRendererComponentPMC.h"
 #include "SpineBoneFollowerComponent.h"
 #include "SpineBoneDriverComponent.h"
 #include "SpineWidget.h"

+ 6 - 12
spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonRendererComponent.cpp

@@ -38,21 +38,21 @@
 using namespace spine;
 
 USpineSkeletonRendererComponent::USpineSkeletonRendererComponent (const FObjectInitializer& ObjectInitializer) 
-: URuntimeMeshComponent(ObjectInitializer) {
+: UProceduralMeshComponent(ObjectInitializer) {
 	PrimaryComponentTick.bCanEverTick = true;
 	bTickInEditor = true;
 	bAutoActivate = true;
 
-	static ConstructorHelpers::FObjectFinder<UMaterialInterface> NormalMaterialRef(TEXT("/SpinePlugin/SpineUnlitNormalMaterial"));
+	static ConstructorHelpers::FObjectFinder<UMaterialInterface> NormalMaterialRef(TEXT("/SpinePlugin/SpineUnlitNormalMaterialPMC"));
 	NormalBlendMaterial = NormalMaterialRef.Object;
 	
-	static ConstructorHelpers::FObjectFinder<UMaterialInterface> AdditiveMaterialRef(TEXT("/SpinePlugin/SpineUnlitAdditiveMaterial"));
+	static ConstructorHelpers::FObjectFinder<UMaterialInterface> AdditiveMaterialRef(TEXT("/SpinePlugin/SpineUnlitAdditiveMaterialPMC"));
 	AdditiveBlendMaterial = AdditiveMaterialRef.Object;
 	
-	static ConstructorHelpers::FObjectFinder<UMaterialInterface> MultiplyMaterialRef(TEXT("/SpinePlugin/SpineUnlitMultiplyMaterial"));
+	static ConstructorHelpers::FObjectFinder<UMaterialInterface> MultiplyMaterialRef(TEXT("/SpinePlugin/SpineUnlitMultiplyMaterialPMC"));
 	MultiplyBlendMaterial = MultiplyMaterialRef.Object;
 	
-	static ConstructorHelpers::FObjectFinder<UMaterialInterface> ScreenMaterialRef(TEXT("/SpinePlugin/SpineUnlitScreenMaterial"));
+	static ConstructorHelpers::FObjectFinder<UMaterialInterface> ScreenMaterialRef(TEXT("/SpinePlugin/SpineUnlitScreenMaterialPMC"));
 	ScreenBlendMaterial = ScreenMaterialRef.Object;
 	
 	TextureParameterName = FName(TEXT("SpriteTexture"));
@@ -169,14 +169,8 @@ void USpineSkeletonRendererComponent::Flush (int &Idx, TArray<FVector> &Vertices
 	if (Vertices.Num() == 0) return;
 	SetMaterial(Idx, Material);
 
-	TArray<FRuntimeMeshVertexTripleUV> verts;
-	for (int32 i = 0; i < Vertices.Num(); i++) {
-		verts.Add(FRuntimeMeshVertexTripleUV(Vertices[i], FVector(), FVector(), Colors[i], Uvs[i], FVector2D(Colors2[i].X, Colors2[i].Y), FVector2D(Colors2[i].Z, 0)));
-	}
-
-	CreateMeshSection(Idx, verts, Indices, true);
+	CreateMeshSection(Idx, Vertices, Indices, TArray<FVector>(), Uvs, Colors, TArray<FProcMeshTangent>(), true);
 
-	// CreateMeshSection(Idx, Vertices, Indices, TArray<FVector>(), Uvs, darkRG, Colors, TArray<FRuntimeMeshTangent>(), false);
 	Vertices.SetNum(0);
 	Indices.SetNum(0);
 	Uvs.SetNum(0);

+ 0 - 311
spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Private/SpineSkeletonRendererComponentPMC.cpp

@@ -1,311 +0,0 @@
-/******************************************************************************
- * Spine Runtimes Software License v2.5
- *
- * Copyright (c) 2013-2016, Esoteric Software
- * All rights reserved.
- *
- * You are granted a perpetual, non-exclusive, non-sublicensable, and
- * non-transferable license to use, install, execute, and perform the Spine
- * Runtimes software and derivative works solely for personal or internal
- * use. Without the written permission of Esoteric Software (see Section 2 of
- * the Spine Software License Agreement), you may not (a) modify, translate,
- * adapt, or develop new applications using the Spine Runtimes or otherwise
- * create derivative works or improvements of the Spine Runtimes or (b) remove,
- * delete, alter, or obscure any trademarks or any copyright, trademark, patent,
- * or other intellectual property or proprietary rights notices on or in the
- * Software, including any copy thereof. Redistributions in binary or source
- * form must include this license and terms.
- *
- * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF
- * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *****************************************************************************/
-
-#include "SpinePluginPrivatePCH.h"
-#include "Engine.h"
-#include "spine/spine.h"
-#include <stdlib.h>
-
-#define LOCTEXT_NAMESPACE "Spine"
-
-using namespace spine;
-
-USpineSkeletonRendererComponentPMC::USpineSkeletonRendererComponentPMC(const FObjectInitializer& ObjectInitializer)
-: UProceduralMeshComponent(ObjectInitializer) {
-	PrimaryComponentTick.bCanEverTick = true;
-	bTickInEditor = true;
-	bAutoActivate = true;
-
-	static ConstructorHelpers::FObjectFinder<UMaterialInterface> NormalMaterialRef(TEXT("/SpinePlugin/SpineUnlitNormalMaterialPMC"));
-	NormalBlendMaterial = NormalMaterialRef.Object;
-	
-	static ConstructorHelpers::FObjectFinder<UMaterialInterface> AdditiveMaterialRef(TEXT("/SpinePlugin/SpineUnlitAdditiveMaterialPMC"));
-	AdditiveBlendMaterial = AdditiveMaterialRef.Object;
-	
-	static ConstructorHelpers::FObjectFinder<UMaterialInterface> MultiplyMaterialRef(TEXT("/SpinePlugin/SpineUnlitMultiplyMaterialPMC"));
-	MultiplyBlendMaterial = MultiplyMaterialRef.Object;
-	
-	static ConstructorHelpers::FObjectFinder<UMaterialInterface> ScreenMaterialRef(TEXT("/SpinePlugin/SpineUnlitScreenMaterialPMC"));
-	ScreenBlendMaterial = ScreenMaterialRef.Object;
-	
-	TextureParameterName = FName(TEXT("SpriteTexture"));
-
-	worldVertices.ensureCapacity(1024 * 2);
-}
-
-void USpineSkeletonRendererComponentPMC::FinishDestroy() {
-	Super::FinishDestroy();
-}
-
-void USpineSkeletonRendererComponentPMC::BeginPlay () {
-	Super::BeginPlay();
-}
-
-void USpineSkeletonRendererComponentPMC::TickComponent (float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) {
-	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
-	
-	AActor* owner = GetOwner();
-	if (owner) {
-		UClass* skeletonClass = USpineSkeletonComponent::StaticClass();
-		USpineSkeletonComponent* skeleton = Cast<USpineSkeletonComponent>(owner->GetComponentByClass(skeletonClass));
-		
-		if (skeleton && !skeleton->IsBeingDestroyed() && skeleton->GetSkeleton() && skeleton->Atlas) {
-			skeleton->GetSkeleton()->getColor().set(Color.R, Color.G, Color.B, Color.A);
-
-			if (atlasNormalBlendMaterials.Num() != skeleton->Atlas->atlasPages.Num()) {
-				atlasNormalBlendMaterials.SetNum(0);
-				pageToNormalBlendMaterial.Empty();
-				atlasAdditiveBlendMaterials.SetNum(0);
-				pageToAdditiveBlendMaterial.Empty();
-				atlasMultiplyBlendMaterials.SetNum(0);
-				pageToMultiplyBlendMaterial.Empty();
-				atlasScreenBlendMaterials.SetNum(0);
-				pageToScreenBlendMaterial.Empty();
-								
-				for (int i = 0; i < skeleton->Atlas->atlasPages.Num(); i++) {
-					AtlasPage* currPage = skeleton->Atlas->GetAtlas(false)->getPages()[i];
-					
-					UMaterialInstanceDynamic* material = UMaterialInstanceDynamic::Create(NormalBlendMaterial, owner);
-					material->SetTextureParameterValue(TextureParameterName, skeleton->Atlas->atlasPages[i]);
-					atlasNormalBlendMaterials.Add(material);
-					pageToNormalBlendMaterial.Add(currPage, material);
-					
-					material = UMaterialInstanceDynamic::Create(AdditiveBlendMaterial, owner);
-					material->SetTextureParameterValue(TextureParameterName, skeleton->Atlas->atlasPages[i]);
-					atlasAdditiveBlendMaterials.Add(material);
-					pageToAdditiveBlendMaterial.Add(currPage, material);
-					
-					material = UMaterialInstanceDynamic::Create(MultiplyBlendMaterial, owner);
-					material->SetTextureParameterValue(TextureParameterName, skeleton->Atlas->atlasPages[i]);
-					atlasMultiplyBlendMaterials.Add(material);
-					pageToMultiplyBlendMaterial.Add(currPage, material);
-					
-					material = UMaterialInstanceDynamic::Create(ScreenBlendMaterial, owner);
-					material->SetTextureParameterValue(TextureParameterName, skeleton->Atlas->atlasPages[i]);
-					atlasScreenBlendMaterials.Add(material);
-					pageToScreenBlendMaterial.Add(currPage, material);					
-				}
-			} else {
-				pageToNormalBlendMaterial.Empty();
-				pageToAdditiveBlendMaterial.Empty();
-				pageToMultiplyBlendMaterial.Empty();
-				pageToScreenBlendMaterial.Empty();
-								
-				for (int i = 0; i < skeleton->Atlas->atlasPages.Num(); i++) {
-					AtlasPage* currPage = skeleton->Atlas->GetAtlas(false)->getPages()[i];
-
-					UTexture2D* texture = skeleton->Atlas->atlasPages[i];
-					UTexture* oldTexture = nullptr;
-					
-					UMaterialInstanceDynamic* current = atlasNormalBlendMaterials[i];
-					if(!current || !current->GetTextureParameterValue(TextureParameterName, oldTexture) || oldTexture != texture) {
-						UMaterialInstanceDynamic* material = UMaterialInstanceDynamic::Create(NormalBlendMaterial, owner);
-						material->SetTextureParameterValue(TextureParameterName, texture);
-						atlasNormalBlendMaterials[i] = material;
-					}
-					pageToNormalBlendMaterial.Add(currPage, atlasNormalBlendMaterials[i]);
-					
-					current = atlasAdditiveBlendMaterials[i];
-					if(!current || !current->GetTextureParameterValue(TextureParameterName, oldTexture) || oldTexture != texture) {
-						UMaterialInstanceDynamic* material = UMaterialInstanceDynamic::Create(AdditiveBlendMaterial, owner);
-						material->SetTextureParameterValue(TextureParameterName, texture);
-						atlasAdditiveBlendMaterials[i] = material;
-					}
-					pageToAdditiveBlendMaterial.Add(currPage, atlasAdditiveBlendMaterials[i]);
-					
-					current = atlasMultiplyBlendMaterials[i];
-					if(!current || !current->GetTextureParameterValue(TextureParameterName, oldTexture) || oldTexture != texture) {
-						UMaterialInstanceDynamic* material = UMaterialInstanceDynamic::Create(MultiplyBlendMaterial, owner);
-						material->SetTextureParameterValue(TextureParameterName, texture);
-						atlasMultiplyBlendMaterials[i] = material;
-					}
-					pageToMultiplyBlendMaterial.Add(currPage, atlasMultiplyBlendMaterials[i]);
-					
-					current = atlasScreenBlendMaterials[i];
-					if(!current || !current->GetTextureParameterValue(TextureParameterName, oldTexture) || oldTexture != texture) {
-						UMaterialInstanceDynamic* material = UMaterialInstanceDynamic::Create(ScreenBlendMaterial, owner);
-						material->SetTextureParameterValue(TextureParameterName, texture);
-						atlasScreenBlendMaterials[i] = material;
-					}
-					pageToScreenBlendMaterial.Add(currPage, atlasScreenBlendMaterials[i]);
-				}
-			}
-			UpdateMesh(skeleton->GetSkeleton());
-		} else {
-			ClearAllMeshSections();
-		}
-	}
-}
-
-
-void USpineSkeletonRendererComponentPMC::Flush (int &Idx, TArray<FVector> &Vertices, TArray<int32> &Indices, TArray<FVector2D> &Uvs, TArray<FColor> &Colors, TArray<FVector>& Colors2, UMaterialInstanceDynamic* Material) {
-	if (Vertices.Num() == 0) return;
-	SetMaterial(Idx, Material);	
-	
-	CreateMeshSection(Idx, Vertices, Indices, TArray<FVector>(), Uvs, Colors, TArray<FProcMeshTangent>(), true);
-	
-	Vertices.SetNum(0);
-	Indices.SetNum(0);
-	Uvs.SetNum(0);
-	Colors.SetNum(0);
-	Colors2.SetNum(0);
-	Idx++;
-}
-
-void USpineSkeletonRendererComponentPMC::UpdateMesh(Skeleton* Skeleton) {
-	TArray<FVector> vertices;
-	TArray<int32> indices;
-	TArray<FVector2D> uvs;
-	TArray<FColor> colors;
-	TArray<FVector> darkColors;
-	
-	int idx = 0;
-	int meshSection = 0;
-	UMaterialInstanceDynamic* lastMaterial = nullptr;
-
-	ClearAllMeshSections();
-
-	float depthOffset = 0;
-	unsigned short quadIndices[] = { 0, 1, 2, 0, 2, 3 };
-
-	for (int i = 0; i < Skeleton->getSlots().size(); ++i) {
-		Vector<float> &attachmentVertices = worldVertices;
-		unsigned short* attachmentIndices = nullptr;
-		int numVertices;
-		int numIndices;
-		AtlasRegion* attachmentAtlasRegion = nullptr;
-		spine::Color attachmentColor;
-		attachmentColor.set(1, 1, 1, 1);
-		float* attachmentUvs = nullptr;
-
-		Slot* slot = Skeleton->getDrawOrder()[i];
-		Attachment* attachment = slot->getAttachment();
-		if (!attachment) continue;
-		if (!attachment->getRTTI().isExactly(RegionAttachment::rtti) && !attachment->getRTTI().isExactly(MeshAttachment::rtti) && !attachment->getRTTI().isExactly(ClippingAttachment::rtti)) continue;		
-		
-		if (attachment->getRTTI().isExactly(RegionAttachment::rtti)) {
-			RegionAttachment* regionAttachment = (RegionAttachment*)attachment;
-			attachmentColor.set(regionAttachment->getColor());
-			attachmentAtlasRegion = (AtlasRegion*)regionAttachment->getRendererObject();
-			regionAttachment->computeWorldVertices(slot->getBone(), attachmentVertices, 0, 2);
-			attachmentIndices = quadIndices;
-			attachmentUvs = regionAttachment->getUVs().buffer();
-			numVertices = 4;
-			numIndices = 6;
-		} else if (attachment->getRTTI().isExactly(MeshAttachment::rtti)) {
-			MeshAttachment* mesh = (MeshAttachment*)attachment;
-			attachmentColor.set(mesh->getColor());
-			attachmentAtlasRegion = (AtlasRegion*)mesh->getRendererObject();			
-			mesh->computeWorldVertices(*slot, 0, mesh->getWorldVerticesLength(), attachmentVertices, 0, 2);
-			attachmentIndices = mesh->getTriangles().buffer();
-			attachmentUvs = mesh->getUVs().buffer();
-			numVertices = mesh->getWorldVerticesLength() >> 1;
-			numIndices = mesh->getTriangles().size();
-		} else /* clipping */ {
-			ClippingAttachment* clip = (ClippingAttachment*)attachment;
-			clipper.clipStart(*slot, clip);
-			continue;
-		}
-
-		// if the user switches the atlas data while not having switched
-		// to the correct skeleton data yet, we won't find any regions.
-		// ignore regions for which we can't find a material
-		UMaterialInstanceDynamic* material = nullptr;
-		switch (slot->getData().getBlendMode()) {
-		case BlendMode_Normal:
-			if (!pageToNormalBlendMaterial.Contains(attachmentAtlasRegion->page)) continue;
-			material = pageToNormalBlendMaterial[attachmentAtlasRegion->page];
-			break;
-		case BlendMode_Additive:
-			if (!pageToAdditiveBlendMaterial.Contains(attachmentAtlasRegion->page)) continue;
-			material = pageToAdditiveBlendMaterial[attachmentAtlasRegion->page];
-			break;
-		case BlendMode_Multiply:
-			if (!pageToMultiplyBlendMaterial.Contains(attachmentAtlasRegion->page)) continue;
-			material = pageToMultiplyBlendMaterial[attachmentAtlasRegion->page];
-			break;
-		case BlendMode_Screen:
-			if (!pageToScreenBlendMaterial.Contains(attachmentAtlasRegion->page)) continue;
-			material = pageToScreenBlendMaterial[attachmentAtlasRegion->page];
-			break;
-		default:
-			if (!pageToNormalBlendMaterial.Contains(attachmentAtlasRegion->page)) continue;
-			material = pageToNormalBlendMaterial[attachmentAtlasRegion->page];
-		}
-
-		if (clipper.isClipping()) {
-			clipper.clipTriangles(attachmentVertices.buffer(), attachmentIndices, numIndices, attachmentUvs, 2);
-			attachmentVertices = clipper.getClippedVertices();
-			numVertices = clipper.getClippedVertices().size() >> 1;
-			attachmentIndices = clipper.getClippedTriangles().buffer();
-			numIndices = clipper.getClippedTriangles().size();
-			attachmentUvs = clipper.getClippedUVs().buffer();
-			if (clipper.getClippedTriangles().size() == 0) continue;
-		}
-
-		if (lastMaterial != material) {
-			Flush(meshSection, vertices, indices, uvs, colors, darkColors, lastMaterial);
-			lastMaterial = material;
-			idx = 0;
-		}
-
-		SetMaterial(meshSection, material);
-
-		uint8 r = static_cast<uint8>(Skeleton->getColor().r * slot->getColor().r * attachmentColor.r * 255);
-		uint8 g = static_cast<uint8>(Skeleton->getColor().g * slot->getColor().g * attachmentColor.g * 255);
-		uint8 b = static_cast<uint8>(Skeleton->getColor().b * slot->getColor().b * attachmentColor.b * 255);
-		uint8 a = static_cast<uint8>(Skeleton->getColor().a * slot->getColor().a * attachmentColor.a * 255);
-
-		float dr = slot->hasDarkColor() ? slot->getDarkColor().r : 0.0f;
-		float dg = slot->hasDarkColor() ? slot->getDarkColor().g : 0.0f;
-		float db = slot->hasDarkColor() ? slot->getDarkColor().b : 0.0f;		
-
-		for (int j = 0; j < numVertices << 1; j += 2) {
-			colors.Add(FColor(r, g, b, a));
-			darkColors.Add(FVector(dr, dg, db));
-			vertices.Add(FVector(attachmentVertices[j], depthOffset, attachmentVertices[j + 1]));
-			uvs.Add(FVector2D(attachmentUvs[j], attachmentUvs[j + 1]));
-		}
-
-		for (int j = 0; j < numIndices; j++) {
-			indices.Add(idx + attachmentIndices[j]);
-		}
-
-		idx += numVertices;
-		depthOffset += this->DepthOffset;
-
-		clipper.clipEnd(*slot);			
-	}
-	
-	Flush(meshSection, vertices, indices, uvs, colors, darkColors, lastMaterial);
-	clipper.clipEnd();
-}
-
-#undef LOCTEXT_NAMESPACE

+ 2 - 2
spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonRendererComponent.h

@@ -31,13 +31,13 @@
 #pragma once
 
 #include "Components/ActorComponent.h"
-#include "RuntimeMeshComponent.h"
+#include "ProceduralMeshComponent.h"
 #include "SpineSkeletonAnimationComponent.h"
 #include "SpineSkeletonRendererComponent.generated.h"
 
 
 UCLASS(ClassGroup=(Spine), meta=(BlueprintSpawnableComponent))
-class SPINEPLUGIN_API USpineSkeletonRendererComponent: public URuntimeMeshComponent {
+class SPINEPLUGIN_API USpineSkeletonRendererComponent: public UProceduralMeshComponent {
 	GENERATED_BODY()
 
 public: 

+ 0 - 97
spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/Public/SpineSkeletonRendererComponentPMC.h

@@ -1,97 +0,0 @@
-/******************************************************************************
- * Spine Runtimes Software License v2.5
- *
- * Copyright (c) 2013-2016, Esoteric Software
- * All rights reserved.
- *
- * You are granted a perpetual, non-exclusive, non-sublicensable, and
- * non-transferable license to use, install, execute, and perform the Spine
- * Runtimes software and derivative works solely for personal or internal
- * use. Without the written permission of Esoteric Software (see Section 2 of
- * the Spine Software License Agreement), you may not (a) modify, translate,
- * adapt, or develop new applications using the Spine Runtimes or otherwise
- * create derivative works or improvements of the Spine Runtimes or (b) remove,
- * delete, alter, or obscure any trademarks or any copyright, trademark, patent,
- * or other intellectual property or proprietary rights notices on or in the
- * Software, including any copy thereof. Redistributions in binary or source
- * form must include this license and terms.
- *
- * THIS SOFTWARE IS PROVIDED BY ESOTERIC SOFTWARE "AS IS" AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL ESOTERIC SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, BUSINESS INTERRUPTION, OR LOSS OF
- * USE, DATA, OR PROFITS) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
- * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *****************************************************************************/
-
-#pragma once
-
-#include "Components/ActorComponent.h"
-#include "ProceduralMeshComponent.h"
-#include "SpineSkeletonAnimationComponent.h"
-#include "SpineSkeletonRendererComponentPMC.generated.h"
-
-
-UCLASS(ClassGroup=(Spine), meta=(BlueprintSpawnableComponent))
-class SPINEPLUGIN_API USpineSkeletonRendererComponentPMC: public UProceduralMeshComponent {
-	GENERATED_BODY()
-
-public: 
-	USpineSkeletonRendererComponentPMC(const FObjectInitializer& ObjectInitializer);
-	
-	virtual void BeginPlay () override;
-		
-	virtual void TickComponent (float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
-
-	UPROPERTY(Category = Spine, EditAnywhere, BlueprintReadOnly)
-	UMaterialInterface* NormalBlendMaterial;
-	
-	UPROPERTY(Category = Spine, EditAnywhere, BlueprintReadOnly)
-	UMaterialInterface* AdditiveBlendMaterial;
-	
-	UPROPERTY(Category = Spine, EditAnywhere, BlueprintReadOnly)
-	UMaterialInterface* MultiplyBlendMaterial;
-	
-	UPROPERTY(Category = Spine, EditAnywhere, BlueprintReadOnly)
-	UMaterialInterface* ScreenBlendMaterial;
-
-	UPROPERTY(Category = Spine, EditAnywhere, BlueprintReadWrite)
-	float DepthOffset = 0.1f;
-	
-	UPROPERTY(Category = Spine, EditAnywhere, BlueprintReadWrite)
-	FName TextureParameterName;
-
-	UPROPERTY(Category = Spine, EditAnywhere, BlueprintReadWrite)
-	FLinearColor Color = FLinearColor(1, 1, 1, 1);
-
-	virtual void FinishDestroy() override;
-	
-protected:
-	void UpdateMesh (spine::Skeleton* Skeleton);
-
-	void Flush (int &Idx, TArray<FVector> &Vertices, TArray<int32> &Indices, TArray<FVector2D> &Uvs, TArray<FColor> &Colors, TArray<FVector> &Colors2, UMaterialInstanceDynamic* Material);
-	
-	// Need to hold on to the dynamic instances, or the GC will kill us while updating them
-	UPROPERTY()
-	TArray<UMaterialInstanceDynamic*> atlasNormalBlendMaterials;
-	TMap<spine::AtlasPage*, UMaterialInstanceDynamic*> pageToNormalBlendMaterial;
-	
-	UPROPERTY()
-	TArray<UMaterialInstanceDynamic*> atlasAdditiveBlendMaterials;
-	TMap<spine::AtlasPage*, UMaterialInstanceDynamic*> pageToAdditiveBlendMaterial;
-	
-	UPROPERTY()
-	TArray<UMaterialInstanceDynamic*> atlasMultiplyBlendMaterials;
-	TMap<spine::AtlasPage*, UMaterialInstanceDynamic*> pageToMultiplyBlendMaterial;
-	
-	UPROPERTY()
-	TArray<UMaterialInstanceDynamic*> atlasScreenBlendMaterials;
-	TMap<spine::AtlasPage*, UMaterialInstanceDynamic*> pageToScreenBlendMaterial;
-
-	spine::Vector<float> worldVertices;
-	spine::SkeletonClipping clipper;
-};

+ 2 - 2
spine-ue4/Plugins/SpinePlugin/Source/SpinePlugin/SpinePlugin.Build.cs

@@ -8,9 +8,9 @@ namespace UnrealBuildTool.Rules
 		{
 			PublicIncludePaths.AddRange(new string[] { "SpinePlugin/Public", "SpinePlugin/Public/spine-cpp/include" });
             PrivateIncludePaths.AddRange(new string[] { "SpinePlugin/Private", "SpinePlugin/Public/spine-cpp/include" });
-            PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "RHI", "RenderCore", "ShaderCore", "RuntimeMeshComponent", "ProceduralMeshComponent", "UMG", "Slate", "SlateCore" });
+            PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "RHI", "RenderCore", "ShaderCore", "ProceduralMeshComponent", "UMG", "Slate", "SlateCore" });
             OptimizeCode = CodeOptimization.Never;
-			Definitions.Add("SPINE_UE4");
+			PublicDefinitions.Add("SPINE_UE4");
 		}
 	}
 }

+ 0 - 4
spine-ue4/Plugins/SpinePlugin/SpinePlugin.uplugin

@@ -29,10 +29,6 @@
     {
       "Name": "ProceduralMeshComponent",
       "Enabled": true
-    },
-    {
-      "Name": "RuntimeMeshComponent",
-      "Enabled":  true
     }
   ]
 }

+ 1 - 1
spine-ue4/Source/SpineUE4/SpineUE4.Build.cs

@@ -6,7 +6,7 @@ public class SpineUE4 : ModuleRules
 {
 	public SpineUE4(ReadOnlyTargetRules Target) : base(Target)
 	{
-		PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "SpinePlugin", "RuntimeMeshComponent" });
+		PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "SpinePlugin", "ProceduralMeshComponent" });
 		PublicIncludePaths.AddRange(new string[] { "SpinePlugin/Public", "SpinePlugin/Classes" });
 
 		PrivateDependencyModuleNames.AddRange(new string[] {  });

+ 1 - 1
spine-ue4/SpineUE4.uproject

@@ -1,6 +1,6 @@
 {
 	"FileVersion": 3,
-	"EngineAssociation": "4.18",
+	"EngineAssociation": "4.19",
 	"Category": "",
 	"Description": "",
 	"Modules": [