aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Region/Physics/OdePlugin/OdePlugin.cs130
1 files changed, 89 insertions, 41 deletions
diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
index ddc6c4a..ac784cf 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
@@ -80,6 +80,7 @@ namespace OpenSim.Region.Physics.OdePlugin
80 80
81 public class OdeScene : PhysicsScene 81 public class OdeScene : PhysicsScene
82 { 82 {
83 private static float ODE_STEPSIZE = 0.004f;
83 private IntPtr contactgroup; 84 private IntPtr contactgroup;
84 private IntPtr LandGeom; 85 private IntPtr LandGeom;
85 private double[] _heightmap; 86 private double[] _heightmap;
@@ -91,7 +92,7 @@ namespace OpenSim.Region.Physics.OdePlugin
91 public Dictionary<IntPtr, String> geom_name_map=new Dictionary<IntPtr, String>(); 92 public Dictionary<IntPtr, String> geom_name_map=new Dictionary<IntPtr, String>();
92 private d.ContactGeom[] contacts = new d.ContactGeom[30]; 93 private d.ContactGeom[] contacts = new d.ContactGeom[30];
93 private d.Contact contact; 94 private d.Contact contact;
94 95 private float step_time=0.0f;
95 public IntPtr world; 96 public IntPtr world;
96 public IntPtr space; 97 public IntPtr space;
97 public static Object OdeLock = new Object(); 98 public static Object OdeLock = new Object();
@@ -101,12 +102,15 @@ namespace OpenSim.Region.Physics.OdePlugin
101 nearCallback = near; 102 nearCallback = near;
102 triCallback = TriCallback; 103 triCallback = TriCallback;
103 triArrayCallback = TriArrayCallback; 104 triArrayCallback = TriArrayCallback;
105 /*
104 contact.surface.mode |= d.ContactFlags.Approx1 | d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP; 106 contact.surface.mode |= d.ContactFlags.Approx1 | d.ContactFlags.SoftCFM | d.ContactFlags.SoftERP;
105 contact.surface.mu = 10.0f; 107 contact.surface.mu = 10.0f;
106 contact.surface.bounce = 0.9f; 108 contact.surface.bounce = 0.9f;
107 contact.surface.soft_erp = 0.005f; 109 contact.surface.soft_erp = 0.005f;
108 contact.surface.soft_cfm = 0.00003f; 110 contact.surface.soft_cfm = 0.00003f;
109 111 */
112 contact.surface.mu = 250.0f;
113 contact.surface.bounce = 0.2f;
110 lock (OdeLock) 114 lock (OdeLock)
111 { 115 {
112 world = d.WorldCreate(); 116 world = d.WorldCreate();
@@ -115,6 +119,8 @@ namespace OpenSim.Region.Physics.OdePlugin
115 d.WorldSetGravity(world, 0.0f, 0.0f, -10.0f); 119 d.WorldSetGravity(world, 0.0f, 0.0f, -10.0f);
116 d.WorldSetAutoDisableFlag(world, false); 120 d.WorldSetAutoDisableFlag(world, false);
117 d.WorldSetContactSurfaceLayer(world, 0.001f); 121 d.WorldSetContactSurfaceLayer(world, 0.001f);
122 d.WorldSetQuickStepNumIterations(world, 10);
123 d.WorldSetContactMaxCorrectingVel(world, 1000.0f);
118 } 124 }
119 125
120 _heightmap = new double[65536]; 126 _heightmap = new double[65536];
@@ -164,10 +170,10 @@ namespace OpenSim.Region.Physics.OdePlugin
164 { 170 {
165 foreach (OdeCharacter chr in _characters) 171 foreach (OdeCharacter chr in _characters)
166 { 172 {
167 d.SpaceCollide2(space, chr.capsule_geom, IntPtr.Zero, nearCallback); 173 d.SpaceCollide2(space, chr.Shell, IntPtr.Zero, nearCallback);
168 foreach (OdeCharacter ch2 in _characters) /// should be a separate space -- lots of avatars will be N**2 slow 174 foreach (OdeCharacter ch2 in _characters) /// should be a separate space -- lots of avatars will be N**2 slow
169 { 175 {
170 d.SpaceCollide2(chr.capsule_geom, ch2.capsule_geom, IntPtr.Zero, nearCallback); 176 d.SpaceCollide2(chr.Shell, ch2.Shell, IntPtr.Zero, nearCallback);
171 } 177 }
172 } 178 }
173 } 179 }
@@ -307,25 +313,29 @@ namespace OpenSim.Region.Physics.OdePlugin
307 313
308 public override void Simulate(float timeStep) 314 public override void Simulate(float timeStep)
309 { 315 {
316 step_time += timeStep;
310 lock (OdeLock) 317 lock (OdeLock)
311 { 318 {
312 foreach (OdePrim p in _prims) 319 foreach (OdePrim p in _prims)
313 { 320 {
314 } 321 }
315 foreach (OdeCharacter actor in _characters) 322 int i = 0;
316 { 323 while (step_time > 0.0f)
317 actor.Move(timeStep);
318 }
319 collision_optimized();
320 for (int i = 0; i < 50; i++)
321 { 324 {
322 d.WorldQuickStep(world, timeStep * 0.02f); 325 foreach (OdeCharacter actor in _characters)
326 {
327 actor.Move(timeStep);
328 }
329 collision_optimized();
330 d.WorldQuickStep(world, ODE_STEPSIZE);
331 d.JointGroupEmpty(contactgroup);
332 step_time -= ODE_STEPSIZE;
333 i++;
323 } 334 }
324 335
325 d.JointGroupEmpty(contactgroup);
326 foreach (OdeCharacter actor in _characters) 336 foreach (OdeCharacter actor in _characters)
327 { 337 {
328 actor.UpdatePosition(); 338 actor.UpdatePositionAndVelocity();
329 } 339 }
330 } 340 }
331 } 341 }
@@ -392,30 +402,35 @@ namespace OpenSim.Region.Physics.OdePlugin
392 private d.Vector3 _zeroPosition; 402 private d.Vector3 _zeroPosition;
393 private bool _zeroFlag=false; 403 private bool _zeroFlag=false;
394 private PhysicsVector _velocity; 404 private PhysicsVector _velocity;
405 private PhysicsVector _target_velocity;
395 private PhysicsVector _acceleration; 406 private PhysicsVector _acceleration;
407 private static float PID_D=4000.0f;
408 private static float PID_P=7000.0f;
409 private static float POSTURE_SERVO = 10000.0f;
396 private bool flying = false; 410 private bool flying = false;
397 //private float gravityAccel; 411 //private float gravityAccel;
398 public IntPtr BoundingCapsule; 412 public IntPtr Body;
399 private OdeScene _parent_scene; 413 private OdeScene _parent_scene;
400 public IntPtr capsule_geom; 414 public IntPtr Shell;
401 public d.Mass capsule_mass; 415 public d.Mass ShellMass;
402 416
403 public OdeCharacter(String avName, OdeScene parent_scene, PhysicsVector pos) 417 public OdeCharacter(String avName, OdeScene parent_scene, PhysicsVector pos)
404 { 418 {
405 _velocity = new PhysicsVector(); 419 _velocity = new PhysicsVector();
420 _target_velocity = new PhysicsVector();
406 _position = pos; 421 _position = pos;
407 _acceleration = new PhysicsVector(); 422 _acceleration = new PhysicsVector();
408 _parent_scene = parent_scene; 423 _parent_scene = parent_scene;
409 lock (OdeScene.OdeLock) 424 lock (OdeScene.OdeLock)
410 { 425 {
411 d.MassSetCapsule(out capsule_mass, 50.0f, 3, 0.5f, 2f); 426 Shell = d.CreateCapsule(parent_scene.space, 0.4f, 1.0f);
412 capsule_geom = d.CreateSphere(parent_scene.space, 1.0f); /// not a typo! Spheres roll, capsules tumble 427 d.MassSetCapsule(out ShellMass, 50.0f, 3, 0.4f, 1.0f);
413 BoundingCapsule = d.BodyCreate(parent_scene.world); 428 Body = d.BodyCreate(parent_scene.world);
414 d.BodySetMass(BoundingCapsule, ref capsule_mass); 429 d.BodySetMass(Body, ref ShellMass);
415 d.BodySetPosition(BoundingCapsule, pos.X, pos.Y, pos.Z); 430 d.BodySetPosition(Body, pos.X, pos.Y, pos.Z);
416 d.GeomSetBody(capsule_geom, BoundingCapsule); 431 d.GeomSetBody(Shell, Body);
417 } 432 }
418 parent_scene.geom_name_map[capsule_geom]=avName; 433 parent_scene.geom_name_map[Shell]=avName;
419 434
420 } 435 }
421 436
@@ -441,7 +456,7 @@ namespace OpenSim.Region.Physics.OdePlugin
441 { 456 {
442 lock (OdeScene.OdeLock) 457 lock (OdeScene.OdeLock)
443 { 458 {
444 d.BodySetPosition(BoundingCapsule, value.X, value.Y, value.Z); 459 d.BodySetPosition(Body, value.X, value.Y, value.Z);
445 _position = value; 460 _position = value;
446 } 461 }
447 } 462 }
@@ -467,7 +482,7 @@ namespace OpenSim.Region.Physics.OdePlugin
467 } 482 }
468 set 483 set
469 { 484 {
470 _velocity = value; 485 _target_velocity = value;
471 } 486 }
472 } 487 }
473 488
@@ -522,38 +537,58 @@ namespace OpenSim.Region.Physics.OdePlugin
522 { 537 {
523 // no lock; for now it's only called from within Simulate() 538 // no lock; for now it's only called from within Simulate()
524 PhysicsVector vec = new PhysicsVector(); 539 PhysicsVector vec = new PhysicsVector();
525 d.Vector3 vel = d.BodyGetLinearVel(BoundingCapsule); 540 d.Vector3 vel = d.BodyGetLinearVel(Body);
526 541
527 // if velocity is zero, use position control; otherwise, velocity control 542 // if velocity is zero, use position control; otherwise, velocity control
528 if (_velocity.X == 0.0f & _velocity.Y == 0.0f & _velocity.Z == 0.0f & !flying) 543 if (_target_velocity.X == 0.0f & _target_velocity.Y == 0.0f & _target_velocity.Z == 0.0f)
529 { 544 {
530 // keep track of where we stopped. No more slippin' & slidin' 545 // keep track of where we stopped. No more slippin' & slidin'
531 if (!_zeroFlag) 546 if (!_zeroFlag)
532 { 547 {
533 _zeroFlag = true; 548 _zeroFlag = true;
534 _zeroPosition = d.BodyGetPosition(BoundingCapsule); 549 _zeroPosition = d.BodyGetPosition(Body);
550 }
551 d.Vector3 pos = d.BodyGetPosition(Body);
552 vec.X = (_target_velocity.X - vel.X) * PID_D + (_zeroPosition.X - pos.X) * PID_P;
553 vec.Y = (_target_velocity.Y - vel.Y) * PID_D + (_zeroPosition.Y - pos.Y) * PID_P;
554 if (flying)
555 {
556 vec.Z = (_target_velocity.Z - vel.Z) * PID_D + (_zeroPosition.Z - pos.Z) * PID_P;
535 } 557 }
536 d.Vector3 pos = d.BodyGetPosition(BoundingCapsule);
537 vec.X = (_velocity.X - vel.X) * 75000.0f + (_zeroPosition.X - pos.X) * 120000.0f;
538 vec.Y = (_velocity.Y - vel.Y) * 75000.0f + (_zeroPosition.Y - pos.Y) * 120000.0f;
539 } 558 }
540 else 559 else
541 { 560 {
542 _zeroFlag = false; 561 _zeroFlag = false;
543 vec.X = (_velocity.X - vel.X) * 75000.0f; 562 vec.X = (_target_velocity.X - vel.X) * PID_D;
544 vec.Y = (_velocity.Y - vel.Y) * 75000.0f; 563 vec.Y = (_target_velocity.Y - vel.Y) * PID_D;
545 if (flying) 564 if (flying)
546 { 565 {
547 vec.Z = (_velocity.Z - vel.Z) * 75000.0f; 566 vec.Z = (_target_velocity.Z - vel.Z) * PID_D;
548 } 567 }
549 } 568 }
550 d.BodyAddForce(this.BoundingCapsule, vec.X, vec.Y, vec.Z); 569 if (flying)
570 {
571 vec.Z += 10.0f;
572 }
573 d.BodyAddForce(this.Body, vec.X, vec.Y, vec.Z);
574
575 // ok -- let's stand up straight!
576 d.Vector3 feet;
577 d.Vector3 head;
578 d.BodyGetRelPointPos(Body, 0.0f, 0.0f, -1.0f, out feet);
579 d.BodyGetRelPointPos(Body, 0.0f, 0.0f, 1.0f, out head);
580 float posture = head.Z - feet.Z;
581
582 // restoring force proportional to lack of posture:
583 float servo = (2.5f-posture) * POSTURE_SERVO;
584 d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, servo, 0.0f, 0.0f, 1.0f);
585 d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, -servo, 0.0f, 0.0f, -1.0f);
551 } 586 }
552 587
553 public void UpdatePosition() 588 public void UpdatePositionAndVelocity()
554 { 589 {
555 // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit! 590 // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
556 d.Vector3 vec = d.BodyGetPosition(BoundingCapsule); 591 d.Vector3 vec = d.BodyGetPosition(Body);
557 592
558 // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!) 593 // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!)
559 if (vec.X < 0.0f) vec.X = 0.0f; 594 if (vec.X < 0.0f) vec.X = 0.0f;
@@ -564,16 +599,29 @@ namespace OpenSim.Region.Physics.OdePlugin
564 this._position.X = vec.X; 599 this._position.X = vec.X;
565 this._position.Y = vec.Y; 600 this._position.Y = vec.Y;
566 this._position.Z = vec.Z; 601 this._position.Z = vec.Z;
602
603 if (_zeroFlag)
604 {
605 _velocity.X = 0.0f;
606 _velocity.Y = 0.0f;
607 _velocity.Z = 0.0f;
608 }
609 else
610 {
611 vec = d.BodyGetLinearVel(Body);
612 _velocity.X = vec.X;
613 _velocity.Y = vec.Y;
614 _velocity.Z = vec.Z;
615 }
567 } 616 }
568 617
569 public void Destroy() 618 public void Destroy()
570 { 619 {
571 lock (OdeScene.OdeLock) 620 lock (OdeScene.OdeLock)
572 { 621 {
573 d.GeomDestroy(this.capsule_geom); 622 d.GeomDestroy(this.Shell);
574 Console.WriteLine("+++ removing geom"); 623 this._parent_scene.geom_name_map.Remove(this.Shell);
575 this._parent_scene.geom_name_map.Remove(this.capsule_geom); 624 d.BodyDestroy(this.Body);
576 d.BodyDestroy(this.BoundingCapsule);
577 } 625 }
578 } 626 }
579 } 627 }