// 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