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>
monroegm-disable-blank-issue-2
Chris Santora 4 years ago committed by santorac
parent a71ee7eb3a
commit fec79a7d53

@ -640,7 +640,8 @@ namespace AZ
Aabb localAabb = lod.m_subMeshProperties[i].m_aabb; Aabb localAabb = lod.m_subMeshProperties[i].m_aabb;
modelLodCreator.SetMeshAabb(AZStd::move(localAabb)); 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(); modelLodCreator.EndMesh();
} }

@ -90,8 +90,8 @@ namespace AZ
private: private:
Model() = default; Model() = default;
static Data::Instance<Model> CreateInternal(ModelAsset& modelAsset); static Data::Instance<Model> CreateInternal(const Data::Asset<ModelAsset>& modelAsset);
RHI::ResultCode Init(ModelAsset& modelAsset); RHI::ResultCode Init(const Data::Asset<ModelAsset>& modelAsset);
AZStd::fixed_vector<Data::Instance<ModelLod>, ModelLodAsset::LodCountMax> m_lods; AZStd::fixed_vector<Data::Instance<ModelLod>, ModelLodAsset::LodCountMax> m_lods;
Data::Asset<ModelAsset> m_modelAsset; Data::Asset<ModelAsset> m_modelAsset;

@ -18,6 +18,7 @@
#include <Atom/RHI.Reflect/Limits.h> #include <Atom/RHI.Reflect/Limits.h>
#include <Atom/RPI.Reflect/Model/ModelLodAsset.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/array_view.h>
#include <AtomCore/std/containers/vector_set.h> #include <AtomCore/std/containers/vector_set.h>
@ -84,7 +85,7 @@ namespace AZ
AZ_INSTANCE_DATA(ModelLod, "{3C796FC9-2067-4E0F-A660-269F8254D1D5}"); AZ_INSTANCE_DATA(ModelLod, "{3C796FC9-2067-4E0F-A660-269F8254D1D5}");
AZ_CLASS_ALLOCATOR(ModelLod, AZ::SystemAllocator, 0); 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; ~ModelLod() = default;
@ -124,8 +125,8 @@ namespace AZ
private: private:
ModelLod() = default; ModelLod() = default;
static Data::Instance<ModelLod> CreateInternal(ModelLodAsset& lodAsset); static Data::Instance<ModelLod> CreateInternal(const Data::Asset<ModelLodAsset>& lodAsset, const AZStd::any* modelAssetAny);
RHI::ResultCode Init(ModelLodAsset& lodAsset); RHI::ResultCode Init(const Data::Asset<ModelLodAsset>& lodAsset, const Data::Asset<ModelAsset>& modelAsset);
bool SetMeshInstanceData( bool SetMeshInstanceData(
const ModelLodAsset::Mesh::StreamBufferInfo& streamBufferInfo, const ModelLodAsset::Mesh::StreamBufferInfo& streamBufferInfo,

@ -51,7 +51,10 @@ namespace AZ
const AZ::Aabb& GetAabb() const; const AZ::Aabb& GetAabb() const;
//! Returns the list of all ModelMaterialSlot's for the model, across all LODs. //! 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 //! Returns the number of Lods in the model
size_t GetLodCount() const; size_t GetLodCount() const;
@ -101,6 +104,13 @@ namespace AZ
mutable AZStd::mutex m_kdTreeLock; mutable AZStd::mutex m_kdTreeLock;
mutable AZStd::optional<AZStd::size_t> m_modelTriangleCount; 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; AZStd::size_t CalculateTriangleCount() const;
}; };

@ -30,6 +30,10 @@ namespace AZ
//! Assigns a name to the model //! Assigns a name to the model
void SetName(AZStd::string_view name); 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. //! Adds a Lod to the model.
void AddLodAsset(Data::Asset<ModelLodAsset>&& lodAsset); void AddLodAsset(Data::Asset<ModelLodAsset>&& lodAsset);

@ -85,9 +85,9 @@ namespace AZ
//! Returns the number of indices in this mesh //! Returns the number of indices in this mesh
uint32_t GetIndexCount() const; uint32_t GetIndexCount() const;
//! Returns the index of the material slot used by this mesh. //! Returns the ID of the material slot used by this mesh.
//! This indexes into the ModelLodAsset's material slot list. //! This maps into the ModelAsset's material slot list.
size_t GetMaterialSlotIndex() const; ModelMaterialSlot::StableId GetMaterialSlotId() const;
//! Returns the name of this mesh //! Returns the name of this mesh
const AZ::Name& GetName() const; const AZ::Name& GetName() const;
@ -126,9 +126,9 @@ namespace AZ
AZ::Name m_name; AZ::Name m_name;
AZ::Aabb m_aabb = AZ::Aabb::CreateNull(); AZ::Aabb m_aabb = AZ::Aabb::CreateNull();
// Identifies the material that is used by this mesh. // Identifies the material slot that is used by this mesh.
// References material slot in the ModelLodAsset that owns this mesh; see ModelLodAsset::GetMaterialSlot(). // References material slot in the ModelAsset that owns this mesh; see ModelAsset::FindMaterialSlot().
size_t m_materialSlotIndex = 0; ModelMaterialSlot::StableId m_materialSlotId = ModelMaterialSlot::InvalidStableId;
// Both the buffer in m_indexBufferAssetView and the buffers in m_streamBufferInfo // Both the buffer in m_indexBufferAssetView and the buffers in m_streamBufferInfo
// may point to either unique buffers for the mesh or to consolidated // may point to either unique buffers for the mesh or to consolidated
@ -148,16 +148,6 @@ namespace AZ
//! Returns the model-space axis-aligned bounding box of all meshes in the lod //! Returns the model-space axis-aligned bounding box of all meshes in the lod
const AZ::Aabb& GetAabb() const; 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: private:
AZStd::vector<Mesh> m_meshes; AZStd::vector<Mesh> m_meshes;
AZ::Aabb m_aabb = AZ::Aabb::CreateNull(); AZ::Aabb m_aabb = AZ::Aabb::CreateNull();
@ -169,13 +159,6 @@ namespace AZ
Data::Asset<BufferAsset> m_indexBuffer; Data::Asset<BufferAsset> m_indexBuffer;
AZStd::vector<Data::Asset<BufferAsset>> m_streamBuffers; 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 AddMesh(const Mesh& mesh);
void SetReady(); void SetReady();

@ -46,10 +46,9 @@ namespace AZ
//! Begin and BeginMesh must be called first. //! Begin and BeginMesh must be called first.
void SetMeshAabb(AZ::Aabb&& aabb); void SetMeshAabb(AZ::Aabb&& aabb);
//! Sets the material slot data for the current SubMesh. //! Sets the ID of the model's material slot that this mesh uses.
//! Adds a new material slot to the ModelLodAsset if it doesn't already exist.
//! Begin and BeginMesh must be called first //! 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. //! Sets the given BufferAssetView to the current SubMesh as the index buffer.
//! Begin and BeginMesh must be called first //! Begin and BeginMesh must be called first

@ -91,7 +91,7 @@ namespace AZ
if (auto* serialize = azrtti_cast<SerializeContext*>(context)) if (auto* serialize = azrtti_cast<SerializeContext*>(context))
{ {
serialize->Class<MaterialAssetBuilderComponent, SceneAPI::SceneCore::ExportingComponent>() serialize->Class<MaterialAssetBuilderComponent, SceneAPI::SceneCore::ExportingComponent>()
->Version(14); // [ATOM-13410] ->Version(16); // Optional material conversion
} }
} }

@ -368,6 +368,9 @@ namespace AZ
MorphTargetMetaAssetCreator morphTargetMetaCreator; MorphTargetMetaAssetCreator morphTargetMetaCreator;
morphTargetMetaCreator.Begin(MorphTargetMetaAsset::ConstructAssetId(modelAssetId, modelAssetName)); morphTargetMetaCreator.Begin(MorphTargetMetaAsset::ConstructAssetId(modelAssetId, modelAssetName));
ModelAssetCreator modelAssetCreator;
modelAssetCreator.Begin(modelAssetId);
uint32_t lodIndex = 0; uint32_t lodIndex = 0;
for (const SourceMeshContentList& sourceMeshContentList : sourceMeshContentListsByLod) for (const SourceMeshContentList& sourceMeshContentList : sourceMeshContentListsByLod)
{ {
@ -429,7 +432,7 @@ namespace AZ
for (const ProductMeshView& meshView : lodMeshViews) 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; return AZ::SceneAPI::Events::ProcessingResult::Failure;
} }
@ -469,10 +472,6 @@ namespace AZ
} }
sourceMeshContentListsByLod.clear(); sourceMeshContentListsByLod.clear();
// Build the final asset structure
ModelAssetCreator modelAssetCreator;
modelAssetCreator.Begin(modelAssetId);
// Finalize all LOD assets // Finalize all LOD assets
for (auto& lodAsset : lodAssets) for (auto& lodAsset : lodAssets)
{ {
@ -1796,6 +1795,7 @@ namespace AZ
const ProductMeshView& meshView, const ProductMeshView& meshView,
const BufferAssetView& lodIndexBuffer, const BufferAssetView& lodIndexBuffer,
const AZStd::vector<ModelLodAsset::Mesh::StreamBufferInfo>& lodStreamBuffers, const AZStd::vector<ModelLodAsset::Mesh::StreamBufferInfo>& lodStreamBuffers,
ModelAssetCreator& modelAssetCreator,
ModelLodAssetCreator& lodAssetCreator, ModelLodAssetCreator& lodAssetCreator,
const MaterialAssetsByUid& materialAssetsByUid) const MaterialAssetsByUid& materialAssetsByUid)
{ {
@ -1811,7 +1811,8 @@ namespace AZ
materialSlot.m_displayName = iter->second.m_name; materialSlot.m_displayName = iter->second.m_name;
materialSlot.m_defaultMaterialAsset = iter->second.m_asset; 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 ProductMeshView& meshView,
const BufferAssetView& lodIndexBuffer, const BufferAssetView& lodIndexBuffer,
const AZStd::vector<ModelLodAsset::Mesh::StreamBufferInfo>& lodStreamBuffers, const AZStd::vector<ModelLodAsset::Mesh::StreamBufferInfo>& lodStreamBuffers,
ModelAssetCreator& modelAssetCreator,
ModelLodAssetCreator& lodAssetCreator, ModelLodAssetCreator& lodAssetCreator,
const MaterialAssetsByUid& materialAssetsByUid); const MaterialAssetsByUid& materialAssetsByUid);

@ -40,7 +40,7 @@ namespace AZ
return m_lods; 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); AZ_PROFILE_FUNCTION(Debug::ProfileCategory::AzRender);
Data::Instance<Model> model = aznew Model(); Data::Instance<Model> model = aznew Model();
@ -54,15 +54,15 @@ namespace AZ
return nullptr; return nullptr;
} }
RHI::ResultCode Model::Init(ModelAsset& modelAsset) RHI::ResultCode Model::Init(const Data::Asset<ModelAsset>& modelAsset)
{ {
AZ_PROFILE_FUNCTION(Debug::ProfileCategory::AzRender); 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) 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) if (!lodAsset)
{ {
@ -70,7 +70,7 @@ namespace AZ
return RHI::ResultCode::Fail; return RHI::ResultCode::Fail;
} }
Data::Instance<ModelLod> lodInstance = ModelLod::FindOrCreate(lodAsset); Data::Instance<ModelLod> lodInstance = ModelLod::FindOrCreate(lodAsset, modelAsset);
if (lodInstance == nullptr) if (lodInstance == nullptr)
{ {
return RHI::ResultCode::Fail; return RHI::ResultCode::Fail;
@ -98,7 +98,7 @@ namespace AZ
m_lods[lodIndex] = AZStd::move(lodInstance); m_lods[lodIndex] = AZStd::move(lodInstance);
} }
m_modelAsset = { &modelAsset, AZ::Data::AssetLoadBehavior::PreLoad }; m_modelAsset = modelAsset;
m_isUploadPending = true; m_isUploadPending = true;
return RHI::ResultCode::Success; return RHI::ResultCode::Success;
} }

@ -19,11 +19,14 @@ namespace AZ
{ {
namespace RPI 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( return Data::InstanceDatabase<ModelLod>::Instance().FindOrCreate(
Data::InstanceId::CreateFromAssetId(lodAsset.GetId()), Data::InstanceId::CreateFromAssetId(lodAsset.GetId()),
lodAsset); lodAsset,
&modelAssetAny);
} }
AZStd::array_view<ModelLod::Mesh> ModelLod::GetMeshes() const AZStd::array_view<ModelLod::Mesh> ModelLod::GetMeshes() const
@ -31,10 +34,13 @@ namespace AZ
return m_meshes; 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(); 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) if (resultCode == RHI::ResultCode::Success)
{ {
@ -44,11 +50,11 @@ namespace AZ
return nullptr; 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(); AZ_TRACE_METHOD();
for (const ModelLodAsset::Mesh& mesh : lodAsset.GetMeshes()) for (const ModelLodAsset::Mesh& mesh : lodAsset->GetMeshes())
{ {
Mesh meshInstance; 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; meshInstance.m_materialSlotStableId = materialSlot.m_stableId;

@ -41,9 +41,9 @@ namespace AZ
{ {
//Create Lod Database //Create Lod Database
AZ::Data::InstanceHandler<ModelLod> lodInstanceHandler; 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); Data::InstanceDatabase<ModelLod>::Create(azrtti_typeid<ModelLodAsset>(), lodInstanceHandler);
@ -51,7 +51,7 @@ namespace AZ
AZ::Data::InstanceHandler<Model> modelInstanceHandler; AZ::Data::InstanceHandler<Model> modelInstanceHandler;
modelInstanceHandler.m_createFunction = [](Data::AssetData* modelAsset) 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); Data::InstanceDatabase<Model>::Create(azrtti_typeid<ModelAsset>(), modelInstanceHandler);
} }

@ -29,9 +29,10 @@ namespace AZ
if (auto* serializeContext = azrtti_cast<SerializeContext*>(context)) if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
{ {
serializeContext->Class<ModelAsset, Data::AssetData>() serializeContext->Class<ModelAsset, Data::AssetData>()
->Version(0) ->Version(1)
->Field("Name", &ModelAsset::m_name) ->Field("Name", &ModelAsset::m_name)
->Field("Aabb", &ModelAsset::m_aabb) ->Field("Aabb", &ModelAsset::m_aabb)
->Field("MaterialSlots", &ModelAsset::m_materialSlots)
->Field("LodAssets", &ModelAsset::m_lodAssets) ->Field("LodAssets", &ModelAsset::m_lodAssets)
; ;
} }
@ -57,29 +58,24 @@ namespace AZ
return m_aabb; 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()) const ModelMaterialSlot& ModelAsset::FindMaterialSlot(uint32_t stableId) const
{
for (const AZ::RPI::ModelMaterialSlot& materialSlot : lod->GetMaterialSlots())
{ {
auto iter = slotMap.find(materialSlot.m_stableId); auto iter = m_materialSlots.find(stableId);
if (iter == slotMap.end())
if (iter == m_materialSlots.end())
{ {
slotMap.emplace(materialSlot.m_stableId, materialSlot); return m_fallbackSlot;
} }
else else
{ {
AZ_Assert(materialSlot.m_displayName == iter->second.m_displayName && materialSlot.m_defaultMaterialAsset.GetId() == iter->second.m_defaultMaterialAsset.GetId(), return iter->second;
"Multiple LODs have mismatched data for the same material slot.");
} }
} }
}
return slotMap;
}
size_t ModelAsset::GetLodCount() const size_t ModelAsset::GetLodCount() const
{ {

@ -30,6 +30,33 @@ namespace AZ
} }
} }
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) void ModelAssetCreator::AddLodAsset(Data::Asset<ModelLodAsset>&& lodAsset)
{ {
if (ValidateIsReady()) if (ValidateIsReady())

@ -23,10 +23,9 @@ namespace AZ
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{ {
serializeContext->Class<ModelLodAsset>() serializeContext->Class<ModelLodAsset>()
->Version(1) ->Version(0)
->Field("Meshes", &ModelLodAsset::m_meshes) ->Field("Meshes", &ModelLodAsset::m_meshes)
->Field("Aabb", &ModelLodAsset::m_aabb) ->Field("Aabb", &ModelLodAsset::m_aabb)
->Field("MaterialSlots", &ModelLodAsset::m_materialSlots)
; ;
} }
@ -41,7 +40,7 @@ namespace AZ
->Version(1) ->Version(1)
->Field("Name", &ModelLodAsset::Mesh::m_name) ->Field("Name", &ModelLodAsset::Mesh::m_name)
->Field("AABB", &ModelLodAsset::Mesh::m_aabb) ->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("IndexBufferAssetView", &ModelLodAsset::Mesh::m_indexBufferAssetView)
->Field("StreamBufferInfo", &ModelLodAsset::Mesh::m_streamBufferInfo) ->Field("StreamBufferInfo", &ModelLodAsset::Mesh::m_streamBufferInfo)
; ;
@ -76,9 +75,9 @@ namespace AZ
return m_indexBufferAssetView.GetBufferViewDescriptor().m_elementCount; 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 const AZ::Name& ModelLodAsset::Mesh::GetName() const
@ -120,41 +119,6 @@ namespace AZ
return m_aabb; 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 BufferAssetView* ModelLodAsset::Mesh::GetSemanticBufferAssetView(const AZ::Name& semantic) const
{ {
const AZStd::array_view<ModelLodAsset::Mesh::StreamBufferInfo>& streamBufferList = GetStreamBufferInfoList(); 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) if (!ValidateIsMeshReady())
{
return existingMaterialSlot.m_stableId == materialSlot.m_stableId;
});
if (iter == m_asset->m_materialSlots.end())
{
m_currentMesh.m_materialSlotIndex = m_asset->m_materialSlots.size();
m_asset->m_materialSlots.push_back(materialSlot);
}
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); return;
} }
*iter = materialSlot; m_currentMesh.m_materialSlotId = id;
}
} }
void ModelLodAssetCreator::SetMeshIndexBuffer(const BufferAssetView& bufferAssetView) void ModelLodAssetCreator::SetMeshIndexBuffer(const BufferAssetView& bufferAssetView)
@ -309,8 +291,7 @@ namespace AZ
AZ::Aabb aabb = sourceMesh.GetAabb(); AZ::Aabb aabb = sourceMesh.GetAabb();
creator.SetMeshAabb(AZStd::move(aabb)); creator.SetMeshAabb(AZStd::move(aabb));
const ModelMaterialSlot& materialSlot = sourceAsset->GetMaterialSlot(sourceMesh.GetMaterialSlotIndex()); creator.SetMeshMaterialSlot(sourceMesh.GetMaterialSlotId());
creator.SetMeshMaterialSlot(materialSlot);
// Mesh index buffer view // Mesh index buffer view
const BufferAssetView& sourceIndexBufferView = sourceMesh.GetIndexBufferAssetView(); const BufferAssetView& sourceIndexBufferView = sourceMesh.GetIndexBufferAssetView();

@ -257,7 +257,7 @@ namespace AZ
Data::Asset<const RPI::ModelAsset> modelAsset = GetModelAsset(); Data::Asset<const RPI::ModelAsset> modelAsset = GetModelAsset();
if (modelAsset.IsReady()) if (modelAsset.IsReady())
{ {
return modelAsset->GetModelMaterialSlots(); return modelAsset->GetMaterialSlots();
} }
else else
{ {

@ -96,7 +96,7 @@ namespace AZ
skinnedSubMesh.m_vertexCount = aznumeric_cast<uint32_t>(subMeshVertexCount); skinnedSubMesh.m_vertexCount = aznumeric_cast<uint32_t>(subMeshVertexCount);
lodVertexCount += 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 // Queue the material asset - the ModelLod seems to handle delayed material loads
skinnedSubMesh.m_materialSlot.m_defaultMaterialAsset.QueueLoad(); skinnedSubMesh.m_materialSlot.m_defaultMaterialAsset.QueueLoad();

@ -313,7 +313,7 @@ namespace AZ
Data::Asset<const RPI::ModelAsset> modelAsset = GetModelAsset(); Data::Asset<const RPI::ModelAsset> modelAsset = GetModelAsset();
if (modelAsset.IsReady()) if (modelAsset.IsReady())
{ {
return modelAsset->GetModelMaterialSlots(); return modelAsset->GetMaterialSlots();
} }
else else
{ {

@ -113,19 +113,7 @@ namespace WhiteBox
modelLodCreator.BeginMesh(); modelLodCreator.BeginMesh();
modelLodCreator.SetMeshAabb(meshData.GetAabb()); modelLodCreator.SetMeshAabb(meshData.GetAabb());
// set the default material modelLodCreator.SetMeshMaterialSlot(OneMaterialSlotId);
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;
}
AddMeshBuffers(modelLodCreator); AddMeshBuffers(modelLodCreator);
modelLodCreator.EndMesh(); modelLodCreator.EndMesh();
@ -157,6 +145,20 @@ namespace WhiteBox
modelCreator.Begin(AZ::Data::AssetId(AZ::Uuid::CreateRandom())); modelCreator.Begin(AZ::Data::AssetId(AZ::Uuid::CreateRandom()));
modelCreator.SetName(ModelName); modelCreator.SetName(ModelName);
modelCreator.AddLodAsset(AZStd::move(m_lodAsset)); 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); modelCreator.End(m_modelAsset);
} }

@ -91,6 +91,7 @@ namespace WhiteBox
// TODO: LYN-784 // TODO: LYN-784
static constexpr AZStd::string_view TexturedMaterialPath = "materials/defaultpbr.azmaterial"; static constexpr AZStd::string_view TexturedMaterialPath = "materials/defaultpbr.azmaterial";
static constexpr AZStd::string_view SolidMaterialPath = "materials/defaultpbr.azmaterial"; static constexpr AZStd::string_view SolidMaterialPath = "materials/defaultpbr.azmaterial";
static constexpr AZ::RPI::ModelMaterialSlot::StableId OneMaterialSlotId = 0;
//! White box model name. //! White box model name.
static constexpr AZStd::string_view ModelName = "WhiteBoxMesh"; static constexpr AZStd::string_view ModelName = "WhiteBoxMesh";

Loading…
Cancel
Save