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; } }
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; }