CSCI441 OpenGL Library 5.9.0
CS@Mines CSCI441 Computer Graphics Course Library
Loading...
Searching...
No Matches
teapot.hpp
Go to the documentation of this file.
1
17#ifndef CSCI441_TEAPOT_HPP
18#define CSCI441_TEAPOT_HPP
19
20#ifdef CSCI441_USE_GLEW
21 #include <GL/glew.h>
22#else
23 #include <glad/gl.h>
24#endif
25
26#include <cstdio>
27#include <cstdlib>
28#include <cmath>
29
30namespace CSCI441_INTERNAL {
31
32 // Draws the Utah teapot as a static collection of Bezier surfaces with position, normal, and texture vertex data
33 // GLfloat unused (kept for legacy consistency)
34 // GLint vertex position attribute location within shader program
35 // GLint vertex normal attribute location within shader program (defaults to -1 and unused)
36 // GLint vertex texture coordinate attribute location within shader program (defaults to -1 and unused)
37 [[maybe_unused]] void teapot( GLfloat size, GLint positionLocation, GLint normalLocation = -1, GLint texCoordLocation = -1);
38
39 // Enables VBO attribute array locations
40 // GLint vertex position attribute location within shader program
41 // GLint vertex normal attribute location within shader program (defaults to -1 and unused)
42 // GLint vertex texture coordinate attribute location within shader program (defaults to -1 and unused)
43 void setTeapotAttributeLocations(GLint positionLocation, GLint normalLocation = -1, GLint texCoordLocation = -1);
44
45 // Draws the Utah teapot as a static collection of Bezier surfaces with position, normal, and
46 // texture vertex data
47 // setTeapotAttributeLocations() must be called first
48 void teapot();
49
50 //************************************************************************************************
51 //************************************************************************************************
52
53 const GLuint TEAPOT_NUMBER_PATCHES = 28;
54 const GLuint TEAPOT_PATCH_DIMENSION = 3;
55 const GLuint TEAPOT_RES_U = 10;
56 const GLuint TEAPOT_RES_V = 10;
57
58 inline GLuint teapot_vao;
59 inline GLuint teapot_vbo, teapot_ibo;
60
61 inline glm::vec3 teapot_cp_vertices[] = {
62 // 1
63 { 1.4f , 0.0f , 2.4f },
64 { 1.4f , -0.784f , 2.4f },
65 { 0.784f , -1.4f , 2.4f },
66 { 0.0f , -1.4f , 2.4f },
67 { 1.3375f, 0.0f , 2.53125f },
68 { 1.3375f, -0.749f , 2.53125f },
69 { 0.749f , -1.3375f, 2.53125f },
70 { 0.0f , -1.3375f, 2.53125f },
71 { 1.4375f, 0.0f , 2.53125f },
72 { 1.4375f, -0.805f , 2.53125f },
73 // 11
74 { 0.805f , -1.4375f, 2.53125f },
75 { 0.0f , -1.4375f, 2.53125f },
76 { 1.5f , 0.0f , 2.4f },
77 { 1.5f , -0.84f , 2.4f },
78 { 0.84f , -1.5f , 2.4f },
79 { 0.0f , -1.5f , 2.4f },
80 { -0.784f , -1.4f , 2.4f },
81 { -1.4f , -0.784f , 2.4f },
82 { -1.4f , 0.0f , 2.4f },
83 { -0.749f , -1.3375f, 2.53125f },
84 // 21
85 { -1.3375f, -0.749f , 2.53125f },
86 { -1.3375f, 0.0f , 2.53125f },
87 { -0.805f , -1.4375f, 2.53125f },
88 { -1.4375f, -0.805f , 2.53125f },
89 { -1.4375f, 0.0f , 2.53125f },
90 { -0.84f , -1.5f , 2.4f },
91 { -1.5f , -0.84f , 2.4f },
92 { -1.5f , 0.0f , 2.4f },
93 { -1.4f , 0.784f , 2.4f },
94 { -0.784f , 1.4f , 2.4f },
95 // 31
96 { 0.0f , 1.4f , 2.4f },
97 { -1.3375f, 0.749f , 2.53125f },
98 { -0.749f , 1.3375f, 2.53125f },
99 { 0.0f , 1.3375f, 2.53125f },
100 { -1.4375f, 0.805f , 2.53125f },
101 { -0.805f , 1.4375f, 2.53125f },
102 { 0.0f , 1.4375f, 2.53125f },
103 { -1.5f , 0.84f , 2.4f },
104 { -0.84f , 1.5f , 2.4f },
105 { 0.0f , 1.5f , 2.4f },
106 // 41
107 { 0.784f , 1.4f , 2.4f },
108 { 1.4f , 0.784f , 2.4f },
109 { 0.749f , 1.3375f, 2.53125f },
110 { 1.3375f, 0.749f , 2.53125f },
111 { 0.805f , 1.4375f, 2.53125f },
112 { 1.4375f, 0.805f , 2.53125f },
113 { 0.84f , 1.5f , 2.4f },
114 { 1.5f , 0.84f , 2.4f },
115 { 1.75f , 0.0f , 1.875f },
116 { 1.75f , -0.98f , 1.875f },
117 // 51
118 { 0.98f , -1.75f , 1.875f },
119 { 0.0f , -1.75f , 1.875f },
120 { 2.0f , 0.0f , 1.35f },
121 { 2.0f , -1.12f , 1.35f },
122 { 1.12f , -2.0f , 1.35f },
123 { 0.0f , -2.0f , 1.35f },
124 { 2.0f , 0.0f , 0.9f },
125 { 2.0f , -1.12f , 0.9f },
126 { 1.12f , -2.0f , 0.9f },
127 { 0.0f , -2.0f , 0.9f },
128 // 61
129 { -0.98f , -1.75f , 1.875f },
130 { -1.75f , -0.98f , 1.875f },
131 { -1.75f , 0.0f , 1.875f },
132 { -1.12f , -2.0f , 1.35f },
133 { -2.0f , -1.12f , 1.35f },
134 { -2.0f , 0.0f , 1.35f },
135 { -1.12f , -2.0f , 0.9f },
136 { -2.0f , -1.12f , 0.9f },
137 { -2.0f , 0.0f , 0.9f },
138 { -1.75f , 0.98f , 1.875f },
139 // 71
140 { -0.98f , 1.75f , 1.875f },
141 { 0.0f , 1.75f , 1.875f },
142 { -2.0f , 1.12f , 1.35f },
143 { -1.12f , 2.0f , 1.35f },
144 { 0.0f , 2.0f , 1.35f },
145 { -2.0f , 1.12f , 0.9f },
146 { -1.12f , 2.0f , 0.9f },
147 { 0.0f , 2.0f , 0.9f },
148 { 0.98f , 1.75f , 1.875f },
149 { 1.75f , 0.98f , 1.875f },
150 // 81
151 { 1.12f , 2.0f , 1.35f },
152 { 2.0f , 1.12f , 1.35f },
153 { 1.12f , 2.0f , 0.9f },
154 { 2.0f , 1.12f , 0.9f },
155 { 2.0f , 0.0f , 0.45f },
156 { 2.0f , -1.12f , 0.45f },
157 { 1.12f , -2.0f , 0.45f },
158 { 0.0f , -2.0f , 0.45f },
159 { 1.5f , 0.0f , 0.225f },
160 { 1.5f , -0.84f , 0.225f },
161 // 91
162 { 0.84f , -1.5f , 0.225f },
163 { 0.0f , -1.5f , 0.225f },
164 { 1.5f , 0.0f , 0.15f },
165 { 1.5f , -0.84f , 0.15f },
166 { 0.84f , -1.5f , 0.15f },
167 { 0.0f , -1.5f , 0.15f },
168 { -1.12f , -2.0f , 0.45f },
169 { -2.0f , -1.12f , 0.45f },
170 { -2.0f , 0.0f , 0.45f },
171 { -0.84f , -1.5f , 0.225f },
172 // 101
173 { -1.5f , -0.84f , 0.225f },
174 { -1.5f , 0.0f , 0.225f },
175 { -0.84f , -1.5f , 0.15f },
176 { -1.5f , -0.84f , 0.15f },
177 { -1.5f , 0.0f , 0.15f },
178 { -2.0f , 1.12f , 0.45f },
179 { -1.12f , 2.0f , 0.45f },
180 { 0.0f , 2.0f , 0.45f },
181 { -1.5f , 0.84f , 0.225f },
182 { -0.84f , 1.5f , 0.225f },
183 // 111
184 { 0.0f , 1.5f , 0.225f },
185 { -1.5f , 0.84f , 0.15f },
186 { -0.84f , 1.5f , 0.15f },
187 { 0.0f , 1.5f , 0.15f },
188 { 1.12f , 2.0f , 0.45f },
189 { 2.0f , 1.12f , 0.45f },
190 { 0.84f , 1.5f , 0.225f },
191 { 1.5f , 0.84f , 0.225f },
192 { 0.84f , 1.5f , 0.15f },
193 { 1.5f , 0.84f , 0.15f },
194 // 121
195 { -1.6f , 0.0f , 2.025f },
196 { -1.6f , -0.3f , 2.025f },
197 { -1.5f , -0.3f , 2.25f },
198 { -1.5f , 0.0f , 2.25f },
199 { -2.3f , 0.0f , 2.025f },
200 { -2.3f , -0.3f , 2.025f },
201 { -2.5f , -0.3f , 2.25f },
202 { -2.5f , 0.0f , 2.25f },
203 { -2.7f , 0.0f , 2.025f },
204 { -2.7f , -0.3f , 2.025f },
205 // 131
206 { -3.0f , -0.3f , 2.25f },
207 { -3.0f , 0.0f , 2.25f },
208 { -2.7f , 0.0f , 1.8f },
209 { -2.7f , -0.3f , 1.8f },
210 { -3.0f , -0.3f , 1.8f },
211 { -3.0f , 0.0f , 1.8f },
212 { -1.5f , 0.3f , 2.25f },
213 { -1.6f , 0.3f , 2.025f },
214 { -2.5f , 0.3f , 2.25f },
215 { -2.3f , 0.3f , 2.025f },
216 // 141
217 { -3.0f , 0.3f , 2.25f },
218 { -2.7f , 0.3f , 2.025f },
219 { -3.0f , 0.3f , 1.8f },
220 { -2.7f , 0.3f , 1.8f },
221 { -2.7f , 0.0f , 1.575f },
222 { -2.7f , -0.3f , 1.575f },
223 { -3.0f , -0.3f , 1.35f },
224 { -3.0f , 0.0f , 1.35f },
225 { -2.5f , 0.0f , 1.125f },
226 { -2.5f , -0.3f , 1.125f },
227 // 151
228 { -2.65f , -0.3f , 0.9375f },
229 { -2.65f , 0.0f , 0.9375f },
230 { -2.0f , -0.3f , 0.9f },
231 { -1.9f , -0.3f , 0.6f },
232 { -1.9f , 0.0f , 0.6f },
233 { -3.0f , 0.3f , 1.35f },
234 { -2.7f , 0.3f , 1.575f },
235 { -2.65f , 0.3f , 0.9375f },
236 { -2.5f , 0.3f , 1.1255f },
237 { -1.9f , 0.3f , 0.6f },
238 // 161
239 { -2.0f , 0.3f , 0.9f },
240 { 1.7f , 0.0f , 1.425f },
241 { 1.7f , -0.66f , 1.425f },
242 { 1.7f , -0.66f , 0.6f },
243 { 1.7f , 0.0f , 0.6f },
244 { 2.6f , 0.0f , 1.425f },
245 { 2.6f , -0.66f , 1.425f },
246 { 3.1f , -0.66f , 0.825f },
247 { 3.1f , 0.0f , 0.825f },
248 { 2.3f , 0.0f , 2.1f },
249 // 171
250 { 2.3f , -0.25f , 2.1f },
251 { 2.4f , -0.25f , 2.025f },
252 { 2.4f , 0.0f , 2.025f },
253 { 2.7f , 0.0f , 2.4f },
254 { 2.7f , -0.25f , 2.4f },
255 { 3.3f , -0.25f , 2.4f },
256 { 3.3f , 0.0f , 2.4f },
257 { 1.7f , 0.66f , 0.6f },
258 { 1.7f , 0.66f , 1.425f },
259 { 3.1f , 0.66f , 0.825f },
260 // 181
261 { 2.6f , 0.66f , 1.425f },
262 { 2.4f , 0.25f , 2.025f },
263 { 2.3f , 0.25f , 2.1f },
264 { 3.3f , 0.25f , 2.4f },
265 { 2.7f , 0.25f , 2.4f },
266 { 2.8f , 0.0f , 2.475f },
267 { 2.8f , -0.25f , 2.475f },
268 { 3.525f , -0.25f , 2.49375f },
269 { 3.525f , 0.0f , 2.49375f },
270 { 2.9f , 0.0f , 2.475f },
271 // 191
272 { 2.9f , -0.15f , 2.475f },
273 { 3.45f , -0.15f , 2.5125f },
274 { 3.45f , 0.0f , 2.5125f },
275 { 2.8f , 0.0f , 2.4f },
276 { 2.8f , -0.15f , 2.4f },
277 { 3.2f , -0.15f , 2.4f },
278 { 3.2f , 0.0f , 2.4f },
279 { 3.525f , 0.25f , 2.49375f },
280 { 2.8f , 0.25f , 2.475f },
281 { 3.45f , 0.15f , 2.5125f },
282 // 201
283 { 2.9f , 0.15f , 2.475f },
284 { 3.2f , 0.15f , 2.4f },
285 { 2.8f , 0.15f , 2.4f },
286 { 0.0f , 0.0f , 3.15f },
287 { 0.0f , -0.002f , 3.15f },
288 { 0.002f , 0.0f , 3.15f },
289 { 0.8f , 0.0f , 3.15f },
290 { 0.8f , -0.45f , 3.15f },
291 { 0.45f , -0.8f , 3.15f },
292 { 0.0f , -0.8f , 3.15f },
293 // 211
294 { 0.0f , 0.0f , 2.85f },
295 { 0.2f , 0.0f , 2.7f },
296 { 0.2f , -0.112f , 2.7f },
297 { 0.112f , -0.2f , 2.7f },
298 { 0.0f , -0.2f , 2.7f },
299 { -0.002f , 0.0f , 3.15f },
300 { -0.45f , -0.8f , 3.15f },
301 { -0.8f , -0.45f , 3.15f },
302 { -0.8f , 0.0f , 3.15f },
303 { -0.112f , -0.2f , 2.7f },
304 // 221
305 { -0.2f , -0.112f , 2.7f },
306 { -0.2f , 0.0f , 2.7f },
307 { 0.0f , 0.002f , 3.15f },
308 { -0.8f , 0.45f , 3.15f },
309 { -0.45f , 0.8f , 3.15f },
310 { 0.0f , 0.8f , 3.15f },
311 { -0.2f , 0.112f , 2.7f },
312 { -0.112f , 0.2f , 2.7f },
313 { 0.0f , 0.2f , 2.7f },
314 { 0.45f , 0.8f , 3.15f },
315 // 231
316 { 0.8f , 0.45f , 3.15f },
317 { 0.112f , 0.2f , 2.7f },
318 { 0.2f , 0.112f , 2.7f },
319 { 0.4f , 0.0f , 2.55f },
320 { 0.4f , -0.224f , 2.55f },
321 { 0.224f , -0.4f , 2.55f },
322 { 0.0f , -0.4f , 2.55f },
323 { 1.3f , 0.0f , 2.55f },
324 { 1.3f , -0.728f , 2.55f },
325 { 0.728f , -1.3f , 2.55f },
326 // 241
327 { 0.0f , -1.3f , 2.55f },
328 { 1.3f , 0.0f , 2.4f },
329 { 1.3f , -0.728f , 2.4f },
330 { 0.728f , -1.3f , 2.4f },
331 { 0.0f , -1.3f , 2.4f },
332 { -0.224f , -0.4f , 2.55f },
333 { -0.4f , -0.224f , 2.55f },
334 { -0.4f , 0.0f , 2.55f },
335 { -0.728f , -1.3f , 2.55f },
336 { -1.3f , -0.728f , 2.55f },
337 // 251
338 { -1.3f , 0.0f , 2.55f },
339 { -0.728f , -1.3f , 2.4f },
340 { -1.3f , -0.728f , 2.4f },
341 { -1.3f , 0.0f , 2.4f },
342 { -0.4f , 0.224f , 2.55f },
343 { -0.224f , 0.4f , 2.55f },
344 { 0.0f , 0.4f , 2.55f },
345 { -1.3f , 0.728f , 2.55f },
346 { -0.728f , 1.3f , 2.55f },
347 { 0.0f , 1.3f , 2.55f },
348 // 261
349 { -1.3f , 0.728f , 2.4f },
350 { -0.728f , 1.3f , 2.4f },
351 { 0.0f , 1.3f , 2.4f },
352 { 0.224f , 0.4f , 2.55f },
353 { 0.4f , 0.224f , 2.55f },
354 { 0.728f , 1.3f , 2.55f },
355 { 1.3f , 0.728f , 2.55f },
356 { 0.728f , 1.3f , 2.4f },
357 { 1.3f , 0.728f , 2.4f },
358 };
359
360 inline GLushort teapot_patches[TEAPOT_NUMBER_PATCHES][TEAPOT_PATCH_DIMENSION + 1][TEAPOT_PATCH_DIMENSION + 1] = {
361 // rim
362 { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 }, { 13, 14, 15, 16, } },
363 { { 4, 17, 18, 19 }, { 8, 20, 21, 22 }, { 12, 23, 24, 25 }, { 16, 26, 27, 28, } },
364 { { 19, 29, 30, 31 }, { 22, 32, 33, 34 }, { 25, 35, 36, 37 }, { 28, 38, 39, 40, } },
365 { { 31, 41, 42, 1 }, { 34, 43, 44, 5 }, { 37, 45, 46, 9 }, { 40, 47, 48, 13, } },
366 // body
367 { { 13, 14, 15, 16 }, { 49, 50, 51, 52 }, { 53, 54, 55, 56 }, { 57, 58, 59, 60, } },
368 { { 16, 26, 27, 28 }, { 52, 61, 62, 63 }, { 56, 64, 65, 66 }, { 60, 67, 68, 69, } },
369 { { 28, 38, 39, 40 }, { 63, 70, 71, 72 }, { 66, 73, 74, 75 }, { 69, 76, 77, 78, } },
370 { { 40, 47, 48, 13 }, { 72, 79, 80, 49 }, { 75, 81, 82, 53 }, { 78, 83, 84, 57, } },
371 { { 57, 58, 59, 60 }, { 85, 86, 87, 88 }, { 89, 90, 91, 92 }, { 93, 94, 95, 96, } },
372 { { 60, 67, 68, 69 }, { 88, 97, 98, 99 }, { 92, 100, 101, 102 }, { 96, 103, 104, 105, } },
373 { { 69, 76, 77, 78 }, { 99, 106, 107, 108 }, { 102, 109, 110, 111 }, { 105, 112, 113, 114, } },
374 { { 78, 83, 84, 57 }, { 108, 115, 116, 85 }, { 111, 117, 118, 89 }, { 114, 119, 120, 93, } },
375 // handle
376 { { 121, 122, 123, 124 }, { 125, 126, 127, 128 }, { 129, 130, 131, 132 }, { 133, 134, 135, 136, } },
377 { { 124, 137, 138, 121 }, { 128, 139, 140, 125 }, { 132, 141, 142, 129 }, { 136, 143, 144, 133, } },
378 { { 133, 134, 135, 136 }, { 145, 146, 147, 148 }, { 149, 150, 151, 152 }, { 69, 153, 154, 155, } },
379 { { 136, 143, 144, 133 }, { 148, 156, 157, 145 }, { 152, 158, 159, 149 }, { 155, 160, 161, 69, } },
380 // spout
381 { { 162, 163, 164, 165 }, { 166, 167, 168, 169 }, { 170, 171, 172, 173 }, { 174, 175, 176, 177, } },
382 { { 165, 178, 179, 162 }, { 169, 180, 181, 166 }, { 173, 182, 183, 170 }, { 177, 184, 185, 174, } },
383 { { 174, 175, 176, 177 }, { 186, 187, 188, 189 }, { 190, 191, 192, 193 }, { 194, 195, 196, 197, } },
384 { { 177, 184, 185, 174 }, { 189, 198, 199, 186 }, { 193, 200, 201, 190 }, { 197, 202, 203, 194, } },
385 // lid
386 { { 204, 204, 204, 204 }, { 207, 208, 209, 210 }, { 211, 211, 211, 211 }, { 212, 213, 214, 215, } },
387 { { 204, 204, 204, 204 }, { 210, 217, 218, 219 }, { 211, 211, 211, 211 }, { 215, 220, 221, 222, } },
388 { { 204, 204, 204, 204 }, { 219, 224, 225, 226 }, { 211, 211, 211, 211 }, { 222, 227, 228, 229, } },
389 { { 204, 204, 204, 204 }, { 226, 230, 231, 207 }, { 211, 211, 211, 211 }, { 229, 232, 233, 212, } },
390 { { 212, 213, 214, 215 }, { 234, 235, 236, 237 }, { 238, 239, 240, 241 }, { 242, 243, 244, 245, } },
391 { { 215, 220, 221, 222 }, { 237, 246, 247, 248 }, { 241, 249, 250, 251 }, { 245, 252, 253, 254, } },
392 { { 222, 227, 228, 229 }, { 248, 255, 256, 257 }, { 251, 258, 259, 260 }, { 254, 261, 262, 263, } },
393 { { 229, 232, 233, 212 }, { 257, 264, 265, 234 }, { 260, 266, 267, 238 }, { 263, 268, 269, 242, } },
394 // no bottom!
395 };
396
397 inline glm::vec3 teapot_vertices[TEAPOT_NUMBER_PATCHES * TEAPOT_RES_U * TEAPOT_RES_V * 3];
398 inline GLushort teapot_elements[TEAPOT_NUMBER_PATCHES * (TEAPOT_RES_U - 1) * (TEAPOT_RES_V - 1) * 2 * 3];
399
400 inline GLboolean teapot_built = GL_FALSE;
401 inline GLint teapot_pos_attr_loc = -1;
402 inline GLint teapot_norm_attr_loc = -1;
403 inline GLint teapot_tex_attr_loc = -1;
404
405 void teapot_build_control_points_k(GLint p, glm::vec3** control_points_k);
406 glm::vec3 teapot_compute_position(glm::vec3** control_points_k, GLfloat u, GLfloat v);
407 glm::vec3 teapot_compute_normal(glm::vec3** control_points_k, GLfloat u, GLfloat v);
408 glm::vec3 teapot_compute_texture(glm::vec3 position);
409 glm::vec3 eval_bezier_curve_du(glm::vec3** control_points_k, GLfloat u, GLfloat v);
410 glm::vec3 eval_bezier_curve_dv(glm::vec3** control_points_k, GLfloat u, GLfloat v);
411 glm::vec3 teapot_evaluate_curve(const glm::vec3* control_points, GLfloat t);
412 GLfloat teapot_bernstein_polynomial(GLuint i, GLuint n, GLfloat u);
413 GLfloat teapot_binomial_coefficient(GLuint i, GLuint n);
414 GLuint teapot_factorial(GLuint n);
415
416 inline void teapot_build_teapot() {
417 // Vertices
418 for (GLuint p = 0; p < TEAPOT_NUMBER_PATCHES; p++) {
419 auto control_points_k = (glm::vec3**)malloc(sizeof(glm::vec3*) * (TEAPOT_PATCH_DIMENSION + 1));
420 for(GLuint i = 0; i < TEAPOT_PATCH_DIMENSION + 1; i++)
421 control_points_k[i] = (glm::vec3*)malloc(sizeof(glm::vec3) * (TEAPOT_PATCH_DIMENSION + 1));
422
423 teapot_build_control_points_k(p, control_points_k);
424
425 for (GLuint ru = 0; ru <= TEAPOT_RES_U - 1; ru++) {
426 GLfloat u = 1.0f * (GLfloat) ru / (TEAPOT_RES_U - 1);
427 for (GLuint rv = 0; rv <= TEAPOT_RES_V - 1; rv++) {
428 GLfloat v = 1.0f * (GLfloat) rv / (TEAPOT_RES_V - 1);
429 teapot_vertices[ p * TEAPOT_RES_U * TEAPOT_RES_V + ru * TEAPOT_RES_V + rv ] = teapot_compute_position(control_points_k, u, v);
430 teapot_vertices[TEAPOT_NUMBER_PATCHES * TEAPOT_RES_U * TEAPOT_RES_V + p * TEAPOT_RES_U * TEAPOT_RES_V + ru * TEAPOT_RES_V + rv ] = teapot_compute_normal(control_points_k, u, v);
431 teapot_vertices[TEAPOT_NUMBER_PATCHES * TEAPOT_RES_U * TEAPOT_RES_V * 2 + p * TEAPOT_RES_U * TEAPOT_RES_V + ru * TEAPOT_RES_V + rv ] = teapot_compute_texture(teapot_vertices[p * TEAPOT_RES_U * TEAPOT_RES_V + ru * TEAPOT_RES_V + rv]);
432 }
433 }
434 }
435
436 // Elements
437 GLint n = 0;
438 for (GLuint p = 0; p < TEAPOT_NUMBER_PATCHES; p++)
439 for (GLuint ru = 0; ru < TEAPOT_RES_U - 1; ru++)
440 for (GLuint rv = 0; rv < TEAPOT_RES_V - 1; rv++) {
441 // 1 square ABCD = 2 triangles ABC + CDA
442 GLushort a = p * TEAPOT_RES_U * TEAPOT_RES_V + ru * TEAPOT_RES_V + rv ;
443 GLushort b = p * TEAPOT_RES_U * TEAPOT_RES_V + ru * TEAPOT_RES_V + (rv + 1);
444 GLushort c = p * TEAPOT_RES_U * TEAPOT_RES_V + (ru + 1) * TEAPOT_RES_V + (rv + 1);
445 GLushort d = p * TEAPOT_RES_U * TEAPOT_RES_V + (ru + 1) * TEAPOT_RES_V + rv ;
446 // ABC
447 teapot_elements[n++] = a;
448 teapot_elements[n++] = b;
449 teapot_elements[n++] = c;
450 // CDA
451 teapot_elements[n++] = c;
452 teapot_elements[n++] = d;
453 teapot_elements[n++] = a;
454 }
455
456 }
457
458 inline void teapot_build_control_points_k(const GLint p, glm::vec3** const control_points_k) {
459 for (GLuint i = 0; i <= TEAPOT_PATCH_DIMENSION; i++)
460 for (GLuint j = 0; j <= TEAPOT_PATCH_DIMENSION; j++)
461 control_points_k[i][j] = teapot_cp_vertices[teapot_patches[p][i][j] - 1];
462 }
463
464 inline glm::vec3 teapot_compute_position(glm::vec3** const control_points_k, const GLfloat u, const GLfloat v) {
465 glm::vec3 position = {0.0f, 0.0f, 0.0f };
466 for (GLuint i = 0; i <= TEAPOT_PATCH_DIMENSION; i++) {
467 GLfloat poly_i = teapot_bernstein_polynomial(i, TEAPOT_PATCH_DIMENSION, u);
468 for (GLuint j = 0; j <= TEAPOT_PATCH_DIMENSION; j++) {
469 GLfloat poly_j = teapot_bernstein_polynomial(j, TEAPOT_PATCH_DIMENSION, v);
470 position += poly_i * poly_j * control_points_k[i][j];
471 }
472 }
473 return position;
474 }
475
476 inline glm::vec3 eval_bezier_curve_du(glm::vec3** const control_points_k, const GLfloat u, const GLfloat v) {
477 glm::vec3 P[4];
478 glm::vec3 vCurve[4];
479 for (GLuint i = 0; i <= TEAPOT_PATCH_DIMENSION; ++i) {
480 for (GLuint j = 0; j <= TEAPOT_PATCH_DIMENSION; ++j) {
481 P[j] = control_points_k[i][j];
482 }
483 vCurve[i] = teapot_evaluate_curve(P, v);
484 }
485
486 return -3.f * (1.f - u) * (1.f - u) * vCurve[0] +
487 (3.f * (1.f - u) * (1.f - u) - 6.f * u * (1.f - u)) * vCurve[1] +
488 (6.f * u * (1.f - u) - 3.f * u * u) * vCurve[2] +
489 3.f * u * u * vCurve[3];
490 }
491
492 inline glm::vec3 eval_bezier_curve_dv(glm::vec3** const control_points_k, const GLfloat u, const GLfloat v) {
493 glm::vec3 P[4];
494 glm::vec3 uCurve[4];
495 for (GLuint j = 0; j <= TEAPOT_PATCH_DIMENSION; ++j) {
496 for (GLuint i = 0; i <= TEAPOT_PATCH_DIMENSION; ++i) {
497 P[i] = control_points_k[i][j];
498 }
499 uCurve[j] = teapot_evaluate_curve(P, u);
500 }
501
502 return -3.f * (1.f - v) * (1.f - v) * uCurve[0] +
503 (3.f * (1.f - v) * (1.f - v) - 6.f * v * (1.f - v)) * uCurve[1] +
504 (6.f * v * (1.f - v) - 3.f * v * v) * uCurve[2] +
505 3.f * v * v * uCurve[3];
506 }
507
508 inline glm::vec3 teapot_compute_normal(glm::vec3** const control_points_k, const GLfloat u, const GLfloat v) {
509 glm::vec3 du = eval_bezier_curve_du(control_points_k, u, v);
510 glm::vec3 dv = eval_bezier_curve_dv(control_points_k, u, v);
511 glm::vec3 normal = -glm::normalize(glm::cross(du, dv));
512 return normal;
513 }
514
515 inline glm::vec3 teapot_compute_texture(const glm::vec3 position) {
516 glm::vec3 textureCoordinate = {0.0f, 0.0f, 0.0f};
517 const GLfloat PI = 3.14159265f;
518 GLfloat theta = atan2(position.y, position.x);
519 textureCoordinate.x = (theta + PI) / (2.0f * PI);
520 textureCoordinate.y = position.z / 3.15f;
521 return textureCoordinate;
522 }
523
524 inline glm::vec3 teapot_evaluate_curve(const glm::vec3* const control_points, GLfloat t) {
525 glm::vec3 position = {0.0f, 0.0f, 0.0f};
526 for(GLuint i = 0; i <= TEAPOT_PATCH_DIMENSION; i++) {
527 position += teapot_bernstein_polynomial(i, TEAPOT_PATCH_DIMENSION, t) * control_points[i];
528 }
529 return position;
530 }
531
532 inline GLfloat teapot_bernstein_polynomial(const GLuint i, const GLuint n, const GLfloat u) {
533 return teapot_binomial_coefficient(i, n) * powf(u, (GLfloat)i) * powf(1 - u, (GLfloat)(n - i));
534 }
535
536 inline GLfloat teapot_binomial_coefficient(const GLuint i, const GLuint n) {
537 return 1.0f * (GLfloat) teapot_factorial(n) / (GLfloat)(teapot_factorial(i) * teapot_factorial(n - i));
538 }
539 inline GLuint teapot_factorial(const GLuint n) {
540 GLuint result = 1;
541 for (GLuint i = n; i > 1; i--)
542 result *= i;
543 return result;
544 }
545
546 inline GLboolean teapot_init_resources() {
547 teapot_build_teapot();
548
549 glGenVertexArrays(1, &teapot_vao);
550 glBindVertexArray(teapot_vao);
551
552 glGenBuffers(1, &teapot_vbo);
553 glBindBuffer(GL_ARRAY_BUFFER, teapot_vbo);
554 glBufferData(GL_ARRAY_BUFFER, sizeof(teapot_vertices), teapot_vertices, GL_STATIC_DRAW);
555
556 glGenBuffers(1, &teapot_ibo);
557 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, teapot_ibo);
558 glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(teapot_elements), teapot_elements, GL_STATIC_DRAW);
559
560 teapot_built = GL_TRUE;
561
562 return GL_TRUE;
563 }
564
565 [[maybe_unused]]
566 inline void teapot( const GLfloat size, const GLint positionLocation, const GLint normalLocation, const GLint texCoordLocation ) {
567 if( !teapot_built ) {
568 teapot_init_resources();
569 }
570 if( positionLocation != teapot_pos_attr_loc || normalLocation != teapot_norm_attr_loc || texCoordLocation != teapot_tex_attr_loc ) {
571 setTeapotAttributeLocations(positionLocation, normalLocation, texCoordLocation);
572 }
573 teapot();
574 }
575
576 inline void setTeapotAttributeLocations(const GLint positionLocation, const GLint normalLocation, const GLint texCoordLocation) {
577 if( !teapot_built ) {
578 teapot_init_resources();
579 }
580
581 glBindVertexArray(teapot_vao );
582 glBindBuffer(GL_ARRAY_BUFFER, teapot_vbo);
583
584 if(teapot_pos_attr_loc != -1) glDisableVertexAttribArray(teapot_pos_attr_loc);
585 if(teapot_norm_attr_loc != -1) glDisableVertexAttribArray(teapot_norm_attr_loc);
586 if(teapot_tex_attr_loc != -1) glDisableVertexAttribArray(teapot_tex_attr_loc);
587
588 teapot_pos_attr_loc = positionLocation;
589 teapot_norm_attr_loc = normalLocation;
590 teapot_tex_attr_loc = texCoordLocation;
591
592 // Describe our vertices array to OpenGL (it can't guess its format automatically)
593 if(teapot_pos_attr_loc != -1) {
594 glEnableVertexAttribArray(teapot_pos_attr_loc);
595 glVertexAttribPointer(
596 teapot_pos_attr_loc, // attribute
597 3, // number of elements per vertex, here (x,y,z)
598 GL_FLOAT, // the type of each element
599 GL_FALSE, // take our values as-is
600 0, // no extra data between each position
601 nullptr // offset of first element
602 );
603 }
604 if(teapot_norm_attr_loc != -1) {
605 glEnableVertexAttribArray(teapot_norm_attr_loc);
606 glVertexAttribPointer(
607 teapot_norm_attr_loc, // attribute
608 3, // number of elements per vertex, here (x,y,z)
609 GL_FLOAT, // the type of each element
610 GL_FALSE, // take our values as-is
611 0, // no extra data between each position
612 (void*)(TEAPOT_NUMBER_PATCHES * TEAPOT_RES_U * TEAPOT_RES_V * sizeof(glm::vec3)) // offset of first element
613 );
614 }
615 if(teapot_tex_attr_loc != -1) {
616 glEnableVertexAttribArray(teapot_tex_attr_loc);
617 glVertexAttribPointer(
618 teapot_tex_attr_loc, // attribute
619 2, // number of elements per vertex, here (s,t)
620 GL_FLOAT, // the type of each element
621 GL_FALSE, // take our values as-is
622 sizeof(glm::vec3), // no extra data between each position
623 (void*)(TEAPOT_NUMBER_PATCHES * TEAPOT_RES_U * TEAPOT_RES_V * 2 * sizeof(glm::vec3)) // offset of first element
624 );
625 }
626 }
627
628 inline void teapot() {
629 glBindVertexArray(teapot_vao );
630 glBindBuffer(GL_ARRAY_BUFFER, teapot_vbo);
631 glDrawElements(GL_TRIANGLES, sizeof(teapot_elements)/sizeof(teapot_elements[0]), GL_UNSIGNED_SHORT, nullptr);
632 }
633}
634
635
636#endif // CSCI441_TEAPOT_HPP