aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics
diff options
context:
space:
mode:
authorMelanie2012-04-23 21:13:08 +0100
committerMelanie2012-04-23 21:13:08 +0100
commit159b3b27ca734ab523c47d2ab65397595b1c0a8e (patch)
tree8038d76c48e48b000e7f96eeade3d335db68daaa /OpenSim/Region/Physics
parentMerge branch 'master' into careminster (diff)
parentubitODE - do own timing control (as chODE does) until heartbeat does it right (diff)
downloadopensim-SC-159b3b27ca734ab523c47d2ab65397595b1c0a8e.zip
opensim-SC-159b3b27ca734ab523c47d2ab65397595b1c0a8e.tar.gz
opensim-SC-159b3b27ca734ab523c47d2ab65397595b1c0a8e.tar.bz2
opensim-SC-159b3b27ca734ab523c47d2ab65397595b1c0a8e.tar.xz
Merge branch 'master' of ssh://melanie@3dhosting.de/var/git/careminster into careminster
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs23
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs746
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs215
3 files changed, 508 insertions, 476 deletions
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs
index ec4be58..6ffcb9e 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs
@@ -686,6 +686,9 @@ namespace OpenSim.Region.Physics.OdePlugin
686 686
687 Body = d.BodyCreate(_parent_scene.world); 687 Body = d.BodyCreate(_parent_scene.world);
688 688
689 _zeroFlag = false;
690 m_pidControllerActive = true;
691
689 d.BodySetAutoDisableFlag(Body, false); 692 d.BodySetAutoDisableFlag(Body, false);
690 d.BodySetPosition(Body, npositionX, npositionY, npositionZ); 693 d.BodySetPosition(Body, npositionX, npositionY, npositionZ);
691 694
@@ -862,12 +865,12 @@ namespace OpenSim.Region.Physics.OdePlugin
862 float depth = terrainheight - chrminZ; 865 float depth = terrainheight - chrminZ;
863 if (!flying) 866 if (!flying)
864 { 867 {
865 vec.Z = -vel.Z * PID_D * 1.5f + depth * PID_P * 60; 868 vec.Z = -vel.Z * PID_D * 1.5f + depth * PID_P * 50;
866 } 869 }
867 else 870 else
868 vec.Z = depth * PID_P * 60; 871 vec.Z = depth * PID_P * 50;
869 872
870 if (depth < 0.2f) 873 if (depth < 0.1f)
871 { 874 {
872 m_iscolliding = true; 875 m_iscolliding = true;
873 m_colliderfilter = 2; 876 m_colliderfilter = 2;
@@ -1009,9 +1012,17 @@ namespace OpenSim.Region.Physics.OdePlugin
1009 1012
1010 // update our local ideia of position velocity and aceleration 1013 // update our local ideia of position velocity and aceleration
1011 _position = localpos; 1014 _position = localpos;
1012 _acceleration = _velocity; // previus velocity 1015 if (_zeroFlag)
1013 _velocity = vel; 1016 {
1014 _acceleration = (vel - _acceleration) / timeStep; 1017 _velocity = Vector3.Zero;
1018 _acceleration = Vector3.Zero;
1019 }
1020 else
1021 {
1022 _acceleration = _velocity; // previus velocity
1023 _velocity = vel;
1024 _acceleration = (vel - _acceleration) / timeStep;
1025 }
1015 1026
1016 } 1027 }
1017 1028
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
index 5467b9f..dc6c18d 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
@@ -68,9 +68,17 @@ namespace OpenSim.Region.Physics.OdePlugin
68 private bool m_fakeisphysical; 68 private bool m_fakeisphysical;
69 private bool m_isphantom; 69 private bool m_isphantom;
70 private bool m_fakeisphantom; 70 private bool m_fakeisphantom;
71 internal bool m_isVolumeDetect; // If true, this prim only detects collisions but doesn't collide actively
72 private bool m_fakeisVolumeDetect; // If true, this prim only detects collisions but doesn't collide actively
71 73
72 protected bool m_building; 74 protected bool m_building;
73 protected bool m_forcePosOrRotation; 75 protected bool m_forcePosOrRotation;
76 private bool m_iscolliding;
77
78 internal bool m_isSelected;
79 private bool m_delaySelect;
80 private bool m_lastdoneSelected;
81 internal bool m_outbounds;
74 82
75 private Quaternion m_lastorientation = new Quaternion(); 83 private Quaternion m_lastorientation = new Quaternion();
76 private Quaternion _orientation; 84 private Quaternion _orientation;
@@ -90,10 +98,12 @@ namespace OpenSim.Region.Physics.OdePlugin
90 private Vector3 m_forceacc; 98 private Vector3 m_forceacc;
91 private Vector3 m_angularForceacc; 99 private Vector3 m_angularForceacc;
92 100
101 private float m_invTimeStep = 50.0f;
102 private float m_timeStep = .02f;
103
104
93 private Vector3 m_PIDTarget; 105 private Vector3 m_PIDTarget;
94 private float m_PIDTau; 106 private float m_PIDTau;
95 private float PID_D = 35f;
96 private float PID_G = 25f;
97 private bool m_usePID; 107 private bool m_usePID;
98 108
99 // KF: These next 7 params apply to llSetHoverHeight(float height, integer water, float tau), 109 // KF: These next 7 params apply to llSetHoverHeight(float height, integer water, float tau),
@@ -153,14 +163,6 @@ namespace OpenSim.Region.Physics.OdePlugin
153 163
154 private List<OdePrim> childrenPrim = new List<OdePrim>(); 164 private List<OdePrim> childrenPrim = new List<OdePrim>();
155 165
156 private bool m_iscolliding;
157
158 public bool m_isSelected;
159 private bool m_delaySelect;
160 private bool m_lastdoneSelected;
161 public bool m_outbounds;
162
163 internal bool m_isVolumeDetect; // If true, this prim only detects collisions but doesn't collide actively
164 166
165 private bool m_throttleUpdates; 167 private bool m_throttleUpdates;
166 private int throttleCounter; 168 private int throttleCounter;
@@ -223,9 +225,12 @@ namespace OpenSim.Region.Physics.OdePlugin
223 225
224 public override bool IsVolumeDtc 226 public override bool IsVolumeDtc
225 { 227 {
226 set { return; } 228 get { return m_fakeisVolumeDetect; }
227 get { return m_isVolumeDetect; } 229 set
228 230 {
231 m_fakeisVolumeDetect = value;
232 AddChange(changes.VolumeDtc, value);
233 }
229 } 234 }
230 235
231 236
@@ -234,10 +239,7 @@ namespace OpenSim.Region.Physics.OdePlugin
234 get { return m_fakeisphantom; } 239 get { return m_fakeisphantom; }
235 set 240 set
236 { 241 {
237 m_fakeisphantom = value; // we show imediatly to outside that we changed physical 242 m_fakeisphantom = value;
238 // and also to stop imediatly some updates
239 // but real change will only happen in taintprocessing
240
241 AddChange(changes.Phantom, value); 243 AddChange(changes.Phantom, value);
242 } 244 }
243 } 245 }
@@ -427,7 +429,8 @@ namespace OpenSim.Region.Physics.OdePlugin
427 429
428 public override void SetVolumeDetect(int param) 430 public override void SetVolumeDetect(int param)
429 { 431 {
430 AddChange(changes.VolumeDtc, (param != 0)); 432 m_fakeisVolumeDetect = (param != 0);
433 AddChange(changes.VolumeDtc, m_fakeisVolumeDetect);
431 } 434 }
432 435
433 public override Vector3 GeometricCenter 436 public override Vector3 GeometricCenter
@@ -631,7 +634,6 @@ namespace OpenSim.Region.Physics.OdePlugin
631 Vector3 pv = Vector3.Zero; 634 Vector3 pv = Vector3.Zero;
632 if (_zeroFlag) 635 if (_zeroFlag)
633 return pv; 636 return pv;
634 m_lastUpdateSent = false;
635 637
636 if (m_rotationalVelocity.ApproxEquals(pv, 0.0001f)) 638 if (m_rotationalVelocity.ApproxEquals(pv, 0.0001f))
637 return pv; 639 return pv;
@@ -685,12 +687,50 @@ namespace OpenSim.Region.Physics.OdePlugin
685 } 687 }
686 688
687 public override bool PIDActive { set { m_usePID = value; } } 689 public override bool PIDActive { set { m_usePID = value; } }
688 public override float PIDTau { set { m_PIDTau = value; } } 690 public override float PIDTau
691 {
692 set
693 {
694 if (value <= 0)
695 m_PIDTau = 0;
696 else
697 {
698 float mint = (0.05f > m_timeStep ? 0.05f : m_timeStep);
699 if (value < mint)
700 m_PIDTau = mint;
701 else
702 m_PIDTau = value;
703 }
704 }
705 }
689 706
690 public override float PIDHoverHeight { set { m_PIDHoverHeight = value; ; } } 707 public override float PIDHoverHeight
708 {
709 set
710 {
711 m_PIDHoverHeight = value;
712 if (value == 0)
713 m_useHoverPID = false;
714 }
715 }
691 public override bool PIDHoverActive { set { m_useHoverPID = value; } } 716 public override bool PIDHoverActive { set { m_useHoverPID = value; } }
692 public override PIDHoverType PIDHoverType { set { m_PIDHoverType = value; } } 717 public override PIDHoverType PIDHoverType { set { m_PIDHoverType = value; } }
693 public override float PIDHoverTau { set { m_PIDHoverTau = value; } } 718 public override float PIDHoverTau
719 {
720 set
721 {
722 if (value <= 0)
723 m_PIDHoverTau = 0;
724 else
725 {
726 float mint = (0.05f > m_timeStep ? 0.05f : m_timeStep);
727 if (value < mint)
728 m_PIDHoverTau = mint;
729 else
730 m_PIDHoverTau = value;
731 }
732 }
733 }
694 734
695 public override Quaternion APIDTarget { set { return; } } 735 public override Quaternion APIDTarget { set { return; } }
696 736
@@ -761,7 +801,7 @@ namespace OpenSim.Region.Physics.OdePlugin
761 { 801 {
762 if (force.IsFinite()) 802 if (force.IsFinite())
763 { 803 {
764 AddChange(changes.AddForce, force / _parent_scene.ODE_STEPSIZE); 804 AddChange(changes.AddForce, force * m_invTimeStep);
765 } 805 }
766 else 806 else
767 { 807 {
@@ -774,7 +814,7 @@ namespace OpenSim.Region.Physics.OdePlugin
774 { 814 {
775 if (force.IsFinite()) 815 if (force.IsFinite())
776 { 816 {
777 AddChange(changes.AddAngForce, force / _parent_scene.ODE_STEPSIZE); 817 AddChange(changes.AddAngForce, force * m_invTimeStep);
778 } 818 }
779 else 819 else
780 { 820 {
@@ -911,8 +951,9 @@ namespace OpenSim.Region.Physics.OdePlugin
911 _position = pos; 951 _position = pos;
912 givefakepos = 0; 952 givefakepos = 0;
913 953
914 PID_D = parent_scene.bodyPIDD; 954 m_timeStep = parent_scene.ODE_STEPSIZE;
915 PID_G = parent_scene.bodyPIDG; 955 m_invTimeStep = 1f / m_timeStep;
956
916 m_density = parent_scene.geomDefaultDensity; 957 m_density = parent_scene.geomDefaultDensity;
917 // m_tensor = parent_scene.bodyMotorJointMaxforceTensor; 958 // m_tensor = parent_scene.bodyMotorJointMaxforceTensor;
918 body_autodisable_frames = parent_scene.bodyFramesAutoDisable; 959 body_autodisable_frames = parent_scene.bodyFramesAutoDisable;
@@ -958,6 +999,7 @@ namespace OpenSim.Region.Physics.OdePlugin
958 m_fakeisphysical = m_isphysical; 999 m_fakeisphysical = m_isphysical;
959 1000
960 m_isVolumeDetect = false; 1001 m_isVolumeDetect = false;
1002 m_fakeisVolumeDetect = false;
961 1003
962 m_force = Vector3.Zero; 1004 m_force = Vector3.Zero;
963 1005
@@ -1066,7 +1108,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1066 prm.m_collisionCategories = CollisionCategories.Selected; 1108 prm.m_collisionCategories = CollisionCategories.Selected;
1067 prm.m_collisionFlags = 0; 1109 prm.m_collisionFlags = 0;
1068 } 1110 }
1069 else if (prm.IsVolumeDtc) 1111 else if (prm.m_isVolumeDetect)
1070 { 1112 {
1071 prm.m_collisionCategories = CollisionCategories.VolumeDtc; 1113 prm.m_collisionCategories = CollisionCategories.VolumeDtc;
1072 if (m_isphysical) 1114 if (m_isphysical)
@@ -1445,14 +1487,14 @@ namespace OpenSim.Region.Physics.OdePlugin
1445 hasOOBoffsetFromMesh = false; 1487 hasOOBoffsetFromMesh = false;
1446 CalcPrimBodyData(); 1488 CalcPrimBodyData();
1447 } 1489 }
1448 1490/*
1449 private void ChildSetGeom(OdePrim odePrim) 1491 private void ChildSetGeom(OdePrim odePrim)
1450 { 1492 {
1451 // well.. 1493 // well..
1452 DestroyBody(); 1494 DestroyBody();
1453 MakeBody(); 1495 MakeBody();
1454 } 1496 }
1455 1497*/
1456 //sets non physical prim m_targetSpace to right space in spaces grid for static prims 1498 //sets non physical prim m_targetSpace to right space in spaces grid for static prims
1457 // should only be called for non physical prims unless they are becoming non physical 1499 // should only be called for non physical prims unless they are becoming non physical
1458 private void SetInStaticSpace(OdePrim prim) 1500 private void SetInStaticSpace(OdePrim prim)
@@ -2650,6 +2692,31 @@ namespace OpenSim.Region.Physics.OdePlugin
2650 ApplyCollisionCatFlags(); 2692 ApplyCollisionCatFlags();
2651 } 2693 }
2652 2694
2695/* not in use
2696 internal void ChildSelectedChange(bool childSelect)
2697 {
2698 if(childPrim)
2699 return;
2700
2701 if (childSelect == m_isSelected)
2702 return;
2703
2704 if (childSelect)
2705 {
2706 DoSelectedStatus(true);
2707 }
2708
2709 else
2710 {
2711 foreach (OdePrim prm in childrenPrim)
2712 {
2713 if (prm.m_isSelected)
2714 return;
2715 }
2716 DoSelectedStatus(false);
2717 }
2718 }
2719*/
2653 private void changeSelectedStatus(bool newval) 2720 private void changeSelectedStatus(bool newval)
2654 { 2721 {
2655 if (m_lastdoneSelected == newval) 2722 if (m_lastdoneSelected == newval)
@@ -2706,6 +2773,9 @@ namespace OpenSim.Region.Physics.OdePlugin
2706 prm.m_delaySelect = false; 2773 prm.m_delaySelect = false;
2707 } 2774 }
2708 } 2775 }
2776// else if (_parent != null)
2777// ((OdePrim)_parent).ChildSelectedChange(true);
2778
2709 2779
2710 if (prim_geom != null) 2780 if (prim_geom != null)
2711 { 2781 {
@@ -2741,8 +2811,13 @@ namespace OpenSim.Region.Physics.OdePlugin
2741 } 2811 }
2742 else 2812 else
2743 { 2813 {
2744 if (!childPrim && Body != IntPtr.Zero && !m_disabled) 2814 if (!childPrim)
2745 d.BodyEnable(Body); 2815 {
2816 if (Body != IntPtr.Zero && !m_disabled)
2817 d.BodyEnable(Body);
2818 }
2819// else if (_parent != null)
2820// ((OdePrim)_parent).ChildSelectedChange(false);
2746 2821
2747 UpdateCollisionCatFlags(); 2822 UpdateCollisionCatFlags();
2748 ApplyCollisionCatFlags(); 2823 ApplyCollisionCatFlags();
@@ -2929,7 +3004,6 @@ namespace OpenSim.Region.Physics.OdePlugin
2929 givefakeori--; 3004 givefakeori--;
2930 if (givefakeori < 0) 3005 if (givefakeori < 0)
2931 givefakeori = 0; 3006 givefakeori = 0;
2932
2933 resetCollisionAccounting(); 3007 resetCollisionAccounting();
2934 } 3008 }
2935 3009
@@ -3084,9 +3158,10 @@ namespace OpenSim.Region.Physics.OdePlugin
3084 d.BodyEnable(Body); 3158 d.BodyEnable(Body);
3085 } 3159 }
3086 3160
3087 private void changeAddForce(Vector3 force) 3161
3162 private void changeAddImpulse(Vector3 impulse)
3088 { 3163 {
3089 m_forceacc += force; 3164 m_forceacc += impulse * m_invTimeStep;
3090 if (!m_isSelected) 3165 if (!m_isSelected)
3091 { 3166 {
3092 lock (this) 3167 lock (this)
@@ -3105,9 +3180,10 @@ namespace OpenSim.Region.Physics.OdePlugin
3105 } 3180 }
3106 } 3181 }
3107 3182
3108 private void changeAddAngularForce(Vector3 aforce) 3183 // actually angular impulse
3184 private void changeAddAngularImpulse(Vector3 aimpulse)
3109 { 3185 {
3110 m_angularForceacc += aforce; 3186 m_angularForceacc += aimpulse * m_invTimeStep;
3111 if (!m_isSelected) 3187 if (!m_isSelected)
3112 { 3188 {
3113 lock (this) 3189 lock (this)
@@ -3145,6 +3221,7 @@ namespace OpenSim.Region.Physics.OdePlugin
3145 private void changeVolumedetetion(bool newVolDtc) 3221 private void changeVolumedetetion(bool newVolDtc)
3146 { 3222 {
3147 m_isVolumeDetect = newVolDtc; 3223 m_isVolumeDetect = newVolDtc;
3224 m_fakeisVolumeDetect = newVolDtc;
3148 UpdateCollisionCatFlags(); 3225 UpdateCollisionCatFlags();
3149 ApplyCollisionCatFlags(); 3226 ApplyCollisionCatFlags();
3150 } 3227 }
@@ -3229,326 +3306,246 @@ namespace OpenSim.Region.Physics.OdePlugin
3229 if (!childPrim && m_isphysical && Body != IntPtr.Zero && 3306 if (!childPrim && m_isphysical && Body != IntPtr.Zero &&
3230 !m_disabled && !m_isSelected && !m_building && !m_outbounds) 3307 !m_disabled && !m_isSelected && !m_building && !m_outbounds)
3231 { 3308 {
3232 if (d.BodyIsEnabled(Body)) 3309 if (!d.BodyIsEnabled(Body))
3233 { 3310 {
3234 float timestep = _parent_scene.ODE_STEPSIZE; 3311 // let vehicles sleep
3235 3312 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
3236 // check outside region
3237 d.Vector3 lpos = d.GeomGetPosition(prim_geom); // root position that is seem by rest of simulator
3238
3239 if (lpos.Z < -100 || lpos.Z > 100000f)
3240 {
3241 m_outbounds = true;
3242
3243 lpos.Z = Util.Clip(lpos.Z, -100f, 100000f);
3244 _acceleration.X = 0;
3245 _acceleration.Y = 0;
3246 _acceleration.Z = 0;
3247
3248 _velocity.X = 0;
3249 _velocity.Y = 0;
3250 _velocity.Z = 0;
3251 m_rotationalVelocity.X = 0;
3252 m_rotationalVelocity.Y = 0;
3253 m_rotationalVelocity.Z = 0;
3254
3255 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
3256 d.BodySetAngularVel(Body, 0, 0, 0); // stop it
3257 d.BodySetPosition(Body, lpos.X, lpos.Y, lpos.Z); // put it somewhere
3258 m_lastposition = _position;
3259 m_lastorientation = _orientation;
3260
3261 base.RequestPhysicsterseUpdate();
3262
3263 m_throttleUpdates = false;
3264 throttleCounter = 0;
3265 _zeroFlag = true;
3266
3267 disableBodySoft(); // disable it and colisions
3268 base.RaiseOutOfBounds(_position);
3269 return; 3313 return;
3270 }
3271 3314
3272 if (lpos.X < 0f) 3315 if (++bodydisablecontrol < 20)
3273 {
3274 _position.X = Util.Clip(lpos.X, -2f, -0.1f);
3275 m_outbounds = true;
3276 }
3277 else if (lpos.X > _parent_scene.WorldExtents.X)
3278 {
3279 _position.X = Util.Clip(lpos.X, _parent_scene.WorldExtents.X + 0.1f, _parent_scene.WorldExtents.X + 2f);
3280 m_outbounds = true;
3281 }
3282 if (lpos.Y < 0f)
3283 {
3284 _position.Y = Util.Clip(lpos.Y, -2f, -0.1f);
3285 m_outbounds = true;
3286 }
3287 else if (lpos.Y > _parent_scene.WorldExtents.Y)
3288 {
3289 _position.Y = Util.Clip(lpos.Y, _parent_scene.WorldExtents.Y + 0.1f, _parent_scene.WorldExtents.Y + 2f);
3290 m_outbounds = true;
3291 }
3292
3293 if (m_outbounds)
3294 {
3295 m_lastposition = _position;
3296 m_lastorientation = _orientation;
3297
3298 d.Vector3 dtmp = d.BodyGetAngularVel(Body);
3299 m_rotationalVelocity.X = dtmp.X;
3300 m_rotationalVelocity.Y = dtmp.Y;
3301 m_rotationalVelocity.Z = dtmp.Z;
3302
3303 dtmp = d.BodyGetLinearVel(Body);
3304 _velocity.X = dtmp.X;
3305 _velocity.Y = dtmp.Y;
3306 _velocity.Z = dtmp.Z;
3307
3308 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
3309 d.BodySetAngularVel(Body, 0, 0, 0);
3310 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
3311 disableBodySoft(); // stop collisions
3312 base.RequestPhysicsterseUpdate();
3313 return; 3316 return;
3314 }
3315 3317
3316 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE) 3318 bodydisablecontrol = 0;
3317 { 3319 d.BodyEnable(Body);
3318 // 'VEHICLES' are dealt with in ODEDynamics.cs 3320 }
3319 m_vehicle.Step();
3320 }
3321 else
3322 {
3323 float fx = 0;
3324 float fy = 0;
3325 float fz = 0;
3326 3321
3327 float m_mass = _mass; 3322 // check outside region
3323 d.Vector3 lpos = d.GeomGetPosition(prim_geom); // root position that is seem by rest of simulator
3328 3324
3329 // fz = 0f; 3325 if (lpos.Z < -100 || lpos.Z > 100000f)
3330 //m_log.Info(m_collisionFlags.ToString()); 3326 {
3331 if (m_usePID) 3327 m_outbounds = true;
3332 {
3333 3328
3334 // If the PID Controller isn't active then we set our force 3329 lpos.Z = Util.Clip(lpos.Z, -100f, 100000f);
3335 // calculating base velocity to the current position 3330 _acceleration.X = 0;
3331 _acceleration.Y = 0;
3332 _acceleration.Z = 0;
3336 3333
3337 if ((m_PIDTau < 1) && (m_PIDTau != 0)) 3334 _velocity.X = 0;
3338 { 3335 _velocity.Y = 0;
3339 //PID_G = PID_G / m_PIDTau; 3336 _velocity.Z = 0;
3340 m_PIDTau = 1; 3337 m_rotationalVelocity.X = 0;
3341 } 3338 m_rotationalVelocity.Y = 0;
3339 m_rotationalVelocity.Z = 0;
3342 3340
3343 if ((PID_G - m_PIDTau) <= 0) 3341 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
3344 { 3342 d.BodySetAngularVel(Body, 0, 0, 0); // stop it
3345 PID_G = m_PIDTau + 1; 3343 d.BodySetPosition(Body, lpos.X, lpos.Y, lpos.Z); // put it somewhere
3346 } 3344 m_lastposition = _position;
3345 m_lastorientation = _orientation;
3347 3346
3348 d.Vector3 vel = d.BodyGetLinearVel(Body); 3347 base.RequestPhysicsterseUpdate();
3349 d.Vector3 pos = d.BodyGetPosition(Body);
3350 _target_velocity =
3351 new Vector3(
3352 (m_PIDTarget.X - pos.X) * ((PID_G - m_PIDTau) * timestep),
3353 (m_PIDTarget.Y - pos.Y) * ((PID_G - m_PIDTau) * timestep),
3354 (m_PIDTarget.Z - pos.Z) * ((PID_G - m_PIDTau) * timestep)
3355 );
3356 3348
3357 // if velocity is zero, use position control; otherwise, velocity control 3349 throttleCounter = 0;
3350 _zeroFlag = true;
3358 3351
3359 if (_target_velocity.ApproxEquals(Vector3.Zero, 0.1f)) 3352 disableBodySoft(); // disable it and colisions
3360 { 3353 base.RaiseOutOfBounds(_position);
3361 // keep track of where we stopped. No more slippin' & slidin' 3354 return;
3362 3355 }
3363 // We only want to deactivate the PID Controller if we think we want to have our surrogate
3364 // react to the physics scene by moving it's position.
3365 // Avatar to Avatar collisions
3366 // Prim to avatar collisions
3367
3368 //fx = (_target_velocity.X - vel.X) * (PID_D) + (_zeroPosition.X - pos.X) * (PID_P * 2);
3369 //fy = (_target_velocity.Y - vel.Y) * (PID_D) + (_zeroPosition.Y - pos.Y) * (PID_P * 2);
3370 //fz = fz + (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P;
3371 d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z);
3372 d.BodySetLinearVel(Body, 0, 0, 0);
3373 d.BodyAddForce(Body, 0, 0, fz);
3374 return;
3375 }
3376 else
3377 {
3378 _zeroFlag = false;
3379 3356
3380 // We're flying and colliding with something 3357 if (lpos.X < 0f)
3381 fx = ((_target_velocity.X) - vel.X) * (PID_D); 3358 {
3382 fy = ((_target_velocity.Y) - vel.Y) * (PID_D); 3359 _position.X = Util.Clip(lpos.X, -2f, -0.1f);
3360 m_outbounds = true;
3361 }
3362 else if (lpos.X > _parent_scene.WorldExtents.X)
3363 {
3364 _position.X = Util.Clip(lpos.X, _parent_scene.WorldExtents.X + 0.1f, _parent_scene.WorldExtents.X + 2f);
3365 m_outbounds = true;
3366 }
3367 if (lpos.Y < 0f)
3368 {
3369 _position.Y = Util.Clip(lpos.Y, -2f, -0.1f);
3370 m_outbounds = true;
3371 }
3372 else if (lpos.Y > _parent_scene.WorldExtents.Y)
3373 {
3374 _position.Y = Util.Clip(lpos.Y, _parent_scene.WorldExtents.Y + 0.1f, _parent_scene.WorldExtents.Y + 2f);
3375 m_outbounds = true;
3376 }
3383 3377
3384 // vec.Z = (_target_velocity.Z - vel.Z) * PID_D + (_zeroPosition.Z - pos.Z) * PID_P; 3378 if (m_outbounds)
3379 {
3380 m_lastposition = _position;
3381 m_lastorientation = _orientation;
3385 3382
3386 fz = ((_target_velocity.Z - vel.Z) * (PID_D)); 3383 d.Vector3 dtmp = d.BodyGetAngularVel(Body);
3387 } 3384 m_rotationalVelocity.X = dtmp.X;
3388 } // end if (m_usePID) 3385 m_rotationalVelocity.Y = dtmp.Y;
3386 m_rotationalVelocity.Z = dtmp.Z;
3389 3387
3390 // Hover PID Controller needs to be mutually exlusive to MoveTo PID controller 3388 dtmp = d.BodyGetLinearVel(Body);
3391 else if (m_useHoverPID) 3389 _velocity.X = dtmp.X;
3392 { 3390 _velocity.Y = dtmp.Y;
3393 //Console.WriteLine("Hover " + Name); 3391 _velocity.Z = dtmp.Z;
3394 3392
3395 // If we're using the PID controller, then we have no gravity 3393 d.BodySetLinearVel(Body, 0, 0, 0); // stop it
3394 d.BodySetAngularVel(Body, 0, 0, 0);
3395 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
3396 disableBodySoft(); // stop collisions
3397 base.RequestPhysicsterseUpdate();
3398 return;
3399 }
3396 3400
3397 // no lock; for now it's only called from within Simulate() 3401 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE)
3402 {
3403 // 'VEHICLES' are dealt with in ODEDynamics.cs
3404 m_vehicle.Step();
3405 return;
3406 }
3398 3407
3399 // If the PID Controller isn't active then we set our force 3408 float fx = 0;
3400 // calculating base velocity to the current position 3409 float fy = 0;
3410 float fz = 0;
3401 3411
3402 if ((m_PIDTau < 1)) 3412 float m_mass = _mass;
3403 {
3404 PID_G = PID_G / m_PIDTau;
3405 }
3406 3413
3407 if ((PID_G - m_PIDTau) <= 0) 3414 if (m_usePID && m_PIDTau > 0)
3408 { 3415 {
3409 PID_G = m_PIDTau + 1; 3416 // for now position error
3410 } 3417 _target_velocity =
3418 new Vector3(
3419 (m_PIDTarget.X - lpos.X),
3420 (m_PIDTarget.Y - lpos.Y),
3421 (m_PIDTarget.Z - lpos.Z)
3422 );
3411 3423
3412 // Where are we, and where are we headed? 3424 if (_target_velocity.ApproxEquals(Vector3.Zero, 0.02f))
3413 d.Vector3 pos = d.BodyGetPosition(Body); 3425 {
3414 d.Vector3 vel = d.BodyGetLinearVel(Body); 3426 d.BodySetPosition(Body, m_PIDTarget.X, m_PIDTarget.Y, m_PIDTarget.Z);
3427 d.BodySetLinearVel(Body, 0, 0, 0);
3428 return;
3429 }
3430 else
3431 {
3432 _zeroFlag = false;
3415 3433
3416 // Non-Vehicles have a limited set of Hover options. 3434 float tmp = 1 / m_PIDTau;
3417 // determine what our target height really is based on HoverType 3435 _target_velocity *= tmp;
3418 switch (m_PIDHoverType)
3419 {
3420 case PIDHoverType.Ground:
3421 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y);
3422 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
3423 break;
3424 case PIDHoverType.GroundAndWater:
3425 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y);
3426 m_waterHeight = _parent_scene.GetWaterLevel();
3427 if (m_groundHeight > m_waterHeight)
3428 {
3429 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
3430 }
3431 else
3432 {
3433 m_targetHoverHeight = m_waterHeight + m_PIDHoverHeight;
3434 }
3435 break;
3436 3436
3437 } // end switch (m_PIDHoverType) 3437 // apply limits
3438 tmp = _target_velocity.Length();
3439 if (tmp > 50.0f)
3440 {
3441 tmp = 50 / tmp;
3442 _target_velocity *= tmp;
3443 }
3444 else if (tmp < 0.05f)
3445 {
3446 tmp = 0.05f / tmp;
3447 _target_velocity *= tmp;
3448 }
3438 3449
3450 d.Vector3 vel = d.BodyGetLinearVel(Body);
3451 fx = (_target_velocity.X - vel.X) * m_invTimeStep;
3452 fy = (_target_velocity.Y - vel.Y) * m_invTimeStep;
3453 fz = (_target_velocity.Z - vel.Z) * m_invTimeStep;
3454 }
3455 } // end if (m_usePID)
3439 3456
3440 _target_velocity = 3457 // Hover PID Controller needs to be mutually exlusive to MoveTo PID controller
3441 new Vector3(0.0f, 0.0f, 3458 else if (m_useHoverPID && m_PIDHoverTau != 0 && m_PIDHoverHeight != 0)
3442 (m_targetHoverHeight - pos.Z) * ((PID_G - m_PIDHoverTau) * timestep) 3459 {
3443 );
3444 3460
3445 // if velocity is zero, use position control; otherwise, velocity control 3461 // Non-Vehicles have a limited set of Hover options.
3462 // determine what our target height really is based on HoverType
3446 3463
3447 if (_target_velocity.ApproxEquals(Vector3.Zero, 0.1f)) 3464 m_groundHeight = _parent_scene.GetTerrainHeightAtXY(lpos.X, lpos.Y);
3448 {
3449 // keep track of where we stopped. No more slippin' & slidin'
3450 3465
3451 // We only want to deactivate the PID Controller if we think we want to have our surrogate 3466 switch (m_PIDHoverType)
3452 // react to the physics scene by moving it's position. 3467 {
3453 // Avatar to Avatar collisions 3468 case PIDHoverType.Ground:
3454 // Prim to avatar collisions 3469 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
3470 break;
3455 3471
3456 d.BodySetPosition(Body, pos.X, pos.Y, m_targetHoverHeight); 3472 case PIDHoverType.GroundAndWater:
3457 d.BodySetLinearVel(Body, vel.X, vel.Y, 0); 3473 m_waterHeight = _parent_scene.GetWaterLevel();
3458 // ? d.BodyAddForce(Body, 0, 0, fz); 3474 if (m_groundHeight > m_waterHeight)
3459 return; 3475 m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
3460 }
3461 else 3476 else
3462 { 3477 m_targetHoverHeight = m_waterHeight + m_PIDHoverHeight;
3463 _zeroFlag = false; 3478 break;
3479 } // end switch (m_PIDHoverType)
3464 3480
3465 // We're flying and colliding with something 3481 // don't go underground unless volumedetector
3466 fz = ((_target_velocity.Z - vel.Z) * (PID_D));
3467 }
3468 }
3469 else
3470 {
3471 float b = (1.0f - m_buoyancy);
3472 fx = _parent_scene.gravityx * b;
3473 fy = _parent_scene.gravityy * b;
3474 fz = _parent_scene.gravityz * b;
3475 }
3476
3477 fx *= m_mass;
3478 fy *= m_mass;
3479 fz *= m_mass;
3480 3482
3481 // constant force 3483 if (m_targetHoverHeight > m_groundHeight || m_isVolumeDetect)
3482 fx += m_force.X; 3484 {
3483 fy += m_force.Y; 3485 d.Vector3 vel = d.BodyGetLinearVel(Body);
3484 fz += m_force.Z;
3485
3486 fx += m_forceacc.X;
3487 fy += m_forceacc.Y;
3488 fz += m_forceacc.Z;
3489 3486
3490 m_forceacc = Vector3.Zero; 3487 fz = (m_targetHoverHeight - lpos.Z);
3491 3488
3492 //m_log.Info("[OBJPID]: X:" + fx.ToString() + " Y:" + fy.ToString() + " Z:" + fz.ToString()); 3489 // if error is zero, use position control; otherwise, velocity control
3493 if (fx != 0 || fy != 0 || fz != 0) 3490 if (Math.Abs(fz) < 0.01f)
3494 { 3491 {
3495 d.BodyAddForce(Body, fx, fy, fz); 3492 d.BodySetPosition(Body, lpos.X, lpos.Y, m_targetHoverHeight);
3496 //Console.WriteLine("AddForce " + fx + "," + fy + "," + fz); 3493 d.BodySetLinearVel(Body, vel.X, vel.Y, 0);
3494 return;
3497 } 3495 }
3496 else
3497 {
3498 _zeroFlag = false;
3499 fz /= m_PIDHoverTau;
3498 3500
3499 Vector3 trq; 3501 float tmp = Math.Abs(fz);
3502 if (tmp > 50)
3503 fz = 50 * Math.Sign(fz);
3504 else if (tmp < 0.1)
3505 fz = 0.1f * Math.Sign(fz);
3500 3506
3501 trq = _torque; 3507 fz = ((fz - vel.Z) * m_invTimeStep);
3502 trq += m_angularForceacc;
3503 m_angularForceacc = Vector3.Zero;
3504 if (trq.X != 0 || trq.Y != 0 || trq.Z != 0)
3505 {
3506 d.BodyAddTorque(Body, trq.X, trq.Y, trq.Z);
3507 } 3508 }
3508 } 3509 }
3510 }
3511 else
3512 {
3513 float b = (1.0f - m_buoyancy);
3514 fx = _parent_scene.gravityx * b;
3515 fy = _parent_scene.gravityy * b;
3516 fz = _parent_scene.gravityz * b;
3517 }
3509 3518
3510 // update our ideia of velocities and acelerations 3519 fx *= m_mass;
3511 d.Quaternion ori; 3520 fy *= m_mass;
3512 d.Vector3 dtmpu; 3521 fz *= m_mass;
3513
3514 _position.X = lpos.X;
3515 _position.Y = lpos.Y;
3516 _position.Z = lpos.Z;
3517
3518 d.GeomCopyQuaternion(prim_geom, out ori);
3519 _orientation.X = ori.X;
3520 _orientation.Y = ori.Y;
3521 _orientation.Z = ori.Z;
3522 _orientation.W = ori.W;
3523
3524 _acceleration = _velocity;
3525 3522
3526 dtmpu = d.BodyGetLinearVel(Body); 3523 // constant force
3527 _velocity.X = dtmpu.X; 3524 fx += m_force.X;
3528 _velocity.Y = dtmpu.Y; 3525 fy += m_force.Y;
3529 _velocity.Z = dtmpu.Z; 3526 fz += m_force.Z;
3530 3527
3531 float invts = 1 / timestep; 3528 fx += m_forceacc.X;
3532 _acceleration = (_velocity - _acceleration) * invts; 3529 fy += m_forceacc.Y;
3530 fz += m_forceacc.Z;
3533 3531
3534 dtmpu = d.BodyGetAngularVel(Body); 3532 m_forceacc = Vector3.Zero;
3535 m_rotationalVelocity.X = dtmpu.X;
3536 m_rotationalVelocity.Y = dtmpu.Y;
3537 m_rotationalVelocity.Z = dtmpu.Z;
3538 }
3539 3533
3540 else // body disabled/sleeping 3534 //m_log.Info("[OBJPID]: X:" + fx.ToString() + " Y:" + fy.ToString() + " Z:" + fz.ToString());
3535 if (fx != 0 || fy != 0 || fz != 0)
3541 { 3536 {
3542 // let vehicles sleep 3537 d.BodyAddForce(Body, fx, fy, fz);
3543 if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE) 3538 //Console.WriteLine("AddForce " + fx + "," + fy + "," + fz);
3544 return; 3539 }
3545 3540
3546 if (++bodydisablecontrol < 20) 3541 Vector3 trq;
3547 return;
3548 3542
3549 bodydisablecontrol = 0; 3543 trq = _torque;
3550 d.BodyEnable(Body); 3544 trq += m_angularForceacc;
3551 return; 3545 m_angularForceacc = Vector3.Zero;
3546 if (trq.X != 0 || trq.Y != 0 || trq.Z != 0)
3547 {
3548 d.BodyAddTorque(Body, trq.X, trq.Y, trq.Z);
3552 } 3549 }
3553 } 3550 }
3554 else 3551 else
@@ -3560,92 +3557,113 @@ namespace OpenSim.Region.Physics.OdePlugin
3560 } 3557 }
3561 } 3558 }
3562 3559
3563 3560 public void UpdatePositionAndVelocity()
3564 public void UpdatePositionAndVelocity(float simulatedtime)
3565 { 3561 {
3566 // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit! 3562 if (_parent == null && !m_disabled && !m_building && !m_outbounds && Body != IntPtr.Zero)
3567 if (_parent == null && !m_disabled && !m_building && !m_outbounds)
3568 { 3563 {
3569 if (Body != IntPtr.Zero) 3564 if (d.BodyIsEnabled(Body) || !_zeroFlag)
3570 { 3565 {
3571 bool lastZeroFlag = _zeroFlag; 3566 bool lastZeroFlag = _zeroFlag;
3572 3567
3573 if ((Math.Abs(m_lastposition.X - _position.X) < 0.01) 3568 d.Vector3 lpos;
3574 && (Math.Abs(m_lastposition.Y - _position.Y) < 0.01) 3569 d.GeomCopyPosition(prim_geom, out lpos); // root position that is seem by rest of simulator
3575 && (Math.Abs(m_lastposition.Z - _position.Z) < 0.01) 3570
3576 && (Math.Abs(m_lastorientation.X - _orientation.X) < 0.0001) 3571 d.Quaternion ori;
3577 && (Math.Abs(m_lastorientation.Y - _orientation.Y) < 0.0001) 3572 d.GeomCopyQuaternion(prim_geom, out ori);
3578 && (Math.Abs(m_lastorientation.Z - _orientation.Z) < 0.0001) 3573
3574 // decide if moving
3575 // use positions since this are integrated quantities
3576 // tolerance values depende a lot on simulation noise...
3577 // use simple math.abs since we dont need to be exact
3578
3579 if (
3580 (Math.Abs(_position.X - lpos.X) < 0.001f)
3581 && (Math.Abs(_position.Y - lpos.Y) < 0.001f)
3582 && (Math.Abs(_position.Z - lpos.Z) < 0.001f)
3583 && (Math.Abs(_orientation.X - ori.X) < 0.0001f)
3584 && (Math.Abs(_orientation.Y - ori.Y) < 0.0001f)
3585 && (Math.Abs(_orientation.Z - ori.Z) < 0.0001f) // ignore W
3579 ) 3586 )
3580 { 3587 {
3581 _zeroFlag = true; 3588 _zeroFlag = true;
3582 m_throttleUpdates = false;
3583 } 3589 }
3584 else 3590 else
3585 {
3586 _zeroFlag = false; 3591 _zeroFlag = false;
3587 m_lastUpdateSent = false;
3588 }
3589 3592
3590 if (_zeroFlag) 3593 // update velocities and aceleration
3594 if (!(_zeroFlag && lastZeroFlag))
3591 { 3595 {
3592 m_lastposition = _position; 3596 d.Vector3 vel = d.BodyGetLinearVel(Body);
3593 m_lastorientation = _orientation;
3594 3597
3595 _velocity = Vector3.Zero; 3598 _acceleration = _velocity;
3596 _acceleration = Vector3.Zero;
3597 m_rotationalVelocity = Vector3.Zero;
3598 3599
3599 if (!m_lastUpdateSent) 3600 if ((Math.Abs(vel.X) < 0.001f) &&
3601 (Math.Abs(vel.Y) < 0.001f) &&
3602 (Math.Abs(vel.Z) < 0.001f))
3600 { 3603 {
3601 m_throttleUpdates = false; 3604 _velocity = Vector3.Zero;
3602 throttleCounter = 0; 3605 float t = -m_invTimeStep;
3603 3606 _acceleration = _acceleration * t;
3604 base.RequestPhysicsterseUpdate();
3605
3606 m_lastUpdateSent = true;
3607 } 3607 }
3608 } 3608 else
3609 else
3610 {
3611 if (lastZeroFlag != _zeroFlag)
3612 { 3609 {
3613 base.RequestPhysicsterseUpdate(); 3610 _velocity.X = vel.X;
3611 _velocity.Y = vel.Y;
3612 _velocity.Z = vel.Z;
3613 _acceleration = (_velocity - _acceleration) * m_invTimeStep;
3614 } 3614 }
3615 3615
3616 m_lastUpdateSent = false; 3616 if ((Math.Abs(_acceleration.X) < 0.01f) &&
3617 if (!m_throttleUpdates || throttleCounter > _parent_scene.geomUpdatesPerThrottledUpdate) 3617 (Math.Abs(_acceleration.Y) < 0.01f) &&
3618 (Math.Abs(_acceleration.Z) < 0.01f))
3618 { 3619 {
3619 m_lastposition = _position; 3620 _acceleration = Vector3.Zero;
3620 m_lastorientation = _orientation; 3621 }
3621 m_lastVelocity = _velocity; 3622
3622 base.RequestPhysicsterseUpdate(); 3623 if ((Math.Abs(_orientation.X - ori.X) < 0.0001) &&
3624 (Math.Abs(_orientation.Y - ori.Y) < 0.0001) &&
3625 (Math.Abs(_orientation.Z - ori.Z) < 0.0001)
3626 )
3627 {
3628 m_rotationalVelocity = Vector3.Zero;
3623 } 3629 }
3624 else 3630 else
3625 { 3631 {
3626 throttleCounter++; 3632 vel = d.BodyGetAngularVel(Body);
3633 m_rotationalVelocity.X = vel.X;
3634 m_rotationalVelocity.Y = vel.Y;
3635 m_rotationalVelocity.Z = vel.Z;
3627 } 3636 }
3628 } 3637 }
3629 }
3630 else if (!m_lastUpdateSent || !_zeroFlag)
3631 {
3632 // Not a body.. so Make sure the client isn't interpolating
3633 _velocity = Vector3.Zero;
3634 _acceleration = Vector3.Zero;
3635 m_rotationalVelocity = Vector3.Zero;
3636 m_lastVelocity = Vector3.Zero;
3637
3638 _zeroFlag = true;
3639 3638
3640 if (!m_lastUpdateSent) 3639 if (_zeroFlag)
3641 { 3640 {
3642 m_throttleUpdates = false; 3641 if (lastZeroFlag)
3643 throttleCounter = 0; 3642 {
3644 3643 _velocity = Vector3.Zero;
3645 base.RequestPhysicsterseUpdate(); 3644 _acceleration = Vector3.Zero;
3645 m_rotationalVelocity = Vector3.Zero;
3646 }
3646 3647
3647 m_lastUpdateSent = true; 3648 if (!m_lastUpdateSent)
3649 {
3650 base.RequestPhysicsterseUpdate();
3651 if (lastZeroFlag)
3652 m_lastUpdateSent = true;
3653 }
3654 return;
3648 } 3655 }
3656
3657 _position.X = lpos.X;
3658 _position.Y = lpos.Y;
3659 _position.Z = lpos.Z;
3660
3661 _orientation.X = ori.X;
3662 _orientation.Y = ori.Y;
3663 _orientation.Z = ori.Z;
3664 _orientation.W = ori.W;
3665 base.RequestPhysicsterseUpdate();
3666 m_lastUpdateSent = false;
3649 } 3667 }
3650 } 3668 }
3651 } 3669 }
@@ -3803,11 +3821,11 @@ namespace OpenSim.Region.Physics.OdePlugin
3803 break; 3821 break;
3804 3822
3805 case changes.AddForce: 3823 case changes.AddForce:
3806 changeAddForce((Vector3)arg); 3824 changeAddImpulse((Vector3)arg);
3807 break; 3825 break;
3808 3826
3809 case changes.AddAngForce: 3827 case changes.AddAngForce:
3810 changeAddAngularForce((Vector3)arg); 3828 changeAddAngularImpulse((Vector3)arg);
3811 break; 3829 break;
3812 3830
3813 case changes.AngLock: 3831 case changes.AngLock:
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs
index 9ca2d3f..cf74f14 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs
@@ -189,9 +189,12 @@ namespace OpenSim.Region.Physics.OdePlugin
189 private const uint m_regionHeight = Constants.RegionSize; 189 private const uint m_regionHeight = Constants.RegionSize;
190 190
191 public float ODE_STEPSIZE = 0.020f; 191 public float ODE_STEPSIZE = 0.020f;
192 public float HalfOdeStep = 0.01f;
192 private float metersInSpace = 25.6f; 193 private float metersInSpace = 25.6f;
193 private float m_timeDilation = 1.0f; 194 private float m_timeDilation = 1.0f;
194 195
196 DateTime m_lastframe;
197
195 public float gravityx = 0f; 198 public float gravityx = 0f;
196 public float gravityy = 0f; 199 public float gravityy = 0f;
197 public float gravityz = -9.8f; 200 public float gravityz = -9.8f;
@@ -485,6 +488,8 @@ namespace OpenSim.Region.Physics.OdePlugin
485 } 488 }
486 } 489 }
487 490
491 HalfOdeStep = ODE_STEPSIZE * 0.5f;
492
488 ContactgeomsArray = Marshal.AllocHGlobal(contactsPerCollision * d.ContactGeom.unmanagedSizeOf); 493 ContactgeomsArray = Marshal.AllocHGlobal(contactsPerCollision * d.ContactGeom.unmanagedSizeOf);
489 GlobalContactsArray = GlobalContactsArray = Marshal.AllocHGlobal(maxContactsbeforedeath * d.Contact.unmanagedSizeOf); 494 GlobalContactsArray = GlobalContactsArray = Marshal.AllocHGlobal(maxContactsbeforedeath * d.Contact.unmanagedSizeOf);
490 495
@@ -521,7 +526,7 @@ namespace OpenSim.Region.Physics.OdePlugin
521 d.WorldSetAngularDamping(world, 0.001f); 526 d.WorldSetAngularDamping(world, 0.001f);
522 d.WorldSetAngularDampingThreshold(world, 0f); 527 d.WorldSetAngularDampingThreshold(world, 0f);
523 d.WorldSetLinearDampingThreshold(world, 0f); 528 d.WorldSetLinearDampingThreshold(world, 0f);
524 d.WorldSetMaxAngularSpeed(world, 256f); 529 d.WorldSetMaxAngularSpeed(world, 100f);
525 530
526 d.WorldSetCFM(world,1e-6f); // a bit harder than default 531 d.WorldSetCFM(world,1e-6f); // a bit harder than default
527 //d.WorldSetCFM(world, 1e-4f); // a bit harder than default 532 //d.WorldSetCFM(world, 1e-4f); // a bit harder than default
@@ -564,6 +569,7 @@ namespace OpenSim.Region.Physics.OdePlugin
564 // let this now be real maximum values 569 // let this now be real maximum values
565 spaceGridMaxX--; 570 spaceGridMaxX--;
566 spaceGridMaxY--; 571 spaceGridMaxY--;
572 m_lastframe = DateTime.UtcNow;
567 } 573 }
568 574
569 internal void waitForSpaceUnlock(IntPtr space) 575 internal void waitForSpaceUnlock(IntPtr space)
@@ -1685,35 +1691,30 @@ namespace OpenSim.Region.Physics.OdePlugin
1685 /// <returns></returns> 1691 /// <returns></returns>
1686 public override float Simulate(float timeStep) 1692 public override float Simulate(float timeStep)
1687 { 1693 {
1688 int statstart;
1689 int statchanges = 0;
1690 int statchmove = 0;
1691 int statactmove = 0;
1692 int statray = 0;
1693 int statcol = 0;
1694 int statstep = 0;
1695 int statmovchar = 0;
1696 int statmovprim;
1697 int totjcontact = 0;
1698 1694
1695 DateTime now = DateTime.UtcNow;
1696 TimeSpan SinceLastFrame = now - m_lastframe;
1697 m_lastframe = now;
1698 timeStep = (float)SinceLastFrame.TotalSeconds;
1699
1699 // acumulate time so we can reduce error 1700 // acumulate time so we can reduce error
1700 step_time += timeStep; 1701 step_time += timeStep;
1701 1702
1702 if (step_time < ODE_STEPSIZE) 1703 if (step_time < HalfOdeStep)
1703 return 0; 1704 return 0;
1704 1705
1705 if (framecount >= int.MaxValue) 1706 if (framecount < 0)
1706 framecount = 0; 1707 framecount = 0;
1707 1708
1708 framecount++; 1709 framecount++;
1709 1710
1710 int curphysiteractions = m_physicsiterations; 1711 int curphysiteractions;
1711 1712
1713 // if in trouble reduce step resolution
1712 if (step_time >= m_SkipFramesAtms) 1714 if (step_time >= m_SkipFramesAtms)
1713 { 1715 curphysiteractions = m_physicsiterations / 2;
1714 // if in trouble reduce step resolution 1716 else
1715 curphysiteractions /= 2; 1717 curphysiteractions = m_physicsiterations;
1716 }
1717 1718
1718 int nodeframes = 0; 1719 int nodeframes = 0;
1719 1720
@@ -1733,13 +1734,10 @@ namespace OpenSim.Region.Physics.OdePlugin
1733 base.TriggerPhysicsBasedRestart(); 1734 base.TriggerPhysicsBasedRestart();
1734 } 1735 }
1735 1736
1736 1737 while (step_time >= HalfOdeStep && nodeframes < 10) //limit number of steps so we don't say here for ever
1737 while (step_time >= ODE_STEPSIZE && nodeframes < 10) //limit number of steps so we don't say here for ever
1738 { 1738 {
1739 try 1739 try
1740 { 1740 {
1741 statstart = Util.EnvironmentTickCount();
1742
1743 // clear pointer/counter to contacts to pass into joints 1741 // clear pointer/counter to contacts to pass into joints
1744 m_global_contactcount = 0; 1742 m_global_contactcount = 0;
1745 1743
@@ -1778,17 +1776,39 @@ namespace OpenSim.Region.Physics.OdePlugin
1778 1776
1779 } 1777 }
1780 1778
1781 statchanges += Util.EnvironmentTickCountSubtract(statstart); 1779 // Move characters
1780 lock (_characters)
1781 {
1782 List<OdeCharacter> defects = new List<OdeCharacter>();
1783 foreach (OdeCharacter actor in _characters)
1784 {
1785 if (actor != null)
1786 actor.Move(ODE_STEPSIZE, defects);
1787 }
1788 if (defects.Count != 0)
1789 {
1790 foreach (OdeCharacter defect in defects)
1791 {
1792 RemoveCharacter(defect);
1793 }
1794 }
1795 }
1796
1797 // Move other active objects
1798 lock (_activegroups)
1799 {
1800 foreach (OdePrim aprim in _activegroups)
1801 {
1802 aprim.Move();
1803 }
1804 }
1782 1805
1783 statactmove += Util.EnvironmentTickCountSubtract(statstart);
1784 //if ((framecount % m_randomizeWater) == 0) 1806 //if ((framecount % m_randomizeWater) == 0)
1785 // randomizeWater(waterlevel); 1807 // randomizeWater(waterlevel);
1786 1808
1787 m_rayCastManager.ProcessQueuedRequests(); 1809 m_rayCastManager.ProcessQueuedRequests();
1788 1810
1789 statray += Util.EnvironmentTickCountSubtract(statstart);
1790 collision_optimized(); 1811 collision_optimized();
1791 statcol += Util.EnvironmentTickCountSubtract(statstart);
1792 1812
1793 lock (_collisionEventPrim) 1813 lock (_collisionEventPrim)
1794 { 1814 {
@@ -1813,38 +1833,39 @@ namespace OpenSim.Region.Physics.OdePlugin
1813 } 1833 }
1814 } 1834 }
1815 1835
1836 // do a ode simulation step
1816 d.WorldQuickStep(world, ODE_STEPSIZE); 1837 d.WorldQuickStep(world, ODE_STEPSIZE);
1817 statstep += Util.EnvironmentTickCountSubtract(statstart); 1838 d.JointGroupEmpty(contactgroup);
1839
1840 // update managed ideia of physical data and do updates to core
1841 /*
1842 lock (_characters)
1843 {
1844 foreach (OdeCharacter actor in _characters)
1845 {
1846 if (actor != null)
1847 {
1848 if (actor.bad)
1849 m_log.WarnFormat("[PHYSICS]: BAD Actor {0} in _characters list was not removed?", actor.m_uuid);
1850
1851 actor.UpdatePositionAndVelocity();
1852 }
1853 }
1854 }
1855 */
1818 1856
1819 // Move characters 1857 lock (_activegroups)
1820 lock (_characters)
1821 { 1858 {
1822 List<OdeCharacter> defects = new List<OdeCharacter>();
1823 foreach (OdeCharacter actor in _characters)
1824 {
1825 if (actor != null)
1826 actor.Move(ODE_STEPSIZE, defects);
1827 }
1828 if (defects.Count != 0)
1829 { 1859 {
1830 foreach (OdeCharacter defect in defects) 1860 foreach (OdePrim actor in _activegroups)
1831 { 1861 {
1832 RemoveCharacter(defect); 1862 if (actor.IsPhysical)
1863 {
1864 actor.UpdatePositionAndVelocity();
1865 }
1833 } 1866 }
1834 } 1867 }
1835 } 1868 }
1836 statchmove += Util.EnvironmentTickCountSubtract(statstart);
1837
1838 // Move other active objects
1839 lock (_activegroups)
1840 {
1841 foreach (OdePrim aprim in _activegroups)
1842 {
1843 aprim.Move();
1844 }
1845 }
1846
1847 //ode.dunlock(world);
1848 } 1869 }
1849 catch (Exception e) 1870 catch (Exception e)
1850 { 1871 {
@@ -1852,32 +1873,11 @@ namespace OpenSim.Region.Physics.OdePlugin
1852// ode.dunlock(world); 1873// ode.dunlock(world);
1853 } 1874 }
1854 1875
1855 d.JointGroupEmpty(contactgroup);
1856 totjcontact += m_global_contactcount;
1857 1876
1858 step_time -= ODE_STEPSIZE; 1877 step_time -= ODE_STEPSIZE;
1859 nodeframes++; 1878 nodeframes++;
1860 } 1879 }
1861 1880
1862 statstart = Util.EnvironmentTickCount();
1863
1864/*
1865// now included in characters move() and done at ode rate
1866// maybe be needed later if we need to do any extra work at hearbeat rate
1867 lock (_characters)
1868 {
1869 foreach (OdeCharacter actor in _characters)
1870 {
1871 if (actor != null)
1872 {
1873 if (actor.bad)
1874 m_log.WarnFormat("[PHYSICS]: BAD Actor {0} in _characters list was not removed?", actor.m_uuid);
1875
1876 actor.UpdatePositionAndVelocity();
1877 }
1878 }
1879 }
1880*/
1881 lock (_badCharacter) 1881 lock (_badCharacter)
1882 { 1882 {
1883 if (_badCharacter.Count > 0) 1883 if (_badCharacter.Count > 0)
@@ -1890,22 +1890,6 @@ namespace OpenSim.Region.Physics.OdePlugin
1890 _badCharacter.Clear(); 1890 _badCharacter.Clear();
1891 } 1891 }
1892 } 1892 }
1893 statmovchar = Util.EnvironmentTickCountSubtract(statstart);
1894
1895 lock (_activegroups)
1896 {
1897 {
1898 foreach (OdePrim actor in _activegroups)
1899 {
1900 if (actor.IsPhysical)
1901 {
1902 actor.UpdatePositionAndVelocity((float)nodeframes * ODE_STEPSIZE);
1903 }
1904 }
1905 }
1906 }
1907
1908 statmovprim = Util.EnvironmentTickCountSubtract(statstart);
1909 1893
1910 int nactivegeoms = d.SpaceGetNumGeoms(ActiveSpace); 1894 int nactivegeoms = d.SpaceGetNumGeoms(ActiveSpace);
1911 int nstaticgeoms = d.SpaceGetNumGeoms(StaticSpace); 1895 int nstaticgeoms = d.SpaceGetNumGeoms(StaticSpace);
@@ -1932,15 +1916,17 @@ namespace OpenSim.Region.Physics.OdePlugin
1932 d.WorldExportDIF(world, fname, physics_logging_append_existing_logfile, prefix); 1916 d.WorldExportDIF(world, fname, physics_logging_append_existing_logfile, prefix);
1933 } 1917 }
1934 1918
1935 // think time dilation is not a physics issue alone.. but ok let's fake something 1919 // think time dilation as to do with dinamic step size that we dont' have
1936 if (step_time < ODE_STEPSIZE) // we did the required loops 1920 // even so tell something to world
1921 if (nodeframes < 10) // we did the requested loops
1937 m_timeDilation = 1.0f; 1922 m_timeDilation = 1.0f;
1938 else 1923 else if (step_time > 0)
1939 { // we didn't forget the lost ones and let user know something 1924 {
1940 m_timeDilation = 1 - step_time / timeStep; 1925 m_timeDilation = timeStep / step_time;
1941 if (m_timeDilation < 0) 1926 if (m_timeDilation > 1)
1942 m_timeDilation = 0; 1927 m_timeDilation = 1;
1943 step_time = 0; 1928 if (step_time > m_SkipFramesAtms)
1929 step_time = 0;
1944 } 1930 }
1945 } 1931 }
1946 1932
@@ -2007,7 +1993,7 @@ namespace OpenSim.Region.Physics.OdePlugin
2007 } 1993 }
2008 else // out world use external height 1994 else // out world use external height
2009 { 1995 {
2010 ix = regsize - 1; 1996 ix = regsize - 2;
2011 dx = 0; 1997 dx = 0;
2012 } 1998 }
2013 if (y < regsize - 1) 1999 if (y < regsize - 1)
@@ -2017,7 +2003,7 @@ namespace OpenSim.Region.Physics.OdePlugin
2017 } 2003 }
2018 else 2004 else
2019 { 2005 {
2020 iy = regsize - 1; 2006 iy = regsize - 2;
2021 dy = 0; 2007 dy = 0;
2022 } 2008 }
2023 } 2009 }
@@ -2034,7 +2020,7 @@ namespace OpenSim.Region.Physics.OdePlugin
2034 } 2020 }
2035 else // out world use external height 2021 else // out world use external height
2036 { 2022 {
2037 iy = regsize - 1; 2023 iy = regsize - 2;
2038 dy = 0; 2024 dy = 0;
2039 } 2025 }
2040 if (y < regsize - 1) 2026 if (y < regsize - 1)
@@ -2044,7 +2030,7 @@ namespace OpenSim.Region.Physics.OdePlugin
2044 } 2030 }
2045 else 2031 else
2046 { 2032 {
2047 ix = regsize - 1; 2033 ix = regsize - 2;
2048 dx = 0; 2034 dx = 0;
2049 } 2035 }
2050 } 2036 }
@@ -2057,18 +2043,35 @@ namespace OpenSim.Region.Physics.OdePlugin
2057 iy += ix; // all indexes have iy + ix 2043 iy += ix; // all indexes have iy + ix
2058 2044
2059 float[] heights = TerrainHeightFieldHeights[heightFieldGeom]; 2045 float[] heights = TerrainHeightFieldHeights[heightFieldGeom];
2046 /*
2047 if ((dx + dy) <= 1.0f)
2048 {
2049 h0 = ((float)heights[iy]); // 0,0 vertice
2050 h1 = (((float)heights[iy + 1]) - h0) * dx; // 1,0 vertice minus 0,0
2051 h2 = (((float)heights[iy + regsize]) - h0) * dy; // 0,1 vertice minus 0,0
2052 }
2053 else
2054 {
2055 h0 = ((float)heights[iy + regsize + 1]); // 1,1 vertice
2056 h1 = (((float)heights[iy + 1]) - h0) * (1 - dy); // 1,1 vertice minus 1,0
2057 h2 = (((float)heights[iy + regsize]) - h0) * (1 - dx); // 1,1 vertice minus 0,1
2058 }
2059 */
2060 h0 = ((float)heights[iy]); // 0,0 vertice
2060 2061
2061 if ((dx + dy) <= 1.0f) 2062 if ((dy > dx))
2062 { 2063 {
2063 h0 = ((float)heights[iy]); // 0,0 vertice 2064 iy += regsize;
2064 h1 = (((float)heights[iy + 1]) - h0) * dx; // 1,0 vertice minus 0,0 2065 h2 = (float)heights[iy]; // 0,1 vertice
2065 h2 = (((float)heights[iy + regsize]) - h0) * dy; // 0,1 vertice minus 0,0 2066 h1 = (h2 - h0) * dy; // 0,1 vertice minus 0,0
2067 h2 = ((float)heights[iy + 1] - h2) * dx; // 1,1 vertice minus 0,1
2066 } 2068 }
2067 else 2069 else
2068 { 2070 {
2069 h0 = ((float)heights[iy + regsize + 1]); // 1,1 vertice 2071 iy++;
2070 h1 = (((float)heights[iy + 1]) - h0) * (1 - dy); // 1,1 vertice minus 1,0 2072 h2 = (float)heights[iy]; // vertice 1,0
2071 h2 = (((float)heights[iy + regsize]) - h0) * (1 - dx); // 1,1 vertice minus 0,1 2073 h1 = (h2 - h0) * dx; // 1,0 vertice minus 0,0
2074 h2 = (((float)heights[iy + regsize]) - h2) * dy; // 1,1 vertice minus 1,0
2072 } 2075 }
2073 2076
2074 return h0 + h1 + h2; 2077 return h0 + h1 + h2;