Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Implemented descriptions on BSP trees

Signed-off-by: Martin Evans <martindevans@gmail.com>
  • Loading branch information...
commit 224ac5ab0fb87e3bb8dcdc8c423e325122cd73a1 1 parent bfb8c4a
@martindevans authored
View
1  csg.net/CsgTests/CsgTests.csproj
@@ -47,6 +47,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Bounds.cs" />
+ <Compile Include="Descriptions.cs" />
<Compile Include="Raycast.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
View
113 csg.net/CsgTests/Descriptions.cs
@@ -0,0 +1,113 @@
+using System;
+using System.Text;
+using System.Collections.Generic;
+using System.Linq;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Xna.Csg.Primitives;
+using Xna.Csg;
+
+namespace CsgTests
+{
+ [TestClass]
+ public class Descriptions
+ {
+ [TestMethod]
+ public void CubeDescription()
+ {
+ Cube c = new Cube();
+
+ Assert.AreEqual(1, c.Description.Count());
+ }
+
+ [TestMethod]
+ public void SphereDescription()
+ {
+ Sphere s = new Sphere(1);
+
+ Assert.AreEqual(2, s.Description.Count());
+ Assert.AreEqual("sphere", s.Description.First());
+ Assert.AreEqual(1, s.Description.Skip(1).First());
+ }
+
+ [TestMethod]
+ public void CylinderDescription()
+ {
+ Cylinder c = new Cylinder(3);
+
+ Assert.AreEqual(2, c.Description.Count());
+ Assert.AreEqual("cylinder", c.Description.First());
+ Assert.AreEqual(3, c.Description.Skip(1).First());
+ }
+
+ [TestMethod]
+ public void CloneCubeDescription()
+ {
+ BSP cube = new Cube();
+ BSP cube2 = cube.Clone();
+ Assert.IsTrue(cube.Description.Zip(cube2.Description, (a, b) => a.Equals(b)).Aggregate((a, b) => a & b));
+
+ BSP sphere = new Sphere(2);
+ Assert.IsFalse(sphere.Description.Zip(cube2.Description, (a, b) => a.Equals(b)).Aggregate((a, b) => a & b));
+ }
+
+ [TestMethod]
+ public void CloneCylinderDescription()
+ {
+ BSP cyl = new Cylinder(3);
+ BSP cyl2 = cyl.Clone();
+ Assert.AreEqual(cyl.Description.Count(), cyl2.Description.Count());
+ Assert.IsTrue(cyl.Description.Zip(cyl2.Description, (a, b) => a.Equals(b)).Aggregate((a, b) => a & b));
+ }
+
+ [TestMethod]
+ public void UnionDescription()
+ {
+ Cube cube = new Cube();
+ Cylinder cyl = new Cylinder(3);
+
+ var shape = cube.Clone();
+ shape.Union(cyl);
+
+ var desc = shape.Description.ToArray();
+ Assert.AreEqual(4, desc.Length);
+ Assert.AreEqual("union", desc[0]);
+ Assert.AreEqual("cube", desc[1]);
+ Assert.AreEqual("cylinder", desc[2]);
+ Assert.AreEqual(3, desc[3]);
+ }
+
+ [TestMethod]
+ public void IntersectionDescription()
+ {
+ Cube cube = new Cube();
+ Cylinder cyl = new Cylinder(3);
+
+ var shape = cube.Clone();
+ shape.Intersect(cyl);
+
+ var desc = shape.Description.ToArray();
+ Assert.AreEqual(4, desc.Length);
+ Assert.AreEqual("intersect", desc[0]);
+ Assert.AreEqual("cube", desc[1]);
+ Assert.AreEqual("cylinder", desc[2]);
+ Assert.AreEqual(3, desc[3]);
+ }
+
+ [TestMethod]
+ public void SubtractDescription()
+ {
+ Cube cube = new Cube();
+ Cylinder cyl = new Cylinder(3);
+
+ var shape = cube.Clone();
+ shape.Subtract(cyl);
+
+ var desc = shape.Description.ToArray();
+ Assert.AreEqual(4, desc.Length);
+ Assert.AreEqual("subtract", desc[0]);
+ Assert.AreEqual("cube", desc[1]);
+ Assert.AreEqual("cylinder", desc[2]);
+ Assert.AreEqual(3, desc[3]);
+ }
+ }
+}
View
55 csg.net/Xna.Csg/BSP.cs
@@ -9,48 +9,63 @@ namespace Xna.Csg
public class BSP
:ICsgProvider
{
+ object[] description;
+ public IEnumerable<object> Description
+ {
+ get
+ {
+ return description;
+ }
+ }
+
public event Action OnChange;
Node root;
-
public BoundingBox? Bounds
{
get;
private set;
}
-
- #region constructors
- public BSP()
- :this(new Node(), null)
+ public IEnumerable<Polygon> Polygons
{
+ get
+ {
+ return root.AllPolygons;
+ }
}
- public BSP(IEnumerable<Polygon> polygons)
- :this()
+ #region constructors
+ public BSP()
+ :this(new Node(), null, new object[0])
{
- root.Build(polygons);
- this.Bounds = MeasureBounds(this);
}
- public BSP(IEnumerable<Polygon> polygons, BoundingBox bounds)
+ protected BSP(IEnumerable<Polygon> polygons, BoundingBox bounds, object[] description)
: this()
{
root.Build(polygons);
this.Bounds = bounds;
+ this.description = description;
}
- private BSP(Node root, BoundingBox? bounds)
+ private BSP(Node root, BoundingBox? bounds, object[] description)
{
this.root = root;
this.Bounds = bounds;
+ this.description = description;
}
public BSP Clone()
{
- return new BSP(root.Clone(), Bounds);
+ return new BSP(root.Clone(), Bounds, description);
}
#endregion
+ private object[] CreateDescription(string operation, object[] existing, params object[] args)
+ {
+ return new object[] { operation }.Append(existing).Append(args).ToArray();
+ }
+
private BoundingBox? MeasureBounds(BSP bsp)
{
BoundingBox? b = null;
@@ -66,14 +81,6 @@ public BSP Clone()
return b;
}
- public IEnumerable<Polygon> Polygons
- {
- get
- {
- return root.AllPolygons;
- }
- }
-
public virtual BSP Transform(Matrix transformation)
{
BSP b = new BSP(
@@ -85,7 +92,9 @@ public virtual BSP Transform(Matrix transformation)
new Vertex(Vector3.Transform(v.Position, transformation), Vector3.TransformNormal(v.Normal, transformation))
)
)
- ), Bounds.Value.Transform(transformation)
+ ),
+ 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)
);
InvokeChange();
@@ -135,6 +144,7 @@ public virtual void Union(BSP bInput)
else
Bounds = bInput.Bounds;
+ description = CreateDescription("union", description, bInput.description);
InvokeChange();
}
@@ -154,6 +164,7 @@ public virtual void Subtract(BSP bInput)
Bounds = MeasureBounds(this);
+ description = CreateDescription("subtract", description, bInput.description);
InvokeChange();
}
@@ -193,6 +204,7 @@ public virtual void Intersect(BSP bInput)
else
Bounds = null;
+ description = CreateDescription("intersect", description, bInput.description);
InvokeChange();
}
@@ -201,6 +213,7 @@ public virtual void Clear()
root = new Node();
Bounds = null;
+ description = new object[0];
InvokeChange();
}
#endregion
View
28 csg.net/Xna.Csg/Extensions.cs
@@ -172,5 +172,33 @@ public static BoundingBox Transform(this BoundingBox bound, Matrix transform)
return b;
}
+
+ /// <summary>
+ /// enumerates the start and then the end
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="start">The start.</param>
+ /// <param name="end">The end.</param>
+ /// <returns></returns>
+ public static IEnumerable<T> Append<T>(this IEnumerable<T> start, IEnumerable<T> end)
+ {
+ foreach (var item in start)
+ yield return item;
+
+ foreach (var item in end)
+ yield return item;
+ }
+
+ /// <summary>
+ /// Appends the given items onto this enumeration
+ /// </summary>
+ /// <typeparam name="T"></typeparam>
+ /// <param name="start">The start.</param>
+ /// <param name="end">The end.</param>
+ /// <returns></returns>
+ public static IEnumerable<T> Append<T>(this IEnumerable<T> start, params T[] end)
+ {
+ return Append(start, end as IEnumerable<T>);
+ }
}
}
View
2  csg.net/Xna.Csg/Primitives/Cube.cs
@@ -10,7 +10,7 @@ public class Cube
: BSP
{
public Cube()
- :base(CreatePolygons(), new BoundingBox(new Vector3(-0.5f), new Vector3(0.5f)))
+ :base(CreatePolygons(), new BoundingBox(new Vector3(-0.5f), new Vector3(0.5f)), new object[] { "cube" })
{
}
View
2  csg.net/Xna.Csg/Primitives/Cylinder.cs
@@ -10,7 +10,7 @@ public class Cylinder
: BSP
{
public Cylinder(int rotations)
- : base(CreatePolygons(rotations + 2), new BoundingBox(new Vector3(-1f), new Vector3(1f)))
+ : base(CreatePolygons(rotations + 2), new BoundingBox(new Vector3(-1f), new Vector3(1f)), new object[] { "cylinder", rotations })
{
}
View
2  csg.net/Xna.Csg/Primitives/Sphere.cs
@@ -10,7 +10,7 @@ public class Sphere
: BSP
{
public Sphere(int subdivisions = 0)
- : base(Subdivide(CreatePolygons(), subdivisions), new BoundingBox(new Vector3(-1f), new Vector3(1f)))
+ : base(Subdivide(CreatePolygons(), subdivisions), new BoundingBox(new Vector3(-1f), new Vector3(1f)), new object[] { "sphere", subdivisions })
{
}
Please sign in to comment.
Something went wrong with that request. Please try again.