2 /*
3 * CS5600 University of Utah
4 * Charles McGarvey
5 * mcgarvey@eng.utah.edu
6 */
8 #ifndef _VEC_H_
9 #define _VEC_H_
11 #include "common.h"
14 /*
15 * A simple vector class.
16 */
17 struct vec
18 {
19 scal_t x;
20 scal_t y;
21 scal_t z;
22 scal_t w;
23 };
24 typedef struct vec vec_t;
26 /*
27 * Initialize a vector with four components.
28 */
29 INLINE_MAYBE
30 void vec_init(vec_t* v, scal_t x, scal_t y, scal_t z, scal_t w)
31 {
32 v->x = x;
33 v->y = y;
34 v->z = z;
35 v->w = w;
36 }
39 /*
40 * Create a new vector with four components.
41 */
42 INLINE_MAYBE
43 vec_t vec_new2(scal_t x, scal_t y, scal_t z, scal_t w)
44 {
45 vec_t v;
46 vec_init(&v, x, y, z, w);
47 return v;
48 }
50 /*
51 * Create a new vector with three components. The fourth component is
52 * initialized to one.
53 */
54 INLINE_MAYBE
55 vec_t vec_new(scal_t x, scal_t y, scal_t z)
56 {
57 return vec_new2(x, y, z, S(1.0));
58 }
60 #define VEC_ZERO vec_new(S(0.0), S(0.0), S(0.0))
61 #define VEC_ORTHO_X vec_new(S(1.0), S(0.0), S(0.0))
62 #define VEC_ORTHO_Y vec_new(S(0.0), S(1.0), S(0.0))
63 #define VEC_ORTHO_Z vec_new(S(0.0), S(0.0), S(1.0))
64 #define VEC_ZERO_FREE vec_new2(S(0.0), S(0.0), S(0.0), S(0.0))
67 /*
68 * Print the vector to stdout.
69 */
70 INLINE_MAYBE
71 void vec_print(vec_t v)
72 {
73 #if (SCALAR_SIZE == 8)
74 const char* fmt = "[ %9.5lf %9.5lf %9.5lf %9.5lf ]";
75 #else
76 const char* fmt = "[ %9.5f %9.5f %9.5f %9.5f ]";
77 #endif
78 printf(fmt, v.x, v.y, v.z, v.w);
79 }
82 /*
83 * Calculate the magnitude of the vector, squared.
84 */
85 INLINE_MAYBE
86 scal_t vec_length2(vec_t v)
87 {
88 return v.x * v.x + v.y * v.y + v.z * v.z;
89 }
91 /*
92 * Calculate the magnitude of the vector.
93 */
94 INLINE_MAYBE
95 scal_t vec_length(vec_t v)
96 {
97 return scal_sqrt(vec_length2(v));
98 }
101 /*
102 * Determine whether or not two vectors are exactly equal.
103 */
104 INLINE_MAYBE
105 bool vec_isequal(vec_t a, vec_t b)
106 {
107 return (a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w);
108 }
110 /*
111 * Determine whether or not two vectors are mostly equal.
112 */
113 INLINE_MAYBE
114 bool vec_isequal2(vec_t a, vec_t b, scal_t epsilon)
115 {
116 return scal_isequal2(a.x, b.x, epsilon) &&
117 scal_isequal2(a.y, b.y, epsilon) &&
118 scal_isequal2(a.z, b.z, epsilon) &&
119 scal_isequal2(a.w, b.w, epsilon);
120 }
122 /*
123 * Determine if one vector is "less than" another, for purposes of sorting.
124 */
125 INLINE_MAYBE
126 int vec_compare(vec_t a, vec_t b)
127 {
128 if (vec_isequal(a, b)) {
129 return 0;
130 }
131 return vec_length2(a) < vec_length2(b) ? -1 : 1;
132 }
135 /*
136 * Scale the vector with a scalar value.
137 */
138 INLINE_MAYBE
139 vec_t vec_scale(vec_t v, scal_t s)
140 {
141 v.x *= s;
142 v.y *= s;
143 v.z *= s;
144 return v;
145 }
147 /*
148 * Add two vectors together.
149 */
150 INLINE_MAYBE
151 vec_t vec_add(vec_t a, vec_t b)
152 {
153 a.x += b.x;
154 a.y += b.y;
155 a.z += b.z;
156 return a;
157 }
159 /*
160 * Add three vectors together.
161 */
162 INLINE_MAYBE
163 vec_t vec_add2(vec_t a, vec_t b, vec_t c)
164 {
166 }
168 /*
169 * Subtract a vector from another vector.
170 */
171 INLINE_MAYBE
172 vec_t vec_sub(vec_t a, vec_t b)
173 {
174 a.x -= b.x;
175 a.y -= b.y;
176 a.z -= b.z;
177 return a;
178 }
180 /*
181 * Negate the vector.
182 */
183 INLINE_MAYBE
184 vec_t vec_neg(vec_t v)
185 {
186 v.x = -v.x;
187 v.y = -v.y;
188 v.z = -v.z;
189 return v;
190 }
193 /*
194 * Get a normalized (unit length) vector.
195 */
196 INLINE_MAYBE
197 vec_t vec_normalize(vec_t v)
198 {
199 scal_t l = vec_length(v);
200 if (l == S(0.0)) {
201 return VEC_ZERO;
202 }
203 return vec_scale(v, S(1.0) / l);
204 }
207 /*
208 * Get the dot product of two vectors, ignoring the last component.
209 */
210 INLINE_MAYBE
211 scal_t vec_dot(vec_t a, vec_t b)
212 {
213 return a.x * b.x + a.y * b.y + a.z * b.z;
214 }
216 /*
217 * Get the dot product of two vectors.
218 */
219 INLINE_MAYBE
220 scal_t vec_dot2(vec_t a, vec_t b)
221 {
222 return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
223 }
226 /*
227 * Get the cross product of two vectors.
228 */
229 INLINE_MAYBE
230 vec_t vec_cross(vec_t a, vec_t b)
231 {
232 return vec_new(a.y * b.z - a.z * b.y,
233 a.z * b.x - a.x * b.z,
234 a.x * b.y - a.y * b.x);
235 }
238 /*
239 * Perform a homogeneous divide.
240 */
241 INLINE_MAYBE
242 vec_t vec_homodiv(vec_t v)
243 {
244 v.x /= v.w;
245 v.y /= v.w;
246 v.z /= v.w;
247 v.w = S(1.0);
248 return v;
249 }
252 /*
253 * Interpolate smoothly between three vectors with barycentric coordinates.
254 */
255 INLINE_MAYBE
256 vec_t vec_interp(vec_t v1, vec_t v2, vec_t v3, scal_t b[3])
257 {
258 return vec_new(v1.x * b[0] + v2.x * b[1] + v3.x * b[2],
259 v1.y * b[0] + v2.y * b[1] + v3.y * b[2],
260 v1.z * b[0] + v2.z * b[1] + v3.z * b[2]);
261 }
265 #endif // _VEC_H_