aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs113
1 files changed, 96 insertions, 17 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
index bc9f9be..fe5b5e3 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
@@ -32,6 +32,31 @@ using OMV = OpenMetaverse;
32 32
33namespace OpenSim.Region.Physics.BulletSPlugin 33namespace OpenSim.Region.Physics.BulletSPlugin
34{ 34{
35
36// When a child is linked, the relationship position of the child to the parent
37// is remembered so the child's world position can be recomputed when it is
38// removed from the linkset.
39sealed class BSLinksetCompoundInfo : BSLinksetInfo
40{
41 public OMV.Vector3 OffsetPos;
42 public OMV.Quaternion OffsetRot;
43 public BSLinksetCompoundInfo(OMV.Vector3 p, OMV.Quaternion r)
44 {
45 OffsetPos = p;
46 OffsetRot = r;
47 }
48 public override string ToString()
49 {
50 StringBuilder buff = new StringBuilder();
51 buff.Append("<p=");
52 buff.Append(OffsetPos.ToString());
53 buff.Append(",r=");
54 buff.Append(OffsetRot.ToString());
55 buff.Append(">");
56 return buff.ToString();
57 }
58};
59
35public sealed class BSLinksetCompound : BSLinkset 60public sealed class BSLinksetCompound : BSLinkset
36{ 61{
37 private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]"; 62 private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]";
@@ -44,6 +69,7 @@ public sealed class BSLinksetCompound : BSLinkset
44 // For compound implimented linksets, if there are children, use compound shape for the root. 69 // For compound implimented linksets, if there are children, use compound shape for the root.
45 public override BSPhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) 70 public override BSPhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor)
46 { 71 {
72 // Returning 'unknown' means we don't have a preference.
47 BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN; 73 BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
48 if (IsRoot(requestor) && HasAnyChildren) 74 if (IsRoot(requestor) && HasAnyChildren)
49 { 75 {
@@ -63,10 +89,10 @@ public sealed class BSLinksetCompound : BSLinkset
63 // InternalRefresh(requestor); 89 // InternalRefresh(requestor);
64 } 90 }
65 91
92 // Schedule a refresh to happen after all the other taint processing.
66 private void InternalRefresh(BSPhysObject requestor) 93 private void InternalRefresh(BSPhysObject requestor)
67 { 94 {
68 DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,requestor={1}", LinksetRoot.LocalID, requestor.LocalID); 95 DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,requestor={1}", LinksetRoot.LocalID, requestor.LocalID);
69 // Queue to happen after all the other taint processing
70 PhysicsScene.PostTaintObject("BSLinksetCompound.Refresh", requestor.LocalID, delegate() 96 PhysicsScene.PostTaintObject("BSLinksetCompound.Refresh", requestor.LocalID, delegate()
71 { 97 {
72 if (IsRoot(requestor) && HasAnyChildren) 98 if (IsRoot(requestor) && HasAnyChildren)
@@ -108,7 +134,7 @@ public sealed class BSLinksetCompound : BSLinkset
108 { 134 {
109 // The non-physical children can come back to life. 135 // The non-physical children can come back to life.
110 BulletSimAPI.RemoveFromCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); 136 BulletSimAPI.RemoveFromCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE);
111 // Don't force activation so setting of DISABLE_SIMULATION can stay. 137 // Don't force activation so setting of DISABLE_SIMULATION can stay if used.
112 BulletSimAPI.Activate2(child.PhysBody.ptr, false); 138 BulletSimAPI.Activate2(child.PhysBody.ptr, false);
113 ret = true; 139 ret = true;
114 } 140 }
@@ -146,6 +172,10 @@ public sealed class BSLinksetCompound : BSLinkset
146 172
147 if (!IsRoot(child)) 173 if (!IsRoot(child))
148 { 174 {
175 // Because it is a convenient time, recompute child world position and rotation based on
176 // its position in the linkset.
177 RecomputeChildWorldPosition(child, true);
178
149 // Cause the current shape to be freed and the new one to be built. 179 // Cause the current shape to be freed and the new one to be built.
150 InternalRefresh(LinksetRoot); 180 InternalRefresh(LinksetRoot);
151 ret = true; 181 ret = true;
@@ -154,6 +184,42 @@ public sealed class BSLinksetCompound : BSLinkset
154 return ret; 184 return ret;
155 } 185 }
156 186
187 // When the linkset is built, the child shape is added
188 // to the compound shape relative to the root shape. The linkset then moves around but
189 // this does not move the actual child prim. The child prim's location must be recomputed
190 // based on the location of the root shape.
191 private void RecomputeChildWorldPosition(BSPhysObject child, bool inTaintTime)
192 {
193 BSLinksetCompoundInfo lci = child.LinksetInfo as BSLinksetCompoundInfo;
194 if (lci != null)
195 {
196 if (inTaintTime)
197 {
198 OMV.Vector3 oldPos = child.RawPosition;
199 child.ForcePosition = LinksetRoot.RawPosition + lci.OffsetPos;
200 child.ForceOrientation = LinksetRoot.RawOrientation * lci.OffsetRot;
201 DetailLog("{0},BSLinksetCompound.RecomputeChildWorldPosition,oldPos={1},lci={2},newPos={3}",
202 child.LocalID, oldPos, lci, child.RawPosition);
203 }
204 else
205 {
206 // TaintedObject is not used here so the raw position is set now and not at taint-time.
207 child.Position = LinksetRoot.RawPosition + lci.OffsetPos;
208 child.Orientation = LinksetRoot.RawOrientation * lci.OffsetRot;
209 }
210 }
211 else
212 {
213 // This happens when children have been added to the linkset but the linkset
214 // has not been constructed yet. So like, at taint time, adding children to a linkset
215 // and then changing properties of the children (makePhysical, for instance)
216 // but the post-print action of actually rebuilding the linkset has not yet happened.
217 // PhysicsScene.Logger.WarnFormat("{0} Restoring linkset child position failed because of no relative position computed. ID={1}",
218 // LogHeader, child.LocalID);
219 DetailLog("{0},BSLinksetCompound.recomputeChildWorldPosition,noRelativePositonInfo", child.LocalID);
220 }
221 }
222
157 // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', 223 // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true',
158 // this routine will restore the removed constraints. 224 // this routine will restore the removed constraints.
159 // Called at taint-time!! 225 // Called at taint-time!!
@@ -192,8 +258,7 @@ public sealed class BSLinksetCompound : BSLinkset
192 child.LocalID, child.PhysBody.ptr.ToString("X")); 258 child.LocalID, child.PhysBody.ptr.ToString("X"));
193 259
194 // Cause the child's body to be rebuilt and thus restored to normal operation 260 // Cause the child's body to be rebuilt and thus restored to normal operation
195 // TODO: position and rotation must be restored because the child could have moved 261 RecomputeChildWorldPosition(child, false);
196 // based on the linkset.
197 child.ForceBodyShapeRebuild(false); 262 child.ForceBodyShapeRebuild(false);
198 263
199 if (!HasAnyChildren) 264 if (!HasAnyChildren)
@@ -228,43 +293,57 @@ public sealed class BSLinksetCompound : BSLinkset
228 { 293 {
229 if (!IsRoot(cPrim)) 294 if (!IsRoot(cPrim))
230 { 295 {
231 // Each child position and rotation is given relative to the root. 296 // Compute the displacement of the child from the root of the linkset.
232 OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation); 297 // This info is saved in the child prim so the relationship does not
233 OMV.Vector3 displacementPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation; 298 // change over time and the new child position can be computed
234 OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation; 299 // when the linkset is being disassembled (the linkset may have moved).
300 BSLinksetCompoundInfo lci = cPrim.LinksetInfo as BSLinksetCompoundInfo;
301 if (lci == null)
302 {
303 // Each child position and rotation is given relative to the root.
304 OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation);
305 OMV.Vector3 displacementPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation;
306 OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation;
307
308 // Save relative position for recomputing child's world position after moving linkset.
309 lci = new BSLinksetCompoundInfo(displacementPos, displacementRot);
310 cPrim.LinksetInfo = lci;
311 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,creatingRelPos,lci={1}", cPrim.LocalID, lci);
312 }
235 313
236 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}", 314 DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}",
237 LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, displacementPos, displacementRot); 315 LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, lci.OffsetPos, lci.OffsetRot);
238 316
239 if (cPrim.PhysShape.isNativeShape) 317 if (cPrim.PhysShape.isNativeShape)
240 { 318 {
241 // A native shape is turning into a null collision shape because native 319 // A native shape is turning into a hull collision shape because native
242 // shapes are not shared so we have to hullify it so it will be tracked 320 // shapes are not shared so we have to hullify it so it will be tracked
243 // and freed at the correct time. This also solves the scaling problem 321 // and freed at the correct time. This also solves the scaling problem
244 // (native shapes scaled but hull/meshes are assumed to not be). 322 // (native shapes scaled but hull/meshes are assumed to not be).
323 // TODO: decide of the native shape can just be used in the compound shape.
324 // Use call to CreateGeomNonSpecial().
245 BulletShape saveShape = cPrim.PhysShape; 325 BulletShape saveShape = cPrim.PhysShape;
246 cPrim.PhysShape.ptr = IntPtr.Zero; // Don't let the create free the child's shape 326 cPrim.PhysShape.Clear(); // Don't let the create free the child's shape
327 // PhysicsScene.Shapes.CreateGeomNonSpecial(true, cPrim, null);
247 PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null); 328 PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null);
248 BulletShape newShape = cPrim.PhysShape; 329 BulletShape newShape = cPrim.PhysShape;
249 cPrim.PhysShape = saveShape; 330 cPrim.PhysShape = saveShape;
250 BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, newShape.ptr, displacementPos, displacementRot); 331 BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, newShape.ptr, lci.OffsetPos , lci.OffsetRot);
251 } 332 }
252 else 333 else
253 { 334 {
254 // For the shared shapes (meshes and hulls), just use the shape in the child. 335 // For the shared shapes (meshes and hulls), just use the shape in the child.
336 // The reference count added here will be decremented when the compound shape
337 // is destroyed in BSShapeCollection (the child shapes are looped over and dereferenced).
255 if (PhysicsScene.Shapes.ReferenceShape(cPrim.PhysShape)) 338 if (PhysicsScene.Shapes.ReferenceShape(cPrim.PhysShape))
256 { 339 {
257 PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}", 340 PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}",
258 LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape); 341 LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape);
259 } 342 }
260 BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, cPrim.PhysShape.ptr, displacementPos, displacementRot); 343 BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, cPrim.PhysShape.ptr, lci.OffsetPos , lci.OffsetRot);
261 } 344 }
262 } 345 }
263 346
264 // TODO: need to phantomize the child prims left behind.
265 // Maybe just destroy the children bodies and shapes and have them rebuild on unlink.
266 // Selection/deselection might cause way too many build/destructions esp. for LARGE linksets.
267
268 return false; // 'false' says to move onto the next child in the list 347 return false; // 'false' says to move onto the next child in the list
269 }); 348 });
270 349