Ejemplo n.º 1
0
        public float[] TraceRay(float[] origin, float[] direction, float min_t, float max_t, float depth)
        {
            var intersection = ClosestIntersection(origin, direction, min_t, max_t);

            if (intersection.Item1 == null && intersection.Item2 == 0)
            {
                return(background_color);
            }
            Figure closest_figure = intersection.Item1;
            float  closest_t      = intersection.Item2;

            float[] point     = new float[3];
            float[] sec_point = new float[3];
            float[] res       = new float[3];
            point     = Add(origin, Multiply(closest_t, direction, res), point);
            sec_point = Add(origin, Multiply(intersection.Item3, direction, res), sec_point);
            float[] normal = intersection.Item4;


            float[] view = new float[3];
            //??
            view = Multiply(-1, direction, view);
            float lightning;

            //для блеска
            lightning = ComputeLighting(point, normal, view, closest_figure.specular);
            float[] local_color = new float[3];
            //вычисл лок цвет
            local_color = Multiply(lightning, closest_figure.color, local_color);
            if (closest_figure.reflective <= 0 || depth <= 0)
            {
                return(local_color);
            }
            float[] reflected_ray = new float[3];
            reflected_ray = ReflectRay(view, normal, reflected_ray);
            float[] reflected_color = new float[3];
            //вычисл цвет отражения
            reflected_color = TraceRay(point, reflected_ray, (float)0.001, float.MaxValue, depth - 1);
            float[] r1                = new float[3];
            float[] r2                = new float[3];
            float[] r3                = new float[3];
            float[] result            = new float[3];
            float[] transparent_color = new float[3];
            float[] transparent_ray   = new float[3];
            float[] a = new float[3];
            float[] b = new float[3];
            float[] c = new float[3];
            float[] k = new float[3];
            k = Multiply(-1, direction, k);
            a = Multiply(DotProduct(k, normal) * (float)1.49, k, a);
            b = Multiply((float)1.49, k, b);
            c = Multiply((float)Math.Sqrt(1 + (float)1.49 * (float)1.49 * DotProduct(k, normal) * DotProduct(k, normal) - 1), normal, c);
            transparent_ray = Subtract(a, b, transparent_ray);
            transparent_ray = Subtract(transparent_ray, c, transparent_ray);



            closest_figure.flag = 1;
            transparent_color   = TraceRay(sec_point, transparent_ray, 1, float.MaxValue, depth);
            closest_figure.flag = 0;
            //смеш цветов?
            r1 = Multiply(1 - closest_figure.reflective, local_color, r1);
            r2 = Multiply(closest_figure.reflective, reflected_color, r2);
            r3 = Multiply(closest_figure.transparent, transparent_color, r3);

            result = Add(r1, r2, result);
            result = Add(result, r3, result);
            return(result);
        }
Ejemplo n.º 2
0
        public Tuple <Figure, float, float, float[]> ClosestIntersection(float[] origin, float[] direction, float min_t, float max_t)
        {
            float sec_point = 0;

            float[] n      = new float[3];
            int[]   flag   = new int[2];
            float[] point  = new float[3];
            float[] res    = new float[3];
            float[] ress   = new float[3];
            float[] normal = new float[3];
            float[] ts     = new float[2];
            float[] tc     = new float[2];
            float   tcc;
            float   tt;
            float   closest_t      = float.MaxValue;
            Figure  closest_figure = null;

            for (int i = 0; i < spheres.Length; i++)
            {
                if (spheres[i].flag == 0)
                {
                    ts = IntersectRaySphere(origin, direction, spheres[i], ts);

                    if (ts[0] < closest_t && min_t < ts[0] && ts[0] < max_t)
                    {
                        closest_t      = ts[0];
                        closest_figure = spheres[i];
                        flag[0]        = 1;
                        flag[1]        = i;
                        sec_point      = ts[1];
                    }
                    if (ts[1] < closest_t && min_t < ts[1] && ts[1] < max_t)
                    {
                        closest_t      = ts[1];
                        closest_figure = spheres[i];
                        flag[0]        = 1;
                        flag[1]        = i;
                        sec_point      = ts[0];
                    }
                }
            }

            for (int i = 0; i < triangles.Length; i++)
            {
                if (triangles[i].flag == 0)
                {
                    float[] AB = new float[3];
                    AB = Subtract(triangles[i].point2, triangles[i].point1, AB);
                    float[] AC = new float[3];
                    AC = Subtract(triangles[i].point3, triangles[i].point1, AC);

                    n = VecMultiply(AB, AC, n);



                    tt = IntersectRayTriangle(origin, direction, triangles[i], n, AB);
                    //normal = Multiply(1 / Length(n), n, n);

                    if (tt < closest_t && min_t < tt && tt < max_t)
                    {
                        closest_t      = tt;
                        closest_figure = triangles[i];
                        flag[0]        = 0;
                        if (i % 2 != 0)
                        {
                            flag[1] = i - 1;
                        }
                        else
                        {
                            flag[1] = i;
                        }

                        //normal = Multiply(1 / Length(n), n, n);
                    }
                }
            }
            for (int i = 0; i < cilinders.Length; i++)
            {
                if (cilinders[i].flag == 0)
                {
                    tc = IntersectRayCilinder(origin, direction, cilinders[i], tc);
                    if (tc[0] < closest_t && min_t < tc[0] && tc[0] < max_t)
                    {
                        closest_t      = tc[0];
                        closest_figure = cilinders[i];
                        flag[0]        = 2;
                        flag[1]        = i;
                    }
                    if (tc[1] < closest_t && min_t < tc[1] && tc[1] < max_t)
                    {
                        closest_t      = tc[1];
                        closest_figure = cilinders[i];
                        flag[0]        = 2;
                        flag[1]        = i;
                    }
                }
            }



            if (closest_figure != null)
            {
                if (flag[0] == 1)
                {
                    point  = Add(origin, Multiply(closest_t, direction, res), point);
                    normal = Subtract(point, spheres[flag[1]].center, normal);
                    normal = Multiply(1 / Length(normal), normal, normal);
                }
                if (flag[0] == 2)
                {
                    point = Add(origin, Multiply(closest_t, direction, ress), point);
                    float[] M = new float[3];
                    M[0]   = cilinders[flag[1]].center[0];
                    M[1]   = point[1];
                    M[2]   = cilinders[flag[1]].center[2];
                    normal = Subtract(point, M, normal);
                    normal = Multiply(1 / Length(normal), normal, normal);
                }
                if (flag[0] == 0)
                {
                    float[] AB = new float[3];

                    float[] AC = new float[3];
                    AB = Subtract(triangles[flag[1]].point2, triangles[flag[1]].point1, AB);

                    AC = Subtract(triangles[flag[1]].point3, triangles[flag[1]].point1, AC);

                    normal = VecMultiply(AB, AC, normal);
                    //normal[0] = 2;
                    //normal[1] = 0;
                    //normal[2] = -2;
                    normal = Multiply(1 / Length(normal), normal, normal);
                }

                return(new Tuple <Figure, float, float, float[]>(closest_figure, closest_t, sec_point, normal));
            }
            return(new Tuple <Figure, float, float, float[]>(null, 0, 0, null));
        }