new public void Update(DwarfTime gameTime, ChunkManager chunks, Camera camera) { if (!IsActive) { return; } // How would this get a NaN anyway? if (MathFunctions.HasNan(Velocity)) { Velocity = Vector3.Zero; } // If we're not sleeping and moving very slowly, go to sleep. if (!IsSleeping && Velocity.LengthSquared() < 0.0225f) { SleepTimer.Update(gameTime); if (SleepTimer.HasTriggered) { applyGravityThisFrame = false; Velocity = Vector3.Zero; IsSleeping = true; } } else { SleepTimer.Reset(); IsSleeping = false; } // If not sleeping, update physics. if (!IsSleeping || overrideSleepThisFrame) { overrideSleepThisFrame = false; float dt = (float)(gameTime.ElapsedGameTime.TotalSeconds); // Calculate the number of timesteps to apply. int numTimesteps = Math.Min(MaxTimesteps, Math.Max((int)(dt / FixedDT), 1)); float velocityLength = Math.Max(Velocity.Length(), 1.0f); // Prepare expanded world bounds. BoundingBox worldBounds = chunks.Bounds; worldBounds.Max.Y += 50; // For each timestep, move and collide. for (int n = 0; n < numTimesteps * velocityLength; n++) { // Move by a fixed amount. Move(FixedDT / velocityLength); // Get the current voxel. chunks.ChunkData.GetVoxel(Position, ref CurrentVoxel); if (CurrentVoxel != null && CurrentVoxel.Chunk != null) { Vector3 gridPos = CurrentVoxel.GridPosition; CurrentVoxel.Chunk.GetNeighborsSuccessors(VoxelChunk.ManhattanSuccessors, (int)gridPos.X, (int)gridPos.Y, (int)gridPos.Z, Neighbors); } // Collide with the world. HandleCollisions(chunks, FixedDT); Matrix transform = LocalTransform; // Avoid leaving the world. if (worldBounds.Contains(LocalTransform.Translation + Velocity * dt) != ContainmentType.Contains) { transform.Translation = LocalTransform.Translation - 0.1f * Velocity * dt; Velocity = new Vector3(Velocity.X * -0.9f, Velocity.Y, Velocity.Z * -0.9f); } // If we're outside the world, die if (LocalTransform.Translation.Y < -10 || worldBounds.Contains(GetBoundingBox()) == ContainmentType.Disjoint) { Die(); } // Orientation logic. if (Orientation == OrientMode.Physics) { Matrix dA = Matrix.Identity; dA *= Matrix.CreateRotationX(AngularVelocity.X * FixedDT); dA *= Matrix.CreateRotationY(AngularVelocity.Y * FixedDT); dA *= Matrix.CreateRotationZ(AngularVelocity.Z * FixedDT); transform = dA * transform; } else if (Orientation != OrientMode.Fixed) { if (Velocity.Length() > 0.4f) { if (Orientation == OrientMode.LookAt) { Matrix newTransform = Matrix.Invert(Matrix.CreateLookAt(Position, Position + Velocity, Vector3.Down)); newTransform.Translation = transform.Translation; transform = newTransform; } else if (Orientation == OrientMode.RotateY) { Rotation = (float)Math.Atan2(Velocity.X, -Velocity.Z); Quaternion newRotation = Quaternion.CreateFromRotationMatrix(Matrix.CreateRotationY(Rotation)); Quaternion oldRotation = Quaternion.CreateFromRotationMatrix(LocalTransform); Quaternion finalRot = Quaternion.Slerp(oldRotation, newRotation, 0.1f); finalRot.Normalize(); Matrix newTransform = Matrix.CreateFromQuaternion(finalRot); newTransform.Translation = transform.Translation; newTransform.Right.Normalize(); newTransform.Up.Normalize(); newTransform.Forward.Normalize(); newTransform.M14 = 0; newTransform.M24 = 0; newTransform.M34 = 0; newTransform.M44 = 1; transform = newTransform; } } } // Final check to ensure we're in the world. transform.Translation = ClampToBounds(transform.Translation); LocalTransform = transform; // Assume that if velocity is small, we're standing on ground (lol bad assumption) // Apply friction. if (Math.Abs(Velocity.Y) < 0.1f) { Velocity = new Vector3(Velocity.X * Friction, Velocity.Y, Velocity.Z * Friction); } // Apply gravity. if (applyGravityThisFrame) { ApplyForce(Gravity, FixedDT / velocityLength); } // Damp the velocity. Vector3 dampingForce = -Velocity * (1.0f - LinearDamping); Velocity += dampingForce * FixedDT; AngularVelocity *= AngularDamping; // These will get called next time around anyway... UpdateBoundingBox(); UpdateTransformsRecursive(Parent as Body); } } applyGravityThisFrame = true; CheckLiquids(chunks, (float)gameTime.ElapsedGameTime.TotalSeconds); PreviousVelocity = Velocity; PreviousPosition = Position; base.Update(gameTime, chunks, camera); }
override public void Update(DwarfTime gameTime, ChunkManager chunks, Camera camera) { base.Update(gameTime, chunks, camera); if (!Active) { return; } // Never apply physics when animating! if (AnimationQueue.Count > 0) { Velocity = Vector3.Zero; return; } if (gameTime.Speed < 0.01) // This a poor man's IsPaused? Does this even get called if paused? { return; } // How would this get a NaN anyway? if (MathFunctions.HasNan(Velocity)) { Velocity = Vector3.Zero; } if (AllowPhysicsSleep) { bool goingSlow = Velocity.LengthSquared() < 0.05f; // If we're not sleeping and moving very slowly, go to sleep. if (!IsSleeping && goingSlow) { WakeTimer.Reset(); SleepTimer.Update(gameTime); if (SleepTimer.HasTriggered) { WakeTimer.Reset(); Velocity = Vector3.Zero; IsSleeping = true; } } else if (IsSleeping && !goingSlow) { WakeTimer.Update(gameTime); SleepTimer.Reset(); if (WakeTimer.HasTriggered) { IsSleeping = false; } } } // If not sleeping, update physics. if (!IsSleeping || overrideSleepThisFrame) { overrideSleepThisFrame = false; float dt = (float)(gameTime.ElapsedGameTime.TotalSeconds); // Calculate the number of timesteps to apply. int numTimesteps = Math.Min(MaxTimesteps, Math.Max((int)(dt / FixedDT), 1)); float velocityLength = Math.Max(Velocity.Length(), 1.0f); // Prepare expanded world bounds. BoundingBox worldBounds = chunks.Bounds; worldBounds.Max.Y += 50; // For each timestep, move and collide. for (int n = 0; n < numTimesteps * velocityLength; n++) { // Move by a fixed amount. Move(FixedDT / velocityLength); prevVoxel = CurrentVoxel; // Get the current voxel. CurrentVoxel = new VoxelHandle(chunks, GlobalVoxelCoordinate.FromVector3(Position)); if (CurrentVoxel != prevVoxel) { queryNeighborhood = true; } // Collide with the world. if (CollisionType != CollisionType.None) { HandleCollisions(queryNeighborhood, neighborHood, chunks, FixedDT); } queryNeighborhood = false; Matrix transform = LocalTransform; // Avoid leaving the world. if (worldBounds.Contains(LocalTransform.Translation + Velocity * dt) != ContainmentType.Contains) { transform.Translation = LocalTransform.Translation - 0.1f * Velocity * dt; Velocity = new Vector3(Velocity.X * -0.9f, Velocity.Y, Velocity.Z * -0.9f); } // If we're outside the world, die if (LocalTransform.Translation.Y < -10 || worldBounds.Contains(GetBoundingBox()) == ContainmentType.Disjoint) { Die(); } // Final check to ensure we're in the world. transform.Translation = ClampToBounds(transform.Translation); LocalTransform = transform; // Assume that if velocity is small, we're standing on ground (lol bad assumption) // Apply friction. if (Math.Abs(Velocity.Y) < 0.1f) { Velocity = new Vector3(Velocity.X * Friction, Velocity.Y, Velocity.Z * Friction); } // Apply gravity. ApplyForce(Gravity, FixedDT / velocityLength); // Damp the velocity. Vector3 dampingForce = -Velocity * (1.0f - LinearDamping); Velocity += dampingForce * FixedDT; AngularVelocity *= AngularDamping; // These will get called next time around anyway... -@blecki // No they won't @blecki, this broke everything!! -@mklingen // Remove check so that it is ALWAYS called when an object moves. Call removed // from component update in ComponentManager. -@blecki if (numTimesteps * velocityLength > 1) { // Assume all physics are attached to the root. if (Parent != null) { globalTransform = LocalTransform * (Parent as GameComponent).GlobalTransform; } else { globalTransform = LocalTransform; } UpdateBoundingBox(); //UpdateTransformsRecursive(Parent as Body); } } if (Orientation != OrientMode.Fixed) { Matrix transform = LocalTransform; if (Velocity.Length() > 0.4f) { if (Orientation == OrientMode.LookAt) { if (Math.Abs(Vector3.Dot(Vector3.Down, Velocity)) < 0.99 * Velocity.Length()) { Matrix newTransform = Matrix.Invert(Matrix.CreateLookAt(LocalPosition, LocalPosition + Velocity, Vector3.Down)); newTransform.Translation = transform.Translation; transform = newTransform; } else { { Matrix newTransform = Matrix.Invert(Matrix.CreateLookAt(LocalPosition, LocalPosition + Velocity, Vector3.Right)); newTransform.Translation = transform.Translation; transform = newTransform; } } } else if (Orientation == OrientMode.RotateY) { Rotation = (float)Math.Atan2(Velocity.X, -Velocity.Z); Quaternion newRotation = Quaternion.CreateFromRotationMatrix(Matrix.CreateRotationY(Rotation)); Quaternion oldRotation = Quaternion.CreateFromRotationMatrix(LocalTransform); Quaternion finalRot = Quaternion.Slerp(oldRotation, newRotation, 0.1f); finalRot.Normalize(); Matrix newTransform = Matrix.CreateFromQuaternion(finalRot); newTransform.Translation = transform.Translation; newTransform.Right.Normalize(); newTransform.Up.Normalize(); newTransform.Forward.Normalize(); newTransform.M14 = 0; newTransform.M24 = 0; newTransform.M34 = 0; newTransform.M44 = 1; transform = newTransform; } } LocalTransform = transform; } } CheckLiquids(chunks, (float)gameTime.ElapsedGameTime.TotalSeconds); PreviousVelocity = Velocity; PreviousPosition = Position; }
public override void Update(DwarfTime gameTime, ChunkManager chunks, Camera camera) { if (!IsActive) { return; } BoundingBox bounds = chunks.Bounds; bounds.Max.Y += 50; if (!IsSleeping && (Velocity).Length() < 0.15f) { SleepTimer.Update(gameTime); if (SleepTimer.HasTriggered) { applyGravityThisFrame = false; Velocity *= 0.0f; IsSleeping = true; } } else { SleepTimer.Reset(); IsSleeping = false; } if (!IsSleeping || overrideSleepThisFrame) { if (overrideSleepThisFrame) { overrideSleepThisFrame = false; } float dt = (float)(gameTime.ElapsedGameTime.TotalSeconds); if (MathFunctions.HasNan(Velocity)) { Velocity = Vector3.Zero; } MoveY(dt); MoveX(dt); MoveZ(dt); chunks.ChunkData.GetVoxel(Position, ref CurrentVoxel); if (CurrentVoxel != null && CurrentVoxel.Chunk != null) { Vector3 gridPos = CurrentVoxel.GridPosition; CurrentVoxel.Chunk.GetNeighborsSuccessors(VoxelChunk.ManhattanSuccessors, (int)gridPos.X, (int)gridPos.Y, (int)gridPos.Z, Neighbors); } HandleCollisions(chunks, dt); Matrix transform = LocalTransform; if (bounds.Contains(LocalTransform.Translation + Velocity * dt) != ContainmentType.Contains) { transform.Translation = LocalTransform.Translation - 0.1f * Velocity * dt; Velocity = new Vector3(Velocity.X * -0.9f, Velocity.Y, Velocity.Z * -0.9f); } if (LocalTransform.Translation.Z < -10 || bounds.Contains(GetBoundingBox()) == ContainmentType.Disjoint) { Die(); } if (Orientation == OrientMode.Physics) { Matrix dA = Matrix.Identity; dA *= Matrix.CreateRotationX(AngularVelocity.X * dt); dA *= Matrix.CreateRotationY(AngularVelocity.Y * dt); dA *= Matrix.CreateRotationZ(AngularVelocity.Z * dt); transform = dA * transform; } else if (Orientation != OrientMode.Fixed) { if (Velocity.Length() > 0.4f) { if (Orientation == OrientMode.LookAt) { Matrix newTransform = Matrix.Invert(Matrix.CreateLookAt(Position, Position + Velocity, Vector3.Down)); newTransform.Translation = transform.Translation; transform = newTransform; } else if (Orientation == OrientMode.RotateY) { Rotation = (float)Math.Atan2(Velocity.X, -Velocity.Z); Quaternion newRotation = Quaternion.CreateFromRotationMatrix(Matrix.CreateRotationY(Rotation)); Quaternion oldRotation = Quaternion.CreateFromRotationMatrix(LocalTransform); Quaternion finalRot = Quaternion.Slerp(oldRotation, newRotation, 0.1f); finalRot.Normalize(); Matrix newTransform = Matrix.CreateFromQuaternion(finalRot); newTransform.Translation = transform.Translation; newTransform.Right.Normalize(); newTransform.Up.Normalize(); newTransform.Forward.Normalize(); newTransform.M14 = 0; newTransform.M24 = 0; newTransform.M34 = 0; newTransform.M44 = 1; transform = newTransform; } } } transform.Translation = ClampToBounds(transform.Translation); LocalTransform = transform; if (Math.Abs(Velocity.Y) < 0.1f) { Velocity = new Vector3(Velocity.X * Friction, Velocity.Y, Velocity.Z * Friction); } if (applyGravityThisFrame) { ApplyForce(Gravity, dt); } else { applyGravityThisFrame = true; } Velocity *= LinearDamping; AngularVelocity *= AngularDamping; UpdateBoundingBox(); } CheckLiquids(chunks, (float)gameTime.ElapsedGameTime.TotalSeconds); Velocity = (PreviousVelocity * 0.1f + Velocity * 0.9f); PreviousVelocity = Velocity; PreviousPosition = Position; base.Update(gameTime, chunks, camera); }