aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics
diff options
context:
space:
mode:
authorRobert Adams2013-04-27 14:00:58 -0700
committerRobert Adams2013-04-29 07:38:35 -0700
commit890cb6a29373a54dde2d06b13e42d07676710dc2 (patch)
tree2d18a626484f9f513f997c7a3d4a092b0b9d6538 /OpenSim/Region/Physics
parentSome more pieces of Avination's ban system - if an avatar isn't allowed on any (diff)
downloadopensim-SC-890cb6a29373a54dde2d06b13e42d07676710dc2.zip
opensim-SC-890cb6a29373a54dde2d06b13e42d07676710dc2.tar.gz
opensim-SC-890cb6a29373a54dde2d06b13e42d07676710dc2.tar.bz2
opensim-SC-890cb6a29373a54dde2d06b13e42d07676710dc2.tar.xz
BulletSim: complete BSShape classes.
Diffstat (limited to 'OpenSim/Region/Physics')
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs2
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BSShapes.cs327
-rwxr-xr-xOpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt6
3 files changed, 316 insertions, 19 deletions
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
index bc26460..0f9b3c3 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs
@@ -499,7 +499,7 @@ public sealed class BSShapeCollection : IDisposable
499 } 499 }
500 500
501 // return 'true' if this shape description does not include any cutting or twisting. 501 // return 'true' if this shape description does not include any cutting or twisting.
502 private bool PrimHasNoCuts(PrimitiveBaseShape pbs) 502 public static bool PrimHasNoCuts(PrimitiveBaseShape pbs)
503 { 503 {
504 return pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0 504 return pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
505 && pbs.ProfileHollow == 0 505 && pbs.ProfileHollow == 0
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
index dd5ae1a..e427dbc 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs
@@ -31,6 +31,7 @@ using System.Text;
31 31
32using OpenSim.Framework; 32using OpenSim.Framework;
33using OpenSim.Region.Physics.Manager; 33using OpenSim.Region.Physics.Manager;
34using OpenSim.Region.Physics.ConvexDecompositionDotNet;
34 35
35using OMV = OpenMetaverse; 36using OMV = OpenMetaverse;
36 37
@@ -73,7 +74,7 @@ public abstract class BSShape
73 if (ret == null && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND) 74 if (ret == null && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND)
74 { 75 {
75 // Getting a reference to a compound shape gets you the compound shape with the root prim shape added 76 // Getting a reference to a compound shape gets you the compound shape with the root prim shape added
76 ret = BSShapeCompound.GetReference(prim); 77 ret = BSShapeCompound.GetReference(physicsScene, prim);
77 physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, ret); 78 physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, ret);
78 } 79 }
79 80
@@ -92,6 +93,7 @@ public abstract class BSShape
92 } 93 }
93 private static BSShape GetShapeReferenceNonSpecial(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) 94 private static BSShape GetShapeReferenceNonSpecial(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
94 { 95 {
96 // TODO: work needed here!!
95 BSShapeMesh.GetReference(physicsScene, forceRebuild, prim); 97 BSShapeMesh.GetReference(physicsScene, forceRebuild, prim);
96 BSShapeHull.GetReference(physicsScene, forceRebuild, prim); 98 BSShapeHull.GetReference(physicsScene, forceRebuild, prim);
97 return null; 99 return null;
@@ -209,7 +211,7 @@ public class BSShapeNative : BSShape
209public class BSShapeMesh : BSShape 211public class BSShapeMesh : BSShape
210{ 212{
211 private static string LogHeader = "[BULLETSIM SHAPE MESH]"; 213 private static string LogHeader = "[BULLETSIM SHAPE MESH]";
212 private static Dictionary<System.UInt64, BSShapeMesh> Meshes = new Dictionary<System.UInt64, BSShapeMesh>(); 214 public static Dictionary<System.UInt64, BSShapeMesh> Meshes = new Dictionary<System.UInt64, BSShapeMesh>();
213 215
214 public BSShapeMesh(BulletShape pShape) : base(pShape) 216 public BSShapeMesh(BulletShape pShape) : base(pShape)
215 { 217 {
@@ -219,10 +221,10 @@ public class BSShapeMesh : BSShape
219 float lod; 221 float lod;
220 System.UInt64 newMeshKey = BSShapeCollection.ComputeShapeKey(prim.Size, prim.BaseShape, out lod); 222 System.UInt64 newMeshKey = BSShapeCollection.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
221 223
222 physicsScene.DetailLog("{0},BSShapeMesh,create,oldKey={1},newKey={2},size={3},lod={4}", 224 physicsScene.DetailLog("{0},BSShapeMesh,getReference,oldKey={1},newKey={2},size={3},lod={4}",
223 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X"), prim.Size, lod); 225 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X"), prim.Size, lod);
224 226
225 BSShapeMesh retMesh; 227 BSShapeMesh retMesh = new BSShapeMesh(new BulletShape());
226 lock (Meshes) 228 lock (Meshes)
227 { 229 {
228 if (Meshes.TryGetValue(newMeshKey, out retMesh)) 230 if (Meshes.TryGetValue(newMeshKey, out retMesh))
@@ -233,13 +235,17 @@ public class BSShapeMesh : BSShape
233 else 235 else
234 { 236 {
235 // An instance of this mesh has not been created. Build and remember same. 237 // An instance of this mesh has not been created. Build and remember same.
236 BulletShape newShape = CreatePhysicalMesh(physicsScene, prim, newMeshKey, prim.BaseShape, prim.Size, lod); 238 BulletShape newShape = retMesh.CreatePhysicalMesh(physicsScene, prim, newMeshKey, prim.BaseShape, prim.Size, lod);
237 // Take evasive action if the mesh was not constructed.
238 newShape = BSShapeCollection.VerifyMeshCreated(physicsScene, newShape, prim);
239 239
240 retMesh = new BSShapeMesh(newShape); 240 // Check to see if mesh was created (might require an asset).
241 newShape = BSShapeCollection.VerifyMeshCreated(physicsScene, newShape, prim);
242 if (newShape.type == BSPhysicsShapeType.SHAPE_MESH)
243 {
244 // If a mesh was what was created, remember the built shape for later sharing.
245 Meshes.Add(newMeshKey, retMesh);
246 }
241 247
242 Meshes.Add(newMeshKey, retMesh); 248 retMesh.physShapeInfo = newShape;
243 } 249 }
244 } 250 }
245 return retMesh; 251 return retMesh;
@@ -252,8 +258,28 @@ public class BSShapeMesh : BSShape
252 // TODO: schedule aging and destruction of unused meshes. 258 // TODO: schedule aging and destruction of unused meshes.
253 } 259 }
254 } 260 }
261 // Loop through all the known meshes and return the description based on the physical address.
262 public static bool TryGetMeshByPtr(BulletShape pShape, out BSShapeMesh outMesh)
263 {
264 bool ret = false;
265 BSShapeMesh foundDesc = null;
266 lock (Meshes)
267 {
268 foreach (BSShapeMesh sm in Meshes.Values)
269 {
270 if (sm.physShapeInfo.ReferenceSame(pShape))
271 {
272 foundDesc = sm;
273 ret = true;
274 break;
275 }
255 276
256 private static BulletShape CreatePhysicalMesh(BSScene physicsScene, BSPhysObject prim, System.UInt64 newMeshKey, 277 }
278 }
279 outMesh = foundDesc;
280 return ret;
281 }
282 private BulletShape CreatePhysicalMesh(BSScene physicsScene, BSPhysObject prim, System.UInt64 newMeshKey,
257 PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) 283 PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
258 { 284 {
259 BulletShape newShape = null; 285 BulletShape newShape = null;
@@ -326,32 +352,301 @@ public class BSShapeMesh : BSShape
326public class BSShapeHull : BSShape 352public class BSShapeHull : BSShape
327{ 353{
328 private static string LogHeader = "[BULLETSIM SHAPE HULL]"; 354 private static string LogHeader = "[BULLETSIM SHAPE HULL]";
329 private static Dictionary<System.UInt64, BSShapeHull> Hulls = new Dictionary<System.UInt64, BSShapeHull>(); 355 public static Dictionary<System.UInt64, BSShapeHull> Hulls = new Dictionary<System.UInt64, BSShapeHull>();
330 356
331 public BSShapeHull(BulletShape pShape) : base(pShape) 357 public BSShapeHull(BulletShape pShape) : base(pShape)
332 { 358 {
333 } 359 }
334 public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) 360 public static BSShape GetReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
335 { 361 {
336 return new BSShapeNull(); 362 float lod;
363 System.UInt64 newHullKey = BSShapeCollection.ComputeShapeKey(prim.Size, prim.BaseShape, out lod);
364
365 physicsScene.DetailLog("{0},BSShapeHull,getReference,oldKey={1},newKey={2},size={3},lod={4}",
366 prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X"), prim.Size, lod);
367
368 BSShapeHull retHull = new BSShapeHull(new BulletShape());
369 lock (Hulls)
370 {
371 if (Hulls.TryGetValue(newHullKey, out retHull))
372 {
373 // The mesh has already been created. Return a new reference to same.
374 retHull.IncrementReference();
375 }
376 else
377 {
378 // An instance of this mesh has not been created. Build and remember same.
379 BulletShape newShape = retHull.CreatePhysicalHull(physicsScene, prim, newHullKey, prim.BaseShape, prim.Size, lod);
380
381 // Check to see if mesh was created (might require an asset).
382 newShape = BSShapeCollection.VerifyMeshCreated(physicsScene, newShape, prim);
383 if (newShape.type == BSPhysicsShapeType.SHAPE_MESH)
384 {
385 // If a mesh was what was created, remember the built shape for later sharing.
386 Hulls.Add(newHullKey, retHull);
387 }
388
389 retHull = new BSShapeHull(newShape);
390 retHull.physShapeInfo = newShape;
391 }
392 }
393 return retHull;
337 } 394 }
338 public override void Dereference(BSScene physicsScene) 395 public override void Dereference(BSScene physicsScene)
339 { 396 {
340 } 397 }
398 List<ConvexResult> m_hulls;
399 private BulletShape CreatePhysicalHull(BSScene physicsScene, BSPhysObject prim, System.UInt64 newHullKey,
400 PrimitiveBaseShape pbs, OMV.Vector3 size, float lod)
401 {
402 BulletShape newShape = new BulletShape();
403 IntPtr hullPtr = IntPtr.Zero;
404
405 if (BSParam.ShouldUseBulletHACD)
406 {
407 physicsScene.DetailLog("{0},BSShapeCollection.CreatePhysicalHull,shouldUseBulletHACD,entry", prim.LocalID);
408 BSShape meshShape = BSShapeMesh.GetReference(physicsScene, true, prim);
409
410 if (meshShape.physShapeInfo.HasPhysicalShape)
411 {
412 HACDParams parms;
413 parms.maxVerticesPerHull = BSParam.BHullMaxVerticesPerHull;
414 parms.minClusters = BSParam.BHullMinClusters;
415 parms.compacityWeight = BSParam.BHullCompacityWeight;
416 parms.volumeWeight = BSParam.BHullVolumeWeight;
417 parms.concavity = BSParam.BHullConcavity;
418 parms.addExtraDistPoints = BSParam.NumericBool(BSParam.BHullAddExtraDistPoints);
419 parms.addNeighboursDistPoints = BSParam.NumericBool(BSParam.BHullAddNeighboursDistPoints);
420 parms.addFacesPoints = BSParam.NumericBool(BSParam.BHullAddFacesPoints);
421 parms.shouldAdjustCollisionMargin = BSParam.NumericBool(BSParam.BHullShouldAdjustCollisionMargin);
422
423 physicsScene.DetailLog("{0},BSShapeCollection.CreatePhysicalHull,hullFromMesh,beforeCall", prim.LocalID, newShape.HasPhysicalShape);
424 newShape = physicsScene.PE.BuildHullShapeFromMesh(physicsScene.World, meshShape.physShapeInfo, parms);
425 physicsScene.DetailLog("{0},BSShapeCollection.CreatePhysicalHull,hullFromMesh,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
426 }
427 // Now done with the mesh shape.
428 meshShape.DecrementReference();
429 physicsScene.DetailLog("{0},BSShapeCollection.CreatePhysicalHull,shouldUseBulletHACD,exit,hasBody={1}", prim.LocalID, newShape.HasPhysicalShape);
430 }
431 if (!newShape.HasPhysicalShape)
432 {
433 // Build a new hull in the physical world.
434 // Pass true for physicalness as this prevents the creation of bounding box which is not needed
435 IMesh meshData = physicsScene.mesher.CreateMesh(prim.PhysObjectName, pbs, size, lod, true /* isPhysical */, false /* shouldCache */);
436 if (meshData != null)
437 {
438 int[] indices = meshData.getIndexListAsInt();
439 List<OMV.Vector3> vertices = meshData.getVertexList();
440
441 //format conversion from IMesh format to DecompDesc format
442 List<int> convIndices = new List<int>();
443 List<float3> convVertices = new List<float3>();
444 for (int ii = 0; ii < indices.GetLength(0); ii++)
445 {
446 convIndices.Add(indices[ii]);
447 }
448 foreach (OMV.Vector3 vv in vertices)
449 {
450 convVertices.Add(new float3(vv.X, vv.Y, vv.Z));
451 }
452
453 uint maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplit;
454 if (BSParam.CSHullMaxDepthSplit != BSParam.CSHullMaxDepthSplitForSimpleShapes)
455 {
456 // Simple primitive shapes we know are convex so they are better implemented with
457 // fewer hulls.
458 // Check for simple shape (prim without cuts) and reduce split parameter if so.
459 if (BSShapeCollection.PrimHasNoCuts(pbs))
460 {
461 maxDepthSplit = (uint)BSParam.CSHullMaxDepthSplitForSimpleShapes;
462 }
463 }
464
465 // setup and do convex hull conversion
466 m_hulls = new List<ConvexResult>();
467 DecompDesc dcomp = new DecompDesc();
468 dcomp.mIndices = convIndices;
469 dcomp.mVertices = convVertices;
470 dcomp.mDepth = maxDepthSplit;
471 dcomp.mCpercent = BSParam.CSHullConcavityThresholdPercent;
472 dcomp.mPpercent = BSParam.CSHullVolumeConservationThresholdPercent;
473 dcomp.mMaxVertices = (uint)BSParam.CSHullMaxVertices;
474 dcomp.mSkinWidth = BSParam.CSHullMaxSkinWidth;
475 ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn);
476 // create the hull into the _hulls variable
477 convexBuilder.process(dcomp);
478
479 physicsScene.DetailLog("{0},BSShapeCollection.CreatePhysicalHull,key={1},inVert={2},inInd={3},split={4},hulls={5}",
480 BSScene.DetailLogZero, newHullKey, indices.GetLength(0), vertices.Count, maxDepthSplit, m_hulls.Count);
481
482 // Convert the vertices and indices for passing to unmanaged.
483 // The hull information is passed as a large floating point array.
484 // The format is:
485 // convHulls[0] = number of hulls
486 // convHulls[1] = number of vertices in first hull
487 // convHulls[2] = hull centroid X coordinate
488 // convHulls[3] = hull centroid Y coordinate
489 // convHulls[4] = hull centroid Z coordinate
490 // convHulls[5] = first hull vertex X
491 // convHulls[6] = first hull vertex Y
492 // convHulls[7] = first hull vertex Z
493 // convHulls[8] = second hull vertex X
494 // ...
495 // convHulls[n] = number of vertices in second hull
496 // convHulls[n+1] = second hull centroid X coordinate
497 // ...
498 //
499 // TODO: is is very inefficient. Someday change the convex hull generator to return
500 // data structures that do not need to be converted in order to pass to Bullet.
501 // And maybe put the values directly into pinned memory rather than marshaling.
502 int hullCount = m_hulls.Count;
503 int totalVertices = 1; // include one for the count of the hulls
504 foreach (ConvexResult cr in m_hulls)
505 {
506 totalVertices += 4; // add four for the vertex count and centroid
507 totalVertices += cr.HullIndices.Count * 3; // we pass just triangles
508 }
509 float[] convHulls = new float[totalVertices];
510
511 convHulls[0] = (float)hullCount;
512 int jj = 1;
513 foreach (ConvexResult cr in m_hulls)
514 {
515 // copy vertices for index access
516 float3[] verts = new float3[cr.HullVertices.Count];
517 int kk = 0;
518 foreach (float3 ff in cr.HullVertices)
519 {
520 verts[kk++] = ff;
521 }
522
523 // add to the array one hull's worth of data
524 convHulls[jj++] = cr.HullIndices.Count;
525 convHulls[jj++] = 0f; // centroid x,y,z
526 convHulls[jj++] = 0f;
527 convHulls[jj++] = 0f;
528 foreach (int ind in cr.HullIndices)
529 {
530 convHulls[jj++] = verts[ind].x;
531 convHulls[jj++] = verts[ind].y;
532 convHulls[jj++] = verts[ind].z;
533 }
534 }
535 // create the hull data structure in Bullet
536 newShape = physicsScene.PE.CreateHullShape(physicsScene.World, hullCount, convHulls);
537 }
538 newShape.shapeKey = newHullKey;
539 }
540 return newShape;
541 }
542 // Callback from convex hull creater with a newly created hull.
543 // Just add it to our collection of hulls for this shape.
544 private void HullReturn(ConvexResult result)
545 {
546 m_hulls.Add(result);
547 return;
548 }
549 // Loop through all the known hulls and return the description based on the physical address.
550 public static bool TryGetHullByPtr(BulletShape pShape, out BSShapeHull outHull)
551 {
552 bool ret = false;
553 BSShapeHull foundDesc = null;
554 lock (Hulls)
555 {
556 foreach (BSShapeHull sh in Hulls.Values)
557 {
558 if (sh.physShapeInfo.ReferenceSame(pShape))
559 {
560 foundDesc = sh;
561 ret = true;
562 break;
563 }
564
565 }
566 }
567 outHull = foundDesc;
568 return ret;
569 }
341} 570}
342 571
572
343// ============================================================================================================ 573// ============================================================================================================
344public class BSShapeCompound : BSShape 574public class BSShapeCompound : BSShape
345{ 575{
346 private static string LogHeader = "[BULLETSIM SHAPE COMPOUND]"; 576 private static string LogHeader = "[BULLETSIM SHAPE COMPOUND]";
347 public BSShapeCompound() : base() 577 public BSShapeCompound(BulletShape pShape) : base(pShape)
348 { 578 {
349 } 579 }
350 public static BSShape GetReference(BSPhysObject prim) 580 public static BSShape GetReference(BSScene physicsScene, BSPhysObject prim)
351 { 581 {
352 return new BSShapeNull(); 582 // Compound shapes are not shared so a new one is created every time.
583 return new BSShapeCompound(CreatePhysicalCompoundShape(physicsScene, prim));
584 }
585 // Dereferencing a compound shape releases the hold on all the child shapes.
586 public override void Dereference(BSScene physicsScene)
587 {
588 if (!physicsScene.PE.IsCompound(physShapeInfo))
589 {
590 // Failed the sanity check!!
591 physicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}",
592 LogHeader, physShapeInfo.type, physShapeInfo.AddrString);
593 physicsScene.DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}",
594 BSScene.DetailLogZero, physShapeInfo.type, physShapeInfo.AddrString);
595 return;
596 }
597
598 int numChildren = physicsScene.PE.GetNumberOfCompoundChildren(physShapeInfo);
599 physicsScene.DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}",
600 BSScene.DetailLogZero, physShapeInfo, numChildren);
601
602 // Loop through all the children dereferencing each.
603 for (int ii = numChildren - 1; ii >= 0; ii--)
604 {
605 BulletShape childShape = physicsScene.PE.RemoveChildShapeFromCompoundShapeIndex(physShapeInfo, ii);
606 DereferenceAnonCollisionShape(physicsScene, childShape);
607 }
608 physicsScene.PE.DeleteCollisionShape(physicsScene.World, physShapeInfo);
609 }
610 private static BulletShape CreatePhysicalCompoundShape(BSScene physicsScene, BSPhysObject prim)
611 {
612 BulletShape cShape = physicsScene.PE.CreateCompoundShape(physicsScene.World, false);
613 return cShape;
614 }
615 // Sometimes we have a pointer to a collision shape but don't know what type it is.
616 // Figure out type and call the correct dereference routine.
617 // Called at taint-time.
618 private void DereferenceAnonCollisionShape(BSScene physicsScene, BulletShape pShape)
619 {
620 BSShapeMesh meshDesc;
621 if (BSShapeMesh.TryGetMeshByPtr(pShape, out meshDesc))
622 {
623 meshDesc.Dereference(physicsScene);
624 }
625 else
626 {
627 BSShapeHull hullDesc;
628 if (BSShapeHull.TryGetHullByPtr(pShape, out hullDesc))
629 {
630 hullDesc.Dereference(physicsScene);
631 }
632 else
633 {
634 if (physicsScene.PE.IsCompound(pShape))
635 {
636 BSShapeCompound recursiveCompound = new BSShapeCompound(pShape);
637 recursiveCompound.Dereference(physicsScene);
638 }
639 else
640 {
641 if (physicsScene.PE.IsNativeShape(pShape))
642 {
643 BSShapeNative nativeShape = new BSShapeNative(pShape);
644 nativeShape.Dereference(physicsScene);
645 }
646 }
647 }
648 }
353 } 649 }
354 public override void Dereference(BSScene physicsScene) { }
355} 650}
356 651
357// ============================================================================================================ 652// ============================================================================================================
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
index 1284ae7..c67081a 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
+++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt
@@ -11,6 +11,8 @@ Deleting a linkset while standing on the root will leave the physical shape of t
11Linkset child rotations. 11Linkset child rotations.
12 Nebadon spiral tube has middle sections which are rotated wrong. 12 Nebadon spiral tube has middle sections which are rotated wrong.
13 Select linked spiral tube. Delink and note where the middle section ends up. 13 Select linked spiral tube. Delink and note where the middle section ends up.
14Refarb compound linkset creation to create a pseudo-root for center-of-mass
15 Let children change their shape to physical indendently and just add shapes to compound
14Vehicle angular vertical attraction 16Vehicle angular vertical attraction
15vehicle angular banking 17vehicle angular banking
16Center-of-gravity 18Center-of-gravity
@@ -27,14 +29,13 @@ llLookAt
27Avatars walking up stairs (HALF DONE) 29Avatars walking up stairs (HALF DONE)
28Avatar movement 30Avatar movement
29 flying into a wall doesn't stop avatar who keeps appearing to move through the obstacle (DONE) 31 flying into a wall doesn't stop avatar who keeps appearing to move through the obstacle (DONE)
30 walking up stairs is not calibrated correctly (stairs out of Kepler cabin) 32 walking up stairs is not calibrated correctly (stairs out of Kepler cabin) (DONE)
31 avatar capsule rotation completed (NOT DONE - Bullet's capsule shape is not the solution) 33 avatar capsule rotation completed (NOT DONE - Bullet's capsule shape is not the solution)
32Vehicle script tuning/debugging 34Vehicle script tuning/debugging
33 Avanti speed script 35 Avanti speed script
34 Weapon shooter script 36 Weapon shooter script
35Move material definitions (friction, ...) into simulator. 37Move material definitions (friction, ...) into simulator.
36Add material densities to the material types. 38Add material densities to the material types.
37Terrain detail: double terrain mesh detail
38One sided meshes? Should terrain be built into a closed shape? 39One sided meshes? Should terrain be built into a closed shape?
39 When meshes get partially wedged into the terrain, they cannot push themselves out. 40 When meshes get partially wedged into the terrain, they cannot push themselves out.
40 It is possible that Bullet processes collisions whether entering or leaving a mesh. 41 It is possible that Bullet processes collisions whether entering or leaving a mesh.
@@ -347,4 +348,5 @@ Angular motion around Z moves the vehicle in world Z and not vehicle Z in ODE.
347 DONE 20130120: BulletSim properly applies force in vehicle relative coordinates. 348 DONE 20130120: BulletSim properly applies force in vehicle relative coordinates.
348Nebadon vehicles turning funny in arena (DONE) 349Nebadon vehicles turning funny in arena (DONE)
349Lock axis (DONE 20130401) 350Lock axis (DONE 20130401)
351Terrain detail: double terrain mesh detail (DONE)
350 352