Ejemplo n.º 1
0
        public void DivideSubdividesChildren()
        {
            var s1 = new Sphere();

            s1.SetTransform(Transform.Translate(-1.5f, 0, 0));
            var s2 = new Sphere();

            s2.SetTransform(Transform.Translate(1.5f, 0, 0));
            var left = new Group(s1, s2);
            var s3   = new Sphere();

            s3.SetTransform(Transform.Translate(0, 0, -1.5f));
            var s4 = new Sphere();

            s4.SetTransform(Transform.Translate(0, 0, 1.5f));
            var right = new Group(s3, s4);
            var s     = new ConstructiveSolid(ConstructiveOp.Difference, left, right);

            s.Divide(1);
            var lg   = (Group)s.Left;
            var rg   = (Group)s.Right;
            var lsg1 = (Group)lg.Children[0];

            lsg1.Children.Should().Contain(s1);
            var lsg2 = (Group)lg.Children[1];

            lsg2.Children.Should().Contain(s2);
            var rsg1 = (Group)rg.Children[0];

            rsg1.Children.Should().Contain(s3);
            var rsg2 = (Group)rg.Children[1];

            rsg2.Children.Should().Contain(s4);
        }
Ejemplo n.º 2
0
        public void RayMissesSolid()
        {
            var c  = new ConstructiveSolid(ConstructiveOp.Union, new Sphere(), new Cube());
            var r  = new Ray(new Point(0, 2, -5), new Vector(0, 0, 1));
            var xs = c.LocalIntersects(in r);

            xs.Count.Should().Be(0);
        }
Ejemplo n.º 3
0
        public void ContainsOperationAndTwoShapes()
        {
            var s1 = new Sphere();
            var s2 = new Cube();
            var c  = new ConstructiveSolid(ConstructiveOp.Union, s1, s2);

            c.Left.Should().Be(s1);
            c.Right.Should().Be(s2);
            s1.Parent.Should().Be(c);
            s2.Parent.Should().Be(c);
        }
Ejemplo n.º 4
0
        public void IntersectTestChildrenIfRayHitsBounds()
        {
            var l   = new TestGeometry();
            var r   = new TestGeometry();
            var s   = new ConstructiveSolid(ConstructiveOp.Difference, l, r);
            var ray = new Ray(new Point(0, 0, -5), new Vector(0, 0, 1));
            var xs  = s.Intersects(ray);

            // Child tested so SavedRay in not default.
            l.SavedRay.Should().NotBe(new Ray());
            r.SavedRay.Should().NotBe(new Ray());
        }
Ejemplo n.º 5
0
        public void IntersectDoesNotTestChildrenIfRayMissesBounds()
        {
            var l   = new TestGeometry();
            var r   = new TestGeometry();
            var s   = new ConstructiveSolid(ConstructiveOp.Difference, l, r);
            var ray = new Ray(new Point(0, 0, -5), new Vector(0, 1, 0));
            var xs  = s.Intersects(ray);

            // Child not tested so SavedRay remains default.
            l.SavedRay.Should().Be(new Ray());
            r.SavedRay.Should().Be(new Ray());
        }
Ejemplo n.º 6
0
        public void BoundsContainsChildren()
        {
            var l = new Sphere();
            var r = new Sphere();

            r.SetTransform(Transform.Translate(2, 3, 4));
            var s = new ConstructiveSolid(ConstructiveOp.Difference, l, r);
            var b = s.LocalBounds();

            b.Min.Should().Be(new Point(-1, -1, -1));
            b.Max.Should().Be(new Point(3, 4, 5));
        }
Ejemplo n.º 7
0
        private static ConstructiveSolid CutPips(ConstructiveSolid csg, Material material)
        {
            Sphere PipSphere(Point point, Material mat)
            {
                var sphere = new Sphere();

                sphere.SetTransform(Transform.Scale(0.2f).Translate(point.X, point.Y, point.Z));
                sphere.SetMaterial(mat);
                return(sphere);
            }

            ConstructiveSolid Diff(IGeometry s, IGeometry child) => new ConstructiveSolid(ConstructiveOp.Difference, s, child);

            var offset = 1.15f;

            // 1
            csg = Diff(csg, PipSphere(new Point(0, 0, -offset), material));

            //2
            csg = Diff(csg, PipSphere(new Point(0.4f, offset, 0.4f), material));
            csg = Diff(csg, PipSphere(new Point(-0.4f, offset, -0.4f), material));

            //3
            csg = Diff(csg, PipSphere(new Point(-offset, 0.4f, 0.4f), material));
            csg = Diff(csg, PipSphere(new Point(-offset, -0.4f, -0.4f), material));
            csg = Diff(csg, PipSphere(new Point(-offset, 0.0f, 0.0f), material));

            //4
            csg = Diff(csg, PipSphere(new Point(offset, 0.4f, 0.4f), material));
            csg = Diff(csg, PipSphere(new Point(offset, -0.4f, -0.4f), material));
            csg = Diff(csg, PipSphere(new Point(offset, -0.4f, 0.4f), material));
            csg = Diff(csg, PipSphere(new Point(offset, 0.4f, -0.4f), material));

            //5
            csg = Diff(csg, PipSphere(new Point(0.4f, -offset, 0.4f), material));
            csg = Diff(csg, PipSphere(new Point(-0.4f, -offset, -0.4f), material));
            csg = Diff(csg, PipSphere(new Point(-0.4f, -offset, 0.4f), material));
            csg = Diff(csg, PipSphere(new Point(0.4f, -offset, -0.4f), material));

            //6
            csg = Diff(csg, PipSphere(new Point(0.4f, 0.4f, offset), material));
            csg = Diff(csg, PipSphere(new Point(0.0f, 0.4f, offset), material));
            csg = Diff(csg, PipSphere(new Point(-0.4f, 0.4f, offset), material));
            csg = Diff(csg, PipSphere(new Point(0.4f, -0.4f, offset), material));
            csg = Diff(csg, PipSphere(new Point(0.0f, -0.4f, offset), material));
            csg = Diff(csg, PipSphere(new Point(-0.4f, -0.4f, offset), material));

            return(csg);
        }
Ejemplo n.º 8
0
        public void RayHitsSolid()
        {
            var s1 = new Sphere();
            var s2 = new Sphere();

            s2.SetTransform(Transform.TranslateZ(0.5f));
            var c  = new ConstructiveSolid(ConstructiveOp.Union, s1, s2);
            var r  = new Ray(new Point(0, 0, -5), new Vector(0, 0, 1));
            var xs = c.LocalIntersects(in r);

            xs.Count.Should().Be(2);
            xs[0].T.Should().Be(4f);
            xs[0].Geometry.Should().Be(s1);
            xs[1].T.Should().Be(6.5f);
            xs[1].Geometry.Should().Be(s2);
        }
Ejemplo n.º 9
0
        private static World BuildWorld()
        {
            Console.WriteLine("Loading file...");
            var filePath = Path.Combine(GetExecutionPath(), "indoor_env.ppm");

            //var filePath = Path.Combine(GetExecutionPath(), "winter_river_1k.ppm");
            Console.WriteLine("Parsing file...");
            var textureCanvas = PPM.ParseFile(filePath);
            var image         = new UVImage(textureCanvas);
            var map           = new TextureMap(image, UVMapping.Spherical);

            var skySphere = new Sphere
            {
                Material =
                {
                    Texture       = map,            Ambient = 1.5f, CastsShadows = false, Transparency = 0f, Roughness = 1f,
                    SpecularColor = new Color(0.0f, 0.0f, 0.0f)
                }
            };

            //skySphere.SetTransform(Transforms.RotateY(3.4f).Scale(1000f));
            skySphere.SetTransform(Transform.RotateY(3.3f).Scale(10000f));

            var s1 = new StripeTexture(Colors.White, Colors.Black);
            var s2 = new StripeTexture(Colors.White, Colors.Black);

            s2.SetTransform(Transform.RotateY(MathF.PI / 2));
            var pattern = new BlendedCompositeTexture(s1, s2);

            pattern.SetTransform(Transform.Scale(1f / 20f));

            var testPattern =
                new UVAlignTestPattern(Colors.White, Colors.Red, Colors.Yellow, Colors.Green, Colors.Blue);
            var testMap = new TextureMap(testPattern, UVMapping.Cylindrical);

            //var stripe = new StripePattern(new Color(0.9f, 0, 0), new Color(0.0f, 0.0f, 0.9f));
            //stripe.SetTransform(Transforms.Scale(0.25f, 0.25f, 0.25f).RotateY(MathF.PI / 4));
            //var perlin = new PerlinRippleCompositePattern(stripe, 0.8f);
            //perlin.SetTransform(Transforms.Scale(0.1f, 0.1f, 0.1f));

            var worldFilePath = Path.Combine(GetExecutionPath(), "world.ppm");
            var worldCanvas   = PPM.ParseFile(worldFilePath);
            var worldTexture  = new UVImage(worldCanvas);
            var worldPattern  = new TextureMap(worldTexture, UVMapping.Spherical);

            var floor = new Cube
            {
                Material =
                {
                    Texture       = pattern,
                    Specular      =           0.1f,
                    Reflective    =           0.1f,
                    Roughness     =          0.22f,
                    Ambient       =             0f,
                    SpecularColor = new Color(0.1f, 0.1f, 0.1f)
                }
            };

            floor.SetTransform(Transform.TranslateY(-1).Scale(20f));

            var middle = new Sphere
            {
                Material =
                {
                    Texture   = worldPattern, Diffuse  = 0.7f, Specular      =             1f, Reflective = 0.4f, Shininess = 600,
                    Roughness =         0.2f, Metallic = 0.3f, SpecularColor = new Color(0.1f,0.2f, 0.5f), Ambient = 0f
                }
            };

            middle.SetTransform(Transform.RotateY(1.5f).Translate(-0.5f, 1f, 0.1f));

            var right = new Sphere
            {
                Material =
                {
                    Texture       = new TextureMap(new UVCheckers(20,   10, Colors.Black, Colors.White), UVMapping.Spherical),
                    Roughness     =                             0.5f,
                    Diffuse       =                             0.7f,
                    Specular      =                             0.3f,
                    Reflective    =                             0.2f,
                    Ambient       =                               0f,
                    SpecularColor = new Color(0.2f,                   0.2f, 0.2f)
                }
            };

            right.SetTransform(Transform.Translate(0.25f, 0.25f, -1f) * Transform.Scale(0.25f));

            var rightPlastic = new Sphere
            {
                Material =
                {
                    Texture       = new SolidColor(new Color(1f, 0.0f, 0.0f)),
                    SpecularColor = new Color(0.2f,              0.2f,  0.2f),
                    Roughness     =                       0.25f, Metallic = 0f,
                    Ambient       = 0.0f
                }
            };

            rightPlastic.SetTransform(Transform.Translate(-0.15f, 0.15f, -0.91f) * Transform.Scale(0.15f));

            var left = new Sphere
            {
                Material =
                {
                    Texture       = new SolidColor(new Color(0.85f, 0.85f, 0.90f)),
                    SpecularColor = new Color(0.3f,                  0.3f,   0.3f),
                    Roughness     =                          0.10f, Metallic = 0.6f,
                    Transparency  =                          0.95f, RefractiveIndex = 1.52f,Ambient = 0.0f
                }
            };

            left.SetTransform(Transform.Translate(-1.3f, 0.30f, -0.75f) * Transform.Scale(0.30f));
            // left.SetTransform(Transforms.Translate(-2.1f, 0.33f, 0.5f) * Transforms.Scale(0.33f, 0.33f, 0.33f));

            var leftChrome = new Sphere
            {
                Material =
                {
                    Texture       = new SolidColor(new Color(0.9f,  0.9f, 0.95f)), Diffuse = 0.05f, Specular  = 0.9f,
                    SpecularColor = new Color(0.9f,                 0.9f,  0.95f),
                    Roughness     =                         0.55f, Metallic = 1f,
                    Transparency  =                             0, RefractiveIndex = 1.52f,Reflective = 1.4f, Ambient = 0.0f, Shininess = 300
                }
            };

            leftChrome.SetTransform(Transform.Translate(-0.95f, 0.15f, -1.1f) * Transform.Scale(0.15f));

            var cube = new Cube
            {
                Material =
                {
                    Texture = new GradientTexture(new Color(1f,              0,   0), new Color(1f, 0.8f, 0f)), Roughness = 0.5f,
                    Ambient =                               0f, SpecularColor = new Color(0.2f,0.2f, 0.2f)
                }
            };

            cube.Material.Texture.SetTransform(Transform.TranslateX(-0.5f).Scale(2f).RotateZ(MathF.PI / 2f));
            cube.SetTransform(Transform.RotateY(MathF.PI / 4f).Translate(2.5f, 1f, 3.6f).Scale(1f, 1f, 1f));

            var cone = new Cone
            {
                IsClosed = true,
                Minimum  = -1f,
                Maximum  = 0f,
                Material =
                {
                    Texture       = new SolidColor(new Color(0.4f, 0.8f, 0.1f)), Diffuse = 0.7f, Specular = 0.3f,
                    Ambient       =                            0f,
                    SpecularColor = new Color(0.2f,                0.2f,  0.2f),
                    Roughness     =                          0.6f,
                    Reflective    = 0.2f
                }
            };

            cone.SetTransform(Transform.Scale(0.6f, 2f, 0.6f).Translate(1.5f, 2.0f, 0));

            var cylinder = new Cylinder
            {
                Minimum  = 0f,
                Maximum  = 3f,
                IsClosed = true,
                Material =
                {
                    Reflective = 0.33f, Specular      =           0.9f, Diffuse   =  0.1f, Ambient = 0.0f, Shininess = 100,
                    Metallic   = 0.76f, SpecularColor = new Color(0.9f, 0.8f, 0.7f), Roughness = 0.02f,
                    Texture    = testMap
                }
            };

            cylinder.SetTransform(Transform.Translate(-3f, 0f, 3.5f));

            //var t = new Triangle(new Point(0, 0, 0), new Point(1, 0.5f, 0), new Point(0.5f, 1f, 1f))
            //{
            //    Material = {Texture = new GradientTexture(new Color(0f, 1, 0), new Color(0f, 0f, 1f))}
            //};
            //t.SetTransform(Transforms.Translate(1f, 2f, 1f));

            var ringMaterial = new Material
            {
                Texture         = new SolidColor(new Color(1f, 0.8f, 0f)),
                Reflective      = 0.4f,
                RefractiveIndex = 0.95f,
                Roughness       = 0.12f,
                Metallic        = 1f,
                SpecularColor   = new Color(0.9f, 0.7f, 0f),
                //Transparency = 0.95f,
                Shininess = 300,
                Specular  = 0.9f,
                Ambient   = 0.0f,
                Diffuse   = 0.3f
            };
            var co = new Cylinder
            {
                Minimum  = -0.01f,
                Maximum  = 0.01f,
                IsClosed = true
            };

            co.SetTransform(Transform.Scale(1.5f, 1f, 1.5f));
            co.SetMaterial(ringMaterial);

            var ci = new Cylinder
            {
                Minimum  = -0.1f,
                Maximum  = 0.1f,
                IsClosed = true
            };

            ci.SetTransform(Transform.Scale(1.2f, 1f, 1.2f));
            ci.SetMaterial(ringMaterial);

            var s = new ConstructiveSolid(ConstructiveOp.Difference, co, ci);

            s.SetTransform(Transform.RotateZ(-0.2f).RotateX(-0.1f).Translate(-0.5f, 1f, 0.1f));

            var gl = new Group();

            gl.AddChild(middle);
            gl.AddChild(left);
            gl.AddChild(leftChrome);
            gl.AddChild(cylinder);
            gl.AddChild(s);
            gl.AddChild(right);
            gl.AddChild(rightPlastic);
            gl.AddChild(cube);
            gl.AddChild(cone);
            //gl.AddChild(t);
            gl.AddChild(floor);
            gl.AddChild(skySphere);

            gl.Divide(1);

            var w = new World();

            w.SetLights(new AreaLight(new Point(-80f, 80, -60), new Vector(100f, 0, 0), 6, new Vector(0, 0f, -10f), 3,
                                      new Color(1.8f, 1.8f, 1.8f), new Sequence(0.7f, 0.3f, 0.9f, 0.1f, 0.5f)));

            //w.SetLights(new PointLight(new Point(-3.5f, 4f, -5f), new Color(0.9f, 0.9f, 0.9f)));
            w.SetObjects(gl);
            return(w);
        }
Ejemplo n.º 10
0
        private static ConstructiveSolid RoundedCube(float radius, Material mat)
        {
            ConstructiveSolid SolidFaces(float r)
            {
                var cY = new Cube();

                cY.SetTransform(Transform.Scale(1f - r, 1f, 1f - r));
                cY.SetMaterial(mat);

                var cX = new Cube();

                cX.SetTransform(Transform.Scale(1f, 1f - r, 1f - r));
                cX.SetMaterial(mat);
                var su = new ConstructiveSolid(ConstructiveOp.Union, cY, cX);

                var cZ = new Cube();

                cZ.SetTransform(Transform.Scale(1f - r, 1f - r, 1f));
                cZ.SetMaterial(mat);
                return(new ConstructiveSolid(ConstructiveOp.Union, su, cZ));
            }

            ConstructiveSolid Union(IGeometry a, IGeometry b) => new ConstructiveSolid(ConstructiveOp.Union, a, b);

            Cylinder CreateCylinder(float r, Point from, Material material, Transform rotation)
            {
                var dist    = 1f - r;
                var fOffset = from * dist;
                var e       = new Cylinder {
                    Minimum = 0f, Maximum = 2f * dist / r, IsClosed = true
                };

                e.SetMaterial(material);
                e.SetTransform(Transform.Scale(r).Apply(rotation).Translate(fOffset.X, fOffset.Y, fOffset.Z));
                return(e);
            }

            Sphere Corner(float r, Point corner, Material material)
            {
                var dist   = 1f - r;
                var offset = corner * dist;
                var sphere = new Sphere();

                sphere.SetTransform(Transform.Scale(r).Translate(offset.X, offset.Y, offset.Z));
                sphere.SetMaterial(material);
                return(sphere);
            }

            Cylinder EdgeX(float r, Point from, Material material) =>
            CreateCylinder(r, from, material, Transform.RotateZ(-MathF.PI / 2));

            Cylinder EdgeY(float r, Point from, Material material) =>
            CreateCylinder(r, from, material, Transform.Identity);

            Cylinder EdgeZ(float r, Point from, Material material) =>
            CreateCylinder(r, from, material, Transform.RotateX(MathF.PI / 2));

            var s      = SolidFaces(radius);
            var points = new[]
            {
                new Point(-1, 1, -1),
                new Point(1, 1, -1),
                new Point(1, 1, 1),
                new Point(-1, 1, 1),
                new Point(-1, -1, -1),
                new Point(1, -1, -1),
                new Point(1, -1, 1),
                new Point(-1, -1, 1)
            };

            foreach (var point in points)
            {
                s = Union(s, Corner(radius, point, mat));
                if (point.X < 0f)
                {
                    s = Union(s, EdgeX(radius, point, mat));
                }

                if (point.Y < 0f)
                {
                    s = Union(s, EdgeY(radius, point, mat));
                }

                if (point.Z < 0f)
                {
                    s = Union(s, EdgeZ(radius, point, mat));
                }
            }

            return(s);
        }