aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/OdePlugin
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Physics/OdePlugin/OdePlugin.cs527
1 files changed, 452 insertions, 75 deletions
diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
index 9ac43bf..4bd36aa 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
@@ -34,7 +34,6 @@ using OpenSim.Framework;
34using OpenSim.Region.Physics.Manager; 34using OpenSim.Region.Physics.Manager;
35using OpenSim.Region.Physics.OdePlugin.Meshing; 35using OpenSim.Region.Physics.OdePlugin.Meshing;
36 36
37
38namespace OpenSim.Region.Physics.OdePlugin 37namespace OpenSim.Region.Physics.OdePlugin
39{ 38{
40 /// <summary> 39 /// <summary>
@@ -84,13 +83,18 @@ namespace OpenSim.Region.Physics.OdePlugin
84 public d.TriArrayCallback triArrayCallback; 83 public d.TriArrayCallback triArrayCallback;
85 private List<OdeCharacter> _characters = new List<OdeCharacter>(); 84 private List<OdeCharacter> _characters = new List<OdeCharacter>();
86 private List<OdePrim> _prims = new List<OdePrim>(); 85 private List<OdePrim> _prims = new List<OdePrim>();
86 private List<OdePrim> _activeprims = new List<OdePrim>();
87 public Dictionary<IntPtr, String> geom_name_map = new Dictionary<IntPtr, String>(); 87 public Dictionary<IntPtr, String> geom_name_map = new Dictionary<IntPtr, String>();
88 public Dictionary<IntPtr, PhysicsActor> actor_name_map = new Dictionary<IntPtr, PhysicsActor>(); 88 public Dictionary<IntPtr, PhysicsActor> actor_name_map = new Dictionary<IntPtr, PhysicsActor>();
89 private d.ContactGeom[] contacts = new d.ContactGeom[30]; 89 private d.ContactGeom[] contacts = new d.ContactGeom[30];
90 private d.Contact contact; 90 private d.Contact contact;
91 private d.Contact TerrainContact;
92 private int m_physicsiterations = 10;
93 private float m_SkipFramesAtms = 0.40f; // Drop frames gracefully at a 400 ms lag
91 private PhysicsActor PANull = new NullPhysicsActor(); 94 private PhysicsActor PANull = new NullPhysicsActor();
92 private float step_time = 0.0f; 95 private float step_time = 0.0f;
93 public IntPtr world; 96 public IntPtr world;
97
94 public IntPtr space; 98 public IntPtr space;
95 public static Object OdeLock = new Object(); 99 public static Object OdeLock = new Object();
96 100
@@ -106,17 +110,25 @@ namespace OpenSim.Region.Physics.OdePlugin
106 contact.surface.soft_erp = 0.005f; 110 contact.surface.soft_erp = 0.005f;
107 contact.surface.soft_cfm = 0.00003f; 111 contact.surface.soft_cfm = 0.00003f;
108 */ 112 */
113
109 contact.surface.mu = 250.0f; 114 contact.surface.mu = 250.0f;
110 contact.surface.bounce = 0.2f; 115 contact.surface.bounce = 0.2f;
116 TerrainContact.surface.mode |= d.ContactFlags.SoftERP;
117 TerrainContact.surface.mu = 250.0f;
118 TerrainContact.surface.bounce = 0.1f;
119 TerrainContact.surface.soft_erp = 0.1025f;
120
111 lock (OdeLock) 121 lock (OdeLock)
112 { 122 {
113 world = d.WorldCreate(); 123 world = d.WorldCreate();
114 space = d.HashSpaceCreate(IntPtr.Zero); 124 space = d.HashSpaceCreate(IntPtr.Zero);
115 contactgroup = d.JointGroupCreate(0); 125 contactgroup = d.JointGroupCreate(0);
126 //contactgroup
127
116 d.WorldSetGravity(world, 0.0f, 0.0f, -10.0f); 128 d.WorldSetGravity(world, 0.0f, 0.0f, -10.0f);
117 d.WorldSetAutoDisableFlag(world, false); 129 d.WorldSetAutoDisableFlag(world, false);
118 d.WorldSetContactSurfaceLayer(world, 0.001f); 130 d.WorldSetContactSurfaceLayer(world, 0.001f);
119 d.WorldSetQuickStepNumIterations(world, 10); 131 d.WorldSetQuickStepNumIterations(world, m_physicsiterations);
120 d.WorldSetContactMaxCorrectingVel(world, 1000.0f); 132 d.WorldSetContactMaxCorrectingVel(world, 1000.0f);
121 } 133 }
122 134
@@ -127,6 +139,7 @@ namespace OpenSim.Region.Physics.OdePlugin
127 // This function blatantly ripped off from BoxStack.cs 139 // This function blatantly ripped off from BoxStack.cs
128 private void near(IntPtr space, IntPtr g1, IntPtr g2) 140 private void near(IntPtr space, IntPtr g1, IntPtr g2)
129 { 141 {
142
130 // no lock here! It's invoked from within Simulate(), which is thread-locked 143 // no lock here! It's invoked from within Simulate(), which is thread-locked
131 IntPtr b1 = d.GeomGetBody(g1); 144 IntPtr b1 = d.GeomGetBody(g1);
132 IntPtr b2 = d.GeomGetBody(g2); 145 IntPtr b2 = d.GeomGetBody(g2);
@@ -142,6 +155,19 @@ namespace OpenSim.Region.Physics.OdePlugin
142 155
143 156
144 d.GeomClassID id = d.GeomGetClass(g1); 157 d.GeomClassID id = d.GeomGetClass(g1);
158
159 String name1 = null;
160 String name2 = null;
161
162 if (!geom_name_map.TryGetValue(g1, out name1))
163 {
164 name1 = "null";
165 }
166 if (!geom_name_map.TryGetValue(g2, out name2))
167 {
168 name2 = "null";
169 }
170
145 if (id == d.GeomClassID.TriMeshClass) 171 if (id == d.GeomClassID.TriMeshClass)
146 { 172 {
147 173
@@ -149,33 +175,47 @@ namespace OpenSim.Region.Physics.OdePlugin
149// MainLog.Instance.Verbose("near: A collision was detected between {1} and {2}", 0, name1, name2); 175// MainLog.Instance.Verbose("near: A collision was detected between {1} and {2}", 0, name1, name2);
150 //System.Console.WriteLine("near: A collision was detected between {1} and {2}", 0, name1, name2); 176 //System.Console.WriteLine("near: A collision was detected between {1} and {2}", 0, name1, name2);
151 } 177 }
152 178
153 int count = d.Collide(g1, g2, contacts.GetLength(0), contacts, d.ContactGeom.SizeOf); 179 int count;
180
181 count = d.Collide(g1, g2, contacts.GetLength(0), contacts, d.ContactGeom.SizeOf);
182
154 for (int i = 0; i < count; i++) 183 for (int i = 0; i < count; i++)
155 { 184 {
156 contact.geom = contacts[i]; 185 IntPtr joint;
157 IntPtr joint = d.JointCreateContact(world, contactgroup, ref contact); 186 // If we're colliding with terrain, use 'TerrainContact' instead of contact.
158 d.JointAttach(joint, b1, b2); 187 // allows us to have different settings
159 PhysicsActor p1; 188 if (name1 == "Terrain" || name2 == "Terrain")
160 PhysicsActor p2;
161
162
163 if (!actor_name_map.TryGetValue(g1, out p1))
164 { 189 {
165 p1 = PANull; 190
191 TerrainContact.geom = contacts[i];
192 joint = d.JointCreateContact(world, contactgroup, ref TerrainContact);
193
166 } 194 }
195 else
196 {
197 contact.geom = contacts[i];
198 joint = d.JointCreateContact(world, contactgroup, ref contact);
199 }
200
201
202 d.JointAttach(joint, b1, b2);
203
204
205 PhysicsActor p2;
206
167 if (!actor_name_map.TryGetValue(g2, out p2)) 207 if (!actor_name_map.TryGetValue(g2, out p2))
168 { 208 {
169 p2 = PANull; 209 p2 = PANull;
170 } 210 }
171 211
172 p1.IsColliding = true; 212 // We only need to test p2 for 'jump crouch purposes'
173 p2.IsColliding = true; 213 p2.IsColliding = true;
174 //System.Console.WriteLine("near: A collision was detected between {1} and {2}", 0, name1, name2); 214 //System.Console.WriteLine("near: A collision was detected between {1} and {2}", 0, name1, name2);
175 } 215 }
176 } 216 }
177 217
178 private void collision_optimized() 218 private void collision_optimized(float timeStep)
179 { 219 {
180 foreach (OdeCharacter chr in _characters) 220 foreach (OdeCharacter chr in _characters)
181 { 221 {
@@ -183,17 +223,45 @@ namespace OpenSim.Region.Physics.OdePlugin
183 } 223 }
184 foreach (OdeCharacter chr in _characters) 224 foreach (OdeCharacter chr in _characters)
185 { 225 {
226
186 227
187 228
188
189 d.SpaceCollide2(space, chr.Shell, IntPtr.Zero, nearCallback); 229 d.SpaceCollide2(space, chr.Shell, IntPtr.Zero, nearCallback);
190 foreach (OdeCharacter ch2 in _characters) 230 foreach (OdeCharacter ch2 in _characters)
191 /// should be a separate space -- lots of avatars will be N**2 slow 231 /// should be a separate space -- lots of avatars will be N**2 slow
192 { 232 {
233
193 234
194
195 d.SpaceCollide2(chr.Shell, ch2.Shell, IntPtr.Zero, nearCallback); 235 d.SpaceCollide2(chr.Shell, ch2.Shell, IntPtr.Zero, nearCallback);
196 } 236 }
237
238 }
239 // If the sim is running slow this frame,
240 // don't process collision for prim!
241 if (timeStep < (m_SkipFramesAtms / 2))
242 {
243 foreach (OdePrim chr in _activeprims)
244 {
245 // This if may not need to be there.. it might be skipped anyway.
246 if (d.BodyIsEnabled(chr.Body))
247 {
248 d.SpaceCollide2(space, chr.prim_geom, IntPtr.Zero, nearCallback);
249 foreach (OdePrim ch2 in _prims)
250 /// should be a separate space -- lots of avatars will be N**2 slow
251 {
252 if (ch2.IsPhysical && d.BodyIsEnabled(ch2.Body))
253 {
254 // Only test prim that are 0.03 meters away in one direction.
255 // This should be Optimized!
256
257 if ((Math.Abs(ch2.Position.X - chr.Position.X) < 0.03) || (Math.Abs(ch2.Position.Y - chr.Position.Y) < 0.03) || (Math.Abs(ch2.Position.X - chr.Position.X) < 0.03))
258 {
259 d.SpaceCollide2(chr.prim_geom, ch2.prim_geom, IntPtr.Zero, nearCallback);
260 }
261 }
262 }
263 }
264 }
197 } 265 }
198 } 266 }
199 267
@@ -223,14 +291,21 @@ namespace OpenSim.Region.Physics.OdePlugin
223 { 291 {
224 lock (OdeLock) 292 lock (OdeLock)
225 { 293 {
226 d.GeomDestroy(((OdePrim) prim).prim_geom); 294 if (prim.IsPhysical)
227 _prims.Remove((OdePrim) prim); 295 {
296 OdePrim p;
297 p = (OdePrim) prim;
298 p.disableBody();
299 }
300 d.GeomDestroy(((OdePrim)prim).prim_geom);
301 _prims.Remove((OdePrim)prim);
302
228 } 303 }
229 } 304 }
230 } 305 }
231 306
232 private PhysicsActor AddPrim(String name, PhysicsVector position, PhysicsVector size, Quaternion rotation, 307 private PhysicsActor AddPrim(String name, PhysicsVector position, PhysicsVector size, Quaternion rotation,
233 Mesh mesh, PrimitiveBaseShape pbs) 308 Mesh mesh, PrimitiveBaseShape pbs, bool isphysical)
234 { 309 {
235 PhysicsVector pos = new PhysicsVector(); 310 PhysicsVector pos = new PhysicsVector();
236 pos.X = position.X; 311 pos.X = position.X;
@@ -248,13 +323,27 @@ namespace OpenSim.Region.Physics.OdePlugin
248 OdePrim newPrim; 323 OdePrim newPrim;
249 lock (OdeLock) 324 lock (OdeLock)
250 { 325 {
251 newPrim = new OdePrim(name, this, pos, siz, rot, mesh, pbs); 326 newPrim = new OdePrim(name, this, pos, siz, rot, mesh, pbs, isphysical);
252 } 327 }
253 _prims.Add(newPrim); 328 _prims.Add(newPrim);
254 return newPrim; 329 return newPrim;
255 } 330 }
256 331
257 332 public void addActivePrim(OdePrim activatePrim)
333 {
334 // adds active prim.. (ones that should be iterated over in collisions_optimized
335 lock (OdeLock)
336 {
337 _activeprims.Add(activatePrim);
338 }
339 }
340 public void remActivePrim(OdePrim deactivatePrim)
341 {
342 lock (OdeLock)
343 {
344 _activeprims.Remove(deactivatePrim);
345 }
346 }
258 public int TriArrayCallback(IntPtr trimesh, IntPtr refObject, int[] triangleIndex, int triCount) 347 public int TriArrayCallback(IntPtr trimesh, IntPtr refObject, int[] triangleIndex, int triCount)
259 { 348 {
260/* String name1 = null; 349/* String name1 = null;
@@ -276,7 +365,6 @@ namespace OpenSim.Region.Physics.OdePlugin
276 365
277 public int TriCallback(IntPtr trimesh, IntPtr refObject, int triangleIndex) 366 public int TriCallback(IntPtr trimesh, IntPtr refObject, int triangleIndex)
278 { 367 {
279/*
280 String name1 = null; 368 String name1 = null;
281 String name2 = null; 369 String name2 = null;
282 370
@@ -297,7 +385,7 @@ namespace OpenSim.Region.Physics.OdePlugin
297 385
298 d.GeomTriMeshGetTriangle(trimesh, 0, ref v0, ref v1, ref v2); 386 d.GeomTriMeshGetTriangle(trimesh, 0, ref v0, ref v1, ref v2);
299// MainLog.Instance.Debug("Triangle {0} is <{1},{2},{3}>, <{4},{5},{6}>, <{7},{8},{9}>", triangleIndex, v0.X, v0.Y, v0.Z, v1.X, v1.Y, v1.Z, v2.X, v2.Y, v2.Z); 387// MainLog.Instance.Debug("Triangle {0} is <{1},{2},{3}>, <{4},{5},{6}>, <{7},{8},{9}>", triangleIndex, v0.X, v0.Y, v0.Z, v1.X, v1.Y, v1.Z, v2.X, v2.Y, v2.Z);
300*/ 388
301 return 1; 389 return 1;
302 } 390 }
303 391
@@ -318,7 +406,6 @@ namespace OpenSim.Region.Physics.OdePlugin
318 { 406 {
319 return this.AddPrimShape(primName, pbs, position, size, rotation, false); 407 return this.AddPrimShape(primName, pbs, position, size, rotation, false);
320 } 408 }
321
322 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, 409 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position,
323 PhysicsVector size, Quaternion rotation, bool isPhysical) 410 PhysicsVector size, Quaternion rotation, bool isPhysical)
324 { 411 {
@@ -337,12 +424,13 @@ namespace OpenSim.Region.Physics.OdePlugin
337 break; 424 break;
338 } 425 }
339 426
340 result = AddPrim(primName, position, size, rotation, mesh, pbs); 427 result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical);
341 428
342 429
343 return result; 430 return result;
344 } 431 }
345 432
433
346 public override void Simulate(float timeStep) 434 public override void Simulate(float timeStep)
347 { 435 {
348 step_time += timeStep; 436 step_time += timeStep;
@@ -367,17 +455,45 @@ namespace OpenSim.Region.Physics.OdePlugin
367 rx.z + "," + ry.z + "," + rz.z); 455 rx.z + "," + ry.z + "," + rz.z);
368 } 456 }
369 } 457 }
458
459
460 // If We're loaded down by something else,
461 // or debugging with the Visual Studio project on pause
462 // skip a few frames to catch up gracefully.
463 // without shooting the physicsactors all over the place
464
465 if (step_time >= m_SkipFramesAtms)
466 {
467 // Instead of trying to catch up, it'll do one physics frame only
468 step_time = ODE_STEPSIZE;
469 this.m_physicsiterations = 5;
470 }
471 else
472 {
473 m_physicsiterations = 10;
474 }
475 // Process 10 frames if the sim is running normal..
476 // process 5 frames if the sim is running slow
477 d.WorldSetQuickStepNumIterations(world, m_physicsiterations);
478
370 int i = 0; 479 int i = 0;
371 while (step_time > 0.0f) 480 while (step_time > 0.0f)
372 { 481 {
373 foreach (OdeCharacter actor in _characters) 482 foreach (OdeCharacter actor in _characters)
374 { 483 {
375 actor.Move(timeStep); 484 actor.Move(timeStep);
485 actor.collidelock = true;
376 } 486 }
377 487
378 collision_optimized(); 488
489 collision_optimized(timeStep);
379 d.WorldQuickStep(world, ODE_STEPSIZE); 490 d.WorldQuickStep(world, ODE_STEPSIZE);
380 d.JointGroupEmpty(contactgroup); 491 d.JointGroupEmpty(contactgroup);
492 foreach (OdeCharacter actor in _characters)
493 {
494 actor.collidelock = false;
495 }
496
381 step_time -= ODE_STEPSIZE; 497 step_time -= ODE_STEPSIZE;
382 i++; 498 i++;
383 } 499 }
@@ -414,6 +530,16 @@ namespace OpenSim.Region.Physics.OdePlugin
414 "1,0,0, 0,1,0, 0,0,1"); // rotation 530 "1,0,0, 0,1,0, 0,0,1"); // rotation
415 } 531 }
416 } 532 }
533 if (timeStep < 0.2f)
534 {
535 foreach (OdePrim actor in _activeprims)
536 {
537 if (actor.IsPhysical && (d.BodyIsEnabled(actor.Body) || !actor._zeroFlag))
538 {
539 actor.UpdatePositionAndVelocity();
540 }
541 }
542 }
417 } 543 }
418 } 544 }
419 545
@@ -495,7 +621,7 @@ namespace OpenSim.Region.Physics.OdePlugin
495 private static float PID_P = 7000.0f; 621 private static float PID_P = 7000.0f;
496 private static float POSTURE_SERVO = 10000.0f; 622 private static float POSTURE_SERVO = 10000.0f;
497 public static float CAPSULE_RADIUS = 0.5f; 623 public static float CAPSULE_RADIUS = 0.5f;
498 public static float CAPSULE_LENGTH = 0.9f; 624 public static float CAPSULE_LENGTH = 0.79f;
499 private bool flying = false; 625 private bool flying = false;
500 private bool iscolliding = false; 626 private bool iscolliding = false;
501 private bool jumping = false; 627 private bool jumping = false;
@@ -504,6 +630,7 @@ namespace OpenSim.Region.Physics.OdePlugin
504 private OdeScene _parent_scene; 630 private OdeScene _parent_scene;
505 public IntPtr Shell; 631 public IntPtr Shell;
506 public d.Mass ShellMass; 632 public d.Mass ShellMass;
633 public bool collidelock = false;
507 634
508 public OdeCharacter(String avName, OdeScene parent_scene, PhysicsVector pos) 635 public OdeCharacter(String avName, OdeScene parent_scene, PhysicsVector pos)
509 { 636 {
@@ -514,6 +641,7 @@ namespace OpenSim.Region.Physics.OdePlugin
514 _parent_scene = parent_scene; 641 _parent_scene = parent_scene;
515 lock (OdeScene.OdeLock) 642 lock (OdeScene.OdeLock)
516 { 643 {
644
517 Shell = d.CreateCapsule(parent_scene.space, CAPSULE_RADIUS, CAPSULE_LENGTH); 645 Shell = d.CreateCapsule(parent_scene.space, CAPSULE_RADIUS, CAPSULE_LENGTH);
518 d.MassSetCapsule(out ShellMass, 50.0f, 3, 0.4f, 1.0f); 646 d.MassSetCapsule(out ShellMass, 50.0f, 3, 0.4f, 1.0f);
519 Body = d.BodyCreate(parent_scene.world); 647 Body = d.BodyCreate(parent_scene.world);
@@ -608,19 +736,22 @@ namespace OpenSim.Region.Physics.OdePlugin
608 } 736 }
609 public void doForce(PhysicsVector force) 737 public void doForce(PhysicsVector force)
610 { 738 {
611 d.BodyAddForce(Body, force.X, force.Y, force.Z); 739 if (!collidelock)
612 740 {
613 // ok -- let's stand up straight! 741 d.BodyAddForce(Body, force.X, force.Y, force.Z);
614 d.Vector3 feet; 742
615 d.Vector3 head; 743 // ok -- let's stand up straight!
616 d.BodyGetRelPointPos(Body, 0.0f, 0.0f, -1.0f, out feet); 744 d.Vector3 feet;
617 d.BodyGetRelPointPos(Body, 0.0f, 0.0f, 1.0f, out head); 745 d.Vector3 head;
618 float posture = head.Z - feet.Z; 746 d.BodyGetRelPointPos(Body, 0.0f, 0.0f, -1.0f, out feet);
619 747 d.BodyGetRelPointPos(Body, 0.0f, 0.0f, 1.0f, out head);
620 // restoring force proportional to lack of posture: 748 float posture = head.Z - feet.Z;
621 float servo = (2.5f - posture) * POSTURE_SERVO; 749
622 d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, servo, 0.0f, 0.0f, 1.0f); 750 // restoring force proportional to lack of posture:
623 d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, -servo, 0.0f, 0.0f, -1.0f); 751 float servo = (2.5f - posture) * POSTURE_SERVO;
752 d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, servo, 0.0f, 0.0f, 1.0f);
753 d.BodyAddForceAtRelPos(Body, 0.0f, 0.0f, -servo, 0.0f, 0.0f, -1.0f);
754 }
624 755
625 } 756 }
626 public override void SetMomentum(PhysicsVector momentum) 757 public override void SetMomentum(PhysicsVector momentum)
@@ -675,6 +806,8 @@ namespace OpenSim.Region.Physics.OdePlugin
675 { 806 {
676 vec.Z += 10.0f; 807 vec.Z += 10.0f;
677 } 808 }
809
810
678 doForce(vec); 811 doForce(vec);
679 } 812 }
680 813
@@ -702,9 +835,9 @@ namespace OpenSim.Region.Physics.OdePlugin
702 else 835 else
703 { 836 {
704 vec = d.BodyGetLinearVel(Body); 837 vec = d.BodyGetLinearVel(Body);
705 _velocity.X = vec.X; 838 _velocity.X = (vec.X);
706 _velocity.Y = vec.Y; 839 _velocity.Y = (vec.Y);
707 _velocity.Z = vec.Z; 840 _velocity.Z = (vec.Z);
708 } 841 }
709 } 842 }
710 843
@@ -723,19 +856,33 @@ namespace OpenSim.Region.Physics.OdePlugin
723 { 856 {
724 public PhysicsVector _position; 857 public PhysicsVector _position;
725 private PhysicsVector _velocity; 858 private PhysicsVector _velocity;
859 private PhysicsVector m_lastVelocity = new PhysicsVector(0.0f,0.0f,0.0f);
860 private PhysicsVector m_lastposition = new PhysicsVector(0.0f, 0.0f, 0.0f);
726 private PhysicsVector _size; 861 private PhysicsVector _size;
727 private PhysicsVector _acceleration; 862 private PhysicsVector _acceleration;
728 public Quaternion _orientation; 863 public Quaternion _orientation;
864
729 private Mesh _mesh; 865 private Mesh _mesh;
730 private PrimitiveBaseShape _pbs; 866 private PrimitiveBaseShape _pbs;
731 private OdeScene _parent_scene; 867 private OdeScene _parent_scene;
732 public IntPtr prim_geom; 868 public IntPtr prim_geom;
733 public IntPtr _triMeshData; 869 public IntPtr _triMeshData;
734 private bool iscolliding = false; 870 private bool iscolliding = false;
871 private bool m_isphysical = false;
872 public bool _zeroFlag = false;
873 public IntPtr Body = (IntPtr) 0;
874 private String m_primName;
875 private PhysicsVector _target_velocity;
876 public d.Mass pMass;
877 private const float MassMultiplier = 500f; // Ref: Water: 1000kg.. this iset to 500
878 private int debugcounter = 0;
879
735 880
736 public OdePrim(String primName, OdeScene parent_scene, PhysicsVector pos, PhysicsVector size, 881 public OdePrim(String primName, OdeScene parent_scene, PhysicsVector pos, PhysicsVector size,
737 Quaternion rotation, Mesh mesh, PrimitiveBaseShape pbs) 882 Quaternion rotation, Mesh mesh, PrimitiveBaseShape pbs, bool pisPhysical)
738 { 883 {
884
885
739 _velocity = new PhysicsVector(); 886 _velocity = new PhysicsVector();
740 _position = pos; 887 _position = pos;
741 _size = size; 888 _size = size;
@@ -744,6 +891,9 @@ namespace OpenSim.Region.Physics.OdePlugin
744 _mesh = mesh; 891 _mesh = mesh;
745 _pbs = pbs; 892 _pbs = pbs;
746 _parent_scene = parent_scene; 893 _parent_scene = parent_scene;
894 m_isphysical = pisPhysical;
895 m_primName = primName;
896
747 897
748 898
749 lock (OdeScene.OdeLock) 899 lock (OdeScene.OdeLock)
@@ -764,20 +914,60 @@ namespace OpenSim.Region.Physics.OdePlugin
764 myrot.Y = rotation.y; 914 myrot.Y = rotation.y;
765 myrot.Z = rotation.z; 915 myrot.Z = rotation.z;
766 d.GeomSetQuaternion(prim_geom, ref myrot); 916 d.GeomSetQuaternion(prim_geom, ref myrot);
917
918
919 if (m_isphysical && Body == (IntPtr)0) {
920 enableBody();
921 }
767 parent_scene.geom_name_map[prim_geom] = primName; 922 parent_scene.geom_name_map[prim_geom] = primName;
768 parent_scene.actor_name_map[prim_geom] = (PhysicsActor) this; 923 parent_scene.actor_name_map[prim_geom] = (PhysicsActor)this;
769 // don't do .add() here; old geoms get recycled with the same hash 924 // don't do .add() here; old geoms get recycled with the same hash
770 } 925 }
771 } 926 }
772 927 public void enableBody()
773 public override bool IsPhysical
774 { 928 {
775 get { return false; } 929 // Sets the geom to a body
776 set { return; } 930 Body = d.BodyCreate(_parent_scene.world);
931
932 setMass();
933 d.BodySetPosition(Body, _position.X, _position.Y, _position.Z);
934 d.Quaternion myrot = new d.Quaternion();
935 myrot.W = _orientation.w;
936 myrot.X = _orientation.x;
937 myrot.Y = _orientation.y;
938 myrot.Z = _orientation.z;
939 d.BodySetQuaternion(Body, ref myrot);
940 d.GeomSetBody(prim_geom, Body);
941 d.BodySetAutoDisableFlag(Body, true);
942 d.BodySetAutoDisableSteps(Body,20);
943 _parent_scene.addActivePrim(this);
944 }
945 public void setMass()
946 {
947 //Sets Mass based on member MassMultiplier.
948 if (Body != (IntPtr)0)
949 {
950 d.MassSetBox(out pMass, (_size.X * _size.Y * _size.Z * MassMultiplier), _size.X, _size.Y, _size.Z);
951 d.BodySetMass(Body, ref pMass);
952 }
953 }
954 public void disableBody()
955 {
956 //this kills the body so things like 'mesh' can re-create it.
957 if (Body != (IntPtr)0)
958 {
959 _parent_scene.remActivePrim(this);
960 d.BodyDestroy(Body);
961 Body = (IntPtr)0;
962 }
777 } 963 }
778
779 public void setMesh(OdeScene parent_scene, Mesh mesh) 964 public void setMesh(OdeScene parent_scene, Mesh mesh)
780 { 965 {
966 //Kill Body so that mesh can re-make the geom
967 if (IsPhysical && Body != (IntPtr)0)
968 {
969 disableBody();
970 }
781 float[] vertexList = mesh.getVertexListAsFloat(); // Note, that vertextList is pinned in memory 971 float[] vertexList = mesh.getVertexListAsFloat(); // Note, that vertextList is pinned in memory
782 int[] indexList = mesh.getIndexListAsInt(); // Also pinned, needs release after usage 972 int[] indexList = mesh.getIndexListAsInt(); // Also pinned, needs release after usage
783 int VertexCount = vertexList.GetLength(0)/3; 973 int VertexCount = vertexList.GetLength(0)/3;
@@ -790,6 +980,46 @@ namespace OpenSim.Region.Physics.OdePlugin
790 d.GeomTriMeshDataPreprocess(_triMeshData); 980 d.GeomTriMeshDataPreprocess(_triMeshData);
791 981
792 prim_geom = d.CreateTriMesh(parent_scene.space, _triMeshData, parent_scene.triCallback, null, null); 982 prim_geom = d.CreateTriMesh(parent_scene.space, _triMeshData, parent_scene.triCallback, null, null);
983
984 if (IsPhysical && Body == (IntPtr)0)
985 {
986 // Recreate the body
987 enableBody();
988 }
989 }
990
991 public override bool IsPhysical
992 {
993 get { return m_isphysical; }
994 set {
995
996 lock (OdeScene.OdeLock)
997 {
998 if (m_isphysical == value)
999 {
1000 // If the object is already what the user checked
1001
1002 return;
1003 }
1004 if (value == true)
1005 {
1006 if (Body == (IntPtr)0)
1007 {
1008 enableBody();
1009 }
1010
1011 }
1012 else if (value == false)
1013 {
1014 if (Body != (IntPtr)0)
1015 {
1016 disableBody();
1017 }
1018 }
1019 m_isphysical = value;
1020 }
1021
1022 }
793 } 1023 }
794 1024
795 public override bool Flying 1025 public override bool Flying
@@ -808,13 +1038,27 @@ namespace OpenSim.Region.Physics.OdePlugin
808 1038
809 public override PhysicsVector Position 1039 public override PhysicsVector Position
810 { 1040 {
811 get { return _position; } 1041 get { return _position;}
812 set 1042 set
813 { 1043 {
814 _position = value; 1044 _position = value;
815 lock (OdeScene.OdeLock) 1045 lock (OdeScene.OdeLock)
816 { 1046 {
817 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); 1047 if (m_isphysical)
1048 {
1049 // This is a fallback.. May no longer be necessary.
1050 if (Body == (IntPtr)0)
1051 enableBody();
1052 // Prim auto disable after 20 frames,
1053 // if you move it, re-enable the prim manually.
1054 d.BodyEnable(Body);
1055 d.BodySetPosition(Body, _position.X, _position.Y, _position.Z);
1056 }
1057 else
1058 {
1059 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
1060
1061 }
818 } 1062 }
819 } 1063 }
820 } 1064 }
@@ -830,29 +1074,38 @@ namespace OpenSim.Region.Physics.OdePlugin
830 string oldname = _parent_scene.geom_name_map[prim_geom]; 1074 string oldname = _parent_scene.geom_name_map[prim_geom];
831 1075
832 // Cleanup of old prim geometry 1076 // Cleanup of old prim geometry
833 d.GeomDestroy(prim_geom);
834 if (_mesh != null) 1077 if (_mesh != null)
835 { 1078 {
836 // Cleanup meshing here 1079 // Cleanup meshing here
837 } 1080 }
838 1081 //kill body to rebuild
1082 if (IsPhysical && Body != (IntPtr)0)
1083 {
1084 disableBody();
1085 }
839 // Construction of new prim 1086 // Construction of new prim
840 if (this._parent_scene.needsMeshing(_pbs)) 1087 if (this._parent_scene.needsMeshing(_pbs))
841 { 1088 {
1089
1090 // Don't need to re-enable body.. it's done in SetMesh
842 Mesh mesh = Meshmerizer.CreateMesh(oldname, _pbs, _size); 1091 Mesh mesh = Meshmerizer.CreateMesh(oldname, _pbs, _size);
843 setMesh(_parent_scene, mesh); 1092 setMesh(_parent_scene, mesh);
844 } else { 1093 } else {
845 prim_geom = d.CreateBox(_parent_scene.space, _size.X, _size.Y, _size.Z); 1094 prim_geom = d.CreateBox(_parent_scene.space, _size.X, _size.Y, _size.Z);
1095
1096 if (IsPhysical && Body == (IntPtr)0)
1097 {
1098 // Re creates body on size.
1099 // EnableBody also does setMass()
1100 enableBody();
1101 d.BodyEnable(Body);
1102 }
1103
846 } 1104 }
1105
1106
847 _parent_scene.geom_name_map[prim_geom] = oldname; 1107 _parent_scene.geom_name_map[prim_geom] = oldname;
848 1108
849 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
850 d.Quaternion myrot = new d.Quaternion();
851 myrot.W = _orientation.w;
852 myrot.X = _orientation.x;
853 myrot.Y = _orientation.y;
854 myrot.Z = _orientation.z;
855 d.GeomSetQuaternion(prim_geom, ref myrot);
856 } 1109 }
857 } 1110 }
858 } 1111 }
@@ -866,11 +1119,17 @@ namespace OpenSim.Region.Physics.OdePlugin
866 { 1119 {
867 string oldname = _parent_scene.geom_name_map[prim_geom]; 1120 string oldname = _parent_scene.geom_name_map[prim_geom];
868 1121
869 // Cleanup of old prim geometry 1122 // Cleanup of old prim geometry and Bodies
1123 if (IsPhysical && Body != (IntPtr)0)
1124 {
1125 disableBody();
1126 }
870 d.GeomDestroy(prim_geom); 1127 d.GeomDestroy(prim_geom);
871 if (_mesh != null) 1128 if (_mesh != null)
872 { 1129 {
873 // Cleanup meshing here 1130
1131 d.GeomBoxSetLengths(prim_geom, _size.X, _size.Y, _size.Z);
1132
874 } 1133 }
875 1134
876 // Construction of new prim 1135 // Construction of new prim
@@ -881,15 +1140,24 @@ namespace OpenSim.Region.Physics.OdePlugin
881 } else { 1140 } else {
882 prim_geom = d.CreateBox(_parent_scene.space, _size.X, _size.Y, _size.Z); 1141 prim_geom = d.CreateBox(_parent_scene.space, _size.X, _size.Y, _size.Z);
883 } 1142 }
1143 if (IsPhysical && Body == (IntPtr)0)
1144 {
1145 //re-create new body
1146 enableBody();
1147 }
1148 else
1149 {
1150 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
1151 d.Quaternion myrot = new d.Quaternion();
1152 myrot.W = _orientation.w;
1153 myrot.X = _orientation.x;
1154 myrot.Y = _orientation.y;
1155 myrot.Z = _orientation.z;
1156 d.GeomSetQuaternion(prim_geom, ref myrot);
1157 }
884 _parent_scene.geom_name_map[prim_geom] = oldname; 1158 _parent_scene.geom_name_map[prim_geom] = oldname;
885 1159
886 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); 1160
887 d.Quaternion myrot = new d.Quaternion();
888 myrot.W = _orientation.w;
889 myrot.X = _orientation.x;
890 myrot.Y = _orientation.y;
891 myrot.Z = _orientation.z;
892 d.GeomSetQuaternion(prim_geom, ref myrot);
893 1161
894 } 1162 }
895 } 1163 }
@@ -897,7 +1165,15 @@ namespace OpenSim.Region.Physics.OdePlugin
897 1165
898 public override PhysicsVector Velocity 1166 public override PhysicsVector Velocity
899 { 1167 {
900 get { return _velocity; } 1168 get {
1169 // Averate previous velocity with the new one so
1170 // client object interpolation works a 'little' better
1171 PhysicsVector returnVelocity = new PhysicsVector();
1172 returnVelocity.X = (m_lastVelocity.X + _velocity.X) / 2;
1173 returnVelocity.Y = (m_lastVelocity.Y + _velocity.Y) / 2;
1174 returnVelocity.Z = (m_lastVelocity.Z + _velocity.Z) / 2;
1175 return returnVelocity;
1176 }
901 set { _velocity = value; } 1177 set { _velocity = value; }
902 } 1178 }
903 1179
@@ -921,6 +1197,10 @@ namespace OpenSim.Region.Physics.OdePlugin
921 myrot.Y = _orientation.y; 1197 myrot.Y = _orientation.y;
922 myrot.Z = _orientation.z; 1198 myrot.Z = _orientation.z;
923 d.GeomSetQuaternion(prim_geom, ref myrot); 1199 d.GeomSetQuaternion(prim_geom, ref myrot);
1200 if (m_isphysical && Body != (IntPtr)0)
1201 {
1202 d.BodySetQuaternion(Body, ref myrot);
1203 }
924 } 1204 }
925 } 1205 }
926 } 1206 }
@@ -930,6 +1210,7 @@ namespace OpenSim.Region.Physics.OdePlugin
930 get { return _acceleration; } 1210 get { return _acceleration; }
931 } 1211 }
932 1212
1213
933 public void SetAcceleration(PhysicsVector accel) 1214 public void SetAcceleration(PhysicsVector accel)
934 { 1215 {
935 _acceleration = accel; 1216 _acceleration = accel;
@@ -938,7 +1219,103 @@ namespace OpenSim.Region.Physics.OdePlugin
938 public override void AddForce(PhysicsVector force) 1219 public override void AddForce(PhysicsVector force)
939 { 1220 {
940 } 1221 }
1222 public void Move(float timestep)
1223 {
1224
1225 }
1226
1227 public void UpdatePositionAndVelocity() {
1228 // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
1229 if (Body != (IntPtr)0)
1230 {
1231 d.Vector3 vec = d.BodyGetPosition(Body);
1232 d.Quaternion ori = d.BodyGetQuaternion(Body);
1233 d.Vector3 vel = d.BodyGetLinearVel(Body);
1234 PhysicsVector l_position = new PhysicsVector();
1235 // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!)
1236 if (vec.X < 0.0f) vec.X = 0.0f;
1237 if (vec.Y < 0.0f) vec.Y = 0.0f;
1238 if (vec.X > 255.95f) vec.X = 255.95f;
1239 if (vec.Y > 255.95f) vec.Y = 255.95f;
1240 m_lastposition = _position;
1241
1242 l_position.X = vec.X;
1243 l_position.Y = vec.Y;
1244 l_position.Z = vec.Z;
1245 if (l_position.Z < 0)
1246 {
1247 // This is so prim that get lost underground don't fall forever and suck up
1248 //
1249 // Sim resources and memory.
1250 // Disables the prim's movement physics....
1251 // It's a hack and will generate a console message if it fails.
1252
1253 try
1254 {
1255 disableBody();
1256
1257 }
1258 catch (System.Exception e)
1259 {
1260 if (Body != (IntPtr)0)
1261 {
1262 d.BodyDestroy(Body);
1263 Body = (IntPtr)0;
1264
1265 }
1266 }
1267 IsPhysical = false;
1268 _velocity.X = 0;
1269 _velocity.Y = 0;
1270 _velocity.Z = 0;
1271 _zeroFlag = true;
1272 }
1273
1274 if (m_lastposition == l_position)
1275 {
1276 _zeroFlag = true;
1277 }
1278 else
1279 {
1280 _zeroFlag = false;
1281 }
1282 m_lastposition = l_position;
1283
1284
1285 if (_zeroFlag)
1286 {
1287 // Supposedly this is supposed to tell SceneObjectGroup that
1288 // no more updates need to be sent..
1289 // but it seems broken.
1290 _velocity.X = 0.0f;
1291 _velocity.Y = 0.0f;
1292 _velocity.Z = 0.0f;
1293 _orientation.w = 0f;
1294 _orientation.x = 0f;
1295 _orientation.y = 0f;
1296 _orientation.z = 0f;
941 1297
1298
1299 }
1300 else
1301 {
1302 m_lastVelocity = _velocity;
1303
1304 _position = l_position;
1305
1306 _velocity.X = vel.X;
1307 _velocity.Y = vel.Y;
1308 _velocity.Z = vel.Z;
1309
1310 _orientation.w = ori.W;
1311 _orientation.x = ori.X;
1312 _orientation.y = ori.Y;
1313 _orientation.z = ori.Z;
1314 }
1315
1316 }
1317
1318 }
942 public override void SetMomentum(PhysicsVector momentum) 1319 public override void SetMomentum(PhysicsVector momentum)
943 { 1320 {
944 } 1321 }