// Compound shapes are always built from scratch. // This shouldn't be to bad since most of the parts will be meshes that had been built previously. private bool GetReferenceToCompoundShape(BSPhysObject prim, ShapeDestructionCallback shapeCallback) { // Remove reference to the old shape // Don't need to do this as the shape is freed when the new root shape is created below. // DereferenceShape(prim.PhysShape, true, shapeCallback); BulletShape cShape = new BulletShape( BulletSimAPI.CreateCompoundShape2(PhysicsScene.World.ptr, false), BSPhysicsShapeType.SHAPE_COMPOUND); // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape. CreateGeomMeshOrHull(prim, shapeCallback); BulletSimAPI.AddChildShapeToCompoundShape2(cShape.ptr, prim.PhysShape.ptr, OMV.Vector3.Zero, OMV.Quaternion.Identity); if (DDetail) { DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addRootPrim,compShape={1},rootShape={2}", prim.LocalID, cShape, prim.PhysShape); } prim.PhysShape = cShape; return(true); }
// Called before the simulation step to make sure the compound based linkset // is all initialized. // Constraint linksets are rebuilt every time. // Note that this works for rebuilding just the root after a linkset is taken apart. // Called at taint time!! private void RecomputeLinksetCompound() { try { // Suppress rebuilding while rebuilding Rebuilding = true; // Cause the root shape to be rebuilt as a compound object with just the root in it LinksetRoot.ForceBodyShapeRebuild(true); DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}", LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren); // Add a shape for each of the other children in the linkset ForEachMember(delegate(BSPhysObject cPrim) { if (!IsRoot(cPrim)) { // Compute the displacement of the child from the root of the linkset. // This info is saved in the child prim so the relationship does not // change over time and the new child position can be computed // when the linkset is being disassembled (the linkset may have moved). BSLinksetCompoundInfo lci = cPrim.LinksetInfo as BSLinksetCompoundInfo; if (lci == null) { // Each child position and rotation is given relative to the root. OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation); OMV.Vector3 displacementPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation; OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation; // Save relative position for recomputing child's world position after moving linkset. lci = new BSLinksetCompoundInfo(displacementPos, displacementRot); cPrim.LinksetInfo = lci; DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,creatingRelPos,lci={1}", cPrim.LocalID, lci); } DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}", LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, lci.OffsetPos, lci.OffsetRot); if (cPrim.PhysShape.isNativeShape) { // A native shape is turning into a hull collision shape because native // shapes are not shared so we have to hullify it so it will be tracked // and freed at the correct time. This also solves the scaling problem // (native shapes scaled but hull/meshes are assumed to not be). // TODO: decide of the native shape can just be used in the compound shape. // Use call to CreateGeomNonSpecial(). BulletShape saveShape = cPrim.PhysShape; cPrim.PhysShape.Clear(); // Don't let the create free the child's shape // PhysicsScene.Shapes.CreateGeomNonSpecial(true, cPrim, null); PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null); BulletShape newShape = cPrim.PhysShape; cPrim.PhysShape = saveShape; BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, newShape.ptr, lci.OffsetPos, lci.OffsetRot); } else { // For the shared shapes (meshes and hulls), just use the shape in the child. // The reference count added here will be decremented when the compound shape // is destroyed in BSShapeCollection (the child shapes are looped over and dereferenced). if (PhysicsScene.Shapes.ReferenceShape(cPrim.PhysShape)) { PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}", LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape); } BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, cPrim.PhysShape.ptr, lci.OffsetPos, lci.OffsetRot); } } return(false); // 'false' says to move onto the next child in the list }); // With all of the linkset packed into the root prim, it has the mass of everyone. LinksetMass = LinksetMass; LinksetRoot.UpdatePhysicalMassProperties(LinksetMass, true); } finally { Rebuilding = false; } BulletSimAPI.RecalculateCompoundShapeLocalAabb2(LinksetRoot.PhysShape.ptr); // DEBUG: see of inter-linkset collisions are causing problems for constraint linksets. // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); }