// When the linkset is built, the child shape is added to the compound shape relative to the // root shape. The linkset then moves around but this does not move the actual child // prim. The child prim's location must be recomputed based on the location of the root shape. private void RecomputeChildWorldPosition(BSPhysObject child, bool inTaintTime) { BSLinksetCompoundInfo lci = child.LinksetInfo as BSLinksetCompoundInfo; if (lci != null) { if (inTaintTime) { OMV.Vector3 oldPos = child.RawPosition; child.ForcePosition = LinksetRoot.RawPosition + lci.OffsetPos; child.ForceOrientation = LinksetRoot.RawOrientation * lci.OffsetRot; DetailLog("{0},BSLinksetCompound.RecomputeChildWorldPosition,oldPos={1},lci={2},newPos={3}", child.LocalID, oldPos, lci, child.RawPosition); } else { // TaintedObject is not used here so the raw position is set now and not at taint-time. child.Position = LinksetRoot.RawPosition + lci.OffsetPos; child.Orientation = LinksetRoot.RawOrientation * lci.OffsetRot; } } else { // This happens when children have been added to the linkset but the linkset // has not been constructed yet. So like, at taint time, adding children to a linkset // and then changing properties of the children (makePhysical, for instance) // but the post-print action of actually rebuilding the linkset has not yet happened. // PhysicsScene.Logger.WarnFormat("{0} Restoring linkset child position failed because of no relative position computed. ID={1}", // LogHeader, child.LocalID); DetailLog("{0},BSLinksetCompound.recomputeChildWorldPosition,noRelativePositonInfo", child.LocalID); } }
// 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; PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, newShape, 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); } PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, cPrim.PhysShape, 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 = ComputeLinksetMass(); LinksetRoot.UpdatePhysicalMassProperties(LinksetMass, true); } finally { Rebuilding = false; } PhysicsScene.PE.RecalculateCompoundShapeLocalAabb(LinksetRoot.PhysShape); }
// 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; PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, newShape, 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); } PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, cPrim.PhysShape, 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 = ComputeLinksetMass(); LinksetRoot.UpdatePhysicalMassProperties(LinksetMass, true); } finally { Rebuilding = false; } PhysicsScene.PE.RecalculateCompoundShapeLocalAabb(LinksetRoot.PhysShape); }