aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapes.cs327
1 files changed, 311 insertions, 16 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
index dd5ae1a..e427dbc 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
@@ -31,6 +31,7 @@ using System.Text;
31 31
32using OpenSim.Framework; 32using OpenSim.Framework;
33using OpenSim.Region.Physics.Manager; 33using OpenSim.Region.Physics.Manager;
34using OpenSim.Region.Physics.ConvexDecompositionDotNet;
34 35
35using OMV = OpenMetaverse; 36using OMV = OpenMetaverse;
36 37
@@ -73,7 +74,7 @@ public abstract class BSShape
73 if (ret == null && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND) 74 if (ret == null && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND)
74 { 75 {
75 // Getting a reference to a compound shape gets you the compound shape with the root prim shape added 76 // Getting a reference to a compound shape gets you the compound shape with the root prim shape added
76 ret = BSShapeCompound.GetReference(prim); 77 ret = BSShapeCompound.GetReference(physicsScene, prim);
77 physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, ret); 78 physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, ret);
78 } 79 }
79 80
@@ -92,6 +93,7 @@ public abstract class BSShape
92 } 93 }
93 private static BSShape GetShapeReferenceNonSpecial(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) 94 private static BSShape GetShapeReferenceNonSpecial(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
94 { 95 {
96 // TODO: work needed here!!
95 BSShapeMesh.GetReference(physicsScene, forceRebuild, prim); 97 BSShapeMesh.GetReference(physicsScene, forceRebuild, prim);
96 BSShapeHull.GetReference(physicsScene, forceRebuild, prim); 98 BSShapeHull.GetReference(physicsScene, forceRebuild, prim);
97 return null; 99 return null;
@@ -209,7 +211,7 @@ public class BSShapeNative : BSShape
209public class BSShapeMesh : BSShape 211public class BSShapeMesh : BSShape
210{ 212{
211 private static string LogHeader = "[BULLETSIM SHAPE MESH]"; 213 private static string LogHeader = "[BULLETSIM SHAPE MESH]";
212 private static Dictionary<System.UInt64, BSShapeMesh> Meshes = new Dictionary<System.UInt64, BSShapeMesh>(); 214 public static Dictionary<System.UInt64, BSShapeMesh> Meshes = new Dictionary<System.UInt64, BSShapeMesh>();
213 215
214 public BSShapeMesh(BulletShape pShape) : base(pShape) 216 public BSShapeMesh(BulletShape pShape) : base(pShape)
215 { 217 {
@@ -219,10 +221,10 @@ public class BSShapeMesh : BSShape
219 float lod; 221 float lod;
220 System.UInt64 newMeshKey = BSShapeCollection.ComputeShapeKey(prim.Size, prim.BaseShape, out lod); 222 System.UInt64 newMeshKey = BSShapeCollection.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
221 223
222 physicsScene.DetailLog("{0},BSShapeMesh,create,oldKey={1},newKey={2},size={3},lod={4}", 224 physicsScene.DetailLog("{0},BSShapeMesh,getReference,oldKey={1},newKey={2},size={3},lod={4}",
223 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X"), prim.Size, lod); 225 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X"), prim.Size, lod);
224 226
225 BSShapeMesh retMesh; 227 BSShapeMesh retMesh = new BSShapeMesh(new BulletShape());
226 lock (Meshes) 228 lock (Meshes)
227 { 229 {
228 if (Meshes.TryGetValue(newMeshKey, out retMesh)) 230 if (Meshes.TryGetValue(newMeshKey, out retMesh))
@@ -233,13 +235,17 @@ public class BSShapeMesh : BSShape
233 else 235 else
234 { 236 {
235 // An instance of this mesh has not been created. Build and remember same. 237 // An instance of this mesh has not been created. Build and remember same.
236 BulletShape newShape = CreatePhysicalMesh(physicsScene, prim, newMeshKey, prim.BaseShape, prim.Size, lod); 238 BulletShape newShape = retMesh.CreatePhysicalMesh(physicsScene, prim, newMeshKey, prim.BaseShape, prim.Size, lod);
237 // Take evasive action if the mesh was not constructed.
238 newShape = BSShapeCollection.VerifyMeshCreated(physicsScene, newShape, prim);
239 239
240 retMesh = new BSShapeMesh(newShape); 240 // Check to see if mesh was created (might require an asset).
241 newShape = BSShapeCollection.VerifyMeshCreated(physicsScene, newShape, prim);
242 if (newShape.type == BSPhysicsShapeType.SHAPE_MESH)
243 {
244 // If a mesh was what was created, remember the built shape for later sharing.
245 Meshes.Add(newMeshKey, retMesh);
246 }
241 247
242 Meshes.Add(newMeshKey, retMesh); 248 retMesh.physShapeInfo = newShape;
243 } 249 }
244 } 250 }
245 return retMesh; 251 return retMesh;
@@ -252,8 +258,28 @@ public class BSShapeMesh : BSShape
252 // TODO: schedule aging and destruction of unused meshes. 258 // TODO: schedule aging and destruction of unused meshes.
253 } 259 }
254 } 260 }
261 // Loop through all the known meshes and return the description based on the physical address.
262 public static bool TryGetMeshByPtr(BulletShape pShape, out BSShapeMesh outMesh)
263 {
264 bool ret = false;
265 BSShapeMesh foundDesc = null;
266 lock (Meshes)
267 {
268 foreach (BSShapeMesh sm in Meshes.Values)
269 {
270 if (sm.physShapeInfo.ReferenceSame(pShape))
271 {
272 foundDesc = sm;
273 ret = true;
274 break;
275 }
255 276
256 private static BulletShape CreatePhysicalMesh(BSScene physicsScene, BSPhysObject prim, System.UInt64 newMeshKey, 277 }
278 }
279 outMesh = foundDesc;
280 return ret;
281 }
282 private BulletShape CreatePhysicalMesh(BSScene physicsScene, BSPhysObject prim, System.UInt64 newMeshKey,
257 PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) 283 PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
258 { 284 {
259 BulletShape newShape = null; 285 BulletShape newShape = null;
@@ -326,32 +352,301 @@ public class BSShapeMesh : BSShape
326public class BSShapeHull : BSShape 352public class BSShapeHull : BSShape
327{ 353{
328 private static string LogHeader = "[BULLETSIM SHAPE HULL]"; 354 private static string LogHeader = "[BULLETSIM SHAPE HULL]";
329 private static Dictionary<System.UInt64, BSShapeHull> Hulls = new Dictionary<System.UInt64, BSShapeHull>(); 355 public static Dictionary<System.UInt64, BSShapeHull> Hulls = new Dictionary<System.UInt64, BSShapeHull>();
330 356
331 public BSShapeHull(BulletShape pShape) : base(pShape) 357 public BSShapeHull(BulletShape pShape) : base(pShape)
332 { 358 {
333 } 359 }
334 public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) 360 public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
335 { 361 {
336 return new BSShapeNull(); 362 float lod;
363 System.UInt64 newHullKey = BSShapeCollection.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
364
365 physicsScene.DetailLog("{0},BSShapeHull,getReference,oldKey={1},newKey={2},size={3},lod={4}",
366 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X"), prim.Size, lod);
367
368 BSShapeHull retHull = new BSShapeHull(new BulletShape());
369 lock (Hulls)
370 {
371 if (Hulls.TryGetValue(newHullKey, out retHull))
372 {
373 // The mesh has already been created. Return a new reference to same.
374 retHull.IncrementReference();
375 }
376 else
377 {
378 // An instance of this mesh has not been created. Build and remember same.
379 BulletShape newShape = retHull.CreatePhysicalHull(physicsScene, prim, newHullKey, prim.BaseShape, prim.Size, lod);
380
381 // Check to see if mesh was created (might require an asset).
382 newShape = BSShapeCollection.VerifyMeshCreated(physicsScene, newShape, prim);
383 if (newShape.type == BSPhysicsShapeType.SHAPE_MESH)
384 {
385 // If a mesh was what was created, remember the built shape for later sharing.
386 Hulls.Add(newHullKey, retHull);
387 }
388
389 retHull = new BSShapeHull(newShape);
390 retHull.physShapeInfo = newShape;
391 }
392 }
393 return retHull;
337 } 394 }
338 public override void Dereference(BSScene physicsScene) 395 public override void Dereference(BSScene physicsScene)
339 { 396 {
340 } 397 }
398 List<ConvexResult> m_hulls;
399 private BulletShape CreatePhysicalHull(BSScene physicsScene, BSPhysObject prim, System.UInt64 newHullKey,
400 PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
401 {
402 BulletShape newShape = new BulletShape();
403 IntPtr hullPtr = IntPtr.Zero;
404
405 if (BSParam.ShouldUseBulletHACD)
406 {
407 physicsScene.DetailLog("{0},BSShapeCollection.CreatePhysicalHull,shouldUseBulletHACD,entry", prim.LocalID);
408 BSShape meshShape = BSShapeMesh.GetReference(physicsScene, true, prim);
409
410 if (meshShape.physShapeInfo.HasPhysicalShape)
411 {
412 HACDParams parms;
413 parms.maxVerticesPerHull = BSParam.BHullMaxVerticesPerHull;
414 parms.minClusters = BSParam.BHullMinClusters;
415 parms.compacityWeight = BSParam.BHullCompacityWeight;
416 parms.volumeWeight = BSParam.BHullVolumeWeight;
417 parms.concavity = BSParam.BHullConcavity;
418 parms.addExtraDistPoints = BSParam.NumericBool(BSParam.BHullAddExtraDistPoints);
419 parms.addNeighboursDistPoints = BSParam.NumericBool(BSParam.BHullAddNeighboursDistPoints);
420 parms.addFacesPoints = BSParam.NumericBool(BSParam.BHullAddFacesPoints);
421 parms.shouldAdjustCollisionMargin = BSParam.NumericBool(BSParam.BHullShouldAdjustCollisionMargin);
422
423 physicsScene.DetailLog("{0},BSShapeCollection.CreatePhysicalHull,hullFromMesh,beforeCall", prim.LocalID, newShape.HasPhysicalShape);
424 newShape = physicsScene.PE.BuildHullShapeFromMesh(physicsScene.World, meshShape.physShapeInfo, parms);
425 physicsScene.DetailLog("{0},BSShapeCollection.CreatePhysicalHull,hullFromMesh,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
426 }
427 // Now done with the mesh shape.
428 meshShape.DecrementReference();
429 physicsScene.DetailLog("{0},BSShapeCollection.CreatePhysicalHull,shouldUseBulletHACD,exit,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
430 }
431 if (!newShape.HasPhysicalShape)
432 {
433 // Build a new hull in the physical world.
434 // Pass true for physicalness as this prevents the creation of bounding box which is not needed
435 IMesh meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */);
436 if (meshData != null)
437 {
438 int[] indices = meshData.getIndexListAsInt();
439 List<OMV.Vector3> vertices = meshData.getVertexList();
440
441 //format conversion from IMesh format to DecompDesc format
442 List<int> convIndices = new List<int>();
443 List<float3> convVertices = new List<float3>();
444 for (int ii = 0; ii < indices.GetLength(0); ii++)
445 {
446 convIndices.Add(indices[ii]);
447 }
448 foreach (OMV.Vector3 vv in vertices)
449 {
450 convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
451 }
452
453 uint maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplit;
454 if (BSParam.CSHullMaxDepthSplit != BSParam.CSHullMaxDepthSplitForSimpleShapes)
455 {
456 // Simple primitive shapes we know are convex so they are better implemented with
457 // fewer hulls.
458 // Check for simple shape (prim without cuts) and reduce split parameter if so.
459 if (BSShapeCollection.PrimHasNoCuts(pbs))
460 {
461 maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplitForSimpleShapes;
462 }
463 }
464
465 // setup and do convex hull conversion
466 m_hulls = new List<ConvexResult>();
467 DecompDesc dcomp = new DecompDesc();
468 dcomp.mIndices = convIndices;
469 dcomp.mVertices = convVertices;
470 dcomp.mDepth = maxDepthSplit;
471 dcomp.mCpercent = BSParam.CSHullConcavityThresholdPercent;
472 dcomp.mPpercent = BSParam.CSHullVolumeConservationThresholdPercent;
473 dcomp.mMaxVertices = (uint)BSParam.CSHullMaxVertices;
474 dcomp.mSkinWidth = BSParam.CSHullMaxSkinWidth;
475 ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
476 // create the hull into the _hulls variable
477 convexBuilder.process(dcomp);
478
479 physicsScene.DetailLog("{0},BSShapeCollection.CreatePhysicalHull,key={1},inVert={2},inInd={3},split={4},hulls={5}",
480 BSScene.DetailLogZero, newHullKey, indices.GetLength(0), vertices.Count, maxDepthSplit, m_hulls.Count);
481
482 // Convert the vertices and indices for passing to unmanaged.
483 // The hull information is passed as a large floating point array.
484 // The format is:
485 // convHulls[0] = number of hulls
486 // convHulls[1] = number of vertices in first hull
487 // convHulls[2] = hull centroid X coordinate
488 // convHulls[3] = hull centroid Y coordinate
489 // convHulls[4] = hull centroid Z coordinate
490 // convHulls[5] = first hull vertex X
491 // convHulls[6] = first hull vertex Y
492 // convHulls[7] = first hull vertex Z
493 // convHulls[8] = second hull vertex X
494 // ...
495 // convHulls[n] = number of vertices in second hull
496 // convHulls[n+1] = second hull centroid X coordinate
497 // ...
498 //
499 // TODO: is is very inefficient. Someday change the convex hull generator to return
500 // data structures that do not need to be converted in order to pass to Bullet.
501 // And maybe put the values directly into pinned memory rather than marshaling.
502 int hullCount = m_hulls.Count;
503 int totalVertices = 1; // include one for the count of the hulls
504 foreach (ConvexResult cr in m_hulls)
505 {
506 totalVertices += 4; // add four for the vertex count and centroid
507 totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
508 }
509 float[] convHulls = new float[totalVertices];
510
511 convHulls[0] = (float)hullCount;
512 int jj = 1;
513 foreach (ConvexResult cr in m_hulls)
514 {
515 // copy vertices for index access
516 float3[] verts = new float3[cr.HullVertices.Count];
517 int kk = 0;
518 foreach (float3 ff in cr.HullVertices)
519 {
520 verts[kk++] = ff;
521 }
522
523 // add to the array one hull's worth of data
524 convHulls[jj++] = cr.HullIndices.Count;
525 convHulls[jj++] = 0f; // centroid x,y,z
526 convHulls[jj++] = 0f;
527 convHulls[jj++] = 0f;
528 foreach (int ind in cr.HullIndices)
529 {
530 convHulls[jj++] = verts[ind].x;
531 convHulls[jj++] = verts[ind].y;
532 convHulls[jj++] = verts[ind].z;
533 }
534 }
535 // create the hull data structure in Bullet
536 newShape = physicsScene.PE.CreateHullShape(physicsScene.World, hullCount, convHulls);
537 }
538 newShape.shapeKey = newHullKey;
539 }
540 return newShape;
541 }
542 // Callback from convex hull creater with a newly created hull.
543 // Just add it to our collection of hulls for this shape.
544 private void HullReturn(ConvexResult result)
545 {
546 m_hulls.Add(result);
547 return;
548 }
549 // Loop through all the known hulls and return the description based on the physical address.
550 public static bool TryGetHullByPtr(BulletShape pShape, out BSShapeHull outHull)
551 {
552 bool ret = false;
553 BSShapeHull foundDesc = null;
554 lock (Hulls)
555 {
556 foreach (BSShapeHull sh in Hulls.Values)
557 {
558 if (sh.physShapeInfo.ReferenceSame(pShape))
559 {
560 foundDesc = sh;
561 ret = true;
562 break;
563 }
564
565 }
566 }
567 outHull = foundDesc;
568 return ret;
569 }
341} 570}
342 571
572
343// ============================================================================================================ 573// ============================================================================================================
344public class BSShapeCompound : BSShape 574public class BSShapeCompound : BSShape
345{ 575{
346 private static string LogHeader = "[BULLETSIM SHAPE COMPOUND]"; 576 private static string LogHeader = "[BULLETSIM SHAPE COMPOUND]";
347 public BSShapeCompound() : base() 577 public BSShapeCompound(BulletShape pShape) : base(pShape)
348 { 578 {
349 } 579 }
350 public static BSShape GetReference(BSPhysObject prim) 580 public static BSShape GetReference(BSScene physicsScene, BSPhysObject prim)
351 { 581 {
352 return new BSShapeNull(); 582 // Compound shapes are not shared so a new one is created every time.
583 return new BSShapeCompound(CreatePhysicalCompoundShape(physicsScene, prim));
584 }
585 // Dereferencing a compound shape releases the hold on all the child shapes.
586 public override void Dereference(BSScene physicsScene)
587 {
588 if (!physicsScene.PE.IsCompound(physShapeInfo))
589 {
590 // Failed the sanity check!!
591 physicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}",
592 LogHeader, physShapeInfo.type, physShapeInfo.AddrString);
593 physicsScene.DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}",
594 BSScene.DetailLogZero, physShapeInfo.type, physShapeInfo.AddrString);
595 return;
596 }
597
598 int numChildren = physicsScene.PE.GetNumberOfCompoundChildren(physShapeInfo);
599 physicsScene.DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}",
600 BSScene.DetailLogZero, physShapeInfo, numChildren);
601
602 // Loop through all the children dereferencing each.
603 for (int ii = numChildren - 1; ii >= 0; ii--)
604 {
605 BulletShape childShape = physicsScene.PE.RemoveChildShapeFromCompoundShapeIndex(physShapeInfo, ii);
606 DereferenceAnonCollisionShape(physicsScene, childShape);
607 }
608 physicsScene.PE.DeleteCollisionShape(physicsScene.World, physShapeInfo);
609 }
610 private static BulletShape CreatePhysicalCompoundShape(BSScene physicsScene, BSPhysObject prim)
611 {
612 BulletShape cShape = physicsScene.PE.CreateCompoundShape(physicsScene.World, false);
613 return cShape;
614 }
615 // Sometimes we have a pointer to a collision shape but don't know what type it is.
616 // Figure out type and call the correct dereference routine.
617 // Called at taint-time.
618 private void DereferenceAnonCollisionShape(BSScene physicsScene, BulletShape pShape)
619 {
620 BSShapeMesh meshDesc;
621 if (BSShapeMesh.TryGetMeshByPtr(pShape, out meshDesc))
622 {
623 meshDesc.Dereference(physicsScene);
624 }
625 else
626 {
627 BSShapeHull hullDesc;
628 if (BSShapeHull.TryGetHullByPtr(pShape, out hullDesc))
629 {
630 hullDesc.Dereference(physicsScene);
631 }
632 else
633 {
634 if (physicsScene.PE.IsCompound(pShape))
635 {
636 BSShapeCompound recursiveCompound = new BSShapeCompound(pShape);
637 recursiveCompound.Dereference(physicsScene);
638 }
639 else
640 {
641 if (physicsScene.PE.IsNativeShape(pShape))
642 {
643 BSShapeNative nativeShape = new BSShapeNative(pShape);
644 nativeShape.Dereference(physicsScene);
645 }
646 }
647 }
648 }
353 } 649 }
354 public override void Dereference(BSScene physicsScene) { }
355} 650}
356 651
357// ============================================================================================================ 652// ============================================================================================================