public SCNPhysicsBody CreatePlanePhysics(SCNGeometry geometry)
        {
            var body = SCNPhysicsBody.CreateStaticBody();

            body.PhysicsShape = SCNPhysicsShape.Create(geometry, new NSDictionary());
            body.Restitution  = 0.5f;
            body.Friction     = 0.5f;

            return(body);
        }
Ejemplo n.º 2
0
        void SetupCollisionNodes(SCNNode node)
        {
            if (node.Geometry != null)
            {
                Console.WriteLine(node.Name);
                node.PhysicsBody = SCNPhysicsBody.CreateStaticBody();
                node.PhysicsBody.CategoryBitMask = (nuint)(int)Bitmask.Collision;

                var options = new SCNPhysicsShapeOptions {
                    ShapeType = SCNPhysicsShapeType.ConcavePolyhedron
                };
                node.PhysicsBody.PhysicsShape = SCNPhysicsShape.Create(node, options);

                // Get grass area to play the right sound steps
                if (node.Geometry.FirstMaterial.Name == "grass-area")
                {
                    if (grassArea != null)
                    {
                        node.Geometry.FirstMaterial = grassArea;
                    }
                    else
                    {
                        grassArea = node.Geometry.FirstMaterial;
                    }
                }

                // Get the water area
                if (node.Geometry.FirstMaterial.Name == "water")
                {
                    waterArea = node.Geometry.FirstMaterial;
                }

                // Temporary workaround because concave shape created from geometry instead of node fails
                SCNNode child = SCNNode.Create();
                node.AddChildNode(child);
                child.Hidden   = true;
                child.Geometry = node.Geometry;
                node.Geometry  = null;
                node.Hidden    = false;

                if (node.Name == "water")
                {
                    node.PhysicsBody.CategoryBitMask = (nuint)(int)Bitmask.Water;
                }
            }

            foreach (SCNNode child in node.ChildNodes)
            {
                if (!child.Hidden)
                {
                    SetupCollisionNodes(child);
                }
            }
        }
        SCNNode CreatePokemonNodeFromFile(string filePath, string nodeName, SCNVector3 vector)
        {
            var pScene  = SCNScene.FromFile(filePath);
            var pokemon = pScene.RootNode.FindChildNode(nodeName, true);

            pokemon.Position    = vector;
            pokemon.PhysicsBody = SCNPhysicsBody.CreateStaticBody();
            pokemon.PhysicsBody.PhysicsShape       = SCNPhysicsShape.Create(pokemon);
            pokemon.PhysicsBody.ContactTestBitMask = (int)BitMaskCategory.Pokeball;
            pokemon.PhysicsBody.CategoryBitMask    = (int)BitMaskCategory.Pokemon;
            return(pokemon);
        }
        public override SCNPhysicsBody CreatePlanePhysics(SCNGeometry geometry)
        {
            var body = SCNPhysicsBody.CreateStaticBody();

            body.PhysicsShape = SCNPhysicsShape.Create(geometry, new SCNPhysicsShapeOptions {
                ShapeType = SCNPhysicsShapeType.BoundingBox
            });
            body.Restitution = 0.5f;
            body.Friction    = 0.5f;

            return(body);
        }
Ejemplo n.º 5
0
        private void SetupInvironment(SCNScene scene)
        {
            var ambientLight = SCNNode.Create();

            ambientLight.Light = new SCNLight {
                LightType = SCNLightType.Ambient,
                Color     = UIColor.FromWhiteAlpha(0.3f, 1f)
            };
            scene.RootNode.AddChildNode(ambientLight);

            var lightNode = new SCNNode {
                Position = new SCNVector3(0f, 80f, 30f),
                Rotation = new SCNVector4(1f, 0f, 0f, (float)(-Math.PI / 2.8))
            };

            lightNode.Light = new SCNLight {
                LightType      = SCNLightType.Spot,
                Color          = UIColor.FromWhiteAlpha(0.8f, 1f),
                SpotInnerAngle = 0f,
                SpotOuterAngle = 50f,
                ShadowColor    = UIColor.Black,
                ZFar           = 500f,
                ZNear          = 50f
            };

            if (IsHighEndDevice)
            {
                ambientLight.Light.CastsShadow = true;
            }

            scene.RootNode.AddChildNode(lightNode);

            spotLightNode = lightNode;

            var floor = SCNNode.Create();

            floor.Geometry = new SCNFloor();
            floor.Geometry.FirstMaterial.Diffuse.Contents          = ResourceManager.GetResourcePath("wood.png");
            floor.Geometry.FirstMaterial.Diffuse.ContentsTransform = SCNMatrix4.Scale(2f, 2f, 1f);
            floor.Geometry.FirstMaterial.LocksAmbientWithDiffuse   = true;

            if (IsHighEndDevice)
            {
                ((SCNFloor)floor.Geometry).ReflectionFalloffEnd = 10f;
            }

            var staticBody = SCNPhysicsBody.CreateStaticBody();

            floor.PhysicsBody = staticBody;
            scene.RootNode.AddChildNode(floor);
        }
Ejemplo n.º 6
0
        public void SCNNode_SetPhysicsBodyTest()
        {
            Asserts.EnsureYosemite();

            if (IntPtr.Size == 8)
            {
                // Create a new empty scene
                var Scene = new SCNScene();

                var floorNode = SCNNode.Create();
                Scene.RootNode.AddChildNode(floorNode);

                floorNode.PhysicsBody    = SCNPhysicsBody.CreateStaticBody();
                Scene.PhysicsWorld.Speed = 0;
            }
        }
Ejemplo n.º 7
0
        private SCNNode CreateConcreteNode(ARPlaneAnchor planeAnchor)
        {
            SCNNode concreteNode = new SCNNode();

            concreteNode.Geometry = SCNPlane.Create(planeAnchor.Extent.X, planeAnchor.Extent.Z);
            concreteNode.Geometry.FirstMaterial.Diffuse.Contents = new UIImage("Concrete.png");
            concreteNode.Geometry.FirstMaterial.DoubleSided      = true;
            concreteNode.Position    = new SCNVector3(planeAnchor.Center.X, planeAnchor.Center.Y, planeAnchor.Center.Z);
            concreteNode.EulerAngles = new SCNVector3(ConvertDegreesToRadians(90), 0, 0);

            //TODO 4.1 Creando superficie
            SCNPhysicsBody staticBody = SCNPhysicsBody.CreateStaticBody();

            concreteNode.PhysicsBody = staticBody;

            return(concreteNode);
        }
Ejemplo n.º 8
0
        private void PresentWalls(PresentationViewController presentationViewController)
        {
            //add spheres and container
            var height = 2;
            var width  = 1;

            var count  = 3;
            var margin = 2;

            var totalWidth = count * (margin + width);

            var blockMesh = CreateBlockMesh(new SCNVector3(width, height, width));

            for (int i = 0; i < count; i++)
            {
                //create a static block
                var wall = SCNNode.Create();
                wall.Position    = new SCNVector3((i - (count / 2)) * (width + margin), -height / 2, totalWidth / 2);
                wall.Geometry    = blockMesh;
                wall.Name        = "container-wall";
                wall.PhysicsBody = SCNPhysicsBody.CreateStaticBody();

                GroundNode.AddChildNode(wall);
                wall.RunAction(SCNAction.MoveBy(new SCNVector3(0, height, 0), 0.5f));

                //one more
                wall          = (SCNNode)wall.Copy();
                wall.Position = new SCNVector3((i - (count / 2)) * (width + margin), -height / 2, -totalWidth / 2);
                GroundNode.AddChildNode(wall);

                // one more
                wall          = (SCNNode)wall.Copy();
                wall.Position = new SCNVector3(totalWidth / 2, -height / 2, (i - (count / 2)) * (width + margin));
                GroundNode.AddChildNode(wall);

                //one more
                wall          = (SCNNode)wall.Copy();
                wall.Position = new SCNVector3(-totalWidth / 2, -height / 2, (i - (count / 2)) * (width + margin));
                GroundNode.AddChildNode(wall);
            }
        }
        public PresentationViewController(string path)
        {
            // Load the presentation settings from the plist file
            var settingsPath = NSBundle.MainBundle.PathForResource(path, "xml");

            SlideSettings = JsonConvert.DeserializeObject <Settings> (File.ReadAllText(settingsPath));

            SlideCache = new Dictionary <string, Slide> ();

            // Create a new empty scene
            Scene = new SCNScene();

            // Create and add a camera to the scene
            // We create three separate nodes to ease the manipulation of the global position, pitch (ie. orientation around the x axis) and relative position
            // - cameraHandle is used to control the global position in world space
            // - cameraPitch  is used to rotate the position around the x axis
            // - cameraNode   is sometimes manipulated by slides to move the camera relatively to the global position (cameraHandle). But this node is supposed to always be repositioned at (0, 0, 0) in the end of a slide.

            CameraHandle      = SCNNode.Create();
            CameraHandle.Name = "cameraHandle";
            Scene.RootNode.AddChildNode(CameraHandle);

            CameraPitch      = SCNNode.Create();
            CameraPitch.Name = "cameraPitch";
            CameraHandle.AddChildNode(CameraPitch);

            CameraNode        = SCNNode.Create();
            CameraNode.Name   = "cameraNode";
            CameraNode.Camera = new SCNCamera();

            // Set the default field of view to 70 degrees (a relatively strong perspective)
            CameraNode.Camera.XFov = 70.0;
            CameraNode.Camera.YFov = 42.0;
            CameraPitch.AddChildNode(CameraNode);

            // Setup the different lights
            InitLighting();

            // Create and add a reflective floor to the scene
            var floorMaterial = new SCNMaterial();

            floorMaterial.Ambient.Contents          = NSColor.Black;
            floorMaterial.Diffuse.Contents          = new NSImage(NSBundle.MainBundle.PathForResource("SharedTextures/floor", "png"));
            floorMaterial.Diffuse.ContentsTransform = SCNMatrix4.CreateFromAxisAngle(new SCNVector3(0, 0, 1), NMath.PI / 4);
            floorMaterial.Specular.WrapS            =
                floorMaterial.Specular.WrapT        =
                    floorMaterial.Diffuse.WrapS     =
                        floorMaterial.Diffuse.WrapT = SCNWrapMode.Mirror;

            Floor = SCNFloor.Create();
            Floor.ReflectionFalloffEnd = 3.0f;
            Floor.FirstMaterial        = floorMaterial;

            var floorNode = SCNNode.Create();

            floorNode.Geometry = Floor;
            Scene.RootNode.AddChildNode(floorNode);

            floorNode.PhysicsBody    = SCNPhysicsBody.CreateStaticBody(); //make floor dynamic for physics slides
            Scene.PhysicsWorld.Speed = 0;                                 //pause physics to avoid continuous drawing

            // Use a shader modifier to support a secondary texture for some slides
            var shaderFile      = NSBundle.MainBundle.PathForResource("Shaders/floor", "shader");
            var surfaceModifier = File.ReadAllText(shaderFile);

            floorMaterial.ShaderModifiers = new SCNShaderModifiers {
                EntryPointSurface = surfaceModifier
            };

            // Set the scene to the view
            View = new SCNView(CGRect.Empty);
            ((SCNView)View).Scene           = Scene;
            ((SCNView)View).BackgroundColor = NSColor.Black;

            // black fog
            Scene.FogColor         = NSColor.FromCalibratedWhite(0, 1);
            Scene.FogEndDistance   = 45;
            Scene.FogStartDistance = 40;

            // Turn on jittering for better anti-aliasing when the scene is still
            ((SCNView)View).JitteringEnabled = true;

            // Start the presentation
            GoToSlide(0);
        }
Ejemplo n.º 10
0
        private void SetupSceneElements(SCNScene scene)
        {
            AddTrainToScene(scene, new SCNVector3(-5f, 20f, -40f));
            AddWoodenBlockToScene(scene, ResourceManager.GetResourcePath("WoodCubeA.jpg"), new SCNVector3(-10f, 15f, 10f));
            AddWoodenBlockToScene(scene, ResourceManager.GetResourcePath("WoodCubeB.jpg"), new SCNVector3(-9f, 10f, 10f));
            AddWoodenBlockToScene(scene, ResourceManager.GetResourcePath("WoodCubeC.jpg"), new SCNVector3(20f, 15f, -11f));
            AddWoodenBlockToScene(scene, ResourceManager.GetResourcePath("WoodCubeA.jpg"), new SCNVector3(25f, 5f, -20f));

            var wallBox = new SCNBox {
                Width         = 400f,
                Height        = 100f,
                Length        = 4f,
                ChamferRadius = 0f
            };

            var wall = SCNNode.FromGeometry(wallBox);

            wall.Geometry.FirstMaterial.Diffuse.Contents          = ResourceManager.GetResourcePath("wall.jpg");
            wall.Geometry.FirstMaterial.Diffuse.ContentsTransform = SCNMatrix4.Mult(
                SCNMatrix4.Scale(24f, 2f, 1f),
                SCNMatrix4.CreateTranslation(0f, 1f, 0f)
                );

            wall.Geometry.FirstMaterial.Diffuse.WrapS = SCNWrapMode.Repeat;
            wall.Geometry.FirstMaterial.Diffuse.WrapT = SCNWrapMode.Mirror;
            wall.Geometry.FirstMaterial.DoubleSided   = false;
            wall.CastsShadow = false;
            wall.Geometry.FirstMaterial.LocksAmbientWithDiffuse = true;

            wall.Position    = new SCNVector3(0f, 50f, -92f);
            wall.PhysicsBody = SCNPhysicsBody.CreateStaticBody();
            scene.RootNode.AddChildNode(wall);

            wall          = wall.Clone();
            wall.Position = new SCNVector3(202f, 50f, 0f);
            wall.Rotation = new SCNVector4(0f, 1f, 0f, (float)Math.PI / 2f);
            scene.RootNode.AddChildNode(wall);

            wall          = wall.Clone();
            wall.Position = new SCNVector3(-202f, 50f, 0f);
            wall.Rotation = new SCNVector4(0f, 1f, 0f, -(float)Math.PI / 2f);
            scene.RootNode.AddChildNode(wall);

            var planeGeometry = new SCNPlane {
                Width  = 400f,
                Height = 100f
            };

            var backWall = SCNNode.FromGeometry(planeGeometry);

            backWall.Geometry.FirstMaterial = wall.Geometry.FirstMaterial;
            backWall.Position    = new SCNVector3(0f, 50f, 200f);
            backWall.Rotation    = new SCNVector4(0f, 1f, 0f, (float)Math.PI);
            backWall.CastsShadow = false;
            backWall.PhysicsBody = SCNPhysicsBody.CreateStaticBody();
            scene.RootNode.AddChildNode(backWall);

            planeGeometry = new SCNPlane {
                Width  = 400f,
                Height = 400f
            };

            var ceilNode = SCNNode.FromGeometry(planeGeometry);

            ceilNode.Position = new SCNVector3(0f, 100f, 0f);
            ceilNode.Rotation = new SCNVector4(1f, 0f, 0f, (float)Math.PI / 2f);
            ceilNode.Geometry.FirstMaterial.DoubleSided = false;
            ceilNode.CastsShadow = false;
            ceilNode.Geometry.FirstMaterial.LocksAmbientWithDiffuse = true;
            scene.RootNode.AddChildNode(ceilNode);

            var rnd = new Random();

            for (int i = 0; i < 4; i++)
            {
                AddWoodenBlockToScene(scene, ResourceManager.GetResourcePath("WoodCubeA.jpg"),
                                      new SCNVector3(rnd.Next(0, 60) - 30f, 20f, rnd.Next(0, 40) - 20f));
                AddWoodenBlockToScene(scene, ResourceManager.GetResourcePath("WoodCubeB.jpg"),
                                      new SCNVector3(rnd.Next(0, 60) - 30f, 20f, rnd.Next(0, 40) - 20f));
                AddWoodenBlockToScene(scene, ResourceManager.GetResourcePath("WoodCubeC.jpg"),
                                      new SCNVector3(rnd.Next(0, 60) - 30f, 20f, rnd.Next(0, 40) - 20f));
            }

            var blockBox = new SCNBox {
                Width         = 22f,
                Height        = 0.2f,
                Length        = 34f,
                ChamferRadius = 0f
            };

            var block = SCNNode.Create();

            block.Position = new SCNVector3(20f, 10f, -16f);
            block.Rotation = new SCNVector4(0f, 1f, 0f, (float)-Math.PI / 4f);
            block.Geometry = blockBox;

            var frontMat = SCNMaterial.Create();

            frontMat.LocksAmbientWithDiffuse = true;
            frontMat.Diffuse.Contents        = ResourceManager.GetResourcePath("book_front.jpg");
            frontMat.Diffuse.MipFilter       = SCNFilterMode.Linear;

            var backMat = SCNMaterial.Create();

            backMat.LocksAmbientWithDiffuse = true;
            backMat.Diffuse.Contents        = ResourceManager.GetResourcePath("book_back.jpg");
            backMat.Diffuse.MipFilter       = SCNFilterMode.Linear;

            block.Geometry.Materials = new SCNMaterial[] { frontMat, backMat };
            block.PhysicsBody        = SCNPhysicsBody.CreateDynamicBody();
            scene.RootNode.AddChildNode(block);

            var rug = SCNNode.Create();

            rug.Position = new SCNVector3(0f, 0.01f, 0f);
            rug.Rotation = new SCNVector4(1f, 0f, 0f, (float)Math.PI / 2f);
            var path = UIBezierPath.FromRoundedRect(new CGRect(-50f, -30f, 100f, 50f), 2.5f);

            path.Flatness = 0.1f;
            rug.Geometry  = SCNShape.Create(path, 0.05f);
            rug.Geometry.FirstMaterial.LocksAmbientWithDiffuse = true;
            rug.Geometry.FirstMaterial.Diffuse.Contents        = ResourceManager.GetResourcePath("carpet.jpg");
            scene.RootNode.AddChildNode(rug);

            var ball = SCNNode.Create();

            ball.Position = new SCNVector3(-5f, 5f, -18f);
            ball.Geometry = SCNSphere.Create(5f);
            ball.Geometry.FirstMaterial.LocksAmbientWithDiffuse   = true;
            ball.Geometry.FirstMaterial.Diffuse.Contents          = ResourceManager.GetResourcePath("ball.jpg");
            ball.Geometry.FirstMaterial.Diffuse.ContentsTransform = SCNMatrix4.Scale(2f, 1f, 1f);
            ball.Geometry.FirstMaterial.Diffuse.WrapS             = SCNWrapMode.Mirror;
            ball.PhysicsBody             = SCNPhysicsBody.CreateDynamicBody();
            ball.PhysicsBody.Restitution = 0.9f;
            scene.RootNode.AddChildNode(ball);
        }
Ejemplo n.º 11
0
        public override void PresentStep(int index, PresentationViewController presentationViewController)
        {
            Step = index;

            switch (index)
            {
            case 0:
                break;

            case 1:
                TextManager.FlipOutText(SlideTextManager.TextType.Bullet);

                TextManager.SetSubtitle("SCNPhysicsBody");

                TextManager.FlipInText(SlideTextManager.TextType.Subtitle);

                TextManager.AddBulletAtLevel("Dynamic Bodies", 0);

                // Add some code
                TextManager.AddCode("#// Make a node dynamic\n"
                                    + "aNode.#physicsBody# = [SCNPhysicsBody #dynamicBody#];#");

                TextManager.FlipInText(SlideTextManager.TextType.Bullet);
                TextManager.FlipInText(SlideTextManager.TextType.Code);
                break;

            case 2:
                //add a cube
                var worldPos = GroundNode.ConvertPositionToNode(new SCNVector3(0, 12, 2), null);
                var dice     = CreateBlock(worldPos, new SCNVector3(1.5f, 1.5f, 1.5f));
                dice.PhysicsBody = null;                 //wait!
                dice.Rotation    = new SCNVector4(0, 0, 1, (float)(Math.PI / 4) * 0.5f);
                dice.Scale       = new SCNVector3(0.001f, 0.001f, 0.001f);

                ((SCNView)presentationViewController.View).Scene.RootNode.AddChildNode(dice);
                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 0.75f;
                dice.Scale = new SCNVector3(2, 2, 2);
                SCNTransaction.Commit();

                Dices.Add(dice);
                break;

            case 3:
                foreach (var node in Dices)
                {
                    node.PhysicsBody = SCNPhysicsBody.CreateDynamicBody();
                }
                break;

            case 4:
                PresentDices(presentationViewController);
                break;

            case 5:
                TextManager.FlipOutText(SlideTextManager.TextType.Bullet);
                TextManager.FlipOutText(SlideTextManager.TextType.Code);

                TextManager.AddBulletAtLevel("Manipulate with forces", 0);

                // Add some code
                TextManager.AddCode("#// Apply an impulse\n"
                                    + "[aNode.physicsBody #applyForce:#aVector3 #atPosition:#aVector3 #impulse:#YES];#");

                TextManager.FlipInText(SlideTextManager.TextType.Bullet);
                TextManager.FlipInText(SlideTextManager.TextType.Code);
                break;

            case 6:
                // remove dices
                var center = new SCNVector3(0, -5, 20);
                center = GroundNode.ConvertPositionToNode(center, null);

                Explosion(center, Dices);

                var popTime = new DispatchTime(DispatchTime.Now, (long)(1 * Utils.NSEC_PER_SEC));
                DispatchQueue.MainQueue.DispatchAfter(popTime, () => {
                    TextManager.FlipOutText(SlideTextManager.TextType.Code);
                    TextManager.FlipOutText(SlideTextManager.TextType.Bullet);

                    TextManager.AddBulletAtLevel("Static Bodies", 0);
                    TextManager.AddCode("#// Make a node static\n"
                                        + "aNode.#physicsBody# = [SCNPhysicsBody #staticBody#];#");
                    TextManager.FlipInText(SlideTextManager.TextType.Bullet);
                    TextManager.FlipInText(SlideTextManager.TextType.Code);
                });
                break;

            case 7:
                PresentWalls(presentationViewController);
                break;

            case 8:
                PresentBalls(presentationViewController);
                break;

            case 9:
                //remove walls
                var walls = new List <SCNNode> ();
                GroundNode.EnumerateChildNodes(delegate(SCNNode node, out bool stop) {
                    stop = false;
                    if (node.Name == "container-wall")
                    {
                        node.RunAction(SCNAction.Sequence(new SCNAction [] {
                            SCNAction.MoveBy(new SCNVector3(0, -2, 0), 0.5),
                            SCNAction.RemoveFromParentNode()
                        }));
                        walls.Add(node);
                    }
                    return(stop);
                });
                break;

            case 10:
                // remove balls
                center = new SCNVector3(0, -5, 5);
                center = GroundNode.ConvertPositionToNode(center, null);
                Explosion(center, Balls);

                popTime = new DispatchTime(DispatchTime.Now, (long)(0.5 * Utils.NSEC_PER_SEC));
                DispatchQueue.MainQueue.DispatchAfter(popTime, () => {
                    TextManager.FlipOutText(SlideTextManager.TextType.Code);
                    TextManager.FlipOutText(SlideTextManager.TextType.Bullet);

                    TextManager.AddBulletAtLevel("Kinematic Bodies", 0);
                    TextManager.AddCode("#// Make a node kinematic\n"
                                        + "aNode.#physicsBody# = [SCNPhysicsBody #kinematicBody#];#");
                    TextManager.FlipInText(SlideTextManager.TextType.Bullet);
                    TextManager.FlipInText(SlideTextManager.TextType.Code);
                });
                break;

            case 11:
                var boxNode = SCNNode.Create();
                boxNode.Geometry = SCNBox.Create(10, 0.2f, 10, 0);
                boxNode.Position = new SCNVector3(0, 5, MIDDLE_Z);
                boxNode.Geometry.FirstMaterial.Emission.Contents = NSColor.DarkGray;
                boxNode.PhysicsBody = SCNPhysicsBody.CreateKinematicBody();
                boxNode.RunAction(SCNAction.RepeatActionForever(SCNAction.RotateBy(0, 0, NMath.PI * 2, 2.0)));
                GroundNode.AddChildNode(boxNode);
                KinematicItems.Add(boxNode);

                var invisibleWall = SCNNode.Create();
                invisibleWall.Geometry = SCNBox.Create(4, 40, 10, 0);
                invisibleWall.Position = new SCNVector3(-7, 0, MIDDLE_Z);
                invisibleWall.Geometry.FirstMaterial.Transparency = 0;
                invisibleWall.PhysicsBody = SCNPhysicsBody.CreateStaticBody();
                GroundNode.AddChildNode(invisibleWall);
                KinematicItems.Add(invisibleWall);

                invisibleWall          = (SCNNode)invisibleWall.Copy();
                invisibleWall.Position = new SCNVector3(7, 0, MIDDLE_Z);
                GroundNode.AddChildNode(invisibleWall);
                KinematicItems.Add(invisibleWall);

                invisibleWall          = (SCNNode)invisibleWall.Copy();
                invisibleWall.Geometry = SCNBox.Create(10, 40, 4, 0);
                invisibleWall.Geometry.FirstMaterial.Transparency = 0;
                invisibleWall.Position    = new SCNVector3(0, 0, MIDDLE_Z - 7);
                invisibleWall.PhysicsBody = SCNPhysicsBody.CreateStaticBody();
                GroundNode.AddChildNode(invisibleWall);
                KinematicItems.Add(invisibleWall);

                invisibleWall          = (SCNNode)invisibleWall.Copy();
                invisibleWall.Position = new SCNVector3(0, 0, MIDDLE_Z + 7);
                GroundNode.AddChildNode(invisibleWall);
                KinematicItems.Add(invisibleWall);


                for (int i = 0; i < 100; i++)
                {
                    var ball = SCNNode.Create();
                    worldPos      = boxNode.ConvertPositionToNode(new SCNVector3(RandFloat(-4, 4), RandFloat(10, 30), RandFloat(-1, 4)), null);
                    ball.Position = worldPos;
                    ball.Geometry = SCNSphere.Create(0.5f);
                    ball.Geometry.FirstMaterial.Diffuse.Contents = NSColor.Cyan;
                    ball.PhysicsBody = SCNPhysicsBody.CreateDynamicBody();
                    ((SCNView)presentationViewController.View).Scene.RootNode.AddChildNode(ball);

                    KinematicItems.Add(ball);
                }
                break;

            case 12:
                TextManager.FlipOutText(SlideTextManager.TextType.Code);
                TextManager.FlipOutText(SlideTextManager.TextType.Bullet);
                TextManager.FlipOutText(SlideTextManager.TextType.Subtitle);
                TextManager.SetSubtitle("SCNPhysicsShape");
                TextManager.AddCode("#// Configure the physics shape\n\n"
                                    + "aNode.physicsBody.#physicsShape# = \n\t[#SCNPhysicsShape# shapeWithGeometry:aGeometry options:options];#");
                TextManager.FlipInText(SlideTextManager.TextType.Bullet);
                TextManager.FlipInText(SlideTextManager.TextType.Code);

                KinematicItems[0].RunAction(SCNAction.Sequence(new SCNAction[] {
                    SCNAction.FadeOut(0.5),
                    SCNAction.RemoveFromParentNode()
                }));
                for (int i = 1; i < 5; i++)
                {
                    KinematicItems[i].RemoveFromParentNode();
                }

                KinematicItems = null;
                break;

            case 13:
                //add meshes
                PresentMeshes(presentationViewController);
                break;

            case 14:
                // remove meshes
                center = new SCNVector3(0, -5, 20);
                center = GroundNode.ConvertPositionToNode(center, null);
                Explosion(center, Meshes);
                break;

            case 15:
                // add shapes
                PresentPrimitives(presentationViewController);
                break;

            case 16:
                // remove shapes
                center = new SCNVector3(0, -5, 20);
                center = GroundNode.ConvertPositionToNode(center, null);
                Explosion(center, Shapes);

                popTime = new DispatchTime(DispatchTime.Now, (long)(0.5 * Utils.NSEC_PER_SEC));
                DispatchQueue.MainQueue.DispatchAfter(popTime, () => {
                    TextManager.FlipOutText(SlideTextManager.TextType.Code);
                    TextManager.FlipOutText(SlideTextManager.TextType.Bullet);
                    TextManager.FlipOutText(SlideTextManager.TextType.Subtitle);

                    TextManager.SetSubtitle("SCNPhysicsBehavior");
                    TextManager.AddCode("#// setup a physics behavior\n\n"
                                        + "#SCNPhysicsHingeJoint# *joint = [SCNPhysicsHingeJoint\n\n"
                                        + "jointWithBodyA:#nodeA.physicsBody# axisA:[...] anchorA:[...]\n\n"
                                        + "bodyB:#nodeB.physicsBody# axisB:[...] anchorB:[...]];\n\n\n"
                                        + "[scene.#physicsWorld# addBehavior:joint];#");

                    TextManager.FlipInText(SlideTextManager.TextType.Bullet);
                    TextManager.FlipInText(SlideTextManager.TextType.Subtitle);
                    TextManager.FlipInText(SlideTextManager.TextType.Code);
                });
                break;

            case 17:
                //add meshes
                PresentHinge(presentationViewController);
                break;

            case 18:
                //remove constraints
                ((SCNView)presentationViewController.View).Scene.PhysicsWorld.RemoveAllBehaviors();

                foreach (var node in Hinges)
                {
                    node.RunAction(SCNAction.Sequence(new SCNAction[] { SCNAction.Wait(3.0), SCNAction.FadeOut(0.5), SCNAction.RemoveFromParentNode() }));
                }

                break;

            case 19:
                TextManager.FlipOutText(SlideTextManager.TextType.Bullet);
                TextManager.FlipOutText(SlideTextManager.TextType.Subtitle);
                TextManager.FlipOutText(SlideTextManager.TextType.Code);

                TextManager.SetSubtitle("More...");

                TextManager.FlipInText(SlideTextManager.TextType.Subtitle);

                TextManager.AddBulletAtLevel("SCNPhysicsField", 0);
                TextManager.AddBulletAtLevel("SCNPhysicsVehicle", 0);

                TextManager.FlipInText(SlideTextManager.TextType.Bullet);
                TextManager.FlipInText(SlideTextManager.TextType.Code);
                break;
            }
        }