Ejemplo n.º 1
0
        public Ray GenerateRay(LocalGeo geo, out RTColor color)
        {
            color = Color;
            RTVector ray = Source - geo.Point;

            return(new Ray(geo.Point, ray.Normalize(), 1e-3f, ray.Length, false));
        }
Ejemplo n.º 2
0
        public void MoveCamera(RTPoint lookFrom, RTPoint lookAt, RTVector up)
        {
            Eye = new RTPoint(lookFrom);

            W = (lookFrom - lookAt).Normalize();
            U = RTVector.CrossProduct(up, W).Normalize();
            V = RTVector.CrossProduct(W, U);
        }
Ejemplo n.º 3
0
 public Vertex(RTPoint vertex, RTVector normal)
 {
     Location = vertex;
     if (normal != null)
     {
         Normal = new Normal(normal);
     }
 }
Ejemplo n.º 4
0
        public Ray GenerateRay(RTPoint p)
        {
            float alpha = (float)Math.Tan(FovX / 2.0f) * ((p.X - (Width / 2.0f)) / (Width / 2.0f));
            float beta  = (float)Math.Tan(FovY / 2.0f) * (((Height / 2.0f) - p.Y) / (Height / 2.0f));

            RTVector rayVec = new RTVector(alpha * U + beta * V - W).Normalize();

            return(new Ray(Eye, rayVec, 0, float.MaxValue, false));
        }
Ejemplo n.º 5
0
        public Camera(RTPoint lookFrom, RTPoint lookAt, RTVector up, float fovy, int width, int height)
        {
            MoveCamera(lookFrom, lookAt, up);

            Width  = width;
            Height = height;

            FovY = fovy.ToRadians();
            FovX = 2.0f * (float)Math.Atan((float)Math.Tan(FovY / 2.0f) * (width / (float)height));
        }
Ejemplo n.º 6
0
        public SceneBuilder SetCameraPosition(RTPoint lookFrom, RTPoint lookAt, RTVector up)
        {
            if (_camera == null)
            {
                InitCameraDefault();
            }

            _camera.MoveCamera(lookFrom, lookAt, up);

            return(this);
        }
Ejemplo n.º 7
0
        public SceneBuilder SetCamera(RTPoint lookFrom, RTPoint lookAt, RTVector up, float fovy)
        {
            if (_sampler == null)
            {
                throw new InvalidOperationException("La taille doit être définie avant la caméra.");
            }

            _camera = new Camera(lookFrom, lookAt, up, fovy, _sampler.Width, _sampler.Height);

            return(this);
        }
Ejemplo n.º 8
0
        public Ray(RTPoint point, RTVector vector, float tMin, float tMax, bool directional)
        {
            Point       = point;
            Vector      = vector;
            TMin        = tMin;
            TMax        = tMax;
            Directional = directional;

            InvDir = 1f / Vector;
            Signs  = new int[] { InvDir.X < 0 ? 1 : 0,
                                 InvDir.Y < 0 ? 1 : 0,
                                 InvDir.Z < 0 ? 1 : 0 };
        }
Ejemplo n.º 9
0
        private RTColor Shading(LocalGeo geo, ShadingInfos si, Ray camRay, Ray lightRay, RTColor lightCol)
        {
            float   nDotL   = RTVector.DotProduct(geo.Normal, lightRay.Vector);
            RTColor lambert = lightCol * si.Diffuse * (nDotL > 0 ? nDotL : 0.0f);

            RTVector half  = (lightRay.Vector - camRay.Vector.Normalize()).Normalize();
            float    nDotH = RTVector.DotProduct(geo.Normal, half);
            RTColor  phong = lightCol * si.Specular * (float)Math.Pow((nDotH > 0 ? nDotH : 0.0f), si.Shininess);

            float   r   = lightRay.Directional ? 0 : lightRay.TMax; // Dans le cas d'un point, le t max est la distance entre le point et la source
            RTColor res = (lambert + phong) / (Attenuation.Constant + Attenuation.Linear * r + Attenuation.Quadratic * (float)Math.Pow(r, 2));

            return(res);
        }
Ejemplo n.º 10
0
        public bool Intersect(Ray ray, bool computeGeo, out LocalGeo geo, out float pos)
        {
            RTPoint A = Vertices[0].Location;
            RTPoint B = Vertices[1].Location;
            RTPoint C = Vertices[2].Location;

            RTVector p0 = new RTVector(ray.Point);

            pos = RTVector.DotProduct(A - ray.Point, Normal) / RTVector.DotProduct(ray.Vector, Normal);

            geo = new LocalGeo();
            if (pos >= ray.TMin && pos <= ray.TMax)
            {
                geo.Point  = ray.Point + pos * ray.Vector;
                geo.Normal = Normal;

                RTVector u = B - A;
                RTVector v = C - A;
                RTVector w = geo.Point - A;

                RTVector vCrossW = RTVector.CrossProduct(v, w);
                RTVector vCrossU = RTVector.CrossProduct(v, u);

                if (RTVector.DotProduct(vCrossW, vCrossU) < 0)
                {
                    return(false);
                }

                RTVector uCrossW = RTVector.CrossProduct(u, w);
                RTVector uCrossV = RTVector.CrossProduct(u, v);

                if (RTVector.DotProduct(uCrossW, uCrossV) < 0)
                {
                    return(false);
                }

                float denom = uCrossV.Length;
                float r     = vCrossW.Length / denom;
                float t     = uCrossW.Length / denom;

                return(r + t <= 1);
            }

            return(false);
        }
Ejemplo n.º 11
0
        private Matrix4x4 ComputeMatrix(RTVector axisIn, float radians)
        {
            Matrix4x4 matrix;

            if (axisIn.X == 1 && axisIn.Y == 0 && axisIn.Z == 0)
            {
                matrix = Matrix4x4.CreateRotationX(radians);
            }
            else if (axisIn.X == 0 && axisIn.Y == 1 && axisIn.Z == 0)
            {
                matrix = Matrix4x4.CreateRotationY(radians);
            }
            else if (axisIn.X == 0 && axisIn.Y == 0 && axisIn.Z == 1)
            {
                matrix = Matrix4x4.CreateRotationZ(radians);
            }
            else
            {
                RTVector  axis  = axisIn.Normalize();
                Matrix4x4 part1 = Matrix4x4.Multiply(Matrix4x4.Identity, (float)Math.Cos(radians));

                Matrix4x4 part2 = Matrix4x4.Multiply(new Matrix4x4((float)Math.Pow(axis.X, 2), axis.X * axis.Y, axis.X * axis.Z, 0,
                                                                   axis.X * axis.Y, (float)Math.Pow(axis.Y, 2), axis.Y * axis.Z, 0,
                                                                   axis.X * axis.Z, axis.Y * axis.Z, (float)Math.Pow(axis.Z, 2), 0,
                                                                   0, 0, 0, 0),
                                                     1.0f - (float)Math.Cos(radians));

                Matrix4x4 part3 = Matrix4x4.Multiply(new Matrix4x4(0, -axis.Z, axis.Y, 0,
                                                                   axis.Z, 0, -axis.X, 0,
                                                                   -axis.Y, axis.X, 0, 0,
                                                                   0, 0, 0, 0),
                                                     (float)Math.Sin(radians));

                matrix     = part1 + Matrix4x4.Transpose(part2) + Matrix4x4.Transpose(part3);
                matrix.M44 = 1;
            }

            return(matrix);
        }
Ejemplo n.º 12
0
        private Normal ComputeNormal()
        {
            Normal res;
            bool   normVertex = Vertices[0].Normal != null;

            if (normVertex)
            {
                // TODO
                res = new Normal(0, 1, 0);
            }
            else
            {
                RTPoint A = Vertices[0].Location;
                RTPoint B = Vertices[1].Location;
                RTPoint C = Vertices[2].Location;

                RTVector U = B - A;
                RTVector V = C - A;

                res = new Normal(RTVector.CrossProduct(U, V));
            }

            return(res);
        }
Ejemplo n.º 13
0
        public Scene BuildScene()
        {
            SceneBuilder sb = new SceneBuilder();

            string line;

            InitPrimitiveProperties();
            _transStack            = new Stack <Transformation>();
            _currentTransformation = new Transformation();

            using (FileStream fs = new FileStream(_path, FileMode.Open, FileAccess.Read, FileShare.Read))
                using (StreamReader sr = new StreamReader(fs))
                {
                    while (!sr.EndOfStream)
                    {
                        line = sr.ReadLine().TrimStart(" \t".ToCharArray()).ToLowerInvariant();

                        if (string.IsNullOrWhiteSpace(line) || line[0] == '#')
                        {
                            continue;
                        }

                        string[] split = line.Split(" \t".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);

                        switch (split[0])
                        {
                            #region General/Camera
                        case "size":
                            int width  = int.Parse(split[1]);
                            int height = int.Parse(split[2]);
                            sb.SetSize(width, height);
                            break;

                        case "maxdepth":
                            int maxDepth = int.Parse(split[1]);
                            sb.SetMaxDepth(maxDepth);
                            break;

                        case "output":
                            sb.SetOutputPath(split[1]);
                            break;

                        case "camera":
                            RTPoint  lFrom = PointFromConfig(split);
                            RTPoint  lAt   = PointFromConfig(split, 4);
                            RTVector up    = VectorFromConfig(split, 7);
                            float    fovy  = float.Parse(split[10]);
                            sb.SetCamera(lFrom, lAt, up, fovy);
                            break;
                            #endregion

                            #region Geometry
                        case "sphere":
                            RTPoint center = PointFromConfig(split);
                            float   radius = float.Parse(split[4]);
                            Sphere  s      = new Sphere(center, radius, _currentTransformation);

                            sb.AddGeoPrimitive(s, _currentMaterial);
                            InitPrimitiveProperties();
                            break;

                        case "maxverts":
                            int maxverts = int.Parse(split[1]);
                            _currentVertex = new List <Vertex>(maxverts);
                            break;

                        case "maxvertsnorms":
                            int maxvertsnorms = int.Parse(split[1]);
                            _currentVertex = new List <Vertex>(maxvertsnorms);
                            break;

                        case "vertex":
                            RTPoint vertex = PointFromConfig(split);
                            _currentVertex.Add(new Vertex(vertex));
                            break;

                        case "vertexnormal":
                            RTPoint  vertexnorm = PointFromConfig(split);
                            RTVector normal     = VectorFromConfig(split, 3);
                            _currentVertex.Add(new Vertex(vertexnorm, normal));
                            break;

                        case "tri":
                        case "trinormal":
                            int v1 = int.Parse(split[1]);
                            int v2 = int.Parse(split[2]);
                            int v3 = int.Parse(split[3]);

                            List <Vertex> vList = new List <Vertex>();
                            vList.Add(_currentVertex[v1]);
                            vList.Add(_currentVertex[v2]);
                            vList.Add(_currentVertex[v3]);

                            Triangle tri = new Triangle(vList, _currentTransformation);
                            sb.AddGeoPrimitive(tri, _currentMaterial);
                            InitPrimitiveProperties();
                            break;
                            #endregion

                            #region Transforms
                        case "translate":
                            RTVector transvec = VectorFromConfig(split);
                            _currentTransformation.AddTransform(new Translation(transvec));
                            break;

                        case "rotate":
                            RTVector rotaxis = VectorFromConfig(split);
                            float    degrees = float.Parse(split[4]);
                            _currentTransformation.AddTransform(new Rotation(rotaxis, degrees));
                            break;

                        case "scale":
                            _currentTransformation.AddTransform(new Scaling(float.Parse(split[1]), float.Parse(split[2]), float.Parse(split[3])));
                            break;

                        case "pushtransform":
                            _transStack.Push(new Transformation(_currentTransformation));
                            break;

                        case "poptransform":
                            _currentTransformation = _transStack.Pop();
                            break;
                            #endregion

                            #region Lights
                        case "directional":
                            RTVector dir    = VectorFromConfig(split);
                            RTColor  dirCol = ColorFromConfig(split, 4);
                            sb.AddLight(new DirLight(dir, dirCol));
                            break;

                        case "point":
                            RTPoint source   = PointFromConfig(split);
                            RTColor pointCol = ColorFromConfig(split, 4);
                            sb.AddLight(new PointLight(source, pointCol));
                            break;

                        case "attenuation":
                            Attenuation att = new Attenuation
                            {
                                Constant  = float.Parse(split[1]),
                                Linear    = float.Parse(split[2]),
                                Quadratic = float.Parse(split[3])
                            };
                            sb.SetAttenuation(att);
                            break;

                        case "ambient":
                            RTColor ambient = ColorFromConfig(split);
                            _currentMaterial.Properties.Ambient = ambient;
                            break;
                            #endregion

                            #region Materials
                        case "diffuse":
                            RTColor diffuse = ColorFromConfig(split);
                            _currentMaterial.Properties.Diffuse = diffuse;
                            break;

                        case "specular":
                            RTColor spec = ColorFromConfig(split);
                            _currentMaterial.Properties.Specular = spec;
                            break;

                        case "shininess":
                            float shine = float.Parse(split[1]);
                            _currentMaterial.Properties.Shininess = shine;
                            break;

                        case "emission":
                            RTColor emission = ColorFromConfig(split);
                            _currentMaterial.Properties.Emission = emission;
                            break;
                            #endregion
                        }
                    }
                }

            return(sb.Build());
        }
Ejemplo n.º 14
0
 public static float DotProduct(RTVector v1, RTVector v2)
 {
     return(Vector4.Dot(v1.Vector, v2.Vector));
 }
Ejemplo n.º 15
0
 public static RTVector CrossProduct(RTVector l, RTVector r)
 {
     return(new RTVector(l.Y * r.Z - l.Z * r.Y,
                         -l.X * r.Z + l.Z * r.X,
                         l.X * r.Y - l.Y * r.X));
 }
Ejemplo n.º 16
0
 public RTVector(RTVector vector)
 {
     Vector = new Vector4(vector.X, vector.Y, vector.Z, 0);
 }
Ejemplo n.º 17
0
        public bool Intersect(Ray ray, bool computeGeo, out LocalGeo geo, out float t)
        {
            RTPoint  tPoint = Transformation.ApplyInverseTo(new RTPoint(ray.Point.X, ray.Point.Y, ray.Point.Z));
            RTVector tVec   = Transformation.ApplyInverseTo(new RTVector(ray.Vector.X, ray.Vector.Y, ray.Vector.Z));

            RTVector ec = tPoint - Center;

            float a = RTVector.DotProduct(tVec, tVec);
            float b = 2.0f * RTVector.DotProduct(tVec, ec);
            float c = RTVector.DotProduct(ec, ec) - (float)Math.Pow(Radius, 2);

            float det = (float)Math.Pow(b, 2) - 4.0f * a * c;

            t = float.MaxValue;

            bool intersect = false;

            if (det == 0d)
            {
                intersect = true;
                t         = -b / (2.0f * a);
            }
            else if (det > 0d)
            {
                float t1 = (-b + (float)Math.Sqrt(det)) / (2.0f * a);
                float t2 = (-b - (float)Math.Sqrt(det)) / (2.0f * a);

                if ((t1 > 0 && t2 < 0) || (t1 < 0 && t2 > 0))
                {
                    intersect = true;
                    if (t1 > 0)
                    {
                        t = t1;
                    }
                    else
                    {
                        t = t2;
                    }
                }
                else if (t1 > 0 && t2 > 0)
                {
                    intersect = true;
                    if (t1 < t2)
                    {
                        t = t1;
                    }
                    else
                    {
                        t = t2;
                    }
                }
            }

            geo = new LocalGeo();
            if (intersect && t >= ray.TMin && t <= ray.TMax)
            {
                if (computeGeo)
                {
                    geo.Point  = tPoint + t * tVec;
                    geo.Normal = new Normal(geo.Point - Center);

                    geo.Point = Transformation.ApplyTo(geo.Point);

                    geo.Normal = new Normal(Transformation.ApplyInverseTransposeTo(geo.Normal));
                }

                return(true);
            }

            return(false);
        }
Ejemplo n.º 18
0
 public DirLight(RTVector dir, RTColor color)
 {
     Direction = dir;
     Color     = color;
 }
Ejemplo n.º 19
0
 public RTVector ApplyInverseTransposeTo(RTVector v)
 {
     return(v.ApplyMatrix(Matrix4x4.Transpose(ComputeInverse())));
 }
Ejemplo n.º 20
0
        public Normal(RTVector vec) : base(vec)
        {
            Vector4 norm = Vector4.Normalize(new Vector4(vec.X, vec.Y, vec.Z, 0));

            Vector = norm;
        }
Ejemplo n.º 21
0
        public RTColor Trace(Ray ray, int depth)
        {
            RTColor res = new RTColor();

            float lastT = float.MaxValue;
            bool  shadow;

            // TODO: initialiser l'arbre autrepart
            // TODO: corriger la bounding box des spheres
            if (_tree == null)
            {
                _tree = new BBTree(Primitives);
            }
            IEnumerable <HitResult> hits = _tree.Hit(ray);

            //IList<HitResult> hits = Primitives.Select(p =>
            //{
            //    if (p.Intersect(ray, true, out LocalGeo geo, out float t))
            //    {
            //        return new HitResult { Primitive = p, Geo = geo, T = t };
            //    }

            //    return null;
            //}).Where(h => h != null).ToList();

            foreach (HitResult h in hits)
            {
                if (h.T < lastT)
                {
                    lastT = h.T;

                    ShadingInfos si = h.Primitive.GetShading(h.Geo);

                    // Ambient & emission
                    res = si.Emission + si.Ambient;

                    // Phong shading
                    foreach (ILight light in Lights)
                    {
                        shadow = false;
                        RTColor lightCol;
                        Ray     lightRay = light.GenerateRay(h.Geo, out lightCol);

                        foreach (IPrimitive pShadow in Primitives)
                        {
                            if (pShadow.Intersect(lightRay, false, out _, out _))
                            {
                                shadow = true;
                            }
                        }

                        if (!shadow)
                        {
                            res += Shading(h.Geo, si, ray, lightRay, lightCol);
                        }
                    }

                    // Reflection
                    if ((si.Specular.Red > 0 || si.Specular.Green > 0 || si.Specular.Blue > 0) && depth < MaxDepth)
                    {
                        Ray reflected = new Ray(h.Geo.Point, ray.Vector - 2.0f * RTVector.DotProduct(ray.Vector, h.Geo.Normal) * h.Geo.Normal, 1e-3f, float.MaxValue, false);
                        res += si.Specular * Trace(reflected, depth + 1);
                    }
                }
            }

            return(res);
        }
Ejemplo n.º 22
0
 public RTVector ApplyTo(RTVector v)
 {
     return(v.ApplyMatrix(Compute()));
 }
Ejemplo n.º 23
0
 public RTVector ApplyInverseTo(RTVector v)
 {
     return(v.ApplyMatrix(ComputeInverse()));
 }
Ejemplo n.º 24
0
 public Translation(RTVector vector)
 {
     Vector = vector;
 }
Ejemplo n.º 25
0
 public Rotation(RTVector axis, float degrees)
 {
     Axis    = axis;
     Degrees = degrees;
 }