29 using System.Collections.Generic;
33 using OpenSim.Framework;
34 using OpenSim.Region.PhysicsModules.SharedBase;
36 using OMV = OpenMetaverse;
46 int m_walkingUpStairs;
52 bool m_waitingForLowVelocityForStationary =
false;
55 : base(physicsScene, pObj, actorName)
57 m_velocityMotor = null;
58 m_walkingUpStairs = 0;
59 m_physicsScene.DetailLog(
"{0},BSActorAvatarMove,constructor", m_controllingPrim.LocalID);
63 public override bool isActive
65 get {
return Enabled && m_controllingPrim.IsPhysicallyActive; }
72 base.SetEnabled(
false);
73 DeactivateAvatarMove();
81 m_physicsScene.DetailLog(
"{0},BSActorAvatarMove,refresh", m_controllingPrim.LocalID);
90 DeactivateAvatarMove();
107 m_physicsScene.TaintedObject(inTaintTime, m_controllingPrim.LocalID,
"BSActorAvatarMove.setVelocityAndTarget", delegate()
109 if (m_velocityMotor != null)
115 m_velocityMotor.Reset();
116 m_velocityMotor.SetTarget(targ);
117 m_velocityMotor.SetCurrent(vel);
118 m_velocityMotor.Enabled =
true;
119 m_physicsScene.DetailLog(
"{0},BSCharacter.MoveMotor,SetVelocityAndTarget,vel={1}, targ={2}",
120 m_controllingPrim.LocalID, vel, targ);
121 m_waitingForLowVelocityForStationary =
false;
128 m_waitingForLowVelocityForStationary =
true;
132 private void ActivateAvatarMove()
134 if (m_velocityMotor == null)
137 m_velocityMotor =
new BSVMotor(
"BSCharacter.Velocity",
142 m_velocityMotor.ErrorZeroThreshold = BSParam.AvatarStopZeroThreshold;
144 SetVelocityAndTarget(m_controllingPrim.RawVelocity, m_controllingPrim.TargetVelocity,
true );
146 m_physicsScene.BeforeStep += Mover;
147 m_controllingPrim.OnPreUpdateProperty += Process_OnPreUpdateProperty;
149 m_walkingUpStairs = 0;
150 m_waitingForLowVelocityForStationary =
false;
154 private void DeactivateAvatarMove()
156 if (m_velocityMotor != null)
158 m_controllingPrim.OnPreUpdateProperty -= Process_OnPreUpdateProperty;
159 m_physicsScene.BeforeStep -= Mover;
160 m_velocityMotor = null;
165 private void Mover(
float timeStep)
187 m_velocityMotor.Step(timeStep);
188 m_controllingPrim.IsStationary =
false;
191 if (m_velocityMotor.ErrorIsZero() && m_velocityMotor.TargetValue == OMV.Vector3.Zero)
194 m_velocityMotor.Zero();
196 if (m_controllingPrim.IsColliding)
199 if (!m_controllingPrim.ColliderIsMoving && !m_controllingPrim.ColliderIsVolumeDetect)
201 if (m_waitingForLowVelocityForStationary)
204 if (m_controllingPrim.RawVelocity.LengthSquared() < BSParam.AvatarStopZeroThresholdSquared)
206 m_waitingForLowVelocityForStationary =
false;
209 if (!m_waitingForLowVelocityForStationary)
211 m_physicsScene.DetailLog(
"{0},BSCharacter.MoveMotor,collidingWithStationary,zeroingMotion", m_controllingPrim.LocalID);
212 m_controllingPrim.IsStationary =
true;
213 m_controllingPrim.ZeroMotion(
true );
217 m_physicsScene.DetailLog(
"{0},BSCharacter.MoveMotor,waitingForLowVel,rawvel={1}",
218 m_controllingPrim.LocalID, m_controllingPrim.RawVelocity.Length());
223 if (m_controllingPrim.Friction != BSParam.AvatarStandingFriction)
225 m_controllingPrim.Friction = BSParam.AvatarStandingFriction;
226 m_physicsScene.PE.SetFriction(m_controllingPrim.PhysBody, m_controllingPrim.Friction);
231 if (m_controllingPrim.Flying)
234 m_controllingPrim.ZeroMotion(
true );
239 if (m_controllingPrim.RawVelocity.Z < BSParam.AvatarTerminalVelocity)
242 OMV.Vector3 slowingForce =
new OMV.Vector3(0f, 0f, BSParam.AvatarTerminalVelocity - m_controllingPrim.RawVelocity.Z) * m_controllingPrim.Mass;
243 m_physicsScene.PE.ApplyCentralImpulse(m_controllingPrim.PhysBody, slowingForce);
249 m_physicsScene.DetailLog(
"{0},BSCharacter.MoveMotor,taint,stopping,target={1},colliding={2},isStationary={3}",
250 m_controllingPrim.LocalID, m_velocityMotor.TargetValue, m_controllingPrim.IsColliding,m_controllingPrim.IsStationary);
255 OMV.Vector3 stepVelocity = m_velocityMotor.CurrentValue;
257 if (m_controllingPrim.Friction != BSParam.AvatarFriction)
260 m_controllingPrim.Friction = BSParam.AvatarFriction;
261 m_physicsScene.PE.SetFriction(m_controllingPrim.PhysBody, m_controllingPrim.Friction);
267 float realVelocityZ = m_controllingPrim.RawVelocity.Z;
270 if (!m_controllingPrim.Flying && realVelocityZ < 0)
273 if (realVelocityZ < BSParam.AvatarTerminalVelocity)
275 realVelocityZ = BSParam.AvatarTerminalVelocity;
278 stepVelocity.Z = realVelocityZ;
285 if (m_controllingPrim.Flying)
287 float hover_height = m_physicsScene.TerrainManager.GetTerrainHeightAtXYZ(m_controllingPrim.RawPosition)
288 + BSParam.AvatarFlyingGroundMargin;
290 if( m_controllingPrim.Position.Z < hover_height)
292 m_physicsScene.DetailLog(
"{0},BSCharacter.MoveMotor,addingUpforceForGroundMargin,height={1},hoverHeight={2}",
293 m_controllingPrim.LocalID, m_controllingPrim.Position.Z, hover_height);
294 stepVelocity.Z += BSParam.AvatarFlyingGroundUpForce;
299 OMV.Vector3 moveForce = (stepVelocity - m_controllingPrim.RawVelocity) * m_controllingPrim.Mass;
302 moveForce += WalkUpStairs();
304 m_physicsScene.DetailLog(
"{0},BSCharacter.MoveMotor,move,stepVel={1},vel={2},mass={3},moveForce={4}",
305 m_controllingPrim.LocalID, stepVelocity, m_controllingPrim.RawVelocity, m_controllingPrim.Mass, moveForce);
306 m_physicsScene.PE.ApplyCentralImpulse(m_controllingPrim.PhysBody, moveForce);
312 private void Process_OnPreUpdateProperty(ref EntityProperties entprop)
315 if (m_controllingPrim.IsStationary)
317 entprop.Position = m_controllingPrim.RawPosition;
318 entprop.Velocity = OMV.Vector3.Zero;
319 m_physicsScene.PE.SetTranslation(m_controllingPrim.PhysBody, entprop.Position, entprop.Rotation);
326 private OMV.Vector3 WalkUpStairs()
328 OMV.Vector3 ret = OMV.Vector3.Zero;
330 m_physicsScene.DetailLog(
"{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4},avHeight={5}",
331 m_controllingPrim.LocalID, m_controllingPrim.IsColliding, m_controllingPrim.Flying,
332 m_controllingPrim.TargetVelocitySpeed, m_controllingPrim.CollisionsLastTick.Count, m_controllingPrim.Size.Z);
335 if ( m_controllingPrim.IsColliding
336 && !m_controllingPrim.Flying
337 && m_controllingPrim.TargetVelocitySpeed > 0.1f )
343 float nearFeetHeightMin = m_controllingPrim.RawPosition.Z - (m_controllingPrim.Size.Z / 2f) - BSParam.AvatarStepGroundFudge;
344 float nearFeetHeightMax = nearFeetHeightMin + BSParam.AvatarStepHeight;
348 OMV.Vector3 highestTouchPosition =
OMV.Vector3.Zero;
349 foreach (KeyValuePair<uint, ContactPoint> kvp in m_controllingPrim.CollisionsLastTick.m_objCollisionList)
352 if (kvp.Key > m_physicsScene.TerrainManager.HighestTerrainID)
354 BSPhysObject collisionObject;
355 if (m_physicsScene.PhysObjects.TryGetValue(kvp.Key, out collisionObject))
357 if (!collisionObject.IsVolumeDetect)
359 OMV.Vector3 touchPosition = kvp.Value.Position;
360 m_physicsScene.DetailLog(
"{0},BSCharacter.WalkUpStairs,min={1},max={2},touch={3}",
361 m_controllingPrim.LocalID, nearFeetHeightMin, nearFeetHeightMax, touchPosition);
362 if (touchPosition.Z >= nearFeetHeightMin && touchPosition.Z <= nearFeetHeightMax)
367 OMV.Vector3 directionFacing = OMV.Vector3.UnitX * m_controllingPrim.RawOrientation;
368 OMV.Vector3 touchNormal = OMV.Vector3.Normalize(kvp.Value.SurfaceNormal);
369 const float PIOver2 = 1.571f;
373 if ((Math.Abs(directionFacing.Z) * PIOver2) < BSParam.AvatarStepAngle
374 && (Math.Abs(touchNormal.Z) * PIOver2) < BSParam.AvatarStepAngle)
378 float diff = Math.Abs(OMV.Vector3.Distance(directionFacing, touchNormal));
379 if (diff < BSParam.AvatarStepApproachFactor)
381 if (highestTouchPosition.Z < touchPosition.Z)
382 highestTouchPosition = touchPosition;
390 m_walkingUpStairs = 0;
392 if (highestTouchPosition !=
OMV.Vector3.Zero)
396 m_walkingUpStairs = BSParam.AvatarStepSmoothingSteps;
398 m_lastStepUp = highestTouchPosition.Z - nearFeetHeightMin;
399 ret = ComputeStairCorrection(m_lastStepUp);
400 m_physicsScene.DetailLog(
"{0},BSCharacter.WalkUpStairs,touchPos={1},nearFeetMin={2},ret={3}",
401 m_controllingPrim.LocalID, highestTouchPosition, nearFeetHeightMin, ret);
408 if (m_walkingUpStairs > 0)
411 ret = ComputeStairCorrection(m_lastStepUp);
418 private OMV.Vector3 ComputeStairCorrection(
float stepUp)
420 OMV.Vector3 ret = OMV.Vector3.Zero;
421 OMV.Vector3 displacement = OMV.Vector3.Zero;
426 if (BSParam.AvatarStepForceFactor > 0f)
428 float upForce = stepUp * m_controllingPrim.Mass * BSParam.AvatarStepForceFactor;
429 ret =
new OMV.Vector3(0f, 0f, upForce);
433 if (BSParam.AvatarStepUpCorrectionFactor > 0f)
436 displacement =
new OMV.Vector3(0f, 0f, stepUp * BSParam.AvatarStepUpCorrectionFactor);
437 m_controllingPrim.ForcePosition = m_controllingPrim.RawPosition + displacement;
441 if (BSParam.AvatarStepUpCorrectionFactor < 0f)
444 displacement =
new OMV.Vector3(0f, 0f, BSParam.AvatarStepHeight);
445 m_controllingPrim.ForcePosition = m_controllingPrim.RawPosition + displacement;
448 m_physicsScene.DetailLog(
"{0},BSCharacter.WalkUpStairs.ComputeStairCorrection,stepUp={1},isp={2},force={3}",
449 m_controllingPrim.LocalID, stepUp, displacement, ret);
Each physical object can have 'actors' who are pushing the object around. This can be used for hover...
void SetVelocityAndTarget(OMV.Vector3 vel, OMV.Vector3 targ, bool inTaintTime)
BSActorAvatarMove(BSScene physicsScene, BSPhysObject pObj, string actorName)
Interactive OpenSim region server
override void RemoveDependencies()
void SuppressStationayCheckUntilLowVelocity()