202 lines
8.2 KiB
C++
202 lines
8.2 KiB
C++
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "Config.h"
|
|
#include "FoliageInstance.h"
|
|
#include "FoliageCluster.h"
|
|
#include "FoliageType.h"
|
|
#include "Engine/Level/Actor.h"
|
|
#include "Engine/Core/Collections/ChunkedArray.h"
|
|
|
|
/// <summary>
|
|
/// Represents a foliage actor that contains a set of instanced meshes.
|
|
/// </summary>
|
|
/// <seealso cref="Actor" />
|
|
API_CLASS() class FLAXENGINE_API Foliage final : public Actor
|
|
{
|
|
DECLARE_SCENE_OBJECT(Foliage);
|
|
private:
|
|
|
|
bool _disableFoliageTypeEvents;
|
|
|
|
public:
|
|
|
|
/// <summary>
|
|
/// The root cluster. Contains all the instances and it's the starting point of the quad-tree hierarchy. Null if no foliage added. It's read-only.
|
|
/// </summary>
|
|
FoliageCluster* Root;
|
|
|
|
/// <summary>
|
|
/// The allocated foliage instances. It's read-only.
|
|
/// </summary>
|
|
ChunkedArray<FoliageInstance, FOLIAGE_INSTANCE_CHUNKS_SIZE> Instances;
|
|
|
|
/// <summary>
|
|
/// The allocated foliage clusters. It's read-only.
|
|
/// </summary>
|
|
ChunkedArray<FoliageCluster, FOLIAGE_CLUSTER_CHUNKS_SIZE> Clusters;
|
|
|
|
/// <summary>
|
|
/// The foliage instances types used by the current foliage actor. It's read-only.
|
|
/// </summary>
|
|
API_FIELD(ReadOnly, Attributes="HideInEditor, NoSerialize")
|
|
Array<FoliageType> FoliageTypes;
|
|
|
|
public:
|
|
|
|
/// <summary>
|
|
/// Gets the total amount of the instanced of foliage.
|
|
/// </summary>
|
|
/// <returns>The foliage instances count.</returns>
|
|
API_PROPERTY() int32 GetInstancesCount() const;
|
|
|
|
/// <summary>
|
|
/// Gets the foliage instance by index.
|
|
/// </summary>
|
|
/// <param name="index">The zero-based index of the foliage instance.</param>
|
|
/// <returns>The foliage instance data.</returns>
|
|
API_FUNCTION() FoliageInstance GetInstance(int32 index) const;
|
|
|
|
/// <summary>
|
|
/// Gets the total amount of the types of foliage.
|
|
/// </summary>
|
|
/// <returns>The foliage types count.</returns>
|
|
API_PROPERTY() int32 GetFoliageTypesCount() const;
|
|
|
|
/// <summary>
|
|
/// Gets the foliage type.
|
|
/// </summary>
|
|
/// <param name="index">The zero-based index of the foliage type.</param>
|
|
/// <returns>The foliage type.</returns>
|
|
API_FUNCTION() FoliageType* GetFoliageType(int32 index);
|
|
|
|
/// <summary>
|
|
/// Adds the type of the foliage.
|
|
/// </summary>
|
|
/// <param name="model">The model to assign. It cannot be null nor already used by the other instance type (it must be unique within the given foliage actor).</param>
|
|
API_FUNCTION() void AddFoliageType(Model* model);
|
|
|
|
/// <summary>
|
|
/// Removes the foliage instance type and all foliage instances using this type.
|
|
/// </summary>
|
|
/// <param name="index">The zero-based index of the foliage instance type.</param>
|
|
API_FUNCTION() void RemoveFoliageType(int32 index);
|
|
|
|
/// <summary>
|
|
/// Gets the total amount of the instanced that use the given foliage type.
|
|
/// </summary>
|
|
/// <param name="index">The zero-based index of the foliage type.</param>
|
|
/// <returns>The foliage type instances count.</returns>
|
|
API_FUNCTION() int32 GetFoliageTypeInstancesCount(int32 index) const;
|
|
|
|
/// <summary>
|
|
/// Adds the new foliage instance. Ensure to always call <see cref="RebuildClusters"/> after editing foliage to sync cached data (call it once after editing one or more instances).
|
|
/// </summary>
|
|
/// <remarks>Input instance bounds, instance random and world matrix are ignored (recalculated).</remarks>
|
|
/// <param name="instance">The instance.</param>
|
|
API_FUNCTION() void AddInstance(API_PARAM(Ref) const FoliageInstance& instance);
|
|
|
|
/// <summary>
|
|
/// Removes the foliage instance. Ensure to always call <see cref="RebuildClusters"/> after editing foliage to sync cached data (call it once after editing one or more instances).
|
|
/// </summary>
|
|
/// <param name="index">The zero-based index of the instance to remove.</param>
|
|
API_FUNCTION() void RemoveInstance(int32 index)
|
|
{
|
|
RemoveInstance(Instances.IteratorAt(index));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Removes the foliage instance. Ensure to always call <see cref="RebuildClusters"/> after editing foliage to sync cached data (call it once after editing one or more instances).
|
|
/// </summary>
|
|
/// <param name="i">The iterator from foliage instances that points to the instance to remove.</param>
|
|
void RemoveInstance(ChunkedArray<FoliageInstance, FOLIAGE_INSTANCE_CHUNKS_SIZE>::Iterator i);
|
|
|
|
/// <summary>
|
|
/// Sets the foliage instance transformation. Ensure to always call <see cref="RebuildClusters"/> after editing foliage to sync cached data (call it once after editing one or more instances).
|
|
/// </summary>
|
|
/// <param name="index">The zero-based index of the foliage instance.</param>
|
|
/// <param name="value">The value.</param>
|
|
API_FUNCTION() void SetInstanceTransform(int32 index, API_PARAM(Ref) const Transform& value);
|
|
|
|
/// <summary>
|
|
/// Called when foliage type model is loaded.
|
|
/// </summary>
|
|
/// <param name="index">The zero-based index of the foliage type.</param>
|
|
void OnFoliageTypeModelLoaded(int32 index);
|
|
|
|
/// <summary>
|
|
/// Rebuilds the foliage clusters used as internal acceleration structures (quad tree).
|
|
/// </summary>
|
|
API_FUNCTION() void RebuildClusters();
|
|
|
|
/// <summary>
|
|
/// Updates the cull distance for all foliage instances and for created clusters.
|
|
/// </summary>
|
|
API_FUNCTION() void UpdateCullDistance();
|
|
|
|
public:
|
|
|
|
/// <summary>
|
|
/// Gets the global density scale for all foliage instances. The default value is 1. Use values from range 0-1. Lower values decrease amount of foliage instances in-game. Use it to tweak game performance for slower devices.
|
|
/// </summary>
|
|
/// <returns>The value.</returns>
|
|
API_PROPERTY() static float GetGlobalDensityScale();
|
|
|
|
/// <summary>
|
|
/// Sets the global density scale for all foliage instances. The default value is 1. Use values from range 0-1. Lower values decrease amount of foliage instances in-game. Use it to tweak game performance for slower devices.
|
|
/// </summary>
|
|
/// <param name="value">The value.</param>
|
|
API_PROPERTY() static void SetGlobalDensityScale(float value);
|
|
|
|
private:
|
|
|
|
/// <summary>
|
|
/// Ensures that the root node of the foliage was added.
|
|
/// </summary>
|
|
void EnsureRoot();
|
|
|
|
/// <summary>
|
|
/// Adds the given foliage instance to the cluster.
|
|
/// </summary>
|
|
/// <param name="cluster">The root cluster.</param>
|
|
/// <param name="instance">The instance.</param>
|
|
void AddToCluster(FoliageCluster* cluster, FoliageInstance& instance);
|
|
|
|
/// <summary>
|
|
/// Draws the cluster.
|
|
/// </summary>
|
|
/// <param name="renderContext">The rendering context.</param>
|
|
/// <param name="cluster">The cluster.</param>
|
|
/// <param name="draw">The draw data.</param>
|
|
void DrawCluster(RenderContext& renderContext, FoliageCluster* cluster, Mesh::DrawInfo& draw);
|
|
|
|
public:
|
|
|
|
/// <summary>
|
|
/// Determines if there is an intersection between the current object or any it's child and a ray.
|
|
/// </summary>
|
|
/// <param name="ray">The ray to test.</param>
|
|
/// <param name="distance">When the method completes, contains the distance of the intersection (if any valid).</param>
|
|
/// <param name="normal">When the method completes, contains the intersection surface normal vector (if any valid).</param>
|
|
/// <param name="instanceIndex">When the method completes, contains zero-based index of the foliage instance that is the closest to the ray.</param>
|
|
/// <returns>True whether the two objects intersected, otherwise false.</returns>
|
|
API_FUNCTION() bool Intersects(API_PARAM(Ref) const Ray& ray, API_PARAM(Out) float& distance, API_PARAM(Out) Vector3& normal, API_PARAM(Out) int32& instanceIndex);
|
|
|
|
public:
|
|
|
|
// [Actor]
|
|
void Draw(RenderContext& renderContext) override;
|
|
void DrawGeneric(RenderContext& renderContext) override;
|
|
bool IntersectsItself(const Ray& ray, float& distance, Vector3& normal) override;
|
|
void Serialize(SerializeStream& stream, const void* otherObj) override;
|
|
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
|
|
|
|
protected:
|
|
|
|
// [Actor]
|
|
void OnEnable() override;
|
|
void OnDisable() override;
|
|
void OnTransformChanged() override;
|
|
};
|