public Sphere(Vector position, double radius, MaterialFunc materialFunc) : base(materialFunc) { this.Position = position; this.Radius = radius; box = createBoundingBox(); }
public Triangle(Material material, params Vector[] vertices) : base(material) { if (vertices.Length != 3) { throw new ArgumentException(string.Format("Cannot construct triangle from {0} vertices", vertices.Length)); } else { this.Vertices = new Vector[3]; vertices.CopyTo(this.Vertices, 0); plane = new Plane(vertices, material); double test = vertices[0].Dot(plane.Normal) + plane.D; test = vertices[1].Dot(plane.Normal) + plane.D; test = vertices[2].Dot(plane.Normal) + plane.D; double x = test; bounds = new BoundingPlane[3]; Vector n; // get bounding plane containing v1, v0 // normal must be perpendicular to v1 - v0 n = plane.Normal.Cross(vertices[1] - vertices[0]); bounds[0].Normal = n; // shift plane so that v0 (thus also v1) lies in the plane bounds[0].d = -vertices[0].Dot(n); test = vertices[0].Dot(bounds[0].Normal) + bounds[0].d; test = vertices[1].Dot(bounds[0].Normal) + bounds[0].d; // make plane positive side face inside of the triangle if (vertices[2].Dot(n) + bounds[0].d < 0) bounds[0].Invert(); n = plane.Normal.Cross(vertices[2] - vertices[1]); bounds[1].Normal = n; bounds[1].d = -vertices[1].Dot(n); test = vertices[2].Dot(bounds[1].Normal) + bounds[1].d; test = vertices[1].Dot(bounds[1].Normal) + bounds[1].d; if (vertices[0].Dot(n) + bounds[1].d < 0) bounds[1].Invert(); n = plane.Normal.Cross(vertices[0] - vertices[2]); bounds[2].Normal = n; bounds[2].d = -vertices[2].Dot(n); test = vertices[0].Dot(bounds[2].Normal) + bounds[2].d; test = vertices[2].Dot(bounds[2].Normal) + bounds[2].d; if (vertices[1].Dot(n) + bounds[2].d < 0) bounds[2].Invert(); double y = test; box = createBoundingBox(); } }
public bool Intersects(BoundingBox other) { if (this == BoundingBox.Infinite || other == BoundingBox.Infinite) return true; // we are likely to pass all tests and intersect if the boxes are real close double e = Constants.Epsilon*10; // try to find a separating plane, do it for all 6 planes if (this.LeftTopFront.X - e > other.RightBottomBack.X) return false; if (this.RightBottomBack.X + e < other.LeftTopFront.X) return false; if (this.LeftTopFront.Y - e > other.RightBottomBack.Y) return false; if (this.RightBottomBack.Y + e < other.LeftTopFront.Y) return false; if (this.LeftTopFront.Z - e > other.RightBottomBack.Z) return false; if (this.RightBottomBack.Z + e < other.LeftTopFront.Z) return false; // cannot separate -> they intersect return true; }
/// <summary> /// Splits node's primitives into 8 new children nodes. /// </summary> private void split() { if (boundingBox == null) throw new Exception("Cannot split null bounding box"); try { this.childs = new OctreeNode[8]; for (int i = 0; i < 8; i++) { childs[i] = new OctreeNode(); childs[i].boundingBox = new BoundingBox(new Vector(), new Vector()); } double dx2 = (boundingBox.RightBottomBack.X - boundingBox.LeftTopFront.X) / 2; double dy2 = (boundingBox.RightBottomBack.Y - boundingBox.LeftTopFront.Y) / 2; double dz2 = (boundingBox.RightBottomBack.Z - boundingBox.LeftTopFront.Z) / 2; childs[0].boundingBox.LeftTopFront = boundingBox.LeftTopFront; childs[1].boundingBox.LeftTopFront = boundingBox.LeftTopFront + new Vector(dx2, 0, 0); childs[2].boundingBox.LeftTopFront = boundingBox.LeftTopFront + new Vector(0, dy2, 0); childs[3].boundingBox.LeftTopFront = boundingBox.LeftTopFront + new Vector(dx2, dy2, 0); childs[4].boundingBox.LeftTopFront = boundingBox.LeftTopFront + new Vector(0, 0, dz2); childs[5].boundingBox.LeftTopFront = boundingBox.LeftTopFront + new Vector(dx2, 0, dz2); childs[6].boundingBox.LeftTopFront = boundingBox.LeftTopFront + new Vector(0, dy2, dz2); childs[7].boundingBox.LeftTopFront = boundingBox.LeftTopFront + new Vector(dx2, dy2, dz2); Vector sizeVector = new Vector(dx2, dy2, dz2); // all childs same size for (int i = 0; i < 8; i++) { childs[i].boundingBox.RightBottomBack = childs[i].boundingBox.LeftTopFront + sizeVector; } // distribute primitives into children foreach (Primitive primitive in primitives) { // primitive may fall into multiple children at the same time // ideally it will fall in only 1 child for (int i = 0; i < 8; i++) { if (primitive.BoundingBox.Intersects(childs[i].boundingBox)) { childs[i].Add(primitive); } } } primitives = null; } catch { // in case of exception clean up any inconsistencies this.childs = null; this.boundingBox = BoundingBox.Zero; throw; } }
public BoxPrimitive(Vector leftTopFront, Vector rightBottomBack, MaterialFunc matFunc) : base(matFunc) { box = new BoundingBox(leftTopFront, rightBottomBack); center = Vector.Combine(leftTopFront, 1.0, (rightBottomBack - leftTopFront), 0.5); }
/// <summary> /// Returns whether bounding box is relatively large to reference bouding box. /// </summary> private bool isBigBoundingBox(BoundingBox tested, BoundingBox reference) { double threshold = 4; Vector extent = tested.RightBottomBack - tested.LeftTopFront; Vector referenceExtent = reference.RightBottomBack - reference.LeftTopFront; // any dimension large enough return extent.X * threshold > referenceExtent.X || extent.Y * threshold > referenceExtent.Y || extent.Z * threshold > referenceExtent.Z; }