Пример #1
0
        public static void ComplexScene(int numTrials)
        {
            // the scene is compressed to avoid git issues
            if (!File.Exists("../Data/breakfast_room.obj"))
            {
                ZipFile.ExtractToDirectory("../Data/breakfast_room.zip", "../Data");
            }

            Stopwatch           stop   = Stopwatch.StartNew();
            List <TriangleMesh> meshes = new();
            Vector3             min    = Vector3.One * float.MaxValue;
            Vector3             max    = -Vector3.One * float.MaxValue;

            Assimp.AssimpContext context = new();
            var scene = context.ImportFile("../Data/breakfast_room.obj",
                                           Assimp.PostProcessSteps.GenerateNormals | Assimp.PostProcessSteps.JoinIdenticalVertices |
                                           Assimp.PostProcessSteps.PreTransformVertices | Assimp.PostProcessSteps.Triangulate);

            foreach (var m in scene.Meshes)
            {
                var    material     = scene.Materials[m.MaterialIndex];
                string materialName = material.Name;

                Vector3[] vertices = new Vector3[m.VertexCount];
                for (int i = 0; i < m.VertexCount; ++i)
                {
                    vertices[i] = new(m.Vertices[i].X, m.Vertices[i].Y, m.Vertices[i].Z);
                }

                meshes.Add(new(vertices, m.GetIndices()));

                min.X = MathF.Min(min.X, m.BoundingBox.Min.X);
                min.Y = MathF.Min(min.X, m.BoundingBox.Min.Y);
                min.Z = MathF.Min(min.X, m.BoundingBox.Min.Z);

                max.X = MathF.Max(max.X, m.BoundingBox.Max.X);
                max.Y = MathF.Max(max.X, m.BoundingBox.Max.Y);
                max.Z = MathF.Max(max.X, m.BoundingBox.Max.Z);
            }

            var diagonal = max - min;

            Console.WriteLine($"Scene loaded in {stop.ElapsedMilliseconds}ms");
            stop.Restart();

            var rt = new Raytracer();

            foreach (var m in meshes)
            {
                rt.AddMesh(m);
            }
            rt.CommitScene();

            Console.WriteLine($"Acceleration structures built in {stop.ElapsedMilliseconds}ms");

            Random rng = new(1337);

            Vector3 NextVector() => new Vector3(
                (float)rng.NextDouble(),
                (float)rng.NextDouble(),
                (float)rng.NextDouble());

            stop.Restart();
            float averageDistance = 0;

            for (int k = 0; k < numTrials; ++k)
            {
                for (int i = 0; i < 1000000; ++i)
                {
                    var hit = rt.Trace(new Ray {
                        Origin      = NextVector() * diagonal + min,
                        Direction   = NextVector(),
                        MinDistance = 0.0f
                    });

                    if (hit)
                    {
                        averageDistance += hit.Distance / 1000000 / numTrials;
                    }
                }
            }
            stop.Stop();
            Console.WriteLine($"One million closest hits found in {stop.ElapsedMilliseconds / numTrials}ms");
            Console.WriteLine($"Average distance: {averageDistance}");

            stop.Restart();
            float averageVisibility = 0;

            for (int k = 0; k < numTrials; ++k)
            {
                for (int i = 0; i < 1000000; ++i)
                {
                    bool occluded = rt.IsOccluded(new ShadowRay(new Ray {
                        Origin      = NextVector() * diagonal + min,
                        Direction   = NextVector(),
                        MinDistance = 0.0f
                    }, maxDistance: (float)rng.NextDouble() * averageDistance * 5));

                    if (!occluded)
                    {
                        averageVisibility += 1.0f / 1000000.0f / numTrials;
                    }
                }
            }
            stop.Stop();
            Console.WriteLine($"One million any hits found in {stop.ElapsedMilliseconds / numTrials}ms");
            Console.WriteLine($"Average visibility: {averageVisibility}");
        }