public override bool IsHit(Ray ray, HitRecord record, float near, float far)
        {
            Vector newCenter;
            if (Velocity.IsBlack())
                newCenter = Center;
            else
            {
                newCenter = this.Center + ray.Time * this.Velocity;
            }

            //e - c
            Vector eMinusC = ray.Start - newCenter;
            //d.(e-c)
            float dDotEMinusC = Vector.Dot3(ray.Direction, eMinusC);
            float dDotD = Vector.Dot3(ray.Direction, ray.Direction);
            //d.(e-c)^2 - (d.d)((e-c).(e-c) - R^2))
            float discriminant = dDotEMinusC * dDotEMinusC - dDotD * (Vector.Dot3(eMinusC, eMinusC) - this.Radius * this.Radius);
            //Intersection occurs
            float t1 = 0, t2 = 0, first_t = 0;
            if (discriminant >= 0)
            {
                t1 = (-dDotEMinusC + (float)Math.Sqrt(discriminant)) / dDotD;
                t2 = (-dDotEMinusC - (float)Math.Sqrt(discriminant)) / dDotD;
                Vector diff;
                Vector worldCoords;

                if (t2 >= 0)
                    first_t = t2;
                else if (t1 >= 0)
                    first_t = t1;
                else
                    return false;

                // t*d
                diff = ray.Direction * first_t;
                // e + t*d
                worldCoords = diff + ray.Start;
                float distance = diff.Magnitude3();

                if (distance <= record.Distance && distance <= ray.MaximumTravelDistance)
                {

                    if (ray.UseBounds)
                    {
                        float cameraOrthogonalDistance = Math.Abs(Vector.Dot3(diff, ray.CameraLookDirection));
                        if (cameraOrthogonalDistance > far && cameraOrthogonalDistance < near)
                        {
                            return false;
                        }
                    }

                    record.T = first_t;
                    record.HitPoint = ray.Start + diff;
                    record.Distance = distance;
                    record.Material = this.Material;
                    record.SurfaceNormal = SurfaceNormal(record.HitPoint, ray.Direction);
                    if (Material.TextureImage != null)
                    {
                        double cos = (record.HitPoint.z - newCenter.z) / Radius;
                        if (cos < -1)
                            cos = -1;
                        else if (cos > 1)
                            cos = 1;

                        double theta = Math.Acos(cos);
                        double phi = Math.Atan2(record.HitPoint.y - newCenter.y, record.HitPoint.x - newCenter.x);
                        if (phi < 0)
                            phi += 2 * Math.PI;

                        float u = (float)(phi / (2 * Math.PI));
                        float v = (float)((Math.PI - theta) / Math.PI);
                        //Console.WriteLine(this.textureWidth);
                        //Console.WriteLine(this.Material.TextureImage.Height);
                        //int i = (int)(u * (this.textureWidth - 1) + 0.5);
                        //int j = (int)(v * (this.textureHeight - 1) + 0.5);
                        record.TextureColor = this.Material.GetTexturePixelColor(u, v);
                    }

                    return true;
                }

            }
            return false;
        }
 public override bool IsHit(Ray ray, HitRecord record, float near, float far)
 {
     throw new NotImplementedException();
 }
        private bool MakesShadow(Ray shadowRay, SceneLight light, int reflections, int refractions, float refractive, float time)
        {
            if (refractions > 5)
                return false;

            bool makesShadow = false;
            shadowRay.Time = time;
            float lightDistance = (light.Position - shadowRay.Start).Magnitude3();
            shadowRay.MaximumTravelDistance = lightDistance;
            ////////////////////////////////////////////////////////////////

            HitRecord shadowRecord = new HitRecord();
            foreach (SceneObject shadowObject in scene.Objects)
            {
                makesShadow = shadowObject.IsHit(shadowRay, shadowRecord, float.MinValue, float.MaxValue) || makesShadow;
            }

            if (makesShadow)
            {
                if (shadowRecord.Material.RefractionIndex.x != 0.0f)
                {
                    Ray refractedShadow = CastRefractionRay(shadowRay, shadowRecord, refractive);
                    refractive = shadowRecord.Material.RefractionIndex.x;
                    makesShadow = MakesShadow(refractedShadow, light, reflections, refractions + 1, shadowRecord.Material.RefractionIndex.x, time);

                    if (RenderingParameters.showMouse && makesShadow)
                    {
                        Console.WriteLine("Shadow made after getting out from traslucent material.");
                    }
                    return makesShadow;
                }
                else
                {
                    if (RenderingParameters.showMouse)
                        Console.WriteLine("Made shadow from " + shadowRecord.Material.Name);
                    return true;
                }
            }

            return makesShadow;
        }
        public override bool IsHit(Ray ray, HitRecord record, float near, float far)
        {
            //(d.h)h
            Vector dDotHTimesH = Vector.Dot3(ray.Direction, HeightDirection) * HeightDirection;
            Vector deltaP = ray.Start - this.BasePoint;
            Vector deltaPDotHTimesH = Vector.Dot3(deltaP, HeightDirection) * HeightDirection;
            Vector deltaPMinusdeltaPDotHTimesH = deltaP - deltaPDotHTimesH;
            Vector dMinusdDotHTimesH = ray.Direction - dDotHTimesH;

            float B = 2 * Vector.Dot3(dMinusdDotHTimesH, deltaPMinusdeltaPDotHTimesH);
            float A = Vector.Dot3(dMinusdDotHTimesH, dMinusdDotHTimesH);
            float C = Vector.Dot3(deltaPMinusdeltaPDotHTimesH, deltaPMinusdeltaPDotHTimesH) - this.Radius * this.Radius;
            Vector diff, worldCoords;
            float discriminant = B * B - 4 * A * C;
            float t1 = 0, t2 = 0, first_t = float.MaxValue;
            List<float> candidates = new List<float>();
            IntersectionType intersectionType = IntersectionType.Cylinder;

            if (discriminant >= 0)
            {
                t1 = (-B - (float)Math.Sqrt(discriminant)) / (2 * A);
                t2 = (-B + (float)Math.Sqrt(discriminant)) / (2 * A);

                if (t1 >= 0 && IsInside(ray.Start + ray.Direction*t1))
                {
                    first_t = t1;
                }
                if (t2 >= 0 && IsInside(ray.Start + ray.Direction*t2) && t2 < first_t)
                {
                    first_t = t2;
                }
            }

            float hDotd = Vector.Dot3(this.HeightDirection, ray.Direction);
            if (hDotd != 0)
            {
                float basePlaneT = Vector.Dot3(this.HeightDirection, this.BasePoint) - Vector.Dot3(this.HeightDirection, ray.Start);
                basePlaneT = basePlaneT / hDotd;
                if (basePlaneT > 0 && IsCap(this.BasePoint, basePlaneT * ray.Direction + ray.Start) && basePlaneT < first_t)
                {
                    intersectionType = IntersectionType.Base;
                    first_t = basePlaneT;
                }

                float endPlaneT = Vector.Dot3(this.HeightDirection, this.EndPoint) - Vector.Dot3(this.HeightDirection, ray.Start);
                endPlaneT = endPlaneT / hDotd;
                if (endPlaneT > 0 && IsCap(this.EndPoint, endPlaneT * ray.Direction + ray.Start) && endPlaneT < first_t)
                {
                    intersectionType = IntersectionType.End;
                    first_t = endPlaneT;
                }
            }

            if (first_t == float.MaxValue)
                return false;

            // t*d
            diff = ray.Direction * first_t;
            // e + t*d
            worldCoords = diff + ray.Start;

            float distance = diff.Magnitude3();

            if (distance <= record.Distance && distance <= ray.MaximumTravelDistance)
            {

                if (ray.UseBounds)
                {
                    float cameraOrthogonalDistance = Math.Abs(Vector.Dot3(diff, ray.CameraLookDirection));
                    if (cameraOrthogonalDistance > far && cameraOrthogonalDistance < near)
                    {
                        return false;
                    }
                }

                record.T = first_t;
                record.HitPoint = ray.Start + diff;
                record.Distance = distance;
                record.Material = this.Material;
                if (intersectionType == IntersectionType.Cylinder)
                {
                    record.SurfaceNormal = SurfaceNormal(record.HitPoint, ray.Direction);
                    if (Material.TextureImage != null)
                    {
                        float heightReached = Vector.Dot3(HeightDirection, record.HitPoint - this.BasePoint);
                        float u = heightReached / Height;
                        Vector circCenter = BasePoint + HeightDirection * heightReached;
                        Vector projection = record.HitPoint - circCenter;
                        projection.Normalize3();
                        float similarity = Vector.Dot3(projection, Tangent);
                        float theta = (float)Math.Acos(similarity);
                        float v = (float)((Math.PI - theta) / Math.PI);
                        v = v < 0 ? -v : v;
                        record.TextureColor = this.Material.GetTexturePixelColor(u, v);
                         // float v =
                    }
                }
                else
                {
                    record.SurfaceNormal = PlaneNormal(record.HitPoint, ray.Direction);
                    if (Material.TextureImage != null)
                    {
                        Vector circCenter = intersectionType == IntersectionType.Base ? BasePoint : EndPoint;
                        Vector projection = record.HitPoint - circCenter;
                        float length = projection.Magnitude3();
                        projection.Normalize3();
                        float similarity = Vector.Dot3(projection, Tangent);
                        float theta = (float)Math.Acos(similarity);
                        float u = length / Radius;
                        float v = (float)((Math.PI - theta) / Math.PI);
                        v = v < 0 ? -v : v;
                        record.TextureColor = this.Material.GetTexturePixelColor(u, v);
                        // float v =
                    }
                }
               // record.SurfaceNormal = SurfaceNormal(record.HitPoint, ray.Direction);
                return true;
            }
            return false;
        }
        private Ray CastRefractionRay(Ray ray, HitRecord record, float refractive)
        {
            Vector rayDirection = ray.Direction;
            Vector surfaceNormal = record.SurfaceNormal;
            Vector refractedColor = new Vector();

            float newRefractive = record.Material.RefractionIndex.x;
            if (newRefractive == refractive)
            {
                newRefractive = 1.0f;
            }
            //rayDirection = -surfaceNormal;
            float dDotn = Vector.Dot3(ray.Direction, surfaceNormal);
            float sqrtArgs = 1.0f - (refractive * refractive * (1 - dDotn * dDotn)) / (newRefractive * newRefractive);
            Vector refractiveDir = new Vector();
            Ray refractionRay;

            if (sqrtArgs > 0.0f)
            {
                Vector nSqrt = surfaceNormal * (float)Math.Sqrt(sqrtArgs);
                refractiveDir = (refractive * (rayDirection - surfaceNormal * dDotn)) / newRefractive - nSqrt;
                refractiveDir.Normalize3();
                //refractiveDir = rayDirection;

                refractionRay = new Ray(record.HitPoint + refractiveDir * 0.1f, refractiveDir);
                refractionRay.Time = ray.Time;
                if (RenderingParameters.showMouse)
                {
                    //Console.WriteLine("Refracting");
                //    Console.WriteLine("Ray direction: ");
                //    Console.WriteLine(rayDirection);
                //    Console.WriteLine("Refraction direction: ");
                //    Console.WriteLine(refractiveDir);
                //    Console.WriteLine();
                }

                return refractionRay;
            }
            else
                return ray;
        }
        private Vector CalculateColor(Ray ray, float minDistance, float maxDistance, int reflections, int refractions, float refractive)
        {
            HitRecord record = new HitRecord();
            Vector finalColor = new Vector();
            Vector lightDirection = new Vector();
            bool hitSomething = false;
            Vector surfaceNormal = new Vector();
            Vector rayDirection = ray.Direction;

            foreach (SceneObject sceneObject in scene.Objects)
            {
                //First check intersection
                bool intersects = sceneObject.IsHit(ray, record, minDistance, maxDistance);
                //If it intersects, diffuse color is set, so set shading color

                if (intersects)
                {
                    hitSomething = true;
                    surfaceNormal = record.SurfaceNormal;

                    if (record.Material.RefractionIndex.x > 0.0f && record.Material.Refractiveness.x == 1.0f)
                    {
                        continue;
                    }
                    record.ShadedColors.Clear();
                    foreach (SceneLight light in scene.Lights)
                    {
                        Vector currentLightColor = new Vector();
                        lightDirection = light.Position - record.HitPoint;
                        lightDirection.Normalize3();

                        //Get cosine of angle between vectors
                        float similarity = Vector.Dot3(surfaceNormal, lightDirection);

                        Vector lambertColor = new Vector();
                        if (record.Material.TextureImage != null)
                        {
                            lambertColor = Vector.ColorMultiplication(light.Color, record.TextureColor) * Math.Max(0, similarity);
                        }
                        else
                        {
                            lambertColor = Vector.ColorMultiplication(light.Color, record.Material.Diffuse) * Math.Max(0, similarity);
                        }

                        //Get half vector between camera direction and light direction
                        Vector halfVector = -1 * rayDirection + lightDirection;
                        halfVector.Normalize3();

                        //Phong shading calculations
                        float normalHalfSimilarity = Vector.Dot3(surfaceNormal, halfVector);
                        Vector phongLightCoefficient = Vector.ColorMultiplication(light.Color, record.Material.Specular);
                        float shininessComponent = (float)Math.Pow(Math.Max(0, normalHalfSimilarity), record.Material.Shininess);
                        Vector phongColor = phongLightCoefficient * shininessComponent;

                        //Add colors and ambient light
                        //Assume no transparency

                        currentLightColor = Vector.LightAdd(lambertColor, phongColor);
                        record.ShadedColors.Add(currentLightColor);
                    }
                }
            }

            if (hitSomething)
            {
                if (RenderingParameters.showMouse)
                {
                    Console.WriteLine("Hit material " + record.Material.Name);
                }
                finalColor = new Vector();
                //////////////////////////////////////////////////////////////
                ///////////////////////SHADOWS///////////////////////////////
                /////////////////////////////////////////////////////////////

                    if (RenderingParameters.showMouse)
                    {
                        Console.WriteLine("Checking for shadows!");
                    }
                    for (int i = 0; i < scene.Lights.Count; i++) //For each light
                    {
                        if (renderingParameters.EnableShadows)
                        {
                            if (record.Material.RefractionIndex.x == 0.0f) //Not refractive surface
                            {
                                Vector direction = scene.Lights[i].Position - record.HitPoint;
                                direction.Normalize3();
                                Vector shadowStart = record.HitPoint + direction * 0.1f;
                                Ray shadowRay = new Ray(shadowStart, direction);
                                bool makesShadow = MakesShadow(shadowRay, scene.Lights[i], reflections, refractions, refractive, ray.Time);
                                if (makesShadow)
                                {
                                    record.ShadedColors[i] = new Vector();
                                }
                            }
                        }
                        if (record.Material.Refractiveness.x != 1.0f)
                        {
                            finalColor = Vector.LightAdd(finalColor, record.ShadedColors[i]);
                            finalColor.w = 1.0f;
                        }
                    }

                ///////////////////////////////////////////////////////////////
                //////////////////////REFRACTIONS/////////////////////////////
                //////////////////////////////////////////////////////////////
                if (renderingParameters.EnableRefractions && refractions < 10 && !record.Material.RefractionIndex.IsBlack())
                {
                    if (record.Material.Refractiveness.x < 1.0f)
                    {
                        int a = 1;
                    }
                    Ray refractedRay = CastRefractionRay(ray, record, refractive);
                    Vector refractiveNess = record.Material.Refractiveness;
                    if (RenderingParameters.showMouse)
                        Console.WriteLine("REFRACTING");

                    finalColor = Vector.ColorMultiplication(refractiveNess, CalculateColor(refractedRay, float.MinValue, float.MaxValue, reflections, refractions + 1, record.Material.RefractionIndex.x))
                        + Vector.ColorMultiplication(new Vector(1.0f, 1.0f, 1.0f) - refractiveNess, finalColor);
                }

                ///////////////////////////////////////////////////////////////
                //////////////////////REFLECTIONS/////////////////////////////
                //////////////////////////////////////////////////////////////
                if (renderingParameters.EnableReflections && reflections < 20 && !record.Material.Reflective.IsBlack() )
                {
                    Vector d = rayDirection;
                    //Check for reflections
                    Vector reflection = d -2* Vector.Dot3(d, surfaceNormal) * surfaceNormal;
                    reflection.Normalize3();
                    HitRecord reflectionRecord = new HitRecord();

                    Ray reflectionRay = new Ray(record.HitPoint + reflection * 0.01f, reflection);
                    reflectionRay.Time = ray.Time;
                    //if (showMouse)
                    //{
                    //    Console.WriteLine("Reflection direction: ");
                    //    Console.WriteLine(reflection);
                    //    Console.WriteLine();
                    //}
                    Vector reflectiveColor = record.Material.Reflective;
                    if (RenderingParameters.showMouse)
                    {
                        Console.WriteLine("REFLECTING - NORMAL: " + surfaceNormal + "\tReflection: " + reflection);
                    }
                    Vector reflectedObjectColor = CalculateColor(reflectionRay, float.MinValue, float.MaxValue, reflections + 1, refractions, refractive);
                    finalColor = Vector.LightAdd(finalColor, Vector.ColorMultiplication(reflectiveColor, reflectedObjectColor));
                    finalColor = Vector.LightAdd(finalColor, scene.Background.AmbientLight);
                }

            }

            if (reflections == 0 && refractions == 0)
            {
                //finalColor = Vector.LightAdd(finalColor, scene.Background.AmbientLight);
                if (RenderingParameters.showMouse)
                {
                    RenderingParameters.showMouse = false;
                    Console.WriteLine("-------------------------------------------------------");
                    Console.WriteLine("-------------------------------------------------------");
                }
            }

            finalColor.w = 1.0f;
            return finalColor;
        }
Beispiel #7
0
        public override bool IsHit(Ray ray, HitRecord record, float near, float far)
        {
            bool isHit = false;

            foreach (SceneTriangle triangle in triangles)
            {
                isHit = triangle.IsHit(ray, record, near, far) || isHit;
            }
            if (isHit)
            {
                record.ObjectName = this.Name;
                if (Material.TextureImage != null)
                {
                    Vector l1 = Vertex[1] - Vertex[0];
                    Vector l2 = Vertex[3] - Vertex[0];
                    float f = l1.x;
                    float g = l2.x;
                    float h = record.HitPoint.x;
                    float i = Vertex[0].x;

                    float j = l1.y;
                    float k = l2.y;
                    float l = record.HitPoint.y;
                    float m = Vertex[0].y;

                    float n = l1.z;
                    float o = l2.z;
                    float p = record.HitPoint.z;
                    float q = Vertex[0].z;

                    float det = g * j - f * k;
                    if (det == 0)
                    {
                        det = o * j - n * k;
                        if (det == 0)
                        {
                            det = g * n - f * o;
                            j = n;
                            k = o;
                            l = p;
                            m = q;
                        }
                        else
                        {
                            f = n;
                            h = o;
                            h = p;
                            i = q;
                        }
                    }
                    if (det != 0)
                    {
                        float alpha = (g * l - g * m - h * k + i * k) / det;
                        float beta = (-f * l + f * m + h * j - i * j) / det;
                        //if (RenderingParameters.showMouse)
                        //{
                        //Console.WriteLine("alpha: " + alpha + "\tbeta: " + beta);

                        record.TextureColor = this.Material.GetTexturePixelColor(alpha, beta);
                    }
                   // }
                }

            }
            return isHit;
        }
 public abstract bool IsHit(Ray ray, HitRecord record, float near, float far);
        public override bool IsHit(Ray ray, HitRecord record, float near, float far)
        {
            //Vamos precalculando variables auxiliares para facilitar el calculo y aumentar eficiencia
            //Convencion de nombres usada es la misma del libro "Fundamentals of Computer Graphics":
            /*
             * | a d g | | beta  |   | j |
             * | b e h | | gamma | = | k |
             * | c f i | |   t   | = | l |
            */

            float a = Vertex[0].x - Vertex[1].x;
            float b = Vertex[0].y - Vertex[1].y;
            float c = Vertex[0].z - Vertex[1].z;

            float d = Vertex[0].x - Vertex[2].x;
            float e = Vertex[0].y - Vertex[2].y;
            float f = Vertex[0].z - Vertex[2].z;

            float g = ray.Direction.x;
            float h = ray.Direction.y;
            float i = ray.Direction.z;

            float j = Vertex[0].x - ray.Start.x;
            float k = Vertex[0].y - ray.Start.y;
            float l = Vertex[0].z - ray.Start.z;

            float eiMinushf = e * i - h * f;
            float gfMinusdi = g * f - d * i;
            float dhMinuseg = d * h - e * g;

            float akMinusjb = a * k - j * b;
            float jcMinusal = j * c - a * l;
            float blMinuskc = b * l - k * c;

            float M = a * eiMinushf + b * gfMinusdi + c * dhMinuseg;
            //e + td = punto triangulo
            float t = -(f * akMinusjb + e * jcMinusal + d * blMinuskc) / M;
            if (t >= 0)
            {
                float gamma = (i * akMinusjb + h * jcMinusal + g * blMinuskc) / M;
                if (gamma >= 0)
                {
                    float beta = (j * eiMinushf + k * gfMinusdi + l * dhMinuseg) / M;
                    //alpha = 1 - beta - gamma
                    if (beta >= 0 && 1 - beta - gamma >= 0)
                    {
                        Vector diff = t * ray.Direction;
                        float distance = diff.Magnitude3();
                        if (distance <= record.Distance && distance <= ray.MaximumTravelDistance)
                        {

                            if (ray.UseBounds)
                            {
                                float cameraOrthogonalDistance = Math.Abs(Vector.Dot3(diff, ray.CameraLookDirection));
                                if (cameraOrthogonalDistance > far && cameraOrthogonalDistance < near)
                                {
                                    return false;
                                }
                            }
                            record.T = t;
                            record.HitPoint = ray.Start + diff;
                            record.Distance = distance;
                            record.Material = Materials[0];
                            record.SurfaceNormal = SurfaceNormal(record.HitPoint, ray.Direction);

                            if (record.Material.TextureImage != null)
                            {
                                float alpha = 1 - beta - gamma;
                                float u = alpha * U[0] + beta * U[1] + gamma * U[2];
                                float v = alpha * V[0] + beta * V[1] + gamma * V[2];
                                record.TextureColor = record.Material.GetTexturePixelColor(u, v);
                            }

                            return true;
                        }
                    }
                }
            }
            return false;
        }