From 3052a5388954592861e0a55681844115485b6ae7 Mon Sep 17 00:00:00 2001
From: UbitUmarov
Date: Mon, 29 Sep 2014 20:17:05 +0100
Subject: change avatar physics and motion control. Still not that good :(
---
.../Scenes/Animation/ScenePresenceAnimator.cs | 147 ++++++++++-----
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 169 ++++++++---------
.../Region/Physics/UbitOdePlugin/ODECharacter.cs | 210 ++++++++++++++++-----
OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs | 167 ++++++++++++++--
4 files changed, 493 insertions(+), 200 deletions(-)
(limited to 'OpenSim/Region')
diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
index db3b834..6003e92 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
@@ -56,11 +56,13 @@ namespace OpenSim.Region.Framework.Scenes.Animation
/// The current movement animation
///
public string CurrentMovementAnimation { get; private set; }
-
+
private int m_animTickFall;
- public int m_animTickJump; // ScenePresence has to see this to control +Z force
+ private int m_animTickLand;
+ private int m_animTickJump;
+
public bool m_jumping = false;
- public float m_jumpVelocity = 0f;
+
// private int m_landing = 0;
///
@@ -68,7 +70,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
///
public bool Falling { get; private set; }
- private float m_fallHeight;
+ private float m_lastFallVelocity;
///
/// The scene presence that this animator applies to
@@ -205,7 +207,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
if (aoSitGndAnim != UUID.Zero)
{
- avnChangeAnim(aoSitGndAnim, false, false);
+ avnChangeAnim(aoSitGndAnim, false, true);
aoSitGndAnim = UUID.Zero;
}
@@ -258,20 +260,38 @@ namespace OpenSim.Region.Framework.Scenes.Animation
return ret;
}
+ public enum motionControlStates : byte
+ {
+ sitted = 0,
+ flying,
+ falling,
+ jumping,
+ landing,
+ onsurface
+ }
+
+ public motionControlStates currentControlState = motionControlStates.onsurface;
+
///
/// This method determines the proper movement related animation
///
private string DetermineMovementAnimation()
{
- const float FALL_DELAY = 800f;
- const float PREJUMP_DELAY = 200f;
- const float JUMP_PERIOD = 800f;
+ const int FALL_DELAY = 800;
+ const int PREJUMP_DELAY = 200;
+ const int JUMP_PERIOD = 800;
#region Inputs
if (m_scenePresence.SitGround)
+ {
+ currentControlState = motionControlStates.sitted;
return "SITGROUND";
+ }
if (m_scenePresence.ParentID != 0 || m_scenePresence.ParentUUID != UUID.Zero)
+ {
+ currentControlState = motionControlStates.sitted;
return "SIT";
+ }
AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags;
PhysicsActor actor = m_scenePresence.PhysicsActor;
@@ -311,17 +331,31 @@ namespace OpenSim.Region.Framework.Scenes.Animation
// bool moving = (move != Vector3.Zero);
#endregion Inputs
+ // no physics actor case
+ if (actor == null)
+ {
+ // well what to do?
+
+ currentControlState = motionControlStates.onsurface;
+ if (move.X != 0f || move.Y != 0f)
+ return "WALK";
+
+ return "STAND";
+ }
+
+
#region Flying
- if (actor != null && actor.Flying)
+ bool isColliding = actor.IsColliding;
+
+ if (actor.Flying)
{
m_animTickFall = 0;
m_animTickJump = 0;
m_jumping = false;
Falling = false;
- m_jumpVelocity = 0f;
- actor.Selected = false;
- m_fallHeight = actor.Position.Z; // save latest flying height
+
+ currentControlState = motionControlStates.flying;
if (move.X != 0f || move.Y != 0f)
{
@@ -333,8 +367,13 @@ namespace OpenSim.Region.Framework.Scenes.Animation
}
else if (move.Z < 0f)
{
- if (actor != null && actor.IsColliding)
+ if (isColliding)
+ {
+ actor.Flying = false;
+ currentControlState = motionControlStates.landing;
+ m_animTickLand = Environment.TickCount;
return "LAND";
+ }
else
return "HOVER_DOWN";
}
@@ -343,29 +382,41 @@ namespace OpenSim.Region.Framework.Scenes.Animation
return "HOVER";
}
}
+ else
+ {
+ if (isColliding && currentControlState == motionControlStates.flying)
+ {
+ currentControlState = motionControlStates.landing;
+ m_animTickLand = Environment.TickCount;
+ return "LAND";
+ }
+ }
#endregion Flying
#region Falling/Floating/Landing
- if ((actor == null || !actor.IsColliding) && !m_jumping)
+ if (!isColliding && currentControlState != motionControlStates.jumping)
{
- float fallElapsed = (float)(Environment.TickCount - m_animTickFall);
- float fallVelocity = (actor != null) ? actor.Velocity.Z : 0.0f;
+ float fallVelocity = actor.Velocity.Z;
- if (!m_jumping && (fallVelocity < -3.0f))
+ if (fallVelocity < -2.5f)
Falling = true;
- if (m_animTickFall == 0 || (fallVelocity >= 0.0f))
+ if (m_animTickFall == 0 || (fallVelocity >= -0.5f))
{
- // not falling yet, or going up
- // reset start of fall time
m_animTickFall = Environment.TickCount;
}
- else if (!m_jumping && (fallElapsed > FALL_DELAY) && (fallVelocity < -3.0f) && (m_scenePresence.WasFlying))
+ else
{
- // Falling long enough to trigger the animation
- return "FALLDOWN";
+ int fallElapsed = (Environment.TickCount - m_animTickFall);
+ if ((fallElapsed > FALL_DELAY) && (fallVelocity < -3.0f))
+ {
+ currentControlState = motionControlStates.falling;
+ m_lastFallVelocity = fallVelocity;
+ // Falling long enough to trigger the animation
+ return "FALLDOWN";
+ }
}
// Check if the user has stopped walking just now
@@ -375,49 +426,44 @@ namespace OpenSim.Region.Framework.Scenes.Animation
return CurrentMovementAnimation;
}
- #endregion Falling/Floating/Landing
+ m_animTickFall = 0;
+ #endregion Falling/Floating/Landing
#region Jumping // section added for jumping...
- int jumptime;
- jumptime = Environment.TickCount - m_animTickJump;
-
- if ((move.Z > 0f) && (!m_jumping))
+ if (isColliding && move.Z > 0f && currentControlState != motionControlStates.jumping)
{
// Start jumping, prejump
- m_animTickFall = 0;
+ currentControlState = motionControlStates.jumping;
m_jumping = true;
Falling = false;
- actor.Selected = true; // borrowed for jumping flag
m_animTickJump = Environment.TickCount;
- m_jumpVelocity = 0.35f;
return "PREJUMP";
}
- if (m_jumping)
+ if (currentControlState == motionControlStates.jumping)
{
+ int jumptime = Environment.TickCount - m_animTickJump;
if ((jumptime > (JUMP_PERIOD * 1.5f)) && actor.IsColliding)
{
// end jumping
m_jumping = false;
Falling = false;
actor.Selected = false; // borrowed for jumping flag
- m_jumpVelocity = 0f;
- m_animTickFall = Environment.TickCount;
+ m_animTickLand = Environment.TickCount;
+ currentControlState = motionControlStates.landing;
return "LAND";
}
else if (jumptime > JUMP_PERIOD)
{
// jump down
- m_jumpVelocity = 0f;
return "JUMP";
}
else if (jumptime > PREJUMP_DELAY)
{
// jump up
m_jumping = true;
- m_jumpVelocity = 10f;
return "JUMP";
}
}
@@ -426,42 +472,48 @@ namespace OpenSim.Region.Framework.Scenes.Animation
#region Ground Movement
- if (CurrentMovementAnimation == "FALLDOWN")
+ if (currentControlState == motionControlStates.falling)
{
Falling = false;
- m_animTickFall = Environment.TickCount;
+ currentControlState = motionControlStates.landing;
+ m_animTickLand = Environment.TickCount;
// TODO: SOFT_LAND support
- float fallHeight = m_fallHeight - actor.Position.Z;
- if (fallHeight > 15.0f)
+ float fallVsq =m_lastFallVelocity*m_lastFallVelocity;
+ if (fallVsq > 300f) // aprox 20*h
return "STANDUP";
- else if (fallHeight > 8.0f)
+ else if (fallVsq > 160f)
return "SOFT_LAND";
else
return "LAND";
}
- else if ((CurrentMovementAnimation == "LAND") || (CurrentMovementAnimation == "SOFT_LAND") || (CurrentMovementAnimation == "STANDUP"))
+
+
+ if (currentControlState == motionControlStates.landing)
{
- int landElapsed = Environment.TickCount - m_animTickFall;
+ Falling = false;
+ int landElapsed = Environment.TickCount - m_animTickLand;
int limit = 1000;
if (CurrentMovementAnimation == "LAND")
limit = 350;
// NB if the above is set too long a weird anim reset from some place prevents STAND from being sent to client
- if ((m_animTickFall != 0) && (landElapsed <= limit))
+ if ((m_animTickLand != 0) && (landElapsed <= limit))
{
return CurrentMovementAnimation;
}
else
{
- m_fallHeight = actor.Position.Z; // save latest flying height
+ currentControlState = motionControlStates.onsurface;
+ m_animTickLand = 0;
return "STAND";
}
}
+
// next section moved outside paren. and realigned for jumping
if (move.X != 0f || move.Y != 0f)
{
- m_fallHeight = actor.Position.Z; // save latest flying height
+ currentControlState = motionControlStates.onsurface;
Falling = false;
// Walking / crouchwalking / running
if (move.Z < 0f)
@@ -480,6 +532,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
}
else if (!m_jumping)
{
+ currentControlState = motionControlStates.onsurface;
Falling = false;
// Not walking
if (move.Z < 0)
@@ -493,8 +546,6 @@ namespace OpenSim.Region.Framework.Scenes.Animation
}
#endregion Ground Movement
- Falling = false;
-
return CurrentMovementAnimation;
}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 5946979..e6a366d 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -287,14 +287,7 @@ namespace OpenSim.Region.Framework.Scenes
set { PhysicsActor.Flying = value; }
}
- // add for fly velocity control
- private bool FlyingOld {get; set;}
- public bool WasFlying
- {
- get; private set;
- }
-
- public bool IsColliding
+ public bool IsColliding
{
get { return PhysicsActor != null && PhysicsActor.IsColliding; }
// We would expect setting IsColliding to be private but it's used by a hack in Scene
@@ -936,7 +929,7 @@ namespace OpenSim.Region.Framework.Scenes
///
/// AGENT_CONTRL_STOP comes about if user holds down space key on viewers.
///
- private float AgentControlStopSlowWhilstMoving = 0.5f;
+ private float AgentControlStopSlowWhilstMoving = 0.2f;
private bool m_forceFly;
@@ -2174,7 +2167,7 @@ namespace OpenSim.Region.Framework.Scenes
bool DCFlagKeyPressed = false;
Vector3 agent_control_v3 = Vector3.Zero;
- bool newFlying = actor.Flying;
+ bool newFlying = false;
if (ForceFly)
newFlying = true;
@@ -2286,11 +2279,11 @@ namespace OpenSim.Region.Framework.Scenes
if (Flying && !ForceFly)
{
// Need to stop in mid air if user holds down AGENT_CONTROL_STOP
- if (AgentControlStopActive)
- {
- agent_control_v3 = Vector3.Zero;
- }
- else
+ // if (AgentControlStopActive)
+ // {
+ // agent_control_v3 = Vector3.Zero;
+ // }
+ // else
{
// Landing detection code
@@ -2298,38 +2291,44 @@ namespace OpenSim.Region.Framework.Scenes
bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) ||
((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
- //m_log.Debug("[CONTROL]: " +flags);
+ //m_log.Debug("[CONTROL]: " +flags);
// Applies a satisfying roll effect to the avatar when flying.
if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0 && (flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0)
{
ApplyFlyingRoll(
- FLY_ROLL_RADIANS_PER_UPDATE,
- (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
+ FLY_ROLL_RADIANS_PER_UPDATE,
+ (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
(flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
- }
+ }
else if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0 &&
(flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
{
ApplyFlyingRoll(
- -FLY_ROLL_RADIANS_PER_UPDATE,
- (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
- (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
+ -FLY_ROLL_RADIANS_PER_UPDATE,
+ (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0,
+ (flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0);
}
else
{
if (m_AngularVelocity.Z != 0)
- m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE);
- }
-
- if (Flying && IsColliding && controlland)
- {
- // nesting this check because LengthSquared() is expensive and we don't
- // want to do it every step when flying.
- if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX))
- StopFlying();
+ m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE);
}
+
+ /*
+ if (Flying && IsColliding && controlland)
+ {
+ // nesting this check because LengthSquared() is expensive and we don't
+ // want to do it every step when flying.
+ if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX))
+ StopFlying();
+ }
+ */
}
}
+ else if (IsColliding && agent_control_v3.Z < 0f)
+ agent_control_v3.Z = 0;
+// else if(AgentControlStopActive %% Velocity.Z <0.01f)
+
// m_log.DebugFormat("[SCENE PRESENCE]: MovementFlag {0} for {1}", MovementFlag, Name);
@@ -2342,32 +2341,22 @@ namespace OpenSim.Region.Framework.Scenes
if (update_movementflag
|| (update_rotation && DCFlagKeyPressed && (!AgentControlStopActive || MovementFlag != 0)))
{
-// if (update_movementflag || !AgentControlStopActive || MovementFlag != 0)
-// {
-// m_log.DebugFormat(
-// "[SCENE PRESENCE]: In {0} adding velocity of {1} to {2}, umf = {3}, mf = {4}, ur = {5}",
-// m_scene.RegionInfo.RegionName, agent_control_v3, Name,
-// update_movementflag, MovementFlag, update_rotation);
-
- float speedModifier;
- if (AgentControlStopActive)
- speedModifier = AgentControlStopSlowWhilstMoving;
+ if (AgentControlStopActive)
+ {
+// if (MovementFlag == 0 && Animator.Falling)
+ if (MovementFlag == 0 && Animator.currentControlState == ScenePresenceAnimator.motionControlStates.falling)
+ {
+ AddNewMovement(agent_control_v3, AgentControlStopSlowWhilstMoving, true);
+ }
else
- speedModifier = 1;
+ AddNewMovement(agent_control_v3, AgentControlStopSlowWhilstMoving);
+ }
+
+ else
+ AddNewMovement(agent_control_v3);
- AddNewMovement(agent_control_v3, speedModifier);
-// }
}
-// else
-// {
-// if (!update_movementflag)
-// {
-// m_log.DebugFormat(
-// "[SCENE PRESENCE]: In {0} ignoring requested update of {1} for {2} as update_movementflag = false",
-// m_scene.RegionInfo.RegionName, agent_control_v3, Name);
-// }
-// }
if (update_movementflag && ParentID == 0)
{
@@ -3246,68 +3235,58 @@ namespace OpenSim.Region.Framework.Scenes
/// The vector in which to move. This is relative to the rotation argument
///
/// Optional additional speed modifier for this particular add. Default is 1
- public void AddNewMovement(Vector3 vec, float thisAddSpeedModifier = 1)
+ public void AddNewMovement(Vector3 vec, float thisAddSpeedModifier = 1, bool breaking = false)
{
-// m_log.DebugFormat(
-// "[SCENE PRESENCE]: Adding new movement {0} with rotation {1}, thisAddSpeedModifier {2} for {3}",
-// vec, Rotation, thisAddSpeedModifier, Name);
+ // m_log.DebugFormat(
+ // "[SCENE PRESENCE]: Adding new movement {0} with rotation {1}, thisAddSpeedModifier {2} for {3}",
+ // vec, Rotation, thisAddSpeedModifier, Name);
Vector3 direc = vec * Rotation;
direc.Normalize();
- if (Flying != FlyingOld) // add for fly velocity control
- {
- FlyingOld = Flying; // add for fly velocity control
- if (!Flying)
- WasFlying = true; // add for fly velocity control
- }
-
- if (IsColliding)
- WasFlying = false; // add for fly velocity control
-
if ((vec.Z == 0f) && !Flying)
direc.Z = 0f; // Prevent camera WASD up.
direc *= 0.03f * 128f * SpeedModifier * thisAddSpeedModifier;
-// m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name);
+ // m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name);
- if (PhysicsActor != null)
+ if (Animator.currentControlState == ScenePresenceAnimator.motionControlStates.falling)
{
- if (Flying)
- {
+ if (breaking)
+ direc.Z = -9999f; //hack
+ else
+ direc = Vector3.Zero;
+ }
+ else if (Flying)
+ {
+ if(IsColliding)
+ direc = Vector3.Zero;
+ else
direc *= 4.0f;
- //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
- //if (controlland)
- // m_log.Info("[AGENT]: landCommand");
- //if (IsColliding)
- // m_log.Info("[AGENT]: colliding");
- //if (Flying && IsColliding && controlland)
- //{
- // StopFlying();
- // m_log.Info("[AGENT]: Stop Flying");
- //}
- }
- if (Animator.Falling && WasFlying) // if falling from flying, disable motion add
+ }
+ else if (IsColliding)
+ {
+ if (direc.Z > 2.0f)
{
- direc *= 0.0f;
+ direc.Z *= 2.6f;
}
- else if (!Flying && IsColliding)
+ else if (direc.Z < 0)
+ direc.Z = 0;
+/*
+ float c = CollisionPlane.Z;
+ if (c > 0.2f && c < 0.94f && (direc.X != 0 || direc.Y != 0))
{
- if (direc.Z > 2.0f)
- {
- direc.Z *= 2.6f;
-
- // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored.
-// Animator.TrySetMovementAnimation("PREJUMP");
-// Animator.TrySetMovementAnimation("JUMP");
- }
+ float p = direc.X * CollisionPlane.X + direc.Y * CollisionPlane.Y;
+ direc.X -= p * CollisionPlane.X;
+ direc.Y -= p * CollisionPlane.Y;
+ direc.Z -= p * c;
}
+ */
}
-// m_log.DebugFormat("[SCENE PRESENCE]: Setting force to apply to {0} for {1}", direc, Name);
+ // m_log.DebugFormat("[SCENE PRESENCE]: Setting force to apply to {0} for {1}", direc, Name);
- // TODO: Add the force instead of only setting it to support multiple forces per frame?
m_forceToApply = direc;
Animator.UpdateMovementAnimations();
}
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs
index daf6c7c..4a98df4 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs
@@ -79,6 +79,7 @@ namespace OpenSim.Region.Physics.OdePlugin
private Vector3 _acceleration;
private Vector3 m_rotationalVelocity;
private Vector3 m_size;
+ private Vector3 m_collideNormal;
private Quaternion m_orientation;
private Quaternion m_orientation2D;
private float m_mass = 80f;
@@ -109,6 +110,7 @@ namespace OpenSim.Region.Physics.OdePlugin
private bool _zeroFlag = false;
+
private uint m_localID = 0;
public bool m_returnCollisions = false;
// taints and their non-tainted counterparts
@@ -153,9 +155,7 @@ namespace OpenSim.Region.Physics.OdePlugin
public UUID m_uuid;
public bool bad = false;
- float mu;
-
-
+ float mu;
public OdeCharacter(uint localID, String avName, OdeScene parent_scene, Vector3 pos, Vector3 pSize, float pfeetOffset, float density, float walk_divisor, float rundivisor)
{
@@ -864,11 +864,12 @@ namespace OpenSim.Region.Physics.OdePlugin
x = tx * cos - y * sin;
y = tx * sin + y * cos;
}
-
-
- public bool Collide(IntPtr me,IntPtr other, bool reverse, ref d.ContactGeom contact, ref bool feetcollision)
+
+ public bool Collide(IntPtr me, IntPtr other, bool reverse, ref d.ContactGeom contact,
+ ref d.ContactGeom altContact , ref bool useAltcontact, ref bool feetcollision)
{
feetcollision = false;
+ useAltcontact = false;
if (me == capsule)
{
@@ -899,31 +900,77 @@ namespace OpenSim.Region.Physics.OdePlugin
{
feetcollision = true;
if (h < boneOff)
+ {
+ m_collideNormal.X = contact.normal.X;
+ m_collideNormal.Y = contact.normal.Y;
+ m_collideNormal.Z = contact.normal.Z;
IsColliding = true;
+ }
}
return true;
- }
+ }
+
+ d.AABB aabb;
+ d.GeomGetAABB(other,out aabb);
+ float othertop = aabb.MaxZ - _position.Z;
+
+ if (offset.Z > 0 || othertop > -feetOff || contact.normal.Z > 0.35f)
+ {
+ if (offset.Z <= 0)
+ {
+ feetcollision = true;
+ if (h < boneOff)
+ {
+ m_collideNormal.X = contact.normal.X;
+ m_collideNormal.Y = contact.normal.Y;
+ m_collideNormal.Z = contact.normal.Z;
+ IsColliding = true;
+ }
+ }
- if (offset.Z > 0)
+ if (contact.normal.Z < 0.2f)
+ {
+ contact.normal.Z = 0;
+ float t = contact.normal.X * contact.normal.X + contact.normal.Y * contact.normal.Y;
+ if (t > 0)
+ {
+ t = 1.0f / t;
+ contact.normal.X *= t;
+ contact.normal.Y *= t;
+ }
+ }
return true;
+ }
+
+ altContact = contact;
+ useAltcontact = true;
offset.Normalize();
+ if (contact.depth > 0.1f)
+ contact.depth = 0.1f;
+
if (reverse)
{
- contact.normal.X = offset.X;
- contact.normal.Y = offset.Y;
- contact.normal.Z = offset.Z;
+ altContact.normal.X = offset.X;
+ altContact.normal.Y = offset.Y;
+ altContact.normal.Z = offset.Z;
}
else
{
- contact.normal.X = -offset.X;
- contact.normal.Y = -offset.Y;
- contact.normal.Z = -offset.Z;
+ altContact.normal.X = -offset.X;
+ altContact.normal.Y = -offset.Y;
+ altContact.normal.Z = -offset.Z;
}
+
feetcollision = true;
if (h < boneOff)
+ {
+ m_collideNormal.X = contact.normal.X;
+ m_collideNormal.Y = contact.normal.Y;
+ m_collideNormal.Z = contact.normal.Z;
IsColliding = true;
+ }
return true;
}
return false;
@@ -1003,6 +1050,9 @@ namespace OpenSim.Region.Physics.OdePlugin
Vector3 vel = new Vector3(dtmp.X, dtmp.Y, dtmp.Z);
float velLengthSquared = vel.LengthSquared();
+
+ Vector3 ctz = _target_velocity;
+
float movementdivisor = 1f;
//Ubit change divisions into multiplications below
if (!m_alwaysRun)
@@ -1010,13 +1060,16 @@ namespace OpenSim.Region.Physics.OdePlugin
else
movementdivisor = 1 / runDivisor;
+ ctz.X *= movementdivisor;
+ ctz.Y *= movementdivisor;
+
//******************************************
// colide with land
d.AABB aabb;
// d.GeomGetAABB(feetbox, out aabb);
d.GeomGetAABB(capsule, out aabb);
- float chrminZ = aabb.MinZ; ; // move up a bit
+ float chrminZ = aabb.MinZ; // move up a bit
Vector3 posch = localpos;
float ftmp;
@@ -1031,15 +1084,18 @@ namespace OpenSim.Region.Physics.OdePlugin
float terrainheight = _parent_scene.GetTerrainHeightAtXY(posch.X, posch.Y);
if (chrminZ < terrainheight)
{
+ if (ctz.Z < 0)
+ ctz.Z = 0;
+
+ Vector3 n = _parent_scene.GetTerrainNormalAtXY(posch.X, posch.Y);
float depth = terrainheight - chrminZ;
+
+ vec.Z = depth * PID_P * 50;
+
if (!flying)
- {
- vec.Z = -vel.Z * PID_D * 1.5f + depth * PID_P * 50;
- }
- else
- vec.Z = depth * PID_P * 50;
+ vec.Z += -vel.Z * PID_D;
- if (depth < 0.1f)
+ if (depth < 0.2f)
{
m_colliderGroundfilter++;
if (m_colliderGroundfilter > 2)
@@ -1053,50 +1109,83 @@ namespace OpenSim.Region.Physics.OdePlugin
m_freemove = false;
}
+ m_collideNormal.X = n.X;
+ m_collideNormal.Y = n.Y;
+ m_collideNormal.Z = n.Z;
+
m_iscollidingGround = true;
+
ContactPoint contact = new ContactPoint();
contact.PenetrationDepth = depth;
contact.Position.X = localpos.X;
contact.Position.Y = localpos.Y;
contact.Position.Z = terrainheight;
- contact.SurfaceNormal.X = 0.0f;
- contact.SurfaceNormal.Y = 0.0f;
- contact.SurfaceNormal.Z = -1f;
+ contact.SurfaceNormal.X = -n.X;
+ contact.SurfaceNormal.Y = -n.Y;
+ contact.SurfaceNormal.Z = -n.Z;
contact.RelativeSpeed = -vel.Z;
contact.CharacterFeet = true;
AddCollisionEvent(0, contact);
- vec.Z *= 0.5f;
+// vec.Z *= 0.5f;
}
}
else
{
- m_colliderGroundfilter = 0;
- m_iscollidingGround = false;
+ m_colliderGroundfilter -= 5;
+ if (m_colliderGroundfilter <= 0)
+ {
+ m_colliderGroundfilter = 0;
+ m_iscollidingGround = false;
+ }
}
}
else
{
- m_colliderGroundfilter = 0;
- m_iscollidingGround = false;
+ m_colliderGroundfilter -= 5;
+ if (m_colliderGroundfilter <= 0)
+ {
+ m_colliderGroundfilter = 0;
+ m_iscollidingGround = false;
+ }
}
//******************************************
+ if (!m_iscolliding)
+ m_collideNormal.Z = 0;
+
+ bool tviszero = (ctz.X == 0.0f && ctz.Y == 0.0f && ctz.Z == 0.0f);
+
- bool tviszero = (_target_velocity.X == 0.0f && _target_velocity.Y == 0.0f && _target_velocity.Z == 0.0f);
- // if (!tviszero || m_iscolliding || velLengthSquared <0.01)
if (!tviszero)
+ {
m_freemove = false;
+ // movement relative to surface if moving on it
+ // dont disturbe vertical movement, ie jumps
+ if (m_iscolliding && !flying && ctz.Z == 0 && m_collideNormal.Z > 0.2f && m_collideNormal.Z < 0.94f)
+ {
+ float p = ctz.X * m_collideNormal.X + ctz.Y * m_collideNormal.Y;
+ ctz.X *= (float)Math.Sqrt(1 - m_collideNormal.X * m_collideNormal.X);
+ ctz.Y *= (float)Math.Sqrt(1 - m_collideNormal.Y * m_collideNormal.Y);
+ ctz.Z -= p;
+ if (ctz.Z < 0)
+ ctz.Z *= 2;
+
+ }
+
+ }
+
+
if (!m_freemove)
{
// if velocity is zero, use position control; otherwise, velocity control
- if (tviszero && m_iscolliding)
+ if (tviszero && m_iscolliding && !flying)
{
// keep track of where we stopped. No more slippin' & slidin'
if (!_zeroFlag)
@@ -1129,22 +1218,48 @@ namespace OpenSim.Region.Physics.OdePlugin
{
if (!flying)
{
- if (_target_velocity.Z > 0.0f)
+ // we are on a surface
+ if (ctz.Z > 0f)
{
- // We're colliding with something and we're not flying but we're moving
- // This means we're walking or running. JUMPING
- vec.Z += (_target_velocity.Z - vel.Z) * PID_D * 1.2f;// +(_zeroPosition.Z - localpos.Z) * PID_P;
+ // moving up or JUMPING
+ vec.Z += (ctz.Z - vel.Z) * PID_D * 1.2f;// +(_zeroPosition.Z - localpos.Z) * PID_P;
+ vec.X += (ctz.X - vel.X) * (PID_D);
+ vec.Y += (ctz.Y - vel.Y) * (PID_D);
}
+ else
+ {
+ // we are moving down on a surface
+ if (ctz.Z == 0)
+ {
+ if (vel.Z > 0)
+ vec.Z -= vel.Z * PID_D * 2.0f;
+ vec.X += (ctz.X - vel.X) * (PID_D);
+ vec.Y += (ctz.Y - vel.Y) * (PID_D);
+ }
+ // intencionally going down
+ else
+ {
+ if (ctz.Z < vel.Z)
+ vec.Z += (ctz.Z - vel.Z) * PID_D * 2.0f;
+ else
+ {
+ }
+
+ if (Math.Abs(ctz.X) > Math.Abs(vel.X))
+ vec.X += (ctz.X - vel.X) * (PID_D);
+ if (Math.Abs(ctz.Y) > Math.Abs(vel.Y))
+ vec.Y += (ctz.Y - vel.Y) * (PID_D);
+ }
+ }
+
// We're standing on something
- vec.X = ((_target_velocity.X * movementdivisor) - vel.X) * (PID_D);
- vec.Y = ((_target_velocity.Y * movementdivisor) - vel.Y) * (PID_D);
}
else
{
// We're flying and colliding with something
- vec.X = ((_target_velocity.X * movementdivisor) - vel.X) * (PID_D * 0.0625f);
- vec.Y = ((_target_velocity.Y * movementdivisor) - vel.Y) * (PID_D * 0.0625f);
- vec.Z += (_target_velocity.Z - vel.Z) * (PID_D);
+ vec.X += (ctz.X - vel.X) * (PID_D * 0.0625f);
+ vec.Y += (ctz.Y - vel.Y) * (PID_D * 0.0625f);
+ vec.Z += (ctz.Z - vel.Z) * (PID_D);
}
}
else // ie not colliding
@@ -1152,9 +1267,9 @@ namespace OpenSim.Region.Physics.OdePlugin
if (flying) //(!m_iscolliding && flying)
{
// we're in mid air suspended
- vec.X = ((_target_velocity.X * movementdivisor) - vel.X) * (PID_D * 1.667f);
- vec.Y = ((_target_velocity.Y * movementdivisor) - vel.Y) * (PID_D * 1.667f);
- vec.Z += (_target_velocity.Z - vel.Z) * (PID_D);
+ vec.X += (ctz.X - vel.X) * (PID_D * 1.667f);
+ vec.Y += (ctz.Y - vel.Y) * (PID_D * 1.667f);
+ vec.Z += (ctz.Z - vel.Z) * (PID_D);
}
else
@@ -1163,8 +1278,11 @@ namespace OpenSim.Region.Physics.OdePlugin
// m_iscolliding includes collisions with the ground.
// d.Vector3 pos = d.BodyGetPosition(Body);
- vec.X = (_target_velocity.X - vel.X) * PID_D * 0.833f;
- vec.Y = (_target_velocity.Y - vel.Y) * PID_D * 0.833f;
+ vec.X += (ctz.X - vel.X) * PID_D * 0.833f;
+ vec.Y += (ctz.Y - vel.Y) * PID_D * 0.833f;
+ // hack for breaking on fall
+ if (ctz.Z == -9999f)
+ vec.Z += -vel.Z * PID_D - _parent_scene.gravityz * m_mass;
}
}
}
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs
index 9bf2abe..2adbe01 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs
@@ -935,18 +935,22 @@ namespace OpenSim.Region.Physics.OdePlugin
SharedTmpcontact.surface.mu = mu;
SharedTmpcontact.surface.bounce = bounce;
+ d.ContactGeom altContact = new d.ContactGeom();
+ bool useAltcontact = false;
+ bool noskip = true;
+
while (true)
{
// if (!(IgnoreNegSides && curContact.side1 < 0))
{
- bool noskip = true;
+ noskip = true;
+ useAltcontact = false;
+
if (dop1ava)
{
- if (!(((OdeCharacter)p1).Collide(g1, g2, false, ref curContact, ref FeetCollision)))
- noskip = false;
- else
+ if ((((OdeCharacter)p1).Collide(g1, g2, false, ref curContact, ref altContact , ref useAltcontact, ref FeetCollision)))
{
- if(p2.PhysicsActorType == (int)ActorTypes.Agent)
+ if (p2.PhysicsActorType == (int)ActorTypes.Agent)
{
p1.CollidingObj = true;
p2.CollidingObj = true;
@@ -954,18 +958,32 @@ namespace OpenSim.Region.Physics.OdePlugin
else if (p2.Velocity.LengthSquared() > 0.0f)
p2.CollidingObj = true;
}
+ else
+ noskip = false;
}
else if (dop2ava)
{
- if (!(((OdeCharacter)p2).Collide(g2,g1, true, ref curContact, ref FeetCollision)))
+ if ((((OdeCharacter)p2).Collide(g2, g1, true, ref curContact, ref altContact , ref useAltcontact, ref FeetCollision)))
+ {
+ if (p1.PhysicsActorType == (int)ActorTypes.Agent)
+ {
+ p1.CollidingObj = true;
+ p2.CollidingObj = true;
+ }
+ else if (p2.Velocity.LengthSquared() > 0.0f)
+ p1.CollidingObj = true;
+ }
+ else
noskip = false;
- else if (p1.Velocity.LengthSquared() > 0.0f)
- p1.CollidingObj = true;
}
if (noskip)
{
- Joint = CreateContacJoint(ref curContact);
+ if(useAltcontact)
+ Joint = CreateContacJoint(ref altContact);
+ else
+ Joint = CreateContacJoint(ref curContact);
+
if (Joint == IntPtr.Zero)
break;
@@ -1924,12 +1942,12 @@ namespace OpenSim.Region.Physics.OdePlugin
dy = 0;
}
}
-
else
{
// we still have square fixed size regions
// also flip x and y because of how map is done for ODE fliped axis
// so ix,iy,dx and dy are inter exchanged
+
if (x < regsize - 1)
{
iy = (int)x;
@@ -1976,7 +1994,7 @@ namespace OpenSim.Region.Physics.OdePlugin
*/
h0 = ((float)heights[iy]); // 0,0 vertice
- if ((dy > dx))
+ if (dy>dx)
{
iy += regsize;
h2 = (float)heights[iy]; // 0,1 vertice
@@ -1994,6 +2012,133 @@ namespace OpenSim.Region.Physics.OdePlugin
return h0 + h1 + h2;
}
+ public Vector3 GetTerrainNormalAtXY(float x, float y)
+ {
+ int offsetX = ((int)(x / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
+ int offsetY = ((int)(y / (int)Constants.RegionSize)) * (int)Constants.RegionSize;
+
+ IntPtr heightFieldGeom = IntPtr.Zero;
+ Vector3 norm = new Vector3(0, 0, 1);
+
+ // get region map
+ if (!RegionTerrain.TryGetValue(new Vector3(offsetX, offsetY, 0), out heightFieldGeom))
+ return norm;
+
+ if (heightFieldGeom == IntPtr.Zero)
+ return norm;
+
+ if (!TerrainHeightFieldHeights.ContainsKey(heightFieldGeom))
+ return norm;
+
+ // TerrainHeightField for ODE as offset 1m
+ x += 1f - offsetX;
+ y += 1f - offsetY;
+
+ // make position fit into array
+ if (x < 0)
+ x = 0;
+ if (y < 0)
+ y = 0;
+
+ // integer indexs
+ int ix;
+ int iy;
+ // interpolators offset
+ float dx;
+ float dy;
+
+
+ int regsize = (int)Constants.RegionSize + 3; // map size see setterrain number of samples
+ int xstep = 1;
+ int ystep = regsize;
+ bool firstTri = false;
+
+ if (OdeUbitLib)
+ {
+ if (x < regsize - 1)
+ {
+ ix = (int)x;
+ dx = x - (float)ix;
+ }
+ else // out world use external height
+ {
+ ix = regsize - 2;
+ dx = 0;
+ }
+ if (y < regsize - 1)
+ {
+ iy = (int)y;
+ dy = y - (float)iy;
+ }
+ else
+ {
+ iy = regsize - 2;
+ dy = 0;
+ }
+ firstTri = dy > dx;
+ }
+
+ else
+ {
+ xstep = regsize;
+ ystep = 1;
+ // we still have square fixed size regions
+ // also flip x and y because of how map is done for ODE fliped axis
+ // so ix,iy,dx and dy are inter exchanged
+ if (x < regsize - 1)
+ {
+ iy = (int)x;
+ dy = x - (float)iy;
+ }
+ else // out world use external height
+ {
+ iy = regsize - 2;
+ dy = 0;
+ }
+ if (y < regsize - 1)
+ {
+ ix = (int)y;
+ dx = y - (float)ix;
+ }
+ else
+ {
+ ix = regsize - 2;
+ dx = 0;
+ }
+ firstTri = dx > dy;
+ }
+
+ float h0;
+ float h1;
+ float h2;
+
+ iy *= regsize;
+ iy += ix; // all indexes have iy + ix
+
+ float[] heights = TerrainHeightFieldHeights[heightFieldGeom];
+
+ if (firstTri)
+ {
+ h1 = ((float)heights[iy]); // 0,0 vertice
+ iy += ystep;
+ h0 = (float)heights[iy]; // 0,1
+ h2 = (float)heights[iy+xstep]; // 1,1 vertice
+ norm.X = h0 - h2;
+ norm.Y = h1 - h0;
+ }
+ else
+ {
+ h2 = ((float)heights[iy]); // 0,0 vertice
+ iy += xstep;
+ h0 = ((float)heights[iy]); // 1,0 vertice
+ h1 = (float)heights[iy+ystep]; // vertice 1,1
+ norm.X = h2 - h0;
+ norm.Y = h0 - h1;
+ }
+ norm.Z = 1;
+ norm.Normalize();
+ return norm;
+ }
public override void SetTerrain(float[] heightMap)
{
--
cgit v1.1