Moved the material slot list from ModelLodAsset to ModelAsset, so all the slots live in one main list. This removes data duplication between LODs and cleans up the code a bit.
I had to update the ModelLod class to take in both the ModelLodAsset and ModelAsset for initialization so it can fetch the slots for each mesh. Signed-off-by: santorac <55155825+santorac@users.noreply.github.com>
This commit is contained in:
@@ -639,8 +639,9 @@ namespace AZ
|
||||
|
||||
Aabb localAabb = lod.m_subMeshProperties[i].m_aabb;
|
||||
modelLodCreator.SetMeshAabb(AZStd::move(localAabb));
|
||||
|
||||
modelLodCreator.SetMeshMaterialSlot(lod.m_subMeshProperties[i].m_materialSlot);
|
||||
|
||||
modelCreator.AddMaterialSlot(lod.m_subMeshProperties[i].m_materialSlot);
|
||||
modelLodCreator.SetMeshMaterialSlot(lod.m_subMeshProperties[i].m_materialSlot.m_stableId);
|
||||
|
||||
modelLodCreator.EndMesh();
|
||||
}
|
||||
|
||||
@@ -90,8 +90,8 @@ namespace AZ
|
||||
private:
|
||||
Model() = default;
|
||||
|
||||
static Data::Instance<Model> CreateInternal(ModelAsset& modelAsset);
|
||||
RHI::ResultCode Init(ModelAsset& modelAsset);
|
||||
static Data::Instance<Model> CreateInternal(const Data::Asset<ModelAsset>& modelAsset);
|
||||
RHI::ResultCode Init(const Data::Asset<ModelAsset>& modelAsset);
|
||||
|
||||
AZStd::fixed_vector<Data::Instance<ModelLod>, ModelLodAsset::LodCountMax> m_lods;
|
||||
Data::Asset<ModelAsset> m_modelAsset;
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <Atom/RHI.Reflect/Limits.h>
|
||||
|
||||
#include <Atom/RPI.Reflect/Model/ModelLodAsset.h>
|
||||
#include <Atom/RPI.Reflect/Model/ModelAsset.h>
|
||||
|
||||
#include <AtomCore/std/containers/array_view.h>
|
||||
#include <AtomCore/std/containers/vector_set.h>
|
||||
@@ -84,7 +85,7 @@ namespace AZ
|
||||
AZ_INSTANCE_DATA(ModelLod, "{3C796FC9-2067-4E0F-A660-269F8254D1D5}");
|
||||
AZ_CLASS_ALLOCATOR(ModelLod, AZ::SystemAllocator, 0);
|
||||
|
||||
static Data::Instance<ModelLod> FindOrCreate(const Data::Asset<ModelLodAsset>& lodAsset);
|
||||
static Data::Instance<ModelLod> FindOrCreate(const Data::Asset<ModelLodAsset>& lodAsset, const Data::Asset<ModelAsset>& modelAsset);
|
||||
|
||||
~ModelLod() = default;
|
||||
|
||||
@@ -124,8 +125,8 @@ namespace AZ
|
||||
private:
|
||||
ModelLod() = default;
|
||||
|
||||
static Data::Instance<ModelLod> CreateInternal(ModelLodAsset& lodAsset);
|
||||
RHI::ResultCode Init(ModelLodAsset& lodAsset);
|
||||
static Data::Instance<ModelLod> CreateInternal(const Data::Asset<ModelLodAsset>& lodAsset, const AZStd::any* modelAssetAny);
|
||||
RHI::ResultCode Init(const Data::Asset<ModelLodAsset>& lodAsset, const Data::Asset<ModelAsset>& modelAsset);
|
||||
|
||||
bool SetMeshInstanceData(
|
||||
const ModelLodAsset::Mesh::StreamBufferInfo& streamBufferInfo,
|
||||
|
||||
@@ -51,7 +51,10 @@ namespace AZ
|
||||
const AZ::Aabb& GetAabb() const;
|
||||
|
||||
//! Returns the list of all ModelMaterialSlot's for the model, across all LODs.
|
||||
RPI::ModelMaterialSlotMap GetModelMaterialSlots() const;
|
||||
const ModelMaterialSlotMap& GetMaterialSlots() const;
|
||||
|
||||
//! Find a material slot with the given stableId, or returns an invalid slot if it isn't found.
|
||||
const ModelMaterialSlot& FindMaterialSlot(uint32_t stableId) const;
|
||||
|
||||
//! Returns the number of Lods in the model
|
||||
size_t GetLodCount() const;
|
||||
@@ -100,6 +103,13 @@ namespace AZ
|
||||
volatile mutable bool m_isKdTreeCalculationRunning = false;
|
||||
mutable AZStd::mutex m_kdTreeLock;
|
||||
mutable AZStd::optional<AZStd::size_t> m_modelTriangleCount;
|
||||
|
||||
// Lists all of the material slots that are used by this LOD.
|
||||
// Note the same slot can appear in multiple LODs in the model, so that LODs don't have to refer back to the model asset.
|
||||
ModelMaterialSlotMap m_materialSlots;
|
||||
|
||||
// A default ModelMaterialSlot to be returned upon error conditions.
|
||||
ModelMaterialSlot m_fallbackSlot;
|
||||
|
||||
AZStd::size_t CalculateTriangleCount() const;
|
||||
};
|
||||
|
||||
@@ -29,6 +29,10 @@ namespace AZ
|
||||
|
||||
//! Assigns a name to the model
|
||||
void SetName(AZStd::string_view name);
|
||||
|
||||
//! Adds a new material slot to the asset.
|
||||
//! If a slot with the same stable ID already exists, it will be replaced.
|
||||
void AddMaterialSlot(const ModelMaterialSlot& materialSlot);
|
||||
|
||||
//! Adds a Lod to the model.
|
||||
void AddLodAsset(Data::Asset<ModelLodAsset>&& lodAsset);
|
||||
|
||||
@@ -85,9 +85,9 @@ namespace AZ
|
||||
//! Returns the number of indices in this mesh
|
||||
uint32_t GetIndexCount() const;
|
||||
|
||||
//! Returns the index of the material slot used by this mesh.
|
||||
//! This indexes into the ModelLodAsset's material slot list.
|
||||
size_t GetMaterialSlotIndex() const;
|
||||
//! Returns the ID of the material slot used by this mesh.
|
||||
//! This maps into the ModelAsset's material slot list.
|
||||
ModelMaterialSlot::StableId GetMaterialSlotId() const;
|
||||
|
||||
//! Returns the name of this mesh
|
||||
const AZ::Name& GetName() const;
|
||||
@@ -126,9 +126,9 @@ namespace AZ
|
||||
AZ::Name m_name;
|
||||
AZ::Aabb m_aabb = AZ::Aabb::CreateNull();
|
||||
|
||||
// Identifies the material that is used by this mesh.
|
||||
// References material slot in the ModelLodAsset that owns this mesh; see ModelLodAsset::GetMaterialSlot().
|
||||
size_t m_materialSlotIndex = 0;
|
||||
// Identifies the material slot that is used by this mesh.
|
||||
// References material slot in the ModelAsset that owns this mesh; see ModelAsset::FindMaterialSlot().
|
||||
ModelMaterialSlot::StableId m_materialSlotId = ModelMaterialSlot::InvalidStableId;
|
||||
|
||||
// Both the buffer in m_indexBufferAssetView and the buffers in m_streamBufferInfo
|
||||
// may point to either unique buffers for the mesh or to consolidated
|
||||
@@ -147,16 +147,6 @@ namespace AZ
|
||||
|
||||
//! Returns the model-space axis-aligned bounding box of all meshes in the lod
|
||||
const AZ::Aabb& GetAabb() const;
|
||||
|
||||
//! Returns an array view into the collection of material slots available to this lod
|
||||
AZStd::array_view<ModelMaterialSlot> GetMaterialSlots() const;
|
||||
|
||||
//! Returns a specific material slot by index, with error checking.
|
||||
//! The index can be retrieved from Mesh::GetMaterialSlotIndex().
|
||||
const ModelMaterialSlot& GetMaterialSlot(size_t slotIndex) const;
|
||||
|
||||
//! Find a material slot with the given stableId, or returns null if it isn't found.
|
||||
const ModelMaterialSlot* FindMaterialSlot(uint32_t stableId) const;
|
||||
|
||||
private:
|
||||
AZStd::vector<Mesh> m_meshes;
|
||||
@@ -169,13 +159,6 @@ namespace AZ
|
||||
Data::Asset<BufferAsset> m_indexBuffer;
|
||||
AZStd::vector<Data::Asset<BufferAsset>> m_streamBuffers;
|
||||
|
||||
// Lists all of the material slots that are used by this LOD.
|
||||
// Note the same slot can appear in multiple LODs in the model, so that LODs don't have to refer back to the model asset.
|
||||
AZStd::vector<ModelMaterialSlot> m_materialSlots;
|
||||
|
||||
// A default ModelMaterialSlot to be returned upon error conditions.
|
||||
ModelMaterialSlot m_fallbackSlot;
|
||||
|
||||
void AddMesh(const Mesh& mesh);
|
||||
|
||||
void SetReady();
|
||||
|
||||
@@ -46,10 +46,9 @@ namespace AZ
|
||||
//! Begin and BeginMesh must be called first.
|
||||
void SetMeshAabb(AZ::Aabb&& aabb);
|
||||
|
||||
//! Sets the material slot data for the current SubMesh.
|
||||
//! Adds a new material slot to the ModelLodAsset if it doesn't already exist.
|
||||
//! Sets the ID of the model's material slot that this mesh uses.
|
||||
//! Begin and BeginMesh must be called first
|
||||
void SetMeshMaterialSlot(const ModelMaterialSlot& materialSlot);
|
||||
void SetMeshMaterialSlot(ModelMaterialSlot::StableId id);
|
||||
|
||||
//! Sets the given BufferAssetView to the current SubMesh as the index buffer.
|
||||
//! Begin and BeginMesh must be called first
|
||||
|
||||
@@ -91,7 +91,7 @@ namespace AZ
|
||||
if (auto* serialize = azrtti_cast<SerializeContext*>(context))
|
||||
{
|
||||
serialize->Class<MaterialAssetBuilderComponent, SceneAPI::SceneCore::ExportingComponent>()
|
||||
->Version(14); // [ATOM-13410]
|
||||
->Version(16); // Optional material conversion
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -367,6 +367,9 @@ namespace AZ
|
||||
|
||||
MorphTargetMetaAssetCreator morphTargetMetaCreator;
|
||||
morphTargetMetaCreator.Begin(MorphTargetMetaAsset::ConstructAssetId(modelAssetId, modelAssetName));
|
||||
|
||||
ModelAssetCreator modelAssetCreator;
|
||||
modelAssetCreator.Begin(modelAssetId);
|
||||
|
||||
uint32_t lodIndex = 0;
|
||||
for (const SourceMeshContentList& sourceMeshContentList : sourceMeshContentListsByLod)
|
||||
@@ -429,7 +432,7 @@ namespace AZ
|
||||
|
||||
for (const ProductMeshView& meshView : lodMeshViews)
|
||||
{
|
||||
if (!CreateMesh(meshView, indexBuffer, streamBuffers, lodAssetCreator, context.m_materialsByUid))
|
||||
if (!CreateMesh(meshView, indexBuffer, streamBuffers, modelAssetCreator, lodAssetCreator, context.m_materialsByUid))
|
||||
{
|
||||
return AZ::SceneAPI::Events::ProcessingResult::Failure;
|
||||
}
|
||||
@@ -469,10 +472,6 @@ namespace AZ
|
||||
}
|
||||
sourceMeshContentListsByLod.clear();
|
||||
|
||||
// Build the final asset structure
|
||||
ModelAssetCreator modelAssetCreator;
|
||||
modelAssetCreator.Begin(modelAssetId);
|
||||
|
||||
// Finalize all LOD assets
|
||||
for (auto& lodAsset : lodAssets)
|
||||
{
|
||||
@@ -1796,6 +1795,7 @@ namespace AZ
|
||||
const ProductMeshView& meshView,
|
||||
const BufferAssetView& lodIndexBuffer,
|
||||
const AZStd::vector<ModelLodAsset::Mesh::StreamBufferInfo>& lodStreamBuffers,
|
||||
ModelAssetCreator& modelAssetCreator,
|
||||
ModelLodAssetCreator& lodAssetCreator,
|
||||
const MaterialAssetsByUid& materialAssetsByUid)
|
||||
{
|
||||
@@ -1811,7 +1811,8 @@ namespace AZ
|
||||
materialSlot.m_displayName = iter->second.m_name;
|
||||
materialSlot.m_defaultMaterialAsset = iter->second.m_asset;
|
||||
|
||||
lodAssetCreator.SetMeshMaterialSlot(materialSlot);
|
||||
modelAssetCreator.AddMaterialSlot(materialSlot);
|
||||
lodAssetCreator.SetMeshMaterialSlot(materialSlot.m_stableId);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -294,6 +294,7 @@ namespace AZ
|
||||
const ProductMeshView& meshView,
|
||||
const BufferAssetView& lodIndexBuffer,
|
||||
const AZStd::vector<ModelLodAsset::Mesh::StreamBufferInfo>& lodStreamBuffers,
|
||||
ModelAssetCreator& modelAssetCreator,
|
||||
ModelLodAssetCreator& lodAssetCreator,
|
||||
const MaterialAssetsByUid& materialAssetsByUid);
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace AZ
|
||||
return m_lods;
|
||||
}
|
||||
|
||||
Data::Instance<Model> Model::CreateInternal(ModelAsset& modelAsset)
|
||||
Data::Instance<Model> Model::CreateInternal(const Data::Asset<ModelAsset>& modelAsset)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(Debug::ProfileCategory::AzRender);
|
||||
Data::Instance<Model> model = aznew Model();
|
||||
@@ -54,15 +54,15 @@ namespace AZ
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RHI::ResultCode Model::Init(ModelAsset& modelAsset)
|
||||
RHI::ResultCode Model::Init(const Data::Asset<ModelAsset>& modelAsset)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(Debug::ProfileCategory::AzRender);
|
||||
|
||||
m_lods.resize(modelAsset.GetLodAssets().size());
|
||||
m_lods.resize(modelAsset->GetLodAssets().size());
|
||||
|
||||
for (size_t lodIndex = 0; lodIndex < m_lods.size(); ++lodIndex)
|
||||
{
|
||||
const Data::Asset<ModelLodAsset>& lodAsset = modelAsset.GetLodAssets()[lodIndex];
|
||||
const Data::Asset<ModelLodAsset>& lodAsset = modelAsset->GetLodAssets()[lodIndex];
|
||||
|
||||
if (!lodAsset)
|
||||
{
|
||||
@@ -70,7 +70,7 @@ namespace AZ
|
||||
return RHI::ResultCode::Fail;
|
||||
}
|
||||
|
||||
Data::Instance<ModelLod> lodInstance = ModelLod::FindOrCreate(lodAsset);
|
||||
Data::Instance<ModelLod> lodInstance = ModelLod::FindOrCreate(lodAsset, modelAsset);
|
||||
if (lodInstance == nullptr)
|
||||
{
|
||||
return RHI::ResultCode::Fail;
|
||||
@@ -98,7 +98,7 @@ namespace AZ
|
||||
m_lods[lodIndex] = AZStd::move(lodInstance);
|
||||
}
|
||||
|
||||
m_modelAsset = { &modelAsset, AZ::Data::AssetLoadBehavior::PreLoad };
|
||||
m_modelAsset = modelAsset;
|
||||
m_isUploadPending = true;
|
||||
return RHI::ResultCode::Success;
|
||||
}
|
||||
|
||||
@@ -19,11 +19,14 @@ namespace AZ
|
||||
{
|
||||
namespace RPI
|
||||
{
|
||||
Data::Instance<ModelLod> ModelLod::FindOrCreate(const Data::Asset<ModelLodAsset>& lodAsset)
|
||||
Data::Instance<ModelLod> ModelLod::FindOrCreate(const Data::Asset<ModelLodAsset>& lodAsset, const Data::Asset<ModelAsset>& modelAsset)
|
||||
{
|
||||
AZStd::any modelAssetAny{&modelAsset};
|
||||
|
||||
return Data::InstanceDatabase<ModelLod>::Instance().FindOrCreate(
|
||||
Data::InstanceId::CreateFromAssetId(lodAsset.GetId()),
|
||||
lodAsset);
|
||||
lodAsset,
|
||||
&modelAssetAny);
|
||||
}
|
||||
|
||||
AZStd::array_view<ModelLod::Mesh> ModelLod::GetMeshes() const
|
||||
@@ -31,10 +34,13 @@ namespace AZ
|
||||
return m_meshes;
|
||||
}
|
||||
|
||||
Data::Instance<ModelLod> ModelLod::CreateInternal(ModelLodAsset& lodAsset)
|
||||
Data::Instance<ModelLod> ModelLod::CreateInternal(const Data::Asset<ModelLodAsset>& lodAsset, const AZStd::any* modelAssetAny)
|
||||
{
|
||||
AZ_Assert(modelAssetAny != nullptr, "Invalid model asset param");
|
||||
auto modelAsset = AZStd::any_cast<Data::Asset<ModelAsset>*>(*modelAssetAny);
|
||||
|
||||
Data::Instance<ModelLod> lod = aznew ModelLod();
|
||||
const RHI::ResultCode resultCode = lod->Init(lodAsset);
|
||||
const RHI::ResultCode resultCode = lod->Init(lodAsset, *modelAsset);
|
||||
|
||||
if (resultCode == RHI::ResultCode::Success)
|
||||
{
|
||||
@@ -44,11 +50,11 @@ namespace AZ
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RHI::ResultCode ModelLod::Init(ModelLodAsset& lodAsset)
|
||||
RHI::ResultCode ModelLod::Init(const Data::Asset<ModelLodAsset>& lodAsset, const Data::Asset<ModelAsset>& modelAsset)
|
||||
{
|
||||
AZ_TRACE_METHOD();
|
||||
|
||||
for (const ModelLodAsset::Mesh& mesh : lodAsset.GetMeshes())
|
||||
for (const ModelLodAsset::Mesh& mesh : lodAsset->GetMeshes())
|
||||
{
|
||||
Mesh meshInstance;
|
||||
|
||||
@@ -100,7 +106,7 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
const ModelMaterialSlot& materialSlot = lodAsset.GetMaterialSlot(mesh.GetMaterialSlotIndex());
|
||||
const ModelMaterialSlot& materialSlot = modelAsset->FindMaterialSlot(mesh.GetMaterialSlotId());
|
||||
|
||||
meshInstance.m_materialSlotStableId = materialSlot.m_stableId;
|
||||
|
||||
|
||||
@@ -41,9 +41,9 @@ namespace AZ
|
||||
{
|
||||
//Create Lod Database
|
||||
AZ::Data::InstanceHandler<ModelLod> lodInstanceHandler;
|
||||
lodInstanceHandler.m_createFunction = [](Data::AssetData* modelLodAsset)
|
||||
lodInstanceHandler.m_createFunctionWithParam = [](Data::AssetData* modelLodAsset, const AZStd::any* modelAsset)
|
||||
{
|
||||
return ModelLod::CreateInternal(*(azrtti_cast<ModelLodAsset*>(modelLodAsset)));
|
||||
return ModelLod::CreateInternal(Data::Asset<ModelLodAsset>{modelLodAsset, AZ::Data::AssetLoadBehavior::PreLoad}, modelAsset);
|
||||
};
|
||||
Data::InstanceDatabase<ModelLod>::Create(azrtti_typeid<ModelLodAsset>(), lodInstanceHandler);
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace AZ
|
||||
AZ::Data::InstanceHandler<Model> modelInstanceHandler;
|
||||
modelInstanceHandler.m_createFunction = [](Data::AssetData* modelAsset)
|
||||
{
|
||||
return Model::CreateInternal(*(azrtti_cast<ModelAsset*>(modelAsset)));
|
||||
return Model::CreateInternal(Data::Asset<ModelAsset>{modelAsset, AZ::Data::AssetLoadBehavior::PreLoad});
|
||||
};
|
||||
Data::InstanceDatabase<Model>::Create(azrtti_typeid<ModelAsset>(), modelInstanceHandler);
|
||||
}
|
||||
|
||||
@@ -29,9 +29,10 @@ namespace AZ
|
||||
if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<ModelAsset, Data::AssetData>()
|
||||
->Version(0)
|
||||
->Version(1)
|
||||
->Field("Name", &ModelAsset::m_name)
|
||||
->Field("Aabb", &ModelAsset::m_aabb)
|
||||
->Field("MaterialSlots", &ModelAsset::m_materialSlots)
|
||||
->Field("LodAssets", &ModelAsset::m_lodAssets)
|
||||
;
|
||||
}
|
||||
@@ -57,28 +58,23 @@ namespace AZ
|
||||
return m_aabb;
|
||||
}
|
||||
|
||||
RPI::ModelMaterialSlotMap ModelAsset::GetModelMaterialSlots() const
|
||||
const ModelMaterialSlotMap& ModelAsset::GetMaterialSlots() const
|
||||
{
|
||||
RPI::ModelMaterialSlotMap slotMap;
|
||||
return m_materialSlots;
|
||||
}
|
||||
|
||||
for (const Data::Asset<AZ::RPI::ModelLodAsset>& lod : GetLodAssets())
|
||||
{
|
||||
for (const AZ::RPI::ModelMaterialSlot& materialSlot : lod->GetMaterialSlots())
|
||||
{
|
||||
auto iter = slotMap.find(materialSlot.m_stableId);
|
||||
if (iter == slotMap.end())
|
||||
{
|
||||
slotMap.emplace(materialSlot.m_stableId, materialSlot);
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Assert(materialSlot.m_displayName == iter->second.m_displayName && materialSlot.m_defaultMaterialAsset.GetId() == iter->second.m_defaultMaterialAsset.GetId(),
|
||||
"Multiple LODs have mismatched data for the same material slot.");
|
||||
}
|
||||
}
|
||||
}
|
||||
const ModelMaterialSlot& ModelAsset::FindMaterialSlot(uint32_t stableId) const
|
||||
{
|
||||
auto iter = m_materialSlots.find(stableId);
|
||||
|
||||
return slotMap;
|
||||
if (iter == m_materialSlots.end())
|
||||
{
|
||||
return m_fallbackSlot;
|
||||
}
|
||||
else
|
||||
{
|
||||
return iter->second;
|
||||
}
|
||||
}
|
||||
|
||||
size_t ModelAsset::GetLodCount() const
|
||||
|
||||
@@ -29,6 +29,33 @@ namespace AZ
|
||||
m_asset->m_name = name;
|
||||
}
|
||||
}
|
||||
|
||||
void ModelAssetCreator::AddMaterialSlot(const ModelMaterialSlot& materialSlot)
|
||||
{
|
||||
if (ValidateIsReady())
|
||||
{
|
||||
auto iter = m_asset->m_materialSlots.find(materialSlot.m_stableId);
|
||||
|
||||
if (iter == m_asset->m_materialSlots.end())
|
||||
{
|
||||
m_asset->m_materialSlots[materialSlot.m_stableId] = materialSlot;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (materialSlot.m_displayName != iter->second.m_displayName)
|
||||
{
|
||||
ReportWarning("Material slot %u was already added with a different name.", materialSlot.m_stableId);
|
||||
}
|
||||
|
||||
if (materialSlot.m_defaultMaterialAsset != iter->second.m_defaultMaterialAsset)
|
||||
{
|
||||
ReportWarning("Material slot %u was already added with a different default MaterialAsset.", materialSlot.m_stableId);
|
||||
}
|
||||
|
||||
iter->second = materialSlot;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ModelAssetCreator::AddLodAsset(Data::Asset<ModelLodAsset>&& lodAsset)
|
||||
{
|
||||
|
||||
@@ -23,10 +23,9 @@ namespace AZ
|
||||
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<ModelLodAsset>()
|
||||
->Version(1)
|
||||
->Version(0)
|
||||
->Field("Meshes", &ModelLodAsset::m_meshes)
|
||||
->Field("Aabb", &ModelLodAsset::m_aabb)
|
||||
->Field("MaterialSlots", &ModelLodAsset::m_materialSlots)
|
||||
;
|
||||
}
|
||||
|
||||
@@ -41,7 +40,7 @@ namespace AZ
|
||||
->Version(1)
|
||||
->Field("Name", &ModelLodAsset::Mesh::m_name)
|
||||
->Field("AABB", &ModelLodAsset::Mesh::m_aabb)
|
||||
->Field("MaterialSlotIndex", &ModelLodAsset::Mesh::m_materialSlotIndex)
|
||||
->Field("MaterialSlotId", &ModelLodAsset::Mesh::m_materialSlotId)
|
||||
->Field("IndexBufferAssetView", &ModelLodAsset::Mesh::m_indexBufferAssetView)
|
||||
->Field("StreamBufferInfo", &ModelLodAsset::Mesh::m_streamBufferInfo)
|
||||
;
|
||||
@@ -76,9 +75,9 @@ namespace AZ
|
||||
return m_indexBufferAssetView.GetBufferViewDescriptor().m_elementCount;
|
||||
}
|
||||
|
||||
size_t ModelLodAsset::Mesh::GetMaterialSlotIndex() const
|
||||
ModelMaterialSlot::StableId ModelLodAsset::Mesh::GetMaterialSlotId() const
|
||||
{
|
||||
return m_materialSlotIndex;
|
||||
return m_materialSlotId;
|
||||
}
|
||||
|
||||
const AZ::Name& ModelLodAsset::Mesh::GetName() const
|
||||
@@ -120,41 +119,6 @@ namespace AZ
|
||||
return m_aabb;
|
||||
}
|
||||
|
||||
AZStd::array_view<ModelMaterialSlot> ModelLodAsset::GetMaterialSlots() const
|
||||
{
|
||||
return m_materialSlots;
|
||||
}
|
||||
|
||||
const ModelMaterialSlot& ModelLodAsset::GetMaterialSlot(size_t slotIndex) const
|
||||
{
|
||||
if (slotIndex < m_materialSlots.size())
|
||||
{
|
||||
return m_materialSlots[slotIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Error("ModelAsset", false, "Material slot index %zu out of range. ModelAsset has %zu slots.", slotIndex, m_materialSlots.size());
|
||||
return m_fallbackSlot;
|
||||
}
|
||||
}
|
||||
|
||||
const ModelMaterialSlot* ModelLodAsset::FindMaterialSlot(uint32_t stableId) const
|
||||
{
|
||||
auto iter = AZStd::find_if(m_materialSlots.begin(), m_materialSlots.end(), [&stableId](const ModelMaterialSlot& existingMaterialSlot)
|
||||
{
|
||||
return existingMaterialSlot.m_stableId == stableId;
|
||||
});
|
||||
|
||||
if (iter == m_materialSlots.end())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
return iter;
|
||||
}
|
||||
}
|
||||
|
||||
const BufferAssetView* ModelLodAsset::Mesh::GetSemanticBufferAssetView(const AZ::Name& semantic) const
|
||||
{
|
||||
const AZStd::array_view<ModelLodAsset::Mesh::StreamBufferInfo>& streamBufferList = GetStreamBufferInfoList();
|
||||
|
||||
@@ -61,32 +61,14 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
void ModelLodAssetCreator::SetMeshMaterialSlot(const ModelMaterialSlot& materialSlot)
|
||||
void ModelLodAssetCreator::SetMeshMaterialSlot(ModelMaterialSlot::StableId id)
|
||||
{
|
||||
auto iter = AZStd::find_if(m_asset->m_materialSlots.begin(), m_asset->m_materialSlots.end(), [&materialSlot](const ModelMaterialSlot& existingMaterialSlot)
|
||||
{
|
||||
return existingMaterialSlot.m_stableId == materialSlot.m_stableId;
|
||||
});
|
||||
|
||||
if (iter == m_asset->m_materialSlots.end())
|
||||
if (!ValidateIsMeshReady())
|
||||
{
|
||||
m_currentMesh.m_materialSlotIndex = m_asset->m_materialSlots.size();
|
||||
m_asset->m_materialSlots.push_back(materialSlot);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (materialSlot.m_displayName != iter->m_displayName)
|
||||
{
|
||||
ReportWarning("Material slot %u was already added with a different name.", materialSlot.m_stableId);
|
||||
}
|
||||
|
||||
if (materialSlot.m_defaultMaterialAsset != iter->m_defaultMaterialAsset)
|
||||
{
|
||||
ReportWarning("Material slot %u was already added with a different MaterialAsset.", materialSlot.m_stableId);
|
||||
}
|
||||
|
||||
*iter = materialSlot;
|
||||
}
|
||||
m_currentMesh.m_materialSlotId = id;
|
||||
}
|
||||
|
||||
void ModelLodAssetCreator::SetMeshIndexBuffer(const BufferAssetView& bufferAssetView)
|
||||
@@ -309,8 +291,7 @@ namespace AZ
|
||||
AZ::Aabb aabb = sourceMesh.GetAabb();
|
||||
creator.SetMeshAabb(AZStd::move(aabb));
|
||||
|
||||
const ModelMaterialSlot& materialSlot = sourceAsset->GetMaterialSlot(sourceMesh.GetMaterialSlotIndex());
|
||||
creator.SetMeshMaterialSlot(materialSlot);
|
||||
creator.SetMeshMaterialSlot(sourceMesh.GetMaterialSlotId());
|
||||
|
||||
// Mesh index buffer view
|
||||
const BufferAssetView& sourceIndexBufferView = sourceMesh.GetIndexBufferAssetView();
|
||||
|
||||
@@ -257,7 +257,7 @@ namespace AZ
|
||||
Data::Asset<const RPI::ModelAsset> modelAsset = GetModelAsset();
|
||||
if (modelAsset.IsReady())
|
||||
{
|
||||
return modelAsset->GetModelMaterialSlots();
|
||||
return modelAsset->GetMaterialSlots();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -96,7 +96,7 @@ namespace AZ
|
||||
skinnedSubMesh.m_vertexCount = aznumeric_cast<uint32_t>(subMeshVertexCount);
|
||||
lodVertexCount += aznumeric_cast<uint32_t>(subMeshVertexCount);
|
||||
|
||||
skinnedSubMesh.m_materialSlot = lodAsset->GetMaterialSlot(modelMesh.GetMaterialSlotIndex());
|
||||
skinnedSubMesh.m_materialSlot = actor->GetMeshAsset()->FindMaterialSlot(modelMesh.GetMaterialSlotId());
|
||||
|
||||
// Queue the material asset - the ModelLod seems to handle delayed material loads
|
||||
skinnedSubMesh.m_materialSlot.m_defaultMaterialAsset.QueueLoad();
|
||||
|
||||
@@ -313,7 +313,7 @@ namespace AZ
|
||||
Data::Asset<const RPI::ModelAsset> modelAsset = GetModelAsset();
|
||||
if (modelAsset.IsReady())
|
||||
{
|
||||
return modelAsset->GetModelMaterialSlots();
|
||||
return modelAsset->GetMaterialSlots();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -112,20 +112,8 @@ namespace WhiteBox
|
||||
AddLodBuffers(modelLodCreator);
|
||||
modelLodCreator.BeginMesh();
|
||||
modelLodCreator.SetMeshAabb(meshData.GetAabb());
|
||||
|
||||
// set the default material
|
||||
if (auto materialAsset = AZ::RPI::AssetUtils::LoadAssetByProductPath<AZ::RPI::MaterialAsset>(TexturedMaterialPath.data()))
|
||||
{
|
||||
AZ::RPI::ModelMaterialSlot materialSlot;
|
||||
materialSlot.m_stableId = 0;
|
||||
materialSlot.m_defaultMaterialAsset = materialAsset;
|
||||
modelLodCreator.SetMeshMaterialSlot(materialSlot);
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Error("CreateLodAsset", false, "Could not load material.");
|
||||
return false;
|
||||
}
|
||||
|
||||
modelLodCreator.SetMeshMaterialSlot(OneMaterialSlotId);
|
||||
|
||||
AddMeshBuffers(modelLodCreator);
|
||||
modelLodCreator.EndMesh();
|
||||
@@ -157,6 +145,20 @@ namespace WhiteBox
|
||||
modelCreator.Begin(AZ::Data::AssetId(AZ::Uuid::CreateRandom()));
|
||||
modelCreator.SetName(ModelName);
|
||||
modelCreator.AddLodAsset(AZStd::move(m_lodAsset));
|
||||
|
||||
if (auto materialAsset = AZ::RPI::AssetUtils::LoadAssetByProductPath<AZ::RPI::MaterialAsset>(TexturedMaterialPath.data()))
|
||||
{
|
||||
AZ::RPI::ModelMaterialSlot materialSlot;
|
||||
materialSlot.m_stableId = OneMaterialSlotId;
|
||||
materialSlot.m_defaultMaterialAsset = materialAsset;
|
||||
modelCreator.AddMaterialSlot(materialSlot);
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Error("CreateLodAsset", false, "Could not load material.");
|
||||
return;
|
||||
}
|
||||
|
||||
modelCreator.End(m_modelAsset);
|
||||
}
|
||||
|
||||
|
||||
@@ -91,6 +91,7 @@ namespace WhiteBox
|
||||
// TODO: LYN-784
|
||||
static constexpr AZStd::string_view TexturedMaterialPath = "materials/defaultpbr.azmaterial";
|
||||
static constexpr AZStd::string_view SolidMaterialPath = "materials/defaultpbr.azmaterial";
|
||||
static constexpr AZ::RPI::ModelMaterialSlot::StableId OneMaterialSlotId = 0;
|
||||
|
||||
//! White box model name.
|
||||
static constexpr AZStd::string_view ModelName = "WhiteBoxMesh";
|
||||
|
||||
Reference in New Issue
Block a user