// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
#pragma once
#include "Engine/Core/Math/BoundingBox.h"
#include "Engine/Core/Math/BoundingSphere.h"
#include "Engine/Core/Math/Matrix.h"
#include "Engine/Core/Math/Transform.h"
#include "Engine/Core/ISerializable.h"
#include "Engine/Content/Assets/MaterialBase.h"
#include "Engine/Level/Scene/Lightmap.h"
class Terrain;
class TerrainPatch;
struct RenderContext;
///
/// Represents a single terrain chunk.
///
API_CLASS(Sealed, NoSpawn) class FLAXENGINE_API TerrainChunk : public ScriptingObject, public ISerializable
{
DECLARE_SCRIPTING_TYPE(TerrainChunk);
friend Terrain;
friend TerrainPatch;
friend TerrainChunk;
private:
TerrainPatch* _patch;
uint16 _x, _z;
Float4 _heightmapUVScaleBias;
Transform _transform;
BoundingBox _bounds;
BoundingSphere _sphere;
float _perInstanceRandom;
float _yOffset, _yHeight;
TerrainChunk* _neighbors[4];
byte _cachedDrawLOD;
IMaterial* _cachedDrawMaterial;
void Init(TerrainPatch* patch, uint16 x, uint16 z);
public:
///
/// The material to override the terrain default one for this chunk.
///
API_FIELD() AssetReference OverrideMaterial;
///
/// The baked lightmap entry info for this chunk.
///
LightmapEntry Lightmap;
public:
///
/// Gets the x coordinate.
///
API_FUNCTION() FORCE_INLINE int32 GetX() const
{
return _x;
}
///
/// Gets the z coordinate.
///
API_FUNCTION() FORCE_INLINE int32 GetZ() const
{
return _z;
}
///
/// Gets the patch.
///
API_FUNCTION() FORCE_INLINE TerrainPatch* GetPatch() const
{
return _patch;
}
///
/// Gets the chunk world bounds.
///
API_FUNCTION() FORCE_INLINE const BoundingBox& GetBounds() const
{
return _bounds;
}
///
/// Gets the chunk transformation (world to local).
///
API_FUNCTION() FORCE_INLINE const Transform& GetTransform() const
{
return _transform;
}
///
/// Gets the scale (in XY) and bias (in ZW) applied to the vertex UVs to get the chunk coordinates.
///
API_FUNCTION() FORCE_INLINE const Float4& GetHeightmapUVScaleBias() const
{
return _heightmapUVScaleBias;
}
///
/// Determines whether this chunk has valid lightmap data.
///
FORCE_INLINE bool HasLightmap() const
{
return Lightmap.TextureIndex != INVALID_INDEX;
}
///
/// Removes the lightmap data from the chunk.
///
FORCE_INLINE void RemoveLightmap()
{
Lightmap.TextureIndex = INVALID_INDEX;
}
public:
///
/// Prepares for drawing chunk. Cached LOD and material.
///
/// The rendering context.
/// True if draw chunk, otherwise false.
bool PrepareDraw(const RenderContext& renderContext);
///
/// Draws the chunk (adds the draw call). Must be called after PrepareDraw.
///
/// The rendering context.
void Draw(const RenderContext& renderContext) const;
///
/// Draws the terrain chunk.
///
/// The rendering context.
/// The material to use for rendering.
/// The LOD index.
API_FUNCTION() void Draw(API_PARAM(Ref) const RenderContext& renderContext, MaterialBase* material, int32 lodIndex = 0) const;
///
/// Determines if there is an intersection between the terrain chunk and a point
///
/// The ray.
/// The output distance.
/// True if chunk intersects with the ray, otherwise false.
API_FUNCTION() bool Intersects(const Ray& ray, API_PARAM(Out) Real& distance);
///
/// Updates the cached bounds of the chunk.
///
void UpdateBounds();
///
/// Updates the cached transform of the chunk.
///
void UpdateTransform();
///
/// Caches the neighbor chunks of this chunk.
///
void CacheNeighbors();
public:
// [ISerializable]
void Serialize(SerializeStream& stream, const void* otherObj) override;
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) override;
};