diff options
author | Robert Adams | 2012-09-25 15:01:18 -0700 |
---|---|---|
committer | Robert Adams | 2012-09-27 22:01:42 -0700 |
commit | 735d89e3692bb7c620b9e3c248a1dbd5924b8b3f (patch) | |
tree | 0d31723cc7302e4928de6ac69905787099442bf1 /OpenSim/Region | |
parent | BulletSim: renamed members of BulletShape, BulletSim and BulletBody (diff) | |
download | opensim-SC-735d89e3692bb7c620b9e3c248a1dbd5924b8b3f.zip opensim-SC-735d89e3692bb7c620b9e3c248a1dbd5924b8b3f.tar.gz opensim-SC-735d89e3692bb7c620b9e3c248a1dbd5924b8b3f.tar.bz2 opensim-SC-735d89e3692bb7c620b9e3c248a1dbd5924b8b3f.tar.xz |
BulletSim: btGhostObjects working to make 'volume detect' work.
Rearrangement and cleanup of shape collection code. Much more readable.
Enabling and use of collision filters and masks.
Addition of ID to body creation BulletSimAPI calls so always set in
shape for collision reporting.
Change default of ShouldSplitSimulationIslands and ShouldRandomizeSolverOrder
from 'false' to 'true'. When 'false', this suppresses NO_CONTACT_RESPONSE
which makes volume detect fail.
Diffstat (limited to '')
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] |