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