changeset 6:707dd4e10c28

ported rest of the constraints (chipmunk 5.3.2)
author Extrawurst
date Thu, 02 Dec 2010 22:26:04 +0100
parents 6dd4bcf20f03
children b68f10432182
files trunk/chipmunkd/constraints/cpConstraint.d trunk/chipmunkd/constraints/cpDampedRotarySpring.d trunk/chipmunkd/constraints/cpGearJoint.d trunk/chipmunkd/constraints/cpGrooveJoint.d trunk/chipmunkd/constraints/cpRatchetJoint.d trunk/chipmunkd/constraints/cpRotaryLimitJoint.d trunk/chipmunkd/constraints/cpSimpleMotor.d trunk/chipmunkd/constraints/cpSlideJoint.d
diffstat 8 files changed, 902 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/trunk/chipmunkd/constraints/cpConstraint.d	Thu Dec 02 02:32:22 2010 +0100
+++ b/trunk/chipmunkd/constraints/cpConstraint.d	Thu Dec 02 22:26:04 2010 +0100
@@ -109,15 +109,15 @@
 //TODO:
 //// Built in Joint types
 public import chipmunkd.constraints.cpPinJoint;
-//#include "cpSlideJoint.h"
+public import chipmunkd.constraints.cpSlideJoint;
 public import chipmunkd.constraints.cpPivotJoint;
-//#include "cpGrooveJoint.h"
+public import chipmunkd.constraints.cpGrooveJoint;
 public import chipmunkd.constraints.cpDampedSpring;
-//#include "cpDampedRotarySpring.h"
-//#include "cpRotaryLimitJoint.h"
-//#include "cpRatchetJoint.h"
-//#include "cpGearJoint.h"
-//#include "cpSimpleMotor.h"
+public import chipmunkd.constraints.cpDampedRotarySpring;
+public import chipmunkd.constraints.cpRotaryLimitJoint;
+public import chipmunkd.constraints.cpRatchetJoint;
+public import chipmunkd.constraints.cpGearJoint;
+public import chipmunkd.constraints.cpSimpleMotor;
 
 
 cpFloat cp_constraint_bias_coef = 0.1f;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/chipmunkd/constraints/cpDampedRotarySpring.d	Thu Dec 02 22:26:04 2010 +0100
@@ -0,0 +1,114 @@
+
+// written in the D programming language
+
+module chipmunkd.constraints.cpDampedRotarySpring;
+
+import chipmunkd.chipmunk;
+import chipmunkd.constraints.util;
+
+alias cpFloat function(cpConstraint *spring, cpFloat relativeAngle) cpDampedRotarySpringTorqueFunc;
+
+//const cpConstraintClass *cpDampedRotarySpringGetClass();
+
+struct cpDampedRotarySpring {
+	cpConstraint constraint;
+	cpFloat restAngle;
+	cpFloat stiffness;
+	cpFloat damping;
+	cpDampedRotarySpringTorqueFunc springTorqueFunc;
+	
+	cpFloat target_wrn;
+	cpFloat w_coef;
+	
+	cpFloat iSum;
+}
+
+//cpDampedRotarySpring *cpDampedRotarySpringAlloc(void);
+//cpDampedRotarySpring *cpDampedRotarySpringInit(cpDampedRotarySpring *joint, cpBody *a, cpBody *b, cpFloat restAngle, cpFloat stiffness, cpFloat damping);
+//cpConstraint *cpDampedRotarySpringNew(cpBody *a, cpBody *b, cpFloat restAngle, cpFloat stiffness, cpFloat damping);
+//
+//CP_DefineConstraintProperty(cpDampedRotarySpring, cpFloat, restAngle, RestAngle);
+//CP_DefineConstraintProperty(cpDampedRotarySpring, cpFloat, stiffness, Stiffness);
+//CP_DefineConstraintProperty(cpDampedRotarySpring, cpFloat, damping, Damping);
+//CP_DefineConstraintProperty(cpDampedRotarySpring, cpDampedRotarySpringTorqueFunc, springTorqueFunc, SpringTorqueFunc);
+
+// cpDampedRotarySpring.c ---------------------------------
+
+static cpFloat
+defaultSpringTorque(cpDampedRotarySpring *spring, cpFloat relativeAngle){
+	return (relativeAngle - spring.restAngle)*spring.stiffness;
+}
+
+static void
+preStep(cpDampedRotarySpring *spring, cpFloat dt, cpFloat dt_inv)
+{
+	mixin(CONSTRAINT_BEGIN!("spring", "a", "b"));
+	
+	cpFloat moment = a.i_inv + b.i_inv;
+	spring.iSum = 1.0f/moment;
+
+	spring.w_coef = 1.0f - cpfexp(-spring.damping*dt*moment);
+	spring.target_wrn = 0.0f;
+
+	// apply spring torque
+	cpFloat j_spring = spring.springTorqueFunc(cast(cpConstraint *)spring, a.a - b.a)*dt;
+	a.w -= j_spring*a.i_inv;
+	b.w += j_spring*b.i_inv;
+}
+
+static void
+applyImpulse(cpDampedRotarySpring *spring)
+{
+	mixin(CONSTRAINT_BEGIN!("spring", "a", "b"));
+	
+	// compute relative velocity
+	cpFloat wrn = a.w - b.w;//normal_relative_velocity(a, b, r1, r2, n) - spring.target_vrn;
+	
+	// compute velocity loss from drag
+	// not 100% certain this is derived correctly, though it makes sense
+	cpFloat w_damp = wrn*spring.w_coef;
+	spring.target_wrn = wrn - w_damp;
+	
+	//apply_impulses(a, b, spring.r1, spring.r2, cpvmult(spring.n, v_damp*spring.nMass));
+	cpFloat j_damp = w_damp*spring.iSum;
+	a.w -= j_damp*a.i_inv;
+	b.w += j_damp*b.i_inv;
+}
+
+static cpFloat
+getImpulse(cpConstraint *constraint)
+{
+	return 0.0f;
+}
+
+static /+const+/ cpConstraintClass klass = {
+	cast(cpConstraintPreStepFunction)&preStep,
+	cast(cpConstraintApplyImpulseFunction)&applyImpulse,
+	cast(cpConstraintGetImpulseFunction)&getImpulse,
+};
+mixin(CP_DefineClassGetter!("cpDampedRotarySpring"));
+
+cpDampedRotarySpring *
+cpDampedRotarySpringAlloc()
+{
+	return cast(cpDampedRotarySpring *)cpmalloc(cpDampedRotarySpring.sizeof);
+}
+
+cpDampedRotarySpring *
+cpDampedRotarySpringInit(cpDampedRotarySpring *spring, cpBody *a, cpBody *b, cpFloat restAngle, cpFloat stiffness, cpFloat damping)
+{
+	cpConstraintInit(cast(cpConstraint *)spring, &klass, a, b);
+	
+	spring.restAngle = restAngle;
+	spring.stiffness = stiffness;
+	spring.damping = damping;
+	spring.springTorqueFunc = cast(cpDampedRotarySpringTorqueFunc)&defaultSpringTorque;
+	
+	return spring;
+}
+
+cpConstraint *
+cpDampedRotarySpringNew(cpBody *a, cpBody *b, cpFloat restAngle, cpFloat stiffness, cpFloat damping)
+{
+	return cast(cpConstraint *)cpDampedRotarySpringInit(cpDampedRotarySpringAlloc(), a, b, restAngle, stiffness, damping);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/chipmunkd/constraints/cpGearJoint.d	Thu Dec 02 22:26:04 2010 +0100
@@ -0,0 +1,119 @@
+
+// written in the D programming language
+
+module chipmunkd.constraints.cpGearJoint;
+
+import chipmunkd.chipmunk;
+import chipmunkd.constraints.util;
+
+//const cpConstraintClass *cpGearJointGetClass();
+
+struct cpGearJoint {
+	cpConstraint constraint;
+	cpFloat phase, ratio;
+	cpFloat ratio_inv;
+	
+	cpFloat iSum;
+		
+	cpFloat bias;
+	cpFloat jAcc, jMax;
+}
+
+//cpGearJoint *cpGearJointAlloc(void);
+//cpGearJoint *cpGearJointInit(cpGearJoint *joint, cpBody *a, cpBody *b, cpFloat phase, cpFloat ratio);
+//cpConstraint *cpGearJointNew(cpBody *a, cpBody *b, cpFloat phase, cpFloat ratio);
+//
+//CP_DefineConstraintProperty(cpGearJoint, cpFloat, phase, Phase);
+//CP_DefineConstraintGetter(cpGearJoint, cpFloat, ratio, Ratio);
+//void cpGearJointSetRatio(cpConstraint *constraint, cpFloat value);
+
+// cpGearJoint.c ---------------------------------
+
+static void
+preStep(cpGearJoint *joint, cpFloat dt, cpFloat dt_inv)
+{
+	mixin(CONSTRAINT_BEGIN!("joint", "a", "b"));
+	
+	// calculate moment of inertia coefficient.
+	joint.iSum = 1.0f/(a.i_inv*joint.ratio_inv + joint.ratio*b.i_inv);
+	
+	// calculate bias velocity
+	cpFloat maxBias = joint.constraint.maxBias;
+	joint.bias = cpfclamp(-joint.constraint.biasCoef*dt_inv*(b.a*joint.ratio - a.a - joint.phase), -maxBias, maxBias);
+	
+	// compute max impulse
+	joint.jMax = mixin(J_MAX!("joint", "dt"));
+
+	// apply joint torque
+	cpFloat j = joint.jAcc;
+	a.w -= j*a.i_inv*joint.ratio_inv;
+	b.w += j*b.i_inv;
+}
+
+static void
+applyImpulse(cpGearJoint *joint)
+{
+	mixin(CONSTRAINT_BEGIN!("joint", "a", "b"));
+	
+	// compute relative rotational velocity
+	cpFloat wr = b.w*joint.ratio - a.w;
+	
+	// compute normal impulse	
+	cpFloat j = (joint.bias - wr)*joint.iSum;
+	cpFloat jOld = joint.jAcc;
+	joint.jAcc = cpfclamp(jOld + j, -joint.jMax, joint.jMax);
+	j = joint.jAcc - jOld;
+	
+	// apply impulse
+	a.w -= j*a.i_inv*joint.ratio_inv;
+	b.w += j*b.i_inv;
+}
+
+static cpFloat
+getImpulse(cpGearJoint *joint)
+{
+	return cpfabs(joint.jAcc);
+}
+
+static /+const+/ cpConstraintClass klass = {
+	cast(cpConstraintPreStepFunction)&preStep,
+	cast(cpConstraintApplyImpulseFunction)&applyImpulse,
+	cast(cpConstraintGetImpulseFunction)&getImpulse,
+};
+mixin(CP_DefineClassGetter!("cpGearJoint"));
+
+cpGearJoint *
+cpGearJointAlloc()
+{
+	return cast(cpGearJoint *)cpmalloc(cpGearJoint.sizeof);
+}
+
+cpGearJoint *
+cpGearJointInit(cpGearJoint *joint, cpBody *a, cpBody *b, cpFloat phase, cpFloat ratio)
+{
+	cpConstraintInit(cast(cpConstraint *)joint, &klass, a, b);
+	
+	joint.phase = phase;
+	joint.ratio = ratio;
+	joint.ratio_inv = 1.0f/ratio;
+	
+	joint.jAcc = 0.0f;
+	
+	return joint;
+}
+
+cpConstraint *
+cpGearJointNew(cpBody *a, cpBody *b, cpFloat phase, cpFloat ratio)
+{
+	return cast(cpConstraint *)cpGearJointInit(cpGearJointAlloc(), a, b, phase, ratio);
+}
+
+void
+cpGearJointSetRatio(cpConstraint *constraint, cpFloat value)
+{
+	//TODO:
+	//cpConstraintCheckCast(constraint, cpGearJoint);
+	(cast(cpGearJoint *)constraint).ratio = value;
+	(cast(cpGearJoint *)constraint).ratio_inv = 1.0f/value;
+	cpConstraintActivateBodies(constraint);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/chipmunkd/constraints/cpGrooveJoint.d	Thu Dec 02 22:26:04 2010 +0100
@@ -0,0 +1,175 @@
+
+// written in the D programming language
+
+module chipmunkd.constraints.cpGrooveJoint;
+
+import chipmunkd.chipmunk;
+import chipmunkd.constraints.util;
+
+//const cpConstraintClass *cpGrooveJointGetClass();
+
+struct cpGrooveJoint {
+	cpConstraint constraint;
+	cpVect grv_n, grv_a, grv_b;
+	cpVect  anchr2;
+	
+	cpVect grv_tn;
+	cpFloat clamp;
+	cpVect r1, r2;
+	cpVect k1, k2;
+	
+	cpVect jAcc;
+	cpFloat jMaxLen;
+	cpVect bias;
+}
+
+//cpGrooveJoint *cpGrooveJointAlloc(void);
+//cpGrooveJoint *cpGrooveJointInit(cpGrooveJoint *joint, cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchr2);
+//cpConstraint *cpGrooveJointNew(cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchr2);
+//
+//
+//CP_DefineConstraintGetter(cpGrooveJoint, cpVect, grv_a, GrooveA);
+//void cpGrooveJointSetGrooveA(cpConstraint *constraint, cpVect value);
+//CP_DefineConstraintGetter(cpGrooveJoint, cpVect, grv_b, GrooveB);
+//void cpGrooveJointSetGrooveB(cpConstraint *constraint, cpVect value);
+//CP_DefineConstraintProperty(cpGrooveJoint, cpVect, anchr2, Anchr2);
+
+// cpGrooveJoint.c ---------------------------------
+
+static void
+preStep(cpGrooveJoint *joint, cpFloat dt, cpFloat dt_inv)
+{
+	mixin(CONSTRAINT_BEGIN!("joint", "a", "b"));
+	
+	// calculate endpoints in worldspace
+	cpVect ta = cpBodyLocal2World(a, joint.grv_a);
+	cpVect tb = cpBodyLocal2World(a, joint.grv_b);
+
+	// calculate axis
+	cpVect n = cpvrotate(joint.grv_n, a.rot);
+	cpFloat d = cpvdot(ta, n);
+	
+	joint.grv_tn = n;
+	joint.r2 = cpvrotate(joint.anchr2, b.rot);
+	
+	// calculate tangential distance along the axis of r2
+	cpFloat td = cpvcross(cpvadd(b.p, joint.r2), n);
+	// calculate clamping factor and r2
+	if(td <= cpvcross(ta, n)){
+		joint.clamp = 1.0f;
+		joint.r1 = cpvsub(ta, a.p);
+	} else if(td >= cpvcross(tb, n)){
+		joint.clamp = -1.0f;
+		joint.r1 = cpvsub(tb, a.p);
+	} else {
+		joint.clamp = 0.0f;
+		joint.r1 = cpvsub(cpvadd(cpvmult(cpvperp(n), -td), cpvmult(n, d)), a.p);
+	}
+	
+	// Calculate mass tensor
+	k_tensor(a, b, joint.r1, joint.r2, &joint.k1, &joint.k2);	
+	
+	// compute max impulse
+	joint.jMaxLen = mixin(J_MAX!("joint", "dt"));
+	
+	// calculate bias velocity
+	cpVect delta = cpvsub(cpvadd(b.p, joint.r2), cpvadd(a.p, joint.r1));
+	joint.bias = cpvclamp(cpvmult(delta, -joint.constraint.biasCoef*dt_inv), joint.constraint.maxBias);
+	
+	// apply accumulated impulse
+	apply_impulses(a, b, joint.r1, joint.r2, joint.jAcc);
+}
+
+static cpVect
+grooveConstrain(cpGrooveJoint *joint, cpVect j){
+	cpVect n = joint.grv_tn;
+	cpVect jClamp = (joint.clamp*cpvcross(j, n) > 0.0f) ? j : cpvproject(j, n);
+	return cpvclamp(jClamp, joint.jMaxLen);
+}
+
+static void
+applyImpulse(cpGrooveJoint *joint)
+{
+	mixin(CONSTRAINT_BEGIN!("joint", "a", "b"));
+	
+	cpVect r1 = joint.r1;
+	cpVect r2 = joint.r2;
+	
+	// compute impulse
+	cpVect vr = relative_velocity(a, b, r1, r2);
+
+	cpVect j = mult_k(cpvsub(joint.bias, vr), joint.k1, joint.k2);
+	cpVect jOld = joint.jAcc;
+	joint.jAcc = grooveConstrain(joint, cpvadd(jOld, j));
+	j = cpvsub(joint.jAcc, jOld);
+	
+	// apply impulse
+	apply_impulses(a, b, joint.r1, joint.r2, j);
+}
+
+static cpFloat
+getImpulse(cpGrooveJoint *joint)
+{
+	return cpvlength(joint.jAcc);
+}
+
+static /+const+/ cpConstraintClass klass = {
+	cast(cpConstraintPreStepFunction)&preStep,
+	cast(cpConstraintApplyImpulseFunction)&applyImpulse,
+	cast(cpConstraintGetImpulseFunction)&getImpulse,
+};
+mixin(CP_DefineClassGetter!("cpGrooveJoint"));
+
+cpGrooveJoint *
+cpGrooveJointAlloc()
+{
+	return cast(cpGrooveJoint *)cpmalloc(cpGrooveJoint.sizeof);
+}
+
+cpGrooveJoint *
+cpGrooveJointInit(cpGrooveJoint *joint, cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchr2)
+{
+	cpConstraintInit(cast(cpConstraint *)joint, &klass, a, b);
+	
+	joint.grv_a = groove_a;
+	joint.grv_b = groove_b;
+	joint.grv_n = cpvperp(cpvnormalize(cpvsub(groove_b, groove_a)));
+	joint.anchr2 = anchr2;
+	
+	joint.jAcc = cpvzero;
+	
+	return joint;
+}
+
+cpConstraint *
+cpGrooveJointNew(cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchr2)
+{
+	return cast(cpConstraint *)cpGrooveJointInit(cpGrooveJointAlloc(), a, b, groove_a, groove_b, anchr2);
+}
+
+void
+cpGrooveJointSetGrooveA(cpConstraint *constraint, cpVect value)
+{
+	cpGrooveJoint *g = cast(cpGrooveJoint *)constraint;
+	//TODO:
+	//cpConstraintCheckCast(constraint, cpGrooveJoint);
+	
+	g.grv_a = value;
+	g.grv_n = cpvperp(cpvnormalize(cpvsub(g.grv_b, value)));
+	
+	cpConstraintActivateBodies(constraint);
+}
+
+void
+cpGrooveJointSetGrooveB(cpConstraint *constraint, cpVect value)
+{
+	cpGrooveJoint *g = cast(cpGrooveJoint *)constraint;
+	//TODO:
+	//cpConstraintCheckCast(constraint, cpGrooveJoint);
+	
+	g.grv_b = value;
+	g.grv_n = cpvperp(cpvnormalize(cpvsub(value, g.grv_a)));
+	
+	cpConstraintActivateBodies(constraint);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/chipmunkd/constraints/cpRatchetJoint.d	Thu Dec 02 22:26:04 2010 +0100
@@ -0,0 +1,129 @@
+
+// written in the D programming language
+
+module chipmunkd.constraints.cpRatchetJoint;
+
+import chipmunkd.chipmunk;
+import chipmunkd.constraints.util;
+
+//const cpConstraintClass *cpRatchetJointGetClass();
+
+struct cpRatchetJoint {
+	cpConstraint constraint;
+	cpFloat angle, phase, ratchet;
+	
+	cpFloat iSum;
+		
+	cpFloat bias;
+	cpFloat jAcc, jMax;
+}
+
+//cpRatchetJoint *cpRatchetJointAlloc(void);
+//cpRatchetJoint *cpRatchetJointInit(cpRatchetJoint *joint, cpBody *a, cpBody *b, cpFloat phase, cpFloat ratchet);
+//cpConstraint *cpRatchetJointNew(cpBody *a, cpBody *b, cpFloat phase, cpFloat ratchet);
+//
+//CP_DefineConstraintProperty(cpRatchetJoint, cpFloat, angle, Angle);
+//CP_DefineConstraintProperty(cpRatchetJoint, cpFloat, phase, Phase);
+//CP_DefineConstraintProperty(cpRatchetJoint, cpFloat, ratchet, Ratchet);
+
+// cpRatchetJoint.c ---------------------------------
+
+static void
+preStep(cpRatchetJoint *joint, cpFloat dt, cpFloat dt_inv)
+{
+	mixin(CONSTRAINT_BEGIN!("joint", "a", "b"));
+	
+	cpFloat angle = joint.angle;
+	cpFloat phase = joint.phase;
+	cpFloat ratchet = joint.ratchet;
+	
+	cpFloat delta = b.a - a.a;
+	cpFloat diff = angle - delta;
+	cpFloat pdist = 0.0f;
+	
+	if(diff*ratchet > 0.0f){
+		pdist = diff;
+	} else {
+		joint.angle = cpffloor((delta - phase)/ratchet)*ratchet + phase;
+	}
+	
+	// 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(cpRatchetJoint *joint)
+{
+	if(!joint.bias) return; // early exit
+
+	mixin(CONSTRAINT_BEGIN!("joint", "a", "b"));
+	
+	// compute relative rotational velocity
+	cpFloat wr = b.w - a.w;
+	cpFloat ratchet = joint.ratchet;
+	
+	// compute normal impulse	
+	cpFloat j = -(joint.bias + wr)*joint.iSum;
+	cpFloat jOld = joint.jAcc;
+	joint.jAcc = cpfclamp((jOld + j)*ratchet, 0.0f, joint.jMax*cpfabs(ratchet))/ratchet;
+	j = joint.jAcc - jOld;
+	
+	// apply impulse
+	a.w -= j*a.i_inv;
+	b.w += j*b.i_inv;
+}
+
+static cpFloat
+getImpulse(cpRatchetJoint *joint)
+{
+	return cpfabs(joint.jAcc);
+}
+
+static /+const+/ cpConstraintClass klass = {
+	cast(cpConstraintPreStepFunction)&preStep,
+	cast(cpConstraintApplyImpulseFunction)&applyImpulse,
+	cast(cpConstraintGetImpulseFunction)&getImpulse,
+};
+mixin(CP_DefineClassGetter!("cpRatchetJoint"));
+
+cpRatchetJoint *
+cpRatchetJointAlloc()
+{
+	return cast(cpRatchetJoint *)cpmalloc(cpRatchetJoint.sizeof);
+}
+
+cpRatchetJoint *
+cpRatchetJointInit(cpRatchetJoint *joint, cpBody *a, cpBody *b, cpFloat phase, cpFloat ratchet)
+{
+	cpConstraintInit(cast(cpConstraint *)joint, &klass, a, b);
+	
+	joint.angle = 0.0f;
+	joint.phase = phase;
+	joint.ratchet = ratchet;
+	
+	// STATIC_BODY_CHECK
+	joint.angle = (b ? b.a : 0.0f) - (a ? a.a : 0.0f);
+	
+	return joint;
+}
+
+cpConstraint *
+cpRatchetJointNew(cpBody *a, cpBody *b, cpFloat phase, cpFloat ratchet)
+{
+	return cast(cpConstraint *)cpRatchetJointInit(cpRatchetJointAlloc(), a, b, phase, ratchet);
+}
--- /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);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/chipmunkd/constraints/cpSimpleMotor.d	Thu Dec 02 22:26:04 2010 +0100
@@ -0,0 +1,98 @@
+
+// written in the D programming language
+
+module chipmunkd.constraints.cpSimpleMotor;
+
+import chipmunkd.chipmunk;
+import chipmunkd.constraints.util;
+
+//const cpConstraintClass *cpSimpleMotorGetClass();
+
+struct cpSimpleMotor {
+	cpConstraint constraint;
+	cpFloat rate;
+	
+	cpFloat iSum;
+		
+	cpFloat jAcc, jMax;
+}
+
+//cpSimpleMotor *cpSimpleMotorAlloc(void);
+//cpSimpleMotor *cpSimpleMotorInit(cpSimpleMotor *joint, cpBody *a, cpBody *b, cpFloat rate);
+//cpConstraint *cpSimpleMotorNew(cpBody *a, cpBody *b, cpFloat rate);
+//
+//CP_DefineConstraintProperty(cpSimpleMotor, cpFloat, rate, Rate);
+
+// cpRotaryLimitJoint.c ---------------------------------
+
+static void
+preStep(cpSimpleMotor *joint, cpFloat dt, cpFloat dt_inv)
+{
+	mixin(CONSTRAINT_BEGIN!("joint", "a", "b"));
+	
+	// calculate moment of inertia coefficient.
+	joint.iSum = 1.0f/(a.i_inv + b.i_inv);
+	
+	// compute max impulse
+	joint.jMax = mixin(J_MAX!("joint", "dt"));
+
+	// apply joint torque
+	a.w -= joint.jAcc*a.i_inv;
+	b.w += joint.jAcc*b.i_inv;
+}
+
+static void
+applyImpulse(cpSimpleMotor *joint)
+{
+	mixin(CONSTRAINT_BEGIN!("joint", "a", "b"));
+	
+	// compute relative rotational velocity
+	cpFloat wr = b.w - a.w + joint.rate;
+	
+	// compute normal impulse	
+	cpFloat j = -wr*joint.iSum;
+	cpFloat jOld = joint.jAcc;
+	joint.jAcc = cpfclamp(jOld + j, -joint.jMax, joint.jMax);
+	j = joint.jAcc - jOld;
+	
+	// apply impulse
+	a.w -= j*a.i_inv;
+	b.w += j*b.i_inv;
+}
+
+static cpFloat
+getImpulse(cpSimpleMotor *joint)
+{
+	return cpfabs(joint.jAcc);
+}
+
+static /+const+/ cpConstraintClass klass = {
+	cast(cpConstraintPreStepFunction)&preStep,
+	cast(cpConstraintApplyImpulseFunction)&applyImpulse,
+	cast(cpConstraintGetImpulseFunction)&getImpulse,
+};
+mixin(CP_DefineClassGetter!("cpSimpleMotor"));
+
+cpSimpleMotor *
+cpSimpleMotorAlloc()
+{
+	return cast(cpSimpleMotor *)cpmalloc(cpSimpleMotor.sizeof);
+}
+
+cpSimpleMotor *
+cpSimpleMotorInit(cpSimpleMotor *joint, cpBody *a, cpBody *b, cpFloat rate)
+{
+	cpConstraintInit(cast(cpConstraint *)joint, &klass, a, b);
+	
+	joint.rate = rate;
+	
+	joint.jAcc = 0.0f;
+	
+	return joint;
+}
+
+cpConstraint *
+cpSimpleMotorNew(cpBody *a, cpBody *b, cpFloat rate)
+{
+	return cast(cpConstraint *)cpSimpleMotorInit(cpSimpleMotorAlloc(), a, b, rate);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/chipmunkd/constraints/cpSlideJoint.d	Thu Dec 02 22:26:04 2010 +0100
@@ -0,0 +1,137 @@
+
+// written in the D programming language
+
+module chipmunkd.constraints.cpSlideJoint;
+
+import chipmunkd.chipmunk;
+import chipmunkd.constraints.util;
+
+//const cpConstraintClass *cpSlideJointGetClass();
+
+struct cpSlideJoint {
+	cpConstraint constraint;
+	cpVect anchr1, anchr2;
+	cpFloat min, max;
+	
+	cpVect r1, r2;
+	cpVect n;
+	cpFloat nMass;
+	
+	cpFloat jnAcc, jnMax;
+	cpFloat bias;
+}
+
+//cpSlideJoint *cpSlideJointAlloc(void);
+//cpSlideJoint *cpSlideJointInit(cpSlideJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat min, cpFloat max);
+//cpConstraint *cpSlideJointNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat min, cpFloat max);
+//
+//CP_DefineConstraintProperty(cpSlideJoint, cpVect, anchr1, Anchr1);
+//CP_DefineConstraintProperty(cpSlideJoint, cpVect, anchr2, Anchr2);
+//CP_DefineConstraintProperty(cpSlideJoint, cpFloat, min, Min);
+//CP_DefineConstraintProperty(cpSlideJoint, cpFloat, max, Max);
+
+// cpSlideJoint.c ---------------------------------
+
+static void
+preStep(cpSlideJoint *joint, cpFloat dt, cpFloat dt_inv)
+{
+	mixin(CONSTRAINT_BEGIN!("joint", "a", "b"));
+	
+	joint.r1 = cpvrotate(joint.anchr1, a.rot);
+	joint.r2 = cpvrotate(joint.anchr2, b.rot);
+	
+	cpVect delta = cpvsub(cpvadd(b.p, joint.r2), cpvadd(a.p, joint.r1));
+	cpFloat dist = cpvlength(delta);
+	cpFloat pdist = 0.0f;
+	if(dist > joint.max) {
+		pdist = dist - joint.max;
+	} else if(dist < joint.min) {
+		pdist = joint.min - dist;
+		dist = -dist;
+	}
+	joint.n = cpvmult(delta, 1.0f/(dist ? dist : cast(cpFloat)INFINITY));
+	
+	// calculate mass normal
+	joint.nMass = 1.0f/k_scalar(a, b, joint.r1, joint.r2, joint.n);
+	
+	// calculate bias velocity
+	cpFloat maxBias = joint.constraint.maxBias;
+	joint.bias = cpfclamp(-joint.constraint.biasCoef*dt_inv*(pdist), -maxBias, maxBias);
+	
+	// compute max impulse
+	joint.jnMax = mixin(J_MAX!("joint", "dt"));
+
+	// apply accumulated impulse
+	if(!joint.bias) //{
+		// if bias is 0, then the joint is not at a limit.
+		joint.jnAcc = 0.0f;
+//	} else {
+		cpVect j = cpvmult(joint.n, joint.jnAcc);
+		apply_impulses(a, b, joint.r1, joint.r2, j);
+//	}
+}
+
+static void
+applyImpulse(cpSlideJoint *joint)
+{
+	if(!joint.bias) return;  // early exit
+
+	mixin(CONSTRAINT_BEGIN!("joint", "a", "b"));
+	
+	cpVect n = joint.n;
+	cpVect r1 = joint.r1;
+	cpVect r2 = joint.r2;
+		
+	// compute relative velocity
+	cpVect vr = relative_velocity(a, b, r1, r2);
+	cpFloat vrn = cpvdot(vr, n);
+	
+	// compute normal impulse
+	cpFloat jn = (joint.bias - vrn)*joint.nMass;
+	cpFloat jnOld = joint.jnAcc;
+	joint.jnAcc = cpfclamp(jnOld + jn, -joint.jnMax, 0.0f);
+	jn = joint.jnAcc - jnOld;
+	
+	// apply impulse
+	apply_impulses(a, b, joint.r1, joint.r2, cpvmult(n, jn));
+}
+
+static cpFloat
+getImpulse(cpConstraint *joint)
+{
+	return cpfabs((cast(cpSlideJoint *)joint).jnAcc);
+}
+
+static /+const+/ cpConstraintClass klass = {
+	cast(cpConstraintPreStepFunction)&preStep,
+	cast(cpConstraintApplyImpulseFunction)&applyImpulse,
+	cast(cpConstraintGetImpulseFunction)&getImpulse,
+};
+mixin(CP_DefineClassGetter!("cpSlideJoint"));
+
+cpSlideJoint *
+cpSlideJointAlloc()
+{
+	return cast(cpSlideJoint *)cpmalloc(cpSlideJoint.sizeof);
+}
+
+cpSlideJoint *
+cpSlideJointInit(cpSlideJoint *joint, cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat min, cpFloat max)
+{
+	cpConstraintInit(cast(cpConstraint *)joint, &klass, a, b);
+	
+	joint.anchr1 = anchr1;
+	joint.anchr2 = anchr2;
+	joint.min = min;
+	joint.max = max;
+	
+	joint.jnAcc = 0.0f;
+	
+	return joint;
+}
+
+cpConstraint *
+cpSlideJointNew(cpBody *a, cpBody *b, cpVect anchr1, cpVect anchr2, cpFloat min, cpFloat max)
+{
+	return cast(cpConstraint *)cpSlideJointInit(cpSlideJointAlloc(), a, b, anchr1, anchr2, min, max);
+}
\ No newline at end of file