2 /*
3 * CS5600 University of Utah
4 * Charles McGarvey
5 * mcgarvey@eng.utah.edu
6 */
8 #ifndef _TRI_H_
9 #define _TRI_H_
11 #include "aabb.h"
12 #include "mat.h"
13 #include "vert.h"
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;
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 }
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 }
50 #define TRI_ZERO tri_new(VERT_ZERO, VERT_ZERO, VERT_ZERO)
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 }
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 return t;
75 }
77 /*
78 * Perform a homogeneous divide on the geometry.
79 */
80 INLINE_MAYBE
81 tri_t tri_homodiv(tri_t t)
82 {
83 t.a.v = vec_homodiv(t.a.v);
84 t.b.v = vec_homodiv(t.b.v);
85 t.c.v = vec_homodiv(t.c.v);
86 return t;
87 }
90 /*
91 * Calculate a normal vector.
92 */
93 INLINE_MAYBE
94 vec_t tri_normal(tri_t t)
95 {
96 return vec_cross(vec_sub(t.b.v, t.a.v), vec_sub(t.c.v, t.a.v));
97 }
100 /*
101 * Calculate the AABB for the triangle.
102 */
103 INLINE_MAYBE
104 aabb_t tri_aabb(tri_t t)
105 {
106 aabb_t b;
107 b.min = vec_new(scal_min2(t.a.v.x, t.b.v.x, t.c.v.x),
108 scal_min2(t.a.v.y, t.b.v.y, t.c.v.y),
109 scal_min2(t.a.v.z, t.b.v.z, t.c.v.z));
110 b.max = vec_new(scal_max2(t.a.v.x, t.b.v.x, t.c.v.x),
111 scal_max2(t.a.v.y, t.b.v.y, t.c.v.y),
112 scal_max2(t.a.v.z, t.b.v.z, t.c.v.z));
113 return b;
114 }
117 /*
118 * Get the barycentric coordinates of a vector against a triangle. The
119 * returned coordinates will be a linear combination, but they may not
120 * actually be barycentric coordinates. Use the function vec_is_barycentric
121 * to check if they really are barycentric coordinates, meaning the point
122 * vector v is inside the triangle, ignoring the Z components.
123 */
124 INLINE_MAYBE
125 bool tri_barycentric(tri_t t, scal_t* b, vec_t v)
126 {
127 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);
128 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;
129 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;
130 b[2] = S(1.0) - b[0] - b[1];
131 if (S(0.0) <= b[0] && b[0] <= S(1.0) &&
132 S(0.0) <= b[1] && b[1] <= S(1.0) &&
133 S(0.0) <= b[2] && b[2] <= S(1.0)) {
134 return true;
135 }
136 return false;
137 }
140 /*
141 * Get an interpolated z-value at the barycentric coordinates.
142 */
143 INLINE_MAYBE
144 scal_t tri_z(tri_t t, scal_t b[3])
145 {
146 return t.a.v.z * b[0] + t.b.v.z * b[1] + t.c.v.z * b[2];
147 }
149 /*
150 * Find the midpoint of the triangle.
151 */
152 INLINE_MAYBE
153 vec_t tri_midpoint(tri_t t)
154 {
155 return vec_new((t.a.v.x + t.b.v.x + t.c.v.x) * S(0.333),
156 (t.a.v.y + t.b.v.y + t.c.v.y) * S(0.333),
157 (t.a.v.z + t.b.v.z + t.c.v.z) * S(0.333));
158 }
160 /*
161 * Get the average color of the triangle.
162 */
163 INLINE_MAYBE
164 color_t tri_color(tri_t t)
165 {
166 scal_t b[] = {S(0.333), S(0.333), S(0.333)};
167 return color_interp2(t.a.c, t.b.c, t.c.c, b);
168 }
171 #endif // _TRI_H_