aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs')
-rw-r--r--OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs1104
1 files changed, 1104 insertions, 0 deletions
diff --git a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs
new file mode 100644
index 0000000..6791671
--- /dev/null
+++ b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs
@@ -0,0 +1,1104 @@
1using System;
2using System.Reflection;
3using BulletDotNET;
4using OpenMetaverse;
5using OpenSim.Framework;
6using OpenSim.Region.Physics.Manager;
7using log4net;
8
9namespace OpenSim.Region.Physics.BulletDotNETPlugin
10{
11 public class BulletDotNETCharacter : PhysicsActor
12 {
13 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
14
15 public btRigidBody Body;
16 public btCollisionShape Shell;
17 public btVector3 tempVector1;
18 public btVector3 tempVector2;
19 public btVector3 tempVector3;
20 public btVector3 tempVector4;
21
22 public btVector3 tempVector5RayCast;
23 public btVector3 tempVector6RayCast;
24 public btVector3 tempVector7RayCast;
25
26 public btQuaternion tempQuat1;
27 public btTransform tempTrans1;
28
29 public ClosestNotMeRayResultCallback ClosestCastResult;
30 private btTransform m_bodyTransform;
31 private btVector3 m_bodyPosition;
32 private btVector3 m_CapsuleOrientationAxis;
33 private btQuaternion m_bodyOrientation;
34 private btDefaultMotionState m_bodyMotionState;
35 private btGeneric6DofConstraint m_aMotor;
36 private PhysicsVector m_movementComparision;
37 private PhysicsVector m_position;
38 private PhysicsVector m_zeroPosition;
39 private bool m_zeroFlag = false;
40 private bool m_lastUpdateSent = false;
41 private PhysicsVector m_velocity;
42 private PhysicsVector m_target_velocity;
43 private PhysicsVector m_acceleration;
44 private PhysicsVector m_rotationalVelocity;
45 private bool m_pidControllerActive = true;
46 public float PID_D = 80.0f;
47 public float PID_P = 90.0f;
48 public float CAPSULE_RADIUS = 0.37f;
49 public float CAPSULE_LENGTH = 2.140599f;
50 public float heightFudgeFactor = 0.52f;
51 public float walkDivisor = 1.3f;
52 public float runDivisor = 0.8f;
53 private float m_mass = 80f;
54 public float m_density = 60f;
55 private bool m_flying = false;
56 private bool m_iscolliding = false;
57 private bool m_iscollidingGround = false;
58 private bool m_wascolliding = false;
59 private bool m_wascollidingGround = false;
60 private bool m_iscollidingObj = false;
61 private bool m_alwaysRun = false;
62 private bool m_hackSentFall = false;
63 private bool m_hackSentFly = false;
64 public uint m_localID = 0;
65 public bool m_returnCollisions = false;
66 // taints and their non-tainted counterparts
67 public bool m_isPhysical = false; // the current physical status
68 public bool m_tainted_isPhysical = false; // set when the physical status is tainted (false=not existing in physics engine, true=existing)
69 private float m_tainted_CAPSULE_LENGTH; // set when the capsule length changes.
70 private bool m_taintRemove = false;
71 private bool m_taintedPosition = false;
72 private PhysicsVector m_taintedPosition_value;
73 private PhysicsVector m_taintedForce;
74
75 private float m_buoyancy = 0f;
76
77 // private CollisionLocker ode;
78
79 private string m_name = String.Empty;
80
81 private bool[] m_colliderarr = new bool[11];
82 private bool[] m_colliderGroundarr = new bool[11];
83
84
85
86 private BulletDotNETScene m_parent_scene;
87
88 public int m_eventsubscription = 0;
89 private CollisionEventUpdate CollisionEventsThisFrame = new CollisionEventUpdate();
90
91 public BulletDotNETCharacter(string avName, BulletDotNETScene parent_scene, PhysicsVector pos, PhysicsVector size, float pid_d, float pid_p, float capsule_radius, float tensor, float density, float height_fudge_factor, float walk_divisor, float rundivisor)
92 {
93 m_taintedForce = new PhysicsVector();
94 m_velocity = new PhysicsVector();
95 m_target_velocity = new PhysicsVector();
96 m_position = pos;
97 m_zeroPosition = new PhysicsVector(pos.X, pos.Y, pos.Z); // this is a class, not a struct. Must make new, or m_zeroPosition will == position regardless
98 m_acceleration = new PhysicsVector();
99 m_parent_scene = parent_scene;
100 PID_D = pid_d;
101 PID_P = pid_p;
102 CAPSULE_RADIUS = capsule_radius;
103 m_density = density;
104 heightFudgeFactor = height_fudge_factor;
105 walkDivisor = walk_divisor;
106 runDivisor = rundivisor;
107
108 for (int i = 0; i < 11; i++)
109 {
110 m_colliderarr[i] = false;
111 }
112 for (int i = 0; i < 11; i++)
113 {
114 m_colliderGroundarr[i] = false;
115 }
116 CAPSULE_LENGTH = (size.Z * 1.15f) - CAPSULE_RADIUS * 2.0f;
117 m_tainted_CAPSULE_LENGTH = CAPSULE_LENGTH;
118 m_isPhysical = false; // current status: no ODE information exists
119 m_tainted_isPhysical = true; // new tainted status: need to create ODE information
120
121 m_parent_scene.AddPhysicsActorTaint(this);
122
123 m_name = avName;
124 tempVector1 = new btVector3(0, 0, 0);
125 tempVector2 = new btVector3(0, 0, 0);
126 tempVector3 = new btVector3(0, 0, 0);
127 tempVector4 = new btVector3(0, 0, 0);
128
129 tempVector5RayCast = new btVector3(0, 0, 0);
130 tempVector6RayCast = new btVector3(0, 0, 0);
131 tempVector7RayCast = new btVector3(0, 0, 0);
132
133 tempQuat1 = new btQuaternion(0, 0, 0, 1);
134 tempTrans1 = new btTransform(tempQuat1, tempVector1);
135 m_movementComparision = new PhysicsVector(0, 0, 0);
136 m_CapsuleOrientationAxis = new btVector3(1, 0, 1);
137
138
139
140 }
141
142 /// <summary>
143 /// This creates the Avatar's physical Surrogate at the position supplied
144 /// </summary>
145 /// <param name="npositionX"></param>
146 /// <param name="npositionY"></param>
147 /// <param name="npositionZ"></param>
148
149 // WARNING: This MUST NOT be called outside of ProcessTaints, else we can have unsynchronized access
150 // to ODE internals. ProcessTaints is called from within thread-locked Simulate(), so it is the only
151 // place that is safe to call this routine AvatarGeomAndBodyCreation.
152 private void AvatarGeomAndBodyCreation(float npositionX, float npositionY, float npositionZ)
153 {
154
155 if (CAPSULE_LENGTH <= 0)
156 {
157 m_log.Warn("[PHYSICS]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!");
158 CAPSULE_LENGTH = 0.01f;
159
160 }
161
162 if (CAPSULE_RADIUS <= 0)
163 {
164 m_log.Warn("[PHYSICS]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!");
165 CAPSULE_RADIUS = 0.01f;
166
167 }
168
169 Shell = new btCapsuleShape(CAPSULE_RADIUS, CAPSULE_LENGTH);
170
171 if (m_bodyPosition == null)
172 m_bodyPosition = new btVector3(npositionX, npositionY, npositionZ);
173
174 m_bodyPosition.setValue(npositionX, npositionY, npositionZ);
175
176 if (m_bodyOrientation == null)
177 m_bodyOrientation = new btQuaternion(m_CapsuleOrientationAxis, (Utils.DEG_TO_RAD * 90));
178
179 if (m_bodyTransform == null)
180 m_bodyTransform = new btTransform(m_bodyOrientation, m_bodyPosition);
181 else
182 {
183 m_bodyTransform.Dispose();
184 m_bodyTransform = new btTransform(m_bodyOrientation, m_bodyPosition);
185 }
186
187 if (m_bodyMotionState == null)
188 m_bodyMotionState = new btDefaultMotionState(m_bodyTransform);
189 else
190 m_bodyMotionState.setWorldTransform(m_bodyTransform);
191
192 m_mass = Mass;
193
194 Body = new btRigidBody(m_mass, m_bodyMotionState, Shell);
195 Body.setUserPointer(new IntPtr((int)Body.Handle));
196
197 if (ClosestCastResult != null)
198 ClosestCastResult.Dispose();
199 ClosestCastResult = new ClosestNotMeRayResultCallback(Body);
200
201 m_parent_scene.AddRigidBody(Body);
202 Body.setActivationState(4);
203 if (m_aMotor != null)
204 {
205 if (m_aMotor.Handle != IntPtr.Zero)
206 {
207 m_parent_scene.getBulletWorld().removeConstraint(m_aMotor);
208 m_aMotor.Dispose();
209 }
210 m_aMotor = null;
211 }
212
213 m_aMotor = new btGeneric6DofConstraint(Body, m_parent_scene.TerrainBody,
214 m_parent_scene.TransZero,
215 m_parent_scene.TransZero, false);
216 m_aMotor.setAngularLowerLimit(m_parent_scene.VectorZero);
217 m_aMotor.setAngularUpperLimit(m_parent_scene.VectorZero);
218
219
220 }
221 public void Remove()
222 {
223 m_taintRemove = true;
224 }
225 public override bool Stopped
226 {
227 get { return m_zeroFlag; }
228 }
229
230 public override PhysicsVector Size
231 {
232 get { return new PhysicsVector(CAPSULE_RADIUS * 2, CAPSULE_RADIUS * 2, CAPSULE_LENGTH); }
233 set
234 {
235 m_pidControllerActive = true;
236
237 PhysicsVector SetSize = value;
238 m_tainted_CAPSULE_LENGTH = (SetSize.Z * 1.15f) - CAPSULE_RADIUS * 2.0f;
239 //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString());
240
241 Velocity = new PhysicsVector(0f, 0f, 0f);
242
243 m_parent_scene.AddPhysicsActorTaint(this);
244 }
245 }
246
247 /// <summary>
248 /// turn the PID controller on or off.
249 /// The PID Controller will turn on all by itself in many situations
250 /// </summary>
251 /// <param name="status"></param>
252 public void SetPidStatus(bool status)
253 {
254 m_pidControllerActive = status;
255 }
256
257 public override PrimitiveBaseShape Shape
258 {
259 set { return; }
260 }
261
262 public override uint LocalID
263 {
264 set { m_localID = value; }
265 }
266
267 public override bool Grabbed
268 {
269 set { return; }
270 }
271
272 public override bool Selected
273 {
274 set { return; }
275 }
276
277
278 public override void CrossingFailure()
279 {
280
281 }
282
283 public override void link(PhysicsActor obj)
284 {
285
286 }
287
288 public override void delink()
289 {
290
291 }
292
293 public override void LockAngularMotion(PhysicsVector axis)
294 {
295
296 }
297
298 public override PhysicsVector Position
299 {
300 get { return m_position; }
301 set
302 {
303 m_taintedPosition_value = value;
304 m_position = value;
305 m_taintedPosition = true;
306 }
307 }
308
309 public override float Mass
310 {
311 get
312 {
313 float AVvolume = (float)(Math.PI * Math.Pow(CAPSULE_RADIUS, 2) * CAPSULE_LENGTH);
314 return m_density * AVvolume;
315 }
316 }
317
318 public override PhysicsVector Force
319 {
320 get { return new PhysicsVector(m_target_velocity.X, m_target_velocity.Y, m_target_velocity.Z); }
321 set { return; }
322 }
323
324 public override int VehicleType
325 {
326 get { return 0; }
327 set { return; }
328 }
329
330 public override void VehicleFloatParam(int param, float value)
331 {
332
333 }
334
335 public override void VehicleVectorParam(int param, PhysicsVector value)
336 {
337
338 }
339
340 public override void VehicleRotationParam(int param, Quaternion rotation)
341 {
342
343 }
344
345 public override void SetVolumeDetect(int param)
346 {
347
348 }
349
350 public override PhysicsVector GeometricCenter
351 {
352 get { return PhysicsVector.Zero; }
353 }
354
355 public override PhysicsVector CenterOfMass
356 {
357 get { return PhysicsVector.Zero; }
358 }
359
360 public override PhysicsVector Velocity
361 {
362 get
363 {
364 // There's a problem with PhysicsVector.Zero! Don't Use it Here!
365 if (m_zeroFlag)
366 return new PhysicsVector(0f, 0f, 0f);
367 m_lastUpdateSent = false;
368 return m_velocity;
369 }
370 set
371 {
372 m_pidControllerActive = true;
373 m_target_velocity = value;
374 }
375 }
376
377 public override PhysicsVector Torque
378 {
379 get { return PhysicsVector.Zero; }
380 set { return; }
381 }
382
383 public override float CollisionScore
384 {
385 get { return 0f; }
386 set { }
387 }
388
389 public override PhysicsVector Acceleration
390 {
391 get { return m_acceleration; }
392 }
393
394 public override Quaternion Orientation
395 {
396 get { return Quaternion.Identity; }
397 set
398 {
399
400 }
401 }
402
403 public override int PhysicsActorType
404 {
405 get { return (int)ActorTypes.Agent; }
406 set { return; }
407 }
408
409 public override bool IsPhysical
410 {
411 get { return false; }
412 set { return; }
413 }
414
415 public override bool Flying
416 {
417 get { return m_flying; }
418 set { m_flying = value; }
419 }
420
421 public override bool SetAlwaysRun
422 {
423 get { return m_alwaysRun; }
424 set { m_alwaysRun = value; }
425 }
426
427
428 public override bool ThrottleUpdates
429 {
430 get { return false; }
431 set { return; }
432 }
433
434 /// <summary>
435 /// Returns if the avatar is colliding in general.
436 /// This includes the ground and objects and avatar.
437 /// </summary>
438 public override bool IsColliding
439 {
440 get { return m_iscolliding; }
441 set
442 {
443 int i;
444 int truecount = 0;
445 int falsecount = 0;
446
447 if (m_colliderarr.Length >= 10)
448 {
449 for (i = 0; i < 10; i++)
450 {
451 m_colliderarr[i] = m_colliderarr[i + 1];
452 }
453 }
454 m_colliderarr[10] = value;
455
456 for (i = 0; i < 11; i++)
457 {
458 if (m_colliderarr[i])
459 {
460 truecount++;
461 }
462 else
463 {
464 falsecount++;
465 }
466 }
467
468 // Equal truecounts and false counts means we're colliding with something.
469 m_log.DebugFormat("[PHYSICS]: TrueCount:{0}, FalseCount:{1}",truecount,falsecount);
470 if (falsecount > 1.2 * truecount)
471 {
472 m_iscolliding = false;
473 }
474 else
475 {
476 m_iscolliding = true;
477 }
478 if (m_wascolliding != m_iscolliding)
479 {
480 //base.SendCollisionUpdate(new CollisionEventUpdate());
481 }
482 m_wascolliding = m_iscolliding;
483 }
484 }
485
486 /// <summary>
487 /// Returns if an avatar is colliding with the ground
488 /// </summary>
489 public override bool CollidingGround
490 {
491 get { return m_iscollidingGround; }
492 set
493 {
494 // Collisions against the ground are not really reliable
495 // So, to get a consistant value we have to average the current result over time
496 // Currently we use 1 second = 10 calls to this.
497 int i;
498 int truecount = 0;
499 int falsecount = 0;
500
501 if (m_colliderGroundarr.Length >= 10)
502 {
503 for (i = 0; i < 10; i++)
504 {
505 m_colliderGroundarr[i] = m_colliderGroundarr[i + 1];
506 }
507 }
508 m_colliderGroundarr[10] = value;
509
510 for (i = 0; i < 11; i++)
511 {
512 if (m_colliderGroundarr[i])
513 {
514 truecount++;
515 }
516 else
517 {
518 falsecount++;
519 }
520 }
521
522 // Equal truecounts and false counts means we're colliding with something.
523
524 if (falsecount > 1.2 * truecount)
525 {
526 m_iscollidingGround = false;
527 }
528 else
529 {
530 m_iscollidingGround = true;
531 }
532 if (m_wascollidingGround != m_iscollidingGround)
533 {
534 //base.SendCollisionUpdate(new CollisionEventUpdate());
535 }
536 m_wascollidingGround = m_iscollidingGround;
537 }
538 }
539
540 /// <summary>
541 /// Returns if the avatar is colliding with an object
542 /// </summary>
543 public override bool CollidingObj
544 {
545 get { return m_iscollidingObj; }
546 set
547 {
548 m_iscollidingObj = value;
549 if (value)
550 m_pidControllerActive = false;
551 else
552 m_pidControllerActive = true;
553 }
554 }
555
556
557 public override bool FloatOnWater
558 {
559 set { return; }
560 }
561
562 public override PhysicsVector RotationalVelocity
563 {
564 get { return m_rotationalVelocity; }
565 set { m_rotationalVelocity = value; }
566 }
567
568 public override bool Kinematic
569 {
570 get { return false; }
571 set { }
572 }
573
574 public override float Buoyancy
575 {
576 get { return m_buoyancy; }
577 set { m_buoyancy = value; }
578 }
579
580 public override PhysicsVector PIDTarget { set { return; } }
581 public override bool PIDActive { set { return; } }
582 public override float PIDTau { set { return; } }
583
584 public override bool PIDHoverActive
585 {
586 set { return; }
587 }
588
589 public override float PIDHoverHeight
590 {
591 set { return; }
592 }
593
594 public override PIDHoverType PIDHoverType
595 {
596 set { return; }
597 }
598
599 public override float PIDHoverTau
600 {
601 set { return; }
602 }
603
604 /// <summary>
605 /// Adds the force supplied to the Target Velocity
606 /// The PID controller takes this target velocity and tries to make it a reality
607 /// </summary>
608 /// <param name="force"></param>
609 /// <param name="pushforce">Is this a push by a script?</param>
610 public override void AddForce(PhysicsVector force, bool pushforce)
611 {
612 if (pushforce)
613 {
614 m_pidControllerActive = false;
615 force *= 100f;
616 doForce(force, false);
617 //System.Console.WriteLine("Push!");
618 //_target_velocity.X += force.X;
619 // _target_velocity.Y += force.Y;
620 //_target_velocity.Z += force.Z;
621 }
622 else
623 {
624 m_pidControllerActive = true;
625 m_target_velocity.X += force.X;
626 m_target_velocity.Y += force.Y;
627 m_target_velocity.Z += force.Z;
628 }
629 //m_lastUpdateSent = false;
630 }
631
632 public void doForce(PhysicsVector force, bool now)
633 {
634
635 tempVector3.setValue(force.X, force.Y, force.Z);
636 if (now)
637 {
638 Body.applyCentralForce(tempVector3);
639 }
640 else
641 {
642 m_taintedForce += force;
643 m_parent_scene.AddPhysicsActorTaint(this);
644 }
645 }
646
647 public void doImpulse(PhysicsVector force, bool now)
648 {
649
650 tempVector3.setValue(force.X, force.Y, force.Z);
651 if (now)
652 {
653 Body.applyCentralImpulse(tempVector3);
654 }
655 else
656 {
657 m_taintedForce += force;
658 m_parent_scene.AddPhysicsActorTaint(this);
659 }
660 }
661
662 public override void AddAngularForce(PhysicsVector force, bool pushforce)
663 {
664
665 }
666
667 public override void SetMomentum(PhysicsVector momentum)
668 {
669
670 }
671
672 public override void SubscribeEvents(int ms)
673 {
674 m_eventsubscription = ms;
675 m_parent_scene.addCollisionEventReporting(this);
676 }
677
678 public override void UnSubscribeEvents()
679 {
680 m_parent_scene.remCollisionEventReporting(this);
681 m_eventsubscription = 0;
682 }
683
684 public override bool SubscribedEvents()
685 {
686 if (m_eventsubscription > 0)
687 return true;
688 return false;
689 }
690
691 internal void Dispose()
692 {
693 if (Body.isInWorld())
694 m_parent_scene.removeFromWorld(Body);
695
696 if (m_aMotor.Handle != IntPtr.Zero)
697 m_parent_scene.getBulletWorld().removeConstraint(m_aMotor);
698
699 m_aMotor.Dispose(); m_aMotor = null;
700 ClosestCastResult.Dispose(); ClosestCastResult = null;
701 Body.Dispose(); Body = null;
702 Shell.Dispose(); Shell = null;
703 tempQuat1.Dispose();
704 tempTrans1.Dispose();
705 tempVector1.Dispose();
706 tempVector2.Dispose();
707 tempVector3.Dispose();
708 tempVector4.Dispose();
709 tempVector5RayCast.Dispose();
710 tempVector6RayCast.Dispose();
711
712 }
713
714 public void ProcessTaints(float timestep)
715 {
716
717 if (m_tainted_isPhysical != m_isPhysical)
718 {
719 if (m_tainted_isPhysical)
720 {
721 // Create avatar capsule and related ODE data
722 if (!(Shell == null && Body == null))
723 {
724 m_log.Warn("[PHYSICS]: re-creating the following avatar ODE data, even though it already exists - "
725 + (Shell != null ? "Shell " : "")
726 + (Body != null ? "Body " : ""));
727 }
728 AvatarGeomAndBodyCreation(m_position.X, m_position.Y, m_position.Z);
729
730
731 }
732 else
733 {
734 // destroy avatar capsule and related ODE data
735
736 Dispose();
737 tempVector1 = new btVector3(0, 0, 0);
738 tempVector2 = new btVector3(0, 0, 0);
739 tempVector3 = new btVector3(0, 0, 0);
740 tempVector4 = new btVector3(0, 0, 0);
741
742 tempVector5RayCast = new btVector3(0, 0, 0);
743 tempVector6RayCast = new btVector3(0, 0, 0);
744 tempVector7RayCast = new btVector3(0, 0, 0);
745
746 tempQuat1 = new btQuaternion(0, 0, 0, 1);
747 tempTrans1 = new btTransform(tempQuat1, tempVector1);
748 m_movementComparision = new PhysicsVector(0, 0, 0);
749 m_CapsuleOrientationAxis = new btVector3(1, 0, 1);
750 }
751
752 m_isPhysical = m_tainted_isPhysical;
753 }
754
755 if (m_tainted_CAPSULE_LENGTH != CAPSULE_LENGTH)
756 {
757 if (Body != null)
758 {
759
760 m_pidControllerActive = true;
761 // no lock needed on _parent_scene.OdeLock because we are called from within the thread lock in OdePlugin's simulate()
762 //d.JointDestroy(Amotor);
763 float prevCapsule = CAPSULE_LENGTH;
764 CAPSULE_LENGTH = m_tainted_CAPSULE_LENGTH;
765 //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString());
766 Dispose();
767
768 tempVector1 = new btVector3(0, 0, 0);
769 tempVector2 = new btVector3(0, 0, 0);
770 tempVector3 = new btVector3(0, 0, 0);
771 tempVector4 = new btVector3(0, 0, 0);
772
773 tempVector5RayCast = new btVector3(0, 0, 0);
774 tempVector6RayCast = new btVector3(0, 0, 0);
775 tempVector7RayCast = new btVector3(0, 0, 0);
776
777 tempQuat1 = new btQuaternion(0, 0, 0, 1);
778 tempTrans1 = new btTransform(tempQuat1, tempVector1);
779 m_movementComparision = new PhysicsVector(0, 0, 0);
780 m_CapsuleOrientationAxis = new btVector3(1, 0, 1);
781
782 AvatarGeomAndBodyCreation(m_position.X, m_position.Y,
783 m_position.Z + (Math.Abs(CAPSULE_LENGTH - prevCapsule) * 2));
784 Velocity = new PhysicsVector(0f, 0f, 0f);
785
786 }
787 else
788 {
789 m_log.Warn("[PHYSICS]: trying to change capsule size, but the following ODE data is missing - "
790 + (Shell == null ? "Shell " : "")
791 + (Body == null ? "Body " : ""));
792 }
793 }
794 if (m_taintRemove)
795 {
796 Dispose();
797 }
798 }
799
800 /// <summary>
801 /// Called from Simulate
802 /// This is the avatar's movement control + PID Controller
803 /// </summary>
804 /// <param name="timeStep"></param>
805 public void Move(float timeStep)
806 {
807 // no lock; for now it's only called from within Simulate()
808
809 // If the PID Controller isn't active then we set our force
810 // calculating base velocity to the current position
811 if (Body == null)
812 return;
813 tempTrans1.Dispose();
814 tempTrans1 = Body.getInterpolationWorldTransform();
815 tempVector1.Dispose();
816 tempVector1 = tempTrans1.getOrigin();
817 tempVector2.Dispose();
818 tempVector2 = Body.getInterpolationLinearVelocity();
819
820 if (m_pidControllerActive == false)
821 {
822 m_zeroPosition.X = tempVector1.getX();
823 m_zeroPosition.Y = tempVector1.getY();
824 m_zeroPosition.Z = tempVector1.getZ();
825 }
826 //PidStatus = true;
827
828 PhysicsVector vec = new PhysicsVector();
829
830 PhysicsVector vel = new PhysicsVector(tempVector2.getX(), tempVector2.getY(), tempVector2.getZ());
831
832 float movementdivisor = 1f;
833
834 if (!m_alwaysRun)
835 {
836 movementdivisor = walkDivisor;
837 }
838 else
839 {
840 movementdivisor = runDivisor;
841 }
842
843 // if velocity is zero, use position control; otherwise, velocity control
844 if (m_target_velocity.X == 0.0f && m_target_velocity.Y == 0.0f && m_target_velocity.Z == 0.0f && m_iscolliding)
845 {
846 // keep track of where we stopped. No more slippin' & slidin'
847 if (!m_zeroFlag)
848 {
849 m_zeroFlag = true;
850 m_zeroPosition.X = tempVector1.getX();
851 m_zeroPosition.Y = tempVector1.getY();
852 m_zeroPosition.Z = tempVector1.getZ();
853 }
854 if (m_pidControllerActive)
855 {
856 // We only want to deactivate the PID Controller if we think we want to have our surrogate
857 // react to the physics scene by moving it's position.
858 // Avatar to Avatar collisions
859 // Prim to avatar collisions
860
861 PhysicsVector pos = new PhysicsVector(tempVector1.getX(), tempVector1.getY(), tempVector1.getZ());
862 vec.X = (m_target_velocity.X - vel.X) * (PID_D) + (m_zeroPosition.X - pos.X) * (PID_P * 2);
863 vec.Y = (m_target_velocity.Y - vel.Y) * (PID_D) + (m_zeroPosition.Y - pos.Y) * (PID_P * 2);
864 if (m_flying)
865 {
866 vec.Z = (m_target_velocity.Z - vel.Z) * (PID_D) + (m_zeroPosition.Z - pos.Z) * PID_P;
867 }
868 }
869 //PidStatus = true;
870 }
871 else
872 {
873 m_pidControllerActive = true;
874 m_zeroFlag = false;
875 if (m_iscolliding && !m_flying)
876 {
877 // We're standing on something
878 vec.X = ((m_target_velocity.X / movementdivisor) - vel.X) * (PID_D);
879 vec.Y = ((m_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D);
880 }
881 else if (m_iscolliding && m_flying)
882 {
883 // We're flying and colliding with something
884 vec.X = ((m_target_velocity.X / movementdivisor) - vel.X) * (PID_D / 16);
885 vec.Y = ((m_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D / 16);
886 }
887 else if (!m_iscolliding && m_flying)
888 {
889 // we're in mid air suspended
890 vec.X = ((m_target_velocity.X / movementdivisor) - vel.X) * (PID_D / 6);
891 vec.Y = ((m_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D / 6);
892 }
893
894 if (m_iscolliding && !m_flying && m_target_velocity.Z > 0.0f)
895 {
896 // We're colliding with something and we're not flying but we're moving
897 // This means we're walking or running.
898 PhysicsVector pos = new PhysicsVector(tempVector1.getX(), tempVector1.getY(), tempVector1.getZ());
899 vec.Z = (m_target_velocity.Z - vel.Z) * PID_D + (m_zeroPosition.Z - pos.Z) * PID_P;
900 if (m_target_velocity.X > 0)
901 {
902 vec.X = ((m_target_velocity.X - vel.X) / 1.2f) * PID_D;
903 }
904 if (m_target_velocity.Y > 0)
905 {
906 vec.Y = ((m_target_velocity.Y - vel.Y) / 1.2f) * PID_D;
907 }
908 }
909 else if (!m_iscolliding && !m_flying)
910 {
911 // we're not colliding and we're not flying so that means we're falling!
912 // m_iscolliding includes collisions with the ground.
913
914 // d.Vector3 pos = d.BodyGetPosition(Body);
915 if (m_target_velocity.X > 0)
916 {
917 vec.X = ((m_target_velocity.X - vel.X) / 1.2f) * PID_D;
918 }
919 if (m_target_velocity.Y > 0)
920 {
921 vec.Y = ((m_target_velocity.Y - vel.Y) / 1.2f) * PID_D;
922 }
923 }
924
925
926 if (m_flying)
927 {
928 vec.Z = (m_target_velocity.Z - vel.Z) * (PID_D);
929 }
930 }
931 if (m_flying)
932 {
933 //vec.Z += ((-1 * m_parent_scene.gravityz) * m_mass);
934 }
935 if (Body != null && (((m_target_velocity.X > 0.2f || m_target_velocity.X < -0.2f) || (m_target_velocity.Y > 0.2f || m_target_velocity.Y < -0.2f))))
936 {
937 Body.setFriction(0.001f);
938 //m_log.DebugFormat("[PHYSICS]: Avatar force applied: {0}, Target:{1}", vec.ToString(), m_target_velocity.ToString());
939 }
940
941 if (Body != null)
942 {
943 int activationstate = Body.getActivationState();
944 if (activationstate == 0)
945 {
946 Body.forceActivationState(1);
947 }
948
949
950 }
951 doImpulse(vec, true);
952 }
953
954 /// <summary>
955 /// Updates the reported position and velocity. This essentially sends the data up to ScenePresence.
956 /// </summary>
957 public void UpdatePositionAndVelocity()
958 {
959 if (Body == null)
960 return;
961 //int val = Environment.TickCount;
962 CheckIfStandingOnObject();
963 //m_log.DebugFormat("time:{0}", Environment.TickCount - val);
964
965 //IsColliding = Body.checkCollideWith(m_parent_scene.TerrainBody);
966
967 tempTrans1.Dispose();
968 tempTrans1 = Body.getInterpolationWorldTransform();
969 tempVector1.Dispose();
970 tempVector1 = tempTrans1.getOrigin();
971 tempVector2.Dispose();
972 tempVector2 = Body.getInterpolationLinearVelocity();
973
974 // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
975 PhysicsVector vec = new PhysicsVector(tempVector1.getX(),tempVector1.getY(),tempVector1.getZ());
976
977 // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!)
978 if (vec.X < 0.0f) vec.X = 0.0f;
979 if (vec.Y < 0.0f) vec.Y = 0.0f;
980 if (vec.X > (int)Constants.RegionSize - 0.2f) vec.X = (int)Constants.RegionSize - 0.2f;
981 if (vec.Y > (int)Constants.RegionSize - 0.2f) vec.Y = (int)Constants.RegionSize - 0.2f;
982
983 m_position.X = vec.X;
984 m_position.Y = vec.Y;
985 m_position.Z = vec.Z;
986
987 // Did we move last? = zeroflag
988 // This helps keep us from sliding all over
989
990 if (m_zeroFlag)
991 {
992 m_velocity.X = 0.0f;
993 m_velocity.Y = 0.0f;
994 m_velocity.Z = 0.0f;
995
996 // Did we send out the 'stopped' message?
997 if (!m_lastUpdateSent)
998 {
999 m_lastUpdateSent = true;
1000 //base.RequestPhysicsterseUpdate();
1001
1002 }
1003 }
1004 else
1005 {
1006 m_lastUpdateSent = false;
1007 vec = new PhysicsVector(tempVector2.getX(), tempVector2.getY(), tempVector2.getZ());
1008 m_velocity.X = (vec.X);
1009 m_velocity.Y = (vec.Y);
1010
1011 m_velocity.Z = (vec.Z);
1012
1013 if (m_velocity.Z < -6 && !m_hackSentFall)
1014 {
1015 m_hackSentFall = true;
1016 m_pidControllerActive = false;
1017 }
1018 else if (m_flying && !m_hackSentFly)
1019 {
1020 //m_hackSentFly = true;
1021 //base.SendCollisionUpdate(new CollisionEventUpdate());
1022 }
1023 else
1024 {
1025 m_hackSentFly = false;
1026 m_hackSentFall = false;
1027 }
1028 }
1029 if (Body != null)
1030 {
1031 if (Body.getFriction() < 0.9f)
1032 Body.setFriction(0.9f);
1033 }
1034 //if (Body != null)
1035 // Body.clearForces();
1036 }
1037
1038 public void CheckIfStandingOnObject()
1039 {
1040
1041 float capsuleHalfHeight = ((CAPSULE_LENGTH + 2*CAPSULE_RADIUS)*0.5f);
1042
1043 tempVector5RayCast.setValue(m_position.X, m_position.Y, m_position.Z);
1044 tempVector6RayCast.setValue(m_position.X, m_position.Y, m_position.Z - 1 * capsuleHalfHeight * 1.1f);
1045
1046
1047 ClosestCastResult.Dispose();
1048 ClosestCastResult = new ClosestNotMeRayResultCallback(Body);
1049
1050 try
1051 {
1052 m_parent_scene.getBulletWorld().rayTest(tempVector5RayCast, tempVector6RayCast, ClosestCastResult);
1053 }
1054 catch (AccessViolationException)
1055 {
1056 m_log.Debug("BAD!");
1057 }
1058 if (ClosestCastResult.hasHit())
1059 {
1060
1061 if (tempVector7RayCast != null)
1062 tempVector7RayCast.Dispose();
1063
1064 //tempVector7RayCast = ClosestCastResult.getHitPointWorld();
1065
1066 /*if (tempVector7RayCast == null) // null == no result also
1067 {
1068 CollidingObj = false;
1069 IsColliding = false;
1070 CollidingGround = false;
1071
1072 return;
1073 }
1074 float zVal = tempVector7RayCast.getZ();
1075 if (zVal != 0)
1076 m_log.Debug("[PHYSICS]: HAAAA");
1077 if (zVal < m_position.Z && zVal > ((CAPSULE_LENGTH + 2 * CAPSULE_RADIUS) *0.5f))
1078 {
1079 CollidingObj = true;
1080 IsColliding = true;
1081 }
1082 else
1083 {
1084 CollidingObj = false;
1085 IsColliding = false;
1086 CollidingGround = false;
1087 }*/
1088
1089 //height+2*radius = capsule full length
1090 //CollidingObj = true;
1091 //IsColliding = true;
1092 m_iscolliding = true;
1093 }
1094 else
1095 {
1096 //CollidingObj = false;
1097 //IsColliding = false;
1098 //CollidingGround = false;
1099 m_iscolliding = false;
1100 }
1101 }
1102 }
1103
1104}