aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics')
-rw-r--r--OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs12
-rw-r--r--OpenSim/Region/Physics/Manager/PhysicsScene.cs4
-rw-r--r--OpenSim/Region/Physics/Meshing/Meshmerizer.cs641
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODECharacter.cs10
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODEPrim.cs279
-rw-r--r--OpenSim/Region/Physics/OdePlugin/OdeScene.cs799
6 files changed, 924 insertions, 821 deletions
diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs
index 6c9d9ab..1ceed1a 100644
--- a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs
+++ b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsScene.cs
@@ -123,11 +123,15 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
123 actorPosition.X = ((int)Constants.RegionSize - 0.1f); 123 actorPosition.X = ((int)Constants.RegionSize - 0.1f);
124 } 124 }
125 125
126 float height = _heightMap[(int)actor.Position.Y * Constants.RegionSize + (int)actor.Position.X] + actor.Size.Z; 126 float terrainHeight = 0;
127 if (_heightMap != null)
128 terrainHeight = _heightMap[(int)actor.Position.Y * Constants.RegionSize + (int)actor.Position.X];
129
130 float height = terrainHeight + actor.Size.Z;
131
127 if (actor.Flying) 132 if (actor.Flying)
128 { 133 {
129 if (actor.Position.Z + (actor.Velocity.Z*timeStep) < 134 if (actor.Position.Z + (actor.Velocity.Z * timeStep) < terrainHeight + 2)
130 _heightMap[(int)actor.Position.Y * Constants.RegionSize + (int)actor.Position.X] + 2)
131 { 135 {
132 actorPosition.Z = height; 136 actorPosition.Z = height;
133 actorVelocity.Z = 0; 137 actorVelocity.Z = 0;
@@ -135,7 +139,7 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
135 } 139 }
136 else 140 else
137 { 141 {
138 actorPosition.Z += actor.Velocity.Z*timeStep; 142 actorPosition.Z += actor.Velocity.Z * timeStep;
139 actor.IsColliding = false; 143 actor.IsColliding = false;
140 } 144 }
141 } 145 }
diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
index 3870411..04efc1d 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
@@ -86,6 +86,10 @@ namespace OpenSim.Region.Physics.Manager
86 86
87 public abstract void RemoveAvatar(PhysicsActor actor); 87 public abstract void RemoveAvatar(PhysicsActor actor);
88 88
89 /// <summary>
90 /// Remove a prim from the physics scene.
91 /// </summary>
92 /// <param name="prim"></param>
89 public abstract void RemovePrim(PhysicsActor prim); 93 public abstract void RemovePrim(PhysicsActor prim);
90 94
91 public abstract PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, 95 public abstract PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
index 5413aa8..e81b982 100644
--- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
+++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
@@ -301,20 +301,22 @@ namespace OpenSim.Region.Physics.Meshing
301 } 301 }
302 } 302 }
303 303
304 /// <summary>
305 /// Create a physics mesh from data that comes with the prim. The actual data used depends on the prim type.
306 /// </summary>
307 /// <param name="primName"></param>
308 /// <param name="primShape"></param>
309 /// <param name="size"></param>
310 /// <param name="lod"></param>
311 /// <returns></returns>
304 private Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, Vector3 size, float lod) 312 private Mesh CreateMeshFromPrimMesher(string primName, PrimitiveBaseShape primShape, Vector3 size, float lod)
305 { 313 {
306// m_log.DebugFormat( 314// m_log.DebugFormat(
307// "[MESH]: Creating physics proxy for {0}, shape {1}", 315// "[MESH]: Creating physics proxy for {0}, shape {1}",
308// primName, (OpenMetaverse.SculptType)primShape.SculptType); 316// primName, (OpenMetaverse.SculptType)primShape.SculptType);
309 317
310 PrimMesh primMesh; 318 List<Coord> coords;
311 PrimMesher.SculptMesh sculptMesh; 319 List<Face> faces;
312
313 List<Coord> coords = new List<Coord>();
314 List<Face> faces = new List<Face>();
315
316 Image idata = null;
317 string decodedSculptFileName = "";
318 320
319 if (primShape.SculptEntry) 321 if (primShape.SculptEntry)
320 { 322 {
@@ -323,337 +325,414 @@ namespace OpenSim.Region.Physics.Meshing
323 if (!useMeshiesPhysicsMesh) 325 if (!useMeshiesPhysicsMesh)
324 return null; 326 return null;
325 327
326 m_log.DebugFormat("[MESH]: experimental mesh proxy generation for {0}", primName); 328 if (!GenerateCoordsAndFacesFromPrimMeshData(primName, primShape, size, out coords, out faces))
329 return null;
330 }
331 else
332 {
333 if (!GenerateCoordsAndFacesFromPrimSculptData(primName, primShape, size, lod, out coords, out faces))
334 return null;
335 }
336 }
337 else
338 {
339 if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, size, out coords, out faces))
340 return null;
341 }
327 342
328 OSD meshOsd = null; 343 // Remove the reference to any JPEG2000 sculpt data so it can be GCed
344 primShape.SculptData = Utils.EmptyBytes;
329 345
330 if (primShape.SculptData.Length <= 0) 346 int numCoords = coords.Count;
331 { 347 int numFaces = faces.Count;
332 m_log.Error("[MESH]: asset data is zero length");
333 return null;
334 }
335 348
336 long start = 0; 349 // Create the list of vertices
337 using (MemoryStream data = new MemoryStream(primShape.SculptData)) 350 List<Vertex> vertices = new List<Vertex>();
338 { 351 for (int i = 0; i < numCoords; i++)
339 try 352 {
340 { 353 Coord c = coords[i];
341 OSD osd = OSDParser.DeserializeLLSDBinary(data); 354 vertices.Add(new Vertex(c.X, c.Y, c.Z));
342 if (osd is OSDMap) 355 }
343 meshOsd = (OSDMap)osd;
344 else
345 {
346 m_log.Warn("[Mesh}: unable to cast mesh asset to OSDMap");
347 return null;
348 }
349 }
350 catch (Exception e)
351 {
352 m_log.Error("[MESH]: Exception deserializing mesh asset header:" + e.ToString());
353 }
354 356
355 start = data.Position; 357 Mesh mesh = new Mesh();
356 } 358 // Add the corresponding triangles to the mesh
359 for (int i = 0; i < numFaces; i++)
360 {
361 Face f = faces[i];
362 mesh.Add(new Triangle(vertices[f.v1], vertices[f.v2], vertices[f.v3]));
363 }
364
365 return mesh;
366 }
357 367
358 if (meshOsd is OSDMap) 368 /// <summary>
369 /// Generate the co-ords and faces necessary to construct a mesh from the mesh data the accompanies a prim.
370 /// </summary>
371 /// <param name="primName"></param>
372 /// <param name="primShape"></param>
373 /// <param name="size"></param>
374 /// <param name="coords">Coords are added to this list by the method.</param>
375 /// <param name="faces">Faces are added to this list by the method.</param>
376 /// <returns>true if coords and faces were successfully generated, false if not</returns>
377 private bool GenerateCoordsAndFacesFromPrimMeshData(
378 string primName, PrimitiveBaseShape primShape, Vector3 size, out List<Coord> coords, out List<Face> faces)
379 {
380 m_log.DebugFormat("[MESH]: experimental mesh proxy generation for {0}", primName);
381
382 coords = new List<Coord>();
383 faces = new List<Face>();
384 OSD meshOsd = null;
385
386 if (primShape.SculptData.Length <= 0)
387 {
388 m_log.Error("[MESH]: asset data is zero length");
389 return false;
390 }
391
392 long start = 0;
393 using (MemoryStream data = new MemoryStream(primShape.SculptData))
394 {
395 try
396 {
397 OSD osd = OSDParser.DeserializeLLSDBinary(data);
398 if (osd is OSDMap)
399 meshOsd = (OSDMap)osd;
400 else
359 { 401 {
360 OSDMap physicsParms = null; 402 m_log.Warn("[Mesh}: unable to cast mesh asset to OSDMap");
361 OSDMap map = (OSDMap)meshOsd; 403 return false;
362 if (map.ContainsKey("physics_shape")) 404 }
363 physicsParms = (OSDMap)map["physics_shape"]; // old asset format 405 }
364 else if (map.ContainsKey("physics_mesh")) 406 catch (Exception e)
365 physicsParms = (OSDMap)map["physics_mesh"]; // new asset format 407 {
366 408 m_log.Error("[MESH]: Exception deserializing mesh asset header:" + e.ToString());
367 if (physicsParms == null) 409 }
368 { 410
369 m_log.Warn("[MESH]: no recognized physics mesh found in mesh asset"); 411 start = data.Position;
370 return null; 412 }
371 }
372 413
373 int physOffset = physicsParms["offset"].AsInteger() + (int)start; 414 if (meshOsd is OSDMap)
374 int physSize = physicsParms["size"].AsInteger(); 415 {
416 OSDMap physicsParms = null;
417 OSDMap map = (OSDMap)meshOsd;
418 if (map.ContainsKey("physics_shape"))
419 physicsParms = (OSDMap)map["physics_shape"]; // old asset format
420 else if (map.ContainsKey("physics_mesh"))
421 physicsParms = (OSDMap)map["physics_mesh"]; // new asset format
422
423 if (physicsParms == null)
424 {
425 m_log.Warn("[MESH]: no recognized physics mesh found in mesh asset");
426 return false;
427 }
375 428
376 if (physOffset < 0 || physSize == 0) 429 int physOffset = physicsParms["offset"].AsInteger() + (int)start;
377 return null; // no mesh data in asset 430 int physSize = physicsParms["size"].AsInteger();
378 431
379 OSD decodedMeshOsd = new OSD(); 432 if (physOffset < 0 || physSize == 0)
380 byte[] meshBytes = new byte[physSize]; 433 return false; // no mesh data in asset
381 System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize); 434
435 OSD decodedMeshOsd = new OSD();
436 byte[] meshBytes = new byte[physSize];
437 System.Buffer.BlockCopy(primShape.SculptData, physOffset, meshBytes, 0, physSize);
382// byte[] decompressed = new byte[physSize * 5]; 438// byte[] decompressed = new byte[physSize * 5];
383 try 439 try
440 {
441 using (MemoryStream inMs = new MemoryStream(meshBytes))
442 {
443 using (MemoryStream outMs = new MemoryStream())
384 { 444 {
385 using (MemoryStream inMs = new MemoryStream(meshBytes)) 445 using (ZOutputStream zOut = new ZOutputStream(outMs))
386 { 446 {
387 using (MemoryStream outMs = new MemoryStream()) 447 byte[] readBuffer = new byte[2048];
448 int readLen = 0;
449 while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0)
388 { 450 {
389 using (ZOutputStream zOut = new ZOutputStream(outMs)) 451 zOut.Write(readBuffer, 0, readLen);
390 {
391 byte[] readBuffer = new byte[2048];
392 int readLen = 0;
393 while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0)
394 {
395 zOut.Write(readBuffer, 0, readLen);
396 }
397 zOut.Flush();
398 outMs.Seek(0, SeekOrigin.Begin);
399
400 byte[] decompressedBuf = outMs.GetBuffer();
401
402 decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf);
403 }
404 } 452 }
453 zOut.Flush();
454 outMs.Seek(0, SeekOrigin.Begin);
455
456 byte[] decompressedBuf = outMs.GetBuffer();
457
458 decodedMeshOsd = OSDParser.DeserializeLLSDBinary(decompressedBuf);
405 } 459 }
406 } 460 }
407 catch (Exception e) 461 }
408 { 462 }
409 m_log.Error("[MESH]: exception decoding physical mesh: " + e.ToString()); 463 catch (Exception e)
410 return null; 464 {
411 } 465 m_log.Error("[MESH]: exception decoding physical mesh: " + e.ToString());
466 return false;
467 }
412 468
413 OSDArray decodedMeshOsdArray = null; 469 OSDArray decodedMeshOsdArray = null;
414 470
415 // physics_shape is an array of OSDMaps, one for each submesh 471 // physics_shape is an array of OSDMaps, one for each submesh
416 if (decodedMeshOsd is OSDArray) 472 if (decodedMeshOsd is OSDArray)
417 { 473 {
418// Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd)); 474// Console.WriteLine("decodedMeshOsd for {0} - {1}", primName, Util.GetFormattedXml(decodedMeshOsd));
419 475
420 decodedMeshOsdArray = (OSDArray)decodedMeshOsd; 476 decodedMeshOsdArray = (OSDArray)decodedMeshOsd;
421 foreach (OSD subMeshOsd in decodedMeshOsdArray) 477 foreach (OSD subMeshOsd in decodedMeshOsdArray)
422 { 478 {
423 if (subMeshOsd is OSDMap) 479 if (subMeshOsd is OSDMap)
424 AddSubMesh(subMeshOsd as OSDMap, size, coords, faces); 480 AddSubMesh(subMeshOsd as OSDMap, size, coords, faces);
425 }
426 }
427 } 481 }
428 } 482 }
429 else 483 }
484
485 return true;
486 }
487
488 /// <summary>
489 /// Generate the co-ords and faces necessary to construct a mesh from the sculpt data the accompanies a prim.
490 /// </summary>
491 /// <param name="primName"></param>
492 /// <param name="primShape"></param>
493 /// <param name="size"></param>
494 /// <param name="lod"></param>
495 /// <param name="coords">Coords are added to this list by the method.</param>
496 /// <param name="faces">Faces are added to this list by the method.</param>
497 /// <returns>true if coords and faces were successfully generated, false if not</returns>
498 private bool GenerateCoordsAndFacesFromPrimSculptData(
499 string primName, PrimitiveBaseShape primShape, Vector3 size, float lod, out List<Coord> coords, out List<Face> faces)
500 {
501 coords = new List<Coord>();
502 faces = new List<Face>();
503 PrimMesher.SculptMesh sculptMesh;
504 Image idata = null;
505 string decodedSculptFileName = "";
506
507 if (cacheSculptMaps && primShape.SculptTexture != UUID.Zero)
508 {
509 decodedSculptFileName = System.IO.Path.Combine(decodedSculptMapPath, "smap_" + primShape.SculptTexture.ToString());
510 try
430 { 511 {
431 if (cacheSculptMaps && primShape.SculptTexture != UUID.Zero) 512 if (File.Exists(decodedSculptFileName))
432 { 513 {
433 decodedSculptFileName = System.IO.Path.Combine(decodedSculptMapPath, "smap_" + primShape.SculptTexture.ToString()); 514 idata = Image.FromFile(decodedSculptFileName);
434 try
435 {
436 if (File.Exists(decodedSculptFileName))
437 {
438 idata = Image.FromFile(decodedSculptFileName);
439 }
440 }
441 catch (Exception e)
442 {
443 m_log.Error("[SCULPT]: unable to load cached sculpt map " + decodedSculptFileName + " " + e.Message);
444
445 }
446 //if (idata != null)
447 // m_log.Debug("[SCULPT]: loaded cached map asset for map ID: " + primShape.SculptTexture.ToString());
448 } 515 }
516 }
517 catch (Exception e)
518 {
519 m_log.Error("[SCULPT]: unable to load cached sculpt map " + decodedSculptFileName + " " + e.Message);
520
521 }
522 //if (idata != null)
523 // m_log.Debug("[SCULPT]: loaded cached map asset for map ID: " + primShape.SculptTexture.ToString());
524 }
525
526 if (idata == null)
527 {
528 if (primShape.SculptData == null || primShape.SculptData.Length == 0)
529 return false;
530
531 try
532 {
533 OpenMetaverse.Imaging.ManagedImage unusedData;
534 OpenMetaverse.Imaging.OpenJPEG.DecodeToImage(primShape.SculptData, out unusedData, out idata);
449 535
450 if (idata == null) 536 if (idata == null)
451 { 537 {
452 if (primShape.SculptData == null || primShape.SculptData.Length == 0) 538 // In some cases it seems that the decode can return a null bitmap without throwing
453 return null; 539 // an exception
540 m_log.WarnFormat("[PHYSICS]: OpenJPEG decoded sculpt data for {0} to a null bitmap. Ignoring.", primName);
454 541
455 try 542 return false;
456 { 543 }
457 OpenMetaverse.Imaging.ManagedImage unusedData;
458 OpenMetaverse.Imaging.OpenJPEG.DecodeToImage(primShape.SculptData, out unusedData, out idata);
459 unusedData = null;
460 544
461 //idata = CSJ2K.J2kImage.FromBytes(primShape.SculptData); 545 unusedData = null;
462 546
463 if (cacheSculptMaps && idata != null) 547 //idata = CSJ2K.J2kImage.FromBytes(primShape.SculptData);
464 {
465 try { idata.Save(decodedSculptFileName, ImageFormat.MemoryBmp); }
466 catch (Exception e) { m_log.Error("[SCULPT]: unable to cache sculpt map " + decodedSculptFileName + " " + e.Message); }
467 }
468 }
469 catch (DllNotFoundException)
470 {
471 m_log.Error("[PHYSICS]: OpenJpeg is not installed correctly on this system. Physics Proxy generation failed. Often times this is because of an old version of GLIBC. You must have version 2.4 or above!");
472 return null;
473 }
474 catch (IndexOutOfRangeException)
475 {
476 m_log.Error("[PHYSICS]: OpenJpeg was unable to decode this. Physics Proxy generation failed");
477 return null;
478 }
479 catch (Exception ex)
480 {
481 m_log.Error("[PHYSICS]: Unable to generate a Sculpty physics proxy. Sculpty texture decode failed: " + ex.Message);
482 return null;
483 }
484 }
485 548
486 PrimMesher.SculptMesh.SculptType sculptType; 549 if (cacheSculptMaps)
487 switch ((OpenMetaverse.SculptType)primShape.SculptType)
488 { 550 {
489 case OpenMetaverse.SculptType.Cylinder: 551 try { idata.Save(decodedSculptFileName, ImageFormat.MemoryBmp); }
490 sculptType = PrimMesher.SculptMesh.SculptType.cylinder; 552 catch (Exception e) { m_log.Error("[SCULPT]: unable to cache sculpt map " + decodedSculptFileName + " " + e.Message); }
491 break;
492 case OpenMetaverse.SculptType.Plane:
493 sculptType = PrimMesher.SculptMesh.SculptType.plane;
494 break;
495 case OpenMetaverse.SculptType.Torus:
496 sculptType = PrimMesher.SculptMesh.SculptType.torus;
497 break;
498 case OpenMetaverse.SculptType.Sphere:
499 sculptType = PrimMesher.SculptMesh.SculptType.sphere;
500 break;
501 default:
502 sculptType = PrimMesher.SculptMesh.SculptType.plane;
503 break;
504 } 553 }
554 }
555 catch (DllNotFoundException)
556 {
557 m_log.Error("[PHYSICS]: OpenJpeg is not installed correctly on this system. Physics Proxy generation failed. Often times this is because of an old version of GLIBC. You must have version 2.4 or above!");
558 return false;
559 }
560 catch (IndexOutOfRangeException)
561 {
562 m_log.Error("[PHYSICS]: OpenJpeg was unable to decode this. Physics Proxy generation failed");
563 return false;
564 }
565 catch (Exception ex)
566 {
567 m_log.Error("[PHYSICS]: Unable to generate a Sculpty physics proxy. Sculpty texture decode failed: " + ex.Message);
568 return false;
569 }
570 }
571
572 PrimMesher.SculptMesh.SculptType sculptType;
573 switch ((OpenMetaverse.SculptType)primShape.SculptType)
574 {
575 case OpenMetaverse.SculptType.Cylinder:
576 sculptType = PrimMesher.SculptMesh.SculptType.cylinder;
577 break;
578 case OpenMetaverse.SculptType.Plane:
579 sculptType = PrimMesher.SculptMesh.SculptType.plane;
580 break;
581 case OpenMetaverse.SculptType.Torus:
582 sculptType = PrimMesher.SculptMesh.SculptType.torus;
583 break;
584 case OpenMetaverse.SculptType.Sphere:
585 sculptType = PrimMesher.SculptMesh.SculptType.sphere;
586 break;
587 default:
588 sculptType = PrimMesher.SculptMesh.SculptType.plane;
589 break;
590 }
505 591
506 bool mirror = ((primShape.SculptType & 128) != 0); 592 bool mirror = ((primShape.SculptType & 128) != 0);
507 bool invert = ((primShape.SculptType & 64) != 0); 593 bool invert = ((primShape.SculptType & 64) != 0);
508 594
509 sculptMesh = new PrimMesher.SculptMesh((Bitmap)idata, sculptType, (int)lod, false, mirror, invert); 595 sculptMesh = new PrimMesher.SculptMesh((Bitmap)idata, sculptType, (int)lod, false, mirror, invert);
510
511 idata.Dispose();
512 596
513 sculptMesh.DumpRaw(baseDir, primName, "primMesh"); 597 idata.Dispose();
514 598
515 sculptMesh.Scale(size.X, size.Y, size.Z); 599 sculptMesh.DumpRaw(baseDir, primName, "primMesh");
516 600
517 coords = sculptMesh.coords; 601 sculptMesh.Scale(size.X, size.Y, size.Z);
518 faces = sculptMesh.faces; 602
519 } 603 coords = sculptMesh.coords;
604 faces = sculptMesh.faces;
605
606 return true;
607 }
608
609 /// <summary>
610 /// Generate the co-ords and faces necessary to construct a mesh from the shape data the accompanies a prim.
611 /// </summary>
612 /// <param name="primName"></param>
613 /// <param name="primShape"></param>
614 /// <param name="size"></param>
615 /// <param name="coords">Coords are added to this list by the method.</param>
616 /// <param name="faces">Faces are added to this list by the method.</param>
617 /// <returns>true if coords and faces were successfully generated, false if not</returns>
618 private bool GenerateCoordsAndFacesFromPrimShapeData(
619 string primName, PrimitiveBaseShape primShape, Vector3 size, out List<Coord> coords, out List<Face> faces)
620 {
621 PrimMesh primMesh;
622 coords = new List<Coord>();
623 faces = new List<Face>();
624
625 float pathShearX = primShape.PathShearX < 128 ? (float)primShape.PathShearX * 0.01f : (float)(primShape.PathShearX - 256) * 0.01f;
626 float pathShearY = primShape.PathShearY < 128 ? (float)primShape.PathShearY * 0.01f : (float)(primShape.PathShearY - 256) * 0.01f;
627 float pathBegin = (float)primShape.PathBegin * 2.0e-5f;
628 float pathEnd = 1.0f - (float)primShape.PathEnd * 2.0e-5f;
629 float pathScaleX = (float)(primShape.PathScaleX - 100) * 0.01f;
630 float pathScaleY = (float)(primShape.PathScaleY - 100) * 0.01f;
631
632 float profileBegin = (float)primShape.ProfileBegin * 2.0e-5f;
633 float profileEnd = 1.0f - (float)primShape.ProfileEnd * 2.0e-5f;
634 float profileHollow = (float)primShape.ProfileHollow * 2.0e-5f;
635 if (profileHollow > 0.95f)
636 profileHollow = 0.95f;
637
638 int sides = 4;
639 if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
640 sides = 3;
641 else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
642 sides = 24;
643 else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
644 { // half circle, prim is a sphere
645 sides = 24;
646
647 profileBegin = 0.5f * profileBegin + 0.5f;
648 profileEnd = 0.5f * profileEnd + 0.5f;
520 } 649 }
521 else
522 {
523 float pathShearX = primShape.PathShearX < 128 ? (float)primShape.PathShearX * 0.01f : (float)(primShape.PathShearX - 256) * 0.01f;
524 float pathShearY = primShape.PathShearY < 128 ? (float)primShape.PathShearY * 0.01f : (float)(primShape.PathShearY - 256) * 0.01f;
525 float pathBegin = (float)primShape.PathBegin * 2.0e-5f;
526 float pathEnd = 1.0f - (float)primShape.PathEnd * 2.0e-5f;
527 float pathScaleX = (float)(primShape.PathScaleX - 100) * 0.01f;
528 float pathScaleY = (float)(primShape.PathScaleY - 100) * 0.01f;
529
530 float profileBegin = (float)primShape.ProfileBegin * 2.0e-5f;
531 float profileEnd = 1.0f - (float)primShape.ProfileEnd * 2.0e-5f;
532 float profileHollow = (float)primShape.ProfileHollow * 2.0e-5f;
533 if (profileHollow > 0.95f)
534 profileHollow = 0.95f;
535
536 int sides = 4;
537 if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
538 sides = 3;
539 else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
540 sides = 24;
541 else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
542 { // half circle, prim is a sphere
543 sides = 24;
544
545 profileBegin = 0.5f * profileBegin + 0.5f;
546 profileEnd = 0.5f * profileEnd + 0.5f;
547 }
548 650
549 int hollowSides = sides; 651 int hollowSides = sides;
550 if (primShape.HollowShape == HollowShape.Circle) 652 if (primShape.HollowShape == HollowShape.Circle)
551 hollowSides = 24; 653 hollowSides = 24;
552 else if (primShape.HollowShape == HollowShape.Square) 654 else if (primShape.HollowShape == HollowShape.Square)
553 hollowSides = 4; 655 hollowSides = 4;
554 else if (primShape.HollowShape == HollowShape.Triangle) 656 else if (primShape.HollowShape == HollowShape.Triangle)
555 hollowSides = 3; 657 hollowSides = 3;
556 658
557 primMesh = new PrimMesh(sides, profileBegin, profileEnd, profileHollow, hollowSides); 659 primMesh = new PrimMesh(sides, profileBegin, profileEnd, profileHollow, hollowSides);
558 660
559 if (primMesh.errorMessage != null) 661 if (primMesh.errorMessage != null)
560 if (primMesh.errorMessage.Length > 0) 662 if (primMesh.errorMessage.Length > 0)
561 m_log.Error("[ERROR] " + primMesh.errorMessage); 663 m_log.Error("[ERROR] " + primMesh.errorMessage);
562 664
563 primMesh.topShearX = pathShearX; 665 primMesh.topShearX = pathShearX;
564 primMesh.topShearY = pathShearY; 666 primMesh.topShearY = pathShearY;
565 primMesh.pathCutBegin = pathBegin; 667 primMesh.pathCutBegin = pathBegin;
566 primMesh.pathCutEnd = pathEnd; 668 primMesh.pathCutEnd = pathEnd;
567 669
568 if (primShape.PathCurve == (byte)Extrusion.Straight || primShape.PathCurve == (byte) Extrusion.Flexible) 670 if (primShape.PathCurve == (byte)Extrusion.Straight || primShape.PathCurve == (byte) Extrusion.Flexible)
569 { 671 {
570 primMesh.twistBegin = primShape.PathTwistBegin * 18 / 10; 672 primMesh.twistBegin = primShape.PathTwistBegin * 18 / 10;
571 primMesh.twistEnd = primShape.PathTwist * 18 / 10; 673 primMesh.twistEnd = primShape.PathTwist * 18 / 10;
572 primMesh.taperX = pathScaleX; 674 primMesh.taperX = pathScaleX;
573 primMesh.taperY = pathScaleY; 675 primMesh.taperY = pathScaleY;
574 676
575 if (profileBegin < 0.0f || profileBegin >= profileEnd || profileEnd > 1.0f) 677 if (profileBegin < 0.0f || profileBegin >= profileEnd || profileEnd > 1.0f)
576 { 678 {
577 ReportPrimError("*** CORRUPT PRIM!! ***", primName, primMesh); 679 ReportPrimError("*** CORRUPT PRIM!! ***", primName, primMesh);
578 if (profileBegin < 0.0f) profileBegin = 0.0f; 680 if (profileBegin < 0.0f) profileBegin = 0.0f;
579 if (profileEnd > 1.0f) profileEnd = 1.0f; 681 if (profileEnd > 1.0f) profileEnd = 1.0f;
580 } 682 }
581#if SPAM 683#if SPAM
582 m_log.Debug("****** PrimMesh Parameters (Linear) ******\n" + primMesh.ParamsToDisplayString()); 684 m_log.Debug("****** PrimMesh Parameters (Linear) ******\n" + primMesh.ParamsToDisplayString());
583#endif 685#endif
584 try 686 try
585 { 687 {
586 primMesh.ExtrudeLinear(); 688 primMesh.ExtrudeLinear();
587 }
588 catch (Exception ex)
589 {
590 ReportPrimError("Extrusion failure: exception: " + ex.ToString(), primName, primMesh);
591 return null;
592 }
593 } 689 }
594 else 690 catch (Exception ex)
595 { 691 {
596 primMesh.holeSizeX = (200 - primShape.PathScaleX) * 0.01f; 692 ReportPrimError("Extrusion failure: exception: " + ex.ToString(), primName, primMesh);
597 primMesh.holeSizeY = (200 - primShape.PathScaleY) * 0.01f; 693 return false;
598 primMesh.radius = 0.01f * primShape.PathRadiusOffset; 694 }
599 primMesh.revolutions = 1.0f + 0.015f * primShape.PathRevolutions; 695 }
600 primMesh.skew = 0.01f * primShape.PathSkew; 696 else
601 primMesh.twistBegin = primShape.PathTwistBegin * 36 / 10; 697 {
602 primMesh.twistEnd = primShape.PathTwist * 36 / 10; 698 primMesh.holeSizeX = (200 - primShape.PathScaleX) * 0.01f;
603 primMesh.taperX = primShape.PathTaperX * 0.01f; 699 primMesh.holeSizeY = (200 - primShape.PathScaleY) * 0.01f;
604 primMesh.taperY = primShape.PathTaperY * 0.01f; 700 primMesh.radius = 0.01f * primShape.PathRadiusOffset;
605 701 primMesh.revolutions = 1.0f + 0.015f * primShape.PathRevolutions;
606 if (profileBegin < 0.0f || profileBegin >= profileEnd || profileEnd > 1.0f) 702 primMesh.skew = 0.01f * primShape.PathSkew;
607 { 703 primMesh.twistBegin = primShape.PathTwistBegin * 36 / 10;
608 ReportPrimError("*** CORRUPT PRIM!! ***", primName, primMesh); 704 primMesh.twistEnd = primShape.PathTwist * 36 / 10;
609 if (profileBegin < 0.0f) profileBegin = 0.0f; 705 primMesh.taperX = primShape.PathTaperX * 0.01f;
610 if (profileEnd > 1.0f) profileEnd = 1.0f; 706 primMesh.taperY = primShape.PathTaperY * 0.01f;
611 } 707
708 if (profileBegin < 0.0f || profileBegin >= profileEnd || profileEnd > 1.0f)
709 {
710 ReportPrimError("*** CORRUPT PRIM!! ***", primName, primMesh);
711 if (profileBegin < 0.0f) profileBegin = 0.0f;
712 if (profileEnd > 1.0f) profileEnd = 1.0f;
713 }
612#if SPAM 714#if SPAM
613 m_log.Debug("****** PrimMesh Parameters (Circular) ******\n" + primMesh.ParamsToDisplayString()); 715 m_log.Debug("****** PrimMesh Parameters (Circular) ******\n" + primMesh.ParamsToDisplayString());
614#endif 716#endif
615 try 717 try
616 { 718 {
617 primMesh.ExtrudeCircular(); 719 primMesh.ExtrudeCircular();
618 } 720 }
619 catch (Exception ex) 721 catch (Exception ex)
620 { 722 {
621 ReportPrimError("Extrusion failure: exception: " + ex.ToString(), primName, primMesh); 723 ReportPrimError("Extrusion failure: exception: " + ex.ToString(), primName, primMesh);
622 return null; 724 return false;
623 }
624 } 725 }
625
626 primMesh.DumpRaw(baseDir, primName, "primMesh");
627
628 primMesh.Scale(size.X, size.Y, size.Z);
629
630 coords = primMesh.coords;
631 faces = primMesh.faces;
632 } 726 }
633 727
634 // Remove the reference to any JPEG2000 sculpt data so it can be GCed 728 primMesh.DumpRaw(baseDir, primName, "primMesh");
635 primShape.SculptData = Utils.EmptyBytes;
636 729
637 int numCoords = coords.Count; 730 primMesh.Scale(size.X, size.Y, size.Z);
638 int numFaces = faces.Count;
639 731
640 // Create the list of vertices 732 coords = primMesh.coords;
641 List<Vertex> vertices = new List<Vertex>(); 733 faces = primMesh.faces;
642 for (int i = 0; i < numCoords; i++)
643 {
644 Coord c = coords[i];
645 vertices.Add(new Vertex(c.X, c.Y, c.Z));
646 }
647
648 Mesh mesh = new Mesh();
649 // Add the corresponding triangles to the mesh
650 for (int i = 0; i < numFaces; i++)
651 {
652 Face f = faces[i];
653 mesh.Add(new Triangle(vertices[f.v1], vertices[f.v2], vertices[f.v3]));
654 }
655 734
656 return mesh; 735 return true;
657 } 736 }
658 737
659 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod) 738 public IMesh CreateMesh(String primName, PrimitiveBaseShape primShape, Vector3 size, float lod)
diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
index 6b74e74..4f461ad 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
@@ -1220,18 +1220,23 @@ namespace OpenSim.Region.Physics.OdePlugin
1220 { 1220 {
1221 m_requestedUpdateFrequency = ms; 1221 m_requestedUpdateFrequency = ms;
1222 m_eventsubscription = ms; 1222 m_eventsubscription = ms;
1223 _parent_scene.addCollisionEventReporting(this); 1223 _parent_scene.AddCollisionEventReporting(this);
1224 } 1224 }
1225
1225 public override void UnSubscribeEvents() 1226 public override void UnSubscribeEvents()
1226 { 1227 {
1227 _parent_scene.remCollisionEventReporting(this); 1228 _parent_scene.RemoveCollisionEventReporting(this);
1228 m_requestedUpdateFrequency = 0; 1229 m_requestedUpdateFrequency = 0;
1229 m_eventsubscription = 0; 1230 m_eventsubscription = 0;
1230 } 1231 }
1232
1231 public void AddCollisionEvent(uint CollidedWith, ContactPoint contact) 1233 public void AddCollisionEvent(uint CollidedWith, ContactPoint contact)
1232 { 1234 {
1233 if (m_eventsubscription > 0) 1235 if (m_eventsubscription > 0)
1234 { 1236 {
1237// m_log.DebugFormat(
1238// "[PHYSICS]: Adding collision event for {0}, collidedWith {1}, contact {2}", "", CollidedWith, contact);
1239
1235 CollisionEventsThisFrame.addCollider(CollidedWith, contact); 1240 CollisionEventsThisFrame.addCollider(CollidedWith, contact);
1236 } 1241 }
1237 } 1242 }
@@ -1248,6 +1253,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1248 m_eventsubscription = 0; 1253 m_eventsubscription = 0;
1249 } 1254 }
1250 } 1255 }
1256
1251 public override bool SubscribedEvents() 1257 public override bool SubscribedEvents()
1252 { 1258 {
1253 if (m_eventsubscription > 0) 1259 if (m_eventsubscription > 0)
diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
index b3045bd..924d7c2 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
@@ -61,6 +61,22 @@ namespace OpenSim.Region.Physics.OdePlugin
61 { 61 {
62 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 62 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
63 63
64 private bool m_isphysical;
65
66 /// <summary>
67 /// Is this prim subject to physics? Even if not, it's still solid for collision purposes.
68 /// </summary>
69 public override bool IsPhysical
70 {
71 get { return m_isphysical; }
72 set
73 {
74 m_isphysical = value;
75 if (!m_isphysical) // Zero the remembered last velocity
76 m_lastVelocity = Vector3.Zero;
77 }
78 }
79
64 private Vector3 _position; 80 private Vector3 _position;
65 private Vector3 _velocity; 81 private Vector3 _velocity;
66 private Vector3 _torque; 82 private Vector3 _torque;
@@ -138,12 +154,15 @@ namespace OpenSim.Region.Physics.OdePlugin
138 private List<Vector3> m_forcelist = new List<Vector3>(); 154 private List<Vector3> m_forcelist = new List<Vector3>();
139 private List<Vector3> m_angularforcelist = new List<Vector3>(); 155 private List<Vector3> m_angularforcelist = new List<Vector3>();
140 156
141 private IMesh _mesh;
142 private PrimitiveBaseShape _pbs; 157 private PrimitiveBaseShape _pbs;
143 private OdeScene _parent_scene; 158 private OdeScene _parent_scene;
159
160 /// <summary>
161 /// The physics space which contains prim geometries
162 /// </summary>
144 public IntPtr m_targetSpace = IntPtr.Zero; 163 public IntPtr m_targetSpace = IntPtr.Zero;
164
145 public IntPtr prim_geom; 165 public IntPtr prim_geom;
146 public IntPtr prev_geom;
147 public IntPtr _triMeshData; 166 public IntPtr _triMeshData;
148 167
149 private IntPtr _linkJointGroup = IntPtr.Zero; 168 private IntPtr _linkJointGroup = IntPtr.Zero;
@@ -153,7 +172,6 @@ namespace OpenSim.Region.Physics.OdePlugin
153 private List<OdePrim> childrenPrim = new List<OdePrim>(); 172 private List<OdePrim> childrenPrim = new List<OdePrim>();
154 173
155 private bool iscolliding; 174 private bool iscolliding;
156 private bool m_isphysical;
157 private bool m_isSelected; 175 private bool m_isSelected;
158 176
159 internal bool m_isVolumeDetect; // If true, this prim only detects collisions but doesn't collide actively 177 internal bool m_isVolumeDetect; // If true, this prim only detects collisions but doesn't collide actively
@@ -188,7 +206,7 @@ namespace OpenSim.Region.Physics.OdePlugin
188 internal int m_material = (int)Material.Wood; 206 internal int m_material = (int)Material.Wood;
189 207
190 public OdePrim(String primName, OdeScene parent_scene, Vector3 pos, Vector3 size, 208 public OdePrim(String primName, OdeScene parent_scene, Vector3 pos, Vector3 size,
191 Quaternion rotation, IMesh mesh, PrimitiveBaseShape pbs, bool pisPhysical, CollisionLocker dode) 209 Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical, CollisionLocker dode)
192 { 210 {
193 Name = primName; 211 Name = primName;
194 m_vehicle = new ODEDynamics(); 212 m_vehicle = new ODEDynamics();
@@ -208,9 +226,7 @@ namespace OpenSim.Region.Physics.OdePlugin
208 // m_tensor = parent_scene.bodyMotorJointMaxforceTensor; 226 // m_tensor = parent_scene.bodyMotorJointMaxforceTensor;
209 body_autodisable_frames = parent_scene.bodyFramesAutoDisable; 227 body_autodisable_frames = parent_scene.bodyFramesAutoDisable;
210 228
211
212 prim_geom = IntPtr.Zero; 229 prim_geom = IntPtr.Zero;
213 prev_geom = IntPtr.Zero;
214 230
215 if (!pos.IsFinite()) 231 if (!pos.IsFinite())
216 { 232 {
@@ -233,20 +249,21 @@ namespace OpenSim.Region.Physics.OdePlugin
233 249
234 _orientation = rotation; 250 _orientation = rotation;
235 m_taintrot = _orientation; 251 m_taintrot = _orientation;
236 _mesh = mesh;
237 _pbs = pbs; 252 _pbs = pbs;
238 253
239 _parent_scene = parent_scene; 254 _parent_scene = parent_scene;
240 m_targetSpace = (IntPtr)0; 255 m_targetSpace = (IntPtr)0;
241 256
242 if (pos.Z < 0) 257 if (pos.Z < 0)
243 m_isphysical = false; 258 {
259 IsPhysical = false;
260 }
244 else 261 else
245 { 262 {
246 m_isphysical = pisPhysical; 263 IsPhysical = pisPhysical;
247 // If we're physical, we need to be in the master space for now. 264 // If we're physical, we need to be in the master space for now.
248 // linksets *should* be in a space together.. but are not currently 265 // linksets *should* be in a space together.. but are not currently
249 if (m_isphysical) 266 if (IsPhysical)
250 m_targetSpace = _parent_scene.space; 267 m_targetSpace = _parent_scene.space;
251 } 268 }
252 269
@@ -289,7 +306,7 @@ namespace OpenSim.Region.Physics.OdePlugin
289 // through it while it's selected 306 // through it while it's selected
290 m_collisionscore = 0; 307 m_collisionscore = 0;
291 308
292 if ((m_isphysical && !_zeroFlag) || !value) 309 if ((IsPhysical && !_zeroFlag) || !value)
293 { 310 {
294 m_taintselected = value; 311 m_taintselected = value;
295 _parent_scene.AddPhysicsActorTaint(this); 312 _parent_scene.AddPhysicsActorTaint(this);
@@ -305,15 +322,21 @@ namespace OpenSim.Region.Physics.OdePlugin
305 } 322 }
306 } 323 }
307 324
325 /// <summary>
326 /// Set a new geometry for this prim.
327 /// </summary>
328 /// <param name="geom"></param>
308 public void SetGeom(IntPtr geom) 329 public void SetGeom(IntPtr geom)
309 { 330 {
310 prev_geom = prim_geom;
311 prim_geom = geom; 331 prim_geom = geom;
312//Console.WriteLine("SetGeom to " + prim_geom + " for " + Name); 332//Console.WriteLine("SetGeom to " + prim_geom + " for " + Name);
313 if (prim_geom != IntPtr.Zero) 333 if (prim_geom != IntPtr.Zero)
314 { 334 {
315 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); 335 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
316 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); 336 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
337
338 _parent_scene.geom_name_map[prim_geom] = Name;
339 _parent_scene.actor_name_map[prim_geom] = this;
317 } 340 }
318 341
319 if (childPrim) 342 if (childPrim)
@@ -332,7 +355,7 @@ namespace OpenSim.Region.Physics.OdePlugin
332 { 355 {
333 if (!childPrim) 356 if (!childPrim)
334 { 357 {
335 if (m_isphysical && Body != IntPtr.Zero) 358 if (IsPhysical && Body != IntPtr.Zero)
336 { 359 {
337 d.BodyEnable(Body); 360 d.BodyEnable(Body);
338 if (m_vehicle.Type != Vehicle.TYPE_NONE) 361 if (m_vehicle.Type != Vehicle.TYPE_NONE)
@@ -347,12 +370,15 @@ namespace OpenSim.Region.Physics.OdePlugin
347 { 370 {
348 m_disabled = true; 371 m_disabled = true;
349 372
350 if (m_isphysical && Body != IntPtr.Zero) 373 if (IsPhysical && Body != IntPtr.Zero)
351 { 374 {
352 d.BodyDisable(Body); 375 d.BodyDisable(Body);
353 } 376 }
354 } 377 }
355 378
379 /// <summary>
380 /// Make a prim subject to physics.
381 /// </summary>
356 public void enableBody() 382 public void enableBody()
357 { 383 {
358 // Don't enable this body if we're a child prim 384 // Don't enable this body if we're a child prim
@@ -728,6 +754,9 @@ namespace OpenSim.Region.Physics.OdePlugin
728 } 754 }
729 } 755 }
730 756
757 /// <summary>
758 /// Stop a prim from being subject to physics.
759 /// </summary>
731 public void disableBody() 760 public void disableBody()
732 { 761 {
733 //this kills the body so things like 'mesh' can re-create it. 762 //this kills the body so things like 'mesh' can re-create it.
@@ -778,6 +807,7 @@ namespace OpenSim.Region.Physics.OdePlugin
778 Body = IntPtr.Zero; 807 Body = IntPtr.Zero;
779 } 808 }
780 } 809 }
810
781 m_disabled = true; 811 m_disabled = true;
782 m_collisionscore = 0; 812 m_collisionscore = 0;
783 } 813 }
@@ -886,7 +916,7 @@ Console.WriteLine("ZProcessTaints for " + Name);
886 } 916 }
887 } 917 }
888 918
889 if (m_taintPhysics != m_isphysical && !(m_taintparent != _parent)) 919 if (m_taintPhysics != IsPhysical && !(m_taintparent != _parent))
890 changePhysicsStatus(timestep); 920 changePhysicsStatus(timestep);
891 921
892 if (!_size.ApproxEquals(m_taintsize, 0f)) 922 if (!_size.ApproxEquals(m_taintsize, 0f))
@@ -968,7 +998,7 @@ Console.WriteLine("ZProcessTaints for " + Name);
968 OdePrim obj = (OdePrim)m_taintparent; 998 OdePrim obj = (OdePrim)m_taintparent;
969 //obj.disableBody(); 999 //obj.disableBody();
970//Console.WriteLine("changelink calls ParentPrim"); 1000//Console.WriteLine("changelink calls ParentPrim");
971 obj.ParentPrim(this); 1001 obj.AddChildPrim(this);
972 1002
973 /* 1003 /*
974 if (obj.Body != (IntPtr)0 && Body != (IntPtr)0 && obj.Body != Body) 1004 if (obj.Body != (IntPtr)0 && Body != (IntPtr)0 && obj.Body != Body)
@@ -1005,14 +1035,16 @@ Console.WriteLine("ZProcessTaints for " + Name);
1005 } 1035 }
1006 1036
1007 _parent = m_taintparent; 1037 _parent = m_taintparent;
1008 m_taintPhysics = m_isphysical; 1038 m_taintPhysics = IsPhysical;
1009 } 1039 }
1010 1040
1011 // I'm the parent 1041 /// <summary>
1012 // prim is the child 1042 /// Add a child prim to this parent prim.
1013 public void ParentPrim(OdePrim prim) 1043 /// </summary>
1044 /// <param name="prim">Child prim</param>
1045 public void AddChildPrim(OdePrim prim)
1014 { 1046 {
1015//Console.WriteLine("ParentPrim " + Name); 1047//Console.WriteLine("AddChildPrim " + Name);
1016 if (this.m_localID != prim.m_localID) 1048 if (this.m_localID != prim.m_localID)
1017 { 1049 {
1018 if (Body == IntPtr.Zero) 1050 if (Body == IntPtr.Zero)
@@ -1035,7 +1067,6 @@ Console.WriteLine("ZProcessTaints for " + Name);
1035 d.MassSetZero(out m2); 1067 d.MassSetZero(out m2);
1036 d.MassSetBoxTotal(out m2, prim.CalculateMass(), prm._size.X, prm._size.Y, prm._size.Z); 1068 d.MassSetBoxTotal(out m2, prim.CalculateMass(), prm._size.X, prm._size.Y, prm._size.Z);
1037 1069
1038
1039 d.Quaternion quat = new d.Quaternion(); 1070 d.Quaternion quat = new d.Quaternion();
1040 quat.W = prm._orientation.W; 1071 quat.W = prm._orientation.W;
1041 quat.X = prm._orientation.X; 1072 quat.X = prm._orientation.X;
@@ -1105,6 +1136,7 @@ Console.WriteLine("ZProcessTaints for " + Name);
1105 prm.Body = Body; 1136 prm.Body = Body;
1106 _parent_scene.addActivePrim(prm); 1137 _parent_scene.addActivePrim(prm);
1107 } 1138 }
1139
1108 m_collisionCategories |= CollisionCategories.Body; 1140 m_collisionCategories |= CollisionCategories.Body;
1109 m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind); 1141 m_collisionFlags |= (CollisionCategories.Land | CollisionCategories.Wind);
1110 1142
@@ -1113,7 +1145,6 @@ Console.WriteLine("ZProcessTaints for " + Name);
1113//Console.WriteLine(" Post GeomSetCategoryBits 2"); 1145//Console.WriteLine(" Post GeomSetCategoryBits 2");
1114 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); 1146 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1115 1147
1116
1117 d.Quaternion quat2 = new d.Quaternion(); 1148 d.Quaternion quat2 = new d.Quaternion();
1118 quat2.W = _orientation.W; 1149 quat2.W = _orientation.W;
1119 quat2.X = _orientation.X; 1150 quat2.X = _orientation.X;
@@ -1135,7 +1166,6 @@ Console.WriteLine("ZProcessTaints for " + Name);
1135 d.BodySetAutoDisableFlag(Body, true); 1166 d.BodySetAutoDisableFlag(Body, true);
1136 d.BodySetAutoDisableSteps(Body, body_autodisable_frames); 1167 d.BodySetAutoDisableSteps(Body, body_autodisable_frames);
1137 1168
1138
1139 m_interpenetrationcount = 0; 1169 m_interpenetrationcount = 0;
1140 m_collisionscore = 0; 1170 m_collisionscore = 0;
1141 m_disabled = false; 1171 m_disabled = false;
@@ -1146,7 +1176,9 @@ Console.WriteLine("ZProcessTaints for " + Name);
1146 createAMotor(m_angularlock); 1176 createAMotor(m_angularlock);
1147 } 1177 }
1148 d.BodySetPosition(Body, Position.X, Position.Y, Position.Z); 1178 d.BodySetPosition(Body, Position.X, Position.Y, Position.Z);
1149 if (m_vehicle.Type != Vehicle.TYPE_NONE) m_vehicle.Enable(Body, _parent_scene); 1179 if (m_vehicle.Type != Vehicle.TYPE_NONE)
1180 m_vehicle.Enable(Body, _parent_scene);
1181
1150 _parent_scene.addActivePrim(this); 1182 _parent_scene.addActivePrim(this);
1151 } 1183 }
1152 } 1184 }
@@ -1156,7 +1188,7 @@ Console.WriteLine("ZProcessTaints for " + Name);
1156 1188
1157 private void ChildSetGeom(OdePrim odePrim) 1189 private void ChildSetGeom(OdePrim odePrim)
1158 { 1190 {
1159 //if (m_isphysical && Body != IntPtr.Zero) 1191 //if (IsPhysical && Body != IntPtr.Zero)
1160 lock (childrenPrim) 1192 lock (childrenPrim)
1161 { 1193 {
1162 foreach (OdePrim prm in childrenPrim) 1194 foreach (OdePrim prm in childrenPrim)
@@ -1172,7 +1204,6 @@ Console.WriteLine("ZProcessTaints for " + Name);
1172 } 1204 }
1173 disableBody(); 1205 disableBody();
1174 1206
1175
1176 if (Body != IntPtr.Zero) 1207 if (Body != IntPtr.Zero)
1177 { 1208 {
1178 _parent_scene.remActivePrim(this); 1209 _parent_scene.remActivePrim(this);
@@ -1183,10 +1214,9 @@ Console.WriteLine("ZProcessTaints for " + Name);
1183 foreach (OdePrim prm in childrenPrim) 1214 foreach (OdePrim prm in childrenPrim)
1184 { 1215 {
1185//Console.WriteLine("ChildSetGeom calls ParentPrim"); 1216//Console.WriteLine("ChildSetGeom calls ParentPrim");
1186 ParentPrim(prm); 1217 AddChildPrim(prm);
1187 } 1218 }
1188 } 1219 }
1189
1190 } 1220 }
1191 1221
1192 private void ChildDelink(OdePrim odePrim) 1222 private void ChildDelink(OdePrim odePrim)
@@ -1223,7 +1253,7 @@ Console.WriteLine("ZProcessTaints for " + Name);
1223 foreach (OdePrim prm in childrenPrim) 1253 foreach (OdePrim prm in childrenPrim)
1224 { 1254 {
1225//Console.WriteLine("ChildDelink calls ParentPrim"); 1255//Console.WriteLine("ChildDelink calls ParentPrim");
1226 ParentPrim(prm); 1256 AddChildPrim(prm);
1227 } 1257 }
1228 } 1258 }
1229 } 1259 }
@@ -1257,7 +1287,7 @@ Console.WriteLine("ZProcessTaints for " + Name);
1257 // first 50 again. then the last 50 are disabled. then the first 50, which were just woken 1287 // first 50 again. then the last 50 are disabled. then the first 50, which were just woken
1258 // up, start simulating again, which in turn wakes up the last 50. 1288 // up, start simulating again, which in turn wakes up the last 50.
1259 1289
1260 if (m_isphysical) 1290 if (IsPhysical)
1261 { 1291 {
1262 disableBodySoft(); 1292 disableBodySoft();
1263 } 1293 }
@@ -1268,7 +1298,7 @@ Console.WriteLine("ZProcessTaints for " + Name);
1268 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); 1298 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1269 } 1299 }
1270 1300
1271 if (m_isphysical) 1301 if (IsPhysical)
1272 { 1302 {
1273 disableBodySoft(); 1303 disableBodySoft();
1274 } 1304 }
@@ -1277,7 +1307,7 @@ Console.WriteLine("ZProcessTaints for " + Name);
1277 { 1307 {
1278 m_collisionCategories = CollisionCategories.Geom; 1308 m_collisionCategories = CollisionCategories.Geom;
1279 1309
1280 if (m_isphysical) 1310 if (IsPhysical)
1281 m_collisionCategories |= CollisionCategories.Body; 1311 m_collisionCategories |= CollisionCategories.Body;
1282 1312
1283 m_collisionFlags = m_default_collisionFlags; 1313 m_collisionFlags = m_default_collisionFlags;
@@ -1292,7 +1322,8 @@ Console.WriteLine("ZProcessTaints for " + Name);
1292 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories); 1322 d.GeomSetCategoryBits(prim_geom, (int)m_collisionCategories);
1293 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags); 1323 d.GeomSetCollideBits(prim_geom, (int)m_collisionFlags);
1294 } 1324 }
1295 if (m_isphysical) 1325
1326 if (IsPhysical)
1296 { 1327 {
1297 if (Body != IntPtr.Zero) 1328 if (Body != IntPtr.Zero)
1298 { 1329 {
@@ -1311,7 +1342,7 @@ Console.WriteLine("ZProcessTaints for " + Name);
1311 { 1342 {
1312 m_taintposition = _position; 1343 m_taintposition = _position;
1313 m_taintrot = _orientation; 1344 m_taintrot = _orientation;
1314 m_taintPhysics = m_isphysical; 1345 m_taintPhysics = IsPhysical;
1315 m_taintselected = m_isSelected; 1346 m_taintselected = m_isSelected;
1316 m_taintsize = _size; 1347 m_taintsize = _size;
1317 m_taintshape = false; 1348 m_taintshape = false;
@@ -1320,14 +1351,19 @@ Console.WriteLine("ZProcessTaints for " + Name);
1320 m_taintVelocity = Vector3.Zero; 1351 m_taintVelocity = Vector3.Zero;
1321 } 1352 }
1322 1353
1323 public void CreateGeom(IntPtr m_targetSpace, IMesh _mesh) 1354 /// <summary>
1355 /// Create a geometry for the given mesh in the given target space.
1356 /// </summary>
1357 /// <param name="m_targetSpace"></param>
1358 /// <param name="mesh">If null, then a mesh is used that is based on the profile shape data.</param>
1359 public void CreateGeom(IntPtr m_targetSpace, IMesh mesh)
1324 { 1360 {
1325#if SPAM 1361#if SPAM
1326Console.WriteLine("CreateGeom:"); 1362Console.WriteLine("CreateGeom:");
1327#endif 1363#endif
1328 if (_mesh != null) 1364 if (mesh != null)
1329 { 1365 {
1330 setMesh(_parent_scene, _mesh); 1366 setMesh(_parent_scene, mesh);
1331 } 1367 }
1332 else 1368 else
1333 { 1369 {
@@ -1400,6 +1436,39 @@ Console.WriteLine("CreateGeom:");
1400 } 1436 }
1401 } 1437 }
1402 1438
1439 /// <summary>
1440 /// Remove the existing geom from this prim.
1441 /// </summary>
1442 /// <param name="m_targetSpace"></param>
1443 /// <param name="mesh">If null, then a mesh is used that is based on the profile shape data.</param>
1444 /// <returns>true if the geom was successfully removed, false if it was already gone or the remove failed.</returns>
1445 public bool RemoveGeom()
1446 {
1447 if (prim_geom != IntPtr.Zero)
1448 {
1449 try
1450 {
1451 _parent_scene.geom_name_map.Remove(prim_geom);
1452 _parent_scene.actor_name_map.Remove(prim_geom);
1453 d.GeomDestroy(prim_geom);
1454 prim_geom = IntPtr.Zero;
1455 }
1456 catch (System.AccessViolationException)
1457 {
1458 prim_geom = IntPtr.Zero;
1459 m_log.ErrorFormat("[PHYSICS]: PrimGeom dead for {0}", Name);
1460
1461 return false;
1462 }
1463
1464 return true;
1465 }
1466 else
1467 {
1468 return false;
1469 }
1470 }
1471
1403 public void changeadd(float timestep) 1472 public void changeadd(float timestep)
1404 { 1473 {
1405 int[] iprimspaceArrItem = _parent_scene.calculateSpaceArrayItemFromPos(_position); 1474 int[] iprimspaceArrItem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
@@ -1410,15 +1479,14 @@ Console.WriteLine("CreateGeom:");
1410 1479
1411 m_targetSpace = targetspace; 1480 m_targetSpace = targetspace;
1412 1481
1413 if (_mesh == null) 1482 IMesh mesh = null;
1483
1484 if (_parent_scene.needsMeshing(_pbs))
1414 { 1485 {
1415 if (_parent_scene.needsMeshing(_pbs)) 1486 // Don't need to re-enable body.. it's done in SetMesh
1416 { 1487 mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, _parent_scene.meshSculptLOD, IsPhysical);
1417 // Don't need to re-enable body.. it's done in SetMesh 1488 // createmesh returns null when it's a shape that isn't a cube.
1418 _mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, _parent_scene.meshSculptLOD, IsPhysical); 1489 // m_log.Debug(m_localID);
1419 // createmesh returns null when it's a shape that isn't a cube.
1420 // m_log.Debug(m_localID);
1421 }
1422 } 1490 }
1423 1491
1424 lock (_parent_scene.OdeLock) 1492 lock (_parent_scene.OdeLock)
@@ -1426,7 +1494,7 @@ Console.WriteLine("CreateGeom:");
1426#if SPAM 1494#if SPAM
1427Console.WriteLine("changeadd 1"); 1495Console.WriteLine("changeadd 1");
1428#endif 1496#endif
1429 CreateGeom(m_targetSpace, _mesh); 1497 CreateGeom(m_targetSpace, mesh);
1430 1498
1431 if (prim_geom != IntPtr.Zero) 1499 if (prim_geom != IntPtr.Zero)
1432 { 1500 {
@@ -1439,15 +1507,12 @@ Console.WriteLine("changeadd 1");
1439 d.GeomSetQuaternion(prim_geom, ref myrot); 1507 d.GeomSetQuaternion(prim_geom, ref myrot);
1440 } 1508 }
1441 1509
1442 if (m_isphysical && Body == IntPtr.Zero) 1510 if (IsPhysical && Body == IntPtr.Zero)
1443 { 1511 {
1444 enableBody(); 1512 enableBody();
1445 } 1513 }
1446 } 1514 }
1447 1515
1448 _parent_scene.geom_name_map[prim_geom] = this.Name;
1449 _parent_scene.actor_name_map[prim_geom] = (PhysicsActor)this;
1450
1451 changeSelectedStatus(timestep); 1516 changeSelectedStatus(timestep);
1452 1517
1453 m_taintadd = false; 1518 m_taintadd = false;
@@ -1455,9 +1520,8 @@ Console.WriteLine("changeadd 1");
1455 1520
1456 public void changemove(float timestep) 1521 public void changemove(float timestep)
1457 { 1522 {
1458 if (m_isphysical) 1523 if (IsPhysical)
1459 { 1524 {
1460
1461 if (!m_disabled && !m_taintremove && !childPrim) 1525 if (!m_disabled && !m_taintremove && !childPrim)
1462 { 1526 {
1463 if (Body == IntPtr.Zero) 1527 if (Body == IntPtr.Zero)
@@ -1789,7 +1853,7 @@ Console.WriteLine(" JointCreateFixed");
1789 { 1853 {
1790 // KF: If this is a root prim do BodySet 1854 // KF: If this is a root prim do BodySet
1791 d.BodySetQuaternion(Body, ref myrot); 1855 d.BodySetQuaternion(Body, ref myrot);
1792 if (m_isphysical) 1856 if (IsPhysical)
1793 { 1857 {
1794 if (!m_angularlock.ApproxEquals(Vector3.One, 0f)) 1858 if (!m_angularlock.ApproxEquals(Vector3.One, 0f))
1795 createAMotor(m_angularlock); 1859 createAMotor(m_angularlock);
@@ -1826,7 +1890,7 @@ Console.WriteLine(" JointCreateFixed");
1826 1890
1827 public void changePhysicsStatus(float timestep) 1891 public void changePhysicsStatus(float timestep)
1828 { 1892 {
1829 if (m_isphysical == true) 1893 if (IsPhysical)
1830 { 1894 {
1831 if (Body == IntPtr.Zero) 1895 if (Body == IntPtr.Zero)
1832 { 1896 {
@@ -1846,25 +1910,12 @@ Console.WriteLine(" JointCreateFixed");
1846 { 1910 {
1847 if (_pbs.SculptEntry && _parent_scene.meshSculptedPrim) 1911 if (_pbs.SculptEntry && _parent_scene.meshSculptedPrim)
1848 { 1912 {
1849 1913 RemoveGeom();
1850 1914
1851 if (prim_geom != IntPtr.Zero)
1852 {
1853 try
1854 {
1855 d.GeomDestroy(prim_geom);
1856 prim_geom = IntPtr.Zero;
1857 _mesh = null;
1858 }
1859 catch (System.AccessViolationException)
1860 {
1861 prim_geom = IntPtr.Zero;
1862 m_log.ErrorFormat("[PHYSICS]: PrimGeom dead for {0}", Name);
1863 }
1864 }
1865//Console.WriteLine("changePhysicsStatus for " + Name); 1915//Console.WriteLine("changePhysicsStatus for " + Name);
1866 changeadd(2f); 1916 changeadd(2f);
1867 } 1917 }
1918
1868 if (childPrim) 1919 if (childPrim)
1869 { 1920 {
1870 if (_parent != null) 1921 if (_parent != null)
@@ -1883,7 +1934,7 @@ Console.WriteLine(" JointCreateFixed");
1883 changeSelectedStatus(timestep); 1934 changeSelectedStatus(timestep);
1884 1935
1885 resetCollisionAccounting(); 1936 resetCollisionAccounting();
1886 m_taintPhysics = m_isphysical; 1937 m_taintPhysics = IsPhysical;
1887 } 1938 }
1888 1939
1889 public void changesize(float timestamp) 1940 public void changesize(float timestamp)
@@ -1892,18 +1943,10 @@ Console.WriteLine(" JointCreateFixed");
1892 m_log.DebugFormat("[ODE PRIM]: Called changesize"); 1943 m_log.DebugFormat("[ODE PRIM]: Called changesize");
1893#endif 1944#endif
1894 1945
1895 string oldname = _parent_scene.geom_name_map[prim_geom];
1896
1897 if (_size.X <= 0) _size.X = 0.01f; 1946 if (_size.X <= 0) _size.X = 0.01f;
1898 if (_size.Y <= 0) _size.Y = 0.01f; 1947 if (_size.Y <= 0) _size.Y = 0.01f;
1899 if (_size.Z <= 0) _size.Z = 0.01f; 1948 if (_size.Z <= 0) _size.Z = 0.01f;
1900 1949
1901 // Cleanup of old prim geometry
1902 if (_mesh != null)
1903 {
1904 // TODO: Cleanup meshing here
1905 }
1906
1907 //kill body to rebuild 1950 //kill body to rebuild
1908 if (IsPhysical && Body != IntPtr.Zero) 1951 if (IsPhysical && Body != IntPtr.Zero)
1909 { 1952 {
@@ -1927,10 +1970,12 @@ Console.WriteLine(" JointCreateFixed");
1927 d.SpaceRemove(m_targetSpace, prim_geom); 1970 d.SpaceRemove(m_targetSpace, prim_geom);
1928 } 1971 }
1929 1972
1930 d.GeomDestroy(prim_geom); 1973 RemoveGeom();
1931 prim_geom = IntPtr.Zero; 1974
1932 // we don't need to do space calculation because the client sends a position update also. 1975 // we don't need to do space calculation because the client sends a position update also.
1933 1976
1977 IMesh mesh = null;
1978
1934 // Construction of new prim 1979 // Construction of new prim
1935 if (_parent_scene.needsMeshing(_pbs)) 1980 if (_parent_scene.needsMeshing(_pbs))
1936 { 1981 {
@@ -1940,27 +1985,11 @@ Console.WriteLine(" JointCreateFixed");
1940 meshlod = _parent_scene.MeshSculptphysicalLOD; 1985 meshlod = _parent_scene.MeshSculptphysicalLOD;
1941 // Don't need to re-enable body.. it's done in SetMesh 1986 // Don't need to re-enable body.. it's done in SetMesh
1942 1987
1943 IMesh mesh = null;
1944
1945 if (_parent_scene.needsMeshing(_pbs)) 1988 if (_parent_scene.needsMeshing(_pbs))
1946 mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); 1989 mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, meshlod, IsPhysical);
1947
1948#if SPAM
1949Console.WriteLine("changesize 1");
1950#endif
1951 CreateGeom(m_targetSpace, mesh);
1952 }
1953 else
1954 {
1955 _mesh = null;
1956
1957#if SPAM
1958Console.WriteLine("changesize 2");
1959#endif
1960
1961 CreateGeom(m_targetSpace, _mesh);
1962 } 1990 }
1963 1991
1992 CreateGeom(m_targetSpace, mesh);
1964 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); 1993 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
1965 d.Quaternion myrot = new d.Quaternion(); 1994 d.Quaternion myrot = new d.Quaternion();
1966 myrot.X = _orientation.X; 1995 myrot.X = _orientation.X;
@@ -1978,8 +2007,6 @@ Console.WriteLine("changesize 2");
1978 d.BodyEnable(Body); 2007 d.BodyEnable(Body);
1979 } 2008 }
1980 2009
1981 _parent_scene.geom_name_map[prim_geom] = oldname;
1982
1983 changeSelectedStatus(timestamp); 2010 changeSelectedStatus(timestamp);
1984 if (childPrim) 2011 if (childPrim)
1985 { 2012 {
@@ -2013,8 +2040,6 @@ Console.WriteLine("changesize 2");
2013 2040
2014 public void changeshape(float timestamp) 2041 public void changeshape(float timestamp)
2015 { 2042 {
2016 string oldname = _parent_scene.geom_name_map[prim_geom];
2017
2018 // Cleanup of old prim geometry and Bodies 2043 // Cleanup of old prim geometry and Bodies
2019 if (IsPhysical && Body != IntPtr.Zero) 2044 if (IsPhysical && Body != IntPtr.Zero)
2020 { 2045 {
@@ -2031,23 +2056,17 @@ Console.WriteLine("changesize 2");
2031 disableBody(); 2056 disableBody();
2032 } 2057 }
2033 } 2058 }
2034 try
2035 {
2036 d.GeomDestroy(prim_geom);
2037 }
2038 catch (System.AccessViolationException)
2039 {
2040 prim_geom = IntPtr.Zero;
2041 m_log.ErrorFormat("[PHYSICS]: PrimGeom dead for {0}", Name);
2042 }
2043 2059
2044 prim_geom = IntPtr.Zero; 2060 RemoveGeom();
2061
2045 // we don't need to do space calculation because the client sends a position update also. 2062 // we don't need to do space calculation because the client sends a position update also.
2046 if (_size.X <= 0) _size.X = 0.01f; 2063 if (_size.X <= 0) _size.X = 0.01f;
2047 if (_size.Y <= 0) _size.Y = 0.01f; 2064 if (_size.Y <= 0) _size.Y = 0.01f;
2048 if (_size.Z <= 0) _size.Z = 0.01f; 2065 if (_size.Z <= 0) _size.Z = 0.01f;
2049 // Construction of new prim 2066 // Construction of new prim
2050 2067
2068 IMesh mesh = null;
2069
2051 if (_parent_scene.needsMeshing(_pbs)) 2070 if (_parent_scene.needsMeshing(_pbs))
2052 { 2071 {
2053 // Don't need to re-enable body.. it's done in CreateMesh 2072 // Don't need to re-enable body.. it's done in CreateMesh
@@ -2057,22 +2076,10 @@ Console.WriteLine("changesize 2");
2057 meshlod = _parent_scene.MeshSculptphysicalLOD; 2076 meshlod = _parent_scene.MeshSculptphysicalLOD;
2058 2077
2059 // createmesh returns null when it doesn't mesh. 2078 // createmesh returns null when it doesn't mesh.
2060 IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); 2079 mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, meshlod, IsPhysical);
2061#if SPAM
2062Console.WriteLine("changeshape needed meshing");
2063#endif
2064 CreateGeom(m_targetSpace, mesh);
2065 }
2066 else
2067 {
2068 _mesh = null;
2069
2070#if SPAM
2071Console.WriteLine("changeshape not need meshing");
2072#endif
2073 CreateGeom(m_targetSpace, null);
2074 } 2080 }
2075 2081
2082 CreateGeom(m_targetSpace, mesh);
2076 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); 2083 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
2077 d.Quaternion myrot = new d.Quaternion(); 2084 d.Quaternion myrot = new d.Quaternion();
2078 //myrot.W = _orientation.w; 2085 //myrot.W = _orientation.w;
@@ -2093,7 +2100,6 @@ Console.WriteLine("changeshape not need meshing");
2093 d.BodyEnable(Body); 2100 d.BodyEnable(Body);
2094 } 2101 }
2095 } 2102 }
2096 _parent_scene.geom_name_map[prim_geom] = oldname;
2097 2103
2098 changeSelectedStatus(timestamp); 2104 changeSelectedStatus(timestamp);
2099 if (childPrim) 2105 if (childPrim)
@@ -2216,16 +2222,6 @@ Console.WriteLine("changeshape not need meshing");
2216 m_taintVelocity = Vector3.Zero; 2222 m_taintVelocity = Vector3.Zero;
2217 } 2223 }
2218 2224
2219 public override bool IsPhysical
2220 {
2221 get { return m_isphysical; }
2222 set {
2223 m_isphysical = value;
2224 if (!m_isphysical) // Zero the remembered last velocity
2225 m_lastVelocity = Vector3.Zero;
2226 }
2227 }
2228
2229 public void setPrimForRemoval() 2225 public void setPrimForRemoval()
2230 { 2226 {
2231 m_taintremove = true; 2227 m_taintremove = true;
@@ -2404,7 +2400,7 @@ Console.WriteLine("changeshape not need meshing");
2404 { 2400 {
2405 get 2401 get
2406 { 2402 {
2407 if (!m_isphysical || Body == IntPtr.Zero) 2403 if (!IsPhysical || Body == IntPtr.Zero)
2408 return Vector3.Zero; 2404 return Vector3.Zero;
2409 2405
2410 return _torque; 2406 return _torque;
@@ -2986,12 +2982,12 @@ Console.WriteLine("changeshape not need meshing");
2986 public override void SubscribeEvents(int ms) 2982 public override void SubscribeEvents(int ms)
2987 { 2983 {
2988 m_eventsubscription = ms; 2984 m_eventsubscription = ms;
2989 _parent_scene.addCollisionEventReporting(this); 2985 _parent_scene.AddCollisionEventReporting(this);
2990 } 2986 }
2991 2987
2992 public override void UnSubscribeEvents() 2988 public override void UnSubscribeEvents()
2993 { 2989 {
2994 _parent_scene.remCollisionEventReporting(this); 2990 _parent_scene.RemoveCollisionEventReporting(this);
2995 m_eventsubscription = 0; 2991 m_eventsubscription = 0;
2996 } 2992 }
2997 2993
@@ -2999,6 +2995,7 @@ Console.WriteLine("changeshape not need meshing");
2999 { 2995 {
3000 if (CollisionEventsThisFrame == null) 2996 if (CollisionEventsThisFrame == null)
3001 CollisionEventsThisFrame = new CollisionEventUpdate(); 2997 CollisionEventsThisFrame = new CollisionEventUpdate();
2998
3002 CollisionEventsThisFrame.addCollider(CollidedWith, contact); 2999 CollisionEventsThisFrame.addCollider(CollidedWith, contact);
3003 } 3000 }
3004 3001
diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
index a307469..6e603e8 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
@@ -100,7 +100,7 @@ namespace OpenSim.Region.Physics.OdePlugin
100 Rubber = 6 100 Rubber = 6
101 } 101 }
102 102
103 public sealed class OdeScene : PhysicsScene 103 public class OdeScene : PhysicsScene
104 { 104 {
105 private readonly ILog m_log; 105 private readonly ILog m_log;
106 // private Dictionary<string, sCollisionData> m_storedCollisions = new Dictionary<string, sCollisionData>(); 106 // private Dictionary<string, sCollisionData> m_storedCollisions = new Dictionary<string, sCollisionData>();
@@ -198,7 +198,12 @@ namespace OpenSim.Region.Physics.OdePlugin
198 private readonly List<OdePrim> _taintedPrimL = new List<OdePrim>(); 198 private readonly List<OdePrim> _taintedPrimL = new List<OdePrim>();
199 private readonly HashSet<OdeCharacter> _taintedActors = new HashSet<OdeCharacter>(); 199 private readonly HashSet<OdeCharacter> _taintedActors = new HashSet<OdeCharacter>();
200 private readonly List<d.ContactGeom> _perloopContact = new List<d.ContactGeom>(); 200 private readonly List<d.ContactGeom> _perloopContact = new List<d.ContactGeom>();
201
202 /// <summary>
203 /// A list of actors that should receive collision events.
204 /// </summary>
201 private readonly List<PhysicsActor> _collisionEventPrim = new List<PhysicsActor>(); 205 private readonly List<PhysicsActor> _collisionEventPrim = new List<PhysicsActor>();
206
202 private readonly HashSet<OdeCharacter> _badCharacter = new HashSet<OdeCharacter>(); 207 private readonly HashSet<OdeCharacter> _badCharacter = new HashSet<OdeCharacter>();
203 public Dictionary<IntPtr, String> geom_name_map = new Dictionary<IntPtr, String>(); 208 public Dictionary<IntPtr, String> geom_name_map = new Dictionary<IntPtr, String>();
204 public Dictionary<IntPtr, PhysicsActor> actor_name_map = new Dictionary<IntPtr, PhysicsActor>(); 209 public Dictionary<IntPtr, PhysicsActor> actor_name_map = new Dictionary<IntPtr, PhysicsActor>();
@@ -299,7 +304,6 @@ namespace OpenSim.Region.Physics.OdePlugin
299 // Create the world and the first space 304 // Create the world and the first space
300 world = d.WorldCreate(); 305 world = d.WorldCreate();
301 space = d.HashSpaceCreate(IntPtr.Zero); 306 space = d.HashSpaceCreate(IntPtr.Zero);
302
303 307
304 contactgroup = d.JointGroupCreate(0); 308 contactgroup = d.JointGroupCreate(0);
305 //contactgroup 309 //contactgroup
@@ -952,7 +956,6 @@ namespace OpenSim.Region.Physics.OdePlugin
952 character.SetPidStatus(true); 956 character.SetPidStatus(true);
953 } 957 }
954 } 958 }
955
956 959
957 if (p1.PhysicsActorType == (int) ActorTypes.Agent) 960 if (p1.PhysicsActorType == (int) ActorTypes.Agent)
958 { 961 {
@@ -1053,9 +1056,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1053 { 1056 {
1054 joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, movintYN]); 1057 joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, movintYN]);
1055 m_global_contactcount++; 1058 m_global_contactcount++;
1056
1057 } 1059 }
1058
1059 } 1060 }
1060 else 1061 else
1061 { 1062 {
@@ -1078,7 +1079,6 @@ namespace OpenSim.Region.Physics.OdePlugin
1078 { 1079 {
1079 joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, movintYN]); 1080 joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, movintYN]);
1080 m_global_contactcount++; 1081 m_global_contactcount++;
1081
1082 } 1082 }
1083 } 1083 }
1084 } 1084 }
@@ -1290,6 +1290,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1290 1290
1291 //returncollisions = true; 1291 //returncollisions = true;
1292 break; 1292 break;
1293
1293 case ActorTypes.Prim: 1294 case ActorTypes.Prim:
1294 if (p1 is OdePrim) 1295 if (p1 is OdePrim)
1295 { 1296 {
@@ -1317,6 +1318,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1317 1318
1318 cc2.AddCollisionEvent(obj2LocalID, contact); 1319 cc2.AddCollisionEvent(obj2LocalID, contact);
1319 break; 1320 break;
1321
1320 case ActorTypes.Prim: 1322 case ActorTypes.Prim:
1321 1323
1322 if (p2 is OdePrim) 1324 if (p2 is OdePrim)
@@ -1421,18 +1423,18 @@ namespace OpenSim.Region.Physics.OdePlugin
1421 1423
1422 public int TriCallback(IntPtr trimesh, IntPtr refObject, int triangleIndex) 1424 public int TriCallback(IntPtr trimesh, IntPtr refObject, int triangleIndex)
1423 { 1425 {
1424 String name1 = null; 1426// String name1 = null;
1425 String name2 = null; 1427// String name2 = null;
1426 1428//
1427 if (!geom_name_map.TryGetValue(trimesh, out name1)) 1429// if (!geom_name_map.TryGetValue(trimesh, out name1))
1428 { 1430// {
1429 name1 = "null"; 1431// name1 = "null";
1430 } 1432// }
1431 1433//
1432 if (!geom_name_map.TryGetValue(refObject, out name2)) 1434// if (!geom_name_map.TryGetValue(refObject, out name2))
1433 { 1435// {
1434 name2 = "null"; 1436// name2 = "null";
1435 } 1437// }
1436 1438
1437 // m_log.InfoFormat("TriCallback: A collision was detected between {1} and {2}. Index was {3}", 0, name1, name2, triangleIndex); 1439 // m_log.InfoFormat("TriCallback: A collision was detected between {1} and {2}. Index was {3}", 0, name1, name2, triangleIndex);
1438 1440
@@ -1604,7 +1606,11 @@ namespace OpenSim.Region.Physics.OdePlugin
1604 } 1606 }
1605// End recovered. Kitto Flora 1607// End recovered. Kitto Flora
1606 1608
1607 public void addCollisionEventReporting(PhysicsActor obj) 1609 /// <summary>
1610 /// Add actor to the list that should receive collision events in the simulate loop.
1611 /// </summary>
1612 /// <param name="obj"></param>
1613 public void AddCollisionEventReporting(PhysicsActor obj)
1608 { 1614 {
1609 lock (_collisionEventPrim) 1615 lock (_collisionEventPrim)
1610 { 1616 {
@@ -1613,7 +1619,11 @@ namespace OpenSim.Region.Physics.OdePlugin
1613 } 1619 }
1614 } 1620 }
1615 1621
1616 public void remCollisionEventReporting(PhysicsActor obj) 1622 /// <summary>
1623 /// Remove actor from the list that should receive collision events in the simulate loop.
1624 /// </summary>
1625 /// <param name="obj"></param>
1626 public void RemoveCollisionEventReporting(PhysicsActor obj)
1617 { 1627 {
1618 lock (_collisionEventPrim) 1628 lock (_collisionEventPrim)
1619 { 1629 {
@@ -1677,7 +1687,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1677 } 1687 }
1678 1688
1679 private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation, 1689 private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation,
1680 IMesh mesh, PrimitiveBaseShape pbs, bool isphysical, uint localID) 1690 PrimitiveBaseShape pbs, bool isphysical, uint localID)
1681 { 1691 {
1682 Vector3 pos = position; 1692 Vector3 pos = position;
1683 Vector3 siz = size; 1693 Vector3 siz = size;
@@ -1686,7 +1696,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1686 OdePrim newPrim; 1696 OdePrim newPrim;
1687 lock (OdeLock) 1697 lock (OdeLock)
1688 { 1698 {
1689 newPrim = new OdePrim(name, this, pos, siz, rot, mesh, pbs, isphysical, ode); 1699 newPrim = new OdePrim(name, this, pos, siz, rot, pbs, isphysical, ode);
1690 1700
1691 lock (_prims) 1701 lock (_prims)
1692 _prims.Add(newPrim); 1702 _prims.Add(newPrim);
@@ -1714,28 +1724,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1714 m_log.DebugFormat("[PHYSICS]: Adding physics actor to {0}", primName); 1724 m_log.DebugFormat("[PHYSICS]: Adding physics actor to {0}", primName);
1715#endif 1725#endif
1716 1726
1717 PhysicsActor result; 1727 return AddPrim(primName, position, size, rotation, pbs, isPhysical, localid);
1718 IMesh mesh = null;
1719
1720 // Don't create the mesh here - wait until the mesh data is loaded from the asset store.
1721// if (needsMeshing(pbs))
1722// {
1723// try
1724// {
1725// mesh = mesher.CreateMesh(primName, pbs, size, 32f, isPhysical);
1726// }
1727// catch(Exception e)
1728// {
1729// m_log.ErrorFormat("[PHYSICS]: Exception while meshing prim {0}.", primName);
1730// m_log.Debug(e.ToString());
1731// mesh = null;
1732// return null;
1733// }
1734// }
1735
1736 result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical, localid);
1737
1738 return result;
1739 } 1728 }
1740 1729
1741 public override float TimeDilation 1730 public override float TimeDilation
@@ -2105,6 +2094,8 @@ namespace OpenSim.Region.Physics.OdePlugin
2105 2094
2106 public override void RemovePrim(PhysicsActor prim) 2095 public override void RemovePrim(PhysicsActor prim)
2107 { 2096 {
2097 // As with all ODE physics operations, we don't remove the prim immediately but signal that it should be
2098 // removed in the next physics simulate pass.
2108 if (prim is OdePrim) 2099 if (prim is OdePrim)
2109 { 2100 {
2110 lock (OdeLock) 2101 lock (OdeLock)
@@ -2121,6 +2112,9 @@ namespace OpenSim.Region.Physics.OdePlugin
2121 /// <summary> 2112 /// <summary>
2122 /// This is called from within simulate but outside the locked portion 2113 /// This is called from within simulate but outside the locked portion
2123 /// We need to do our own locking here 2114 /// We need to do our own locking here
2115 /// (Note: As of 20110801 this no longer appears to be true - this is being called within lock (odeLock) in
2116 /// Simulate() -- justincc).
2117 ///
2124 /// Essentially, we need to remove the prim from our space segment, whatever segment it's in. 2118 /// Essentially, we need to remove the prim from our space segment, whatever segment it's in.
2125 /// 2119 ///
2126 /// If there are no more prim in the segment, we need to empty (spacedestroy)the segment and reclaim memory 2120 /// If there are no more prim in the segment, we need to empty (spacedestroy)the segment and reclaim memory
@@ -2132,7 +2126,7 @@ namespace OpenSim.Region.Physics.OdePlugin
2132//Console.WriteLine("RemovePrimThreadLocked " + prim.m_primName); 2126//Console.WriteLine("RemovePrimThreadLocked " + prim.m_primName);
2133 lock (prim) 2127 lock (prim)
2134 { 2128 {
2135 remCollisionEventReporting(prim); 2129 RemoveCollisionEventReporting(prim);
2136 lock (ode) 2130 lock (ode)
2137 { 2131 {
2138 if (prim.prim_geom != IntPtr.Zero) 2132 if (prim.prim_geom != IntPtr.Zero)
@@ -2177,24 +2171,12 @@ namespace OpenSim.Region.Physics.OdePlugin
2177 //} 2171 //}
2178 //} 2172 //}
2179 //m_log.Warn(prim.prim_geom); 2173 //m_log.Warn(prim.prim_geom);
2180 try 2174
2181 { 2175 if (!prim.RemoveGeom())
2182 if (prim.prim_geom != IntPtr.Zero) 2176 m_log.Warn("[PHYSICS]: Unable to remove prim from physics scene");
2183 { 2177
2184 d.GeomDestroy(prim.prim_geom);
2185 prim.prim_geom = IntPtr.Zero;
2186 }
2187 else
2188 {
2189 m_log.Warn("[PHYSICS]: Unable to remove prim from physics scene");
2190 }
2191 }
2192 catch (AccessViolationException)
2193 {
2194 m_log.Info("[PHYSICS]: Couldn't remove prim from physics scene, it was already be removed.");
2195 }
2196 lock (_prims) 2178 lock (_prims)
2197 _prims.Remove(prim); 2179 _prims.Remove(prim);
2198 2180
2199 //If there are no more geometries in the sub-space, we don't need it in the main space anymore 2181 //If there are no more geometries in the sub-space, we don't need it in the main space anymore
2200 //if (d.SpaceGetNumGeoms(prim.m_targetSpace) == 0) 2182 //if (d.SpaceGetNumGeoms(prim.m_targetSpace) == 0)
@@ -2687,320 +2669,148 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name);
2687 //if (!ode.lockquery()) 2669 //if (!ode.lockquery())
2688 //{ 2670 //{
2689 // ode.dlock(world); 2671 // ode.dlock(world);
2690 try
2691 {
2692 // Insert, remove Characters
2693 bool processedtaints = false;
2694 2672
2695 lock (_taintedActors) 2673 try
2696 { 2674 {
2697 if (_taintedActors.Count > 0) 2675 // Insert, remove Characters
2698 { 2676 bool processedtaints = false;
2699 foreach (OdeCharacter character in _taintedActors)
2700 {
2701 character.ProcessTaints(timeStep);
2702 2677
2703 processedtaints = true; 2678 lock (_taintedActors)
2704 //character.m_collisionscore = 0; 2679 {
2705 } 2680 if (_taintedActors.Count > 0)
2681 {
2682 foreach (OdeCharacter character in _taintedActors)
2683 {
2684 character.ProcessTaints(timeStep);
2706 2685
2707 if (processedtaints) 2686 processedtaints = true;
2708 _taintedActors.Clear(); 2687 //character.m_collisionscore = 0;
2709 }
2710 } 2688 }
2711 2689
2712 // Modify other objects in the scene. 2690 if (processedtaints)
2713 processedtaints = false; 2691 _taintedActors.Clear();
2692 }
2693 }
2694
2695 // Modify other objects in the scene.
2696 processedtaints = false;
2714 2697
2715 lock (_taintedPrimLock) 2698 lock (_taintedPrimLock)
2699 {
2700 foreach (OdePrim prim in _taintedPrimL)
2701 {
2702 if (prim.m_taintremove)
2716 { 2703 {
2717 foreach (OdePrim prim in _taintedPrimL) 2704// Console.WriteLine("Simulate calls RemovePrimThreadLocked for {0}", prim.Name);
2718 { 2705 RemovePrimThreadLocked(prim);
2719 if (prim.m_taintremove) 2706 }
2720 { 2707 else
2721 //Console.WriteLine("Simulate calls RemovePrimThreadLocked"); 2708 {
2722 RemovePrimThreadLocked(prim); 2709// Console.WriteLine("Simulate calls ProcessTaints for {0}", prim.Name);
2723 } 2710 prim.ProcessTaints(timeStep);
2724 else 2711 }
2725 {
2726 //Console.WriteLine("Simulate calls ProcessTaints");
2727 prim.ProcessTaints(timeStep);
2728 }
2729 processedtaints = true;
2730 prim.m_collisionscore = 0;
2731
2732 // This loop can block up the Heartbeat for a very long time on large regions.
2733 // We need to let the Watchdog know that the Heartbeat is not dead
2734 // NOTE: This is currently commented out, but if things like OAR loading are
2735 // timing the heartbeat out we will need to uncomment it
2736 //Watchdog.UpdateThread();
2737 }
2738 2712
2739 if (SupportsNINJAJoints) 2713 processedtaints = true;
2740 { 2714 prim.m_collisionscore = 0;
2741 // Create pending joints, if possible
2742 2715
2743 // joints can only be processed after ALL bodies are processed (and exist in ODE), since creating 2716 // This loop can block up the Heartbeat for a very long time on large regions.
2744 // a joint requires specifying the body id of both involved bodies 2717 // We need to let the Watchdog know that the Heartbeat is not dead
2745 if (pendingJoints.Count > 0) 2718 // NOTE: This is currently commented out, but if things like OAR loading are
2746 { 2719 // timing the heartbeat out we will need to uncomment it
2747 List<PhysicsJoint> successfullyProcessedPendingJoints = new List<PhysicsJoint>(); 2720 //Watchdog.UpdateThread();
2748 //DoJointErrorMessage(joints_connecting_actor, "taint: " + pendingJoints.Count + " pending joints"); 2721 }
2749 foreach (PhysicsJoint joint in pendingJoints)
2750 {
2751 //DoJointErrorMessage(joint, "taint: time to create joint with parms: " + joint.RawParams);
2752 string[] jointParams = joint.RawParams.Split(" ".ToCharArray(), System.StringSplitOptions.RemoveEmptyEntries);
2753 List<IntPtr> jointBodies = new List<IntPtr>();
2754 bool allJointBodiesAreReady = true;
2755 foreach (string jointParam in jointParams)
2756 {
2757 if (jointParam == "NULL")
2758 {
2759 //DoJointErrorMessage(joint, "attaching NULL joint to world");
2760 jointBodies.Add(IntPtr.Zero);
2761 }
2762 else
2763 {
2764 //DoJointErrorMessage(joint, "looking for prim name: " + jointParam);
2765 bool foundPrim = false;
2766 lock (_prims)
2767 {
2768 foreach (OdePrim prim in _prims) // FIXME: inefficient
2769 {
2770 if (prim.SOPName == jointParam)
2771 {
2772 //DoJointErrorMessage(joint, "found for prim name: " + jointParam);
2773 if (prim.IsPhysical && prim.Body != IntPtr.Zero)
2774 {
2775 jointBodies.Add(prim.Body);
2776 foundPrim = true;
2777 break;
2778 }
2779 else
2780 {
2781 DoJointErrorMessage(joint, "prim name " + jointParam +
2782 " exists but is not (yet) physical; deferring joint creation. " +
2783 "IsPhysical property is " + prim.IsPhysical +
2784 " and body is " + prim.Body);
2785 foundPrim = false;
2786 break;
2787 }
2788 }
2789 }
2790 }
2791 if (foundPrim)
2792 {
2793 // all is fine
2794 }
2795 else
2796 {
2797 allJointBodiesAreReady = false;
2798 break;
2799 }
2800 }
2801 }
2802 if (allJointBodiesAreReady)
2803 {
2804 //DoJointErrorMessage(joint, "allJointBodiesAreReady for " + joint.ObjectNameInScene + " with parms " + joint.RawParams);
2805 if (jointBodies[0] == jointBodies[1])
2806 {
2807 DoJointErrorMessage(joint, "ERROR: joint cannot be created; the joint bodies are the same, body1==body2. Raw body is " + jointBodies[0] + ". raw parms: " + joint.RawParams);
2808 }
2809 else
2810 {
2811 switch (joint.Type)
2812 {
2813 case PhysicsJointType.Ball:
2814 {
2815 IntPtr odeJoint;
2816 //DoJointErrorMessage(joint, "ODE creating ball joint ");
2817 odeJoint = d.JointCreateBall(world, IntPtr.Zero);
2818 //DoJointErrorMessage(joint, "ODE attaching ball joint: " + odeJoint + " with b1:" + jointBodies[0] + " b2:" + jointBodies[1]);
2819 d.JointAttach(odeJoint, jointBodies[0], jointBodies[1]);
2820 //DoJointErrorMessage(joint, "ODE setting ball anchor: " + odeJoint + " to vec:" + joint.Position);
2821 d.JointSetBallAnchor(odeJoint,
2822 joint.Position.X,
2823 joint.Position.Y,
2824 joint.Position.Z);
2825 //DoJointErrorMessage(joint, "ODE joint setting OK");
2826 //DoJointErrorMessage(joint, "The ball joint's bodies are here: b0: ");
2827 //DoJointErrorMessage(joint, "" + (jointBodies[0] != IntPtr.Zero ? "" + d.BodyGetPosition(jointBodies[0]) : "fixed environment"));
2828 //DoJointErrorMessage(joint, "The ball joint's bodies are here: b1: ");
2829 //DoJointErrorMessage(joint, "" + (jointBodies[1] != IntPtr.Zero ? "" + d.BodyGetPosition(jointBodies[1]) : "fixed environment"));
2830
2831 if (joint is OdePhysicsJoint)
2832 {
2833 ((OdePhysicsJoint)joint).jointID = odeJoint;
2834 }
2835 else
2836 {
2837 DoJointErrorMessage(joint, "WARNING: non-ode joint in ODE!");
2838 }
2839 }
2840 break;
2841 case PhysicsJointType.Hinge:
2842 {
2843 IntPtr odeJoint;
2844 //DoJointErrorMessage(joint, "ODE creating hinge joint ");
2845 odeJoint = d.JointCreateHinge(world, IntPtr.Zero);
2846 //DoJointErrorMessage(joint, "ODE attaching hinge joint: " + odeJoint + " with b1:" + jointBodies[0] + " b2:" + jointBodies[1]);
2847 d.JointAttach(odeJoint, jointBodies[0], jointBodies[1]);
2848 //DoJointErrorMessage(joint, "ODE setting hinge anchor: " + odeJoint + " to vec:" + joint.Position);
2849 d.JointSetHingeAnchor(odeJoint,
2850 joint.Position.X,
2851 joint.Position.Y,
2852 joint.Position.Z);
2853 // We use the orientation of the x-axis of the joint's coordinate frame
2854 // as the axis for the hinge.
2855
2856 // Therefore, we must get the joint's coordinate frame based on the
2857 // joint.Rotation field, which originates from the orientation of the
2858 // joint's proxy object in the scene.
2859
2860 // The joint's coordinate frame is defined as the transformation matrix
2861 // that converts a vector from joint-local coordinates into world coordinates.
2862 // World coordinates are defined as the XYZ coordinate system of the sim,
2863 // as shown in the top status-bar of the viewer.
2864
2865 // Once we have the joint's coordinate frame, we extract its X axis (AtAxis)
2866 // and use that as the hinge axis.
2867
2868 //joint.Rotation.Normalize();
2869 Matrix4 proxyFrame = Matrix4.CreateFromQuaternion(joint.Rotation);
2870
2871 // Now extract the X axis of the joint's coordinate frame.
2872
2873 // Do not try to use proxyFrame.AtAxis or you will become mired in the
2874 // tar pit of transposed, inverted, and generally messed-up orientations.
2875 // (In other words, Matrix4.AtAxis() is borked.)
2876 // Vector3 jointAxis = proxyFrame.AtAxis; <--- this path leadeth to madness
2877
2878 // Instead, compute the X axis of the coordinate frame by transforming
2879 // the (1,0,0) vector. At least that works.
2880
2881 //m_log.Debug("PHY: making axis: complete matrix is " + proxyFrame);
2882 Vector3 jointAxis = Vector3.Transform(Vector3.UnitX, proxyFrame);
2883 //m_log.Debug("PHY: making axis: hinge joint axis is " + jointAxis);
2884 //DoJointErrorMessage(joint, "ODE setting hinge axis: " + odeJoint + " to vec:" + jointAxis);
2885 d.JointSetHingeAxis(odeJoint,
2886 jointAxis.X,
2887 jointAxis.Y,
2888 jointAxis.Z);
2889 //d.JointSetHingeParam(odeJoint, (int)dParam.CFM, 0.1f);
2890 if (joint is OdePhysicsJoint)
2891 {
2892 ((OdePhysicsJoint)joint).jointID = odeJoint;
2893 }
2894 else
2895 {
2896 DoJointErrorMessage(joint, "WARNING: non-ode joint in ODE!");
2897 }
2898 }
2899 break;
2900 }
2901 successfullyProcessedPendingJoints.Add(joint);
2902 }
2903 }
2904 else
2905 {
2906 DoJointErrorMessage(joint, "joint could not yet be created; still pending");
2907 }
2908 }
2909 foreach (PhysicsJoint successfullyProcessedJoint in successfullyProcessedPendingJoints)
2910 {
2911 //DoJointErrorMessage(successfullyProcessedJoint, "finalizing succesfully procsssed joint " + successfullyProcessedJoint.ObjectNameInScene + " parms " + successfullyProcessedJoint.RawParams);
2912 //DoJointErrorMessage(successfullyProcessedJoint, "removing from pending");
2913 InternalRemovePendingJoint(successfullyProcessedJoint);
2914 //DoJointErrorMessage(successfullyProcessedJoint, "adding to active");
2915 InternalAddActiveJoint(successfullyProcessedJoint);
2916 //DoJointErrorMessage(successfullyProcessedJoint, "done");
2917 }
2918 }
2919 }
2920 2722
2921 if (processedtaints) 2723 if (SupportsNINJAJoints)
2724 SimulatePendingNINJAJoints();
2725
2726 if (processedtaints)
2727 {
2922//Console.WriteLine("Simulate calls Clear of _taintedPrim list"); 2728//Console.WriteLine("Simulate calls Clear of _taintedPrim list");
2923 _taintedPrimH.Clear(); 2729 _taintedPrimH.Clear();
2924 _taintedPrimL.Clear(); 2730 _taintedPrimL.Clear();
2925 } 2731 }
2732 }
2926 2733
2927 // Move characters 2734 // Move characters
2928 lock (_characters) 2735 lock (_characters)
2736 {
2737 List<OdeCharacter> defects = new List<OdeCharacter>();
2738 foreach (OdeCharacter actor in _characters)
2739 {
2740 if (actor != null)
2741 actor.Move(timeStep, defects);
2742 }
2743 if (0 != defects.Count)
2744 {
2745 foreach (OdeCharacter defect in defects)
2929 { 2746 {
2930 List<OdeCharacter> defects = new List<OdeCharacter>(); 2747 RemoveCharacter(defect);
2931 foreach (OdeCharacter actor in _characters)
2932 {
2933 if (actor != null)
2934 actor.Move(timeStep, defects);
2935 }
2936 if (0 != defects.Count)
2937 {
2938 foreach (OdeCharacter defect in defects)
2939 {
2940 RemoveCharacter(defect);
2941 }
2942 }
2943 } 2748 }
2749 }
2750 }
2944 2751
2945 // Move other active objects 2752 // Move other active objects
2946 lock (_activeprims) 2753 lock (_activeprims)
2947 { 2754 {
2948 foreach (OdePrim prim in _activeprims) 2755 foreach (OdePrim prim in _activeprims)
2949 { 2756 {
2950 prim.m_collisionscore = 0; 2757 prim.m_collisionscore = 0;
2951 prim.Move(timeStep); 2758 prim.Move(timeStep);
2952 } 2759 }
2953 } 2760 }
2761
2762 //if ((framecount % m_randomizeWater) == 0)
2763 // randomizeWater(waterlevel);
2954 2764
2955 //if ((framecount % m_randomizeWater) == 0) 2765 //int RayCastTimeMS = m_rayCastManager.ProcessQueuedRequests();
2956 // randomizeWater(waterlevel); 2766 m_rayCastManager.ProcessQueuedRequests();
2957 2767
2958 //int RayCastTimeMS = m_rayCastManager.ProcessQueuedRequests(); 2768 collision_optimized(timeStep);
2959 m_rayCastManager.ProcessQueuedRequests();
2960 2769
2961 collision_optimized(timeStep); 2770 lock (_collisionEventPrim)
2771 {
2772 foreach (PhysicsActor obj in _collisionEventPrim)
2773 {
2774 if (obj == null)
2775 continue;
2962 2776
2963 lock (_collisionEventPrim) 2777// m_log.DebugFormat("[PHYSICS]: Assessing {0} for collision events", obj.SOPName);
2778
2779 switch ((ActorTypes)obj.PhysicsActorType)
2964 { 2780 {
2965 foreach (PhysicsActor obj in _collisionEventPrim) 2781 case ActorTypes.Agent:
2966 { 2782 OdeCharacter cobj = (OdeCharacter)obj;
2967 if (obj == null) 2783 cobj.AddCollisionFrameTime(100);
2968 continue; 2784 cobj.SendCollisions();
2785 break;
2969 2786
2970 switch ((ActorTypes)obj.PhysicsActorType) 2787 case ActorTypes.Prim:
2971 { 2788 OdePrim pobj = (OdePrim)obj;
2972 case ActorTypes.Agent: 2789 pobj.SendCollisions();
2973 OdeCharacter cobj = (OdeCharacter)obj; 2790 break;
2974 cobj.AddCollisionFrameTime(100);
2975 cobj.SendCollisions();
2976 break;
2977 case ActorTypes.Prim:
2978 OdePrim pobj = (OdePrim)obj;
2979 pobj.SendCollisions();
2980 break;
2981 }
2982 }
2983 } 2791 }
2792 }
2793 }
2984 2794
2985 //if (m_global_contactcount > 5) 2795 //if (m_global_contactcount > 5)
2986 //{ 2796 //{
2987 // m_log.DebugFormat("[PHYSICS]: Contacts:{0}", m_global_contactcount); 2797 // m_log.DebugFormat("[PHYSICS]: Contacts:{0}", m_global_contactcount);
2988 //} 2798 //}
2989 2799
2990 m_global_contactcount = 0; 2800 m_global_contactcount = 0;
2991 2801
2992 d.WorldQuickStep(world, ODE_STEPSIZE); 2802 d.WorldQuickStep(world, ODE_STEPSIZE);
2993 d.JointGroupEmpty(contactgroup); 2803 d.JointGroupEmpty(contactgroup);
2994 //ode.dunlock(world); 2804 //ode.dunlock(world);
2995 } 2805 }
2996 catch (Exception e) 2806 catch (Exception e)
2997 { 2807 {
2998 m_log.ErrorFormat("[PHYSICS]: {0}, {1}, {2}", e.Message, e.TargetSite, e); 2808 m_log.ErrorFormat("[PHYSICS]: {0}, {1}, {2}", e.Message, e.TargetSite, e);
2999 ode.dunlock(world); 2809 ode.dunlock(world);
3000 } 2810 }
3001 2811
3002 step_time -= ODE_STEPSIZE; 2812 step_time -= ODE_STEPSIZE;
3003 i++; 2813 i++;
3004 //} 2814 //}
3005 //else 2815 //else
3006 //{ 2816 //{
@@ -3017,6 +2827,7 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name);
3017 { 2827 {
3018 if (actor.bad) 2828 if (actor.bad)
3019 m_log.WarnFormat("[PHYSICS]: BAD Actor {0} in _characters list was not removed?", actor.m_uuid); 2829 m_log.WarnFormat("[PHYSICS]: BAD Actor {0} in _characters list was not removed?", actor.m_uuid);
2830
3020 actor.UpdatePositionAndVelocity(); 2831 actor.UpdatePositionAndVelocity();
3021 } 2832 }
3022 } 2833 }
@@ -3030,6 +2841,7 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name);
3030 { 2841 {
3031 RemoveCharacter(chr); 2842 RemoveCharacter(chr);
3032 } 2843 }
2844
3033 _badCharacter.Clear(); 2845 _badCharacter.Clear();
3034 } 2846 }
3035 } 2847 }
@@ -3045,30 +2857,7 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name);
3045 actor.UpdatePositionAndVelocity(); 2857 actor.UpdatePositionAndVelocity();
3046 2858
3047 if (SupportsNINJAJoints) 2859 if (SupportsNINJAJoints)
3048 { 2860 SimulateActorPendingJoints(actor);
3049 // If an actor moved, move its joint proxy objects as well.
3050 // There seems to be an event PhysicsActor.OnPositionUpdate that could be used
3051 // for this purpose but it is never called! So we just do the joint
3052 // movement code here.
3053
3054 if (actor.SOPName != null &&
3055 joints_connecting_actor.ContainsKey(actor.SOPName) &&
3056 joints_connecting_actor[actor.SOPName] != null &&
3057 joints_connecting_actor[actor.SOPName].Count > 0)
3058 {
3059 foreach (PhysicsJoint affectedJoint in joints_connecting_actor[actor.SOPName])
3060 {
3061 if (affectedJoint.IsInPhysicsEngine)
3062 {
3063 DoJointMoved(affectedJoint);
3064 }
3065 else
3066 {
3067 DoJointErrorMessage(affectedJoint, "a body connected to a joint was moved, but the joint doesn't exist yet! this will lead to joint error. joint was: " + affectedJoint.ObjectNameInScene + " parms:" + affectedJoint.RawParams);
3068 }
3069 }
3070 }
3071 }
3072 } 2861 }
3073 } 2862 }
3074 } 2863 }
@@ -3079,7 +2868,7 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name);
3079 // Finished with all sim stepping. If requested, dump world state to file for debugging. 2868 // Finished with all sim stepping. If requested, dump world state to file for debugging.
3080 // TODO: This call to the export function is already inside lock (OdeLock) - but is an extra lock needed? 2869 // TODO: This call to the export function is already inside lock (OdeLock) - but is an extra lock needed?
3081 // TODO: This overwrites all dump files in-place. Should this be a growing logfile, or separate snapshots? 2870 // TODO: This overwrites all dump files in-place. Should this be a growing logfile, or separate snapshots?
3082 if (physics_logging && (physics_logging_interval>0) && (framecount % physics_logging_interval == 0)) 2871 if (physics_logging && (physics_logging_interval > 0) && (framecount % physics_logging_interval == 0))
3083 { 2872 {
3084 string fname = "state-" + world.ToString() + ".DIF"; // give each physics world a separate filename 2873 string fname = "state-" + world.ToString() + ".DIF"; // give each physics world a separate filename
3085 string prefix = "world" + world.ToString(); // prefix for variable names in exported .DIF file 2874 string prefix = "world" + world.ToString(); // prefix for variable names in exported .DIF file
@@ -3091,8 +2880,10 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name);
3091 fwriter.WriteLine(header); 2880 fwriter.WriteLine(header);
3092 fwriter.Close(); 2881 fwriter.Close();
3093 } 2882 }
2883
3094 d.WorldExportDIF(world, fname, physics_logging_append_existing_logfile, prefix); 2884 d.WorldExportDIF(world, fname, physics_logging_append_existing_logfile, prefix);
3095 } 2885 }
2886
3096 latertickcount = Util.EnvironmentTickCount() - tickCountFrameRun; 2887 latertickcount = Util.EnvironmentTickCount() - tickCountFrameRun;
3097 2888
3098 // OpenSimulator above does 10 fps. 10 fps = means that the main thread loop and physics 2889 // OpenSimulator above does 10 fps. 10 fps = means that the main thread loop and physics
@@ -3101,7 +2892,9 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name);
3101 // If Physics stalls, it takes longer which makes the tick count ms larger. 2892 // If Physics stalls, it takes longer which makes the tick count ms larger.
3102 2893
3103 if (latertickcount < 100) 2894 if (latertickcount < 100)
2895 {
3104 m_timeDilation = 1.0f; 2896 m_timeDilation = 1.0f;
2897 }
3105 else 2898 else
3106 { 2899 {
3107 m_timeDilation = 100f / latertickcount; 2900 m_timeDilation = 100f / latertickcount;
@@ -3114,6 +2907,229 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name);
3114 return fps; 2907 return fps;
3115 } 2908 }
3116 2909
2910 /// <summary>
2911 /// Simulate pending NINJA joints.
2912 /// </summary>
2913 /// <remarks>
2914 /// Called by the main Simulate() loop if NINJA joints are active. Should not be called from anywhere else.
2915 /// </remarks>
2916 protected void SimulatePendingNINJAJoints()
2917 {
2918 // Create pending joints, if possible
2919
2920 // joints can only be processed after ALL bodies are processed (and exist in ODE), since creating
2921 // a joint requires specifying the body id of both involved bodies
2922 if (pendingJoints.Count > 0)
2923 {
2924 List<PhysicsJoint> successfullyProcessedPendingJoints = new List<PhysicsJoint>();
2925 //DoJointErrorMessage(joints_connecting_actor, "taint: " + pendingJoints.Count + " pending joints");
2926 foreach (PhysicsJoint joint in pendingJoints)
2927 {
2928 //DoJointErrorMessage(joint, "taint: time to create joint with parms: " + joint.RawParams);
2929 string[] jointParams = joint.RawParams.Split(" ".ToCharArray(), System.StringSplitOptions.RemoveEmptyEntries);
2930 List<IntPtr> jointBodies = new List<IntPtr>();
2931 bool allJointBodiesAreReady = true;
2932 foreach (string jointParam in jointParams)
2933 {
2934 if (jointParam == "NULL")
2935 {
2936 //DoJointErrorMessage(joint, "attaching NULL joint to world");
2937 jointBodies.Add(IntPtr.Zero);
2938 }
2939 else
2940 {
2941 //DoJointErrorMessage(joint, "looking for prim name: " + jointParam);
2942 bool foundPrim = false;
2943 lock (_prims)
2944 {
2945 foreach (OdePrim prim in _prims) // FIXME: inefficient
2946 {
2947 if (prim.SOPName == jointParam)
2948 {
2949 //DoJointErrorMessage(joint, "found for prim name: " + jointParam);
2950 if (prim.IsPhysical && prim.Body != IntPtr.Zero)
2951 {
2952 jointBodies.Add(prim.Body);
2953 foundPrim = true;
2954 break;
2955 }
2956 else
2957 {
2958 DoJointErrorMessage(joint, "prim name " + jointParam +
2959 " exists but is not (yet) physical; deferring joint creation. " +
2960 "IsPhysical property is " + prim.IsPhysical +
2961 " and body is " + prim.Body);
2962 foundPrim = false;
2963 break;
2964 }
2965 }
2966 }
2967 }
2968 if (foundPrim)
2969 {
2970 // all is fine
2971 }
2972 else
2973 {
2974 allJointBodiesAreReady = false;
2975 break;
2976 }
2977 }
2978 }
2979
2980 if (allJointBodiesAreReady)
2981 {
2982 //DoJointErrorMessage(joint, "allJointBodiesAreReady for " + joint.ObjectNameInScene + " with parms " + joint.RawParams);
2983 if (jointBodies[0] == jointBodies[1])
2984 {
2985 DoJointErrorMessage(joint, "ERROR: joint cannot be created; the joint bodies are the same, body1==body2. Raw body is " + jointBodies[0] + ". raw parms: " + joint.RawParams);
2986 }
2987 else
2988 {
2989 switch (joint.Type)
2990 {
2991 case PhysicsJointType.Ball:
2992 {
2993 IntPtr odeJoint;
2994 //DoJointErrorMessage(joint, "ODE creating ball joint ");
2995 odeJoint = d.JointCreateBall(world, IntPtr.Zero);
2996 //DoJointErrorMessage(joint, "ODE attaching ball joint: " + odeJoint + " with b1:" + jointBodies[0] + " b2:" + jointBodies[1]);
2997 d.JointAttach(odeJoint, jointBodies[0], jointBodies[1]);
2998 //DoJointErrorMessage(joint, "ODE setting ball anchor: " + odeJoint + " to vec:" + joint.Position);
2999 d.JointSetBallAnchor(odeJoint,
3000 joint.Position.X,
3001 joint.Position.Y,
3002 joint.Position.Z);
3003 //DoJointErrorMessage(joint, "ODE joint setting OK");
3004 //DoJointErrorMessage(joint, "The ball joint's bodies are here: b0: ");
3005 //DoJointErrorMessage(joint, "" + (jointBodies[0] != IntPtr.Zero ? "" + d.BodyGetPosition(jointBodies[0]) : "fixed environment"));
3006 //DoJointErrorMessage(joint, "The ball joint's bodies are here: b1: ");
3007 //DoJointErrorMessage(joint, "" + (jointBodies[1] != IntPtr.Zero ? "" + d.BodyGetPosition(jointBodies[1]) : "fixed environment"));
3008
3009 if (joint is OdePhysicsJoint)
3010 {
3011 ((OdePhysicsJoint)joint).jointID = odeJoint;
3012 }
3013 else
3014 {
3015 DoJointErrorMessage(joint, "WARNING: non-ode joint in ODE!");
3016 }
3017 }
3018 break;
3019 case PhysicsJointType.Hinge:
3020 {
3021 IntPtr odeJoint;
3022 //DoJointErrorMessage(joint, "ODE creating hinge joint ");
3023 odeJoint = d.JointCreateHinge(world, IntPtr.Zero);
3024 //DoJointErrorMessage(joint, "ODE attaching hinge joint: " + odeJoint + " with b1:" + jointBodies[0] + " b2:" + jointBodies[1]);
3025 d.JointAttach(odeJoint, jointBodies[0], jointBodies[1]);
3026 //DoJointErrorMessage(joint, "ODE setting hinge anchor: " + odeJoint + " to vec:" + joint.Position);
3027 d.JointSetHingeAnchor(odeJoint,
3028 joint.Position.X,
3029 joint.Position.Y,
3030 joint.Position.Z);
3031 // We use the orientation of the x-axis of the joint's coordinate frame
3032 // as the axis for the hinge.
3033
3034 // Therefore, we must get the joint's coordinate frame based on the
3035 // joint.Rotation field, which originates from the orientation of the
3036 // joint's proxy object in the scene.
3037
3038 // The joint's coordinate frame is defined as the transformation matrix
3039 // that converts a vector from joint-local coordinates into world coordinates.
3040 // World coordinates are defined as the XYZ coordinate system of the sim,
3041 // as shown in the top status-bar of the viewer.
3042
3043 // Once we have the joint's coordinate frame, we extract its X axis (AtAxis)
3044 // and use that as the hinge axis.
3045
3046 //joint.Rotation.Normalize();
3047 Matrix4 proxyFrame = Matrix4.CreateFromQuaternion(joint.Rotation);
3048
3049 // Now extract the X axis of the joint's coordinate frame.
3050
3051 // Do not try to use proxyFrame.AtAxis or you will become mired in the
3052 // tar pit of transposed, inverted, and generally messed-up orientations.
3053 // (In other words, Matrix4.AtAxis() is borked.)
3054 // Vector3 jointAxis = proxyFrame.AtAxis; <--- this path leadeth to madness
3055
3056 // Instead, compute the X axis of the coordinate frame by transforming
3057 // the (1,0,0) vector. At least that works.
3058
3059 //m_log.Debug("PHY: making axis: complete matrix is " + proxyFrame);
3060 Vector3 jointAxis = Vector3.Transform(Vector3.UnitX, proxyFrame);
3061 //m_log.Debug("PHY: making axis: hinge joint axis is " + jointAxis);
3062 //DoJointErrorMessage(joint, "ODE setting hinge axis: " + odeJoint + " to vec:" + jointAxis);
3063 d.JointSetHingeAxis(odeJoint,
3064 jointAxis.X,
3065 jointAxis.Y,
3066 jointAxis.Z);
3067 //d.JointSetHingeParam(odeJoint, (int)dParam.CFM, 0.1f);
3068 if (joint is OdePhysicsJoint)
3069 {
3070 ((OdePhysicsJoint)joint).jointID = odeJoint;
3071 }
3072 else
3073 {
3074 DoJointErrorMessage(joint, "WARNING: non-ode joint in ODE!");
3075 }
3076 }
3077 break;
3078 }
3079 successfullyProcessedPendingJoints.Add(joint);
3080 }
3081 }
3082 else
3083 {
3084 DoJointErrorMessage(joint, "joint could not yet be created; still pending");
3085 }
3086 }
3087
3088 foreach (PhysicsJoint successfullyProcessedJoint in successfullyProcessedPendingJoints)
3089 {
3090 //DoJointErrorMessage(successfullyProcessedJoint, "finalizing succesfully procsssed joint " + successfullyProcessedJoint.ObjectNameInScene + " parms " + successfullyProcessedJoint.RawParams);
3091 //DoJointErrorMessage(successfullyProcessedJoint, "removing from pending");
3092 InternalRemovePendingJoint(successfullyProcessedJoint);
3093 //DoJointErrorMessage(successfullyProcessedJoint, "adding to active");
3094 InternalAddActiveJoint(successfullyProcessedJoint);
3095 //DoJointErrorMessage(successfullyProcessedJoint, "done");
3096 }
3097 }
3098 }
3099
3100 /// <summary>
3101 /// Simulate the joint proxies of a NINJA actor.
3102 /// </summary>
3103 /// <remarks>
3104 /// Called as part of the Simulate() loop if NINJA physics is active. Must only be called from there.
3105 /// </remarks>
3106 /// <param name="actor"></param>
3107 protected void SimulateActorPendingJoints(OdePrim actor)
3108 {
3109 // If an actor moved, move its joint proxy objects as well.
3110 // There seems to be an event PhysicsActor.OnPositionUpdate that could be used
3111 // for this purpose but it is never called! So we just do the joint
3112 // movement code here.
3113
3114 if (actor.SOPName != null &&
3115 joints_connecting_actor.ContainsKey(actor.SOPName) &&
3116 joints_connecting_actor[actor.SOPName] != null &&
3117 joints_connecting_actor[actor.SOPName].Count > 0)
3118 {
3119 foreach (PhysicsJoint affectedJoint in joints_connecting_actor[actor.SOPName])
3120 {
3121 if (affectedJoint.IsInPhysicsEngine)
3122 {
3123 DoJointMoved(affectedJoint);
3124 }
3125 else
3126 {
3127 DoJointErrorMessage(affectedJoint, "a body connected to a joint was moved, but the joint doesn't exist yet! this will lead to joint error. joint was: " + affectedJoint.ObjectNameInScene + " parms:" + affectedJoint.RawParams);
3128 }
3129 }
3130 }
3131 }
3132
3117 public override void GetResults() 3133 public override void GetResults()
3118 { 3134 {
3119 } 3135 }
@@ -3459,24 +3475,21 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name);
3459 float hfmin = 2000; 3475 float hfmin = 2000;
3460 float hfmax = -2000; 3476 float hfmax = -2000;
3461 3477
3462 for (int x = 0; x < heightmapWidthSamples; x++) 3478 for (int x = 0; x < heightmapWidthSamples; x++)
3479 {
3480 for (int y = 0; y < heightmapHeightSamples; y++)
3463 { 3481 {
3464 for (int y = 0; y < heightmapHeightSamples; y++) 3482 int xx = Util.Clip(x - 1, 0, regionsize - 1);
3465 { 3483 int yy = Util.Clip(y - 1, 0, regionsize - 1);
3466 int xx = Util.Clip(x - 1, 0, regionsize - 1); 3484
3467 int yy = Util.Clip(y - 1, 0, regionsize - 1); 3485
3468 3486 float val= heightMap[yy * (int)Constants.RegionSize + xx];
3469 3487 _heightmap[x * ((int)Constants.RegionSize + 2) + y] = val;
3470 float val= heightMap[yy * (int)Constants.RegionSize + xx]; 3488
3471 _heightmap[x * ((int)Constants.RegionSize + 2) + y] = val; 3489 hfmin = (val < hfmin) ? val : hfmin;
3472 3490 hfmax = (val > hfmax) ? val : hfmax;
3473 hfmin = (val < hfmin) ? val : hfmin;
3474 hfmax = (val > hfmax) ? val : hfmax;
3475 }
3476 } 3491 }
3477 3492 }
3478
3479
3480 3493
3481 lock (OdeLock) 3494 lock (OdeLock)
3482 { 3495 {
@@ -3531,7 +3544,6 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name);
3531 } 3544 }
3532 RegionTerrain.Add(pOffset, GroundGeom, GroundGeom); 3545 RegionTerrain.Add(pOffset, GroundGeom, GroundGeom);
3533 TerrainHeightFieldHeights.Add(GroundGeom,_heightmap); 3546 TerrainHeightFieldHeights.Add(GroundGeom,_heightmap);
3534
3535 } 3547 }
3536 } 3548 }
3537 3549
@@ -3694,6 +3706,7 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name);
3694 //d.CloseODE(); 3706 //d.CloseODE();
3695 } 3707 }
3696 } 3708 }
3709
3697 public override Dictionary<uint, float> GetTopColliders() 3710 public override Dictionary<uint, float> GetTopColliders()
3698 { 3711 {
3699 Dictionary<uint, float> returncolliders = new Dictionary<uint, float>(); 3712 Dictionary<uint, float> returncolliders = new Dictionary<uint, float>();