]> Dogcows Code - chaz/rasterize/blob - vec.h
add opengl support
[chaz/rasterize] / vec.h
1
2 /*
3 * CS5600 University of Utah
4 * Charles McGarvey
5 * mcgarvey@eng.utah.edu
6 */
7
8 #ifndef _VEC_H_
9 #define _VEC_H_
10
11 #include "common.h"
12
13
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;
25
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 }
37
38
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 }
49
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 }
59
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))
65
66
67 /*
68 * Get a pointer to the vector data.
69 */
70 INLINE_MAYBE
71 const scal_t* vec_data(const vec_t* v)
72 {
73 return &v->x;
74 }
75
76
77 /*
78 * Print the vector to stdout.
79 */
80 INLINE_MAYBE
81 void vec_print(vec_t v)
82 {
83 #if (SCALAR_SIZE == 8)
84 const char* fmt = "[ %9.5lf %9.5lf %9.5lf %9.5lf ]";
85 #else
86 const char* fmt = "[ %9.5f %9.5f %9.5f %9.5f ]";
87 #endif
88 printf(fmt, v.x, v.y, v.z, v.w);
89 }
90
91
92 /*
93 * Calculate the magnitude of the vector, squared.
94 */
95 INLINE_MAYBE
96 scal_t vec_length2(vec_t v)
97 {
98 return v.x * v.x + v.y * v.y + v.z * v.z;
99 }
100
101 /*
102 * Calculate the magnitude of the vector.
103 */
104 INLINE_MAYBE
105 scal_t vec_length(vec_t v)
106 {
107 return scal_sqrt(vec_length2(v));
108 }
109
110
111 /*
112 * Determine whether or not two vectors are exactly equal.
113 */
114 INLINE_MAYBE
115 bool vec_isequal(vec_t a, vec_t b)
116 {
117 return (a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w);
118 }
119
120 /*
121 * Determine whether or not two vectors are mostly equal.
122 */
123 INLINE_MAYBE
124 bool vec_isequal2(vec_t a, vec_t b, scal_t epsilon)
125 {
126 return scal_isequal2(a.x, b.x, epsilon) &&
127 scal_isequal2(a.y, b.y, epsilon) &&
128 scal_isequal2(a.z, b.z, epsilon) &&
129 scal_isequal2(a.w, b.w, epsilon);
130 }
131
132 /*
133 * Determine if one vector is "less than" another, for purposes of sorting.
134 */
135 INLINE_MAYBE
136 int vec_compare(vec_t a, vec_t b)
137 {
138 if (vec_isequal(a, b)) {
139 return 0;
140 }
141 return vec_length2(a) < vec_length2(b) ? -1 : 1;
142 }
143
144
145 /*
146 * Scale the vector with a scalar value.
147 */
148 INLINE_MAYBE
149 vec_t vec_scale(vec_t v, scal_t s)
150 {
151 v.x *= s;
152 v.y *= s;
153 v.z *= s;
154 return v;
155 }
156
157 /*
158 * Add two vectors together.
159 */
160 INLINE_MAYBE
161 vec_t vec_add(vec_t a, vec_t b)
162 {
163 a.x += b.x;
164 a.y += b.y;
165 a.z += b.z;
166 return a;
167 }
168
169 /*
170 * Add three vectors together.
171 */
172 INLINE_MAYBE
173 vec_t vec_add2(vec_t a, vec_t b, vec_t c)
174 {
175 return vec_add(vec_add(a, b), c);
176 }
177
178 /*
179 * Subtract a vector from another vector.
180 */
181 INLINE_MAYBE
182 vec_t vec_sub(vec_t a, vec_t b)
183 {
184 a.x -= b.x;
185 a.y -= b.y;
186 a.z -= b.z;
187 return a;
188 }
189
190 /*
191 * Negate the vector.
192 */
193 INLINE_MAYBE
194 vec_t vec_neg(vec_t v)
195 {
196 v.x = -v.x;
197 v.y = -v.y;
198 v.z = -v.z;
199 return v;
200 }
201
202
203 /*
204 * Get a normalized (unit length) vector.
205 */
206 INLINE_MAYBE
207 vec_t vec_normalize(vec_t v)
208 {
209 scal_t l = vec_length(v);
210 if (l == S(0.0)) {
211 return VEC_ZERO;
212 }
213 return vec_scale(v, S(1.0) / l);
214 }
215
216
217 /*
218 * Get the dot product of two vectors, ignoring the last component.
219 */
220 INLINE_MAYBE
221 scal_t vec_dot(vec_t a, vec_t b)
222 {
223 return a.x * b.x + a.y * b.y + a.z * b.z;
224 }
225
226 /*
227 * Get the dot product of two vectors.
228 */
229 INLINE_MAYBE
230 scal_t vec_dot2(vec_t a, vec_t b)
231 {
232 return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
233 }
234
235
236 /*
237 * Get the cross product of two vectors.
238 */
239 INLINE_MAYBE
240 vec_t vec_cross(vec_t a, vec_t b)
241 {
242 return vec_new(a.y * b.z - a.z * b.y,
243 a.z * b.x - a.x * b.z,
244 a.x * b.y - a.y * b.x);
245 }
246
247
248 /*
249 * Perform a homogeneous divide.
250 */
251 INLINE_MAYBE
252 vec_t vec_homodiv(vec_t v)
253 {
254 v.x /= v.w;
255 v.y /= v.w;
256 v.z /= v.w;
257 v.w = S(1.0);
258 return v;
259 }
260
261
262 /*
263 * Interpolate smoothly between three vectors with barycentric coordinates.
264 */
265 INLINE_MAYBE
266 vec_t vec_interp(vec_t v1, vec_t v2, vec_t v3, scal_t b[3])
267 {
268 return vec_new(v1.x * b[0] + v2.x * b[1] + v3.x * b[2],
269 v1.y * b[0] + v2.y * b[1] + v3.y * b[2],
270 v1.z * b[0] + v2.z * b[1] + v3.z * b[2]);
271 }
272
273 /*
274 * Interpolate smoothly between three texture coordinates with barycentric
275 * coordinates and perspective correction.
276 */
277 INLINE_MAYBE
278 vec_t vec_tinterp(vec_t v1, vec_t v2, vec_t v3, scal_t b[3])
279 {
280 scal_t denom = (S(1.0) / v1.w) * b[0]
281 + (S(1.0) / v2.w) * b[1]
282 + (S(1.0) / v3.w) * b[2];
283 return vec_new(scal_clamp(((v1.x / v1.w) * b[0]
284 + (v2.x / v2.w) * b[1]
285 + (v3.x / v3.w) * b[2]) / denom, S(0.0), S(1.0)),
286 scal_clamp(((v1.y / v1.w) * b[0]
287 + (v2.y / v2.w) * b[1]
288 + (v3.y / v3.w) * b[2]) / denom, S(0.0), S(1.0)),
289 S(0.0));
290 }
291
292
293 #endif // _VEC_H_
294
This page took 0.047162 seconds and 4 git commands to generate.