// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
#pragma once
#include "Types.h"
#include "Engine/Core/Types/Guid.h"
#include "Engine/Core/Math/Plane.h"
#include "Engine/Core/Math/AABB.h"
#include "Engine/Core/Math/Vector2.h"
class Scene;
namespace CSG
{
///
/// CSG plane surface
///
struct Surface : Plane
{
Guid Material;
Float2 TexCoordScale;
Float2 TexCoordOffset;
float TexCoordRotation;
float ScaleInLightmap;
public:
///
/// Default constructor
///
Surface()
: Plane()
, TexCoordScale(1)
, TexCoordOffset(0.0f)
, TexCoordRotation(0)
, ScaleInLightmap(1)
{
}
Surface(const Plane& plane)
: Plane(plane)
, Material(Guid::Empty)
, TexCoordScale(1)
, TexCoordOffset(0.0f)
, TexCoordRotation(0)
, ScaleInLightmap(1)
{
}
Surface(const Surface& plane)
: Plane(plane)
, Material(plane.Material)
, TexCoordScale(1)
, TexCoordOffset(0.0f)
, TexCoordRotation(0)
, ScaleInLightmap(1)
{
}
Surface(const Vector3& normal, float d)
: Plane(normal, d)
, Material(Guid::Empty)
, TexCoordScale(1)
, TexCoordOffset(0.0f)
, TexCoordRotation(0)
, ScaleInLightmap(1)
{
}
Surface(const Vector3& point1, const Vector3& point2, const Vector3& point3)
: Plane(point1, point2, point3)
, Material(Guid::Empty)
, TexCoordScale(1)
, TexCoordOffset(0.0f)
, TexCoordRotation(0)
, ScaleInLightmap(1)
{
}
public:
static Vector3 Intersection(const Vector3& start, const Vector3& end, Real sdist, Real edist)
{
Vector3 vector = end - start;
Real length = edist - sdist;
Real delta = edist / length;
return end - (delta * vector);
}
Vector3 Intersection(const Vector3& start, const Vector3& end) const
{
return Intersection(start, end, Distance(start), Distance(end));
}
Real Distance(const Vector3& vertex) const
{
return
(
(Normal.X * vertex.X) +
(Normal.Y * vertex.Y) +
(Normal.Z * vertex.Z) -
(D)
);
}
static PlaneIntersectionType OnSide(Real distance)
{
if (distance > DistanceEpsilon)
return PlaneIntersectionType::Front;
if (distance < -DistanceEpsilon)
return PlaneIntersectionType::Back;
return PlaneIntersectionType::Intersecting;
}
PlaneIntersectionType OnSide(const Vector3& vertex) const
{
return OnSide(Distance(vertex));
}
PlaneIntersectionType OnSide(const AABB& box) const
{
Vector3 min;
Vector3 max;
max.X = static_cast((Normal.X >= 0.0f) ? box.MinX : box.MaxX);
max.Y = static_cast((Normal.Y >= 0.0f) ? box.MinY : box.MaxY);
max.Z = static_cast((Normal.Z >= 0.0f) ? box.MinZ : box.MaxZ);
min.X = static_cast((Normal.X >= 0.0f) ? box.MaxX : box.MinX);
min.Y = static_cast((Normal.Y >= 0.0f) ? box.MaxY : box.MinY);
min.Z = static_cast((Normal.Z >= 0.0f) ? box.MaxZ : box.MinZ);
Real distance = Vector3::Dot(Normal, max) - D;
if (distance > DistanceEpsilon)
return PlaneIntersectionType::Front;
distance = Vector3::Dot(Normal, min) - D;
if (distance < -DistanceEpsilon)
return PlaneIntersectionType::Back;
return PlaneIntersectionType::Intersecting;
}
};
///
/// CSG brush object
///
class FLAXENGINE_API Brush
{
public:
///
/// Gets the scene.
///
/// Scene
virtual Scene* GetBrushScene() const = 0;
///
/// Returns true if brush affects world
///
/// True if use CSG brush during level geometry building
virtual bool CanUseCSG() const
{
return true;
}
///
/// Gets the CSG brush object ID.
///
/// The unique ID.
virtual Guid GetBrushID() const = 0;
///
/// Gets CSG brush mode
///
/// Mode
virtual Mode GetBrushMode() const = 0;
///
/// Gets brush surfaces
///
/// Result list of surfaces
virtual void GetSurfaces(Array& surfaces) = 0;
///
/// Gets brush surfaces amount
///
/// The mount of the brush surfaces.
virtual int32 GetSurfacesCount() = 0;
public:
///
/// Called when brush data gets modified (will request rebuilding in Editor).
///
virtual void OnBrushModified();
};
};