Beispiel #1
0
        public override void Update(double deltaTime)
        {
            SCNMatrix4 mtx         = Transform;
            var        gravity     = new SCNVector3(0f, -90f, 0f);
            var        gravitystep = SCNVector3.Multiply(gravity, (nfloat)deltaTime);

            velocity = SCNVector3.Add(velocity, gravitystep);
            var minMovement = new SCNVector3(0f, -50f, 0f);
            var maxMovement = new SCNVector3(100f, 100f, 100f);

            velocity          = MathUtils.GetMaxVector(velocity, minMovement);
            velocity          = MathUtils.GetMinVector(velocity, maxMovement);
            mtx               = mtx.TranslateWithVector(velocity);
            groundPlaneHeight = GetGroundHeight(mtx);

            if (mtx.M42 < groundPlaneHeight)
            {
                if (!Launching && velocity.Y < 0.0f)
                {
                    if (Jumping)
                    {
                        Jumping = false;
                        if (DustPoof != null)
                        {
                            AddParticleSystem(DustPoof);
                            DustPoof.Loops = false;
                        }
                        PlayLand();
                        JumpBoost = 0.0f;
                    }
                }
                // tie to ground
                mtx.M42 = groundPlaneHeight;

                velocity.Y = 0.0f;
            }

            Transform = mtx;
            //-- move the camera
            SCNNode camera = GameSimulation.Sim.GameLevel.Camera.ParentNode;

            if (camera != null)
            {
                nfloat x = Position.X + ((PlayerWalkDirection == WalkDirection.Right) ? 250 : -250);
                nfloat y = (Position.Y + 261) - (0.85f * (Position.Y - groundPlaneHeight));
                nfloat z = Position.Z + 1500;

                var pos = new SCNVector3(x, y, z);

                SCNMatrix4 desiredTransform = camera.Transform.SetPosition(pos);
                camera.Transform = MathUtils.Interpolate(camera.Transform, desiredTransform, 0.025f);
            }
        }
        public static FeatureHitTestResult HitTestFromOrigin(this ARSCNView self, SCNVector3 origin, SCNVector3 direction)
        {
            if (self.Session == null || ViewController.CurrentFrame == null)
            {
                return(null);
            }

            var currentFrame = ViewController.CurrentFrame;

            var features = currentFrame.RawFeaturePoints;

            if (features == null)
            {
                return(null);
            }

            var points = features.Points;

            // Determine the point from the whole point cloud which is closest to the hit test ray.
            var closestFeaturePoint = origin;
            var minDistance         = float.MaxValue;

            for (int n = 0; n < (int)features.Count; ++n)
            {
                var feature    = points[n];
                var featurePos = new SCNVector3(feature.X, feature.Y, feature.Z);

                var originVector = origin.Subtract(featurePos);
                var crossProduct = originVector.Cross(direction);
                var featureDistanceFromResult = crossProduct.Length;

                if (featureDistanceFromResult < minDistance)
                {
                    closestFeaturePoint = featurePos;
                    minDistance         = featureDistanceFromResult;
                }
            }

            // Compute the point along the ray that is closest to the selected feature.
            var originToFeature       = closestFeaturePoint.Subtract(origin);
            var hitTestResult         = origin.Add(direction * direction.Dot(originToFeature));
            var hitTestResultDistance = hitTestResult.Subtract(origin).LengthFast;

            // Return result
            return(new FeatureHitTestResult(hitTestResult, hitTestResultDistance, closestFeaturePoint, minDistance));
        }
Beispiel #3
0
        public static SCNNode SCAddChildNode(SCNNode container, string name, string path, nfloat scale)
        {
            // Load the scene from the specified file
            var scene = SCNScene.FromFile(path);

            // Retrieve the root node
            var node = scene.RootNode;

            // Search for the node named "name"
            if (name.Length > 0)
            {
                node = node.FindChildNode(name, true);
            }
            else
            {
                node = node.ChildNodes [0];                 // Take the first child if no name is passed
            }
            if (scale != 0)
            {
                // Rescale based on the current bounding box and the desired scale
                // Align the node to 0 on the Y axis
                var min = new SCNVector3();
                var max = new SCNVector3();
                node.GetBoundingBox(ref min, ref max);

                var mid = SCNVector3.Add(min, max);
                mid   = SCNVector3.Multiply(mid, 0.5f);
                mid.Y = min.Y;                 // Align on bottom

                var size    = SCNVector3.Subtract(max, min);
                var maxSize = (nfloat)Math.Max(Math.Max(size.X, size.Y), size.Z);

                scale = scale / maxSize;
                mid   = SCNVector3.Multiply(mid, scale);
                mid   = -mid;

                node.Scale    = new SCNVector3(scale, scale, scale);
                node.Position = new SCNVector3(mid);
            }

            // Add to the container passed in argument
            container.AddChildNode(node);

            return(node);
        }
Beispiel #4
0
        void SetupJumpAnimation()
        {
            NSString jumpKey    = KeyForAnimationType(CharacterAnimation.Jump);
            NSString fallingKey = KeyForAnimationType(CharacterAnimation.JumpFalling);
            NSString landKey    = KeyForAnimationType(CharacterAnimation.JumpLand);
            NSString idleKey    = KeyForAnimationType(CharacterAnimation.Idle);

            CAAnimation jumpAnimation = LoadAndCacheAnimation("art.scnassets/characters/explorer/jump_start", jumpKey);
            CAAnimation fallAnimation = LoadAndCacheAnimation("art.scnassets/characters/explorer/jump_falling", fallingKey);
            CAAnimation landAnimation = LoadAndCacheAnimation("art.scnassets/characters/explorer/jump_land", landKey);

            jumpAnimation.FadeInDuration  = 0.15f;
            jumpAnimation.FadeOutDuration = 0.15f;
            fallAnimation.FadeInDuration  = 0.15f;
            landAnimation.FadeInDuration  = 0.15f;
            landAnimation.FadeOutDuration = 0.15f;

            jumpAnimation.RepeatCount = 0;
            fallAnimation.RepeatCount = 0;
            landAnimation.RepeatCount = 0;

            jumpForce = 7.0f;


            SCNAnimationEventHandler leaveGroundBlock = (animation, animatedObject, playingBackward) => {
                var jumpVelocity = new SCNVector3(0f, jumpForce * 2.1f, 0f);
                velocity        = SCNVector3.Add(velocity, jumpVelocity);
                Launching       = false;
                InJumpAnimation = false;
            };

            SCNAnimationEventHandler pause = (animation, animatedObject, playingBackward) => {
                mainSkeleton.PauseAnimation(fallingKey);
            };

            jumpAnimation.AnimationEvents = new SCNAnimationEvent[] { SCNAnimationEvent.Create(0.25f, leaveGroundBlock) };
            fallAnimation.AnimationEvents = new SCNAnimationEvent[] { SCNAnimationEvent.Create(0.5f, pause) };

            // Animation Sequence is to Jump -> Fall -> Land -> Idle.
            ChainAnimation(jumpKey, fallingKey);
            ChainAnimation(landKey, idleKey);
        }
Beispiel #5
0
        public SCNVector3?IntersectionWithHorizontalPlane(float planeY)
        {
            SCNVector3 rayOrigin = Origin;
            SCNVector3 direction = Direction;

            // Normalize direction
            direction = direction.Normalized();

            // Special case handling: Check if the ray is horizontal as well.
            if (direction.Y == 0)
            {
                if (rayOrigin.Y == planeY)
                {
                    // The ray is horizontal and on the plane, thus all points on the ray intersect with the plane.
                    // Therefore we simply return the ray origin.
                    return(rayOrigin);
                }
                else
                {
                    // The ray is parallel to the plane and never intersects.
                    return(null);
                }
            }

            // The distance from the ray's origin to the intersection point on the plane is:
            //   (pointOnPlane - rayOrigin) dot planeNormal
            //  --------------------------------------------
            //          direction dot planeNormal

            // Since we know that horizontal planes have normal (0, 1, 0), we can simplify this to:
            var dist = (planeY - rayOrigin.Y) / direction.Y;

            // Do not return intersections behind the ray's origin.
            if (dist < 0)
            {
                return(null);
            }

            // Return the intersection point.
            return(rayOrigin.Add(direction * dist));
        }
        void CharacterNodeHitWallWithContact(SCNNode capsule, SCNPhysicsContact contact)
        {
            if (capsule.ParentNode != Character.Node)
            {
                return;
            }

            if (maxPenetrationDistance > contact.PenetrationDistance)
            {
                return;
            }

            maxPenetrationDistance = contact.PenetrationDistance;

            var        charPosition = Character.Node.Position;
            SCNVector3 n            = contact.ContactNormal;

            SCNVector3.Multiply(ref n, (float)contact.PenetrationDistance, out n);
            n.Y = 0;

            SCNVector3.Add(ref charPosition, ref n, out replacementPosition);
            positionNeedsAdjustment = true;
        }
Beispiel #7
0
        private SCNNode SetupVehicle(SCNScene scene)
        {
            var carScene    = SCNScene.FromFile("rc_car", ResourceManager.ResourceFolder, (NSDictionary)null);
            var chassisNode = carScene.RootNode.FindChildNode("rccarBody", false);

            chassisNode.Position = new SCNVector3(0f, 10f, 30f);
            chassisNode.Rotation = new SCNVector4(0f, 1f, 0f, (float)Math.PI);

            var body = SCNPhysicsBody.CreateDynamicBody();

            body.AllowsResting   = false;
            body.Mass            = 80f;
            body.Restitution     = 0.1f;
            body.Friction        = 0.5f;
            body.RollingFriction = 0f;

            chassisNode.PhysicsBody = body;

            var frontCameraNode = SCNNode.Create();

            frontCameraNode.Position    = new SCNVector3(0f, 3.5f, 2.5f);
            frontCameraNode.Rotation    = new SCNVector4(0f, 1f, 0f, (float)Math.PI);
            frontCameraNode.Camera      = SCNCamera.Create();
            frontCameraNode.Camera.XFov = 75f;
            frontCameraNode.Camera.ZFar = 500f;

            chassisNode.AddChildNode(frontCameraNode);

            scene.RootNode.AddChildNode(chassisNode);

            var pipeNode = chassisNode.FindChildNode("pipe", true);

            reactor = SCNParticleSystem.Create("reactor", ResourceManager.ResourceFolder);
            reactor.ParticleImage   = ResourceManager.GetResourcePath("spark.png");
            reactorDefaultBirthRate = reactor.BirthRate;
            reactor.BirthRate       = 0;
            pipeNode.AddParticleSystem(reactor);

            SCNNode wheel0Node = chassisNode.FindChildNode("wheelLocator_FL", true);
            SCNNode wheel1Node = chassisNode.FindChildNode("wheelLocator_FR", true);
            SCNNode wheel2Node = chassisNode.FindChildNode("wheelLocator_RL", true);
            SCNNode wheel3Node = chassisNode.FindChildNode("wheelLocator_RR", true);

            var wheel0 = SCNPhysicsVehicleWheel.Create(wheel0Node);
            var wheel1 = SCNPhysicsVehicleWheel.Create(wheel1Node);
            var wheel2 = SCNPhysicsVehicleWheel.Create(wheel2Node);
            var wheel3 = SCNPhysicsVehicleWheel.Create(wheel3Node);

            var min = SCNVector3.Zero;
            var max = SCNVector3.Zero;

            wheel0Node.GetBoundingBox(ref min, ref max);
            float wheelHalfWidth = 0.5f * (max.X - min.X);

            wheel0.ConnectionPosition = SCNVector3.Add(wheel0Node.ConvertPositionToNode(SCNVector3.Zero, chassisNode), new SCNVector3(wheelHalfWidth, 0f, 0f));
            wheel1.ConnectionPosition = SCNVector3.Subtract(wheel1Node.ConvertPositionToNode(SCNVector3.Zero, chassisNode), new SCNVector3(wheelHalfWidth, 0f, 0f));
            wheel2.ConnectionPosition = SCNVector3.Add(wheel2Node.ConvertPositionToNode(SCNVector3.Zero, chassisNode), new SCNVector3(wheelHalfWidth, 0f, 0f));
            wheel3.ConnectionPosition = SCNVector3.Subtract(wheel3Node.ConvertPositionToNode(SCNVector3.Zero, chassisNode), new SCNVector3(wheelHalfWidth, 0f, 0f));

            var vehicle = SCNPhysicsVehicle.Create(chassisNode.PhysicsBody,
                                                   new SCNPhysicsVehicleWheel[] { wheel0, wheel1, wheel2, wheel3 });

            scene.PhysicsWorld.AddBehavior(vehicle);
            this.vehicle = vehicle;

            return(chassisNode);
        }
Beispiel #8
0
        public virtual void DidSimulatePhysics(ISCNSceneRenderer renderer, double timeInSeconds)
        {
            float defaultEngineForce  = 300.0f;
            float defaultBrakingForce = 3.0f;
            float steeringClamp       = 0.6f;
            float cameraDamping       = 0.3f;

            GameView scnView = GameView;

            float engineForce  = 0;
            float brakingForce = 0;

            var   controllers = GCController.Controllers;
            float orientation = this.orientation;

            switch (scnView.TouchesCount)
            {
            case 1:
                engineForce       = defaultEngineForce;
                reactor.BirthRate = reactorDefaultBirthRate;
                break;

            case 2:
                engineForce       = -defaultEngineForce;
                reactor.BirthRate = 0;
                break;

            case 3:
                brakingForce      = 100;
                reactor.BirthRate = 0;
                break;

            default:
                brakingForce      = defaultBrakingForce;
                reactor.BirthRate = 0;
                break;
            }

            if (controllers != null && controllers.Length > 0)
            {
                GCController             controller = controllers [0];
                GCGamepad                pad        = controller.Gamepad;
                GCControllerDirectionPad dpad       = pad.DPad;

                if (dpad.Right.IsPressed)
                {
                    if (orientationCum < 0f)
                    {
                        orientationCum *= decrementOrientation;
                    }

                    orientationCum += incrementOrientation;

                    if (orientationCum > 1f)
                    {
                        orientationCum = 1f;
                    }
                }
                else if (dpad.Left.IsPressed)
                {
                    if (orientationCum > 0)
                    {
                        orientationCum *= decrementOrientation;
                    }

                    orientationCum -= incrementOrientation;

                    if (orientationCum < -1)
                    {
                        orientationCum = -1;
                    }
                }
                else
                {
                    orientationCum *= decrementOrientation;
                }
            }

            vehicleSteering = -orientation;
            if (orientation == 0)
            {
                vehicleSteering *= 0.9f;
            }
            if (vehicleSteering < -steeringClamp)
            {
                vehicleSteering = -steeringClamp;
            }
            if (vehicleSteering > steeringClamp)
            {
                vehicleSteering = steeringClamp;
            }

            vehicle.SetSteeringAngle(vehicleSteering, 0);
            vehicle.SetSteeringAngle(vehicleSteering, 1);

            vehicle.ApplyEngineForce(engineForce, 2);
            vehicle.ApplyEngineForce(engineForce, 3);

            vehicle.ApplyBrakingForce(brakingForce, 2);
            vehicle.ApplyBrakingForce(brakingForce, 3);

            ReorientCarIfNeeded();

            SCNNode    car       = vehicleNode.PresentationNode;
            SCNVector3 carPos    = car.Position;
            var        targetPos = new SCNVector3(carPos.X, 30f, carPos.Z + 25f);
            var        cameraPos = new SCNVector3(cameraNode.Position);

            cameraPos           = SCNVector3.Add(cameraPos, cameraDamping * (SCNVector3.Subtract(targetPos, cameraPos)));
            cameraNode.Position = cameraPos;

            if (scnView.InCarView)
            {
                var frontPosition = scnView.PointOfView.PresentationNode.ConvertPositionToNode(new SCNVector3(0f, 0f, -30f), null);
                spotLightNode.Position = new SCNVector3(frontPosition.X, 80f, frontPosition.Z);
                spotLightNode.Rotation = new SCNVector4(1f, 0f, 0f, -(float)Math.PI / 2f);
            }
            else
            {
                spotLightNode.Position = new SCNVector3(carPos.X, 80f, carPos.Z + 30f);
                spotLightNode.Rotation = new SCNVector4(1f, 0f, 0f, -(float)(Math.PI / 2.8));
            }

            var overlayScene = (OverlayScene)scnView.OverlayScene;

            overlayScene.SpeedNeedle.ZRotation = -(vehicle.SpeedInKilometersPerHour * (float)Math.PI / maxSpeed);
        }