// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved. #pragma once #include "ModelInstanceActor.h" #include "Engine/Content/Assets/Model.h" class Spline; /// /// Renders model over the spline segments. /// API_CLASS() class FLAXENGINE_API SplineModel : public ModelInstanceActor { DECLARE_SCENE_OBJECT(SplineModel); private: struct Instance { BoundingSphere Sphere; float RotDeterminant; }; float _boundsScale = 1.0f, _quality = 1.0f; char _lodBias = 0; char _forcedLod = -1; bool _deformationDirty = false; Array _instances; Transform _preTransform = Transform::Identity; Spline* _spline = nullptr; GPUBuffer* _deformationBuffer = nullptr; void* _deformationBufferData = nullptr; float _chunksPerSegment, _meshMinZ, _meshMaxZ; public: ~SplineModel(); /// /// The model asset to draw. /// API_FIELD(Attributes="EditorOrder(20), DefaultValue(null), EditorDisplay(\"Model\")") AssetReference Model; /// /// Gets the transformation applied to the model geometry before placing it over the spline. Can be used to change the way model goes over the spline. /// API_PROPERTY(Attributes="EditorOrder(21), EditorDisplay(\"Model\")") Transform GetPreTransform() const; /// /// Sets the transformation applied to the model geometry before placing it over the spline. Can be used to change the way model goes over the spline. /// API_PROPERTY() void SetPreTransform(const Transform& value); /// /// The draw passes to use for rendering this object. /// API_FIELD(Attributes="EditorOrder(15), DefaultValue(DrawPass.Default), EditorDisplay(\"Model\")") DrawPass DrawModes = DrawPass::Default; /// /// Gets the spline model quality scale. Higher values improve the spline representation (better tessellation) but reduce performance. /// API_PROPERTY(Attributes="EditorOrder(11), DefaultValue(1.0f), EditorDisplay(\"Model\"), Limit(0.1f, 100.0f, 0.1f)") float GetQuality() const; /// /// Sets the spline model quality scale. Higher values improve the spline representation (better tessellation) but reduce performance. /// API_PROPERTY() void SetQuality(float value); /// /// Gets the model bounds scale. It is useful when using Position Offset to animate the vertices of the object outside of its bounds. /// API_PROPERTY(Attributes="EditorOrder(12), DefaultValue(1.0f), EditorDisplay(\"Model\"), Limit(0, 10.0f, 0.1f)") float GetBoundsScale() const; /// /// Sets the model bounds scale. It is useful when using Position Offset to animate the vertices of the object outside of its bounds. /// API_PROPERTY() void SetBoundsScale(float value); /// /// Gets the model Level Of Detail bias value. Allows to increase or decrease rendered model quality. /// API_PROPERTY(Attributes="EditorOrder(40), DefaultValue(0), Limit(-100, 100, 0.1f), EditorDisplay(\"Model\", \"LOD Bias\")") int32 GetLODBias() const; /// /// Sets the model Level Of Detail bias value. Allows to increase or decrease rendered model quality. /// API_PROPERTY() void SetLODBias(int32 value); /// /// Gets the model forced Level Of Detail index. Allows to bind the given model LOD to show. Value -1 disables this feature. /// API_PROPERTY(Attributes="EditorOrder(50), DefaultValue(-1), Limit(-1, 100, 0.1f), EditorDisplay(\"Model\", \"Forced LOD\")") int32 GetForcedLOD() const; /// /// Sets the model forced Level Of Detail index. Allows to bind the given model LOD to show. Value -1 disables this feature. /// API_PROPERTY() void SetForcedLOD(int32 value); private: void OnModelChanged(); void OnModelLoaded(); void OnSplineUpdated(); void UpdateDeformationBuffer(); public: // [ModelInstanceActor] bool HasContentLoaded() const override; void Draw(RenderContext& renderContext) override; bool IntersectsItself(const Ray& ray, Real& distance, Vector3& normal) override; void Serialize(SerializeStream& stream, const void* otherObj) override; void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override; void OnParentChanged() override; const Span GetMaterialSlots() const override; MaterialBase* GetMaterial(int32 entryIndex) override; void UpdateBounds() override; protected: // [ModelInstanceActor] void OnActiveInTreeChanged() override; };