diff options
Diffstat (limited to 'OpenSim/Region/Physics/OdePlugin/ODECharacter.cs')
-rw-r--r-- | OpenSim/Region/Physics/OdePlugin/ODECharacter.cs | 758 |
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 |