Add MeshBase as shared impl part for Mesh and SkinnedMesh

This commit is contained in:
Wojtek Figat
2021-03-30 17:57:53 +02:00
parent 3e1356ba2d
commit e01a0585a8
11 changed files with 272 additions and 256 deletions

View File

@@ -464,7 +464,7 @@ void Mesh::Draw(const RenderContext& renderContext, const DrawInfo& info, float
renderContext.List->AddDrawCall(drawModes, info.Flags, drawCall, entry.ReceiveDecals);
}
bool Mesh::ExtractData(MeshBufferType type, BytesContainer& result) const
bool Mesh::DownloadDataGPU(MeshBufferType type, BytesContainer& result) const
{
GPUBuffer* buffer = nullptr;
switch (type)
@@ -485,7 +485,7 @@ bool Mesh::ExtractData(MeshBufferType type, BytesContainer& result) const
return buffer && buffer->DownloadData(result);
}
Task* Mesh::ExtractDataAsync(MeshBufferType type, BytesContainer& result) const
Task* Mesh::DownloadDataGPUAsync(MeshBufferType type, BytesContainer& result) const
{
GPUBuffer* buffer = nullptr;
switch (type)
@@ -506,6 +506,15 @@ Task* Mesh::ExtractDataAsync(MeshBufferType type, BytesContainer& result) const
return buffer ? buffer->DownloadDataAsync(result) : nullptr;
}
bool Mesh::DownloadDataCPU(MeshBufferType type, BytesContainer& result) const
{
#if !BUILD_RELEASE
// TODO: implement this
LOG(Error, "Mesh::DownloadDataCPU not implemented.");
#endif
return true;
}
ScriptingObject* Mesh::GetParentModel()
{
return _model;
@@ -661,7 +670,7 @@ bool Mesh::DownloadBuffer(bool forceGpu, MonoArray* resultObj, int32 typeI)
// TODO: support reusing the input memory buffer to perform a single copy from staging buffer to the input CPU buffer
BytesContainer data;
auto task = mesh->ExtractDataAsync(bufferType, data);
auto task = mesh->DownloadDataGPUAsync(bufferType, data);
if (task == nullptr)
return true;

View File

@@ -2,9 +2,7 @@
#pragma once
#include "Engine/Core/Math/BoundingBox.h"
#include "Engine/Core/Math/BoundingSphere.h"
#include "Engine/Scripting/ScriptingObject.h"
#include "MeshBase.h"
#include "Engine/Renderer/RenderList.h"
#include "Engine/Graphics/RenderTask.h"
#include "ModelInstanceEntry.h"
@@ -19,21 +17,16 @@ class GPUBuffer;
/// <summary>
/// Represents part of the model that is made of vertices and can be rendered using custom material and transformation.
/// </summary>
API_CLASS(NoSpawn) class FLAXENGINE_API Mesh : public PersistentScriptingObject
API_CLASS(NoSpawn) class FLAXENGINE_API Mesh : public MeshBase
{
DECLARE_SCRIPTING_TYPE_WITH_CONSTRUCTOR_IMPL(Mesh, PersistentScriptingObject);
DECLARE_SCRIPTING_TYPE_WITH_CONSTRUCTOR_IMPL(Mesh, MeshBase);
protected:
Model* _model;
int32 _index;
int32 _lodIndex;
int32 _materialSlotIndex;
bool _use16BitIndexBuffer;
bool _hasLightmapUVs;
BoundingBox _box;
BoundingSphere _sphere;
uint32 _vertices;
uint32 _triangles;
GPUBuffer* _vertexBuffers[3];
GPUBuffer* _indexBuffer;
#if USE_PRECISE_MESH_INTERSECTS
@@ -94,22 +87,6 @@ public:
/// </summary>
API_PROPERTY() void SetMaterialSlotIndex(int32 value);
/// <summary>
/// Gets the triangle count.
/// </summary>
API_PROPERTY() FORCE_INLINE int32 GetTriangleCount() const
{
return _triangles;
}
/// <summary>
/// Gets the vertex count.
/// </summary>
API_PROPERTY() FORCE_INLINE int32 GetVertexCount() const
{
return _vertices;
}
/// <summary>
/// Gets the index buffer.
/// </summary>
@@ -138,15 +115,6 @@ public:
return _vertexBuffers[0] != nullptr;
}
/// <summary>
/// Determines whether this mesh is using 16 bit index buffer, otherwise it's 32 bit.
/// </summary>
/// <returns>True if this mesh is using 16 bit index buffer, otherwise 32 bit index buffer.</returns>
API_PROPERTY() FORCE_INLINE bool Use16BitIndexBuffer() const
{
return _use16BitIndexBuffer;
}
/// <summary>
/// Determines whether this mesh has a vertex colors buffer.
/// </summary>
@@ -165,34 +133,6 @@ public:
return _hasLightmapUVs;
}
/// <summary>
/// Sets the mesh bounds.
/// </summary>
/// <param name="box">The bounding box.</param>
void SetBounds(const BoundingBox& box)
{
_box = box;
BoundingSphere::FromBox(box, _sphere);
}
/// <summary>
/// Gets the box.
/// </summary>
/// <returns>The bounding box.</returns>
API_PROPERTY() FORCE_INLINE const BoundingBox& GetBox() const
{
return _box;
}
/// <summary>
/// Gets the sphere.
/// </summary>
/// <returns>The bounding sphere.</returns>
API_PROPERTY() FORCE_INLINE const BoundingSphere& GetSphere() const
{
return _sphere;
}
#if USE_PRECISE_MESH_INTERSECTS
/// <summary>
@@ -473,21 +413,10 @@ public:
public:
/// <summary>
/// Extract mesh buffer data (cannot be called from the main thread!).
/// </summary>
/// <param name="type">Buffer type</param>
/// <param name="result">The result data</param>
/// <returns>True if failed, otherwise false</returns>
bool ExtractData(MeshBufferType type, BytesContainer& result) const;
/// <summary>
/// Extracts mesh buffer data in the async task.
/// </summary>
/// <param name="type">Buffer type</param>
/// <param name="result">The result data</param>
/// <returns>Created async task used to gather the buffer data.</returns>
Task* ExtractDataAsync(MeshBufferType type, BytesContainer& result) const;
// [MeshBase]
bool DownloadDataGPU(MeshBufferType type, BytesContainer& result) const override;
Task* DownloadDataGPUAsync(MeshBufferType type, BytesContainer& result) const override;
bool DownloadDataCPU(MeshBufferType type, BytesContainer& result) const override;
private:

View File

@@ -0,0 +1,110 @@
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
#pragma once
#include "Engine/Core/Math/BoundingBox.h"
#include "Engine/Core/Math/BoundingSphere.h"
#include "Engine/Core/Types/DataContainer.h"
#include "Engine/Graphics/Models/Types.h"
#include "Engine/Scripting/ScriptingObject.h"
class Task;
/// <summary>
/// Base class for model resources meshes.
/// </summary>
API_CLASS(Abstract, NoSpawn) class FLAXENGINE_API MeshBase : public PersistentScriptingObject
{
DECLARE_SCRIPTING_TYPE_MINIMAL(MeshBase);
protected:
bool _use16BitIndexBuffer;
BoundingBox _box;
BoundingSphere _sphere;
uint32 _vertices;
uint32 _triangles;
explicit MeshBase(const SpawnParams& params)
: PersistentScriptingObject(params)
{
}
public:
/// <summary>
/// Gets the triangle count.
/// </summary>
/// <returns>The triangles</returns>
API_PROPERTY() FORCE_INLINE int32 GetTriangleCount() const
{
return _triangles;
}
/// <summary>
/// Gets the vertex count.
/// </summary>
/// <returns>The vertices</returns>
API_PROPERTY() FORCE_INLINE int32 GetVertexCount() const
{
return _vertices;
}
/// <summary>
/// Gets the box.
/// </summary>
/// <returns>The bounding box.</returns>
API_PROPERTY() FORCE_INLINE const BoundingBox& GetBox() const
{
return _box;
}
/// <summary>
/// Gets the sphere.
/// </summary>
/// <returns>The bounding sphere.</returns>
API_PROPERTY() FORCE_INLINE const BoundingSphere& GetSphere() const
{
return _sphere;
}
/// <summary>
/// Determines whether this mesh is using 16 bit index buffer, otherwise it's 32 bit.
/// </summary>
/// <returns>True if this mesh is using 16 bit index buffer, otherwise 32 bit index buffer.</returns>
API_PROPERTY() FORCE_INLINE bool Use16BitIndexBuffer() const
{
return _use16BitIndexBuffer;
}
/// <summary>
/// Sets the mesh bounds.
/// </summary>
/// <param name="box">The bounding box.</param>
void SetBounds(const BoundingBox& box);
public:
/// <summary>
/// Extract mesh buffer data from GPU. Cannot be called from the main thread.
/// </summary>
/// <param name="type">Buffer type</param>
/// <param name="result">The result data</param>
/// <returns>True if failed, otherwise false</returns>
virtual bool DownloadDataGPU(MeshBufferType type, BytesContainer& result) const = 0;
/// <summary>
/// Extracts mesh buffer data from GPU in the async task.
/// </summary>
/// <param name="type">Buffer type</param>
/// <param name="result">The result data</param>
/// <returns>Created async task used to gather the buffer data.</returns>
virtual Task* DownloadDataGPUAsync(MeshBufferType type, BytesContainer& result) const = 0;
/// <summary>
/// Extract mesh buffer data from CPU. Cached internally.
/// </summary>
/// <param name="type">Buffer type</param>
/// <param name="result">The result data</param>
/// <returns>True if failed, otherwise false</returns>
virtual bool DownloadDataCPU(MeshBufferType type, BytesContainer& result) const = 0;
};

View File

@@ -218,7 +218,7 @@ bool SkinnedMesh::DownloadDataGPU(MeshBufferType type, BytesContainer& result) c
return buffer && buffer->DownloadData(result);
}
Task* SkinnedMesh::DownloadDataAsyncGPU(MeshBufferType type, BytesContainer& result) const
Task* SkinnedMesh::DownloadDataGPUAsync(MeshBufferType type, BytesContainer& result) const
{
GPUBuffer* buffer = nullptr;
switch (type)
@@ -535,7 +535,7 @@ bool SkinnedMesh::DownloadBuffer(bool forceGpu, MonoArray* resultObj, int32 type
{
// Get data from GPU
// TODO: support reusing the input memory buffer to perform a single copy from staging buffer to the input CPU buffer
auto task = mesh->DownloadDataAsyncGPU(bufferType, data);
auto task = mesh->DownloadDataGPUAsync(bufferType, data);
if (task == nullptr)
return true;
task->Start();

View File

@@ -2,9 +2,7 @@
#pragma once
#include "Engine/Core/Math/BoundingBox.h"
#include "Engine/Core/Math/BoundingSphere.h"
#include "Engine/Scripting/ScriptingObject.h"
#include "MeshBase.h"
#include "Engine/Renderer/RenderList.h"
#include "Engine/Graphics/RenderTask.h"
#include "ModelInstanceEntry.h"
@@ -16,20 +14,15 @@ class GPUBuffer;
/// <summary>
/// Represents part of the skinned model that is made of vertices and can be rendered using custom material, transformation and skeleton bones hierarchy.
/// </summary>
API_CLASS(NoSpawn) class FLAXENGINE_API SkinnedMesh : public PersistentScriptingObject
API_CLASS(NoSpawn) class FLAXENGINE_API SkinnedMesh : public MeshBase
{
DECLARE_SCRIPTING_TYPE_WITH_CONSTRUCTOR_IMPL(SkinnedMesh, PersistentScriptingObject);
DECLARE_SCRIPTING_TYPE_WITH_CONSTRUCTOR_IMPL(SkinnedMesh, MeshBase);
protected:
SkinnedModel* _model;
int32 _index;
int32 _lodIndex;
int32 _materialSlotIndex;
bool _use16BitIndexBuffer;
BoundingBox _box;
BoundingSphere _sphere;
uint32 _vertices;
uint32 _triangles;
GPUBuffer* _vertexBuffer;
GPUBuffer* _indexBuffer;
mutable Array<byte> _cachedIndexBuffer;
@@ -85,24 +78,6 @@ public:
/// <param name="value">The value.</param>
API_PROPERTY() void SetMaterialSlotIndex(int32 value);
/// <summary>
/// Gets the triangle count.
/// </summary>
/// <returns>The triangles</returns>
API_PROPERTY() FORCE_INLINE int32 GetTriangleCount() const
{
return _triangles;
}
/// <summary>
/// Gets the vertex count.
/// </summary>
/// <returns>The vertices</returns>
API_PROPERTY() FORCE_INLINE int32 GetVertexCount() const
{
return _vertices;
}
/// <summary>
/// Determines whether this mesh is initialized (has vertex and index buffers initialized).
/// </summary>
@@ -112,15 +87,6 @@ public:
return _vertexBuffer != nullptr;
}
/// <summary>
/// Determines whether this mesh is using 16 bit index buffer, otherwise it's 32 bit.
/// </summary>
/// <returns>True if this mesh is using 16 bit index buffer, otherwise 32 bit index buffer.</returns>
API_PROPERTY() FORCE_INLINE bool Use16BitIndexBuffer() const
{
return _use16BitIndexBuffer;
}
/// <summary>
/// Blend shapes used by this mesh.
/// </summary>
@@ -194,36 +160,6 @@ public:
/// <returns>True if failed, otherwise false.</returns>
bool UpdateMesh(uint32 vertexCount, uint32 triangleCount, VB0SkinnedElementType* vb, void* ib, bool use16BitIndices);
public:
/// <summary>
/// Sets the mesh bounds.
/// </summary>
/// <param name="box">The bounding box.</param>
void SetBounds(const BoundingBox& box)
{
_box = box;
BoundingSphere::FromBox(box, _sphere);
}
/// <summary>
/// Gets the box.
/// </summary>
/// <returns>The bounding box.</returns>
API_PROPERTY() FORCE_INLINE BoundingBox GetBox() const
{
return _box;
}
/// <summary>
/// Gets the sphere.
/// </summary>
/// <returns>The bounding sphere.</returns>
API_PROPERTY() FORCE_INLINE BoundingSphere GetSphere() const
{
return _sphere;
}
public:
/// <summary>
@@ -319,29 +255,10 @@ public:
public:
/// <summary>
/// Extract mesh buffer data from the GPU (cannot be called from the main thread!).
/// </summary>
/// <param name="type">Buffer type</param>
/// <param name="result">The result data</param>
/// <returns>True if failed, otherwise false</returns>
bool DownloadDataGPU(MeshBufferType type, BytesContainer& result) const;
/// <summary>
/// Extracts mesh buffer data from the GPU in the async task.
/// </summary>
/// <param name="type">Buffer type</param>
/// <param name="result">The result data</param>
/// <returns>Created async task used to gather the buffer data.</returns>
Task* DownloadDataAsyncGPU(MeshBufferType type, BytesContainer& result) const;
/// <summary>
/// Extract mesh buffer data from the CPU.
/// </summary>
/// <param name="type">Buffer type</param>
/// <param name="result">The result data</param>
/// <returns>True if failed, otherwise false</returns>
bool DownloadDataCPU(MeshBufferType type, BytesContainer& result) const;
// [MeshBase]
bool DownloadDataGPU(MeshBufferType type, BytesContainer& result) const override;
Task* DownloadDataGPUAsync(MeshBufferType type, BytesContainer& result) const override;
bool DownloadDataCPU(MeshBufferType type, BytesContainer& result) const override;
private: