// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved. #pragma once #include "Engine/Level/Actor.h" #include "Engine/Graphics/Models/ModelInstanceEntry.h" /// /// Base class for actor types that use ModelInstanceEntries for mesh rendering. /// /// API_CLASS(Abstract) class FLAXENGINE_API ModelInstanceActor : public Actor { DECLARE_SCENE_OBJECT_ABSTRACT(ModelInstanceActor); /// /// Utility container to reference a single mesh within . /// API_STRUCT(NoDefault) struct MeshReference : ISerializable { DECLARE_SCRIPTING_TYPE_MINIMAL(MeshReference); API_AUTO_SERIALIZATION(); // Owning actor. API_FIELD() ScriptingObjectReference 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 public: /// /// The model instance buffer. /// ModelInstanceEntries Entries; /// /// Gets the model entries collection. Each entry contains data how to render meshes using this entry (transformation, material, shadows casting, etc.). /// API_PROPERTY(Attributes="Serialize, EditorOrder(1000), EditorDisplay(\"Entries\", EditorDisplayAttribute.InlineStyle), Collection(CanReorderItems=false, NotNullItems=true, CanResize=false, Spacing=10)") FORCE_INLINE const Array& GetEntries() const { return Entries; } /// /// Sets the model entries collection. Each entry contains data how to render meshes using this entry (transformation, material, shadows casting, etc.). /// API_PROPERTY() void SetEntries(const Array& value); /// /// Gets the material slots array set on the asset (eg. model or skinned model asset). /// API_PROPERTY(Sealed) virtual const Span GetMaterialSlots() const = 0; /// /// Gets the material used to draw the meshes which are assigned to that slot (set in Entries or model's default). /// /// The material slot entry index. API_FUNCTION(Sealed) virtual MaterialBase* GetMaterial(int32 entryIndex) = 0; /// /// Sets the material to the entry slot. Can be used to override the material of the meshes using this slot. /// /// The material slot entry index. /// The material to set. API_FUNCTION() void SetMaterial(int32 entryIndex, MaterialBase* material); /// /// Utility to crate a new virtual Material Instance asset, set its parent to the currently applied material, and assign it to the entry. Can be used to modify the material parameters from code. /// /// The material slot entry index. /// The created virtual material instance. API_FUNCTION() MaterialInstance* CreateAndSetVirtualMaterialInstance(int32 entryIndex); /// /// Determines if there is an intersection between the model actor mesh entry and a ray. /// If mesh data is available on the CPU performs exact intersection check with the geometry. /// Otherwise performs simple vs test. /// For more efficient collisions detection and ray casting use physics. /// /// The material slot entry index to test. /// The ray to test. /// When the method completes and returns true, contains the distance of the intersection (if any valid). /// When the method completes, contains the intersection surface normal vector (if any valid). /// True if the actor is intersected by the ray, otherwise false. API_FUNCTION() virtual bool IntersectsEntry(int32 entryIndex, API_PARAM(Ref) const Ray& ray, API_PARAM(Out) Real& distance, API_PARAM(Out) Vector3& normal) { return false; } /// /// Determines if there is an intersection between the model actor mesh entry and a ray. /// If mesh data is available on the CPU performs exact intersection check with the geometry. /// Otherwise performs simple vs test. /// For more efficient collisions detection and ray casting use physics. /// /// The ray to test. /// When the method completes and returns true, contains the distance of the intersection (if any valid). /// When the method completes, contains the intersection surface normal vector (if any valid). /// When the method completes, contains the intersection entry index (if any valid). /// True if the actor is intersected by the ray, otherwise false. API_FUNCTION() virtual bool IntersectsEntry(API_PARAM(Ref) const Ray& ray, API_PARAM(Out) Real& distance, API_PARAM(Out) Vector3& normal, API_PARAM(Out) int32& entryIndex) { return false; } /// /// Extracts mesh buffer data from CPU. Might be cached internally (eg. by Model/SkinnedModel). /// /// Mesh reference. /// Buffer type /// The result data /// The amount of items inside the result buffer. /// True if failed, otherwise false. virtual bool GetMeshData(const MeshReference& mesh, MeshBufferType type, BytesContainer& result, int32& count) const { return true; } /// /// Gets the mesh deformation utility for this model instance (optional). /// /// Model deformation utility or null if not supported. virtual MeshDeformation* GetMeshDeformation() const { return nullptr; } /// /// Updates the model bounds (eg. when mesh has applied significant deformation). /// virtual void UpdateBounds() = 0; protected: virtual void WaitForModelLoad(); public: // [Actor] void OnLayerChanged() override; void OnStaticFlagsChanged() override; void OnTransformChanged() override; protected: // [Actor] void OnEnable() override; void OnDisable() override; };