aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/OdePlugin/OdePlugin.cs')
-rw-r--r--OpenSim/Region/Physics/OdePlugin/OdePlugin.cs220
1 files changed, 188 insertions, 32 deletions
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;