diff options
Diffstat (limited to 'OpenSim/Region/Physics')
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; | |||
39 | using OpenMetaverse; | 39 | using 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 | { |
37 | public class BSShapeCollection : IDisposable | 37 | public 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 |
346 | public enum CollisionFilterGroups : uint | 352 | public 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. |
365 | public enum ConstraintParams : int | 391 | public 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] |
563 | public static extern IntPtr BuildHullShape2(IntPtr world, IntPtr meshShape); | 589 | public static extern IntPtr BuildHullShapeFromMesh2(IntPtr world, IntPtr meshShape); |
564 | 590 | ||
565 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 591 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
566 | public static extern IntPtr BuildNativeShape2(IntPtr world, ShapeData shapeData); | 592 | public static extern IntPtr BuildNativeShape2(IntPtr world, ShapeData shapeData); |
@@ -581,7 +607,7 @@ public static extern void RemoveChildFromCompoundShape2(IntPtr cShape, IntPtr re | |||
581 | public static extern IntPtr DuplicateCollisionShape2(IntPtr sim, IntPtr srcShape, uint id); | 607 | public 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] |
584 | public static extern IntPtr CreateBodyFromShapeAndInfo2(IntPtr sim, IntPtr shape, IntPtr constructionInfo); | 610 | public 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] |
587 | public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape); | 613 | public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape); |
@@ -590,13 +616,13 @@ public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape); | |||
590 | public static extern int GetBodyType2(IntPtr obj); | 616 | public static extern int GetBodyType2(IntPtr obj); |
591 | 617 | ||
592 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 618 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
593 | public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, Vector3 pos, Quaternion rot); | 619 | public 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] |
596 | public static extern IntPtr CreateBodyWithDefaultMotionState2(IntPtr shape, Vector3 pos, Quaternion rot); | 622 | public 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] |
599 | public static extern IntPtr CreateGhostFromShape2(IntPtr sim, IntPtr shape, Vector3 pos, Quaternion rot); | 625 | public 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] |
602 | public static extern IntPtr AllocateBodyInfo2(IntPtr obj); | 628 | public 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] |
1016 | public static extern Vector3 GetTurnVelocity2(IntPtr obj); | 1042 | public static extern Vector3 GetTurnVelocity2(IntPtr obj); |
1017 | 1043 | ||
1044 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
1045 | public 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] |
1067 | public static extern float GetMargin2(IntPtr shape); | 1096 | public static extern float GetMargin2(IntPtr shape); |
1068 | 1097 | ||
1069 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
1070 | public 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] |