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.cs369
1 files changed, 288 insertions, 81 deletions
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs
index 94ed663..3d5be3e 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs
@@ -79,6 +79,8 @@ 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;
@@ -86,10 +88,17 @@ namespace OpenSim.Region.Physics.OdePlugin
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 90
89 public float CAPSULE_RADIUS = 0.37f;
90 public float CAPSULE_LENGTH = 2.140599f;
91 91
92 const float CAP_OFFSET = -.2f; // compensation of SL size offset plus spheric collision shape bottom 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
93 102
94 public float walkDivisor = 1.3f; 103 public float walkDivisor = 1.3f;
95 public float runDivisor = 0.8f; 104 public float runDivisor = 0.8f;
@@ -127,10 +136,16 @@ namespace OpenSim.Region.Physics.OdePlugin
127 // we do land collisions not ode | CollisionCategories.Land); 136 // we do land collisions not ode | CollisionCategories.Land);
128 public IntPtr Body = IntPtr.Zero; 137 public IntPtr Body = IntPtr.Zero;
129 private OdeScene _parent_scene; 138 private OdeScene _parent_scene;
130 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
131 public IntPtr Amotor = IntPtr.Zero; 144 public IntPtr Amotor = IntPtr.Zero;
145
132 public d.Mass ShellMass; 146 public d.Mass ShellMass;
133// public bool collidelock = false; 147
148
134 149
135 public int m_eventsubscription = 0; 150 public int m_eventsubscription = 0;
136 private int m_cureventsubscription = 0; 151 private int m_cureventsubscription = 0;
@@ -145,7 +160,7 @@ namespace OpenSim.Region.Physics.OdePlugin
145 160
146 161
147 162
148 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) 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)
149 { 164 {
150 m_uuid = UUID.Random(); 165 m_uuid = UUID.Random();
151 166
@@ -171,9 +186,20 @@ namespace OpenSim.Region.Physics.OdePlugin
171 186
172 PID_D = pid_d; 187 PID_D = pid_d;
173 PID_P = pid_p; 188 PID_P = pid_p;
174 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;
175 m_density = density; 202 m_density = density;
176 m_mass = 80f; // sure we have a default
177 203
178 // force lower density for testing 204 // force lower density for testing
179 m_density = 3.0f; 205 m_density = 3.0f;
@@ -183,8 +209,7 @@ namespace OpenSim.Region.Physics.OdePlugin
183 walkDivisor = walk_divisor; 209 walkDivisor = walk_divisor;
184 runDivisor = rundivisor; 210 runDivisor = rundivisor;
185 211
186 CAPSULE_LENGTH = size.Z - CAPSULE_RADIUS + CAP_OFFSET; 212 m_mass = m_density * m_size.X * m_size.Y * m_size.Z; ; // sure we have a default
187 //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString());
188 213
189 m_isPhysical = false; // current status: no ODE information exists 214 m_isPhysical = false; // current status: no ODE information exists
190 215
@@ -426,14 +451,21 @@ namespace OpenSim.Region.Physics.OdePlugin
426 /// </summary> 451 /// </summary>
427 public override Vector3 Size 452 public override Vector3 Size
428 { 453 {
429 get { 454 get
430 float d = CAPSULE_RADIUS * 2; 455 {
431 return new Vector3(d, d, (CAPSULE_LENGTH + CAPSULE_RADIUS - CAP_OFFSET)); 456 return m_size;
432 } 457 }
433 set 458 set
434 { 459 {
435 if (value.IsFinite()) 460 if (value.IsFinite())
436 { 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
437 AddChange(changes.Size, value); 469 AddChange(changes.Size, value);
438 } 470 }
439 else 471 else
@@ -459,8 +491,7 @@ namespace OpenSim.Region.Physics.OdePlugin
459 { 491 {
460 get 492 get
461 { 493 {
462 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;
463 return m_density * AVvolume;
464 } 495 }
465 } 496 }
466 public override void link(PhysicsActor obj) 497 public override void link(PhysicsActor obj)
@@ -578,9 +609,14 @@ namespace OpenSim.Region.Physics.OdePlugin
578 609
579 public override Quaternion Orientation 610 public override Quaternion Orientation
580 { 611 {
581 get { return Quaternion.Identity; } 612 get { return m_orientation; }
582 set 613 set
583 { 614 {
615 // fakeori = value;
616 // givefakeori++;
617
618 value.Normalize();
619 AddChange(changes.Orientation, value);
584 } 620 }
585 } 621 }
586 622
@@ -632,32 +668,65 @@ namespace OpenSim.Region.Physics.OdePlugin
632 AddChange(changes.Momentum, momentum); 668 AddChange(changes.Momentum, momentum);
633 } 669 }
634 670
635
636 // WARNING: This MUST NOT be called outside of ProcessTaints, else we can have unsynchronized access
637 // to ODE internals. ProcessTaints is called from within thread-locked Simulate(), so it is the only
638 // place that is safe to call this routine AvatarGeomAndBodyCreation.
639 private void AvatarGeomAndBodyCreation(float npositionX, float npositionY, float npositionZ) 671 private void AvatarGeomAndBodyCreation(float npositionX, float npositionY, float npositionZ)
640 { 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
641 _parent_scene.waitForSpaceUnlock(_parent_scene.ActiveSpace); 711 _parent_scene.waitForSpaceUnlock(_parent_scene.ActiveSpace);
642 if (CAPSULE_LENGTH <= 0)
643 {
644 m_log.Warn("[PHYSICS]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!");
645 CAPSULE_LENGTH = 0.01f;
646 712
647 } 713 feetbox = d.CreateBox(_parent_scene.ActiveSpace, feetsx, feetsy, feetsz);
714 d.GeomSetCategoryBits(feetbox, (uint)m_collisionCategories);
715 d.GeomSetCollideBits(feetbox, (uint)m_collisionFlags);
648 716
649 if (CAPSULE_RADIUS <= 0) 717 midbox = d.CreateBox(_parent_scene.ActiveSpace, midsx, midsy, midsz);
650 { 718 d.GeomSetCategoryBits(midbox, (uint)m_collisionCategories);
651 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);
652 CAPSULE_RADIUS = 0.01f;
653 720
654 } 721 topbox = d.CreateBox(_parent_scene.ActiveSpace, topsx, topsy, topsz);
655 Shell = d.CreateCapsule(_parent_scene.ActiveSpace, CAPSULE_RADIUS, CAPSULE_LENGTH); 722 d.GeomSetCategoryBits(topbox, (uint)m_collisionCategories);
723 d.GeomSetCollideBits(topbox, (uint)m_collisionFlags);
656 724
657 d.GeomSetCategoryBits(Shell, (uint)m_collisionCategories); 725 bonebox = d.CreateBox(_parent_scene.ActiveSpace, bonesx, bonesy, bonesz);
658 d.GeomSetCollideBits(Shell, (uint)m_collisionFlags); 726 d.GeomSetCategoryBits(bonebox, (uint)m_collisionCategories);
727 d.GeomSetCollideBits(bonebox, (uint)m_collisionFlags);
659 728
660 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);
661 730
662 m_mass = ShellMass.mass; // update mass 731 m_mass = ShellMass.mass; // update mass
663 732
@@ -688,7 +757,14 @@ namespace OpenSim.Region.Physics.OdePlugin
688 _position.Z = npositionZ; 757 _position.Z = npositionZ;
689 758
690 d.BodySetMass(Body, ref ShellMass); 759 d.BodySetMass(Body, ref ShellMass);
691 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);
692 768
693 // 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
694 // surrogate from rotating while moving 770 // surrogate from rotating while moving
@@ -748,15 +824,152 @@ namespace OpenSim.Region.Physics.OdePlugin
748 Body = IntPtr.Zero; 824 Body = IntPtr.Zero;
749 } 825 }
750 826
751 //kill the Geometry 827 //kill the Geoms
752 if (Shell != IntPtr.Zero) 828 if (topbox != IntPtr.Zero)
753 { 829 {
754// _parent_scene.geom_name_map.Remove(Shell); 830 _parent_scene.actor_name_map.Remove(topbox);
755 _parent_scene.actor_name_map.Remove(Shell);
756 _parent_scene.waitForSpaceUnlock(_parent_scene.ActiveSpace); 831 _parent_scene.waitForSpaceUnlock(_parent_scene.ActiveSpace);
757 d.GeomDestroy(Shell); 832 d.GeomDestroy(topbox);
758 Shell = IntPtr.Zero; 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)
851 {
852 _parent_scene.actor_name_map.Remove(bonebox);
853 _parent_scene.waitForSpaceUnlock(_parent_scene.ActiveSpace);
854 d.GeomDestroy(bonebox);
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;
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;
759 } 968 }
969 else
970 return false;
971
972 return true;
760 } 973 }
761 974
762 /// <summary> 975 /// <summary>
@@ -776,10 +989,10 @@ namespace OpenSim.Region.Physics.OdePlugin
776 // so force it back to identity 989 // so force it back to identity
777 990
778 d.Quaternion qtmp; 991 d.Quaternion qtmp;
779 qtmp.W = 1; 992 qtmp.W = m_orientation.W;
780 qtmp.X = 0; 993 qtmp.X = m_orientation.X;
781 qtmp.Y = 0; 994 qtmp.Y = m_orientation.Y;
782 qtmp.Z = 0; 995 qtmp.Z = m_orientation.Z;
783 d.BodySetQuaternion(Body, ref qtmp); 996 d.BodySetQuaternion(Body, ref qtmp);
784 997
785 if (m_pidControllerActive == false) 998 if (m_pidControllerActive == false)
@@ -843,7 +1056,7 @@ namespace OpenSim.Region.Physics.OdePlugin
843 //****************************************** 1056 //******************************************
844 // colide with land 1057 // colide with land
845 d.AABB aabb; 1058 d.AABB aabb;
846 d.GeomGetAABB(Shell, out aabb); 1059 d.GeomGetAABB(feetbox, out aabb);
847 float chrminZ = aabb.MinZ - 0.04f; // move up a bit 1060 float chrminZ = aabb.MinZ - 0.04f; // move up a bit
848 Vector3 posch = localpos; 1061 Vector3 posch = localpos;
849 1062
@@ -1182,20 +1395,14 @@ namespace OpenSim.Region.Physics.OdePlugin
1182 { 1395 {
1183 if (NewStatus) 1396 if (NewStatus)
1184 { 1397 {
1185 // Create avatar capsule and related ODE data 1398 AvatarGeomAndBodyDestroy();
1186 if ((Shell != IntPtr.Zero))
1187 {
1188 // a lost shell ?
1189 m_log.Warn("[PHYSICS]: re-creating the following avatar ODE data, even though it already exists - "
1190 + (Shell != IntPtr.Zero ? "Shell " : "")
1191 + (Body != IntPtr.Zero ? "Body " : "")
1192 + (Amotor != IntPtr.Zero ? "Amotor " : ""));
1193 AvatarGeomAndBodyDestroy();
1194 }
1195 1399
1196 AvatarGeomAndBodyCreation(_position.X, _position.Y, _position.Z); 1400 AvatarGeomAndBodyCreation(_position.X, _position.Y, _position.Z);
1197 1401
1198 _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;
1199 _parent_scene.AddCharacter(this); 1406 _parent_scene.AddCharacter(this);
1200 } 1407 }
1201 else 1408 else
@@ -1224,37 +1431,29 @@ namespace OpenSim.Region.Physics.OdePlugin
1224 { 1431 {
1225 } 1432 }
1226 1433
1227 private void changeSize(Vector3 Size) 1434 private void changeSize(Vector3 pSize)
1228 { 1435 {
1229 if (Size.IsFinite()) 1436 if (pSize.IsFinite())
1230 { 1437 {
1231 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();
1232 1442
1233 caplen = caplen - CAPSULE_RADIUS + CAP_OFFSET;
1234 1443
1235 if (caplen != CAPSULE_LENGTH) 1444 float oldsz = m_size.Z;
1236 { 1445 m_size = pSize;
1237 if (Shell != IntPtr.Zero && Body != IntPtr.Zero && Amotor != IntPtr.Zero)
1238 {
1239 AvatarGeomAndBodyDestroy();
1240 1446
1241 float prevCapsule = CAPSULE_LENGTH;
1242 CAPSULE_LENGTH = caplen;
1243 1447
1244 AvatarGeomAndBodyCreation(_position.X, _position.Y, 1448 AvatarGeomAndBodyCreation(_position.X, _position.Y,
1245 _position.Z + (CAPSULE_LENGTH - prevCapsule) * 0.5f); 1449 _position.Z + (m_size.Z - oldsz) * 0.5f);
1246 1450
1247 Velocity = Vector3.Zero; 1451 Velocity = Vector3.Zero;
1248 1452
1249 _parent_scene.actor_name_map[Shell] = (PhysicsActor)this; 1453 _parent_scene.actor_name_map[topbox] = (PhysicsActor)this;
1250 } 1454 _parent_scene.actor_name_map[midbox] = (PhysicsActor)this;
1251 else 1455 _parent_scene.actor_name_map[feetbox] = (PhysicsActor)this;
1252 { 1456 _parent_scene.actor_name_map[bonebox] = (PhysicsActor)this;
1253 m_log.Warn("[PHYSICS]: trying to change capsule size, but the following ODE data is missing - "
1254 + (Shell == IntPtr.Zero ? "Shell " : "")
1255 + (Body == IntPtr.Zero ? "Body " : "")
1256 + (Amotor == IntPtr.Zero ? "Amotor " : ""));
1257 }
1258 } 1457 }
1259 m_freemove = false; 1458 m_freemove = false;
1260 m_pidControllerActive = true; 1459 m_pidControllerActive = true;
@@ -1276,6 +1475,14 @@ namespace OpenSim.Region.Physics.OdePlugin
1276 1475
1277 private void changeOrientation(Quaternion newOri) 1476 private void changeOrientation(Quaternion newOri)
1278 { 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;
1279 } 1486 }
1280 1487
1281 private void changeVelocity(Vector3 newVel) 1488 private void changeVelocity(Vector3 newVel)
@@ -1365,7 +1572,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1365 1572
1366 public bool DoAChange(changes what, object arg) 1573 public bool DoAChange(changes what, object arg)
1367 { 1574 {
1368 if (Shell == IntPtr.Zero && what != changes.Add && what != changes.Remove) 1575 if (topbox == IntPtr.Zero && what != changes.Add && what != changes.Remove)
1369 { 1576 {
1370 return false; 1577 return false;
1371 } 1578 }