aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs429
1 files changed, 298 insertions, 131 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index 30fa50a..29a23c0 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -34,11 +34,11 @@ using OpenSim.Region.Physics.ConvexDecompositionDotNet;
34 34
35namespace OpenSim.Region.Physics.BulletSPlugin 35namespace OpenSim.Region.Physics.BulletSPlugin
36{ 36{
37public class BSShapeCollection : IDisposable 37public sealed class BSShapeCollection : IDisposable
38{ 38{
39 private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]"; 39 private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]";
40 40
41 protected BSScene PhysicsScene { get; set; } 41 private BSScene PhysicsScene { get; set; }
42 42
43 private Object m_collectionActivityLock = new Object(); 43 private Object m_collectionActivityLock = new Object();
44 44
@@ -48,6 +48,7 @@ public class BSShapeCollection : IDisposable
48 public IntPtr ptr; 48 public IntPtr ptr;
49 public int referenceCount; 49 public int referenceCount;
50 public DateTime lastReferenced; 50 public DateTime lastReferenced;
51 public UInt64 shapeKey;
51 } 52 }
52 53
53 // Description of a hull. 54 // Description of a hull.
@@ -57,6 +58,7 @@ public class BSShapeCollection : IDisposable
57 public IntPtr ptr; 58 public IntPtr ptr;
58 public int referenceCount; 59 public int referenceCount;
59 public DateTime lastReferenced; 60 public DateTime lastReferenced;
61 public UInt64 shapeKey;
60 } 62 }
61 63
62 // The sharable set of meshes and hulls. Indexed by their shape hash. 64 // The sharable set of meshes and hulls. Indexed by their shape hash.
@@ -90,9 +92,10 @@ public class BSShapeCollection : IDisposable
90 // remove the physical constraints before the body is destroyed. 92 // remove the physical constraints before the body is destroyed.
91 // Called at taint-time!! 93 // Called at taint-time!!
92 public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPhysObject prim, 94 public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPhysObject prim,
93 ShapeData shapeData, PrimitiveBaseShape pbs,
94 ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback) 95 ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback)
95 { 96 {
97 PhysicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape");
98
96 bool ret = false; 99 bool ret = false;
97 100
98 // This lock could probably be pushed down lower but building shouldn't take long 101 // This lock could probably be pushed down lower but building shouldn't take long
@@ -100,41 +103,38 @@ public class BSShapeCollection : IDisposable
100 { 103 {
101 // Do we have the correct geometry for this type of object? 104 // Do we have the correct geometry for this type of object?
102 // Updates prim.BSShape with information/pointers to shape. 105 // Updates prim.BSShape with information/pointers to shape.
103 // CreateGeom returns 'true' of BSShape as changed to a new shape. 106 // Returns 'true' of BSShape is changed to a new shape.
104 bool newGeom = CreateGeom(forceRebuild, prim, shapeData, pbs, shapeCallback); 107 bool newGeom = CreateGeom(forceRebuild, prim, shapeCallback);
105 // If we had to select a new shape geometry for the object, 108 // If we had to select a new shape geometry for the object,
106 // rebuild the body around it. 109 // rebuild the body around it.
107 // Updates prim.BSBody with information/pointers to requested body 110 // Updates prim.BSBody with information/pointers to requested body
111 // Returns 'true' if BSBody was changed.
108 bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, 112 bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World,
109 prim.BSShape, shapeData, bodyCallback); 113 prim.PhysShape, bodyCallback);
110 ret = newGeom || newBody; 114 ret = newGeom || newBody;
111 } 115 }
112 DetailLog("{0},BSShapeCollection.GetBodyAndShape,force={1},ret={2},body={3},shape={4}", 116 DetailLog("{0},BSShapeCollection.GetBodyAndShape,taintExit,force={1},ret={2},body={3},shape={4}",
113 prim.LocalID, forceRebuild, ret, prim.BSBody, prim.BSShape); 117 prim.LocalID, forceRebuild, ret, prim.PhysBody, prim.PhysShape);
114 118
115 return ret; 119 return ret;
116 } 120 }
117 121
118 // Track another user of a body 122 // Track another user of a body.
119 // We presume the caller has allocated the body. 123 // We presume the caller has allocated the body.
120 // Bodies only have one user so the body is just put into the world if not already there. 124 // Bodies only have one user so the body is just put into the world if not already there.
121 public void ReferenceBody(BulletBody body, bool inTaintTime) 125 public void ReferenceBody(BulletBody body, bool inTaintTime)
122 { 126 {
123 lock (m_collectionActivityLock) 127 lock (m_collectionActivityLock)
124 { 128 {
125 DetailLog("{0},BSShapeCollection.ReferenceBody,newBody", body.ID, body); 129 DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body);
126 BSScene.TaintCallback createOperation = delegate() 130 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.ReferenceBody", delegate()
127 { 131 {
128 if (!BulletSimAPI.IsInWorld2(body.ptr)) 132 if (!BulletSimAPI.IsInWorld2(body.ptr))
129 { 133 {
130 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr); 134 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr);
131 DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body); 135 DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body);
132 } 136 }
133 }; 137 });
134 if (inTaintTime)
135 createOperation();
136 else
137 PhysicsScene.TaintedObject("BSShapeCollection.ReferenceBody", createOperation);
138 } 138 }
139 } 139 }
140 140
@@ -147,25 +147,23 @@ public class BSShapeCollection : IDisposable
147 147
148 lock (m_collectionActivityLock) 148 lock (m_collectionActivityLock)
149 { 149 {
150 BSScene.TaintCallback removeOperation = delegate() 150 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceBody", delegate()
151 { 151 {
152 DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. ptr={1}, inTaintTime={2}", 152 DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1},inTaintTime={2}",
153 body.ID, body.ptr.ToString("X"), inTaintTime); 153 body.ID, body, inTaintTime);
154 // If the caller needs to know the old body is going away, pass the event up. 154 // If the caller needs to know the old body is going away, pass the event up.
155 if (bodyCallback != null) bodyCallback(body); 155 if (bodyCallback != null) bodyCallback(body);
156 156
157 // It may have already been removed from the world in which case the next is a NOOP. 157 if (BulletSimAPI.IsInWorld2(body.ptr))
158 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr); 158 {
159 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr);
160 DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body);
161 }
159 162
160 // Zero any reference to the shape so it is not freed when the body is deleted. 163 // Zero any reference to the shape so it is not freed when the body is deleted.
161 BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero); 164 BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero);
162 BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr); 165 BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr);
163 }; 166 });
164 // If already in taint-time, do the operations now. Otherwise queue for later.
165 if (inTaintTime)
166 removeOperation();
167 else
168 PhysicsScene.TaintedObject("BSShapeCollection.DereferenceBody", removeOperation);
169 } 167 }
170 } 168 }
171 169
@@ -175,7 +173,7 @@ public class BSShapeCollection : IDisposable
175 // Meshes and hulls for the same shape have the same hash key. 173 // Meshes and hulls for the same shape have the same hash key.
176 // NOTE that native shapes are not added to the mesh list or removed. 174 // NOTE that native shapes are not added to the mesh list or removed.
177 // Returns 'true' if this is the initial reference to the shape. Otherwise reused. 175 // Returns 'true' if this is the initial reference to the shape. Otherwise reused.
178 private bool ReferenceShape(BulletShape shape) 176 public bool ReferenceShape(BulletShape shape)
179 { 177 {
180 bool ret = false; 178 bool ret = false;
181 switch (shape.type) 179 switch (shape.type)
@@ -193,6 +191,7 @@ public class BSShapeCollection : IDisposable
193 { 191 {
194 // This is a new reference to a mesh 192 // This is a new reference to a mesh
195 meshDesc.ptr = shape.ptr; 193 meshDesc.ptr = shape.ptr;
194 meshDesc.shapeKey = shape.shapeKey;
196 // We keep a reference to the underlying IMesh data so a hull can be built 195 // We keep a reference to the underlying IMesh data so a hull can be built
197 meshDesc.referenceCount = 1; 196 meshDesc.referenceCount = 1;
198 DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}", 197 DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}",
@@ -215,6 +214,7 @@ public class BSShapeCollection : IDisposable
215 { 214 {
216 // This is a new reference to a hull 215 // This is a new reference to a hull
217 hullDesc.ptr = shape.ptr; 216 hullDesc.ptr = shape.ptr;
217 hullDesc.shapeKey = shape.shapeKey;
218 hullDesc.referenceCount = 1; 218 hullDesc.referenceCount = 1;
219 DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}", 219 DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}",
220 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); 220 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
@@ -239,7 +239,7 @@ public class BSShapeCollection : IDisposable
239 if (shape.ptr == IntPtr.Zero) 239 if (shape.ptr == IntPtr.Zero)
240 return; 240 return;
241 241
242 BSScene.TaintCallback dereferenceOperation = delegate() 242 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceShape", delegate()
243 { 243 {
244 if (shape.ptr != IntPtr.Zero) 244 if (shape.ptr != IntPtr.Zero)
245 { 245 {
@@ -261,6 +261,9 @@ public class BSShapeCollection : IDisposable
261 case ShapeData.PhysicsShapeType.SHAPE_MESH: 261 case ShapeData.PhysicsShapeType.SHAPE_MESH:
262 DereferenceMesh(shape, shapeCallback); 262 DereferenceMesh(shape, shapeCallback);
263 break; 263 break;
264 case ShapeData.PhysicsShapeType.SHAPE_COMPOUND:
265 DereferenceCompound(shape, shapeCallback);
266 break;
264 case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN: 267 case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN:
265 break; 268 break;
266 default: 269 default:
@@ -268,18 +271,7 @@ public class BSShapeCollection : IDisposable
268 } 271 }
269 } 272 }
270 } 273 }
271 }; 274 });
272 if (inTaintTime)
273 {
274 lock (m_collectionActivityLock)
275 {
276 dereferenceOperation();
277 }
278 }
279 else
280 {
281 PhysicsScene.TaintedObject("BSShapeCollection.DereferenceShape", dereferenceOperation);
282 }
283 } 275 }
284 276
285 // Count down the reference count for a mesh shape 277 // Count down the reference count for a mesh shape
@@ -294,8 +286,8 @@ public class BSShapeCollection : IDisposable
294 if (shapeCallback != null) shapeCallback(shape); 286 if (shapeCallback != null) shapeCallback(shape);
295 meshDesc.lastReferenced = System.DateTime.Now; 287 meshDesc.lastReferenced = System.DateTime.Now;
296 Meshes[shape.shapeKey] = meshDesc; 288 Meshes[shape.shapeKey] = meshDesc;
297 DetailLog("{0},BSShapeCollection.DereferenceMesh,key={1},refCnt={2}", 289 DetailLog("{0},BSShapeCollection.DereferenceMesh,shape={1},refCnt={2}",
298 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); 290 BSScene.DetailLogZero, shape, meshDesc.referenceCount);
299 291
300 } 292 }
301 } 293 }
@@ -309,11 +301,94 @@ public class BSShapeCollection : IDisposable
309 { 301 {
310 hullDesc.referenceCount--; 302 hullDesc.referenceCount--;
311 // TODO: release the Bullet storage (aging old entries?) 303 // TODO: release the Bullet storage (aging old entries?)
304
305 // Tell upper layers that, if they have dependencies on this shape, this link is going away
312 if (shapeCallback != null) shapeCallback(shape); 306 if (shapeCallback != null) shapeCallback(shape);
307
313 hullDesc.lastReferenced = System.DateTime.Now; 308 hullDesc.lastReferenced = System.DateTime.Now;
314 Hulls[shape.shapeKey] = hullDesc; 309 Hulls[shape.shapeKey] = hullDesc;
315 DetailLog("{0},BSShapeCollection.DereferenceHull,key={1},refCnt={2}", 310 DetailLog("{0},BSShapeCollection.DereferenceHull,shape={1},refCnt={2}",
316 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); 311 BSScene.DetailLogZero, shape, hullDesc.referenceCount);
312 }
313 }
314
315 // Remove a reference to a compound shape.
316 // Taking a compound shape apart is a little tricky because if you just delete the
317 // physical shape, it will free all the underlying children. We can't do that because
318 // they could be shared. So, this removes each of the children from the compound and
319 // dereferences them separately before destroying the compound collision object itself.
320 // Called at taint-time.
321 private void DereferenceCompound(BulletShape shape, ShapeDestructionCallback shapeCallback)
322 {
323 if (!BulletSimAPI.IsCompound2(shape.ptr))
324 {
325 // Failed the sanity check!!
326 PhysicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}",
327 LogHeader, shape.type, shape.ptr.ToString("X"));
328 DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}",
329 BSScene.DetailLogZero, shape.type, shape.ptr.ToString("X"));
330 return;
331 }
332
333 int numChildren = BulletSimAPI.GetNumberOfCompoundChildren2(shape.ptr);
334 DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}", BSScene.DetailLogZero, shape, numChildren);
335
336 for (int ii = numChildren - 1; ii >= 0; ii--)
337 {
338 IntPtr childShape = BulletSimAPI.RemoveChildShapeFromCompoundShapeIndex2(shape.ptr, ii);
339 DereferenceAnonCollisionShape(childShape);
340 }
341 BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr);
342 }
343
344 // Sometimes we have a pointer to a collision shape but don't know what type it is.
345 // Figure out type and call the correct dereference routine.
346 // Called at taint-time.
347 private void DereferenceAnonCollisionShape(IntPtr cShape)
348 {
349 MeshDesc meshDesc;
350 HullDesc hullDesc;
351
352 BulletShape shapeInfo = new BulletShape(cShape);
353 if (TryGetMeshByPtr(cShape, out meshDesc))
354 {
355 shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_MESH;
356 shapeInfo.shapeKey = meshDesc.shapeKey;
357 }
358 else
359 {
360 if (TryGetHullByPtr(cShape, out hullDesc))
361 {
362 shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_HULL;
363 shapeInfo.shapeKey = hullDesc.shapeKey;
364 }
365 else
366 {
367 if (BulletSimAPI.IsCompound2(cShape))
368 {
369 shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_COMPOUND;
370 }
371 else
372 {
373 if (BulletSimAPI.IsNativeShape2(cShape))
374 {
375 shapeInfo.isNativeShape = true;
376 shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter)
377 }
378 }
379 }
380 }
381
382 DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo);
383
384 if (shapeInfo.type != ShapeData.PhysicsShapeType.SHAPE_UNKNOWN)
385 {
386 DereferenceShape(shapeInfo, true, null);
387 }
388 else
389 {
390 PhysicsScene.Logger.ErrorFormat("{0} Could not decypher shape type. Region={1}, addr={2}",
391 LogHeader, PhysicsScene.RegionName, cShape.ToString("X"));
317 } 392 }
318 } 393 }
319 394
@@ -325,22 +400,46 @@ public class BSShapeCollection : IDisposable
325 // Info in prim.BSShape is updated to the new shape. 400 // Info in prim.BSShape is updated to the new shape.
326 // Returns 'true' if the geometry was rebuilt. 401 // Returns 'true' if the geometry was rebuilt.
327 // Called at taint-time! 402 // Called at taint-time!
328 private bool CreateGeom(bool forceRebuild, BSPhysObject prim, ShapeData shapeData, 403 private bool CreateGeom(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback)
329 PrimitiveBaseShape pbs, ShapeDestructionCallback shapeCallback)
330 { 404 {
331 bool ret = false; 405 bool ret = false;
332 bool haveShape = false; 406 bool haveShape = false;
333 bool nativeShapePossible = true;
334 407
335 if (shapeData.Type == ShapeData.PhysicsShapeType.SHAPE_AVATAR) 408 if (!haveShape && prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_AVATAR)
336 { 409 {
337 // an avatar capsule is close to a native shape (it is not shared) 410 // an avatar capsule is close to a native shape (it is not shared)
338 ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_AVATAR, 411 ret = GetReferenceToNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_AVATAR,
339 ShapeData.FixedShapeKey.KEY_CAPSULE, shapeCallback); 412 ShapeData.FixedShapeKey.KEY_CAPSULE, shapeCallback);
340 DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.BSShape); 413 DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape);
341 ret = true; 414 ret = true;
342 haveShape = true; 415 haveShape = true;
343 } 416 }
417
418 // Compound shapes are handled special as they are rebuilt from scratch.
419 // This isn't too great a hardship since most of the child shapes will already been created.
420 if (!haveShape && prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_COMPOUND)
421 {
422 ret = GetReferenceToCompoundShape(prim, shapeCallback);
423 DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape);
424 haveShape = true;
425 }
426
427 if (!haveShape)
428 {
429 ret = CreateGeomNonSpecial(forceRebuild, prim, shapeCallback);
430 }
431
432 return ret;
433 }
434
435 // Create a mesh/hull shape or a native shape if 'nativeShapePossible' is 'true'.
436 private bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback)
437 {
438 bool ret = false;
439 bool haveShape = false;
440 bool nativeShapePossible = true;
441 PrimitiveBaseShape pbs = prim.BaseShape;
442
344 // If the prim attributes are simple, this could be a simple Bullet native shape 443 // If the prim attributes are simple, this could be a simple Bullet native shape
345 if (!haveShape 444 if (!haveShape
346 && pbs != null 445 && pbs != null
@@ -354,98 +453,110 @@ public class BSShapeCollection : IDisposable
354 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 453 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
355 && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) ) 454 && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) )
356 { 455 {
456 // It doesn't look like Bullet scales spheres so make sure the scales are all equal
357 if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) 457 if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
358 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z) 458 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z)
359 { 459 {
360 haveShape = true; 460 haveShape = true;
361 if (forceRebuild 461 if (forceRebuild
362 || prim.Scale != shapeData.Size 462 || prim.Scale != prim.Size
363 || prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE 463 || prim.PhysShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE
364 ) 464 )
365 { 465 {
366 ret = GetReferenceToNativeShape(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_SPHERE, 466 ret = GetReferenceToNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_SPHERE,
367 ShapeData.FixedShapeKey.KEY_SPHERE, shapeCallback); 467 ShapeData.FixedShapeKey.KEY_SPHERE, shapeCallback);
368 DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}", 468 DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}",
369 prim.LocalID, forceRebuild, prim.BSShape); 469 prim.LocalID, forceRebuild, prim.PhysShape);
370 } 470 }
371 } 471 }
372 if (pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) 472 if (!haveShape && pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
373 { 473 {
374 haveShape = true; 474 haveShape = true;
375 if (forceRebuild 475 if (forceRebuild
376 || prim.Scale != shapeData.Size 476 || prim.Scale != prim.Size
377 || prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX 477 || prim.PhysShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX
378 ) 478 )
379 { 479 {
380 ret = GetReferenceToNativeShape( prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_BOX, 480 ret = GetReferenceToNativeShape( prim, ShapeData.PhysicsShapeType.SHAPE_BOX,
381 ShapeData.FixedShapeKey.KEY_BOX, shapeCallback); 481 ShapeData.FixedShapeKey.KEY_BOX, shapeCallback);
382 DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}", 482 DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}",
383 prim.LocalID, forceRebuild, prim.BSShape); 483 prim.LocalID, forceRebuild, prim.PhysShape);
384 } 484 }
385 } 485 }
386 } 486 }
487
387 // If a simple shape is not happening, create a mesh and possibly a hull. 488 // If a simple shape is not happening, create a mesh and possibly a hull.
388 // Note that if it's a native shape, the check for physical/non-physical is not
389 // made. Native shapes are best used in either case.
390 if (!haveShape && pbs != null) 489 if (!haveShape && pbs != null)
391 { 490 {
392 if (prim.IsPhysical && PhysicsScene.ShouldUseHullsForPhysicalObjects) 491 ret = CreateGeomMeshOrHull(prim, shapeCallback);
393 { 492 }
394 // Update prim.BSShape to reference a hull of this shape. 493
395 ret = GetReferenceToHull(prim, shapeData, pbs, shapeCallback); 494 return ret;
396 DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}", 495 }
397 shapeData.ID, prim.BSShape, prim.BSShape.shapeKey.ToString("X")); 496
398 } 497 public bool CreateGeomMeshOrHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
399 else 498 {
400 { 499
401 ret = GetReferenceToMesh(prim, shapeData, pbs, shapeCallback); 500 bool ret = false;
402 DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}", 501 // Note that if it's a native shape, the check for physical/non-physical is not
403 shapeData.ID, prim.BSShape, prim.BSShape.shapeKey.ToString("X")); 502 // made. Native shapes work in either case.
404 } 503 if (prim.IsPhysical && PhysicsScene.ShouldUseHullsForPhysicalObjects)
504 {
505 // Update prim.BSShape to reference a hull of this shape.
506 ret = GetReferenceToHull(prim,shapeCallback);
507 DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}",
508 prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
509 }
510 else
511 {
512 ret = GetReferenceToMesh(prim, shapeCallback);
513 DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}",
514 prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
405 } 515 }
406 return ret; 516 return ret;
407 } 517 }
408 518
409 // Creates a native shape and assignes it to prim.BSShape. 519 // Creates a native shape and assignes it to prim.BSShape.
410 // "Native" shapes are never shared. they are created here and destroyed in DereferenceShape(). 520 // "Native" shapes are never shared. they are created here and destroyed in DereferenceShape().
411 private bool GetReferenceToNativeShape(BSPhysObject prim, ShapeData shapeData, 521 private bool GetReferenceToNativeShape(BSPhysObject prim,
412 ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey, 522 ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey,
413 ShapeDestructionCallback shapeCallback) 523 ShapeDestructionCallback shapeCallback)
414 { 524 {
415 // release any previous shape 525 // release any previous shape
416 DereferenceShape(prim.BSShape, true, shapeCallback); 526 DereferenceShape(prim.PhysShape, true, shapeCallback);
417 527
418 shapeData.Type = shapeType;
419 // Bullet native objects are scaled by the Bullet engine so pass the size in 528 // Bullet native objects are scaled by the Bullet engine so pass the size in
420 prim.Scale = shapeData.Size; 529 prim.Scale = prim.Size;
421 shapeData.Scale = shapeData.Size;
422 530
423 BulletShape newShape = BuildPhysicalNativeShape(shapeType, shapeData, shapeKey); 531 BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey);
424 532
425 // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. 533 // Don't need to do a 'ReferenceShape()' here because native shapes are not shared.
426 DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}", 534 DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}",
427 shapeData.ID, newShape, shapeData.Scale); 535 prim.LocalID, newShape, prim.Scale);
428 536
429 prim.BSShape = newShape; 537 prim.PhysShape = newShape;
430 return true; 538 return true;
431 } 539 }
432 540
433 private BulletShape BuildPhysicalNativeShape(ShapeData.PhysicsShapeType shapeType, 541 private BulletShape BuildPhysicalNativeShape(BSPhysObject prim, ShapeData.PhysicsShapeType shapeType,
434 ShapeData shapeData, ShapeData.FixedShapeKey shapeKey) 542 ShapeData.FixedShapeKey shapeKey)
435 { 543 {
436 BulletShape newShape; 544 BulletShape newShape;
437 // Need to make sure the passed shape information is for the native type. 545 // Need to make sure the passed shape information is for the native type.
438 ShapeData nativeShapeData = shapeData; 546 ShapeData nativeShapeData = new ShapeData();
439 nativeShapeData.Type = shapeType; 547 nativeShapeData.Type = shapeType;
548 nativeShapeData.ID = prim.LocalID;
549 nativeShapeData.Scale = prim.Scale;
550 nativeShapeData.Size = prim.Scale;
440 nativeShapeData.MeshKey = (ulong)shapeKey; 551 nativeShapeData.MeshKey = (ulong)shapeKey;
441 nativeShapeData.HullKey = (ulong)shapeKey; 552 nativeShapeData.HullKey = (ulong)shapeKey;
442 553
443 if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) 554 if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR)
444 { 555 {
445 newShape = new BulletShape( 556 newShape = new BulletShape(
446 BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, nativeShapeData.Scale) 557 BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, prim.Scale)
447 , shapeType); 558 , shapeType);
448 DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", nativeShapeData.ID, nativeShapeData.Scale); 559 DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale);
449 } 560 }
450 else 561 else
451 { 562 {
@@ -454,7 +565,7 @@ public class BSShapeCollection : IDisposable
454 if (newShape.ptr == IntPtr.Zero) 565 if (newShape.ptr == IntPtr.Zero)
455 { 566 {
456 PhysicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", 567 PhysicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}",
457 LogHeader, nativeShapeData.ID, nativeShapeData.Type); 568 LogHeader, prim.LocalID, shapeType);
458 } 569 }
459 newShape.shapeKey = (System.UInt64)shapeKey; 570 newShape.shapeKey = (System.UInt64)shapeKey;
460 newShape.isNativeShape = true; 571 newShape.isNativeShape = true;
@@ -466,33 +577,32 @@ public class BSShapeCollection : IDisposable
466 // Dereferences previous shape in BSShape and adds a reference for this new shape. 577 // Dereferences previous shape in BSShape and adds a reference for this new shape.
467 // Returns 'true' of a mesh was actually built. Otherwise . 578 // Returns 'true' of a mesh was actually built. Otherwise .
468 // Called at taint-time! 579 // Called at taint-time!
469 private bool GetReferenceToMesh(BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs, 580 private bool GetReferenceToMesh(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
470 ShapeDestructionCallback shapeCallback)
471 { 581 {
472 BulletShape newShape = new BulletShape(IntPtr.Zero); 582 BulletShape newShape = new BulletShape(IntPtr.Zero);
473 583
474 float lod; 584 float lod;
475 System.UInt64 newMeshKey = ComputeShapeKey(shapeData, pbs, out lod); 585 System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
476 586
477 // if this new shape is the same as last time, don't recreate the mesh 587 // if this new shape is the same as last time, don't recreate the mesh
478 if (newMeshKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH) 588 if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH)
479 return false; 589 return false;
480 590
481 DetailLog("{0},BSShapeCollection.CreateGeomMesh,create,oldKey={1},newKey={2}", 591 DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2}",
482 prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newMeshKey.ToString("X")); 592 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X"));
483 593
484 // Since we're recreating new, get rid of the reference to the previous shape 594 // Since we're recreating new, get rid of the reference to the previous shape
485 DereferenceShape(prim.BSShape, true, shapeCallback); 595 DereferenceShape(prim.PhysShape, true, shapeCallback);
486 596
487 newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, pbs, shapeData.Size, lod); 597 newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, prim.BaseShape, prim.Size, lod);
488 // Take evasive action if the mesh was not constructed. 598 // Take evasive action if the mesh was not constructed.
489 newShape = VerifyMeshCreated(newShape, prim, shapeData, pbs); 599 newShape = VerifyMeshCreated(newShape, prim);
490 600
491 ReferenceShape(newShape); 601 ReferenceShape(newShape);
492 602
493 // meshes are already scaled by the meshmerizer 603 // meshes are already scaled by the meshmerizer
494 prim.Scale = new OMV.Vector3(1f, 1f, 1f); 604 prim.Scale = new OMV.Vector3(1f, 1f, 1f);
495 prim.BSShape = newShape; 605 prim.PhysShape = newShape;
496 606
497 return true; // 'true' means a new shape has been added to this prim 607 return true; // 'true' means a new shape has been added to this prim
498 } 608 }
@@ -526,7 +636,7 @@ public class BSShapeCollection : IDisposable
526 verticesAsFloats[vi++] = vv.Z; 636 verticesAsFloats[vi++] = vv.Z;
527 } 637 }
528 638
529 // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", 639 // m_log.DebugFormat("{0}: BSShapeCollection.CreatePhysicalMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}",
530 // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count); 640 // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count);
531 641
532 meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, 642 meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr,
@@ -541,32 +651,31 @@ public class BSShapeCollection : IDisposable
541 651
542 // See that hull shape exists in the physical world and update prim.BSShape. 652 // See that hull shape exists in the physical world and update prim.BSShape.
543 // We could be creating the hull because scale changed or whatever. 653 // We could be creating the hull because scale changed or whatever.
544 private bool GetReferenceToHull(BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs, 654 private bool GetReferenceToHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
545 ShapeDestructionCallback shapeCallback)
546 { 655 {
547 BulletShape newShape; 656 BulletShape newShape;
548 657
549 float lod; 658 float lod;
550 System.UInt64 newHullKey = ComputeShapeKey(shapeData, pbs, out lod); 659 System.UInt64 newHullKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
551 660
552 // if the hull hasn't changed, don't rebuild it 661 // if the hull hasn't changed, don't rebuild it
553 if (newHullKey == prim.BSShape.shapeKey && prim.BSShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL) 662 if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL)
554 return false; 663 return false;
555 664
556 DetailLog("{0},BSShapeCollection.CreateGeomHull,create,oldKey={1},newKey={2}", 665 DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}",
557 prim.LocalID, prim.BSShape.shapeKey.ToString("X"), newHullKey.ToString("X")); 666 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X"));
558 667
559 // Remove usage of the previous shape. 668 // Remove usage of the previous shape.
560 DereferenceShape(prim.BSShape, true, shapeCallback); 669 DereferenceShape(prim.PhysShape, true, shapeCallback);
561 670
562 newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, pbs, shapeData.Size, lod); 671 newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod);
563 newShape = VerifyMeshCreated(newShape, prim, shapeData, pbs); 672 newShape = VerifyMeshCreated(newShape, prim);
564 673
565 ReferenceShape(newShape); 674 ReferenceShape(newShape);
566 675
567 // hulls are already scaled by the meshmerizer 676 // hulls are already scaled by the meshmerizer
568 prim.Scale = new OMV.Vector3(1f, 1f, 1f); 677 prim.Scale = new OMV.Vector3(1f, 1f, 1f);
569 prim.BSShape = newShape; 678 prim.PhysShape = newShape;
570 return true; // 'true' means a new shape has been added to this prim 679 return true; // 'true' means a new shape has been added to this prim
571 } 680 }
572 681
@@ -685,9 +794,31 @@ public class BSShapeCollection : IDisposable
685 return; 794 return;
686 } 795 }
687 796
797 // Compound shapes are always built from scratch.
798 // This shouldn't be to bad since most of the parts will be meshes that had been built previously.
799 private bool GetReferenceToCompoundShape(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
800 {
801 // Remove reference to the old shape
802 // Don't need to do this as the shape is freed when the new root shape is created below.
803 // DereferenceShape(prim.PhysShape, true, shapeCallback);
804
805 BulletShape cShape = new BulletShape(
806 BulletSimAPI.CreateCompoundShape2(PhysicsScene.World.ptr, false), ShapeData.PhysicsShapeType.SHAPE_COMPOUND);
807
808 // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape.
809 CreateGeomMeshOrHull(prim, shapeCallback);
810 BulletSimAPI.AddChildShapeToCompoundShape2(cShape.ptr, prim.PhysShape.ptr, OMV.Vector3.Zero, OMV.Quaternion.Identity);
811 DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addRootPrim,compShape={1},rootShape={2}",
812 prim.LocalID, cShape, prim.PhysShape);
813
814 prim.PhysShape = cShape;
815
816 return true;
817 }
818
688 // Create a hash of all the shape parameters to be used as a key 819 // Create a hash of all the shape parameters to be used as a key
689 // for this particular shape. 820 // for this particular shape.
690 private System.UInt64 ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs, out float retLod) 821 private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod)
691 { 822 {
692 // level of detail based on size and type of the object 823 // level of detail based on size and type of the object
693 float lod = PhysicsScene.MeshLOD; 824 float lod = PhysicsScene.MeshLOD;
@@ -695,40 +826,40 @@ public class BSShapeCollection : IDisposable
695 lod = PhysicsScene.SculptLOD; 826 lod = PhysicsScene.SculptLOD;
696 827
697 // Mega prims usually get more detail because one can interact with shape approximations at this size. 828 // Mega prims usually get more detail because one can interact with shape approximations at this size.
698 float maxAxis = Math.Max(shapeData.Size.X, Math.Max(shapeData.Size.Y, shapeData.Size.Z)); 829 float maxAxis = Math.Max(size.X, Math.Max(size.Y, size.Z));
699 if (maxAxis > PhysicsScene.MeshMegaPrimThreshold) 830 if (maxAxis > PhysicsScene.MeshMegaPrimThreshold)
700 lod = PhysicsScene.MeshMegaPrimLOD; 831 lod = PhysicsScene.MeshMegaPrimLOD;
701 832
702 retLod = lod; 833 retLod = lod;
703 return pbs.GetMeshKey(shapeData.Size, lod); 834 return pbs.GetMeshKey(size, lod);
704 } 835 }
705 // For those who don't want the LOD 836 // For those who don't want the LOD
706 private System.UInt64 ComputeShapeKey(ShapeData shapeData, PrimitiveBaseShape pbs) 837 private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs)
707 { 838 {
708 float lod; 839 float lod;
709 return ComputeShapeKey(shapeData, pbs, out lod); 840 return ComputeShapeKey(size, pbs, out lod);
710 } 841 }
711 842
712 // The creation of a mesh or hull can fail if an underlying asset is not available. 843 // The creation of a mesh or hull can fail if an underlying asset is not available.
713 // There are two cases: 1) the asset is not in the cache and it needs to be fetched; 844 // There are two cases: 1) the asset is not in the cache and it needs to be fetched;
714 // and 2) the asset cannot be converted (like decompressing JPEG2000s). 845 // and 2) the asset cannot be converted (like failed decompression of JPEG2000s).
715 // The first case causes the asset to be fetched. The second case just requires 846 // The first case causes the asset to be fetched. The second case requires
716 // us to not loop forever. 847 // us to not loop forever.
717 // Called after creating a physical mesh or hull. If the physical shape was created, 848 // Called after creating a physical mesh or hull. If the physical shape was created,
718 // just return. 849 // just return.
719 private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim, ShapeData shapeData, PrimitiveBaseShape pbs) 850 private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim)
720 { 851 {
721 // If the shape was successfully created, nothing more to do 852 // If the shape was successfully created, nothing more to do
722 if (newShape.ptr != IntPtr.Zero) 853 if (newShape.ptr != IntPtr.Zero)
723 return newShape; 854 return newShape;
724 855
725 // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset 856 // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset
726 if (pbs.SculptEntry && !prim.LastAssetBuildFailed && pbs.SculptTexture != OMV.UUID.Zero) 857 if (prim.BaseShape.SculptEntry && !prim.LastAssetBuildFailed && prim.BaseShape.SculptTexture != OMV.UUID.Zero)
727 { 858 {
728 prim.LastAssetBuildFailed = true; 859 prim.LastAssetBuildFailed = true;
729 BSPhysObject xprim = prim; 860 BSPhysObject xprim = prim;
730 DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset,lID={1},lastFailed={2}", 861 DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset,lID={1},lastFailed={2}",
731 LogHeader, shapeData.ID.ToString("X"), prim.LastAssetBuildFailed); 862 LogHeader, prim.LocalID, prim.LastAssetBuildFailed);
732 Util.FireAndForget(delegate 863 Util.FireAndForget(delegate
733 { 864 {
734 RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod; 865 RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod;
@@ -745,7 +876,7 @@ public class BSShapeCollection : IDisposable
745 yprim.BaseShape.SculptData = asset.Data; 876 yprim.BaseShape.SculptData = asset.Data;
746 // This will cause the prim to see that the filler shape is not the right 877 // This will cause the prim to see that the filler shape is not the right
747 // one and try again to build the object. 878 // one and try again to build the object.
748 // No race condition with the native sphere setting since the rebuild is at taint time. 879 // No race condition with the normal shape setting since the rebuild is at taint time.
749 yprim.ForceBodyShapeRebuild(false); 880 yprim.ForceBodyShapeRebuild(false);
750 881
751 }); 882 });
@@ -757,13 +888,13 @@ public class BSShapeCollection : IDisposable
757 if (prim.LastAssetBuildFailed) 888 if (prim.LastAssetBuildFailed)
758 { 889 {
759 PhysicsScene.Logger.ErrorFormat("{0} Mesh failed to fetch asset. lID={1}, texture={2}", 890 PhysicsScene.Logger.ErrorFormat("{0} Mesh failed to fetch asset. lID={1}, texture={2}",
760 LogHeader, shapeData.ID, pbs.SculptTexture); 891 LogHeader, prim.LocalID, prim.BaseShape.SculptTexture);
761 } 892 }
762 } 893 }
763 894
764 // While we figure out the real problem, stick a simple native shape on the object. 895 // While we figure out the real problem, stick a simple native shape on the object.
765 BulletShape fillinShape = 896 BulletShape fillinShape =
766 BuildPhysicalNativeShape(ShapeData.PhysicsShapeType.SHAPE_BOX, shapeData, ShapeData.FixedShapeKey.KEY_BOX); 897 BuildPhysicalNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_BOX, ShapeData.FixedShapeKey.KEY_BOX);
767 898
768 return fillinShape; 899 return fillinShape;
769 } 900 }
@@ -773,18 +904,18 @@ public class BSShapeCollection : IDisposable
773 // Returns 'true' if an object was actually created. 904 // Returns 'true' if an object was actually created.
774 // Called at taint-time. 905 // Called at taint-time.
775 private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletSim sim, BulletShape shape, 906 private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletSim sim, BulletShape shape,
776 ShapeData shapeData, BodyDestructionCallback bodyCallback) 907 BodyDestructionCallback bodyCallback)
777 { 908 {
778 bool ret = false; 909 bool ret = false;
779 910
780 // the mesh, hull or native shape must have already been created in Bullet 911 // the mesh, hull or native shape must have already been created in Bullet
781 bool mustRebuild = (prim.BSBody.ptr == IntPtr.Zero); 912 bool mustRebuild = (prim.PhysBody.ptr == IntPtr.Zero);
782 913
783 // If there is an existing body, verify it's of an acceptable type. 914 // If there is an existing body, verify it's of an acceptable type.
784 // If not a solid object, body is a GhostObject. Otherwise a RigidBody. 915 // If not a solid object, body is a GhostObject. Otherwise a RigidBody.
785 if (!mustRebuild) 916 if (!mustRebuild)
786 { 917 {
787 CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(prim.BSBody.ptr); 918 CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(prim.PhysBody.ptr);
788 if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY 919 if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY
789 || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT) 920 || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT)
790 { 921 {
@@ -796,27 +927,27 @@ public class BSShapeCollection : IDisposable
796 if (mustRebuild || forceRebuild) 927 if (mustRebuild || forceRebuild)
797 { 928 {
798 // Free any old body 929 // Free any old body
799 DereferenceBody(prim.BSBody, true, bodyCallback); 930 DereferenceBody(prim.PhysBody, true, bodyCallback);
800 931
801 BulletBody aBody; 932 BulletBody aBody;
802 IntPtr bodyPtr = IntPtr.Zero; 933 IntPtr bodyPtr = IntPtr.Zero;
803 if (prim.IsSolid) 934 if (prim.IsSolid)
804 { 935 {
805 bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr, 936 bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr,
806 shapeData.ID, shapeData.Position, shapeData.Rotation); 937 prim.LocalID, prim.RawPosition, prim.RawOrientation);
807 DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); 938 DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
808 } 939 }
809 else 940 else
810 { 941 {
811 bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr, 942 bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr,
812 shapeData.ID, shapeData.Position, shapeData.Rotation); 943 prim.LocalID, prim.ForcePosition, prim.ForceOrientation);
813 DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); 944 DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
814 } 945 }
815 aBody = new BulletBody(shapeData.ID, bodyPtr); 946 aBody = new BulletBody(prim.LocalID, bodyPtr);
816 947
817 ReferenceBody(aBody, true); 948 ReferenceBody(aBody, true);
818 949
819 prim.BSBody = aBody; 950 prim.PhysBody = aBody;
820 951
821 ret = true; 952 ret = true;
822 } 953 }
@@ -824,6 +955,42 @@ public class BSShapeCollection : IDisposable
824 return ret; 955 return ret;
825 } 956 }
826 957
958 private bool TryGetMeshByPtr(IntPtr addr, out MeshDesc outDesc)
959 {
960 bool ret = false;
961 MeshDesc foundDesc = new MeshDesc();
962 foreach (MeshDesc md in Meshes.Values)
963 {
964 if (md.ptr == addr)
965 {
966 foundDesc = md;
967 ret = true;
968 break;
969 }
970
971 }
972 outDesc = foundDesc;
973 return ret;
974 }
975
976 private bool TryGetHullByPtr(IntPtr addr, out HullDesc outDesc)
977 {
978 bool ret = false;
979 HullDesc foundDesc = new HullDesc();
980 foreach (HullDesc hd in Hulls.Values)
981 {
982 if (hd.ptr == addr)
983 {
984 foundDesc = hd;
985 ret = true;
986 break;
987 }
988
989 }
990 outDesc = foundDesc;
991 return ret;
992 }
993
827 private void DetailLog(string msg, params Object[] args) 994 private void DetailLog(string msg, params Object[] args)
828 { 995 {
829 if (PhysicsScene.PhysicsLogging.Enabled) 996 if (PhysicsScene.PhysicsLogging.Enabled)