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