Skip to content

Commit

Permalink
tmp
Browse files Browse the repository at this point in the history
  • Loading branch information
nicklockwood committed Dec 22, 2023
1 parent 93d3335 commit f9105ba
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 33 deletions.
4 changes: 4 additions & 0 deletions Example/SceneKitViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ class SceneKitViewController: UIViewController {
// let sphere = Mesh.sphere(slices: 120, material: UIColor.blue)
// let mesh = cube.subtracting(sphere).makeWatertight()

// let cube = Mesh.cube().inverted()
// let cube2 = Mesh.cube().inverted().translated(by: Vector(0.5, 0.5, 0.5))
// let mesh = cube.union(cube2).inverted()

// print("Time:", CFAbsoluteTimeGetCurrent() - start)
// print("Polygons:", mesh.polygons.count)
// print("Triangles:", mesh.triangulate().polygons.count)
Expand Down
15 changes: 10 additions & 5 deletions Sources/BSP.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,14 @@ extension BSP {
}

init(_ mesh: Mesh, _ isCancelled: CancellationHandler) {
self.init(mesh.polygons, isConvex: mesh.isKnownConvex, isCancelled)
}

init(_ polygons: [Polygon], isConvex: Bool, _ isCancelled: CancellationHandler) {
self.nodes = [BSPNode]()
self.isConvex = mesh.isKnownConvex
self.isConvex = isConvex
self.isInverted = false
initialize(mesh.polygons, isCancelled)
initialize(polygons, isCancelled)
}

func clip(
Expand Down Expand Up @@ -138,12 +142,13 @@ private extension BSP {
}

mutating func initialize(_ polygons: [Polygon], _ isCancelled: CancellationHandler) {
guard !polygons.isEmpty else {
return
}

var rng = DeterministicRNG()

guard isConvex else {
guard !polygons.isEmpty else {
return
}
let startPlane = polygons[0].plane
// Randomly shuffle polygons to reduce average number of splits
let polygons = polygons.shuffled(using: &rng)
Expand Down
104 changes: 77 additions & 27 deletions Sources/Mesh+CSG.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,40 @@ public extension Mesh {
/// - Returns: A new mesh representing the union of the input meshes.
func union(_ mesh: Mesh, isCancelled: CancellationHandler = { false }) -> Mesh {
let intersection = bounds.intersection(mesh.bounds)
if intersection.isEmpty {
let absp = getBSP(isCancelled), bbsp = mesh.getBSP(isCancelled)
switch (absp.isInverted, bbsp.isInverted) {
case (false, false):
if intersection.isEmpty {
return Mesh(
unchecked: polygons + mesh.polygons,
bounds: bounds.union(mesh.bounds),
isConvex: false,
isWatertight: watertightIfSet.flatMap { isWatertight in
mesh.watertightIfSet.map { $0 && isWatertight }
},
submeshes: [self, mesh]
)
}
var lhs: [Polygon] = [], rhs: [Polygon] = []
inParallel({
var aout: [Polygon]? = []
let ap = BSP(mesh, isCancelled).clip(
boundsTest(intersection, polygons, &aout),
.greaterThan,
isCancelled
)
lhs = aout! + ap
}, {
var bout: [Polygon]? = []
let bp = BSP(self, isCancelled).clip(
boundsTest(intersection, mesh.polygons, &bout),
.greaterThanEqual,
isCancelled
)
rhs = bout! + bp
})
return Mesh(
unchecked: polygons + mesh.polygons,
unchecked: lhs + rhs,
bounds: bounds.union(mesh.bounds),
isConvex: false,
isWatertight: watertightIfSet.flatMap { isWatertight in
Expand All @@ -66,32 +97,47 @@ public extension Mesh {
mesh.submeshesIfEmpty.map { _ in [self, mesh] }
}
)
}
var lhs: [Polygon] = [], rhs: [Polygon] = []
inParallel({
var aout: [Polygon]? = []
let ap = BSP(mesh, isCancelled).clip(
boundsTest(intersection, polygons, &aout),
case (true, true):
if intersection.isEmpty {
return .empty
}
var out: [Polygon]?
let ap = bbsp.clip(
boundsTest(intersection, polygons, &out),
.greaterThan,
isCancelled
)
lhs = aout! + ap
}, {
var bout: [Polygon]? = []
let bp = BSP(self, isCancelled).clip(
boundsTest(intersection, mesh.polygons, &bout),
let bp = absp.clip(
boundsTest(intersection, mesh.polygons, &out),
.greaterThanEqual,
isCancelled
)
rhs = bout! + bp
})
return Mesh(
unchecked: lhs + rhs,
bounds: bounds.union(mesh.bounds),
isConvex: false,
isWatertight: nil,
submeshes: nil // TODO: can this be preserved?
)
return Mesh(
unchecked: ap + bp,
bounds: bounds.union(mesh.bounds),
isConvex: false,
isWatertight: nil,
submeshes: nil // TODO: can this be preserved?
)
default:
let ap = bbsp.clip(
polygons,
.greaterThan,
isCancelled
)
let bp = absp.clip(
mesh.polygons,
.greaterThanEqual,
isCancelled
)
return Mesh(
unchecked: ap + bp,
bounds: bounds.union(mesh.bounds),
isConvex: false,
isWatertight: nil,
submeshes: nil // TODO: can this be preserved?
)
}
}

/// Efficiently forms a union from multiple meshes.
Expand Down Expand Up @@ -210,7 +256,6 @@ public extension Mesh {
let (bp2, bp1) = absp.split(bp, .greaterThan, .lessThan, isCancelled)
rhs = bout! + bp2 + bp1.inverted()
})

return Mesh(
unchecked: lhs + rhs,
bounds: nil, // TODO: is there a way to efficiently preserve this?
Expand Down Expand Up @@ -337,7 +382,7 @@ public extension Mesh {
}
var aout: [Polygon]? = []
let ap = boundsTest(bounds.intersection(mesh.bounds), polygons, &aout)
let bsp = BSP(mesh, isCancelled)
let bsp = mesh.getBSP(isCancelled)
let (outside, inside) = bsp.split(ap, .greaterThan, .lessThanEqual, isCancelled)
let material = mesh.polygons.first?.material
return Mesh(
Expand Down Expand Up @@ -408,11 +453,16 @@ public extension Mesh {

/// Clip mesh to the specified plane and optionally fill sheared faces with specified material.
/// - Parameters
/// - plane: The plane to clip the mesh to
/// - fill: The material to fill the sheared face(s) with.
/// - plane: The plane to clip the mesh against.
/// - fill: Optional material to fill the sheared face(s) with.
/// - isCancelled: Callback used to cancel the operation.
///
/// > Note: Specifying nil for the fill material will leave the sheared face unfilled.
func clip(to plane: Plane, fill: Material? = nil) -> Mesh {
func clip(
to plane: Plane,
fill: Material? = nil,
isCancelled: CancellationHandler = { false }
) -> Mesh {
guard !polygons.isEmpty else {
return self
}
Expand Down
19 changes: 18 additions & 1 deletion Sources/Mesh.swift
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ public extension Mesh {
/// - Returns: `true` if the point lies inside the mesh, and `false` otherwise.
func containsPoint(_ point: Vector) -> Bool {
guard isKnownConvex else {
return BSP(self) { false }.containsPoint(point)
return storage.getBSP { false }.containsPoint(point)
}
if !bounds.containsPoint(point) {
return false
Expand Down Expand Up @@ -386,11 +386,16 @@ extension Mesh {

var boundsIfSet: Bounds? { storage.boundsIfSet }
var watertightIfSet: Bool? { storage.watertightIfSet }
var bspIfSet: Bool? { storage.watertightIfSet }
var isKnownConvex: Bool { storage.isConvex }
/// Note: we don't expose submeshesIfSet because it's unsafe to reuse
var submeshesIfEmpty: [Mesh]? {
storage.submeshesIfSet.flatMap { $0.isEmpty ? [] : nil }
}

func getBSP(_ isCancelled: CancellationHandler) -> BSP {
storage.getBSP(isCancelled)
}
}

private extension Mesh {
Expand Down Expand Up @@ -437,6 +442,18 @@ private extension Mesh {
return watertightIfSet!
}

private(set) var bspIfSet: BSP?
func getBSP(_ isCancelled: CancellationHandler) -> BSP {
var bsp = bspIfSet
if bsp == nil {
bsp = BSP(polygons, isConvex: isConvex, isCancelled)
if !isCancelled() {
bspIfSet = bsp
}
}
return bsp!
}

private(set) var submeshesIfSet: [Mesh]?
var submeshes: [Mesh] {
if submeshesIfSet == nil {
Expand Down

0 comments on commit f9105ba

Please sign in to comment.