diff options
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin')
10 files changed, 274 insertions, 132 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 9e1206a..2a5397e 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs | |||
@@ -200,7 +200,9 @@ public sealed class BSCharacter : BSPhysObject | |||
200 | } | 200 | } |
201 | // I want the physics engine to make an avatar capsule | 201 | // I want the physics engine to make an avatar capsule |
202 | public override ShapeData.PhysicsShapeType PreferredPhysicalShape | 202 | public override ShapeData.PhysicsShapeType PreferredPhysicalShape |
203 | { get { return ShapeData.PhysicsShapeType.SHAPE_AVATAR; } } | 203 | { |
204 | get {return ShapeData.PhysicsShapeType.SHAPE_AVATAR; } | ||
205 | } | ||
204 | 206 | ||
205 | public override bool Grabbed { | 207 | public override bool Grabbed { |
206 | set { _grabbed = value; } | 208 | set { _grabbed = value; } |
@@ -238,6 +240,7 @@ public sealed class BSCharacter : BSPhysObject | |||
238 | } | 240 | } |
239 | public override OMV.Vector3 Position { | 241 | public override OMV.Vector3 Position { |
240 | get { | 242 | get { |
243 | // Don't refetch the position because this function is called a zillion times | ||
241 | // _position = BulletSimAPI.GetObjectPosition2(Scene.World.ptr, LocalID); | 244 | // _position = BulletSimAPI.GetObjectPosition2(Scene.World.ptr, LocalID); |
242 | return _position; | 245 | return _position; |
243 | } | 246 | } |
@@ -304,15 +307,11 @@ public sealed class BSCharacter : BSPhysObject | |||
304 | { | 307 | { |
305 | // The new position value must be pushed into the physics engine but we can't | 308 | // The new position value must be pushed into the physics engine but we can't |
306 | // just assign to "Position" because of potential call loops. | 309 | // just assign to "Position" because of potential call loops. |
307 | BSScene.TaintCallback sanityOperation = delegate() | 310 | PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate() |
308 | { | 311 | { |
309 | DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); | 312 | DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); |
310 | BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); | 313 | BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); |
311 | }; | 314 | }); |
312 | if (inTaintTime) | ||
313 | sanityOperation(); | ||
314 | else | ||
315 | PhysicsScene.TaintedObject("BSCharacter.PositionSanityCheck", sanityOperation); | ||
316 | ret = true; | 315 | ret = true; |
317 | } | 316 | } |
318 | return ret; | 317 | return ret; |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 9e0f499..8f973f4 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | |||
@@ -48,7 +48,8 @@ public abstract class BSLinkset | |||
48 | */ | 48 | */ |
49 | 49 | ||
50 | // at the moment, there is only one | 50 | // at the moment, there is only one |
51 | ret = new BSLinksetConstraints(physScene, parent); | 51 | // ret = new BSLinksetConstraints(physScene, parent); |
52 | ret = new BSLinksetCompound(physScene, parent); | ||
52 | 53 | ||
53 | return ret; | 54 | return ret; |
54 | } | 55 | } |
@@ -69,10 +70,19 @@ public abstract class BSLinkset | |||
69 | protected object m_linksetActivityLock = new Object(); | 70 | protected object m_linksetActivityLock = new Object(); |
70 | 71 | ||
71 | // Some linksets have a preferred physical shape. | 72 | // Some linksets have a preferred physical shape. |
72 | // Returns SHAPE_UNKNOWN if there is no preference. | 73 | // Returns SHAPE_UNKNOWN if there is no preference. Causes the correct shape to be selected. |
73 | public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape | 74 | public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) |
74 | { get { return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; } } | 75 | { |
76 | return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; | ||
77 | } | ||
75 | 78 | ||
79 | // Linksets move around the children so the linkset might need to compute the child position | ||
80 | public virtual OMV.Vector3 Position(BSPhysObject member) | ||
81 | { return member.RawPosition; } | ||
82 | public virtual OMV.Quaternion Orientation(BSPhysObject member) | ||
83 | { return member.RawOrientation; } | ||
84 | // TODO: does this need to be done for Velocity and RotationalVelocityy? | ||
85 | |||
76 | // We keep the prim's mass in the linkset structure since it could be dependent on other prims | 86 | // We keep the prim's mass in the linkset structure since it could be dependent on other prims |
77 | protected float m_mass; | 87 | protected float m_mass; |
78 | public float LinksetMass | 88 | public float LinksetMass |
@@ -177,7 +187,6 @@ public abstract class BSLinkset | |||
177 | } | 187 | } |
178 | 188 | ||
179 | // Perform an action on each member of the linkset including root prim. | 189 | // Perform an action on each member of the linkset including root prim. |
180 | // The action is performed only on the objects that are physically in the linkset. | ||
181 | // Depends on the action on whether this should be done at taint time. | 190 | // Depends on the action on whether this should be done at taint time. |
182 | public delegate bool ForEachMemberAction(BSPhysObject obj); | 191 | public delegate bool ForEachMemberAction(BSPhysObject obj); |
183 | public virtual bool ForEachMember(ForEachMemberAction action) | 192 | public virtual bool ForEachMember(ForEachMemberAction action) |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs index 638fae1..8b97ebb 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs | |||
@@ -41,18 +41,31 @@ public sealed class BSLinksetCompound : BSLinkset | |||
41 | base.Initialize(scene, parent); | 41 | base.Initialize(scene, parent); |
42 | } | 42 | } |
43 | 43 | ||
44 | // For compound implimented linksets, if there are children, use compound shape for the root. | ||
45 | public override ShapeData.PhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) | ||
46 | { | ||
47 | ShapeData.PhysicsShapeType ret = ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; | ||
48 | if (IsRoot(requestor) && HasAnyChildren) | ||
49 | { | ||
50 | ret = ShapeData.PhysicsShapeType.SHAPE_COMPOUND; | ||
51 | } | ||
52 | // DetailLog("{0},BSLinksetCompound.PreferredPhysicalShape,call,shape={1}", LinksetRoot.LocalID, ret); | ||
53 | return ret; | ||
54 | } | ||
55 | |||
44 | // When physical properties are changed the linkset needs to recalculate | 56 | // When physical properties are changed the linkset needs to recalculate |
45 | // its internal properties. | 57 | // its internal properties. |
46 | // This is queued in the 'post taint' queue so the | 58 | // This is queued in the 'post taint' queue so the |
47 | // refresh will happen once after all the other taints are applied. | 59 | // refresh will happen once after all the other taints are applied. |
48 | public override void Refresh(BSPhysObject requestor) | 60 | public override void Refresh(BSPhysObject requestor) |
49 | { | 61 | { |
62 | DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,requestor={1}", LinksetRoot.LocalID, requestor.LocalID); | ||
50 | // Queue to happen after all the other taint processing | 63 | // Queue to happen after all the other taint processing |
51 | PhysicsScene.PostTaintObject("BSLinksetcompound.Refresh", requestor.LocalID, delegate() | 64 | PhysicsScene.PostTaintObject("BSLinksetCompound.Refresh", requestor.LocalID, delegate() |
52 | { | 65 | { |
53 | if (HasAnyChildren && IsRoot(requestor)) | 66 | if (IsRoot(requestor) && HasAnyChildren) |
54 | RecomputeLinksetCompound(); | 67 | RecomputeLinksetCompound(); |
55 | }); | 68 | }); |
56 | } | 69 | } |
57 | 70 | ||
58 | // The object is going dynamic (physical). Do any setup necessary | 71 | // The object is going dynamic (physical). Do any setup necessary |
@@ -63,8 +76,17 @@ public sealed class BSLinksetCompound : BSLinkset | |||
63 | // Called at taint-time! | 76 | // Called at taint-time! |
64 | public override bool MakeDynamic(BSPhysObject child) | 77 | public override bool MakeDynamic(BSPhysObject child) |
65 | { | 78 | { |
66 | // What is done for each object in BSPrim is what we want. | 79 | bool ret = false; |
67 | return false; | 80 | DetailLog("{0},BSLinksetCompound.MakeDynamic,call,isChild={1}", child.LocalID, HasChild(child)); |
81 | if (HasChild(child)) | ||
82 | { | ||
83 | // Physical children are removed from the world as the shape ofthe root compound | ||
84 | // shape takes over. | ||
85 | BulletSimAPI.AddToCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); | ||
86 | BulletSimAPI.ForceActivationState2(child.PhysBody.ptr, ActivationState.DISABLE_SIMULATION); | ||
87 | ret = true; | ||
88 | } | ||
89 | return ret; | ||
68 | } | 90 | } |
69 | 91 | ||
70 | // The object is going static (non-physical). Do any setup necessary for a static linkset. | 92 | // The object is going static (non-physical). Do any setup necessary for a static linkset. |
@@ -74,8 +96,17 @@ public sealed class BSLinksetCompound : BSLinkset | |||
74 | // Called at taint-time! | 96 | // Called at taint-time! |
75 | public override bool MakeStatic(BSPhysObject child) | 97 | public override bool MakeStatic(BSPhysObject child) |
76 | { | 98 | { |
77 | // What is done for each object in BSPrim is what we want. | 99 | bool ret = false; |
78 | return false; | 100 | DetailLog("{0},BSLinksetCompound.MakeStatic,call,hasChild={1}", child.LocalID, HasChild(child)); |
101 | if (HasChild(child)) | ||
102 | { | ||
103 | // The non-physical children can come back to life. | ||
104 | BulletSimAPI.RemoveFromCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); | ||
105 | // Don't force activation so setting of DISABLE_SIMULATION can stay. | ||
106 | BulletSimAPI.Activate2(child.PhysBody.ptr, false); | ||
107 | ret = true; | ||
108 | } | ||
109 | return ret; | ||
79 | } | 110 | } |
80 | 111 | ||
81 | // Called at taint-time!! | 112 | // Called at taint-time!! |
@@ -84,20 +115,35 @@ public sealed class BSLinksetCompound : BSLinkset | |||
84 | // Nothing to do for constraints on property updates | 115 | // Nothing to do for constraints on property updates |
85 | } | 116 | } |
86 | 117 | ||
118 | // The children move around in relationship to the root. | ||
119 | // Just grab the current values of wherever it is right now. | ||
120 | public override OMV.Vector3 Position(BSPhysObject member) | ||
121 | { | ||
122 | return BulletSimAPI.GetPosition2(member.PhysBody.ptr); | ||
123 | } | ||
124 | |||
125 | public override OMV.Quaternion Orientation(BSPhysObject member) | ||
126 | { | ||
127 | return BulletSimAPI.GetOrientation2(member.PhysBody.ptr); | ||
128 | } | ||
129 | |||
87 | // Routine called when rebuilding the body of some member of the linkset. | 130 | // Routine called when rebuilding the body of some member of the linkset. |
88 | // Destroy all the constraints have have been made to root and set | 131 | // Since we don't keep in-physical world relationships, do nothing unless it's a child changing. |
89 | // up to rebuild the constraints before the next simulation step. | ||
90 | // Returns 'true' of something was actually removed and would need restoring | 132 | // Returns 'true' of something was actually removed and would need restoring |
91 | // Called at taint-time!! | 133 | // Called at taint-time!! |
92 | public override bool RemoveBodyDependencies(BSPrim child) | 134 | public override bool RemoveBodyDependencies(BSPrim child) |
93 | { | 135 | { |
94 | bool ret = false; | 136 | bool ret = false; |
95 | 137 | ||
96 | DetailLog("{0},BSLinksetcompound.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", | 138 | DetailLog("{0},BSLinksetCompound.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2},isRoot={3}", |
97 | child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X")); | 139 | child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), IsRoot(child)); |
98 | 140 | ||
99 | // Cause the current shape to be freed and the new one to be built. | 141 | if (!IsRoot(child)) |
100 | Refresh(LinksetRoot); | 142 | { |
143 | // Cause the current shape to be freed and the new one to be built. | ||
144 | Refresh(LinksetRoot); | ||
145 | ret = true; | ||
146 | } | ||
101 | 147 | ||
102 | return ret; | 148 | return ret; |
103 | } | 149 | } |
@@ -139,13 +185,19 @@ public sealed class BSLinksetCompound : BSLinkset | |||
139 | LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), | 185 | LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), |
140 | child.LocalID, child.PhysBody.ptr.ToString("X")); | 186 | child.LocalID, child.PhysBody.ptr.ToString("X")); |
141 | 187 | ||
142 | // See that the linkset parameters are recomputed at the end of the taint time. | 188 | // Cause the child's body to be rebuilt and thus restored to normal operation |
143 | Refresh(LinksetRoot); | 189 | child.ForceBodyShapeRebuild(false); |
144 | } | 190 | |
145 | else | 191 | if (!HasAnyChildren) |
146 | { | 192 | { |
147 | // Non-fatal occurance. | 193 | // The linkset is now empty. The root needs rebuilding. |
148 | // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader); | 194 | LinksetRoot.ForceBodyShapeRebuild(false); |
195 | } | ||
196 | else | ||
197 | { | ||
198 | // Schedule a rebuild of the linkset before the next simulation tick. | ||
199 | Refresh(LinksetRoot); | ||
200 | } | ||
149 | } | 201 | } |
150 | return; | 202 | return; |
151 | } | 203 | } |
@@ -158,16 +210,18 @@ public sealed class BSLinksetCompound : BSLinkset | |||
158 | // Called at taint time!! | 210 | // Called at taint time!! |
159 | private void RecomputeLinksetCompound() | 211 | private void RecomputeLinksetCompound() |
160 | { | 212 | { |
161 | // Release the existing shape | 213 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},numChildren={2}", |
162 | PhysicsScene.Shapes.DereferenceShape(LinksetRoot.PhysShape, true, null); | 214 | LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), NumberOfChildren); |
163 | 215 | ||
216 | LinksetRoot.ForceBodyShapeRebuild(true); | ||
217 | |||
164 | float linksetMass = LinksetMass; | 218 | float linksetMass = LinksetMass; |
165 | LinksetRoot.UpdatePhysicalMassProperties(linksetMass); | 219 | LinksetRoot.UpdatePhysicalMassProperties(linksetMass); |
166 | 220 | ||
167 | // DEBUG: see of inter-linkset collisions are causing problems | 221 | // DEBUG: see of inter-linkset collisions are causing problems |
168 | // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, | 222 | // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, |
169 | // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); | 223 | // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); |
170 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,set,rBody={1},linksetMass={2}", | 224 | DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,end,rBody={1},linksetMass={2}", |
171 | LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), linksetMass); | 225 | LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), linksetMass); |
172 | 226 | ||
173 | 227 | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs index 65aed77..67a59ef 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs | |||
@@ -84,6 +84,18 @@ public sealed class BSLinksetConstraints : BSLinkset | |||
84 | // Nothing to do for constraints on property updates | 84 | // Nothing to do for constraints on property updates |
85 | } | 85 | } |
86 | 86 | ||
87 | // The children of the linkset are moved around by the constraints. | ||
88 | // Just grab the current values of wherever it is right now. | ||
89 | public override OMV.Vector3 Position(BSPhysObject member) | ||
90 | { | ||
91 | return BulletSimAPI.GetPosition2(member.PhysBody.ptr); | ||
92 | } | ||
93 | |||
94 | public override OMV.Quaternion Orientation(BSPhysObject member) | ||
95 | { | ||
96 | return BulletSimAPI.GetOrientation2(member.PhysBody.ptr); | ||
97 | } | ||
98 | |||
87 | // Routine called when rebuilding the body of some member of the linkset. | 99 | // Routine called when rebuilding the body of some member of the linkset. |
88 | // Destroy all the constraints have have been made to root and set | 100 | // Destroy all the constraints have have been made to root and set |
89 | // up to rebuild the constraints before the next simulation step. | 101 | // up to rebuild the constraints before the next simulation step. |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index 65d7f34..7127aaf 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs | |||
@@ -81,7 +81,9 @@ public abstract class BSPhysObject : PhysicsActor | |||
81 | // Some types of objects have preferred physical representations. | 81 | // Some types of objects have preferred physical representations. |
82 | // Returns SHAPE_UNKNOWN if there is no preference. | 82 | // Returns SHAPE_UNKNOWN if there is no preference. |
83 | public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape | 83 | public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape |
84 | { get { return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; } } | 84 | { |
85 | get { return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; } | ||
86 | } | ||
85 | 87 | ||
86 | // When the physical properties are updated, an EntityProperty holds the update values. | 88 | // When the physical properties are updated, an EntityProperty holds the update values. |
87 | // Keep the current and last EntityProperties to enable computation of differences | 89 | // Keep the current and last EntityProperties to enable computation of differences |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 1754be6..af403aa 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | |||
@@ -173,20 +173,16 @@ public sealed class BSPrim : BSPhysObject | |||
173 | } | 173 | } |
174 | // Whatever the linkset wants is what I want. | 174 | // Whatever the linkset wants is what I want. |
175 | public override ShapeData.PhysicsShapeType PreferredPhysicalShape | 175 | public override ShapeData.PhysicsShapeType PreferredPhysicalShape |
176 | { get { return Linkset.PreferredPhysicalShape; } } | 176 | { get { return Linkset.PreferredPhysicalShape(this); } } |
177 | 177 | ||
178 | public override bool ForceBodyShapeRebuild(bool inTaintTime) | 178 | public override bool ForceBodyShapeRebuild(bool inTaintTime) |
179 | { | 179 | { |
180 | LastAssetBuildFailed = false; | 180 | LastAssetBuildFailed = false; |
181 | BSScene.TaintCallback rebuildOperation = delegate() | 181 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ForceBodyShapeRebuild", delegate() |
182 | { | 182 | { |
183 | _mass = CalculateMass(); // changing the shape changes the mass | 183 | _mass = CalculateMass(); // changing the shape changes the mass |
184 | CreateGeomAndObject(true); | 184 | CreateGeomAndObject(true); |
185 | }; | 185 | }); |
186 | if (inTaintTime) | ||
187 | rebuildOperation(); | ||
188 | else | ||
189 | PhysicsScene.TaintedObject("BSPrim.ForceBodyShapeRebuild", rebuildOperation); | ||
190 | return true; | 186 | return true; |
191 | } | 187 | } |
192 | public override bool Grabbed { | 188 | public override bool Grabbed { |
@@ -263,9 +259,9 @@ public sealed class BSPrim : BSPhysObject | |||
263 | } | 259 | } |
264 | public override OMV.Vector3 Position { | 260 | public override OMV.Vector3 Position { |
265 | get { | 261 | get { |
262 | // child prims move around based on their parent. Need to get the latest location | ||
266 | if (!Linkset.IsRoot(this)) | 263 | if (!Linkset.IsRoot(this)) |
267 | // child prims move around based on their parent. Need to get the latest location | 264 | _position = Linkset.Position(this); |
268 | _position = BulletSimAPI.GetPosition2(PhysBody.ptr); | ||
269 | 265 | ||
270 | // don't do the GetObjectPosition for root elements because this function is called a zillion times | 266 | // don't do the GetObjectPosition for root elements because this function is called a zillion times |
271 | // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); | 267 | // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); |
@@ -344,16 +340,11 @@ public sealed class BSPrim : BSPhysObject | |||
344 | { | 340 | { |
345 | // The new position value must be pushed into the physics engine but we can't | 341 | // The new position value must be pushed into the physics engine but we can't |
346 | // just assign to "Position" because of potential call loops. | 342 | // just assign to "Position" because of potential call loops. |
347 | BSScene.TaintCallback sanityOperation = delegate() | 343 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.PositionSanityCheck", delegate() |
348 | { | 344 | { |
349 | DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); | 345 | DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); |
350 | ForcePosition = _position; | 346 | ForcePosition = _position; |
351 | }; | 347 | }); |
352 | if (inTaintTime) | ||
353 | sanityOperation(); | ||
354 | else | ||
355 | PhysicsScene.TaintedObject("BSPrim.PositionSanityCheck", sanityOperation); | ||
356 | |||
357 | ret = true; | 348 | ret = true; |
358 | } | 349 | } |
359 | return ret; | 350 | return ret; |
@@ -542,10 +533,10 @@ public sealed class BSPrim : BSPhysObject | |||
542 | } | 533 | } |
543 | public override OMV.Quaternion Orientation { | 534 | public override OMV.Quaternion Orientation { |
544 | get { | 535 | get { |
536 | // Children move around because tied to parent. Get a fresh value. | ||
545 | if (!Linkset.IsRoot(this)) | 537 | if (!Linkset.IsRoot(this)) |
546 | { | 538 | { |
547 | // Children move around because tied to parent. Get a fresh value. | 539 | _orientation = Linkset.Orientation(this); |
548 | _orientation = BulletSimAPI.GetOrientation2(PhysBody.ptr); | ||
549 | } | 540 | } |
550 | return _orientation; | 541 | return _orientation; |
551 | } | 542 | } |
@@ -946,7 +937,7 @@ public sealed class BSPrim : BSPhysObject | |||
946 | m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); | 937 | m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); |
947 | return; | 938 | return; |
948 | } | 939 | } |
949 | BSScene.TaintCallback addForceOperation = delegate() | 940 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate() |
950 | { | 941 | { |
951 | OMV.Vector3 fSum = OMV.Vector3.Zero; | 942 | OMV.Vector3 fSum = OMV.Vector3.Zero; |
952 | lock (m_accumulatedForces) | 943 | lock (m_accumulatedForces) |
@@ -961,11 +952,7 @@ public sealed class BSPrim : BSPhysObject | |||
961 | DetailLog("{0},BSPrim.AddForce,taint,force={1}", LocalID, fSum); | 952 | DetailLog("{0},BSPrim.AddForce,taint,force={1}", LocalID, fSum); |
962 | if (fSum != OMV.Vector3.Zero) | 953 | if (fSum != OMV.Vector3.Zero) |
963 | BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, fSum); | 954 | BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, fSum); |
964 | }; | 955 | }); |
965 | if (inTaintTime) | ||
966 | addForceOperation(); | ||
967 | else | ||
968 | PhysicsScene.TaintedObject("BSPrim.AddForce", addForceOperation); | ||
969 | } | 956 | } |
970 | 957 | ||
971 | private List<OMV.Vector3> m_accumulatedAngularForces = new List<OMV.Vector3>(); | 958 | private List<OMV.Vector3> m_accumulatedAngularForces = new List<OMV.Vector3>(); |
@@ -985,7 +972,7 @@ public sealed class BSPrim : BSPhysObject | |||
985 | m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); | 972 | m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); |
986 | return; | 973 | return; |
987 | } | 974 | } |
988 | BSScene.TaintCallback addAngularForceOperation = delegate() | 975 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddAngularForce", delegate() |
989 | { | 976 | { |
990 | OMV.Vector3 fSum = OMV.Vector3.Zero; | 977 | OMV.Vector3 fSum = OMV.Vector3.Zero; |
991 | lock (m_accumulatedAngularForces) | 978 | lock (m_accumulatedAngularForces) |
@@ -1003,26 +990,19 @@ public sealed class BSPrim : BSPhysObject | |||
1003 | BulletSimAPI.ApplyTorque2(PhysBody.ptr, fSum); | 990 | BulletSimAPI.ApplyTorque2(PhysBody.ptr, fSum); |
1004 | _torque = fSum; | 991 | _torque = fSum; |
1005 | } | 992 | } |
1006 | }; | 993 | }); |
1007 | if (inTaintTime) | ||
1008 | addAngularForceOperation(); | ||
1009 | else | ||
1010 | PhysicsScene.TaintedObject("BSPrim.AddAngularForce", addAngularForceOperation); | ||
1011 | } | 994 | } |
1012 | // A torque impulse. | 995 | // A torque impulse. |
1013 | public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime) | 996 | public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime) |
1014 | { | 997 | { |
1015 | OMV.Vector3 applyImpulse = impulse; | 998 | OMV.Vector3 applyImpulse = impulse; |
1016 | BSScene.TaintCallback applyTorqueImpulseOperation = delegate() | 999 | PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate() |
1017 | { | 1000 | { |
1018 | DetailLog("{0},BSPrim.ApplyTorqueImpulse,taint,tImpulse={1}", LocalID, applyImpulse); | 1001 | DetailLog("{0},BSPrim.ApplyTorqueImpulse,taint,tImpulse={1}", LocalID, applyImpulse); |
1019 | BulletSimAPI.ApplyTorqueImpulse2(PhysBody.ptr, applyImpulse); | 1002 | BulletSimAPI.ApplyTorqueImpulse2(PhysBody.ptr, applyImpulse); |
1020 | }; | 1003 | }); |
1021 | if (inTaintTime) | ||
1022 | applyTorqueImpulseOperation(); | ||
1023 | else | ||
1024 | PhysicsScene.TaintedObject("BSPrim.ApplyTorqueImpulse", applyTorqueImpulseOperation); | ||
1025 | } | 1004 | } |
1005 | |||
1026 | public override void SetMomentum(OMV.Vector3 momentum) { | 1006 | public override void SetMomentum(OMV.Vector3 momentum) { |
1027 | // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); | 1007 | // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); |
1028 | } | 1008 | } |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index cc5dbb2..dcfcb83 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs | |||
@@ -692,6 +692,16 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
692 | return; | 692 | return; |
693 | } | 693 | } |
694 | 694 | ||
695 | // Sometimes a potentially tainted operation can be used in and out of taint time. | ||
696 | // This routine executes the command immediately if in taint-time otherwise it is queued. | ||
697 | public void TaintedObject(bool inTaintTime, string ident, TaintCallback callback) | ||
698 | { | ||
699 | if (inTaintTime) | ||
700 | callback(); | ||
701 | else | ||
702 | TaintedObject(ident, callback); | ||
703 | } | ||
704 | |||
695 | // When someone tries to change a property on a BSPrim or BSCharacter, the object queues | 705 | // When someone tries to change a property on a BSPrim or BSCharacter, the object queues |
696 | // a callback into itself to do the actual property change. That callback is called | 706 | // a callback into itself to do the actual property change. That callback is called |
697 | // here just before the physics engine is called to step the simulation. | 707 | // here just before the physics engine is called to step the simulation. |
@@ -1438,7 +1448,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters | |||
1438 | { | 1448 | { |
1439 | PhysicsLogging.Write(msg, args); | 1449 | PhysicsLogging.Write(msg, args); |
1440 | // Add the Flush() if debugging crashes to get all the messages written out. | 1450 | // Add the Flush() if debugging crashes to get all the messages written out. |
1441 | // PhysicsLogging.Flush(); | 1451 | PhysicsLogging.Flush(); |
1442 | } | 1452 | } |
1443 | // Used to fill in the LocalID when there isn't one. It's the correct number of characters. | 1453 | // Used to fill in the LocalID when there isn't one. It's the correct number of characters. |
1444 | public const string DetailLogZero = "0000000000"; | 1454 | public const string DetailLogZero = "0000000000"; |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index e131919..107befe 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs | |||
@@ -122,18 +122,14 @@ public sealed class BSShapeCollection : IDisposable | |||
122 | lock (m_collectionActivityLock) | 122 | lock (m_collectionActivityLock) |
123 | { | 123 | { |
124 | DetailLog("{0},BSShapeCollection.ReferenceBody,newBody", body.ID, body); | 124 | DetailLog("{0},BSShapeCollection.ReferenceBody,newBody", body.ID, body); |
125 | BSScene.TaintCallback createOperation = delegate() | 125 | PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.ReferenceBody", delegate() |
126 | { | 126 | { |
127 | if (!BulletSimAPI.IsInWorld2(body.ptr)) | 127 | if (!BulletSimAPI.IsInWorld2(body.ptr)) |
128 | { | 128 | { |
129 | BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr); | 129 | BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr); |
130 | DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body); | 130 | DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body); |
131 | } | 131 | } |
132 | }; | 132 | }); |
133 | if (inTaintTime) | ||
134 | createOperation(); | ||
135 | else | ||
136 | PhysicsScene.TaintedObject("BSShapeCollection.ReferenceBody", createOperation); | ||
137 | } | 133 | } |
138 | } | 134 | } |
139 | 135 | ||
@@ -146,7 +142,7 @@ public sealed class BSShapeCollection : IDisposable | |||
146 | 142 | ||
147 | lock (m_collectionActivityLock) | 143 | lock (m_collectionActivityLock) |
148 | { | 144 | { |
149 | BSScene.TaintCallback removeOperation = delegate() | 145 | PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceBody", delegate() |
150 | { | 146 | { |
151 | DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}, inTaintTime={2}", | 147 | DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}, inTaintTime={2}", |
152 | body.ID, body.ptr.ToString("X"), inTaintTime); | 148 | body.ID, body.ptr.ToString("X"), inTaintTime); |
@@ -159,12 +155,7 @@ public sealed class BSShapeCollection : IDisposable | |||
159 | // Zero any reference to the shape so it is not freed when the body is deleted. | 155 | // Zero any reference to the shape so it is not freed when the body is deleted. |
160 | BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero); | 156 | BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero); |
161 | BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr); | 157 | BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr); |
162 | }; | 158 | }); |
163 | // If already in taint-time, do the operations now. Otherwise queue for later. | ||
164 | if (inTaintTime) | ||
165 | removeOperation(); | ||
166 | else | ||
167 | PhysicsScene.TaintedObject("BSShapeCollection.DereferenceBody", removeOperation); | ||
168 | } | 159 | } |
169 | } | 160 | } |
170 | 161 | ||
@@ -238,7 +229,7 @@ public sealed class BSShapeCollection : IDisposable | |||
238 | if (shape.ptr == IntPtr.Zero) | 229 | if (shape.ptr == IntPtr.Zero) |
239 | return; | 230 | return; |
240 | 231 | ||
241 | BSScene.TaintCallback dereferenceOperation = delegate() | 232 | PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceShape", delegate() |
242 | { | 233 | { |
243 | if (shape.ptr != IntPtr.Zero) | 234 | if (shape.ptr != IntPtr.Zero) |
244 | { | 235 | { |
@@ -270,18 +261,7 @@ public sealed class BSShapeCollection : IDisposable | |||
270 | } | 261 | } |
271 | } | 262 | } |
272 | } | 263 | } |
273 | }; | 264 | }); |
274 | if (inTaintTime) | ||
275 | { | ||
276 | lock (m_collectionActivityLock) | ||
277 | { | ||
278 | dereferenceOperation(); | ||
279 | } | ||
280 | } | ||
281 | else | ||
282 | { | ||
283 | PhysicsScene.TaintedObject("BSShapeCollection.DereferenceShape", dereferenceOperation); | ||
284 | } | ||
285 | } | 265 | } |
286 | 266 | ||
287 | // Count down the reference count for a mesh shape | 267 | // Count down the reference count for a mesh shape |
@@ -311,7 +291,10 @@ public sealed class BSShapeCollection : IDisposable | |||
311 | { | 291 | { |
312 | hullDesc.referenceCount--; | 292 | hullDesc.referenceCount--; |
313 | // TODO: release the Bullet storage (aging old entries?) | 293 | // TODO: release the Bullet storage (aging old entries?) |
294 | |||
295 | // Tell upper layers that, if they have dependencies on this shape, this link is going away | ||
314 | if (shapeCallback != null) shapeCallback(shape); | 296 | if (shapeCallback != null) shapeCallback(shape); |
297 | |||
315 | hullDesc.lastReferenced = System.DateTime.Now; | 298 | hullDesc.lastReferenced = System.DateTime.Now; |
316 | Hulls[shape.shapeKey] = hullDesc; | 299 | Hulls[shape.shapeKey] = hullDesc; |
317 | DetailLog("{0},BSShapeCollection.DereferenceHull,key={1},refCnt={2}", | 300 | DetailLog("{0},BSShapeCollection.DereferenceHull,key={1},refCnt={2}", |
@@ -320,10 +303,48 @@ public sealed class BSShapeCollection : IDisposable | |||
320 | } | 303 | } |
321 | 304 | ||
322 | // Remove a reference to a compound shape. | 305 | // Remove a reference to a compound shape. |
306 | // Taking a compound shape apart is a little tricky because if you just delete the | ||
307 | // physical object, it will free all the underlying children. We can't do that because | ||
308 | // they could be shared. So, this removes each of the children from the compound and | ||
309 | // dereferences them separately before destroying the compound collision object itself. | ||
323 | // Called at taint-time. | 310 | // Called at taint-time. |
324 | private void DereferenceCompound(BulletShape shape, ShapeDestructionCallback shapeCallback) | 311 | private void DereferenceCompound(BulletShape shape, ShapeDestructionCallback shapeCallback) |
325 | { | 312 | { |
326 | // Compound shape is made of a bunch of meshes and natives. | 313 | if (!BulletSimAPI.IsCompound2(shape.ptr)) |
314 | { | ||
315 | // Failed the sanity check!! | ||
316 | PhysicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}", | ||
317 | LogHeader, shape.type, shape.ptr.ToString("X")); | ||
318 | DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}", | ||
319 | BSScene.DetailLogZero, shape.type, shape.ptr.ToString("X")); | ||
320 | return; | ||
321 | } | ||
322 | int numChildren = BulletSimAPI.GetNumberOfCompoundChildren2(shape.ptr); | ||
323 | for (int ii = 0; ii < numChildren; ii++) | ||
324 | { | ||
325 | IntPtr childShape = BulletSimAPI.RemoveChildShapeFromCompoundShapeIndex2(shape.ptr, ii); | ||
326 | DereferenceAnonCollisionShape(childShape); | ||
327 | } | ||
328 | BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); | ||
329 | } | ||
330 | |||
331 | // Sometimes we have a pointer to a collision shape but don't know what type it is. | ||
332 | // Figure out type and call the correct dereference routine. | ||
333 | // This is coming from a compound shape that we created so we know it is either native or mesh. | ||
334 | // Called at taint-time. | ||
335 | private void DereferenceAnonCollisionShape(IntPtr cShape) | ||
336 | { | ||
337 | BulletShape shapeInfo = new BulletShape(cShape, ShapeData.PhysicsShapeType.SHAPE_MESH); | ||
338 | if (BulletSimAPI.IsCompound2(cShape)) | ||
339 | shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_COMPOUND; | ||
340 | |||
341 | if (BulletSimAPI.IsNativeShape2(cShape)) | ||
342 | { | ||
343 | shapeInfo.isNativeShape = true; | ||
344 | shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter) | ||
345 | } | ||
346 | |||
347 | DereferenceShape(shapeInfo, true, null); | ||
327 | } | 348 | } |
328 | 349 | ||
329 | // Create the geometry information in Bullet for later use. | 350 | // Create the geometry information in Bullet for later use. |
@@ -338,10 +359,8 @@ public sealed class BSShapeCollection : IDisposable | |||
338 | { | 359 | { |
339 | bool ret = false; | 360 | bool ret = false; |
340 | bool haveShape = false; | 361 | bool haveShape = false; |
341 | bool nativeShapePossible = true; | ||
342 | PrimitiveBaseShape pbs = prim.BaseShape; | ||
343 | 362 | ||
344 | if (prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_AVATAR) | 363 | if (!haveShape && prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_AVATAR) |
345 | { | 364 | { |
346 | // an avatar capsule is close to a native shape (it is not shared) | 365 | // an avatar capsule is close to a native shape (it is not shared) |
347 | ret = GetReferenceToNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_AVATAR, | 366 | ret = GetReferenceToNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_AVATAR, |
@@ -350,6 +369,31 @@ public sealed class BSShapeCollection : IDisposable | |||
350 | ret = true; | 369 | ret = true; |
351 | haveShape = true; | 370 | haveShape = true; |
352 | } | 371 | } |
372 | |||
373 | // Compound shapes are handled special as they are rebuilt from scratch. | ||
374 | // This isn't too great a hardship since most of the child shapes will already been created. | ||
375 | if (!haveShape && prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_COMPOUND) | ||
376 | { | ||
377 | ret = GetReferenceToCompoundShape(prim, shapeCallback); | ||
378 | DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape); | ||
379 | haveShape = true; | ||
380 | } | ||
381 | |||
382 | if (!haveShape) | ||
383 | { | ||
384 | ret = CreateGeomNonSpecial(forceRebuild, prim, shapeCallback); | ||
385 | } | ||
386 | |||
387 | return ret; | ||
388 | } | ||
389 | |||
390 | private bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback) | ||
391 | { | ||
392 | bool ret = false; | ||
393 | bool haveShape = false; | ||
394 | bool nativeShapePossible = true; | ||
395 | PrimitiveBaseShape pbs = prim.BaseShape; | ||
396 | |||
353 | // If the prim attributes are simple, this could be a simple Bullet native shape | 397 | // If the prim attributes are simple, this could be a simple Bullet native shape |
354 | if (!haveShape | 398 | if (!haveShape |
355 | && pbs != null | 399 | && pbs != null |
@@ -363,6 +407,7 @@ public sealed class BSShapeCollection : IDisposable | |||
363 | && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 | 407 | && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 |
364 | && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) ) | 408 | && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) ) |
365 | { | 409 | { |
410 | // It doesn't look like Bullet scales spheres so make sure the scales are all equal | ||
366 | if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) | 411 | if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) |
367 | && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z) | 412 | && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z) |
368 | { | 413 | { |
@@ -378,7 +423,7 @@ public sealed class BSShapeCollection : IDisposable | |||
378 | prim.LocalID, forceRebuild, prim.PhysShape); | 423 | prim.LocalID, forceRebuild, prim.PhysShape); |
379 | } | 424 | } |
380 | } | 425 | } |
381 | if (pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) | 426 | if (!haveShape && pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) |
382 | { | 427 | { |
383 | haveShape = true; | 428 | haveShape = true; |
384 | if (forceRebuild | 429 | if (forceRebuild |
@@ -393,9 +438,10 @@ public sealed class BSShapeCollection : IDisposable | |||
393 | } | 438 | } |
394 | } | 439 | } |
395 | } | 440 | } |
441 | |||
396 | // If a simple shape is not happening, create a mesh and possibly a hull. | 442 | // If a simple shape is not happening, create a mesh and possibly a hull. |
397 | // Note that if it's a native shape, the check for physical/non-physical is not | 443 | // Note that if it's a native shape, the check for physical/non-physical is not |
398 | // made. Native shapes are best used in either case. | 444 | // made. Native shapes work in either case. |
399 | if (!haveShape && pbs != null) | 445 | if (!haveShape && pbs != null) |
400 | { | 446 | { |
401 | if (prim.IsPhysical && PhysicsScene.ShouldUseHullsForPhysicalObjects) | 447 | if (prim.IsPhysical && PhysicsScene.ShouldUseHullsForPhysicalObjects) |
@@ -487,7 +533,7 @@ public sealed class BSShapeCollection : IDisposable | |||
487 | if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH) | 533 | if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH) |
488 | return false; | 534 | return false; |
489 | 535 | ||
490 | DetailLog("{0},BSShapeCollection.CreateGeomMesh,create,oldKey={1},newKey={2}", | 536 | DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2}", |
491 | prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X")); | 537 | prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X")); |
492 | 538 | ||
493 | // Since we're recreating new, get rid of the reference to the previous shape | 539 | // Since we're recreating new, get rid of the reference to the previous shape |
@@ -535,7 +581,7 @@ public sealed class BSShapeCollection : IDisposable | |||
535 | verticesAsFloats[vi++] = vv.Z; | 581 | verticesAsFloats[vi++] = vv.Z; |
536 | } | 582 | } |
537 | 583 | ||
538 | // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", | 584 | // m_log.DebugFormat("{0}: BSShapeCollection.CreatePhysicalMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", |
539 | // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count); | 585 | // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count); |
540 | 586 | ||
541 | meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, | 587 | meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, |
@@ -561,7 +607,7 @@ public sealed class BSShapeCollection : IDisposable | |||
561 | if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL) | 607 | if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL) |
562 | return false; | 608 | return false; |
563 | 609 | ||
564 | DetailLog("{0},BSShapeCollection.CreateGeomHull,create,oldKey={1},newKey={2}", | 610 | DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}", |
565 | prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X")); | 611 | prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X")); |
566 | 612 | ||
567 | // Remove usage of the previous shape. | 613 | // Remove usage of the previous shape. |
@@ -693,6 +739,42 @@ public sealed class BSShapeCollection : IDisposable | |||
693 | return; | 739 | return; |
694 | } | 740 | } |
695 | 741 | ||
742 | // Compound shapes are always built from scratch. | ||
743 | // This shouldn't be to bad since most of the parts will be meshes that had been built previously. | ||
744 | private bool GetReferenceToCompoundShape(BSPhysObject prim, ShapeDestructionCallback shapeCallback) | ||
745 | { | ||
746 | BulletShape cShape = new BulletShape( | ||
747 | BulletSimAPI.CreateCompoundShape2(PhysicsScene.World.ptr), ShapeData.PhysicsShapeType.SHAPE_COMPOUND); | ||
748 | |||
749 | // The prim's linkset is the source of the children. | ||
750 | // TODO: there is too much knowledge here about the internals of linksets and too much | ||
751 | // dependency on the relationship of compound shapes and linksets (what if we want to use | ||
752 | // compound shapes for something else?). Think through this and clean up so the | ||
753 | // appropriate knowledge is used at the correct software levels. | ||
754 | |||
755 | // Recreate the geometry of the root prim (might have been a linkset root in the past) | ||
756 | CreateGeomNonSpecial(true, prim, null); | ||
757 | |||
758 | BSPhysObject rootPrim = prim.Linkset.LinksetRoot; | ||
759 | |||
760 | prim.Linkset.ForEachMember(delegate(BSPhysObject cPrim) | ||
761 | { | ||
762 | OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(rootPrim.RawOrientation); | ||
763 | OMV.Vector3 displacementPos = (cPrim.RawPosition - rootPrim.RawPosition) * invRootOrientation; | ||
764 | OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation; | ||
765 | |||
766 | DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}", | ||
767 | prim.LocalID, cPrim.LocalID, cPrim.PhysShape.ptr.ToString("X"), displacementPos, displacementRot); | ||
768 | |||
769 | BulletSimAPI.AddChildShapeToCompoundShape2(cShape.ptr, cPrim.PhysShape.ptr, displacementPos, displacementRot); | ||
770 | return false; | ||
771 | }); | ||
772 | |||
773 | prim.PhysShape = cShape; | ||
774 | |||
775 | return true; | ||
776 | } | ||
777 | |||
696 | // Create a hash of all the shape parameters to be used as a key | 778 | // Create a hash of all the shape parameters to be used as a key |
697 | // for this particular shape. | 779 | // for this particular shape. |
698 | private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod) | 780 | private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod) |
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs index 11298fe..7c34af2 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs | |||
@@ -238,7 +238,7 @@ public sealed class BSTerrainManager | |||
238 | DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,call,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}", | 238 | DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,call,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}", |
239 | BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY); | 239 | BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY); |
240 | 240 | ||
241 | BSScene.TaintCallback rebuildOperation = delegate() | 241 | PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateOrCreateTerrain:UpdateExisting", delegate() |
242 | { | 242 | { |
243 | if (MegaRegionParentPhysicsScene != null) | 243 | if (MegaRegionParentPhysicsScene != null) |
244 | { | 244 | { |
@@ -337,14 +337,7 @@ public sealed class BSTerrainManager | |||
337 | BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION); | 337 | BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION); |
338 | 338 | ||
339 | m_terrainModified = true; | 339 | m_terrainModified = true; |
340 | }; | 340 | }); |
341 | |||
342 | // There is the option to do the changes now (we're already in 'taint time'), or | ||
343 | // to do the Bullet operations later. | ||
344 | if (inTaintTime) | ||
345 | rebuildOperation(); | ||
346 | else | ||
347 | PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:UpdateExisting", rebuildOperation); | ||
348 | } | 341 | } |
349 | else | 342 | else |
350 | { | 343 | { |
@@ -364,7 +357,7 @@ public sealed class BSTerrainManager | |||
364 | BSScene.DetailLogZero, newTerrainID, minCoords, minCoords); | 357 | BSScene.DetailLogZero, newTerrainID, minCoords, minCoords); |
365 | 358 | ||
366 | // Code that must happen at taint-time | 359 | // Code that must happen at taint-time |
367 | BSScene.TaintCallback createOperation = delegate() | 360 | PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateOrCreateTerrain:NewTerrain", delegate() |
368 | { | 361 | { |
369 | DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,taint,baseX={1},baseY={2}", BSScene.DetailLogZero, minCoords.X, minCoords.Y); | 362 | DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,taint,baseX={1},baseY={2}", BSScene.DetailLogZero, minCoords.X, minCoords.Y); |
370 | // Create a new mapInfo that will be filled with the new info | 363 | // Create a new mapInfo that will be filled with the new info |
@@ -377,13 +370,7 @@ public sealed class BSTerrainManager | |||
377 | UpdateOrCreateTerrain(newTerrainID, heightMap, minCoords, maxCoords, true); | 370 | UpdateOrCreateTerrain(newTerrainID, heightMap, minCoords, maxCoords, true); |
378 | 371 | ||
379 | m_terrainModified = true; | 372 | m_terrainModified = true; |
380 | }; | 373 | }); |
381 | |||
382 | // If already in taint-time, just call Bullet. Otherwise queue the operations for the safe time. | ||
383 | if (inTaintTime) | ||
384 | createOperation(); | ||
385 | else | ||
386 | PhysicsScene.TaintedObject("BSScene.UpdateOrCreateTerrain:NewTerrain", createOperation); | ||
387 | } | 374 | } |
388 | } | 375 | } |
389 | 376 | ||
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 3b6355c..143b8be 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs | |||
@@ -399,8 +399,6 @@ public enum CollisionFilterGroups : uint | |||
399 | 399 | ||
400 | }; | 400 | }; |
401 | 401 | ||
402 | |||
403 | |||
404 | // CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0 | 402 | // CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0 |
405 | // ERP controls amount of correction per tick. Usable range=0.1..0.8. Default=0.2. | 403 | // ERP controls amount of correction per tick. Usable range=0.1..0.8. Default=0.2. |
406 | public enum ConstraintParams : int | 404 | public enum ConstraintParams : int |
@@ -618,10 +616,19 @@ public static extern IntPtr BuildCapsuleShape2(IntPtr world, float radius, float | |||
618 | public static extern IntPtr CreateCompoundShape2(IntPtr sim); | 616 | public static extern IntPtr CreateCompoundShape2(IntPtr sim); |
619 | 617 | ||
620 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 618 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
621 | public static extern void AddChildToCompoundShape2(IntPtr cShape, IntPtr addShape, Vector3 pos, Quaternion rot); | 619 | public static extern int GetNumberOfCompoundChildren2(IntPtr cShape); |
620 | |||
621 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
622 | public static extern void AddChildShapeToCompoundShape2(IntPtr cShape, IntPtr addShape, Vector3 pos, Quaternion rot); | ||
623 | |||
624 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
625 | public static extern IntPtr GetChildShapeFromCompoundShapeIndex2(IntPtr cShape, int indx); | ||
626 | |||
627 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | ||
628 | public static extern IntPtr RemoveChildShapeFromCompoundShapeIndex2(IntPtr cShape, int indx); | ||
622 | 629 | ||
623 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 630 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
624 | public static extern void RemoveChildFromCompoundShape2(IntPtr cShape, IntPtr removeShape); | 631 | public static extern void RemoveChildShapeFromCompoundShape2(IntPtr cShape, IntPtr removeShape); |
625 | 632 | ||
626 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] | 633 | [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] |
627 | public static extern IntPtr DuplicateCollisionShape2(IntPtr sim, IntPtr srcShape, uint id); | 634 | public static extern IntPtr DuplicateCollisionShape2(IntPtr sim, IntPtr srcShape, uint id); |