mirror of
https://github.com/EsotericSoftware/spine-runtimes.git
synced 2025-12-21 17:56:04 +08:00
188 lines
4.9 KiB
C++
188 lines
4.9 KiB
C++
// 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;
|
|
};
|