17#ifndef CSCI441_TEAPOT_HPP
18#define CSCI441_TEAPOT_HPP
22#ifdef CSCI441_USE_GLEW
32namespace CSCI441_INTERNAL {
39 [[maybe_unused]]
void teapot( GLfloat size, GLint positionLocation, GLint normalLocation = -1, GLint texCoordLocation = -1);
45 void setTeapotAttributeLocations(GLint positionLocation, GLint normalLocation = -1, GLint texCoordLocation = -1);
55 const GLuint TEAPOT_NUMBER_PATCHES = 28;
56 const GLuint TEAPOT_PATCH_DIMENSION = 3;
57 const GLuint TEAPOT_RES_U = 10;
58 const GLuint TEAPOT_RES_V = 10;
60 inline GLuint teapot_vao;
61 inline GLuint teapot_vbo, teapot_ibo;
63 inline glm::vec3 teapot_cp_vertices[] = {
65 { 1.4f , 0.0f , 2.4f },
66 { 1.4f , -0.784f , 2.4f },
67 { 0.784f , -1.4f , 2.4f },
68 { 0.0f , -1.4f , 2.4f },
69 { 1.3375f, 0.0f , 2.53125f },
70 { 1.3375f, -0.749f , 2.53125f },
71 { 0.749f , -1.3375f, 2.53125f },
72 { 0.0f , -1.3375f, 2.53125f },
73 { 1.4375f, 0.0f , 2.53125f },
74 { 1.4375f, -0.805f , 2.53125f },
76 { 0.805f , -1.4375f, 2.53125f },
77 { 0.0f , -1.4375f, 2.53125f },
78 { 1.5f , 0.0f , 2.4f },
79 { 1.5f , -0.84f , 2.4f },
80 { 0.84f , -1.5f , 2.4f },
81 { 0.0f , -1.5f , 2.4f },
82 { -0.784f , -1.4f , 2.4f },
83 { -1.4f , -0.784f , 2.4f },
84 { -1.4f , 0.0f , 2.4f },
85 { -0.749f , -1.3375f, 2.53125f },
87 { -1.3375f, -0.749f , 2.53125f },
88 { -1.3375f, 0.0f , 2.53125f },
89 { -0.805f , -1.4375f, 2.53125f },
90 { -1.4375f, -0.805f , 2.53125f },
91 { -1.4375f, 0.0f , 2.53125f },
92 { -0.84f , -1.5f , 2.4f },
93 { -1.5f , -0.84f , 2.4f },
94 { -1.5f , 0.0f , 2.4f },
95 { -1.4f , 0.784f , 2.4f },
96 { -0.784f , 1.4f , 2.4f },
98 { 0.0f , 1.4f , 2.4f },
99 { -1.3375f, 0.749f , 2.53125f },
100 { -0.749f , 1.3375f, 2.53125f },
101 { 0.0f , 1.3375f, 2.53125f },
102 { -1.4375f, 0.805f , 2.53125f },
103 { -0.805f , 1.4375f, 2.53125f },
104 { 0.0f , 1.4375f, 2.53125f },
105 { -1.5f , 0.84f , 2.4f },
106 { -0.84f , 1.5f , 2.4f },
107 { 0.0f , 1.5f , 2.4f },
109 { 0.784f , 1.4f , 2.4f },
110 { 1.4f , 0.784f , 2.4f },
111 { 0.749f , 1.3375f, 2.53125f },
112 { 1.3375f, 0.749f , 2.53125f },
113 { 0.805f , 1.4375f, 2.53125f },
114 { 1.4375f, 0.805f , 2.53125f },
115 { 0.84f , 1.5f , 2.4f },
116 { 1.5f , 0.84f , 2.4f },
117 { 1.75f , 0.0f , 1.875f },
118 { 1.75f , -0.98f , 1.875f },
120 { 0.98f , -1.75f , 1.875f },
121 { 0.0f , -1.75f , 1.875f },
122 { 2.0f , 0.0f , 1.35f },
123 { 2.0f , -1.12f , 1.35f },
124 { 1.12f , -2.0f , 1.35f },
125 { 0.0f , -2.0f , 1.35f },
126 { 2.0f , 0.0f , 0.9f },
127 { 2.0f , -1.12f , 0.9f },
128 { 1.12f , -2.0f , 0.9f },
129 { 0.0f , -2.0f , 0.9f },
131 { -0.98f , -1.75f , 1.875f },
132 { -1.75f , -0.98f , 1.875f },
133 { -1.75f , 0.0f , 1.875f },
134 { -1.12f , -2.0f , 1.35f },
135 { -2.0f , -1.12f , 1.35f },
136 { -2.0f , 0.0f , 1.35f },
137 { -1.12f , -2.0f , 0.9f },
138 { -2.0f , -1.12f , 0.9f },
139 { -2.0f , 0.0f , 0.9f },
140 { -1.75f , 0.98f , 1.875f },
142 { -0.98f , 1.75f , 1.875f },
143 { 0.0f , 1.75f , 1.875f },
144 { -2.0f , 1.12f , 1.35f },
145 { -1.12f , 2.0f , 1.35f },
146 { 0.0f , 2.0f , 1.35f },
147 { -2.0f , 1.12f , 0.9f },
148 { -1.12f , 2.0f , 0.9f },
149 { 0.0f , 2.0f , 0.9f },
150 { 0.98f , 1.75f , 1.875f },
151 { 1.75f , 0.98f , 1.875f },
153 { 1.12f , 2.0f , 1.35f },
154 { 2.0f , 1.12f , 1.35f },
155 { 1.12f , 2.0f , 0.9f },
156 { 2.0f , 1.12f , 0.9f },
157 { 2.0f , 0.0f , 0.45f },
158 { 2.0f , -1.12f , 0.45f },
159 { 1.12f , -2.0f , 0.45f },
160 { 0.0f , -2.0f , 0.45f },
161 { 1.5f , 0.0f , 0.225f },
162 { 1.5f , -0.84f , 0.225f },
164 { 0.84f , -1.5f , 0.225f },
165 { 0.0f , -1.5f , 0.225f },
166 { 1.5f , 0.0f , 0.15f },
167 { 1.5f , -0.84f , 0.15f },
168 { 0.84f , -1.5f , 0.15f },
169 { 0.0f , -1.5f , 0.15f },
170 { -1.12f , -2.0f , 0.45f },
171 { -2.0f , -1.12f , 0.45f },
172 { -2.0f , 0.0f , 0.45f },
173 { -0.84f , -1.5f , 0.225f },
175 { -1.5f , -0.84f , 0.225f },
176 { -1.5f , 0.0f , 0.225f },
177 { -0.84f , -1.5f , 0.15f },
178 { -1.5f , -0.84f , 0.15f },
179 { -1.5f , 0.0f , 0.15f },
180 { -2.0f , 1.12f , 0.45f },
181 { -1.12f , 2.0f , 0.45f },
182 { 0.0f , 2.0f , 0.45f },
183 { -1.5f , 0.84f , 0.225f },
184 { -0.84f , 1.5f , 0.225f },
186 { 0.0f , 1.5f , 0.225f },
187 { -1.5f , 0.84f , 0.15f },
188 { -0.84f , 1.5f , 0.15f },
189 { 0.0f , 1.5f , 0.15f },
190 { 1.12f , 2.0f , 0.45f },
191 { 2.0f , 1.12f , 0.45f },
192 { 0.84f , 1.5f , 0.225f },
193 { 1.5f , 0.84f , 0.225f },
194 { 0.84f , 1.5f , 0.15f },
195 { 1.5f , 0.84f , 0.15f },
197 { -1.6f , 0.0f , 2.025f },
198 { -1.6f , -0.3f , 2.025f },
199 { -1.5f , -0.3f , 2.25f },
200 { -1.5f , 0.0f , 2.25f },
201 { -2.3f , 0.0f , 2.025f },
202 { -2.3f , -0.3f , 2.025f },
203 { -2.5f , -0.3f , 2.25f },
204 { -2.5f , 0.0f , 2.25f },
205 { -2.7f , 0.0f , 2.025f },
206 { -2.7f , -0.3f , 2.025f },
208 { -3.0f , -0.3f , 2.25f },
209 { -3.0f , 0.0f , 2.25f },
210 { -2.7f , 0.0f , 1.8f },
211 { -2.7f , -0.3f , 1.8f },
212 { -3.0f , -0.3f , 1.8f },
213 { -3.0f , 0.0f , 1.8f },
214 { -1.5f , 0.3f , 2.25f },
215 { -1.6f , 0.3f , 2.025f },
216 { -2.5f , 0.3f , 2.25f },
217 { -2.3f , 0.3f , 2.025f },
219 { -3.0f , 0.3f , 2.25f },
220 { -2.7f , 0.3f , 2.025f },
221 { -3.0f , 0.3f , 1.8f },
222 { -2.7f , 0.3f , 1.8f },
223 { -2.7f , 0.0f , 1.575f },
224 { -2.7f , -0.3f , 1.575f },
225 { -3.0f , -0.3f , 1.35f },
226 { -3.0f , 0.0f , 1.35f },
227 { -2.5f , 0.0f , 1.125f },
228 { -2.5f , -0.3f , 1.125f },
230 { -2.65f , -0.3f , 0.9375f },
231 { -2.65f , 0.0f , 0.9375f },
232 { -2.0f , -0.3f , 0.9f },
233 { -1.9f , -0.3f , 0.6f },
234 { -1.9f , 0.0f , 0.6f },
235 { -3.0f , 0.3f , 1.35f },
236 { -2.7f , 0.3f , 1.575f },
237 { -2.65f , 0.3f , 0.9375f },
238 { -2.5f , 0.3f , 1.1255f },
239 { -1.9f , 0.3f , 0.6f },
241 { -2.0f , 0.3f , 0.9f },
242 { 1.7f , 0.0f , 1.425f },
243 { 1.7f , -0.66f , 1.425f },
244 { 1.7f , -0.66f , 0.6f },
245 { 1.7f , 0.0f , 0.6f },
246 { 2.6f , 0.0f , 1.425f },
247 { 2.6f , -0.66f , 1.425f },
248 { 3.1f , -0.66f , 0.825f },
249 { 3.1f , 0.0f , 0.825f },
250 { 2.3f , 0.0f , 2.1f },
252 { 2.3f , -0.25f , 2.1f },
253 { 2.4f , -0.25f , 2.025f },
254 { 2.4f , 0.0f , 2.025f },
255 { 2.7f , 0.0f , 2.4f },
256 { 2.7f , -0.25f , 2.4f },
257 { 3.3f , -0.25f , 2.4f },
258 { 3.3f , 0.0f , 2.4f },
259 { 1.7f , 0.66f , 0.6f },
260 { 1.7f , 0.66f , 1.425f },
261 { 3.1f , 0.66f , 0.825f },
263 { 2.6f , 0.66f , 1.425f },
264 { 2.4f , 0.25f , 2.025f },
265 { 2.3f , 0.25f , 2.1f },
266 { 3.3f , 0.25f , 2.4f },
267 { 2.7f , 0.25f , 2.4f },
268 { 2.8f , 0.0f , 2.475f },
269 { 2.8f , -0.25f , 2.475f },
270 { 3.525f , -0.25f , 2.49375f },
271 { 3.525f , 0.0f , 2.49375f },
272 { 2.9f , 0.0f , 2.475f },
274 { 2.9f , -0.15f , 2.475f },
275 { 3.45f , -0.15f , 2.5125f },
276 { 3.45f , 0.0f , 2.5125f },
277 { 2.8f , 0.0f , 2.4f },
278 { 2.8f , -0.15f , 2.4f },
279 { 3.2f , -0.15f , 2.4f },
280 { 3.2f , 0.0f , 2.4f },
281 { 3.525f , 0.25f , 2.49375f },
282 { 2.8f , 0.25f , 2.475f },
283 { 3.45f , 0.15f , 2.5125f },
285 { 2.9f , 0.15f , 2.475f },
286 { 3.2f , 0.15f , 2.4f },
287 { 2.8f , 0.15f , 2.4f },
288 { 0.0f , 0.0f , 3.15f },
289 { 0.0f , -0.002f , 3.15f },
290 { 0.002f , 0.0f , 3.15f },
291 { 0.8f , 0.0f , 3.15f },
292 { 0.8f , -0.45f , 3.15f },
293 { 0.45f , -0.8f , 3.15f },
294 { 0.0f , -0.8f , 3.15f },
296 { 0.0f , 0.0f , 2.85f },
297 { 0.2f , 0.0f , 2.7f },
298 { 0.2f , -0.112f , 2.7f },
299 { 0.112f , -0.2f , 2.7f },
300 { 0.0f , -0.2f , 2.7f },
301 { -0.002f , 0.0f , 3.15f },
302 { -0.45f , -0.8f , 3.15f },
303 { -0.8f , -0.45f , 3.15f },
304 { -0.8f , 0.0f , 3.15f },
305 { -0.112f , -0.2f , 2.7f },
307 { -0.2f , -0.112f , 2.7f },
308 { -0.2f , 0.0f , 2.7f },
309 { 0.0f , 0.002f , 3.15f },
310 { -0.8f , 0.45f , 3.15f },
311 { -0.45f , 0.8f , 3.15f },
312 { 0.0f , 0.8f , 3.15f },
313 { -0.2f , 0.112f , 2.7f },
314 { -0.112f , 0.2f , 2.7f },
315 { 0.0f , 0.2f , 2.7f },
316 { 0.45f , 0.8f , 3.15f },
318 { 0.8f , 0.45f , 3.15f },
319 { 0.112f , 0.2f , 2.7f },
320 { 0.2f , 0.112f , 2.7f },
321 { 0.4f , 0.0f , 2.55f },
322 { 0.4f , -0.224f , 2.55f },
323 { 0.224f , -0.4f , 2.55f },
324 { 0.0f , -0.4f , 2.55f },
325 { 1.3f , 0.0f , 2.55f },
326 { 1.3f , -0.728f , 2.55f },
327 { 0.728f , -1.3f , 2.55f },
329 { 0.0f , -1.3f , 2.55f },
330 { 1.3f , 0.0f , 2.4f },
331 { 1.3f , -0.728f , 2.4f },
332 { 0.728f , -1.3f , 2.4f },
333 { 0.0f , -1.3f , 2.4f },
334 { -0.224f , -0.4f , 2.55f },
335 { -0.4f , -0.224f , 2.55f },
336 { -0.4f , 0.0f , 2.55f },
337 { -0.728f , -1.3f , 2.55f },
338 { -1.3f , -0.728f , 2.55f },
340 { -1.3f , 0.0f , 2.55f },
341 { -0.728f , -1.3f , 2.4f },
342 { -1.3f , -0.728f , 2.4f },
343 { -1.3f , 0.0f , 2.4f },
344 { -0.4f , 0.224f , 2.55f },
345 { -0.224f , 0.4f , 2.55f },
346 { 0.0f , 0.4f , 2.55f },
347 { -1.3f , 0.728f , 2.55f },
348 { -0.728f , 1.3f , 2.55f },
349 { 0.0f , 1.3f , 2.55f },
351 { -1.3f , 0.728f , 2.4f },
352 { -0.728f , 1.3f , 2.4f },
353 { 0.0f , 1.3f , 2.4f },
354 { 0.224f , 0.4f , 2.55f },
355 { 0.4f , 0.224f , 2.55f },
356 { 0.728f , 1.3f , 2.55f },
357 { 1.3f , 0.728f , 2.55f },
358 { 0.728f , 1.3f , 2.4f },
359 { 1.3f , 0.728f , 2.4f },
362 inline GLushort teapot_patches[TEAPOT_NUMBER_PATCHES][TEAPOT_PATCH_DIMENSION + 1][TEAPOT_PATCH_DIMENSION + 1] = {
364 { { 1, 2, 3, 4 }, { 5, 6, 7, 8 }, { 9, 10, 11, 12 }, { 13, 14, 15, 16, } },
365 { { 4, 17, 18, 19 }, { 8, 20, 21, 22 }, { 12, 23, 24, 25 }, { 16, 26, 27, 28, } },
366 { { 19, 29, 30, 31 }, { 22, 32, 33, 34 }, { 25, 35, 36, 37 }, { 28, 38, 39, 40, } },
367 { { 31, 41, 42, 1 }, { 34, 43, 44, 5 }, { 37, 45, 46, 9 }, { 40, 47, 48, 13, } },
369 { { 13, 14, 15, 16 }, { 49, 50, 51, 52 }, { 53, 54, 55, 56 }, { 57, 58, 59, 60, } },
370 { { 16, 26, 27, 28 }, { 52, 61, 62, 63 }, { 56, 64, 65, 66 }, { 60, 67, 68, 69, } },
371 { { 28, 38, 39, 40 }, { 63, 70, 71, 72 }, { 66, 73, 74, 75 }, { 69, 76, 77, 78, } },
372 { { 40, 47, 48, 13 }, { 72, 79, 80, 49 }, { 75, 81, 82, 53 }, { 78, 83, 84, 57, } },
373 { { 57, 58, 59, 60 }, { 85, 86, 87, 88 }, { 89, 90, 91, 92 }, { 93, 94, 95, 96, } },
374 { { 60, 67, 68, 69 }, { 88, 97, 98, 99 }, { 92, 100, 101, 102 }, { 96, 103, 104, 105, } },
375 { { 69, 76, 77, 78 }, { 99, 106, 107, 108 }, { 102, 109, 110, 111 }, { 105, 112, 113, 114, } },
376 { { 78, 83, 84, 57 }, { 108, 115, 116, 85 }, { 111, 117, 118, 89 }, { 114, 119, 120, 93, } },
378 { { 121, 122, 123, 124 }, { 125, 126, 127, 128 }, { 129, 130, 131, 132 }, { 133, 134, 135, 136, } },
379 { { 124, 137, 138, 121 }, { 128, 139, 140, 125 }, { 132, 141, 142, 129 }, { 136, 143, 144, 133, } },
380 { { 133, 134, 135, 136 }, { 145, 146, 147, 148 }, { 149, 150, 151, 152 }, { 69, 153, 154, 155, } },
381 { { 136, 143, 144, 133 }, { 148, 156, 157, 145 }, { 152, 158, 159, 149 }, { 155, 160, 161, 69, } },
383 { { 162, 163, 164, 165 }, { 166, 167, 168, 169 }, { 170, 171, 172, 173 }, { 174, 175, 176, 177, } },
384 { { 165, 178, 179, 162 }, { 169, 180, 181, 166 }, { 173, 182, 183, 170 }, { 177, 184, 185, 174, } },
385 { { 174, 175, 176, 177 }, { 186, 187, 188, 189 }, { 190, 191, 192, 193 }, { 194, 195, 196, 197, } },
386 { { 177, 184, 185, 174 }, { 189, 198, 199, 186 }, { 193, 200, 201, 190 }, { 197, 202, 203, 194, } },
388 { { 204, 204, 204, 204 }, { 207, 208, 209, 210 }, { 211, 211, 211, 211 }, { 212, 213, 214, 215, } },
389 { { 204, 204, 204, 204 }, { 210, 217, 218, 219 }, { 211, 211, 211, 211 }, { 215, 220, 221, 222, } },
390 { { 204, 204, 204, 204 }, { 219, 224, 225, 226 }, { 211, 211, 211, 211 }, { 222, 227, 228, 229, } },
391 { { 204, 204, 204, 204 }, { 226, 230, 231, 207 }, { 211, 211, 211, 211 }, { 229, 232, 233, 212, } },
392 { { 212, 213, 214, 215 }, { 234, 235, 236, 237 }, { 238, 239, 240, 241 }, { 242, 243, 244, 245, } },
393 { { 215, 220, 221, 222 }, { 237, 246, 247, 248 }, { 241, 249, 250, 251 }, { 245, 252, 253, 254, } },
394 { { 222, 227, 228, 229 }, { 248, 255, 256, 257 }, { 251, 258, 259, 260 }, { 254, 261, 262, 263, } },
395 { { 229, 232, 233, 212 }, { 257, 264, 265, 234 }, { 260, 266, 267, 238 }, { 263, 268, 269, 242, } },
399 inline glm::vec3 teapot_vertices[TEAPOT_NUMBER_PATCHES * TEAPOT_RES_U * TEAPOT_RES_V * 3];
400 inline GLushort teapot_elements[TEAPOT_NUMBER_PATCHES * (TEAPOT_RES_U - 1) * (TEAPOT_RES_V - 1) * 2 * 3];
402 inline GLboolean teapot_built = GL_FALSE;
403 inline GLint teapot_pos_attr_loc = -1;
404 inline GLint teapot_norm_attr_loc = -1;
405 inline GLint teapot_tex_attr_loc = -1;
407 void teapot_build_control_points_k(GLint p, glm::vec3** control_points_k);
408 glm::vec3 teapot_compute_position(glm::vec3** control_points_k, GLfloat u, GLfloat v);
409 glm::vec3 teapot_compute_normal(glm::vec3** control_points_k, GLfloat u, GLfloat v);
410 glm::vec3 teapot_compute_texture(glm::vec3 position);
411 glm::vec3 eval_bezier_curve_du(glm::vec3** control_points_k, GLfloat u, GLfloat v);
412 glm::vec3 eval_bezier_curve_dv(glm::vec3** control_points_k, GLfloat u, GLfloat v);
413 glm::vec3 teapot_evaluate_curve(
const glm::vec3* control_points, GLfloat t);
414 GLfloat teapot_bernstein_polynomial(GLuint i, GLuint n, GLfloat u);
415 GLfloat teapot_binomial_coefficient(GLuint i, GLuint n);
416 GLuint teapot_factorial(GLuint n);
418 inline void teapot_build_teapot() {
420 for (GLuint p = 0; p < TEAPOT_NUMBER_PATCHES; p++) {
421 auto control_points_k = (glm::vec3**)malloc(
sizeof(glm::vec3*) * (TEAPOT_PATCH_DIMENSION + 1));
422 for(GLuint i = 0; i < TEAPOT_PATCH_DIMENSION + 1; i++)
423 control_points_k[i] = (glm::vec3*)malloc(
sizeof(glm::vec3) * (TEAPOT_PATCH_DIMENSION + 1));
425 teapot_build_control_points_k(p, control_points_k);
427 for (GLuint ru = 0; ru <= TEAPOT_RES_U - 1; ru++) {
428 GLfloat u = 1.0f * (GLfloat) ru / (TEAPOT_RES_U - 1);
429 for (GLuint rv = 0; rv <= TEAPOT_RES_V - 1; rv++) {
430 GLfloat v = 1.0f * (GLfloat) rv / (TEAPOT_RES_V - 1);
431 teapot_vertices[ p * TEAPOT_RES_U * TEAPOT_RES_V + ru * TEAPOT_RES_V + rv ] = teapot_compute_position(control_points_k, u, v);
432 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);
433 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]);
440 for (GLuint p = 0; p < TEAPOT_NUMBER_PATCHES; p++)
441 for (GLuint ru = 0; ru < TEAPOT_RES_U - 1; ru++)
442 for (GLuint rv = 0; rv < TEAPOT_RES_V - 1; rv++) {
444 GLushort a = p * TEAPOT_RES_U * TEAPOT_RES_V + ru * TEAPOT_RES_V + rv ;
445 GLushort b = p * TEAPOT_RES_U * TEAPOT_RES_V + ru * TEAPOT_RES_V + (rv + 1);
446 GLushort c = p * TEAPOT_RES_U * TEAPOT_RES_V + (ru + 1) * TEAPOT_RES_V + (rv + 1);
447 GLushort d = p * TEAPOT_RES_U * TEAPOT_RES_V + (ru + 1) * TEAPOT_RES_V + rv ;
449 teapot_elements[n++] = a;
450 teapot_elements[n++] = b;
451 teapot_elements[n++] = c;
453 teapot_elements[n++] = c;
454 teapot_elements[n++] = d;
455 teapot_elements[n++] = a;
460 inline void teapot_build_control_points_k(
const GLint p, glm::vec3**
const control_points_k) {
461 for (GLuint i = 0; i <= TEAPOT_PATCH_DIMENSION; i++)
462 for (GLuint j = 0; j <= TEAPOT_PATCH_DIMENSION; j++)
463 control_points_k[i][j] = teapot_cp_vertices[teapot_patches[p][i][j] - 1];
466 inline glm::vec3 teapot_compute_position(glm::vec3**
const control_points_k,
const GLfloat u,
const GLfloat v) {
467 glm::vec3 position = {0.0f, 0.0f, 0.0f };
468 for (GLuint i = 0; i <= TEAPOT_PATCH_DIMENSION; i++) {
469 GLfloat poly_i = teapot_bernstein_polynomial(i, TEAPOT_PATCH_DIMENSION, u);
470 for (GLuint j = 0; j <= TEAPOT_PATCH_DIMENSION; j++) {
471 GLfloat poly_j = teapot_bernstein_polynomial(j, TEAPOT_PATCH_DIMENSION, v);
472 position += poly_i * poly_j * control_points_k[i][j];
478 inline glm::vec3 eval_bezier_curve_du(glm::vec3**
const control_points_k,
const GLfloat u,
const GLfloat v) {
481 for (GLuint i = 0; i <= TEAPOT_PATCH_DIMENSION; ++i) {
482 for (GLuint j = 0; j <= TEAPOT_PATCH_DIMENSION; ++j) {
483 P[j] = control_points_k[i][j];
485 vCurve[i] = teapot_evaluate_curve(P, v);
488 return -3.f * (1.f - u) * (1.f - u) * vCurve[0] +
489 (3.f * (1.f - u) * (1.f - u) - 6.f * u * (1.f - u)) * vCurve[1] +
490 (6.f * u * (1.f - u) - 3.f * u * u) * vCurve[2] +
491 3.f * u * u * vCurve[3];
494 inline glm::vec3 eval_bezier_curve_dv(glm::vec3**
const control_points_k,
const GLfloat u,
const GLfloat v) {
497 for (GLuint j = 0; j <= TEAPOT_PATCH_DIMENSION; ++j) {
498 for (GLuint i = 0; i <= TEAPOT_PATCH_DIMENSION; ++i) {
499 P[i] = control_points_k[i][j];
501 uCurve[j] = teapot_evaluate_curve(P, u);
504 return -3.f * (1.f - v) * (1.f - v) * uCurve[0] +
505 (3.f * (1.f - v) * (1.f - v) - 6.f * v * (1.f - v)) * uCurve[1] +
506 (6.f * v * (1.f - v) - 3.f * v * v) * uCurve[2] +
507 3.f * v * v * uCurve[3];
510 inline glm::vec3 teapot_compute_normal(glm::vec3**
const control_points_k,
const GLfloat u,
const GLfloat v) {
511 glm::vec3 du = eval_bezier_curve_du(control_points_k, u, v);
512 glm::vec3 dv = eval_bezier_curve_dv(control_points_k, u, v);
513 glm::vec3 normal = -glm::normalize(glm::cross(du, dv));
517 inline glm::vec3 teapot_compute_texture(
const glm::vec3 position) {
518 glm::vec3 textureCoordinate = {0.0f, 0.0f, 0.0f};
519 const GLfloat PI = 3.14159265f;
520 GLfloat theta = atan2(position.y, position.x);
521 textureCoordinate.x = (theta + PI) / (2.0f * PI);
522 textureCoordinate.y = position.z / 3.15f;
523 return textureCoordinate;
526 inline glm::vec3 teapot_evaluate_curve(
const glm::vec3*
const control_points, GLfloat t) {
527 glm::vec3 position = {0.0f, 0.0f, 0.0f};
528 for(GLuint i = 0; i <= TEAPOT_PATCH_DIMENSION; i++) {
529 position += teapot_bernstein_polynomial(i, TEAPOT_PATCH_DIMENSION, t) * control_points[i];
534 inline GLfloat teapot_bernstein_polynomial(
const GLuint i,
const GLuint n,
const GLfloat u) {
535 return teapot_binomial_coefficient(i, n) * powf(u, (GLfloat)i) * powf(1 - u, (GLfloat)(n - i));
538 inline GLfloat teapot_binomial_coefficient(
const GLuint i,
const GLuint n) {
539 return 1.0f * (GLfloat) teapot_factorial(n) / (GLfloat)(teapot_factorial(i) * teapot_factorial(n - i));
541 inline GLuint teapot_factorial(
const GLuint n) {
543 for (GLuint i = n; i > 1; i--)
548 inline GLboolean teapot_init_resources() {
549 teapot_build_teapot();
551 glGenVertexArrays(1, &teapot_vao);
552 glBindVertexArray(teapot_vao);
554 glGenBuffers(1, &teapot_vbo);
555 glBindBuffer(GL_ARRAY_BUFFER, teapot_vbo);
556 glBufferData(GL_ARRAY_BUFFER,
sizeof(teapot_vertices), teapot_vertices, GL_STATIC_DRAW);
558 glGenBuffers(1, &teapot_ibo);
559 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, teapot_ibo);
560 glBufferData(GL_ELEMENT_ARRAY_BUFFER,
sizeof(teapot_elements), teapot_elements, GL_STATIC_DRAW);
562 teapot_built = GL_TRUE;
568 inline void teapot(
const GLfloat size,
const GLint positionLocation,
const GLint normalLocation,
const GLint texCoordLocation ) {
569 if( !teapot_built ) {
570 teapot_init_resources();
572 if( positionLocation != teapot_pos_attr_loc || normalLocation != teapot_norm_attr_loc || texCoordLocation != teapot_tex_attr_loc ) {
573 setTeapotAttributeLocations(positionLocation, normalLocation, texCoordLocation);
578 inline void setTeapotAttributeLocations(
const GLint positionLocation,
const GLint normalLocation,
const GLint texCoordLocation) {
579 if( !teapot_built ) {
580 teapot_init_resources();
583 glBindVertexArray(teapot_vao );
584 glBindBuffer(GL_ARRAY_BUFFER, teapot_vbo);
586 if(teapot_pos_attr_loc != -1) glDisableVertexAttribArray(teapot_pos_attr_loc);
587 if(teapot_norm_attr_loc != -1) glDisableVertexAttribArray(teapot_norm_attr_loc);
588 if(teapot_tex_attr_loc != -1) glDisableVertexAttribArray(teapot_tex_attr_loc);
590 teapot_pos_attr_loc = positionLocation;
591 teapot_norm_attr_loc = normalLocation;
592 teapot_tex_attr_loc = texCoordLocation;
595 if(teapot_pos_attr_loc != -1) {
596 glEnableVertexAttribArray(teapot_pos_attr_loc);
597 glVertexAttribPointer(
606 if(teapot_norm_attr_loc != -1) {
607 glEnableVertexAttribArray(teapot_norm_attr_loc);
608 glVertexAttribPointer(
609 teapot_norm_attr_loc,
614 (
void*)(TEAPOT_NUMBER_PATCHES * TEAPOT_RES_U * TEAPOT_RES_V *
sizeof(glm::vec3))
617 if(teapot_tex_attr_loc != -1) {
618 glEnableVertexAttribArray(teapot_tex_attr_loc);
619 glVertexAttribPointer(
625 (
void*)(TEAPOT_NUMBER_PATCHES * TEAPOT_RES_U * TEAPOT_RES_V * 2 *
sizeof(glm::vec3))
630 inline void teapot() {
631 glBindVertexArray(teapot_vao );
632 glBindBuffer(GL_ARRAY_BUFFER, teapot_vbo);
633 glDrawElements(GL_TRIANGLES,
sizeof(teapot_elements)/
sizeof(teapot_elements[0]), GL_UNSIGNED_SHORT,
nullptr);