// Get a reference to a physical shape. Create if it doesn't exist public static BSShape GetShapeReference(BSScene physicsScene, bool forceRebuild, BSPhysObject prim) { BSShape ret = null; if (prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_CAPSULE) { // an avatar capsule is close to a native shape (it is not shared) ret = BSShapeNative.GetReference(physicsScene, prim, BSPhysicsShapeType.SHAPE_CAPSULE, FixedShapeKey.KEY_CAPSULE); physicsScene.DetailLog("{0},BSShape.GetShapeReference,avatarCapsule,shape={1}", prim.LocalID, ret); } // Compound shapes are handled special as they are rebuilt from scratch. // This isn't too great a hardship since most of the child shapes will already been created. if (ret == null && prim.PreferredPhysicalShape == BSPhysicsShapeType.SHAPE_COMPOUND) { // Getting a reference to a compound shape gets you the compound shape with the root prim shape added ret = BSShapeCompound.GetReference(prim); physicsScene.DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, ret); } if (ret == null) ret = GetShapeReferenceNonSpecial(physicsScene, forceRebuild, prim); return ret; }
private bool UseBulletSimRootOffsetHack = false; // Attempt to have Bullet track the coords of root compound shape private void RecomputeLinksetCompound() { try { Rebuilding = true; // No matter what is being done, force the root prim's PhysBody and PhysShape to get set // to what they should be as if the root was not in a linkset. // Not that bad since we only get into this routine if there are children in the linkset and // something has been updated/changed. // Have to do the rebuild before checking for physical because this might be a linkset // being destructed and going non-physical. LinksetRoot.ForceBodyShapeRebuild(true); // There is no reason to build all this physical stuff for a non-physical linkset. if (!LinksetRoot.IsPhysicallyActive) { DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,notPhysical", LinksetRoot.LocalID); return; // Note the 'finally' clause at the botton which will get executed. } // Get a new compound shape to build the linkset shape in. BSShape linksetShape = BSShapeCompound.GetReference(m_physicsScene); // Compute a displacement for each component so it is relative to the center-of-mass. // Bullet presumes an object's origin (relative <0,0,0>) is its center-of-mass OMV.Vector3 centerOfMassW = ComputeLinksetCenterOfMass(); OMV.Quaternion invRootOrientation = OMV.Quaternion.Normalize(OMV.Quaternion.Inverse(LinksetRoot.RawOrientation)); OMV.Vector3 origRootPosition = LinksetRoot.RawPosition; // 'centerDisplacementV' is the vehicle relative distance from the simulator root position to the center-of-mass OMV.Vector3 centerDisplacementV = (centerOfMassW - LinksetRoot.RawPosition) * invRootOrientation; if (UseBulletSimRootOffsetHack || !BSParam.LinksetOffsetCenterOfMass) { // Zero everything if center-of-mass displacement is not being done. centerDisplacementV = OMV.Vector3.Zero; LinksetRoot.ClearDisplacement(); } else { // The actual center-of-mass could have been set by the user. centerDisplacementV = LinksetRoot.SetEffectiveCenterOfMassDisplacement(centerDisplacementV); } DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,COM,rootPos={1},com={2},comDisp={3}", LinksetRoot.LocalID, origRootPosition, centerOfMassW, centerDisplacementV); // Add the shapes of all the components of the linkset int memberIndex = 1; ForEachMember((cPrim) => { if (IsRoot(cPrim)) { // Root shape is always index zero. cPrim.LinksetChildIndex = 0; } else { cPrim.LinksetChildIndex = memberIndex; memberIndex++; } // Get a reference to the shape of the child for adding of that shape to the linkset compound shape BSShape childShape = cPrim.PhysShape.GetReference(m_physicsScene, cPrim); // Offset the child shape from the center-of-mass and rotate it to vehicle relative. OMV.Vector3 offsetPos = (cPrim.RawPosition - origRootPosition) * invRootOrientation - centerDisplacementV; OMV.Quaternion offsetRot = OMV.Quaternion.Normalize(cPrim.RawOrientation) * invRootOrientation; // Add the child shape to the compound shape being built m_physicsScene.PE.AddChildShapeToCompoundShape(linksetShape.physShapeInfo, childShape.physShapeInfo, offsetPos, offsetRot); DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addChild,indx={1},cShape={2},offPos={3},offRot={4}", LinksetRoot.LocalID, cPrim.LinksetChildIndex, childShape, offsetPos, offsetRot); // Since we are borrowing the shape of the child, disable the origional child body if (!IsRoot(cPrim)) { m_physicsScene.PE.AddToCollisionFlags(cPrim.PhysBody, CollisionFlags.CF_NO_CONTACT_RESPONSE); m_physicsScene.PE.ForceActivationState(cPrim.PhysBody, ActivationState.DISABLE_SIMULATION); // We don't want collisions from the old linkset children. m_physicsScene.PE.RemoveFromCollisionFlags(cPrim.PhysBody, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); cPrim.PhysBody.collisionType = CollisionType.LinksetChild; } return(false); // 'false' says to move onto the next child in the list }); // Replace the root shape with the built compound shape. // Object removed and added to world to get collision cache rebuilt for new shape. LinksetRoot.PhysShape.Dereference(m_physicsScene); LinksetRoot.PhysShape = linksetShape; m_physicsScene.PE.RemoveObjectFromWorld(m_physicsScene.World, LinksetRoot.PhysBody); m_physicsScene.PE.SetCollisionShape(m_physicsScene.World, LinksetRoot.PhysBody, linksetShape.physShapeInfo); m_physicsScene.PE.AddObjectToWorld(m_physicsScene.World, LinksetRoot.PhysBody); DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addBody,body={1},shape={2}", LinksetRoot.LocalID, LinksetRoot.PhysBody, linksetShape); // With all of the linkset packed into the root prim, it has the mass of everyone. LinksetMass = ComputeLinksetMass(); LinksetRoot.UpdatePhysicalMassProperties(LinksetMass, true); if (UseBulletSimRootOffsetHack) { // Enable the physical position updator to return the position and rotation of the root shape. // This enables a feature in the C++ code to return the world coordinates of the first shape in the // compound shape. This aleviates the need to offset the returned physical position by the // center-of-mass offset. // TODO: either debug this feature or remove it. m_physicsScene.PE.AddToCollisionFlags(LinksetRoot.PhysBody, CollisionFlags.BS_RETURN_ROOT_COMPOUND_SHAPE); } } finally { Rebuilding = false; } // See that the Aabb surrounds the new shape m_physicsScene.PE.RecalculateCompoundShapeLocalAabb(LinksetRoot.PhysShape.physShapeInfo); }
public static bool TryGetCompoundByPtr(BulletShape pShape, out BSShapeCompound outCompound) { lock (CompoundShapes) { string addr = pShape.AddrString; return CompoundShapes.TryGetValue(addr, out outCompound); } }
public static BSShape GetReference(BSScene physicsScene) { // Base compound shapes are not shared so this returns a raw shape. // A built compound shape can be reused in linksets. BSShapeCompound ret = new BSShapeCompound(CreatePhysicalCompoundShape(physicsScene)); CompoundShapes.Add(ret.AddrString, ret); return ret; }
// Sometimes we have a pointer to a collision shape but don't know what type it is. // Figure out type and call the correct dereference routine. // Called at taint-time. private void DereferenceAnonCollisionShape(BSScene physicsScene, BulletShape pShape) { BSShapeMesh meshDesc; if (BSShapeMesh.TryGetMeshByPtr(pShape, out meshDesc)) { meshDesc.Dereference(physicsScene); } else { BSShapeHull hullDesc; if (BSShapeHull.TryGetHullByPtr(pShape, out hullDesc)) { hullDesc.Dereference(physicsScene); } else { BSShapeConvexHull chullDesc; if (BSShapeConvexHull.TryGetHullByPtr(pShape, out chullDesc)) { chullDesc.Dereference(physicsScene); } else { if (physicsScene.PE.IsCompound(pShape)) { BSShapeCompound recursiveCompound = new BSShapeCompound(pShape); recursiveCompound.Dereference(physicsScene); } else { if (physicsScene.PE.IsNativeShape(pShape)) { BSShapeNative nativeShape = new BSShapeNative(pShape); nativeShape.Dereference(physicsScene); } } } } } }
// Sometimes we have a pointer to a collision shape but don't know what type it is. // Figure out type and call the correct dereference routine. // Called at taint-time. private void DereferenceAnonCollisionShape(BSScene physicsScene, BulletShape pShape) { // TODO: figure a better way to go through all the shape types and find a possible instance. BSShapeMesh meshDesc; if (BSShapeMesh.TryGetMeshByPtr(pShape, out meshDesc)) { meshDesc.Dereference(physicsScene); } else { BSShapeHull hullDesc; if (BSShapeHull.TryGetHullByPtr(pShape, out hullDesc)) { hullDesc.Dereference(physicsScene); } else { BSShapeConvexHull chullDesc; if (BSShapeConvexHull.TryGetHullByPtr(pShape, out chullDesc)) { chullDesc.Dereference(physicsScene); } else { BSShapeGImpact gImpactDesc; if (BSShapeGImpact.TryGetGImpactByPtr(pShape, out gImpactDesc)) { gImpactDesc.Dereference(physicsScene); } else { // Didn't find it in the lists of specific types. It could be compound. if (physicsScene.PE.IsCompound(pShape)) { BSShapeCompound recursiveCompound = new BSShapeCompound(pShape); recursiveCompound.Dereference(physicsScene); } else { // If none of the above, maybe it is a simple native shape. if (physicsScene.PE.IsNativeShape(pShape)) { BSShapeNative nativeShape = new BSShapeNative(pShape); nativeShape.Dereference(physicsScene); } } } } } } }