aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/OdePlugin/ODECharacter.cs')
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODECharacter.cs758
1 files changed, 366 insertions, 392 deletions
diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
index 2a66060..73c1c02 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
@@ -39,7 +39,6 @@ namespace OpenSim.Region.Physics.OdePlugin
39 /// <summary> 39 /// <summary>
40 /// Various properties that ODE uses for AMotors but isn't exposed in ODE.NET so we must define them ourselves. 40 /// Various properties that ODE uses for AMotors but isn't exposed in ODE.NET so we must define them ourselves.
41 /// </summary> 41 /// </summary>
42
43 public enum dParam : int 42 public enum dParam : int
44 { 43 {
45 LowStop = 0, 44 LowStop = 0,
@@ -64,31 +63,32 @@ namespace OpenSim.Region.Physics.OdePlugin
64 StopERP3 = 7 + 512, 63 StopERP3 = 7 + 512,
65 StopCFM3 = 8 + 512 64 StopCFM3 = 8 + 512
66 } 65 }
66
67 public class OdeCharacter : PhysicsActor 67 public class OdeCharacter : PhysicsActor
68 { 68 {
69 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 69 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
70 70
71 private Vector3 _position; 71 private Vector3 _position;
72 private d.Vector3 _zeroPosition; 72 private d.Vector3 _zeroPosition;
73 // private d.Matrix3 m_StandUpRotation;
74 private bool _zeroFlag = false; 73 private bool _zeroFlag = false;
75 private bool m_lastUpdateSent = false; 74 private bool m_lastUpdateSent = false;
76 private Vector3 _velocity; 75 private Vector3 _velocity;
76 private Vector3 m_taintTargetVelocity;
77 private Vector3 _target_velocity; 77 private Vector3 _target_velocity;
78 private Vector3 _acceleration; 78 private Vector3 _acceleration;
79 private Vector3 m_rotationalVelocity; 79 private Vector3 m_rotationalVelocity;
80 private float m_mass = 80f; 80 private float m_mass = 80f;
81 public float m_density = 60f; 81 private float m_density = 60f;
82 private bool m_pidControllerActive = true; 82 private bool m_pidControllerActive = true;
83 public float PID_D = 800.0f; 83 private float PID_D = 800.0f;
84 public float PID_P = 900.0f; 84 private float PID_P = 900.0f;
85 //private static float POSTURE_SERVO = 10000.0f; 85 //private static float POSTURE_SERVO = 10000.0f;
86 public float CAPSULE_RADIUS = 0.37f; 86 private float CAPSULE_RADIUS = 0.37f;
87 public float CAPSULE_LENGTH = 2.140599f; 87 private float CAPSULE_LENGTH = 2.140599f;
88 public float m_tensor = 3800000f; 88 private float m_tensor = 3800000f;
89 public float heightFudgeFactor = 0.52f; 89// private float heightFudgeFactor = 0.52f;
90 public float walkDivisor = 1.3f; 90 private float walkDivisor = 1.3f;
91 public float runDivisor = 0.8f; 91 private float runDivisor = 0.8f;
92 private bool flying = false; 92 private bool flying = false;
93 private bool m_iscolliding = false; 93 private bool m_iscolliding = false;
94 private bool m_iscollidingGround = false; 94 private bool m_iscollidingGround = false;
@@ -99,24 +99,29 @@ namespace OpenSim.Region.Physics.OdePlugin
99 private bool m_hackSentFall = false; 99 private bool m_hackSentFall = false;
100 private bool m_hackSentFly = false; 100 private bool m_hackSentFly = false;
101 private int m_requestedUpdateFrequency = 0; 101 private int m_requestedUpdateFrequency = 0;
102 private Vector3 m_taintPosition = Vector3.Zero; 102 private Vector3 m_taintPosition;
103 public uint m_localID = 0; 103
104 public bool m_returnCollisions = false; 104 /// <summary>
105 /// Hold set forces so we can process them outside physics calculations. This prevents race conditions if we set force
106 /// while calculatios are going on
107 /// </summary>
108 private Vector3 m_taintForce;
109
105 // taints and their non-tainted counterparts 110 // taints and their non-tainted counterparts
106 public bool m_isPhysical = false; // the current physical status 111 private bool m_isPhysical = false; // the current physical status
107 public bool m_tainted_isPhysical = false; // set when the physical status is tainted (false=not existing in physics engine, true=existing) 112 private bool m_tainted_isPhysical = false; // set when the physical status is tainted (false=not existing in physics engine, true=existing)
108 public float MinimumGroundFlightOffset = 3f; 113 internal float MinimumGroundFlightOffset = 3f;
109 114
110 private float m_tainted_CAPSULE_LENGTH; // set when the capsule length changes. 115 private float m_tainted_CAPSULE_LENGTH; // set when the capsule length changes.
111 private float m_tiltMagnitudeWhenProjectedOnXYPlane = 0.1131371f; // used to introduce a fixed tilt because a straight-up capsule falls through terrain, probably a bug in terrain collider
112 116
117 /// <summary>
118 /// Used to introduce a fixed tilt because a straight-up capsule falls through terrain, probably a bug in terrain collider
119 /// </summary>
120 private float m_tiltMagnitudeWhenProjectedOnXYPlane = 0.1131371f;
113 121
114 private float m_buoyancy = 0f; 122 private float m_buoyancy = 0f;
115 123
116 // private CollisionLocker ode; 124 // private CollisionLocker ode;
117
118 private string m_name = String.Empty;
119
120 private bool[] m_colliderarr = new bool[11]; 125 private bool[] m_colliderarr = new bool[11];
121 private bool[] m_colliderGroundarr = new bool[11]; 126 private bool[] m_colliderGroundarr = new bool[11];
122 127
@@ -129,21 +134,23 @@ namespace OpenSim.Region.Physics.OdePlugin
129 | CollisionCategories.Body 134 | CollisionCategories.Body
130 | CollisionCategories.Character 135 | CollisionCategories.Character
131 | CollisionCategories.Land); 136 | CollisionCategories.Land);
132 public IntPtr Body = IntPtr.Zero; 137 internal IntPtr Body = IntPtr.Zero;
133 private OdeScene _parent_scene; 138 private OdeScene _parent_scene;
134 public IntPtr Shell = IntPtr.Zero; 139 internal IntPtr Shell = IntPtr.Zero;
135 public IntPtr Amotor = IntPtr.Zero; 140 internal IntPtr Amotor = IntPtr.Zero;
136 public d.Mass ShellMass; 141 private d.Mass ShellMass;
137 public bool collidelock = false;
138 142
139 public int m_eventsubscription = 0; 143 private int m_eventsubscription = 0;
140 private CollisionEventUpdate CollisionEventsThisFrame = new CollisionEventUpdate(); 144 private CollisionEventUpdate CollisionEventsThisFrame = new CollisionEventUpdate();
141 145
142 // unique UUID of this character object 146 // unique UUID of this character object
143 public UUID m_uuid; 147 internal UUID m_uuid { get; private set; }
144 public bool bad = false; 148 internal bool bad = false;
145 149
146 public OdeCharacter(String avName, OdeScene parent_scene, Vector3 pos, CollisionLocker dode, Vector3 size, float pid_d, float pid_p, float capsule_radius, float tensor, float density, float height_fudge_factor, float walk_divisor, float rundivisor) 150 public OdeCharacter(
151 String avName, OdeScene parent_scene, Vector3 pos, Vector3 size, float pid_d, float pid_p,
152 float capsule_radius, float tensor, float density,
153 float walk_divisor, float rundivisor)
147 { 154 {
148 m_uuid = UUID.Random(); 155 m_uuid = UUID.Random();
149 156
@@ -157,18 +164,20 @@ namespace OpenSim.Region.Physics.OdePlugin
157 { 164 {
158 pos.Z = parent_scene.GetTerrainHeightAtXY(127, 127) + 5; 165 pos.Z = parent_scene.GetTerrainHeightAtXY(127, 127) + 5;
159 } 166 }
167
160 _position = pos; 168 _position = pos;
161 m_taintPosition.X = pos.X; 169 m_taintPosition = pos;
162 m_taintPosition.Y = pos.Y;
163 m_taintPosition.Z = pos.Z;
164 } 170 }
165 else 171 else
166 { 172 {
167 _position = new Vector3(((float)_parent_scene.WorldExtents.X * 0.5f), ((float)_parent_scene.WorldExtents.Y * 0.5f), parent_scene.GetTerrainHeightAtXY(128f, 128f) + 10f); 173 _position
168 m_taintPosition.X = _position.X; 174 = new Vector3(
169 m_taintPosition.Y = _position.Y; 175 (float)_parent_scene.WorldExtents.X * 0.5f,
170 m_taintPosition.Z = _position.Z; 176 (float)_parent_scene.WorldExtents.Y * 0.5f,
171 m_log.Warn("[PHYSICS]: Got NaN Position on Character Create"); 177 parent_scene.GetTerrainHeightAtXY(128f, 128f) + 10f);
178 m_taintPosition = _position;
179
180 m_log.WarnFormat("[ODE CHARACTER]: Got NaN Position on Character Create for {0}", avName);
172 } 181 }
173 182
174 _parent_scene = parent_scene; 183 _parent_scene = parent_scene;
@@ -178,7 +187,7 @@ namespace OpenSim.Region.Physics.OdePlugin
178 CAPSULE_RADIUS = capsule_radius; 187 CAPSULE_RADIUS = capsule_radius;
179 m_tensor = tensor; 188 m_tensor = tensor;
180 m_density = density; 189 m_density = density;
181 heightFudgeFactor = height_fudge_factor; 190// heightFudgeFactor = height_fudge_factor;
182 walkDivisor = walk_divisor; 191 walkDivisor = walk_divisor;
183 runDivisor = rundivisor; 192 runDivisor = rundivisor;
184 193
@@ -191,7 +200,7 @@ namespace OpenSim.Region.Physics.OdePlugin
191 m_colliderarr[i] = false; 200 m_colliderarr[i] = false;
192 } 201 }
193 CAPSULE_LENGTH = (size.Z * 1.15f) - CAPSULE_RADIUS * 2.0f; 202 CAPSULE_LENGTH = (size.Z * 1.15f) - CAPSULE_RADIUS * 2.0f;
194 //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString()); 203 //m_log.Info("[ODE CHARACTER]: " + CAPSULE_LENGTH.ToString());
195 m_tainted_CAPSULE_LENGTH = CAPSULE_LENGTH; 204 m_tainted_CAPSULE_LENGTH = CAPSULE_LENGTH;
196 205
197 m_isPhysical = false; // current status: no ODE information exists 206 m_isPhysical = false; // current status: no ODE information exists
@@ -199,7 +208,7 @@ namespace OpenSim.Region.Physics.OdePlugin
199 208
200 _parent_scene.AddPhysicsActorTaint(this); 209 _parent_scene.AddPhysicsActorTaint(this);
201 210
202 m_name = avName; 211 Name = avName;
203 } 212 }
204 213
205 public override int PhysicsActorType 214 public override int PhysicsActorType
@@ -217,11 +226,6 @@ namespace OpenSim.Region.Physics.OdePlugin
217 set { m_alwaysRun = value; } 226 set { m_alwaysRun = value; }
218 } 227 }
219 228
220 public override uint LocalID
221 {
222 set { m_localID = value; }
223 }
224
225 public override bool Grabbed 229 public override bool Grabbed
226 { 230 {
227 set { return; } 231 set { return; }
@@ -258,7 +262,11 @@ namespace OpenSim.Region.Physics.OdePlugin
258 public override bool Flying 262 public override bool Flying
259 { 263 {
260 get { return flying; } 264 get { return flying; }
261 set { flying = value; } 265 set
266 {
267 flying = value;
268// m_log.DebugFormat("[ODE CHARACTER]: Set OdeCharacter Flying to {0}", flying);
269 }
262 } 270 }
263 271
264 /// <summary> 272 /// <summary>
@@ -305,10 +313,12 @@ namespace OpenSim.Region.Physics.OdePlugin
305 { 313 {
306 m_iscolliding = true; 314 m_iscolliding = true;
307 } 315 }
316
308 if (m_wascolliding != m_iscolliding) 317 if (m_wascolliding != m_iscolliding)
309 { 318 {
310 //base.SendCollisionUpdate(new CollisionEventUpdate()); 319 //base.SendCollisionUpdate(new CollisionEventUpdate());
311 } 320 }
321
312 m_wascolliding = m_iscolliding; 322 m_wascolliding = m_iscolliding;
313 } 323 }
314 } 324 }
@@ -421,18 +431,12 @@ namespace OpenSim.Region.Physics.OdePlugin
421 value.Z = _parent_scene.GetTerrainHeightAtXY(127, 127) + 5; 431 value.Z = _parent_scene.GetTerrainHeightAtXY(127, 127) + 5;
422 } 432 }
423 433
424 _position.X = value.X; 434 m_taintPosition = value;
425 _position.Y = value.Y;
426 _position.Z = value.Z;
427
428 m_taintPosition.X = value.X;
429 m_taintPosition.Y = value.Y;
430 m_taintPosition.Z = value.Z;
431 _parent_scene.AddPhysicsActorTaint(this); 435 _parent_scene.AddPhysicsActorTaint(this);
432 } 436 }
433 else 437 else
434 { 438 {
435 m_log.Warn("[PHYSICS]: Got a NaN Position from Scene on a Character"); 439 m_log.WarnFormat("[ODE CHARACTER]: Got a NaN Position from Scene on character {0}", Name);
436 } 440 }
437 } 441 }
438 } 442 }
@@ -458,16 +462,18 @@ namespace OpenSim.Region.Physics.OdePlugin
458 m_pidControllerActive = true; 462 m_pidControllerActive = true;
459 463
460 Vector3 SetSize = value; 464 Vector3 SetSize = value;
461 m_tainted_CAPSULE_LENGTH = (SetSize.Z*1.15f) - CAPSULE_RADIUS*2.0f; 465 m_tainted_CAPSULE_LENGTH = (SetSize.Z * 1.15f) - CAPSULE_RADIUS * 2.0f;
462 //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString()); 466// m_log.Info("[ODE CHARACTER]: " + CAPSULE_LENGTH);
463 467
464 Velocity = Vector3.Zero; 468 // If we reset velocity here, then an avatar stalls when it crosses a border for the first time
469 // (as the height of the new root agent is set).
470// Velocity = Vector3.Zero;
465 471
466 _parent_scene.AddPhysicsActorTaint(this); 472 _parent_scene.AddPhysicsActorTaint(this);
467 } 473 }
468 else 474 else
469 { 475 {
470 m_log.Warn("[PHYSICS]: Got a NaN Size from Scene on a Character"); 476 m_log.WarnFormat("[ODE CHARACTER]: Got a NaN Size from Scene on {0}", Name);
471 } 477 }
472 } 478 }
473 } 479 }
@@ -519,7 +525,6 @@ namespace OpenSim.Region.Physics.OdePlugin
519 } 525 }
520 } 526 }
521 527
522
523 // movementVector.Z is zero 528 // movementVector.Z is zero
524 529
525 // calculate tilt components based on desired amount of tilt and current (snapped) heading. 530 // calculate tilt components based on desired amount of tilt and current (snapped) heading.
@@ -527,7 +532,7 @@ namespace OpenSim.Region.Physics.OdePlugin
527 float xTiltComponent = -movementVector.X * m_tiltMagnitudeWhenProjectedOnXYPlane; 532 float xTiltComponent = -movementVector.X * m_tiltMagnitudeWhenProjectedOnXYPlane;
528 float yTiltComponent = -movementVector.Y * m_tiltMagnitudeWhenProjectedOnXYPlane; 533 float yTiltComponent = -movementVector.Y * m_tiltMagnitudeWhenProjectedOnXYPlane;
529 534
530 //m_log.Debug("[PHYSICS] changing avatar tilt"); 535 //m_log.Debug("[ODE CHARACTER]: changing avatar tilt");
531 d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, xTiltComponent); 536 d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, xTiltComponent);
532 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, xTiltComponent); // must be same as lowstop, else a different, spurious tilt is introduced 537 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, xTiltComponent); // must be same as lowstop, else a different, spurious tilt is introduced
533 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, yTiltComponent); 538 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, yTiltComponent);
@@ -537,127 +542,6 @@ namespace OpenSim.Region.Physics.OdePlugin
537 } 542 }
538 543
539 /// <summary> 544 /// <summary>
540 /// This creates the Avatar's physical Surrogate at the position supplied
541 /// </summary>
542 /// <param name="npositionX"></param>
543 /// <param name="npositionY"></param>
544 /// <param name="npositionZ"></param>
545
546 // WARNING: This MUST NOT be called outside of ProcessTaints, else we can have unsynchronized access
547 // to ODE internals. ProcessTaints is called from within thread-locked Simulate(), so it is the only
548 // place that is safe to call this routine AvatarGeomAndBodyCreation.
549 private void AvatarGeomAndBodyCreation(float npositionX, float npositionY, float npositionZ, float tensor)
550 {
551 //CAPSULE_LENGTH = -5;
552 //CAPSULE_RADIUS = -5;
553 int dAMotorEuler = 1;
554 _parent_scene.waitForSpaceUnlock(_parent_scene.space);
555 if (CAPSULE_LENGTH <= 0)
556 {
557 m_log.Warn("[PHYSICS]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!");
558 CAPSULE_LENGTH = 0.01f;
559
560 }
561
562 if (CAPSULE_RADIUS <= 0)
563 {
564 m_log.Warn("[PHYSICS]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!");
565 CAPSULE_RADIUS = 0.01f;
566
567 }
568 Shell = d.CreateCapsule(_parent_scene.space, CAPSULE_RADIUS, CAPSULE_LENGTH);
569
570 d.GeomSetCategoryBits(Shell, (int)m_collisionCategories);
571 d.GeomSetCollideBits(Shell, (int)m_collisionFlags);
572
573 d.MassSetCapsuleTotal(out ShellMass, m_mass, 2, CAPSULE_RADIUS, CAPSULE_LENGTH);
574 Body = d.BodyCreate(_parent_scene.world);
575 d.BodySetPosition(Body, npositionX, npositionY, npositionZ);
576
577 _position.X = npositionX;
578 _position.Y = npositionY;
579 _position.Z = npositionZ;
580
581
582 m_taintPosition.X = npositionX;
583 m_taintPosition.Y = npositionY;
584 m_taintPosition.Z = npositionZ;
585
586 d.BodySetMass(Body, ref ShellMass);
587 d.Matrix3 m_caprot;
588 // 90 Stand up on the cap of the capped cyllinder
589 if (_parent_scene.IsAvCapsuleTilted)
590 {
591 d.RFromAxisAndAngle(out m_caprot, 1, 0, 1, (float)(Math.PI / 2));
592 }
593 else
594 {
595 d.RFromAxisAndAngle(out m_caprot, 0, 0, 1, (float)(Math.PI / 2));
596 }
597
598
599 d.GeomSetRotation(Shell, ref m_caprot);
600 d.BodySetRotation(Body, ref m_caprot);
601
602 d.GeomSetBody(Shell, Body);
603
604
605 // The purpose of the AMotor here is to keep the avatar's physical
606 // surrogate from rotating while moving
607 Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero);
608 d.JointAttach(Amotor, Body, IntPtr.Zero);
609 d.JointSetAMotorMode(Amotor, dAMotorEuler);
610 d.JointSetAMotorNumAxes(Amotor, 3);
611 d.JointSetAMotorAxis(Amotor, 0, 0, 1, 0, 0);
612 d.JointSetAMotorAxis(Amotor, 1, 0, 0, 1, 0);
613 d.JointSetAMotorAxis(Amotor, 2, 0, 0, 0, 1);
614 d.JointSetAMotorAngle(Amotor, 0, 0);
615 d.JointSetAMotorAngle(Amotor, 1, 0);
616 d.JointSetAMotorAngle(Amotor, 2, 0);
617
618 // These lowstops and high stops are effectively (no wiggle room)
619 if (_parent_scene.IsAvCapsuleTilted)
620 {
621 d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, -0.000000000001f);
622 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -0.000000000001f);
623 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, -0.000000000001f);
624 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0.000000000001f);
625 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0.000000000001f);
626 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0.000000000001f);
627 }
628 else
629 {
630 #region Documentation of capsule motor LowStop and HighStop parameters
631 // Intentionally introduce some tilt into the capsule by setting
632 // the motor stops to small epsilon values. This small tilt prevents
633 // the capsule from falling into the terrain; a straight-up capsule
634 // (with -0..0 motor stops) falls into the terrain for reasons yet
635 // to be comprehended in their entirety.
636 #endregion
637 AlignAvatarTiltWithCurrentDirectionOfMovement(Vector3.Zero);
638 d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, 0.08f);
639 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -0f);
640 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, 0.08f);
641 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0.08f); // must be same as lowstop, else a different, spurious tilt is introduced
642 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0f); // same as lowstop
643 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0.08f); // same as lowstop
644 }
645
646 // Fudge factor is 1f by default, we're setting it to 0. We don't want it to Fudge or the
647 // capped cyllinder will fall over
648 d.JointSetAMotorParam(Amotor, (int)dParam.FudgeFactor, 0f);
649 d.JointSetAMotorParam(Amotor, (int)dParam.FMax, tensor);
650
651 //d.Matrix3 bodyrotation = d.BodyGetRotation(Body);
652 //d.QfromR(
653 //d.Matrix3 checkrotation = new d.Matrix3(0.7071068,0.5, -0.7071068,
654 //
655 //m_log.Info("[PHYSICSAV]: Rotation: " + bodyrotation.M00 + " : " + bodyrotation.M01 + " : " + bodyrotation.M02 + " : " + bodyrotation.M10 + " : " + bodyrotation.M11 + " : " + bodyrotation.M12 + " : " + bodyrotation.M20 + " : " + bodyrotation.M21 + " : " + bodyrotation.M22);
656 //standupStraight();
657 }
658
659 //
660 /// <summary>
661 /// Uses the capped cyllinder volume formula to calculate the avatar's mass. 545 /// Uses the capped cyllinder volume formula to calculate the avatar's mass.
662 /// This may be used in calculations in the scene/scenepresence 546 /// This may be used in calculations in the scene/scenepresence
663 /// </summary> 547 /// </summary>
@@ -669,20 +553,12 @@ namespace OpenSim.Region.Physics.OdePlugin
669 return m_density*AVvolume; 553 return m_density*AVvolume;
670 } 554 }
671 } 555 }
672 public override void link(PhysicsActor obj)
673 {
674 556
675 } 557 public override void link(PhysicsActor obj) {}
676 558
677 public override void delink() 559 public override void delink() {}
678 {
679 560
680 } 561 public override void LockAngularMotion(Vector3 axis) {}
681
682 public override void LockAngularMotion(Vector3 axis)
683 {
684
685 }
686 562
687// This code is very useful. Written by DanX0r. We're just not using it right now. 563// This code is very useful. Written by DanX0r. We're just not using it right now.
688// Commented out to prevent a warning. 564// Commented out to prevent a warning.
@@ -704,7 +580,7 @@ namespace OpenSim.Region.Physics.OdePlugin
704// d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, servo, 0.0f, 0.0f, 1.0f); 580// d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, servo, 0.0f, 0.0f, 1.0f);
705// d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, -servo, 0.0f, 0.0f, -1.0f); 581// d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, -servo, 0.0f, 0.0f, -1.0f);
706// //d.Matrix3 bodyrotation = d.BodyGetRotation(Body); 582// //d.Matrix3 bodyrotation = d.BodyGetRotation(Body);
707// //m_log.Info("[PHYSICSAV]: Rotation: " + bodyrotation.M00 + " : " + bodyrotation.M01 + " : " + bodyrotation.M02 + " : " + bodyrotation.M10 + " : " + bodyrotation.M11 + " : " + bodyrotation.M12 + " : " + bodyrotation.M20 + " : " + bodyrotation.M21 + " : " + bodyrotation.M22); 583// //m_log.Info("[PHYSICSAV]: Rotation: " + bodyrotation.M00 + " : " + bodyFArotation.M01 + " : " + bodyrotation.M02 + " : " + bodyrotation.M10 + " : " + bodyrotation.M11 + " : " + bodyrotation.M12 + " : " + bodyrotation.M20 + " : " + bodyrotation.M21 + " : " + bodyrotation.M22);
708// } 584// }
709 585
710 public override Vector3 Force 586 public override Vector3 Force
@@ -721,27 +597,22 @@ namespace OpenSim.Region.Physics.OdePlugin
721 597
722 public override void VehicleFloatParam(int param, float value) 598 public override void VehicleFloatParam(int param, float value)
723 { 599 {
724
725 } 600 }
726 601
727 public override void VehicleVectorParam(int param, Vector3 value) 602 public override void VehicleVectorParam(int param, Vector3 value)
728 { 603 {
729
730 } 604 }
731 605
732 public override void VehicleRotationParam(int param, Quaternion rotation) 606 public override void VehicleRotationParam(int param, Quaternion rotation)
733 { 607 {
734
735 } 608 }
736 609
737 public override void VehicleFlags(int param, bool remove) 610 public override void VehicleFlags(int param, bool remove)
738 { 611 {
739
740 } 612 }
741 613
742 public override void SetVolumeDetect(int param) 614 public override void SetVolumeDetect(int param)
743 { 615 {
744
745 } 616 }
746 617
747 public override Vector3 CenterOfMass 618 public override Vector3 CenterOfMass
@@ -761,24 +632,29 @@ namespace OpenSim.Region.Physics.OdePlugin
761 632
762 public override Vector3 Velocity 633 public override Vector3 Velocity
763 { 634 {
764 get { 635 get
636 {
765 // There's a problem with Vector3.Zero! Don't Use it Here! 637 // There's a problem with Vector3.Zero! Don't Use it Here!
766 if (_zeroFlag) 638 if (_zeroFlag)
767 return Vector3.Zero; 639 return Vector3.Zero;
768 m_lastUpdateSent = false; 640 m_lastUpdateSent = false;
769 return _velocity; 641 return _velocity;
770 } 642 }
643
771 set 644 set
772 { 645 {
773 if (value.IsFinite()) 646 if (value.IsFinite())
774 { 647 {
775 m_pidControllerActive = true; 648 m_pidControllerActive = true;
776 _target_velocity = value; 649 m_taintTargetVelocity = value;
650 _parent_scene.AddPhysicsActorTaint(this);
777 } 651 }
778 else 652 else
779 { 653 {
780 m_log.Warn("[PHYSICS]: Got a NaN velocity from Scene in a Character"); 654 m_log.WarnFormat("[ODE CHARACTER]: Got a NaN velocity from Scene for {0}", Name);
781 } 655 }
656
657// m_log.DebugFormat("[PHYSICS]: Set target velocity of {0}", m_taintTargetVelocity);
782 } 658 }
783 } 659 }
784 660
@@ -834,63 +710,48 @@ namespace OpenSim.Region.Physics.OdePlugin
834 { 710 {
835 m_pidControllerActive = false; 711 m_pidControllerActive = false;
836 force *= 100f; 712 force *= 100f;
837 doForce(force); 713 m_taintForce += force;
714 _parent_scene.AddPhysicsActorTaint(this);
715
838 // If uncommented, things get pushed off world 716 // If uncommented, things get pushed off world
839 // 717 //
840 // m_log.Debug("Push!"); 718 // m_log.Debug("Push!");
841 // _target_velocity.X += force.X; 719 // m_taintTargetVelocity.X += force.X;
842 // _target_velocity.Y += force.Y; 720 // m_taintTargetVelocity.Y += force.Y;
843 // _target_velocity.Z += force.Z; 721 // m_taintTargetVelocity.Z += force.Z;
844 } 722 }
845 else 723 else
846 { 724 {
847 m_pidControllerActive = true; 725 m_pidControllerActive = true;
848 _target_velocity.X += force.X; 726 m_taintTargetVelocity += force;
849 _target_velocity.Y += force.Y;
850 _target_velocity.Z += force.Z;
851 } 727 }
852 } 728 }
853 else 729 else
854 { 730 {
855 m_log.Warn("[PHYSICS]: Got a NaN force applied to a Character"); 731 m_log.WarnFormat("[ODE CHARACTER]: Got a NaN force applied to {0}", Name);
856 } 732 }
857 //m_lastUpdateSent = false; 733 //m_lastUpdateSent = false;
858 } 734 }
859 735
860 public override void AddAngularForce(Vector3 force, bool pushforce) 736 public override void AddAngularForce(Vector3 force, bool pushforce)
861 { 737 {
862
863 }
864
865 /// <summary>
866 /// After all of the forces add up with 'add force' we apply them with doForce
867 /// </summary>
868 /// <param name="force"></param>
869 public void doForce(Vector3 force)
870 {
871 if (!collidelock)
872 {
873 d.BodyAddForce(Body, force.X, force.Y, force.Z);
874 //d.BodySetRotation(Body, ref m_StandUpRotation);
875 //standupStraight();
876
877 }
878 } 738 }
879 739
880 public override void SetMomentum(Vector3 momentum) 740 public override void SetMomentum(Vector3 momentum)
881 { 741 {
882 } 742 }
883 743
884
885 /// <summary> 744 /// <summary>
886 /// Called from Simulate 745 /// Called from Simulate
887 /// This is the avatar's movement control + PID Controller 746 /// This is the avatar's movement control + PID Controller
888 /// </summary> 747 /// </summary>
889 /// <param name="timeStep"></param> 748 /// <param name="defects">The character will be added to this list if there is something wrong (non-finite
890 public void Move(float timeStep, List<OdeCharacter> defects) 749 /// position or velocity).
750 /// </param>
751 internal void Move(List<OdeCharacter> defects)
891 { 752 {
892 // no lock; for now it's only called from within Simulate() 753 // no lock; for now it's only called from within Simulate()
893 754
894 // If the PID Controller isn't active then we set our force 755 // If the PID Controller isn't active then we set our force
895 // calculating base velocity to the current position 756 // calculating base velocity to the current position
896 757
@@ -908,36 +769,11 @@ namespace OpenSim.Region.Physics.OdePlugin
908 769
909 if (!localPos.IsFinite()) 770 if (!localPos.IsFinite())
910 { 771 {
772 m_log.WarnFormat(
773 "[ODE CHARACTER]: Avatar position of {0} for {1} is non-finite! Removing from physics scene.",
774 localPos, Name);
911 775
912 m_log.Warn("[PHYSICS]: Avatar Position is non-finite!");
913 defects.Add(this); 776 defects.Add(this);
914 // _parent_scene.RemoveCharacter(this);
915
916 // destroy avatar capsule and related ODE data
917 if (Amotor != IntPtr.Zero)
918 {
919 // Kill the Amotor
920 d.JointDestroy(Amotor);
921 Amotor = IntPtr.Zero;
922 }
923
924 //kill the Geometry
925 _parent_scene.waitForSpaceUnlock(_parent_scene.space);
926
927 if (Body != IntPtr.Zero)
928 {
929 //kill the body
930 d.BodyDestroy(Body);
931
932 Body = IntPtr.Zero;
933 }
934
935 if (Shell != IntPtr.Zero)
936 {
937 d.GeomDestroy(Shell);
938 _parent_scene.geom_name_map.Remove(Shell);
939 Shell = IntPtr.Zero;
940 }
941 777
942 return; 778 return;
943 } 779 }
@@ -965,6 +801,7 @@ namespace OpenSim.Region.Physics.OdePlugin
965 _zeroFlag = true; 801 _zeroFlag = true;
966 _zeroPosition = d.BodyGetPosition(Body); 802 _zeroPosition = d.BodyGetPosition(Body);
967 } 803 }
804
968 if (m_pidControllerActive) 805 if (m_pidControllerActive)
969 { 806 {
970 // We only want to deactivate the PID Controller if we think we want to have our surrogate 807 // We only want to deactivate the PID Controller if we think we want to have our surrogate
@@ -974,7 +811,7 @@ namespace OpenSim.Region.Physics.OdePlugin
974 811
975 d.Vector3 pos = d.BodyGetPosition(Body); 812 d.Vector3 pos = d.BodyGetPosition(Body);
976 vec.X = (_target_velocity.X - vel.X) * (PID_D) + (_zeroPosition.X - pos.X) * (PID_P * 2); 813 vec.X = (_target_velocity.X - vel.X) * (PID_D) + (_zeroPosition.X - pos.X) * (PID_P * 2);
977 vec.Y = (_target_velocity.Y - vel.Y)*(PID_D) + (_zeroPosition.Y - pos.Y)* (PID_P * 2); 814 vec.Y = (_target_velocity.Y - vel.Y) * (PID_D) + (_zeroPosition.Y - pos.Y)* (PID_P * 2);
978 if (flying) 815 if (flying)
979 { 816 {
980 vec.Z = (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P; 817 vec.Z = (_target_velocity.Z - vel.Z) * (PID_D) + (_zeroPosition.Z - pos.Z) * PID_P;
@@ -995,14 +832,18 @@ namespace OpenSim.Region.Physics.OdePlugin
995 else if (m_iscolliding && flying) 832 else if (m_iscolliding && flying)
996 { 833 {
997 // We're flying and colliding with something 834 // We're flying and colliding with something
998 vec.X = ((_target_velocity.X/movementdivisor) - vel.X)*(PID_D / 16); 835 vec.X = ((_target_velocity.X / movementdivisor) - vel.X) * (PID_D / 16);
999 vec.Y = ((_target_velocity.Y/movementdivisor) - vel.Y)*(PID_D / 16); 836 vec.Y = ((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D / 16);
1000 } 837 }
1001 else if (!m_iscolliding && flying) 838 else if (!m_iscolliding && flying)
1002 { 839 {
1003 // we're in mid air suspended 840 // we're in mid air suspended
1004 vec.X = ((_target_velocity.X / movementdivisor) - vel.X) * (PID_D/6); 841 vec.X = ((_target_velocity.X / movementdivisor) - vel.X) * (PID_D / 6);
1005 vec.Y = ((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D/6); 842 vec.Y = ((_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D / 6);
843
844// m_log.DebugFormat(
845// "[ODE CHARACTER]: !m_iscolliding && flying, vec {0}, _target_velocity {1}, movementdivisor {2}, vel {3}",
846// vec, _target_velocity, movementdivisor, vel);
1006 } 847 }
1007 848
1008 if (m_iscolliding && !flying && _target_velocity.Z > 0.0f) 849 if (m_iscolliding && !flying && _target_velocity.Z > 0.0f)
@@ -1013,11 +854,11 @@ namespace OpenSim.Region.Physics.OdePlugin
1013 vec.Z = (_target_velocity.Z - vel.Z)*PID_D + (_zeroPosition.Z - pos.Z)*PID_P; 854 vec.Z = (_target_velocity.Z - vel.Z)*PID_D + (_zeroPosition.Z - pos.Z)*PID_P;
1014 if (_target_velocity.X > 0) 855 if (_target_velocity.X > 0)
1015 { 856 {
1016 vec.X = ((_target_velocity.X - vel.X)/1.2f)*PID_D; 857 vec.X = ((_target_velocity.X - vel.X) / 1.2f) * PID_D;
1017 } 858 }
1018 if (_target_velocity.Y > 0) 859 if (_target_velocity.Y > 0)
1019 { 860 {
1020 vec.Y = ((_target_velocity.Y - vel.Y)/1.2f)*PID_D; 861 vec.Y = ((_target_velocity.Y - vel.Y) / 1.2f) * PID_D;
1021 } 862 }
1022 } 863 }
1023 else if (!m_iscolliding && !flying) 864 else if (!m_iscolliding && !flying)
@@ -1028,11 +869,11 @@ namespace OpenSim.Region.Physics.OdePlugin
1028 // d.Vector3 pos = d.BodyGetPosition(Body); 869 // d.Vector3 pos = d.BodyGetPosition(Body);
1029 if (_target_velocity.X > 0) 870 if (_target_velocity.X > 0)
1030 { 871 {
1031 vec.X = ((_target_velocity.X - vel.X)/1.2f)*PID_D; 872 vec.X = ((_target_velocity.X - vel.X) / 1.2f) * PID_D;
1032 } 873 }
1033 if (_target_velocity.Y > 0) 874 if (_target_velocity.Y > 0)
1034 { 875 {
1035 vec.Y = ((_target_velocity.Y - vel.Y)/1.2f)*PID_D; 876 vec.Y = ((_target_velocity.Y - vel.Y) / 1.2f) * PID_D;
1036 } 877 }
1037 } 878 }
1038 879
@@ -1041,9 +882,10 @@ namespace OpenSim.Region.Physics.OdePlugin
1041 vec.Z = (_target_velocity.Z - vel.Z) * (PID_D); 882 vec.Z = (_target_velocity.Z - vel.Z) * (PID_D);
1042 } 883 }
1043 } 884 }
885
1044 if (flying) 886 if (flying)
1045 { 887 {
1046 vec.Z += ((-1 * _parent_scene.gravityz)*m_mass); 888 vec.Z += ((-1 * _parent_scene.gravityz) * m_mass);
1047 889
1048 //Added for auto fly height. Kitto Flora 890 //Added for auto fly height. Kitto Flora
1049 //d.Vector3 pos = d.BodyGetPosition(Body); 891 //d.Vector3 pos = d.BodyGetPosition(Body);
@@ -1055,112 +897,98 @@ namespace OpenSim.Region.Physics.OdePlugin
1055 } 897 }
1056 // end add Kitto Flora 898 // end add Kitto Flora
1057 } 899 }
900
1058 if (vec.IsFinite()) 901 if (vec.IsFinite())
1059 { 902 {
1060 doForce(vec); 903 // Apply the total force acting on this avatar
904 d.BodyAddForce(Body, vec.X, vec.Y, vec.Z);
905
1061 if (!_zeroFlag) 906 if (!_zeroFlag)
1062 { 907 AlignAvatarTiltWithCurrentDirectionOfMovement(vec);
1063 AlignAvatarTiltWithCurrentDirectionOfMovement(vec);
1064 }
1065 } 908 }
1066 else 909 else
1067 { 910 {
1068 m_log.Warn("[PHYSICS]: Got a NaN force vector in Move()"); 911 m_log.WarnFormat(
1069 m_log.Warn("[PHYSICS]: Avatar Position is non-finite!"); 912 "[ODE CHARACTER]: Got a NaN force vector {0} in Move() for {1}. Removing character from physics scene.",
1070 defects.Add(this); 913 vec, Name);
1071 // _parent_scene.RemoveCharacter(this);
1072 // destroy avatar capsule and related ODE data
1073 if (Amotor != IntPtr.Zero)
1074 {
1075 // Kill the Amotor
1076 d.JointDestroy(Amotor);
1077 Amotor = IntPtr.Zero;
1078 }
1079 //kill the Geometry
1080 _parent_scene.waitForSpaceUnlock(_parent_scene.space);
1081
1082 if (Body != IntPtr.Zero)
1083 {
1084 //kill the body
1085 d.BodyDestroy(Body);
1086 914
1087 Body = IntPtr.Zero; 915 defects.Add(this);
1088 }
1089 916
1090 if (Shell != IntPtr.Zero) 917 return;
1091 {
1092 d.GeomDestroy(Shell);
1093 _parent_scene.geom_name_map.Remove(Shell);
1094 Shell = IntPtr.Zero;
1095 }
1096 } 918 }
1097 } 919 }
1098 920
1099 /// <summary> 921 /// <summary>
1100 /// Updates the reported position and velocity. This essentially sends the data up to ScenePresence. 922 /// Updates the reported position and velocity. This essentially sends the data up to ScenePresence.
1101 /// </summary> 923 /// </summary>
1102 public void UpdatePositionAndVelocity() 924 /// <param name="defects">The character will be added to this list if there is something wrong (non-finite
925 /// position or velocity).
926 /// </param>
927 internal void UpdatePositionAndVelocity(List<OdeCharacter> defects)
1103 { 928 {
1104 // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit! 929 // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
1105 d.Vector3 vec; 930 d.Vector3 newPos;
1106 try 931 try
1107 { 932 {
1108 vec = d.BodyGetPosition(Body); 933 newPos = d.BodyGetPosition(Body);
1109 } 934 }
1110 catch (NullReferenceException) 935 catch (NullReferenceException)
1111 { 936 {
1112 bad = true; 937 bad = true;
1113 _parent_scene.BadCharacter(this); 938 defects.Add(this);
1114 vec = new d.Vector3(_position.X, _position.Y, _position.Z); 939 newPos = new d.Vector3(_position.X, _position.Y, _position.Z);
1115 base.RaiseOutOfBounds(_position); // Tells ScenePresence that there's a problem! 940 base.RaiseOutOfBounds(_position); // Tells ScenePresence that there's a problem!
1116 m_log.WarnFormat("[ODEPLUGIN]: Avatar Null reference for Avatar {0}, physical actor {1}", m_name, m_uuid); 941 m_log.WarnFormat("[ODE CHARACTER]: Avatar Null reference for Avatar {0}, physical actor {1}", Name, m_uuid);
942
943 return;
1117 } 944 }
1118
1119 945
1120 // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!) 946 // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!)
1121 if (vec.X < 0.0f) vec.X = 0.0f; 947 if (newPos.X < 0.0f) newPos.X = 0.0f;
1122 if (vec.Y < 0.0f) vec.Y = 0.0f; 948 if (newPos.Y < 0.0f) newPos.Y = 0.0f;
1123 if (vec.X > (int)_parent_scene.WorldExtents.X - 0.05f) vec.X = (int)_parent_scene.WorldExtents.X - 0.05f; 949 if (newPos.X > (int)_parent_scene.WorldExtents.X - 0.05f) newPos.X = (int)_parent_scene.WorldExtents.X - 0.05f;
1124 if (vec.Y > (int)_parent_scene.WorldExtents.Y - 0.05f) vec.Y = (int)_parent_scene.WorldExtents.Y - 0.05f; 950 if (newPos.Y > (int)_parent_scene.WorldExtents.Y - 0.05f) newPos.Y = (int)_parent_scene.WorldExtents.Y - 0.05f;
951
952 _position.X = newPos.X;
953 _position.Y = newPos.Y;
954 _position.Z = newPos.Z;
1125 955
1126 _position.X = vec.X; 956 // I think we need to update the taintPosition too -- Diva 12/24/10
1127 _position.Y = vec.Y; 957 m_taintPosition = _position;
1128 _position.Z = vec.Z;
1129 958
1130 // Did we move last? = zeroflag 959 // Did we move last? = zeroflag
1131 // This helps keep us from sliding all over 960 // This helps keep us from sliding all over
1132 961
1133 if (_zeroFlag) 962 if (_zeroFlag)
1134 { 963 {
1135 _velocity.X = 0.0f; 964 _velocity = Vector3.Zero;
1136 _velocity.Y = 0.0f;
1137 _velocity.Z = 0.0f;
1138 965
1139 // Did we send out the 'stopped' message? 966 // Did we send out the 'stopped' message?
1140 if (!m_lastUpdateSent) 967 if (!m_lastUpdateSent)
1141 { 968 {
1142 m_lastUpdateSent = true; 969 m_lastUpdateSent = true;
1143 //base.RequestPhysicsterseUpdate(); 970 //base.RequestPhysicsterseUpdate();
1144
1145 } 971 }
1146 } 972 }
1147 else 973 else
1148 { 974 {
1149 m_lastUpdateSent = false; 975 m_lastUpdateSent = false;
976 d.Vector3 newVelocity;
977
1150 try 978 try
1151 { 979 {
1152 vec = d.BodyGetLinearVel(Body); 980 newVelocity = d.BodyGetLinearVel(Body);
1153 } 981 }
1154 catch (NullReferenceException) 982 catch (NullReferenceException)
1155 { 983 {
1156 vec.X = _velocity.X; 984 newVelocity.X = _velocity.X;
1157 vec.Y = _velocity.Y; 985 newVelocity.Y = _velocity.Y;
1158 vec.Z = _velocity.Z; 986 newVelocity.Z = _velocity.Z;
1159 } 987 }
1160 _velocity.X = (vec.X);
1161 _velocity.Y = (vec.Y);
1162 988
1163 _velocity.Z = (vec.Z); 989 _velocity.X = newVelocity.X;
990 _velocity.Y = newVelocity.Y;
991 _velocity.Z = newVelocity.Z;
1164 992
1165 if (_velocity.Z < -6 && !m_hackSentFall) 993 if (_velocity.Z < -6 && !m_hackSentFall)
1166 { 994 {
@@ -1181,14 +1009,164 @@ namespace OpenSim.Region.Physics.OdePlugin
1181 } 1009 }
1182 1010
1183 /// <summary> 1011 /// <summary>
1012 /// This creates the Avatar's physical Surrogate in ODE at the position supplied
1013 /// </summary>
1014 /// <remarks>
1015 /// WARNING: This MUST NOT be called outside of ProcessTaints, else we can have unsynchronized access
1016 /// to ODE internals. ProcessTaints is called from within thread-locked Simulate(), so it is the only
1017 /// place that is safe to call this routine AvatarGeomAndBodyCreation.
1018 /// </remarks>
1019 /// <param name="npositionX"></param>
1020 /// <param name="npositionY"></param>
1021 /// <param name="npositionZ"></param>
1022 /// <param name="tensor"></param>
1023 private void CreateOdeStructures(float npositionX, float npositionY, float npositionZ, float tensor)
1024 {
1025 int dAMotorEuler = 1;
1026// _parent_scene.waitForSpaceUnlock(_parent_scene.space);
1027 if (CAPSULE_LENGTH <= 0)
1028 {
1029 m_log.Warn("[ODE CHARACTER]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!");
1030 CAPSULE_LENGTH = 0.01f;
1031 }
1032
1033 if (CAPSULE_RADIUS <= 0)
1034 {
1035 m_log.Warn("[ODE CHARACTER]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!");
1036 CAPSULE_RADIUS = 0.01f;
1037 }
1038
1039 Shell = d.CreateCapsule(_parent_scene.space, CAPSULE_RADIUS, CAPSULE_LENGTH);
1040
1041 d.GeomSetCategoryBits(Shell, (int)m_collisionCategories);
1042 d.GeomSetCollideBits(Shell, (int)m_collisionFlags);
1043
1044 d.MassSetCapsuleTotal(out ShellMass, m_mass, 2, CAPSULE_RADIUS, CAPSULE_LENGTH);
1045 Body = d.BodyCreate(_parent_scene.world);
1046 d.BodySetPosition(Body, npositionX, npositionY, npositionZ);
1047
1048 _position.X = npositionX;
1049 _position.Y = npositionY;
1050 _position.Z = npositionZ;
1051
1052 m_taintPosition = _position;
1053
1054 d.BodySetMass(Body, ref ShellMass);
1055 d.Matrix3 m_caprot;
1056 // 90 Stand up on the cap of the capped cyllinder
1057 if (_parent_scene.IsAvCapsuleTilted)
1058 {
1059 d.RFromAxisAndAngle(out m_caprot, 1, 0, 1, (float)(Math.PI / 2));
1060 }
1061 else
1062 {
1063 d.RFromAxisAndAngle(out m_caprot, 0, 0, 1, (float)(Math.PI / 2));
1064 }
1065
1066 d.GeomSetRotation(Shell, ref m_caprot);
1067 d.BodySetRotation(Body, ref m_caprot);
1068
1069 d.GeomSetBody(Shell, Body);
1070
1071 // The purpose of the AMotor here is to keep the avatar's physical
1072 // surrogate from rotating while moving
1073 Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero);
1074 d.JointAttach(Amotor, Body, IntPtr.Zero);
1075 d.JointSetAMotorMode(Amotor, dAMotorEuler);
1076 d.JointSetAMotorNumAxes(Amotor, 3);
1077 d.JointSetAMotorAxis(Amotor, 0, 0, 1, 0, 0);
1078 d.JointSetAMotorAxis(Amotor, 1, 0, 0, 1, 0);
1079 d.JointSetAMotorAxis(Amotor, 2, 0, 0, 0, 1);
1080 d.JointSetAMotorAngle(Amotor, 0, 0);
1081 d.JointSetAMotorAngle(Amotor, 1, 0);
1082 d.JointSetAMotorAngle(Amotor, 2, 0);
1083
1084 // These lowstops and high stops are effectively (no wiggle room)
1085 if (_parent_scene.IsAvCapsuleTilted)
1086 {
1087 d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, -0.000000000001f);
1088 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -0.000000000001f);
1089 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, -0.000000000001f);
1090 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0.000000000001f);
1091 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0.000000000001f);
1092 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0.000000000001f);
1093 }
1094 else
1095 {
1096 #region Documentation of capsule motor LowStop and HighStop parameters
1097 // Intentionally introduce some tilt into the capsule by setting
1098 // the motor stops to small epsilon values. This small tilt prevents
1099 // the capsule from falling into the terrain; a straight-up capsule
1100 // (with -0..0 motor stops) falls into the terrain for reasons yet
1101 // to be comprehended in their entirety.
1102 #endregion
1103 AlignAvatarTiltWithCurrentDirectionOfMovement(Vector3.Zero);
1104 d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, 0.08f);
1105 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -0f);
1106 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, 0.08f);
1107 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0.08f); // must be same as lowstop, else a different, spurious tilt is introduced
1108 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0f); // same as lowstop
1109 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0.08f); // same as lowstop
1110 }
1111
1112 // Fudge factor is 1f by default, we're setting it to 0. We don't want it to Fudge or the
1113 // capped cyllinder will fall over
1114 d.JointSetAMotorParam(Amotor, (int)dParam.FudgeFactor, 0f);
1115 d.JointSetAMotorParam(Amotor, (int)dParam.FMax, tensor);
1116
1117 //d.Matrix3 bodyrotation = d.BodyGetRotation(Body);
1118 //d.QfromR(
1119 //d.Matrix3 checkrotation = new d.Matrix3(0.7071068,0.5, -0.7071068,
1120 //
1121 //m_log.Info("[PHYSICSAV]: Rotation: " + bodyrotation.M00 + " : " + bodyrotation.M01 + " : " + bodyrotation.M02 + " : " + bodyrotation.M10 + " : " + bodyrotation.M11 + " : " + bodyrotation.M12 + " : " + bodyrotation.M20 + " : " + bodyrotation.M21 + " : " + bodyrotation.M22);
1122 //standupStraight();
1123
1124 _parent_scene.geom_name_map[Shell] = Name;
1125 _parent_scene.actor_name_map[Shell] = this;
1126 }
1127
1128 /// <summary>
1184 /// Cleanup the things we use in the scene. 1129 /// Cleanup the things we use in the scene.
1185 /// </summary> 1130 /// </summary>
1186 public void Destroy() 1131 internal void Destroy()
1187 { 1132 {
1188 m_tainted_isPhysical = false; 1133 m_tainted_isPhysical = false;
1189 _parent_scene.AddPhysicsActorTaint(this); 1134 _parent_scene.AddPhysicsActorTaint(this);
1190 } 1135 }
1191 1136
1137 /// <summary>
1138 /// Used internally to destroy the ODE structures associated with this character.
1139 /// </summary>
1140 internal void DestroyOdeStructures()
1141 {
1142 // destroy avatar capsule and related ODE data
1143 if (Amotor != IntPtr.Zero)
1144 {
1145 // Kill the Amotor
1146 d.JointDestroy(Amotor);
1147 Amotor = IntPtr.Zero;
1148 }
1149
1150 //kill the Geometry
1151// _parent_scene.waitForSpaceUnlock(_parent_scene.space);
1152
1153 if (Body != IntPtr.Zero)
1154 {
1155 //kill the body
1156 d.BodyDestroy(Body);
1157 Body = IntPtr.Zero;
1158 }
1159
1160 if (Shell != IntPtr.Zero)
1161 {
1162 d.GeomDestroy(Shell);
1163 _parent_scene.geom_name_map.Remove(Shell);
1164 _parent_scene.actor_name_map.Remove(Shell);
1165
1166 Shell = IntPtr.Zero;
1167 }
1168 }
1169
1192 public override void CrossingFailure() 1170 public override void CrossingFailure()
1193 { 1171 {
1194 } 1172 }
@@ -1214,34 +1192,40 @@ namespace OpenSim.Region.Physics.OdePlugin
1214 { 1192 {
1215 m_requestedUpdateFrequency = ms; 1193 m_requestedUpdateFrequency = ms;
1216 m_eventsubscription = ms; 1194 m_eventsubscription = ms;
1217 _parent_scene.addCollisionEventReporting(this); 1195 CollisionEventsThisFrame.Clear();
1196 _parent_scene.AddCollisionEventReporting(this);
1218 } 1197 }
1198
1219 public override void UnSubscribeEvents() 1199 public override void UnSubscribeEvents()
1220 { 1200 {
1221 _parent_scene.remCollisionEventReporting(this); 1201 CollisionEventsThisFrame.Clear();
1202 _parent_scene.RemoveCollisionEventReporting(this);
1222 m_requestedUpdateFrequency = 0; 1203 m_requestedUpdateFrequency = 0;
1223 m_eventsubscription = 0; 1204 m_eventsubscription = 0;
1224 } 1205 }
1225 public void AddCollisionEvent(uint CollidedWith, ContactPoint contact) 1206
1207 internal void AddCollisionEvent(uint CollidedWith, ContactPoint contact)
1226 { 1208 {
1227 if (m_eventsubscription > 0) 1209 if (m_eventsubscription > 0)
1228 { 1210 {
1229 CollisionEventsThisFrame.addCollider(CollidedWith, contact); 1211// m_log.DebugFormat(
1212// "[PHYSICS]: Adding collision event for {0}, collidedWith {1}, contact {2}", "", CollidedWith, contact);
1213
1214 CollisionEventsThisFrame.AddCollider(CollidedWith, contact);
1230 } 1215 }
1231 } 1216 }
1232 1217
1233 public void SendCollisions() 1218 internal void SendCollisions()
1234 { 1219 {
1235 if (m_eventsubscription > m_requestedUpdateFrequency) 1220 if (m_eventsubscription > m_requestedUpdateFrequency)
1236 { 1221 {
1237 if (CollisionEventsThisFrame != null) 1222 base.SendCollisionUpdate(CollisionEventsThisFrame);
1238 { 1223
1239 base.SendCollisionUpdate(CollisionEventsThisFrame); 1224 CollisionEventsThisFrame.Clear();
1240 }
1241 CollisionEventsThisFrame = new CollisionEventUpdate();
1242 m_eventsubscription = 0; 1225 m_eventsubscription = 0;
1243 } 1226 }
1244 } 1227 }
1228
1245 public override bool SubscribedEvents() 1229 public override bool SubscribedEvents()
1246 { 1230 {
1247 if (m_eventsubscription > 0) 1231 if (m_eventsubscription > 0)
@@ -1249,8 +1233,32 @@ namespace OpenSim.Region.Physics.OdePlugin
1249 return false; 1233 return false;
1250 } 1234 }
1251 1235
1252 public void ProcessTaints(float timestep) 1236 internal void ProcessTaints()
1253 { 1237 {
1238 if (m_taintPosition != _position)
1239 {
1240 if (Body != IntPtr.Zero)
1241 {
1242 d.BodySetPosition(Body, m_taintPosition.X, m_taintPosition.Y, m_taintPosition.Z);
1243 _position = m_taintPosition;
1244 }
1245 }
1246
1247 if (m_taintForce != Vector3.Zero)
1248 {
1249 if (Body != IntPtr.Zero)
1250 {
1251 // FIXME: This is not a good solution since it's subject to a race condition if a force is another
1252 // thread sets a new force while we're in this loop (since it could be obliterated by
1253 // m_taintForce = Vector3.Zero. Need to lock ProcessTaints() when we set a new tainted force.
1254 d.BodyAddForce(Body, m_taintForce.X, m_taintForce.Y, m_taintForce.Z);
1255 }
1256
1257 m_taintForce = Vector3.Zero;
1258 }
1259
1260 if (m_taintTargetVelocity != _target_velocity)
1261 _target_velocity = m_taintTargetVelocity;
1254 1262
1255 if (m_tainted_isPhysical != m_isPhysical) 1263 if (m_tainted_isPhysical != m_isPhysical)
1256 { 1264 {
@@ -1259,45 +1267,19 @@ namespace OpenSim.Region.Physics.OdePlugin
1259 // Create avatar capsule and related ODE data 1267 // Create avatar capsule and related ODE data
1260 if (!(Shell == IntPtr.Zero && Body == IntPtr.Zero && Amotor == IntPtr.Zero)) 1268 if (!(Shell == IntPtr.Zero && Body == IntPtr.Zero && Amotor == IntPtr.Zero))
1261 { 1269 {
1262 m_log.Warn("[PHYSICS]: re-creating the following avatar ODE data, even though it already exists - " 1270 m_log.Warn("[ODE CHARACTER]: re-creating the following avatar ODE data for " + Name + ", even though it already exists - "
1263 + (Shell!=IntPtr.Zero ? "Shell ":"") 1271 + (Shell!=IntPtr.Zero ? "Shell ":"")
1264 + (Body!=IntPtr.Zero ? "Body ":"") 1272 + (Body!=IntPtr.Zero ? "Body ":"")
1265 + (Amotor!=IntPtr.Zero ? "Amotor ":"")); 1273 + (Amotor!=IntPtr.Zero ? "Amotor ":""));
1266 } 1274 }
1267 AvatarGeomAndBodyCreation(_position.X, _position.Y, _position.Z, m_tensor); 1275
1268 1276 CreateOdeStructures(_position.X, _position.Y, _position.Z, m_tensor);
1269 _parent_scene.geom_name_map[Shell] = m_name;
1270 _parent_scene.actor_name_map[Shell] = (PhysicsActor)this;
1271 _parent_scene.AddCharacter(this); 1277 _parent_scene.AddCharacter(this);
1272 } 1278 }
1273 else 1279 else
1274 { 1280 {
1275 _parent_scene.RemoveCharacter(this); 1281 _parent_scene.RemoveCharacter(this);
1276 // destroy avatar capsule and related ODE data 1282 DestroyOdeStructures();
1277 if (Amotor != IntPtr.Zero)
1278 {
1279 // Kill the Amotor
1280 d.JointDestroy(Amotor);
1281 Amotor = IntPtr.Zero;
1282 }
1283 //kill the Geometry
1284 _parent_scene.waitForSpaceUnlock(_parent_scene.space);
1285
1286 if (Body != IntPtr.Zero)
1287 {
1288 //kill the body
1289 d.BodyDestroy(Body);
1290
1291 Body = IntPtr.Zero;
1292 }
1293
1294 if (Shell != IntPtr.Zero)
1295 {
1296 d.GeomDestroy(Shell);
1297 _parent_scene.geom_name_map.Remove(Shell);
1298 Shell = IntPtr.Zero;
1299 }
1300
1301 } 1283 }
1302 1284
1303 m_isPhysical = m_tainted_isPhysical; 1285 m_isPhysical = m_tainted_isPhysical;
@@ -1307,43 +1289,35 @@ namespace OpenSim.Region.Physics.OdePlugin
1307 { 1289 {
1308 if (Shell != IntPtr.Zero && Body != IntPtr.Zero && Amotor != IntPtr.Zero) 1290 if (Shell != IntPtr.Zero && Body != IntPtr.Zero && Amotor != IntPtr.Zero)
1309 { 1291 {
1310 1292// m_log.DebugFormat(
1293// "[ODE CHARACTER]: Changing capsule size from {0} to {1} for {2}",
1294// CAPSULE_LENGTH, m_tainted_CAPSULE_LENGTH, Name);
1295
1311 m_pidControllerActive = true; 1296 m_pidControllerActive = true;
1297
1312 // no lock needed on _parent_scene.OdeLock because we are called from within the thread lock in OdePlugin's simulate() 1298 // no lock needed on _parent_scene.OdeLock because we are called from within the thread lock in OdePlugin's simulate()
1313 d.JointDestroy(Amotor); 1299 DestroyOdeStructures();
1300
1314 float prevCapsule = CAPSULE_LENGTH; 1301 float prevCapsule = CAPSULE_LENGTH;
1315 CAPSULE_LENGTH = m_tainted_CAPSULE_LENGTH; 1302 CAPSULE_LENGTH = m_tainted_CAPSULE_LENGTH;
1316 //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString()); 1303
1317 d.BodyDestroy(Body); 1304 CreateOdeStructures(
1318 d.GeomDestroy(Shell); 1305 _position.X,
1319 AvatarGeomAndBodyCreation(_position.X, _position.Y, 1306 _position.Y,
1320 _position.Z + (Math.Abs(CAPSULE_LENGTH - prevCapsule) * 2), m_tensor); 1307 _position.Z + (Math.Abs(CAPSULE_LENGTH - prevCapsule) * 2), m_tensor);
1321 Velocity = Vector3.Zero; 1308
1322 1309 // As with Size, we reset velocity. However, this isn't strictly necessary since it doesn't
1323 _parent_scene.geom_name_map[Shell] = m_name; 1310 // appear to stall initial region crossings when done here. Being done for consistency.
1324 _parent_scene.actor_name_map[Shell] = (PhysicsActor)this; 1311// Velocity = Vector3.Zero;
1325 } 1312 }
1326 else 1313 else
1327 { 1314 {
1328 m_log.Warn("[PHYSICS]: trying to change capsule size, but the following ODE data is missing - " 1315 m_log.Warn("[ODE CHARACTER]: trying to change capsule size for " + Name + ", but the following ODE data is missing - "
1329 + (Shell==IntPtr.Zero ? "Shell ":"") 1316 + (Shell==IntPtr.Zero ? "Shell ":"")
1330 + (Body==IntPtr.Zero ? "Body ":"") 1317 + (Body==IntPtr.Zero ? "Body ":"")
1331 + (Amotor==IntPtr.Zero ? "Amotor ":"")); 1318 + (Amotor==IntPtr.Zero ? "Amotor ":""));
1332 } 1319 }
1333 } 1320 }
1334
1335 if (!m_taintPosition.ApproxEquals(_position, 0.05f))
1336 {
1337 if (Body != IntPtr.Zero)
1338 {
1339 d.BodySetPosition(Body, m_taintPosition.X, m_taintPosition.Y, m_taintPosition.Z);
1340
1341 _position.X = m_taintPosition.X;
1342 _position.Y = m_taintPosition.Y;
1343 _position.Z = m_taintPosition.Z;
1344 }
1345 }
1346
1347 } 1321 }
1348 1322
1349 internal void AddCollisionFrameTime(int p) 1323 internal void AddCollisionFrameTime(int p)
@@ -1354,4 +1328,4 @@ namespace OpenSim.Region.Physics.OdePlugin
1354 m_eventsubscription += p; 1328 m_eventsubscription += p;
1355 } 1329 }
1356 } 1330 }
1357} 1331} \ No newline at end of file