diff options
Diffstat (limited to 'OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs')
-rwxr-xr-x | OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs | 558 |
1 files changed, 334 insertions, 224 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 892c34b..220fbbc 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"); |
@@ -109,8 +116,7 @@ public sealed class BSShapeCollection : IDisposable | |||
109 | // rebuild the body around it. | 116 | // rebuild the body around it. |
110 | // Updates prim.BSBody with information/pointers to requested body | 117 | // Updates prim.BSBody with information/pointers to requested body |
111 | // Returns 'true' if BSBody was changed. | 118 | // Returns 'true' if BSBody was changed. |
112 | bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, | 119 | bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, bodyCallback); |
113 | prim.PhysShape, bodyCallback); | ||
114 | ret = newGeom || newBody; | 120 | ret = newGeom || newBody; |
115 | } | 121 | } |
116 | DetailLog("{0},BSShapeCollection.GetBodyAndShape,taintExit,force={1},ret={2},body={3},shape={4}", | 122 | DetailLog("{0},BSShapeCollection.GetBodyAndShape,taintExit,force={1},ret={2},body={3},shape={4}", |
@@ -119,51 +125,52 @@ public sealed class BSShapeCollection : IDisposable | |||
119 | return ret; | 125 | return ret; |
120 | } | 126 | } |
121 | 127 | ||
128 | public bool GetBodyAndShape(bool forceRebuild, BulletWorld sim, BSPhysObject prim) | ||
129 | { | ||
130 | return GetBodyAndShape(forceRebuild, sim, prim, null, null); | ||
131 | } | ||
132 | |||
122 | // Track another user of a body. | 133 | // Track another user of a body. |
123 | // We presume the caller has allocated the body. | 134 | // 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. | 135 | // Bodies only have one user so the body is just put into the world if not already there. |
125 | public void ReferenceBody(BulletBody body, bool inTaintTime) | 136 | private void ReferenceBody(BulletBody body) |
126 | { | 137 | { |
127 | lock (m_collectionActivityLock) | 138 | lock (m_collectionActivityLock) |
128 | { | 139 | { |
129 | DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body); | 140 | if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body); |
130 | PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.ReferenceBody", delegate() | 141 | if (!PhysicsScene.PE.IsInWorld(PhysicsScene.World, body)) |
131 | { | 142 | { |
132 | if (!BulletSimAPI.IsInWorld2(body.ptr)) | 143 | PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, body); |
133 | { | 144 | if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body); |
134 | BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr); | 145 | } |
135 | DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body); | ||
136 | } | ||
137 | }); | ||
138 | } | 146 | } |
139 | } | 147 | } |
140 | 148 | ||
141 | // Release the usage of a body. | 149 | // Release the usage of a body. |
142 | // Called when releasing use of a BSBody. BSShape is handled separately. | 150 | // Called when releasing use of a BSBody. BSShape is handled separately. |
143 | public void DereferenceBody(BulletBody body, bool inTaintTime, BodyDestructionCallback bodyCallback ) | 151 | // Called in taint time. |
152 | public void DereferenceBody(BulletBody body, BodyDestructionCallback bodyCallback ) | ||
144 | { | 153 | { |
145 | if (body.ptr == IntPtr.Zero) | 154 | if (!body.HasPhysicalBody) |
146 | return; | 155 | return; |
147 | 156 | ||
157 | PhysicsScene.AssertInTaintTime("BSShapeCollection.DereferenceBody"); | ||
158 | |||
148 | lock (m_collectionActivityLock) | 159 | lock (m_collectionActivityLock) |
149 | { | 160 | { |
150 | PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceBody", delegate() | 161 | if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1}", body.ID, body); |
151 | { | 162 | // If the caller needs to know the old body is going away, pass the event up. |
152 | DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1},inTaintTime={2}", | 163 | if (bodyCallback != null) bodyCallback(body); |
153 | body.ID, body, inTaintTime); | ||
154 | // If the caller needs to know the old body is going away, pass the event up. | ||
155 | if (bodyCallback != null) bodyCallback(body); | ||
156 | 164 | ||
157 | if (BulletSimAPI.IsInWorld2(body.ptr)) | 165 | if (PhysicsScene.PE.IsInWorld(PhysicsScene.World, body)) |
158 | { | 166 | { |
159 | BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr); | 167 | PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, body); |
160 | DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body); | 168 | if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body); |
161 | } | 169 | } |
162 | 170 | ||
163 | // Zero any reference to the shape so it is not freed when the body is deleted. | 171 | // 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); | 172 | PhysicsScene.PE.SetCollisionShape(PhysicsScene.World, body, null); |
165 | BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr); | 173 | PhysicsScene.PE.DestroyObject(PhysicsScene.World, body); |
166 | }); | ||
167 | } | 174 | } |
168 | } | 175 | } |
169 | 176 | ||
@@ -184,17 +191,17 @@ public sealed class BSShapeCollection : IDisposable | |||
184 | { | 191 | { |
185 | // There is an existing instance of this mesh. | 192 | // There is an existing instance of this mesh. |
186 | meshDesc.referenceCount++; | 193 | meshDesc.referenceCount++; |
187 | DetailLog("{0},BSShapeCollection.ReferenceShape,existingMesh,key={1},cnt={2}", | 194 | if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,existingMesh,key={1},cnt={2}", |
188 | BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); | 195 | BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); |
189 | } | 196 | } |
190 | else | 197 | else |
191 | { | 198 | { |
192 | // This is a new reference to a mesh | 199 | // This is a new reference to a mesh |
193 | meshDesc.ptr = shape.ptr; | 200 | meshDesc.shape = shape.Clone(); |
194 | meshDesc.shapeKey = shape.shapeKey; | 201 | meshDesc.shapeKey = shape.shapeKey; |
195 | // We keep a reference to the underlying IMesh data so a hull can be built | 202 | // We keep a reference to the underlying IMesh data so a hull can be built |
196 | meshDesc.referenceCount = 1; | 203 | meshDesc.referenceCount = 1; |
197 | DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}", | 204 | if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}", |
198 | BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); | 205 | BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); |
199 | ret = true; | 206 | ret = true; |
200 | } | 207 | } |
@@ -207,16 +214,16 @@ public sealed class BSShapeCollection : IDisposable | |||
207 | { | 214 | { |
208 | // There is an existing instance of this hull. | 215 | // There is an existing instance of this hull. |
209 | hullDesc.referenceCount++; | 216 | hullDesc.referenceCount++; |
210 | DetailLog("{0},BSShapeCollection.ReferenceShape,existingHull,key={1},cnt={2}", | 217 | if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,existingHull,key={1},cnt={2}", |
211 | BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); | 218 | BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); |
212 | } | 219 | } |
213 | else | 220 | else |
214 | { | 221 | { |
215 | // This is a new reference to a hull | 222 | // This is a new reference to a hull |
216 | hullDesc.ptr = shape.ptr; | 223 | hullDesc.shape = shape.Clone(); |
217 | hullDesc.shapeKey = shape.shapeKey; | 224 | hullDesc.shapeKey = shape.shapeKey; |
218 | hullDesc.referenceCount = 1; | 225 | hullDesc.referenceCount = 1; |
219 | DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}", | 226 | if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}", |
220 | BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); | 227 | BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); |
221 | ret = true; | 228 | ret = true; |
222 | 229 | ||
@@ -234,44 +241,43 @@ public sealed class BSShapeCollection : IDisposable | |||
234 | } | 241 | } |
235 | 242 | ||
236 | // Release the usage of a shape. | 243 | // Release the usage of a shape. |
237 | public void DereferenceShape(BulletShape shape, bool inTaintTime, ShapeDestructionCallback shapeCallback) | 244 | public void DereferenceShape(BulletShape shape, ShapeDestructionCallback shapeCallback) |
238 | { | 245 | { |
239 | if (shape.ptr == IntPtr.Zero) | 246 | if (!shape.HasPhysicalShape) |
240 | return; | 247 | return; |
241 | 248 | ||
242 | PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceShape", delegate() | 249 | PhysicsScene.AssertInTaintTime("BSShapeCollection.DereferenceShape"); |
250 | |||
251 | if (shape.HasPhysicalShape) | ||
243 | { | 252 | { |
244 | if (shape.ptr != IntPtr.Zero) | 253 | if (shape.isNativeShape) |
245 | { | 254 | { |
246 | if (shape.isNativeShape) | 255 | // Native shapes are not tracked and are released immediately |
247 | { | 256 | if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1}", |
248 | // Native shapes are not tracked and are released immediately | 257 | BSScene.DetailLogZero, shape.AddrString); |
249 | DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}", | 258 | if (shapeCallback != null) shapeCallback(shape); |
250 | BSScene.DetailLogZero, shape.ptr.ToString("X"), inTaintTime); | 259 | PhysicsScene.PE.DeleteCollisionShape(PhysicsScene.World, shape); |
251 | if (shapeCallback != null) shapeCallback(shape); | 260 | } |
252 | BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); | 261 | else |
253 | } | 262 | { |
254 | else | 263 | switch (shape.type) |
255 | { | 264 | { |
256 | switch (shape.type) | 265 | case BSPhysicsShapeType.SHAPE_HULL: |
257 | { | 266 | DereferenceHull(shape, shapeCallback); |
258 | case BSPhysicsShapeType.SHAPE_HULL: | 267 | break; |
259 | DereferenceHull(shape, shapeCallback); | 268 | case BSPhysicsShapeType.SHAPE_MESH: |
260 | break; | 269 | DereferenceMesh(shape, shapeCallback); |
261 | case BSPhysicsShapeType.SHAPE_MESH: | 270 | break; |
262 | DereferenceMesh(shape, shapeCallback); | 271 | case BSPhysicsShapeType.SHAPE_COMPOUND: |
263 | break; | 272 | DereferenceCompound(shape, shapeCallback); |
264 | case BSPhysicsShapeType.SHAPE_COMPOUND: | 273 | break; |
265 | DereferenceCompound(shape, shapeCallback); | 274 | case BSPhysicsShapeType.SHAPE_UNKNOWN: |
266 | break; | 275 | break; |
267 | case BSPhysicsShapeType.SHAPE_UNKNOWN: | 276 | default: |
268 | break; | 277 | break; |
269 | default: | ||
270 | break; | ||
271 | } | ||
272 | } | 278 | } |
273 | } | 279 | } |
274 | }); | 280 | } |
275 | } | 281 | } |
276 | 282 | ||
277 | // Count down the reference count for a mesh shape | 283 | // Count down the reference count for a mesh shape |
@@ -286,7 +292,7 @@ public sealed class BSShapeCollection : IDisposable | |||
286 | if (shapeCallback != null) shapeCallback(shape); | 292 | if (shapeCallback != null) shapeCallback(shape); |
287 | meshDesc.lastReferenced = System.DateTime.Now; | 293 | meshDesc.lastReferenced = System.DateTime.Now; |
288 | Meshes[shape.shapeKey] = meshDesc; | 294 | Meshes[shape.shapeKey] = meshDesc; |
289 | DetailLog("{0},BSShapeCollection.DereferenceMesh,shape={1},refCnt={2}", | 295 | if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceMesh,shape={1},refCnt={2}", |
290 | BSScene.DetailLogZero, shape, meshDesc.referenceCount); | 296 | BSScene.DetailLogZero, shape, meshDesc.referenceCount); |
291 | 297 | ||
292 | } | 298 | } |
@@ -307,7 +313,7 @@ public sealed class BSShapeCollection : IDisposable | |||
307 | 313 | ||
308 | hullDesc.lastReferenced = System.DateTime.Now; | 314 | hullDesc.lastReferenced = System.DateTime.Now; |
309 | Hulls[shape.shapeKey] = hullDesc; | 315 | Hulls[shape.shapeKey] = hullDesc; |
310 | DetailLog("{0},BSShapeCollection.DereferenceHull,shape={1},refCnt={2}", | 316 | if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceHull,shape={1},refCnt={2}", |
311 | BSScene.DetailLogZero, shape, hullDesc.referenceCount); | 317 | BSScene.DetailLogZero, shape, hullDesc.referenceCount); |
312 | } | 318 | } |
313 | } | 319 | } |
@@ -320,57 +326,56 @@ public sealed class BSShapeCollection : IDisposable | |||
320 | // Called at taint-time. | 326 | // Called at taint-time. |
321 | private void DereferenceCompound(BulletShape shape, ShapeDestructionCallback shapeCallback) | 327 | private void DereferenceCompound(BulletShape shape, ShapeDestructionCallback shapeCallback) |
322 | { | 328 | { |
323 | if (!BulletSimAPI.IsCompound2(shape.ptr)) | 329 | if (!PhysicsScene.PE.IsCompound(shape)) |
324 | { | 330 | { |
325 | // Failed the sanity check!! | 331 | // Failed the sanity check!! |
326 | PhysicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}", | 332 | 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")); | 333 | LogHeader, shape.type, shape.AddrString); |
328 | DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}", | 334 | if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}", |
329 | BSScene.DetailLogZero, shape.type, shape.ptr.ToString("X")); | 335 | BSScene.DetailLogZero, shape.type, shape.AddrString); |
330 | return; | 336 | return; |
331 | } | 337 | } |
332 | 338 | ||
333 | int numChildren = BulletSimAPI.GetNumberOfCompoundChildren2(shape.ptr); | 339 | int numChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(shape); |
334 | DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}", BSScene.DetailLogZero, shape, numChildren); | 340 | if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}", BSScene.DetailLogZero, shape, numChildren); |
335 | 341 | ||
336 | for (int ii = numChildren - 1; ii >= 0; ii--) | 342 | for (int ii = numChildren - 1; ii >= 0; ii--) |
337 | { | 343 | { |
338 | IntPtr childShape = BulletSimAPI.RemoveChildShapeFromCompoundShapeIndex2(shape.ptr, ii); | 344 | BulletShape childShape = PhysicsScene.PE.RemoveChildShapeFromCompoundShapeIndex(shape, ii); |
339 | DereferenceAnonCollisionShape(childShape); | 345 | DereferenceAnonCollisionShape(childShape); |
340 | } | 346 | } |
341 | BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); | 347 | PhysicsScene.PE.DeleteCollisionShape(PhysicsScene.World, shape); |
342 | } | 348 | } |
343 | 349 | ||
344 | // Sometimes we have a pointer to a collision shape but don't know what type it is. | 350 | // 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. | 351 | // Figure out type and call the correct dereference routine. |
346 | // Called at taint-time. | 352 | // Called at taint-time. |
347 | private void DereferenceAnonCollisionShape(IntPtr cShape) | 353 | private void DereferenceAnonCollisionShape(BulletShape shapeInfo) |
348 | { | 354 | { |
349 | MeshDesc meshDesc; | 355 | MeshDesc meshDesc; |
350 | HullDesc hullDesc; | 356 | HullDesc hullDesc; |
351 | 357 | ||
352 | BulletShape shapeInfo = new BulletShape(cShape); | 358 | if (TryGetMeshByPtr(shapeInfo, out meshDesc)) |
353 | if (TryGetMeshByPtr(cShape, out meshDesc)) | ||
354 | { | 359 | { |
355 | shapeInfo.type = BSPhysicsShapeType.SHAPE_MESH; | 360 | shapeInfo.type = BSPhysicsShapeType.SHAPE_MESH; |
356 | shapeInfo.shapeKey = meshDesc.shapeKey; | 361 | shapeInfo.shapeKey = meshDesc.shapeKey; |
357 | } | 362 | } |
358 | else | 363 | else |
359 | { | 364 | { |
360 | if (TryGetHullByPtr(cShape, out hullDesc)) | 365 | if (TryGetHullByPtr(shapeInfo, out hullDesc)) |
361 | { | 366 | { |
362 | shapeInfo.type = BSPhysicsShapeType.SHAPE_HULL; | 367 | shapeInfo.type = BSPhysicsShapeType.SHAPE_HULL; |
363 | shapeInfo.shapeKey = hullDesc.shapeKey; | 368 | shapeInfo.shapeKey = hullDesc.shapeKey; |
364 | } | 369 | } |
365 | else | 370 | else |
366 | { | 371 | { |
367 | if (BulletSimAPI.IsCompound2(cShape)) | 372 | if (PhysicsScene.PE.IsCompound(shapeInfo)) |
368 | { | 373 | { |
369 | shapeInfo.type = BSPhysicsShapeType.SHAPE_COMPOUND; | 374 | shapeInfo.type = BSPhysicsShapeType.SHAPE_COMPOUND; |
370 | } | 375 | } |
371 | else | 376 | else |
372 | { | 377 | { |
373 | if (BulletSimAPI.IsNativeShape2(cShape)) | 378 | if (PhysicsScene.PE.IsNativeShape(shapeInfo)) |
374 | { | 379 | { |
375 | shapeInfo.isNativeShape = true; | 380 | shapeInfo.isNativeShape = true; |
376 | shapeInfo.type = BSPhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter) | 381 | shapeInfo.type = BSPhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter) |
@@ -379,16 +384,16 @@ public sealed class BSShapeCollection : IDisposable | |||
379 | } | 384 | } |
380 | } | 385 | } |
381 | 386 | ||
382 | DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo); | 387 | if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo); |
383 | 388 | ||
384 | if (shapeInfo.type != BSPhysicsShapeType.SHAPE_UNKNOWN) | 389 | if (shapeInfo.type != BSPhysicsShapeType.SHAPE_UNKNOWN) |
385 | { | 390 | { |
386 | DereferenceShape(shapeInfo, true, null); | 391 | DereferenceShape(shapeInfo, null); |
387 | } | 392 | } |
388 | else | 393 | else |
389 | { | 394 | { |
390 | PhysicsScene.Logger.ErrorFormat("{0} Could not decypher shape type. Region={1}, addr={2}", | 395 | PhysicsScene.Logger.ErrorFormat("{0} Could not decypher shape type. Region={1}, addr={2}", |
391 | LogHeader, PhysicsScene.RegionName, cShape.ToString("X")); | 396 | LogHeader, PhysicsScene.RegionName, shapeInfo.AddrString); |
392 | } | 397 | } |
393 | } | 398 | } |
394 | 399 | ||
@@ -408,19 +413,18 @@ public sealed class BSShapeCollection : IDisposable | |||
408 | if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_CAPSULE) | 413 | if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_CAPSULE) |
409 | { | 414 | { |
410 | // an avatar capsule is close to a native shape (it is not shared) | 415 | // an avatar capsule is close to a native shape (it is not shared) |
411 | ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_CAPSULE, | 416 | GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_CAPSULE, FixedShapeKey.KEY_CAPSULE, shapeCallback); |
412 | FixedShapeKey.KEY_CAPSULE, shapeCallback); | 417 | 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; | 418 | ret = true; |
415 | haveShape = true; | 419 | haveShape = true; |
416 | } | 420 | } |
417 | 421 | ||
418 | // Compound shapes are handled special as they are rebuilt from scratch. | 422 | // 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. | 423 | // 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) | 424 | if (!haveShape && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND) |
421 | { | 425 | { |
422 | ret = GetReferenceToCompoundShape(prim, shapeCallback); | 426 | ret = GetReferenceToCompoundShape(prim, shapeCallback); |
423 | DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape); | 427 | if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape); |
424 | haveShape = true; | 428 | haveShape = true; |
425 | } | 429 | } |
426 | 430 | ||
@@ -432,8 +436,9 @@ public sealed class BSShapeCollection : IDisposable | |||
432 | return ret; | 436 | return ret; |
433 | } | 437 | } |
434 | 438 | ||
435 | // Create a mesh/hull shape or a native shape if 'nativeShapePossible' is 'true'. | 439 | // Create a mesh, hull or native shape. |
436 | private bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback) | 440 | // Return 'true' if the prim's shape was changed. |
441 | public bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback) | ||
437 | { | 442 | { |
438 | bool ret = false; | 443 | bool ret = false; |
439 | bool haveShape = false; | 444 | bool haveShape = false; |
@@ -442,46 +447,48 @@ public sealed class BSShapeCollection : IDisposable | |||
442 | 447 | ||
443 | // If the prim attributes are simple, this could be a simple Bullet native shape | 448 | // If the prim attributes are simple, this could be a simple Bullet native shape |
444 | if (!haveShape | 449 | if (!haveShape |
445 | && pbs != null | ||
446 | && nativeShapePossible | 450 | && nativeShapePossible |
447 | && ((pbs.SculptEntry && !PhysicsScene.ShouldMeshSculptedPrim) | 451 | && pbs != null |
448 | || (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0 | 452 | && !pbs.SculptEntry |
449 | && pbs.ProfileHollow == 0 | 453 | && ((pbs.SculptEntry && !BSParam.ShouldMeshSculptedPrim) || PrimHasNoCuts(pbs)) ) |
450 | && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0 | 454 | { |
451 | && pbs.PathBegin == 0 && pbs.PathEnd == 0 | 455 | // Get the scale of any existing shape so we can see if the new shape is same native type and same size. |
452 | && pbs.PathTaperX == 0 && pbs.PathTaperY == 0 | 456 | OMV.Vector3 scaleOfExistingShape = OMV.Vector3.Zero; |
453 | && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 | 457 | if (prim.PhysShape.HasPhysicalShape) |
454 | && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) ) | 458 | scaleOfExistingShape = PhysicsScene.PE.GetLocalScaling(prim.PhysShape); |
455 | { | 459 | |
456 | // It doesn't look like Bullet scales spheres so make sure the scales are all equal | 460 | if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,maybeNative,force={1},primScale={2},primSize={3},primShape={4}", |
461 | prim.LocalID, forceRebuild, prim.Scale, prim.Size, prim.PhysShape.type); | ||
462 | |||
463 | // 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) | 464 | if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) |
458 | && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z) | 465 | && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z) |
459 | { | 466 | { |
460 | haveShape = true; | 467 | haveShape = true; |
461 | if (forceRebuild | 468 | if (forceRebuild |
462 | || prim.Scale != prim.Size | 469 | || prim.Scale != scaleOfExistingShape |
463 | || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_SPHERE | 470 | || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_SPHERE |
464 | ) | 471 | ) |
465 | { | 472 | { |
466 | ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_SPHERE, | 473 | ret = GetReferenceToNativeShape(prim, BSPhysicsShapeType.SHAPE_SPHERE, |
467 | FixedShapeKey.KEY_SPHERE, shapeCallback); | 474 | FixedShapeKey.KEY_SPHERE, shapeCallback); |
468 | DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}", | ||
469 | prim.LocalID, forceRebuild, prim.PhysShape); | ||
470 | } | 475 | } |
476 | if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},rebuilt={2},shape={3}", | ||
477 | prim.LocalID, forceRebuild, ret, prim.PhysShape); | ||
471 | } | 478 | } |
472 | if (!haveShape && pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) | 479 | if (!haveShape && pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) |
473 | { | 480 | { |
474 | haveShape = true; | 481 | haveShape = true; |
475 | if (forceRebuild | 482 | if (forceRebuild |
476 | || prim.Scale != prim.Size | 483 | || prim.Scale != scaleOfExistingShape |
477 | || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_BOX | 484 | || prim.PhysShape.type != BSPhysicsShapeType.SHAPE_BOX |
478 | ) | 485 | ) |
479 | { | 486 | { |
480 | ret = GetReferenceToNativeShape( prim, BSPhysicsShapeType.SHAPE_BOX, | 487 | ret = GetReferenceToNativeShape( prim, BSPhysicsShapeType.SHAPE_BOX, |
481 | FixedShapeKey.KEY_BOX, shapeCallback); | 488 | FixedShapeKey.KEY_BOX, shapeCallback); |
482 | DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}", | ||
483 | prim.LocalID, forceRebuild, prim.PhysShape); | ||
484 | } | 489 | } |
490 | if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},rebuilt={2},shape={3}", | ||
491 | prim.LocalID, forceRebuild, ret, prim.PhysShape); | ||
485 | } | 492 | } |
486 | } | 493 | } |
487 | 494 | ||
@@ -494,23 +501,36 @@ public sealed class BSShapeCollection : IDisposable | |||
494 | return ret; | 501 | return ret; |
495 | } | 502 | } |
496 | 503 | ||
504 | // return 'true' if this shape description does not include any cutting or twisting. | ||
505 | private bool PrimHasNoCuts(PrimitiveBaseShape pbs) | ||
506 | { | ||
507 | return pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0 | ||
508 | && pbs.ProfileHollow == 0 | ||
509 | && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0 | ||
510 | && pbs.PathBegin == 0 && pbs.PathEnd == 0 | ||
511 | && pbs.PathTaperX == 0 && pbs.PathTaperY == 0 | ||
512 | && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 | ||
513 | && pbs.PathShearX == 0 && pbs.PathShearY == 0; | ||
514 | } | ||
515 | |||
516 | // return 'true' if the prim's shape was changed. | ||
497 | public bool CreateGeomMeshOrHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback) | 517 | public bool CreateGeomMeshOrHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback) |
498 | { | 518 | { |
499 | 519 | ||
500 | bool ret = false; | 520 | bool ret = false; |
501 | // Note that if it's a native shape, the check for physical/non-physical is not | 521 | // Note that if it's a native shape, the check for physical/non-physical is not |
502 | // made. Native shapes work in either case. | 522 | // made. Native shapes work in either case. |
503 | if (prim.IsPhysical && PhysicsScene.ShouldUseHullsForPhysicalObjects) | 523 | if (prim.IsPhysical && BSParam.ShouldUseHullsForPhysicalObjects) |
504 | { | 524 | { |
505 | // Update prim.BSShape to reference a hull of this shape. | 525 | // Update prim.BSShape to reference a hull of this shape. |
506 | ret = GetReferenceToHull(prim,shapeCallback); | 526 | ret = GetReferenceToHull(prim, shapeCallback); |
507 | DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}", | 527 | if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}", |
508 | prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); | 528 | prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); |
509 | } | 529 | } |
510 | else | 530 | else |
511 | { | 531 | { |
512 | ret = GetReferenceToMesh(prim, shapeCallback); | 532 | ret = GetReferenceToMesh(prim, shapeCallback); |
513 | DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}", | 533 | if (DDetail) DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}", |
514 | prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); | 534 | prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); |
515 | } | 535 | } |
516 | return ret; | 536 | return ret; |
@@ -523,14 +543,15 @@ public sealed class BSShapeCollection : IDisposable | |||
523 | ShapeDestructionCallback shapeCallback) | 543 | ShapeDestructionCallback shapeCallback) |
524 | { | 544 | { |
525 | // release any previous shape | 545 | // release any previous shape |
526 | DereferenceShape(prim.PhysShape, true, shapeCallback); | 546 | DereferenceShape(prim.PhysShape, shapeCallback); |
527 | 547 | ||
528 | BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey); | 548 | BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey); |
529 | 549 | ||
530 | // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. | 550 | // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. |
531 | DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}", | 551 | if (DDetail) DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}", |
532 | prim.LocalID, newShape, prim.Scale); | 552 | prim.LocalID, newShape, prim.Scale); |
533 | 553 | ||
554 | // native shapes are scaled by Bullet | ||
534 | prim.PhysShape = newShape; | 555 | prim.PhysShape = newShape; |
535 | return true; | 556 | return true; |
536 | } | 557 | } |
@@ -550,20 +571,17 @@ public sealed class BSShapeCollection : IDisposable | |||
550 | 571 | ||
551 | if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE) | 572 | if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE) |
552 | { | 573 | { |
553 | // The proper scale has been calculated in the prim. | 574 | |
554 | newShape = new BulletShape( | 575 | newShape = PhysicsScene.PE.BuildCapsuleShape(PhysicsScene.World, 1f, 1f, prim.Scale); |
555 | BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, prim.Scale) | 576 | if (DDetail) DetailLog("{0},BSShapeCollection.BuildPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale); |
556 | , shapeType); | ||
557 | DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale); | ||
558 | } | 577 | } |
559 | else | 578 | else |
560 | { | 579 | { |
561 | // Native shapes are scaled in Bullet so set the scaling to the size | 580 | // Native shapes are scaled in Bullet so set the scaling to the size |
562 | prim.Scale = prim.Size; | 581 | newShape = PhysicsScene.PE.BuildNativeShape(PhysicsScene.World, nativeShapeData); |
563 | nativeShapeData.Scale = prim.Scale; | 582 | |
564 | newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, nativeShapeData), shapeType); | ||
565 | } | 583 | } |
566 | if (newShape.ptr == IntPtr.Zero) | 584 | if (!newShape.HasPhysicalShape) |
567 | { | 585 | { |
568 | PhysicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", | 586 | PhysicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", |
569 | LogHeader, prim.LocalID, shapeType); | 587 | LogHeader, prim.LocalID, shapeType); |
@@ -580,7 +598,7 @@ public sealed class BSShapeCollection : IDisposable | |||
580 | // Called at taint-time! | 598 | // Called at taint-time! |
581 | private bool GetReferenceToMesh(BSPhysObject prim, ShapeDestructionCallback shapeCallback) | 599 | private bool GetReferenceToMesh(BSPhysObject prim, ShapeDestructionCallback shapeCallback) |
582 | { | 600 | { |
583 | BulletShape newShape = new BulletShape(IntPtr.Zero); | 601 | BulletShape newShape = new BulletShape(); |
584 | 602 | ||
585 | float lod; | 603 | float lod; |
586 | System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod); | 604 | System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod); |
@@ -589,62 +607,96 @@ public sealed class BSShapeCollection : IDisposable | |||
589 | if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_MESH) | 607 | if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_MESH) |
590 | return false; | 608 | return false; |
591 | 609 | ||
592 | DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2}", | 610 | if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2},size={3},lod={4}", |
593 | prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X")); | 611 | prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X"), prim.Size, lod); |
594 | 612 | ||
595 | // Since we're recreating new, get rid of the reference to the previous shape | 613 | // Since we're recreating new, get rid of the reference to the previous shape |
596 | DereferenceShape(prim.PhysShape, true, shapeCallback); | 614 | DereferenceShape(prim.PhysShape, shapeCallback); |
597 | 615 | ||
598 | newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, prim.BaseShape, prim.Size, lod); | 616 | newShape = CreatePhysicalMesh(prim, newMeshKey, prim.BaseShape, prim.Size, lod); |
599 | // Take evasive action if the mesh was not constructed. | 617 | // Take evasive action if the mesh was not constructed. |
600 | newShape = VerifyMeshCreated(newShape, prim); | 618 | newShape = VerifyMeshCreated(newShape, prim); |
601 | 619 | ||
602 | ReferenceShape(newShape); | 620 | ReferenceShape(newShape); |
603 | 621 | ||
604 | // meshes are already scaled by the meshmerizer | ||
605 | prim.Scale = new OMV.Vector3(1f, 1f, 1f); | ||
606 | prim.PhysShape = newShape; | 622 | prim.PhysShape = newShape; |
607 | 623 | ||
608 | return true; // 'true' means a new shape has been added to this prim | 624 | return true; // 'true' means a new shape has been added to this prim |
609 | } | 625 | } |
610 | 626 | ||
611 | private BulletShape CreatePhysicalMesh(string objName, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) | 627 | private BulletShape CreatePhysicalMesh(BSPhysObject prim, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) |
612 | { | 628 | { |
613 | IMesh meshData = null; | 629 | BulletShape newShape = new BulletShape(); |
614 | IntPtr meshPtr = IntPtr.Zero; | 630 | |
615 | MeshDesc meshDesc; | 631 | MeshDesc meshDesc; |
616 | if (Meshes.TryGetValue(newMeshKey, out meshDesc)) | 632 | if (Meshes.TryGetValue(newMeshKey, out meshDesc)) |
617 | { | 633 | { |
618 | // If the mesh has already been built just use it. | 634 | // If the mesh has already been built just use it. |
619 | meshPtr = meshDesc.ptr; | 635 | newShape = meshDesc.shape.Clone(); |
620 | } | 636 | } |
621 | else | 637 | else |
622 | { | 638 | { |
623 | // Pass false for physicalness as this creates some sort of bounding box which we don't need | 639 | IMesh meshData = PhysicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, |
624 | meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false); | 640 | true, |
641 | false, // say it is not physical so a bounding box is not built | ||
642 | false, // do not cache the mesh and do not use previously built versions | ||
643 | false // It's NOT for ODE | ||
644 | ); | ||
625 | 645 | ||
626 | if (meshData != null) | 646 | if (meshData != null) |
627 | { | 647 | { |
648 | |||
628 | int[] indices = meshData.getIndexListAsInt(); | 649 | int[] indices = meshData.getIndexListAsInt(); |
629 | List<OMV.Vector3> vertices = meshData.getVertexList(); | 650 | int realIndicesIndex = indices.Length; |
651 | float[] verticesAsFloats = meshData.getVertexListAsFloat(); | ||
630 | 652 | ||
631 | float[] verticesAsFloats = new float[vertices.Count * 3]; | 653 | if (BSParam.ShouldRemoveZeroWidthTriangles) |
632 | int vi = 0; | ||
633 | foreach (OMV.Vector3 vv in vertices) | ||
634 | { | 654 | { |
635 | verticesAsFloats[vi++] = vv.X; | 655 | // Remove degenerate triangles. These are triangles with two of the vertices |
636 | verticesAsFloats[vi++] = vv.Y; | 656 | // are the same. This is complicated by the problem that vertices are not |
637 | verticesAsFloats[vi++] = vv.Z; | 657 | // made unique in sculpties so we have to compare the values in the vertex. |
658 | realIndicesIndex = 0; | ||
659 | for (int tri = 0; tri < indices.Length; tri += 3) | ||
660 | { | ||
661 | // Compute displacements into vertex array for each vertex of the triangle | ||
662 | int v1 = indices[tri + 0] * 3; | ||
663 | int v2 = indices[tri + 1] * 3; | ||
664 | int v3 = indices[tri + 2] * 3; | ||
665 | // Check to see if any two of the vertices are the same | ||
666 | if (!( ( verticesAsFloats[v1 + 0] == verticesAsFloats[v2 + 0] | ||
667 | && verticesAsFloats[v1 + 1] == verticesAsFloats[v2 + 1] | ||
668 | && verticesAsFloats[v1 + 2] == verticesAsFloats[v2 + 2]) | ||
669 | || ( verticesAsFloats[v2 + 0] == verticesAsFloats[v3 + 0] | ||
670 | && verticesAsFloats[v2 + 1] == verticesAsFloats[v3 + 1] | ||
671 | && verticesAsFloats[v2 + 2] == verticesAsFloats[v3 + 2]) | ||
672 | || ( verticesAsFloats[v1 + 0] == verticesAsFloats[v3 + 0] | ||
673 | && verticesAsFloats[v1 + 1] == verticesAsFloats[v3 + 1] | ||
674 | && verticesAsFloats[v1 + 2] == verticesAsFloats[v3 + 2]) ) | ||
675 | ) | ||
676 | { | ||
677 | // None of the vertices of the triangles are the same. This is a good triangle; | ||
678 | indices[realIndicesIndex + 0] = indices[tri + 0]; | ||
679 | indices[realIndicesIndex + 1] = indices[tri + 1]; | ||
680 | indices[realIndicesIndex + 2] = indices[tri + 2]; | ||
681 | realIndicesIndex += 3; | ||
682 | } | ||
683 | } | ||
638 | } | 684 | } |
685 | DetailLog("{0},BSShapeCollection.CreatePhysicalMesh,origTri={1},realTri={2},numVerts={3}", | ||
686 | BSScene.DetailLogZero, indices.Length / 3, realIndicesIndex / 3, verticesAsFloats.Length / 3); | ||
639 | 687 | ||
640 | // m_log.DebugFormat("{0}: BSShapeCollection.CreatePhysicalMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", | 688 | if (realIndicesIndex != 0) |
641 | // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count); | 689 | { |
642 | 690 | newShape = PhysicsScene.PE.CreateMeshShape(PhysicsScene.World, | |
643 | meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, | 691 | realIndicesIndex, indices, verticesAsFloats.Length / 3, verticesAsFloats); |
644 | indices.GetLength(0), indices, vertices.Count, verticesAsFloats); | 692 | } |
693 | else | ||
694 | { | ||
695 | PhysicsScene.Logger.DebugFormat("{0} All mesh triangles degenerate. Prim {1} at {2} in {3}", | ||
696 | LogHeader, prim.PhysObjectName, prim.RawPosition, PhysicsScene.Name); | ||
697 | } | ||
645 | } | 698 | } |
646 | } | 699 | } |
647 | BulletShape newShape = new BulletShape(meshPtr, BSPhysicsShapeType.SHAPE_MESH); | ||
648 | newShape.shapeKey = newMeshKey; | 700 | newShape.shapeKey = newMeshKey; |
649 | 701 | ||
650 | return newShape; | 702 | return newShape; |
@@ -652,6 +704,7 @@ public sealed class BSShapeCollection : IDisposable | |||
652 | 704 | ||
653 | // See that hull shape exists in the physical world and update prim.BSShape. | 705 | // See that hull shape exists in the physical world and update prim.BSShape. |
654 | // We could be creating the hull because scale changed or whatever. | 706 | // We could be creating the hull because scale changed or whatever. |
707 | // Return 'true' if a new hull was built. Otherwise, returning a shared hull instance. | ||
655 | private bool GetReferenceToHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback) | 708 | private bool GetReferenceToHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback) |
656 | { | 709 | { |
657 | BulletShape newShape; | 710 | BulletShape newShape; |
@@ -663,19 +716,18 @@ public sealed class BSShapeCollection : IDisposable | |||
663 | if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_HULL) | 716 | if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == BSPhysicsShapeType.SHAPE_HULL) |
664 | return false; | 717 | return false; |
665 | 718 | ||
666 | DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}", | 719 | if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}", |
667 | prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X")); | 720 | prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X")); |
668 | 721 | ||
669 | // Remove usage of the previous shape. | 722 | // Remove usage of the previous shape. |
670 | DereferenceShape(prim.PhysShape, true, shapeCallback); | 723 | DereferenceShape(prim.PhysShape, shapeCallback); |
671 | 724 | ||
672 | newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod); | 725 | newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod); |
726 | // It might not have been created if we're waiting for an asset. | ||
673 | newShape = VerifyMeshCreated(newShape, prim); | 727 | newShape = VerifyMeshCreated(newShape, prim); |
674 | 728 | ||
675 | ReferenceShape(newShape); | 729 | ReferenceShape(newShape); |
676 | 730 | ||
677 | // hulls are already scaled by the meshmerizer | ||
678 | prim.Scale = new OMV.Vector3(1f, 1f, 1f); | ||
679 | prim.PhysShape = newShape; | 731 | prim.PhysShape = newShape; |
680 | return true; // 'true' means a new shape has been added to this prim | 732 | return true; // 'true' means a new shape has been added to this prim |
681 | } | 733 | } |
@@ -684,18 +736,20 @@ public sealed class BSShapeCollection : IDisposable | |||
684 | private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) | 736 | private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) |
685 | { | 737 | { |
686 | 738 | ||
739 | BulletShape newShape = new BulletShape(); | ||
687 | IntPtr hullPtr = IntPtr.Zero; | 740 | IntPtr hullPtr = IntPtr.Zero; |
741 | |||
688 | HullDesc hullDesc; | 742 | HullDesc hullDesc; |
689 | if (Hulls.TryGetValue(newHullKey, out hullDesc)) | 743 | if (Hulls.TryGetValue(newHullKey, out hullDesc)) |
690 | { | 744 | { |
691 | // If the hull shape already is created, just use it. | 745 | // If the hull shape already has been created, just use the one shared instance. |
692 | hullPtr = hullDesc.ptr; | 746 | newShape = hullDesc.shape.Clone(); |
693 | } | 747 | } |
694 | else | 748 | else |
695 | { | 749 | { |
696 | // Build a new hull in the physical world | 750 | // 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 | 751 | // Pass true for physicalness as this prevents the creation of bounding box which is not needed |
698 | IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false); | 752 | IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, true, false, false, false); |
699 | if (meshData != null) | 753 | if (meshData != null) |
700 | { | 754 | { |
701 | 755 | ||
@@ -714,15 +768,35 @@ public sealed class BSShapeCollection : IDisposable | |||
714 | convVertices.Add(new float3(vv.X, vv.Y, vv.Z)); | 768 | convVertices.Add(new float3(vv.X, vv.Y, vv.Z)); |
715 | } | 769 | } |
716 | 770 | ||
771 | uint maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplit; | ||
772 | if (BSParam.CSHullMaxDepthSplit != BSParam.CSHullMaxDepthSplitForSimpleShapes) | ||
773 | { | ||
774 | // Simple primitive shapes we know are convex so they are better implemented with | ||
775 | // fewer hulls. | ||
776 | // Check for simple shape (prim without cuts) and reduce split parameter if so. | ||
777 | if (PrimHasNoCuts(pbs)) | ||
778 | { | ||
779 | maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplitForSimpleShapes; | ||
780 | } | ||
781 | } | ||
782 | |||
717 | // setup and do convex hull conversion | 783 | // setup and do convex hull conversion |
718 | m_hulls = new List<ConvexResult>(); | 784 | m_hulls = new List<ConvexResult>(); |
719 | DecompDesc dcomp = new DecompDesc(); | 785 | DecompDesc dcomp = new DecompDesc(); |
720 | dcomp.mIndices = convIndices; | 786 | dcomp.mIndices = convIndices; |
721 | dcomp.mVertices = convVertices; | 787 | dcomp.mVertices = convVertices; |
788 | dcomp.mDepth = maxDepthSplit; | ||
789 | dcomp.mCpercent = BSParam.CSHullConcavityThresholdPercent; | ||
790 | dcomp.mPpercent = BSParam.CSHullVolumeConservationThresholdPercent; | ||
791 | dcomp.mMaxVertices = (uint)BSParam.CSHullMaxVertices; | ||
792 | dcomp.mSkinWidth = BSParam.CSHullMaxSkinWidth; | ||
722 | ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn); | 793 | ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn); |
723 | // create the hull into the _hulls variable | 794 | // create the hull into the _hulls variable |
724 | convexBuilder.process(dcomp); | 795 | convexBuilder.process(dcomp); |
725 | 796 | ||
797 | DetailLog("{0},BSShapeCollection.CreatePhysicalHull,key={1},inVert={2},inInd={3},split={4},hulls={5}", | ||
798 | BSScene.DetailLogZero, newHullKey, indices.GetLength(0), vertices.Count, maxDepthSplit, m_hulls.Count); | ||
799 | |||
726 | // Convert the vertices and indices for passing to unmanaged. | 800 | // Convert the vertices and indices for passing to unmanaged. |
727 | // The hull information is passed as a large floating point array. | 801 | // The hull information is passed as a large floating point array. |
728 | // The format is: | 802 | // The format is: |
@@ -777,14 +851,13 @@ public sealed class BSShapeCollection : IDisposable | |||
777 | } | 851 | } |
778 | } | 852 | } |
779 | // create the hull data structure in Bullet | 853 | // create the hull data structure in Bullet |
780 | hullPtr = BulletSimAPI.CreateHullShape2(PhysicsScene.World.ptr, hullCount, convHulls); | 854 | newShape = PhysicsScene.PE.CreateHullShape(PhysicsScene.World, hullCount, convHulls); |
781 | } | 855 | } |
782 | } | 856 | } |
783 | 857 | ||
784 | BulletShape newShape = new BulletShape(hullPtr, BSPhysicsShapeType.SHAPE_HULL); | ||
785 | newShape.shapeKey = newHullKey; | 858 | newShape.shapeKey = newHullKey; |
786 | 859 | ||
787 | return newShape; // 'true' means a new shape has been added to this prim | 860 | return newShape; |
788 | } | 861 | } |
789 | 862 | ||
790 | // Callback from convex hull creater with a newly created hull. | 863 | // Callback from convex hull creater with a newly created hull. |
@@ -803,13 +876,12 @@ 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. | 876 | // 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); | 877 | // DereferenceShape(prim.PhysShape, true, shapeCallback); |
805 | 878 | ||
806 | BulletShape cShape = new BulletShape( | 879 | BulletShape cShape = PhysicsScene.PE.CreateCompoundShape(PhysicsScene.World, false); |
807 | BulletSimAPI.CreateCompoundShape2(PhysicsScene.World.ptr, false), BSPhysicsShapeType.SHAPE_COMPOUND); | ||
808 | 880 | ||
809 | // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape. | 881 | // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape. |
810 | CreateGeomMeshOrHull(prim, shapeCallback); | 882 | CreateGeomMeshOrHull(prim, shapeCallback); |
811 | BulletSimAPI.AddChildShapeToCompoundShape2(cShape.ptr, prim.PhysShape.ptr, OMV.Vector3.Zero, OMV.Quaternion.Identity); | 883 | PhysicsScene.PE.AddChildShapeToCompoundShape(cShape, prim.PhysShape, OMV.Vector3.Zero, OMV.Quaternion.Identity); |
812 | DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addRootPrim,compShape={1},rootShape={2}", | 884 | if (DDetail) DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addRootPrim,compShape={1},rootShape={2}", |
813 | prim.LocalID, cShape, prim.PhysShape); | 885 | prim.LocalID, cShape, prim.PhysShape); |
814 | 886 | ||
815 | prim.PhysShape = cShape; | 887 | prim.PhysShape = cShape; |
@@ -822,14 +894,19 @@ public sealed class BSShapeCollection : IDisposable | |||
822 | private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod) | 894 | private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod) |
823 | { | 895 | { |
824 | // level of detail based on size and type of the object | 896 | // level of detail based on size and type of the object |
825 | float lod = PhysicsScene.MeshLOD; | 897 | float lod = BSParam.MeshLOD; |
898 | |||
899 | // prims with curvy internal cuts need higher lod | ||
900 | if (pbs.HollowShape == HollowShape.Circle) | ||
901 | lod = BSParam.MeshCircularLOD; | ||
902 | |||
826 | if (pbs.SculptEntry) | 903 | if (pbs.SculptEntry) |
827 | lod = PhysicsScene.SculptLOD; | 904 | lod = BSParam.SculptLOD; |
828 | 905 | ||
829 | // Mega prims usually get more detail because one can interact with shape approximations at this size. | 906 | // 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)); | 907 | float maxAxis = Math.Max(size.X, Math.Max(size.Y, size.Z)); |
831 | if (maxAxis > PhysicsScene.MeshMegaPrimThreshold) | 908 | if (maxAxis > BSParam.MeshMegaPrimThreshold) |
832 | lod = PhysicsScene.MeshMegaPrimLOD; | 909 | lod = BSParam.MeshMegaPrimLOD; |
833 | 910 | ||
834 | retLod = lod; | 911 | retLod = lod; |
835 | return pbs.GetMeshKey(size, lod); | 912 | return pbs.GetMeshKey(size, lod); |
@@ -851,51 +928,88 @@ public sealed class BSShapeCollection : IDisposable | |||
851 | private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim) | 928 | private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim) |
852 | { | 929 | { |
853 | // If the shape was successfully created, nothing more to do | 930 | // If the shape was successfully created, nothing more to do |
854 | if (newShape.ptr != IntPtr.Zero) | 931 | if (newShape.HasPhysicalShape) |
855 | return newShape; | 932 | return newShape; |
856 | 933 | ||
857 | // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset | 934 | // VerifyMeshCreated is called after trying to create the mesh. If we think the asset had been |
858 | if (prim.BaseShape.SculptEntry && !prim.LastAssetBuildFailed && prim.BaseShape.SculptTexture != OMV.UUID.Zero) | 935 | // fetched but we end up here again, the meshing of the asset must have failed. |
936 | // Prevent trying to keep fetching the mesh by declaring failure. | ||
937 | if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Fetched) | ||
859 | { | 938 | { |
860 | prim.LastAssetBuildFailed = true; | 939 | prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed; |
861 | BSPhysObject xprim = prim; | 940 | PhysicsScene.Logger.WarnFormat("{0} Fetched asset would not mesh. {1}, texture={2}", |
862 | DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset,lID={1},lastFailed={2}", | 941 | LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture); |
863 | LogHeader, prim.LocalID, prim.LastAssetBuildFailed); | ||
864 | Util.FireAndForget(delegate | ||
865 | { | ||
866 | RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod; | ||
867 | if (assetProvider != null) | ||
868 | { | ||
869 | BSPhysObject yprim = xprim; // probably not necessary, but, just in case. | ||
870 | assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset) | ||
871 | { | ||
872 | if (!yprim.BaseShape.SculptEntry) | ||
873 | return; | ||
874 | if (yprim.BaseShape.SculptTexture.ToString() != asset.ID) | ||
875 | return; | ||
876 | |||
877 | yprim.BaseShape.SculptData = asset.Data; | ||
878 | // This will cause the prim to see that the filler shape is not the right | ||
879 | // one and try again to build the object. | ||
880 | // No race condition with the normal shape setting since the rebuild is at taint time. | ||
881 | yprim.ForceBodyShapeRebuild(false); | ||
882 | |||
883 | }); | ||
884 | } | ||
885 | }); | ||
886 | } | 942 | } |
887 | else | 943 | else |
888 | { | 944 | { |
889 | if (prim.LastAssetBuildFailed) | 945 | // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset |
946 | if (prim.BaseShape.SculptEntry | ||
947 | && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Failed | ||
948 | && prim.PrimAssetState != BSPhysObject.PrimAssetCondition.Waiting | ||
949 | && prim.BaseShape.SculptTexture != OMV.UUID.Zero | ||
950 | ) | ||
890 | { | 951 | { |
891 | PhysicsScene.Logger.ErrorFormat("{0} Mesh failed to fetch asset. lID={1}, texture={2}", | 952 | DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset", prim.LocalID); |
892 | LogHeader, prim.LocalID, prim.BaseShape.SculptTexture); | 953 | // Multiple requestors will know we're waiting for this asset |
954 | prim.PrimAssetState = BSPhysObject.PrimAssetCondition.Waiting; | ||
955 | |||
956 | BSPhysObject xprim = prim; | ||
957 | Util.FireAndForget(delegate | ||
958 | { | ||
959 | RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod; | ||
960 | if (assetProvider != null) | ||
961 | { | ||
962 | BSPhysObject yprim = xprim; // probably not necessary, but, just in case. | ||
963 | assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset) | ||
964 | { | ||
965 | bool assetFound = false; | ||
966 | string mismatchIDs = String.Empty; // DEBUG DEBUG | ||
967 | if (asset != null && yprim.BaseShape.SculptEntry) | ||
968 | { | ||
969 | if (yprim.BaseShape.SculptTexture.ToString() == asset.ID) | ||
970 | { | ||
971 | yprim.BaseShape.SculptData = asset.Data; | ||
972 | // This will cause the prim to see that the filler shape is not the right | ||
973 | // one and try again to build the object. | ||
974 | // No race condition with the normal shape setting since the rebuild is at taint time. | ||
975 | yprim.ForceBodyShapeRebuild(false /* inTaintTime */); | ||
976 | assetFound = true; | ||
977 | } | ||
978 | else | ||
979 | { | ||
980 | mismatchIDs = yprim.BaseShape.SculptTexture.ToString() + "/" + asset.ID; | ||
981 | } | ||
982 | } | ||
983 | if (assetFound) | ||
984 | yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Fetched; | ||
985 | else | ||
986 | yprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed; | ||
987 | DetailLog("{0},BSShapeCollection,fetchAssetCallback,found={1},isSculpt={2},ids={3}", | ||
988 | yprim.LocalID, assetFound, yprim.BaseShape.SculptEntry, mismatchIDs ); | ||
989 | |||
990 | }); | ||
991 | } | ||
992 | else | ||
993 | { | ||
994 | xprim.PrimAssetState = BSPhysObject.PrimAssetCondition.Failed; | ||
995 | PhysicsScene.Logger.ErrorFormat("{0} Physical object requires asset but no asset provider. Name={1}", | ||
996 | LogHeader, PhysicsScene.Name); | ||
997 | } | ||
998 | }); | ||
999 | } | ||
1000 | else | ||
1001 | { | ||
1002 | if (prim.PrimAssetState == BSPhysObject.PrimAssetCondition.Failed) | ||
1003 | { | ||
1004 | PhysicsScene.Logger.WarnFormat("{0} Mesh failed to fetch asset. obj={1}, texture={2}", | ||
1005 | LogHeader, prim.PhysObjectName, prim.BaseShape.SculptTexture); | ||
1006 | } | ||
893 | } | 1007 | } |
894 | } | 1008 | } |
895 | 1009 | ||
896 | // While we figure out the real problem, stick a simple native shape on the object. | 1010 | // While we wait for the mesh defining asset to be loaded, stick in a simple box for the object. |
897 | BulletShape fillinShape = | 1011 | BulletShape fillinShape = BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX); |
898 | BuildPhysicalNativeShape(prim, BSPhysicsShapeType.SHAPE_BOX, FixedShapeKey.KEY_BOX); | 1012 | DetailLog("{0},BSShapeCollection.VerifyMeshCreated,boxTempShape", prim.LocalID); |
899 | 1013 | ||
900 | return fillinShape; | 1014 | return fillinShape; |
901 | } | 1015 | } |
@@ -904,49 +1018,45 @@ public sealed class BSShapeCollection : IDisposable | |||
904 | // Updates prim.BSBody with the information about the new body if one is created. | 1018 | // Updates prim.BSBody with the information about the new body if one is created. |
905 | // Returns 'true' if an object was actually created. | 1019 | // Returns 'true' if an object was actually created. |
906 | // Called at taint-time. | 1020 | // Called at taint-time. |
907 | private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletSim sim, BulletShape shape, | 1021 | private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletWorld sim, BodyDestructionCallback bodyCallback) |
908 | BodyDestructionCallback bodyCallback) | ||
909 | { | 1022 | { |
910 | bool ret = false; | 1023 | bool ret = false; |
911 | 1024 | ||
912 | // the mesh, hull or native shape must have already been created in Bullet | 1025 | // the mesh, hull or native shape must have already been created in Bullet |
913 | bool mustRebuild = (prim.PhysBody.ptr == IntPtr.Zero); | 1026 | bool mustRebuild = !prim.PhysBody.HasPhysicalBody; |
914 | 1027 | ||
915 | // If there is an existing body, verify it's of an acceptable type. | 1028 | // 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. | 1029 | // If not a solid object, body is a GhostObject. Otherwise a RigidBody. |
917 | if (!mustRebuild) | 1030 | if (!mustRebuild) |
918 | { | 1031 | { |
919 | CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(prim.PhysBody.ptr); | 1032 | CollisionObjectTypes bodyType = (CollisionObjectTypes)PhysicsScene.PE.GetBodyType(prim.PhysBody); |
920 | if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY | 1033 | if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY |
921 | || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT) | 1034 | || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT) |
922 | { | 1035 | { |
923 | // If the collisionObject is not the correct type for solidness, rebuild what's there | 1036 | // If the collisionObject is not the correct type for solidness, rebuild what's there |
924 | mustRebuild = true; | 1037 | mustRebuild = true; |
1038 | if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,forceRebuildBecauseChangingBodyType,bodyType={1}", prim.LocalID, bodyType); | ||
925 | } | 1039 | } |
926 | } | 1040 | } |
927 | 1041 | ||
928 | if (mustRebuild || forceRebuild) | 1042 | if (mustRebuild || forceRebuild) |
929 | { | 1043 | { |
930 | // Free any old body | 1044 | // Free any old body |
931 | DereferenceBody(prim.PhysBody, true, bodyCallback); | 1045 | DereferenceBody(prim.PhysBody, bodyCallback); |
932 | 1046 | ||
933 | BulletBody aBody; | 1047 | BulletBody aBody; |
934 | IntPtr bodyPtr = IntPtr.Zero; | ||
935 | if (prim.IsSolid) | 1048 | if (prim.IsSolid) |
936 | { | 1049 | { |
937 | bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr, | 1050 | aBody = PhysicsScene.PE.CreateBodyFromShape(sim, prim.PhysShape, prim.LocalID, prim.RawPosition, prim.RawOrientation); |
938 | prim.LocalID, prim.RawPosition, prim.RawOrientation); | 1051 | 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 | } | 1052 | } |
941 | else | 1053 | else |
942 | { | 1054 | { |
943 | bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr, | 1055 | aBody = PhysicsScene.PE.CreateGhostFromShape(sim, prim.PhysShape, prim.LocalID, prim.RawPosition, prim.RawOrientation); |
944 | prim.LocalID, prim.RawPosition, prim.RawOrientation); | 1056 | 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 | } | 1057 | } |
947 | aBody = new BulletBody(prim.LocalID, bodyPtr); | ||
948 | 1058 | ||
949 | ReferenceBody(aBody, true); | 1059 | ReferenceBody(aBody); |
950 | 1060 | ||
951 | prim.PhysBody = aBody; | 1061 | prim.PhysBody = aBody; |
952 | 1062 | ||
@@ -956,13 +1066,13 @@ public sealed class BSShapeCollection : IDisposable | |||
956 | return ret; | 1066 | return ret; |
957 | } | 1067 | } |
958 | 1068 | ||
959 | private bool TryGetMeshByPtr(IntPtr addr, out MeshDesc outDesc) | 1069 | private bool TryGetMeshByPtr(BulletShape shape, out MeshDesc outDesc) |
960 | { | 1070 | { |
961 | bool ret = false; | 1071 | bool ret = false; |
962 | MeshDesc foundDesc = new MeshDesc(); | 1072 | MeshDesc foundDesc = new MeshDesc(); |
963 | foreach (MeshDesc md in Meshes.Values) | 1073 | foreach (MeshDesc md in Meshes.Values) |
964 | { | 1074 | { |
965 | if (md.ptr == addr) | 1075 | if (md.shape.ReferenceSame(shape)) |
966 | { | 1076 | { |
967 | foundDesc = md; | 1077 | foundDesc = md; |
968 | ret = true; | 1078 | ret = true; |
@@ -974,13 +1084,13 @@ public sealed class BSShapeCollection : IDisposable | |||
974 | return ret; | 1084 | return ret; |
975 | } | 1085 | } |
976 | 1086 | ||
977 | private bool TryGetHullByPtr(IntPtr addr, out HullDesc outDesc) | 1087 | private bool TryGetHullByPtr(BulletShape shape, out HullDesc outDesc) |
978 | { | 1088 | { |
979 | bool ret = false; | 1089 | bool ret = false; |
980 | HullDesc foundDesc = new HullDesc(); | 1090 | HullDesc foundDesc = new HullDesc(); |
981 | foreach (HullDesc hd in Hulls.Values) | 1091 | foreach (HullDesc hd in Hulls.Values) |
982 | { | 1092 | { |
983 | if (hd.ptr == addr) | 1093 | if (hd.shape.ReferenceSame(shape)) |
984 | { | 1094 | { |
985 | foundDesc = hd; | 1095 | foundDesc = hd; |
986 | ret = true; | 1096 | ret = true; |