]> Dogcows Code - chaz/rasterize/blob - tri.h
add texture mapping with perspective correction
[chaz/rasterize] / tri.h
1
2 /*
3 * CS5600 University of Utah
4 * Charles McGarvey
5 * mcgarvey@eng.utah.edu
6 */
7
8 #ifndef _TRI_H_
9 #define _TRI_H_
10
11 #include "aabb.h"
12 #include "mat.h"
13 #include "vert.h"
14
15
16 /*
17 * A triangle is a polygon of three vertices.
18 */
19 struct tri
20 {
21 vert_t a;
22 vert_t b;
23 vert_t c;
24 };
25 typedef struct tri tri_t;
26
27 /*
28 * Initialize a triangle.
29 */
30 INLINE_MAYBE
31 void tri_init(tri_t* t, vert_t a, vert_t b, vert_t c)
32 {
33 t->a = a;
34 t->b = b;
35 t->c = c;
36 }
37
38
39 /*
40 * Create a new triangle.
41 */
42 INLINE_MAYBE
43 tri_t tri_new(vert_t a, vert_t b, vert_t c)
44 {
45 tri_t t;
46 tri_init(&t, a, b, c);
47 return t;
48 }
49
50 #define TRI_ZERO tri_new(VERT_ZERO, VERT_ZERO, VERT_ZERO)
51
52
53 /*
54 * Create a new triangle on the heap.
55 */
56 INLINE_MAYBE
57 tri_t* tri_alloc(vert_t a, vert_t b, vert_t c)
58 {
59 tri_t* t = (tri_t*)mem_alloc(sizeof(tri_t));
60 tri_init(t, a, b, c);
61 return t;
62 }
63
64
65 /*
66 * Apply a transformation matrix to alter the triangle geometry.
67 */
68 INLINE_MAYBE
69 tri_t tri_transform(tri_t t, mat_t m)
70 {
71 t.a.v = mat_apply(m, t.a.v);
72 t.b.v = mat_apply(m, t.b.v);
73 t.c.v = mat_apply(m, t.c.v);
74 t.a.n.w = t.b.n.w = t.c.n.w = S(0.0);
75 t.a.n = vec_normalize(mat_apply(m, t.a.n));
76 t.b.n = vec_normalize(mat_apply(m, t.b.n));
77 t.c.n = vec_normalize(mat_apply(m, t.c.n));
78 return t;
79 }
80
81 /*
82 * Perform a homogeneous divide on the geometry.
83 */
84 INLINE_MAYBE
85 tri_t tri_homodiv(tri_t t)
86 {
87 t.a.v = vec_homodiv(t.a.v);
88 t.b.v = vec_homodiv(t.b.v);
89 t.c.v = vec_homodiv(t.c.v);
90 return t;
91 }
92
93
94 /*
95 * Calculate a normal vector.
96 */
97 INLINE_MAYBE
98 vec_t tri_normal(tri_t t)
99 {
100 vec_t n = vec_cross(vec_sub(t.b.v, t.a.v), vec_sub(t.c.v, t.a.v));
101 return n;
102 }
103
104
105 /*
106 * Calculate the AABB for the triangle.
107 */
108 INLINE_MAYBE
109 aabb_t tri_aabb(tri_t t)
110 {
111 aabb_t b;
112 b.min = vec_new(scal_min2(t.a.v.x, t.b.v.x, t.c.v.x),
113 scal_min2(t.a.v.y, t.b.v.y, t.c.v.y),
114 scal_min2(t.a.v.z, t.b.v.z, t.c.v.z));
115 b.max = vec_new(scal_max2(t.a.v.x, t.b.v.x, t.c.v.x),
116 scal_max2(t.a.v.y, t.b.v.y, t.c.v.y),
117 scal_max2(t.a.v.z, t.b.v.z, t.c.v.z));
118 return b;
119 }
120
121
122 /*
123 * Get the barycentric coordinates of a vector against a triangle. The
124 * returned coordinates will be a linear combination, but they may not
125 * actually be barycentric coordinates. Use the function vec_is_barycentric
126 * to check if they really are barycentric coordinates, meaning the point
127 * vector v is inside the triangle, ignoring the Z components.
128 */
129 INLINE_MAYBE
130 bool tri_barycentric(tri_t t, scal_t* b, vec_t v)
131 {
132 scal_t denom = (t.b.v.y - t.c.v.y) * (t.a.v.x - t.c.v.x) + (t.c.v.x - t.b.v.x) * (t.a.v.y - t.c.v.y);
133 b[0] = ((t.b.v.y - t.c.v.y) * (v.x - t.c.v.x) + (t.c.v.x - t.b.v.x) * (v.y - t.c.v.y)) / denom;
134 b[1] = ((t.c.v.y - t.a.v.y) * (v.x - t.c.v.x) + (t.a.v.x - t.c.v.x) * (v.y - t.c.v.y)) / denom;
135 b[2] = S(1.0) - b[0] - b[1];
136 if (S(0.0) <= b[0] && b[0] <= S(1.0) &&
137 S(0.0) <= b[1] && b[1] <= S(1.0) &&
138 S(0.0) <= b[2] && b[2] <= S(1.0)) {
139 return true;
140 }
141 return false;
142 }
143
144
145 /*
146 * Find the midpoint of the triangle.
147 */
148 INLINE_MAYBE
149 vec_t tri_midpoint(tri_t t)
150 {
151 return vec_new((t.a.v.x + t.b.v.x + t.c.v.x) * S(0.333),
152 (t.a.v.y + t.b.v.y + t.c.v.y) * S(0.333),
153 (t.a.v.z + t.b.v.z + t.c.v.z) * S(0.333));
154 }
155
156 /*
157 * Get the average color of the triangle.
158 */
159 INLINE_MAYBE
160 color_t tri_color(tri_t t)
161 {
162 scal_t b[] = {S(0.333), S(0.333), S(0.333)};
163 return color_interp2(t.a.c, t.b.c, t.c.c, b);
164 }
165
166
167 /*
168 * Get an interpolated z-value at the barycentric coordinates.
169 */
170 INLINE_MAYBE
171 scal_t tri_z(tri_t t, scal_t b[3])
172 {
173 return t.a.v.z * b[0] + t.b.v.z * b[1] + t.c.v.z * b[2];
174 }
175
176 /*
177 * Calculate an interpolated point.
178 */
179 INLINE_MAYBE
180 vec_t tri_point(tri_t t, scal_t b[3])
181 {
182 return vec_interp(t.a.v, t.b.v, t.c.v, b);
183 }
184
185 /*
186 * Calculate an interpolated normal.
187 */
188 INLINE_MAYBE
189 vec_t tri_normal2(tri_t t, scal_t b[3])
190 {
191 return vec_normalize(vec_interp(t.a.n, t.b.n, t.c.n, b));
192 }
193
194 /*
195 * Calculate an interpolated texture coordinate.
196 */
197 INLINE_MAYBE
198 vec_t tri_tcoord(tri_t t, scal_t b[3])
199 {
200 #if PERSPECTIVE_FIX
201 return vec_tinterp(t.a.t, t.b.t, t.c.t, b);
202 #else
203 return vec_interp(t.a.t, t.b.t, t.c.t, b);
204 #endif
205 }
206
207 /*
208 * Calculate an entirely new vertex within the triangle based on barycentric
209 * coordinates.
210 */
211 INLINE_MAYBE
212 vert_t tri_interp(tri_t t, scal_t b[3])
213 {
214 vert_t v = vert_new(tri_point(t, b));
215 v.c = color_interp2(t.a.c, t.b.c, t.c.c, b);
216 v.n = tri_normal2(t, b);
217 v.t = tri_tcoord(t, b);
218 return v;
219 }
220
221
222 #endif // _TRI_H_
223
This page took 0.041693 seconds and 4 git commands to generate.