コード例 #1
0
ファイル: Sphere.cs プロジェクト: mkonicek/raytracer
 public Sphere(Vector position, double radius, MaterialFunc materialFunc)
     : base(materialFunc)
 {
     this.Position = position;
     this.Radius = radius;
     box = createBoundingBox();
 }
コード例 #2
0
ファイル: Triangle.cs プロジェクト: mkonicek/raytracer
        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();
            }
        }
コード例 #3
0
ファイル: BoundingBox.cs プロジェクト: mkonicek/raytracer
        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;
        }
コード例 #4
0
ファイル: OctreeNode.cs プロジェクト: mkonicek/raytracer
        /// <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;
            }
        }
コード例 #5
0
ファイル: BoxPrimitive.cs プロジェクト: mkonicek/raytracer
 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);
 }
コード例 #6
0
ファイル: Octree.cs プロジェクト: mkonicek/raytracer
        /// <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;
        }