static void Qt_ToBallPoints (Quat q, HVect *arcFrom, HVect *arcTo) { double s; s = sqrt(q.x*q.x + q.y*q.y); if (s == 0.0) *arcFrom = V3_(0.0, 1.0, 0.0); else *arcFrom = V3_(-q.y/s, q.x/s, 0.0); arcTo->x = q.w*arcFrom->x - q.z*arcFrom->y; arcTo->y = q.w*arcFrom->y + q.z*arcFrom->x; arcTo->z = q.x*arcFrom->y - q.y*arcFrom->x; if (q.w < 0.0) *arcFrom = V3_(-arcFrom->x, -arcFrom->y, 0.0); }
static HVect ConstrainToAxis (HVect loose, HVect axis) { HVect onPlane; register double norm; onPlane = V3_Sub(loose, V3_Scale(axis, V3_Dot(axis, loose))); norm = V3_Norm(onPlane); if (norm > 0.0) { if (onPlane.z < 0.0) onPlane = V3_Negate(onPlane); return ( V3_Scale(onPlane, 1/sqrt(norm)) ); } /* else drop through */ /* ================= */ if (axis.z == 1) onPlane = V3_(1.0, 0.0, 0.0); else onPlane = V3_Unit(V3_(-axis.y, axis.x, 0.0)); return (onPlane); }
/* Halve arc between unit vectors v0 and v1. */ HVect V3_Bisect(HVect v0, HVect v1) { HVect v = {0, 0, 0, 0}; float Nv; v = V3_Add(v0, v1); Nv = V3_Norm(v); if (Nv < 1.0e-5) { v = V3_(0, 0, 1); } else { v = V3_Scale(v, 1/sqrt(Nv)); } return (v); }