/** * @ingroup quaternion * @brief Given two vectors, find a quaternion that will get you from one to the other * * @param from the starting vector * @param to the ending vector * @param qR the resulting quaternion that gets you from the starting vector to the ending vector */ HYPAPI quaternion * quaternion_get_rotation_tov3(const vector3 *from, const vector3 *to, quaternion *qR) { /* this code avoids sqrt and cos and sin and would be nice to avoid division */ vector3 w; float dot; float norm; vector3_cross_product(&w, from, to); dot = vector3_dot_product(from, to); qR->x = w.x; qR->y = w.y; qR->z = w.z; qR->w = dot; norm = quaternion_norm(qR); qR->w += norm; /* normalization with avoidance of div/0 and reusing the norm (already calculated above) */ if(norm != 0) { qR->x /= norm; qR->y /= norm; qR->z /= norm; qR->w /= norm; } return qR; }
static char *test_vector3_cross_product(void) { struct vector3 a; struct vector3 b; struct vector3 r; vector3_setf3(&a, 3.0f, -3.0f, 1.0f); vector3_setf3(&b, 4.0f, 9.0f, 2.0f); vector3_cross_product(&r, &a, &b); test_assert(scalar_equalsf(r.x, -15.0f)); test_assert(scalar_equalsf(r.y, -2.0f)); test_assert(scalar_equalsf(r.z, 39.0f)); /* tests lack of commutative property */ vector3_cross_product(&r, &b, &a); test_assert(!scalar_equalsf(r.x, -15.0f)); test_assert(!scalar_equalsf(r.y, -2.0f)); test_assert(!scalar_equalsf(r.z, 39.0f)); return 0; }
/** * @ingroup vector3 * @brief finds the vector describing the normal between two vectors * */ HYPAPI vector3 *vector3_find_normal_axis_between(vector3 *vR, const vector3 *vT1, const vector3 *vT2) { vector3_cross_product(vR, vT1, vT2); vector3_normalize(vR); return vR; }