// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
#pragma once
#include "Config.h"
#include "Engine/Core/Collections/Array.h"
#include "Engine/Core/Math/BoundingBox.h"
#include "Engine/Core/Math/BoundingSphere.h"
///
/// Represents a single foliage cluster that contains a sub clusters organized in quad-tree or if it's a leaf node it contains a set of foliage instances.
///
class FLAXENGINE_API FoliageCluster
{
public:
///
/// The cluster bounds (in world space). Made of subdivided parent node in quad-tree.
///
BoundingBox Bounds;
///
/// The cached cluster total bounds (in world space). Made of attached instances bounds including children.
///
BoundingBox TotalBounds;
///
/// The cached cluster total bounds (in world space). Made of attached instances bounds including children.
///
BoundingSphere TotalBoundsSphere;
///
/// The maximum cull distance for the instances that are located in this cluster (including child clusters).
///
float MaxCullDistance;
///
/// The child clusters. If any element is valid then all are created.
///
FoliageCluster* Children[4];
///
/// The allocated foliage instances within this cluster.
///
Array> Instances;
public:
///
/// Initializes this instance.
///
/// The bounds.
void Init(const BoundingBox& bounds);
///
/// Updates the total bounds of the cluster and all child clusters and cull distance (as UpdateCullDistance does).
///
void UpdateTotalBoundsAndCullDistance();
///
/// Updates the cull distance for all foliage instances added to the cluster and its children.
///
void UpdateCullDistance();
///
/// Determines if there is an intersection between the current object or any it's child and a ray.
///
/// The parent foliage actor.
/// The ray to test.
/// When the method completes, 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 pointer of the foliage instance that is the closest to the ray.
/// True whether the two objects intersected, otherwise false.
bool Intersects(Foliage* foliage, const Ray& ray, Real& distance, Vector3& normal, FoliageInstance*& instance);
};