/// <summary>
 /// Determina si hay interseccion entre un rayo y un modelo determinado.
 /// En la estructura info se devuelve la informacion relacionada al punto de interseccion.
 /// </summary>
 /// modificado
 public static bool Intersect(Ray r, Model model, out IntersectionInfo info)
 {
     bool intersect;
     switch (model)
     {
         case Model.Cube: intersect = IntersectCube(r, out info); break;
         case Model.Cone: intersect = IntersectCone(r, out info); break;
         case Model.Cylinder: intersect = IntersectCylinder(r, out info); break;
         case Model.Disk: intersect = IntersectDisk(r, out info); break;
         case Model.Plane: intersect = IntersectPlane(r, out info); break;
         case Model.Sphere: intersect = IntersectSphere(r, out info); break;
         default: throw new NotImplementedException();
     }
     if (intersect)
         info.TextureCoordenates = model.TextureCoordenates(info.Position);
     return intersect;
 }
 private static bool Intersect2DModel(Ray r, out IntersectionInfo info, Func<vec3, bool> func)
 {
     info = new IntersectionInfo();
     if (r.From.Y < 0 && r.Direction.Y > 0
         && (func(info.Position = r.From + r.Direction*((0 - r.From.Y)/r.Direction.Y))))
     {
         info.Normal = new vec3(0, -1, 0);
         return true;
     }
     if (r.From.Y > 0 && r.Direction.Y < 0
         && (func(info.Position = r.From + r.Direction*((0 - r.From.Y)/r.Direction.Y))))
     {
         info.Normal = new vec3(0, 1, 0);
         return true;
     }
     return false;
 }
 //modificado para annadir el ModelGraphic a info
 private bool Intersect(Ray r, ModelGraphic model, out IntersectionInfo info)
 {
     if (Intersecter.Intersect(r, model.Model, out info))
     {
         info.ModelGraphic = model;
         return true;
     }
     return false;
 }
 //modificado para transformar la normal y la posicion del punto
 private bool Intersect(Ray r, TransformedGraphic graphic, out IntersectionInfo info)
 {
     Ray transformedRay = r.Transformed(graphic.Transform.Inverse);
     if (Intersect(transformedRay, graphic.Graphic, out info))
     {
         info.Position = (vec3)(new vec4(info.Position, 1) * graphic.Transform);
         info.Normal = info.Normal * ((mat3x3)graphic.Transform);
         return true;
     }
     return false;
 }
            //modificado escogia el color por la pos del punto
            private vec4 CalculateIlumination(IntersectionInfo info, Ray r, int depth)
            {
                Material material = info.ModelGraphic.Material;

                //Ver si el material es emisivo
                vec4 result = new vec4();
                if (material is EmissiveMaterial)
                    result = ((EmissiveMaterial)material).LightColor;

                //Ver si el material es bump
                if (material is BumpMaterial)
                {
                    var image = material.Diffuse;
                    int px = (int)(info.TextureCoordenates.X * (image.Width - 1));
                    int py = (int)(info.TextureCoordenates.Y * (image.Height - 1));
                    info.Normal = info.Normal + 10 * (vec3)((BumpMaterial)material).Normals[px, py];
                }

                //Buscando el color en el punto (se puede variar el modo de Sampling)
                vec4 colorOfPoint = material.Diffuse.BilinearSample(info.TextureCoordenates.X, 1-info.TextureCoordenates.Y); ;

                //Aporte de la luz ambiental
                result += (1 - material.Translucence) * colorOfPoint * Scene.AmbientLight;

                #region Aporte de cada luz al punto
                foreach (var light in Lights)
                {
                    Ray ray = Ray.FromTo(info.Position, light.Position);
                    bool eclipsedLight = false;

                    //Detectar si la luz es eclipsada por otro objeto
                    foreach (var graphic in Scene.Graphics)
                    {
                        IntersectionInfo infoAux;
                        if (Intersect(ray, graphic, out infoAux)
                        && (infoAux.Position - ray.From).Length < (light.Position - ray.From).Length
                        && (infoAux.ModelGraphic != light.ModelGraphic)
                        && (infoAux.ModelGraphic != info.ModelGraphic))
                        {
                            eclipsedLight = true;
                            break;
                        }
                    }
                    //Procesar el aporte de la luz si no esta eclipsada
                    if (!eclipsedLight)
                    {
                        //este vector tiene la direccion desde el pto a la luz
                        vec3 lightDirection = (light.Position - info.Position).Normalized;

                        //Aporte de la reflexion difusa
                        //la intensidad de la luz es directamente proporcional al coseno del angulo entre el rayo de luz y la normal
                        result += PutInRange(light.Intensity *  colorOfPoint *  (vec3.dot(lightDirection, info.Normal)));

                        //Aporte de la reflexion especular
                        result += PutInRange(light.Intensity * colorOfPoint * (float)Math.Pow(vec3.dot(info.Normal, lightDirection - r.Direction), material.Shinness));
                    }
                }
                #endregion

                if (depth > 0)
                {
                    //Aporte de la luz reflejada por otros objetos
                    Ray reflectionRay = Ray.FromDirection(info.Position, r.Direction - 2 * vec3.dot(r.Direction, info.Normal) * info.Normal);
                    vec4 reflectionColor = GetRayColor(reflectionRay, depth - 1, false);
                    result += material.Reflectance * reflectionColor;

                    //Aporte de la luz refractada
                    if(material.Translucence > 0)
                    {
                        float desc = (float)(1 + (Math.Pow(vec3.dot(-1 * r.Direction, info.Normal), 2) - 1) / Math.Pow(material.Density, 2));
                        if (desc > 0)
                        {
                            vec3 refractionDirection = (r.Direction*(1f/material.Density)) +
                                                       ((vec3.dot(-1 * r.Direction, info.Normal) * (1f / material.Density)) -
                                                        (float) Math.Sqrt(desc))*info.Normal;
                            Ray refractionRay = Ray.FromDirection(info.Position, refractionDirection);
                            vec4 refractionColor = GetRayColor(refractionRay, depth - 1, false);
                            result += material.Translucence *refractionColor;
                        }
                    }
                }
                return PutInRange(result);
            }
            //modificado para annadir depthReflection y refle
            private vec4 GetRayColor(Ray r, int depth = 4, bool firstRay = true)
            {
                /// Variable para identificar el primer "hit"
                bool find = false;
                /// Interseccion mas cercana al punto de partida del rayo.
                IntersectionInfo nearest = new IntersectionInfo();

                /// Para cada grafico en la escena
                foreach (var o in Scene.Graphics)
                {
                    IntersectionInfo info;
                    /// Si se intersecta
                    if ((Intersect(r, o, out info))
                    && (!find || (info.Position - r.From).Length < (nearest.Position - r.From).Length)
                    && ((info.Position - r.From).Length > 0.01f))
                    {
                        nearest = info;
                        find = true;
                    }
                }

                if (find)
                {
                    /// Aqui vendria el calculo de iluminacion para el punto de interseccion.
                    return CalculateIlumination(nearest, r, depth);
                }
                if (firstRay)
                    return BackColor.ToVec4();
                return Color.Empty.ToVec4();
            }
 private static bool IntersectPlane(Ray r, out IntersectionInfo info)
 {
     //el disco esta en el plano XZ
     Func<vec3, bool> isInPlane = v => Math.Abs(v.X) <= 0.50001 && Math.Abs(v.Z) <= 0.50001;
     return Intersect2DModel(r, out info, isInPlane);
 }
 private static bool IntersectSphere(Ray r, out IntersectionInfo info)
 {
     info = new IntersectionInfo();
     //esfera con centro en (0, 0, 0) y radio 1
     float a = 1;
     float b = 2 * (r.From.X * r.Direction.X + r.From.Y * r.Direction.Y + r.From.Z * r.Direction.Z);
     float c = r.From.X * r.From.X + r.From.Y * r.From.Y + r.From.Z * r.From.Z - 1;
     float t;
     if (FindSolution(a, b, c, out t))
     {
         info.Position = r.From + r.Direction * t;
         info.Normal = info.Position;
         return true;
     }
     return false;
 }
 private static bool IntersectDisk(Ray r, out IntersectionInfo info)
 {
     //el disco esta en el plano XZ
     Func<vec3, bool> isInDisk = v => v.X * v.X + v.Z * v.Z <= 1.00001;
     return Intersect2DModel(r, out info, isInDisk);
 }
        private static bool IntersectCylinder(Ray r, out IntersectionInfo info)
        {
            info = new IntersectionInfo();
            Func<vec3, bool> isInDisk = v => v.X * v.X + v.Z * v.Z <= 1.00001;
            // Top Intersection
            if (r.From.Y > 1 && r.Direction.Y < 0
                && (isInDisk(info.Position = r.From + r.Direction * ((1 - r.From.Y) / r.Direction.Y))))
            {
                info.Normal = new vec3(0, 1, 0);
                return true;
            }
            // Bottom Intersection
            if (r.From.Y < 0 && r.Direction.Y > 0
                && (isInDisk(info.Position = r.From + r.Direction * ((0 - r.From.Y) / r.Direction.Y))))
            {
                info.Normal = new vec3(0, -1, 0);
                return true;
            }

            float a = r.Direction.X * r.Direction.X + r.Direction.Z * r.Direction.Z;
            float b = 2 * (r.From.X * r.Direction.X + r.From.Z * r.Direction.Z);
            float c = r.From.X * r.From.X + r.From.Z * r.From.Z - 1;
            float t;
            if (FindSolution(a, b, c, out t))
            {
                info.Position = r.From + r.Direction * t;
                if (0.00001 <= info.Position.Y && info.Position.Y <= 1.00001) //hay interseccion con las paredes
                {
                    info.Normal = new vec3(info.Position.X, 0, info.Position.Z);
                    return true;
                }
            }

            return false;
        }
        /// modificado
        private static bool IntersectCube(Ray r, out IntersectionInfo info)
        {
            Func<vec3, bool> isInCube = v => v.X >= -0.00001 && v.X <= 1.00001 && v.Y >= -0.00001 && v.Y <= 1.00001 && v.Z >= -0.00001 && v.Z <= 1.00001;
            info = new IntersectionInfo();
            // Front Intersection
            if (r.From.Z < 0 && r.Direction.Z > 0
                && (isInCube(info.Position = r.From + r.Direction * ((0 - r.From.Z) / r.Direction.Z))))
            {
                info.Position = new vec3(info.Position.X, info.Position.Y, 0);
                info.Normal = new vec3(0, 0, -1);
                return true;
            }
            // Back Intersection
            if (r.From.Z > 1 && r.Direction.Z < 0
                && (isInCube(info.Position = r.From + r.Direction * ((1 - r.From.Z) / r.Direction.Z))))
            {
                info.Position = new vec3(info.Position.X, info.Position.Y, 1);
                info.Normal = new vec3(0, 0, 1);
                return true;
            }
            // Left Intersection
            if (r.From.X < 0 && r.Direction.X > 0
                && (isInCube(info.Position = r.From + r.Direction * ((0 - r.From.X) / r.Direction.X))))
            {
                info.Position = new vec3(0, info.Position.Y, info.Position.Z);
                info.Normal = new vec3(-1, 0, 0);
                return true;
            }
            // Right Intersection
            if (r.From.X > 1 && r.Direction.X < 0
                && (isInCube(info.Position = r.From + r.Direction * ((1 - r.From.X) / r.Direction.X))))
            {
                info.Position = new vec3(1, info.Position.Y, info.Position.Z);
                info.Normal = new vec3(1, 0, 0);
                return true;
            }
            // Bottom Intersection
            if (r.From.Y < 0 && r.Direction.Y > 0
                && (isInCube(info.Position = r.From + r.Direction * ((0 - r.From.Y) / r.Direction.Y))))
            {
                info.Position = new vec3(info.Position.X, 0, info.Position.Z);
                info.Normal = new vec3(0, -1, 0);
                return true;
            }
            // Top Intersection
            if (r.From.Y > 1 && r.Direction.Y < 0
                && (isInCube(info.Position = r.From + r.Direction * ((1 - r.From.Y) / r.Direction.Y))))
            {
                info.Position = new vec3(info.Position.X, 1, info.Position.Z);
                info.Normal = new vec3(0, 1, 0);
                return true;
            }

            return false;
        }
Beispiel #12
0
 /// <summary>
 /// Permite determinar si un rayo intersecta un grafico. 
 /// En la variable info queda almacenada la informacion referente a la interseccion.
 /// </summary>
 private bool Intersect(Ray r, Graphic graphic, out IntersectionInfo info)
 {
     if (graphic is ModelGraphic)
         return Intersect(r, (ModelGraphic)graphic, out info);
     if (graphic is TransformedGraphic)
         return Intersect(r, (TransformedGraphic)graphic, out info);
     if (graphic is CSGGraphic)
         return Intersect(r, (CSGGraphic)graphic, out info);
     throw new NotSupportedException();
 }
Beispiel #13
0
 /// <summary>
 /// Permite determinar si un rayo intersecta un grafico CSG. 
 /// En la variable info queda almacenada la informacion referente a la interseccion.
 /// </summary>
 private bool Intersect(Ray r, CSGGraphic graphic, out IntersectionInfo info)
 {
     throw new NotSupportedException();
 }