diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs | 746 |
1 files changed, 382 insertions, 364 deletions
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: |