void* KB_PosInitialize(int numKeys, PositionKey* key) { assert(numKeys >= 4); float omt0, omc0, opc0, omb0, opb0, adj0, out0, out1; float omt1, omc1, opc1, omb1, opb1, adj1, in0, in1; Point3 Tout, Tin; Point3 DP; SplineInfo* info = (SplineInfo*) calloc(1, sizeof(SplineInfo)); info->numPolys = numKeys-3; info->poly = (CubicPolynomial*) calloc(info->numPolys, sizeof(CubicPolynomial)); int i0 = 0, i1 = 1, i2 = 2, i3 = 3; for (; i0 < info->numPolys; i0++, i1++, i2++, i3++) { /* Build P[i2] - P[i1]. */ DP.x = key[i2].P.x - key[i1].P.x; DP.y = key[i2].P.y - key[i1].P.y; DP.z = key[i2].P.z - key[i1].P.z; /* Build multipliers at point P[i1]. Names are derived as follows: * one - minus / plus - t / c / b */ omt0 = 1 - key[i1].tension; //1 - p1.t omc0 = 1 - key[i1].continuity; //1 - p1.c opc0 = 1 + key[i1].continuity; //1 + p1.c omb0 = 1 - key[i1].bias; //1 - p1.b opb0 = 1 + key[i1].bias; //1 + p1.b /* I don't get this adjustment. It differs from the explanation on Wikpedia, and the * 2 cancels with the / 2 later. */ adj0 = 2 * (key[i2].t - key[i1].t) / (key[i2].t - key[i0].t); //2 * (t2 - t1) / (t2 - t0) out0 = (adj0 * omt0 * opc0 * opb0) / 2; out1 = (adj0 * omt0 * omc0 * omb0) / 2; /* Build outgoing tangent at P[i1]. */ Tout.x = out1 * (DP.x) + out0 * (key[i1].P.x - key[i0].P.x); Tout.y = out1 * (DP.y) + out0 * (key[i1].P.y - key[i0].P.y); Tout.z = out1 * (DP.z) + out0 * (key[i1].P.z - key[i0].P.z); /* Build multipliers at point P[i2]. */ omt1 = 1 - key[i2].tension; //1 - p2.t omc1 = 1 - key[i2].continuity; //1 - p2.c opc1 = 1 + key[i2].continuity; //1 + p2.c omb1 = 1 - key[i2].bias; //1 - p2.b opb1 = 1 + key[i2].bias; //1 + p2.b adj1 = 2 * (key[i2].t - key[i1].t) / (key[i3].t - key[i1].t); //2 * (t2 - t1) / (t3 - t1) in0 = (adj1 * omt1 * omc1 * opb1) / 2; in1 = (adj1 * omt1 * opc1 * omb1) / 2; /* Build incoming tangent at P[i2]. */ Tin.x = in1 * (key[i3].P.x - key[i2].P.x) + in0 * (DP.x); Tin.y = in1 * (key[i3].P.y - key[i2].P.y) + in0 * (DP.y); Tin.z = in1 * (key[i3].P.z - key[i2].P.z) + in0 * (DP.z); info->poly[i0].C0.x = key[i1].P.x; info->poly[i0].C0.y = key[i1].P.y; info->poly[i0].C0.z = key[i1].P.z; info->poly[i0].C1.x = Tout.x; info->poly[i0].C1.y = Tout.y; info->poly[i0].C1.z = Tout.z; info->poly[i0].C2.x = 3 * DP.x - 2 * Tout.x - Tin.x; info->poly[i0].C2.y = 3 * DP.y - 2 * Tout.y - Tin.y; info->poly[i0].C2.z = 3 * DP.z - 2 * Tout.z - Tin.z; info->poly[i0].C3.x = -2 * DP.x + Tout.x + Tin.x; info->poly[i0].C3.y = -2 * DP.y + Tout.y + Tin.y; info->poly[i0].C3.z = -2 * DP.z + Tout.z + Tin.z; info->poly[i0].tmin = key[i1].t; info->poly[i0].tmax = key[i2].t; info->poly[i0].trange = info->poly[i0].tmax - info->poly[i0].tmin; } ComputeArcLength(info); return info; }
/*-------------------------------------------------------------------------*/ void* KB_PosInitialize (int numKeys, PositionKey* key) { /* assert: numKeys >= 4 */ double omt0, omc0, opc0, omb0, opb0, adj0, out0, out1; double omt1, omc1, opc1, omb1, opb1, adj1, in0, in1; Point3 Tout, Tin; Point3 DP; int i0 = 0, i1 = 1, i2 = 2, i3 = 3; SplineInfo* info = (SplineInfo*)calloc(1, sizeof(SplineInfo)); info->numPolys = numKeys-3; info->poly = (CubicPolynomial*)calloc(info->numPolys, sizeof(CubicPolynomial)); for (/**/; i0 < info->numPolys; i0++, i1++, i2++, i3++) { /* build P[i2]-P[i1]; */ DP.x = key[i2].P.x - key[i1].P.x; DP.y = key[i2].P.y - key[i1].P.y; DP.z = key[i2].P.z - key[i1].P.z; /* build multipliers at point P[i1] */ omt0 = 1-key[i1].tension; omc0 = 1-key[i1].continuity; opc0 = 1+key[i1].continuity; omb0 = 1-key[i1].bias; opb0 = 1+key[i1].bias; adj0 = 2*(key[i2].t-key[i1].t)/(key[i2].t-key[i0].t); out0 = 0.5*adj0*omt0*opc0*opb0; out1 = 0.5*adj0*omt0*omc0*omb0; /* build outgoing tangent at P[i1] */ Tout.x = out1*(DP.x)+out0*(key[i1].P.x-key[i0].P.x); Tout.y = out1*(DP.y)+out0*(key[i1].P.y-key[i0].P.y); Tout.z = out1*(DP.z)+out0*(key[i1].P.z-key[i0].P.z); /* build multipliers at point P[i2] */ omt1 = 1-key[i2].tension; omc1 = 1-key[i2].continuity; opc1 = 1+key[i2].continuity; omb1 = 1-key[i2].bias; opb1 = 1+key[i2].bias; adj1 = 2*(key[i2].t-key[i1].t)/(key[i3].t-key[i1].t); in0 = 0.5*adj1*omt1*omc1*opb1; in1 = 0.5*adj1*omt1*opc1*omb1; /* build incoming tangent at P[i2] */ Tin.x = in1*(key[i3].P.x-key[i2].P.x)+in0*(DP.x); Tin.y = in1*(key[i3].P.y-key[i2].P.y)+in0*(DP.y); Tin.z = in1*(key[i3].P.z-key[i2].P.z)+in0*(DP.z); info->poly[i0].C0.x = key[i1].P.x; info->poly[i0].C0.y = key[i1].P.y; info->poly[i0].C0.z = key[i1].P.z; info->poly[i0].C1.x = Tout.x; info->poly[i0].C1.y = Tout.y; info->poly[i0].C1.z = Tout.z; info->poly[i0].C2.x = 3*DP.x-2*Tout.x-Tin.x; info->poly[i0].C2.y = 3*DP.y-2*Tout.y-Tin.y; info->poly[i0].C2.z = 3*DP.z-2*Tout.z-Tin.z; info->poly[i0].C3.x = -2*DP.x+Tout.x+Tin.x; info->poly[i0].C3.y = -2*DP.y+Tout.y+Tin.y; info->poly[i0].C3.z = -2*DP.z+Tout.z+Tin.z; info->poly[i0].tmin = key[i1].t; info->poly[i0].tmax = key[i2].t; info->poly[i0].trange = info->poly[i0].tmax-info->poly[i0].tmin; } ComputeArcLength(info); return info; }