aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin')
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs10
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs8
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs28
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BSScene.cs24
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs296
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs12
-rw-r--r--OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs78
7 files changed, 265 insertions, 191 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index e4b1dd4..961bcde 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -90,7 +90,8 @@ public class BSCharacter : BSPhysObject
90 // Physics creates a unit capsule which is scaled by the physics engine. 90 // Physics creates a unit capsule which is scaled by the physics engine.
91 ComputeAvatarScale(_size); 91 ComputeAvatarScale(_size);
92 _avatarDensity = PhysicsScene.Params.avatarDensity; 92 _avatarDensity = PhysicsScene.Params.avatarDensity;
93 ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale 93 // set _avatarVolume and _mass based on capsule size, _density and _scale
94 ComputeAvatarVolumeAndMass();
94 95
95 ShapeData shapeData = new ShapeData(); 96 ShapeData shapeData = new ShapeData();
96 shapeData.ID = LocalID; 97 shapeData.ID = LocalID;
@@ -111,10 +112,15 @@ public class BSCharacter : BSPhysObject
111 DetailLog("{0},BSCharacter.create,taint", LocalID); 112 DetailLog("{0},BSCharacter.create,taint", LocalID);
112 BulletSimAPI.CreateObject(PhysicsScene.WorldID, shapeData); 113 BulletSimAPI.CreateObject(PhysicsScene.WorldID, shapeData);
113 114
114 // Set the buoyancy for flying. This will be refactored when all the settings happen in C# 115 // Set the buoyancy for flying. This will be refactored when all the settings happen in C#.
116 // If not set at creation, the avatar will stop flying when created after crossing a region boundry.
115 BulletSimAPI.SetObjectBuoyancy(PhysicsScene.WorldID, LocalID, _buoyancy); 117 BulletSimAPI.SetObjectBuoyancy(PhysicsScene.WorldID, LocalID, _buoyancy);
116 118
117 BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(PhysicsScene.World.ptr, LocalID)); 119 BSBody = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(PhysicsScene.World.ptr, LocalID));
120
121 // This works here because CreateObject has already put the character into the physical world.
122 BulletSimAPI.SetCollisionFilterMask2(BSBody.ptr,
123 (uint)CollisionFilterGroups.AvatarFilter, (uint)CollisionFilterGroups.AvatarMask);
118 }); 124 });
119 125
120 return; 126 return;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index 6a9fe50..3458477 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -123,6 +123,7 @@ public abstract class BSPhysObject : PhysicsActor
123 CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); 123 CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth));
124 DetailLog("{0},{1}.Collison.AddCollider,call,with={2},point={3},normal={4},depth={5}", 124 DetailLog("{0},{1}.Collison.AddCollider,call,with={2},point={3},normal={4},depth={5}",
125 LocalID, TypeName, collidingWith, contactPoint, contactNormal, pentrationDepth); 125 LocalID, TypeName, collidingWith, contactPoint, contactNormal, pentrationDepth);
126
126 ret = true; 127 ret = true;
127 } 128 }
128 return ret; 129 return ret;
@@ -145,7 +146,10 @@ public abstract class BSPhysObject : PhysicsActor
145 // We are called if we previously had collisions. If there are no collisions 146 // We are called if we previously had collisions. If there are no collisions
146 // this time, send up one last empty event so OpenSim can sense collision end. 147 // this time, send up one last empty event so OpenSim can sense collision end.
147 if (CollisionCollection.Count == 0) 148 if (CollisionCollection.Count == 0)
149 {
150 // If I have no collisions this time, remove me from the list of objects with collisions.
148 PhysicsScene.ObjectsWithNoMoreCollisions.Add(this); 151 PhysicsScene.ObjectsWithNoMoreCollisions.Add(this);
152 }
149 153
150 DetailLog("{0},{1}.SendCollisionUpdate,call,numCollisions={2}", LocalID, TypeName, CollisionCollection.Count); 154 DetailLog("{0},{1}.SendCollisionUpdate,call,numCollisions={2}", LocalID, TypeName, CollisionCollection.Count);
151 base.SendCollisionUpdate(CollisionCollection); 155 base.SendCollisionUpdate(CollisionCollection);
@@ -159,7 +163,7 @@ public abstract class BSPhysObject : PhysicsActor
159 // Subscribe for collision events. 163 // Subscribe for collision events.
160 // Parameter is the millisecond rate the caller wishes collision events to occur. 164 // Parameter is the millisecond rate the caller wishes collision events to occur.
161 public override void SubscribeEvents(int ms) { 165 public override void SubscribeEvents(int ms) {
162 DetailLog("{0},BSScene.SubscribeEvents,subscribing,ms={1}", BSScene.DetailLogZero, ms); 166 DetailLog("{0},{1}.SubscribeEvents,subscribing,ms={2}", LocalID, TypeName, ms);
163 SubscribedEventsMs = ms; 167 SubscribedEventsMs = ms;
164 if (ms > 0) 168 if (ms > 0)
165 { 169 {
@@ -178,7 +182,7 @@ public abstract class BSPhysObject : PhysicsActor
178 } 182 }
179 } 183 }
180 public override void UnSubscribeEvents() { 184 public override void UnSubscribeEvents() {
181 DetailLog("{0},BSScene.UnSubscribeEvents,unsubscribing", BSScene.DetailLogZero); 185 DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName);
182 SubscribedEventsMs = 0; 186 SubscribedEventsMs = 0;
183 PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate() 187 PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate()
184 { 188 {
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index 5be2b1b..1c6d476 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -271,7 +271,7 @@ public sealed class BSPrim : BSPhysObject
271 _position = BulletSimAPI.GetPosition2(BSBody.ptr); 271 _position = BulletSimAPI.GetPosition2(BSBody.ptr);
272 272
273 // don't do the GetObjectPosition for root elements because this function is called a zillion times 273 // don't do the GetObjectPosition for root elements because this function is called a zillion times
274 // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, LocalID); 274 // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr);
275 return _position; 275 return _position;
276 } 276 }
277 set { 277 set {
@@ -432,7 +432,7 @@ public sealed class BSPrim : BSPhysObject
432 // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint? 432 // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint?
433 PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate() 433 PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate()
434 { 434 {
435 // _position = BulletSimAPI.GetObjectPosition(Scene.WorldID, LocalID); 435 // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr);
436 DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); 436 DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation);
437 BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation); 437 BulletSimAPI.SetTranslation2(BSBody.ptr, _position, _orientation);
438 }); 438 });
@@ -492,7 +492,8 @@ public sealed class BSPrim : BSPhysObject
492 { 492 {
493 DetailLog("{0},BSPrim.UpdatePhysicalParameters,entry,body={1},shape={2}", LocalID, BSBody, BSShape); 493 DetailLog("{0},BSPrim.UpdatePhysicalParameters,entry,body={1},shape={2}", LocalID, BSBody, BSShape);
494 494
495 // Mangling all the physical properties requires the object to be out of the physical world 495 // Mangling all the physical properties requires the object to be out of the physical world.
496 // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found).
496 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, BSBody.ptr); 497 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, BSBody.ptr);
497 498
498#if !CSHARP_BODY_MANAGEMENT 499#if !CSHARP_BODY_MANAGEMENT
@@ -517,6 +518,14 @@ public sealed class BSPrim : BSPhysObject
517 // Rebuild its shape 518 // Rebuild its shape
518 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, BSBody.ptr); 519 BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, BSBody.ptr);
519 520
521 // Collision filter can be set only when the object is in the world
522 if (BSBody.collisionFilter != 0 || BSBody.collisionMask != 0)
523 {
524 BulletSimAPI.SetCollisionFilterMask2(BSBody.ptr, (uint)BSBody.collisionFilter, (uint)BSBody.collisionMask);
525 DetailLog("{0},BSPrim.UpdatePhysicalParameters,setCollisionFilterMask,filter={1},mask={2}",
526 LocalID, BSBody.collisionFilter.ToString("X"), BSBody.collisionMask.ToString("X"));
527 }
528
520 // Recompute any linkset parameters. 529 // Recompute any linkset parameters.
521 // When going from non-physical to physical, this re-enables the constraints that 530 // When going from non-physical to physical, this re-enables the constraints that
522 // had been automatically disabled when the mass was set to zero. 531 // had been automatically disabled when the mass was set to zero.
@@ -548,8 +557,11 @@ public sealed class BSPrim : BSPhysObject
548 // There can be special things needed for implementing linksets 557 // There can be special things needed for implementing linksets
549 Linkset.MakeStatic(this); 558 Linkset.MakeStatic(this);
550 // The activation state is 'sleeping' so Bullet will not try to act on it 559 // The activation state is 'sleeping' so Bullet will not try to act on it
551 BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING); 560 // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING);
552 // BulletSimAPI.ForceActivationState2(BSBody.Ptr, ActivationState.DISABLE_SIMULATION); 561 BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.DISABLE_SIMULATION);
562
563 BSBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter;
564 BSBody.collisionMask = CollisionFilterGroups.StaticObjectMask;
553 } 565 }
554 else 566 else
555 { 567 {
@@ -582,6 +594,9 @@ public sealed class BSPrim : BSPhysObject
582 594
583 // Force activation of the object so Bullet will act on it. 595 // Force activation of the object so Bullet will act on it.
584 BulletSimAPI.Activate2(BSBody.ptr, true); 596 BulletSimAPI.Activate2(BSBody.ptr, true);
597
598 BSBody.collisionFilter = CollisionFilterGroups.ObjectFilter;
599 BSBody.collisionMask = CollisionFilterGroups.ObjectMask;
585 } 600 }
586 } 601 }
587 602
@@ -609,6 +624,8 @@ public sealed class BSPrim : BSPhysObject
609 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType); 624 m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType);
610 } 625 }
611 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); 626 CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(BSBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
627 BSBody.collisionFilter = CollisionFilterGroups.VolumeDetectFilter;
628 BSBody.collisionMask = CollisionFilterGroups.VolumeDetectMask;
612 } 629 }
613#else 630#else
614 // If doing the body management in C#, all this logic is in CSShapeCollection.CreateObject(). 631 // If doing the body management in C#, all this logic is in CSShapeCollection.CreateObject().
@@ -745,7 +762,6 @@ public sealed class BSPrim : BSPhysObject
745 // Buoyancy is faked by changing the gravity applied to the object 762 // Buoyancy is faked by changing the gravity applied to the object
746 float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); 763 float grav = PhysicsScene.Params.gravity * (1f - _buoyancy);
747 BulletSimAPI.SetGravity2(BSBody.ptr, new OMV.Vector3(0f, 0f, grav)); 764 BulletSimAPI.SetGravity2(BSBody.ptr, new OMV.Vector3(0f, 0f, grav));
748 // BulletSimAPI.SetObjectBuoyancy(Scene.WorldID, LocalID, _buoyancy);
749 }); 765 });
750 } 766 }
751 } 767 }
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
index 87c7b1b..e8c628c 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs
@@ -39,20 +39,20 @@ using log4net;
39using OpenMetaverse; 39using OpenMetaverse;
40 40
41// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim) 41// TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim)
42// Adjust character capsule size when height is adjusted (ScenePresence.SetHeight) 42// Move all logic out of the C++ code and into the C# code for easier future modifications.
43// Test sculpties 43// Test sculpties (verified that they don't work)
44// Compute physics FPS reasonably 44// Compute physics FPS reasonably
45// Based on material, set density and friction 45// Based on material, set density and friction
46// More efficient memory usage when passing hull information from BSPrim to BulletSim 46// Don't use constraints in linksets of non-physical objects. Means having to move children manually.
47// Move all logic out of the C++ code and into the C# code for easier future modifications.
48// Four states of prim: Physical, regular, phantom and selected. Are we modeling these correctly? 47// Four states of prim: Physical, regular, phantom and selected. Are we modeling these correctly?
49// In SL one can set both physical and phantom (gravity, does not effect others, makes collisions with ground) 48// In SL one can set both physical and phantom (gravity, does not effect others, makes collisions with ground)
50// At the moment, physical and phantom causes object to drop through the terrain 49// At the moment, physical and phantom causes object to drop through the terrain
51// Physical phantom objects and related typing (collision options ) 50// Physical phantom objects and related typing (collision options )
52// Use collision masks for collision with terrain and phantom objects
53// Check out llVolumeDetect. Must do something for that. 51// Check out llVolumeDetect. Must do something for that.
52// Use collision masks for collision with terrain and phantom objects
53// More efficient memory usage when passing hull information from BSPrim to BulletSim
54// Should prim.link() and prim.delink() membership checking happen at taint time? 54// Should prim.link() and prim.delink() membership checking happen at taint time?
55// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once 55// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once.
56// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect 56// Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect
57// Implement LockAngularMotion 57// Implement LockAngularMotion
58// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation) 58// Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation)
@@ -356,6 +356,12 @@ public class BSScene : PhysicsScene, IPhysicsParameters
356 Constraints = null; 356 Constraints = null;
357 } 357 }
358 358
359 if (Shapes != null)
360 {
361 Shapes.Dispose();
362 Shapes = null;
363 }
364
359 // Anything left in the unmanaged code should be cleaned out 365 // Anything left in the unmanaged code should be cleaned out
360 BulletSimAPI.Shutdown(WorldID); 366 BulletSimAPI.Shutdown(WorldID);
361 367
@@ -589,7 +595,6 @@ public class BSScene : PhysicsScene, IPhysicsParameters
589 { 595 {
590 if (localID <= TerrainManager.HighestTerrainID) 596 if (localID <= TerrainManager.HighestTerrainID)
591 { 597 {
592 DetailLog("{0},BSScene.SendCollision,collideWithTerrain,id={1},with={2}", DetailLogZero, localID, collidingWith);
593 return; // don't send collisions to the terrain 598 return; // don't send collisions to the terrain
594 } 599 }
595 600
@@ -601,8 +606,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
601 return; 606 return;
602 } 607 }
603 608
604 // The terrain is not in the physical object list so 'collidee' 609 // The terrain is not in the physical object list so 'collidee' can be null when Collide() is called.
605 // can be null when Collide() is called.
606 BSPhysObject collidee = null; 610 BSPhysObject collidee = null;
607 PhysObjects.TryGetValue(collidingWith, out collidee); 611 PhysObjects.TryGetValue(collidingWith, out collidee);
608 612
@@ -1026,7 +1030,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters
1026 (s) => { return s.m_params[0].shouldRandomizeSolverOrder; }, 1030 (s) => { return s.m_params[0].shouldRandomizeSolverOrder; },
1027 (s,p,l,v) => { s.m_params[0].shouldRandomizeSolverOrder = v; } ), 1031 (s,p,l,v) => { s.m_params[0].shouldRandomizeSolverOrder = v; } ),
1028 new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands", 1032 new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands",
1029 ConfigurationParameters.numericFalse, 1033 ConfigurationParameters.numericTrue,
1030 (s,cf,p,v) => { s.m_params[0].shouldSplitSimulationIslands = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, 1034 (s,cf,p,v) => { s.m_params[0].shouldSplitSimulationIslands = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); },
1031 (s) => { return s.m_params[0].shouldSplitSimulationIslands; }, 1035 (s) => { return s.m_params[0].shouldSplitSimulationIslands; },
1032 (s,p,l,v) => { s.m_params[0].shouldSplitSimulationIslands = v; } ), 1036 (s,p,l,v) => { s.m_params[0].shouldSplitSimulationIslands = v; } ),
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index 6b90661..7fce8c9 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -36,6 +36,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin
36{ 36{
37public class BSShapeCollection : IDisposable 37public class BSShapeCollection : IDisposable
38{ 38{
39 private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]";
40
39 protected BSScene PhysicsScene { get; set; } 41 protected BSScene PhysicsScene { get; set; }
40 42
41 private Object m_collectionActivityLock = new Object(); 43 private Object m_collectionActivityLock = new Object();
@@ -43,24 +45,23 @@ public class BSShapeCollection : IDisposable
43 // Description of a Mesh 45 // Description of a Mesh
44 private struct MeshDesc 46 private struct MeshDesc
45 { 47 {
46 public IntPtr Ptr; 48 public IntPtr ptr;
47 public int referenceCount; 49 public int referenceCount;
48 public DateTime lastReferenced; 50 public DateTime lastReferenced;
49 public IMesh meshData;
50 } 51 }
51 52
52 // Description of a hull. 53 // Description of a hull.
53 // Meshes and hulls have the same shape hash key but we only need hulls for efficient physical objects 54 // Meshes and hulls have the same shape hash key but we only need hulls for efficient physical objects
54 private struct HullDesc 55 private struct HullDesc
55 { 56 {
56 public IntPtr Ptr; 57 public IntPtr ptr;
57 public int referenceCount; 58 public int referenceCount;
58 public DateTime lastReferenced; 59 public DateTime lastReferenced;
59 } 60 }
60 61
61 private struct BodyDesc 62 private struct BodyDesc
62 { 63 {
63 public IntPtr Ptr; 64 public IntPtr ptr;
64 // Bodies are only used once so reference count is always either one or zero 65 // Bodies are only used once so reference count is always either one or zero
65 public int referenceCount; 66 public int referenceCount;
66 public DateTime lastReferenced; 67 public DateTime lastReferenced;
@@ -93,14 +94,16 @@ public class BSShapeCollection : IDisposable
93 lock (m_collectionActivityLock) 94 lock (m_collectionActivityLock)
94 { 95 {
95 // Do we have the correct geometry for this type of object? 96 // Do we have the correct geometry for this type of object?
97 // Updates prim.BSShape with information/pointers to requested shape
96 bool newGeom = CreateGeom(forceRebuild, prim, shapeData, pbs); 98 bool newGeom = CreateGeom(forceRebuild, prim, shapeData, pbs);
97 // If we had to select a new shape geometry for the object, 99 // If we had to select a new shape geometry for the object,
98 // rebuild the body around it. 100 // rebuild the body around it.
101 // Updates prim.BSBody with information/pointers to requested body
99 bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, prim.BSShape, shapeData); 102 bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, prim.BSShape, shapeData);
100 ret = newGeom || newBody; 103 ret = newGeom || newBody;
101 } 104 }
102 DetailLog("{0},BSShapeCollection.GetBodyAndShape,force-{1},ret={2},body={3},shape={4}", 105 DetailLog("{0},BSShapeCollection.GetBodyAndShape,force={1},ret={2},body={3},shape={4}",
103 prim.LocalID, forceRebuild, ret, prim.BSBody, prim.BSShape); 106 prim.LocalID, forceRebuild, ret, prim.BSBody, prim.BSShape);
104 107
105 return ret; 108 return ret;
106 } 109 }
@@ -120,7 +123,8 @@ public class BSShapeCollection : IDisposable
120 } 123 }
121 else 124 else
122 { 125 {
123 bodyDesc.Ptr = shape.ptr; 126 // New entry
127 bodyDesc.ptr = shape.ptr;
124 bodyDesc.referenceCount = 1; 128 bodyDesc.referenceCount = 1;
125 DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,ref={1}", shape.ID, bodyDesc.referenceCount); 129 DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,ref={1}", shape.ID, bodyDesc.referenceCount);
126 } 130 }
@@ -130,7 +134,7 @@ public class BSShapeCollection : IDisposable
130} 134}
131 135
132 // Release the usage of a body. 136 // Release the usage of a body.
133 // Not that this will also delete the body in BUllet if the body is now unused (reference count = 0). 137 // Called when releasing use of a BSBody. BSShape is handled separately.
134 public void DereferenceBody(BulletBody shape, bool inTaintTime) 138 public void DereferenceBody(BulletBody shape, bool inTaintTime)
135 { 139 {
136 if (shape.ptr == IntPtr.Zero) 140 if (shape.ptr == IntPtr.Zero)
@@ -146,15 +150,17 @@ public class BSShapeCollection : IDisposable
146 Bodies[shape.ID] = bodyDesc; 150 Bodies[shape.ID] = bodyDesc;
147 DetailLog("{0},BSShapeCollection.DereferenceBody,ref={1}", shape.ID, bodyDesc.referenceCount); 151 DetailLog("{0},BSShapeCollection.DereferenceBody,ref={1}", shape.ID, bodyDesc.referenceCount);
148 152
153 // If body is no longer being used, free it -- bodies are never shared.
149 if (bodyDesc.referenceCount == 0) 154 if (bodyDesc.referenceCount == 0)
150 { 155 {
151 Bodies.Remove(shape.ID); 156 Bodies.Remove(shape.ID);
152 BSScene.TaintCallback removeOperation = delegate() 157 BSScene.TaintCallback removeOperation = delegate()
153 { 158 {
154 DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. Ptr={1:X}", shape.ID, shape.ptr); 159 DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}",
155 // zero any reference to the shape so it is not freed when the body is deleted 160 shape.ID, shape.ptr.ToString("X"));
161 // Zero any reference to the shape so it is not freed when the body is deleted.
156 BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, shape.ptr, IntPtr.Zero); 162 BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, shape.ptr, IntPtr.Zero);
157 // It may have already been removed from the world in which case the next is a NOOP 163 // It may have already been removed from the world in which case the next is a NOOP.
158 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, shape.ptr); 164 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, shape.ptr);
159 BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, shape.ptr); 165 BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, shape.ptr);
160 }; 166 };
@@ -172,19 +178,13 @@ public class BSShapeCollection : IDisposable
172 } 178 }
173 } 179 }
174 180
175 // Track another user of the shape
176 private bool ReferenceShape(BulletShape shape)
177 {
178 return ReferenceShape(shape, null);
179 }
180
181 // Track the datastructures and use count for a shape. 181 // Track the datastructures and use count for a shape.
182 // When creating a hull, this is called first to reference the mesh 182 // When creating a hull, this is called first to reference the mesh
183 // and then again to reference the hull. 183 // and then again to reference the hull.
184 // Meshes and hulls for the same shape have the same hash key. 184 // Meshes and hulls for the same shape have the same hash key.
185 // NOTE that native shapes are not added to the mesh list or removed. 185 // NOTE that native shapes are not added to the mesh list or removed.
186 // Returns 'true' if this is the initial reference to the shape. Otherwise reused. 186 // Returns 'true' if this is the initial reference to the shape. Otherwise reused.
187 private bool ReferenceShape(BulletShape shape, IMesh meshData) 187 private bool ReferenceShape(BulletShape shape)
188 { 188 {
189 bool ret = false; 189 bool ret = false;
190 switch (shape.type) 190 switch (shape.type)
@@ -196,16 +196,16 @@ public class BSShapeCollection : IDisposable
196 // There is an existing instance of this mesh. 196 // There is an existing instance of this mesh.
197 meshDesc.referenceCount++; 197 meshDesc.referenceCount++;
198 DetailLog("{0},BSShapeColliction.ReferenceShape,existingMesh,key={1},cnt={2}", 198 DetailLog("{0},BSShapeColliction.ReferenceShape,existingMesh,key={1},cnt={2}",
199 BSScene.DetailLogZero, shape.shapeKey, meshDesc.referenceCount); 199 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
200 } 200 }
201 else 201 else
202 { 202 {
203 // This is a new reference to a mesh 203 // This is a new reference to a mesh
204 meshDesc.Ptr = shape.ptr; 204 meshDesc.ptr = shape.ptr;
205 meshDesc.meshData = meshData; 205 // We keep a reference to the underlying IMesh data so a hull can be built
206 meshDesc.referenceCount = 1; 206 meshDesc.referenceCount = 1;
207 DetailLog("{0},BSShapeColliction.ReferenceShape,newMesh,key={1},cnt={2}", 207 DetailLog("{0},BSShapeColliction.ReferenceShape,newMesh,key={1},cnt={2}",
208 BSScene.DetailLogZero, shape.shapeKey, meshDesc.referenceCount); 208 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
209 ret = true; 209 ret = true;
210 } 210 }
211 meshDesc.lastReferenced = System.DateTime.Now; 211 meshDesc.lastReferenced = System.DateTime.Now;
@@ -215,18 +215,18 @@ public class BSShapeCollection : IDisposable
215 HullDesc hullDesc; 215 HullDesc hullDesc;
216 if (Hulls.TryGetValue(shape.shapeKey, out hullDesc)) 216 if (Hulls.TryGetValue(shape.shapeKey, out hullDesc))
217 { 217 {
218 // There is an existing instance of this mesh. 218 // There is an existing instance of this hull.
219 hullDesc.referenceCount++; 219 hullDesc.referenceCount++;
220 DetailLog("{0},BSShapeColliction.ReferenceShape,existingHull,key={1},cnt={2}", 220 DetailLog("{0},BSShapeColliction.ReferenceShape,existingHull,key={1},cnt={2}",
221 BSScene.DetailLogZero, shape.shapeKey, hullDesc.referenceCount); 221 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
222 } 222 }
223 else 223 else
224 { 224 {
225 // This is a new reference to a hull 225 // This is a new reference to a hull
226 hullDesc.Ptr = shape.ptr; 226 hullDesc.ptr = shape.ptr;
227 hullDesc.referenceCount = 1; 227 hullDesc.referenceCount = 1;
228 DetailLog("{0},BSShapeColliction.ReferenceShape,newHull,key={1},cnt={2}", 228 DetailLog("{0},BSShapeColliction.ReferenceShape,newHull,key={1},cnt={2}",
229 BSScene.DetailLogZero, shape.shapeKey, hullDesc.referenceCount); 229 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
230 ret = true; 230 ret = true;
231 231
232 } 232 }
@@ -242,7 +242,8 @@ public class BSShapeCollection : IDisposable
242 return ret; 242 return ret;
243 } 243 }
244 244
245 // Release the usage of a shape 245 // Release the usage of a shape.
246 // The collisionObject is released since it is a copy of the real collision shape.
246 private void DereferenceShape(BulletShape shape, bool atTaintTime) 247 private void DereferenceShape(BulletShape shape, bool atTaintTime)
247 { 248 {
248 if (shape.ptr == IntPtr.Zero) 249 if (shape.ptr == IntPtr.Zero)
@@ -254,8 +255,6 @@ public class BSShapeCollection : IDisposable
254 { 255 {
255 case ShapeData.PhysicsShapeType.SHAPE_HULL: 256 case ShapeData.PhysicsShapeType.SHAPE_HULL:
256 DereferenceHull(shape); 257 DereferenceHull(shape);
257 // Hulls also include a mesh
258 DereferenceMesh(shape);
259 break; 258 break;
260 case ShapeData.PhysicsShapeType.SHAPE_MESH: 259 case ShapeData.PhysicsShapeType.SHAPE_MESH:
261 DereferenceMesh(shape); 260 DereferenceMesh(shape);
@@ -266,15 +265,24 @@ public class BSShapeCollection : IDisposable
266 // Native shapes are not tracked and are released immediately 265 // Native shapes are not tracked and are released immediately
267 if (shape.ptr != IntPtr.Zero & shape.isNativeShape) 266 if (shape.ptr != IntPtr.Zero & shape.isNativeShape)
268 { 267 {
268 DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}",
269 BSScene.DetailLogZero, shape.ptr.ToString("X"), atTaintTime);
269 BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); 270 BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr);
270 } 271 }
271 break; 272 break;
272 } 273 }
273 }; 274 };
274 if (atTaintTime) 275 if (atTaintTime)
275 dereferenceOperation(); 276 {
277 lock (m_collectionActivityLock)
278 {
279 dereferenceOperation();
280 }
281 }
276 else 282 else
283 {
277 PhysicsScene.TaintedObject("BSShapeCollection.DereferenceShape", dereferenceOperation); 284 PhysicsScene.TaintedObject("BSShapeCollection.DereferenceShape", dereferenceOperation);
285 }
278 } 286 }
279 287
280 // Count down the reference count for a mesh shape 288 // Count down the reference count for a mesh shape
@@ -288,8 +296,8 @@ public class BSShapeCollection : IDisposable
288 // TODO: release the Bullet storage 296 // TODO: release the Bullet storage
289 meshDesc.lastReferenced = System.DateTime.Now; 297 meshDesc.lastReferenced = System.DateTime.Now;
290 Meshes[shape.shapeKey] = meshDesc; 298 Meshes[shape.shapeKey] = meshDesc;
291 DetailLog("{0},BSShapeColliction.DereferenceMesh,key={1},cnt={2}", 299 DetailLog("{0},BSShapeCollection.DereferenceMesh,key={1},refCnt={2}",
292 BSScene.DetailLogZero, shape.shapeKey, meshDesc.referenceCount); 300 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
293 301
294 } 302 }
295 } 303 }
@@ -305,8 +313,8 @@ public class BSShapeCollection : IDisposable
305 // TODO: release the Bullet storage (aging old entries?) 313 // TODO: release the Bullet storage (aging old entries?)
306 hullDesc.lastReferenced = System.DateTime.Now; 314 hullDesc.lastReferenced = System.DateTime.Now;
307 Hulls[shape.shapeKey] = hullDesc; 315 Hulls[shape.shapeKey] = hullDesc;
308 DetailLog("{0},BSShapeColliction.DereferenceHull,key={1},cnt={2}", 316 DetailLog("{0},BSShapeCollection.DereferenceHull,key={1},refCnt={2}",
309 BSScene.DetailLogZero, shape.shapeKey, hullDesc.referenceCount); 317 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
310 } 318 }
311 } 319 }
312 320
@@ -322,8 +330,6 @@ public class BSShapeCollection : IDisposable
322 bool haveShape = false; 330 bool haveShape = false;
323 bool nativeShapePossible = true; 331 bool nativeShapePossible = true;
324 332
325 BulletShape newShape = new BulletShape(IntPtr.Zero);
326
327 // If the prim attributes are simple, this could be a simple Bullet native shape 333 // If the prim attributes are simple, this could be a simple Bullet native shape
328 if (nativeShapePossible 334 if (nativeShapePossible
329 && ((pbs.SculptEntry && !PhysicsScene.ShouldMeshSculptedPrim) 335 && ((pbs.SculptEntry && !PhysicsScene.ShouldMeshSculptedPrim)
@@ -340,137 +346,117 @@ public class BSShapeCollection : IDisposable
340 haveShape = true; 346 haveShape = true;
341 if (forceRebuild || (prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE)) 347 if (forceRebuild || (prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE))
342 { 348 {
343 newShape = AddNativeShapeToPrim( 349 ret = GetReferenceToNativeShape(prim, shapeData,
344 prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_SPHERE, ShapeData.FixedShapeKey.KEY_SPHERE); 350 ShapeData.PhysicsShapeType.SHAPE_SPHERE, ShapeData.FixedShapeKey.KEY_SPHERE);
345 DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}", 351 DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}",
346 prim.LocalID, forceRebuild,prim.BSShape); 352 prim.LocalID, forceRebuild, prim.BSShape);
347
348 ret = true;
349 } 353 }
350 } 354 }
351 else 355 else
352 { 356 {
353 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size);
354 haveShape = true; 357 haveShape = true;
355 if (forceRebuild || (prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX)) 358 if (forceRebuild || (prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX))
356 { 359 {
357 newShape = AddNativeShapeToPrim( 360 ret = GetReferenceToNativeShape(
358 prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_BOX, ShapeData.FixedShapeKey.KEY_BOX); 361 prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_BOX, ShapeData.FixedShapeKey.KEY_BOX);
359 DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}", 362 DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}",
360 prim.LocalID, forceRebuild,prim.BSShape); 363 prim.LocalID, forceRebuild, prim.BSShape);
361
362 ret = true;
363 } 364 }
364 } 365 }
365 } 366 }
366 // If a simple shape is not happening, create a mesh and possibly a hull 367 // If a simple shape is not happening, create a mesh and possibly a hull.
367 // Note that if it's a native shape, the check for physical/non-physical is not 368 // Note that if it's a native shape, the check for physical/non-physical is not
368 // made. Native shapes are best used in either case. 369 // made. Native shapes are best used in either case.
369 if (!haveShape) 370 if (!haveShape)
370 { 371 {
371 if (prim.IsPhysical) 372 if (prim.IsPhysical)
372 { 373 {
373 if (forceRebuild || !Hulls.ContainsKey(shapeData.HullKey)) 374 // Update prim.BSShape to reference a hull of this shape.
374 { 375 ret = GetReferenceToHull(prim, shapeData, pbs);
375 // physical objects require a hull for interaction. 376 DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}",
376 // This also creates the mesh if it doesn't already exist. 377 shapeData.ID, prim.BSShape, prim.BSShape.shapeKey.ToString("X"));
377 ret = CreateGeomHull(prim, shapeData, pbs);
378 }
379 else
380 {
381 prim.BSShape = new BulletShape(Hulls[shapeData.HullKey].Ptr,
382 ShapeData.PhysicsShapeType.SHAPE_HULL);
383 prim.BSShape.shapeKey = shapeData.HullKey;
384 // Another user of this shape.
385 ReferenceShape(prim.BSShape);
386 ret = true;
387 }
388 } 378 }
389 else 379 else
390 { 380 {
391 if (forceRebuild || !Meshes.ContainsKey(prim.BSShape.shapeKey)) 381 ret = GetReferenceToMesh(prim, shapeData, pbs);
392 { 382 DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}",
393 // Static (non-physical) objects only need a mesh for bumping into 383 shapeData.ID, prim.BSShape, prim.BSShape.shapeKey.ToString("X"));
394 // Returning 'true' means prim.BShape was changed.
395 ret = CreateGeomMesh(prim, shapeData, pbs);
396 }
397 else
398 {
399 prim.BSShape = new BulletShape(Hulls[shapeData.MeshKey].Ptr,
400 ShapeData.PhysicsShapeType.SHAPE_MESH);
401 prim.BSShape.shapeKey = shapeData.MeshKey;
402 ReferenceShape(prim.BSShape);
403 ret = true;
404 }
405 } 384 }
406 } 385 }
407 return ret; 386 return ret;
408 } 387 }
409 388
410 // Creates a native shape and assignes it to prim.BSShape 389 // Creates a native shape and assignes it to prim.BSShape
411 private BulletShape AddNativeShapeToPrim( 390 private bool GetReferenceToNativeShape( BSPrim prim, ShapeData shapeData,
412 BSPrim prim, ShapeData shapeData, ShapeData.PhysicsShapeType shapeType, 391 ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey)
413 ShapeData.FixedShapeKey shapeKey)
414 { 392 {
415 BulletShape newShape; 393 BulletShape newShape;
416 394
395 shapeData.Type = shapeType;
417 // Bullet native objects are scaled by the Bullet engine so pass the size in 396 // Bullet native objects are scaled by the Bullet engine so pass the size in
418 prim.Scale = shapeData.Size; 397 prim.Scale = shapeData.Size;
419 shapeData.Type = shapeType; 398 shapeData.Scale = shapeData.Size;
420 shapeData.Scale = prim.Scale;
421 399
422 // release any previous shape 400 // release any previous shape
423 DereferenceShape(prim.BSShape, true); 401 DereferenceShape(prim.BSShape, true);
424 402
425 // Shape of this discriptioin is not allocated. Create new. 403 // Native shapes are always built independently.
426 newShape = new BulletShape( 404 newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType);
427 BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType);
428 newShape.shapeKey = (ulong)shapeKey; 405 newShape.shapeKey = (ulong)shapeKey;
429 newShape.isNativeShape = true; 406 newShape.isNativeShape = true;
430 407
431 // Don't to a 'ReferenceShape()' here because native shapes are not tracked. 408 // Don't need to do a 'ReferenceShape()' here because native shapes are not tracked.
409 DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1}", shapeData.ID, newShape);
432 410
433 prim.BSShape = newShape; 411 prim.BSShape = newShape;
434 return newShape; 412 return true;
435 } 413 }
436 414
437 // Returns 'true' of a mesh was actually rebuild. 415 // Builds a mesh shape in the physical world and updates prim.BSShape.
416 // Dereferences previous shape in BSShape and adds a reference for this new shape.
417 // Returns 'true' of a mesh was actually built. Otherwise .
438 // Called at taint-time! 418 // Called at taint-time!
439 private bool CreateGeomMesh(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs) 419 private bool GetReferenceToMesh(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs)
440 { 420 {
441 BulletShape newShape = new BulletShape(IntPtr.Zero); 421 BulletShape newShape = new BulletShape(IntPtr.Zero);
442 422
443 // level of detail based on size and type of the object 423 float lod;
444 float lod = PhysicsScene.MeshLOD; 424 ulong newMeshKey = ComputeShapeKey(shapeData, pbs, out lod);
445 if (pbs.SculptEntry)
446 lod = PhysicsScene.SculptLOD;
447
448 float maxAxis = Math.Max(shapeData.Size.X, Math.Max(shapeData.Size.Y, shapeData.Size.Z));
449 if (maxAxis > PhysicsScene.MeshMegaPrimThreshold)
450 lod = PhysicsScene.MeshMegaPrimLOD;
451
452 ulong newMeshKey = (ulong)pbs.GetMeshKey(shapeData.Size, lod);
453 425
454 // if this new shape is the same as last time, don't recreate the mesh 426 // if this new shape is the same as last time, don't recreate the mesh
455 if (prim.BSShape.shapeKey == newMeshKey) return false; 427 if (prim.BSShape.shapeKey == newMeshKey) return false;
456 428
457 DetailLog("{0},BSShapeCollection.CreateGeomMesh,create,key={1}", prim.LocalID, newMeshKey); 429 DetailLog("{0},BSShapeCollection.CreateGeomMesh,create,oldKey={1},newKey={2}",
430 prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newMeshKey.ToString("X"));
458 431
459 // Since we're recreating new, get rid of the reference to the previous shape 432 // Since we're recreating new, get rid of the reference to the previous shape
460 DereferenceShape(prim.BSShape, true); 433 DereferenceShape(prim.BSShape, true);
461 434
435 newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, pbs, shapeData.Size, lod);
436
437 ReferenceShape(newShape);
438
439 // meshes are already scaled by the meshmerizer
440 prim.Scale = new OMV.Vector3(1f, 1f, 1f);
441 prim.BSShape = newShape;
442
443 return true; // 'true' means a new shape has been added to this prim
444 }
445
446 private BulletShape CreatePhysicalMesh(string objName, ulong newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
447 {
462 IMesh meshData = null; 448 IMesh meshData = null;
463 IntPtr meshPtr; 449 IntPtr meshPtr;
464 MeshDesc meshDesc; 450 MeshDesc meshDesc;
465 if (Meshes.TryGetValue(newMeshKey, out meshDesc)) 451 if (Meshes.TryGetValue(newMeshKey, out meshDesc))
466 { 452 {
467 // If the mesh has already been built just use it. 453 // If the mesh has already been built just use it.
468 meshPtr = meshDesc.Ptr; 454 meshPtr = meshDesc.ptr;
469 } 455 }
470 else 456 else
471 { 457 {
472 // always pass false for physicalness as this creates some sort of bounding box which we don't need 458 // Pass false for physicalness as this creates some sort of bounding box which we don't need
473 meshData = PhysicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, shapeData.Size, lod, false); 459 meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false);
474 460
475 int[] indices = meshData.getIndexListAsInt(); 461 int[] indices = meshData.getIndexListAsInt();
476 List<OMV.Vector3> vertices = meshData.getVertexList(); 462 List<OMV.Vector3> vertices = meshData.getVertexList();
@@ -490,56 +476,62 @@ public class BSShapeCollection : IDisposable
490 meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, 476 meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr,
491 indices.GetLength(0), indices, vertices.Count, verticesAsFloats); 477 indices.GetLength(0), indices, vertices.Count, verticesAsFloats);
492 } 478 }
493 newShape = new BulletShape(meshPtr, ShapeData.PhysicsShapeType.SHAPE_MESH); 479 BulletShape newShape = new BulletShape(meshPtr, ShapeData.PhysicsShapeType.SHAPE_MESH);
494 newShape.shapeKey = newMeshKey; 480 newShape.shapeKey = newMeshKey;
495 481
496 ReferenceShape(newShape, meshData); 482 return newShape;
497
498 // meshes are already scaled by the meshmerizer
499 prim.Scale = new OMV.Vector3(1f, 1f, 1f);
500 prim.BSShape = newShape;
501 return true; // 'true' means a new shape has been added to this prim
502 } 483 }
503 484
504 // Returns 'true' of a mesh was actually rebuild (we could also have one of these specs). 485 // See that hull shape exists in the physical world and update prim.BSShape.
505 List<ConvexResult> m_hulls; 486 // We could be creating the hull because scale changed or whatever.
506 private bool CreateGeomHull(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs) 487 private bool GetReferenceToHull(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs)
507 { 488 {
508 BulletShape newShape; 489 BulletShape newShape;
509 490
510 // Level of detail for the mesh can be different for sculpties and regular meshes. 491 float lod;
511 float lod = pbs.SculptEntry ? PhysicsScene.SculptLOD : PhysicsScene.MeshLOD; 492 ulong newHullKey = ComputeShapeKey(shapeData, pbs, out lod);
512
513 ulong newHullKey = (ulong)pbs.GetMeshKey(shapeData.Size, lod);
514 493
515 // if the hull hasn't changed, don't rebuild it 494 // if the hull hasn't changed, don't rebuild it
516 if (newHullKey == prim.BSShape.shapeKey) return false; 495 if (newHullKey == prim.BSShape.shapeKey) return false;
517 496
518 DetailLog("{0},BSShapeCollection.CreateGeomHull,create,oldKey={1},newKey={2}", prim.LocalID, newHullKey, newHullKey); 497 DetailLog("{0},BSShapeCollection.CreateGeomHull,create,oldKey={1},newKey={2}",
498 prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newHullKey.ToString("X"));
519 499
520 // Remove references to the previous shape. Also removes reference to underlying mesh. 500 // Remove usage of the previous shape. Also removes reference to underlying mesh if it is a hull.
521 DereferenceShape(prim.BSShape, true); 501 DereferenceShape(prim.BSShape, true);
522 502
523 // Do not let the mesh dereference itself again. Was done in the above DerefereceShape(). 503 newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, pbs, shapeData.Size, lod);
524 prim.BSShape.type = ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; 504
525 505 if (!ReferenceShape(newShape))
526 // Make sure the underlying mesh exists and is correct. 506 {
527 // Since we're in the hull code, we know CreateGeomMesh() will not create a native shape. 507 PhysicsScene.Logger.ErrorFormat("{0} Created new hull shape but one already exists: id={1}, key={2}, refCnt={3}",
528 CreateGeomMesh(prim, shapeData, pbs); 508 LogHeader, shapeData.ID, newHullKey.ToString("X"), Hulls[newHullKey].referenceCount);
529 MeshDesc meshDesc = Meshes[newHullKey]; 509 }
510 // hulls are already scaled by the meshmerizer
511 prim.Scale = new OMV.Vector3(1f, 1f, 1f);
512 prim.BSShape = newShape;
513 return true; // 'true' means a new shape has been added to this prim
514 }
515
516 List<ConvexResult> m_hulls;
517 private BulletShape CreatePhysicalHull(string objName, ulong newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
518 {
530 519
531 IntPtr hullPtr; 520 IntPtr hullPtr;
532 HullDesc hullDesc; 521 HullDesc hullDesc;
533 if (Hulls.TryGetValue(newHullKey, out hullDesc)) 522 if (Hulls.TryGetValue(newHullKey, out hullDesc))
534 { 523 {
535 // If the hull shape already is created, just use it. 524 // If the hull shape already is created, just use it.
536 hullPtr = hullDesc.Ptr; 525 hullPtr = hullDesc.ptr;
537 } 526 }
538 else 527 else
539 { 528 {
540 // Build a new hull in the physical world 529 // Build a new hull in the physical world
541 int[] indices = meshDesc.meshData.getIndexListAsInt(); 530 // Pass false for physicalness as this creates some sort of bounding box which we don't need
542 List<OMV.Vector3> vertices = meshDesc.meshData.getVertexList(); 531 IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false);
532
533 int[] indices = meshData.getIndexListAsInt();
534 List<OMV.Vector3> vertices = meshData.getVertexList();
543 535
544 //format conversion from IMesh format to DecompDesc format 536 //format conversion from IMesh format to DecompDesc format
545 List<int> convIndices = new List<int>(); 537 List<int> convIndices = new List<int>();
@@ -616,20 +608,13 @@ public class BSShapeCollection : IDisposable
616 } 608 }
617 } 609 }
618 // create the hull data structure in Bullet 610 // create the hull data structure in Bullet
619 // m_log.DebugFormat("{0}: CreateGeom: calling CreateHull. lid={1}, key={2}, hulls={3}", LogHeader, LocalID, _hullKey, hullCount);
620 hullPtr = BulletSimAPI.CreateHullShape2(PhysicsScene.World.ptr, hullCount, convHulls); 611 hullPtr = BulletSimAPI.CreateHullShape2(PhysicsScene.World.ptr, hullCount, convHulls);
621 } 612 }
622 613
623 newShape = new BulletShape(hullPtr, ShapeData.PhysicsShapeType.SHAPE_HULL); 614 BulletShape newShape = new BulletShape(hullPtr, ShapeData.PhysicsShapeType.SHAPE_HULL);
624 newShape.shapeKey = newHullKey; 615 newShape.shapeKey = newHullKey;
625 newShape.meshPtr = meshDesc.Ptr;
626
627 ReferenceShape(newShape);
628 616
629 // meshes and hulls are already scaled by the meshmerizer 617 return newShape; // 'true' means a new shape has been added to this prim
630 prim.Scale = new OMV.Vector3(1f, 1f, 1f);
631 prim.BSShape = newShape;
632 return true; // 'true' means a new shape has been added to this prim
633 } 618 }
634 619
635 // Callback from convex hull creater with a newly created hull. 620 // Callback from convex hull creater with a newly created hull.
@@ -640,7 +625,30 @@ public class BSShapeCollection : IDisposable
640 return; 625 return;
641 } 626 }
642 627
643 // Create an object in Bullet if it has not already been created. 628 // Create a hash of all the shape parameters to be used as a key
629 // for this particular shape.
630 private ulong ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs, out float retLod)
631 {
632 // level of detail based on size and type of the object
633 float lod = PhysicsScene.MeshLOD;
634 if (pbs.SculptEntry)
635 lod = PhysicsScene.SculptLOD;
636
637 float maxAxis = Math.Max(shapeData.Size.X, Math.Max(shapeData.Size.Y, shapeData.Size.Z));
638 if (maxAxis > PhysicsScene.MeshMegaPrimThreshold)
639 lod = PhysicsScene.MeshMegaPrimLOD;
640
641 retLod = lod;
642 return (ulong)pbs.GetMeshKey(shapeData.Size, lod);
643 }
644 // For those who don't want the LOD
645 private ulong ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs)
646 {
647 float lod;
648 return ComputeShapeKey(shapeData, pbs, out lod);
649 }
650
651 // Create a body object in Bullet.
644 // Updates prim.BSBody with the information about the new body if one is created. 652 // Updates prim.BSBody with the information about the new body if one is created.
645 // Returns 'true' if an object was actually created. 653 // Returns 'true' if an object was actually created.
646 // Called at taint-time. 654 // Called at taint-time.
@@ -665,7 +673,7 @@ public class BSShapeCollection : IDisposable
665 673
666 } 674 }
667 675
668 if (mustRebuild) 676 if (mustRebuild || forceRebuild)
669 { 677 {
670 DereferenceBody(prim.BSBody, true); 678 DereferenceBody(prim.BSBody, true);
671 679
@@ -673,13 +681,15 @@ public class BSShapeCollection : IDisposable
673 IntPtr bodyPtr = IntPtr.Zero; 681 IntPtr bodyPtr = IntPtr.Zero;
674 if (prim.IsSolid) 682 if (prim.IsSolid)
675 { 683 {
676 bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr, shapeData.Position, shapeData.Rotation); 684 bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr,
677 DetailLog("{0},BSShapeCollection.CreateObject,mesh,ptr={1:X}", prim.LocalID, bodyPtr); 685 shapeData.ID, shapeData.Position, shapeData.Rotation);
686 DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
678 } 687 }
679 else 688 else
680 { 689 {
681 bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr, shapeData.Position, shapeData.Rotation); 690 bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr,
682 DetailLog("{0},BSShapeCollection.CreateObject,ghost,ptr={1:X}", prim.LocalID, bodyPtr); 691 shapeData.ID, shapeData.Position, shapeData.Rotation);
692 DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
683 } 693 }
684 aBody = new BulletBody(shapeData.ID, bodyPtr); 694 aBody = new BulletBody(shapeData.ID, bodyPtr);
685 695
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
index 093d2a4..5d5d9cb 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs
@@ -111,8 +111,12 @@ public class BSTerrainManager
111 BulletSimAPI.CreateGroundPlaneShape2(BSScene.GROUNDPLANE_ID, 1f, TERRAIN_COLLISION_MARGIN), 111 BulletSimAPI.CreateGroundPlaneShape2(BSScene.GROUNDPLANE_ID, 1f, TERRAIN_COLLISION_MARGIN),
112 ShapeData.PhysicsShapeType.SHAPE_GROUNDPLANE); 112 ShapeData.PhysicsShapeType.SHAPE_GROUNDPLANE);
113 m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID, 113 m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID,
114 BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, Vector3.Zero, Quaternion.Identity)); 114 BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID,
115 Vector3.Zero, Quaternion.Identity));
115 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr); 116 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr);
117 // Everything collides with the ground plane.
118 BulletSimAPI.SetCollisionFilterMask2(m_groundPlane.ptr,
119 (uint)CollisionFilterGroups.GroundPlaneFilter, (uint)CollisionFilterGroups.GroundPlaneMask);
116 120
117 Vector3 minTerrainCoords = new Vector3(0f, 0f, HEIGHT_INITIALIZATION - HEIGHT_EQUAL_FUDGE); 121 Vector3 minTerrainCoords = new Vector3(0f, 0f, HEIGHT_INITIALIZATION - HEIGHT_EQUAL_FUDGE);
118 Vector3 maxTerrainCoords = new Vector3(DefaultRegionSize.X, DefaultRegionSize.Y, HEIGHT_INITIALIZATION); 122 Vector3 maxTerrainCoords = new Vector3(DefaultRegionSize.X, DefaultRegionSize.Y, HEIGHT_INITIALIZATION);
@@ -304,7 +308,11 @@ public class BSTerrainManager
304 308
305 mapInfo.terrainBody = new BulletBody(mapInfo.ID, 309 mapInfo.terrainBody = new BulletBody(mapInfo.ID,
306 BulletSimAPI.CreateBodyWithDefaultMotionState2(mapInfo.terrainShape.ptr, 310 BulletSimAPI.CreateBodyWithDefaultMotionState2(mapInfo.terrainShape.ptr,
307 centerPos, Quaternion.Identity)); 311 id, centerPos, Quaternion.Identity));
312
313 BulletSimAPI.SetCollisionFilterMask2(mapInfo.terrainBody.ptr,
314 (uint)CollisionFilterGroups.TerrainFilter,
315 (uint)CollisionFilterGroups.TerrainMask);
308 } 316 }
309 317
310 // Make sure the entry is in the heightmap table 318 // Make sure the entry is in the heightmap table
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
index 8480dd1..6910050 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs
@@ -57,9 +57,13 @@ public struct BulletBody
57 { 57 {
58 ID = id; 58 ID = id;
59 ptr = xx; 59 ptr = xx;
60 collisionFilter = 0;
61 collisionMask = 0;
60 } 62 }
61 public IntPtr ptr; 63 public IntPtr ptr;
62 public uint ID; 64 public uint ID;
65 public CollisionFilterGroups collisionFilter;
66 public CollisionFilterGroups collisionMask;
63 public override string ToString() 67 public override string ToString()
64 { 68 {
65 StringBuilder buff = new StringBuilder(); 69 StringBuilder buff = new StringBuilder();
@@ -67,6 +71,13 @@ public struct BulletBody
67 buff.Append(ID.ToString()); 71 buff.Append(ID.ToString());
68 buff.Append(",p="); 72 buff.Append(",p=");
69 buff.Append(ptr.ToString("X")); 73 buff.Append(ptr.ToString("X"));
74 if (collisionFilter != 0 && collisionMask != 0)
75 {
76 buff.Append(",f=");
77 buff.Append(collisionFilter.ToString("X"));
78 buff.Append(",m=");
79 buff.Append(collisionMask.ToString("X"));
80 }
70 buff.Append(">"); 81 buff.Append(">");
71 return buff.ToString(); 82 return buff.ToString();
72 } 83 }
@@ -80,7 +91,6 @@ public struct BulletShape
80 type=ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; 91 type=ShapeData.PhysicsShapeType.SHAPE_UNKNOWN;
81 shapeKey = 0; 92 shapeKey = 0;
82 isNativeShape = false; 93 isNativeShape = false;
83 meshPtr = IntPtr.Zero;
84 } 94 }
85 public BulletShape(IntPtr xx, ShapeData.PhysicsShapeType typ) 95 public BulletShape(IntPtr xx, ShapeData.PhysicsShapeType typ)
86 { 96 {
@@ -88,14 +98,12 @@ public struct BulletShape
88 type = typ; 98 type = typ;
89 shapeKey = 0; 99 shapeKey = 0;
90 isNativeShape = false; 100 isNativeShape = false;
91 meshPtr = IntPtr.Zero;
92 } 101 }
93 public IntPtr ptr; 102 public IntPtr ptr;
94 public ShapeData.PhysicsShapeType type; 103 public ShapeData.PhysicsShapeType type;
95 public ulong shapeKey; 104 public ulong shapeKey;
96 public bool isNativeShape; 105 public bool isNativeShape;
97 // Hulls have an underlying mesh. A pointer to it is hidden here. 106 // Hulls have an underlying mesh. A pointer to it is hidden here.
98 public IntPtr meshPtr;
99 public override string ToString() 107 public override string ToString()
100 { 108 {
101 StringBuilder buff = new StringBuilder(); 109 StringBuilder buff = new StringBuilder();
@@ -107,8 +115,6 @@ public struct BulletShape
107 buff.Append(shapeKey.ToString("X")); 115 buff.Append(shapeKey.ToString("X"));
108 buff.Append(",n="); 116 buff.Append(",n=");
109 buff.Append(isNativeShape.ToString()); 117 buff.Append(isNativeShape.ToString());
110 buff.Append(",m=");
111 buff.Append(meshPtr.ToString("X"));
112 buff.Append(">"); 118 buff.Append(">");
113 return buff.ToString(); 119 return buff.ToString();
114 } 120 }
@@ -124,7 +130,7 @@ public struct BulletConstraint
124 public IntPtr Ptr; 130 public IntPtr Ptr;
125} 131}
126 132
127// An allocated HeightMapThing which hold various heightmap info 133// An allocated HeightMapThing which holds various heightmap info.
128// Made a class rather than a struct so there would be only one 134// Made a class rather than a struct so there would be only one
129// instance of this and C# will pass around pointers rather 135// instance of this and C# will pass around pointers rather
130// than making copies. 136// than making copies.
@@ -345,21 +351,41 @@ public enum CollisionFlags : uint
345// Values for collisions groups and masks 351// Values for collisions groups and masks
346public enum CollisionFilterGroups : uint 352public enum CollisionFilterGroups : uint
347{ 353{
348 NoneFilter = 0, 354 // Don't use the bit definitions!! Define the use in a
349 DefaultFilter = 1 << 0, 355 // filter/mask definition below. This way collision interactions
350 StaticFilter = 1 << 1, 356 // are more easily debugged.
351 KinematicFilter = 1 << 2, 357 BNoneFilter = 0,
352 DebrisFilter = 1 << 3, 358 BDefaultFilter = 1 << 0,
353 SensorTrigger = 1 << 4, 359 BStaticFilter = 1 << 1,
354 CharacterFilter = 1 << 5, 360 BKinematicFilter = 1 << 2,
355 AllFilter = 0xFFFFFFFF, 361 BDebrisFilter = 1 << 3,
362 BSensorTrigger = 1 << 4,
363 BCharacterFilter = 1 << 5,
364 BAllFilter = 0xFFFFFFFF,
356 // Filter groups defined by BulletSim 365 // Filter groups defined by BulletSim
357 GroundPlaneFilter = 1 << 10, 366 BGroundPlaneFilter = 1 << 10,
358 TerrainFilter = 1 << 11, 367 BTerrainFilter = 1 << 11,
359 RaycastFilter = 1 << 12, 368 BRaycastFilter = 1 << 12,
360 SolidFilter = 1 << 13, 369 BSolidFilter = 1 << 13,
370
371 // The collsion filters and masked are defined in one place -- don't want them scattered
372 AvatarFilter = BDefaultFilter | BCharacterFilter | BSolidFilter,
373 AvatarMask = BAllFilter,
374 ObjectFilter = BDefaultFilter | BSolidFilter,
375 ObjectMask = BAllFilter,
376 StaticObjectFilter = BDefaultFilter | BStaticFilter | BSolidFilter,
377 StaticObjectMask = BAllFilter,
378 VolumeDetectFilter = BSensorTrigger,
379 VolumeDetectMask = ~BSensorTrigger,
380 TerrainFilter = BTerrainFilter,
381 TerrainMask = BAllFilter,
382 GroundPlaneFilter = BAllFilter,
383 GroundPlaneMask = BAllFilter
384
361}; 385};
362 386
387
388
363// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0 389// CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0
364// ERP controls amount of correction per tick. Usable range=0.1..0.8. Default=0.2. 390// ERP controls amount of correction per tick. Usable range=0.1..0.8. Default=0.2.
365public enum ConstraintParams : int 391public enum ConstraintParams : int
@@ -560,7 +586,7 @@ public static extern IntPtr CreateHullShape2(IntPtr world,
560 int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls); 586 int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls);
561 587
562[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 588[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
563public static extern IntPtr BuildHullShape2(IntPtr world, IntPtr meshShape); 589public static extern IntPtr BuildHullShapeFromMesh2(IntPtr world, IntPtr meshShape);
564 590
565[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 591[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
566public static extern IntPtr BuildNativeShape2(IntPtr world, ShapeData shapeData); 592public static extern IntPtr BuildNativeShape2(IntPtr world, ShapeData shapeData);
@@ -581,7 +607,7 @@ public static extern void RemoveChildFromCompoundShape2(IntPtr cShape, IntPtr re
581public static extern IntPtr DuplicateCollisionShape2(IntPtr sim, IntPtr srcShape, uint id); 607public static extern IntPtr DuplicateCollisionShape2(IntPtr sim, IntPtr srcShape, uint id);
582 608
583[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 609[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
584public static extern IntPtr CreateBodyFromShapeAndInfo2(IntPtr sim, IntPtr shape, IntPtr constructionInfo); 610public static extern IntPtr CreateBodyFromShapeAndInfo2(IntPtr sim, IntPtr shape, uint id, IntPtr constructionInfo);
585 611
586[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 612[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
587public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape); 613public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape);
@@ -590,13 +616,13 @@ public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape);
590public static extern int GetBodyType2(IntPtr obj); 616public static extern int GetBodyType2(IntPtr obj);
591 617
592[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 618[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
593public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, Vector3 pos, Quaternion rot); 619public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, uint id, Vector3 pos, Quaternion rot);
594 620
595[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 621[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
596public static extern IntPtr CreateBodyWithDefaultMotionState2(IntPtr shape, Vector3 pos, Quaternion rot); 622public static extern IntPtr CreateBodyWithDefaultMotionState2(IntPtr shape, uint id, Vector3 pos, Quaternion rot);
597 623
598[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 624[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
599public static extern IntPtr CreateGhostFromShape2(IntPtr sim, IntPtr shape, Vector3 pos, Quaternion rot); 625public static extern IntPtr CreateGhostFromShape2(IntPtr sim, IntPtr shape, uint id, Vector3 pos, Quaternion rot);
600 626
601[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 627[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
602public static extern IntPtr AllocateBodyInfo2(IntPtr obj); 628public static extern IntPtr AllocateBodyInfo2(IntPtr obj);
@@ -1015,6 +1041,9 @@ public static extern Vector3 GetPushVelocity2(IntPtr obj);
1015[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1041[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1016public static extern Vector3 GetTurnVelocity2(IntPtr obj); 1042public static extern Vector3 GetTurnVelocity2(IntPtr obj);
1017 1043
1044[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1045public static extern void SetCollisionFilterMask2(IntPtr body, uint filter, uint mask);
1046
1018// ===================================================================================== 1047// =====================================================================================
1019// btCollisionShape entries 1048// btCollisionShape entries
1020 1049
@@ -1066,9 +1095,6 @@ public static extern void SetMargin2(IntPtr shape, float val);
1066[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1095[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1067public static extern float GetMargin2(IntPtr shape); 1096public static extern float GetMargin2(IntPtr shape);
1068 1097
1069[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
1070public static extern void SetCollisionFilterMask(IntPtr shape, uint filter, uint mask);
1071
1072// ===================================================================================== 1098// =====================================================================================
1073// Debugging 1099// Debugging
1074[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] 1100[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]