Exemplo n.º 1
0
        public IntersectionInfo Intersection(Ray r)
        {
            Vector3D normal = VectorOperations.VectorProduct(new Vector3D(A, B), new Vector3D(A, C));

            normal *= (1 / normal.Length);

            Vector3D V = new Vector3D(r.Origin.X - A.X, r.Origin.Y - A.Y, r.Origin.Z - A.Z);

            //определяем пересекает ли луч треугольник
            double t = -VectorOperations.ScalarProduct(V, normal) / VectorOperations.ScalarProduct(r.Direction, normal);

            if (t <= epsilon || Double.IsNaN(t) || Double.IsInfinity(t))
            {
                return(null);
            }

            Point3D crossPoint = new Point3D(r.Origin.X + r.Direction.X * t,
                                             r.Origin.Y + r.Direction.Y * t,
                                             r.Origin.Z + r.Direction.Z * t);

            Vector3D OX = new Vector3D(A, B);
            Vector3D AC = new Vector3D(A, C);
            Vector3D AD = new Vector3D(A, crossPoint);
            Vector3D OY = VectorOperations.VectorProduct(normal, OX);

            Line3D axis     = new Line3D(A, OX);
            Line3D ordinate = new Line3D(A, OY);

            double Bx = VectorOperations.Distance(ordinate, B);
            double By = 0;

            double Cx = VectorOperations.Distance(ordinate, C) * ((VectorOperations.Cos(OX, AC) < 0)? -1 : 1);
            double Cy = VectorOperations.Distance(axis, C) * ((VectorOperations.Cos(OY, AC) < 0)? -1 : 1);

            double Dx = VectorOperations.Distance(ordinate, crossPoint) * ((VectorOperations.Cos(OX, AD) < 0)? -1 : 1);
            double Dy = VectorOperations.Distance(axis, crossPoint) * ((VectorOperations.Cos(OY, AD) < 0) ? -1 : 1);

            int s1 = Math.Sign(Bx * Dy - By * Dx);
            int s2 = Math.Sign((Cx - Bx) * (Dy - By) - (Cy - By) * (Dx - Bx));
            int s3 = Math.Sign(-Cx * (Dy - Cy) + Cy * (Dx - Cx));

            if (s1 == s2 && s1 == s3 && s2 == s3)
            {
                Material m = ownerSurface.MaterialFront;
                if (VectorOperations.Cos(normal, r.Direction) >= -epsilon && (ownerSurface.MaterialBack != null))
                {
                    normal *= (-1);
                    m       = ownerSurface.MaterialBack;
                }

                return(new IntersectionInfo(crossPoint, normal, m));
            }

            return(null);
        }
Exemplo n.º 2
0
        internal bool IsVisible(Light L, Point3D P)
        {//видим ли источник света из данной точки
            Vector3D v = new Vector3D(P, L.Position);
            //для упрощения: если источник закрыт прозрачным предметом, то считаем, что он в тени
            IntersectionInfo info = this.GetFirstIntersection(new Ray(P, v));

            if (info == null)
            {
                return(true);
            }
            else
            {
                return(VectorOperations.Distance(P, L.Position) < VectorOperations.Distance(P, info.CrossPoint));
            }
        }
Exemplo n.º 3
0
        internal IntersectionInfo GetFirstIntersection(Ray r)
        {
            IntersectionInfo res      = null;
            double           distance = Double.MaxValue;

            foreach (IGraphicsObject3D obj in graphicObjects)
            {
                IntersectionInfo info = obj.Intersection(r);
                if (info != null)
                {
                    if (VectorOperations.Distance(info.CrossPoint, r.Origin) < distance)
                    {
                        distance = VectorOperations.Distance(info.CrossPoint, r.Origin);
                        res      = info;
                    }
                }
            }
            return(res);
        }
Exemplo n.º 4
0
        public IntersectionInfo Intersection(Ray r)
        {
            Vector3D N = VectorOperations.VectorProduct(new Vector3D(A, B), new Vector3D(A, C));

            //нормаль определяет внешнюю и внутреннюю сторону треугольника
            N *= (1 / N.Length);
            Vector3D V = new Vector3D(r.Origin.X - A.X,
                                      r.Origin.Y - A.Y,
                                      r.Origin.Z - A.Z);
            double t = -VectorOperations.ScalarProduct(V, N) / VectorOperations.ScalarProduct(r.Direction, N);

            if (t <= epsilon || Double.IsNaN(t) || Double.IsInfinity(t))
            {
                return(null);
            }

            Point3D crossPoint = new Point3D(r.Origin.X + r.Direction.X * t,
                                             r.Origin.Y + r.Direction.Y * t,
                                             r.Origin.Z + r.Direction.Z * t);

            Vector3D OX = new Vector3D(A, B);
            Vector3D AC = new Vector3D(A, C);
            Vector3D AD = new Vector3D(A, crossPoint);
            Vector3D OY = VectorOperations.VectorProduct(N, OX);

            Line3D axis     = new Line3D(A, OX);
            Line3D ordinate = new Line3D(A, OY);

            double Bx = VectorOperations.Distance(ordinate, B);
            double By = 0;

            double Cx = VectorOperations.Distance(ordinate, C);

            if (VectorOperations.Cos(OX, AC) < 0)
            {
                Cx *= -1;
            }

            double Cy = VectorOperations.Distance(axis, C);

            if (VectorOperations.Cos(OY, AC) < 0)
            {
                Cy *= -1;
            }

            double Dx = VectorOperations.Distance(ordinate, crossPoint);

            if (VectorOperations.Cos(OX, AD) < 0)
            {
                Dx *= -1;
            }

            double Dy = VectorOperations.Distance(axis, crossPoint);

            if (VectorOperations.Cos(OY, AD) < 0)
            {
                Dy *= -1;
            }


            int s1 = Math.Sign(Bx * Dy - By * Dx);
            int s2 = Math.Sign((Cx - Bx) * (Dy - By) - (Cy - By) * (Dx - Bx));
            int s3 = Math.Sign(-Cx * (Dy - Cy) + Cy * (Dx - Cx));

            if (s1 == s2 && s1 == s3 && s2 == s3)
            {
                Material m = material_front;
                if (VectorOperations.Cos(N, r.Direction) >= -epsilon && (material_back != null))
                {
                    N *= (-1);
                    m  = material_back;
                }

                return(new IntersectionInfo(crossPoint, N, m));
            }

            return(null);
        }
Exemplo n.º 5
0
        //public Material Material
        //{
        //    set
        //    {
        //        material = value;
        //    }
        //}
        public IntersectionInfo Intersection(Ray r)
        {
            double   epsilon = 0.01;
            Vector3D v       = new Vector3D(r.Origin.X - center.X, r.Origin.Y - center.Y, r.Origin.Z - center.Z);
            double   A       = r.Direction.LengthSquare;
            double   B       = VectorOperations.ScalarProduct(r.Direction, v);
            double   C       = v.LengthSquare - radius * radius;
            double   D       = B * B - A * C;

            if (D <= 0.0)
            {
                return(null);
            }

            double t1 = (-B - Math.Sqrt(D)) / A;
            double t2 = (-B + Math.Sqrt(D)) / A;
            double t  = t1;

            if (t2 <= epsilon)
            {
                return(null);
            }

            if (t1 <= epsilon)    //луч идет из шара
            {
                t = t2;
            }

            Point3D P = new Point3D(r.Origin.X + r.Direction.X * t,
                                    r.Origin.Y + r.Direction.Y * t,
                                    r.Origin.Z + r.Direction.Z * t); //первая точка пересечения

            Vector3D N = new Vector3D(center, P);                    //вектор нормали единичной длины

            N *= (1 / N.Length);
            if (t1 <= epsilon)    //луч идет из шара
            {
                N *= (-1.0);
            }


            if (texture != null)
            {
                Point3D E = new Point3D(P.X - center.X, P.Y - center.Y, P.Z - center.Z);
                double  psi, fi;
                psi = Math.Asin(E.Z / radius);

                if (Math.Abs(psi) == Math.PI / 2)
                {
                    fi = 0;
                }
                else
                {
                    double cosfi = E.X / (radius * Math.Cos(psi));
                    if (cosfi > 1)
                    {
                        cosfi = 1;
                    }
                    if (cosfi < -1)
                    {
                        cosfi = -1;
                    }
                    fi = Math.Acos(cosfi);
                    if (E.Y < 0)
                    {
                        fi = 2 * Math.PI - fi;
                    }
                }
                Material m;
                lock (texture)
                {
                    int x = (int)((fi / (Math.PI * 2)) * (texture.Width - 1));
                    int y = (int)((0.5 - psi / Math.PI) * (texture.Height - 1));
                    m = new Material(texture.GetPixel(x, y), material.Diffusion, material.Specularity,
                                     material.Reflection, material.Transparency, material.FongCoeff);
                }
                material = m;
            }
            return(new IntersectionInfo(P, N, material));
        }
Exemplo n.º 6
0
        internal Color RayTracing(Ray r, int depth)
        {
            if (depth > 5)
            {
                return(Color.Black);
            }

            IntersectionInfo info = GetFirstIntersection(r);

            if (info == null)   //луч не пересекает предмет
            {
                return(defaultColor);
            }

            double R = 0, G = 0, B = 0;
            //луч пересекает предмет

            double IdR = 0, IdG = 0, IdB = 0;
            double IsR = 0, IsG = 0, IsB = 0;
            double pFong = info.Material.FongCoeff;   //

            foreach (Light L in lights)
            {
                Vector3D V = new Vector3D(info.CrossPoint, L.Position); //направление на источник L
                V *= (1 / V.Length);

                if (this.IsVisible(L, info.CrossPoint))
                {
                    double distance    = VectorOperations.Distance(L.Position, info.CrossPoint);
                    double attenuation = L.Attenuation(distance);

                    if (info.Material.Diffusion > 0)    //для предмета задано свойство диффузного отражения
                    {
                        double cos = VectorOperations.Cos(info.Normal, V);
                        if (cos < 0)
                        {
                            cos = 0;
                        }

                        IdR += L.Color.R * cos / attenuation;
                        IdG += L.Color.G * cos / attenuation;
                        IdB += L.Color.B * cos / attenuation;
                    }
                    if (info.Material.Specularity > 0)  //для предмета задано свойство зеркального отражения
                    {
                        Vector3D reflected;
                        if (VectorOperations.ReflectedVector(info.Normal, r.Direction, out reflected))
                        {
                            double cos = VectorOperations.Cos(V, reflected);
                            if (cos < 0)
                            {
                                cos = 0;
                            }

                            IsR += L.Color.R * Math.Pow(cos, pFong) / attenuation;
                            IsG += L.Color.G * Math.Pow(cos, pFong) / attenuation;
                            IsB += L.Color.B * Math.Pow(cos, pFong) / attenuation;
                        }
                    }
                }
            }
            R += info.Material.Diffusion * IdR * info.Material.Color.R / 255;
            G += info.Material.Diffusion * IdG * info.Material.Color.G / 255;
            B += info.Material.Diffusion * IdB * info.Material.Color.B / 255;

            R += info.Material.Specularity * IsR;
            G += info.Material.Specularity * IsG;
            B += info.Material.Specularity * IsB;

            if (info.Material.Reflection > 0)
            {
                Vector3D reflected;
                if (VectorOperations.ReflectedVector(info.Normal, r.Direction, out reflected))
                {
                    Ray   reflectedRay   = new Ray(info.CrossPoint, reflected);
                    Color reflectedColor = this.RayTracing(reflectedRay, depth + 1);

                    R += info.Material.Reflection * reflectedColor.R;
                    G += info.Material.Reflection * reflectedColor.G;
                    B += info.Material.Reflection * reflectedColor.B;
                }
            }
            if (info.Material.Transparency > 0)
            {
                double   n12 = info.Material.RefractiveIndex;
                Vector3D refracted;

                if (VectorOperations.RefractedVector(info.Normal, r.Direction, n12, out refracted))
                {
                    Ray   refractedRay   = new Ray(info.CrossPoint, refracted);
                    Color refractedColor = this.RayTracing(refractedRay, depth + 1);

                    R += info.Material.Transparency * refractedColor.R;
                    G += info.Material.Transparency * refractedColor.G;
                    B += info.Material.Transparency * refractedColor.B;
                }
            }

            R += info.Material.Color.R * Ka;
            G += info.Material.Color.G * Ka;
            B += info.Material.Color.B * Ka;
            return(Color.FromArgb(Math.Min((int)R, 255), Math.Min((int)G, 255), Math.Min((int)B, 255)));
        }