コード例 #1
0
ファイル: BSLinkset.cs プロジェクト: BogusCurry/opensim-1
        public bool TryGetLinkInfo(BSPrimLinkable child, out BSLinkInfo foundInfo)
        {
            bool       ret   = false;
            BSLinkInfo found = null;

            lock (m_linksetActivityLock)
            {
                ret = m_children.TryGetValue(child, out found);
            }
            foundInfo = found;
            return(ret);
        }
コード例 #2
0
 public bool TryGetLinkInfo(BSPrimLinkable child, out BSLinkInfo foundInfo)
 {
     m_linksetActivityLock.AcquireReaderLock(-1);
     try
     {
         return(m_children.TryGetValue(child, out foundInfo));
     }
     finally
     {
         m_linksetActivityLock.ReleaseReaderLock();
     }
 }
コード例 #3
0
        public bool TryGetLinkInfo(BSPrimLinkable child, out BSLinkInfo foundInfo)
        {
            bool       ret   = false;
            BSLinkInfo found = null;

            m_linksetActivityLock.AcquireReaderLock(-1);
            try
            {
                ret = m_children.TryGetValue(child, out found);
            }
            finally
            {
                m_linksetActivityLock.ReleaseReaderLock();
            }
            foundInfo = found;
            return(ret);
        }
コード例 #4
0
    // Create a static constraint between the two passed objects
    private BSConstraint BuildConstraint(BSPrimLinkable rootPrim, BSLinkInfo li)
    {
        BSLinkInfoConstraint linkInfo = li as BSLinkInfoConstraint;
        if (linkInfo == null)
            return null;

        // Zero motion for children so they don't interpolate
        li.member.ZeroMotion(true);

        BSConstraint constrain = null;

        switch (linkInfo.constraintType)
        {
            case ConstraintType.BS_FIXED_CONSTRAINT_TYPE:
            case ConstraintType.D6_CONSTRAINT_TYPE:
                // Relative position normalized to the root prim
                // Essentually a vector pointing from center of rootPrim to center of li.member
                OMV.Vector3 childRelativePosition = linkInfo.member.Position - rootPrim.Position;

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

                DetailLog("{0},BSLinksetConstraint.BuildConstraint,6Dof,rBody={1},cBody={2},rLoc={3},cLoc={4},midLoc={5}",
                                                rootPrim.LocalID, rootPrim.PhysBody, linkInfo.member.PhysBody,
                                                rootPrim.Position, linkInfo.member.Position, midPoint);

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

                constrain = new BSConstraint6Dof(
                                    m_physicsScene.World, rootPrim.PhysBody, linkInfo.member.PhysBody, 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 = (liConstraint.member.Position - rootPrim.Position) * invThisOrientation;

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

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

                break;
            case ConstraintType.D6_SPRING_CONSTRAINT_TYPE:
                constrain = new BSConstraintSpring(m_physicsScene.World, rootPrim.PhysBody, linkInfo.member.PhysBody,
                                linkInfo.frameInAloc, linkInfo.frameInArot, linkInfo.frameInBloc, linkInfo.frameInBrot,
                                linkInfo.useLinearReferenceFrameA,
                                true /*disableCollisionsBetweenLinkedBodies*/);
                DetailLog("{0},BSLinksetConstraint.BuildConstraint,spring,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6}",
                                                rootPrim.LocalID,
                                                rootPrim.LocalID, rootPrim.PhysBody.AddrString,
                                                linkInfo.member.LocalID, linkInfo.member.PhysBody.AddrString,
                                                rootPrim.Position, linkInfo.member.Position);

                break;
            default:
                break;
        }

        linkInfo.SetLinkParameters(constrain);

        m_physicsScene.Constraints.AddConstraint(constrain);

        return constrain;
    }
コード例 #5
0
ファイル: BSLinkset.cs プロジェクト: BogusCurry/arribasim-dev
 public bool TryGetLinkInfo(BSPrimLinkable child, out BSLinkInfo foundInfo)
 {
     m_linksetActivityLock.AcquireReaderLock(-1);
     try
     {
         return m_children.TryGetValue(child, out foundInfo);
     }
     finally
     {
         m_linksetActivityLock.ReleaseReaderLock();
     }
 }
コード例 #6
0
ファイル: BSLinkset.cs プロジェクト: Kubwa/opensim
 public bool TryGetLinkInfo(BSPrimLinkable child, out BSLinkInfo foundInfo)
 {
     bool ret = false;
     BSLinkInfo found = null;
     lock (m_linksetActivityLock)
     {
         ret = m_children.TryGetValue(child, out found);
     }
     foundInfo = found;
     return ret;
 }
コード例 #7
0
        public override object Extension(string pFunct, params object[] pParams)
        {
            object ret = null;

            switch (pFunct)
            {
            // pParams = [ BSPhysObject root, BSPhysObject child, integer linkType ]
            case ExtendedPhysics.PhysFunctChangeLinkType:
                if (pParams.Length > 2)
                {
                    int requestedType = (int)pParams[2];
                    DetailLog("{0},BSLinksetConstraint.ChangeLinkType,requestedType={1}", LinksetRoot.LocalID, requestedType);
                    if (requestedType == (int)ConstraintType.BS_FIXED_CONSTRAINT_TYPE ||
                        requestedType == (int)ConstraintType.D6_CONSTRAINT_TYPE ||
                        requestedType == (int)ConstraintType.D6_SPRING_CONSTRAINT_TYPE ||
                        requestedType == (int)ConstraintType.HINGE_CONSTRAINT_TYPE ||
                        requestedType == (int)ConstraintType.CONETWIST_CONSTRAINT_TYPE ||
                        requestedType == (int)ConstraintType.SLIDER_CONSTRAINT_TYPE)
                    {
                        BSPrimLinkable child = pParams[1] as BSPrimLinkable;
                        if (child != null)
                        {
                            DetailLog("{0},BSLinksetConstraint.ChangeLinkType,rootID={1},childID={2},type={3}",
                                      LinksetRoot.LocalID, LinksetRoot.LocalID, child.LocalID, requestedType);
                            m_physicsScene.TaintedObject(child.LocalID, "BSLinksetConstraint.PhysFunctChangeLinkType", delegate()
                            {
                                // Pick up all the constraints currently created.
                                RemoveDependencies(child);

                                BSLinkInfo linkInfo = null;
                                if (TryGetLinkInfo(child, out linkInfo))
                                {
                                    BSLinkInfoConstraint linkInfoC = linkInfo as BSLinkInfoConstraint;
                                    if (linkInfoC != null)
                                    {
                                        linkInfoC.constraintType = (ConstraintType)requestedType;
                                        ret = (object)true;
                                        DetailLog("{0},BSLinksetConstraint.ChangeLinkType,link={1},type={2}",
                                                  linkInfo.member.LocalID, linkInfo.member.LocalID, linkInfoC.constraintType);
                                    }
                                    else
                                    {
                                        DetailLog("{0},BSLinksetConstraint.ChangeLinkType,linkInfoNotConstraint,childID={1}", LinksetRoot.LocalID, child.LocalID);
                                    }
                                }
                                else
                                {
                                    DetailLog("{0},BSLinksetConstraint.ChangeLinkType,noLinkInfoForChild,childID={1}", LinksetRoot.LocalID, child.LocalID);
                                }
                                // Cause the whole linkset to be rebuilt in post-taint time.
                                Refresh(child);
                            });
                        }
                        else
                        {
                            DetailLog("{0},BSLinksetConstraint.SetLinkType,childNotBSPrimLinkable", LinksetRoot.LocalID);
                        }
                    }
                    else
                    {
                        DetailLog("{0},BSLinksetConstraint.SetLinkType,illegalRequestedType,reqested={1},spring={2}",
                                  LinksetRoot.LocalID, requestedType, ((int)ConstraintType.D6_SPRING_CONSTRAINT_TYPE));
                    }
                }
                break;

            // pParams = [ BSPhysObject root, BSPhysObject child ]
            case ExtendedPhysics.PhysFunctGetLinkType:
                if (pParams.Length > 0)
                {
                    BSPrimLinkable child = pParams[1] as BSPrimLinkable;
                    if (child != null)
                    {
                        BSLinkInfo linkInfo = null;
                        if (TryGetLinkInfo(child, out linkInfo))
                        {
                            BSLinkInfoConstraint linkInfoC = linkInfo as BSLinkInfoConstraint;
                            if (linkInfoC != null)
                            {
                                ret = (object)(int)linkInfoC.constraintType;
                                DetailLog("{0},BSLinksetConstraint.GetLinkType,link={1},type={2}",
                                          linkInfo.member.LocalID, linkInfo.member.LocalID, linkInfoC.constraintType);
                            }
                        }
                    }
                }
                break;

            // pParams = [ BSPhysObject root, BSPhysObject child, int op, object opParams, int op, object opParams, ... ]
            case ExtendedPhysics.PhysFunctChangeLinkParams:
                // There should be two parameters: the childActor and a list of parameters to set
                if (pParams.Length > 2)
                {
                    BSPrimLinkable child        = pParams[1] as BSPrimLinkable;
                    BSLinkInfo     baseLinkInfo = null;
                    if (TryGetLinkInfo(child, out baseLinkInfo))
                    {
                        BSLinkInfoConstraint linkInfo = baseLinkInfo as BSLinkInfoConstraint;
                        if (linkInfo != null)
                        {
                            int            valueInt;
                            float          valueFloat;
                            bool           valueBool;
                            OMV.Vector3    valueVector;
                            OMV.Vector3    valueVector2;
                            OMV.Quaternion valueQuaternion;
                            int            axisLow, axisHigh;

                            int opIndex = 2;
                            while (opIndex < pParams.Length)
                            {
                                int    thisOp = 0;
                                string errMsg = "";
                                try
                                {
                                    thisOp = (int)pParams[opIndex];
                                    DetailLog("{0},BSLinksetConstraint.ChangeLinkParams2,op={1},val={2}",
                                              linkInfo.member.LocalID, thisOp, pParams[opIndex + 1]);
                                    switch (thisOp)
                                    {
                                    case ExtendedPhysics.PHYS_PARAM_LINK_TYPE:
                                        valueInt = (int)pParams[opIndex + 1];
                                        ConstraintType valueType = (ConstraintType)valueInt;
                                        if (valueType == ConstraintType.BS_FIXED_CONSTRAINT_TYPE ||
                                            valueType == ConstraintType.D6_CONSTRAINT_TYPE ||
                                            valueType == ConstraintType.D6_SPRING_CONSTRAINT_TYPE ||
                                            valueType == ConstraintType.HINGE_CONSTRAINT_TYPE ||
                                            valueType == ConstraintType.CONETWIST_CONSTRAINT_TYPE ||
                                            valueType == ConstraintType.SLIDER_CONSTRAINT_TYPE)
                                        {
                                            linkInfo.constraintType = valueType;
                                        }
                                        opIndex += 2;
                                        break;

                                    case ExtendedPhysics.PHYS_PARAM_FRAMEINA_LOC:
                                        errMsg               = "PHYS_PARAM_FRAMEINA_LOC takes one parameter of type vector";
                                        valueVector          = (OMV.Vector3)pParams[opIndex + 1];
                                        linkInfo.frameInAloc = valueVector;
                                        opIndex             += 2;
                                        break;

                                    case ExtendedPhysics.PHYS_PARAM_FRAMEINA_ROT:
                                        errMsg               = "PHYS_PARAM_FRAMEINA_ROT takes one parameter of type rotation";
                                        valueQuaternion      = (OMV.Quaternion)pParams[opIndex + 1];
                                        linkInfo.frameInArot = valueQuaternion;
                                        opIndex             += 2;
                                        break;

                                    case ExtendedPhysics.PHYS_PARAM_FRAMEINB_LOC:
                                        errMsg               = "PHYS_PARAM_FRAMEINB_LOC takes one parameter of type vector";
                                        valueVector          = (OMV.Vector3)pParams[opIndex + 1];
                                        linkInfo.frameInBloc = valueVector;
                                        opIndex             += 2;
                                        break;

                                    case ExtendedPhysics.PHYS_PARAM_FRAMEINB_ROT:
                                        errMsg               = "PHYS_PARAM_FRAMEINB_ROT takes one parameter of type rotation";
                                        valueQuaternion      = (OMV.Quaternion)pParams[opIndex + 1];
                                        linkInfo.frameInBrot = valueQuaternion;
                                        opIndex             += 2;
                                        break;

                                    case ExtendedPhysics.PHYS_PARAM_LINEAR_LIMIT_LOW:
                                        errMsg                  = "PHYS_PARAM_LINEAR_LIMIT_LOW takes one parameter of type vector";
                                        valueVector             = (OMV.Vector3)pParams[opIndex + 1];
                                        linkInfo.linearLimitLow = valueVector;
                                        opIndex                += 2;
                                        break;

                                    case ExtendedPhysics.PHYS_PARAM_LINEAR_LIMIT_HIGH:
                                        errMsg      = "PHYS_PARAM_LINEAR_LIMIT_HIGH takes one parameter of type vector";
                                        valueVector = (OMV.Vector3)pParams[opIndex + 1];
                                        linkInfo.linearLimitHigh = valueVector;
                                        opIndex += 2;
                                        break;

                                    case ExtendedPhysics.PHYS_PARAM_ANGULAR_LIMIT_LOW:
                                        errMsg      = "PHYS_PARAM_ANGULAR_LIMIT_LOW takes one parameter of type vector";
                                        valueVector = (OMV.Vector3)pParams[opIndex + 1];
                                        linkInfo.angularLimitLow = valueVector;
                                        opIndex += 2;
                                        break;

                                    case ExtendedPhysics.PHYS_PARAM_ANGULAR_LIMIT_HIGH:
                                        errMsg      = "PHYS_PARAM_ANGULAR_LIMIT_HIGH takes one parameter of type vector";
                                        valueVector = (OMV.Vector3)pParams[opIndex + 1];
                                        linkInfo.angularLimitHigh = valueVector;
                                        opIndex += 2;
                                        break;

                                    case ExtendedPhysics.PHYS_PARAM_USE_FRAME_OFFSET:
                                        errMsg    = "PHYS_PARAM_USE_FRAME_OFFSET takes one parameter of type integer (bool)";
                                        valueBool = ((int)pParams[opIndex + 1]) != 0;
                                        linkInfo.useFrameOffset = valueBool;
                                        opIndex += 2;
                                        break;

                                    case ExtendedPhysics.PHYS_PARAM_ENABLE_TRANSMOTOR:
                                        errMsg    = "PHYS_PARAM_ENABLE_TRANSMOTOR takes one parameter of type integer (bool)";
                                        valueBool = ((int)pParams[opIndex + 1]) != 0;
                                        linkInfo.enableTransMotor = valueBool;
                                        opIndex += 2;
                                        break;

                                    case ExtendedPhysics.PHYS_PARAM_TRANSMOTOR_MAXVEL:
                                        errMsg     = "PHYS_PARAM_TRANSMOTOR_MAXVEL takes one parameter of type float";
                                        valueFloat = (float)pParams[opIndex + 1];
                                        linkInfo.transMotorMaxVel = valueFloat;
                                        opIndex += 2;
                                        break;

                                    case ExtendedPhysics.PHYS_PARAM_TRANSMOTOR_MAXFORCE:
                                        errMsg     = "PHYS_PARAM_TRANSMOTOR_MAXFORCE takes one parameter of type float";
                                        valueFloat = (float)pParams[opIndex + 1];
                                        linkInfo.transMotorMaxForce = valueFloat;
                                        opIndex += 2;
                                        break;

                                    case ExtendedPhysics.PHYS_PARAM_CFM:
                                        errMsg       = "PHYS_PARAM_CFM takes one parameter of type float";
                                        valueFloat   = (float)pParams[opIndex + 1];
                                        linkInfo.cfm = valueFloat;
                                        opIndex     += 2;
                                        break;

                                    case ExtendedPhysics.PHYS_PARAM_ERP:
                                        errMsg       = "PHYS_PARAM_ERP takes one parameter of type float";
                                        valueFloat   = (float)pParams[opIndex + 1];
                                        linkInfo.erp = valueFloat;
                                        opIndex     += 2;
                                        break;

                                    case ExtendedPhysics.PHYS_PARAM_SOLVER_ITERATIONS:
                                        errMsg     = "PHYS_PARAM_SOLVER_ITERATIONS takes one parameter of type float";
                                        valueFloat = (float)pParams[opIndex + 1];
                                        linkInfo.solverIterations = valueFloat;
                                        opIndex += 2;
                                        break;

                                    case ExtendedPhysics.PHYS_PARAM_SPRING_AXIS_ENABLE:
                                        errMsg    = "PHYS_PARAM_SPRING_AXIS_ENABLE takes two parameters of types integer and integer (bool)";
                                        valueInt  = (int)pParams[opIndex + 1];
                                        valueBool = ((int)pParams[opIndex + 2]) != 0;
                                        GetAxisRange(valueInt, out axisLow, out axisHigh);
                                        for (int ii = axisLow; ii <= axisHigh; ii++)
                                        {
                                            linkInfo.springAxisEnable[ii] = valueBool;
                                        }
                                        opIndex += 3;
                                        break;

                                    case ExtendedPhysics.PHYS_PARAM_SPRING_DAMPING:
                                        errMsg     = "PHYS_PARAM_SPRING_DAMPING takes two parameters of types integer and float";
                                        valueInt   = (int)pParams[opIndex + 1];
                                        valueFloat = (float)pParams[opIndex + 2];
                                        GetAxisRange(valueInt, out axisLow, out axisHigh);
                                        for (int ii = axisLow; ii <= axisHigh; ii++)
                                        {
                                            linkInfo.springDamping[ii] = valueFloat;
                                        }
                                        opIndex += 3;
                                        break;

                                    case ExtendedPhysics.PHYS_PARAM_SPRING_STIFFNESS:
                                        errMsg     = "PHYS_PARAM_SPRING_STIFFNESS takes two parameters of types integer and float";
                                        valueInt   = (int)pParams[opIndex + 1];
                                        valueFloat = (float)pParams[opIndex + 2];
                                        GetAxisRange(valueInt, out axisLow, out axisHigh);
                                        for (int ii = axisLow; ii <= axisHigh; ii++)
                                        {
                                            linkInfo.springStiffness[ii] = valueFloat;
                                        }
                                        opIndex += 3;
                                        break;

                                    case ExtendedPhysics.PHYS_PARAM_SPRING_EQUILIBRIUM_POINT:
                                        errMsg       = "PHYS_PARAM_SPRING_EQUILIBRIUM_POINT takes two parameters of type vector";
                                        valueVector  = (OMV.Vector3)pParams[opIndex + 1];
                                        valueVector2 = (OMV.Vector3)pParams[opIndex + 2];
                                        linkInfo.springLinearEquilibriumPoint  = valueVector;
                                        linkInfo.springAngularEquilibriumPoint = valueVector2;
                                        opIndex += 3;
                                        break;

                                    case ExtendedPhysics.PHYS_PARAM_USE_LINEAR_FRAMEA:
                                        errMsg    = "PHYS_PARAM_USE_LINEAR_FRAMEA takes one parameter of type integer (bool)";
                                        valueBool = ((int)pParams[opIndex + 1]) != 0;
                                        linkInfo.useLinearReferenceFrameA = valueBool;
                                        opIndex += 2;
                                        break;

                                    default:
                                        break;
                                    }
                                }
                                catch (InvalidCastException e)
                                {
                                    m_physicsScene.Logger.WarnFormat("{0} value of wrong type in physSetLinksetParams: {1}, err={2}",
                                                                     LogHeader, errMsg, e);
                                }
                                catch (Exception e)
                                {
                                    m_physicsScene.Logger.WarnFormat("{0} bad parameters in physSetLinksetParams: {1}", LogHeader, e);
                                }
                            }
                        }
                        // Something changed so a rebuild is in order
                        Refresh(child);
                    }
                }
                break;

            default:
                ret = base.Extension(pFunct, pParams);
                break;
            }
            return(ret);
        }
コード例 #8
0
        // Create a static constraint between the two passed objects
        private BSConstraint BuildConstraint(BSPrimLinkable rootPrim, BSLinkInfo li)
        {
            BSLinkInfoConstraint linkInfo = li as BSLinkInfoConstraint;

            if (linkInfo == null)
            {
                return(null);
            }

            // Zero motion for children so they don't interpolate
            li.member.ZeroMotion(true);

            BSConstraint constrain = null;

            switch (linkInfo.constraintType)
            {
            case ConstraintType.BS_FIXED_CONSTRAINT_TYPE:
            case ConstraintType.D6_CONSTRAINT_TYPE:
                // Relative position normalized to the root prim
                // Essentually a vector pointing from center of rootPrim to center of li.member
                OMV.Vector3 childRelativePosition = linkInfo.member.Position - rootPrim.Position;

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

                DetailLog("{0},BSLinksetConstraint.BuildConstraint,6Dof,rBody={1},cBody={2},rLoc={3},cLoc={4},midLoc={5}",
                          rootPrim.LocalID, rootPrim.PhysBody, linkInfo.member.PhysBody,
                          rootPrim.Position, linkInfo.member.Position, midPoint);

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

                constrain = new BSConstraint6Dof(
                    m_physicsScene.World, rootPrim.PhysBody, linkInfo.member.PhysBody, 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 = (liConstraint.member.Position - rootPrim.Position) * invThisOrientation;
                 *
                 * // relative rotation of the child to the parent
                 * OMV.Quaternion childRelativeRotation = invThisOrientation * liConstraint.member.Orientation;
                 * OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation);
                 *
                 * DetailLog("{0},BSLinksetConstraint.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, liConstraint.member.LocalID);
                 * constrain = new BS6DofConstraint(
                 *              PhysicsScene.World, rootPrim.Body, liConstraint.member.Body,
                 *              OMV.Vector3.Zero,
                 *              OMV.Quaternion.Inverse(rootPrim.Orientation),
                 *              OMV.Vector3.Zero,
                 *              OMV.Quaternion.Inverse(liConstraint.member.Orientation),
                 *              true,
                 *              true
                 *              );
                 * // ==================================================================================
                 */

                break;

            case ConstraintType.D6_SPRING_CONSTRAINT_TYPE:
                constrain = new BSConstraintSpring(m_physicsScene.World, rootPrim.PhysBody, linkInfo.member.PhysBody,
                                                   linkInfo.frameInAloc, linkInfo.frameInArot, linkInfo.frameInBloc, linkInfo.frameInBrot,
                                                   linkInfo.useLinearReferenceFrameA,
                                                   true /*disableCollisionsBetweenLinkedBodies*/);
                DetailLog("{0},BSLinksetConstraint.BuildConstraint,spring,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6}",
                          rootPrim.LocalID,
                          rootPrim.LocalID, rootPrim.PhysBody.AddrString,
                          linkInfo.member.LocalID, linkInfo.member.PhysBody.AddrString,
                          rootPrim.Position, linkInfo.member.Position);

                break;

            default:
                break;
            }

            linkInfo.SetLinkParameters(constrain);

            m_physicsScene.Constraints.AddConstraint(constrain);

            return(constrain);
        }