public void Subtract(BSP brush) { DoCsgOperation(brush, (b, world) => { world.Subtract(b); }); }
public void Intersect(BSP brush) { DoCsgOperation(brush, (b, world) => { world.Intersect(b); }); }
public void Union(BSP brush) { DoCsgOperation(brush, (b, world) => { world.Union(b); }); }
private BoundingBox? MeasureBounds(BSP bsp) { BoundingBox? b = null; foreach (var position in bsp.Polygons.SelectMany(a => a.Vertices).Select(a => a.Position)) { if (b.HasValue) b.Value.IncludePoint(position); else b = new BoundingBox(position, position); } return b; }
private void DoCsgOperation(BSP brush, Action<BSP, BSP> action) { var brushClone = brush.Clone(); while (!brush.Polygons.IsEmpty()) { //Get the subspace which contains this polygon var subSpace = GetSpace(brush.Vertices.First().Position); //Make a new brush which only fits into this subspace var clone = brushClone.Clone(); subSpace.ClipToBounds(clone); //Remove brush for this subspace from overall brush brushClone.Subtract(clone); //Do the action with the brush which fits in this space and the space itself action(clone, subSpace.BSP); } }
public virtual BSP Transform(Matrix transformation) { var polys = _root.AllPolygons.Select(a => new Polygon(a.Vertices.Select(v => v.Clone().Transform(transformation)))); BSP b = new BSP( polys, Bounds.Value.Transform(transformation), CreateDescription("transform", _description, transformation.M11, transformation.M12, transformation.M13, transformation.M14, transformation.M21, transformation.M22, transformation.M23, transformation.M24, transformation.M31, transformation.M32, transformation.M33, transformation.M34, transformation.M41, transformation.M42, transformation.M43, transformation.M44) ); return b; }
public virtual void Split(out BSP topLeftFront, out BSP topLeftBack, out BSP topRightBack, out BSP topRightFront, out BSP bottomLeftFront, out BSP bottomLeftBack, out BSP bottomRightBack, out BSP bottomRightFront, Func<Vector3, Vector3, Vertex> vertexFactory = null) { if (!Bounds.HasValue) throw new InvalidOperationException("Cannot split a BSP tree without bounds"); vertexFactory = vertexFactory ?? ((p, n) => new Vertex(p, n)); var bounds = Bounds.Value; var size = (bounds.Max - bounds.Min); float halfWidth = size.X / 2; float halfHeight = size.Y / 2; float halfDepth = size.Z / 2; float qtrWidth = halfWidth / 2; float qtrHeight = halfHeight / 2; float qtrDepth = halfDepth / 2; topLeftFront = new Cube(vertexFactory).Transform(Matrix.CreateScale(halfWidth, halfHeight, halfDepth) * Matrix.CreateTranslation(-qtrWidth, qtrHeight, -qtrDepth)); topLeftFront.Intersect(this); topLeftBack = new Cube(vertexFactory).Transform(Matrix.CreateScale(halfWidth, halfHeight, halfDepth) * Matrix.CreateTranslation(-qtrWidth, qtrHeight, qtrDepth)); topLeftBack.Intersect(this); topRightFront = new Cube(vertexFactory).Transform(Matrix.CreateScale(halfWidth, halfHeight, halfDepth) * Matrix.CreateTranslation(qtrWidth, qtrHeight, -qtrDepth)); topRightFront.Intersect(this); topRightBack = new Cube(vertexFactory).Transform(Matrix.CreateScale(halfWidth, halfHeight, halfDepth) * Matrix.CreateTranslation(qtrWidth, qtrHeight, qtrDepth)); topRightBack.Intersect(this); bottomLeftFront = new Cube(vertexFactory).Transform(Matrix.CreateScale(halfWidth, halfHeight, halfDepth) * Matrix.CreateTranslation(-qtrWidth, -qtrHeight, -qtrDepth)); bottomLeftFront.Intersect(this); bottomLeftBack = new Cube(vertexFactory).Transform(Matrix.CreateScale(halfWidth, halfHeight, halfDepth) * Matrix.CreateTranslation(-qtrWidth, -qtrHeight, qtrDepth)); bottomLeftBack.Intersect(this); bottomRightFront = new Cube(vertexFactory).Transform(Matrix.CreateScale(halfWidth, halfHeight, halfDepth) * Matrix.CreateTranslation(qtrWidth, -qtrHeight, -qtrDepth)); bottomRightFront.Intersect(this); bottomRightBack = new Cube(vertexFactory).Transform(Matrix.CreateScale(halfWidth, halfHeight, halfDepth) * Matrix.CreateTranslation(qtrWidth, -qtrHeight, qtrDepth)); bottomRightBack.Intersect(this); }
public virtual void Intersect(BSP bInput) { if (!_root.AllPolygons.Any()) return; var a = this._root; var b = bInput._root.Clone(null); a.Invert(); b.ClipTo(a); b.Invert(); a.ClipTo(b); b.ClipTo(a); a.Build(b.AllPolygons); a.Invert(); if (Bounds.HasValue) { if (bInput.Bounds.HasValue) { Bounds = new BoundingBox( new Vector3( Math.Max(Bounds.Value.Min.X, bInput.Bounds.Value.Min.X), Math.Max(Bounds.Value.Min.Y, bInput.Bounds.Value.Min.Y), Math.Max(Bounds.Value.Min.Z, bInput.Bounds.Value.Min.Z) ), new Vector3( Math.Min(Bounds.Value.Max.X, bInput.Bounds.Value.Max.X), Math.Min(Bounds.Value.Max.Y, bInput.Bounds.Value.Max.Y), Math.Min(Bounds.Value.Max.Z, bInput.Bounds.Value.Max.Z) ) ); } else Bounds = null; } else Bounds = null; _description = CreateDescription("intersect", _description, bInput._description); }
public virtual void Subtract(BSP bInput) { if (!_root.AllPolygons.Any()) return; var a = this._root; var b = bInput._root.Clone(null); a.Invert(); a.ClipTo(b); b.ClipTo(a); b.Invert(); b.ClipTo(a); b.Invert(); a.Build(b.AllPolygons); a.Invert(); Bounds = MeasureBounds(this); _description = CreateDescription("subtract", _description, bInput._description); }
public virtual void Union(BSP bInput) { var a = _root; var b = bInput._root.Clone(null); a.ClipTo(b); b.ClipTo(a); b.Invert(); b.ClipTo(a); b.Invert(); a.Build(b.AllPolygons); if (Bounds.HasValue) { if (bInput.Bounds.HasValue) { Bounds = new BoundingBox( new Vector3( Math.Min(Bounds.Value.Min.X, bInput.Bounds.Value.Min.X), Math.Min(Bounds.Value.Min.Y, bInput.Bounds.Value.Min.Y), Math.Min(Bounds.Value.Min.Z, bInput.Bounds.Value.Min.Z) ), new Vector3( Math.Max(Bounds.Value.Max.X, bInput.Bounds.Value.Max.X), Math.Max(Bounds.Value.Max.Y, bInput.Bounds.Value.Max.Y), Math.Max(Bounds.Value.Max.Z, bInput.Bounds.Value.Max.Z) ) ); } else Bounds = Bounds; } else Bounds = bInput.Bounds; _description = CreateDescription("union", _description, bInput._description); }
public void ClipToBounds(BSP clone) { Vector3 center = new Vector3(MinX * 0.5f + MaxX * 0.5f, MinY * 0.5f + MaxY * 0.5f, MinZ * 0.5f + MaxZ * 0.5f); clone.Intersect(new Cube().Transform(Matrix.CreateScale(Size) * Matrix.CreateTranslation(center.X, center.Y, center.Z))); }
public SubSpace(int x, int y, int z, int size) { BSP = new BSP(); MinX = x; MinY = y; MinZ = z; MaxX = x + size; MaxY = y + size; MaxZ = z + size; Size = size; }
public static float?Intersects(this Ray ray, BSP bsp) { return(bsp.RayCast(ray)); }