aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs')
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs544
1 files changed, 379 insertions, 165 deletions
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs
index 3d5be3e..b769c88 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs
@@ -74,7 +74,6 @@ namespace OpenSim.Region.Physics.OdePlugin
74 74
75 private Vector3 _position; 75 private Vector3 _position;
76 private Vector3 _zeroPosition; 76 private Vector3 _zeroPosition;
77 private bool _zeroFlag = false;
78 private Vector3 _velocity; 77 private Vector3 _velocity;
79 private Vector3 _target_velocity; 78 private Vector3 _target_velocity;
80 private Vector3 _acceleration; 79 private Vector3 _acceleration;
@@ -84,21 +83,21 @@ namespace OpenSim.Region.Physics.OdePlugin
84 private float m_mass = 80f; 83 private float m_mass = 80f;
85 public float m_density = 60f; 84 public float m_density = 60f;
86 private bool m_pidControllerActive = true; 85 private bool m_pidControllerActive = true;
87 public float PID_D = 800.0f;
88 public float PID_P = 900.0f;
89 //private static float POSTURE_SERVO = 10000.0f;
90 86
87 const float basePID_D = 0.55f; // scaled for unit mass unit time (2200 /(50*80))
88 const float basePID_P = 0.225f; // scaled for unit mass unit time (900 /(50*80))
89 public float PID_D;
90 public float PID_P;
91 91
92 private float m_invElipSizeX; 92 private float timeStep;
93 private float m_invElipSizeY; 93 private float invtimeStep;
94 94
95 private float m_feetOffset = 0;
95 private float feetOff = 0; 96 private float feetOff = 0;
96 private float feetSZ = 0.5f; 97 private float feetSZ = 0.5f;
97 const float feetScale = 0.9f; 98 const float feetScale = 0.8f;
98 const float invFeetScale = 1.0f / 0.9f;
99 const float sizeZAdjust = 0.15f;
100 private float boneOff = 0; 99 private float boneOff = 0;
101 100 private float m_lastVelocitySqr = 0;
102 101
103 public float walkDivisor = 1.3f; 102 public float walkDivisor = 1.3f;
104 public float runDivisor = 0.8f; 103 public float runDivisor = 0.8f;
@@ -107,6 +106,9 @@ namespace OpenSim.Region.Physics.OdePlugin
107 private bool m_iscollidingGround = false; 106 private bool m_iscollidingGround = false;
108 private bool m_iscollidingObj = false; 107 private bool m_iscollidingObj = false;
109 private bool m_alwaysRun = false; 108 private bool m_alwaysRun = false;
109
110 private bool _zeroFlag = false;
111
110 private int m_requestedUpdateFrequency = 0; 112 private int m_requestedUpdateFrequency = 0;
111 private uint m_localID = 0; 113 private uint m_localID = 0;
112 public bool m_returnCollisions = false; 114 public bool m_returnCollisions = false;
@@ -124,6 +126,7 @@ namespace OpenSim.Region.Physics.OdePlugin
124 int m_colliderfilter = 0; 126 int m_colliderfilter = 0;
125 int m_colliderGroundfilter = 0; 127 int m_colliderGroundfilter = 0;
126 int m_colliderObjectfilter = 0; 128 int m_colliderObjectfilter = 0;
129 bool m_collisionException = false;
127 130
128 // Default we're a Character 131 // Default we're a Character
129 private CollisionCategories m_collisionCategories = (CollisionCategories.Character); 132 private CollisionCategories m_collisionCategories = (CollisionCategories.Character);
@@ -136,10 +139,11 @@ namespace OpenSim.Region.Physics.OdePlugin
136 // we do land collisions not ode | CollisionCategories.Land); 139 // we do land collisions not ode | CollisionCategories.Land);
137 public IntPtr Body = IntPtr.Zero; 140 public IntPtr Body = IntPtr.Zero;
138 private OdeScene _parent_scene; 141 private OdeScene _parent_scene;
139 public IntPtr topbox = IntPtr.Zero; 142 private IntPtr topbox = IntPtr.Zero;
140 public IntPtr midbox = IntPtr.Zero; 143 private IntPtr midbox = IntPtr.Zero;
141 public IntPtr feetbox = IntPtr.Zero; 144 private IntPtr feetbox = IntPtr.Zero;
142 public IntPtr bonebox = IntPtr.Zero; 145 private IntPtr bbox = IntPtr.Zero;
146 public IntPtr collider = IntPtr.Zero;
143 147
144 public IntPtr Amotor = IntPtr.Zero; 148 public IntPtr Amotor = IntPtr.Zero;
145 149
@@ -147,6 +151,7 @@ namespace OpenSim.Region.Physics.OdePlugin
147 151
148 152
149 153
154
150 public int m_eventsubscription = 0; 155 public int m_eventsubscription = 0;
151 private int m_cureventsubscription = 0; 156 private int m_cureventsubscription = 0;
152 private CollisionEventUpdate CollisionEventsThisFrame = null; 157 private CollisionEventUpdate CollisionEventsThisFrame = null;
@@ -160,9 +165,13 @@ namespace OpenSim.Region.Physics.OdePlugin
160 165
161 166
162 167
163 public OdeCharacter(String avName, OdeScene parent_scene, Vector3 pos, Vector3 pSize, float pid_d, float pid_p, float density, float walk_divisor, float rundivisor) 168 public OdeCharacter(uint localID, String avName, OdeScene parent_scene, Vector3 pos, Vector3 pSize, float pfeetOffset, float density, float walk_divisor, float rundivisor)
164 { 169 {
165 m_uuid = UUID.Random(); 170 m_uuid = UUID.Random();
171 m_localID = localID;
172
173 timeStep = parent_scene.ODE_STEPSIZE;
174 invtimeStep = 1 / timeStep;
166 175
167 if (pos.IsFinite()) 176 if (pos.IsFinite())
168 { 177 {
@@ -184,8 +193,6 @@ namespace OpenSim.Region.Physics.OdePlugin
184 193
185 _parent_scene = parent_scene; 194 _parent_scene = parent_scene;
186 195
187 PID_D = pid_d;
188 PID_P = pid_p;
189 196
190 m_size.X = pSize.X; 197 m_size.X = pSize.X;
191 m_size.Y = pSize.Y; 198 m_size.Y = pSize.Y;
@@ -198,12 +205,15 @@ namespace OpenSim.Region.Physics.OdePlugin
198 if(m_size.Z <0.01f) 205 if(m_size.Z <0.01f)
199 m_size.Z = 0.01f; 206 m_size.Z = 0.01f;
200 207
208 m_feetOffset = pfeetOffset;
201 m_orientation = Quaternion.Identity; 209 m_orientation = Quaternion.Identity;
202 m_density = density; 210 m_density = density;
203 211
204 // force lower density for testing 212 // force lower density for testing
205 m_density = 3.0f; 213 m_density = 3.0f;
206 214
215 m_density *= 1.4f; // scale to have mass similar to capsule
216
207 mu = parent_scene.AvatarFriction; 217 mu = parent_scene.AvatarFriction;
208 218
209 walkDivisor = walk_divisor; 219 walkDivisor = walk_divisor;
@@ -211,6 +221,9 @@ namespace OpenSim.Region.Physics.OdePlugin
211 221
212 m_mass = m_density * m_size.X * m_size.Y * m_size.Z; ; // sure we have a default 222 m_mass = m_density * m_size.X * m_size.Y * m_size.Z; ; // sure we have a default
213 223
224 PID_D = basePID_D * m_mass * invtimeStep;
225 PID_P = basePID_P * m_mass * invtimeStep;
226
214 m_isPhysical = false; // current status: no ODE information exists 227 m_isPhysical = false; // current status: no ODE information exists
215 228
216 Name = avName; 229 Name = avName;
@@ -292,7 +305,7 @@ namespace OpenSim.Region.Physics.OdePlugin
292 set 305 set
293 { 306 {
294 flying = value; 307 flying = value;
295 // m_log.DebugFormat("[PHYSICS]: Set OdeCharacter Flying to {0}", flying); 308// m_log.DebugFormat("[PHYSICS]: Set OdeCharacter Flying to {0}", flying);
296 } 309 }
297 } 310 }
298 311
@@ -336,25 +349,25 @@ namespace OpenSim.Region.Physics.OdePlugin
336 get { return m_iscollidingGround; } 349 get { return m_iscollidingGround; }
337 set 350 set
338 { 351 {
339 /* we now control this 352/* we now control this
340 if (value) 353 if (value)
341 { 354 {
342 m_colliderGroundfilter += 2; 355 m_colliderGroundfilter += 2;
343 if (m_colliderGroundfilter > 2) 356 if (m_colliderGroundfilter > 2)
344 m_colliderGroundfilter = 2; 357 m_colliderGroundfilter = 2;
345 } 358 }
346 else 359 else
347 { 360 {
348 m_colliderGroundfilter--; 361 m_colliderGroundfilter--;
349 if (m_colliderGroundfilter < 0) 362 if (m_colliderGroundfilter < 0)
350 m_colliderGroundfilter = 0; 363 m_colliderGroundfilter = 0;
351 } 364 }
352 365
353 if (m_colliderGroundfilter == 0) 366 if (m_colliderGroundfilter == 0)
354 m_iscollidingGround = false; 367 m_iscollidingGround = false;
355 else 368 else
356 m_iscollidingGround = true; 369 m_iscollidingGround = true;
357 */ 370 */
358 } 371 }
359 372
360 } 373 }
@@ -386,7 +399,7 @@ namespace OpenSim.Region.Physics.OdePlugin
386 else 399 else
387 m_iscollidingObj = true; 400 m_iscollidingObj = true;
388 401
389 // m_iscollidingObj = value; 402// m_iscollidingObj = value;
390 403
391 if (m_iscollidingObj) 404 if (m_iscollidingObj)
392 m_pidControllerActive = false; 405 m_pidControllerActive = false;
@@ -475,6 +488,28 @@ namespace OpenSim.Region.Physics.OdePlugin
475 } 488 }
476 } 489 }
477 490
491 public override void setAvatarSize(Vector3 size, float feetOffset)
492 {
493 if (size.IsFinite())
494 {
495 if (size.X < 0.01f)
496 size.X = 0.01f;
497 if (size.Y < 0.01f)
498 size.Y = 0.01f;
499 if (size.Z < 0.01f)
500 size.Z = 0.01f;
501
502 strAvatarSize st = new strAvatarSize();
503 st.size = size;
504 st.offset = feetOffset;
505 AddChange(changes.AvatarSize, st);
506 }
507 else
508 {
509 m_log.Warn("[PHYSICS]: Got a NaN AvatarSize from Scene on a Character");
510 }
511
512 }
478 /// <summary> 513 /// <summary>
479 /// This creates the Avatar's physical Surrogate at the position supplied 514 /// This creates the Avatar's physical Surrogate at the position supplied
480 /// </summary> 515 /// </summary>
@@ -491,7 +526,7 @@ namespace OpenSim.Region.Physics.OdePlugin
491 { 526 {
492 get 527 get
493 { 528 {
494 return m_density * m_size.X * m_size.Y * m_size.Z; 529 return m_mass;
495 } 530 }
496 } 531 }
497 public override void link(PhysicsActor obj) 532 public override void link(PhysicsActor obj)
@@ -612,8 +647,8 @@ namespace OpenSim.Region.Physics.OdePlugin
612 get { return m_orientation; } 647 get { return m_orientation; }
613 set 648 set
614 { 649 {
615 // fakeori = value; 650// fakeori = value;
616 // givefakeori++; 651// givefakeori++;
617 652
618 value.Normalize(); 653 value.Normalize();
619 AddChange(changes.Orientation, value); 654 AddChange(changes.Orientation, value);
@@ -668,33 +703,72 @@ namespace OpenSim.Region.Physics.OdePlugin
668 AddChange(changes.Momentum, momentum); 703 AddChange(changes.Momentum, momentum);
669 } 704 }
670 705
706 private void ajustCollider()
707 {
708 float vq = _velocity.LengthSquared();
709 if (m_lastVelocitySqr != vq)
710 {
711 m_lastVelocitySqr = vq;
712 if (vq > 100.0f)
713 {
714 Vector3 off = _velocity;
715 float t = 0.5f * timeStep;
716 off = off * t;
717 d.GeomSetOffsetPosition(bbox, off.X, off.Y, off.Z);
718 off.X = 2.0f * (m_size.X + Math.Abs(off.X));
719 off.Y = 2.0f * (m_size.Y + Math.Abs(off.Y));
720 off.Z = m_size.Z + 2.0f * Math.Abs(off.Z);
721 d.GeomBoxSetLengths(bbox, off.X, off.Y, off.Z);
722
723 d.GeomSetCategoryBits(bbox, (uint)m_collisionCategories);
724 d.GeomSetCollideBits(bbox, (uint)m_collisionFlags);
725 d.GeomSetCategoryBits(topbox, 0);
726 d.GeomSetCollideBits(topbox, 0);
727 d.GeomSetCategoryBits(midbox, 0);
728 d.GeomSetCollideBits(midbox, 0);
729 d.GeomSetCategoryBits(feetbox, 0);
730 d.GeomSetCollideBits(feetbox, 0);
731 }
732 else
733 {
734 d.GeomSetCategoryBits(bbox, 0);
735 d.GeomSetCollideBits(bbox, 0);
736 d.GeomSetCategoryBits(topbox, (uint)m_collisionCategories);
737 d.GeomSetCollideBits(topbox, (uint)m_collisionFlags);
738 d.GeomSetCategoryBits(midbox, (uint)m_collisionCategories);
739 d.GeomSetCollideBits(midbox, (uint)m_collisionFlags);
740 d.GeomSetCategoryBits(feetbox, (uint)m_collisionCategories);
741 d.GeomSetCollideBits(feetbox, (uint)m_collisionFlags);
742 }
743 }
744 }
745
671 private void AvatarGeomAndBodyCreation(float npositionX, float npositionY, float npositionZ) 746 private void AvatarGeomAndBodyCreation(float npositionX, float npositionY, float npositionZ)
672 { 747 {
673 // sizes one day should came from visual parameters 748 // sizes one day should came from visual parameters
674 float sz = m_size.Z + sizeZAdjust; 749 float sx = m_size.X;
675 750 float sy = m_size.Y;
676 m_invElipSizeX = 1.0f / m_size.X; 751 float sz = m_size.Z;
677 m_invElipSizeY = 1.0f / m_size.Y; 752
678 753 float topsx = sx * 0.9f;
679 float topsx = m_size.X; 754 float midsx = sx;
680 float midsx = m_size.X; 755 float feetsx = sx * feetScale;
681 float feetsx = m_size.X * feetScale; 756 float bonesx = sx * 0.2f;
682 float bonesx = feetsx * 0.2f; 757
683 758 float topsy = sy * 0.4f;
684 float topsy = m_size.Y * 0.5f; 759 float midsy = sy;
685 float midsy = m_size.Y; 760 float feetsy = sy * feetScale * 0.8f;
686 float feetsy = m_size.Y * feetScale;
687 float bonesy = feetsy * 0.2f; 761 float bonesy = feetsy * 0.2f;
688 762
689 float topsz = sz * 0.15f; 763 float topsz = sz * 0.15f;
690 float feetsz = sz * 0.3f; 764 float feetsz = sz * 0.45f;
691 if (feetsz > 0.6f) 765 if (feetsz > 0.6f)
692 feetsz = 0.6f; 766 feetsz = 0.6f;
693 767
694 float midsz = sz - topsz - feetsz; 768 float midsz = sz - topsz - feetsz;
695 float bonesz = sz; 769 float bonesz = sz;
696 770
697 float bot = -sz * 0.5f; 771 float bot = -sz * 0.5f + m_feetOffset;
698 772
699 boneOff = bot + 0.3f; 773 boneOff = bot + 0.3f;
700 774
@@ -708,47 +782,37 @@ namespace OpenSim.Region.Physics.OdePlugin
708 bot += midsz; 782 bot += midsz;
709 float topz = bot + topsz * 0.5f; 783 float topz = bot + topsz * 0.5f;
710 784
711 _parent_scene.waitForSpaceUnlock(_parent_scene.ActiveSpace); 785 _parent_scene.waitForSpaceUnlock(_parent_scene.CharsSpace);
712
713 feetbox = d.CreateBox(_parent_scene.ActiveSpace, feetsx, feetsy, feetsz);
714 d.GeomSetCategoryBits(feetbox, (uint)m_collisionCategories);
715 d.GeomSetCollideBits(feetbox, (uint)m_collisionFlags);
716
717 midbox = d.CreateBox(_parent_scene.ActiveSpace, midsx, midsy, midsz);
718 d.GeomSetCategoryBits(midbox, (uint)m_collisionCategories);
719 d.GeomSetCollideBits(midbox, (uint)m_collisionFlags);
720
721 topbox = d.CreateBox(_parent_scene.ActiveSpace, topsx, topsy, topsz);
722 d.GeomSetCategoryBits(topbox, (uint)m_collisionCategories);
723 d.GeomSetCollideBits(topbox, (uint)m_collisionFlags);
724 786
725 bonebox = d.CreateBox(_parent_scene.ActiveSpace, bonesx, bonesy, bonesz); 787 collider = d.HashSpaceCreate(_parent_scene.CharsSpace);
726 d.GeomSetCategoryBits(bonebox, (uint)m_collisionCategories); 788 d.HashSpaceSetLevels(collider, -4, 3);
727 d.GeomSetCollideBits(bonebox, (uint)m_collisionFlags); 789 d.SpaceSetSublevel(collider, 3);
790 d.SpaceSetCleanup(collider, false);
791 d.GeomSetCategoryBits(collider, (uint)m_collisionCategories);
792 d.GeomSetCollideBits(collider, (uint)m_collisionFlags);
728 793
729 d.MassSetBox(out ShellMass, m_density, m_size.X , m_size.Y, m_size.Z); 794 feetbox = d.CreateBox(collider, feetsx, feetsy, feetsz);
795 midbox = d.CreateBox(collider, midsx, midsy, midsz);
796 topbox = d.CreateBox(collider, topsx, topsy, topsz);
797 bbox = d.CreateBox(collider, m_size.X, m_size.Y, m_size.Z);
730 798
731 m_mass = ShellMass.mass; // update mass 799 m_mass = m_density * m_size.X * m_size.Y * m_size.Z; // update mass
732 800
733 // rescale PID parameters 801 d.MassSetBoxTotal(out ShellMass, m_mass, m_size.X, m_size.Y, m_size.Z);
734 PID_D = _parent_scene.avPIDD;
735 PID_P = _parent_scene.avPIDP;
736 802
737 // rescale PID parameters so that this aren't affected by mass 803 PID_D = basePID_D * m_mass / _parent_scene.ODE_STEPSIZE;
738 // and so don't get unstable for some masses 804 PID_P = basePID_P * m_mass / _parent_scene.ODE_STEPSIZE;
739 // also scale by ode time step so you don't need to refix them
740
741 PID_D /= 50 * 80; //scale to original mass of around 80 and 50 ODE fps
742 PID_D *= m_mass / _parent_scene.ODE_STEPSIZE;
743 PID_P /= 50 * 80;
744 PID_P *= m_mass / _parent_scene.ODE_STEPSIZE;
745 805
746 Body = d.BodyCreate(_parent_scene.world); 806 Body = d.BodyCreate(_parent_scene.world);
747 807
748 _zeroFlag = false; 808 _zeroFlag = false;
809 m_collisionException = false;
749 m_pidControllerActive = true; 810 m_pidControllerActive = true;
750 m_freemove = false; 811 m_freemove = false;
751 812
813 _velocity = Vector3.Zero;
814 m_lastVelocitySqr = 0;
815
752 d.BodySetAutoDisableFlag(Body, false); 816 d.BodySetAutoDisableFlag(Body, false);
753 d.BodySetPosition(Body, npositionX, npositionY, npositionZ); 817 d.BodySetPosition(Body, npositionX, npositionY, npositionZ);
754 818
@@ -760,12 +824,15 @@ namespace OpenSim.Region.Physics.OdePlugin
760 d.GeomSetBody(feetbox, Body); 824 d.GeomSetBody(feetbox, Body);
761 d.GeomSetBody(midbox, Body); 825 d.GeomSetBody(midbox, Body);
762 d.GeomSetBody(topbox, Body); 826 d.GeomSetBody(topbox, Body);
763 d.GeomSetBody(bonebox, Body); 827 d.GeomSetBody(bbox, Body);
764 828
765 d.GeomSetOffsetPosition(feetbox, 0, 0, feetz); 829 d.GeomSetOffsetPosition(feetbox, 0, 0, feetz);
766 d.GeomSetOffsetPosition(midbox, 0, 0, midz); 830 d.GeomSetOffsetPosition(midbox, 0, 0, midz);
767 d.GeomSetOffsetPosition(topbox, 0, 0, topz); 831 d.GeomSetOffsetPosition(topbox, 0, 0, topz);
768 832
833 ajustCollider();
834
835
769 // The purpose of the AMotor here is to keep the avatar's physical 836 // The purpose of the AMotor here is to keep the avatar's physical
770 // surrogate from rotating while moving 837 // surrogate from rotating while moving
771 Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero); 838 Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero);
@@ -828,86 +895,136 @@ namespace OpenSim.Region.Physics.OdePlugin
828 if (topbox != IntPtr.Zero) 895 if (topbox != IntPtr.Zero)
829 { 896 {
830 _parent_scene.actor_name_map.Remove(topbox); 897 _parent_scene.actor_name_map.Remove(topbox);
831 _parent_scene.waitForSpaceUnlock(_parent_scene.ActiveSpace); 898 _parent_scene.waitForSpaceUnlock(collider);
832 d.GeomDestroy(topbox); 899 d.GeomDestroy(topbox);
833 topbox = IntPtr.Zero; 900 topbox = IntPtr.Zero;
834 } 901 }
835 if (midbox != IntPtr.Zero) 902 if (midbox != IntPtr.Zero)
836 { 903 {
837 _parent_scene.actor_name_map.Remove(midbox); 904 _parent_scene.actor_name_map.Remove(midbox);
838 _parent_scene.waitForSpaceUnlock(_parent_scene.ActiveSpace); 905 _parent_scene.waitForSpaceUnlock(collider);
839 d.GeomDestroy(midbox); 906 d.GeomDestroy(midbox);
840 midbox = IntPtr.Zero; 907 midbox = IntPtr.Zero;
841 } 908 }
842 if (feetbox != IntPtr.Zero) 909 if (feetbox != IntPtr.Zero)
843 { 910 {
844 _parent_scene.actor_name_map.Remove(feetbox); 911 _parent_scene.actor_name_map.Remove(feetbox);
845 _parent_scene.waitForSpaceUnlock(_parent_scene.ActiveSpace); 912 _parent_scene.waitForSpaceUnlock(collider);
846 d.GeomDestroy(feetbox); 913 d.GeomDestroy(feetbox);
847 feetbox = IntPtr.Zero; 914 feetbox = IntPtr.Zero;
848 } 915 }
849 916
850 if (bonebox != IntPtr.Zero) 917 if (bbox != IntPtr.Zero)
851 { 918 {
852 _parent_scene.actor_name_map.Remove(bonebox); 919 _parent_scene.actor_name_map.Remove(bbox);
853 _parent_scene.waitForSpaceUnlock(_parent_scene.ActiveSpace); 920 _parent_scene.waitForSpaceUnlock(collider);
854 d.GeomDestroy(bonebox); 921 d.GeomDestroy(bbox);
855 bonebox = IntPtr.Zero; 922 bbox = IntPtr.Zero;
923 }
924
925 if (collider != IntPtr.Zero)
926 {
927 d.SpaceDestroy(collider);
928 collider = IntPtr.Zero;
856 } 929 }
857 930
858 } 931 }
859 932
860 public bool Collide(IntPtr me, bool reverse, ref d.ContactGeom contact) 933 //in place 2D rotation around Z assuming rot is normalised and is a rotation around Z
934 public void RotateXYonZ(ref float x, ref float y, ref Quaternion rot)
861 { 935 {
936 float sin = 2.0f * rot.Z * rot.W;
937 float cos = rot.W * rot.W - rot.Z * rot.Z;
938 float tx = x;
862 939
863 if (me == bonebox) // inner bone 940 x = tx * cos - y * sin;
864 { 941 y = tx * sin + y * cos;
865 if (contact.pos.Z - _position.Z < boneOff) 942 }
866 IsColliding = true; 943 public void RotateXYonZ(ref float x, ref float y, ref float sin, ref float cos)
867 return true; 944 {
868 } 945 float tx = x;
946 x = tx * cos - y * sin;
947 y = tx * sin + y * cos;
948 }
949 public void invRotateXYonZ(ref float x, ref float y, ref float sin, ref float cos)
950 {
951 float tx = x;
952 x = tx * cos + y * sin;
953 y = -tx * sin + y * cos;
954 }
869 955
870 if (me == topbox) // keep a box head 956 public void invRotateXYonZ(ref float x, ref float y, ref Quaternion rot)
871 return true; 957 {
958 float sin = - 2.0f * rot.Z * rot.W;
959 float cos = rot.W * rot.W - rot.Z * rot.Z;
960 float tx = x;
872 961
873 // rotate elipsoide assuming only rotation around Z 962 x = tx * cos - y * sin;
874 float ca = m_orientation.W * m_orientation.W - m_orientation.Z * m_orientation.Z; 963 y = tx * sin + y * cos;
875 float sa = 2 * m_orientation.W * m_orientation.Z; 964 }
876 965
877 float isx;
878 float isy;
879 966
880 if (me == feetbox) // feet have narrow bounds 967 public bool Collide(IntPtr me, bool reverse, ref d.ContactGeom contact, ref bool feetcollision)
881 { 968 {
969 feetcollision = false;
970 if (m_collisionException)
971 return false;
882 972
883 isx = m_invElipSizeX * invFeetScale; 973 if (me == bbox) // if moving fast
884 isy = m_invElipSizeY * invFeetScale;
885 }
886 else
887 { 974 {
888 isx = m_invElipSizeX; 975 // force a full inelastic collision
889 isy = m_invElipSizeY; 976 m_collisionException = true;
977
978 Vector3 off = m_size * 0.5f;
979 off.X += contact.depth;
980 off.Y += contact.depth;
981 off.Z += contact.depth;
982 if (reverse)
983 {
984 off.X *= -contact.normal.X;
985 off.Y *= -contact.normal.Y;
986 off.Z *= -contact.normal.Z;
987 }
988 else
989 {
990 off.X *= contact.normal.X;
991 off.Y *= contact.normal.Y;
992 off.Z *= contact.normal.Z;
993 }
994
995 off.X += contact.pos.X;
996 off.Y += contact.pos.Y;
997 off.Z += contact.pos.Z;
998
999 _position = off;
1000 return false;
890 } 1001 }
891 1002
892 float a = isx * ca - isy * sa; 1003 if (me == topbox) // keep a box head
893 float b = isx * sa + isy * ca; 1004 return true;
894 1005
1006 float t;
895 float offx = contact.pos.X - _position.X; 1007 float offx = contact.pos.X - _position.X;
896 float er = offx * a;
897 er *= er;
898
899 float offy = contact.pos.Y - _position.Y; 1008 float offy = contact.pos.Y - _position.Y;
900 float ty = offy * b;
901 er += ty * ty;
902 1009
903 if (me == midbox) 1010 if (me == midbox)
904 { 1011 {
905 if (er > 4.0f) // no collision 1012 if (Math.Abs(contact.normal.Z) > 0.95f)
906 return false; 1013 {
907 if (er < 0.2f) 1014 float nz = contact.normal.Z;
908 return true; 1015 if (!reverse)
1016 nz = -nz;
1017
1018 if (nz > 0)
1019 return true; // missed head TODO
1020
1021 // missed feet collision?
1022
909 1023
910 float t = offx * offx + offy * offy; 1024 return true;
1025 }
1026
1027 t = offx * offx + offy * offy;
911 t = (float)Math.Sqrt(t); 1028 t = (float)Math.Sqrt(t);
912 t = 1 / t; 1029 t = 1 / t;
913 offx *= t; 1030 offx *= t;
@@ -930,40 +1047,58 @@ namespace OpenSim.Region.Physics.OdePlugin
930 1047
931 else if (me == feetbox) 1048 else if (me == feetbox)
932 { 1049 {
933 float c = feetSZ * 2;
934 float h = contact.pos.Z - _position.Z; 1050 float h = contact.pos.Z - _position.Z;
935 float offz = h - feetOff; // distance from top of feetbox
936 1051
937 float tz = offz / c; 1052 if (Math.Abs(contact.normal.Z) > 0.95f)
938 er += tz * tz; 1053 {
1054 if (contact.normal.Z > 0)
1055 contact.normal.Z = 1.0f;
1056 else
1057 contact.normal.Z = -1.0f;
1058 contact.normal.X = 0.0f;
1059 contact.normal.Y = 0.0f;
1060 feetcollision = true;
1061 if (h < boneOff)
1062 IsColliding = true;
1063 return true;
1064 }
1065
1066
1067 float offz = h - feetOff; // distance from top of feetbox
939 1068
940 if (er > 4.0f) // no collision 1069 if (offz > 0)
941 return false; 1070 return false;
942 1071
943 if (er > 0.2f) 1072 if (offz > -0.01)
944 { 1073 {
945 float t = offx * offx + offy * offy + offz * offz; 1074 offx = 0;
1075 offy = 0;
1076 offz = -1.0f;
1077 }
1078 else
1079 {
1080 t = offx * offx + offy * offy + offz * offz;
946 t = (float)Math.Sqrt(t); 1081 t = (float)Math.Sqrt(t);
947 t = 1 / t; 1082 t = 1 / t;
948 offx *= t; 1083 offx *= t;
949 offy *= t; 1084 offy *= t;
950 offz *= t; 1085 offz *= t;
951
952 if (reverse)
953 {
954 contact.normal.X = offx;
955 contact.normal.Y = offy;
956 contact.normal.Z = offz;
957 }
958 else
959 {
960 contact.normal.X = -offx;
961 contact.normal.Y = -offy;
962 contact.normal.Z = -offz;
963 }
964 } 1086 }
965 1087
966 if(h < boneOff) 1088 if (reverse)
1089 {
1090 contact.normal.X = offx;
1091 contact.normal.Y = offy;
1092 contact.normal.Z = offz;
1093 }
1094 else
1095 {
1096 contact.normal.X = -offx;
1097 contact.normal.Y = -offy;
1098 contact.normal.Z = -offz;
1099 }
1100 feetcollision = true;
1101 if (h < boneOff)
967 IsColliding = true; 1102 IsColliding = true;
968 } 1103 }
969 else 1104 else
@@ -977,11 +1112,28 @@ namespace OpenSim.Region.Physics.OdePlugin
977 /// This is the avatar's movement control + PID Controller 1112 /// This is the avatar's movement control + PID Controller
978 /// </summary> 1113 /// </summary>
979 /// <param name="timeStep"></param> 1114 /// <param name="timeStep"></param>
980 public void Move(float timeStep, List<OdeCharacter> defects) 1115 public void Move(List<OdeCharacter> defects)
981 { 1116 {
982 if (Body == IntPtr.Zero) 1117 if (Body == IntPtr.Zero)
983 return; 1118 return;
984 1119
1120 if (m_collisionException)
1121 {
1122 d.BodySetPosition(Body,_position.X, _position.Y, _position.Z);
1123 d.BodySetLinearVel(Body, 0, 0, 0);
1124
1125 float v = _velocity.Length();
1126 if (v != 0)
1127 {
1128 v = 6.0f / v;
1129 _velocity = _velocity * v;
1130 d.BodySetLinearVel(Body, _velocity.X, _velocity.Y, _velocity.Z);
1131 }
1132 ajustCollider();
1133 m_collisionException = false;
1134 return;
1135 }
1136
985 d.Vector3 dtmp = d.BodyGetPosition(Body); 1137 d.Vector3 dtmp = d.BodyGetPosition(Body);
986 Vector3 localpos = new Vector3(dtmp.X, dtmp.Y, dtmp.Z); 1138 Vector3 localpos = new Vector3(dtmp.X, dtmp.Y, dtmp.Z);
987 1139
@@ -1055,9 +1207,10 @@ namespace OpenSim.Region.Physics.OdePlugin
1055 1207
1056 //****************************************** 1208 //******************************************
1057 // colide with land 1209 // colide with land
1210
1058 d.AABB aabb; 1211 d.AABB aabb;
1059 d.GeomGetAABB(feetbox, out aabb); 1212 d.GeomGetAABB(feetbox, out aabb);
1060 float chrminZ = aabb.MinZ - 0.04f; // move up a bit 1213 float chrminZ = aabb.MinZ; ; // move up a bit
1061 Vector3 posch = localpos; 1214 Vector3 posch = localpos;
1062 1215
1063 float ftmp; 1216 float ftmp;
@@ -1100,11 +1253,12 @@ namespace OpenSim.Region.Physics.OdePlugin
1100 contact.PenetrationDepth = depth; 1253 contact.PenetrationDepth = depth;
1101 contact.Position.X = localpos.X; 1254 contact.Position.X = localpos.X;
1102 contact.Position.Y = localpos.Y; 1255 contact.Position.Y = localpos.Y;
1103 contact.Position.Z = chrminZ; 1256 contact.Position.Z = terrainheight;
1104 contact.SurfaceNormal.X = 0f; 1257 contact.SurfaceNormal.X = 0.0f;
1105 contact.SurfaceNormal.Y = 0f; 1258 contact.SurfaceNormal.Y = 0.0f;
1106 contact.SurfaceNormal.Z = -1f; 1259 contact.SurfaceNormal.Z = -1f;
1107 contact.RelativeSpeed = -vel.Z; 1260 contact.RelativeSpeed = -vel.Z;
1261 contact.CharacterFeet = true;
1108 AddCollisionEvent(0, contact); 1262 AddCollisionEvent(0, contact);
1109 1263
1110 vec.Z *= 0.5f; 1264 vec.Z *= 0.5f;
@@ -1123,6 +1277,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1123 m_iscollidingGround = false; 1277 m_iscollidingGround = false;
1124 } 1278 }
1125 1279
1280
1126 //****************************************** 1281 //******************************************
1127 1282
1128 bool tviszero = (_target_velocity.X == 0.0f && _target_velocity.Y == 0.0f && _target_velocity.Z == 0.0f); 1283 bool tviszero = (_target_velocity.X == 0.0f && _target_velocity.Y == 0.0f && _target_velocity.Z == 0.0f);
@@ -1258,21 +1413,58 @@ namespace OpenSim.Region.Physics.OdePlugin
1258 } 1413 }
1259 1414
1260 // update our local ideia of position velocity and aceleration 1415 // update our local ideia of position velocity and aceleration
1416 // _position = localpos;
1261 _position = localpos; 1417 _position = localpos;
1418
1262 if (_zeroFlag) 1419 if (_zeroFlag)
1263 { 1420 {
1264 _velocity = Vector3.Zero; 1421 _velocity = Vector3.Zero;
1265 _acceleration = Vector3.Zero; 1422 _acceleration = Vector3.Zero;
1423 m_rotationalVelocity = Vector3.Zero;
1266 } 1424 }
1267 else 1425 else
1268 { 1426 {
1269 _acceleration = _velocity; // previus velocity 1427 Vector3 a =_velocity; // previus velocity
1270 _velocity = vel; 1428 SetSmooth(ref _velocity, ref vel, 2);
1271 _acceleration = (vel - _acceleration) / timeStep; 1429 a = (_velocity - a) * invtimeStep;
1430 SetSmooth(ref _acceleration, ref a, 2);
1431
1432 dtmp = d.BodyGetAngularVel(Body);
1433 m_rotationalVelocity.X = 0f;
1434 m_rotationalVelocity.Y = 0f;
1435 m_rotationalVelocity.Z = dtmp.Z;
1436 Math.Round(m_rotationalVelocity.Z,3);
1272 } 1437 }
1273 1438 ajustCollider();
1439 }
1440
1441 public void round(ref Vector3 v, int digits)
1442 {
1443 v.X = (float)Math.Round(v.X, digits);
1444 v.Y = (float)Math.Round(v.Y, digits);
1445 v.Z = (float)Math.Round(v.Z, digits);
1446 }
1447
1448 public void SetSmooth(ref Vector3 dst, ref Vector3 value)
1449 {
1450 dst.X = 0.1f * dst.X + 0.9f * value.X;
1451 dst.Y = 0.1f * dst.Y + 0.9f * value.Y;
1452 dst.Z = 0.1f * dst.Z + 0.9f * value.Z;
1453 }
1454
1455 public void SetSmooth(ref Vector3 dst, ref Vector3 value, int rounddigits)
1456 {
1457 dst.X = 0.4f * dst.X + 0.6f * value.X;
1458 dst.X = (float)Math.Round(dst.X, rounddigits);
1459
1460 dst.Y = 0.4f * dst.Y + 0.6f * value.Y;
1461 dst.Y = (float)Math.Round(dst.Y, rounddigits);
1462
1463 dst.Z = 0.4f * dst.Z + 0.6f * value.Z;
1464 dst.Z = (float)Math.Round(dst.Z, rounddigits);
1274 } 1465 }
1275 1466
1467
1276 /// <summary> 1468 /// <summary>
1277 /// Updates the reported position and velocity. 1469 /// Updates the reported position and velocity.
1278 /// Used to copy variables from unmanaged space at heartbeat rate and also trigger scene updates acording 1470 /// Used to copy variables from unmanaged space at heartbeat rate and also trigger scene updates acording
@@ -1399,10 +1591,11 @@ namespace OpenSim.Region.Physics.OdePlugin
1399 1591
1400 AvatarGeomAndBodyCreation(_position.X, _position.Y, _position.Z); 1592 AvatarGeomAndBodyCreation(_position.X, _position.Y, _position.Z);
1401 1593
1402 _parent_scene.actor_name_map[topbox] = (PhysicsActor)this; 1594 _parent_scene.actor_name_map[collider] = (PhysicsActor)this;
1403 _parent_scene.actor_name_map[midbox] = (PhysicsActor)this;
1404 _parent_scene.actor_name_map[feetbox] = (PhysicsActor)this; 1595 _parent_scene.actor_name_map[feetbox] = (PhysicsActor)this;
1405 _parent_scene.actor_name_map[bonebox] = (PhysicsActor)this; 1596 _parent_scene.actor_name_map[midbox] = (PhysicsActor)this;
1597 _parent_scene.actor_name_map[topbox] = (PhysicsActor)this;
1598 _parent_scene.actor_name_map[bbox] = (PhysicsActor)this;
1406 _parent_scene.AddCharacter(this); 1599 _parent_scene.AddCharacter(this);
1407 } 1600 }
1408 else 1601 else
@@ -1431,6 +1624,12 @@ namespace OpenSim.Region.Physics.OdePlugin
1431 { 1624 {
1432 } 1625 }
1433 1626
1627 private void changeAvatarSize(strAvatarSize st)
1628 {
1629 m_feetOffset = st.offset;
1630 changeSize(st.size);
1631 }
1632
1434 private void changeSize(Vector3 pSize) 1633 private void changeSize(Vector3 pSize)
1435 { 1634 {
1436 if (pSize.IsFinite()) 1635 if (pSize.IsFinite())
@@ -1449,13 +1648,16 @@ namespace OpenSim.Region.Physics.OdePlugin
1449 _position.Z + (m_size.Z - oldsz) * 0.5f); 1648 _position.Z + (m_size.Z - oldsz) * 0.5f);
1450 1649
1451 Velocity = Vector3.Zero; 1650 Velocity = Vector3.Zero;
1651
1452 1652
1453 _parent_scene.actor_name_map[topbox] = (PhysicsActor)this; 1653 _parent_scene.actor_name_map[collider] = (PhysicsActor)this;
1454 _parent_scene.actor_name_map[midbox] = (PhysicsActor)this;
1455 _parent_scene.actor_name_map[feetbox] = (PhysicsActor)this; 1654 _parent_scene.actor_name_map[feetbox] = (PhysicsActor)this;
1456 _parent_scene.actor_name_map[bonebox] = (PhysicsActor)this; 1655 _parent_scene.actor_name_map[midbox] = (PhysicsActor)this;
1656 _parent_scene.actor_name_map[topbox] = (PhysicsActor)this;
1657 _parent_scene.actor_name_map[bbox] = (PhysicsActor)this;
1457 } 1658 }
1458 m_freemove = false; 1659 m_freemove = false;
1660 m_collisionException = false;
1459 m_pidControllerActive = true; 1661 m_pidControllerActive = true;
1460 } 1662 }
1461 else 1663 else
@@ -1564,6 +1766,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1564 1766
1565 if (Body != IntPtr.Zero) 1767 if (Body != IntPtr.Zero)
1566 d.BodySetLinearVel(Body, newmomentum.X, newmomentum.Y, newmomentum.Z); 1768 d.BodySetLinearVel(Body, newmomentum.X, newmomentum.Y, newmomentum.Z);
1769 ajustCollider();
1567 } 1770 }
1568 1771
1569 private void donullchange() 1772 private void donullchange()
@@ -1572,7 +1775,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1572 1775
1573 public bool DoAChange(changes what, object arg) 1776 public bool DoAChange(changes what, object arg)
1574 { 1777 {
1575 if (topbox == IntPtr.Zero && what != changes.Add && what != changes.Remove) 1778 if (collider == IntPtr.Zero && what != changes.Add && what != changes.Remove)
1576 { 1779 {
1577 return false; 1780 return false;
1578 } 1781 }
@@ -1638,6 +1841,10 @@ namespace OpenSim.Region.Physics.OdePlugin
1638 changeSize((Vector3)arg); 1841 changeSize((Vector3)arg);
1639 break; 1842 break;
1640 1843
1844 case changes.AvatarSize:
1845 changeAvatarSize((strAvatarSize)arg);
1846 break;
1847
1641 case changes.Momentum: 1848 case changes.Momentum:
1642 changeMomentum((Vector3)arg); 1849 changeMomentum((Vector3)arg);
1643 break; 1850 break;
@@ -1685,5 +1892,12 @@ namespace OpenSim.Region.Physics.OdePlugin
1685 { 1892 {
1686 _parent_scene.AddChange((PhysicsActor)this, what, arg); 1893 _parent_scene.AddChange((PhysicsActor)this, what, arg);
1687 } 1894 }
1895
1896 private struct strAvatarSize
1897 {
1898 public Vector3 size;
1899 public float offset;
1900 }
1901
1688 } 1902 }
1689} 1903}