Пример #1
0
        public static Color Trace(Scene scene, Ray r, int max)
        {
            IntersectionResult tr = NearestIntersection(scene, r);

            if (tr.triangle != null)
            {
                //v1:
                //return scene.Materials[tr.MaterialIndex].Color;
                // v2:
                Color c = new Color(0, 0, 0, 1);

                // contribuição luz ambiente:
                foreach (var light in scene.Lights)
                {
                    c += light.Color * scene.Materials[tr.triangle.MaterialIndex].Color *
                        scene.Materials[tr.triangle.MaterialIndex].Ambient;
                }

                // contribuição luz difusa
                foreach (var light in scene.Lights)
                {
                    Vector3 l = light.Position - tr.point;
                    float dist = Vector3.Length(l);
                    l = Vector3.Normalize(l);
                    float cost = tr.triangle.Normal.Dot(l);

                    Ray s = new Ray()
                    {
                        origin = tr.point,
                        direction = l
                    };

                    if (IsExposedToLight(scene, s, dist) && cost > 0)
                        c = c + light.Color * scene.Materials[tr.triangle.MaterialIndex].Color
                            * scene.Materials[tr.triangle.MaterialIndex].Diffuse * cost;
                }

                // reflection, material reflective?
                if (scene.Materials[tr.triangle.MaterialIndex].Reflection > 0.0f)
                {
                    float c1 = -tr.triangle.Normal.Dot(r.direction);
                    Vector3 rl = Vector3.Normalize(r.direction + (tr.triangle.Normal * 2.0f * c1));
                    Ray refl = new Ray()
                    {
                        origin = tr.point,
                        direction = rl
                    };

                    c += (max > 0 ? Ray.Trace(scene, refl, --max) : new Color(0, 0, 0)) *
                        scene.Materials[tr.triangle.MaterialIndex].Reflection *
                        scene.Materials[tr.triangle.MaterialIndex].Color;
                }
                else if (scene.Materials[tr.triangle.MaterialIndex].RefractionCoef > 0.0f)
                {
                    Vector3 n1 = new Vector3();
                    double m1, m2;
                    if (RayEnters(r.direction, tr.triangle.Normal))
                    {
                        n1 = tr.triangle.Normal;
                        m1 = 1.0f; // air
                        m2 = scene.Materials[tr.triangle.MaterialIndex].RefractionIndex;
                    }
                    else
                    {
                        n1 = tr.triangle.Normal * -1;
                        m1 = scene.Materials[tr.triangle.MaterialIndex].RefractionIndex;
                        m2 = 1.0f;
                    }

                    double c1 = -(n1).Dot(r.direction);
                    double m = m1 / m2;
                    double c2 = Math.Sqrt(1 - m * m * (1 - c1 * c1));

                    Vector3 rr = Vector3.Normalize((r.direction * (float)m) + n1 * (float)(m * c1 - c2));
                    Ray refr = new Ray()
                    {
                        origin = tr.point,
                        direction = rr
                    };

                    c += (max > 0 ? Ray.Trace(scene, refr, --max) : new Color(0, 0, 0)) *
                         scene.Materials[tr.triangle.MaterialIndex].RefractionCoef  *
                         scene.Materials[tr.triangle.MaterialIndex].Color;
                }

                return c;
            }

            return scene.Image.Color;
        }
Пример #2
0
        private static IntersectionResult NearestIntersection(Scene scene, Ray r)
        {
            Vector3 intersectionPoint = new Vector3(0, 0, 0);
            double tmin = double.MaxValue;
            Triangle nearestTriangle = null;
            foreach (Solid s in scene.Solids)
            {
                foreach (Triangle tr in s.Triangles)
                {
                    float t = (float)Intersection(r, tr);
                    if (t > 0 && t < tmin)
                    {
                        tmin = t;
                        nearestTriangle = tr;
                        intersectionPoint = r.origin + (r.direction * t); // p(t)
                    }
                }
            }

            return new IntersectionResult() {
                triangle = nearestTriangle,
                point = intersectionPoint
            };
        }
Пример #3
0
        private static double Intersection(Ray r, Triangle tr)
        {
            double[,] a = new double[3, 3] {
                {tr.Points[0].X - tr.Points[1].X, tr.Points[0].X - tr.Points[2].X, r.direction.X},
                {tr.Points[0].Y - tr.Points[1].Y, tr.Points[0].Y - tr.Points[2].Y, r.direction.Y},
                {tr.Points[0].Z - tr.Points[1].Z, tr.Points[0].Z - tr.Points[2].Z, r.direction.Z}};

            double detA = Determinant(a);

            double[,] b = new double[3, 3] {
                {tr.Points[0].X - r.origin.X, tr.Points[0].X - tr.Points[2].X, r.direction.X},
                {tr.Points[0].Y - r.origin.Y, tr.Points[0].Y - tr.Points[2].Y, r.direction.Y},
                {tr.Points[0].Z - r.origin.Z, tr.Points[0].Z - tr.Points[2].Z, r.direction.Z}};

            double detB = Determinant(b) / detA;

            if (detB < 0) return -1;

            double[,] y = new double[3, 3] {
                {tr.Points[0].X - tr.Points[1].X, tr.Points[0].X - r.origin.X, r.direction.X},
                {tr.Points[0].Y - tr.Points[1].Y, tr.Points[0].Y - r.origin.Y, r.direction.Y},
                {tr.Points[0].Z - tr.Points[1].Z, tr.Points[0].Z - r.origin.Z, r.direction.Z}};

            double detY = Determinant(y) / detA;

            if (detY < 0) return -1;

            if (detB + detY >= 1) return -1;

            double[,] t = new double[3, 3] {
                {tr.Points[0].X - tr.Points[1].X, tr.Points[0].X - tr.Points[2].X, tr.Points[0].X  - r.origin.X},
                {tr.Points[0].Y - tr.Points[1].Y, tr.Points[0].Y - tr.Points[2].Y, tr.Points[0].Y  - r.origin.Y},
                {tr.Points[0].Z - tr.Points[1].Z, tr.Points[0].Z - tr.Points[2].Z, tr.Points[0].Z  - r.origin.Z}};

            double detT = Determinant(t) / detA;

            if (detT < EPSILON) return -1;

            return detT;
        }
Пример #4
0
        private static bool IsExposedToLight(Scene scene, Ray r, float dist)
        {
            // if (intersection  => light : triangles) return true; // basta encontrar 1 (mas dentro da largura entre a luz e o ponto)
            foreach (Solid s in scene.Solids)
            {
                foreach (Triangle tr in s.Triangles)
                {
                    float t = (float)Intersection(r, tr);

                    if (t > 0 && t < dist) return false;
                }
            }

            return true;
        }
Пример #5
0
        void bgWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            if (myScene != null)
            {
                stopwatch.Reset();
                stopwatch.Start();

                try
                {
                    Bitmap bmp = new Bitmap(myScene.Image.Horizontal, myScene.Image.Vertical);
                    System.Drawing.Color[,] bmData = new System.Drawing.Color[myScene.Image.Horizontal, myScene.Image.Vertical];
                    //byte[] colorArray = new byte[myScene.Images[0].Horizontal * myScene.Images[0].Vertical];

                    float height = 2 * myScene.Camera.Distance *
                               (float)Math.Tan((myScene.Camera.FieldOfView * (Math.PI / 180.0f)) / 2);
                    float width = myScene.Image.Horizontal / myScene.Image.Vertical * height;

                    float pixelSize = width / myScene.Image.Horizontal;

                    Vector3 origin = new Vector3(myScene.Camera.Position.X, myScene.Camera.Position.Y, myScene.Camera.Distance);

                    int c = 0;
                    Parallel.ForEach(Partitioner.Create(0, myScene.Image.Horizontal), range =>
                    {
                        //Console.WriteLine("BLOCK PARALLEL");
                        for (int i = range.Item1; i < range.Item2; i++)
                        {
                            for (int y = 0; y < myScene.Image.Vertical; y++)
                            //Parallel.For(0, myScene.Images[0].Vertical, y =>
                            {
                                float px = pixelSize * (i + 0.5f) - (width / 2);
                                float py = pixelSize * (y + 0.5f) - (height / 2);
                                Vector3 df = new Vector3(px, py, 0) - origin;
                                Vector3 direction = Vector3.Normalize(df);

                                Ray r = new Ray()
                                {
                                    Direction = direction,
                                    Origin = origin
                                };

                                Enox.Framework.Color color = Ray.Trace(myScene, r, myScene.RecursionDepth);

                                float red = (color.R > 1 ? 1 : color.R);
                                float green = (color.G > 1 ? 1 : color.G);
                                float blue = (color.B > 1 ? 1 : color.B);

                                //lock (mutex)
                                //{
                                //    bmp.SetPixel(i, y,
                                //        System.Drawing.Color.FromArgb((int)(255), (int)(red * 255),
                                //        (int)(green * 255), (int)(blue * 255)));
                                //}

                                bmData[i, y] = System.Drawing.Color.FromArgb((int)(255), (int)(red * 255),
                                                (int)(green * 255), (int)(blue * 255));

                                c++;
                                bgWorker.ReportProgress(c * 100 / (myScene.Image.Horizontal * myScene.Image.Vertical));

                            }
                        }
                        // });
                    });

                    // store pixel data on bitmap:
                    for (int i = 0; i < myScene.Image.Horizontal; i++)
                    {
                        for (int y = 0; y < myScene.Image.Vertical; y++)
                        {
                            bmp.SetPixel(i, y, bmData[i, y]);
                        }
                    }

                    // old way (without parallelism)
                    //for (int i = 0; i < myScene.Images[0].Horizontal; i++)
                    //{
                    //    for (int y = 0; y < myScene.Images[0].Vertical; y++)
                    //    {
                    //        float px = pixelSize * (i + 0.5f) - (width / 2);
                    //        float py = pixelSize * (y + 0.5f) - (height / 2);
                    //        Vector3 df = new Vector3(px, py, 0) - origin;
                    //        Vector3 direction = Vector3.Normalize(df);

                    //        Ray r = new Ray()
                    //        {
                    //            Direction = direction,
                    //            Origin = origin
                    //        };

                    //        Enox.Framework.Color color = Ray.Trace(myScene, r, 2);

                    //        float red = (color.R > 1 ? 1 : color.R);
                    //        float green = (color.G > 1 ? 1 : color.G);
                    //        float blue = (color.B > 1 ? 1 : color.B);

                    //        bmp.SetPixel(i, y,
                    //            System.Drawing.Color.FromArgb((int)(255), (int)(red * 255),
                    //            (int)(green * 255), (int)(blue * 255)));
                    //    }
                    //}

                    //for (int i = 0; i < 3; i++)
                    //{
                    //    for (int y = 0; y < 3; y++)
                    //    {
                    //        Task t = new Task(() =>
                    //        {
                    //            int myi = i;
                    //            int myy = y;
                    //            Console.WriteLine(myi + "**" + myy);
                    //            float rangeX = divx * myi + divx;
                    //            for (int l = divx * myi; l < rangeX; l++)
                    //            {
                    //                float rangeY = divy * myy + divy;
                    //                for (int c = divy * myy; c < rangeY; c++)
                    //                {

                    //                    float px = pixelSize * (myi + 0.5f) - (width / 2);
                    //                    float py = pixelSize * (myy + 0.5f) - (height / 2);
                    //                    Vector3 df = new Vector3(px, py, 0) - origin;
                    //                    Vector3 direction = Vector3.Normalize(df);

                    //                    Ray r = new Ray()
                    //                    {
                    //                        Direction = direction,
                    //                        Origin = origin
                    //                    };

                    //                    Enox.Framework.Color color = Ray.Trace(myScene, r, 2);

                    //                    float red = (color.R > 1 ? 1 : color.R);
                    //                    float green = (color.G > 1 ? 1 : color.G);
                    //                    float blue = (color.B > 1 ? 1 : color.B);

                    //                    lock (mutex)
                    //                    {
                    //                        //try
                    //                        //{
                    //                        bmp.SetPixel(l, c,
                    //                            System.Drawing.Color.FromArgb((int)(255), (int)(red * 255),
                    //                            (int)(green * 255), (int)(blue * 255)));
                    //                        //}
                    //                        //catch (Exception ex)
                    //                        //{
                    //                        //    Console.WriteLine(ex.ToString());
                    //                        //}
                    //                    }
                    //                }
                    //            }
                    //        });
                    //        t.Start();
                    //        tasks.Add(t);
                    //    }
                    //}

                    //for (int i = 0; i < myScene.Images[0].Horizontal; i++)
                    //{
                    //    for (int y = 0; y < myScene.Images[0].Vertical; y++)
                    //    {
                    // construir raio(i, j)
                    // Color c = RayTrace(r);
                    // pixel[i, j] = c;

                    // origin camera  = (0, 0, d); d = 3
                    // direçao = normalize((px, py, pz) - (origin))
                    // px = pixelSize * (i + 0.5f) - (width/2)
                    // py = pixelSize * (y + 0.5f) - (height/2)
                    // pz = 0

                    //#if DEBUG
                    //                            if (i == 0 && y == 100)
                    //                            {
                    //                                //Console.WriteLine(direction);
                    //                                Console.WriteLine("color: " + c);
                    //                            }
                    //#endif
                    //    }
                    //}

                    //Task.WaitAll(tasks.ToArray());

                    bmp.RotateFlip(RotateFlipType.Rotate180FlipX);
                    pictureBox1.Image = bmp;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "Error!");
                }
            }
        }