diff trunk/chipmunkd/constraints/cpRotaryLimitJoint.d @ 6:707dd4e10c28

ported rest of the constraints (chipmunk 5.3.2)
author Extrawurst
date Thu, 02 Dec 2010 22:26:04 +0100
parents
children b68f10432182
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/chipmunkd/constraints/cpRotaryLimitJoint.d	Thu Dec 02 22:26:04 2010 +0100
@@ -0,0 +1,123 @@
+
+// written in the D programming language
+
+module chipmunkd.constraints.cpRotaryLimitJoint;
+
+import chipmunkd.chipmunk;
+import chipmunkd.constraints.util;
+
+//const cpConstraintClass *cpRotaryLimitJointGetClass();
+
+struct cpRotaryLimitJoint {
+	cpConstraint constraint;
+	cpFloat min, max;
+	
+	cpFloat iSum;
+		
+	cpFloat bias;
+	cpFloat jAcc, jMax;
+}
+
+//cpRotaryLimitJoint *cpRotaryLimitJointAlloc(void);
+//cpRotaryLimitJoint *cpRotaryLimitJointInit(cpRotaryLimitJoint *joint, cpBody *a, cpBody *b, cpFloat min, cpFloat max);
+//cpConstraint *cpRotaryLimitJointNew(cpBody *a, cpBody *b, cpFloat min, cpFloat max);
+//
+//CP_DefineConstraintProperty(cpRotaryLimitJoint, cpFloat, min, Min);
+//CP_DefineConstraintProperty(cpRotaryLimitJoint, cpFloat, max, Max);
+
+// cpRotaryLimitJoint.c ---------------------------------
+
+static void
+preStep(cpRotaryLimitJoint *joint, cpFloat dt, cpFloat dt_inv)
+{
+	mixin(CONSTRAINT_BEGIN!("joint", "a", "b"));
+	
+	cpFloat dist = b.a - a.a;
+	cpFloat pdist = 0.0f;
+	if(dist > joint.max) {
+		pdist = joint.max - dist;
+	} else if(dist < joint.min) {
+		pdist = joint.min - dist;
+	}
+	
+	// calculate moment of inertia coefficient.
+	joint.iSum = 1.0f/(a.i_inv + b.i_inv);
+	
+	// calculate bias velocity
+	cpFloat maxBias = joint.constraint.maxBias;
+	joint.bias = cpfclamp(-joint.constraint.biasCoef*dt_inv*(pdist), -maxBias, maxBias);
+	
+	// compute max impulse
+	joint.jMax = mixin(J_MAX!("joint", "dt"));
+
+	// If the bias is 0, the joint is not at a limit. Reset the impulse.
+	if(!joint.bias)
+		joint.jAcc = 0.0f;
+
+	// apply joint torque
+	a.w -= joint.jAcc*a.i_inv;
+	b.w += joint.jAcc*b.i_inv;
+}
+
+static void
+applyImpulse(cpRotaryLimitJoint *joint)
+{
+	if(!joint.bias) return; // early exit
+
+	mixin(CONSTRAINT_BEGIN!("joint", "a", "b"));
+	
+	// compute relative rotational velocity
+	cpFloat wr = b.w - a.w;
+	
+	// compute normal impulse	
+	cpFloat j = -(joint.bias + wr)*joint.iSum;
+	cpFloat jOld = joint.jAcc;
+	if(joint.bias < 0.0f){
+		joint.jAcc = cpfclamp(jOld + j, 0.0f, joint.jMax);
+	} else {
+		joint.jAcc = cpfclamp(jOld + j, -joint.jMax, 0.0f);
+	}
+	j = joint.jAcc - jOld;
+	
+	// apply impulse
+	a.w -= j*a.i_inv;
+	b.w += j*b.i_inv;
+}
+
+static cpFloat
+getImpulse(cpRotaryLimitJoint *joint)
+{
+	return cpfabs(joint.jAcc);
+}
+
+static /+const+/ cpConstraintClass klass = {
+	cast(cpConstraintPreStepFunction)&preStep,
+	cast(cpConstraintApplyImpulseFunction)&applyImpulse,
+	cast(cpConstraintGetImpulseFunction)&getImpulse,
+};
+mixin(CP_DefineClassGetter!("cpRotaryLimitJoint"));
+
+cpRotaryLimitJoint *
+cpRotaryLimitJointAlloc()
+{
+	return cast(cpRotaryLimitJoint *)cpmalloc(cpRotaryLimitJoint.sizeof);
+}
+
+cpRotaryLimitJoint *
+cpRotaryLimitJointInit(cpRotaryLimitJoint *joint, cpBody *a, cpBody *b, cpFloat min, cpFloat max)
+{
+	cpConstraintInit(cast(cpConstraint *)joint, &klass, a, b);
+	
+	joint.min = min;
+	joint.max  = max;
+	
+	joint.jAcc = 0.0f;
+	
+	return joint;
+}
+
+cpConstraint *
+cpRotaryLimitJointNew(cpBody *a, cpBody *b, cpFloat min, cpFloat max)
+{
+	return cast(cpConstraint *)cpRotaryLimitJointInit(cpRotaryLimitJointAlloc(), a, b, min, max);
+}