コード例 #1
0
ファイル: PointLight.cs プロジェクト: mkonicek/raytracer
 public PointLight(Vector pos, Color color, double value)
     : base(pos, color, value)
 {
     this.Pos = pos;
     this.Color = color;
     this.Value = value;
 }
コード例 #2
0
ファイル: Sphere.cs プロジェクト: mkonicek/raytracer
 public Sphere(Vector position, double radius, MaterialFunc materialFunc)
     : base(materialFunc)
 {
     this.Position = position;
     this.Radius = radius;
     box = createBoundingBox();
 }
コード例 #3
0
ファイル: BoundingBox.cs プロジェクト: mkonicek/raytracer
        public BoundingBox(Vector leftTopFront, Vector rightBottomBack)
        {
            if (!leftTopFront.SmallerAllCoordsThan(rightBottomBack))
                throw new Exception("Box specified incorrectly");

            this.LeftTopFront = leftTopFront;
            this.RightBottomBack = rightBottomBack;
        }
コード例 #4
0
ファイル: Primitive.cs プロジェクト: mkonicek/raytracer
 /// <summary>
 /// Returns material at given point.
 /// </summary>
 /// <param name="v">Point in space.</param>
 public Material GetMaterialAt(Vector v)
 {
     if (this.materialFunc == null)
     {
         return this.material;
     }
     else
     {
         return materialFunc(v);
     }
 }
コード例 #5
0
ファイル: Plane.cs プロジェクト: mkonicek/raytracer
        private void initFromVertices(Vector[] vertices)
        {
            if (vertices.Length < 3)
            {
                throw new ArgumentException("Cannot construct plane from less than 3 vertices.");
            }

            Vector v1, v2;
            v1 = vertices[1] - vertices[0];
            v2 = vertices[2] - vertices[0];
            this.Normal = v1.Cross(v2);
            this.Normal.Normalize();
            // from plane equation by inserting vertices[0] (or [1] or [2])
            this.D = -vertices[0].Dot(this.Normal);
        }
コード例 #6
0
ファイル: BoxPrimitive.cs プロジェクト: mkonicek/raytracer
 public override Vector GetNormalAt(Vector v)
 {
     // determine to which side "center to v" points
     Vector outwards = v - center;
     // transform to [1x1x1] cube
     outwards.X /= (box.RightBottomBack.X - box.LeftTopFront.X);
     outwards.Y /= (box.RightBottomBack.Y - box.LeftTopFront.Y);
     outwards.Z /= (box.RightBottomBack.Z - box.LeftTopFront.Z);
     double absX = Math.Abs(outwards.X);
     double absY = Math.Abs(outwards.Y);
     double absZ = Math.Abs(outwards.Z);
     double maxCoord = Math.Max(absX, Math.Max(absY, absZ));
     if (maxCoord == absX)
         return outwards.X < 0 ? vLeft : vRight;
     else if (maxCoord == absY)
         return outwards.Y < 0 ? vUp : vDown;
     else
         return outwards.Z < 0 ? vBack : vForward;
 }
コード例 #7
0
ファイル: Sphere.cs プロジェクト: mkonicek/raytracer
 public override Vector GetNormalAt(Vector v)
 {
     Vector n = v - this.Position;
     // normalize (divide by radius)
     n.Mul(1.0 / Radius);
     return n/* + new Vector(Math.Sin(v.X*v.Y * 15) * 0.05, Math.Cos(v.Z * 12) * 0.05, Math.Cos(v.Y * 8)*0.08)*/;
 }
コード例 #8
0
ファイル: Plane.cs プロジェクト: mkonicek/raytracer
 public Plane(Vector[] vertices, MaterialFunc materialFunc)
     : base(materialFunc)
 {
     initFromVertices(vertices);
 }
コード例 #9
0
ファイル: Light.cs プロジェクト: mkonicek/raytracer
 public Light(Vector pos, Color color, double value)
 {
     this.Pos = pos;
     this.Color = color;
     this.Value = value;
 }
コード例 #10
0
ファイル: Triangle.cs プロジェクト: mkonicek/raytracer
        private BoundingBox createBoundingBox()
        {
            double x = Math.Min(Vertices[0].X, Math.Min(Vertices[1].X, Vertices[2].X));
            double y = Math.Min(Vertices[0].Y, Math.Min(Vertices[1].Y, Vertices[2].Y));
            double z = Math.Min(Vertices[0].Z, Math.Min(Vertices[1].Z, Vertices[2].Z));
            Vector leftUpFront = new Vector(x, y, z);

            x = Math.Max(Vertices[0].X, Math.Max(Vertices[1].X, Vertices[2].X));
            y = Math.Max(Vertices[0].Y, Math.Max(Vertices[1].Y, Vertices[2].Y));
            z = Math.Max(Vertices[0].Z, Math.Max(Vertices[1].Z, Vertices[2].Z));

            return new BoundingBox(leftUpFront - new Vector(Constants.Epsilon, Constants.Epsilon, Constants.Epsilon),
                new Vector(x + Constants.Epsilon, y + Constants.Epsilon, z + Constants.Epsilon));
        }
コード例 #11
0
ファイル: Vector.cs プロジェクト: mkonicek/raytracer
 /// <summary>
 /// Cross product.
 /// </summary>
 public Vector Cross(Vector v)
 {
     return new Vector(Y * v.Z - Z * v.Y, Z * v.X - X * v.Z, X * v.Y - Y * v.X);
 }
コード例 #12
0
ファイル: Vector.cs プロジェクト: mkonicek/raytracer
 /// <summary>
 /// Linear combination.
 /// </summary>
 public static Vector Combine(Vector v1, double t1, Vector v2, double t2)
 {
     return new Vector(v1.X * t1 + v2.X * t2, v1.Y * t1 + v2.Y * t2, v1.Z * t1 + v2.Z * t2);
 }
コード例 #13
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;
            }
        }
コード例 #14
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);
 }
コード例 #15
0
ファイル: Matrix.cs プロジェクト: mkonicek/raytracer
 /// <summary>
 /// Multiplies vector by matrix including translation.
 /// </summary>
 public static Vector operator *(Matrix m, Vector v)
 {
     Vector result = new Vector();
     // calc result vector coordinates
     for (int i = 0; i < 3; i++)
     {
         for (int j = 0; j < 3; j++)
         {
             result[i] += m[i, j] * v[j];
         }
         // add translation, we suppose that 4th coord of the vector is always 1
         result[i] += m[i, 3];
     }
     return result;
 }
コード例 #16
0
ファイル: Primitive.cs プロジェクト: mkonicek/raytracer
 /// <summary>
 /// Returns surface normal at given point.
 /// </summary>
 /// <param name="v">Point in space.</param>
 public abstract Vector GetNormalAt(Vector v);
コード例 #17
0
ファイル: Triangle.cs プロジェクト: mkonicek/raytracer
 public override Vector GetNormalAt(Vector v)
 {
     return plane.Normal/* + new Vector(Math.Sin(v.x * 8) * 0.05, Math.Cos(v.z * 8) * 0.05, 0)*/;
 }
コード例 #18
0
ファイル: Vector.cs プロジェクト: mkonicek/raytracer
 /// <summary>
 /// Dot product.
 /// </summary>
 public double Dot(Vector v)
 {
     return X * v.X + Y * v.Y + Z * v.Z;
 }
コード例 #19
0
ファイル: Triangle.cs プロジェクト: mkonicek/raytracer
 /// <summary>
 /// Tells if given vector lies on negative side of this plane.
 /// </summary>
 internal bool liesOnNegativeSide(ref Vector v)
 {
     return (Normal.Dot(v) + d < -Constants.Epsilon);
 }
コード例 #20
0
ファイル: Vector.cs プロジェクト: mkonicek/raytracer
 /// <summary>
 /// Returns true if all coords of this vector are smaller than corresponding v coords.
 /// </summary>
 public bool SmallerAllCoordsThan(Vector v)
 {
     return this.X <= v.X && this.Y <= v.Y && this.Z <= v.Z;
 }
コード例 #21
0
ファイル: Plane.cs プロジェクト: mkonicek/raytracer
 public Plane(Vector normal, double d, MaterialFunc materialFunc)
     : base(materialFunc)
 {
     this.Normal = normal;
     this.D = d;
 }
コード例 #22
0
ファイル: Vector.cs プロジェクト: mkonicek/raytracer
 /// <summary>
 /// Returns true if any coord of this vector is smaller than corresponding v coord.
 /// </summary>
 public bool SmallerAnyCoordThan(Vector v)
 {
     return this.X <= v.X || this.Y <= v.Y || this.Z <= v.Z;
 }
コード例 #23
0
ファイル: Plane.cs プロジェクト: mkonicek/raytracer
 public override Vector GetNormalAt(Vector v)
 {
     return this.Normal;
 }
コード例 #24
0
ファイル: BoundingBox.cs プロジェクト: mkonicek/raytracer
 public bool Contains(Vector v)
 {
     return (v.X > LeftTopFront.X && v.X < RightBottomBack.X) &&
            (v.Y > LeftTopFront.Y && v.Y < RightBottomBack.Y) &&
            (v.Z > LeftTopFront.X && v.Z < RightBottomBack.Z);
 }
コード例 #25
0
ファイル: Scene.cs プロジェクト: mkonicek/raytracer
        /// <summary>
        /// Gets lightness and specular ligthness at given point in the scene.
        /// </summary>
        /// <param name="specularLightness">Returned specular lightness.</param>
        /// <param name="pos">Point in space where to calc ligthness.</param>
        /// <param name="reflectionDir">Direction of reflection.</param>
        /// <param name="normalDir">Direction of normal.</param>
        /// <param name="surfaceSpecular">Specular of the material.</param>
        /// <returns></returns>
        private Color lightColorAt(Vector pos, out double specularLightness, Vector vReflection, Vector normal, double surfaceSpecular)
        {
            Ray shadowRay = new Ray();
            shadowRay.Origin = pos;
            Color result = Color.Black;
            specularLightness = 0.0;

            foreach (Light light in this.lights)
            {
                int visibleRayCount = 0;

                // test all rays to this light
                for (int i = 0; i < light.GetRayCount(); i++)
                {
                    shadowRay.Direction = light.GetNextRaySource() - shadowRay.Origin;
                    // only front sides get lit
                    if (shadowRay.Direction.Dot(normal) >= Constants.Epsilon)
                    {
                        double isectDistance = 0;
                        objects.GetClosestIntersection(ref shadowRay, out isectDistance);
                        //double isectDistance2 = isectDistance * isectDistance;
                        //light visible from pos?
                        //if (!(isectDistance2 > Constants.Epsilon && isectDistance2 < shadowRay.Direction.LenSquared - Constants.Epsilon))
                        double lightDist2 = shadowRay.Direction.LenSquared;
                        shadowRay.Direction.Normalize();
                        if (!(isectDistance > Constants.Epsilon && isectDistance*isectDistance < lightDist2 - Constants.Epsilon))
                        {
                            visibleRayCount++;

                            Vector reflectionNorm = vReflection;
                            reflectionNorm.Normalize();

                            // is reflected ray pointing towards light?
                            double specularDot = reflectionNorm.Dot(shadowRay.Direction);
                            if (specularDot > -Constants.Epsilon)
                            {
                                specularDot *= specularDot;
                                specularDot *= specularDot;
                                specularDot *= specularDot;
                                specularDot *= specularDot;
                                specularDot *= specularDot; // ^32

                                specularLightness += specularDot;
                            }

                        }
                    }
                }
                result = Color.Combine(result, 1.0, light.Color,
                     visibleRayCount / (double)light.GetRayCount() * light.Value * shadowRay.Direction.Dot(normal));
            }

            specularLightness *= surfaceSpecular;
            return result;
        }
コード例 #26
0
ファイル: Scenes.cs プロジェクト: mkonicek/raytracer
 private static void addSphereGrid(ScnFile file, int xs, int ys, int zs)
 {
     Material mat = getRandMaterial();
     file.Materials.Add(mat);
     // real dimensions
     double xw = 8; double yw = 8; double zw = 8;
     for (int x = 0; x < xs; x++)
     {
         for (int y = 0; y < ys; y++)
         {
             for (int z = 0; z < zs; z++)
             {
                 Vector center = new Vector(-4 + x / (double)xs * xw,
                                -4 + y / (double)ys * yw,
                                2 + z / (double)zs * zw);
                 file.Primitives.Add(new Sphere(center, 0.05/*rand(0.06, 0.16)*/,
                     mat));
             }
         }
     }
 }