protected PositionalForce HoverMotor(IPhysicsObject actor, IPhysicalObject obj, Vector3 pos) { lock (m_HoverParamsLock) { if (m_HoverEnabled) { var v = new Vector3(0, 0, (m_Buoyancy - 1) * GravityConstant(actor, obj)); double targetHoverHeight; SceneInterface.LocationInfo locInfo = LocationInfoProvider.At(obj.GlobalPosition); targetHoverHeight = locInfo.GroundHeight; if (targetHoverHeight < locInfo.WaterHeight && m_AboveWater) { targetHoverHeight = locInfo.WaterHeight; } v.Z += (targetHoverHeight - obj.Position.Z) * m_HoverTau; return(new PositionalForce("HoverMotor", v, pos)); } else { return(new PositionalForce("HoverMotor", Vector3.Zero, pos)); } } }
protected List <PositionalForce> CalculateForces(double dt, out Vector3 agentTorque) { var forces = new List <PositionalForce>(); agentTorque = Vector3.Zero; Vector3 linearVelocity = Agent.Velocity; double horizontalVelocity = linearVelocity.HorizontalLength; Vector3 currentPosition = Agent.GlobalPosition; Vector3 size = Agent.Size; if (Agent.SittingOnObject != null || Agent.SceneID != m_StateData.SceneID) { /* No animation update on disabled physics */ return(forces); } else if (Agent.IsFlying) { bool isUnderwater = currentPosition.Z < LocationInfoProvider.At(currentPosition).WaterHeight; if (horizontalVelocity >= FlySlowFastSpeedSwitchThreshold * SpeedFactor) { Agent.SetDefaultAnimation(isUnderwater ? AnimationState.Swimming : AnimationState.Flying); } else if (horizontalVelocity > 0.2) { Agent.SetDefaultAnimation(isUnderwater ? AnimationState.SwimmingSlow : AnimationState.FlyingSlow); } else if (Agent.Velocity.Z > 0.2) { Agent.SetDefaultAnimation(isUnderwater ? AnimationState.SwimmingUp : AnimationState.HoveringUp); } else if (Agent.Velocity.Z < -0.2) { Agent.SetDefaultAnimation(isUnderwater ? AnimationState.SwimmingDown : AnimationState.HoveringDown); } else { Agent.SetDefaultAnimation(isUnderwater ? AnimationState.Floating : AnimationState.Hovering); } /* TODO: implement taking off */ } else { Vector3 angularVelocity = Agent.AngularVelocity; double groundHeightDiff = Agent.GlobalPositionOnGround.Z - LocationInfoProvider.At(Agent.GlobalPosition).GroundHeight; bool isfalling = Agent.Velocity.Z > 0.1; bool standing_still = horizontalVelocity < StandstillSpeedThreshold; bool iscrouching = m_ControlFlags.HasDown(); AnimationState oldState = Agent.GetDefaultAnimation(); //Vector3 bodyRotDiff = Agent.BodyRotation.GetEulerAngles() - m_LastKnownBodyRotation.GetEulerAngles(); if (isfalling && oldState != AnimationState.Running && oldState != AnimationState.Walking && oldState != AnimationState.Crouching && oldState != AnimationState.CrouchWalking) { Agent.SetDefaultAnimation(AnimationState.FallingDown); } else if (iscrouching) { Agent.SetDefaultAnimation(standing_still ? AnimationState.Crouching : AnimationState.CrouchWalking); } else if (m_ControlFlags.HasUp()) { Agent.SetDefaultAnimation(AnimationState.Prejumping); } else if (!standing_still) { Agent.SetDefaultAnimation(horizontalVelocity >= WalkRunSpeedSwitchThreshold * SpeedFactor ? AnimationState.Running : AnimationState.Walking); } else if (m_ControlFlags.HasLeft()) { Agent.SetDefaultAnimation(AnimationState.TurningLeft); } else if (m_ControlFlags.HasRight()) { Agent.SetDefaultAnimation(AnimationState.TurningRight); } else { Agent.SetDefaultAnimation(AnimationState.Standing); } /* TODO: implement striding, prejumping, jumping, soft landing */ } m_LastKnownBodyRotation = Agent.BodyRotation; forces.Add(BuoyancyMotor(this, Agent, Vector3.Zero)); if (!Agent.IsFlying && currentPosition.Z - size.Z / 2 > LocationInfoProvider.At(currentPosition).GroundHeight) { forces.Add(GravityMotor(this, Agent, Vector3.Zero)); } forces.Add(HoverMotor(this, Agent, Vector3.Zero)); forces.Add(new PositionalForce("ControlInput", ControlLinearInput * ControlLinearInputFactor * SpeedFactor * Agent.GlobalRotation, Vector3.Zero)); Vector3 restitutionForce = -Agent.Velocity * RestitutionInputFactor; if (!Agent.IsFlying) { restitutionForce.Z = 0; } forces.Add(new PositionalForce("LinearRestitutionMotor", restitutionForce, Vector3.Zero)); /* let us allow advanced physics force input to be used on agents */ foreach (ObjectGroup grp in Agent.Attachments.All) { foreach (KeyValuePair <UUID, Vector3> kvp in grp.AttachedForces) { ObjectPart part; if (grp.TryGetValue(kvp.Key, out part)) { forces.Add(new PositionalForce("AdvPhysics", kvp.Value, part.LocalPosition + grp.Position)); } } } lock (m_Lock) { forces.Add(new PositionalForce("LinearImpulse", m_LinearImpulse, Vector3.Zero)); m_LinearImpulse = Vector3.Zero; forces.Add(new PositionalForce("AppliedForce", m_AppliedForce, Vector3.Zero)); } forces.Add(MoveToTargetMotor(Agent)); agentTorque += LookAtMotor(Agent); agentTorque += (ControlAngularInput - Agent.AngularVelocity) * dt; return(forces); }