aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs377
1 files changed, 295 insertions, 82 deletions
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs
index f5bf05d..3d5be3e 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs
@@ -79,14 +79,27 @@ namespace OpenSim.Region.Physics.OdePlugin
79 private Vector3 _target_velocity; 79 private Vector3 _target_velocity;
80 private Vector3 _acceleration; 80 private Vector3 _acceleration;
81 private Vector3 m_rotationalVelocity; 81 private Vector3 m_rotationalVelocity;
82 private Vector3 m_size;
83 private Quaternion m_orientation;
82 private float m_mass = 80f; 84 private float m_mass = 80f;
83 public float m_density = 60f; 85 public float m_density = 60f;
84 private bool m_pidControllerActive = true; 86 private bool m_pidControllerActive = true;
85 public float PID_D = 800.0f; 87 public float PID_D = 800.0f;
86 public float PID_P = 900.0f; 88 public float PID_P = 900.0f;
87 //private static float POSTURE_SERVO = 10000.0f; 89 //private static float POSTURE_SERVO = 10000.0f;
88 public float CAPSULE_RADIUS = 0.37f; 90
89 public float CAPSULE_LENGTH = 2.140599f; 91
92 private float m_invElipSizeX;
93 private float m_invElipSizeY;
94
95 private float feetOff = 0;
96 private float feetSZ = 0.5f;
97 const float feetScale = 0.9f;
98 const float invFeetScale = 1.0f / 0.9f;
99 const float sizeZAdjust = 0.15f;
100 private float boneOff = 0;
101
102
90 public float walkDivisor = 1.3f; 103 public float walkDivisor = 1.3f;
91 public float runDivisor = 0.8f; 104 public float runDivisor = 0.8f;
92 private bool flying = false; 105 private bool flying = false;
@@ -123,10 +136,16 @@ namespace OpenSim.Region.Physics.OdePlugin
123 // we do land collisions not ode | CollisionCategories.Land); 136 // we do land collisions not ode | CollisionCategories.Land);
124 public IntPtr Body = IntPtr.Zero; 137 public IntPtr Body = IntPtr.Zero;
125 private OdeScene _parent_scene; 138 private OdeScene _parent_scene;
126 public IntPtr Shell = IntPtr.Zero; 139 public IntPtr topbox = IntPtr.Zero;
140 public IntPtr midbox = IntPtr.Zero;
141 public IntPtr feetbox = IntPtr.Zero;
142 public IntPtr bonebox = IntPtr.Zero;
143
127 public IntPtr Amotor = IntPtr.Zero; 144 public IntPtr Amotor = IntPtr.Zero;
145
128 public d.Mass ShellMass; 146 public d.Mass ShellMass;
129// public bool collidelock = false; 147
148
130 149
131 public int m_eventsubscription = 0; 150 public int m_eventsubscription = 0;
132 private int m_cureventsubscription = 0; 151 private int m_cureventsubscription = 0;
@@ -139,7 +158,9 @@ namespace OpenSim.Region.Physics.OdePlugin
139 158
140 float mu; 159 float mu;
141 160
142 public OdeCharacter(String avName, OdeScene parent_scene, Vector3 pos, Vector3 size, float pid_d, float pid_p, float capsule_radius, float density, float walk_divisor, float rundivisor) 161
162
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)
143 { 164 {
144 m_uuid = UUID.Random(); 165 m_uuid = UUID.Random();
145 166
@@ -165,9 +186,20 @@ namespace OpenSim.Region.Physics.OdePlugin
165 186
166 PID_D = pid_d; 187 PID_D = pid_d;
167 PID_P = pid_p; 188 PID_P = pid_p;
168 CAPSULE_RADIUS = capsule_radius; 189
190 m_size.X = pSize.X;
191 m_size.Y = pSize.Y;
192 m_size.Z = pSize.Z;
193
194 if(m_size.X <0.01f)
195 m_size.X = 0.01f;
196 if(m_size.Y <0.01f)
197 m_size.Y = 0.01f;
198 if(m_size.Z <0.01f)
199 m_size.Z = 0.01f;
200
201 m_orientation = Quaternion.Identity;
169 m_density = density; 202 m_density = density;
170 m_mass = 80f; // sure we have a default
171 203
172 // force lower density for testing 204 // force lower density for testing
173 m_density = 3.0f; 205 m_density = 3.0f;
@@ -177,8 +209,7 @@ namespace OpenSim.Region.Physics.OdePlugin
177 walkDivisor = walk_divisor; 209 walkDivisor = walk_divisor;
178 runDivisor = rundivisor; 210 runDivisor = rundivisor;
179 211
180 CAPSULE_LENGTH = size.Z * 1.15f - CAPSULE_RADIUS * 2.0f; 212 m_mass = m_density * m_size.X * m_size.Y * m_size.Z; ; // sure we have a default
181 //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString());
182 213
183 m_isPhysical = false; // current status: no ODE information exists 214 m_isPhysical = false; // current status: no ODE information exists
184 215
@@ -420,13 +451,21 @@ namespace OpenSim.Region.Physics.OdePlugin
420 /// </summary> 451 /// </summary>
421 public override Vector3 Size 452 public override Vector3 Size
422 { 453 {
423 get { 454 get
424 float d = CAPSULE_RADIUS * 2; 455 {
425 return new Vector3(d, d, (CAPSULE_LENGTH +d)/1.15f); } 456 return m_size;
457 }
426 set 458 set
427 { 459 {
428 if (value.IsFinite()) 460 if (value.IsFinite())
429 { 461 {
462 if(value.X <0.01f)
463 value.X = 0.01f;
464 if(value.Y <0.01f)
465 value.Y = 0.01f;
466 if(value.Z <0.01f)
467 value.Z = 0.01f;
468
430 AddChange(changes.Size, value); 469 AddChange(changes.Size, value);
431 } 470 }
432 else 471 else
@@ -452,8 +491,7 @@ namespace OpenSim.Region.Physics.OdePlugin
452 { 491 {
453 get 492 get
454 { 493 {
455 float AVvolume = (float)(Math.PI * CAPSULE_RADIUS * CAPSULE_RADIUS * (1.3333333333f * CAPSULE_RADIUS + CAPSULE_LENGTH)); 494 return m_density * m_size.X * m_size.Y * m_size.Z;
456 return m_density * AVvolume;
457 } 495 }
458 } 496 }
459 public override void link(PhysicsActor obj) 497 public override void link(PhysicsActor obj)
@@ -571,9 +609,14 @@ namespace OpenSim.Region.Physics.OdePlugin
571 609
572 public override Quaternion Orientation 610 public override Quaternion Orientation
573 { 611 {
574 get { return Quaternion.Identity; } 612 get { return m_orientation; }
575 set 613 set
576 { 614 {
615 // fakeori = value;
616 // givefakeori++;
617
618 value.Normalize();
619 AddChange(changes.Orientation, value);
577 } 620 }
578 } 621 }
579 622
@@ -625,32 +668,65 @@ namespace OpenSim.Region.Physics.OdePlugin
625 AddChange(changes.Momentum, momentum); 668 AddChange(changes.Momentum, momentum);
626 } 669 }
627 670
628
629 // WARNING: This MUST NOT be called outside of ProcessTaints, else we can have unsynchronized access
630 // to ODE internals. ProcessTaints is called from within thread-locked Simulate(), so it is the only
631 // place that is safe to call this routine AvatarGeomAndBodyCreation.
632 private void AvatarGeomAndBodyCreation(float npositionX, float npositionY, float npositionZ) 671 private void AvatarGeomAndBodyCreation(float npositionX, float npositionY, float npositionZ)
633 { 672 {
673 // sizes one day should came from visual parameters
674 float sz = m_size.Z + sizeZAdjust;
675
676 m_invElipSizeX = 1.0f / m_size.X;
677 m_invElipSizeY = 1.0f / m_size.Y;
678
679 float topsx = m_size.X;
680 float midsx = m_size.X;
681 float feetsx = m_size.X * feetScale;
682 float bonesx = feetsx * 0.2f;
683
684 float topsy = m_size.Y * 0.5f;
685 float midsy = m_size.Y;
686 float feetsy = m_size.Y * feetScale;
687 float bonesy = feetsy * 0.2f;
688
689 float topsz = sz * 0.15f;
690 float feetsz = sz * 0.3f;
691 if (feetsz > 0.6f)
692 feetsz = 0.6f;
693
694 float midsz = sz - topsz - feetsz;
695 float bonesz = sz;
696
697 float bot = -sz * 0.5f;
698
699 boneOff = bot + 0.3f;
700
701 float feetz = bot + feetsz * 0.5f;
702 bot += feetsz;
703
704 feetOff = bot;
705 feetSZ = feetsz;
706
707 float midz = bot + midsz * 0.5f;
708 bot += midsz;
709 float topz = bot + topsz * 0.5f;
710
634 _parent_scene.waitForSpaceUnlock(_parent_scene.ActiveSpace); 711 _parent_scene.waitForSpaceUnlock(_parent_scene.ActiveSpace);
635 if (CAPSULE_LENGTH <= 0)
636 {
637 m_log.Warn("[PHYSICS]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!");
638 CAPSULE_LENGTH = 0.01f;
639 712
640 } 713 feetbox = d.CreateBox(_parent_scene.ActiveSpace, feetsx, feetsy, feetsz);
714 d.GeomSetCategoryBits(feetbox, (uint)m_collisionCategories);
715 d.GeomSetCollideBits(feetbox, (uint)m_collisionFlags);
641 716
642 if (CAPSULE_RADIUS <= 0) 717 midbox = d.CreateBox(_parent_scene.ActiveSpace, midsx, midsy, midsz);
643 { 718 d.GeomSetCategoryBits(midbox, (uint)m_collisionCategories);
644 m_log.Warn("[PHYSICS]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!"); 719 d.GeomSetCollideBits(midbox, (uint)m_collisionFlags);
645 CAPSULE_RADIUS = 0.01f;
646 720
647 } 721 topbox = d.CreateBox(_parent_scene.ActiveSpace, topsx, topsy, topsz);
648 Shell = d.CreateCapsule(_parent_scene.ActiveSpace, CAPSULE_RADIUS, CAPSULE_LENGTH); 722 d.GeomSetCategoryBits(topbox, (uint)m_collisionCategories);
723 d.GeomSetCollideBits(topbox, (uint)m_collisionFlags);
649 724
650 d.GeomSetCategoryBits(Shell, (uint)m_collisionCategories); 725 bonebox = d.CreateBox(_parent_scene.ActiveSpace, bonesx, bonesy, bonesz);
651 d.GeomSetCollideBits(Shell, (uint)m_collisionFlags); 726 d.GeomSetCategoryBits(bonebox, (uint)m_collisionCategories);
727 d.GeomSetCollideBits(bonebox, (uint)m_collisionFlags);
652 728
653 d.MassSetCapsule(out ShellMass, m_density, 3, CAPSULE_RADIUS, CAPSULE_LENGTH); 729 d.MassSetBox(out ShellMass, m_density, m_size.X , m_size.Y, m_size.Z);
654 730
655 m_mass = ShellMass.mass; // update mass 731 m_mass = ShellMass.mass; // update mass
656 732
@@ -681,7 +757,14 @@ namespace OpenSim.Region.Physics.OdePlugin
681 _position.Z = npositionZ; 757 _position.Z = npositionZ;
682 758
683 d.BodySetMass(Body, ref ShellMass); 759 d.BodySetMass(Body, ref ShellMass);
684 d.GeomSetBody(Shell, Body); 760 d.GeomSetBody(feetbox, Body);
761 d.GeomSetBody(midbox, Body);
762 d.GeomSetBody(topbox, Body);
763 d.GeomSetBody(bonebox, Body);
764
765 d.GeomSetOffsetPosition(feetbox, 0, 0, feetz);
766 d.GeomSetOffsetPosition(midbox, 0, 0, midz);
767 d.GeomSetOffsetPosition(topbox, 0, 0, topz);
685 768
686 // The purpose of the AMotor here is to keep the avatar's physical 769 // The purpose of the AMotor here is to keep the avatar's physical
687 // surrogate from rotating while moving 770 // surrogate from rotating while moving
@@ -741,15 +824,152 @@ namespace OpenSim.Region.Physics.OdePlugin
741 Body = IntPtr.Zero; 824 Body = IntPtr.Zero;
742 } 825 }
743 826
744 //kill the Geometry 827 //kill the Geoms
745 if (Shell != IntPtr.Zero) 828 if (topbox != IntPtr.Zero)
829 {
830 _parent_scene.actor_name_map.Remove(topbox);
831 _parent_scene.waitForSpaceUnlock(_parent_scene.ActiveSpace);
832 d.GeomDestroy(topbox);
833 topbox = IntPtr.Zero;
834 }
835 if (midbox != IntPtr.Zero)
836 {
837 _parent_scene.actor_name_map.Remove(midbox);
838 _parent_scene.waitForSpaceUnlock(_parent_scene.ActiveSpace);
839 d.GeomDestroy(midbox);
840 midbox = IntPtr.Zero;
841 }
842 if (feetbox != IntPtr.Zero)
843 {
844 _parent_scene.actor_name_map.Remove(feetbox);
845 _parent_scene.waitForSpaceUnlock(_parent_scene.ActiveSpace);
846 d.GeomDestroy(feetbox);
847 feetbox = IntPtr.Zero;
848 }
849
850 if (bonebox != IntPtr.Zero)
746 { 851 {
747// _parent_scene.geom_name_map.Remove(Shell); 852 _parent_scene.actor_name_map.Remove(bonebox);
748 _parent_scene.actor_name_map.Remove(Shell);
749 _parent_scene.waitForSpaceUnlock(_parent_scene.ActiveSpace); 853 _parent_scene.waitForSpaceUnlock(_parent_scene.ActiveSpace);
750 d.GeomDestroy(Shell); 854 d.GeomDestroy(bonebox);
751 Shell = IntPtr.Zero; 855 bonebox = IntPtr.Zero;
856 }
857
858 }
859
860 public bool Collide(IntPtr me, bool reverse, ref d.ContactGeom contact)
861 {
862
863 if (me == bonebox) // inner bone
864 {
865 if (contact.pos.Z - _position.Z < boneOff)
866 IsColliding = true;
867 return true;
752 } 868 }
869
870 if (me == topbox) // keep a box head
871 return true;
872
873 // rotate elipsoide assuming only rotation around Z
874 float ca = m_orientation.W * m_orientation.W - m_orientation.Z * m_orientation.Z;
875 float sa = 2 * m_orientation.W * m_orientation.Z;
876
877 float isx;
878 float isy;
879
880 if (me == feetbox) // feet have narrow bounds
881 {
882
883 isx = m_invElipSizeX * invFeetScale;
884 isy = m_invElipSizeY * invFeetScale;
885 }
886 else
887 {
888 isx = m_invElipSizeX;
889 isy = m_invElipSizeY;
890 }
891
892 float a = isx * ca - isy * sa;
893 float b = isx * sa + isy * ca;
894
895 float offx = contact.pos.X - _position.X;
896 float er = offx * a;
897 er *= er;
898
899 float offy = contact.pos.Y - _position.Y;
900 float ty = offy * b;
901 er += ty * ty;
902
903 if (me == midbox)
904 {
905 if (er > 4.0f) // no collision
906 return false;
907 if (er < 0.2f)
908 return true;
909
910 float t = offx * offx + offy * offy;
911 t = (float)Math.Sqrt(t);
912 t = 1 / t;
913 offx *= t;
914 offy *= t;
915
916 if (reverse)
917 {
918 contact.normal.X = offx;
919 contact.normal.Y = offy;
920 }
921 else
922 {
923 contact.normal.X = -offx;
924 contact.normal.Y = -offy;
925 }
926
927 contact.normal.Z = 0;
928 return true;
929 }
930
931 else if (me == feetbox)
932 {
933 float c = feetSZ * 2;
934 float h = contact.pos.Z - _position.Z;
935 float offz = h - feetOff; // distance from top of feetbox
936
937 float tz = offz / c;
938 er += tz * tz;
939
940 if (er > 4.0f) // no collision
941 return false;
942
943 if (er > 0.2f)
944 {
945 float t = offx * offx + offy * offy + offz * offz;
946 t = (float)Math.Sqrt(t);
947 t = 1 / t;
948 offx *= t;
949 offy *= t;
950 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 }
965
966 if(h < boneOff)
967 IsColliding = true;
968 }
969 else
970 return false;
971
972 return true;
753 } 973 }
754 974
755 /// <summary> 975 /// <summary>
@@ -769,10 +989,10 @@ namespace OpenSim.Region.Physics.OdePlugin
769 // so force it back to identity 989 // so force it back to identity
770 990
771 d.Quaternion qtmp; 991 d.Quaternion qtmp;
772 qtmp.W = 1; 992 qtmp.W = m_orientation.W;
773 qtmp.X = 0; 993 qtmp.X = m_orientation.X;
774 qtmp.Y = 0; 994 qtmp.Y = m_orientation.Y;
775 qtmp.Z = 0; 995 qtmp.Z = m_orientation.Z;
776 d.BodySetQuaternion(Body, ref qtmp); 996 d.BodySetQuaternion(Body, ref qtmp);
777 997
778 if (m_pidControllerActive == false) 998 if (m_pidControllerActive == false)
@@ -836,9 +1056,8 @@ namespace OpenSim.Region.Physics.OdePlugin
836 //****************************************** 1056 //******************************************
837 // colide with land 1057 // colide with land
838 d.AABB aabb; 1058 d.AABB aabb;
839 d.GeomGetAABB(Shell, out aabb); 1059 d.GeomGetAABB(feetbox, out aabb);
840 float chrminZ = aabb.MinZ; 1060 float chrminZ = aabb.MinZ - 0.04f; // move up a bit
841
842 Vector3 posch = localpos; 1061 Vector3 posch = localpos;
843 1062
844 float ftmp; 1063 float ftmp;
@@ -1176,20 +1395,14 @@ namespace OpenSim.Region.Physics.OdePlugin
1176 { 1395 {
1177 if (NewStatus) 1396 if (NewStatus)
1178 { 1397 {
1179 // Create avatar capsule and related ODE data 1398 AvatarGeomAndBodyDestroy();
1180 if ((Shell != IntPtr.Zero))
1181 {
1182 // a lost shell ?
1183 m_log.Warn("[PHYSICS]: re-creating the following avatar ODE data, even though it already exists - "
1184 + (Shell != IntPtr.Zero ? "Shell " : "")
1185 + (Body != IntPtr.Zero ? "Body " : "")
1186 + (Amotor != IntPtr.Zero ? "Amotor " : ""));
1187 AvatarGeomAndBodyDestroy();
1188 }
1189 1399
1190 AvatarGeomAndBodyCreation(_position.X, _position.Y, _position.Z); 1400 AvatarGeomAndBodyCreation(_position.X, _position.Y, _position.Z);
1191 1401
1192 _parent_scene.actor_name_map[Shell] = (PhysicsActor)this; 1402 _parent_scene.actor_name_map[topbox] = (PhysicsActor)this;
1403 _parent_scene.actor_name_map[midbox] = (PhysicsActor)this;
1404 _parent_scene.actor_name_map[feetbox] = (PhysicsActor)this;
1405 _parent_scene.actor_name_map[bonebox] = (PhysicsActor)this;
1193 _parent_scene.AddCharacter(this); 1406 _parent_scene.AddCharacter(this);
1194 } 1407 }
1195 else 1408 else
@@ -1218,37 +1431,29 @@ namespace OpenSim.Region.Physics.OdePlugin
1218 { 1431 {
1219 } 1432 }
1220 1433
1221 private void changeSize(Vector3 Size) 1434 private void changeSize(Vector3 pSize)
1222 { 1435 {
1223 if (Size.IsFinite()) 1436 if (pSize.IsFinite())
1224 { 1437 {
1225 float caplen = Size.Z; 1438 // for now only look to Z changes since viewers also don't change X and Y
1439 if (pSize.Z != m_size.Z)
1440 {
1441 AvatarGeomAndBodyDestroy();
1226 1442
1227 caplen = caplen * 1.15f - CAPSULE_RADIUS * 2.0f;
1228 1443
1229 if (caplen != CAPSULE_LENGTH) 1444 float oldsz = m_size.Z;
1230 { 1445 m_size = pSize;
1231 if (Shell != IntPtr.Zero && Body != IntPtr.Zero && Amotor != IntPtr.Zero)
1232 {
1233 AvatarGeomAndBodyDestroy();
1234 1446
1235 float prevCapsule = CAPSULE_LENGTH;
1236 CAPSULE_LENGTH = caplen;
1237 1447
1238 AvatarGeomAndBodyCreation(_position.X, _position.Y, 1448 AvatarGeomAndBodyCreation(_position.X, _position.Y,
1239 _position.Z + (CAPSULE_LENGTH - prevCapsule) * 0.5f); 1449 _position.Z + (m_size.Z - oldsz) * 0.5f);
1240 1450
1241 Velocity = Vector3.Zero; 1451 Velocity = Vector3.Zero;
1242 1452
1243 _parent_scene.actor_name_map[Shell] = (PhysicsActor)this; 1453 _parent_scene.actor_name_map[topbox] = (PhysicsActor)this;
1244 } 1454 _parent_scene.actor_name_map[midbox] = (PhysicsActor)this;
1245 else 1455 _parent_scene.actor_name_map[feetbox] = (PhysicsActor)this;
1246 { 1456 _parent_scene.actor_name_map[bonebox] = (PhysicsActor)this;
1247 m_log.Warn("[PHYSICS]: trying to change capsule size, but the following ODE data is missing - "
1248 + (Shell == IntPtr.Zero ? "Shell " : "")
1249 + (Body == IntPtr.Zero ? "Body " : "")
1250 + (Amotor == IntPtr.Zero ? "Amotor " : ""));
1251 }
1252 } 1457 }
1253 m_freemove = false; 1458 m_freemove = false;
1254 m_pidControllerActive = true; 1459 m_pidControllerActive = true;
@@ -1270,6 +1475,14 @@ namespace OpenSim.Region.Physics.OdePlugin
1270 1475
1271 private void changeOrientation(Quaternion newOri) 1476 private void changeOrientation(Quaternion newOri)
1272 { 1477 {
1478 d.Quaternion myrot = new d.Quaternion();
1479 myrot.X = newOri.X;
1480 myrot.Y = newOri.Y;
1481 myrot.Z = newOri.Z;
1482 myrot.W = newOri.W;
1483 float t = d.JointGetAMotorAngle(Amotor, 2);
1484 d.BodySetQuaternion(Body,ref myrot);
1485 m_orientation = newOri;
1273 } 1486 }
1274 1487
1275 private void changeVelocity(Vector3 newVel) 1488 private void changeVelocity(Vector3 newVel)
@@ -1359,7 +1572,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1359 1572
1360 public bool DoAChange(changes what, object arg) 1573 public bool DoAChange(changes what, object arg)
1361 { 1574 {
1362 if (Shell == IntPtr.Zero && what != changes.Add && what != changes.Remove) 1575 if (topbox == IntPtr.Zero && what != changes.Add && what != changes.Remove)
1363 { 1576 {
1364 return false; 1577 return false;
1365 } 1578 }