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:
Chris Santora
2021-07-20 16:23:56 -07:00
committed by santorac
parent a71ee7eb3a
commit fec79a7d53
22 changed files with 135 additions and 158 deletions
@@ -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();