Esempio n. 1
0
        //отражение

        /*
         * Направление отраженного луча определяется по закону:
         * отраженный луч = падающий луч -  2* нормаль к точке попадания луча на сторону  на скалярное произведение падающего луча и нормали
         * из презентации
         */
        public Ray Reflect(PointXYZ hit_point, PointXYZ normal)
        {
            //высчитываем направление отраженного луча
            PointXYZ reflect_dir = End - 2 * normal * PointXYZ.ScalarMul(End, normal);

            return(new Ray(hit_point, hit_point + reflect_dir));
        }
Esempio n. 2
0
        //модель освещения
        public PointXYZ Lumiance(PointXYZ hit_point, PointXYZ normal, PointXYZ material_color, float diffuse_coef)
        {
            PointXYZ direction = PointXYZ.normal(point_light - hit_point);// направление луча
            //если угол между нормалью и направлением луча больше 90 градусов,то диффузное  освещение равно 0
            PointXYZ diff = diffuse_coef * color_light * Math.Max(PointXYZ.ScalarMul(normal, direction), 0);

            return(new PointXYZ(diff.X * material_color.X, diff.Y * material_color.Y, diff.Z * material_color.Z));
        }
Esempio n. 3
0
        public bool TriangleInter(Ray r, PointXYZ p0, PointXYZ p1, PointXYZ p2, out float intersect)
        {
            intersect = -1;
            PointXYZ edge1 = p1 - p0;
            PointXYZ edge2 = p2 - p0;
            PointXYZ h     = r.End * edge2;
            float    a     = PointXYZ.ScalarMul(edge1, h);

            if (a > -0.0001 && a < 0.0001)
            {
                return(false);       // Этот луч параллелен этому треугольнику.
            }
            float    f = 1.0f / a;
            PointXYZ s = r.Start - p0;
            float    u = f * PointXYZ.ScalarMul(s, h);

            if (u < 0 || u > 1)
            {
                return(false);
            }
            PointXYZ q = s * edge1;
            float    v = f * PointXYZ.ScalarMul(r.End, q);

            if (v < 0 || u + v > 1)
            {
                return(false);
            }
            // На этом этапе мы можем вычислить t, чтобы узнать, где находится точка пересечения на линии.
            float t = f * PointXYZ.ScalarMul(edge2, q);

            if (t > 0.0001)
            {
                intersect = t;
                return(true);
            }
            else      //Это означает, что есть пересечение линий, но не пересечение лучей.
            {
                return(false);
            }
        }
Esempio n. 4
0
        //преломление
        //все вычисления взяты из презентации
        public Ray Refract(PointXYZ hit_point, PointXYZ normal, float refraction, float refract_coef)
        {
            Ray   res_ray = new Ray();
            float sclr    = PointXYZ.ScalarMul(normal, End);

            /*
             * Если луч падает,то он проходит прямо,не преломляясь
             */
            float n1n2div       = refraction / refract_coef;
            float theta_formula = 1 - n1n2div * n1n2div * (1 - sclr * sclr);

            if (theta_formula >= 0)
            {
                float cos_theta = (float)Math.Sqrt(theta_formula);
                res_ray.Start = new PointXYZ(hit_point);
                res_ray.End   = PointXYZ.normal(End * n1n2div - (cos_theta + n1n2div * sclr) * normal);
                return(res_ray);
            }
            else
            {
                return(null);
            }
        }
Esempio n. 5
0
        public PointXYZ RTAlgotithm(Ray r, int iter, float env)
        {
            if (iter <= 0)
            {
                return(new PointXYZ(0, 0, 0));
            }
            float intersectionRayFigure = 0;// позиция точки пересечения луча с фигурой на луче
            //нормаль стороны фигуры,с которой пересекся луч
            PointXYZ normal    = null;
            Surface  surface   = new Surface();
            PointXYZ res_color = new PointXYZ(0, 0, 0);

            bool isFigureRefrat = false;

            foreach (var f in figuresList)
            {
                if (f.FigureIntersection(r, out float intersect, out PointXYZ norm))
                {
                    if (intersect < intersectionRayFigure || intersectionRayFigure == 0)// нужна ближайшая фигура к точке наблюдения
                    {
                        intersectionRayFigure = intersect;
                        normal  = norm;
                        surface = new Surface(f.FigureSurface);
                    }
                }
            }

            if (intersectionRayFigure == 0)    //если не пересекается с фигурой
            {
                return(new PointXYZ(0, 0, 0)); //Луч уходит в свободное пространство .Возвращаем значение по умолчанию
            }
            //угол между направление луча и нормалью стороны острый
            //определяем из какой среды в какую
            //http://edu.glavsprav.ru/info/zakon-prelomleniya-sveta/
            if (PointXYZ.ScalarMul(r.End, normal) > 0)
            {
                normal        *= -1;
                isFigureRefrat = true;
            }


            //Точка пересечения луча с фигурой
            PointXYZ hit_point = r.Start + r.End * intersectionRayFigure;

            /*В точке пересечения луча с объектом строится три вторичных
             * луча – один в направлении отражения (1), второй – в направлении
             * источника света (2), третий в направлении преломления
             * прозрачной поверхностью (3).
             */

            //цвет коэффициент принятия фонового освещения
            PointXYZ lightk = raySource.color_light * surface.ambient;

            lightk.X   = (lightk.X * surface.Color.X);
            lightk.Y   = (lightk.Y * surface.Color.Y);
            lightk.Z   = (lightk.Z * surface.Color.Z);
            res_color += lightk;

            //диффузное освещение
            //если точка пересечения луча с объектом видна из источника света
            float raydist = (raySource.point_light - hit_point).Distance(); //координаты источника света луча
            Ray   tmp_r   = new Ray(hit_point, raySource.point_light);

            foreach (Figure fig in figuresList)
            {
                if (fig.FigureIntersection(tmp_r, out float t, out PointXYZ n))
                {
                    if (t < raydist || t > 0.0001)
                    {
                        res_color += raySource.Lumiance(hit_point, normal, surface.Color, surface.diffuse);
                    }
                }
            }



            /*Для отраженного луча
             * проверяется возможность
             * пересечения с другими
             * объектами сцены.
             *
             *  Если пересечений нет, то
             *  интенсивность и цвет
             *  отраженного луча равна
             *  интенсивности и цвету фона.
             *
             *  Если пересечение есть, то в
             *  новой точке снова строится
             *  три типа лучей – теневые,
             *  отражения и преломления.
             */
            if (surface.reflection > 0)
            {
                Ray refray = r.Reflect(hit_point, normal);
                res_color += surface.reflection * RTAlgotithm(refray, iter - 1, env);
            }


            //расчет коэфициентов преломления
            if (surface.refraction > 0)
            {
                //взависимости от того,из какой среды в какую,будет меняться коэффициент приломления
                float refractk;
                if (isFigureRefrat)
                {
                    refractk = surface.environment;
                }
                else
                {
                    refractk = 1 / surface.environment;
                }

                Ray refracted_ray = r.Refract(hit_point, normal, surface.refraction, refractk);//создаем приломленный луч

                /*
                 * Как и в предыдущем случае,
                 * проверяется пересечение вновь
                 * построенного луча с объектами,
                 * и, если они есть, в новой точке
                 * строятся три луча, если нет – используется интенсивность и
                 * цвет фона.
                 */
                if (refracted_ray != null)
                {
                    res_color += surface.refraction * RTAlgotithm(refracted_ray, iter - 1, surface.environment);
                }
            }
            return(res_color);
        }