1 module chipmunk.cpTransform; 2 3 import chipmunk.chipmunk_types; 4 import chipmunk.cpBB; 5 import chipmunk.cpVect; 6 7 extern (C): 8 9 /// Identity transform matrix. 10 static const cpTransform cpTransformIdentity = {1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}; 11 12 /// Construct a new transform matrix. 13 /// (a, b) is the x basis vector. 14 /// (c, d) is the y basis vector. 15 /// (tx, ty) is the translation. 16 static cpTransform 17 cpTransformNew(cpFloat a, cpFloat b, cpFloat c, cpFloat d, cpFloat tx, cpFloat ty) 18 { 19 cpTransform t = {a, b, c, d, tx, ty}; 20 return t; 21 } 22 23 /// Construct a new transform matrix in transposed order. 24 static cpTransform 25 cpTransformNewTranspose(cpFloat a, cpFloat c, cpFloat tx, cpFloat b, cpFloat d, cpFloat ty) 26 { 27 cpTransform t = {a, b, c, d, tx, ty}; 28 return t; 29 } 30 31 /// Get the inverse of a transform matrix. 32 static cpTransform 33 cpTransformInverse(cpTransform t) 34 { 35 cpFloat inv_det = 1.0/(t.a*t.d - t.c*t.b); 36 return cpTransformNewTranspose( 37 t.d*inv_det, -t.c*inv_det, (t.c*t.ty - t.tx*t.d)*inv_det, 38 -t.b*inv_det, t.a*inv_det, (t.tx*t.b - t.a*t.ty)*inv_det 39 ); 40 } 41 42 /// Multiply two transformation matrices. 43 static cpTransform 44 cpTransformMult(cpTransform t1, cpTransform t2) 45 { 46 return cpTransformNewTranspose( 47 t1.a*t2.a + t1.c*t2.b, t1.a*t2.c + t1.c*t2.d, t1.a*t2.tx + t1.c*t2.ty + t1.tx, 48 t1.b*t2.a + t1.d*t2.b, t1.b*t2.c + t1.d*t2.d, t1.b*t2.tx + t1.d*t2.ty + t1.ty 49 ); 50 } 51 52 /// Transform an absolute point. (i.e. a vertex) 53 static cpVect 54 cpTransformPoint(cpTransform t, cpVect p) 55 { 56 return cpv(t.a*p.x + t.c*p.y + t.tx, t.b*p.x + t.d*p.y + t.ty); 57 } 58 59 /// Transform a vector (i.e. a normal) 60 static cpVect 61 cpTransformVect(cpTransform t, cpVect v) 62 { 63 return cpv(t.a*v.x + t.c*v.y, t.b*v.x + t.d*v.y); 64 } 65 66 /// Transform a cpBB. 67 static cpBB 68 cpTransformbBB(cpTransform t, cpBB bb) 69 { 70 cpVect center = cpBBCenter(bb); 71 cpFloat hw = (bb.r - bb.l)*0.5; 72 cpFloat hh = (bb.t - bb.b)*0.5; 73 74 cpFloat a = t.a*hw, b = t.c*hh, d = t.b*hw, e = t.d*hh; 75 cpFloat hw_max = cpfmax(cpfabs(a + b), cpfabs(a - b)); 76 cpFloat hh_max = cpfmax(cpfabs(d + e), cpfabs(d - e)); 77 return cpBBNewForExtents(cpTransformPoint(t, center), hw_max, hh_max); 78 } 79 80 /// Create a transation matrix. 81 static cpTransform 82 cpTransformTranslate(cpVect translate) 83 { 84 return cpTransformNewTranspose( 85 1.0, 0.0, translate.x, 86 0.0, 1.0, translate.y 87 ); 88 } 89 90 /// Create a scale matrix. 91 static cpTransform 92 cpTransformScale(cpFloat scaleX, cpFloat scaleY) 93 { 94 return cpTransformNewTranspose( 95 scaleX, 0.0, 0.0, 96 0.0, scaleY, 0.0 97 ); 98 } 99 100 /// Create a rotation matrix. 101 static cpTransform 102 cpTransformRotate(cpFloat radians) 103 { 104 cpVect rot = cpvforangle(radians); 105 return cpTransformNewTranspose( 106 rot.x, -rot.y, 0.0, 107 rot.y, rot.x, 0.0 108 ); 109 } 110 111 /// Create a rigid transformation matrix. (transation + rotation) 112 static cpTransform 113 cpTransformRigid(cpVect translate, cpFloat radians) 114 { 115 cpVect rot = cpvforangle(radians); 116 return cpTransformNewTranspose( 117 rot.x, -rot.y, translate.x, 118 rot.y, rot.x, translate.y 119 ); 120 } 121 122 /// Fast inverse of a rigid transformation matrix. 123 static cpTransform 124 cpTransformRigidInverse(cpTransform t) 125 { 126 return cpTransformNewTranspose( 127 t.d, -t.c, (t.c*t.ty - t.tx*t.d), 128 -t.b, t.a, (t.tx*t.b - t.a*t.ty) 129 ); 130 } 131 132 //MARK: Miscellaneous (but useful) transformation matrices. 133 // See source for documentation... 134 135 static cpTransform 136 cpTransformWrap(cpTransform outer, cpTransform inner) 137 { 138 return cpTransformMult(cpTransformInverse(outer), cpTransformMult(inner, outer)); 139 } 140 141 static cpTransform 142 cpTransformWrapInverse(cpTransform outer, cpTransform inner) 143 { 144 return cpTransformMult(outer, cpTransformMult(inner, cpTransformInverse(outer))); 145 } 146 147 static cpTransform 148 cpTransformOrtho(cpBB bb) 149 { 150 return cpTransformNewTranspose( 151 2.0/(bb.r - bb.l), 0.0, -(bb.r + bb.l)/(bb.r - bb.l), 152 0.0, 2.0/(bb.t - bb.b), -(bb.t + bb.b)/(bb.t - bb.b) 153 ); 154 } 155 156 static cpTransform 157 cpTransformBoneScale(cpVect v0, cpVect v1) 158 { 159 cpVect d = cpvsub(v1, v0); 160 return cpTransformNewTranspose( 161 d.x, -d.y, v0.x, 162 d.y, d.x, v0.y 163 ); 164 } 165 166 static cpTransform 167 cpTransformAxialScale(cpVect axis, cpVect pivot, cpFloat scale) 168 { 169 cpFloat A = axis.x*axis.y*(scale - 1.0); 170 cpFloat B = cpvdot(axis, pivot)*(1.0 - scale); 171 172 return cpTransformNewTranspose( 173 scale*axis.x*axis.x + axis.y*axis.y, A, axis.x*B, 174 A, axis.x*axis.x + scale*axis.y*axis.y, axis.y*B 175 ); 176 }