public override void Update(double deltaTime) { PlayerCharacter playerCharacter = GameSimulation.Sim.GameLevel.PlayerCharacter; SCNVector3 pos = ParentNode.Position; nfloat distanceToCharacter = SCNVector3.Subtract(playerCharacter.Position, pos).Length; if (distanceToCharacter >= 1000f) { return; } if (!isIdle) { return; } if (playerCharacter.IsWalking) { mainSkeleton.AddAnimation(CachedAnimationForKey("monkey_get_coconut-1"), null); isIdle = false; } else if (MathUtils.RandomPercent() <= 0.001f) { isIdle = false; mainSkeleton.AddAnimation(CachedAnimationForKey("monkey_tree_hang_taunt-1"), null); } }
public void UpdateVirtualObjectPosition(VirtualObject virtualObject, SCNVector3 position, bool filterPosition, NMatrix4 cameraTransform) { var cameraWorldPos = cameraTransform.Translation(); var cameraToPosition = position.Subtract(cameraWorldPos); // Limit the distance of the object from the camera to a maximum of 10m if (cameraToPosition.LengthFast > 10) { cameraToPosition = cameraToPosition.Normalized() * 10; } // Compute the average distance of the object from the camera over the last ten // updates. If filterPosition is true, compute a new position for the object // with this average. Notice that the distance is applied to the vector from // the camera to the content, so it only affects the percieved distance of the // object - the averaging does _not_ make the content "lag". var hitTestResultDistance = cameraToPosition.LengthFast; virtualObject.RecentVirtualObjectDistances.Add(hitTestResultDistance); virtualObject.RecentVirtualObjectDistances.KeepLast(10); if (filterPosition) { var averageDistance = virtualObject.RecentVirtualObjectDistances.Average(); var averagedDistancePos = cameraWorldPos + cameraToPosition.Normalized() * averageDistance; virtualObject.Position = averagedDistancePos; } else { virtualObject.Position = cameraWorldPos + cameraToPosition; } }
void ResamplePathPositions() { // Calc the phatom end control point. SCNVector3 controlPointA = PathPositions [PathPositions.Count - 2]; SCNVector3 controlPointB = PathPositions [PathPositions.Count - 3]; SCNVector3 controlPoint; controlPoint.X = controlPointA.X + (controlPointA.X - controlPointB.X); controlPoint.Y = controlPointA.Y + (controlPointA.Y - controlPointB.Y); controlPoint.Z = controlPointA.Z + (controlPointA.Z - controlPointB.Z); PathPositions [PathPositions.Count - 1] = controlPoint; // Calc the phatom begin control point. controlPointA = PathPositions [1]; controlPointB = PathPositions [2]; controlPoint.X = controlPointA.X + (controlPointA.X - controlPointB.X); controlPoint.Y = controlPointA.Y + (controlPointA.Y - controlPointB.Y); controlPoint.Z = controlPointA.Z + (controlPointA.Z - controlPointB.Z); PathPositions [0] = controlPoint; var newPath = new List <SCNVector3> (); var lastPosition = new SCNVector3(); float minDistanceBetweenPoints = 10.0f; float steps = 10000f; for (int i = 0; i < steps; i++) { float t = i / steps; SCNVector3 currentPostion = LocationAlongPath(t); if (i == 0) { newPath.Add(currentPostion); lastPosition = currentPostion; } else { var sub = SCNVector3.Subtract(lastPosition, currentPostion); nfloat dist = sub.Length; if (dist > minDistanceBetweenPoints) { newPath.Add(currentPostion); lastPosition = currentPostion; } } } // Last Step. Return the path position array for our pathing system to query. PathPositions = newPath; }
private void SetNewVirtualObjectPosition(VirtualObject virtualObject, SCNVector3 position, NMatrix4 cameraTransform) { var cameraWorldPos = cameraTransform.Translation(); var cameraToPosition = position.Subtract(cameraWorldPos); // Limit the distance of the object from the camera to a maximum of 10m if (cameraToPosition.LengthFast > 10) { cameraToPosition = cameraToPosition.Normalized() * 10; } virtualObject.Position = cameraWorldPos + cameraToPosition; virtualObject.RecentVirtualObjectDistances.Clear(); }
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); }
private void Explosion(SCNVector3 center, List <SCNNode> nodes) { foreach (var node in nodes) { var position = node.PresentationNode.Position; var dir = SCNVector3.Subtract(position, center); var force = (nfloat)25.0f; var distance = dir.Length; dir = SCNVector3.Multiply(dir, force / NMath.Max(0.01f, distance)); node.PhysicsBody.ApplyForce(dir, new SCNVector3(RandFloat(-0.2, 0.2), RandFloat(-0.2, 0.2), RandFloat(-0.2, 0.2)), true); node.RunAction(SCNAction.Sequence(new SCNAction[] { SCNAction.Wait(2), SCNAction.FadeOut(0.5f), SCNAction.RemoveFromParentNode() })); } }
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); }
public virtual void Update(ISCNSceneRenderer renderer, double timeInSeconds) { // delta time since last update if (Math.Abs(previousUpdateTime) < float.Epsilon) { previousUpdateTime = timeInSeconds; } double deltaTime = Math.Min(Math.Max(1.0 / 60.0, timeInSeconds - previousUpdateTime), 1f); previousUpdateTime = timeInSeconds; // Reset some states every frame maxPenetrationDistance = 0; positionNeedsAdjustment = false; SCNVector3 direction = GameView.CurrentDirection; SCNVector3 initialPosition = Character.Node.Position; // Move if (Math.Abs(direction.X) > float.Epsilon && Math.Abs(direction.Z) > float.Epsilon) { var characterSpeed = (float)deltaTime * CharacterSpeedFactor * .84f; Character.Node.Position = new SCNVector3( initialPosition.X + direction.X * characterSpeed, initialPosition.Y + direction.Y * characterSpeed, initialPosition.Z + direction.Z * characterSpeed ); // update orientation double angle = Math.Atan2(direction.X, direction.Z); Character.Direction = (float)angle; Character.Walking = true; } else { Character.Walking = false; } var p0 = Character.Node.Position; var p1 = Character.Node.Position; p0.Y -= MaxJump; p1.Y += MaxRise; var options = new SCNPhysicsTest { CollisionBitMask = (nuint)(int)(Bitmask.Collision | Bitmask.Water), SearchMode = SCNPhysicsSearchMode.Closest }; SCNHitTestResult[] results = GameView.Scene.PhysicsWorld.RayTestWithSegmentFromPoint(p1, p0, options); float groundY = -10; if (results.Length > 0) { SCNHitTestResult result = results [0]; groundY = result.WorldCoordinates.Y; UpdateCameraWithCurrentGround(result.Node); SCNMaterial groundMaterial = result.Node.ChildNodes [0].Geometry.FirstMaterial; if (grassArea == groundMaterial) { Character.CurrentFloorMaterial = FloorMaterial.Grass; } else if (waterArea == groundMaterial) { if (Character.Burning) { Character.Pshhhh(); Character.Node.RunAction(SCNAction.Sequence(new [] { SCNAction.PlayAudioSource(pshhhSound, true), SCNAction.PlayAudioSource(aahSound, false) })); } Character.CurrentFloorMaterial = FloorMaterial.Water; options = new SCNPhysicsTest { CollisionBitMask = (nuint)(int)Bitmask.Collision, SearchMode = SCNPhysicsSearchMode.Closest }; results = GameView.Scene.PhysicsWorld.RayTestWithSegmentFromPoint(p1, p0, options); result = results [0]; groundY = result.WorldCoordinates.Y; } else { Character.CurrentFloorMaterial = FloorMaterial.Rock; } } // var nextPosition = Character.Node.Position; // const double threshold = 1e-5; // // if (groundY < nextPosition.Y - threshold) { // // approximation of acceleration for a delta time // accelerationY += (float)(deltaTime * GravityAcceleration); // if (groundY < nextPosition.Y - 0.2) // Character.CurrentFloorMaterial = FloorMaterial.Air; // } else { // accelerationY = 0; // } // // nextPosition.Y -= accelerationY; // // // reset acceleration if we touch the ground // if (groundY > nextPosition.Y) { // accelerationY = 0; // nextPosition.Y = groundY; // } // Flames are static physics bodies, but they are moved by an action - So we need to tell the physics engine that the transforms did change. foreach (SCNNode flame in flames) { flame.PhysicsBody.ResetTransform(); } // Adjust the volume of the enemy based on the distance with the character. float distanceToClosestEnemy = float.MaxValue; SCNVector3 pos3 = Character.Node.Position; foreach (SCNNode enemy in enemies) { // distance to enemy SCNMatrix4 enemyMat = enemy.WorldTransform; var enemyPosition = new SCNVector3(enemyMat.M41, enemyMat.M42, enemyMat.M43); float distance = SCNVector3.Subtract(pos3, enemyPosition).Length; distanceToClosestEnemy = Math.Min(distanceToClosestEnemy, distance); } // Adjust sounds volumes based on distance with the enemy. if (!gameIsComplete) { double fireVolume = 0.3 * Math.Max(0.0, Math.Min(1.0, 1.0 - (distanceToClosestEnemy - 1.2) / 1.6)); var mixerNode = flameThrowerSound.AudioNode as AVAudioMixerNode; if (mixerNode != null) { mixerNode.Volume = (float)fireVolume; } } }