public List<BlockIndex> BlocksBeneath(PhysicsObject obj) { List<BlockIndex> returnList = new List<BlockIndex>(); for (int x = (int)Math.Floor(obj.BoundingBox.Min.X); x <= Math.Floor(obj.BoundingBox.Max.X); x++) { for (int z = (int)Math.Floor(obj.BoundingBox.Min.Z); z <= Math.Floor(obj.BoundingBox.Max.Z); z++) { returnList.Add(new BlockIndex(x, (int)Math.Floor(obj.Position.Y - Constants.Player.MinDistanceToGround), z)); } } return returnList; }
public bool IsOnGround(PhysicsObject obj) { return !PlaceFree(obj, obj.Position - Vector3d.UnitY * Constants.Player.MinDistanceToGround); }
private void UpdateVelocity(PhysicsObject currentObject) { // To avoid errors (specifically, NaN), remove velocity if too small. if (Player.Velocity.Length <= Constants.Physics.MinSpeed) { Player.Velocity = Vector3d.Zero; } // Gravity currentObject.Accelerate(-Vector3d.UnitY * Constants.Physics.Gravity); // Buoyancy currentObject.Accelerate(Vector3d.UnitY * currentObject.BuoyancyMagnitude); // Surface friction Vector3d horizontalVelocity = Vector3d.Multiply(currentObject.Velocity, new Vector3d(1, 0, 1)); if (IsOnGround(currentObject) && horizontalVelocity != Vector3d.Zero) { currentObject.Accelerate((-Vector3d.Normalize(horizontalVelocity) * currentObject.KineticFrictionCoefficient * Constants.Physics.Gravity) * horizontalVelocity.Length * Constants.Physics.FrictionSignificance / Constants.Physics.GripSignificance); } // Update velocity currentObject.ApplyAcceleration(); }
private void UpdatePositionOneDimension(PhysicsObject obj, ref double position, ref double velocity, Vector3d axis) { while (!PlaceFree(obj, velocity * Constants.Physics.TimeStep * axis + obj.Position)) { if (Math.Round(velocity, 4) != 0.0) { velocity = velocity / 1.5; } else { velocity = 0.0; return; } } position += velocity * Constants.Physics.TimeStep; }
private void UpdatePosition(PhysicsObject obj) { Vector3d newPos = obj.Position + obj.Velocity * Constants.Physics.TimeStep; if (PlaceFree(obj, newPos)) { obj.Position = newPos; } else { UpdatePositionOneDimension(obj, ref obj.Position.Y, ref obj.Velocity.Y, Vector3d.UnitY); if (Math.Abs(obj.Velocity.X) > Math.Abs(obj.Velocity.Z)) { UpdatePositionOneDimension(obj, ref obj.Position.X, ref obj.Velocity.X, Vector3d.UnitX); UpdatePositionOneDimension(obj, ref obj.Position.Z, ref obj.Velocity.Z, Vector3d.UnitZ); } else { UpdatePositionOneDimension(obj, ref obj.Position.Z, ref obj.Velocity.Z, Vector3d.UnitZ); UpdatePositionOneDimension(obj, ref obj.Position.X, ref obj.Velocity.X, Vector3d.UnitX); } } }
private bool PlaceFree(PhysicsObject obj, Vector3d position) { foreach (BlockIndex index in obj.BoundingBox.At(position).IntersectionIndices) { if (ChunkManager.GetBlock(index).Solidity) { return false; } } return true; }