Add MeshBase as shared impl part for Mesh and SkinnedMesh
This commit is contained in:
@@ -396,21 +396,21 @@ bool Model::Save(bool withMeshDataFromGpu, const StringView& path)
|
||||
auto& meshData = meshesData[meshIndex];
|
||||
|
||||
// Vertex Buffer 0 (required)
|
||||
auto task = mesh.ExtractDataAsync(MeshBufferType::Vertex0, meshData.VB0);
|
||||
auto task = mesh.DownloadDataGPUAsync(MeshBufferType::Vertex0, meshData.VB0);
|
||||
if (task == nullptr)
|
||||
return true;
|
||||
task->Start();
|
||||
tasks.Add(task);
|
||||
|
||||
// Vertex Buffer 1 (required)
|
||||
task = mesh.ExtractDataAsync(MeshBufferType::Vertex1, meshData.VB1);
|
||||
task = mesh.DownloadDataGPUAsync(MeshBufferType::Vertex1, meshData.VB1);
|
||||
if (task == nullptr)
|
||||
return true;
|
||||
task->Start();
|
||||
tasks.Add(task);
|
||||
|
||||
// Vertex Buffer 2 (optional)
|
||||
task = mesh.ExtractDataAsync(MeshBufferType::Vertex2, meshData.VB2);
|
||||
task = mesh.DownloadDataGPUAsync(MeshBufferType::Vertex2, meshData.VB2);
|
||||
if (task)
|
||||
{
|
||||
task->Start();
|
||||
@@ -418,7 +418,7 @@ bool Model::Save(bool withMeshDataFromGpu, const StringView& path)
|
||||
}
|
||||
|
||||
// Index Buffer (required)
|
||||
task = mesh.ExtractDataAsync(MeshBufferType::Index, meshData.IB);
|
||||
task = mesh.DownloadDataGPUAsync(MeshBufferType::Index, meshData.IB);
|
||||
if (task == nullptr)
|
||||
return true;
|
||||
task->Start();
|
||||
@@ -618,6 +618,19 @@ void Model::SetupMaterialSlots(int32 slotsCount)
|
||||
}
|
||||
}
|
||||
|
||||
int32 Model::GetLODsCount() const
|
||||
{
|
||||
return LODs.Count();
|
||||
}
|
||||
|
||||
void Model::GetMeshes(Array<MeshBase*>& meshes, int32 lodIndex)
|
||||
{
|
||||
auto& lod = LODs[lodIndex];
|
||||
meshes.Resize(lod.Meshes.Count());
|
||||
for (int32 meshIndex = 0; meshIndex < lod.Meshes.Count(); meshIndex++)
|
||||
meshes[meshIndex] = &lod.Meshes[meshIndex];
|
||||
}
|
||||
|
||||
void Model::InitAsVirtual()
|
||||
{
|
||||
// Init with a single LOD and one mesh
|
||||
@@ -628,6 +641,21 @@ void Model::InitAsVirtual()
|
||||
BinaryAsset::InitAsVirtual();
|
||||
}
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
void Model::GetReferences(Array<Guid>& output) const
|
||||
{
|
||||
// Base
|
||||
BinaryAsset::GetReferences(output);
|
||||
|
||||
for (int32 i = 0; i < MaterialSlots.Count(); i++)
|
||||
{
|
||||
output.Add(MaterialSlots[i].Material.GetID());
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int32 Model::GetMaxResidency() const
|
||||
{
|
||||
return LODs.Count();
|
||||
@@ -837,3 +865,33 @@ AssetChunksFlag Model::getChunksToPreload() const
|
||||
// Note: we don't preload any LODs here because it's done by the Streaming Manager
|
||||
return GET_CHUNK_FLAG(0);
|
||||
}
|
||||
|
||||
void ModelBase::SetupMaterialSlots(int32 slotsCount)
|
||||
{
|
||||
CHECK(slotsCount >= 0 && slotsCount < 4096);
|
||||
if (!IsVirtual() && WaitForLoaded())
|
||||
return;
|
||||
|
||||
ScopeLock lock(Locker);
|
||||
|
||||
const int32 prevCount = MaterialSlots.Count();
|
||||
MaterialSlots.Resize(slotsCount, false);
|
||||
|
||||
// Initialize slot names
|
||||
for (int32 i = prevCount; i < slotsCount; i++)
|
||||
MaterialSlots[i].Name = String::Format(TEXT("Material {0}"), i + 1);
|
||||
}
|
||||
|
||||
MaterialSlot* ModelBase::GetSlot(const StringView& name)
|
||||
{
|
||||
MaterialSlot* result = nullptr;
|
||||
for (auto& slot : MaterialSlots)
|
||||
{
|
||||
if (slot.Name == name)
|
||||
{
|
||||
result = &slot;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -55,15 +55,6 @@ public:
|
||||
return LODs.HasItems();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets amount of the level of details in the model
|
||||
/// </summary>
|
||||
/// <returns>Amount of the level of details in the model</returns>
|
||||
FORCE_INLINE int32 GetLODsCount() const
|
||||
{
|
||||
return LODs.Count();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the amount of loaded model LODs.
|
||||
/// </summary>
|
||||
@@ -237,18 +228,11 @@ public:
|
||||
|
||||
// [ModelBase]
|
||||
void SetupMaterialSlots(int32 slotsCount) override;
|
||||
int32 GetLODsCount() const override;
|
||||
void GetMeshes(Array<MeshBase*>& meshes, int32 lodIndex = 0) override;
|
||||
void InitAsVirtual() override;
|
||||
#if USE_EDITOR
|
||||
void GetReferences(Array<Guid>& output) const override
|
||||
{
|
||||
// Base
|
||||
BinaryAsset::GetReferences(output);
|
||||
|
||||
for (int32 i = 0; i < MaterialSlots.Count(); i++)
|
||||
{
|
||||
output.Add(MaterialSlots[i].Material.GetID());
|
||||
}
|
||||
}
|
||||
void GetReferences(Array<Guid>& output) const override;
|
||||
#endif
|
||||
|
||||
// [StreamableResource]
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include "Engine/Graphics/Models/MaterialSlot.h"
|
||||
#include "Engine/Streaming/StreamableResource.h"
|
||||
|
||||
class MeshBase;
|
||||
|
||||
/// <summary>
|
||||
/// Base class for asset types that can contain a model resource.
|
||||
/// </summary>
|
||||
@@ -44,38 +46,23 @@ public:
|
||||
/// <summary>
|
||||
/// Resizes the material slots collection. Updates meshes that were using removed slots.
|
||||
/// </summary>
|
||||
API_FUNCTION() virtual void SetupMaterialSlots(int32 slotsCount)
|
||||
{
|
||||
CHECK(slotsCount >= 0 && slotsCount < 4096);
|
||||
if (!IsVirtual() && WaitForLoaded())
|
||||
return;
|
||||
|
||||
ScopeLock lock(Locker);
|
||||
|
||||
const int32 prevCount = MaterialSlots.Count();
|
||||
MaterialSlots.Resize(slotsCount, false);
|
||||
|
||||
// Initialize slot names
|
||||
for (int32 i = prevCount; i < slotsCount; i++)
|
||||
MaterialSlots[i].Name = String::Format(TEXT("Material {0}"), i + 1);
|
||||
}
|
||||
API_FUNCTION() virtual void SetupMaterialSlots(int32 slotsCount);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the material slot by the name.
|
||||
/// </summary>
|
||||
/// <param name="name">The slot name.</param>
|
||||
/// <returns>The material slot with the given name or null if cannot find it (asset may be not loaded yet).</returns>
|
||||
API_FUNCTION() MaterialSlot* GetSlot(const StringView& name)
|
||||
{
|
||||
MaterialSlot* result = nullptr;
|
||||
for (auto& slot : MaterialSlots)
|
||||
{
|
||||
if (slot.Name == name)
|
||||
{
|
||||
result = &slot;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
API_FUNCTION() MaterialSlot* GetSlot(const StringView& name);
|
||||
|
||||
/// <summary>
|
||||
/// Gets amount of the level of details in the model.
|
||||
/// </summary>
|
||||
/// <returns>Amount of the level of details in the model.</returns>
|
||||
virtual int32 GetLODsCount() const = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the meshes for a particular LOD index.
|
||||
/// </summary>
|
||||
virtual void GetMeshes(Array<MeshBase*>& meshes, int32 lodIndex = 0) = 0;
|
||||
};
|
||||
|
||||
@@ -137,6 +137,18 @@ Array<String> SkinnedModel::GetBlendShapes()
|
||||
return result;
|
||||
}
|
||||
|
||||
ContentLoadTask* SkinnedModel::RequestLODDataAsync(int32 lodIndex)
|
||||
{
|
||||
const int32 chunkIndex = SKINNED_MODEL_LOD_TO_CHUNK_INDEX(lodIndex);
|
||||
return RequestChunkDataAsync(chunkIndex);
|
||||
}
|
||||
|
||||
void SkinnedModel::GetLODData(int32 lodIndex, BytesContainer& data) const
|
||||
{
|
||||
const int32 chunkIndex = SKINNED_MODEL_LOD_TO_CHUNK_INDEX(lodIndex);
|
||||
GetChunkData(chunkIndex, data);
|
||||
}
|
||||
|
||||
bool SkinnedModel::Intersects(const Ray& ray, const Matrix& world, float& distance, Vector3& normal, SkinnedMesh** mesh, int32 lodIndex)
|
||||
{
|
||||
return LODs[lodIndex].Intersects(ray, world, distance, normal, mesh);
|
||||
@@ -389,7 +401,7 @@ bool SkinnedModel::Save(bool withMeshDataFromGpu, const StringView& path)
|
||||
{
|
||||
auto& slot = MaterialSlots[materialSlotIndex];
|
||||
|
||||
const auto id =slot.Material.GetID();
|
||||
const auto id = slot.Material.GetID();
|
||||
stream->Write(&id);
|
||||
stream->WriteByte(static_cast<byte>(slot.ShadowsMode));
|
||||
stream->WriteString(slot.Name, 11);
|
||||
@@ -505,14 +517,14 @@ bool SkinnedModel::Save(bool withMeshDataFromGpu, const StringView& path)
|
||||
auto& meshData = meshesData[meshIndex];
|
||||
|
||||
// Vertex Buffer 0 (required)
|
||||
auto task = mesh.DownloadDataAsyncGPU(MeshBufferType::Vertex0, meshData.VB0);
|
||||
auto task = mesh.DownloadDataGPUAsync(MeshBufferType::Vertex0, meshData.VB0);
|
||||
if (task == nullptr)
|
||||
return true;
|
||||
task->Start();
|
||||
tasks.Add(task);
|
||||
|
||||
// Index Buffer (required)
|
||||
task = mesh.DownloadDataAsyncGPU(MeshBufferType::Index, meshData.IB);
|
||||
task = mesh.DownloadDataGPUAsync(MeshBufferType::Index, meshData.IB);
|
||||
if (task == nullptr)
|
||||
return true;
|
||||
task->Start();
|
||||
@@ -701,6 +713,19 @@ void SkinnedModel::SetupMaterialSlots(int32 slotsCount)
|
||||
}
|
||||
}
|
||||
|
||||
int32 SkinnedModel::GetLODsCount() const
|
||||
{
|
||||
return LODs.Count();
|
||||
}
|
||||
|
||||
void SkinnedModel::GetMeshes(Array<MeshBase*>& meshes, int32 lodIndex)
|
||||
{
|
||||
auto& lod = LODs[lodIndex];
|
||||
meshes.Resize(lod.Meshes.Count());
|
||||
for (int32 meshIndex = 0; meshIndex < lod.Meshes.Count(); meshIndex++)
|
||||
meshes[meshIndex] = &lod.Meshes[meshIndex];
|
||||
}
|
||||
|
||||
void SkinnedModel::InitAsVirtual()
|
||||
{
|
||||
// Init with one mesh and single bone
|
||||
@@ -723,6 +748,21 @@ void SkinnedModel::InitAsVirtual()
|
||||
BinaryAsset::InitAsVirtual();
|
||||
}
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
void SkinnedModel::GetReferences(Array<Guid>& output) const
|
||||
{
|
||||
// Base
|
||||
BinaryAsset::GetReferences(output);
|
||||
|
||||
for (int32 i = 0; i < MaterialSlots.Count(); i++)
|
||||
{
|
||||
output.Add(MaterialSlots[i].Material.GetID());
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int32 SkinnedModel::GetMaxResidency() const
|
||||
{
|
||||
return LODs.Count();
|
||||
|
||||
@@ -61,15 +61,6 @@ public:
|
||||
return LODs.HasItems();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets amount of the level of details in the model
|
||||
/// </summary>
|
||||
/// <returns>Amount of the level of details in the model</returns>
|
||||
FORCE_INLINE int32 GetLODsCount() const
|
||||
{
|
||||
return LODs.Count();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the amount of loaded model LODs.
|
||||
/// </summary>
|
||||
@@ -184,22 +175,14 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="lodIndex">Index of the LOD.</param>
|
||||
/// <returns>Task that will gather chunk data or null if already here.</returns>
|
||||
ContentLoadTask* RequestLODDataAsync(int32 lodIndex)
|
||||
{
|
||||
const int32 chunkIndex = SKINNED_MODEL_LOD_TO_CHUNK_INDEX(lodIndex);
|
||||
return RequestChunkDataAsync(chunkIndex);
|
||||
}
|
||||
ContentLoadTask* RequestLODDataAsync(int32 lodIndex);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the model LOD data (links bytes).
|
||||
/// </summary>
|
||||
/// <param name="lodIndex">Index of the LOD.</param>
|
||||
/// <param name="data">The data (may be missing if failed to get it).</param>
|
||||
void GetLODData(int32 lodIndex, BytesContainer& data) const
|
||||
{
|
||||
const int32 chunkIndex = SKINNED_MODEL_LOD_TO_CHUNK_INDEX(lodIndex);
|
||||
GetChunkData(chunkIndex, data);
|
||||
}
|
||||
void GetLODData(int32 lodIndex, BytesContainer& data) const;
|
||||
|
||||
public:
|
||||
|
||||
@@ -300,18 +283,11 @@ public:
|
||||
|
||||
// [ModelBase]
|
||||
void SetupMaterialSlots(int32 slotsCount) override;
|
||||
int32 GetLODsCount() const override;
|
||||
void GetMeshes(Array<MeshBase*>& meshes, int32 lodIndex = 0) override;
|
||||
void InitAsVirtual() override;
|
||||
#if USE_EDITOR
|
||||
void GetReferences(Array<Guid>& output) const override
|
||||
{
|
||||
// Base
|
||||
BinaryAsset::GetReferences(output);
|
||||
|
||||
for (int32 i = 0; i < MaterialSlots.Count(); i++)
|
||||
{
|
||||
output.Add(MaterialSlots[i].Material.GetID());
|
||||
}
|
||||
}
|
||||
void GetReferences(Array<Guid>& output) const override;
|
||||
#endif
|
||||
|
||||
// [StreamableResource]
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
110
Source/Engine/Graphics/Models/MeshBase.h
Normal file
110
Source/Engine/Graphics/Models/MeshBase.h
Normal 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;
|
||||
};
|
||||
@@ -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();
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -553,3 +553,9 @@ float ViewToCenterLessRadius(const RenderView& view, const Vector3& center, floa
|
||||
// Calculate result
|
||||
return viewToCenter - radius;
|
||||
}
|
||||
|
||||
void MeshBase::SetBounds(const BoundingBox& box)
|
||||
{
|
||||
_box = box;
|
||||
BoundingSphere::FromBox(box, _sphere);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user