aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
diff options
context:
space:
mode:
authorRobert Adams2012-09-20 10:12:51 -0700
committerRobert Adams2012-09-27 22:01:26 -0700
commit22290ef35aa13edb1501c69b3cce63a885302563 (patch)
tree2c4762479fb5336c3338acdd2d761fc8c15a04e9 /OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
parentBulletSim: add class and infrastructure for shape and object (diff)
downloadopensim-SC-22290ef35aa13edb1501c69b3cce63a885302563.zip
opensim-SC-22290ef35aa13edb1501c69b3cce63a885302563.tar.gz
opensim-SC-22290ef35aa13edb1501c69b3cce63a885302563.tar.bz2
opensim-SC-22290ef35aa13edb1501c69b3cce63a885302563.tar.xz
BulletSim: complete code for managed code shape and body tracking. Not debugged.
Eliminate some null exceptions created adding the above code. Add and remove some detailed logging statements.
Diffstat (limited to '')
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs617
1 files changed, 547 insertions, 70 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index eb4b2ad..7470d23 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -1,70 +1,547 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright 7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyrightD 9 * * Redistributions in binary form must reproduce the above copyrightD
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the 12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products 13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission. 14 * derived from this software without specific prior written permission.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY 16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27using System; 27using System;
28using System.Collections.Generic; 28using System.Collections.Generic;
29using System.Text; 29using System.Text;
30using OMV = OpenMetaverse; 30using OMV = OpenMetaverse;
31 31using OpenSim.Framework;
32namespace OpenSim.Region.Physics.BulletSPlugin 32using OpenSim.Region.Physics.Manager;
33{ 33using OpenSim.Region.Physics.ConvexDecompositionDotNet;
34public class BSShapeCollection : IDisposable 34
35{ 35namespace OpenSim.Region.Physics.BulletSPlugin
36 protected BSScene PhysicsScene { get; set; } 36{
37 37public class BSShapeCollection : IDisposable
38 public BSShapeCollection(BSScene physScene) 38{
39 { 39 protected BSScene PhysicsScene { get; set; }
40 PhysicsScene = physScene; 40
41 } 41 private Object m_shapeActivityLock = new Object();
42 42
43 public void Dispose() 43 private struct MeshDesc
44 { 44 {
45 } 45 public IntPtr Ptr;
46 46 public int referenceCount;
47 // Track another user of a body 47 public DateTime lastReferenced;
48 public void ReferenceBody(BulletBody shape) 48 public IMesh meshData;
49 { 49 }
50 } 50
51 51 private struct HullDesc
52 // Release the usage of a body 52 {
53 public void DereferenceBody(BulletBody shape) 53 public IntPtr Ptr;
54 { 54 public int referenceCount;
55 } 55 public DateTime lastReferenced;
56 56 }
57 // Track another user of the shape 57
58 public void ReferenceShape(BulletShape shape) 58 private Dictionary<ulong, MeshDesc> Meshes = new Dictionary<ulong, MeshDesc>();
59 { 59 private Dictionary<ulong, HullDesc> Hulls = new Dictionary<ulong, HullDesc>();
60 } 60
61 61 public BSShapeCollection(BSScene physScene)
62 // Release the usage of a shape 62 {
63 public void DereferenceShape(BulletShape shape) 63 PhysicsScene = physScene;
64 { 64 }
65 } 65
66 66 public void Dispose()
67 67 {
68 68 }
69} 69
70} 70 // Called to update/change the body and shape for an object.
71 // First checks the shape and updates that if necessary then makes
72 // sure the body is of the right type.
73 // Return 'true' if either the body or the shape changed.
74 // Called at taint-time!!
75 public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs)
76 {
77 bool ret = false;
78
79 // Do we have the correct geometry for this type of object?
80 if (CreateGeom(forceRebuild, prim, shapeData, pbs))
81 {
82 // If we had to select a new shape geometry for the object,
83 // rebuild the body around it.
84 CreateObject(true, prim, PhysicsScene.World, prim.BSShape, shapeData);
85 ret = true;
86 }
87
88 return ret;
89 }
90
91 // Track another user of a body
92 public void ReferenceBody(BulletBody shape)
93 {
94 }
95
96 // Release the usage of a body
97 public void DereferenceBody(BulletBody shape)
98 {
99 }
100
101 // Track another user of the shape
102 public void ReferenceShape(BulletShape shape)
103 {
104 ReferenceShape(shape, null);
105 }
106
107 // Track the datastructures and use count for a shape.
108 // When creating a hull, this is called first to reference the mesh
109 // and then again to reference the hull.
110 // Meshes and hulls for the same shape have the same hash key.
111 private void ReferenceShape(BulletShape shape, IMesh meshData)
112 {
113 switch (shape.type)
114 {
115 case ShapeData.PhysicsShapeType.SHAPE_MESH:
116 MeshDesc meshDesc;
117 if (Meshes.TryGetValue(shape.shapeKey, out meshDesc))
118 {
119 // There is an existing instance of this mesh.
120 meshDesc.referenceCount++;
121 }
122 else
123 {
124 // This is a new reference to a mesh
125 meshDesc.Ptr = shape.Ptr;
126 meshDesc.meshData = meshData;
127 meshDesc.referenceCount = 1;
128
129 }
130 meshDesc.lastReferenced = System.DateTime.Now;
131 Meshes[shape.shapeKey] = meshDesc;
132 break;
133 case ShapeData.PhysicsShapeType.SHAPE_HULL:
134 HullDesc hullDesc;
135 if (Hulls.TryGetValue(shape.shapeKey, out hullDesc))
136 {
137 // There is an existing instance of this mesh.
138 hullDesc.referenceCount++;
139 }
140 else
141 {
142 // This is a new reference to a mesh
143 hullDesc.Ptr = shape.Ptr;
144 hullDesc.referenceCount = 1;
145
146 }
147 hullDesc.lastReferenced = System.DateTime.Now;
148 Hulls[shape.shapeKey] = hullDesc;
149 break;
150 default:
151 break;
152 }
153 }
154
155 // Release the usage of a shape
156 public void DereferenceShape(BulletShape shape)
157 {
158 switch (shape.type)
159 {
160 case ShapeData.PhysicsShapeType.SHAPE_HULL:
161 DereferenceHull(shape);
162 // Hulls also include a mesh
163 DereferenceMesh(shape);
164 break;
165 case ShapeData.PhysicsShapeType.SHAPE_MESH:
166 DereferenceMesh(shape);
167 break;
168 default:
169 break;
170 }
171 }
172
173 // Count down the reference count for a mesh shape
174 private void DereferenceMesh(BulletShape shape)
175 {
176 MeshDesc meshDesc;
177 if (Meshes.TryGetValue(shape.shapeKey, out meshDesc))
178 {
179 meshDesc.referenceCount--;
180 // TODO: release the Bullet storage
181 meshDesc.lastReferenced = System.DateTime.Now;
182 Meshes[shape.shapeKey] = meshDesc;
183 }
184 }
185
186 // Count down the reference count for a hull shape
187 private void DereferenceHull(BulletShape shape)
188 {
189 HullDesc hullDesc;
190 if (Hulls.TryGetValue(shape.shapeKey, out hullDesc))
191 {
192 hullDesc.referenceCount--;
193 // TODO: release the Bullet storage (aging old entries?)
194 hullDesc.lastReferenced = System.DateTime.Now;
195 Hulls[shape.shapeKey] = hullDesc;
196 }
197 }
198
199 // Create the geometry information in Bullet for later use.
200 // The objects needs a hull if it's physical otherwise a mesh is enough.
201 // No locking here because this is done when we know physics is not simulating.
202 // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used.
203 // Returns 'true' if the geometry was rebuilt.
204 // Called at taint-time!
205 private bool CreateGeom(bool forceRebuild, BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs)
206 {
207 bool ret = false;
208 bool haveShape = false;
209 bool nativeShapePossible = true;
210
211 BulletShape newShape = new BulletShape(IntPtr.Zero);
212
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
218 if (nativeShapePossible
219 && ((pbs.SculptEntry && !PhysicsScene.ShouldMeshSculptedPrim)
220 || (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
221 && pbs.ProfileHollow == 0
222 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
223 && pbs.PathBegin == 0 && pbs.PathEnd == 0
224 && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
225 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
226 && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) )
227 {
228 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
229 {
230 haveShape = true;
231 if (forceRebuild || (prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE))
232 {
233 DetailLog("{0},BSShapeCollection.CreateGeom,sphere (force={1}", prim.LocalID, forceRebuild);
234 newShape = AddNativeShapeToPrim(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_SPHERE);
235
236 ret = true;
237 }
238 }
239 else
240 {
241 // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size);
242 haveShape = true;
243 if (forceRebuild || (prim.BSShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX))
244 {
245 DetailLog("{0},BSShapeCollection.CreateGeom,box (force={1})", prim.LocalID, forceRebuild);
246 newShape = AddNativeShapeToPrim(prim, shapeData, ShapeData.PhysicsShapeType.SHAPE_BOX);
247
248 ret = true;
249 }
250 }
251 }
252 // If a simple shape isn't happening, create a mesh and possibly a hull
253 if (!haveShape)
254 {
255 if (prim.IsPhysical)
256 {
257 if (forceRebuild || !Hulls.ContainsKey(prim.BSShape.shapeKey))
258 {
259 // physical objects require a hull for interaction.
260 // This also creates the mesh if it doesn't already exist
261 ret = CreateGeomHull(prim, shapeData, pbs);
262 }
263 }
264 else
265 {
266 if (forceRebuild || !Meshes.ContainsKey(prim.BSShape.shapeKey))
267 {
268 // Static (non-physical) objects only need a mesh for bumping into
269 ret = CreateGeomMesh(prim, shapeData, pbs);
270 }
271 }
272 }
273 return ret;
274 }
275
276 private BulletShape AddNativeShapeToPrim(BSPrim prim, ShapeData shapeData, ShapeData.PhysicsShapeType shapeType)
277 {
278 BulletShape newShape;
279
280 // Bullet native objects are scaled by the Bullet engine so pass the size in
281 prim.Scale = shapeData.Size;
282
283 // release any previous shape
284 DereferenceShape(prim.BSShape);
285
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;
305 return newShape;
306 }
307
308 // No locking here because this is done when we know physics is not simulating
309 // Returns 'true' of a mesh was actually rebuild (we could also have one of these specs).
310 // Called at taint-time!
311 private bool CreateGeomMesh(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs)
312 {
313 BulletShape newShape = new BulletShape(IntPtr.Zero);
314
315 // level of detail based on size and type of the object
316 float lod = PhysicsScene.MeshLOD;
317 if (pbs.SculptEntry)
318 lod = PhysicsScene.SculptLOD;
319
320 float maxAxis = Math.Max(shapeData.Size.X, Math.Max(shapeData.Size.Y, shapeData.Size.Z));
321 if (maxAxis > PhysicsScene.MeshMegaPrimThreshold)
322 lod = PhysicsScene.MeshMegaPrimLOD;
323
324 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
327 // if this new shape is the same as last time, don't recreate the mesh
328 if (prim.BSShape.shapeKey == newMeshKey) return false;
329
330 DetailLog("{0},BSShapeCollection.CreateGeomMesh,create,key={1}", prim.LocalID, newMeshKey);
331
332 // Since we're recreating new, get rid of the reference to the previous shape
333 DereferenceShape(prim.BSShape);
334
335 IMesh meshData = null;
336 IntPtr meshPtr;
337 MeshDesc meshDesc;
338 if (Meshes.TryGetValue(newMeshKey, out meshDesc))
339 {
340 // If the mesh has already been built just use it.
341 meshPtr = meshDesc.Ptr;
342 }
343 else
344 {
345 // always pass false for physicalness as this creates some sort of bounding box which we don't need
346 meshData = PhysicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, shapeData.Size, lod, false);
347
348 int[] indices = meshData.getIndexListAsInt();
349 List<OMV.Vector3> vertices = meshData.getVertexList();
350
351 float[] verticesAsFloats = new float[vertices.Count * 3];
352 int vi = 0;
353 foreach (OMV.Vector3 vv in vertices)
354 {
355 verticesAsFloats[vi++] = vv.X;
356 verticesAsFloats[vi++] = vv.Y;
357 verticesAsFloats[vi++] = vv.Z;
358 }
359
360 // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}",
361 // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count);
362
363 meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.Ptr,
364 indices.GetLength(0), indices, vertices.Count, verticesAsFloats);
365 }
366 newShape = new BulletShape(meshPtr, ShapeData.PhysicsShapeType.SHAPE_MESH);
367 newShape.shapeKey = newMeshKey;
368
369 ReferenceShape(newShape, meshData);
370
371 // meshes are already scaled by the meshmerizer
372 prim.Scale = new OMV.Vector3(1f, 1f, 1f);
373 prim.BSShape = newShape;
374 return true; // 'true' means a new shape has been added to this prim
375 }
376
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).
379 List<ConvexResult> m_hulls;
380 private bool CreateGeomHull(BSPrim prim, ShapeData shapeData, PrimitiveBaseShape pbs)
381 {
382 BulletShape newShape;
383
384 float lod = pbs.SculptEntry ? PhysicsScene.SculptLOD : PhysicsScene.MeshLOD;
385 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
388 // if the hull hasn't changed, don't rebuild it
389 if (newHullKey == prim.BSShape.shapeKey) return false;
390
391 DetailLog("{0},BSShapeCollection.CreateGeomHull,create,oldKey={1},newKey={2}", prim.LocalID, newHullKey, newHullKey);
392
393 // remove references to any previous shape
394 DereferenceShape(prim.BSShape);
395
396 // 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.
398 CreateGeomMesh(prim, shapeData, pbs);
399 MeshDesc meshDesc = Meshes[newHullKey];
400
401 IntPtr hullPtr;
402 HullDesc hullDesc;
403 if (Hulls.TryGetValue(newHullKey, out hullDesc))
404 {
405 hullPtr = hullDesc.Ptr;
406 }
407 else
408 {
409 int[] indices = meshDesc.meshData.getIndexListAsInt();
410 List<OMV.Vector3> vertices = meshDesc.meshData.getVertexList();
411
412 //format conversion from IMesh format to DecompDesc format
413 List<int> convIndices = new List<int>();
414 List<float3> convVertices = new List<float3>();
415 for (int ii = 0; ii < indices.GetLength(0); ii++)
416 {
417 convIndices.Add(indices[ii]);
418 }
419 foreach (OMV.Vector3 vv in vertices)
420 {
421 convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
422 }
423
424 // setup and do convex hull conversion
425 m_hulls = new List<ConvexResult>();
426 DecompDesc dcomp = new DecompDesc();
427 dcomp.mIndices = convIndices;
428 dcomp.mVertices = convVertices;
429 ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
430 // create the hull into the _hulls variable
431 convexBuilder.process(dcomp);
432
433 // Convert the vertices and indices for passing to unmanaged.
434 // The hull information is passed as a large floating point array.
435 // The format is:
436 // convHulls[0] = number of hulls
437 // convHulls[1] = number of vertices in first hull
438 // convHulls[2] = hull centroid X coordinate
439 // convHulls[3] = hull centroid Y coordinate
440 // convHulls[4] = hull centroid Z coordinate
441 // convHulls[5] = first hull vertex X
442 // convHulls[6] = first hull vertex Y
443 // convHulls[7] = first hull vertex Z
444 // convHulls[8] = second hull vertex X
445 // ...
446 // convHulls[n] = number of vertices in second hull
447 // convHulls[n+1] = second hull centroid X coordinate
448 // ...
449 //
450 // TODO: is is very inefficient. Someday change the convex hull generator to return
451 // data structures that do not need to be converted in order to pass to Bullet.
452 // And maybe put the values directly into pinned memory rather than marshaling.
453 int hullCount = m_hulls.Count;
454 int totalVertices = 1; // include one for the count of the hulls
455 foreach (ConvexResult cr in m_hulls)
456 {
457 totalVertices += 4; // add four for the vertex count and centroid
458 totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
459 }
460 float[] convHulls = new float[totalVertices];
461
462 convHulls[0] = (float)hullCount;
463 int jj = 1;
464 foreach (ConvexResult cr in m_hulls)
465 {
466 // copy vertices for index access
467 float3[] verts = new float3[cr.HullVertices.Count];
468 int kk = 0;
469 foreach (float3 ff in cr.HullVertices)
470 {
471 verts[kk++] = ff;
472 }
473
474 // add to the array one hull's worth of data
475 convHulls[jj++] = cr.HullIndices.Count;
476 convHulls[jj++] = 0f; // centroid x,y,z
477 convHulls[jj++] = 0f;
478 convHulls[jj++] = 0f;
479 foreach (int ind in cr.HullIndices)
480 {
481 convHulls[jj++] = verts[ind].x;
482 convHulls[jj++] = verts[ind].y;
483 convHulls[jj++] = verts[ind].z;
484 }
485 }
486 // 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);
488 hullPtr = BulletSimAPI.CreateHullShape2(PhysicsScene.World.Ptr, hullCount, convHulls);
489 }
490 newShape = new BulletShape(hullPtr, ShapeData.PhysicsShapeType.SHAPE_HULL);
491 newShape.shapeKey = newHullKey;
492
493 ReferenceShape(newShape);
494
495 // meshes are already scaled by the meshmerizer
496 prim.Scale = new OMV.Vector3(1f, 1f, 1f);
497 prim.BSShape = newShape;
498 return true; // 'true' means a new shape has been added to this prim
499 }
500
501 // Callback from convex hull creater with a newly created hull.
502 // Just add it to the collection of hulls for this shape.
503 private void HullReturn(ConvexResult result)
504 {
505 m_hulls.Add(result);
506 return;
507 }
508
509 // 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
511 // Returns 'true' if an object was actually created.
512 private bool CreateObject(bool forceRebuild, BSPrim prim, BulletSim sim, BulletShape shape, ShapeData shapeData)
513 {
514 // the mesh or hull must have already been created in Bullet
515 // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, LocalID, shape.Type);
516
517 DereferenceBody(prim.BSBody);
518
519 BulletBody aBody;
520 IntPtr bodyPtr = IntPtr.Zero;
521 if (prim.IsSolid)
522 {
523 bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.Ptr, shape.Ptr, shapeData.Position, shapeData.Rotation);
524 }
525 else
526 {
527 bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.Ptr, shape.Ptr, shapeData.Position, shapeData.Rotation);
528 }
529 aBody = new BulletBody(shapeData.ID, bodyPtr);
530
531 ReferenceBody(aBody);
532
533 prim.BSBody = aBody;
534 return true;
535 }
536
537 private void DetailLog(string msg, params Object[] args)
538 {
539 PhysicsScene.PhysicsLogging.Write(msg, args);
540 }
541
542
543
544
545
546}
547}