// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
#pragma once
#include "Engine/Core/Math/BoundingBox.h"
#include "Engine/Core/Math/Matrix.h"
#include "Engine/Serialization/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.
///
class FLAXENGINE_API TerrainChunk : public ISerializable
{
friend Terrain;
friend TerrainPatch;
friend TerrainChunk;
private:
TerrainPatch* _patch;
uint16 _x, _z;
Vector4 _heightmapUVScaleBias;
Matrix _world;
BoundingBox _bounds;
Vector3 _boundsCenter;
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.
///
AssetReference OverrideMaterial;
///
/// The baked lightmap entry info for this chunk.
///
LightmapEntry Lightmap;
public:
///
/// Gets the x coordinate.
///
/// The x position.
FORCE_INLINE int32 GetX() const
{
return _x;
}
///
/// Gets the z coordinate.
///
/// The z position.
FORCE_INLINE int32 GetZ() const
{
return _z;
}
///
/// Gets the patch.
///
/// The terrain patch,
FORCE_INLINE TerrainPatch* GetPatch() const
{
return _patch;
}
///
/// Gets the chunk world bounds.
///
/// The bounding box.
FORCE_INLINE const BoundingBox& GetBounds() const
{
return _bounds;
}
///
/// Gets the model world matrix transform.
///
/// The result world matrix.
FORCE_INLINE void GetWorld(Matrix* world) const
{
*world = _world;
}
///
/// Gets the scale (in XY) and bias (in ZW) applied to the vertex UVs to get the chunk coordinates.
///
/// The result.
FORCE_INLINE void GetHeightmapUVScaleBias(Vector4* result) const
{
*result = _heightmapUVScaleBias;
}
///
/// Determines whether this chunk has valid lightmap data.
///
/// true if this chunk has valid lightmap data; otherwise, false.
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.
void Draw(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.
bool Intersects(const Ray& ray, float& 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;
};