BulletSim: complete linkage of spring constraint into linkset constraint.

varregion
Robert Adams 2013-08-07 07:56:37 -07:00
parent 9a7d0e489c
commit 0971c7ae77
3 changed files with 77 additions and 15 deletions

View File

@ -32,12 +32,19 @@ using OpenMetaverse;
namespace OpenSim.Region.Physics.BulletSPlugin namespace OpenSim.Region.Physics.BulletSPlugin
{ {
public sealed class BSConstraint6Dof : BSConstraint public class BSConstraint6Dof : BSConstraint
{ {
private static string LogHeader = "[BULLETSIM 6DOF CONSTRAINT]"; private static string LogHeader = "[BULLETSIM 6DOF CONSTRAINT]";
public override ConstraintType Type { get { return ConstraintType.D6_CONSTRAINT_TYPE; } } public override ConstraintType Type { get { return ConstraintType.D6_CONSTRAINT_TYPE; } }
public BSConstraint6Dof(BulletWorld world, BulletBody obj1, BulletBody obj2) :base(world)
{
m_body1 = obj1;
m_body2 = obj2;
m_enabled = false;
}
// Create a btGeneric6DofConstraint // Create a btGeneric6DofConstraint
public BSConstraint6Dof(BulletWorld world, BulletBody obj1, BulletBody obj2, public BSConstraint6Dof(BulletWorld world, BulletBody obj1, BulletBody obj2,
Vector3 frame1, Quaternion frame1rot, Vector3 frame1, Quaternion frame1rot,

View File

@ -77,6 +77,8 @@ public abstract class BSLinkset
{ {
member = pMember; member = pMember;
} }
public virtual void ResetLink() { }
public virtual void SetLinkParameters(BSConstraint constrain) { }
} }
public LinksetImplementation LinksetImpl { get; protected set; } public LinksetImplementation LinksetImpl { get; protected set; }

View File

@ -51,16 +51,26 @@ public sealed class BSLinksetConstraints : BSLinkset
public float cfm; public float cfm;
public float erp; public float erp;
public float solverIterations; public float solverIterations;
//
public OMV.Vector3 frameInAloc;
public OMV.Quaternion frameInArot;
public OMV.Vector3 frameInBloc;
public OMV.Quaternion frameInBrot;
// Spring
public float springDamping;
public float springStiffness;
public BSLinkInfoConstraint(BSPrimLinkable pMember) public BSLinkInfoConstraint(BSPrimLinkable pMember)
: base(pMember) : base(pMember)
{ {
constraint = null; constraint = null;
ResetToFixedConstraint(); ResetLink();
} }
// Set all the parameters for this constraint to a fixed, non-movable constraint. // Set all the parameters for this constraint to a fixed, non-movable constraint.
public void ResetToFixedConstraint() public override void ResetLink()
{ {
constraintType = ConstraintType.D6_CONSTRAINT_TYPE; constraintType = ConstraintType.D6_CONSTRAINT_TYPE;
linearLimitLow = OMV.Vector3.Zero; linearLimitLow = OMV.Vector3.Zero;
@ -74,10 +84,16 @@ public sealed class BSLinksetConstraints : BSLinkset
cfm = BSParam.LinkConstraintCFM; cfm = BSParam.LinkConstraintCFM;
erp = BSParam.LinkConstraintERP; erp = BSParam.LinkConstraintERP;
solverIterations = BSParam.LinkConstraintSolverIterations; solverIterations = BSParam.LinkConstraintSolverIterations;
frameInAloc = OMV.Vector3.Zero;
frameInArot = OMV.Quaternion.Identity;
frameInBloc = OMV.Vector3.Zero;
frameInBrot = OMV.Quaternion.Identity;
springDamping = -1f;
springStiffness = -1f;
} }
// Given a constraint, apply the current constraint parameters to same. // Given a constraint, apply the current constraint parameters to same.
public void SetConstraintParameters(BSConstraint constrain) public override void SetLinkParameters(BSConstraint constrain)
{ {
switch (constraintType) switch (constraintType)
{ {
@ -85,6 +101,7 @@ public sealed class BSLinksetConstraints : BSLinkset
BSConstraint6Dof constrain6dof = constrain as BSConstraint6Dof; BSConstraint6Dof constrain6dof = constrain as BSConstraint6Dof;
if (constrain6dof != null) 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 // zero linear and angular limits makes the objects unable to move in relation to each other
constrain6dof.SetLinearLimits(linearLimitLow, linearLimitHigh); constrain6dof.SetLinearLimits(linearLimitLow, linearLimitHigh);
constrain6dof.SetAngularLimits(angularLimitLow, angularLimitHigh); constrain6dof.SetAngularLimits(angularLimitLow, angularLimitHigh);
@ -99,6 +116,31 @@ public sealed class BSLinksetConstraints : BSLinkset
} }
} }
break; 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 < 6; ii++)
{
if (springDamping != -1)
constrainSpring.SetDamping(ii, springDamping);
if (springStiffness != -1)
constrainSpring.SetStiffness(ii, springStiffness);
}
}
break;
default: default:
break; break;
} }
@ -262,8 +304,8 @@ public sealed class BSLinksetConstraints : BSLinkset
// Create a static constraint between the two passed objects // Create a static constraint between the two passed objects
private BSConstraint BuildConstraint(BSPrimLinkable rootPrim, BSLinkInfo li) private BSConstraint BuildConstraint(BSPrimLinkable rootPrim, BSLinkInfo li)
{ {
BSLinkInfoConstraint liConstraint = li as BSLinkInfoConstraint; BSLinkInfoConstraint linkInfo = li as BSLinkInfoConstraint;
if (liConstraint == null) if (linkInfo == null)
return null; return null;
// Zero motion for children so they don't interpolate // Zero motion for children so they don't interpolate
@ -271,27 +313,25 @@ public sealed class BSLinksetConstraints : BSLinkset
BSConstraint constrain = null; BSConstraint constrain = null;
switch (liConstraint.constraintType) switch (linkInfo.constraintType)
{ {
case ConstraintType.D6_CONSTRAINT_TYPE: case ConstraintType.D6_CONSTRAINT_TYPE:
// Relative position normalized to the root prim // Relative position normalized to the root prim
// Essentually a vector pointing from center of rootPrim to center of li.member // Essentually a vector pointing from center of rootPrim to center of li.member
OMV.Vector3 childRelativePosition = liConstraint.member.Position - rootPrim.Position; OMV.Vector3 childRelativePosition = linkInfo.member.Position - rootPrim.Position;
// real world coordinate of midpoint between the two objects // real world coordinate of midpoint between the two objects
OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); 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}", DetailLog("{0},BSLinksetConstraint.BuildConstraint,6Dof,rBody={1},cBody={2},rLoc={3},cLoc={4},midLoc={7}",
rootPrim.LocalID, rootPrim.LocalID, rootPrim.PhysBody, linkInfo.member.PhysBody,
rootPrim.LocalID, rootPrim.PhysBody.AddrString, rootPrim.Position, linkInfo.member.Position, midPoint);
liConstraint.member.LocalID, liConstraint.member.PhysBody.AddrString,
rootPrim.Position, liConstraint.member.Position, midPoint);
// create a constraint that allows no freedom of movement between the two objects // create a constraint that allows no freedom of movement between the two objects
// http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818
constrain = new BSConstraint6Dof( constrain = new BSConstraint6Dof(
m_physicsScene.World, rootPrim.PhysBody, liConstraint.member.PhysBody, midPoint, true, true ); m_physicsScene.World, rootPrim.PhysBody, linkInfo.member.PhysBody, midPoint, true, true );
/* NOTE: below is an attempt to build constraint with full frame computation, etc. /* 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 * Using the midpoint is easier since it lets the Bullet code manipulate the transforms
@ -319,12 +359,24 @@ public sealed class BSLinksetConstraints : BSLinkset
// ================================================================================== // ==================================================================================
*/ */
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,
true /*useLinearReferenceFrameA*/,
true /*disableCollisionsBetweenLinkedBodies*/);
DetailLog("{0},BSLinksetConstraint.BuildConstraint,spring,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}",
rootPrim.LocalID,
rootPrim.LocalID, rootPrim.PhysBody.AddrString,
linkInfo.member.LocalID, linkInfo.member.PhysBody.AddrString,
rootPrim.Position, linkInfo.member.Position);
break; break;
default: default:
break; break;
} }
liConstraint.SetConstraintParameters(constrain); linkInfo.SetLinkParameters(constrain);
m_physicsScene.Constraints.AddConstraint(constrain); m_physicsScene.Constraints.AddConstraint(constrain);
@ -401,6 +453,7 @@ public sealed class BSLinksetConstraints : BSLinkset
// If constraint doesn't exist yet, create it. // If constraint doesn't exist yet, create it.
constrain = BuildConstraint(LinksetRoot, li); constrain = BuildConstraint(LinksetRoot, li);
} }
li.SetLinkParameters(constrain);
constrain.RecomputeConstraintVariables(linksetMass); constrain.RecomputeConstraintVariables(linksetMass);
// PhysicsScene.PE.DumpConstraint(PhysicsScene.World, constrain.Constraint); // DEBUG DEBUG // PhysicsScene.PE.DumpConstraint(PhysicsScene.World, constrain.Constraint); // DEBUG DEBUG