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.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}