示例#1
0
        // Create a constraint between me (root of linkset) and the passed prim (the child).
        // Called at taint time!
        private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BulletBody rootBody,
                                                BSPhysObject childPrim, BulletBody childBody)
        {
            // Zero motion for children so they don't interpolate
            childPrim.ZeroMotion();

            // 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},PhysicallyLinkAChildToRoot,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}",
                      rootPrim.LocalID,
                      rootPrim.LocalID, rootBody.ptr.ToString("X"),
                      childPrim.LocalID, childBody.ptr.ToString("X"),
                      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

            // There is great subtlty in these paramters. Notice the check for a ptr of zero.
            // We pass the BulletBody structure into the taint in order to capture the pointer
            //     of the body at the time of constraint creation. This doesn't work for the very first
            //     construction because there is no body yet. The body
            //     is constructed later at taint time. Thus we use the body address at time of the
            //     taint creation but, if it is zero, use what's in the prim at the moment.
            //     There is a possible race condition since shape can change without a taint call
            //     (like changing to a mesh that is already constructed). The fix for that would be
            //     to only change BSShape at taint time thus syncronizing these operations at
            //     the cost of efficiency and lag.
            BS6DofConstraint constrain = new BS6DofConstraint(
                PhysicsScene.World,
                rootBody.ptr == IntPtr.Zero ? rootPrim.BSBody : rootBody,
                childBody.ptr == IntPtr.Zero ? childPrim.BSBody : childBody,
                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 as a warning to 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);
             *
             * // create a constraint that allows no freedom of movement between the two objects
             * // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
             * DetailLog("{0},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),
             *              // A point half way between the parent and child
             *              // childRelativePosition/2,
             *              // childRelativeRotation,
             *              // childRelativePosition/2,
             *              // inverseChildRelativeRotation,
             *              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(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintUseFrameOffset));
            constrain.TranslationalLimitMotor(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintEnableTransMotor),
                                              PhysicsScene.Params.linkConstraintTransMotorMaxVel,
                                              PhysicsScene.Params.linkConstraintTransMotorMaxForce);
            constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP);
            if (PhysicsScene.Params.linkConstraintSolverIterations != 0f)
            {
                constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations);
            }

            RecomputeLinksetConstraintVariables();
        }