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 };
        }
示例#2
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;
            }
        }
示例#3
0
        public override void SetupSlide(PresentationViewController presentationViewController)
        {
            TextManager.SetTitle("Constraints");
            TextManager.SetSubtitle("SCNIKConstraint");

            TextManager.AddBulletAtLevel("Inverse Kinematics", 0);
            TextManager.AddBulletAtLevel("Node chain", 0);
            TextManager.AddBulletAtLevel("Target", 0);

            //load the hero
            Hero          = Utils.SCAddChildNode(GroundNode, "heroGroup", "Scenes.scnassets/hero/hero", 12);
            Hero.Position = new SCNVector3(0, 0, 5);
            Hero.Rotation = new SCNVector4(1, 0, 0, -(nfloat)Math.PI / 2);

            //hide the sword
            var sword = Hero.FindChildNode("sword", true);

            sword.Hidden = true;

            //load attack animation
            var path   = NSBundle.MainBundle.PathForResource("Scenes.scnassets/hero/attack", "dae");
            var source = SCNSceneSource.FromUrl(NSUrl.FromFilename(path), (NSDictionary)null);

            Attack                 = (CAAnimation)source.GetEntryWithIdentifier("attackID", new Class("CAAnimation"));
            Attack.RepeatCount     = 0;
            Attack.FadeInDuration  = 0.1f;
            Attack.FadeOutDuration = 0.3f;
            Attack.Speed           = 0.75f;

            Attack.AnimationEvents = new SCNAnimationEvent[] { SCNAnimationEvent.Create(0.55f, (CAAnimation animation, NSObject animatedObject, bool playingBackward) => {
                    if (IkActive)
                    {
                        DestroyTarget();
                    }
                }) };

            AnimationDuration = Attack.Duration;

            //setup IK
            var hand     = Hero.FindChildNode("Bip01_R_Hand", true);
            var clavicle = Hero.FindChildNode("Bip01_R_Clavicle", true);
            var head     = Hero.FindChildNode("Bip01_Head", true);

            Ik = SCNIKConstraint.Create(clavicle);
            hand.Constraints   = new SCNConstraint[] { Ik };
            Ik.InfluenceFactor = 0.0f;

            //add target
            Target          = SCNNode.Create();
            Target.Position = new SCNVector3(-4, 7, 10);
            Target.Opacity  = 0;
            Target.Geometry = SCNPlane.Create(2, 2);
            Target.Geometry.FirstMaterial.Diffuse.Contents = new NSImage(NSBundle.MainBundle.PathForResource("Images/target", "png"));
            GroundNode.AddChildNode(Target);

            //look at
            LookAt = SCNLookAtConstraint.Create(Target);
            LookAt.InfluenceFactor = 0;
            head.Constraints       = new SCNConstraint[] { LookAt };

            ((SCNView)presentationViewController.View).WeakSceneRendererDelegate = this;
        }
示例#4
0
        public override void ViewDidLoad()
        {
            base.ViewDidLoad();
            // Perform any additional setup after loading the view, typically from a nib.
            var scene = new SCNScene();

            var rnd = new Random();

            Func <int, int, bool, float> random = (min, max, clamp) => {
                float num = (float)((double)rnd.Next(min, max) * rnd.NextDouble());
                if (!clamp)
                {
                    return(num);
                }
                else if (num < 1.0f)
                {
                    return(1.0f);
                }
                else
                {
                    return(num);
                }
            };

            Enumerable.Range(0, 200).Select <int, int> ((i) => Building(
                                                            random(2, 5, true),
                                                            random(2, 5, true),
                                                            random(2, 10, true),
                                                            random(-20, 20, false),
                                                            random(-20, 20, false),
                                                            scene,
                                                            rnd
                                                            )).ToArray();

            //Lights!
            var lightNode = new SCNNode()
            {
                Light    = new SCNLight(),
                Position = new SCNVector3(30.0F, 20.0F, 60.0F)
            };

            lightNode.Light.LightType = SCNLightType.Omni;
            scene.RootNode.AddChildNode(lightNode);

            var ambientLightNode = new SCNNode()
            {
                Light = new SCNLight()
            };

            ambientLightNode.Light.LightType = SCNLightType.Ambient;
            ambientLightNode.Light.Color     = UIColor.DarkGray;
            scene.RootNode.AddChildNode(ambientLightNode);

            //Camera!
            var cameraNode = new SCNNode()
            {
                Camera = new SCNCamera()
            };

            scene.RootNode.AddChildNode(cameraNode);
            cameraNode.Position = new SCNVector3(0.0F, 10.0F, 20.0F);

            var targetNode = new SCNNode()
            {
                Position = new SCNVector3(00.0F, 1.5F, 0.0F)
            };

            scene.RootNode.AddChildNode(targetNode);

            var lc = SCNLookAtConstraint.Create(targetNode);

            cameraNode.Constraints = new[] { lc };

            var scnView = new SCNView(UIScreen.MainScreen.Bounds)
            {
                Scene = scene,
                AllowsCameraControl = true,
                ShowsStatistics     = true,
                BackgroundColor     = UIColor.FromRGB(52, 152, 219)
            };

            var floorNode = new SCNNode {
                Geometry = new SCNPlane {
                    Height = 40.0F,
                    Width  = 40.0F
                },
                Position = SCNVector3.Zero
            };

            var pi2 = Math.PI / 2.0;

            floorNode.Orientation = SCNQuaternion.FromAxisAngle(SCNVector3.UnitX, (float)(0.0 - pi2));

            scene.RootNode.AddChildNode(floorNode);

            var material = new SCNMaterial();

            material.Diffuse.Contents            = UIImage.FromFile("Content/road.jpg");
            material.Diffuse.ContentsTransform   = SCNMatrix4.Scale(new SCNVector3(10.0f, 10.0f, 1.0f));
            material.Diffuse.MinificationFilter  = SCNFilterMode.Linear;
            material.Diffuse.MagnificationFilter = SCNFilterMode.Linear;
            material.Diffuse.MipFilter           = SCNFilterMode.Linear;
            material.Diffuse.WrapS     = SCNWrapMode.Repeat;
            material.Diffuse.WrapT     = SCNWrapMode.Repeat;
            material.Specular.Contents = UIColor.Gray;

            floorNode.Geometry.FirstMaterial = material;

            this.View = scnView;
        }
示例#5
0
        public override void PresentStep(int index, PresentationViewController presentationViewController)
        {
            switch (index)
            {
            case 0:
                break;

            case 1:
                TextManager.HighlightBullet(0);

                StaticShadowNode.Opacity = 1;

                var node = TextManager.AddCode("#aMaterial.#multiply#.contents = aShadowMap;#");
                node.Position = new SCNVector3(node.Position.X, node.Position.Y - 4, node.Position.Z);
                foreach (var child in node.ChildNodes)
                {
                    child.RenderingOrder = 1;
                    foreach (var m in child.Geometry.Materials)
                    {
                        m.ReadsFromDepthBuffer = false;
                    }
                }
                break;

            case 2:
                //move the tree
                PalmTree.RunAction(SCNAction.RotateBy(0, NMath.PI * 4, 0, 8));
                break;

            case 3:
                TextManager.FadesIn = true;
                TextManager.FadeOutText(SlideTextManager.TextType.Code);
                TextManager.AddEmptyLine();

                node = TextManager.AddCode("#aLight.#castsShadow# = YES;#");
                foreach (SCNNode child in node.ChildNodes)
                {
                    child.RenderingOrder = 1;
                    foreach (SCNMaterial m in child.Geometry.Materials)
                    {
                        m.ReadsFromDepthBuffer = false;
                        m.WritesToDepthBuffer  = false;
                    }
                }

                node.Position = new SCNVector3(node.Position.X, node.Position.Y - 6, node.Position.Z);

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

                var spot = presentationViewController.SpotLight;
                OldSpotShadowColor      = spot.Light.ShadowColor;
                spot.Light.ShadowColor  = NSColor.Black;
                spot.Light.ShadowRadius = 3;

                var tp = TextManager.TextNode.Position;

                var superNode = presentationViewController.CameraNode.ParentNode.ParentNode;

                var p0 = GroundNode.ConvertPositionToNode(SCNVector3.Zero, null);
                var p1 = GroundNode.ConvertPositionToNode(new SCNVector3(20, 0, 0), null);
                var tr = new SCNVector3(p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z);

                var p = superNode.Position;
                p.X  += tr.X;
                p.Y  += tr.Y;
                p.Z  += tr.Z;
                tp.X += 20;
                tp.Y += 0;
                tp.Z += 0;
                superNode.Position            = p;
                TextManager.TextNode.Position = tp;
                SCNTransaction.Commit();

                TextManager.HighlightBullet(1);

                break;

            case 4:
                //move the light
                var lightPivot = SCNNode.Create();
                lightPivot.Position = Character.Position;
                GroundNode.AddChildNode(lightPivot);

                spot            = presentationViewController.SpotLight;
                OldSpotPosition = spot.Position;
                OldSpotParent   = spot.ParentNode;
                OldSpotZNear    = spot.Light.ZNear;

                spot.Light.ZNear = 20;
                spot.Position    = lightPivot.ConvertPositionFromNode(spot.Position, spot.ParentNode);
                lightPivot.AddChildNode(spot);

                //add an object to represent the light
                var lightModel  = SCNNode.Create();
                var lightHandle = SCNNode.Create();
                var cone        = SCNCone.Create(0, 0.5f, 1);
                cone.RadialSegmentCount = 10;
                cone.HeightSegmentCount = 5;
                lightModel.Geometry     = cone;
                lightModel.Geometry.FirstMaterial.Emission.Contents = NSColor.Yellow;
                lightHandle.Position   = new SCNVector3(spot.Position.X * DIST, spot.Position.Y * DIST, spot.Position.Z * DIST);
                lightModel.CastsShadow = false;
                lightModel.EulerAngles = new SCNVector3(NMath.PI / 2, 0, 0);
                lightHandle.AddChildNode(lightModel);
                lightHandle.Constraints = new SCNConstraint[] { SCNLookAtConstraint.Create(Character) };
                lightPivot.AddChildNode(lightHandle);
                LightHandle = lightHandle;

                var animation = CABasicAnimation.FromKeyPath("eulerAngles.z");
                animation.From           = new NSNumber((nfloat)(Math.PI / 4) * 1.7f);
                animation.To             = new NSNumber((nfloat)(-Math.PI / 4) * 0.3f);
                animation.Duration       = 4;
                animation.AutoReverses   = true;
                animation.RepeatCount    = float.MaxValue;
                animation.TimingFunction = CAMediaTimingFunction.FromName(CAMediaTimingFunction.EaseInEaseOut);
                animation.TimeOffset     = animation.Duration / 2;
                lightPivot.AddAnimation(animation, new NSString("lightAnim"));
                break;

            case 5:
                TextManager.FadeOutText(SlideTextManager.TextType.Code);
                var text = TextManager.AddCode("#aLight.#shadowMode# =\n#SCNShadowModeModulated#;\naLight.#gobo# = anImage;#");
                text.Position = new SCNVector3(text.Position.X, text.Position.Y - 6, text.Position.Z);
                text.EnumerateChildNodes((SCNNode child, out bool stop) => {
                    stop = false;
                    child.RenderingOrder = 1;
                    foreach (var m in child.Geometry.Materials)
                    {
                        m.ReadsFromDepthBuffer = false;
                        m.WritesToDepthBuffer  = false;
                    }
                    return(stop);
                });

                LightHandle.RemoveFromParentNode();

                RestoreSpotPosition(presentationViewController);
                TextManager.HighlightBullet(2);


                spot = presentationViewController.SpotLight;
                spot.Light.CastsShadow = false;

                var head = Character.FindChildNode("Bip001_Pelvis", true);

                node                      = SCNNode.Create();
                node.Light                = SCNLight.Create();
                node.Light.LightType      = SCNLightType.Spot;
                node.Light.SpotOuterAngle = 30;
                node.Constraints          = new SCNConstraint[] { SCNLookAtConstraint.Create(head) };
                node.Position             = new SCNVector3(0, 220, 0);
                node.Light.ZNear          = 10;
                node.Light.ZFar           = 1000;
                node.Light.Gobo.Contents  = new NSImage(NSBundle.MainBundle.PathForResource("SharedTextures/blobShadow", "jpg"));
                node.Light.Gobo.Intensity = 0.65f;
                node.Light.ShadowMode     = SCNShadowMode.Modulated;

                //exclude character from shadow
                node.Light.CategoryBitMask = 0x1;
                Character.FindNodes((SCNNode child, out bool stop) => {
                    stop = false;
                    child.CategoryBitMask = 0x2;
                    return(stop);
                });

                Projector = node;
                Character.AddChildNode(node);

                break;
            }
        }