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.cs864
1 files changed, 449 insertions, 415 deletions
diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
index 266cb3d..5b1fd78 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
@@ -229,14 +229,7 @@ namespace OpenSim.Region.Physics.OdePlugin
229 } 229 }
230 } 230 }
231 231
232 public void starttiming() 232
233 {
234 ms = Environment.TickCount;
235 }
236 public int stoptiming()
237 {
238 return Environment.TickCount - ms;
239 }
240 // Initialize the mesh plugin 233 // Initialize the mesh plugin
241 public override void Initialise(IMesher meshmerizer) 234 public override void Initialise(IMesher meshmerizer)
242 { 235 {
@@ -245,15 +238,9 @@ namespace OpenSim.Region.Physics.OdePlugin
245 238
246 internal void waitForSpaceUnlock(IntPtr space) 239 internal void waitForSpaceUnlock(IntPtr space)
247 { 240 {
248 241 while (d.SpaceLockQuery(space)){ } // Wait and do nothing
249 while (d.SpaceLockQuery(space))
250 {
251
252 }
253
254
255
256 } 242 }
243
257 /// <summary> 244 /// <summary>
258 /// Debug space message for printing the space that a prim/avatar is in. 245 /// Debug space message for printing the space that a prim/avatar is in.
259 /// </summary> 246 /// </summary>
@@ -264,6 +251,8 @@ namespace OpenSim.Region.Physics.OdePlugin
264 return calculateSpaceForGeom(pos).ToString(); 251 return calculateSpaceForGeom(pos).ToString();
265 } 252 }
266 253
254 #region Collision Detection
255
267 /// <summary> 256 /// <summary>
268 /// This is our near callback. A geometry is near a body 257 /// This is our near callback. A geometry is near a body
269 /// </summary> 258 /// </summary>
@@ -299,314 +288,359 @@ namespace OpenSim.Region.Physics.OdePlugin
299 //Collide all geoms in each space.. 288 //Collide all geoms in each space..
300 //if (d.GeomIsSpace(g1)) d.SpaceCollide(g1, IntPtr.Zero, nearCallback); 289 //if (d.GeomIsSpace(g1)) d.SpaceCollide(g1, IntPtr.Zero, nearCallback);
301 //if (d.GeomIsSpace(g2)) d.SpaceCollide(g2, IntPtr.Zero, nearCallback); 290 //if (d.GeomIsSpace(g2)) d.SpaceCollide(g2, IntPtr.Zero, nearCallback);
291 return;
302 } 292 }
303 else 293
304 { 294
305 // Colliding Geom To Geom 295 // Colliding Geom To Geom
306 // This portion of the function 'was' blatantly ripped off from BoxStack.cs 296 // This portion of the function 'was' blatantly ripped off from BoxStack.cs
307 if (g1 == (IntPtr)0 || g2 == (IntPtr)0) 297 if (g1 == (IntPtr)0 || g2 == (IntPtr)0)
308 return; 298 return;
309 299
310 IntPtr b1 = d.GeomGetBody(g1); 300 IntPtr b1 = d.GeomGetBody(g1);
311 IntPtr b2 = d.GeomGetBody(g2); 301 IntPtr b2 = d.GeomGetBody(g2);
312 302
313 if (g1 == g2) 303 if (g1 == g2)
314 return; // Can't collide with yourself 304 return; // Can't collide with yourself
315 305
316 if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact)) 306 if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
317 return; 307 return;
308
309
310
311 d.GeomClassID id = d.GeomGetClass(g1);
312
313 String name1 = null;
314 String name2 = null;
318 315
316 if (!geom_name_map.TryGetValue(g1, out name1))
317 {
318 name1 = "null";
319 }
320 if (!geom_name_map.TryGetValue(g2, out name2))
321 {
322 name2 = "null";
323 }
324
325 //if (id == d.GeomClassId.TriMeshClass)
326 //{
327 // m_log.InfoFormat("near: A collision was detected between {1} and {2}", 0, name1, name2);
328 //System.Console.WriteLine("near: A collision was detected between {1} and {2}", 0, name1, name2);
329 //}
330
331 // Figure out how many contact points we have
332 int count = 0;
333 try
334 {
335 //m_log.Warn(g1.ToString() + "|" + g2.ToString());
336 count = d.Collide(g1, g2, contacts.GetLength(0), contacts, d.ContactGeom.SizeOf);
337 }
338 catch (SEHException)
339 {
340 m_log.Error("[PHYSICS]: The Operating system shut down ODE because of corrupt memory. This could be a result of really irregular terrain. If this repeats continuously, restart using Basic Physics and terrain fill your terrain. Restarting the sim.");
341 ode.drelease(world);
342 base.TriggerPhysicsBasedRestart();
343 }
344 catch (System.AccessViolationException)
345 {
319 346
347 m_log.Warn("[PHYSICS]: Unable to collide test an object");
348 return;
349 }
320 350
321 d.GeomClassID id = d.GeomGetClass(g1); 351 PhysicsActor p1;
352 PhysicsActor p2;
322 353
323 String name1 = null; 354 for (int i = 0; i < count; i++)
324 String name2 = null; 355 {
356 //m_log.Warn("[CCOUNT]: " + count);
357 IntPtr joint;
358 // If we're colliding with terrain, use 'TerrainContact' instead of contact.
359 // allows us to have different settings
325 360
326 if (!geom_name_map.TryGetValue(g1, out name1)) 361 if (!actor_name_map.TryGetValue(g1, out p1))
327 { 362 {
328 name1 = "null"; 363 p1 = PANull;
329 } 364 }
330 if (!geom_name_map.TryGetValue(g2, out name2)) 365 if (!actor_name_map.TryGetValue(g2, out p2))
331 { 366 {
332 name2 = "null"; 367 p2 = PANull;
333 } 368 }
334 369
335 //if (id == d.GeomClassId.TriMeshClass) 370 // We only need to test p2 for 'jump crouch purposes'
336 //{ 371 p2.IsColliding = true;
337 // m_log.InfoFormat("near: A collision was detected between {1} and {2}", 0, name1, name2);
338 //System.Console.WriteLine("near: A collision was detected between {1} and {2}", 0, name1, name2);
339 //}
340 372
341 // Figure out how many contact points we have 373 switch (p1.PhysicsActorType)
342 int count = 0;
343 try
344 { 374 {
345 //m_log.Warn(g1.ToString() + "|" + g2.ToString()); 375 case (int)ActorTypes.Agent:
346 count = d.Collide(g1, g2, contacts.GetLength(0), contacts, d.ContactGeom.SizeOf); 376 p2.CollidingObj = true;
347 } 377 break;
348 catch (SEHException) 378 case (int)ActorTypes.Prim:
349 { 379 if (p2.Velocity.X > 0 || p2.Velocity.Y > 0 || p2.Velocity.Z > 0)
350 m_log.Error("[PHYSICS]: The Operating system shut down ODE because of corrupt memory. This could be a result of really irregular terrain. If this repeats continuously, restart using Basic Physics and terrain fill your terrain. Restarting the sim."); 380 p2.CollidingObj = true;
351 ode.drelease(world); 381 break;
352 base.TriggerPhysicsBasedRestart(); 382 case (int)ActorTypes.Unknown:
353 } 383 p2.CollidingGround = true;
354 catch (System.AccessViolationException) 384 break;
355 { 385 default:
356 386 p2.CollidingGround = true;
357 m_log.Warn("[PHYSICS]: Unable to collide test an object"); 387 break;
358 return;
359 } 388 }
360 389
361 PhysicsActor p1; 390 // we don't want prim or avatar to explode
362 PhysicsActor p2;
363 391
364 for (int i = 0; i < count; i++) 392 #region InterPenetration Handling - Unintended physics explosions
365 {
366 //m_log.Warn("[CCOUNT]: " + count);
367 IntPtr joint;
368 // If we're colliding with terrain, use 'TerrainContact' instead of contact.
369 // allows us to have different settings
370 393
371 if (!actor_name_map.TryGetValue(g1, out p1)) 394 if (contacts[i].depth >= 0.08f)
395 {
396 //This is disabled at the moment only because it needs more tweaking
397 //It will eventually be uncommented
398
399 if (contacts[i].depth >= 1.00f)
372 { 400 {
373 p1 = PANull; 401 //m_log.Debug("[PHYSICS]: " + contacts[i].depth.ToString());
374 } 402 }
375 if (!actor_name_map.TryGetValue(g2, out p2)) 403
404 //If you interpenetrate a prim with an agent
405 if ((p2.PhysicsActorType == (int) ActorTypes.Agent &&
406 p1.PhysicsActorType == (int) ActorTypes.Prim) ||
407 (p1.PhysicsActorType == (int) ActorTypes.Agent &&
408 p2.PhysicsActorType == (int) ActorTypes.Prim))
376 { 409 {
377 p2 = PANull; 410 # region disabled code1
411 //contacts[i].depth = contacts[i].depth * 4.15f;
412 /*
413 if (p2.PhysicsActorType == (int) ActorTypes.Agent)
414 {
415 p2.CollidingObj = true;
416 contacts[i].depth = 0.003f;
417 p2.Velocity = p2.Velocity + new PhysicsVector(0, 0, 2.5f);
418 OdeCharacter character = (OdeCharacter) p2;
419 character.SetPidStatus(true);
420 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));
421
422 }
423 else
424 {
425
426 //contacts[i].depth = 0.0000000f;
427 }
428 if (p1.PhysicsActorType == (int) ActorTypes.Agent)
429 {
430
431 p1.CollidingObj = true;
432 contacts[i].depth = 0.003f;
433 p1.Velocity = p1.Velocity + new PhysicsVector(0, 0, 2.5f);
434 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));
435 OdeCharacter character = (OdeCharacter)p1;
436 character.SetPidStatus(true);
437 }
438 else
439 {
440
441 //contacts[i].depth = 0.0000000f;
442 }
443 */
444 #endregion
378 } 445 }
446
379 447
380 // We only need to test p2 for 'jump crouch purposes' 448 // If you interpenetrate a prim with another prim
381 p2.IsColliding = true; 449 if (p1.PhysicsActorType == (int) ActorTypes.Prim && p2.PhysicsActorType == (int) ActorTypes.Prim)
382
383 switch (p1.PhysicsActorType)
384 { 450 {
385 case (int)ActorTypes.Agent: 451 #region disabledcode2
386 p2.CollidingObj = true; 452 //OdePrim op1 = (OdePrim)p1;
387 break; 453 //OdePrim op2 = (OdePrim)p2;
388 case (int)ActorTypes.Prim: 454 //op1.m_collisionscore++;
389 if (p2.Velocity.X > 0 || p2.Velocity.Y > 0 || p2.Velocity.Z > 0) 455 //op2.m_collisionscore++;
390 p2.CollidingObj = true; 456
391 break;
392 case (int)ActorTypes.Unknown:
393 p2.CollidingGround = true;
394 break;
395 default:
396 p2.CollidingGround = true;
397 break;
398 }
399 457
400 // we don't want prim or avatar to explode 458 //if (op1.m_collisionscore > 8000 || op2.m_collisionscore > 8000)
459 //{
460 //op1.m_taintdisable = true;
461 //AddPhysicsActorTaint(p1);
462 //op2.m_taintdisable = true;
463 //AddPhysicsActorTaint(p2);
464 //}
465
466 //if (contacts[i].depth >= 0.25f)
467 //{
468 // Don't collide, one or both prim will expld.
469
401 470
402 #region InterPenetration Handling - Unintended physics explosions 471 //op1.m_interpenetrationcount++;
472 //op2.m_interpenetrationcount++;
473 //interpenetrations_before_disable = 200;
474 //if (op1.m_interpenetrationcount >= interpenetrations_before_disable)
475 //{
476 //op1.m_taintdisable = true;
477 //AddPhysicsActorTaint(p1);
478 //}
479 //if (op2.m_interpenetrationcount >= interpenetrations_before_disable)
480 //{
481 // op2.m_taintdisable = true;
482 //AddPhysicsActorTaint(p2);
483 //}
403 484
404 if (contacts[i].depth >= 0.08f) 485
486 //contacts[i].depth = contacts[i].depth / 8f;
487 //contacts[i].normal = new d.Vector3(0, 0, 1);
488 //}
489 //if (op1.m_disabled || op2.m_disabled)
490 //{
491 //Manually disabled objects stay disabled
492 //contacts[i].depth = 0f;
493 //}
494 #endregion
495 }
496 if (contacts[i].depth >= 1.00f)
405 { 497 {
406 //This is disabled at the moment only because it needs more tweaking 498 //m_log.Info("[P]: " + contacts[i].depth.ToString());
407 //It will eventually be uncommented
408
409 if (contacts[i].depth >= 1.00f)
410 {
411 //m_log.Debug("[PHYSICS]: " + contacts[i].depth.ToString());
412 }
413
414 //If you interpenetrate a prim with an agent
415 if ((p2.PhysicsActorType == (int) ActorTypes.Agent && 499 if ((p2.PhysicsActorType == (int) ActorTypes.Agent &&
416 p1.PhysicsActorType == (int) ActorTypes.Prim) || 500 p1.PhysicsActorType == (int) ActorTypes.Unknown) ||
417 (p1.PhysicsActorType == (int) ActorTypes.Agent && 501 (p1.PhysicsActorType == (int) ActorTypes.Agent &&
418 p2.PhysicsActorType == (int) ActorTypes.Prim)) 502 p2.PhysicsActorType == (int) ActorTypes.Unknown))
419 { 503 {
420 //contacts[i].depth = contacts[i].depth * 4.15f;
421 /*
422 if (p2.PhysicsActorType == (int) ActorTypes.Agent) 504 if (p2.PhysicsActorType == (int) ActorTypes.Agent)
423 { 505 {
424 p2.CollidingObj = true;
425 contacts[i].depth = 0.003f;
426 p2.Velocity = p2.Velocity + new PhysicsVector(0, 0, 2.5f);
427 OdeCharacter character = (OdeCharacter) p2; 506 OdeCharacter character = (OdeCharacter) p2;
507
508 //p2.CollidingObj = true;
509 contacts[i].depth = 0.00000003f;
510 p2.Velocity = p2.Velocity + new PhysicsVector(0, 0, 0.5f);
511 contacts[i].pos =
512 new d.Vector3(contacts[i].pos.X + (p1.Size.X/2),
513 contacts[i].pos.Y + (p1.Size.Y/2),
514 contacts[i].pos.Z + (p1.Size.Z/2));
428 character.SetPidStatus(true); 515 character.SetPidStatus(true);
429 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));
430
431 } 516 }
432 else 517 else
433 { 518 {
434
435 //contacts[i].depth = 0.0000000f;
436 } 519 }
437 if (p1.PhysicsActorType == (int) ActorTypes.Agent) 520 if (p1.PhysicsActorType == (int) ActorTypes.Agent)
438 { 521 {
439
440 p1.CollidingObj = true;
441 contacts[i].depth = 0.003f;
442 p1.Velocity = p1.Velocity + new PhysicsVector(0, 0, 2.5f);
443 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));
444 OdeCharacter character = (OdeCharacter)p1; 522 OdeCharacter character = (OdeCharacter)p1;
523
524 //p2.CollidingObj = true;
525 contacts[i].depth = 0.00000003f;
526 p1.Velocity = p1.Velocity + new PhysicsVector(0, 0, 0.5f);
527 contacts[i].pos =
528 new d.Vector3(contacts[i].pos.X + (p1.Size.X/2),
529 contacts[i].pos.Y + (p1.Size.Y/2),
530 contacts[i].pos.Z + (p1.Size.Z/2));
445 character.SetPidStatus(true); 531 character.SetPidStatus(true);
446 } 532 }
447 else 533 else
448 { 534 {
449
450 //contacts[i].depth = 0.0000000f; 535 //contacts[i].depth = 0.0000000f;
451 } 536 }
452 */
453 } 537 }
454 538 }
539 }
455 540
456 // If you interpenetrate a prim with another prim 541 #endregion
457 if (p1.PhysicsActorType == (int) ActorTypes.Prim && p2.PhysicsActorType == (int) ActorTypes.Prim)
458 {
459 //OdePrim op1 = (OdePrim)p1;
460 //OdePrim op2 = (OdePrim)p2;
461 //op1.m_collisionscore++;
462 //op2.m_collisionscore++;
463
464 542
465 //if (op1.m_collisionscore > 8000 || op2.m_collisionscore > 8000) 543 if (contacts[i].depth >= 0f)
466 //{ 544 {
467 //op1.m_taintdisable = true; 545 // If we're collidng against terrain
468 //AddPhysicsActorTaint(p1); 546 if (name1 == "Terrain" || name2 == "Terrain")
469 //op2.m_taintdisable = true; 547 {
470 //AddPhysicsActorTaint(p2); 548 // If we're moving
471 //} 549 if ((p2.PhysicsActorType == (int) ActorTypes.Agent) &&
472 550 (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f))
473 //if (contacts[i].depth >= 0.25f) 551 {
474 //{ 552 // Use the movement terrain contact
475 // Don't collide, one or both prim will expld. 553 AvatarMovementTerrainContact.geom = contacts[i];
476 554 joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementTerrainContact);
477
478 //op1.m_interpenetrationcount++;
479 //op2.m_interpenetrationcount++;
480 //interpenetrations_before_disable = 200;
481 //if (op1.m_interpenetrationcount >= interpenetrations_before_disable)
482 //{
483 //op1.m_taintdisable = true;
484 //AddPhysicsActorTaint(p1);
485 //}
486 //if (op2.m_interpenetrationcount >= interpenetrations_before_disable)
487 //{
488 // op2.m_taintdisable = true;
489 //AddPhysicsActorTaint(p2);
490 //}
491
492
493 //contacts[i].depth = contacts[i].depth / 8f;
494 //contacts[i].normal = new d.Vector3(0, 0, 1);
495 //}
496 //if (op1.m_disabled || op2.m_disabled)
497 //{
498 //Manually disabled objects stay disabled
499 //contacts[i].depth = 0f;
500 //}
501 } 555 }
502 if (contacts[i].depth >= 1.00f) 556 else
503 { 557 {
504 //m_log.Info("[P]: " + contacts[i].depth.ToString()); 558 // Use the non moving terrain contact
505 if ((p2.PhysicsActorType == (int) ActorTypes.Agent && 559 TerrainContact.geom = contacts[i];
506 p1.PhysicsActorType == (int) ActorTypes.Unknown) || 560 joint = d.JointCreateContact(world, contactgroup, ref TerrainContact);
507 (p1.PhysicsActorType == (int) ActorTypes.Agent &&
508 p2.PhysicsActorType == (int) ActorTypes.Unknown))
509 {
510 if (p2.PhysicsActorType == (int) ActorTypes.Agent)
511 {
512 OdeCharacter character = (OdeCharacter) p2;
513
514 //p2.CollidingObj = true;
515 contacts[i].depth = 0.00000003f;
516 p2.Velocity = p2.Velocity + new PhysicsVector(0, 0, 0.5f);
517 contacts[i].pos =
518 new d.Vector3(contacts[i].pos.X + (p1.Size.X/2),
519 contacts[i].pos.Y + (p1.Size.Y/2),
520 contacts[i].pos.Z + (p1.Size.Z/2));
521 character.SetPidStatus(true);
522 }
523 else
524 {
525 }
526 if (p1.PhysicsActorType == (int) ActorTypes.Agent)
527 {
528 OdeCharacter character = (OdeCharacter)p1;
529
530 //p2.CollidingObj = true;
531 contacts[i].depth = 0.00000003f;
532 p1.Velocity = p1.Velocity + new PhysicsVector(0, 0, 0.5f);
533 contacts[i].pos =
534 new d.Vector3(contacts[i].pos.X + (p1.Size.X/2),
535 contacts[i].pos.Y + (p1.Size.Y/2),
536 contacts[i].pos.Z + (p1.Size.Z/2));
537 character.SetPidStatus(true);
538 }
539 else
540 {
541 //contacts[i].depth = 0.0000000f;
542 }
543 }
544 } 561 }
545 } 562 }
546 563 else
547 #endregion
548
549 if (contacts[i].depth >= 0f)
550 { 564 {
551 // If we're collidng against terrain 565 // we're colliding with prim or avatar
552 if (name1 == "Terrain" || name2 == "Terrain") 566
567 // check if we're moving
568 if ((p2.PhysicsActorType == (int) ActorTypes.Agent) &&
569 (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f))
553 { 570 {
554 // If we're moving 571 // Use the Movement prim contact
555 if ((p2.PhysicsActorType == (int) ActorTypes.Agent) && 572 AvatarMovementprimContact.geom = contacts[i];
556 (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f)) 573 joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementprimContact);
557 {
558 // Use the movement terrain contact
559 AvatarMovementTerrainContact.geom = contacts[i];
560 joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementTerrainContact);
561 }
562 else
563 {
564 // Use the non moving terrain contact
565 TerrainContact.geom = contacts[i];
566 joint = d.JointCreateContact(world, contactgroup, ref TerrainContact);
567 }
568 } 574 }
569 else 575 else
570 { 576 {
571 // we're colliding with prim or avatar 577 // Use the non movement contact
572 578 contact.geom = contacts[i];
573 // check if we're moving 579 joint = d.JointCreateContact(world, contactgroup, ref contact);
574 if ((p2.PhysicsActorType == (int) ActorTypes.Agent) &&
575 (Math.Abs(p2.Velocity.X) > 0.01f || Math.Abs(p2.Velocity.Y) > 0.01f))
576 {
577 // Use the Movement prim contact
578 AvatarMovementprimContact.geom = contacts[i];
579 joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementprimContact);
580 }
581 else
582 {
583 // Use the non movement contact
584 contact.geom = contacts[i];
585 joint = d.JointCreateContact(world, contactgroup, ref contact);
586 }
587 } 580 }
588 d.JointAttach(joint, b1, b2);
589 } 581 }
582 d.JointAttach(joint, b1, b2);
583 }
590 584
591 if (count > 3) 585 if (count > 3)
592 { 586 {
593 // If there are more then 3 contact points, it's likely 587 // If there are more then 3 contact points, it's likely
594 // that we've got a pile of objects 588 // that we've got a pile of objects
595 // 589 //
596 // We don't want to send out hundreds of terse updates over and over again 590 // We don't want to send out hundreds of terse updates over and over again
597 // so lets throttle them and send them again after it's somewhat sorted out. 591 // so lets throttle them and send them again after it's somewhat sorted out.
598 p2.ThrottleUpdates = true; 592 p2.ThrottleUpdates = true;
599 }
600 //System.Console.WriteLine(count.ToString());
601 //System.Console.WriteLine("near: A collision was detected between {1} and {2}", 0, name1, name2);
602 } 593 }
594 //System.Console.WriteLine(count.ToString());
595 //System.Console.WriteLine("near: A collision was detected between {1} and {2}", 0, name1, name2);
603 } 596 }
597
604 } 598 }
605 private float GetTerrainHeightAtXY(float x, float y) 599
600 public int TriArrayCallback(IntPtr trimesh, IntPtr refObject, int[] triangleIndex, int triCount)
606 { 601 {
607 return (float)_origheightmap[(int)y * Constants.RegionSize + (int)x]; 602 /* String name1 = null;
608 603 String name2 = null;
609 604
605 if (!geom_name_map.TryGetValue(trimesh, out name1))
606 {
607 name1 = "null";
608 }
609 if (!geom_name_map.TryGetValue(refObject, out name2))
610 {
611 name2 = "null";
612 }
613
614 m_log.InfoFormat("TriArrayCallback: A collision was detected between {1} and {2}", 0, name1, name2);
615 */
616 return 1;
617 }
618
619 public int TriCallback(IntPtr trimesh, IntPtr refObject, int triangleIndex)
620 {
621 String name1 = null;
622 String name2 = null;
623
624 if (!geom_name_map.TryGetValue(trimesh, out name1))
625 {
626 name1 = "null";
627 }
628
629 if (!geom_name_map.TryGetValue(refObject, out name2))
630 {
631 name2 = "null";
632 }
633
634 // m_log.InfoFormat("TriCallback: A collision was detected between {1} and {2}. Index was {3}", 0, name1, name2, triangleIndex);
635
636 d.Vector3 v0 = new d.Vector3();
637 d.Vector3 v1 = new d.Vector3();
638 d.Vector3 v2 = new d.Vector3();
639
640 d.GeomTriMeshGetTriangle(trimesh, 0, ref v0, ref v1, ref v2);
641 // m_log.DebugFormat("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);
642
643 return 1;
610 } 644 }
611 645
612 /// <summary> 646 /// <summary>
@@ -715,6 +749,17 @@ namespace OpenSim.Region.Physics.OdePlugin
715 } 749 }
716 } 750 }
717 751
752 #endregion
753
754 private float GetTerrainHeightAtXY(float x, float y)
755 {
756 return (float)_origheightmap[(int)y * Constants.RegionSize + (int)x];
757
758
759 }
760
761 #region Add/Remove Entities
762
718 public override PhysicsActor AddAvatar(string avName, PhysicsVector position, PhysicsVector size) 763 public override PhysicsActor AddAvatar(string avName, PhysicsVector position, PhysicsVector size)
719 { 764 {
720 PhysicsVector pos = new PhysicsVector(); 765 PhysicsVector pos = new PhysicsVector();
@@ -735,6 +780,80 @@ namespace OpenSim.Region.Physics.OdePlugin
735 } 780 }
736 } 781 }
737 782
783 private PhysicsActor AddPrim(String name, PhysicsVector position, PhysicsVector size, Quaternion rotation,
784 IMesh mesh, PrimitiveBaseShape pbs, bool isphysical)
785 {
786 PhysicsVector pos = new PhysicsVector();
787 pos.X = position.X;
788 pos.Y = position.Y;
789 pos.Z = position.Z;
790 PhysicsVector siz = new PhysicsVector();
791 siz.X = size.X;
792 siz.Y = size.Y;
793 siz.Z = size.Z;
794 Quaternion rot = new Quaternion();
795 rot.w = rotation.w;
796 rot.x = rotation.x;
797 rot.y = rotation.y;
798 rot.z = rotation.z;
799
800
801
802 OdePrim newPrim;
803 lock (OdeLock)
804 {
805 newPrim = new OdePrim(name, this, pos, siz, rot, mesh, pbs, isphysical, ode);
806
807 _prims.Add(newPrim);
808 }
809
810
811 return newPrim;
812 }
813
814 public void addActivePrim(OdePrim activatePrim)
815 {
816 // adds active prim.. (ones that should be iterated over in collisions_optimized
817
818 _activeprims.Add(activatePrim);
819 }
820
821 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position,
822 PhysicsVector size, Quaternion rotation) //To be removed
823 {
824 return AddPrimShape(primName, pbs, position, size, rotation, false);
825 }
826
827 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position,
828 PhysicsVector size, Quaternion rotation, bool isPhysical)
829 {
830 PhysicsActor result;
831 IMesh mesh = null;
832
833 switch (pbs.ProfileShape)
834 {
835 case ProfileShape.Square:
836 /// support simple box & hollow box now; later, more shapes
837 if (needsMeshing(pbs))
838 {
839 mesh = mesher.CreateMesh(primName, pbs, size);
840 }
841
842 break;
843 }
844
845 result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical);
846
847
848 return result;
849 }
850
851
852 public void remActivePrim(OdePrim deactivatePrim)
853 {
854 _activeprims.Remove(deactivatePrim);
855 }
856
738 public override void RemovePrim(PhysicsActor prim) 857 public override void RemovePrim(PhysicsActor prim)
739 { 858 {
740 if (prim is OdePrim) 859 if (prim is OdePrim)
@@ -767,10 +886,8 @@ namespace OpenSim.Region.Physics.OdePlugin
767 { 886 {
768 if (prim.prim_geom != (IntPtr)0) 887 if (prim.prim_geom != (IntPtr)0)
769 { 888 {
770 while (ode.lockquery()) 889
771 { 890
772 }
773 ode.dlock(world);
774 //System.Threading.Thread.Sleep(20); 891 //System.Threading.Thread.Sleep(20);
775 prim.ResetTaints(); 892 prim.ResetTaints();
776 893
@@ -846,11 +963,15 @@ namespace OpenSim.Region.Physics.OdePlugin
846 //} 963 //}
847 } 964 }
848 965
849 ode.dunlock(world); 966
850 } 967 }
851 } 968 }
852 } 969 }
853 970
971 #endregion
972
973 #region Space Separation Calculation
974
854 /// <summary> 975 /// <summary>
855 /// Takes a space pointer and zeros out the array we're using to hold the spaces 976 /// Takes a space pointer and zeros out the array we're using to hold the spaces
856 /// </summary> 977 /// </summary>
@@ -1065,95 +1186,10 @@ namespace OpenSim.Region.Physics.OdePlugin
1065 1186
1066 return returnint; 1187 return returnint;
1067 } 1188 }
1189 #endregion
1068 1190
1069 private PhysicsActor AddPrim(String name, PhysicsVector position, PhysicsVector size, Quaternion rotation,
1070 IMesh mesh, PrimitiveBaseShape pbs, bool isphysical)
1071 {
1072 PhysicsVector pos = new PhysicsVector();
1073 pos.X = position.X;
1074 pos.Y = position.Y;
1075 pos.Z = position.Z;
1076 PhysicsVector siz = new PhysicsVector();
1077 siz.X = size.X;
1078 siz.Y = size.Y;
1079 siz.Z = size.Z;
1080 Quaternion rot = new Quaternion();
1081 rot.w = rotation.w;
1082 rot.x = rotation.x;
1083 rot.y = rotation.y;
1084 rot.z = rotation.z;
1085
1086
1087
1088 OdePrim newPrim;
1089 lock (OdeLock)
1090 {
1091 newPrim = new OdePrim(name, this, pos, siz, rot, mesh, pbs, isphysical, ode);
1092
1093 _prims.Add(newPrim);
1094 }
1095
1096
1097 return newPrim;
1098 }
1099
1100 public void addActivePrim(OdePrim activatePrim)
1101 {
1102 // adds active prim.. (ones that should be iterated over in collisions_optimized
1103
1104 _activeprims.Add(activatePrim);
1105 }
1106
1107 public void remActivePrim(OdePrim deactivatePrim)
1108 {
1109 _activeprims.Remove(deactivatePrim);
1110 }
1111
1112 public int TriArrayCallback(IntPtr trimesh, IntPtr refObject, int[] triangleIndex, int triCount)
1113 {
1114/* String name1 = null;
1115 String name2 = null;
1116
1117 if (!geom_name_map.TryGetValue(trimesh, out name1))
1118 {
1119 name1 = "null";
1120 }
1121 if (!geom_name_map.TryGetValue(refObject, out name2))
1122 {
1123 name2 = "null";
1124 }
1125
1126 m_log.InfoFormat("TriArrayCallback: A collision was detected between {1} and {2}", 0, name1, name2);
1127*/
1128 return 1;
1129 }
1130
1131 public int TriCallback(IntPtr trimesh, IntPtr refObject, int triangleIndex)
1132 {
1133 String name1 = null;
1134 String name2 = null;
1135
1136 if (!geom_name_map.TryGetValue(trimesh, out name1))
1137 {
1138 name1 = "null";
1139 }
1140
1141 if (!geom_name_map.TryGetValue(refObject, out name2))
1142 {
1143 name2 = "null";
1144 }
1145
1146// m_log.InfoFormat("TriCallback: A collision was detected between {1} and {2}. Index was {3}", 0, name1, name2, triangleIndex);
1147
1148 d.Vector3 v0 = new d.Vector3();
1149 d.Vector3 v1 = new d.Vector3();
1150 d.Vector3 v2 = new d.Vector3();
1151 1191
1152 d.GeomTriMeshGetTriangle(trimesh, 0, ref v0, ref v1, ref v2);
1153// m_log.DebugFormat("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);
1154 1192
1155 return 1;
1156 }
1157 1193
1158 /// <summary> 1194 /// <summary>
1159 /// Routine to figure out if we need to mesh this prim with our mesher 1195 /// Routine to figure out if we need to mesh this prim with our mesher
@@ -1183,36 +1219,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1183 return false; 1219 return false;
1184 } 1220 }
1185 1221
1186 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position, 1222
1187 PhysicsVector size, Quaternion rotation) //To be removed
1188 {
1189 return AddPrimShape(primName, pbs, position, size, rotation, false);
1190 }
1191
1192 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, PhysicsVector position,
1193 PhysicsVector size, Quaternion rotation, bool isPhysical)
1194 {
1195 PhysicsActor result;
1196 IMesh mesh = null;
1197
1198 switch (pbs.ProfileShape)
1199 {
1200 case ProfileShape.Square:
1201 /// support simple box & hollow box now; later, more shapes
1202 if (needsMeshing(pbs))
1203 {
1204 mesh = mesher.CreateMesh(primName, pbs, size);
1205 }
1206
1207 break;
1208 }
1209
1210 result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical);
1211
1212
1213 return result;
1214 }
1215
1216 /// <summary> 1223 /// <summary>
1217 /// Called after our prim properties are set Scale, position etc. 1224 /// Called after our prim properties are set Scale, position etc.
1218 /// We use this event queue like method to keep changes to the physical scene occuring in the threadlocked mutex 1225 /// We use this event queue like method to keep changes to the physical scene occuring in the threadlocked mutex
@@ -1224,8 +1231,11 @@ namespace OpenSim.Region.Physics.OdePlugin
1224 if (prim is OdePrim) 1231 if (prim is OdePrim)
1225 { 1232 {
1226 OdePrim taintedprim = ((OdePrim) prim); 1233 OdePrim taintedprim = ((OdePrim) prim);
1227 if (!(_taintedPrim.Contains(taintedprim))) 1234 lock (_taintedPrim)
1228 _taintedPrim.Add(taintedprim); 1235 {
1236 if (!(_taintedPrim.Contains(taintedprim)))
1237 _taintedPrim.Add(taintedprim);
1238 }
1229 } 1239 }
1230 } 1240 }
1231 1241
@@ -1292,12 +1302,50 @@ namespace OpenSim.Region.Physics.OdePlugin
1292 ode.dlock(world); 1302 ode.dlock(world);
1293 try 1303 try
1294 { 1304 {
1295 foreach (OdeCharacter actor in _characters) 1305 lock (_characters)
1296 { 1306 {
1297 if (actor != null) 1307 foreach (OdeCharacter actor in _characters)
1298 actor.Move(timeStep); 1308 {
1309 if (actor != null)
1310 actor.Move(timeStep);
1311 }
1299 } 1312 }
1300 1313
1314
1315 bool processedtaints = false;
1316
1317 lock (_taintedPrim)
1318 {
1319 foreach (OdePrim prim in _taintedPrim)
1320 {
1321 if (prim.m_taintremove)
1322 {
1323 RemovePrimThreadLocked(prim);
1324 }
1325
1326 prim.ProcessTaints(timeStep);
1327
1328 processedtaints = true;
1329 prim.m_collisionscore = 0;
1330 }
1331
1332 if (processedtaints)
1333 _taintedPrim = new List<OdePrim>();
1334
1335 }
1336
1337 lock (_activeprims)
1338 {
1339 foreach (OdePrim prim in _activeprims)
1340 {
1341 prim.m_collisionscore = 0;
1342 }
1343 }
1344
1345
1346
1347
1348
1301 collision_optimized(timeStep); 1349 collision_optimized(timeStep);
1302 1350
1303 d.WorldQuickStep(world, ODE_STEPSIZE); 1351 d.WorldQuickStep(world, ODE_STEPSIZE);
@@ -1321,47 +1369,29 @@ namespace OpenSim.Region.Physics.OdePlugin
1321 } 1369 }
1322 } 1370 }
1323 1371
1324 foreach (OdeCharacter actor in _characters) 1372 lock (_characters)
1325 {
1326 if (actor != null)
1327 actor.UpdatePositionAndVelocity();
1328 }
1329
1330 if (!ode.lockquery())
1331 {
1332 bool processedtaints = false;
1333 foreach (OdePrim prim in _taintedPrim)
1334 {
1335 if (prim.m_taintremove)
1336 {
1337 RemovePrimThreadLocked(prim);
1338 }
1339
1340 prim.ProcessTaints(timeStep);
1341
1342 processedtaints = true;
1343 prim.m_collisionscore = 0;
1344 }
1345 if (processedtaints)
1346 _taintedPrim = new List<OdePrim>();
1347 }
1348 foreach (OdePrim prim in _activeprims)
1349 { 1373 {
1350 prim.m_collisionscore = 0; 1374 foreach (OdeCharacter actor in _characters)
1375 {
1376 if (actor != null)
1377 actor.UpdatePositionAndVelocity();
1378 }
1351 } 1379 }
1352 1380
1353 1381 lock (_activeprims)
1354
1355 if (timeStep < 0.2f)
1356 { 1382 {
1357 foreach (OdePrim actor in _activeprims) 1383 if (timeStep < 0.2f)
1358 { 1384 {
1359 if (actor.IsPhysical && (d.BodyIsEnabled(actor.Body) || !actor._zeroFlag)) 1385 foreach (OdePrim actor in _activeprims)
1360 { 1386 {
1361 actor.UpdatePositionAndVelocity(); 1387 if (actor.IsPhysical && (d.BodyIsEnabled(actor.Body) || !actor._zeroFlag))
1388 {
1389 actor.UpdatePositionAndVelocity();
1390 }
1362 } 1391 }
1363 } 1392 }
1364 } 1393 }
1394
1365 } 1395 }
1366 return fps; 1396 return fps;
1367 } 1397 }
@@ -1375,6 +1405,8 @@ namespace OpenSim.Region.Physics.OdePlugin
1375 // for now we won't be multithreaded 1405 // for now we won't be multithreaded
1376 get { return (false); } 1406 get { return (false); }
1377 } 1407 }
1408
1409 #region ODE Specific Terrain Fixes
1378 public float[] ResizeTerrain512NearestNeighbour(float[] heightMap) 1410 public float[] ResizeTerrain512NearestNeighbour(float[] heightMap)
1379 { 1411 {
1380 float[] returnarr = new float[262144]; 1412 float[] returnarr = new float[262144];
@@ -1637,11 +1669,12 @@ namespace OpenSim.Region.Physics.OdePlugin
1637 return returnarr; 1669 return returnarr;
1638 } 1670 }
1639 1671
1672 #endregion
1673
1640 public override void SetTerrain(float[] heightMap) 1674 public override void SetTerrain(float[] heightMap)
1641 { 1675 {
1642 // this._heightmap[i] = (double)heightMap[i]; 1676 // this._heightmap[i] = (double)heightMap[i];
1643 // dbm (danx0r) -- heightmap x,y must be swapped for Ode (should fix ODE, but for now...) 1677 // dbm (danx0r) -- creating a buffer zone of one extra sample all around
1644 // also, creating a buffer zone of one extra sample all around
1645 _origheightmap = heightMap; 1678 _origheightmap = heightMap;
1646 const uint heightmapWidth = m_regionWidth + 2; 1679 const uint heightmapWidth = m_regionWidth + 2;
1647 const uint heightmapHeight = m_regionHeight + 2; 1680 const uint heightmapHeight = m_regionHeight + 2;
@@ -1654,6 +1687,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1654 1687
1655 //Double resolution 1688 //Double resolution
1656 heightMap = ResizeTerrain512Interpolation(heightMap); 1689 heightMap = ResizeTerrain512Interpolation(heightMap);
1690
1657 for (int x = 0; x < heightmapWidthSamples; x++) 1691 for (int x = 0; x < heightmapWidthSamples; x++)
1658 { 1692 {
1659 for (int y = 0; y < heightmapHeightSamples; y++) 1693 for (int y = 0; y < heightmapHeightSamples; y++)