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;
            }
        }
Beispiel #2
0
        private void CreateLayers(UIImage image)
        {
            if (image == null)
            {
                return;
            }

            Layer.Sublayers = new CALayer[0];

            var imageFrame = new CGRect(
                Frame.Width / 2f - Frame.Width / 4f,
                Frame.Height / 2f - Frame.Height / 4f,
                Frame.Width / 2f,
                Frame.Height / 2f);
            var imgCenterPoint = new CGPoint(imageFrame.GetMidX(), imageFrame.GetMidY());
            var lineFrame      = new CGRect(
                imageFrame.X - imageFrame.Width / 4f,
                imageFrame.Y - imageFrame.Height / 4f,
                imageFrame.Width * 1.5f,
                imageFrame.Height * 1.5f);

            //===============
            // circle layer
            //===============
            circleShape           = new CAShapeLayer();
            circleShape.Bounds    = imageFrame;
            circleShape.Position  = imgCenterPoint;
            circleShape.Path      = UIBezierPath.FromOval(imageFrame).CGPath;
            circleShape.FillColor = circleColor.CGColor;
            circleShape.Transform = CATransform3D.MakeScale(0.0f, 0.0f, 1.0f);
            Layer.AddSublayer(circleShape);

            circleMaskShape          = new CAShapeLayer();
            circleMaskShape.Bounds   = imageFrame;
            circleMaskShape.Position = imgCenterPoint;
            circleMaskShape.FillRule = CAShapeLayer.FillRuleEvenOdd;
            circleShape.Mask         = circleMaskShape;

            var maskPath = UIBezierPath.FromRect(imageFrame);

            maskPath.AddArc(imgCenterPoint, 0.1f, 0.0f, fPI * 2f, true);
            circleMaskShape.Path = maskPath.CGPath;

            //===============
            // line layer
            //===============
            lineShapes = new CAShapeLayer[5];
            for (int i = 0; i < 5; i++)
            {
                var line = new CAShapeLayer();
                line.Bounds        = lineFrame;
                line.Position      = imgCenterPoint;
                line.MasksToBounds = true;
                line.Actions       = NSDictionary.FromObjectsAndKeys(
                    new[] { NSNull.Null, NSNull.Null },
                    new[] { (NSString)"strokeStart", (NSString)"strokeEnd" });
                line.StrokeColor = linesColor.CGColor;
                line.LineWidth   = 1.25f;
                line.MiterLimit  = 1.25f;
                var path = new CGPath();
                path.MoveToPoint(lineFrame.GetMidX(), lineFrame.GetMidY());
                path.AddLineToPoint(lineFrame.X + lineFrame.Width / 2f, lineFrame.Y);
                line.Path        = path;
                line.LineCap     = CAShapeLayer.CapRound;
                line.LineJoin    = CAShapeLayer.JoinRound;
                line.StrokeStart = 0.0f;
                line.StrokeEnd   = 0.0f;
                line.Opacity     = 0.0f;
                line.Transform   = CATransform3D.MakeRotation(fPI / 5f * (i * 2f + 1f), 0.0f, 0.0f, 1.0f);
                Layer.AddSublayer(line);
                lineShapes[i] = line;
            }

            //===============
            // image layer
            //===============
            imageShape           = new CAShapeLayer();
            imageShape.Bounds    = imageFrame;
            imageShape.Position  = imgCenterPoint;
            imageShape.Path      = UIBezierPath.FromRect(imageFrame).CGPath;
            imageShape.FillColor = Checked ? Color.CGColor : SkeletonColor.CGColor;
            imageShape.Actions   = NSDictionary.FromObjectAndKey(NSNull.Null, (NSString)"fillColor");
            Layer.AddSublayer(imageShape);

            imageShape.Mask          = new CALayer();
            imageShape.Mask.Contents = image.CGImage;
            imageShape.Mask.Bounds   = imageFrame;
            imageShape.Mask.Position = imgCenterPoint;

            //==============================
            // circle transform animation
            //==============================
            circleTransform.Values = new[]
            {
                NSValue.FromCATransform3D(CATransform3D.MakeScale(0.0f, 0.0f, 1.0f)),      //  0/10
                NSValue.FromCATransform3D(CATransform3D.MakeScale(0.5f, 0.5f, 1.0f)),      //  1/10
                NSValue.FromCATransform3D(CATransform3D.MakeScale(1.0f, 1.0f, 1.0f)),      //  2/10
                NSValue.FromCATransform3D(CATransform3D.MakeScale(1.2f, 1.2f, 1.0f)),      //  3/10
                NSValue.FromCATransform3D(CATransform3D.MakeScale(1.3f, 1.3f, 1.0f)),      //  4/10
                NSValue.FromCATransform3D(CATransform3D.MakeScale(1.37f, 1.37f, 1.0f)),    //  5/10
                NSValue.FromCATransform3D(CATransform3D.MakeScale(1.4f, 1.4f, 1.0f)),      //  6/10
                NSValue.FromCATransform3D(CATransform3D.MakeScale(1.4f, 1.4f, 1.0f))       // 10/10
            };
            circleTransform.KeyTimes = new[]
            {
                NSNumber.FromDouble(0.0),    //  0/10
                NSNumber.FromDouble(0.1),    //  1/10
                NSNumber.FromDouble(0.2),    //  2/10
                NSNumber.FromDouble(0.3),    //  3/10
                NSNumber.FromDouble(0.4),    //  4/10
                NSNumber.FromDouble(0.5),    //  5/10
                NSNumber.FromDouble(0.6),    //  6/10
                NSNumber.FromDouble(1.0)     // 10/10
            };

            circleMaskTransform.Values = new[]
            {
                NSValue.FromCATransform3D(CATransform3D.Identity),                                                                 //  0/10
                NSValue.FromCATransform3D(CATransform3D.Identity),                                                                 //  2/10
                NSValue.FromCATransform3D(CATransform3D.MakeScale(imageFrame.Width * 1.25f, imageFrame.Height * 1.25f, 1.0f)),     //  3/10
                NSValue.FromCATransform3D(CATransform3D.MakeScale(imageFrame.Width * 2.688f, imageFrame.Height * 2.688f, 1.0f)),   //  4/10
                NSValue.FromCATransform3D(CATransform3D.MakeScale(imageFrame.Width * 3.923f, imageFrame.Height * 3.923f, 1.0f)),   //  5/10
                NSValue.FromCATransform3D(CATransform3D.MakeScale(imageFrame.Width * 4.375f, imageFrame.Height * 4.375f, 1.0f)),   //  6/10
                NSValue.FromCATransform3D(CATransform3D.MakeScale(imageFrame.Width * 4.731f, imageFrame.Height * 4.731f, 1.0f)),   //  7/10
                NSValue.FromCATransform3D(CATransform3D.MakeScale(imageFrame.Width * 5.0f, imageFrame.Height * 5.0f, 1.0f)),       //  9/10
                NSValue.FromCATransform3D(CATransform3D.MakeScale(imageFrame.Width * 5.0f, imageFrame.Height * 5.0f, 1.0f))        // 10/10
            };
            circleMaskTransform.KeyTimes = new[]
            {
                NSNumber.FromDouble(0.0),    //  0/10
                NSNumber.FromDouble(0.2),    //  2/10
                NSNumber.FromDouble(0.3),    //  3/10
                NSNumber.FromDouble(0.4),    //  4/10
                NSNumber.FromDouble(0.5),    //  5/10
                NSNumber.FromDouble(0.6),    //  6/10
                NSNumber.FromDouble(0.7),    //  7/10
                NSNumber.FromDouble(0.9),    //  9/10
                NSNumber.FromDouble(1.0)     // 10/10
            };

            //==============================
            // line stroke animation
            //==============================
            lineStrokeStart.Values = new[]
            {
                NSNumber.FromDouble(0.0),    //  0/18
                NSNumber.FromDouble(0.0),    //  1/18
                NSNumber.FromDouble(0.18),   //  2/18
                NSNumber.FromDouble(0.2),    //  3/18
                NSNumber.FromDouble(0.26),   //  4/18
                NSNumber.FromDouble(0.32),   //  5/18
                NSNumber.FromDouble(0.4),    //  6/18
                NSNumber.FromDouble(0.6),    //  7/18
                NSNumber.FromDouble(0.71),   //  8/18
                NSNumber.FromDouble(0.89),   // 17/18
                NSNumber.FromDouble(0.92)    // 18/18
            };
            lineStrokeStart.KeyTimes = new[]
            {
                NSNumber.FromDouble(0.0),    //  0/18
                NSNumber.FromDouble(0.056),  //  1/18
                NSNumber.FromDouble(0.111),  //  2/18
                NSNumber.FromDouble(0.167),  //  3/18
                NSNumber.FromDouble(0.222),  //  4/18
                NSNumber.FromDouble(0.278),  //  5/18
                NSNumber.FromDouble(0.333),  //  6/18
                NSNumber.FromDouble(0.389),  //  7/18
                NSNumber.FromDouble(0.444),  //  8/18
                NSNumber.FromDouble(0.944),  // 17/18
                NSNumber.FromDouble(1.0),    // 18/18
            };

            lineStrokeEnd.Values = new[]
            {
                NSNumber.FromDouble(0.0),    //  0/18
                NSNumber.FromDouble(0.0),    //  1/18
                NSNumber.FromDouble(0.32),   //  2/18
                NSNumber.FromDouble(0.48),   //  3/18
                NSNumber.FromDouble(0.64),   //  4/18
                NSNumber.FromDouble(0.68),   //  5/18
                NSNumber.FromDouble(0.92),   // 17/18
                NSNumber.FromDouble(0.92)    // 18/18
            };
            lineStrokeEnd.KeyTimes = new[]
            {
                NSNumber.FromDouble(0.0),    //  0/18
                NSNumber.FromDouble(0.056),  //  1/18
                NSNumber.FromDouble(0.111),  //  2/18
                NSNumber.FromDouble(0.167),  //  3/18
                NSNumber.FromDouble(0.222),  //  4/18
                NSNumber.FromDouble(0.278),  //  5/18
                NSNumber.FromDouble(0.944),  // 17/18
                NSNumber.FromDouble(1.0),    // 18/18
            };

            lineOpacity.Values = new[]
            {
                NSNumber.FromDouble(1.0),    //  0/30
                NSNumber.FromDouble(1.0),    // 12/30
                NSNumber.FromDouble(0.0)     // 17/30
            };
            lineOpacity.KeyTimes = new[]
            {
                NSNumber.FromDouble(0.0),    //  0/30
                NSNumber.FromDouble(0.4),    // 12/30
                NSNumber.FromDouble(0.567)   // 17/30
            };

            //==============================
            // image transform animation
            //==============================
            imageTransform.Values = new[]
            {
                NSValue.FromCATransform3D(CATransform3D.MakeScale(0.0f, 0.0f, 1.0f)),      //  0/30
                NSValue.FromCATransform3D(CATransform3D.MakeScale(0.0f, 0.0f, 1.0f)),      //  3/30
                NSValue.FromCATransform3D(CATransform3D.MakeScale(1.2f, 1.2f, 1.0f)),      //  9/30
                NSValue.FromCATransform3D(CATransform3D.MakeScale(1.25f, 1.25f, 1.0f)),    // 10/30
                NSValue.FromCATransform3D(CATransform3D.MakeScale(1.2f, 1.2f, 1.0f)),      // 11/30
                NSValue.FromCATransform3D(CATransform3D.MakeScale(0.9f, 0.9f, 1.0f)),      // 14/30
                NSValue.FromCATransform3D(CATransform3D.MakeScale(0.875f, 0.875f, 1.0f)),  // 15/30
                NSValue.FromCATransform3D(CATransform3D.MakeScale(0.875f, 0.875f, 1.0f)),  // 16/30
                NSValue.FromCATransform3D(CATransform3D.MakeScale(0.9f, 0.9f, 1.0f)),      // 17/30
                NSValue.FromCATransform3D(CATransform3D.MakeScale(1.013f, 1.013f, 1.0f)),  // 20/30
                NSValue.FromCATransform3D(CATransform3D.MakeScale(1.025f, 1.025f, 1.0f)),  // 21/30
                NSValue.FromCATransform3D(CATransform3D.MakeScale(1.013f, 1.013f, 1.0f)),  // 22/30
                NSValue.FromCATransform3D(CATransform3D.MakeScale(0.96f, 0.96f, 1.0f)),    // 25/30
                NSValue.FromCATransform3D(CATransform3D.MakeScale(0.95f, 0.95f, 1.0f)),    // 26/30
                NSValue.FromCATransform3D(CATransform3D.MakeScale(0.96f, 0.96f, 1.0f)),    // 27/30
                NSValue.FromCATransform3D(CATransform3D.MakeScale(0.99f, 0.99f, 1.0f)),    // 29/30
                NSValue.FromCATransform3D(CATransform3D.Identity)                          // 30/30
            };
            imageTransform.KeyTimes = new[]
            {
                NSNumber.FromDouble(0.0),    //  0/30
                NSNumber.FromDouble(0.1),    //  3/30
                NSNumber.FromDouble(0.3),    //  9/30
                NSNumber.FromDouble(0.333),  // 10/30
                NSNumber.FromDouble(0.367),  // 11/30
                NSNumber.FromDouble(0.467),  // 14/30
                NSNumber.FromDouble(0.5),    // 15/30
                NSNumber.FromDouble(0.533),  // 16/30
                NSNumber.FromDouble(0.567),  // 17/30
                NSNumber.FromDouble(0.667),  // 20/30
                NSNumber.FromDouble(0.7),    // 21/30
                NSNumber.FromDouble(0.733),  // 22/30
                NSNumber.FromDouble(0.833),  // 25/30
                NSNumber.FromDouble(0.867),  // 26/30
                NSNumber.FromDouble(0.9),    // 27/30
                NSNumber.FromDouble(0.967),  // 29/30
                NSNumber.FromDouble(1.0)     // 30/30
            };

            // re-set the durations
            Duration = duration;
        }