aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/OdePlugin
diff options
context:
space:
mode:
authorTeravus Ovares2008-01-13 07:14:54 +0000
committerTeravus Ovares2008-01-13 07:14:54 +0000
commitd9e45332022b18b50f00353588afd4bbe3392870 (patch)
treedcc39ec2e123052bc25f6b529dfd0821c47e4908 /OpenSim/Region/Physics/OdePlugin
parentThank you very much, Kinoc for implementing llGetSubString and llDeleteSubStr... (diff)
downloadopensim-SC_OLD-d9e45332022b18b50f00353588afd4bbe3392870.zip
opensim-SC_OLD-d9e45332022b18b50f00353588afd4bbe3392870.tar.gz
opensim-SC_OLD-d9e45332022b18b50f00353588afd4bbe3392870.tar.bz2
opensim-SC_OLD-d9e45332022b18b50f00353588afd4bbe3392870.tar.xz
* Fixed an overflow in the land manager
* Did some goofy math undoing in the Sim Stats Reporter * More reduction to the amount of calls per second to UnManaged ODE code * Added a significant amount of comments to ODE
Diffstat (limited to 'OpenSim/Region/Physics/OdePlugin')
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODECharacter.cs247
-rw-r--r--OpenSim/Region/Physics/OdePlugin/OdePlugin.cs220
2 files changed, 369 insertions, 98 deletions
diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
index 8e92171..b824cbe 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
@@ -34,6 +34,26 @@ using OpenSim.Region.Physics.Manager;
34 34
35namespace OpenSim.Region.Physics.OdePlugin 35namespace OpenSim.Region.Physics.OdePlugin
36{ 36{
37 /// <summary>
38 /// Various properties that ODE uses for AMotors but isn't exposed in ODE.NET so we must define them ourselves.
39 /// </summary>
40
41 public enum dParam : int
42 {
43 LowStop = 0,
44 HiStop = 1,
45 Vel = 2,
46 FMax = 3,
47 FudgeFactor = 4,
48 Bounce = 5,
49 CFM = 6,
50 ERP = 7,
51 StopCFM = 8,
52 LoStop2 = 256,
53 HiStop2 = 257,
54 LoStop3 = 512,
55 HiStop3 = 513
56 }
37 public class OdeCharacter : PhysicsActor 57 public class OdeCharacter : PhysicsActor
38 { 58 {
39 private PhysicsVector _position; 59 private PhysicsVector _position;
@@ -45,7 +65,8 @@ namespace OpenSim.Region.Physics.OdePlugin
45 private PhysicsVector _target_velocity; 65 private PhysicsVector _target_velocity;
46 private PhysicsVector _acceleration; 66 private PhysicsVector _acceleration;
47 private PhysicsVector m_rotationalVelocity; 67 private PhysicsVector m_rotationalVelocity;
48 private float m_density = 50f; 68 private float m_mass = 80f;
69 private float m_density = 60f;
49 private bool m_pidControllerActive = true; 70 private bool m_pidControllerActive = true;
50 private static float PID_D = 3020.0f; 71 private static float PID_D = 3020.0f;
51 private static float PID_P = 7000.0f; 72 private static float PID_P = 7000.0f;
@@ -96,34 +117,7 @@ namespace OpenSim.Region.Physics.OdePlugin
96 117
97 lock (OdeScene.OdeLock) 118 lock (OdeScene.OdeLock)
98 { 119 {
99 int dAMotorEuler = 1; 120 AvatarGeomAndBodyCreation(pos.X, pos.Y, pos.Z);
100 Shell = d.CreateCapsule(parent_scene.space, CAPSULE_RADIUS, CAPSULE_LENGTH);
101 d.MassSetCapsule(out ShellMass, m_density, 3, CAPSULE_RADIUS, CAPSULE_LENGTH);
102 Body = d.BodyCreate(parent_scene.world);
103 d.BodySetMass(Body, ref ShellMass);
104 d.BodySetPosition(Body, pos.X, pos.Y, pos.Z);
105 d.GeomSetBody(Shell, Body);
106
107
108 d.BodySetRotation(Body, ref m_StandUpRotation);
109
110
111 //Amotor = d.JointCreateAMotor(parent_scene.world, IntPtr.Zero);
112 //d.JointAttach(Amotor, Body, IntPtr.Zero);
113 //d.JointSetAMotorMode(Amotor, dAMotorEuler);
114 //d.JointSetAMotorNumAxes(Amotor, 3);
115 //d.JointSetAMotorAxis(Amotor, 0, 0, 1, 0, 0);
116 //d.JointSetAMotorAxis(Amotor, 1, 0, 0, 1, 0);
117 ///d.JointSetAMotorAxis(Amotor, 2, 0, 0, 0, 1);
118 //d.JointSetAMotorAngle(Amotor, 0, 0);
119 //d.JointSetAMotorAngle(Amotor, 1, 0);
120 //d.JointSetAMotorAngle(Amotor, 2, 0);
121 //d.JointSetAMotorParam(Amotor, 0, -0);
122 //d.JointSetAMotorParam(Amotor, 0x200, -0);
123 //d.JointSetAMotorParam(Amotor, 0x100, -0);
124 // d.JointSetAMotorParam(Amotor, 0, 0);
125 // d.JointSetAMotorParam(Amotor, 3, 0);
126 // d.JointSetAMotorParam(Amotor, 2, 0);
127 } 121 }
128 m_name = avName; 122 m_name = avName;
129 parent_scene.geom_name_map[Shell] = avName; 123 parent_scene.geom_name_map[Shell] = avName;
@@ -136,6 +130,9 @@ namespace OpenSim.Region.Physics.OdePlugin
136 set { return; } 130 set { return; }
137 } 131 }
138 132
133 /// <summary>
134 /// If this is set, the avatar will move faster
135 /// </summary>
139 public override bool SetAlwaysRun 136 public override bool SetAlwaysRun
140 { 137 {
141 get { return m_alwaysRun; } 138 get { return m_alwaysRun; }
@@ -160,6 +157,10 @@ namespace OpenSim.Region.Physics.OdePlugin
160 set { flying = value; } 157 set { flying = value; }
161 } 158 }
162 159
160 /// <summary>
161 /// Returns if the avatar is colliding in general.
162 /// This includes the ground and objects and avatar.
163 /// </summary>
163 public override bool IsColliding 164 public override bool IsColliding
164 { 165 {
165 get { return m_iscolliding; } 166 get { return m_iscolliding; }
@@ -208,11 +209,17 @@ namespace OpenSim.Region.Physics.OdePlugin
208 } 209 }
209 } 210 }
210 211
212 /// <summary>
213 /// Returns if an avatar is colliding with the ground
214 /// </summary>
211 public override bool CollidingGround 215 public override bool CollidingGround
212 { 216 {
213 get { return m_iscollidingGround; } 217 get { return m_iscollidingGround; }
214 set 218 set
215 { 219 {
220 // Collisions against the ground are not really reliable
221 // So, to get a consistant value we have to average the current result over time
222 // Currently we use 1 second = 10 calls to this.
216 int i; 223 int i;
217 int truecount = 0; 224 int truecount = 0;
218 int falsecount = 0; 225 int falsecount = 0;
@@ -256,6 +263,9 @@ namespace OpenSim.Region.Physics.OdePlugin
256 } 263 }
257 } 264 }
258 265
266 /// <summary>
267 /// Returns if the avatar is colliding with an object
268 /// </summary>
259 public override bool CollidingObj 269 public override bool CollidingObj
260 { 270 {
261 get { return m_iscollidingObj; } 271 get { return m_iscollidingObj; }
@@ -269,11 +279,21 @@ namespace OpenSim.Region.Physics.OdePlugin
269 } 279 }
270 } 280 }
271 281
282 /// <summary>
283 /// turn the PID controller on or off.
284 /// The PID Controller will turn on all by itself in many situations
285 /// </summary>
286 /// <param name="status"></param>
272 public void SetPidStatus(bool status) 287 public void SetPidStatus(bool status)
273 { 288 {
274 m_pidControllerActive = status; 289 m_pidControllerActive = status;
275 } 290 }
276 291
292 /// <summary>
293 /// This 'puts' an avatar somewhere in the physics space.
294 /// Not really a good choice unless you 'know' it's a good
295 /// spot otherwise you're likely to orbit the avatar.
296 /// </summary>
277 public override PhysicsVector Position 297 public override PhysicsVector Position
278 { 298 {
279 get { return _position; } 299 get { return _position; }
@@ -293,6 +313,10 @@ namespace OpenSim.Region.Physics.OdePlugin
293 set { m_rotationalVelocity = value; } 313 set { m_rotationalVelocity = value; }
294 } 314 }
295 315
316 /// <summary>
317 /// This property sets the height of the avatar only. We use the height to make sure the avatar stands up straight
318 /// and use it to offset landings properly
319 /// </summary>
296 public override PhysicsVector Size 320 public override PhysicsVector Size
297 { 321 {
298 get { return new PhysicsVector(CAPSULE_RADIUS*2, CAPSULE_RADIUS*2, CAPSULE_LENGTH); } 322 get { return new PhysicsVector(CAPSULE_RADIUS*2, CAPSULE_RADIUS*2, CAPSULE_LENGTH); }
@@ -301,6 +325,7 @@ namespace OpenSim.Region.Physics.OdePlugin
301 m_pidControllerActive = true; 325 m_pidControllerActive = true;
302 lock (OdeScene.OdeLock) 326 lock (OdeScene.OdeLock)
303 { 327 {
328 d.JointDestroy(Amotor);
304 PhysicsVector SetSize = value; 329 PhysicsVector SetSize = value;
305 float prevCapsule = CAPSULE_LENGTH; 330 float prevCapsule = CAPSULE_LENGTH;
306 float capsuleradius = CAPSULE_RADIUS; 331 float capsuleradius = CAPSULE_RADIUS;
@@ -309,20 +334,91 @@ namespace OpenSim.Region.Physics.OdePlugin
309 CAPSULE_LENGTH = (SetSize.Z - ((SetSize.Z*0.43f))); // subtract 43% of the size 334 CAPSULE_LENGTH = (SetSize.Z - ((SetSize.Z*0.43f))); // subtract 43% of the size
310 d.BodyDestroy(Body); 335 d.BodyDestroy(Body);
311 d.GeomDestroy(Shell); 336 d.GeomDestroy(Shell);
312 //MainLog.Instance.Verbose("PHYSICS", "Set Avatar Height To: " + (CAPSULE_RADIUS + CAPSULE_LENGTH)); 337 AvatarGeomAndBodyCreation(_position.X, _position.Y,
313 Shell = d.CreateCapsule(_parent_scene.space, capsuleradius, CAPSULE_LENGTH); 338 _position.Z + (Math.Abs(CAPSULE_LENGTH - prevCapsule)*2));
314 d.MassSetCapsule(out ShellMass, m_density, 3, CAPSULE_RADIUS, CAPSULE_LENGTH); 339 Velocity = new PhysicsVector(0f, 0f, 0f);
315 Body = d.BodyCreate(_parent_scene.world); 340
316 d.BodySetMass(Body, ref ShellMass);
317 d.BodySetPosition(Body, _position.X, _position.Y,
318 _position.Z + Math.Abs(CAPSULE_LENGTH - prevCapsule));
319 d.GeomSetBody(Shell, Body);
320 } 341 }
321 _parent_scene.geom_name_map[Shell] = m_name; 342 _parent_scene.geom_name_map[Shell] = m_name;
322 _parent_scene.actor_name_map[Shell] = (PhysicsActor) this; 343 _parent_scene.actor_name_map[Shell] = (PhysicsActor) this;
323 } 344 }
324 } 345 }
346 /// <summary>
347 /// This creates the Avatar's physical Surrogate at the position supplied
348 /// </summary>
349 /// <param name="npositionX"></param>
350 /// <param name="npositionY"></param>
351 /// <param name="npositionZ"></param>
352 private void AvatarGeomAndBodyCreation(float npositionX, float npositionY, float npositionZ)
353 {
354 int dAMotorEuler = 1;
355 Shell = d.CreateCapsule(_parent_scene.space, CAPSULE_RADIUS, CAPSULE_LENGTH);
356 d.MassSetCapsuleTotal(out ShellMass, m_mass, 2, CAPSULE_RADIUS, CAPSULE_LENGTH);
357 Body = d.BodyCreate(_parent_scene.world);
358 d.BodySetPosition(Body, npositionX, npositionY, npositionZ);
359
360 d.BodySetMass(Body, ref ShellMass);
361
362 // 90 Stand up on the cap of the capped cyllinder
363 d.RFromAxisAndAngle(out m_StandUpRotation, 1, 0, 0, (float)(Math.PI / 2));
364
365
366 d.GeomSetRotation(Shell, ref m_StandUpRotation);
367 d.BodySetRotation(Body, ref m_StandUpRotation);
368
369 d.GeomSetBody(Shell, Body);
370
371
372 // The purpose of the AMotor here is to keep the avatar's physical
373 // surrogate from rotating while moving
374 Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero);
375 d.JointAttach(Amotor, Body, IntPtr.Zero);
376 d.JointSetAMotorMode(Amotor, dAMotorEuler);
377 d.JointSetAMotorNumAxes(Amotor, 3);
378 d.JointSetAMotorAxis(Amotor, 0, 0, 1, 0, 0);
379 d.JointSetAMotorAxis(Amotor, 1, 0, 0, 1, 0);
380 d.JointSetAMotorAxis(Amotor, 2, 0, 0, 0, 1);
381 d.JointSetAMotorAngle(Amotor, 0, 0);
382 d.JointSetAMotorAngle(Amotor, 1, 0);
383 d.JointSetAMotorAngle(Amotor, 2, 0);
384
385 // These lowstops and high stops are effectively (no wiggle room)
386 d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, -0.000000000001f);
387 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -0.000000000001f);
388 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, -0.000000000001f);
389 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0.000000000001f);
390 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0.000000000001f);
391 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0.000000000001f);
392
393 // Fudge factor is 1f by default, we're setting it to 0. We don't want it to Fudge or the
394 // capped cyllinder will fall over
395 d.JointSetAMotorParam(Amotor, (int)dParam.FudgeFactor, 0f);
396 d.JointSetAMotorParam(Amotor, (int)dParam.FMax, 3800000f);
397
398
399 // The purpose of this routine here is to quickly stabilize the Body while it's popped up in the air.
400 // The amotor needs a few seconds to stabilize so without it, the avatar shoots up sky high when you
401 // change appearance and when you enter the simulator
402 // After this routine is done, the amotor stabilizes much quicker
403 d.Vector3 feet;
404 d.Vector3 head;
405 d.BodyGetRelPointPos(Body, 0.0f, 0.0f, -1.0f, out feet);
406 d.BodyGetRelPointPos(Body, 0.0f, 0.0f, 1.0f, out head);
407 float posture = head.Z - feet.Z;
408
409 // restoring force proportional to lack of posture:
410 float servo = (2.5f - posture) * POSTURE_SERVO;
411 d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, servo, 0.0f, 0.0f, 1.0f);
412 d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, -servo, 0.0f, 0.0f, -1.0f);
413
414
415 }
325 416
417 //
418 /// <summary>
419 /// Uses the capped cyllinder volume formula to calculate the avatar's mass.
420 /// This may be used in calculations in the scene/scenepresence
421 /// </summary>
326 public override float Mass 422 public override float Mass
327 { 423 {
328 get 424 get
@@ -385,6 +481,11 @@ namespace OpenSim.Region.Physics.OdePlugin
385 _acceleration = accel; 481 _acceleration = accel;
386 } 482 }
387 483
484 /// <summary>
485 /// Adds the force supplied to the Target Velocity
486 /// The PID controller takes this target velocity and tries to make it a reality
487 /// </summary>
488 /// <param name="force"></param>
388 public override void AddForce(PhysicsVector force) 489 public override void AddForce(PhysicsVector force)
389 { 490 {
390 m_pidControllerActive = true; 491 m_pidControllerActive = true;
@@ -395,29 +496,15 @@ namespace OpenSim.Region.Physics.OdePlugin
395 //m_lastUpdateSent = false; 496 //m_lastUpdateSent = false;
396 } 497 }
397 498
499 /// <summary>
500 /// After all of the forces add up with 'add force' we apply them with doForce
501 /// </summary>
502 /// <param name="force"></param>
398 public void doForce(PhysicsVector force) 503 public void doForce(PhysicsVector force)
399 { 504 {
400 if (!collidelock) 505 if (!collidelock)
401 { 506 {
402 d.BodyAddForce(Body, force.X, force.Y, force.Z); 507 d.BodyAddForce(Body, force.X, force.Y, force.Z);
403
404 // ok -- let's stand up straight!
405 //d.Matrix3 StandUpRotationalMatrix = new d.Matrix3(0.8184158f, -0.5744568f, -0.0139677f, 0.5744615f, 0.8185215f, -0.004074608f, 0.01377355f, -0.004689182f, 0.9998941f);
406 //d.BodySetRotation(Body, ref StandUpRotationalMatrix);
407 //d.BodySetRotation(Body, ref m_StandUpRotation);
408 // The above matrix was generated with the amazing standup routine below by danX0r *cheer*
409 d.Vector3 feet;
410 d.Vector3 head;
411 d.BodyGetRelPointPos(Body, 0.0f, 0.0f, -1.0f, out feet);
412 d.BodyGetRelPointPos(Body, 0.0f, 0.0f, 1.0f, out head);
413 float posture = head.Z - feet.Z;
414
415 // restoring force proportional to lack of posture:
416 float servo = (2.5f - posture) * POSTURE_SERVO;
417 d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, servo, 0.0f, 0.0f, 1.0f);
418 d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, -servo, 0.0f, 0.0f, -1.0f);
419
420 //m_lastUpdateSent = false;
421 } 508 }
422 } 509 }
423 510
@@ -425,9 +512,19 @@ namespace OpenSim.Region.Physics.OdePlugin
425 { 512 {
426 } 513 }
427 514
515
516 /// <summary>
517 /// Called from Simulate
518 /// This is the avatar's movement control + PID Controller
519 /// </summary>
520 /// <param name="timeStep"></param>
428 public void Move(float timeStep) 521 public void Move(float timeStep)
429 { 522 {
430 // no lock; for now it's only called from within Simulate() 523 // no lock; for now it's only called from within Simulate()
524
525 // If the PID Controller isn't active then we set our force
526 // calculating base velocity to the current position
527
431 if (m_pidControllerActive == false) 528 if (m_pidControllerActive == false)
432 { 529 {
433 _zeroPosition = d.BodyGetPosition(Body); 530 _zeroPosition = d.BodyGetPosition(Body);
@@ -458,6 +555,11 @@ namespace OpenSim.Region.Physics.OdePlugin
458 } 555 }
459 if (m_pidControllerActive) 556 if (m_pidControllerActive)
460 { 557 {
558 // We only want to deactivate the PID Controller if we think we want to have our surrogate
559 // react to the physics scene by moving it's position.
560 // Avatar to Avatar collisions
561 // Prim to avatar collisions
562
461 d.Vector3 pos = d.BodyGetPosition(Body); 563 d.Vector3 pos = d.BodyGetPosition(Body);
462 vec.X = (_target_velocity.X - vel.X)*PID_D + (_zeroPosition.X - pos.X)*PID_P; 564 vec.X = (_target_velocity.X - vel.X)*PID_D + (_zeroPosition.X - pos.X)*PID_P;
463 vec.Y = (_target_velocity.Y - vel.Y)*PID_D + (_zeroPosition.Y - pos.Y)*PID_P; 565 vec.Y = (_target_velocity.Y - vel.Y)*PID_D + (_zeroPosition.Y - pos.Y)*PID_P;
@@ -474,11 +576,14 @@ namespace OpenSim.Region.Physics.OdePlugin
474 _zeroFlag = false; 576 _zeroFlag = false;
475 if (m_iscolliding || flying) 577 if (m_iscolliding || flying)
476 { 578 {
579 // We're flying and colliding with something
477 vec.X = ((_target_velocity.X/movementdivisor) - vel.X)*PID_D; 580 vec.X = ((_target_velocity.X/movementdivisor) - vel.X)*PID_D;
478 vec.Y = ((_target_velocity.Y/movementdivisor) - vel.Y)*PID_D; 581 vec.Y = ((_target_velocity.Y/movementdivisor) - vel.Y)*PID_D;
479 } 582 }
480 if (m_iscolliding && !flying && _target_velocity.Z > 0.0f) 583 if (m_iscolliding && !flying && _target_velocity.Z > 0.0f)
481 { 584 {
585 // We're colliding with something and we're not flying but we're moving
586 // This means we're walking or running.
482 d.Vector3 pos = d.BodyGetPosition(Body); 587 d.Vector3 pos = d.BodyGetPosition(Body);
483 vec.Z = (_target_velocity.Z - vel.Z)*PID_D + (_zeroPosition.Z - pos.Z)*PID_P; 588 vec.Z = (_target_velocity.Z - vel.Z)*PID_D + (_zeroPosition.Z - pos.Z)*PID_P;
484 if (_target_velocity.X > 0) 589 if (_target_velocity.X > 0)
@@ -492,6 +597,8 @@ namespace OpenSim.Region.Physics.OdePlugin
492 } 597 }
493 else if (!m_iscolliding && !flying) 598 else if (!m_iscolliding && !flying)
494 { 599 {
600 // we're not colliding and we're not flying so that means we're falling!
601 // m_iscolliding includes collisions with the ground.
495 d.Vector3 pos = d.BodyGetPosition(Body); 602 d.Vector3 pos = d.BodyGetPosition(Body);
496 if (_target_velocity.X > 0) 603 if (_target_velocity.X > 0)
497 { 604 {
@@ -518,6 +625,9 @@ namespace OpenSim.Region.Physics.OdePlugin
518 doForce(vec); 625 doForce(vec);
519 } 626 }
520 627
628 /// <summary>
629 /// Updates the reported position and velocity. This essentially sends the data up to ScenePresence.
630 /// </summary>
521 public void UpdatePositionAndVelocity() 631 public void UpdatePositionAndVelocity()
522 { 632 {
523 // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit! 633 // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
@@ -533,25 +643,21 @@ namespace OpenSim.Region.Physics.OdePlugin
533 _position.Y = vec.Y; 643 _position.Y = vec.Y;
534 _position.Z = vec.Z; 644 _position.Z = vec.Z;
535 645
646 // Did we move last? = zeroflag
647 // This helps keep us from sliding all over
648
536 if (_zeroFlag) 649 if (_zeroFlag)
537 { 650 {
538 _velocity.X = 0.0f; 651 _velocity.X = 0.0f;
539 _velocity.Y = 0.0f; 652 _velocity.Y = 0.0f;
540 _velocity.Z = 0.0f; 653 _velocity.Z = 0.0f;
654
655 // Did we send out the 'stopped' message?
541 if (!m_lastUpdateSent) 656 if (!m_lastUpdateSent)
542 { 657 {
543 m_lastUpdateSent = true; 658 m_lastUpdateSent = true;
544 base.RequestPhysicsterseUpdate(); 659 base.RequestPhysicsterseUpdate();
545 //string primScenAvatarIn = _parent_scene.whichspaceamIin(_position); 660
546 //int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
547 //if (primScenAvatarIn == "0")
548 //{
549 //MainLog.Instance.Verbose("Physics", "Avatar " + m_name + " in space with no prim. Arr:':" + arrayitem[0].ToString() + "," + arrayitem[1].ToString());
550 //}
551 //else
552 //{
553 // MainLog.Instance.Verbose("Physics", "Avatar " + m_name + " in Prim space':" + primScenAvatarIn + ". Arr:" + arrayitem[0].ToString() + "," + arrayitem[1].ToString());
554 //}
555 } 661 }
556 } 662 }
557 else 663 else
@@ -564,6 +670,7 @@ namespace OpenSim.Region.Physics.OdePlugin
564 _velocity.Z = (vec.Z); 670 _velocity.Z = (vec.Z);
565 if (_velocity.Z < -6 && !m_hackSentFall) 671 if (_velocity.Z < -6 && !m_hackSentFall)
566 { 672 {
673 // Collisionupdates will be used in the future, right now the're not being used.
567 m_hackSentFall = true; 674 m_hackSentFall = true;
568 //base.SendCollisionUpdate(new CollisionEventUpdate()); 675 //base.SendCollisionUpdate(new CollisionEventUpdate());
569 m_pidControllerActive = false; 676 m_pidControllerActive = false;
@@ -581,13 +688,21 @@ namespace OpenSim.Region.Physics.OdePlugin
581 } 688 }
582 } 689 }
583 690
691 /// <summary>
692 /// Cleanup the things we use in the scene.
693 /// </summary>
584 public void Destroy() 694 public void Destroy()
585 { 695 {
586 lock (OdeScene.OdeLock) 696 lock (OdeScene.OdeLock)
587 { 697 {
588 // d.JointDestroy(Amotor); 698 // Kill the Amotor
699 d.JointDestroy(Amotor);
700
701 //kill the Geometry
589 d.GeomDestroy(Shell); 702 d.GeomDestroy(Shell);
590 _parent_scene.geom_name_map.Remove(Shell); 703 _parent_scene.geom_name_map.Remove(Shell);
704
705 //kill the body
591 d.BodyDestroy(Body); 706 d.BodyDestroy(Body);
592 } 707 }
593 } 708 }
diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
index 17dbd0a..366f30b 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
@@ -86,6 +86,7 @@ namespace OpenSim.Region.Physics.OdePlugin
86 private IntPtr contactgroup; 86 private IntPtr contactgroup;
87 private IntPtr LandGeom = (IntPtr) 0; 87 private IntPtr LandGeom = (IntPtr) 0;
88 private double[] _heightmap; 88 private double[] _heightmap;
89 private float[] _origheightmap;
89 private d.NearCallback nearCallback; 90 private d.NearCallback nearCallback;
90 public d.TriCallback triCallback; 91 public d.TriCallback triCallback;
91 public d.TriArrayCallback triArrayCallback; 92 public d.TriArrayCallback triArrayCallback;
@@ -115,6 +116,12 @@ namespace OpenSim.Region.Physics.OdePlugin
115 116
116 public IMesher mesher; 117 public IMesher mesher;
117 118
119
120 /// <summary>
121 /// Initiailizes the scene
122 /// Sets many properties that ODE requires to be stable
123 /// These settings need to be tweaked 'exactly' right or weird stuff happens.
124 /// </summary>
118 public OdeScene() 125 public OdeScene()
119 { 126 {
120 nearCallback = near; 127 nearCallback = near;
@@ -128,17 +135,27 @@ namespace OpenSim.Region.Physics.OdePlugin
128 contact.surface.soft_cfm = 0.00003f; 135 contact.surface.soft_cfm = 0.00003f;
129 */ 136 */
130 137
138 // Centeral contact friction and bounce
131 contact.surface.mu = 250.0f; 139 contact.surface.mu = 250.0f;
132 contact.surface.bounce = 0.2f; 140 contact.surface.bounce = 0.2f;
133 141
142 // Terrain contact friction and Bounce
143 // This is the *non* moving version. Use this when an avatar
144 // isn't moving to keep it in place better
134 TerrainContact.surface.mode |= d.ContactFlags.SoftERP; 145 TerrainContact.surface.mode |= d.ContactFlags.SoftERP;
135 TerrainContact.surface.mu = 550.0f; 146 TerrainContact.surface.mu = 550.0f;
136 TerrainContact.surface.bounce = 0.1f; 147 TerrainContact.surface.bounce = 0.1f;
137 TerrainContact.surface.soft_erp = 0.1025f; 148 TerrainContact.surface.soft_erp = 0.1025f;
138 149
150 // Prim contact friction and bounce
151 // THis is the *non* moving version of friction and bounce
152 // Use this when an avatar comes in contact with a prim
153 // and is moving
139 AvatarMovementprimContact.surface.mu = 150.0f; 154 AvatarMovementprimContact.surface.mu = 150.0f;
140 AvatarMovementprimContact.surface.bounce = 0.1f; 155 AvatarMovementprimContact.surface.bounce = 0.1f;
141 156
157 // Terrain contact friction bounce and various error correcting calculations
158 // Use this when an avatar is in contact with the terrain and moving.
142 AvatarMovementTerrainContact.surface.mode |= d.ContactFlags.SoftERP; 159 AvatarMovementTerrainContact.surface.mode |= d.ContactFlags.SoftERP;
143 AvatarMovementTerrainContact.surface.mu = 150.0f; 160 AvatarMovementTerrainContact.surface.mu = 150.0f;
144 AvatarMovementTerrainContact.surface.bounce = 0.1f; 161 AvatarMovementTerrainContact.surface.bounce = 0.1f;
@@ -146,6 +163,7 @@ namespace OpenSim.Region.Physics.OdePlugin
146 163
147 lock (OdeLock) 164 lock (OdeLock)
148 { 165 {
166 // Creat the world and the first space
149 world = d.WorldCreate(); 167 world = d.WorldCreate();
150 space = d.HashSpaceCreate(IntPtr.Zero); 168 space = d.HashSpaceCreate(IntPtr.Zero);
151 d.HashSpaceSetLevels(space, -4, 128); 169 d.HashSpaceSetLevels(space, -4, 128);
@@ -153,15 +171,25 @@ namespace OpenSim.Region.Physics.OdePlugin
153 //contactgroup 171 //contactgroup
154 172
155 173
174 // Set the gravity,, don't disable things automatically (we set it explicitly on some things)
175
156 d.WorldSetGravity(world, 0.0f, 0.0f, -10.0f); 176 d.WorldSetGravity(world, 0.0f, 0.0f, -10.0f);
157 d.WorldSetAutoDisableFlag(world, false); 177 d.WorldSetAutoDisableFlag(world, false);
158 d.WorldSetContactSurfaceLayer(world, 0.001f); 178 d.WorldSetContactSurfaceLayer(world, 0.001f);
179
180 // Set how many steps we go without running collision testing
181 // This is in addition to the step size.
182 // Essentially Steps * m_physicsiterations
159 d.WorldSetQuickStepNumIterations(world, m_physicsiterations); 183 d.WorldSetQuickStepNumIterations(world, m_physicsiterations);
160 d.WorldSetContactMaxCorrectingVel(world, 1000.0f); 184 ///d.WorldSetContactMaxCorrectingVel(world, 1000.0f);
161 } 185 }
162 186
187 // zero out a heightmap array float array (single dimention [flattened]))
163 _heightmap = new double[514*514]; 188 _heightmap = new double[514*514];
164 189
190
191 // Zero out the prim spaces array (we split our space into smaller spaces so
192 // we can hit test less.
165 for (int i = 0; i < staticPrimspace.GetLength(0); i++) 193 for (int i = 0; i < staticPrimspace.GetLength(0); i++)
166 { 194 {
167 for (int j = 0; j < staticPrimspace.GetLength(1); j++) 195 for (int j = 0; j < staticPrimspace.GetLength(1); j++)
@@ -171,19 +199,35 @@ namespace OpenSim.Region.Physics.OdePlugin
171 } 199 }
172 } 200 }
173 201
202 // Initialize the mesh plugin
174 public override void Initialise(IMesher meshmerizer) 203 public override void Initialise(IMesher meshmerizer)
175 { 204 {
176 mesher = meshmerizer; 205 mesher = meshmerizer;
177 } 206 }
178 207
208 /// <summary>
209 /// Debug space message for printing the space that a prim/avatar is in.
210 /// </summary>
211 /// <param name="pos"></param>
212 /// <returns>Returns which split up space the given position is in.</returns>
179 public string whichspaceamIin(PhysicsVector pos) 213 public string whichspaceamIin(PhysicsVector pos)
180 { 214 {
181 return calculateSpaceForGeom(pos).ToString(); 215 return calculateSpaceForGeom(pos).ToString();
182 } 216 }
183 217
218 /// <summary>
219 /// This is our near callback. A geometry is near a body
220 /// </summary>
221 /// <param name="space">The space that contains the geoms. Remember, spaces are also geoms</param>
222 /// <param name="g1">a geometry or space</param>
223 /// <param name="g2">another geometry or space</param>
184 private void near(IntPtr space, IntPtr g1, IntPtr g2) 224 private void near(IntPtr space, IntPtr g1, IntPtr g2)
185 { 225 {
186 // no lock here! It's invoked from within Simulate(), which is thread-locked 226 // no lock here! It's invoked from within Simulate(), which is thread-locked
227
228 // Test if we're collidng a geom with a space.
229 // If so we have to drill down into the space recursively
230
187 if (d.GeomIsSpace(g1) || d.GeomIsSpace(g2)) 231 if (d.GeomIsSpace(g1) || d.GeomIsSpace(g2))
188 { 232 {
189 // Separating static prim geometry spaces. 233 // Separating static prim geometry spaces.
@@ -192,7 +236,7 @@ namespace OpenSim.Region.Physics.OdePlugin
192 // contact points in the space 236 // contact points in the space
193 237
194 d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback); 238 d.SpaceCollide2(g1, g2, IntPtr.Zero, nearCallback);
195 //Colliding a space or a geom with a space or a geom. 239 //Colliding a space or a geom with a space or a geom. so drill down
196 240
197 //Collide all geoms in each space.. 241 //Collide all geoms in each space..
198 //if (d.GeomIsSpace(g1)) d.SpaceCollide(g1, IntPtr.Zero, nearCallback); 242 //if (d.GeomIsSpace(g1)) d.SpaceCollide(g1, IntPtr.Zero, nearCallback);
@@ -226,12 +270,13 @@ namespace OpenSim.Region.Physics.OdePlugin
226 name2 = "null"; 270 name2 = "null";
227 } 271 }
228 272
229 if (id == d.GeomClassID.TriMeshClass) 273 //if (id == d.GeomClassID.TriMeshClass)
230 { 274 //{
231 // MainLog.Instance.Verbose("near: A collision was detected between {1} and {2}", 0, name1, name2); 275 // MainLog.Instance.Verbose("near: A collision was detected between {1} and {2}", 0, name1, name2);
232 //System.Console.WriteLine("near: A collision was detected between {1} and {2}", 0, name1, name2); 276 //System.Console.WriteLine("near: A collision was detected between {1} and {2}", 0, name1, name2);
233 } 277 //}
234 278
279 // Figure out how many contact points we have
235 int count = 0; 280 int count = 0;
236 try 281 try
237 { 282 {
@@ -244,13 +289,15 @@ namespace OpenSim.Region.Physics.OdePlugin
244 base.TriggerPhysicsBasedRestart(); 289 base.TriggerPhysicsBasedRestart();
245 } 290 }
246 291
292 PhysicsActor p1;
293 PhysicsActor p2;
294
247 for (int i = 0; i < count; i++) 295 for (int i = 0; i < count; i++)
248 { 296 {
249 IntPtr joint; 297 IntPtr joint;
250 // If we're colliding with terrain, use 'TerrainContact' instead of contact. 298 // If we're colliding with terrain, use 'TerrainContact' instead of contact.
251 // allows us to have different settings 299 // allows us to have different settings
252 PhysicsActor p1; 300
253 PhysicsActor p2;
254 301
255 if (!actor_name_map.TryGetValue(g1, out p1)) 302 if (!actor_name_map.TryGetValue(g1, out p1))
256 { 303 {
@@ -267,14 +314,14 @@ namespace OpenSim.Region.Physics.OdePlugin
267 314
268 switch (p1.PhysicsActorType) 315 switch (p1.PhysicsActorType)
269 { 316 {
270 case (int) ActorTypes.Agent: 317 case (int)ActorTypes.Agent:
271 p2.CollidingObj = true; 318 p2.CollidingObj = true;
272 break; 319 break;
273 case (int) ActorTypes.Prim: 320 case (int)ActorTypes.Prim:
274 if (p2.Velocity.X > 0 || p2.Velocity.Y > 0 || p2.Velocity.Z > 0) 321 if (p2.Velocity.X > 0 || p2.Velocity.Y > 0 || p2.Velocity.Z > 0)
275 p2.CollidingObj = true; 322 p2.CollidingObj = true;
276 break; 323 break;
277 case (int) ActorTypes.Unknown: 324 case (int)ActorTypes.Unknown:
278 p2.CollidingGround = true; 325 p2.CollidingGround = true;
279 break; 326 break;
280 default: 327 default:
@@ -288,11 +335,15 @@ namespace OpenSim.Region.Physics.OdePlugin
288 335
289 if (contacts[i].depth >= 0.08f) 336 if (contacts[i].depth >= 0.08f)
290 { 337 {
338 /* This is disabled at the moment only because it needs more tweaking
339 It will eventually be uncommented
340
291 if (contacts[i].depth >= 1.00f) 341 if (contacts[i].depth >= 1.00f)
292 { 342 {
293 //MainLog.Instance.Debug("PHYSICS",contacts[i].depth.ToString()); 343 //MainLog.Instance.Debug("PHYSICS",contacts[i].depth.ToString());
294 } 344 }
295 // If you interpenetrate a prim with an agent 345
346 //If you interpenetrate a prim with an agent
296 if ((p2.PhysicsActorType == (int) ActorTypes.Agent && 347 if ((p2.PhysicsActorType == (int) ActorTypes.Agent &&
297 p1.PhysicsActorType == (int) ActorTypes.Prim) || 348 p1.PhysicsActorType == (int) ActorTypes.Prim) ||
298 (p1.PhysicsActorType == (int) ActorTypes.Agent && 349 (p1.PhysicsActorType == (int) ActorTypes.Agent &&
@@ -300,35 +351,37 @@ namespace OpenSim.Region.Physics.OdePlugin
300 { 351 {
301 if (p2.PhysicsActorType == (int) ActorTypes.Agent) 352 if (p2.PhysicsActorType == (int) ActorTypes.Agent)
302 { 353 {
303 //p2.CollidingObj = true; 354 p2.CollidingObj = true;
304 //contacts[i].depth = 0.003f; 355 contacts[i].depth = 0.003f;
305 //p2.Velocity = p2.Velocity + new PhysicsVector(0, 0, 2.5f); 356 p2.Velocity = p2.Velocity + new PhysicsVector(0, 0, 2.5f);
306 //OdeCharacter character = (OdeCharacter) p2; 357 OdeCharacter character = (OdeCharacter) p2;
307 //character.SetPidStatus(true); 358 character.SetPidStatus(true);
308 //contacts[i].pos = new d.Vector3(contacts[i].pos.X + (p1.Size.X / 2), contacts[i].pos.Y + (p1.Size.Y / 2), contacts[i].pos.Z + (p1.Size.Z / 2)); 359 contacts[i].pos = new d.Vector3(contacts[i].pos.X + (p1.Size.X / 2), contacts[i].pos.Y + (p1.Size.Y / 2), contacts[i].pos.Z + (p1.Size.Z / 2));
309 360
310 } 361 }
311 else 362 else
312 { 363 {
313 364
314 //contacts[i].depth = 0.0000000f; 365 contacts[i].depth = 0.0000000f;
315 } 366 }
316 if (p1.PhysicsActorType == (int) ActorTypes.Agent) 367 if (p1.PhysicsActorType == (int) ActorTypes.Agent)
317 { 368 {
318 369
319 //p1.CollidingObj = true; 370 p1.CollidingObj = true;
320 //contacts[i].depth = 0.003f; 371 contacts[i].depth = 0.003f;
321 //p1.Velocity = p1.Velocity + new PhysicsVector(0, 0, 2.5f); 372 p1.Velocity = p1.Velocity + new PhysicsVector(0, 0, 2.5f);
322 //contacts[i].pos = new d.Vector3(contacts[i].pos.X + (p2.Size.X / 2), contacts[i].pos.Y + (p2.Size.Y / 2), contacts[i].pos.Z + (p2.Size.Z / 2)); 373 contacts[i].pos = new d.Vector3(contacts[i].pos.X + (p2.Size.X / 2), contacts[i].pos.Y + (p2.Size.Y / 2), contacts[i].pos.Z + (p2.Size.Z / 2));
323 //OdeCharacter character = (OdeCharacter)p1; 374 OdeCharacter character = (OdeCharacter)p1;
324 //character.SetPidStatus(true); 375 character.SetPidStatus(true);
325 } 376 }
326 else 377 else
327 { 378 {
328 379
329 //contacts[i].depth = 0.0000000f; 380 contacts[i].depth = 0.0000000f;
330 } 381 }
331 } 382 }
383 */
384
332 // If you interpenetrate a prim with another prim 385 // If you interpenetrate a prim with another prim
333 if (p1.PhysicsActorType == (int) ActorTypes.Prim && p2.PhysicsActorType == (int) ActorTypes.Prim) 386 if (p1.PhysicsActorType == (int) ActorTypes.Prim && p2.PhysicsActorType == (int) ActorTypes.Prim)
334 { 387 {
@@ -337,6 +390,7 @@ namespace OpenSim.Region.Physics.OdePlugin
337 } 390 }
338 if (contacts[i].depth >= 1.00f) 391 if (contacts[i].depth >= 1.00f)
339 { 392 {
393 OpenSim.Framework.Console.MainLog.Instance.Verbose("P", contacts[i].depth.ToString());
340 if ((p2.PhysicsActorType == (int) ActorTypes.Agent && 394 if ((p2.PhysicsActorType == (int) ActorTypes.Agent &&
341 p1.PhysicsActorType == (int) ActorTypes.Unknown) || 395 p1.PhysicsActorType == (int) ActorTypes.Unknown) ||
342 (p1.PhysicsActorType == (int) ActorTypes.Agent && 396 (p1.PhysicsActorType == (int) ActorTypes.Agent &&
@@ -347,7 +401,7 @@ namespace OpenSim.Region.Physics.OdePlugin
347 OdeCharacter character = (OdeCharacter) p2; 401 OdeCharacter character = (OdeCharacter) p2;
348 402
349 //p2.CollidingObj = true; 403 //p2.CollidingObj = true;
350 contacts[i].depth = 0.003f; 404 contacts[i].depth = 0.00000003f;
351 p2.Velocity = p2.Velocity + new PhysicsVector(0, 0, 0.5f); 405 p2.Velocity = p2.Velocity + new PhysicsVector(0, 0, 0.5f);
352 contacts[i].pos = 406 contacts[i].pos =
353 new d.Vector3(contacts[i].pos.X + (p1.Size.X/2), 407 new d.Vector3(contacts[i].pos.X + (p1.Size.X/2),
@@ -363,7 +417,7 @@ namespace OpenSim.Region.Physics.OdePlugin
363 OdeCharacter character = (OdeCharacter)p1; 417 OdeCharacter character = (OdeCharacter)p1;
364 418
365 //p2.CollidingObj = true; 419 //p2.CollidingObj = true;
366 contacts[i].depth = 0.003f; 420 contacts[i].depth = 0.00000003f;
367 p1.Velocity = p1.Velocity + new PhysicsVector(0, 0, 0.5f); 421 p1.Velocity = p1.Velocity + new PhysicsVector(0, 0, 0.5f);
368 contacts[i].pos = 422 contacts[i].pos =
369 new d.Vector3(contacts[i].pos.X + (p1.Size.X/2), 423 new d.Vector3(contacts[i].pos.X + (p1.Size.X/2),
@@ -383,30 +437,39 @@ namespace OpenSim.Region.Physics.OdePlugin
383 437
384 if (contacts[i].depth >= 0f) 438 if (contacts[i].depth >= 0f)
385 { 439 {
440 // If we're collidng against terrain
386 if (name1 == "Terrain" || name2 == "Terrain") 441 if (name1 == "Terrain" || name2 == "Terrain")
387 { 442 {
443 // If we're moving
388 if ((p2.PhysicsActorType == (int) ActorTypes.Agent) && 444 if ((p2.PhysicsActorType == (int) ActorTypes.Agent) &&
389 (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) 445 (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f))
390 { 446 {
447 // Use the movement terrain contact
391 AvatarMovementTerrainContact.geom = contacts[i]; 448 AvatarMovementTerrainContact.geom = contacts[i];
392 joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementTerrainContact); 449 joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementTerrainContact);
393 } 450 }
394 else 451 else
395 { 452 {
453 // Use the non moving terrain contact
396 TerrainContact.geom = contacts[i]; 454 TerrainContact.geom = contacts[i];
397 joint = d.JointCreateContact(world, contactgroup, ref TerrainContact); 455 joint = d.JointCreateContact(world, contactgroup, ref TerrainContact);
398 } 456 }
399 } 457 }
400 else 458 else
401 { 459 {
460 // we're colliding with prim or avatar
461
462 // check if we're moving
402 if ((p2.PhysicsActorType == (int) ActorTypes.Agent) && 463 if ((p2.PhysicsActorType == (int) ActorTypes.Agent) &&
403 (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) 464 (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f))
404 { 465 {
466 // Use the Movement prim contact
405 AvatarMovementprimContact.geom = contacts[i]; 467 AvatarMovementprimContact.geom = contacts[i];
406 joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementprimContact); 468 joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementprimContact);
407 } 469 }
408 else 470 else
409 { 471 {
472 // Use the non movement contact
410 contact.geom = contacts[i]; 473 contact.geom = contacts[i];
411 joint = d.JointCreateContact(world, contactgroup, ref contact); 474 joint = d.JointCreateContact(world, contactgroup, ref contact);
412 } 475 }
@@ -416,6 +479,11 @@ namespace OpenSim.Region.Physics.OdePlugin
416 479
417 if (count > 3) 480 if (count > 3)
418 { 481 {
482 // If there are more then 3 contact points, it's likely
483 // that we've got a pile of objects
484 //
485 // We don't want to send out hundreds of terse updates over and over again
486 // so lets throttle them and send them again after it's somewhat sorted out.
419 p2.ThrottleUpdates = true; 487 p2.ThrottleUpdates = true;
420 } 488 }
421 //System.Console.WriteLine(count.ToString()); 489 //System.Console.WriteLine(count.ToString());
@@ -423,16 +491,43 @@ namespace OpenSim.Region.Physics.OdePlugin
423 } 491 }
424 } 492 }
425 } 493 }
494 private float GetTerrainHeightAtXY(float x, float y)
495 {
496 return (float)_origheightmap[(int) y*256 + (int) x];
497
426 498
499 }
500
501 /// <summary>
502 /// This is our collision testing routine in ODE
503 /// </summary>
504 /// <param name="timeStep"></param>
427 private void collision_optimized(float timeStep) 505 private void collision_optimized(float timeStep)
428 { 506 {
429 foreach (OdeCharacter chr in _characters) 507 foreach (OdeCharacter chr in _characters)
430 { 508 {
509 // Reset the collision values to false
510 // since we don't know if we're colliding yet
511
431 chr.IsColliding = false; 512 chr.IsColliding = false;
432 chr.CollidingGround = false; 513 chr.CollidingGround = false;
433 chr.CollidingObj = false; 514 chr.CollidingObj = false;
515
516 // test the avatar's geometry for collision with the space
517 // This will return near and the space that they are the closest to
518 // And we'll run this again against the avatar and the space segment
519 // This will return with a bunch of possible objects in the space segment
520 // and we'll run it again on all of them.
521
434 d.SpaceCollide2(space, chr.Shell, IntPtr.Zero, nearCallback); 522 d.SpaceCollide2(space, chr.Shell, IntPtr.Zero, nearCallback);
523 //float terrainheight = GetTerrainHeightAtXY(chr.Position.X, chr.Position.Y);
524 //if (chr.Position.Z + (chr.Velocity.Z * timeStep) < terrainheight + 10)
525 //{
526 //chr.Position.Z = terrainheight + 10.0f;
527 //forcedZ = true;
528 //}
435 } 529 }
530
436 // If the sim is running slow this frame, 531 // If the sim is running slow this frame,
437 // don't process collision for prim! 532 // don't process collision for prim!
438 if (timeStep < (m_SkipFramesAtms/3)) 533 if (timeStep < (m_SkipFramesAtms/3))
@@ -469,6 +564,8 @@ namespace OpenSim.Region.Physics.OdePlugin
469 // This if may not need to be there.. it might be skipped anyway. 564 // This if may not need to be there.. it might be skipped anyway.
470 if (d.BodyIsEnabled(chr.Body)) 565 if (d.BodyIsEnabled(chr.Body))
471 { 566 {
567 // Collide test the prims with the terrain.. since if you don't do this,
568 // next frame, all of the physical prim in the scene will awaken and explode upwards
472 d.SpaceCollide2(LandGeom, chr.prim_geom, IntPtr.Zero, nearCallback); 569 d.SpaceCollide2(LandGeom, chr.prim_geom, IntPtr.Zero, nearCallback);
473 } 570 }
474 } 571 }
@@ -509,6 +606,15 @@ namespace OpenSim.Region.Physics.OdePlugin
509 } 606 }
510 } 607 }
511 608
609 /// <summary>
610 /// This is called from within simulate but outside the locked portion
611 /// We need to do our own locking here
612 /// Essentially, we need to remove the prim from our space segment, whatever segment it's in.
613 ///
614 /// If there are no more prim in the segment, we need to empty (spacedestroy)the segment and reclaim memory
615 /// that the space was using.
616 /// </summary>
617 /// <param name="prim"></param>
512 public void RemovePrimThreadLocked(OdePrim prim) 618 public void RemovePrimThreadLocked(OdePrim prim)
513 { 619 {
514 lock (OdeLock) 620 lock (OdeLock)
@@ -567,7 +673,10 @@ namespace OpenSim.Region.Physics.OdePlugin
567 _prims.Remove(prim); 673 _prims.Remove(prim);
568 } 674 }
569 } 675 }
570 676 /// <summary>
677 /// Takes a space pointer and zeros out the array we're using to hold the spaces
678 /// </summary>
679 /// <param name="space"></param>
571 public void resetSpaceArrayItemToZero(IntPtr space) 680 public void resetSpaceArrayItemToZero(IntPtr space)
572 { 681 {
573 for (int x = 0; x < staticPrimspace.GetLength(0); x++) 682 for (int x = 0; x < staticPrimspace.GetLength(0); x++)
@@ -585,15 +694,25 @@ namespace OpenSim.Region.Physics.OdePlugin
585 staticPrimspace[arrayitemX, arrayitemY] = IntPtr.Zero; 694 staticPrimspace[arrayitemX, arrayitemY] = IntPtr.Zero;
586 } 695 }
587 696
697 /// <summary>
698 /// Called when a static prim moves. Allocates a space for the prim based on it's position
699 /// </summary>
700 /// <param name="geom">the pointer to the geom that moved</param>
701 /// <param name="pos">the position that the geom moved to</param>
702 /// <param name="currentspace">a pointer to the space it was in before it was moved.</param>
703 /// <returns>a pointer to the new space it's in</returns>
588 public IntPtr recalculateSpaceForGeom(IntPtr geom, PhysicsVector pos, IntPtr currentspace) 704 public IntPtr recalculateSpaceForGeom(IntPtr geom, PhysicsVector pos, IntPtr currentspace)
589 { 705 {
590 //Todo recalculate space the prim is in. 706
591 // Called from setting the Position and Size of an ODEPrim so 707 // Called from setting the Position and Size of an ODEPrim so
592 // it's already in locked space. 708 // it's already in locked space.
593 709
594 // we don't want to remove the main space 710 // we don't want to remove the main space
595 // we don't need to test physical here because this function should 711 // we don't need to test physical here because this function should
596 // never be called if the prim is physical(active) 712 // never be called if the prim is physical(active)
713
714 // All physical prim end up in the root space
715
597 if (currentspace != space) 716 if (currentspace != space)
598 { 717 {
599 if (d.SpaceQuery(currentspace, geom) && currentspace != (IntPtr) 0) 718 if (d.SpaceQuery(currentspace, geom) && currentspace != (IntPtr) 0)
@@ -707,6 +826,12 @@ namespace OpenSim.Region.Physics.OdePlugin
707 return newspace; 826 return newspace;
708 } 827 }
709 828
829 /// <summary>
830 /// Creates a new space at X Y
831 /// </summary>
832 /// <param name="iprimspaceArrItemX"></param>
833 /// <param name="iprimspaceArrItemY"></param>
834 /// <returns>A pointer to the created space</returns>
710 public IntPtr createprimspace(int iprimspaceArrItemX, int iprimspaceArrItemY) 835 public IntPtr createprimspace(int iprimspaceArrItemX, int iprimspaceArrItemY)
711 { 836 {
712 // creating a new space for prim and inserting it into main space. 837 // creating a new space for prim and inserting it into main space.
@@ -715,6 +840,11 @@ namespace OpenSim.Region.Physics.OdePlugin
715 return staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY]; 840 return staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY];
716 } 841 }
717 842
843 /// <summary>
844 /// Calculates the space the prim should be in by it's position
845 /// </summary>
846 /// <param name="pos"></param>
847 /// <returns>a pointer to the space. This could be a new space or reused space.</returns>
718 public IntPtr calculateSpaceForGeom(PhysicsVector pos) 848 public IntPtr calculateSpaceForGeom(PhysicsVector pos)
719 { 849 {
720 int[] xyspace = calculateSpaceArrayItemFromPos(pos); 850 int[] xyspace = calculateSpaceArrayItemFromPos(pos);
@@ -725,6 +855,11 @@ namespace OpenSim.Region.Physics.OdePlugin
725 return locationbasedspace; 855 return locationbasedspace;
726 } 856 }
727 857
858 /// <summary>
859 /// Holds the space allocation logic
860 /// </summary>
861 /// <param name="pos"></param>
862 /// <returns>an array item based on the position</returns>
728 public int[] calculateSpaceArrayItemFromPos(PhysicsVector pos) 863 public int[] calculateSpaceArrayItemFromPos(PhysicsVector pos)
729 { 864 {
730 int[] returnint = new int[2]; 865 int[] returnint = new int[2];
@@ -837,7 +972,11 @@ namespace OpenSim.Region.Physics.OdePlugin
837 return 1; 972 return 1;
838 } 973 }
839 974
840 975 /// <summary>
976 /// Routine to figure out if we need to mesh this prim with our mesher
977 /// </summary>
978 /// <param name="pbs"></param>
979 /// <returns></returns>
841 public bool needsMeshing(PrimitiveBaseShape pbs) 980 public bool needsMeshing(PrimitiveBaseShape pbs)
842 { 981 {
843 if (pbs.ProfileHollow != 0) 982 if (pbs.ProfileHollow != 0)
@@ -879,6 +1018,12 @@ namespace OpenSim.Region.Physics.OdePlugin
879 return result; 1018 return result;
880 } 1019 }
881 1020
1021 /// <summary>
1022 /// Called after our prim properties are set Scale, position etc.
1023 /// We use this event queue like method to keep changes to the physical scene occuring in the threadlocked mutex
1024 /// This assures us that we have no race conditions
1025 /// </summary>
1026 /// <param name="prim"></param>
882 public override void AddPhysicsActorTaint(PhysicsActor prim) 1027 public override void AddPhysicsActorTaint(PhysicsActor prim)
883 { 1028 {
884 if (prim is OdePrim) 1029 if (prim is OdePrim)
@@ -889,6 +1034,15 @@ namespace OpenSim.Region.Physics.OdePlugin
889 } 1034 }
890 } 1035 }
891 1036
1037 /// <summary>
1038 /// This is our main simulate loop
1039 /// It's thread locked by a Mutex in the scene.
1040 /// It holds Collisions, it instructs ODE to step through the physical reactions
1041 /// It moves the objects around in memory
1042 /// It calls the methods that report back to the object owners.. (scenepresence, SceneObjectGroup)
1043 /// </summary>
1044 /// <param name="timeStep"></param>
1045 /// <returns></returns>
892 public override float Simulate(float timeStep) 1046 public override float Simulate(float timeStep)
893 { 1047 {
894 float fps = 0; 1048 float fps = 0;
@@ -904,7 +1058,7 @@ namespace OpenSim.Region.Physics.OdePlugin
904 1058
905 if (step_time >= m_SkipFramesAtms) 1059 if (step_time >= m_SkipFramesAtms)
906 { 1060 {
907 // Instead of trying to catch up, it'll do one physics frame only 1061 // Instead of trying to catch up, it'll do 5 physics frames only
908 step_time = ODE_STEPSIZE; 1062 step_time = ODE_STEPSIZE;
909 m_physicsiterations = 5; 1063 m_physicsiterations = 5;
910 } 1064 }
@@ -960,6 +1114,7 @@ namespace OpenSim.Region.Physics.OdePlugin
960 { 1114 {
961 actor.UpdatePositionAndVelocity(); 1115 actor.UpdatePositionAndVelocity();
962 } 1116 }
1117
963 bool processedtaints = false; 1118 bool processedtaints = false;
964 foreach (OdePrim prim in _taintedPrim) 1119 foreach (OdePrim prim in _taintedPrim)
965 { 1120 {
@@ -970,6 +1125,7 @@ namespace OpenSim.Region.Physics.OdePlugin
970 } 1125 }
971 processedtaints = true; 1126 processedtaints = true;
972 } 1127 }
1128
973 if (processedtaints) 1129 if (processedtaints)
974 _taintedPrim = new List<OdePrim>(); 1130 _taintedPrim = new List<OdePrim>();
975 1131
@@ -1152,7 +1308,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1152 // this._heightmap[i] = (double)heightMap[i]; 1308 // this._heightmap[i] = (double)heightMap[i];
1153 // dbm (danx0r) -- heightmap x,y must be swapped for Ode (should fix ODE, but for now...) 1309 // dbm (danx0r) -- heightmap x,y must be swapped for Ode (should fix ODE, but for now...)
1154 // also, creating a buffer zone of one extra sample all around 1310 // also, creating a buffer zone of one extra sample all around
1155 1311 _origheightmap = heightMap;
1156 const uint heightmapWidth = m_regionWidth + 2; 1312 const uint heightmapWidth = m_regionWidth + 2;
1157 const uint heightmapHeight = m_regionHeight + 2; 1313 const uint heightmapHeight = m_regionHeight + 2;
1158 const uint heightmapWidthSamples = 2*m_regionWidth + 2; 1314 const uint heightmapWidthSamples = 2*m_regionWidth + 2;