Mercurial > projects > chipmunkd
view trunk/chipmunkd/constraints/util.d @ 4:7ebbd4d05553
initial commit
author | Extrawurst |
---|---|
date | Thu, 02 Dec 2010 02:11:26 +0100 |
parents | |
children | df4ebc8add66 |
line wrap: on
line source
// written in the D programming language module chipmunkd.constraints.util; import chipmunkd.cpBody; import chipmunkd.chipmunk_types_h; import chipmunkd.cpVect,chipmunkd.cpVect_h; template CP_DefineClassGetter(string t) { enum CP_DefineClassGetter = "cpConstraintClass* "~t~"GetClass(){return cast(cpConstraintClass *)&klass;}"; } template J_MAX(string constraint,string dt) { enum J_MAX = "((cast(cpConstraint *)"~constraint~").maxForce*("~dt~"))"; } template CONSTRAINT_BEGIN(string constraint,string a_var,string b_var) { enum CONSTRAINT_BEGIN = "cpBody *"~a_var~"; cpBody *"~b_var~"; "~a_var~" = (cast(cpConstraint *)"~constraint~")."~a_var~"; "~b_var~" = (cast(cpConstraint *)"~constraint~")."~b_var~"; if( (cpBodyIsSleeping("~a_var~") || cpBodyIsStatic("~a_var~")) && (cpBodyIsSleeping("~b_var~") || cpBodyIsStatic("~b_var~")) ) return; "; } static cpVect relative_velocity(cpBody *a, cpBody *b, cpVect r1, cpVect r2){ cpVect v1_sum = cpvadd(a.v, cpvmult(cpvperp(r1), a.w)); cpVect v2_sum = cpvadd(b.v, cpvmult(cpvperp(r2), b.w)); return cpvsub(v2_sum, v1_sum); } static cpFloat normal_relative_velocity(cpBody *a, cpBody *b, cpVect r1, cpVect r2, cpVect n){ return cpvdot(relative_velocity(a, b, r1, r2), n); } static void apply_impulses(cpBody *a , cpBody *b, cpVect r1, cpVect r2, cpVect j) { cpBodyApplyImpulse(a, cpvneg(j), r1); cpBodyApplyImpulse(b, j, r2); } static void apply_bias_impulse(cpBody *_body, cpVect j, cpVect r) { _body.v_bias = cpvadd(_body.v_bias, cpvmult(j, _body.m_inv)); _body.w_bias += _body.i_inv*cpvcross(r, j); } static void apply_bias_impulses(cpBody *a , cpBody *b, cpVect r1, cpVect r2, cpVect j) { apply_bias_impulse(a, cpvneg(j), r1); apply_bias_impulse(b, j, r2); } static cpVect clamp_vect(cpVect v, cpFloat len) { return cpvclamp(v, len); // return (cpvdot(v,v) > len*len) ? cpvmult(cpvnormalize(v), len) : v; } static cpFloat k_scalar(cpBody *a, cpBody *b, cpVect r1, cpVect r2, cpVect n) { cpFloat mass_sum = a.m_inv + b.m_inv; cpFloat r1cn = cpvcross(r1, n); cpFloat r2cn = cpvcross(r2, n); cpFloat value = mass_sum + a.i_inv*r1cn*r1cn + b.i_inv*r2cn*r2cn; assert(value != 0.0, "Unsolvable collision or constraint."); return value; } static void k_tensor(cpBody *a, cpBody *b, cpVect r1, cpVect r2, cpVect *k1, cpVect *k2) { // calculate mass matrix // If I wasn't lazy and wrote a proper matrix class, this wouldn't be so gross... cpFloat k11, k12, k21, k22; cpFloat m_sum = a.m_inv + b.m_inv; // start with I*m_sum k11 = m_sum; k12 = 0.0f; k21 = 0.0f; k22 = m_sum; // add the influence from r1 cpFloat a_i_inv = a.i_inv; cpFloat r1xsq = r1.x * r1.x * a_i_inv; cpFloat r1ysq = r1.y * r1.y * a_i_inv; cpFloat r1nxy = -r1.x * r1.y * a_i_inv; k11 += r1ysq; k12 += r1nxy; k21 += r1nxy; k22 += r1xsq; // add the influnce from r2 cpFloat b_i_inv = b.i_inv; cpFloat r2xsq = r2.x * r2.x * b_i_inv; cpFloat r2ysq = r2.y * r2.y * b_i_inv; cpFloat r2nxy = -r2.x * r2.y * b_i_inv; k11 += r2ysq; k12 += r2nxy; k21 += r2nxy; k22 += r2xsq; // invert cpFloat determinant = k11*k22 - k12*k21; assert(determinant != 0.0, "Unsolvable constraint."); cpFloat det_inv = 1.0f/determinant; *k1 = cpv( k22*det_inv, -k12*det_inv); *k2 = cpv(-k21*det_inv, k11*det_inv); } static cpVect mult_k(cpVect vr, cpVect k1, cpVect k2) { return cpv(cpvdot(vr, k1), cpvdot(vr, k2)); }