public void ChainAnimation(string firstKey, string secondKey, float fadeTime) { CAAnimation firstAnim = animationsDict [firstKey]; CAAnimation secondAnim = animationsDict [secondKey]; if (firstAnim == null || secondAnim == null) { return; } SCNAnimationEventHandler chainEventBlock = (CAAnimation animation, NSObject animatedObject, bool playingBackward) => { mainSkeleton.AddAnimation(secondAnim, secondKey); }; if (firstAnim.AnimationEvents == null || firstAnim.AnimationEvents.Length == 0) { firstAnim.AnimationEvents = new SCNAnimationEvent[] { SCNAnimationEvent.Create(fadeTime, chainEventBlock) }; } else { var pastEvents = new List <SCNAnimationEvent> (firstAnim.AnimationEvents); pastEvents.Add(SCNAnimationEvent.Create(fadeTime, chainEventBlock)); firstAnim.AnimationEvents = pastEvents.ToArray(); } }
public override void SetupSlide(PresentationViewController presentationViewController) { // Load the character and add it to the scene var heroNode = Utils.SCAddChildNode(GroundNode, "heroGroup", "Scenes/hero/hero", 0.0f); heroNode.Scale = new SCNVector3(0.023f, 0.023f, 0.023f); heroNode.Position = new SCNVector3(0.0f, 0.0f, 15.0f); heroNode.Rotation = new SCNVector4(1.0f, 0.0f, 0.0f, -(float)(Math.PI / 2)); GroundNode.AddChildNode(heroNode); // Convert sceneTime-based animations into systemTime-based animations. // Animations loaded from DAE files will play according to the `currentTime` property of the scene renderer if this one is playing // (see the SCNSceneRenderer protocol). Here we don't play a specific DAE so we want the animations to animate as soon as we add // them to the scene (i.e have them to play according the time of the system when the animation was added). HeroSkeletonNode = heroNode.FindChildNode("skeleton", true); foreach (var animationKey in HeroSkeletonNode.GetAnimationKeys()) { // Find all the animations. Make them system time based and repeat forever. // And finally replace the old animation. var animation = HeroSkeletonNode.GetAnimation(animationKey); animation.UsesSceneTimeBase = false; animation.RepeatCount = float.MaxValue; HeroSkeletonNode.AddAnimation(animation, animationKey); } // Load other animations so that we will use them later SetAnimation(CharacterAnimation.Attack, "attackID", "attack"); SetAnimation(CharacterAnimation.Die, "DeathID", "death"); SetAnimation(CharacterAnimation.Walk, "WalkID", "walk"); }
public override void SetupSlide (PresentationViewController presentationViewController) { // Load the character and add it to the scene var heroNode = Utils.SCAddChildNode (GroundNode, "heroGroup", "Scenes/hero/hero", 0.0f); heroNode.Scale = new SCNVector3 (0.023f, 0.023f, 0.023f); heroNode.Position = new SCNVector3 (0.0f, 0.0f, 15.0f); heroNode.Rotation = new SCNVector4 (1.0f, 0.0f, 0.0f, -(float)(Math.PI / 2)); GroundNode.AddChildNode (heroNode); // Convert sceneTime-based animations into systemTime-based animations. // Animations loaded from DAE files will play according to the `currentTime` property of the scene renderer if this one is playing // (see the SCNSceneRenderer protocol). Here we don't play a specific DAE so we want the animations to animate as soon as we add // them to the scene (i.e have them to play according the time of the system when the animation was added). HeroSkeletonNode = heroNode.FindChildNode ("skeleton", true); foreach (var animationKey in HeroSkeletonNode.GetAnimationKeys ()) { // Find all the animations. Make them system time based and repeat forever. // And finally replace the old animation. var animation = HeroSkeletonNode.GetAnimation (animationKey); animation.UsesSceneTimeBase = false; animation.RepeatCount = float.MaxValue; HeroSkeletonNode.AddAnimation (animation, animationKey); } // Load other animations so that we will use them later SetAnimation (CharacterAnimation.Attack, "attackID", "attack"); SetAnimation (CharacterAnimation.Die, "DeathID", "death"); SetAnimation (CharacterAnimation.Walk, "WalkID", "walk"); }
void SetupCamera() { SCNNode pov = GameView.PointOfView; const float altitude = 1f; const float distance = 10f; cameraYHandle = SCNNode.Create(); cameraXHandle = SCNNode.Create(); cameraYHandle.Position = new SCNVector3(0f, altitude, 0f); cameraYHandle.AddChildNode(cameraXHandle); GameView.Scene.RootNode.AddChildNode(cameraYHandle); pov.EulerAngles = new SCNVector3(0f, 0f, 0f); pov.Position = new SCNVector3(0f, 0f, distance); cameraYHandle.Rotation = new SCNVector4(0f, 1f, 0f, (float)Math.PI / 2f + (float)Math.PI / 4f * 3f); cameraXHandle.Rotation = new SCNVector4(1f, 0f, 0f, -(float)Math.PI / 4f * 0.125f); cameraXHandle.AddChildNode(pov); // Animate camera on launch and prevent the user from manipulating the camera until the end of the animation lockCamera = true; SCNTransaction.Begin(); SCNTransaction.SetCompletionBlock(() => { lockCamera = false; }); var cameraYAnimation = CABasicAnimation.FromKeyPath("rotation.w"); cameraYAnimation.From = NSNumber.FromDouble(Math.PI * 2 - cameraYHandle.Rotation.W); cameraYAnimation.To = NSNumber.FromDouble(0.0); cameraYAnimation.Additive = true; cameraYAnimation.BeginTime = CAAnimation.CurrentMediaTime() + 3; cameraYAnimation.FillMode = CAFillMode.Both; cameraYAnimation.Duration = 5.0; cameraYAnimation.TimingFunction = CAMediaTimingFunction.FromName(CAMediaTimingFunction.EaseInEaseOut); cameraYHandle.AddAnimation(cameraYAnimation, null); var cameraXAnimation = CABasicAnimation.FromKeyPath("rotation.w"); cameraXAnimation.From = NSNumber.FromDouble(-Math.PI / 2 + cameraXHandle.Rotation.W); cameraXAnimation.To = NSNumber.FromDouble(0.0); cameraXAnimation.Additive = true; cameraXAnimation.FillMode = CAFillMode.Both; cameraXAnimation.Duration = 5.0; cameraXAnimation.BeginTime = CAAnimation.CurrentMediaTime() + 3; cameraXAnimation.TimingFunction = CAMediaTimingFunction.FromName(CAMediaTimingFunction.EaseInEaseOut); cameraXHandle.AddAnimation(cameraXAnimation, null); SCNTransaction.Commit(); var lookAtConstraint = SCNLookAtConstraint.Create(Character.Node.FindChildNode("Bip001_Head", true)); lookAtConstraint.InfluenceFactor = 0; pov.Constraints = new SCNConstraint[] { lookAtConstraint }; }
public void SCNNode_AddAnimation() { SCNNode c = new SCNNode(); CABasicAnimation a = CABasicAnimation.FromKeyPath("hidden"); NSString key = new NSString("MyKey"); c.AddAnimation(a, key); CAPropertyAnimation cur = (CAPropertyAnimation)c.GetAnimation(key); Assert.IsNotNull(cur); Assert.AreEqual(cur.KeyPath, "hidden"); c.RemoveAnimation(key); cur = (CAPropertyAnimation)c.GetAnimation(key); Assert.IsNull(cur); }
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")); }
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")); }
void SetupCamera () { SCNNode pov = GameView.PointOfView; const float altitude = 1f; const float distance = 10f; cameraYHandle = SCNNode.Create (); cameraXHandle = SCNNode.Create (); cameraYHandle.Position = new SCNVector3 (0f, altitude, 0f); cameraYHandle.AddChildNode (cameraXHandle); GameView.Scene.RootNode.AddChildNode (cameraYHandle); pov.EulerAngles = new SCNVector3 (0f, 0f, 0f); pov.Position = new SCNVector3 (0f, 0f, distance); cameraYHandle.Rotation = new SCNVector4 (0f, 1f, 0f, (float)Math.PI / 2f + (float)Math.PI / 4f * 3f); cameraXHandle.Rotation = new SCNVector4 (1f, 0f, 0f, -(float)Math.PI / 4f * 0.125f); cameraXHandle.AddChildNode (pov); // Animate camera on launch and prevent the user from manipulating the camera until the end of the animation lockCamera = true; SCNTransaction.Begin (); SCNTransaction.SetCompletionBlock (() => { lockCamera = false; }); var cameraYAnimation = CABasicAnimation.FromKeyPath ("rotation.w"); cameraYAnimation.From = NSNumber.FromDouble (Math.PI * 2 - cameraYHandle.Rotation.W); cameraYAnimation.To = NSNumber.FromDouble (0.0); cameraYAnimation.Additive = true; cameraYAnimation.BeginTime = CAAnimation.CurrentMediaTime () + 3; cameraYAnimation.FillMode = CAFillMode.Both; cameraYAnimation.Duration = 5.0; cameraYAnimation.TimingFunction = CAMediaTimingFunction.FromName (CAMediaTimingFunction.EaseInEaseOut); cameraYHandle.AddAnimation (cameraYAnimation, null); var cameraXAnimation = CABasicAnimation.FromKeyPath ("rotation.w"); cameraXAnimation.From = NSNumber.FromDouble (-Math.PI / 2 + cameraXHandle.Rotation.W); cameraXAnimation.To = NSNumber.FromDouble (0.0); cameraXAnimation.Additive = true; cameraXAnimation.FillMode = CAFillMode.Both; cameraXAnimation.Duration = 5.0; cameraXAnimation.BeginTime = CAAnimation.CurrentMediaTime () + 3; cameraXAnimation.TimingFunction = CAMediaTimingFunction.FromName (CAMediaTimingFunction.EaseInEaseOut); cameraXHandle.AddAnimation (cameraXAnimation, null); SCNTransaction.Commit (); var lookAtConstraint = SCNLookAtConstraint.Create (Character.Node.FindChildNode ("Bip001_Head", true)); lookAtConstraint.InfluenceFactor = 0; pov.Constraints = new SCNConstraint[] { lookAtConstraint }; }
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); }
public override void SetupSlide (PresentationViewController presentationViewController) { // Set the slide's title and subtile and add some text TextManager.SetTitle ("Node Attributes"); TextManager.SetSubtitle ("Geometry"); 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/teapots/teapotLowRes", 17); TeapotNodeForUVs = Utils.SCAddChildNode (allTeapotsNode, "Teapot", "Scenes/teapots/teapot", 17); TeapotNodeForMaterials = Utils.SCAddChildNode (allTeapotsNode, "teapotMaterials", "Scenes/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.Normal.Intensity = 0.3f; 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); 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); TeapotNodeForPositionsAndNormals.AddChildNode (PositionsVisualizationNode); TeapotNodeForPositionsAndNormals.AddChildNode (NormalsVisualizationNode); }