diff trunk/chipmunkd/constraints/cpGrooveJoint.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/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);
+}
+