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.cs1165
1 files changed, 0 insertions, 1165 deletions
diff --git a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs b/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs
deleted file mode 100644
index 198962b..0000000
--- a/OpenSim/Region/Physics/BulletDotNETPlugin/BulletDotNETCharacter.cs
+++ /dev/null
@@ -1,1165 +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
112
113 private BulletDotNETScene m_parent_scene;
114
115 public int m_eventsubscription = 0;
116 // private CollisionEventUpdate CollisionEventsThisFrame = new CollisionEventUpdate();
117
118 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)
119 {
120 m_position = pos;
121 m_zeroPosition = pos;
122 m_parent_scene = parent_scene;
123 PID_D = pid_d;
124 PID_P = pid_p;
125 CAPSULE_RADIUS = capsule_radius;
126 m_density = density;
127 heightFudgeFactor = height_fudge_factor;
128 walkDivisor = walk_divisor;
129 runDivisor = rundivisor;
130
131 for (int i = 0; i < 11; i++)
132 {
133 m_colliderarr[i] = false;
134 }
135 for (int i = 0; i < 11; i++)
136 {
137 m_colliderGroundarr[i] = false;
138 }
139 CAPSULE_LENGTH = (size.Z * 1.15f) - CAPSULE_RADIUS * 2.0f;
140 m_tainted_CAPSULE_LENGTH = CAPSULE_LENGTH;
141 m_isPhysical = false; // current status: no ODE information exists
142 m_tainted_isPhysical = true; // new tainted status: need to create ODE information
143
144 m_parent_scene.AddPhysicsActorTaint(this);
145
146 // m_name = avName;
147 tempVector1 = new btVector3(0, 0, 0);
148 tempVector2 = new btVector3(0, 0, 0);
149 tempVector3 = new btVector3(0, 0, 0);
150 tempVector4 = new btVector3(0, 0, 0);
151
152 tempVector5RayCast = new btVector3(0, 0, 0);
153 tempVector6RayCast = new btVector3(0, 0, 0);
154 tempVector7RayCast = new btVector3(0, 0, 0);
155
156 tempQuat1 = new btQuaternion(0, 0, 0, 1);
157 tempTrans1 = new btTransform(tempQuat1, tempVector1);
158 // m_movementComparision = new PhysicsVector(0, 0, 0);
159 m_CapsuleOrientationAxis = new btVector3(1, 0, 1);
160 }
161
162 /// <summary>
163 /// This creates the Avatar's physical Surrogate at the position supplied
164 /// </summary>
165 /// <param name="npositionX"></param>
166 /// <param name="npositionY"></param>
167 /// <param name="npositionZ"></param>
168
169 // WARNING: This MUST NOT be called outside of ProcessTaints, else we can have unsynchronized access
170 // to ODE internals. ProcessTaints is called from within thread-locked Simulate(), so it is the only
171 // place that is safe to call this routine AvatarGeomAndBodyCreation.
172 private void AvatarGeomAndBodyCreation(float npositionX, float npositionY, float npositionZ)
173 {
174
175 if (CAPSULE_LENGTH <= 0)
176 {
177 m_log.Warn("[PHYSICS]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!");
178 CAPSULE_LENGTH = 0.01f;
179
180 }
181
182 if (CAPSULE_RADIUS <= 0)
183 {
184 m_log.Warn("[PHYSICS]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!");
185 CAPSULE_RADIUS = 0.01f;
186
187 }
188
189 Shell = new btCapsuleShape(CAPSULE_RADIUS, CAPSULE_LENGTH);
190
191 if (m_bodyPosition == null)
192 m_bodyPosition = new btVector3(npositionX, npositionY, npositionZ);
193
194 m_bodyPosition.setValue(npositionX, npositionY, npositionZ);
195
196 if (m_bodyOrientation == null)
197 m_bodyOrientation = new btQuaternion(m_CapsuleOrientationAxis, (Utils.DEG_TO_RAD * 90));
198
199 if (m_bodyTransform == null)
200 m_bodyTransform = new btTransform(m_bodyOrientation, m_bodyPosition);
201 else
202 {
203 m_bodyTransform.Dispose();
204 m_bodyTransform = new btTransform(m_bodyOrientation, m_bodyPosition);
205 }
206
207 if (m_bodyMotionState == null)
208 m_bodyMotionState = new btDefaultMotionState(m_bodyTransform);
209 else
210 m_bodyMotionState.setWorldTransform(m_bodyTransform);
211
212 m_mass = Mass;
213
214 Body = new btRigidBody(m_mass, m_bodyMotionState, Shell);
215 Body.setUserPointer(new IntPtr((int)Body.Handle));
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 public override Quaternion APIDTarget
629 {
630 set { return; }
631 }
632
633 public override bool APIDActive
634 {
635 set { return; }
636 }
637
638 public override float APIDStrength
639 {
640 set { return; }
641 }
642
643 public override float APIDDamping
644 {
645 set { return; }
646 }
647
648 /// <summary>
649 /// Adds the force supplied to the Target Velocity
650 /// The PID controller takes this target velocity and tries to make it a reality
651 /// </summary>
652 /// <param name="force"></param>
653 /// <param name="pushforce">Is this a push by a script?</param>
654 public override void AddForce(Vector3 force, bool pushforce)
655 {
656 if (pushforce)
657 {
658 m_pidControllerActive = false;
659 force *= 100f;
660 doForce(force, false);
661 //System.Console.WriteLine("Push!");
662 //_target_velocity.X += force.X;
663 // _target_velocity.Y += force.Y;
664 //_target_velocity.Z += force.Z;
665 }
666 else
667 {
668 m_pidControllerActive = true;
669 m_target_velocity.X += force.X;
670 m_target_velocity.Y += force.Y;
671 m_target_velocity.Z += force.Z;
672 }
673 //m_lastUpdateSent = false;
674 }
675
676 public void doForce(Vector3 force, bool now)
677 {
678
679 tempVector3.setValue(force.X, force.Y, force.Z);
680 if (now)
681 {
682 Body.applyCentralForce(tempVector3);
683 }
684 else
685 {
686 m_taintedForce += force;
687 m_parent_scene.AddPhysicsActorTaint(this);
688 }
689 }
690
691 public void doImpulse(Vector3 force, bool now)
692 {
693
694 tempVector3.setValue(force.X, force.Y, force.Z);
695 if (now)
696 {
697 Body.applyCentralImpulse(tempVector3);
698 }
699 else
700 {
701 m_taintedForce += force;
702 m_parent_scene.AddPhysicsActorTaint(this);
703 }
704 }
705
706 public override void AddAngularForce(Vector3 force, bool pushforce)
707 {
708
709 }
710
711 public override void SetMomentum(Vector3 momentum)
712 {
713
714 }
715
716 public override void SubscribeEvents(int ms)
717 {
718 m_eventsubscription = ms;
719 m_parent_scene.addCollisionEventReporting(this);
720 }
721
722 public override void UnSubscribeEvents()
723 {
724 m_parent_scene.remCollisionEventReporting(this);
725 m_eventsubscription = 0;
726 }
727
728 public override bool SubscribedEvents()
729 {
730 if (m_eventsubscription > 0)
731 return true;
732 return false;
733 }
734
735 internal void Dispose()
736 {
737 if (Body.isInWorld())
738 m_parent_scene.removeFromWorld(Body);
739
740 if (m_aMotor.Handle != IntPtr.Zero)
741 m_parent_scene.getBulletWorld().removeConstraint(m_aMotor);
742
743 m_aMotor.Dispose(); m_aMotor = null;
744 ClosestCastResult.Dispose(); ClosestCastResult = null;
745 Body.Dispose(); Body = null;
746 Shell.Dispose(); Shell = null;
747 tempQuat1.Dispose();
748 tempTrans1.Dispose();
749 tempVector1.Dispose();
750 tempVector2.Dispose();
751 tempVector3.Dispose();
752 tempVector4.Dispose();
753 tempVector5RayCast.Dispose();
754 tempVector6RayCast.Dispose();
755
756 }
757
758 public void ProcessTaints(float timestep)
759 {
760
761 if (m_tainted_isPhysical != m_isPhysical)
762 {
763 if (m_tainted_isPhysical)
764 {
765 // Create avatar capsule and related ODE data
766 if (!(Shell == null && Body == null))
767 {
768 m_log.Warn("[PHYSICS]: re-creating the following avatar ODE data, even though it already exists - "
769 + (Shell != null ? "Shell " : "")
770 + (Body != null ? "Body " : ""));
771 }
772 AvatarGeomAndBodyCreation(m_position.X, m_position.Y, m_position.Z);
773
774
775 }
776 else
777 {
778 // destroy avatar capsule and related ODE data
779
780 Dispose();
781 tempVector1 = new btVector3(0, 0, 0);
782 tempVector2 = new btVector3(0, 0, 0);
783 tempVector3 = new btVector3(0, 0, 0);
784 tempVector4 = new btVector3(0, 0, 0);
785
786 tempVector5RayCast = new btVector3(0, 0, 0);
787 tempVector6RayCast = new btVector3(0, 0, 0);
788 tempVector7RayCast = new btVector3(0, 0, 0);
789
790 tempQuat1 = new btQuaternion(0, 0, 0, 1);
791 tempTrans1 = new btTransform(tempQuat1, tempVector1);
792 // m_movementComparision = new PhysicsVector(0, 0, 0);
793 m_CapsuleOrientationAxis = new btVector3(1, 0, 1);
794 }
795
796 m_isPhysical = m_tainted_isPhysical;
797 }
798
799 if (m_tainted_CAPSULE_LENGTH != CAPSULE_LENGTH)
800 {
801 if (Body != null)
802 {
803
804 m_pidControllerActive = true;
805 // no lock needed on _parent_scene.OdeLock because we are called from within the thread lock in OdePlugin's simulate()
806 //d.JointDestroy(Amotor);
807 float prevCapsule = CAPSULE_LENGTH;
808 CAPSULE_LENGTH = m_tainted_CAPSULE_LENGTH;
809 //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString());
810 Dispose();
811
812 tempVector1 = new btVector3(0, 0, 0);
813 tempVector2 = new btVector3(0, 0, 0);
814 tempVector3 = new btVector3(0, 0, 0);
815 tempVector4 = new btVector3(0, 0, 0);
816
817 tempVector5RayCast = new btVector3(0, 0, 0);
818 tempVector6RayCast = new btVector3(0, 0, 0);
819 tempVector7RayCast = new btVector3(0, 0, 0);
820
821 tempQuat1 = new btQuaternion(0, 0, 0, 1);
822 tempTrans1 = new btTransform(tempQuat1, tempVector1);
823 // m_movementComparision = new PhysicsVector(0, 0, 0);
824 m_CapsuleOrientationAxis = new btVector3(1, 0, 1);
825
826 AvatarGeomAndBodyCreation(m_position.X, m_position.Y,
827 m_position.Z + (Math.Abs(CAPSULE_LENGTH - prevCapsule) * 2));
828 Velocity = Vector3.Zero;
829
830 }
831 else
832 {
833 m_log.Warn("[PHYSICS]: trying to change capsule size, but the following ODE data is missing - "
834 + (Shell == null ? "Shell " : "")
835 + (Body == null ? "Body " : ""));
836 }
837 }
838 if (m_taintRemove)
839 {
840 Dispose();
841 }
842 }
843
844 /// <summary>
845 /// Called from Simulate
846 /// This is the avatar's movement control + PID Controller
847 /// </summary>
848 /// <param name="timeStep"></param>
849 public void Move(float timeStep)
850 {
851 // no lock; for now it's only called from within Simulate()
852
853 // If the PID Controller isn't active then we set our force
854 // calculating base velocity to the current position
855 if (Body == null)
856 return;
857 tempTrans1.Dispose();
858 tempTrans1 = Body.getInterpolationWorldTransform();
859 tempVector1.Dispose();
860 tempVector1 = tempTrans1.getOrigin();
861 tempVector2.Dispose();
862 tempVector2 = Body.getInterpolationLinearVelocity();
863
864 if (m_pidControllerActive == false)
865 {
866 m_zeroPosition.X = tempVector1.getX();
867 m_zeroPosition.Y = tempVector1.getY();
868 m_zeroPosition.Z = tempVector1.getZ();
869 }
870 //PidStatus = true;
871
872 Vector3 vec = Vector3.Zero;
873
874 Vector3 vel = new Vector3(tempVector2.getX(), tempVector2.getY(), tempVector2.getZ());
875
876 float movementdivisor = 1f;
877
878 if (!m_alwaysRun)
879 {
880 movementdivisor = walkDivisor;
881 }
882 else
883 {
884 movementdivisor = runDivisor;
885 }
886
887 // if velocity is zero, use position control; otherwise, velocity control
888 if (m_target_velocity.X == 0.0f && m_target_velocity.Y == 0.0f && m_target_velocity.Z == 0.0f && m_iscolliding)
889 {
890 // keep track of where we stopped. No more slippin' & slidin'
891 if (!m_zeroFlag)
892 {
893 m_zeroFlag = true;
894 m_zeroPosition.X = tempVector1.getX();
895 m_zeroPosition.Y = tempVector1.getY();
896 m_zeroPosition.Z = tempVector1.getZ();
897 }
898 if (m_pidControllerActive)
899 {
900 // We only want to deactivate the PID Controller if we think we want to have our surrogate
901 // react to the physics scene by moving it's position.
902 // Avatar to Avatar collisions
903 // Prim to avatar collisions
904
905 Vector3 pos = new Vector3(tempVector1.getX(), tempVector1.getY(), tempVector1.getZ());
906 vec.X = (m_target_velocity.X - vel.X) * (PID_D) + (m_zeroPosition.X - pos.X) * (PID_P * 2);
907 vec.Y = (m_target_velocity.Y - vel.Y) * (PID_D) + (m_zeroPosition.Y - pos.Y) * (PID_P * 2);
908 if (m_flying)
909 {
910 vec.Z = (m_target_velocity.Z - vel.Z) * (PID_D) + (m_zeroPosition.Z - pos.Z) * PID_P;
911 }
912 }
913 //PidStatus = true;
914 }
915 else
916 {
917 m_pidControllerActive = true;
918 m_zeroFlag = false;
919 if (m_iscolliding && !m_flying)
920 {
921 // We're standing on something
922 vec.X = ((m_target_velocity.X / movementdivisor) - vel.X) * (PID_D);
923 vec.Y = ((m_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D);
924 }
925 else if (m_iscolliding && m_flying)
926 {
927 // We're flying and colliding with something
928 vec.X = ((m_target_velocity.X / movementdivisor) - vel.X) * (PID_D / 16);
929 vec.Y = ((m_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D / 16);
930 }
931 else if (!m_iscolliding && m_flying)
932 {
933 // we're in mid air suspended
934 vec.X = ((m_target_velocity.X / movementdivisor) - vel.X) * (PID_D / 6);
935 vec.Y = ((m_target_velocity.Y / movementdivisor) - vel.Y) * (PID_D / 6);
936
937 // We don't want linear velocity to cause our avatar to bounce, so we check target Z and actual velocity X, Y
938 // rebound preventing
939 if (m_target_velocity.Z < 0.025f && m_velocity.X < 0.25f && m_velocity.Y < 0.25f)
940 m_zeroFlag = true;
941 }
942
943 if (m_iscolliding && !m_flying && m_target_velocity.Z > 0.0f)
944 {
945 // We're colliding with something and we're not flying but we're moving
946 // This means we're walking or running.
947 Vector3 pos = new Vector3(tempVector1.getX(), tempVector1.getY(), tempVector1.getZ());
948 vec.Z = (m_target_velocity.Z - vel.Z) * PID_D + (m_zeroPosition.Z - pos.Z) * PID_P;
949 if (m_target_velocity.X > 0)
950 {
951 vec.X = ((m_target_velocity.X - vel.X) / 1.2f) * PID_D;
952 }
953 if (m_target_velocity.Y > 0)
954 {
955 vec.Y = ((m_target_velocity.Y - vel.Y) / 1.2f) * PID_D;
956 }
957 }
958 else if (!m_iscolliding && !m_flying)
959 {
960 // we're not colliding and we're not flying so that means we're falling!
961 // m_iscolliding includes collisions with the ground.
962
963 // d.Vector3 pos = d.BodyGetPosition(Body);
964 if (m_target_velocity.X > 0)
965 {
966 vec.X = ((m_target_velocity.X - vel.X) / 1.2f) * PID_D;
967 }
968 if (m_target_velocity.Y > 0)
969 {
970 vec.Y = ((m_target_velocity.Y - vel.Y) / 1.2f) * PID_D;
971 }
972 }
973
974
975 if (m_flying)
976 {
977 vec.Z = (m_target_velocity.Z - vel.Z) * (PID_D);
978 }
979 }
980 if (m_flying)
981 {
982 // Slight PID correction
983 vec.Z += (((-1 * m_parent_scene.gravityz) * m_mass) * 0.06f);
984
985
986 //auto fly height. Kitto Flora
987 //d.Vector3 pos = d.BodyGetPosition(Body);
988 float target_altitude = m_parent_scene.GetTerrainHeightAtXY(m_position.X, m_position.Y) + 5.0f;
989
990 if (m_position.Z < target_altitude)
991 {
992 vec.Z += (target_altitude - m_position.Z) * PID_P * 5.0f;
993 }
994
995 }
996 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))))
997 {
998 Body.setFriction(0.001f);
999 //m_log.DebugFormat("[PHYSICS]: Avatar force applied: {0}, Target:{1}", vec.ToString(), m_target_velocity.ToString());
1000 }
1001
1002 if (Body != null)
1003 {
1004 int activationstate = Body.getActivationState();
1005 if (activationstate == 0)
1006 {
1007 Body.forceActivationState(1);
1008 }
1009
1010
1011 }
1012 doImpulse(vec, true);
1013 }
1014
1015 /// <summary>
1016 /// Updates the reported position and velocity. This essentially sends the data up to ScenePresence.
1017 /// </summary>
1018 public void UpdatePositionAndVelocity()
1019 {
1020 if (Body == null)
1021 return;
1022 //int val = Environment.TickCount;
1023 CheckIfStandingOnObject();
1024 //m_log.DebugFormat("time:{0}", Environment.TickCount - val);
1025
1026 //IsColliding = Body.checkCollideWith(m_parent_scene.TerrainBody);
1027
1028 tempTrans1.Dispose();
1029 tempTrans1 = Body.getInterpolationWorldTransform();
1030 tempVector1.Dispose();
1031 tempVector1 = tempTrans1.getOrigin();
1032 tempVector2.Dispose();
1033 tempVector2 = Body.getInterpolationLinearVelocity();
1034
1035 // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
1036 Vector3 vec = new Vector3(tempVector1.getX(), tempVector1.getY(), tempVector1.getZ());
1037
1038 // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!)
1039 if (vec.X < -10.0f) vec.X = 0.0f;
1040 if (vec.Y < -10.0f) vec.Y = 0.0f;
1041 if (vec.X > (int)Constants.RegionSize + 10.2f) vec.X = (int)Constants.RegionSize + 10.2f;
1042 if (vec.Y > (int)Constants.RegionSize + 10.2f) vec.Y = (int)Constants.RegionSize + 10.2f;
1043
1044 m_position.X = vec.X;
1045 m_position.Y = vec.Y;
1046 m_position.Z = vec.Z;
1047
1048 // Did we move last? = zeroflag
1049 // This helps keep us from sliding all over
1050
1051 if (m_zeroFlag)
1052 {
1053 m_velocity.X = 0.0f;
1054 m_velocity.Y = 0.0f;
1055 m_velocity.Z = 0.0f;
1056
1057 // Did we send out the 'stopped' message?
1058 if (!m_lastUpdateSent)
1059 {
1060 m_lastUpdateSent = true;
1061 //base.RequestPhysicsterseUpdate();
1062
1063 }
1064 }
1065 else
1066 {
1067 m_lastUpdateSent = false;
1068 vec = new Vector3(tempVector2.getX(), tempVector2.getY(), tempVector2.getZ());
1069 m_velocity.X = (vec.X);
1070 m_velocity.Y = (vec.Y);
1071
1072 m_velocity.Z = (vec.Z);
1073 //m_log.Debug(m_target_velocity);
1074 if (m_velocity.Z < -6 && !m_hackSentFall)
1075 {
1076 m_hackSentFall = true;
1077 m_pidControllerActive = false;
1078 }
1079 else if (m_flying && !m_hackSentFly)
1080 {
1081 //m_hackSentFly = true;
1082 //base.SendCollisionUpdate(new CollisionEventUpdate());
1083 }
1084 else
1085 {
1086 m_hackSentFly = false;
1087 m_hackSentFall = false;
1088 }
1089 }
1090 if (Body != null)
1091 {
1092 if (Body.getFriction() < 0.9f)
1093 Body.setFriction(0.9f);
1094 }
1095 //if (Body != null)
1096 // Body.clearForces();
1097 }
1098
1099 public void CheckIfStandingOnObject()
1100 {
1101
1102 float capsuleHalfHeight = ((CAPSULE_LENGTH + 2*CAPSULE_RADIUS)*0.5f);
1103
1104 tempVector5RayCast.setValue(m_position.X, m_position.Y, m_position.Z);
1105 tempVector6RayCast.setValue(m_position.X, m_position.Y, m_position.Z - 1 * capsuleHalfHeight * 1.1f);
1106
1107
1108 ClosestCastResult.Dispose();
1109 ClosestCastResult = new ClosestNotMeRayResultCallback(Body);
1110
1111 try
1112 {
1113 m_parent_scene.getBulletWorld().rayTest(tempVector5RayCast, tempVector6RayCast, ClosestCastResult);
1114 }
1115 catch (AccessViolationException)
1116 {
1117 m_log.Debug("BAD!");
1118 }
1119 if (ClosestCastResult.hasHit())
1120 {
1121
1122 if (tempVector7RayCast != null)
1123 tempVector7RayCast.Dispose();
1124
1125 //tempVector7RayCast = ClosestCastResult.getHitPointWorld();
1126
1127 /*if (tempVector7RayCast == null) // null == no result also
1128 {
1129 CollidingObj = false;
1130 IsColliding = false;
1131 CollidingGround = false;
1132
1133 return;
1134 }
1135 float zVal = tempVector7RayCast.getZ();
1136 if (zVal != 0)
1137 m_log.Debug("[PHYSICS]: HAAAA");
1138 if (zVal < m_position.Z && zVal > ((CAPSULE_LENGTH + 2 * CAPSULE_RADIUS) *0.5f))
1139 {
1140 CollidingObj = true;
1141 IsColliding = true;
1142 }
1143 else
1144 {
1145 CollidingObj = false;
1146 IsColliding = false;
1147 CollidingGround = false;
1148 }*/
1149
1150 //height+2*radius = capsule full length
1151 //CollidingObj = true;
1152 //IsColliding = true;
1153 m_iscolliding = true;
1154 }
1155 else
1156 {
1157 //CollidingObj = false;
1158 //IsColliding = false;
1159 //CollidingGround = false;
1160 m_iscolliding = false;
1161 }
1162 }
1163 }
1164
1165}