public NSDictionary?ToDictionary()
        {
            var n = 0;

            if (ShapeType.HasValue)
            {
                n++;
            }
            if (KeepAsCompound.HasValue)
            {
                n++;
            }
            if (Scale.HasValue)
            {
                n++;
            }

            if (n == 0)
            {
                return(null);
            }

            var i      = 0;
            var keys   = new NSString [n];
            var values = new NSObject [n];

            if (ShapeType.HasValue)
            {
                keys [i] = SCNPhysicsShapeOptionsKeys.Type;
                switch (ShapeType.Value)
                {
                case SCNPhysicsShapeType.BoundingBox:
                    values [i] = SCNPhysicsShapeOptionsTypes.BoundingBox;
                    break;

                case SCNPhysicsShapeType.ConcavePolyhedron:
                    values [i] = SCNPhysicsShapeOptionsTypes.ConcavePolyhedron;
                    break;

                case SCNPhysicsShapeType.ConvexHull:
                default:
                    values [i] = SCNPhysicsShapeOptionsTypes.ConvexHull;
                    break;
                }
            }

            if (KeepAsCompound.HasValue)
            {
                keys [i]   = SCNPhysicsShapeOptionsKeys.KeepAsCompound;
                values [i] = new NSNumber(KeepAsCompound.Value);
            }

            if (Scale.HasValue)
            {
                keys [i]   = SCNPhysicsShapeOptionsKeys.Scale;
                values [i] = NSValue.FromVector(Scale.Value);
            }

            return(NSDictionary.FromObjectsAndKeys(values, keys));
        }
        public override void PresentStep(int index, PresentationViewController presentationViewController)
        {
            // Animate by default
            SCNTransaction.Begin();

            switch (index)
            {
            case 0:
                // Disable animations for first step
                SCNTransaction.AnimationDuration = 0;

                // Initially dim the torus
                AnimatedNode.Opacity = 0.0f;

                TextManager.HighlightCodeChunks(null);
                break;

            case 1:
                TextManager.HighlightCodeChunks(new int[] { 0 });
                break;

            case 2:
                TextManager.HighlightCodeChunks(new int[] { 1, 2, 3 });
                break;

            case 3:
                TextManager.HighlightCodeChunks(new int[] { 4, 5 });
                break;

            case 4:
                SCNTransaction.AnimationDuration = 1.0f;

                // Show the torus
                AnimatedNode.Opacity = 1.0f;

                // Animate explicitly
                var animation = CABasicAnimation.FromKeyPath("rotation");
                animation.Duration    = 2.0f;
                animation.To          = NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI * 2)));
                animation.RepeatCount = float.MaxValue;
                AnimatedNode.AddAnimation(animation, new NSString("myAnimation"));

                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 1;
                // Dim the text
                TextManager.TextNode.Opacity = 0.75f;

                presentationViewController.CameraHandle.Position = presentationViewController.CameraHandle.ConvertPositionToNode(new SCNVector3(9, 8, 15), presentationViewController.CameraHandle.ParentNode);
                presentationViewController.CameraPitch.Rotation  = new SCNVector4(1, 0, 0, -(float)(Math.PI / 10));

                SCNTransaction.Commit();
                break;
            }

            SCNTransaction.Commit();
        }
        public override void SetupSlide(PresentationViewController presentationViewController)
        {
            // Create a node for Earth and another node to display clouds
            // Use the 'pivot' property to tilt Earth because we don't want to see the north pole.
            EarthNode          = SCNNode.Create();
            EarthNode.Pivot    = SCNMatrix4.CreateFromAxisAngle(new SCNVector3(1, 0, 0), (float)(Math.PI * 0.1f));
            EarthNode.Position = new SCNVector3(6, 7.2f, -2);
            EarthNode.Geometry = SCNSphere.Create(7.2f);

            CloudsNode          = SCNNode.Create();
            CloudsNode.Geometry = SCNSphere.Create(7.9f);

            GroundNode.AddChildNode(EarthNode);
            EarthNode.AddChildNode(CloudsNode);

            // Initially hide everything
            EarthNode.Opacity  = 0.0f;
            CloudsNode.Opacity = 0.0f;

            EarthNode.Geometry.FirstMaterial.Ambient.Intensity    = 0;
            EarthNode.Geometry.FirstMaterial.Normal.Intensity     = 0;
            EarthNode.Geometry.FirstMaterial.Reflective.Intensity = 0;
            EarthNode.Geometry.FirstMaterial.Emission.Intensity   = 0;

            // Use a shader modifier to display an environment map independently of the lighting model used
            EarthNode.Geometry.ShaderModifiers = new SCNShaderModifiers {
                EntryPointFragment = " _output.color.rgb -= _surface.reflective.rgb * _lightingContribution.diffuse;"
                                     + "_output.color.rgb += _surface.reflective.rgb;"
            };

            // Add animations
            var rotationAnimation = CABasicAnimation.FromKeyPath("rotation");

            rotationAnimation.Duration    = 40.0f;
            rotationAnimation.RepeatCount = float.MaxValue;
            rotationAnimation.To          = NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI * 2)));
            EarthNode.AddAnimation(rotationAnimation, new NSString("earthNodeAnimation"));

            rotationAnimation.Duration = 100.0f;
            CloudsNode.AddAnimation(rotationAnimation, new NSString("cloudsNodeAnimation"));
        }
        public static SCNPhysicsShape Create(SCNPhysicsShape [] shapes, SCNVector3 [] transforms)
        {
            if (shapes == null)
            {
                throw new ArgumentNullException("shapes");
            }

            if (transforms == null)
            {
                throw new ArgumentNullException("transforms");
            }

            var t = new NSValue [transforms.Length];

            for (var i = 0; i < t.Length; i++)
            {
                t [i] = NSValue.FromVector(transforms [i]);
            }

            return(Create(shapes, t));
        }
        public static SCNPhysicsShape Create(SCNPhysicsShape [] shapes, SCNVector3 [] transforms)
        {
            if (shapes == null)
            {
                ObjCRuntime.ThrowHelper.ThrowArgumentException(nameof(shapes));
            }

            if (transforms == null)
            {
                ObjCRuntime.ThrowHelper.ThrowArgumentException(nameof(transforms));
            }

            var t = new NSValue [transforms.Length];

            for (var i = 0; i < t.Length; i++)
            {
                t [i] = NSValue.FromVector(transforms [i]);
            }

            return(Create(shapes, t));
        }
        // Updates the secondary image of the floor if needed
        private void UpdateFloorImage(NSImage image, Slide slide)
        {
            // We don't want to animate if we replace the secondary image by a new one
            // Otherwise we want to translate the secondary image to the new location
            var disableAction = false;

            if (FloorImage != image)
            {
                FloorImage    = image;
                disableAction = true;

                if (image != null)
                {
                    // Set a new material property with this image to the "floorMap" custom property of the floor
                    var property = SCNMaterialProperty.Create(image);
                    property.WrapS     = SCNWrapMode.Repeat;
                    property.WrapT     = SCNWrapMode.Repeat;
                    property.MipFilter = SCNFilterMode.Linear;

                    Floor.FirstMaterial.SetValueForKey(property, new NSString("floorMap"));
                }
            }

            if (image != null)
            {
                var slidePosition = slide.GroundNode.ConvertPositionToNode(new SCNVector3(0, 0, 10), null);

                if (disableAction)
                {
                    SCNTransaction.Begin();
                    SCNTransaction.AnimationDuration = 0;
                    Floor.FirstMaterial.SetValueForKey(NSValue.FromVector(slidePosition), new NSString("floorImageNamePosition"));
                    SCNTransaction.Commit();
                }
                else
                {
                    Floor.FirstMaterial.SetValueForKey(NSValue.FromVector(slidePosition), new NSString("floorImageNamePosition"));
                }
            }
        }
示例#7
0
        public override void SetupSlide(PresentationViewController presentationViewController)
        {
            TextManager.SetTitle("Extending Scene Kit with OpenGL");
            TextManager.SetSubtitle("Material custom program");

            TextManager.AddBulletAtLevel("Custom GLSL code per material", 0);
            TextManager.AddBulletAtLevel("Overrides Scene Kit’s rendering", 0);
            TextManager.AddBulletAtLevel("Geometry attributes are provided", 0);
            TextManager.AddBulletAtLevel("Transform uniforms are also provided", 0);

            // Add a torus and animate it
            TorusNode          = Utils.SCAddChildNode(GroundNode, "torus", "Scenes/torus/torus", 10);
            TorusNode.Position = new SCNVector3(8, 8, 4);
            TorusNode.Name     = "object";

            var rotationAnimation = CABasicAnimation.FromKeyPath("rotation");

            rotationAnimation.Duration    = 10.0f;
            rotationAnimation.RepeatCount = float.MaxValue;
            rotationAnimation.To          = NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI * 2)));
            TorusNode.AddAnimation(rotationAnimation, new NSString("torusRotation"));
        }
示例#8
0
        public override void PresentStep(int index, PresentationViewController presentationViewController)
        {
            switch (index)
            {
            case 0:
                // Set the slide's title and subtitle and add some text
                TextManager.SetTitle("Constraints");
                TextManager.SetSubtitle("SCNConstraint");

                TextManager.AddBulletAtLevel("Applied sequentially at render time", 0);
                TextManager.AddBulletAtLevel("Only affect presentation values", 0);

                TextManager.AddCode("#aNode.#Constraints# = new SCNConstraint[] { aConstraint, anotherConstraint, ... };#");

                // Tweak the near clipping plane of the spot light to get a precise shadow map
                presentationViewController.SpotLight.Light.SetAttribute(new NSNumber(10), SCNLightAttribute.ShadowNearClippingKey);
                break;

            case 1:
                // Remove previous text
                TextManager.FlipOutText(SlideTextManager.TextType.Subtitle);
                TextManager.FlipOutText(SlideTextManager.TextType.Bullet);
                TextManager.FlipOutText(SlideTextManager.TextType.Code);

                // Add new text
                TextManager.SetSubtitle("SCNLookAtConstraint");
                TextManager.AddBulletAtLevel("Makes a node to look at another node", 0);
                TextManager.AddCode("#nodeA.Constraints = new SCNConstraint[] { #SCNLookAtConstraint.Create# (nodeB) };#");

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

            case 2:
                // Setup the scene
                SetupLookAtScene();

                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 1;
                // Dim the text and move back a little bit
                TextManager.TextNode.Opacity = 0.5f;
                presentationViewController.CameraHandle.Position = presentationViewController.CameraNode.ConvertPositionToNode(new SCNVector3(0, 0, 5.0f), presentationViewController.CameraHandle.ParentNode);
                SCNTransaction.Commit();
                break;

            case 3:
                // Add constraints to the arrows
                var container = ContentNode.FindChildNode("arrowContainer", true);

                // "Look at" constraint
                var constraint = SCNLookAtConstraint.Create(BallNode);

                var i = 0;
                foreach (var arrow in container.ChildNodes)
                {
                    var delayInSeconds = 0.1 * i++;
                    var popTime        = new DispatchTime(DispatchTime.Now, (long)(delayInSeconds * Utils.NSEC_PER_SEC));
                    DispatchQueue.MainQueue.DispatchAfter(popTime, () => {
                        SCNTransaction.Begin();
                        SCNTransaction.AnimationDuration = 1;
                        // Animate to the result of applying the constraint
                        ((SCNNode)arrow.ChildNodes [0]).Rotation = new SCNVector4(0, 1, 0, (float)(Math.PI / 2));
                        arrow.Constraints = new SCNConstraint[] { constraint };
                        SCNTransaction.Commit();
                    });
                }
                break;

            case 4:
                // Create a keyframe animation to move the ball
                var animation = CAKeyFrameAnimation.FromKeyPath("position");
                animation.KeyTimes = new NSNumber[] {
                    0.0f,
                    (1.0f / 8.0f),
                    (2.0f / 8.0f),
                    (3.0f / 8.0f),
                    (4.0f / 8.0f),
                    (5.0f / 8.0f),
                    (6.0f / 8.0f),
                    (7.0f / 8.0f),
                    1.0f
                };

                animation.Values = new NSObject[] {
                    NSValue.FromVector(new SCNVector3(0, 0.0f, 0)),
                    NSValue.FromVector(new SCNVector3(20.0f, 0.0f, 20.0f)),
                    NSValue.FromVector(new SCNVector3(40.0f, 0.0f, 0)),
                    NSValue.FromVector(new SCNVector3(20.0f, 0.0f, -20.0f)),
                    NSValue.FromVector(new SCNVector3(0, 0.0f, 0)),
                    NSValue.FromVector(new SCNVector3(-20.0f, 0.0f, 20.0f)),
                    NSValue.FromVector(new SCNVector3(-40.0f, 0.0f, 0)),
                    NSValue.FromVector(new SCNVector3(-20.0f, 0.0f, -20.0f)),
                    NSValue.FromVector(new SCNVector3(0, 0.0f, 0))
                };

                animation.CalculationMode = CAAnimation.AnimationCubicPaced;                 // smooth the movement between keyframes
                animation.RepeatCount     = float.MaxValue;
                animation.Duration        = 10.0f;
                animation.TimingFunction  = CAMediaTimingFunction.FromName(CAMediaTimingFunction.Linear);
                BallNode.AddAnimation(animation, new NSString("ballNodeAnimation"));

                // Rotate the ball to give the illusion of a rolling ball
                // We need two animations to do that:
                // - one rotation to orient the ball in the right direction
                // - one rotation to spin the ball
                animation          = CAKeyFrameAnimation.FromKeyPath("rotation");
                animation.KeyTimes = new NSNumber[] {
                    0.0f,
                    (0.7f / 8.0f),
                    (1.0f / 8.0f),
                    (2.0f / 8.0f),
                    (3.0f / 8.0f),
                    (3.3f / 8.0f),
                    (4.7f / 8.0f),
                    (5.0f / 8.0f),
                    (6.0f / 8.0f),
                    (7.0f / 8.0f),
                    (7.3f / 8.0f),
                    1.0f
                };

                animation.Values = new NSObject[] {
                    NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI / 4))),
                    NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI / 4))),
                    NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI / 2))),
                    NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI))),
                    NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI + Math.PI / 2))),
                    NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI * 2 - Math.PI / 4))),
                    NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI * 2 - Math.PI / 4))),
                    NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI * 2 - Math.PI / 2))),
                    NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI))),
                    NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI - Math.PI / 2))),
                    NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI / 4))),
                    NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI / 4)))
                };

                animation.RepeatCount    = float.MaxValue;
                animation.Duration       = 10.0f;
                animation.TimingFunction = CAMediaTimingFunction.FromName(CAMediaTimingFunction.Linear);
                BallNode.AddAnimation(animation, new NSString("ballNodeAnimation2"));

                var rotationAnimation = CABasicAnimation.FromKeyPath("rotation");
                rotationAnimation.Duration    = 1.0f;
                rotationAnimation.RepeatCount = float.MaxValue;
                rotationAnimation.To          = NSValue.FromVector(new SCNVector4(1, 0, 0, (float)(Math.PI * 2)));
                BallNode.ChildNodes [1].AddAnimation(rotationAnimation, new NSString("ballNodeRotation"));
                break;

            case 5:
                // Add a constraint to the camera
                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 1;
                constraint = SCNLookAtConstraint.Create(BallNode);
                presentationViewController.CameraNode.Constraints = new SCNConstraint[] { constraint };
                SCNTransaction.Commit();
                break;

            case 6:
                // Add a constraint to the light
                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 1;
                var cameraTarget = ContentNode.FindChildNode("cameraTarget", true);
                constraint = SCNLookAtConstraint.Create(cameraTarget);
                presentationViewController.SpotLight.Constraints = new SCNConstraint[] { constraint };
                SCNTransaction.Commit();
                break;
            }
        }
示例#9
0
        public override void PresentStep(int switchIndex, PresentationViewController presentationViewController)
        {
            switch (switchIndex)
            {
            case 0:
                // Set the slide's title and subtitle and add some text
                TextManager.SetTitle("Core Image");
                TextManager.SetSubtitle("CI Filters");

                TextManager.AddBulletAtLevel("Screen-space effects", 0);
                TextManager.AddBulletAtLevel("Applies to a node hierarchy", 0);
                TextManager.AddBulletAtLevel("Filter parameters are animatable", 0);
                TextManager.AddCode("#aNode.#Filters# = new CIFilter[] { filter1, filter2 };#");
                break;

            case 1:
                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 1.0f;
                // Dim the text and move back a little
                TextManager.TextNode.Opacity = 0.0f;
                presentationViewController.CameraHandle.Position = presentationViewController.CameraNode.ConvertPositionToNode(new SCNVector3(0, 0, 5.0f), presentationViewController.CameraHandle.ParentNode);
                SCNTransaction.Commit();

                // Reveal the grid
                GroupNode.Opacity = 1;
                break;

            case 2:
                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 1;
                // Highlight an item
                HighlightContact(13, presentationViewController);
                SCNTransaction.Commit();
                break;

            case 3:
                var index   = 13;
                var subStep = 0;

                // Successively select items
                for (var i = 0; i < 5; ++i)
                {
                    var popTime = new DispatchTime(DispatchTime.Now, (long)(i * 0.2 * Utils.NSEC_PER_SEC));
                    DispatchQueue.MainQueue.DispatchAfter(popTime, () => {
                        SCNTransaction.Begin();
                        SCNTransaction.AnimationDuration = 0.2f;
                        UnhighlightContact(index);

                        if (subStep++ == 3)
                        {
                            index += ColumnCount;
                        }
                        else
                        {
                            index++;
                        }

                        HighlightContact(index, presentationViewController);
                        SCNTransaction.Commit();
                    });
                }
                break;

            case 4:
                // BLUR+DESATURATE in the background, GLOW in the foreground

                // Here we will change the node hierarchy in order to group all the nodes in the background under a single node.
                // This way we can use a single Core Image filter and apply it on the whole grid, and have another CI filter for the node in the foreground.

                var selectionParent = HeroNode.ParentNode;

                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 0;
                // Stop the animations of the selected node
                HeroNode.Transform = HeroNode.PresentationNode.Transform;                 // set the current rotation to the current presentation value
                HeroNode.RemoveAllAnimations();

                // Re-parent the node by preserving its world tranform
                var wantedWorldTransform = selectionParent.WorldTransform;
                GroupNode.ParentNode.AddChildNode(selectionParent);
                selectionParent.Transform = selectionParent.ParentNode.ConvertTransformFromNode(wantedWorldTransform, null);
                SCNTransaction.Commit();

                // Add CIFilters

                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 1;
                // A negative 'centerX' value means no scaling.
                //TODO HeroNode.Filters [0].SetValueForKey (new NSNumber (-1), new NSString ("centerX"));

                // Move the selection to the foreground
                selectionParent.Rotation = new SCNVector4(0, 1, 0, 0);
                HeroNode.Transform       = ContentNode.ConvertTransformToNode(SCNMatrix4.CreateTranslation(0, Altitude, 29), selectionParent);
                HeroNode.Scale           = new SCNVector3(1, 1, 1);
                HeroNode.Rotation        = new SCNVector4(1, 0, 0, -(float)(Math.PI / 4) * 0.25f);

                // Upon completion, rotate the selection forever
                SCNTransaction.SetCompletionBlock(() => {
                    var animation            = CABasicAnimation.FromKeyPath("rotation");
                    animation.Duration       = 4.0f;
                    animation.From           = NSValue.FromVector(new SCNVector4(0, 1, 0, 0));
                    animation.To             = NSValue.FromVector(new SCNVector4(0, 1, 0, NMath.PI * 2));
                    animation.TimingFunction = CAMediaTimingFunction.FromName(CAMediaTimingFunction.EaseInEaseOut);
                    animation.RepeatCount    = float.MaxValue;

                    HeroNode.ChildNodes [0].AddAnimation(animation, new NSString("heroNodeAnimation"));
                });

                // Add the filters
                var blurFilter = CIFilter.FromName("CIGaussianBlur");
                blurFilter.SetDefaults();
                blurFilter.Name = "blur";
                blurFilter.SetValueForKey(new NSNumber(0), CIFilterInputKey.Radius);

                var desaturateFilter = CIFilter.FromName("CIColorControls");
                desaturateFilter.SetDefaults();
                desaturateFilter.Name = "desaturate";
                GroupNode.Filters     = new CIFilter[] { blurFilter, desaturateFilter };
                SCNTransaction.Commit();

                // Increate the blur radius and desaturate progressively
                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 2;
                GroupNode.SetValueForKey(new NSNumber(10), new NSString("filters.blur.inputRadius"));
                GroupNode.SetValueForKey(new NSNumber(0.1), new NSString("filters.desaturate.inputSaturation"));
                SCNTransaction.Commit();

                break;
            }
        }
示例#10
0
        private void BuildImageGrid()
        {
            // Create a root node for the grid
            GroupNode = SCNNode.Create();

            // Retrieve the template node to replicate
            var scene        = SCNScene.FromFile("Contacts/contact");
            var templateNode = scene.RootNode.FindChildNode("people", true);

            for (int k = 0, j = 0; j < RowCount; j++)
            {
                for (var i = 0; i < ColumnCount; i++, k++)
                {
                    // Hierarchy : __groupNode > container > node
                    var container = SCNNode.Create();
                    var node      = templateNode.Clone();
                    node.Name = "contact" + k;

                    GroupNode.AddChildNode(container);
                    container.AddChildNode(node);

                    if (k == 28)
                    {
                        HeroNode = node;
                    }

                    // Curved layout
                    var angle = 0.12f * ((ColumnCount - 1) / 2.0f - i);
                    var x     = NMath.Cos(angle + (float)(Math.PI / 2)) * 500.0f;
                    var z     = NMath.Sin(angle + (float)(Math.PI / 2)) * 500.0f;
                    container.Position = new SCNVector3(x, j * 60, -z + 400);
                    container.Rotation = new SCNVector4(0, 1, 0, angle);

                    // We want a different image on each elemement and to do that we need to
                    // unshare the geometry first and then unshare the material

                    var geometryNode = node.ChildNodes [0];
                    geometryNode.Geometry = (SCNGeometry)geometryNode.Geometry.Copy();

                    var materialCopy = (SCNMaterial)geometryNode.Geometry.Materials [1].Copy();
                    materialCopy.Diffuse.Contents = new NSImage(NSBundle.MainBundle.PathForResource("Contacts/contact" + (k % ContactImageCount), "jpg"));
                    geometryNode.Geometry.ReplaceMaterial(1, materialCopy);

                    // Animate (rotate forever)
                    var animation = CAKeyFrameAnimation.GetFromKeyPath("rotation");
                    animation.Duration = 4.0f;
                    animation.KeyTimes = new NSNumber[] { 0.0f, 0.3f, 1.0f };
                    animation.Values   = new NSObject[] { NSValue.FromVector(new SCNVector4(0, 1, 0, 0)),
                                                          NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI * 2))),
                                                          NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI * 2))) };

                    var tf = CAMediaTimingFunction.FromName(CAMediaTimingFunction.EaseInEaseOut);
                    animation.TimingFunctions = new CAMediaTimingFunction[] { tf, tf, tf };
                    animation.RepeatCount     = float.MaxValue;
                    animation.BeginTime       = CAAnimation.CurrentMediaTime() + 1.0f + j * 0.1f + i * 0.05f;                // desynchronize the animations
                    node.AddAnimation(animation, new NSString("animation"));
                }
            }

            // Add the group to the scene
            GroupNode.Scale    = new SCNVector3(0.03f, 0.03f, 0.03f);
            GroupNode.Position = new SCNVector3(0, Altitude - 2.8f, 18);
            GroupNode.Opacity  = 0.0f;

            GroundNode.AddChildNode(GroupNode);
        }
示例#11
0
        public override void PresentStep(int index, PresentationViewController presentationViewController)
        {
            switch (index)
            {
            case 0:
                // Set the slide's title and subtitle
                TextManager.SetTitle("Scene Graph");
                TextManager.SetSubtitle("Summary");
                break;

            case 1:
                // A node that will help visualize the position of the stars
                WireframeBoxNode          = SCNNode.Create();
                WireframeBoxNode.Rotation = new SCNVector4(0, 1, 0, (float)(Math.PI / 4));
                WireframeBoxNode.Geometry = SCNBox.Create(1, 1, 1, 0);
                WireframeBoxNode.Geometry.FirstMaterial.Diffuse.Contents  = new NSImage(NSBundle.MainBundle.PathForResource("SharedTextures/box_wireframe", "png"));
                WireframeBoxNode.Geometry.FirstMaterial.LightingModelName = SCNLightingModel.Constant; // no lighting
                WireframeBoxNode.Geometry.FirstMaterial.DoubleSided       = true;                      // double sided

                // Sun
                SunNode          = SCNNode.Create();
                SunNode.Position = new SCNVector3(0, 30, 0);
                ContentNode.AddChildNode(SunNode);
                SunNode.AddChildNode((SCNNode)WireframeBoxNode.Copy());

                // Earth-rotation (center of rotation of the Earth around the Sun)
                var earthRotationNode = SCNNode.Create();
                SunNode.AddChildNode(earthRotationNode);

                // Earth-group (will contain the Earth, and the Moon)
                EarthGroupNode          = SCNNode.Create();
                EarthGroupNode.Position = new SCNVector3(15, 0, 0);
                earthRotationNode.AddChildNode(EarthGroupNode);

                // Earth
                EarthNode          = (SCNNode)WireframeBoxNode.Copy();
                EarthNode.Position = new SCNVector3(0, 0, 0);
                EarthGroupNode.AddChildNode(EarthNode);

                // Rotate the Earth around the Sun
                var animation = CABasicAnimation.FromKeyPath("rotation");
                animation.Duration    = 10.0f;
                animation.To          = NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI * 2)));
                animation.RepeatCount = float.MaxValue;
                earthRotationNode.AddAnimation(animation, new NSString("earth rotation around sun"));

                // Rotate the Earth
                animation             = CABasicAnimation.FromKeyPath("rotation");
                animation.Duration    = 1.0f;
                animation.From        = NSValue.FromVector(new SCNVector4(0, 1, 0, 0));
                animation.To          = NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI * 2)));
                animation.RepeatCount = float.MaxValue;
                EarthNode.AddAnimation(animation, new NSString("earth rotation"));
                break;

            case 2:
                // Moon-rotation (center of rotation of the Moon around the Earth)
                var moonRotationNode = SCNNode.Create();
                EarthGroupNode.AddChildNode(moonRotationNode);

                // Moon
                MoonNode          = (SCNNode)WireframeBoxNode.Copy();
                MoonNode.Position = new SCNVector3(5, 0, 0);
                moonRotationNode.AddChildNode(MoonNode);

                // Rotate the moon around the Earth
                animation             = CABasicAnimation.FromKeyPath("rotation");
                animation.Duration    = 1.5f;
                animation.To          = NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI * 2)));
                animation.RepeatCount = float.MaxValue;
                moonRotationNode.AddAnimation(animation, new NSString("moon rotation around earth"));

                // Rotate the moon
                animation             = CABasicAnimation.FromKeyPath("rotation");
                animation.Duration    = 1.5f;
                animation.To          = NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI * 2)));
                animation.RepeatCount = float.MaxValue;
                MoonNode.AddAnimation(animation, new NSString("moon rotation"));
                break;

            case 3:
                // Add geometries (spheres) to represent the stars
                SunNode.Geometry   = SCNSphere.Create(2.5f);
                EarthNode.Geometry = SCNSphere.Create(1.5f);
                MoonNode.Geometry  = SCNSphere.Create(0.75f);

                // Add a textured plane to represent Earth's orbit
                var earthOrbit = SCNNode.Create();
                earthOrbit.Opacity  = 0.4f;
                earthOrbit.Geometry = SCNPlane.Create(31, 31);
                earthOrbit.Geometry.FirstMaterial.Diffuse.Contents  = new NSImage(NSBundle.MainBundle.PathForResource("Scenes/earth/orbit", "png"));
                earthOrbit.Geometry.FirstMaterial.Diffuse.MipFilter = SCNFilterMode.Linear;
                earthOrbit.Rotation = new SCNVector4(1, 0, 0, -(float)(Math.PI / 2));
                earthOrbit.Geometry.FirstMaterial.LightingModelName = SCNLightingModel.Constant;                 // no lighting
                SunNode.AddChildNode(earthOrbit);
                break;

            case 4:
                // Add a halo to the Sun (a simple textured plane that does not write to depth)
                SunHaloNode          = SCNNode.Create();
                SunHaloNode.Geometry = SCNPlane.Create(30, 30);
                SunHaloNode.Rotation = new SCNVector4(1, 0, 0, Pitch * (float)(Math.PI / 180.0f));
                SunHaloNode.Geometry.FirstMaterial.Diffuse.Contents    = new NSImage(NSBundle.MainBundle.PathForResource("Scenes/earth/sun-halo", "png"));
                SunHaloNode.Geometry.FirstMaterial.LightingModelName   = SCNLightingModel.Constant; // no lighting
                SunHaloNode.Geometry.FirstMaterial.WritesToDepthBuffer = false;                     // do not write to depth
                SunHaloNode.Opacity = 0.2f;
                SunNode.AddChildNode(SunHaloNode);

                // Add materials to the stars
                EarthNode.Geometry.FirstMaterial.Diffuse.Contents  = new NSImage(NSBundle.MainBundle.PathForResource("Scenes/earth/earth-diffuse-mini", "jpg"));
                EarthNode.Geometry.FirstMaterial.Emission.Contents = new NSImage(NSBundle.MainBundle.PathForResource("Scenes/earth/earth-emissive-mini", "jpg"));
                EarthNode.Geometry.FirstMaterial.Specular.Contents = new NSImage(NSBundle.MainBundle.PathForResource("Scenes/earth/earth-specular-mini", "jpg"));
                MoonNode.Geometry.FirstMaterial.Diffuse.Contents   = new NSImage(NSBundle.MainBundle.PathForResource("Scenes/earth/moon", "jpg"));
                SunNode.Geometry.FirstMaterial.Multiply.Contents   = new NSImage(NSBundle.MainBundle.PathForResource("Scenes/earth/sun", "jpg"));
                SunNode.Geometry.FirstMaterial.Diffuse.Contents    = new NSImage(NSBundle.MainBundle.PathForResource("Scenes/earth/sun", "jpg"));
                SunNode.Geometry.FirstMaterial.Multiply.Intensity  = 0.5f;
                SunNode.Geometry.FirstMaterial.LightingModelName   = SCNLightingModel.Constant;

                SunNode.Geometry.FirstMaterial.Multiply.WrapS            =
                    SunNode.Geometry.FirstMaterial.Diffuse.WrapS         =
                        SunNode.Geometry.FirstMaterial.Multiply.WrapT    =
                            SunNode.Geometry.FirstMaterial.Diffuse.WrapT = SCNWrapMode.Repeat;

                EarthNode.Geometry.FirstMaterial.LocksAmbientWithDiffuse       =
                    MoonNode.Geometry.FirstMaterial.LocksAmbientWithDiffuse    =
                        SunNode.Geometry.FirstMaterial.LocksAmbientWithDiffuse = true;

                EarthNode.Geometry.FirstMaterial.Shininess          = 0.1f;
                EarthNode.Geometry.FirstMaterial.Specular.Intensity = 0.5f;
                MoonNode.Geometry.FirstMaterial.Specular.Contents   = NSColor.Gray;

                // Achieve a lava effect by animating textures
                animation          = CABasicAnimation.FromKeyPath("contentsTransform");
                animation.Duration = 10.0f;

                var animationTransform1 = CATransform3D.MakeTranslation(0, 0, 0);
                animationTransform1 = animationTransform1.Concat(CATransform3D.MakeScale(3, 3, 3));
                var animationTransform2 = CATransform3D.MakeTranslation(1, 0, 0);
                animationTransform2 = animationTransform1.Concat(CATransform3D.MakeScale(3, 3, 3));

                animation.From        = NSValue.FromCATransform3D(animationTransform1);
                animation.To          = NSValue.FromCATransform3D(animationTransform2);
                animation.RepeatCount = float.MaxValue;
                SunNode.Geometry.FirstMaterial.Diffuse.AddAnimation(animation, new NSString("sun-texture"));

                animation          = CABasicAnimation.FromKeyPath("contentsTransform");
                animation.Duration = 30.0f;

                animationTransform1 = CATransform3D.MakeTranslation(0, 0, 0);
                animationTransform1 = animationTransform1.Concat(CATransform3D.MakeScale(5, 5, 5));
                animationTransform2 = CATransform3D.MakeTranslation(1, 0, 0);
                animationTransform2 = animationTransform1.Concat(CATransform3D.MakeScale(5, 5, 5));

                animation.From        = NSValue.FromCATransform3D(animationTransform1);
                animation.To          = NSValue.FromCATransform3D(animationTransform2);
                animation.RepeatCount = float.MaxValue;
                SunNode.Geometry.FirstMaterial.Multiply.AddAnimation(animation, new NSString("sun-texture2"));
                break;

            case 5:
                // We will turn off all the lights in the scene and add a new light
                // to give the impression that the Sun lights the scene
                var lightNode = SCNNode.Create();
                lightNode.Light           = SCNLight.Create();
                lightNode.Light.Color     = NSColor.Black;             // initially switched off
                lightNode.Light.LightType = SCNLightType.Omni;
                SunNode.AddChildNode(lightNode);

                // Configure attenuation distances because we don't want to light the floor
                lightNode.Light.SetAttribute(new NSNumber(20), SCNLightAttribute.AttenuationEndKey);
                lightNode.Light.SetAttribute(new NSNumber(19.5), SCNLightAttribute.AttenuationStartKey);

                // Animation
                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 1;
                lightNode.Light.Color            = NSColor.White;                               // switch on
                presentationViewController.UpdateLightingWithIntensities(new float[] { 0.0f }); //switch off all the other lights
                SunHaloNode.Opacity = 0.5f;                                                     // make the halo stronger
                SCNTransaction.Commit();
                break;
            }
        }
示例#12
0
        public override void PresentStep(int index, PresentationViewController presentationViewController)
        {
            switch (index)
            {
            case 0:
                // Hide everything (in case the user went backward)
                for (var i = 1; i < 4; i++)
                {
                    var teapot = GroundNode.FindChildNode("Teapot" + i, true);
                    teapot.Opacity = 0.0f;
                }
                break;

            case 1:
                // Move the camera and adjust the clipping plane
                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 3;
                presentationViewController.CameraNode.Position    = new SCNVector3(0, 0, 200);
                presentationViewController.CameraNode.Camera.ZFar = 500.0f;
                SCNTransaction.Commit();
                break;

            case 2:
                // Revert to original position
                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 1;
                presentationViewController.CameraNode.Position    = new SCNVector3(0, 0, 0);
                presentationViewController.CameraNode.Camera.ZFar = 100.0f;
                SCNTransaction.Commit();
                break;

            case 3:
                var numberNodes = new SCNNode[] { AddNumberNode("64k", -17),
                                                  AddNumberNode("6k", -9),
                                                  AddNumberNode("3k", -1),
                                                  AddNumberNode("1k", 6.5f),
                                                  AddNumberNode("256", 14) };
                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 1;

                // Move the camera and the text
                presentationViewController.CameraHandle.Position = new SCNVector3(presentationViewController.CameraHandle.Position.X, presentationViewController.CameraHandle.Position.Y + 6, presentationViewController.CameraHandle.Position.Z);
                TextManager.TextNode.Position = new SCNVector3(TextManager.TextNode.Position.X, TextManager.TextNode.Position.Y + 6, TextManager.TextNode.Position.Z);

                // Show the remaining resolutions
                for (var i = 0; i < 5; i++)
                {
                    var numberNode = numberNodes [i];
                    numberNode.Position = new SCNVector3(numberNode.Position.X, 7, -5);

                    var teapot = GroundNode.FindChildNode("Teapot" + i, true);
                    teapot.Opacity  = 1.0f;
                    teapot.Rotation = new SCNVector4(0, 0, 1, (float)(Math.PI / 4));
                    teapot.Position = new SCNVector3((i - 2) * 8, 5, teapot.Position.Z);
                }

                SCNTransaction.Commit();
                break;

            case 4:
                presentationViewController.ShowsNewInSceneKitBadge(true);

                // Remove the numbers
                RemoveNumberNodes();

                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 1;
                // Add some text and code
                TextManager.SetSubtitle("SCNLevelOfDetail");

                TextManager.AddCode("#var lod1 = SCNLevelOfDetail.#CreateWithWorldSpaceDistance# (aGeometry, aDistance); \n"
                                    + "geometry.#LevelsOfDetail# = new SCNLevelOfDetail { lod1, lod2, ..., lodn };#");

                // Animation the merge
                for (int i = 0; i < 5; i++)
                {
                    var teapot = GroundNode.FindChildNode("Teapot" + i, true);

                    teapot.Opacity  = i == 0 ? 1.0f : 0.0f;
                    teapot.Rotation = new SCNVector4(0, 0, 1, 0);
                    teapot.Position = new SCNVector3(0, -5, teapot.Position.Z);
                }

                // Move the camera and the text
                presentationViewController.CameraHandle.Position = new SCNVector3(presentationViewController.CameraHandle.Position.X, presentationViewController.CameraHandle.Position.Y - 3, presentationViewController.CameraHandle.Position.Z);
                TextManager.TextNode.Position = new SCNVector3(TextManager.TextNode.Position.X, TextManager.TextNode.Position.Y - 3, TextManager.TextNode.Position.Z);

                SCNTransaction.Commit();
                break;

            case 5:
                presentationViewController.ShowsNewInSceneKitBadge(false);

                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 3;
                // Change the lighting to remove the front light and rise the main light
                presentationViewController.UpdateLightingWithIntensities(new float[] { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.3f });
                presentationViewController.RiseMainLight(true);

                // Remove some text
                TextManager.FadeOutText(SlideTextManager.TextType.Title);
                TextManager.FadeOutText(SlideTextManager.TextType.Subtitle);
                TextManager.FadeOutText(SlideTextManager.TextType.Code);
                SCNTransaction.Commit();

                // Retrieve the main teapot
                var maintTeapot = GroundNode.FindChildNode("Teapot0", true);

                // The distances to use for each LOD
                var distances = new float[] { 30, 50, 90, 150 };

                // An array of SCNLevelOfDetail instances that we will build
                var levelsOfDetail = new SCNLevelOfDetail[4];
                for (var i = 1; i < 5; i++)
                {
                    var teapotNode = GroundNode.FindChildNode("Teapot" + i, true);
                    var teapot     = teapotNode.Geometry;

                    // Unshare the material because we will highlight the different levels of detail with different colors in the next step
                    teapot.FirstMaterial = (SCNMaterial)teapot.FirstMaterial.Copy();

                    // Build the SCNLevelOfDetail instance
                    var levelOfDetail = SCNLevelOfDetail.CreateWithWorldSpaceDistance(teapot, distances [i - 1]);
                    levelsOfDetail [i - 1] = levelOfDetail;
                }

                maintTeapot.Geometry.LevelsOfDetail = levelsOfDetail;

                // Duplicate and move the teapots
                var startTime = CAAnimation.CurrentMediaTime();
                var delay     = 0.2;

                var rowCount    = 9;
                var columnCount = 12;

                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 0;
                // Change the far clipping plane to be able to see far away
                presentationViewController.CameraNode.Camera.ZFar = 1000.0;

                for (var j = 0; j < columnCount; j++)
                {
                    for (var i = 0; i < rowCount; i++)
                    {
                        // Clone
                        var clone = maintTeapot.Clone();
                        maintTeapot.ParentNode.AddChildNode(clone);

                        // Animate
                        var animation = CABasicAnimation.FromKeyPath("position");
                        animation.Additive  = true;
                        animation.Duration  = 1.0;
                        animation.To        = NSValue.FromVector(new SCNVector3((i - rowCount / 2.0f) * 12.0f, 5 + (columnCount - j) * 15.0f, 0));
                        animation.From      = NSValue.FromVector(new SCNVector3(0, 0, 0));
                        animation.BeginTime = startTime + delay;                         // desynchronize

                        // Freeze at the end of the animation
                        animation.RemovedOnCompletion = false;
                        animation.FillMode            = CAFillMode.Forwards;

                        clone.AddAnimation(animation, new NSString("cloneAnimation"));

                        // Animate the hidden property to automatically show the node when the position animation starts
                        animation          = CABasicAnimation.FromKeyPath("hidden");
                        animation.Duration = delay + 0.01;
                        animation.FillMode = CAFillMode.Both;
                        animation.From     = new NSNumber(1);
                        animation.To       = new NSNumber(0);
                        clone.AddAnimation(animation, new NSString("cloneAnimation2"));

                        delay += 0.05;
                    }
                }
                SCNTransaction.Commit();

                // Animate the camera while we duplicate the nodes
                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 1.0 + rowCount * columnCount * 0.05;

                var position = presentationViewController.CameraHandle.Position;
                presentationViewController.CameraHandle.Position = new SCNVector3(position.X, position.Y + 5, position.Z);
                presentationViewController.CameraPitch.Rotation  = new SCNVector4(1, 0, 0, presentationViewController.CameraPitch.Rotation.W - ((float)(Math.PI / 4) * 0.1f));
                SCNTransaction.Commit();
                break;

            case 6:
                // Highlight the levels of detail with colors
                var teapotChild = GroundNode.FindChildNode("Teapot0", true);
                var colors      = new NSColor[] { NSColor.Red, NSColor.Orange, NSColor.Yellow, NSColor.Green };

                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 1;
                for (var i = 0; i < 4; i++)
                {
                    var levelOfDetail = teapotChild.Geometry.LevelsOfDetail [i];
                    levelOfDetail.Geometry.FirstMaterial.Multiply.Contents = colors [i];
                }
                SCNTransaction.Commit();
                break;
            }
        }
示例#13
0
        public override void SetupSlide(PresentationViewController presentationViewController)
        {
            // Set the slide's title and subtile and add some text
            TextManager.SetTitle("Node Attributes");
            TextManager.SetSubtitle("SCNGeometry");

            TextManager.AddBulletAtLevel("Triangles", 0);
            TextManager.AddBulletAtLevel("Vertices", 0);
            TextManager.AddBulletAtLevel("Normals", 0);
            TextManager.AddBulletAtLevel("UVs", 0);
            TextManager.AddBulletAtLevel("Materials", 0);

            // We create a container for several versions of the teapot model
            // - one teapot to show positions and normals
            // - one teapot to show texture coordinates
            // - one teapot to show materials
            var allTeapotsNode = SCNNode.Create();

            allTeapotsNode.Rotation = new SCNVector4(1, 0, 0, -(float)(Math.PI / 2));
            GroundNode.AddChildNode(allTeapotsNode);

            TeapotNodeForPositionsAndNormals = Utils.SCAddChildNode(allTeapotsNode, "TeapotLowRes", "Scenes.scnassets/teapots/teapotLowRes", 17);
            TeapotNodeForUVs       = Utils.SCAddChildNode(allTeapotsNode, "Teapot", "Scenes.scnassets/teapots/teapot", 17);
            TeapotNodeForMaterials = Utils.SCAddChildNode(allTeapotsNode, "teapotMaterials", "Scenes.scnassets/teapots/teapotMaterial", 17);

            TeapotNodeForPositionsAndNormals.Position = new SCNVector3(4, 0, 0);
            TeapotNodeForUVs.Position       = new SCNVector3(4, 0, 0);
            TeapotNodeForMaterials.Position = new SCNVector3(4, 0, 0);

            foreach (var child in TeapotNodeForMaterials.ChildNodes)
            {
                foreach (var material in child.Geometry.Materials)
                {
                    material.Multiply.Contents = new NSImage(NSBundle.MainBundle.PathForResource("Scenes.scnassets/teapots/UVs", "png"));
                    material.Multiply.WrapS    = SCNWrapMode.Repeat;
                    material.Multiply.WrapT    = SCNWrapMode.Repeat;
                    //material.Reflective.Contents = NSColor.White;
                    //material.Reflective.Intensity = 3.0f;
                    //material.FresnelExponent = 3.0f;
                }
            }

            // Animate the teapots (rotate forever)
            var rotationAnimation = CABasicAnimation.FromKeyPath("rotation");

            rotationAnimation.Duration    = 40.0f;
            rotationAnimation.RepeatCount = float.MaxValue;
            rotationAnimation.To          = NSValue.FromVector(new SCNVector4(0, 0, 1, (float)(Math.PI * 2)));

            TeapotNodeForPositionsAndNormals.AddAnimation(rotationAnimation, new NSString("teapotNodeForPositionsAndNormalsAnimation"));
            TeapotNodeForUVs.AddAnimation(rotationAnimation, new NSString("teapotNodeForUVsAnimation"));
            TeapotNodeForMaterials.AddAnimation(rotationAnimation, new NSString("teapotNodeForMaterialsAnimation"));

            // Load the "explode" shader modifier and add it to the geometry
            //var explodeShaderPath = NSBundle.MainBundle.PathForResource ("Shaders/explode", "shader");
            //var explodeShaderSource = System.IO.File.ReadAllText (explodeShaderPath);
            // TODO TeapotNodeForPositionsAndNormals.Geometry.ShaderModifiers = new SCNShaderModifiers { EntryPointGeometry = explodeShaderSource };

            PositionsVisualizationNode = SCNNode.Create();
            NormalsVisualizationNode   = SCNNode.Create();

            // Build nodes that will help visualize the vertices (position and normal)
            BuildVisualizationsOfNode(TeapotNodeForPositionsAndNormals, ref PositionsVisualizationNode, ref NormalsVisualizationNode);

            NormalsVisualizationNode.CastsShadow = false;

            TeapotNodeForMaterials.AddChildNode(PositionsVisualizationNode);
            TeapotNodeForMaterials.AddChildNode(NormalsVisualizationNode);
        }
示例#14
0
        public override void PresentStep(int index, PresentationViewController presentationViewController)
        {
            SCNTransaction.Begin();

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

                TextManager.SetSubtitle("API");

                TextManager.AddEmptyLine();
                TextManager.AddCode("#aMaterial.#ShaderModifiers# = new SCNShaderModifiers {\n"
                                    + "     <Entry Point> = <GLSL Code>\n"
                                    + "};#");
                TextManager.FlipInText(SlideTextManager.TextType.Code);
                TextManager.FlipInText(SlideTextManager.TextType.Subtitle);

                break;

            case 2:
                TextManager.FlipOutText(SlideTextManager.TextType.Code);

                TextManager.AddEmptyLine();
                TextManager.AddCode("#aMaterial.#ShaderModifiers# = new SCNShaderModifiers { \n"
                                    + "     EntryCGPointragment = \n"
                                    + "     new Vector3 (1.0f) - #output#.Color.GetRgb () \n"
                                    + "};#");

                TextManager.FlipInText(SlideTextManager.TextType.Code);

                break;

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

                TextManager.SetSubtitle("Entry points");

                TextManager.AddBulletAtLevel("Geometry", 0);
                TextManager.AddBulletAtLevel("Surface", 0);
                TextManager.AddBulletAtLevel("Lighting", 0);
                TextManager.AddBulletAtLevel("Fragment", 0);
                TextManager.FlipInText(SlideTextManager.TextType.Bullet);
                TextManager.FlipInText(SlideTextManager.TextType.Subtitle);

                break;

            case 4:
                SCNTransaction.AnimationDuration = 1;

                TextManager.HighlightBullet(0);

                // Create a (very) tesselated plane
                var plane = SCNPlane.Create(10, 10);
                plane.WidthSegmentCount  = 200;
                plane.HeightSegmentCount = 200;

                // Setup the material (same as the floor)
                plane.FirstMaterial.Diffuse.WrapS             = SCNWrapMode.Mirror;
                plane.FirstMaterial.Diffuse.WrapT             = SCNWrapMode.Mirror;
                plane.FirstMaterial.Diffuse.Contents          = new NSImage("/Library/Desktop Pictures/Circles.jpg");
                plane.FirstMaterial.Diffuse.ContentsTransform = SCNMatrix4.CreateFromAxisAngle(new SCNVector3(0, 0, 1), NMath.PI / 4);
                plane.FirstMaterial.Specular.Contents         = NSColor.White;
                plane.FirstMaterial.Reflective.Contents       = new NSImage(NSBundle.MainBundle.PathForResource("SharedTextures/envmap", "jpg"));
                plane.FirstMaterial.Reflective.Intensity      = 0.0f;

                // Create a node to hold that plane
                PlaneNode          = SCNNode.Create();
                PlaneNode.Position = new SCNVector3(0, 0.1f, 0);
                PlaneNode.Rotation = new SCNVector4(1, 0, 0, -(float)(Math.PI / 2));
                PlaneNode.Scale    = new SCNVector3(5, 5, 1);
                PlaneNode.Geometry = plane;
                ContentNode.AddChildNode(PlaneNode);

                // Attach the "wave" shader modifier, and set an initial intensity value of 0
                var shaderFile       = NSBundle.MainBundle.PathForResource("Shaders/wave", "shader");
                var geometryModifier = File.ReadAllText(shaderFile);
                PlaneNode.Geometry.ShaderModifiers = new SCNShaderModifiers {
                    EntryPointGeometry = geometryModifier
                };
                PlaneNode.Geometry.SetValueForKey(new NSNumber(0.0f), new NSString("intensity"));

                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 0;
                // Show the pseudo code for the deformation
                var textNode = TextManager.AddCode("#float len = #geometry#.Position.Xy.Length;\n"
                                                   + "aMaterial.ShaderModifiers = new SCNShaderModifiers { \n"
                                                   + "     #EntryPointGeometry# = geometry.Position.Y \n"
                                                   + "};#");

                textNode.Position = new SCNVector3(8.5f, 7, 0);
                SCNTransaction.Commit();
                break;

            case 5:
                // Progressively increase the intensity
                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 2;
                PlaneNode.Geometry.SetValueForKey(new NSNumber(1.0f), new NSString("intensity"));
                PlaneNode.Geometry.FirstMaterial.Reflective.Intensity = 0.3f;
                SCNTransaction.Commit();

                // Redraw forever
                ((SCNView)presentationViewController.View).Playing = true;
                ((SCNView)presentationViewController.View).Loops   = true;
                break;

            case 6:
                SCNTransaction.AnimationDuration = 1;

                TextManager.FadeOutText(SlideTextManager.TextType.Code);

                // Hide the plane used for the previous modifier
                PlaneNode.Geometry.SetValueForKey(new NSNumber(0.0f), new NSString("intensity"));
                PlaneNode.Geometry.FirstMaterial.Reflective.Intensity = 0.0f;
                PlaneNode.Opacity = 0.0f;

                // Create a sphere to illustrate the "car paint" modifier
                var sphere = SCNSphere.Create(6);
                sphere.SegmentCount = 100;
                sphere.FirstMaterial.Diffuse.Contents    = new NSImage(NSBundle.MainBundle.PathForResource("SharedTextures/noise", "png"));
                sphere.FirstMaterial.Diffuse.WrapS       = SCNWrapMode.Repeat;
                sphere.FirstMaterial.Diffuse.WrapT       = SCNWrapMode.Repeat;
                sphere.FirstMaterial.Reflective.Contents = new NSImage(NSBundle.MainBundle.PathForResource("SharedTextures/envmap3", "jpg"));
                sphere.FirstMaterial.FresnelExponent     = 1.3f;

                SphereNode          = SCNNode.FromGeometry(sphere);
                SphereNode.Position = new SCNVector3(5, 6, 0);
                GroundNode.AddChildNode(SphereNode);

                // Attach the "car paint" shader modifier
                shaderFile = NSBundle.MainBundle.PathForResource("Shaders/carPaint", "shader");
                var surfaceModifier = File.ReadAllText(shaderFile);
                sphere.FirstMaterial.ShaderModifiers = new SCNShaderModifiers {
                    EntryPointSurface = surfaceModifier
                };

                var rotationAnimation = CABasicAnimation.FromKeyPath("rotation");
                rotationAnimation.Duration    = 15.0f;
                rotationAnimation.RepeatCount = float.MaxValue;
                rotationAnimation.By          = NSValue.FromVector(new SCNVector4(0, 1, 0, -(float)(Math.PI * 2)));
                SphereNode.AddAnimation(rotationAnimation, new NSString("sphereNodeAnimation"));

                TextManager.HighlightBullet(1);
                break;

            case 7:
                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration       = 1.5f;
                SCNTransaction.AnimationTimingFunction = CAMediaTimingFunction.FromName(CAMediaTimingFunction.EaseInEaseOut);
                // Move the camera closer
                presentationViewController.CameraNode.Position = new SCNVector3(5, -0.5f, -17);
                SCNTransaction.Commit();
                break;

            case 8:
                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration       = 1.0f;
                SCNTransaction.AnimationTimingFunction = CAMediaTimingFunction.FromName(CAMediaTimingFunction.EaseInEaseOut);
                // Move back
                presentationViewController.CameraNode.Position = new SCNVector3(0, 0, 0);
                SCNTransaction.Commit();
                break;

            case 9:
                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 1.0f;
                // Hide the sphere used for the previous modifier
                SphereNode.Opacity  = 0.0f;
                SphereNode.Position = new SCNVector3(6, 4, -8);
                SCNTransaction.Commit();

                SCNTransaction.AnimationDuration = 0;

                TextManager.HighlightBullet(2);

                // Load the model, animate
                var intermediateNode = SCNNode.Create();
                intermediateNode.Position = new SCNVector3(4, 0.1f, 10);
                TorusNode = Utils.SCAddChildNode(intermediateNode, "torus", "Scenes/torus/torus", 11);

                rotationAnimation             = CABasicAnimation.FromKeyPath("rotation");
                rotationAnimation.Duration    = 10.0f;
                rotationAnimation.RepeatCount = float.MaxValue;
                rotationAnimation.To          = NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI * 2)));
                TorusNode.AddAnimation(rotationAnimation, new NSString("torusNodeAnimation"));

                GroundNode.AddChildNode(intermediateNode);

                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 1.0f;
                intermediateNode.Position        = new SCNVector3(4, 0.1f, 0);
                SCNTransaction.Commit();

                break;

            case 10:
                // Attach the shader modifier
                shaderFile = NSBundle.MainBundle.PathForResource("Shaders/toon", "shader");
                var lightingModifier = File.ReadAllText(shaderFile);
                TorusNode.Geometry.ShaderModifiers = new SCNShaderModifiers {
                    EntryPointLightingModel = lightingModifier
                };
                break;

            case 11:
                SCNTransaction.AnimationDuration = 1.0f;

                // Hide the torus used for the previous modifier
                TorusNode.Position = new SCNVector3(TorusNode.Position.X, TorusNode.Position.Y, TorusNode.Position.Z - 10);
                TorusNode.Opacity  = 0.0f;

                // Load the model, animate
                intermediateNode          = SCNNode.Create();
                intermediateNode.Position = new SCNVector3(4, -2.6f, 14);
                intermediateNode.Scale    = new SCNVector3(70, 70, 70);

                XRayNode          = Utils.SCAddChildNode(intermediateNode, "node", "Scenes/bunny", 12);
                XRayNode.Position = new SCNVector3(0, 0, 0);
                XRayNode.Opacity  = 0.0f;

                GroundNode.AddChildNode(intermediateNode);

                rotationAnimation             = CABasicAnimation.FromKeyPath("rotation");
                rotationAnimation.Duration    = 10.0f;
                rotationAnimation.RepeatCount = float.MaxValue;
                rotationAnimation.From        = NSValue.FromVector(new SCNVector4(0, 1, 0, 0));
                rotationAnimation.To          = NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI * 2)));
                intermediateNode.AddAnimation(rotationAnimation, new NSString("bunnyNodeAnimation"));

                TextManager.HighlightBullet(3);

                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 1.0f;
                XRayNode.Opacity          = 1.0f;
                intermediateNode.Position = new SCNVector3(4, -2.6f, -2);
                SCNTransaction.Commit();
                break;

            case 12:
                // Attach the "x ray" modifier
                shaderFile = NSBundle.MainBundle.PathForResource("Shaders/xRay", "shader");
                var fragmentModifier = File.ReadAllText(shaderFile);
                XRayNode.Geometry.ShaderModifiers = new SCNShaderModifiers {
                    EntryPointFragment = fragmentModifier
                };
                XRayNode.Geometry.FirstMaterial.ReadsFromDepthBuffer = false;
                break;

            case 13:
                // Highlight everything
                TextManager.HighlightBullet(-1);

                // Hide the node used for the previous modifier
                XRayNode.Opacity             = 0.0f;
                XRayNode.ParentNode.Position = new SCNVector3(4, -2.6f, -5);

                // Create the model
                sphere = SCNSphere.Create(5);
                sphere.SegmentCount = 150;                 // tesselate a lot

                VirusNode          = SCNNode.FromGeometry(sphere);
                VirusNode.Position = new SCNVector3(3, 6, 0);
                VirusNode.Rotation = new SCNVector4(1, 0, 0, Pitch * (float)(Math.PI / 180.0f));
                GroundNode.AddChildNode(VirusNode);

                // Set the shader modifiers
                var geomFile  = NSBundle.MainBundle.PathForResource("Shaders/sm_geom", "shader");
                var surfFile  = NSBundle.MainBundle.PathForResource("Shaders/sm_surf", "shader");
                var lightFile = NSBundle.MainBundle.PathForResource("Shaders/sm_light", "shader");
                var fragFile  = NSBundle.MainBundle.PathForResource("Shaders/sm_frag", "shader");
                geometryModifier = File.ReadAllText(geomFile);
                surfaceModifier  = File.ReadAllText(surfFile);
                lightingModifier = File.ReadAllText(lightFile);
                fragmentModifier = File.ReadAllText(fragFile);
                VirusNode.Geometry.FirstMaterial.ShaderModifiers = new SCNShaderModifiers {
                    EntryPointGeometry      = geometryModifier,
                    EntryPointSurface       = surfaceModifier,
                    EntryPointLightingModel = lightingModifier,
                    EntryPointFragment      = fragmentModifier
                };
                break;

            case 14:
                SCNTransaction.AnimationDuration = 1.0f;

                // Hide the node used for the previous modifier
                VirusNode.Opacity  = 0.0f;
                VirusNode.Position = new SCNVector3(3, 6, -10);

                // Change the text
                TextManager.FadeOutText(SlideTextManager.TextType.Code);
                TextManager.FlipOutText(SlideTextManager.TextType.Bullet);
                TextManager.FlipOutText(SlideTextManager.TextType.Subtitle);

                TextManager.SetSubtitle("SCNShadable");

                TextManager.AddBulletAtLevel("Protocol adopted by SCNMaterial and SCNGeometry", 0);
                TextManager.AddBulletAtLevel("Shaders parameters are animatable", 0);
                TextManager.AddBulletAtLevel("Texture samplers are bound to a SCNMaterialProperty", 0);

                TextManager.AddCode("#var aProperty = SCNMaterialProperty.#Create# (anImage);\n"
                                    + "aMaterial.#SetValueForKey# (aProperty, #new NSString# (\"aSampler\"));#");

                TextManager.FlipInText(SlideTextManager.TextType.Subtitle);
                TextManager.FlipInText(SlideTextManager.TextType.Bullet);
                TextManager.FlipInText(SlideTextManager.TextType.Code);
                break;
            }
            SCNTransaction.Commit();
        }
示例#15
0
        // Create a carousel of 3D primitives
        private void PresentPrimitives()
        {
            // Create the carousel node. It will host all the primitives as child nodes.
            CarouselNode          = SCNNode.Create();
            CarouselNode.Position = new SCNVector3(0, 0.1f, -5);
            CarouselNode.Scale    = new SCNVector3(0, 0, 0);           // start infinitely small
            ContentNode.AddChildNode(CarouselNode);

            // Animate the scale to achieve a "grow" effect
            SCNTransaction.Begin();
            SCNTransaction.AnimationDuration = 1;
            CarouselNode.Scale = new SCNVector3(1, 1, 1);
            SCNTransaction.Commit();

            // Rotate the carousel forever
            var rotationAnimation = CABasicAnimation.FromKeyPath("rotation");

            rotationAnimation.Duration    = 40.0f;
            rotationAnimation.RepeatCount = float.MaxValue;
            rotationAnimation.To          = NSValue.FromVector(new SCNVector4(0, 1, 0, (float)Math.PI * 2));
            CarouselNode.AddAnimation(rotationAnimation, new NSString("rotationAnimation"));

            // A material shared by all the primitives
            var sharedMaterial = SCNMaterial.Create();

            sharedMaterial.Reflective.Contents  = new NSImage(NSBundle.MainBundle.PathForResource("SharedTextures/envmap", "jpg"));
            sharedMaterial.Reflective.Intensity = 0.2f;
            sharedMaterial.DoubleSided          = true;

            PrimitiveIndex = 0;

            // SCNBox
            var box = SCNBox.Create(5.0f, 5.0f, 5.0f, 5.0f * 0.05f);

            box.WidthSegmentCount   = 4;
            box.HeightSegmentCount  = 4;
            box.LengthSegmentCount  = 4;
            box.ChamferSegmentCount = 4;
            AddPrimitive(box, 5.0f / 2, rotationAnimation, sharedMaterial);

            // SCNPyramid
            var pyramid = SCNPyramid.Create(5.0f * 0.8f, 5.0f, 5.0f * 0.8f);

            pyramid.WidthSegmentCount  = 4;
            pyramid.HeightSegmentCount = 10;
            pyramid.LengthSegmentCount = 4;
            AddPrimitive(pyramid, 0, rotationAnimation, sharedMaterial);

            // SCNCone
            var cone = SCNCone.Create(0, 5.0f / 2, 5.0f);

            cone.RadialSegmentCount = 20;
            cone.HeightSegmentCount = 4;
            AddPrimitive(cone, 5.0f / 2, rotationAnimation, sharedMaterial);

            // SCNTube
            var tube = SCNTube.Create(5.0f * 0.25f, 5.0f * 0.5f, 5.0f);

            tube.HeightSegmentCount = 5;
            tube.RadialSegmentCount = 40;
            AddPrimitive(tube, 5.0f / 2, rotationAnimation, sharedMaterial);

            // SCNCapsule
            var capsule = SCNCapsule.Create(5.0f * 0.4f, 5.0f * 1.4f);

            capsule.HeightSegmentCount = 5;
            capsule.RadialSegmentCount = 20;
            AddPrimitive(capsule, 5.0f * 0.7f, rotationAnimation, sharedMaterial);

            // SCNCylinder
            var cylinder = SCNCylinder.Create(5.0f * 0.5f, 5.0f);

            cylinder.HeightSegmentCount = 5;
            cylinder.RadialSegmentCount = 40;
            AddPrimitive(cylinder, 5.0f / 2, rotationAnimation, sharedMaterial);

            // SCNSphere
            var sphere = SCNSphere.Create(5.0f * 0.5f);

            sphere.SegmentCount = 20;
            AddPrimitive(sphere, 5.0f / 2, rotationAnimation, sharedMaterial);

            // SCNTorus
            var torus = SCNTorus.Create(5.0f * 0.5f, 5.0f * 0.25f);

            torus.RingSegmentCount = 40;
            torus.PipeSegmentCount = 20;
            AddPrimitive(torus, 5.0f / 4, rotationAnimation, sharedMaterial);

            // SCNPlane
            var plane = SCNPlane.Create(5.0f, 5.0f);

            plane.WidthSegmentCount  = 5;
            plane.HeightSegmentCount = 5;
            plane.CornerRadius       = 5.0f * 0.1f;
            AddPrimitive(plane, 5.0f / 2, rotationAnimation, sharedMaterial);
        }
示例#16
0
        public override void PresentStep(int index, PresentationViewController presentationViewController)
        {
            switch (index)
            {
            case (int)ParticleSteps.Fire:
                TextManager.FlipOutText(SlideTextManager.TextType.Bullet);

                TextManager.AddEmptyLine();
                TextManager.AddBulletAtLevel("Particle Image", 0);
                TextManager.AddBulletAtLevel("Color over life duration", 0);
                TextManager.AddBulletAtLevel("Size over life duration", 0);
                TextManager.AddBulletAtLevel("Several blend modes", 0);

                TextManager.FlipInText(SlideTextManager.TextType.Bullet);

                var hole = SCNNode.Create();
                hole.Geometry = SCNTube.Create(1.7f, 1.9f, 1.5f);
                hole.Position = new SCNVector3(0, 0, HOLE_Z);
                hole.Scale    = new SCNVector3(1, 0, 1);

                GroundNode.AddChildNode(hole);

                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 0.5f;

                hole.Scale = new SCNVector3(1, 1, 1);

                SCNTransaction.Commit();

                var ps = SCNParticleSystem.Create("fire", "Particles");
                hole.AddParticleSystem(ps);

                Hole = hole;
                break;

            case (int)ParticleSteps.FireScreen:
                ps           = Hole.ParticleSystems [0];
                ps.BlendMode = SCNParticleBlendMode.Screen;
                break;

            case (int)ParticleSteps.Local:
                TextManager.FlipOutText(SlideTextManager.TextType.Bullet);

                TextManager.AddBulletAtLevel("Local vs Global", 0);
                TextManager.FlipInText(SlideTextManager.TextType.Bullet);

                Hole.RemoveAllParticleSystems();
                Hole2          = Hole.Clone();
                Hole2.Geometry = (SCNGeometry)Hole.Geometry.Copy();
                Hole2.Position = new SCNVector3(0, -2, HOLE_Z - 4);
                GroundNode.AddChildNode(Hole2);
                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 0.5;
                Hole2.Position = new SCNVector3(0, 0, HOLE_Z - 4);
                SCNTransaction.Commit();

                ps = SCNParticleSystem.Create("reactor", "Particles");
                ps.ParticleColorVariation = new SCNVector4(0, 0, 0.5f, 0);
                Hole.AddParticleSystem(ps);

                var localPs = (SCNParticleSystem)ps.Copy();
                localPs.ParticleImage = ps.ParticleImage;
                localPs.Local         = true;
                Hole2.AddParticleSystem(localPs);

                var animation = CABasicAnimation.FromKeyPath("position");
                animation.From           = NSValue.FromVector(new SCNVector3(7, 0, HOLE_Z));
                animation.To             = NSValue.FromVector(new SCNVector3(-7, 0, HOLE_Z));
                animation.BeginTime      = CAAnimation.CurrentMediaTime() + 0.75;
                animation.Duration       = 8;
                animation.AutoReverses   = true;
                animation.RepeatCount    = float.MaxValue;
                animation.TimingFunction = CAMediaTimingFunction.FromName(CAMediaTimingFunction.EaseInEaseOut);
                animation.TimeOffset     = animation.Duration / 2;
                Hole.AddAnimation(animation, new NSString("animateHole"));

                animation                = CABasicAnimation.FromKeyPath("position");
                animation.From           = NSValue.FromVector(new SCNVector3(-7, 0, HOLE_Z - 4));
                animation.To             = NSValue.FromVector(new SCNVector3(7, 0, HOLE_Z - 4));
                animation.BeginTime      = CAAnimation.CurrentMediaTime() + 0.75;
                animation.Duration       = 8;
                animation.AutoReverses   = true;
                animation.RepeatCount    = float.MaxValue;
                animation.TimingFunction = CAMediaTimingFunction.FromName(CAMediaTimingFunction.EaseInEaseOut);
                animation.TimeOffset     = animation.Duration / 2;
                Hole2.AddAnimation(animation, new NSString("animateHole"));
                break;

            case (int)ParticleSteps.Gravity:
                TextManager.FlipOutText(SlideTextManager.TextType.Bullet);

                TextManager.AddBulletAtLevel("Affected by gravity", 0);
                TextManager.FlipInText(SlideTextManager.TextType.Bullet);

                Hole2.RemoveAllParticleSystems();
                Hole2.RunAction(SCNAction.Sequence(new SCNAction[] {
                    SCNAction.ScaleTo(0, 0.5),
                    SCNAction.RemoveFromParentNode()
                }));
                Hole.RemoveAllParticleSystems();
                Hole.RemoveAnimation(new NSString("animateHole"), 0.5f);

                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 0.5;

                var tube = (SCNTube)Hole.Geometry;
                tube.InnerRadius = 0.3f;
                tube.OuterRadius = 0.4f;
                tube.Height      = 1.0f;

                SCNTransaction.Commit();

                ps = SCNParticleSystem.Create("sparks", "Particles");
                Hole.RemoveAllParticleSystems();
                Hole.AddParticleSystem(ps);

                foreach (var child in ((SCNView)presentationViewController.View).Scene.RootNode.ChildNodes)
                {
                    if (child.Geometry != null)
                    {
                        if (child.Geometry.GetType() == typeof(SCNFloor))
                        {
                            FloorNode = child;
                        }
                    }
                }

                /*FloorNode = ((SCNView)presentationViewController.View).Scene.RootNode.FindNodes ((SCNNode child, out bool stop) => {
                 *      stop = false;
                 *      if (child.Geometry != null)
                 *              stop = (child.Geometry.GetType () == typeof(SCNFloor));
                 *      return stop;
                 * });*/

                /*FloorNode = [presentationViewController.view.scene.rootNode childNodesPassingTest:^BOOL(SCNNode *child, BOOL *stop) {
                 *      return [child.geometry isKindOfClass:[SCNFloor class]];
                 * }][0];*/

                ps.ColliderNodes = new SCNNode[] { FloorNode };

                break;

            case (int)ParticleSteps.Collider:
                TextManager.FlipOutText(SlideTextManager.TextType.Bullet);

                TextManager.AddBulletAtLevel("Affected by colliders", 0);
                TextManager.FlipInText(SlideTextManager.TextType.Bullet);

                var boxNode = SCNNode.Create();
                boxNode.Geometry = SCNBox.Create(5, 0.2f, 5, 0);
                boxNode.Position = new SCNVector3(0, 7, HOLE_Z);
                boxNode.Geometry.FirstMaterial.Emission.Contents = NSColor.DarkGray;

                GroundNode.AddChildNode(boxNode);

                ps = Hole.ParticleSystems [0];
                ps.ColliderNodes = new SCNNode[] { FloorNode, boxNode };

                animation                = CABasicAnimation.FromKeyPath("eulerAngles");
                animation.From           = NSValue.FromVector(new SCNVector3(0, 0, NMath.PI / 4 * 1.7f));
                animation.To             = NSValue.FromVector(new SCNVector3(0, 0, -NMath.PI / 4 * 1.7f));
                animation.BeginTime      = CAAnimation.CurrentMediaTime() + 0.5;
                animation.Duration       = 2;
                animation.AutoReverses   = true;
                animation.RepeatCount    = float.MaxValue;
                animation.TimingFunction = CAMediaTimingFunction.FromName(CAMediaTimingFunction.EaseInEaseOut);
                animation.TimeOffset     = animation.Duration / 2;
                boxNode.AddAnimation(animation, new NSString("animateHole"));

                BoxNode = boxNode;
                break;

            case (int)ParticleSteps.Fields:
                Hole.RemoveAllParticleSystems();

                Hole.RunAction(SCNAction.Sequence(new SCNAction[] {
                    SCNAction.ScaleTo(0, 0.75),
                    SCNAction.RemoveFromParentNode()
                }));

                BoxNode.RunAction(SCNAction.Sequence(new SCNAction[] {
                    SCNAction.MoveBy(0, 15, 0, 1.0),
                    SCNAction.RemoveFromParentNode()
                }));

                var particleHolder = SCNNode.Create();
                particleHolder.Position = new SCNVector3(0, 20, HOLE_Z);
                GroundNode.AddChildNode(particleHolder);

                ParticleHolder = particleHolder;

                TextManager.FlipOutText(SlideTextManager.TextType.Bullet);
                TextManager.AddBulletAtLevel("Affected by physics fields", 0);
                TextManager.FlipInText(SlideTextManager.TextType.Bullet);

                ps = SCNParticleSystem.Create("snow", "Particles");
                ps.AffectedByPhysicsFields = true;
                ParticleHolder.AddParticleSystem(ps);
                Snow = ps;

                //physics field
                var field = SCNPhysicsField.CreateTurbulenceField(50, 1);
                field.HalfExtent = new SCNVector3(20, 20, 20);
                field.Strength   = 4.0f;

                var fieldOwner = SCNNode.Create();
                fieldOwner.Position = new SCNVector3(0, 5, HOLE_Z);

                GroundNode.AddChildNode(fieldOwner);
                fieldOwner.PhysicsField = field;
                FieldOwner = fieldOwner;

                ps.ColliderNodes = new SCNNode[] { FloorNode };
                break;

            case (int)ParticleSteps.FieldsVortex:
                VortexFieldOwner          = SCNNode.Create();
                VortexFieldOwner.Position = new SCNVector3(0, 5, HOLE_Z);

                GroundNode.AddChildNode(VortexFieldOwner);

                //tornado
                var worldOrigin = new SCNVector3(FieldOwner.WorldTransform.M41, FieldOwner.WorldTransform.M42, FieldOwner.WorldTransform.M43);
                var worldAxis   = new SCNVector3(0, 1, 0);

                var vortex = SCNPhysicsField.CustomField((SCNVector3 position, SCNVector3 velocity, float mass, float charge, double timeInSeconds) => {
                    var l        = new SCNVector3();
                    l.X          = worldOrigin.X - position.X;
                    l.Z          = worldOrigin.Z - position.Z;
                    SCNVector3 t = Cross(worldAxis, l);
                    var d2       = (l.X * l.X + l.Z * l.Z);
                    var vs       = (nfloat)(VS / Math.Sqrt(d2));
                    var fy       = (nfloat)(1.0 - (Math.Min(1.0, (position.Y / 15.0))));
                    return(new SCNVector3(t.X * vs + l.X * (nfloat)VW * fy, 0, t.Z * vs + l.Z * (nfloat)VW * fy));
                });
                vortex.HalfExtent             = new SCNVector3(100, 100, 100);
                VortexFieldOwner.PhysicsField = vortex;
                break;

            case (int)ParticleSteps.SubSystems:
                FieldOwner.RemoveFromParentNode();
                ParticleHolder.RemoveAllParticleSystems();
                Snow.DampingFactor = -1;

                TextManager.FlipOutText(SlideTextManager.TextType.Bullet);
                TextManager.AddBulletAtLevel("Sub-particle system on collision", 0);
                TextManager.FlipInText(SlideTextManager.TextType.Bullet);

                ps = SCNParticleSystem.Create("rain", "Particles");
                var pss = SCNParticleSystem.Create("plok", "Particles");
                pss.IdleDuration = 0;
                pss.Loops        = false;

                ps.SystemSpawnedOnCollision = pss;

                ParticleHolder.AddParticleSystem(ps);
                ps.ColliderNodes = new SCNNode[] { FloorNode };
                break;

            case (int)ParticleSteps.Confetti:
                ParticleHolder.RemoveAllParticleSystems();

                TextManager.FlipOutText(SlideTextManager.TextType.Bullet);
                TextManager.AddBulletAtLevel("Custom blocks", 0);
                TextManager.FlipInText(SlideTextManager.TextType.Bullet);

                ps = SCNParticleSystem.Create();
                ps.EmitterShape                     = SCNBox.Create(20, 9, 5, 0);
                ps.BirthRate                        = 100;
                ps.ParticleLifeSpan                 = 10;
                ps.ParticleLifeSpanVariation        = 0;
                ps.SpreadingAngle                   = 20;
                ps.ParticleSize                     = 0.25f;
                ps.ParticleVelocity                 = 10;
                ps.ParticleVelocityVariation        = 19;
                ps.BirthDirection                   = SCNParticleBirthDirection.Constant;
                ps.EmittingDirection                = new SCNVector3(0, -1, 0);
                ps.BirthLocation                    = SCNParticleBirthLocation.Volume;
                ps.ParticleImage                    = new NSImage(NSBundle.MainBundle.PathForResource("Particles/confetti", "png"));
                ps.LightingEnabled                  = true;
                ps.OrientationMode                  = SCNParticleOrientationMode.Free;
                ps.SortingMode                      = SCNParticleSortingMode.Distance;
                ps.ParticleAngleVariation           = 180;
                ps.ParticleAngularVelocity          = 200;
                ps.ParticleAngularVelocityVariation = 400;
                ps.ParticleColor                    = NSColor.Green;
                ps.ParticleColorVariation           = new SCNVector4(0.2f, 0.1f, 0.1f, 0);
                ps.ParticleBounce                   = 0;
                ps.ParticleFriction                 = 0.6f;
                ps.ColliderNodes                    = new SCNNode[] { FloorNode };
                ps.BlendMode                        = SCNParticleBlendMode.Alpha;

                var floatAnimation = CAKeyFrameAnimation.FromKeyPath("");
                floatAnimation.Values   = new NSNumber[] { 1, 1, 0 };
                floatAnimation.KeyTimes = new NSNumber[] { 0, 0.9f, 1 };
                floatAnimation.Duration = 1.0f;
                floatAnimation.Additive = false;

                //ps.PropertyControllers = @{ SCNParticlePropertyOpacity: [SCNParticlePropertyController controllerWithAnimation:floatAnimation] };
                //ps.HandleEvent (SCNParticleEvent.Birth,

                /*[ps handleEvent:SCNParticleEventBirth forProperties:@[SCNParticlePropertyColor] withBlock:^(void **data, size_t *dataStride, uint32_t *indices , NSInteger count) {
                 *
                 *      for (int i = 0; i < count; ++i) {
                 *              var col = (float *)((char *)data[0] + dataStride[0] * i);
                 *              if (rand() & 0x1) { // swith green for red
                 *                      col[0] = col[1];
                 *                      col[1] = 0;
                 *              }
                 *
                 *      }
                 * }];*/

                /*[ps handleEvent:SCNParticleEventCollision forProperties:@[SCNParticlePropertyAngle, SCNParticlePropertyRotationAxis, SCNParticlePropertyAngularVelocity, SCNParticlePropertyVelocity, SCNParticlePropertyContactNormal] withBlock:^(void **data, size_t *dataStride, uint32_t *indices , NSInteger count) {
                 *
                 *      for (NSInteger i = 0; i < count; ++i) {
                 *              // fix orientation
                 *              float *angle = (float *)((char *)data[0] + dataStride[0] * indices[i]);
                 *              float *axis = (float *)((char *)data[1] + dataStride[1] * indices[i]);
                 *
                 *              float *colNrm = (float *)((char *)data[4] + dataStride[4] * indices[i]);
                 *              SCNVector3 collisionNormal = {colNrm[0], colNrm[1], colNrm[2]};
                 *              SCNVector3 cp = SCNVector3CrossProduct(collisionNormal, SCNVector3Make(0, 0, 1));
                 *              CGFloat cpLen = SCNVector3Length(cp);
                 *              angle[0] = asin(cpLen);
                 *
                 *              axis[0] = cp.x / cpLen;
                 *              axis[1] = cp.y / cpLen;
                 *              axis[2] = cp.z / cpLen;
                 *
                 *              // kill angular rotation
                 *              float *angVel = (float *)((char *)data[2] + dataStride[2] * indices[i]);
                 *              angVel[0] = 0;
                 *
                 *              if (colNrm[1] > 0.4) {
                 *                      float *vel = (float *)((char *)data[3] + dataStride[3] * indices[i]);
                 *                      vel[0] = 0;
                 *                      vel[1] = 0;
                 *                      vel[2] = 0;
                 *              }
                 *      }
                 * }];*/

                ParticleHolder.AddParticleSystem(ps);
                break;

            case (int)ParticleSteps.EmitterCube:
                ParticleHolder.RemoveAllParticleSystems();

                TextManager.FlipOutText(SlideTextManager.TextType.Bullet);
                TextManager.AddBulletAtLevel("Emitter shape", 0);
                TextManager.FlipInText(SlideTextManager.TextType.Bullet);

                ParticleHolder.RemoveFromParentNode();

                ps       = SCNParticleSystem.Create("emitters", "Particles");
                ps.Local = true;
                ParticleHolder.AddParticleSystem(ps);

                var node = SCNNode.Create();
                node.Position = new SCNVector3(3, 6, HOLE_Z);
                node.RunAction(SCNAction.RepeatActionForever(SCNAction.RotateBy(NMath.PI * 2, new SCNVector3(0.3f, 1, 0), 8)));
                GroundNode.AddChildNode(node);
                Bokeh = ps;

                node.AddParticleSystem(ps);
                break;

            case (int)ParticleSteps.EmitterSphere:
                Bokeh.EmitterShape = SCNSphere.Create(5);
                break;

            case (int)ParticleSteps.EmitterTorus:
                Bokeh.EmitterShape = SCNTorus.Create(5, 1);
                break;
            }
        }
        public override void SetupSlide(PresentationViewController presentationViewController)
        {
            // Set the slide's title and add some code
            TextManager.SetTitle("Materials");

            TextManager.AddBulletAtLevel("Diffuse", 0);
            TextManager.AddBulletAtLevel("Ambient", 0);
            TextManager.AddBulletAtLevel("Specular", 0);
            TextManager.AddBulletAtLevel("Normal", 0);
            TextManager.AddBulletAtLevel("Reflective", 0);
            TextManager.AddBulletAtLevel("Emission", 0);
            TextManager.AddBulletAtLevel("Transparent", 0);
            TextManager.AddBulletAtLevel("Multiply", 0);

            // Create a node for Earth and another node to display clouds
            // Use the 'pivot' property to tilt Earth because we don't want to see the north pole.
            EarthNode          = SCNNode.Create();
            EarthNode.Pivot    = SCNMatrix4.CreateFromAxisAngle(new SCNVector3(1, 0, 0), (float)(Math.PI * 0.1f));
            EarthNode.Position = new SCNVector3(6, 7.2f, -2);
            EarthNode.Geometry = SCNSphere.Create(7.2f);

            CloudsNode          = SCNNode.Create();
            CloudsNode.Geometry = SCNSphere.Create(7.9f);

            GroundNode.AddChildNode(EarthNode);
            EarthNode.AddChildNode(CloudsNode);

            // Initially hide everything
            EarthNode.Opacity  = 1.0f;
            CloudsNode.Opacity = 0.5f;

            EarthNode.Geometry.FirstMaterial.Ambient.Intensity    = 1;
            EarthNode.Geometry.FirstMaterial.Normal.Intensity     = 1;
            EarthNode.Geometry.FirstMaterial.Reflective.Intensity = 0.2f;
            EarthNode.Geometry.FirstMaterial.Reflective.Contents  = NSColor.White;
            EarthNode.Geometry.FirstMaterial.FresnelExponent      = 3;

            EarthNode.Geometry.FirstMaterial.Emission.Intensity = 1;
            EarthNode.Geometry.FirstMaterial.Diffuse.Contents   = new NSImage(NSBundle.MainBundle.PathForResource("Scenes.scnassets/earth/earth-diffuse", "jpg"));

            EarthNode.Geometry.FirstMaterial.Shininess          = 0.1f;
            EarthNode.Geometry.FirstMaterial.Specular.Contents  = new NSImage(NSBundle.MainBundle.PathForResource("Scenes.scnassets/earth/earth-specular", "jpg"));
            EarthNode.Geometry.FirstMaterial.Specular.Intensity = 0.8f;

            EarthNode.Geometry.FirstMaterial.Normal.Contents  = new NSImage(NSBundle.MainBundle.PathForResource("Scenes.scnassets/earth/earth-bump", "png"));
            EarthNode.Geometry.FirstMaterial.Normal.Intensity = 1.3f;

            EarthNode.Geometry.FirstMaterial.Emission.Contents = new NSImage(NSBundle.MainBundle.PathForResource("Scenes.scnassets/earth/earth-emissive", "jpg"));
            //EarthNode.Geometry.FirstMaterial.Reflective.Intensity = 1.0f;

            // This effect can also be achieved with an image with some transparency set as the contents of the 'diffuse' property
            CloudsNode.Geometry.FirstMaterial.Transparent.Contents = new NSImage(NSBundle.MainBundle.PathForResource("Scenes.scnassets/earth/cloudsTransparency", "png"));
            CloudsNode.Geometry.FirstMaterial.TransparencyMode     = SCNTransparencyMode.RgbZero;

            // Use a shader modifier to display an environment map independently of the lighting model used

            /*EarthNode.Geometry.ShaderModifiers = new SCNShaderModifiers {
             *      EntryCGPointragment = " _output.color.rgb -= _surface.reflective.rgb * _lightingContribution.diffuse;"
             + "_output.color.rgb += _surface.reflective.rgb;"
             + };*/

            // Add animations
            var rotationAnimation = CABasicAnimation.FromKeyPath("rotation");

            rotationAnimation.Duration    = 40.0f;
            rotationAnimation.RepeatCount = float.MaxValue;
            rotationAnimation.To          = NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI * 2)));
            EarthNode.AddAnimation(rotationAnimation, new NSString("earthNodeAnimation"));

            rotationAnimation.Duration = 100.0f;
            CloudsNode.AddAnimation(rotationAnimation, new NSString("cloudsNodeAnimation"));

            //animate light
            var lightHandleNode = SCNNode.Create();
            var lightNode       = SCNNode.Create();

            lightNode.Light             = SCNLight.Create();
            lightNode.Light.LightType   = SCNLightType.Directional;
            lightNode.Light.CastsShadow = true;
            lightHandleNode.RunAction(SCNAction.RepeatActionForever(SCNAction.RotateBy(0, -NMath.PI * 2, 0, 12)));
            lightHandleNode.AddChildNode(lightNode);

            EarthNode.AddChildNode(lightHandleNode);
        }
示例#18
0
 public static void SetFloat4(this SCNGeometry geometry, string uniform, SCNVector4 value)
 {
     geometry.SetValueForKey(NSValue.FromVector(value), new NSString(uniform));
 }
示例#19
0
        void Setup()
        {
            // create a new scene
            var scene = SCNScene.FromFile("art.scnassets/ship");

            // create and add a camera to the scene
            var cameraNode = SCNNode.Create();

            cameraNode.Camera = SCNCamera.Create();
            scene.RootNode.AddChildNode(cameraNode);

            // place the camera
            cameraNode.Position = new SCNVector3(0, 0, 15);

            // create and add a light to the scene
            var lightNode = SCNNode.Create();

            lightNode.Light           = SCNLight.Create();
            lightNode.Light.LightType = SCNLightType.Omni;
            lightNode.Position        = new SCNVector3(0, 10, 10);
            scene.RootNode.AddChildNode(lightNode);

            // create and add an ambient light to the scene
            var ambientLightNode = SCNNode.Create();

            ambientLightNode.Light           = SCNLight.Create();
            ambientLightNode.Light.LightType = SCNLightType.Ambient;
            ambientLightNode.Light.Color     = SKColor.DarkGray;
            scene.RootNode.AddChildNode(ambientLightNode);

            // retrieve the ship node
            var ship = scene.RootNode.FindChildNode("ship", true);

            // animate the 3d object
#if __IOS__
            ship.RunAction(SCNAction.RepeatActionForever(SCNAction.RotateBy(0, 2, 0, 1)));
#else
            var animation = CABasicAnimation.FromKeyPath("rotation");
            animation.To          = NSValue.FromVector(new SCNVector4(0, 1, 0, NMath.PI * 2));
            animation.Duration    = 3;
            animation.RepeatCount = float.MaxValue; //repeat forever
            ship.AddAnimation(animation, null);
#endif

            // retrieve the SCNView
            var scnView = (SCNView)View;

            // set the scene to the view
            scnView.Scene = scene;

            // allows the user to manipulate the camera
            scnView.AllowsCameraControl = true;

            // show statistics such as fps and timing information
            scnView.ShowsStatistics = true;

            // configure the view
            scnView.BackgroundColor = SKColor.Black;

#if __IOS__
            // add a tap gesture recognizer
            var tapGesture         = new UITapGestureRecognizer(HandleTap);
            var gestureRecognizers = new List <UIGestureRecognizer> ();
            gestureRecognizers.Add(tapGesture);
            gestureRecognizers.AddRange(scnView.GestureRecognizers);
            scnView.GestureRecognizers = gestureRecognizers.ToArray();
#endif
        }
示例#20
0
        // Takes a string an creates a node hierarchy where each letter is an independent geometry that is animated
        private SCNNode SplittedStylizedText(string message)
        {
            var textNode      = SCNNode.Create();
            var frontMaterial = TextFrontMaterial();
            var border        = TextSideAndChamferMaterial();

            // Current x position of the next letter to add
            var positionX = 0.0f;

            // For each letter
            for (var i = 0; i < message.Length; i++)
            {
                var letterNode   = SCNNode.Create();
                var letterString = message.Substring(i, 1);
                var text         = SCNText.Create(letterString, 50.0f);
                text.Font = NSFont.FromFontName("Avenir Next Heavy", 288);

                text.ChamferRadius  = 3.0f;
                text.ChamferProfile = TextChamferProfile();

                // use a different material for the "heart" character
                var finalFrontMaterial = frontMaterial;
                if (i == 1)
                {
                    finalFrontMaterial = (SCNMaterial)finalFrontMaterial.Copy();
                    finalFrontMaterial.Diffuse.Contents    = NSColor.Red;
                    finalFrontMaterial.Reflective.Contents = NSColor.Black;
                    letterNode.Scale = new SCNVector3(1.1f, 1.1f, 1.0f);
                }

                text.Materials = new SCNMaterial[] { finalFrontMaterial, finalFrontMaterial, border, border, border };

                letterNode.Geometry = text;
                textNode.AddChildNode(letterNode);

                // measure the letter we just added to update the position
                SCNVector3 min, max;
                max = new SCNVector3(0, 0, 0);
                min = new SCNVector3(0, 0, 0);
                if (letterNode.GetBoundingBox(ref min, ref max))
                {
                    letterNode.Position = new SCNVector3(positionX - min.X + (max.X + min.X) * 0.5f, -min.Y, 0);
                    positionX          += (float)max.X;
                }
                else
                {
                    // if we have no bounding box, it is probably because of the "space" character. In that case, move to the right a little bit.
                    positionX += 50.0f;
                }

                // Place the pivot at the center of the letter so that the rotation animation looks good
                letterNode.Pivot = SCNMatrix4.CreateTranslation((max.X + min.X) * 0.5f, 0, 0);

                // Animate the letter
                var animation = CAKeyFrameAnimation.GetFromKeyPath("rotation");
                animation.Duration = 4.0f;
                animation.KeyTimes = new NSNumber[] { 0.0f, 0.3f, 1.0f };
                animation.Values   = new NSObject[] {
                    NSValue.FromVector(new SCNVector4(0, 1, 0, 0)),
                    NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI * 2))),
                    NSValue.FromVector(new SCNVector4(0, 1, 0, (float)(Math.PI * 2)))
                };

                var timingFunction = CAMediaTimingFunction.FromName(CAMediaTimingFunction.EaseInEaseOut);
                animation.TimingFunctions = new CAMediaTimingFunction[] { timingFunction, timingFunction, timingFunction };
                animation.RepeatCount     = float.MaxValue;
                animation.BeginTime       = CAAnimation.CurrentMediaTime() + 1.0 + i * 0.2;            // desynchronize animations
                letterNode.AddAnimation(animation, new NSString("letterNodeAnimation"));
            }

            return(textNode);
        }
示例#21
0
        public override void PresentStep(int index, PresentationViewController presentationViewController)
        {
            switch (index)
            {
            case 1:
                // Load the scene
                var intermediateNode = SCNNode.Create();
                intermediateNode.Position = new SCNVector3(0.0f, 0.1f, -24.5f);
                intermediateNode.Scale    = new SCNVector3(2.3f, 1.0f, 1.0f);
                intermediateNode.Opacity  = 0.0f;
                RoomNode = Utils.SCAddChildNode(intermediateNode, "Mesh", "Scenes/cornell-box/cornell-box", 15);
                ContentNode.AddChildNode(intermediateNode);

                // Hide the light maps for now
                foreach (var material in RoomNode.Geometry.Materials)
                {
                    material.Multiply.Intensity = 0.0f;
                    material.LightingModelName  = SCNLightingModel.Blinn;
                }

                // Animate the point of view with an implicit animation.
                // On completion add to move the camera from right to left and back and forth.
                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 0.75f;

                SCNTransaction.SetCompletionBlock(() => {
                    SCNTransaction.Begin();
                    SCNTransaction.AnimationDuration = 2;

                    SCNTransaction.SetCompletionBlock(() => {
                        var animation            = CABasicAnimation.FromKeyPath("position");
                        animation.Duration       = 10.0f;
                        animation.Additive       = true;
                        animation.To             = NSValue.FromVector(new SCNVector3(-5, 0, 0));
                        animation.From           = NSValue.FromVector(new SCNVector3(5, 0, 0));
                        animation.TimeOffset     = -animation.Duration / 2;
                        animation.AutoReverses   = true;
                        animation.TimingFunction = CAMediaTimingFunction.FromName(CAMediaTimingFunction.EaseInEaseOut);
                        animation.RepeatCount    = float.MaxValue;

                        presentationViewController.CameraNode.AddAnimation(animation, new NSString("myAnim"));
                    });
                    presentationViewController.CameraHandle.Position = presentationViewController.CameraHandle.ConvertPositionToNode(new SCNVector3(0, +5, -30), presentationViewController.CameraHandle.ParentNode);
                    presentationViewController.CameraPitch.Rotation  = new SCNVector4(1, 0, 0, -(float)(Math.PI / 4) * 0.2f);
                    SCNTransaction.Commit();
                });

                intermediateNode.Opacity = 1.0f;
                SCNTransaction.Commit();
                break;

            case 2:
                // Remove the lighting by using a constant lighing model (no lighting)
                foreach (var material in RoomNode.Geometry.Materials)
                {
                    material.LightingModelName = SCNLightingModel.Constant;
                }
                break;

            case 3:
                // Activate the light maps smoothly
                SCNTransaction.Begin();
                SCNTransaction.AnimationDuration = 1;
                foreach (var material in RoomNode.Geometry.Materials)
                {
                    material.Multiply.Intensity = 1.0f;
                }
                SCNTransaction.Commit();
                break;
            }
        }