aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs')
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs283
1 files changed, 154 insertions, 129 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index 892c34b..473ef10 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -45,7 +45,7 @@ public sealed class BSShapeCollection : IDisposable
45 // Description of a Mesh 45 // Description of a Mesh
46 private struct MeshDesc 46 private struct MeshDesc
47 { 47 {
48 public IntPtr ptr; 48 public BulletShape shape;
49 public int referenceCount; 49 public int referenceCount;
50 public DateTime lastReferenced; 50 public DateTime lastReferenced;
51 public UInt64 shapeKey; 51 public UInt64 shapeKey;
@@ -55,7 +55,7 @@ public sealed class BSShapeCollection : IDisposable
55 // Meshes and hulls have the same shape hash key but we only need hulls for efficient collision calculations. 55 // Meshes and hulls have the same shape hash key but we only need hulls for efficient collision calculations.
56 private struct HullDesc 56 private struct HullDesc
57 { 57 {
58 public IntPtr ptr; 58 public BulletShape shape;
59 public int referenceCount; 59 public int referenceCount;
60 public DateTime lastReferenced; 60 public DateTime lastReferenced;
61 public UInt64 shapeKey; 61 public UInt64 shapeKey;
@@ -65,9 +65,16 @@ public sealed class BSShapeCollection : IDisposable
65 private Dictionary<System.UInt64, MeshDesc> Meshes = new Dictionary<System.UInt64, MeshDesc>(); 65 private Dictionary<System.UInt64, MeshDesc> Meshes = new Dictionary<System.UInt64, MeshDesc>();
66 private Dictionary<System.UInt64, HullDesc> Hulls = new Dictionary<System.UInt64, HullDesc>(); 66 private Dictionary<System.UInt64, HullDesc> Hulls = new Dictionary<System.UInt64, HullDesc>();
67 67
68 private bool DDetail = false;
69
68 public BSShapeCollection(BSScene physScene) 70 public BSShapeCollection(BSScene physScene)
69 { 71 {
70 PhysicsScene = physScene; 72 PhysicsScene = physScene;
73 // Set the next to 'true' for very detailed shape update detailed logging (detailed details?)
74 // While detailed debugging is still active, this is better than commenting out all the
75 // DetailLog statements. When debugging slows down, this and the protected logging
76 // statements can be commented/removed.
77 DDetail = true;
71 } 78 }
72 79
73 public void Dispose() 80 public void Dispose()
@@ -91,7 +98,7 @@ public sealed class BSShapeCollection : IDisposable
91 // higher level dependencies on the shape or body. Mostly used for LinkSets to 98 // higher level dependencies on the shape or body. Mostly used for LinkSets to
92 // remove the physical constraints before the body is destroyed. 99 // remove the physical constraints before the body is destroyed.
93 // Called at taint-time!! 100 // Called at taint-time!!
94 public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPhysObject prim, 101 public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim,
95 ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback) 102 ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback)
96 { 103 {
97 PhysicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape"); 104 PhysicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape");
@@ -119,6 +126,11 @@ public sealed class BSShapeCollection : IDisposable
119 return ret; 126 return ret;
120 } 127 }
121 128
129 public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim)
130 {
131 return GetBodyAndShape(forceRebuild, sim, prim, null, null);
132 }
133
122 // Track another user of a body. 134 // Track another user of a body.
123 // We presume the caller has allocated the body. 135 // We presume the caller has allocated the body.
124 // Bodies only have one user so the body is just put into the world if not already there. 136 // Bodies only have one user so the body is just put into the world if not already there.
@@ -126,13 +138,13 @@ public sealed class BSShapeCollection : IDisposable
126 { 138 {
127 lock (m_collectionActivityLock) 139 lock (m_collectionActivityLock)
128 { 140 {
129 DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body); 141 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body);
130 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.ReferenceBody", delegate() 142 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.ReferenceBody", delegate()
131 { 143 {
132 if (!BulletSimAPI.IsInWorld2(body.ptr)) 144 if (!PhysicsScene.PE.IsInWorld(PhysicsScene.World, body))
133 { 145 {
134 BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr); 146 PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, body);
135 DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body); 147 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body);
136 } 148 }
137 }); 149 });
138 } 150 }
@@ -142,27 +154,27 @@ public sealed class BSShapeCollection : IDisposable
142 // Called when releasing use of a BSBody. BSShape is handled separately. 154 // Called when releasing use of a BSBody. BSShape is handled separately.
143 public void DereferenceBody(BulletBody body, bool inTaintTime, BodyDestructionCallback bodyCallback ) 155 public void DereferenceBody(BulletBody body, bool inTaintTime, BodyDestructionCallback bodyCallback )
144 { 156 {
145 if (body.ptr == IntPtr.Zero) 157 if (!body.HasPhysicalBody)
146 return; 158 return;
147 159
148 lock (m_collectionActivityLock) 160 lock (m_collectionActivityLock)
149 { 161 {
150 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceBody", delegate() 162 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceBody", delegate()
151 { 163 {
152 DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1},inTaintTime={2}", 164 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1},inTaintTime={2}",
153 body.ID, body, inTaintTime); 165 body.ID, body, inTaintTime);
154 // If the caller needs to know the old body is going away, pass the event up. 166 // If the caller needs to know the old body is going away, pass the event up.
155 if (bodyCallback != null) bodyCallback(body); 167 if (bodyCallback != null) bodyCallback(body);
156 168
157 if (BulletSimAPI.IsInWorld2(body.ptr)) 169 if (PhysicsScene.PE.IsInWorld(PhysicsScene.World, body))
158 { 170 {
159 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr); 171 PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, body);
160 DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body); 172 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body);
161 } 173 }
162 174
163 // Zero any reference to the shape so it is not freed when the body is deleted. 175 // Zero any reference to the shape so it is not freed when the body is deleted.
164 BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero); 176 PhysicsScene.PE.SetCollisionShape(PhysicsScene.World, body, null);
165 BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr); 177 PhysicsScene.PE.DestroyObject(PhysicsScene.World, body);
166 }); 178 });
167 } 179 }
168 } 180 }
@@ -184,17 +196,17 @@ public sealed class BSShapeCollection : IDisposable
184 { 196 {
185 // There is an existing instance of this mesh. 197 // There is an existing instance of this mesh.
186 meshDesc.referenceCount++; 198 meshDesc.referenceCount++;
187 DetailLog("{0},BSShapeCollection.ReferenceShape,existingMesh,key={1},cnt={2}", 199 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,existingMesh,key={1},cnt={2}",
188 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); 200 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
189 } 201 }
190 else 202 else
191 { 203 {
192 // This is a new reference to a mesh 204 // This is a new reference to a mesh
193 meshDesc.ptr = shape.ptr; 205 meshDesc.shape = shape.Clone();
194 meshDesc.shapeKey = shape.shapeKey; 206 meshDesc.shapeKey = shape.shapeKey;
195 // We keep a reference to the underlying IMesh data so a hull can be built 207 // We keep a reference to the underlying IMesh data so a hull can be built
196 meshDesc.referenceCount = 1; 208 meshDesc.referenceCount = 1;
197 DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}", 209 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}",
198 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); 210 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount);
199 ret = true; 211 ret = true;
200 } 212 }
@@ -207,16 +219,16 @@ public sealed class BSShapeCollection : IDisposable
207 { 219 {
208 // There is an existing instance of this hull. 220 // There is an existing instance of this hull.
209 hullDesc.referenceCount++; 221 hullDesc.referenceCount++;
210 DetailLog("{0},BSShapeCollection.ReferenceShape,existingHull,key={1},cnt={2}", 222 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,existingHull,key={1},cnt={2}",
211 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); 223 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
212 } 224 }
213 else 225 else
214 { 226 {
215 // This is a new reference to a hull 227 // This is a new reference to a hull
216 hullDesc.ptr = shape.ptr; 228 hullDesc.shape = shape.Clone();
217 hullDesc.shapeKey = shape.shapeKey; 229 hullDesc.shapeKey = shape.shapeKey;
218 hullDesc.referenceCount = 1; 230 hullDesc.referenceCount = 1;
219 DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}", 231 if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}",
220 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); 232 BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount);
221 ret = true; 233 ret = true;
222 234
@@ -236,20 +248,20 @@ public sealed class BSShapeCollection : IDisposable
236 // Release the usage of a shape. 248 // Release the usage of a shape.
237 public void DereferenceShape(BulletShape shape, bool inTaintTime, ShapeDestructionCallback shapeCallback) 249 public void DereferenceShape(BulletShape shape, bool inTaintTime, ShapeDestructionCallback shapeCallback)
238 { 250 {
239 if (shape.ptr == IntPtr.Zero) 251 if (!shape.HasPhysicalShape)
240 return; 252 return;
241 253
242 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceShape", delegate() 254 PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceShape", delegate()
243 { 255 {
244 if (shape.ptr != IntPtr.Zero) 256 if (shape.HasPhysicalShape)
245 { 257 {
246 if (shape.isNativeShape) 258 if (shape.isNativeShape)
247 { 259 {
248 // Native shapes are not tracked and are released immediately 260 // Native shapes are not tracked and are released immediately
249 DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}", 261 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}",
250 BSScene.DetailLogZero, shape.ptr.ToString("X"), inTaintTime); 262 BSScene.DetailLogZero, shape.AddrString, inTaintTime);
251 if (shapeCallback != null) shapeCallback(shape); 263 if (shapeCallback != null) shapeCallback(shape);
252 BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); 264 PhysicsScene.PE.DeleteCollisionShape(PhysicsScene.World, shape);
253 } 265 }
254 else 266 else
255 { 267 {
@@ -286,7 +298,7 @@ public sealed class BSShapeCollection : IDisposable
286 if (shapeCallback != null) shapeCallback(shape); 298 if (shapeCallback != null) shapeCallback(shape);
287 meshDesc.lastReferenced = System.DateTime.Now; 299 meshDesc.lastReferenced = System.DateTime.Now;
288 Meshes[shape.shapeKey] = meshDesc; 300 Meshes[shape.shapeKey] = meshDesc;
289 DetailLog("{0},BSShapeCollection.DereferenceMesh,shape={1},refCnt={2}", 301 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceMesh,shape={1},refCnt={2}",
290 BSScene.DetailLogZero, shape, meshDesc.referenceCount); 302 BSScene.DetailLogZero, shape, meshDesc.referenceCount);
291 303
292 } 304 }
@@ -307,7 +319,7 @@ public sealed class BSShapeCollection : IDisposable
307 319
308 hullDesc.lastReferenced = System.DateTime.Now; 320 hullDesc.lastReferenced = System.DateTime.Now;
309 Hulls[shape.shapeKey] = hullDesc; 321 Hulls[shape.shapeKey] = hullDesc;
310 DetailLog("{0},BSShapeCollection.DereferenceHull,shape={1},refCnt={2}", 322 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceHull,shape={1},refCnt={2}",
311 BSScene.DetailLogZero, shape, hullDesc.referenceCount); 323 BSScene.DetailLogZero, shape, hullDesc.referenceCount);
312 } 324 }
313 } 325 }
@@ -320,57 +332,56 @@ public sealed class BSShapeCollection : IDisposable
320 // Called at taint-time. 332 // Called at taint-time.
321 private void DereferenceCompound(BulletShape shape, ShapeDestructionCallback shapeCallback) 333 private void DereferenceCompound(BulletShape shape, ShapeDestructionCallback shapeCallback)
322 { 334 {
323 if (!BulletSimAPI.IsCompound2(shape.ptr)) 335 if (!PhysicsScene.PE.IsCompound(shape))
324 { 336 {
325 // Failed the sanity check!! 337 // Failed the sanity check!!
326 PhysicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}", 338 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")); 339 LogHeader, shape.type, shape.AddrString);
328 DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}", 340 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}",
329 BSScene.DetailLogZero, shape.type, shape.ptr.ToString("X")); 341 BSScene.DetailLogZero, shape.type, shape.AddrString);
330 return; 342 return;
331 } 343 }
332 344
333 int numChildren = BulletSimAPI.GetNumberOfCompoundChildren2(shape.ptr); 345 int numChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(shape);
334 DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}", BSScene.DetailLogZero, shape, numChildren); 346 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}", BSScene.DetailLogZero, shape, numChildren);
335 347
336 for (int ii = numChildren - 1; ii >= 0; ii--) 348 for (int ii = numChildren - 1; ii >= 0; ii--)
337 { 349 {
338 IntPtr childShape = BulletSimAPI.RemoveChildShapeFromCompoundShapeIndex2(shape.ptr, ii); 350 BulletShape childShape = PhysicsScene.PE.RemoveChildShapeFromCompoundShapeIndex(shape, ii);
339 DereferenceAnonCollisionShape(childShape); 351 DereferenceAnonCollisionShape(childShape);
340 } 352 }
341 BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); 353 PhysicsScene.PE.DeleteCollisionShape(PhysicsScene.World, shape);
342 } 354 }
343 355
344 // Sometimes we have a pointer to a collision shape but don't know what type it is. 356 // 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. 357 // Figure out type and call the correct dereference routine.
346 // Called at taint-time. 358 // Called at taint-time.
347 private void DereferenceAnonCollisionShape(IntPtr cShape) 359 private void DereferenceAnonCollisionShape(BulletShape shapeInfo)
348 { 360 {
349 MeshDesc meshDesc; 361 MeshDesc meshDesc;
350 HullDesc hullDesc; 362 HullDesc hullDesc;
351 363
352 BulletShape shapeInfo = new BulletShape(cShape); 364 if (TryGetMeshByPtr(shapeInfo, out meshDesc))
353 if (TryGetMeshByPtr(cShape, out meshDesc))
354 { 365 {
355 shapeInfo.type = BSPhysicsShapeType.SHAPE_MESH; 366 shapeInfo.type = BSPhysicsShapeType.SHAPE_MESH;
356 shapeInfo.shapeKey = meshDesc.shapeKey; 367 shapeInfo.shapeKey = meshDesc.shapeKey;
357 } 368 }
358 else 369 else
359 { 370 {
360 if (TryGetHullByPtr(cShape, out hullDesc)) 371 if (TryGetHullByPtr(shapeInfo, out hullDesc))
361 { 372 {
362 shapeInfo.type = BSPhysicsShapeType.SHAPE_HULL; 373 shapeInfo.type = BSPhysicsShapeType.SHAPE_HULL;
363 shapeInfo.shapeKey = hullDesc.shapeKey; 374 shapeInfo.shapeKey = hullDesc.shapeKey;
364 } 375 }
365 else 376 else
366 { 377 {
367 if (BulletSimAPI.IsCompound2(cShape)) 378 if (PhysicsScene.PE.IsCompound(shapeInfo))
368 { 379 {
369 shapeInfo.type = BSPhysicsShapeType.SHAPE_COMPOUND; 380 shapeInfo.type = BSPhysicsShapeType.SHAPE_COMPOUND;
370 } 381 }
371 else 382 else
372 { 383 {
373 if (BulletSimAPI.IsNativeShape2(cShape)) 384 if (PhysicsScene.PE.IsNativeShape(shapeInfo))
374 { 385 {
375 shapeInfo.isNativeShape = true; 386 shapeInfo.isNativeShape = true;
376 shapeInfo.type = BSPhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter) 387 shapeInfo.type = BSPhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter)
@@ -379,7 +390,7 @@ public sealed class BSShapeCollection : IDisposable
379 } 390 }
380 } 391 }
381 392
382 DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo); 393 if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo);
383 394
384 if (shapeInfo.type != BSPhysicsShapeType.SHAPE_UNKNOWN) 395 if (shapeInfo.type != BSPhysicsShapeType.SHAPE_UNKNOWN)
385 { 396 {
@@ -388,7 +399,7 @@ public sealed class BSShapeCollection : IDisposable
388 else 399 else
389 { 400 {
390 PhysicsScene.Logger.ErrorFormat("{0} Could not decypher shape type. Region={1}, addr={2}", 401 PhysicsScene.Logger.ErrorFormat("{0} Could not decypher shape type. Region={1}, addr={2}",
391 LogHeader, PhysicsScene.RegionName, cShape.ToString("X")); 402 LogHeader, PhysicsScene.RegionName, shapeInfo.AddrString);
392 } 403 }
393 } 404 }
394 405
@@ -408,19 +419,18 @@ public sealed class BSShapeCollection : IDisposable
408 if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_CAPSULE) 419 if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_CAPSULE)
409 { 420 {
410 // an avatar capsule is close to a native shape (it is not shared) 421 // an avatar capsule is close to a native shape (it is not shared)
411 ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_CAPSULE, 422 GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_CAPSULE, FixedShapeKey.KEY_CAPSULE, shapeCallback);
412 FixedShapeKey.KEY_CAPSULE, shapeCallback); 423 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape);
413 DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape);
414 ret = true; 424 ret = true;
415 haveShape = true; 425 haveShape = true;
416 } 426 }
417 427
418 // Compound shapes are handled special as they are rebuilt from scratch. 428 // 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. 429 // This isn't too great a hardship since most of the child shapes will have already been created.
420 if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND) 430 if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND)
421 { 431 {
422 ret = GetReferenceToCompoundShape(prim, shapeCallback); 432 ret = GetReferenceToCompoundShape(prim, shapeCallback);
423 DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape); 433 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape);
424 haveShape = true; 434 haveShape = true;
425 } 435 }
426 436
@@ -432,8 +442,9 @@ public sealed class BSShapeCollection : IDisposable
432 return ret; 442 return ret;
433 } 443 }
434 444
435 // Create a mesh/hull shape or a native shape if 'nativeShapePossible' is 'true'. 445 // Create a mesh, hull or native shape.
436 private bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback) 446 // Return 'true' if the prim's shape was changed.
447 public bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback)
437 { 448 {
438 bool ret = false; 449 bool ret = false;
439 bool haveShape = false; 450 bool haveShape = false;
@@ -443,8 +454,9 @@ public sealed class BSShapeCollection : IDisposable
443 // If the prim attributes are simple, this could be a simple Bullet native shape 454 // If the prim attributes are simple, this could be a simple Bullet native shape
444 if (!haveShape 455 if (!haveShape
445 && pbs != null 456 && pbs != null
457 && !pbs.SculptEntry
446 && nativeShapePossible 458 && nativeShapePossible
447 && ((pbs.SculptEntry && !PhysicsScene.ShouldMeshSculptedPrim) 459 && ((pbs.SculptEntry && !BSParam.ShouldMeshSculptedPrim)
448 || (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0 460 || (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
449 && pbs.ProfileHollow == 0 461 && pbs.ProfileHollow == 0
450 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0 462 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
@@ -453,35 +465,43 @@ public sealed class BSShapeCollection : IDisposable
453 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 465 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
454 && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) ) 466 && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) )
455 { 467 {
456 // It doesn't look like Bullet scales spheres so make sure the scales are all equal 468 // Get the scale of any existing shape so we can see if the new shape is same native type and same size.
469 OMV.Vector3 scaleOfExistingShape = OMV.Vector3.Zero;
470 if (prim.PhysShape.HasPhysicalShape)
471 scaleOfExistingShape = PhysicsScene.PE.GetLocalScaling(prim.PhysShape);
472
473 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,maybeNative,force={1},primScale={2},primSize={3},primShape={4}",
474 prim.LocalID, forceRebuild, prim.Scale, prim.Size, prim.PhysShape.type);
475
476 // It doesn't look like Bullet scales native spheres so make sure the scales are all equal
457 if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) 477 if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
458 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z) 478 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z)
459 { 479 {
460 haveShape = true; 480 haveShape = true;
461 if (forceRebuild 481 if (forceRebuild
462 || prim.Scale != prim.Size 482 || prim.Scale != scaleOfExistingShape
463 || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_SPHERE 483 || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_SPHERE
464 ) 484 )
465 { 485 {
466 ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_SPHERE, 486 ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_SPHERE,
467 FixedShapeKey.KEY_SPHERE, shapeCallback); 487 FixedShapeKey.KEY_SPHERE, shapeCallback);
468 DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}",
469 prim.LocalID, forceRebuild, prim.PhysShape);
470 } 488 }
489 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},rebuilt={2},shape={3}",
490 prim.LocalID, forceRebuild, ret, prim.PhysShape);
471 } 491 }
472 if (!haveShape && pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) 492 if (!haveShape && pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
473 { 493 {
474 haveShape = true; 494 haveShape = true;
475 if (forceRebuild 495 if (forceRebuild
476 || prim.Scale != prim.Size 496 || prim.Scale != scaleOfExistingShape
477 || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_BOX 497 || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_BOX
478 ) 498 )
479 { 499 {
480 ret = GetReferenceToNativeShape( prim, BSPhysicsShapeType.SHAPE_BOX, 500 ret = GetReferenceToNativeShape( prim, BSPhysicsShapeType.SHAPE_BOX,
481 FixedShapeKey.KEY_BOX, shapeCallback); 501 FixedShapeKey.KEY_BOX, shapeCallback);
482 DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}",
483 prim.LocalID, forceRebuild, prim.PhysShape);
484 } 502 }
503 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},rebuilt={2},shape={3}",
504 prim.LocalID, forceRebuild, ret, prim.PhysShape);
485 } 505 }
486 } 506 }
487 507
@@ -494,23 +514,24 @@ public sealed class BSShapeCollection : IDisposable
494 return ret; 514 return ret;
495 } 515 }
496 516
517 // return 'true' if the prim's shape was changed.
497 public bool CreateGeomMeshOrHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback) 518 public bool CreateGeomMeshOrHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
498 { 519 {
499 520
500 bool ret = false; 521 bool ret = false;
501 // Note that if it's a native shape, the check for physical/non-physical is not 522 // Note that if it's a native shape, the check for physical/non-physical is not
502 // made. Native shapes work in either case. 523 // made. Native shapes work in either case.
503 if (prim.IsPhysical && PhysicsScene.ShouldUseHullsForPhysicalObjects) 524 if (prim.IsPhysical && BSParam.ShouldUseHullsForPhysicalObjects)
504 { 525 {
505 // Update prim.BSShape to reference a hull of this shape. 526 // Update prim.BSShape to reference a hull of this shape.
506 ret = GetReferenceToHull(prim,shapeCallback); 527 ret = GetReferenceToHull(prim,shapeCallback);
507 DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}", 528 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}",
508 prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); 529 prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
509 } 530 }
510 else 531 else
511 { 532 {
512 ret = GetReferenceToMesh(prim, shapeCallback); 533 ret = GetReferenceToMesh(prim, shapeCallback);
513 DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}", 534 if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}",
514 prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); 535 prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X"));
515 } 536 }
516 return ret; 537 return ret;
@@ -528,9 +549,10 @@ public sealed class BSShapeCollection : IDisposable
528 BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey); 549 BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey);
529 550
530 // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. 551 // Don't need to do a 'ReferenceShape()' here because native shapes are not shared.
531 DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}", 552 if (DDetail) DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}",
532 prim.LocalID, newShape, prim.Scale); 553 prim.LocalID, newShape, prim.Scale);
533 554
555 // native shapes are scaled by Bullet
534 prim.PhysShape = newShape; 556 prim.PhysShape = newShape;
535 return true; 557 return true;
536 } 558 }
@@ -550,20 +572,17 @@ public sealed class BSShapeCollection : IDisposable
550 572
551 if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE) 573 if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE)
552 { 574 {
553 // The proper scale has been calculated in the prim. 575
554 newShape = new BulletShape( 576 newShape = PhysicsScene.PE.BuildCapsuleShape(PhysicsScene.World, 1f, 1f, prim.Scale);
555 BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, prim.Scale) 577 if (DDetail) DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale);
556 , shapeType);
557 DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale);
558 } 578 }
559 else 579 else
560 { 580 {
561 // Native shapes are scaled in Bullet so set the scaling to the size 581 // Native shapes are scaled in Bullet so set the scaling to the size
562 prim.Scale = prim.Size; 582 newShape = PhysicsScene.PE.BuildNativeShape(PhysicsScene.World, nativeShapeData);
563 nativeShapeData.Scale = prim.Scale; 583
564 newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, nativeShapeData), shapeType);
565 } 584 }
566 if (newShape.ptr == IntPtr.Zero) 585 if (!newShape.HasPhysicalShape)
567 { 586 {
568 PhysicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", 587 PhysicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}",
569 LogHeader, prim.LocalID, shapeType); 588 LogHeader, prim.LocalID, shapeType);
@@ -580,7 +599,7 @@ public sealed class BSShapeCollection : IDisposable
580 // Called at taint-time! 599 // Called at taint-time!
581 private bool GetReferenceToMesh(BSPhysObject prim, ShapeDestructionCallback shapeCallback) 600 private bool GetReferenceToMesh(BSPhysObject prim, ShapeDestructionCallback shapeCallback)
582 { 601 {
583 BulletShape newShape = new BulletShape(IntPtr.Zero); 602 BulletShape newShape = new BulletShape();
584 603
585 float lod; 604 float lod;
586 System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod); 605 System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
@@ -589,7 +608,7 @@ public sealed class BSShapeCollection : IDisposable
589 if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_MESH) 608 if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_MESH)
590 return false; 609 return false;
591 610
592 DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2}", 611 if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2}",
593 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X")); 612 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X"));
594 613
595 // Since we're recreating new, get rid of the reference to the previous shape 614 // Since we're recreating new, get rid of the reference to the previous shape
@@ -601,8 +620,6 @@ public sealed class BSShapeCollection : IDisposable
601 620
602 ReferenceShape(newShape); 621 ReferenceShape(newShape);
603 622
604 // meshes are already scaled by the meshmerizer
605 prim.Scale = new OMV.Vector3(1f, 1f, 1f);
606 prim.PhysShape = newShape; 623 prim.PhysShape = newShape;
607 624
608 return true; // 'true' means a new shape has been added to this prim 625 return true; // 'true' means a new shape has been added to this prim
@@ -610,18 +627,18 @@ public sealed class BSShapeCollection : IDisposable
610 627
611 private BulletShape CreatePhysicalMesh(string objName, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) 628 private BulletShape CreatePhysicalMesh(string objName, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
612 { 629 {
630 BulletShape newShape = new BulletShape();
613 IMesh meshData = null; 631 IMesh meshData = null;
614 IntPtr meshPtr = IntPtr.Zero; 632
615 MeshDesc meshDesc; 633 MeshDesc meshDesc;
616 if (Meshes.TryGetValue(newMeshKey, out meshDesc)) 634 if (Meshes.TryGetValue(newMeshKey, out meshDesc))
617 { 635 {
618 // If the mesh has already been built just use it. 636 // If the mesh has already been built just use it.
619 meshPtr = meshDesc.ptr; 637 newShape = meshDesc.shape.Clone();
620 } 638 }
621 else 639 else
622 { 640 {
623 // Pass false for physicalness as this creates some sort of bounding box which we don't need 641 meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true, false, false, false);
624 meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false);
625 642
626 if (meshData != null) 643 if (meshData != null)
627 { 644 {
@@ -640,11 +657,10 @@ public sealed class BSShapeCollection : IDisposable
640 // m_log.DebugFormat("{0}: BSShapeCollection.CreatePhysicalMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", 657 // m_log.DebugFormat("{0}: BSShapeCollection.CreatePhysicalMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}",
641 // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count); 658 // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count);
642 659
643 meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, 660 newShape = PhysicsScene.PE.CreateMeshShape(PhysicsScene.World,
644 indices.GetLength(0), indices, vertices.Count, verticesAsFloats); 661 indices.GetLength(0), indices, vertices.Count, verticesAsFloats);
645 } 662 }
646 } 663 }
647 BulletShape newShape = new BulletShape(meshPtr, BSPhysicsShapeType.SHAPE_MESH);
648 newShape.shapeKey = newMeshKey; 664 newShape.shapeKey = newMeshKey;
649 665
650 return newShape; 666 return newShape;
@@ -663,7 +679,7 @@ public sealed class BSShapeCollection : IDisposable
663 if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_HULL) 679 if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_HULL)
664 return false; 680 return false;
665 681
666 DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}", 682 if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}",
667 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X")); 683 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X"));
668 684
669 // Remove usage of the previous shape. 685 // Remove usage of the previous shape.
@@ -674,8 +690,6 @@ public sealed class BSShapeCollection : IDisposable
674 690
675 ReferenceShape(newShape); 691 ReferenceShape(newShape);
676 692
677 // hulls are already scaled by the meshmerizer
678 prim.Scale = new OMV.Vector3(1f, 1f, 1f);
679 prim.PhysShape = newShape; 693 prim.PhysShape = newShape;
680 return true; // 'true' means a new shape has been added to this prim 694 return true; // 'true' means a new shape has been added to this prim
681 } 695 }
@@ -684,18 +698,20 @@ public sealed class BSShapeCollection : IDisposable
684 private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) 698 private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
685 { 699 {
686 700
701 BulletShape newShape = new BulletShape();
687 IntPtr hullPtr = IntPtr.Zero; 702 IntPtr hullPtr = IntPtr.Zero;
703
688 HullDesc hullDesc; 704 HullDesc hullDesc;
689 if (Hulls.TryGetValue(newHullKey, out hullDesc)) 705 if (Hulls.TryGetValue(newHullKey, out hullDesc))
690 { 706 {
691 // If the hull shape already is created, just use it. 707 // If the hull shape already is created, just use it.
692 hullPtr = hullDesc.ptr; 708 newShape = hullDesc.shape.Clone();
693 } 709 }
694 else 710 else
695 { 711 {
696 // Build a new hull in the physical world 712 // Build a new hull in the physical world
697 // Pass false for physicalness as this creates some sort of bounding box which we don't need 713 // Pass true for physicalness as this creates some sort of bounding box which we don't need
698 IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false); 714 IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true, false, false, false);
699 if (meshData != null) 715 if (meshData != null)
700 { 716 {
701 717
@@ -777,14 +793,13 @@ public sealed class BSShapeCollection : IDisposable
777 } 793 }
778 } 794 }
779 // create the hull data structure in Bullet 795 // create the hull data structure in Bullet
780 hullPtr = BulletSimAPI.CreateHullShape2(PhysicsScene.World.ptr, hullCount, convHulls); 796 newShape = PhysicsScene.PE.CreateHullShape(PhysicsScene.World, hullCount, convHulls);
781 } 797 }
782 } 798 }
783 799
784 BulletShape newShape = new BulletShape(hullPtr, BSPhysicsShapeType.SHAPE_HULL);
785 newShape.shapeKey = newHullKey; 800 newShape.shapeKey = newHullKey;
786 801
787 return newShape; // 'true' means a new shape has been added to this prim 802 return newShape;
788 } 803 }
789 804
790 // Callback from convex hull creater with a newly created hull. 805 // Callback from convex hull creater with a newly created hull.
@@ -803,13 +818,13 @@ public sealed class BSShapeCollection : IDisposable
803 // Don't need to do this as the shape is freed when the new root shape is created below. 818 // Don't need to do this as the shape is freed when the new root shape is created below.
804 // DereferenceShape(prim.PhysShape, true, shapeCallback); 819 // DereferenceShape(prim.PhysShape, true, shapeCallback);
805 820
806 BulletShape cShape = new BulletShape( 821
807 BulletSimAPI.CreateCompoundShape2(PhysicsScene.World.ptr, false), BSPhysicsShapeType.SHAPE_COMPOUND); 822 BulletShape cShape = PhysicsScene.PE.CreateCompoundShape(PhysicsScene.World, false);
808 823
809 // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape. 824 // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape.
810 CreateGeomMeshOrHull(prim, shapeCallback); 825 CreateGeomMeshOrHull(prim, shapeCallback);
811 BulletSimAPI.AddChildShapeToCompoundShape2(cShape.ptr, prim.PhysShape.ptr, OMV.Vector3.Zero, OMV.Quaternion.Identity); 826 PhysicsScene.PE.AddChildShapeToCompoundShape(cShape, prim.PhysShape, OMV.Vector3.Zero, OMV.Quaternion.Identity);
812 DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addRootPrim,compShape={1},rootShape={2}", 827 if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addRootPrim,compShape={1},rootShape={2}",
813 prim.LocalID, cShape, prim.PhysShape); 828 prim.LocalID, cShape, prim.PhysShape);
814 829
815 prim.PhysShape = cShape; 830 prim.PhysShape = cShape;
@@ -822,14 +837,14 @@ public sealed class BSShapeCollection : IDisposable
822 private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod) 837 private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod)
823 { 838 {
824 // level of detail based on size and type of the object 839 // level of detail based on size and type of the object
825 float lod = PhysicsScene.MeshLOD; 840 float lod = BSParam.MeshLOD;
826 if (pbs.SculptEntry) 841 if (pbs.SculptEntry)
827 lod = PhysicsScene.SculptLOD; 842 lod = BSParam.SculptLOD;
828 843
829 // Mega prims usually get more detail because one can interact with shape approximations at this size. 844 // Mega prims usually get more detail because one can interact with shape approximations at this size.
830 float maxAxis = Math.Max(size.X, Math.Max(size.Y, size.Z)); 845 float maxAxis = Math.Max(size.X, Math.Max(size.Y, size.Z));
831 if (maxAxis > PhysicsScene.MeshMegaPrimThreshold) 846 if (maxAxis > BSParam.MeshMegaPrimThreshold)
832 lod = PhysicsScene.MeshMegaPrimLOD; 847 lod = BSParam.MeshMegaPrimLOD;
833 848
834 retLod = lod; 849 retLod = lod;
835 return pbs.GetMeshKey(size, lod); 850 return pbs.GetMeshKey(size, lod);
@@ -851,7 +866,7 @@ public sealed class BSShapeCollection : IDisposable
851 private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim) 866 private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim)
852 { 867 {
853 // If the shape was successfully created, nothing more to do 868 // If the shape was successfully created, nothing more to do
854 if (newShape.ptr != IntPtr.Zero) 869 if (newShape.HasPhysicalShape)
855 return newShape; 870 return newShape;
856 871
857 // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset 872 // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset
@@ -859,8 +874,7 @@ public sealed class BSShapeCollection : IDisposable
859 { 874 {
860 prim.LastAssetBuildFailed = true; 875 prim.LastAssetBuildFailed = true;
861 BSPhysObject xprim = prim; 876 BSPhysObject xprim = prim;
862 DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset,lID={1},lastFailed={2}", 877 DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset,lastFailed={1}", prim.LocalID, prim.LastAssetBuildFailed);
863 LogHeader, prim.LocalID, prim.LastAssetBuildFailed);
864 Util.FireAndForget(delegate 878 Util.FireAndForget(delegate
865 { 879 {
866 RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod; 880 RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod;
@@ -869,19 +883,34 @@ public sealed class BSShapeCollection : IDisposable
869 BSPhysObject yprim = xprim; // probably not necessary, but, just in case. 883 BSPhysObject yprim = xprim; // probably not necessary, but, just in case.
870 assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset) 884 assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset)
871 { 885 {
872 if (!yprim.BaseShape.SculptEntry) 886 bool assetFound = false; // DEBUG DEBUG
873 return; 887 string mismatchIDs = String.Empty; // DEBUG DEBUG
874 if (yprim.BaseShape.SculptTexture.ToString() != asset.ID) 888 if (yprim.BaseShape.SculptEntry)
875 return; 889 {
876 890 if (yprim.BaseShape.SculptTexture.ToString() == asset.ID)
877 yprim.BaseShape.SculptData = asset.Data; 891 {
878 // This will cause the prim to see that the filler shape is not the right 892 yprim.BaseShape.SculptData = asset.Data;
879 // one and try again to build the object. 893 // This will cause the prim to see that the filler shape is not the right
880 // No race condition with the normal shape setting since the rebuild is at taint time. 894 // one and try again to build the object.
881 yprim.ForceBodyShapeRebuild(false); 895 // No race condition with the normal shape setting since the rebuild is at taint time.
896 yprim.ForceBodyShapeRebuild(false /* inTaintTime */);
897 assetFound = true;
898 }
899 else
900 {
901 mismatchIDs = yprim.BaseShape.SculptTexture.ToString() + "/" + asset.ID;
902 }
903 }
904 DetailLog("{0},BSShapeCollection,fetchAssetCallback,found={1},isSculpt={2},ids={3}",
905 yprim.LocalID, assetFound, yprim.BaseShape.SculptEntry, mismatchIDs );
882 906
883 }); 907 });
884 } 908 }
909 else
910 {
911 PhysicsScene.Logger.ErrorFormat("{0} Physical object requires asset but no asset provider. Name={1}",
912 LogHeader, PhysicsScene.Name);
913 }
885 }); 914 });
886 } 915 }
887 else 916 else
@@ -893,9 +922,9 @@ public sealed class BSShapeCollection : IDisposable
893 } 922 }
894 } 923 }
895 924
896 // While we figure out the real problem, stick a simple native shape on the object. 925 // While we wait for the mesh defining asset to be loaded, stick in a simple box for the object.
897 BulletShape fillinShape = 926 BulletShape fillinShape = BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX);
898 BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX); 927 DetailLog("{0},BSShapeCollection.VerifyMeshCreated,boxTempShape", prim.LocalID);
899 928
900 return fillinShape; 929 return fillinShape;
901 } 930 }
@@ -904,19 +933,19 @@ public sealed class BSShapeCollection : IDisposable
904 // Updates prim.BSBody with the information about the new body if one is created. 933 // Updates prim.BSBody with the information about the new body if one is created.
905 // Returns 'true' if an object was actually created. 934 // Returns 'true' if an object was actually created.
906 // Called at taint-time. 935 // Called at taint-time.
907 private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletSim sim, BulletShape shape, 936 private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletWorld sim, BulletShape shape,
908 BodyDestructionCallback bodyCallback) 937 BodyDestructionCallback bodyCallback)
909 { 938 {
910 bool ret = false; 939 bool ret = false;
911 940
912 // the mesh, hull or native shape must have already been created in Bullet 941 // the mesh, hull or native shape must have already been created in Bullet
913 bool mustRebuild = (prim.PhysBody.ptr == IntPtr.Zero); 942 bool mustRebuild = !prim.PhysBody.HasPhysicalBody;
914 943
915 // If there is an existing body, verify it's of an acceptable type. 944 // If there is an existing body, verify it's of an acceptable type.
916 // If not a solid object, body is a GhostObject. Otherwise a RigidBody. 945 // If not a solid object, body is a GhostObject. Otherwise a RigidBody.
917 if (!mustRebuild) 946 if (!mustRebuild)
918 { 947 {
919 CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(prim.PhysBody.ptr); 948 CollisionObjectTypes bodyType = (CollisionObjectTypes)PhysicsScene.PE.GetBodyType(prim.PhysBody);
920 if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY 949 if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY
921 || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT) 950 || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT)
922 { 951 {
@@ -931,20 +960,16 @@ public sealed class BSShapeCollection : IDisposable
931 DereferenceBody(prim.PhysBody, true, bodyCallback); 960 DereferenceBody(prim.PhysBody, true, bodyCallback);
932 961
933 BulletBody aBody; 962 BulletBody aBody;
934 IntPtr bodyPtr = IntPtr.Zero;
935 if (prim.IsSolid) 963 if (prim.IsSolid)
936 { 964 {
937 bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr, 965 aBody = PhysicsScene.PE.CreateBodyFromShape(sim, shape, prim.LocalID, prim.RawPosition, prim.RawOrientation);
938 prim.LocalID, prim.RawPosition, prim.RawOrientation); 966 if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,mesh,body={1}", prim.LocalID, aBody);
939 DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
940 } 967 }
941 else 968 else
942 { 969 {
943 bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr, 970 aBody = PhysicsScene.PE.CreateGhostFromShape(sim, shape, prim.LocalID, prim.RawPosition, prim.RawOrientation);
944 prim.LocalID, prim.RawPosition, prim.RawOrientation); 971 if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,ghost,body={1}", prim.LocalID, aBody);
945 DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X"));
946 } 972 }
947 aBody = new BulletBody(prim.LocalID, bodyPtr);
948 973
949 ReferenceBody(aBody, true); 974 ReferenceBody(aBody, true);
950 975
@@ -956,13 +981,13 @@ public sealed class BSShapeCollection : IDisposable
956 return ret; 981 return ret;
957 } 982 }
958 983
959 private bool TryGetMeshByPtr(IntPtr addr, out MeshDesc outDesc) 984 private bool TryGetMeshByPtr(BulletShape shape, out MeshDesc outDesc)
960 { 985 {
961 bool ret = false; 986 bool ret = false;
962 MeshDesc foundDesc = new MeshDesc(); 987 MeshDesc foundDesc = new MeshDesc();
963 foreach (MeshDesc md in Meshes.Values) 988 foreach (MeshDesc md in Meshes.Values)
964 { 989 {
965 if (md.ptr == addr) 990 if (md.shape.ReferenceSame(shape))
966 { 991 {
967 foundDesc = md; 992 foundDesc = md;
968 ret = true; 993 ret = true;
@@ -974,13 +999,13 @@ public sealed class BSShapeCollection : IDisposable
974 return ret; 999 return ret;
975 } 1000 }
976 1001
977 private bool TryGetHullByPtr(IntPtr addr, out HullDesc outDesc) 1002 private bool TryGetHullByPtr(BulletShape shape, out HullDesc outDesc)
978 { 1003 {
979 bool ret = false; 1004 bool ret = false;
980 HullDesc foundDesc = new HullDesc(); 1005 HullDesc foundDesc = new HullDesc();
981 foreach (HullDesc hd in Hulls.Values) 1006 foreach (HullDesc hd in Hulls.Values)
982 { 1007 {
983 if (hd.ptr == addr) 1008 if (hd.shape.ReferenceSame(shape))
984 { 1009 {
985 foundDesc = hd; 1010 foundDesc = hd;
986 ret = true; 1011 ret = true;