X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Frasterize;a=blobdiff_plain;f=vec.h;h=48635238202c5de1a437161028112bf1085352c1;hp=f08945c444275218dbbd92ae0cedc8a8b3f36927;hb=95850b98f73ad7033af60a30e324e9c3cda55389;hpb=0f2508a4f227523a6b7e54798487af19d06a6ce9 diff --git a/vec.h b/vec.h index f08945c..4863523 100644 --- a/vec.h +++ b/vec.h @@ -5,8 +5,8 @@ * mcgarvey@eng.utah.edu */ -#ifndef __VEC_H__ -#define __VEC_H__ +#ifndef _VEC_H_ +#define _VEC_H_ #include "common.h" @@ -26,7 +26,7 @@ typedef struct vec vec_t; /* * Initialize a vector with four components. */ -__fast__ +INLINE_MAYBE void vec_init(vec_t* v, scal_t x, scal_t y, scal_t z, scal_t w) { v->x = x; @@ -39,7 +39,7 @@ void vec_init(vec_t* v, scal_t x, scal_t y, scal_t z, scal_t w) /* * Create a new vector with four components. */ -__fast__ +INLINE_MAYBE vec_t vec_new2(scal_t x, scal_t y, scal_t z, scal_t w) { vec_t v; @@ -51,22 +51,91 @@ vec_t vec_new2(scal_t x, scal_t y, scal_t z, scal_t w) * Create a new vector with three components. The fourth component is * initialized to one. */ -__fast__ +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 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. */ -__fast__ +INLINE_MAYBE vec_t vec_scale(vec_t v, scal_t s) { v.x *= s; @@ -78,7 +147,7 @@ vec_t vec_scale(vec_t v, scal_t s) /* * Add two vectors together. */ -__fast__ +INLINE_MAYBE vec_t vec_add(vec_t a, vec_t b) { a.x += b.x; @@ -87,10 +156,19 @@ vec_t vec_add(vec_t a, vec_t b) 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. */ -__fast__ +INLINE_MAYBE vec_t vec_sub(vec_t a, vec_t b) { a.x -= b.x; @@ -99,46 +177,90 @@ vec_t vec_sub(vec_t a, vec_t b) 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 the dot product of two vectors. + * Get a normalized (unit length) vector. */ -__fast__ -scal_t vec_dot(vec_t a, vec_t b) +INLINE_MAYBE +vec_t vec_normalize(vec_t v) { - return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; + 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. */ -__fast__ -scal_t vec_dot3(vec_t a, vec_t b) +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; +} + /* - * Check whether the values of the first three components could actually be - * barycentric coordinates. Note: The necessary condition of each component - * adding up to one is assumed and not checked. + * Get the cross product of two vectors. */ -__fast__ -bool vec_is_barycentric(vec_t v) +INLINE_MAYBE +vec_t vec_cross(vec_t a, vec_t b) { - /* - * XXX: I'm fudging the bounds a little because horizontal edges (relative - * to the screen) are otherwise sometimes really jagged. This probably - * isn't the best solution. - */ - if (S(-0.000001) <= v.x && v.x <= S(1.000001) && - S(-0.000001) <= v.y && v.y <= S(1.000001) && - S(-0.000001) <= v.z && v.z <= S(1.000001)) { - return true; - } - return false; + 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; } -#endif // __VEC_H__ + +/* + * 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_