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

@@ -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;
}

View File

@@ -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]

View File

@@ -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;
};

View File

@@ -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();

View File

@@ -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]