Пример #1
0
 public void Subtract(BSP brush)
 {
     DoCsgOperation(brush, (b, world) =>
     {
         world.Subtract(b);
     });
 }
Пример #2
0
 public void Intersect(BSP brush)
 {
     DoCsgOperation(brush, (b, world) =>
     {
         world.Intersect(b);
     });
 }
Пример #3
0
 public void Union(BSP brush)
 {
     DoCsgOperation(brush, (b, world) =>
         {
             world.Union(b);
         });
 }
Пример #4
0
        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;
        }
Пример #5
0
        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);
            }
        }
Пример #6
0
        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;
        }
Пример #7
0
        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);
        }
Пример #8
0
        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);
        }
Пример #9
0
        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);
        }
Пример #10
0
        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);
        }
Пример #11
0
            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)));
            }
Пример #12
0
            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;
            }
Пример #13
0
 public static float?Intersects(this Ray ray, BSP bsp)
 {
     return(bsp.RayCast(ray));
 }
Пример #14
0
            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)));
            }