Add MeshReference to ModelInstanceActor for easy mesh referencing and its data access interface

This commit is contained in:
Wojtek Figat
2023-06-29 16:50:00 +02:00
parent 656866c1d4
commit e3cbe1458d
6 changed files with 394 additions and 2 deletions

View File

@@ -945,6 +945,18 @@ bool AnimatedModel::IntersectsEntry(const Ray& ray, Real& distance, Vector3& nor
return result;
}
bool AnimatedModel::GetMeshData(const MeshReference& mesh, MeshBufferType type, BytesContainer& result, int32& count) const
{
count = 0;
if (mesh.LODIndex < 0 || mesh.MeshIndex < 0)
return true;
const auto model = SkinnedModel.Get();
if (!model || model->WaitForLoaded())
return true;
auto& lod = model->LODs[Math::Min(mesh.LODIndex, model->LODs.Count() - 1)];
return lod.Meshes[Math::Min(mesh.MeshIndex, lod.Meshes.Count() - 1)].DownloadDataCPU(type, result, count);
}
void AnimatedModel::OnDeleteObject()
{
// Ensure this object is no longer referenced for anim update

View File

@@ -374,6 +374,7 @@ public:
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
bool IntersectsEntry(int32 entryIndex, const Ray& ray, Real& distance, Vector3& normal) override;
bool IntersectsEntry(const Ray& ray, Real& distance, Vector3& normal, int32& entryIndex) override;
bool GetMeshData(const MeshReference& mesh, MeshBufferType type, BytesContainer& result, int32& count) const override;
void OnDeleteObject() override;
protected:

View File

@@ -12,6 +12,23 @@
API_CLASS(Abstract) class FLAXENGINE_API ModelInstanceActor : public Actor
{
DECLARE_SCENE_OBJECT_ABSTRACT(ModelInstanceActor);
/// <summary>
/// Utility container to reference a single mesh within <see cref="ModelInstanceActor"/>.
/// </summary>
API_STRUCT(NoDefault) struct MeshReference : ISerializable
{
DECLARE_SCRIPTING_TYPE_MINIMAL(MeshReference);
API_AUTO_SERIALIZATION();
// Owning actor.
API_FIELD() ScriptingObjectReference<ModelInstanceActor> Actor;
// Index of the LOD (Level Of Detail).
API_FIELD() int32 LODIndex = 0;
// Index of the mesh (within the LOD).
API_FIELD() int32 MeshIndex = 0;
};
protected:
int32 _sceneRenderingKey = -1; // Uses SceneRendering::DrawCategory::SceneDrawAsync
@@ -24,8 +41,8 @@ public:
/// <summary>
/// Gets the model entries collection. Each entry contains data how to render meshes using this entry (transformation, material, shadows casting, etc.).
/// </summary>
API_PROPERTY(Attributes="Serialize, EditorOrder(1000), EditorDisplay(\"Entries\", EditorDisplayAttribute.InlineStyle), Collection(CanReorderItems = false, NotNullItems = true, ReadOnly = true, Spacing = 10)")
FORCE_INLINE Array<ModelInstanceEntry> GetEntries() const
API_PROPERTY(Attributes="Serialize, EditorOrder(1000), EditorDisplay(\"Entries\", EditorDisplayAttribute.InlineStyle), Collection(CanReorderItems=false, NotNullItems=true, ReadOnly=true, Spacing=10)")
FORCE_INLINE const Array<ModelInstanceEntry>& GetEntries() const
{
return Entries;
}
@@ -80,6 +97,19 @@ public:
{
return false;
}
/// <summary>
/// Extracts mesh buffer data from CPU. Might be cached internally (eg. by Model/SkinnedModel).
/// </summary>
/// <param name="mesh">Mesh reference.</param>
/// <param name="type">Buffer type</param>
/// <param name="result">The result data</param>
/// <param name="count">The amount of items inside the result buffer.</param>
/// <returns>True if failed, otherwise false</returns>
virtual bool GetMeshData(const MeshReference& mesh, MeshBufferType type, BytesContainer& result, int32& count) const
{
return true;
}
protected:
virtual void WaitForModelLoad();

View File

@@ -588,6 +588,18 @@ bool StaticModel::IntersectsEntry(const Ray& ray, Real& distance, Vector3& norma
return result;
}
bool StaticModel::GetMeshData(const MeshReference& mesh, MeshBufferType type, BytesContainer& result, int32& count) const
{
count = 0;
if (mesh.LODIndex < 0 || mesh.MeshIndex < 0)
return true;
const auto model = Model.Get();
if (!model || model->WaitForLoaded())
return true;
auto& lod = model->LODs[Math::Min(mesh.LODIndex, model->LODs.Count() - 1)];
return lod.Meshes[Math::Min(mesh.MeshIndex, lod.Meshes.Count() - 1)].DownloadDataCPU(type, result, count);
}
void StaticModel::OnTransformChanged()
{
// Base

View File

@@ -168,6 +168,7 @@ public:
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
bool IntersectsEntry(int32 entryIndex, const Ray& ray, Real& distance, Vector3& normal) override;
bool IntersectsEntry(const Ray& ray, Real& distance, Vector3& normal, int32& entryIndex) override;
bool GetMeshData(const MeshReference& mesh, MeshBufferType type, BytesContainer& result, int32& count) const override;
protected:
// [ModelInstanceActor]