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