// Given a constraint, apply the current constraint parameters to same. public override void SetLinkParameters(BSConstraint constrain) { member.PhysScene.DetailLog("{0},BSLinkInfoConstraint.SetLinkParameters,type={1}", member.LocalID, constraintType); switch (constraintType) { case ConstraintType.FIXED_CONSTRAINT_TYPE: case ConstraintType.D6_CONSTRAINT_TYPE: BSConstraint6Dof constrain6dof = constrain as BSConstraint6Dof; if (constrain6dof != null) { // NOTE: D6_SPRING_CONSTRAINT_TYPE should be updated if you change any of this code. // zero linear and angular limits makes the objects unable to move in relation to each other constrain6dof.SetLinearLimits(linearLimitLow, linearLimitHigh); constrain6dof.SetAngularLimits(angularLimitLow, angularLimitHigh); // tweek the constraint to increase stability constrain6dof.UseFrameOffset(useFrameOffset); constrain6dof.TranslationalLimitMotor(enableTransMotor, transMotorMaxVel, transMotorMaxForce); constrain6dof.SetCFMAndERP(cfm, erp); if (solverIterations != 0f) { constrain6dof.SetSolverIterations(solverIterations); } } break; case ConstraintType.D6_SPRING_CONSTRAINT_TYPE: BSConstraintSpring constrainSpring = constrain as BSConstraintSpring; if (constrainSpring != null) { // zero linear and angular limits makes the objects unable to move in relation to each other constrainSpring.SetLinearLimits(linearLimitLow, linearLimitHigh); constrainSpring.SetAngularLimits(angularLimitLow, angularLimitHigh); // tweek the constraint to increase stability constrainSpring.UseFrameOffset(useFrameOffset); constrainSpring.TranslationalLimitMotor(enableTransMotor, transMotorMaxVel, transMotorMaxForce); constrainSpring.SetCFMAndERP(cfm, erp); if (solverIterations != 0f) { constrainSpring.SetSolverIterations(solverIterations); } for (int ii = 0; ii < springAxisEnable.Length; ii++) { constrainSpring.SetAxisEnable(ii, springAxisEnable[ii]); if (springDamping[ii] != BSAPITemplate.SPRING_NOT_SPECIFIED) { constrainSpring.SetDamping(ii, springDamping[ii]); } if (springStiffness[ii] != BSAPITemplate.SPRING_NOT_SPECIFIED) { constrainSpring.SetStiffness(ii, springStiffness[ii]); } } constrainSpring.CalculateTransforms(); if (springLinearEquilibriumPoint != OMV.Vector3.Zero) { constrainSpring.SetEquilibriumPoint(springLinearEquilibriumPoint, springAngularEquilibriumPoint); } else { constrainSpring.SetEquilibriumPoint(BSAPITemplate.SPRING_NOT_SPECIFIED, BSAPITemplate.SPRING_NOT_SPECIFIED); } } break; default: break; } }
// 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.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); }
// 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.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; }