Пример #1
0
        public void A_ray_misses_a_CSG_object()
        {
            var csg           = new CsgShape(CsgOperation.Union, new Sphere(), new Cube());
            var ray           = new Ray(new Point(0, 2, -5), new Vector(0, 0, 1));
            var intersections = csg.LocalIntersect(ray);

            intersections.Should().BeEmpty();
        }
Пример #2
0
        public void A_ray_hits_a_CSG_object()
        {
            var left          = new Sphere();
            var right         = new Sphere(transform: Matrix4x4.CreateTranslation(0, 0, 0.5));
            var csg           = new CsgShape(CsgOperation.Union, left, right);
            var ray           = new Ray(new Point(0, 0, -5), new Vector(0, 0, 1));
            var intersections = csg.LocalIntersect(ray);

            intersections.Should().HaveCount(2);
            intersections.Ts.Should().ContainInOrder(4, 6.5);
            intersections.Shapes.Should().ContainInOrder(left, right);
        }
Пример #3
0
        public void A_CSG_shape_is_composed_of_an_operation_and_two_operand_shapes()
        {
            var sphere = new Sphere();
            var cube   = new Cube();
            var csg    = new CsgShape(CsgOperation.Union, sphere, cube);

            csg.Operation.Should().Be(CsgOperation.Union);
            csg.Left.Should().Be(sphere);
            csg.Right.Should().Be(cube);

            sphere.Parent.Should().Be(csg);
            cube.Parent.Should().Be(csg);
        }
Пример #4
0
 public void A_CSG_difference_preserves_all_intersections_not_exclusively_inside_the_object_on_the_right(
     bool isLeftHit,
     bool isWithinLeft,
     bool isWithinRight,
     bool expectedResult)
 {
     CsgShape.IsIntersectionAllowed(
         CsgOperation.Difference,
         isLeftHit,
         isWithinLeft,
         isWithinRight)
     .Should()
     .Be(expectedResult);
 }
Пример #5
0
 public void A_CSG_intersect_preserves_all_intersections_where_both_shapes_overlap(
     bool isLeftHit,
     bool isWithinLeft,
     bool isWithinRight,
     bool expectedResult)
 {
     CsgShape.IsIntersectionAllowed(
         CsgOperation.Intersection,
         isLeftHit,
         isWithinLeft,
         isWithinRight)
     .Should()
     .Be(expectedResult);
 }
Пример #6
0
 public void A_CSG_union_preserves_all_intersections_on_the_exterior_of_both_shapes(
     bool isLeftHit,
     bool isWithinLeft,
     bool isWithinRight,
     bool expectedResult)
 {
     CsgShape.IsIntersectionAllowed(
         CsgOperation.Union,
         isLeftHit,
         isWithinLeft,
         isWithinRight)
     .Should()
     .Be(expectedResult);
 }
Пример #7
0
        Given_a_set_of_intersections_produce_a_subset_of_only_those_intersections_that_conform_to_the_operation_of_the_current_CSG_object(
            CsgOperation operation,
            int intersectionIndex1,
            int intersectionIndex2)
        {
            var left          = new Sphere();
            var right         = new Cube();
            var csg           = new CsgShape(operation, left, right);
            var intersections = new IntersectionList((1, left), (2, right), (3, left), (4, right));
            var filtered      = csg.FilterIntersections(intersections);

            filtered.Should()
            .HaveCount(2)
            .And.ContainInOrder(intersections[intersectionIndex1], intersections[intersectionIndex2]);
        }
Пример #8
0
        protected override Canvas Render(CameraRenderOptions options)
        {
            // Shapes
            var floorCeiling = new Cube(
                "FloorCeiling",
                Matrix4x4.CreateTranslation(0, 1, 0).Scale(20, 7, 20),
                new Material(
                    pattern: new CheckerPattern(
                        Colors.Black,
                        Colors.DarkGray,
                        Matrix4x4.CreateScaling(0.07, 0.07, 0.07)),
                    ambient: 0.25,
                    diffuse: 0.7,
                    specular: 0.9,
                    shininess: 300,
                    reflective: 0.1));

            var walls = new Cube(
                "Walls",
                Matrix4x4.CreateScaling(10, 10, 10),
                new Material(
                    pattern: new CheckerPattern(
                        new Color(0.4863, 0.3765, 0.2941),
                        new Color(0.3725, 0.2902, 0.2275),
                        Matrix4x4.CreateScaling(0.05, 20, 0.05)),
                    ambient: 0.1,
                    diffuse: 0.7,
                    specular: 0.9,
                    shininess: 300,
                    reflective: 0.1));

            var csgUnion = new CsgShape(
                "Union",
                CsgOperation.Union,
                new Cube(
                    "YellowCube",
                    Matrix4x4.CreateTranslation(0, 1.5, 0),
                    new Material(Colors.Yellow, diffuse: 0.7, specular: 0.3)),
                new Sphere(
                    "RedSphere",
                    Matrix4x4.CreateTranslation(0.6, 2, -0.6),
                    new Material(Colors.Red, diffuse: 0.7, specular: 0.9)),
                transform: Matrix4x4.CreateRotationY(-Math.PI / 3).Translate(-4, 0, -2));

            var csgIntersection = new CsgShape(
                "Intersection",
                CsgOperation.Intersection,
                new Cube(
                    "YellowCube",
                    Matrix4x4.CreateTranslation(0, 1.5, 0),
                    new Material(Colors.Yellow, diffuse: 0.7, specular: 0.3)),
                new Sphere(
                    "RedSphere",
                    Matrix4x4.CreateTranslation(0.6, 2, -0.6),
                    new Material(Colors.Red, diffuse: 0.7, specular: 0.9)),
                transform: Matrix4x4.CreateRotationY(-Math.PI / 2).Translate(0, 0, -2));

            var csgDifference = new CsgShape(
                "Difference",
                CsgOperation.Difference,
                new Cube(
                    "YellowCube",
                    Matrix4x4.CreateTranslation(0, 1.5, 0),
                    new Material(Colors.Yellow, diffuse: 0.7, specular: 0.3)),
                new Sphere(
                    "RedSphere",
                    Matrix4x4.CreateTranslation(0.6, 2, -0.6),
                    new Material(Colors.Red, diffuse: 0.7, specular: 0)),
                transform: Matrix4x4.CreateRotationY(-Math.PI / 6).Translate(3, 0, 2));

            // Lights, camera, action.
            var light = new PointLight(new Point(8, 8, -5), Colors.White);
            var world = new World(light, floorCeiling, walls, csgUnion, csgIntersection, csgDifference);

            var cameraTransform = Matrix4x4.CreateLookAt(new Point(8, 6, -8), new Point(0, 3, 0), Vector.UnitY);
            var camera          = new Camera(CanvasWidth, CanvasHeight, fieldOfView: 0.785, cameraTransform);

            Canvas canvas = camera.Render(world, options);

            return(canvas);
        }