// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
#pragma once
#include "Engine/Core/Math/AABB.h"
#include "Engine/Core/Collections/Array.h"
#include "Brush.h"
#include "HalfEdge.h"
#include "Polygon.h"
#include "Engine/Graphics/Models/Types.h"
#define CSG_MESH_UV_SCALE (1.0f / 100.0f)
#if COMPILE_WITH_CSG_BUILDER
namespace CSG
{
class RawData;
enum PolygonOperation
{
Keep,
Remove,
Flip
};
///
/// CSG mesh object
///
class Mesh
{
private:
struct BrushMeta
{
Mode Mode;
int32 StartSurfaceIndex;
int32 SurfacesCount;
AABB Bounds;
Brush* Parent;
};
private:
AABB _bounds;
Array _polygons;
Array _edges;
Array _vertices;
Array _surfaces;
Array _brushesMeta;
public:
///
/// Mesh index (assigned by the builder)
///
int32 Index = 0;
///
/// Gets mesh bounds area
///
/// Mesh bounds
AABB GetBounds() const
{
return _bounds;
}
///
/// Check if any of this brush sub-brushes is on given type
///
/// True if brush is using given mode
bool HasMode(Mode mode) const;
///
/// Gets array with polygons
///
/// Polygon
const Array* GetPolygons() const
{
return &_polygons;
}
///
/// Gets array with surfaces
///
/// Surfaces
const Array* GetSurfaces() const
{
return &_surfaces;
}
///
/// Gets array with edges
///
/// Half edges
const Array* GetEdges() const
{
return &_edges;
}
///
/// Gets array with vertices
///
/// Vertices
const Array* GetVertices() const
{
return &_vertices;
}
public:
///
/// Build mesh from brush
///
/// Parent brush to use
void Build(Brush* parentBrush);
///
/// Triangulate mesh
///
/// Result data
/// Cache data
/// True if cannot generate valid mesh data (due to missing triangles etc.)
bool Triangulate(RawData& data, Array& cacheVB) const;
///
/// Perform CSG operation with another mesh
///
/// Other mesh data to process
void PerformOperation(Mesh* other);
///
/// Add other mesh data
///
/// Other mesh to merge with
void Add(const Mesh* other);
private:
void intersect(const Mesh* other, PolygonOperation insideOp, PolygonOperation outsideOp);
void intersectSubMesh(const Mesh* other, int32 subMeshIndex, PolygonOperation insideOp, PolygonOperation outsideOp);
void updateBounds();
static void resolvePolygon(Polygon& polygon, PolygonOperation op);
void edgeSplit(int32 edgeIndex, const Vector3& vertex);
PolygonSplitResult polygonSplit(const Surface& cuttingPlane, int32 inputPolygonIndex, Polygon** outputPolygon);
void doPolygonsOperation(bool isInverted, bool visibility);
};
typedef Array MeshesArray;
};
#endif