Exemple #1
0
    // 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;
    }
 // For compound implimented linksets, if there are children, use compound shape for the root.
 public override BSPhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor)
 { 
     // Returning 'unknown' means we don't have a preference.
     BSPhysicsShapeType ret = BSPhysicsShapeType.SHAPE_UNKNOWN;
     if (IsRoot(requestor) && HasAnyChildren)
     {
         ret = BSPhysicsShapeType.SHAPE_COMPOUND;
     }
     // DetailLog("{0},BSLinksetCompound.PreferredPhysicalShape,call,shape={1}", LinksetRoot.LocalID, ret);
     return ret;
 }
    // When physical properties are changed the linkset needs to recalculate
    //   its internal properties.
    // This is queued in the 'post taint' queue so the
    //   refresh will happen once after all the other taints are applied.
    public override void Refresh(BSPhysObject requestor)
    {
        base.Refresh(requestor);

        // Queue to happen after all the other taint processing
        PhysicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate()
            {
                if (HasAnyChildren && IsRoot(requestor))
                    RecomputeLinksetConstraints();
            });
    }
Exemple #4
0
    // Create the correct type of linkset for this child
    public static BSLinkset Factory(BSScene physScene, BSPhysObject parent)
    {
        BSLinkset ret = null;

        switch ((int)BSParam.LinksetImplementation)
        {
            case (int)LinksetImplementation.Constraint:
                ret = new BSLinksetConstraints(physScene, parent);
                break;
            case (int)LinksetImplementation.Compound:
                ret = new BSLinksetCompound(physScene, parent);
                break;
            case (int)LinksetImplementation.Manual:
                // ret = new BSLinksetManual(physScene, parent);
                break;
            default:
                ret = new BSLinksetCompound(physScene, parent);
                break;
        }
        return ret;
    }
 public void RestoreBodyDependencies(BSPhysObject prim)
 {
     if (Prim.LocalID != prim.LocalID)
     {
         // The call should be on us by our prim. Error if not.
         PhysicsScene.Logger.ErrorFormat("{0} RestoreBodyDependencies: called by not my prim. passedLocalID={1}, vehiclePrimLocalID={2}",
                         LogHeader, prim.LocalID, Prim.LocalID);
         return;
     }
     Refresh();
 }
 // Called at taint-time!!
 public override void UpdateProperties(BSPhysObject updated, bool inTaintTime)
 {
     // Nothing to do for constraints on property updates
 }
    // Remove linkage between myself and any possible children I might have.
    // Returns 'true' of any constraints were destroyed.
    // Called at taint time!
    private bool PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim)
    {
        DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID);

        return PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody);
    }
    private BSConstraint BuildConstraint(BSPhysObject rootPrim, BSPhysObject childPrim)
    {
        // Zero motion for children so they don't interpolate
        childPrim.ZeroMotion(true);

        // Relative position normalized to the root prim
        // Essentually a vector pointing from center of rootPrim to center of childPrim
        OMV.Vector3 childRelativePosition = childPrim.Position - rootPrim.Position;

        // real world coordinate of midpoint between the two objects
        OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2);

        DetailLog("{0},BSLinksetConstraint.BuildConstraint,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}",
                                        rootPrim.LocalID,
                                        rootPrim.LocalID, rootPrim.PhysBody.ptr.ToString(),
                                        childPrim.LocalID, childPrim.PhysBody.ptr.ToString(),
                                        rootPrim.Position, childPrim.Position, midPoint);

        // create a constraint that allows no freedom of movement between the two objects
        // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818

        BSConstraint6Dof constrain = new BSConstraint6Dof(
                            PhysicsScene.World, rootPrim.PhysBody, childPrim.PhysBody, midPoint, true, true );
                            // PhysicsScene.World, childPrim.BSBody, rootPrim.BSBody, midPoint, true, true );

        /* NOTE: below is an attempt to build constraint with full frame computation, etc.
         *     Using the midpoint is easier since it lets the Bullet code manipulate the transforms
         *     of the objects.
         * Code left for future programmers.
        // ==================================================================================
        // relative position normalized to the root prim
        OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation);
        OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation;

        // relative rotation of the child to the parent
        OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation;
        OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation);

        DetailLog("{0},BSLinksetConstraint.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID);
        BS6DofConstraint constrain = new BS6DofConstraint(
                        PhysicsScene.World, rootPrim.Body, childPrim.Body,
                        OMV.Vector3.Zero,
                        OMV.Quaternion.Inverse(rootPrim.Orientation),
                        OMV.Vector3.Zero,
                        OMV.Quaternion.Inverse(childPrim.Orientation),
                        true,
                        true
                        );
        // ==================================================================================
        */

        PhysicsScene.Constraints.AddConstraint(constrain);

        // zero linear and angular limits makes the objects unable to move in relation to each other
        constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);
        constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero);

        // tweek the constraint to increase stability
        constrain.UseFrameOffset(BSParam.BoolNumeric(BSParam.LinkConstraintUseFrameOffset));
        constrain.TranslationalLimitMotor(BSParam.BoolNumeric(BSParam.LinkConstraintEnableTransMotor),
                        BSParam.LinkConstraintTransMotorMaxVel,
                        BSParam.LinkConstraintTransMotorMaxForce);
        constrain.SetCFMAndERP(BSParam.LinkConstraintCFM, BSParam.LinkConstraintERP);
        if (BSParam.LinkConstraintSolverIterations != 0f)
        {
            constrain.SetSolverIterations(BSParam.LinkConstraintSolverIterations);
        }
        return constrain;
    }
    // Remove the specified child from the linkset.
    // Safe to call even if the child is not really in my linkset.
    protected override void RemoveChildFromLinkset(BSPhysObject child)
    {
        if (m_children.Remove(child))
        {
            BSPhysObject rootx = LinksetRoot; // capture the root and body as of now
            BSPhysObject childx = child;

            DetailLog("{0},BSLinksetConstraints.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}",
                            childx.LocalID,
                            rootx.LocalID, rootx.PhysBody.ptr.ToString(),
                            childx.LocalID, childx.PhysBody.ptr.ToString());

            PhysicsScene.TaintedObject("BSLinksetConstraints.RemoveChildFromLinkset", delegate()
            {
                PhysicallyUnlinkAChildFromRoot(rootx, childx);
            });
            // See that the linkset parameters are recomputed at the end of the taint time.
            Refresh(LinksetRoot);
        }
        else
        {
            // Non-fatal occurance.
            // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader);
        }
        return;
    }
Exemple #10
0
 // I am the root of a linkset and one of my children is being removed.
 // Safe to call even if the child is not really in my linkset.
 protected abstract void RemoveChildFromLinkset(BSPhysObject child);
Exemple #11
0
 // Return 'true' if the passed object is the root object of this linkset
 public bool IsRoot(BSPhysObject requestor)
 {
     return(requestor.LocalID == LinksetRoot.LocalID);
 }
 public BSLinksetCompound(BSScene scene, BSPhysObject parent) : base(scene, parent)
 {
 }
Exemple #13
0
 // Called when a parameter update comes from the physics engine for any object
 //      of the linkset is received.
 // Passed flag is update came from physics engine (true) or the user (false).
 // Called at taint-time!!
 public abstract void UpdateProperties(BSPhysObject physObject, bool physicalUpdate);
Exemple #14
0
 // The object is going static (non-physical). Do any setup necessary
 //     for a static linkset.
 // Return 'true' if any properties updated on the passed object.
 // Called at taint-time!
 public abstract bool MakeStatic(BSPhysObject child);
Exemple #15
0
 // The object is going dynamic (physical). Do any setup necessary
 //     for a dynamic linkset.
 // Only the state of the passed object can be modified. The rest of the linkset
 //     has not yet been fully constructed.
 // Return 'true' if any properties updated on the passed object.
 // Called at taint-time!
 public abstract bool MakeDynamic(BSPhysObject child);
Exemple #16
0
 // When physical properties are changed the linkset needs to recalculate
 //   its internal properties.
 // May be called at runtime or taint-time.
 public virtual void Refresh(BSPhysObject requestor)
 {
     LinksetMass = ComputeLinksetMass();
 }
Exemple #17
0
    private BSShapeNative(BSScene physicsScene, BSPhysObject prim,
                    BSPhysicsShapeType shapeType, FixedShapeKey shapeKey)
    {
        ShapeData nativeShapeData = new ShapeData();
        nativeShapeData.Type = shapeType;
        nativeShapeData.ID = prim.LocalID;
        nativeShapeData.Scale = prim.Scale;
        nativeShapeData.Size = prim.Scale;
        nativeShapeData.MeshKey = (ulong)shapeKey;
        nativeShapeData.HullKey = (ulong)shapeKey;

       
        if (shapeType == BSPhysicsShapeType.SHAPE_CAPSULE)
        {
            ptr = BulletSimAPI.BuildCapsuleShape2(physicsScene.World.ptr, 1f, 1f, prim.Scale);
            physicsScene.DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale);
        }
        else
        {
            ptr = BulletSimAPI.BuildNativeShape2(physicsScene.World.ptr, nativeShapeData);
        }
        if (ptr == null)
        {
            physicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}",
                                    LogHeader, prim.LocalID, shapeType);
        }
        type = shapeType;
        key = (UInt64)shapeKey;
    }
Exemple #18
0
 // Some linksets have a preferred physical shape.
 // Returns SHAPE_UNKNOWN if there is no preference. Causes the correct shape to be selected.
 public virtual BSPhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor)
 {
     return BSPhysicsShapeType.SHAPE_UNKNOWN;
 }
Exemple #19
0
 // I am the root of a linkset and a new child is being added
 // Called while LinkActivity is locked.
 protected abstract void AddChildToLinkset(BSPhysObject child);
Exemple #20
0
 // Link to a linkset where the child knows the parent.
 // Parent changing should not happen so do some sanity checking.
 // We return the parent's linkset so the child can track its membership.
 // Called at runtime.
 public BSLinkset AddMeToLinkset(BSPhysObject child)
 {
     lock (m_linksetActivityLock)
     {
         // Don't add the root to its own linkset
         if (!IsRoot(child))
             AddChildToLinkset(child);
         LinksetMass = ComputeLinksetMass();
     }
     return this;
 }
Exemple #21
0
    // Remove a child from a linkset.
    // Returns a new linkset for the child which is a linkset of one (just the
    //    orphened child).
    // Called at runtime.
    public BSLinkset RemoveMeFromLinkset(BSPhysObject child)
    {
        lock (m_linksetActivityLock)
        {
            if (IsRoot(child))
            {
                // Cannot remove the root from a linkset.
                return this;
            }
            RemoveChildFromLinkset(child);
            LinksetMass = ComputeLinksetMass();
        }

        // The child is down to a linkset of just itself
        return BSLinkset.Factory(PhysicsScene, child);
    }
    // ================================================================

    // Add a new child to the linkset.
    // Called while LinkActivity is locked.
    protected override void AddChildToLinkset(BSPhysObject child)
    {
        if (!HasChild(child))
        {
            m_children.Add(child);

            DetailLog("{0},BSLinksetConstraints.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID);

            // Cause constraints and assorted properties to be recomputed before the next simulation step.
            Refresh(LinksetRoot);
        }
        return;
    }
Exemple #23
0
 // Return 'true' if the passed object is the root object of this linkset
 public bool IsRoot(BSPhysObject requestor)
 {
     return (requestor.LocalID == LinksetRoot.LocalID);
 }
 // Create a constraint between me (root of linkset) and the passed prim (the child).
 // Called at taint time!
 private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim)
 {
     // Don't build the constraint when asked. Put it off until just before the simulation step.
     Refresh(rootPrim);
 }
Exemple #25
0
 // Return 'true' if this child is in this linkset
 public bool HasChild(BSPhysObject child)
 {
     bool ret = false;
     lock (m_linksetActivityLock)
     {
         ret = m_children.Contains(child);
         /* Safer version but the above should work
         foreach (BSPhysObject bp in m_children)
         {
             if (child.LocalID == bp.LocalID)
             {
                 ret = true;
                 break;
             }
         }
          */
     }
     return ret;
 }
    // Remove linkage between the linkset root and a particular child
    // The root and child bodies are passed in because we need to remove the constraint between
    //      the bodies that were present at unlink time.
    // Called at taint time!
    private bool PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim)
    {
        bool ret = false;
        DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}",
                            rootPrim.LocalID,
                            rootPrim.LocalID, rootPrim.PhysBody.ptr.ToString(),
                            childPrim.LocalID, childPrim.PhysBody.ptr.ToString());

        // Find the constraint for this link and get rid of it from the overall collection and from my list
        if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody, childPrim.PhysBody))
        {
            // Make the child refresh its location
            BulletSimAPI.PushUpdate2(childPrim.PhysBody.ptr);
            ret = true;
        }

        return ret;
    }
Exemple #27
0
 // I am the root of a linkset and a new child is being added
 // Called while LinkActivity is locked.
 protected abstract void AddChildToLinkset(BSPhysObject child);
    // private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]";

    public BSLinksetConstraints(BSScene scene, BSPhysObject parent) : base(scene, parent)
    {
    }
Exemple #29
0
 // I am the root of a linkset and one of my children is being removed.
 // Safe to call even if the child is not really in my linkset.
 protected abstract void RemoveChildFromLinkset(BSPhysObject child);
 // The object is going static (non-physical). Do any setup necessary for a static linkset.
 // Return 'true' if any properties updated on the passed object.
 // This doesn't normally happen -- OpenSim removes the objects from the physical
 //     world if it is a static linkset.
 // Called at taint-time!
 public override bool MakeStatic(BSPhysObject child)
 {
     // What is done for each object in BSPrim is what we want.
     return false;
 }
Exemple #31
0
 // When physical properties are changed the linkset needs to recalculate
 //   its internal properties.
 // May be called at runtime or taint-time.
 public virtual void Refresh(BSPhysObject requestor)
 {
     LinksetMass = ComputeLinksetMass();
 }
Exemple #32
0
 public bool RemoveBodyDependencies(BSPhysObject prim)
 {
     // If active, we need to add our properties back when the body is rebuilt.
     return IsActive;
 }
Exemple #33
0
 // The object is going dynamic (physical). Do any setup necessary
 //     for a dynamic linkset.
 // Only the state of the passed object can be modified. The rest of the linkset
 //     has not yet been fully constructed.
 // Return 'true' if any properties updated on the passed object.
 // Called at taint-time!
 public abstract bool MakeDynamic(BSPhysObject child);
Exemple #34
0
 public static BSShape GetReference(BSScene physicsScene, BSPhysObject prim, 
                 BSPhysicsShapeType shapeType, FixedShapeKey shapeKey) 
 {
     // Native shapes are not shared and are always built anew.
     return new BSShapeNative(physicsScene, prim, shapeType, shapeKey);
 }
Exemple #35
0
 // The object is going static (non-physical). Do any setup necessary
 //     for a static linkset.
 // Return 'true' if any properties updated on the passed object.
 // Called at taint-time!
 public abstract bool MakeStatic(BSPhysObject child);
Exemple #36
0
 public static BSShape GetReference(BSPhysObject prim) 
 { 
     return new BSShapeNull();
 }
Exemple #37
0
 // Called when a parameter update comes from the physics engine for any object
 //      of the linkset is received.
 // Passed flag is update came from physics engine (true) or the user (false).
 // Called at taint-time!!
 public abstract void UpdateProperties(BSPhysObject physObject, bool physicalUpdate);
Exemple #38
0
 public static BSShape GetShapeReferenceNonNative(BSScene physicsScene, bool forceRebuild, BSPhysObject prim)
 {
     return null;
 }
Exemple #39
0
 // Some linksets have a preferred physical shape.
 // Returns SHAPE_UNKNOWN if there is no preference. Causes the correct shape to be selected.
 public virtual BSPhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor)
 {
     return(BSPhysicsShapeType.SHAPE_UNKNOWN);
 }