/* * CS5600 University of Utah * Charles McGarvey * mcgarvey@eng.utah.edu */ #ifndef _VEC_H_ #define _VEC_H_ #include "common.h" /* * A simple vector class. */ struct vec { scal_t x; scal_t y; scal_t z; scal_t w; }; typedef struct vec vec_t; /* * Initialize a vector with four components. */ INLINE_MAYBE void vec_init(vec_t* v, scal_t x, scal_t y, scal_t z, scal_t w) { v->x = x; v->y = y; v->z = z; v->w = w; } /* * Create a new vector with four components. */ INLINE_MAYBE vec_t vec_new2(scal_t x, scal_t y, scal_t z, scal_t w) { vec_t v; vec_init(&v, x, y, z, w); return v; } /* * Create a new vector with three components. The fourth component is * initialized to one. */ INLINE_MAYBE vec_t vec_new(scal_t x, scal_t y, scal_t z) { return vec_new2(x, y, z, S(1.0)); } #define VEC_ZERO vec_new(S(0.0), S(0.0), S(0.0)) #define VEC_ORTHO_X vec_new(S(1.0), S(0.0), S(0.0)) #define VEC_ORTHO_Y vec_new(S(0.0), S(1.0), S(0.0)) #define VEC_ORTHO_Z vec_new(S(0.0), S(0.0), S(1.0)) #define VEC_ZERO_FREE vec_new2(S(0.0), S(0.0), S(0.0), S(0.0)) /* * Print the vector to stdout. */ INLINE_MAYBE void vec_print(vec_t v) { #if (SCALAR_SIZE == 8) const char* fmt = "[ %9.5lf %9.5lf %9.5lf %9.5lf ]"; #else const char* fmt = "[ %9.5f %9.5f %9.5f %9.5f ]"; #endif printf(fmt, v.x, v.y, v.z, v.w); } /* * Calculate the magnitude of the vector, squared. */ INLINE_MAYBE scal_t vec_length2(vec_t v) { return v.x * v.x + v.y * v.y + v.z * v.z; } /* * Calculate the magnitude of the vector. */ INLINE_MAYBE scal_t vec_length(vec_t v) { return scal_sqrt(vec_length2(v)); } /* * Determine whether or not two vectors are exactly equal. */ INLINE_MAYBE bool vec_isequal(vec_t a, vec_t b) { return (a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w); } /* * Determine whether or not two vectors are mostly equal. */ INLINE_MAYBE bool vec_isequal2(vec_t a, vec_t b, scal_t epsilon) { return scal_isequal2(a.x, b.x, epsilon) && scal_isequal2(a.y, b.y, epsilon) && scal_isequal2(a.z, b.z, epsilon) && scal_isequal2(a.w, b.w, epsilon); } /* * Determine if one vector is "less than" another, for purposes of sorting. */ INLINE_MAYBE int vec_compare(vec_t a, vec_t b) { if (vec_isequal(a, b)) { return 0; } return vec_length2(a) < vec_length2(b) ? -1 : 1; } /* * Scale the vector with a scalar value. */ INLINE_MAYBE vec_t vec_scale(vec_t v, scal_t s) { v.x *= s; v.y *= s; v.z *= s; return v; } /* * Add two vectors together. */ INLINE_MAYBE vec_t vec_add(vec_t a, vec_t b) { a.x += b.x; a.y += b.y; a.z += b.z; return a; } /* * Add three vectors together. */ INLINE_MAYBE vec_t vec_add2(vec_t a, vec_t b, vec_t c) { return vec_add(vec_add(a, b), c); } /* * Subtract a vector from another vector. */ INLINE_MAYBE vec_t vec_sub(vec_t a, vec_t b) { a.x -= b.x; a.y -= b.y; a.z -= b.z; return a; } /* * Negate the vector. */ INLINE_MAYBE vec_t vec_neg(vec_t v) { v.x = -v.x; v.y = -v.y; v.z = -v.z; return v; } /* * Get a normalized (unit length) vector. */ INLINE_MAYBE vec_t vec_normalize(vec_t v) { scal_t l = vec_length(v); if (l == S(0.0)) { return VEC_ZERO; } return vec_scale(v, S(1.0) / l); } /* * Get the dot product of two vectors, ignoring the last component. */ INLINE_MAYBE scal_t vec_dot(vec_t a, vec_t b) { return a.x * b.x + a.y * b.y + a.z * b.z; } /* * Get the dot product of two vectors. */ INLINE_MAYBE scal_t vec_dot2(vec_t a, vec_t b) { return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; } /* * Get the cross product of two vectors. */ INLINE_MAYBE vec_t vec_cross(vec_t a, vec_t b) { return vec_new(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x); } /* * Perform a homogeneous divide. */ INLINE_MAYBE vec_t vec_homodiv(vec_t v) { v.x /= v.w; v.y /= v.w; v.z /= v.w; v.w = S(1.0); return v; } /* * Interpolate smoothly between three vectors with barycentric coordinates. */ INLINE_MAYBE vec_t vec_interp(vec_t v1, vec_t v2, vec_t v3, scal_t b[3]) { return vec_new(v1.x * b[0] + v2.x * b[1] + v3.x * b[2], v1.y * b[0] + v2.y * b[1] + v3.y * b[2], v1.z * b[0] + v2.z * b[1] + v3.z * b[2]); } #endif // _VEC_H_