aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
diff options
context:
space:
mode:
authorRobert Adams2012-09-23 18:39:46 -0700
committerRobert Adams2012-09-27 22:01:37 -0700
commitd016051fa028a485b09fac47b3fa3d8fd08e207a (patch)
tree8f483976bb64b1328439b76754675126b09943b0 /OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
parentBulletSim: fix regression that caused cylindar shapes to have a box collision... (diff)
downloadopensim-SC_OLD-d016051fa028a485b09fac47b3fa3d8fd08e207a.zip
opensim-SC_OLD-d016051fa028a485b09fac47b3fa3d8fd08e207a.tar.gz
opensim-SC_OLD-d016051fa028a485b09fac47b3fa3d8fd08e207a.tar.bz2
opensim-SC_OLD-d016051fa028a485b09fac47b3fa3d8fd08e207a.tar.xz
BulletSim: renamed members of BulletShape, BulletSim and BulletBody
so the members case is consistant. Caused modifications everywhere. New logic in BSShapeCollection to track use and sharing of shapes. I just reslized, though, that shapes cannot be shared because the shape's UserPointer is the localID of the prim and is required for tracking collisions. More changes coming. Added DuplicateCollisionShape2() to API and changed BuildNativeShape2 to take a ShapeData structure so don't have to pass so many parameters. This matches the latest version of BulletSim.dll. Additions and removal of DetailLog() statements for debugging.
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs')
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs344
1 files changed, 249 insertions, 95 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index 7470d23..6b90661 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -38,8 +38,9 @@ public class BSShapeCollection : IDisposable
38{ 38{
39 protected BSScene PhysicsScene { get; set; } 39 protected BSScene PhysicsScene { get; set; }
40 40
41 private Object m_shapeActivityLock = new Object(); 41 private Object m_collectionActivityLock = new Object();
42 42
43 // Description of a Mesh
43 private struct MeshDesc 44 private struct MeshDesc
44 { 45 {
45 public IntPtr Ptr; 46 public IntPtr Ptr;
@@ -48,6 +49,8 @@ public class BSShapeCollection : IDisposable
48 public IMesh meshData; 49 public IMesh meshData;
49 } 50 }
50 51
52 // Description of a hull.
53 // Meshes and hulls have the same shape hash key but we only need hulls for efficient physical objects
51 private struct HullDesc 54 private struct HullDesc
52 { 55 {
53 public IntPtr Ptr; 56 public IntPtr Ptr;
@@ -55,8 +58,17 @@ public class BSShapeCollection : IDisposable
55 public DateTime lastReferenced; 58 public DateTime lastReferenced;
56 } 59 }
57 60
61 private struct BodyDesc
62 {
63 public IntPtr Ptr;
64 // Bodies are only used once so reference count is always either one or zero
65 public int referenceCount;
66 public DateTime lastReferenced;
67 }
68
58 private Dictionary<ulong, MeshDesc> Meshes = new Dictionary<ulong, MeshDesc>(); 69 private Dictionary<ulong, MeshDesc> Meshes = new Dictionary<ulong, MeshDesc>();
59 private Dictionary<ulong, HullDesc> Hulls = new Dictionary<ulong, HullDesc>(); 70 private Dictionary<ulong, HullDesc> Hulls = new Dictionary<ulong, HullDesc>();
71 private Dictionary<uint, BodyDesc> Bodies = new Dictionary<uint, BodyDesc>();
60 72
61 public BSShapeCollection(BSScene physScene) 73 public BSShapeCollection(BSScene physScene)
62 { 74 {
@@ -65,6 +77,7 @@ public class BSShapeCollection : IDisposable
65 77
66 public void Dispose() 78 public void Dispose()
67 { 79 {
80 // TODO!!!!!!!!!
68 } 81 }
69 82
70 // Called to update/change the body and shape for an object. 83 // Called to update/change the body and shape for an object.
@@ -76,40 +89,104 @@ public class BSShapeCollection : IDisposable
76 { 89 {
77 bool ret = false; 90 bool ret = false;
78 91
79 // Do we have the correct geometry for this type of object? 92 // This lock could probably be pushed down lower but building shouldn't take long
80 if (CreateGeom(forceRebuild, prim, shapeData, pbs)) 93 lock (m_collectionActivityLock)
81 { 94 {
95 // Do we have the correct geometry for this type of object?
96 bool newGeom = CreateGeom(forceRebuild, prim, shapeData, pbs);
82 // If we had to select a new shape geometry for the object, 97 // If we had to select a new shape geometry for the object,
83 // rebuild the body around it. 98 // rebuild the body around it.
84 CreateObject(true, prim, PhysicsScene.World, prim.BSShape, shapeData); 99 bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, prim.BSShape, shapeData);
85 ret = true; 100 ret = newGeom || newBody;
86 } 101 }
102 DetailLog("{0},BSShapeCollection.GetBodyAndShape,force-{1},ret={2},body={3},shape={4}",
103 prim.LocalID, forceRebuild, ret, prim.BSBody, prim.BSShape);
87 104
88 return ret; 105 return ret;
89 } 106 }
90 107
91 // Track another user of a body 108 // Track another user of a body
92 public void ReferenceBody(BulletBody shape) 109 // We presume the caller has allocated the body.
110 // Bodies only have one user so the reference count is either 1 or 0.
111 public void ReferenceBody(BulletBody shape, bool atTaintTime)
93 { 112 {
94 } 113 lock (m_collectionActivityLock)
114 {
115 BodyDesc bodyDesc;
116 if (Bodies.TryGetValue(shape.ID, out bodyDesc))
117 {
118 bodyDesc.referenceCount++;
119 DetailLog("{0},BSShapeCollection.ReferenceBody,existingBody,ref={1}", shape.ID, bodyDesc.referenceCount);
120 }
121 else
122 {
123 bodyDesc.Ptr = shape.ptr;
124 bodyDesc.referenceCount = 1;
125 DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,ref={1}", shape.ID, bodyDesc.referenceCount);
126 }
127 bodyDesc.lastReferenced = System.DateTime.Now;
128 Bodies[shape.ID] = bodyDesc;
129 }
130}
95 131
96 // Release the usage of a body 132 // Release the usage of a body.
97 public void DereferenceBody(BulletBody shape) 133 // Not that this will also delete the body in BUllet if the body is now unused (reference count = 0).
134 public void DereferenceBody(BulletBody shape, bool inTaintTime)
98 { 135 {
136 if (shape.ptr == IntPtr.Zero)
137 return;
138
139 lock (m_collectionActivityLock)
140 {
141 BodyDesc bodyDesc;
142 if (Bodies.TryGetValue(shape.ID, out bodyDesc))
143 {
144 bodyDesc.referenceCount--;
145 bodyDesc.lastReferenced = System.DateTime.Now;
146 Bodies[shape.ID] = bodyDesc;
147 DetailLog("{0},BSShapeCollection.DereferenceBody,ref={1}", shape.ID, bodyDesc.referenceCount);
148
149 if (bodyDesc.referenceCount == 0)
150 {
151 Bodies.Remove(shape.ID);
152 BSScene.TaintCallback removeOperation = delegate()
153 {
154 DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody. Ptr={1:X}", shape.ID, shape.ptr);
155 // zero any reference to the shape so it is not freed when the body is deleted
156 BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, shape.ptr, IntPtr.Zero);
157 // It may have already been removed from the world in which case the next is a NOOP
158 BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, shape.ptr);
159 BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, shape.ptr);
160 };
161 // If already in taint-time, do the operations now. Otherwise queue for later.
162 if (inTaintTime)
163 removeOperation();
164 else
165 PhysicsScene.TaintedObject("BSShapeCollection.DereferenceBody", removeOperation);
166 }
167 }
168 else
169 {
170 DetailLog("{0},BSShapeCollection.DereferenceBody,DID NOT FIND BODY", shape.ID, bodyDesc.referenceCount);
171 }
172 }
99 } 173 }
100 174
101 // Track another user of the shape 175 // Track another user of the shape
102 public void ReferenceShape(BulletShape shape) 176 private bool ReferenceShape(BulletShape shape)
103 { 177 {
104 ReferenceShape(shape, null); 178 return ReferenceShape(shape, null);
105 } 179 }
106 180
107 // Track the datastructures and use count for a shape. 181 // Track the datastructures and use count for a shape.
108 // When creating a hull, this is called first to reference the mesh 182 // When creating a hull, this is called first to reference the mesh
109 // and then again to reference the hull. 183 // and then again to reference the hull.
110 // Meshes and hulls for the same shape have the same hash key. 184 // Meshes and hulls for the same shape have the same hash key.
111 private void ReferenceShape(BulletShape shape, IMesh meshData) 185 // NOTE that native shapes are not added to the mesh list or removed.
186 // Returns 'true' if this is the initial reference to the shape. Otherwise reused.
187 private bool ReferenceShape(BulletShape shape, IMesh meshData)
112 { 188 {
189 bool ret = false;
113 switch (shape.type) 190 switch (shape.type)
114 { 191 {
115 case ShapeData.PhysicsShapeType.SHAPE_MESH: 192 case ShapeData.PhysicsShapeType.SHAPE_MESH:
@@ -118,14 +195,18 @@ public class BSShapeCollection : IDisposable
118 { 195 {
119 // There is an existing instance of this mesh. 196 // There is an existing instance of this mesh.
120 meshDesc.referenceCount++; 197 meshDesc.referenceCount++;
198 DetailLog("{0},BSShapeColliction.ReferenceShape,existingMesh,key={1},cnt={2}",
199 BSScene.DetailLogZero, shape.shapeKey, meshDesc.referenceCount);
121 } 200 }
122 else 201 else
123 { 202 {
124 // This is a new reference to a mesh 203 // This is a new reference to a mesh
125 meshDesc.Ptr = shape.Ptr; 204 meshDesc.Ptr = shape.ptr;
126 meshDesc.meshData = meshData; 205 meshDesc.meshData = meshData;
127 meshDesc.referenceCount = 1; 206 meshDesc.referenceCount = 1;
128 207 DetailLog("{0},BSShapeColliction.ReferenceShape,newMesh,key={1},cnt={2}",
208 BSScene.DetailLogZero, shape.shapeKey, meshDesc.referenceCount);
209 ret = true;
129 } 210 }
130 meshDesc.lastReferenced = System.DateTime.Now; 211 meshDesc.lastReferenced = System.DateTime.Now;
131 Meshes[shape.shapeKey] = meshDesc; 212 Meshes[shape.shapeKey] = meshDesc;
@@ -136,41 +217,68 @@ public class BSShapeCollection : IDisposable
136 { 217 {
137 // There is an existing instance of this mesh. 218 // There is an existing instance of this mesh.
138 hullDesc.referenceCount++; 219 hullDesc.referenceCount++;
220 DetailLog("{0},BSShapeColliction.ReferenceShape,existingHull,key={1},cnt={2}",
221 BSScene.DetailLogZero, shape.shapeKey, hullDesc.referenceCount);
139 } 222 }
140 else 223 else
141 { 224 {
142 // This is a new reference to a mesh 225 // This is a new reference to a hull
143 hullDesc.Ptr = shape.Ptr; 226 hullDesc.Ptr = shape.ptr;
144 hullDesc.referenceCount = 1; 227 hullDesc.referenceCount = 1;
228 DetailLog("{0},BSShapeColliction.ReferenceShape,newHull,key={1},cnt={2}",
229 BSScene.DetailLogZero, shape.shapeKey, hullDesc.referenceCount);
230 ret = true;
145 231
146 } 232 }
147 hullDesc.lastReferenced = System.DateTime.Now; 233 hullDesc.lastReferenced = System.DateTime.Now;
148 Hulls[shape.shapeKey] = hullDesc; 234 Hulls[shape.shapeKey] = hullDesc;
149 break; 235 break;
236 case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN:
237 break;
150 default: 238 default:
239 // Native shapes are not tracked and they don't go into any list
151 break; 240 break;
152 } 241 }
242 return ret;
153 } 243 }
154 244
155 // Release the usage of a shape 245 // Release the usage of a shape
156 public void DereferenceShape(BulletShape shape) 246 private void DereferenceShape(BulletShape shape, bool atTaintTime)
157 { 247 {
158 switch (shape.type) 248 if (shape.ptr == IntPtr.Zero)
249 return;
250
251 BSScene.TaintCallback dereferenceOperation = delegate()
159 { 252 {
160 case ShapeData.PhysicsShapeType.SHAPE_HULL: 253 switch (shape.type)
161 DereferenceHull(shape); 254 {
162 // Hulls also include a mesh 255 case ShapeData.PhysicsShapeType.SHAPE_HULL:
163 DereferenceMesh(shape); 256 DereferenceHull(shape);
164 break; 257 // Hulls also include a mesh
165 case ShapeData.PhysicsShapeType.SHAPE_MESH: 258 DereferenceMesh(shape);
166 DereferenceMesh(shape); 259 break;
167 break; 260 case ShapeData.PhysicsShapeType.SHAPE_MESH:
168 default: 261 DereferenceMesh(shape);
169 break; 262 break;
170 } 263 case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN:
264 break;
265 default:
266 // Native shapes are not tracked and are released immediately
267 if (shape.ptr != IntPtr.Zero & shape.isNativeShape)
268 {
269 BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr);
270 }
271 break;
272 }
273 };
274 if (atTaintTime)
275 dereferenceOperation();
276 else
277 PhysicsScene.TaintedObject("BSShapeCollection.DereferenceShape", dereferenceOperation);
171 } 278 }
172 279
173 // Count down the reference count for a mesh shape 280 // Count down the reference count for a mesh shape
281 // Called at taint-time.
174 private void DereferenceMesh(BulletShape shape) 282 private void DereferenceMesh(BulletShape shape)
175 { 283 {
176 MeshDesc meshDesc; 284 MeshDesc meshDesc;
@@ -180,10 +288,14 @@ public class BSShapeCollection : IDisposable
180 // TODO: release the Bullet storage 288 // TODO: release the Bullet storage
181 meshDesc.lastReferenced = System.DateTime.Now; 289 meshDesc.lastReferenced = System.DateTime.Now;
182 Meshes[shape.shapeKey] = meshDesc; 290 Meshes[shape.shapeKey] = meshDesc;
291 DetailLog("{0},BSShapeColliction.DereferenceMesh,key={1},cnt={2}",
292 BSScene.DetailLogZero, shape.shapeKey, meshDesc.referenceCount);
293
183 } 294 }
184 } 295 }
185 296
186 // Count down the reference count for a hull shape 297 // Count down the reference count for a hull shape
298 // Called at taint-time.
187 private void DereferenceHull(BulletShape shape) 299 private void DereferenceHull(BulletShape shape)
188 { 300 {
189 HullDesc hullDesc; 301 HullDesc hullDesc;
@@ -193,6 +305,8 @@ public class BSShapeCollection : IDisposable
193 // TODO: release the Bullet storage (aging old entries?) 305 // TODO: release the Bullet storage (aging old entries?)
194 hullDesc.lastReferenced = System.DateTime.Now; 306 hullDesc.lastReferenced = System.DateTime.Now;
195 Hulls[shape.shapeKey] = hullDesc; 307 Hulls[shape.shapeKey] = hullDesc;
308 DetailLog("{0},BSShapeColliction.DereferenceHull,key={1},cnt={2}",
309 BSScene.DetailLogZero, shape.shapeKey, hullDesc.referenceCount);
196 } 310 }
197 } 311 }
198 312
@@ -210,10 +324,6 @@ public class BSShapeCollection : IDisposable
210 324
211 BulletShape newShape = new BulletShape(IntPtr.Zero); 325 BulletShape newShape = new BulletShape(IntPtr.Zero);
212 326
213 // If the object is dynamic, it must have a hull shape
214 if (prim.IsPhysical)
215 nativeShapePossible = false;
216
217 // If the prim attributes are simple, this could be a simple Bullet native shape 327 // If the prim attributes are simple, this could be a simple Bullet native shape
218 if (nativeShapePossible 328 if (nativeShapePossible
219 && ((pbs.SculptEntry && !PhysicsScene.ShouldMeshSculptedPrim) 329 && ((pbs.SculptEntry && !PhysicsScene.ShouldMeshSculptedPrim)
@@ -230,8 +340,10 @@ public class BSShapeCollection : IDisposable
230 haveShape = true; 340 haveShape = true;
231 if (forceRebuild || (prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE)) 341 if (forceRebuild || (prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE))
232 { 342 {
233 DetailLog("{0},BSShapeCollection.CreateGeom,sphere (force={1}", prim.LocalID, forceRebuild); 343 newShape = AddNativeShapeToPrim(
234 newShape = AddNativeShapeToPrim(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_SPHERE); 344 prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_SPHERE, ShapeData.FixedShapeKey.KEY_SPHERE);
345 DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}",
346 prim.LocalID, forceRebuild,prim.BSShape);
235 347
236 ret = true; 348 ret = true;
237 } 349 }
@@ -242,71 +354,87 @@ public class BSShapeCollection : IDisposable
242 haveShape = true; 354 haveShape = true;
243 if (forceRebuild || (prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX)) 355 if (forceRebuild || (prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX))
244 { 356 {
245 DetailLog("{0},BSShapeCollection.CreateGeom,box (force={1})", prim.LocalID, forceRebuild); 357 newShape = AddNativeShapeToPrim(
246 newShape = AddNativeShapeToPrim(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_BOX); 358 prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_BOX, ShapeData.FixedShapeKey.KEY_BOX);
359 DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}",
360 prim.LocalID, forceRebuild,prim.BSShape);
247 361
248 ret = true; 362 ret = true;
249 } 363 }
250 } 364 }
251 } 365 }
252 // If a simple shape isn't happening, create a mesh and possibly a hull 366 // If a simple shape is not happening, create a mesh and possibly a hull
367 // Note that if it's a native shape, the check for physical/non-physical is not
368 // made. Native shapes are best used in either case.
253 if (!haveShape) 369 if (!haveShape)
254 { 370 {
255 if (prim.IsPhysical) 371 if (prim.IsPhysical)
256 { 372 {
257 if (forceRebuild || !Hulls.ContainsKey(prim.BSShape.shapeKey)) 373 if (forceRebuild || !Hulls.ContainsKey(shapeData.HullKey))
258 { 374 {
259 // physical objects require a hull for interaction. 375 // physical objects require a hull for interaction.
260 // This also creates the mesh if it doesn't already exist 376 // This also creates the mesh if it doesn't already exist.
261 ret = CreateGeomHull(prim, shapeData, pbs); 377 ret = CreateGeomHull(prim, shapeData, pbs);
262 } 378 }
379 else
380 {
381 prim.BSShape = new BulletShape(Hulls[shapeData.HullKey].Ptr,
382 ShapeData.PhysicsShapeType.SHAPE_HULL);
383 prim.BSShape.shapeKey = shapeData.HullKey;
384 // Another user of this shape.
385 ReferenceShape(prim.BSShape);
386 ret = true;
387 }
263 } 388 }
264 else 389 else
265 { 390 {
266 if (forceRebuild || !Meshes.ContainsKey(prim.BSShape.shapeKey)) 391 if (forceRebuild || !Meshes.ContainsKey(prim.BSShape.shapeKey))
267 { 392 {
268 // Static (non-physical) objects only need a mesh for bumping into 393 // Static (non-physical) objects only need a mesh for bumping into
394 // Returning 'true' means prim.BShape was changed.
269 ret = CreateGeomMesh(prim, shapeData, pbs); 395 ret = CreateGeomMesh(prim, shapeData, pbs);
270 } 396 }
397 else
398 {
399 prim.BSShape = new BulletShape(Hulls[shapeData.MeshKey].Ptr,
400 ShapeData.PhysicsShapeType.SHAPE_MESH);
401 prim.BSShape.shapeKey = shapeData.MeshKey;
402 ReferenceShape(prim.BSShape);
403 ret = true;
404 }
271 } 405 }
272 } 406 }
273 return ret; 407 return ret;
274 } 408 }
275 409
276 private BulletShape AddNativeShapeToPrim(BSPrim prim, ShapeData shapeData, ShapeData.PhysicsShapeType shapeType) 410 // Creates a native shape and assignes it to prim.BSShape
411 private BulletShape AddNativeShapeToPrim(
412 BSPrim prim, ShapeData shapeData, ShapeData.PhysicsShapeType shapeType,
413 ShapeData.FixedShapeKey shapeKey)
277 { 414 {
278 BulletShape newShape; 415 BulletShape newShape;
279 416
280 // Bullet native objects are scaled by the Bullet engine so pass the size in 417 // Bullet native objects are scaled by the Bullet engine so pass the size in
281 prim.Scale = shapeData.Size; 418 prim.Scale = shapeData.Size;
419 shapeData.Type = shapeType;
420 shapeData.Scale = prim.Scale;
282 421
283 // release any previous shape 422 // release any previous shape
284 DereferenceShape(prim.BSShape); 423 DereferenceShape(prim.BSShape, true);
424
425 // Shape of this discriptioin is not allocated. Create new.
426 newShape = new BulletShape(
427 BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, shapeData), shapeType);
428 newShape.shapeKey = (ulong)shapeKey;
429 newShape.isNativeShape = true;
430
431 // Don't to a 'ReferenceShape()' here because native shapes are not tracked.
285 432
286 MeshDesc existingShapeDesc;
287 if (Meshes.TryGetValue(shapeData.MeshKey, out existingShapeDesc))
288 {
289 // If there is an existing allocated shape, use it
290 newShape = new BulletShape(existingShapeDesc.Ptr, shapeType);
291 }
292 else
293 {
294 // Shape of this discriptioin is not allocated. Create new.
295 newShape = new BulletShape(
296 BulletSimAPI.BuildNativeShape2(PhysicsScene.World.Ptr,
297 (float)shapeType,
298 PhysicsScene.Params.collisionMargin,
299 prim.Scale),
300 shapeType);
301 }
302 newShape.shapeKey = shapeData.MeshKey;
303 ReferenceShape(newShape);
304 prim.BSShape = newShape; 433 prim.BSShape = newShape;
305 return newShape; 434 return newShape;
306 } 435 }
307 436
308 // No locking here because this is done when we know physics is not simulating 437 // Returns 'true' of a mesh was actually rebuild.
309 // Returns 'true' of a mesh was actually rebuild (we could also have one of these specs).
310 // Called at taint-time! 438 // Called at taint-time!
311 private bool CreateGeomMesh(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs) 439 private bool CreateGeomMesh(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs)
312 { 440 {
@@ -322,7 +450,6 @@ public class BSShapeCollection : IDisposable
322 lod = PhysicsScene.MeshMegaPrimLOD; 450 lod = PhysicsScene.MeshMegaPrimLOD;
323 451
324 ulong newMeshKey = (ulong)pbs.GetMeshKey(shapeData.Size, lod); 452 ulong newMeshKey = (ulong)pbs.GetMeshKey(shapeData.Size, lod);
325 // m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, LocalID, _meshKey, newMeshKey);
326 453
327 // if this new shape is the same as last time, don't recreate the mesh 454 // if this new shape is the same as last time, don't recreate the mesh
328 if (prim.BSShape.shapeKey == newMeshKey) return false; 455 if (prim.BSShape.shapeKey == newMeshKey) return false;
@@ -330,7 +457,7 @@ public class BSShapeCollection : IDisposable
330 DetailLog("{0},BSShapeCollection.CreateGeomMesh,create,key={1}", prim.LocalID, newMeshKey); 457 DetailLog("{0},BSShapeCollection.CreateGeomMesh,create,key={1}", prim.LocalID, newMeshKey);
331 458
332 // Since we're recreating new, get rid of the reference to the previous shape 459 // Since we're recreating new, get rid of the reference to the previous shape
333 DereferenceShape(prim.BSShape); 460 DereferenceShape(prim.BSShape, true);
334 461
335 IMesh meshData = null; 462 IMesh meshData = null;
336 IntPtr meshPtr; 463 IntPtr meshPtr;
@@ -360,7 +487,7 @@ public class BSShapeCollection : IDisposable
360 // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", 487 // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}",
361 // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count); 488 // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count);
362 489
363 meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.Ptr, 490 meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr,
364 indices.GetLength(0), indices, vertices.Count, verticesAsFloats); 491 indices.GetLength(0), indices, vertices.Count, verticesAsFloats);
365 } 492 }
366 newShape = new BulletShape(meshPtr, ShapeData.PhysicsShapeType.SHAPE_MESH); 493 newShape = new BulletShape(meshPtr, ShapeData.PhysicsShapeType.SHAPE_MESH);
@@ -374,26 +501,29 @@ public class BSShapeCollection : IDisposable
374 return true; // 'true' means a new shape has been added to this prim 501 return true; // 'true' means a new shape has been added to this prim
375 } 502 }
376 503
377 // No locking here because this is done when we know physics is not simulating
378 // Returns 'true' of a mesh was actually rebuild (we could also have one of these specs). 504 // Returns 'true' of a mesh was actually rebuild (we could also have one of these specs).
379 List<ConvexResult> m_hulls; 505 List<ConvexResult> m_hulls;
380 private bool CreateGeomHull(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs) 506 private bool CreateGeomHull(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs)
381 { 507 {
382 BulletShape newShape; 508 BulletShape newShape;
383 509
510 // Level of detail for the mesh can be different for sculpties and regular meshes.
384 float lod = pbs.SculptEntry ? PhysicsScene.SculptLOD : PhysicsScene.MeshLOD; 511 float lod = pbs.SculptEntry ? PhysicsScene.SculptLOD : PhysicsScene.MeshLOD;
512
385 ulong newHullKey = (ulong)pbs.GetMeshKey(shapeData.Size, lod); 513 ulong newHullKey = (ulong)pbs.GetMeshKey(shapeData.Size, lod);
386 // m_log.DebugFormat("{0}: CreateGeomHull: lID={1}, oldKey={2}, newKey={3}", LogHeader, LocalID, _hullKey, newHullKey);
387 514
388 // if the hull hasn't changed, don't rebuild it 515 // if the hull hasn't changed, don't rebuild it
389 if (newHullKey == prim.BSShape.shapeKey) return false; 516 if (newHullKey == prim.BSShape.shapeKey) return false;
390 517
391 DetailLog("{0},BSShapeCollection.CreateGeomHull,create,oldKey={1},newKey={2}", prim.LocalID, newHullKey, newHullKey); 518 DetailLog("{0},BSShapeCollection.CreateGeomHull,create,oldKey={1},newKey={2}", prim.LocalID, newHullKey, newHullKey);
392 519
393 // remove references to any previous shape 520 // Remove references to the previous shape. Also removes reference to underlying mesh.
394 DereferenceShape(prim.BSShape); 521 DereferenceShape(prim.BSShape, true);
395 522
396 // Make sure the underlying mesh exists and is correct 523 // Do not let the mesh dereference itself again. Was done in the above DerefereceShape().
524 prim.BSShape.type = ShapeData.PhysicsShapeType.SHAPE_UNKNOWN;
525
526 // Make sure the underlying mesh exists and is correct.
397 // Since we're in the hull code, we know CreateGeomMesh() will not create a native shape. 527 // Since we're in the hull code, we know CreateGeomMesh() will not create a native shape.
398 CreateGeomMesh(prim, shapeData, pbs); 528 CreateGeomMesh(prim, shapeData, pbs);
399 MeshDesc meshDesc = Meshes[newHullKey]; 529 MeshDesc meshDesc = Meshes[newHullKey];
@@ -402,10 +532,12 @@ public class BSShapeCollection : IDisposable
402 HullDesc hullDesc; 532 HullDesc hullDesc;
403 if (Hulls.TryGetValue(newHullKey, out hullDesc)) 533 if (Hulls.TryGetValue(newHullKey, out hullDesc))
404 { 534 {
535 // If the hull shape already is created, just use it.
405 hullPtr = hullDesc.Ptr; 536 hullPtr = hullDesc.Ptr;
406 } 537 }
407 else 538 else
408 { 539 {
540 // Build a new hull in the physical world
409 int[] indices = meshDesc.meshData.getIndexListAsInt(); 541 int[] indices = meshDesc.meshData.getIndexListAsInt();
410 List<OMV.Vector3> vertices = meshDesc.meshData.getVertexList(); 542 List<OMV.Vector3> vertices = meshDesc.meshData.getVertexList();
411 543
@@ -485,63 +617,85 @@ public class BSShapeCollection : IDisposable
485 } 617 }
486 // create the hull data structure in Bullet 618 // create the hull data structure in Bullet
487 // m_log.DebugFormat("{0}: CreateGeom: calling CreateHull. lid={1}, key={2}, hulls={3}", LogHeader, LocalID, _hullKey, hullCount); 619 // m_log.DebugFormat("{0}: CreateGeom: calling CreateHull. lid={1}, key={2}, hulls={3}", LogHeader, LocalID, _hullKey, hullCount);
488 hullPtr = BulletSimAPI.CreateHullShape2(PhysicsScene.World.Ptr, hullCount, convHulls); 620 hullPtr = BulletSimAPI.CreateHullShape2(PhysicsScene.World.ptr, hullCount, convHulls);
489 } 621 }
622
490 newShape = new BulletShape(hullPtr, ShapeData.PhysicsShapeType.SHAPE_HULL); 623 newShape = new BulletShape(hullPtr, ShapeData.PhysicsShapeType.SHAPE_HULL);
491 newShape.shapeKey = newHullKey; 624 newShape.shapeKey = newHullKey;
625 newShape.meshPtr = meshDesc.Ptr;
492 626
493 ReferenceShape(newShape); 627 ReferenceShape(newShape);
494 628
495 // meshes are already scaled by the meshmerizer 629 // meshes and hulls are already scaled by the meshmerizer
496 prim.Scale = new OMV.Vector3(1f, 1f, 1f); 630 prim.Scale = new OMV.Vector3(1f, 1f, 1f);
497 prim.BSShape = newShape; 631 prim.BSShape = newShape;
498 return true; // 'true' means a new shape has been added to this prim 632 return true; // 'true' means a new shape has been added to this prim
499 } 633 }
500 634
501 // Callback from convex hull creater with a newly created hull. 635 // Callback from convex hull creater with a newly created hull.
502 // Just add it to the collection of hulls for this shape. 636 // Just add it to our collection of hulls for this shape.
503 private void HullReturn(ConvexResult result) 637 private void HullReturn(ConvexResult result)
504 { 638 {
505 m_hulls.Add(result); 639 m_hulls.Add(result);
506 return; 640 return;
507 } 641 }
508 642
509 // Create an object in Bullet if it has not already been created 643 // Create an object in Bullet if it has not already been created.
510 // No locking here because this is done when the physics engine is not simulating 644 // Updates prim.BSBody with the information about the new body if one is created.
511 // Returns 'true' if an object was actually created. 645 // Returns 'true' if an object was actually created.
512 private bool CreateObject(bool forceRebuild, BSPrim prim, BulletSim sim, BulletShape shape, ShapeData shapeData) 646 // Called at taint-time.
647 private bool CreateBody(bool forceRebuild, BSPrim prim, BulletSim sim, BulletShape shape, ShapeData shapeData)
513 { 648 {
514 // the mesh or hull must have already been created in Bullet 649 bool ret = false;
515 // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, LocalID, shape.Type);
516 650
517 DereferenceBody(prim.BSBody); 651 // the mesh, hull or native shape must have already been created in Bullet
652 bool mustRebuild = (prim.BSBody.ptr == IntPtr.Zero);
518 653
519 BulletBody aBody; 654 // If there is an existing body, verify it's of an acceptable type.
520 IntPtr bodyPtr = IntPtr.Zero; 655 // If not a solid object, body is a GhostObject. Otherwise a RigidBody.
521 if (prim.IsSolid) 656 if (!mustRebuild)
522 { 657 {
523 bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.Ptr, shape.Ptr, shapeData.Position, shapeData.Rotation); 658 CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(prim.BSBody.ptr);
659 if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY
660 || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT)
661 {
662 // If the collisionObject is not the correct type for solidness, rebuild what's there
663 mustRebuild = true;
664 }
665
524 } 666 }
525 else 667
668 if (mustRebuild)
526 { 669 {
527 bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.Ptr, shape.Ptr, shapeData.Position, shapeData.Rotation); 670 DereferenceBody(prim.BSBody, true);
528 } 671
529 aBody = new BulletBody(shapeData.ID, bodyPtr); 672 BulletBody aBody;
673 IntPtr bodyPtr = IntPtr.Zero;
674 if (prim.IsSolid)
675 {
676 bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr, shapeData.Position, shapeData.Rotation);
677 DetailLog("{0},BSShapeCollection.CreateObject,mesh,ptr={1:X}", prim.LocalID, bodyPtr);
678 }
679 else
680 {
681 bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr, shapeData.Position, shapeData.Rotation);
682 DetailLog("{0},BSShapeCollection.CreateObject,ghost,ptr={1:X}", prim.LocalID, bodyPtr);
683 }
684 aBody = new BulletBody(shapeData.ID, bodyPtr);
685
686 ReferenceBody(aBody, true);
687
688 prim.BSBody = aBody;
530 689
531 ReferenceBody(aBody); 690 ret = true;
691 }
532 692
533 prim.BSBody = aBody; 693 return ret;
534 return true;
535 } 694 }
536 695
537 private void DetailLog(string msg, params Object[] args) 696 private void DetailLog(string msg, params Object[] args)
538 { 697 {
539 PhysicsScene.PhysicsLogging.Write(msg, args); 698 PhysicsScene.PhysicsLogging.Write(msg, args);
540 } 699 }
541
542
543
544
545
546} 700}
547} 701}