glPopAttrib();
}
+#define NUM_TEAPOT_INDICES (sizeof teapot_index / sizeof *teapot_index)
+#define NUM_TEAPOT_VERTS (sizeof teapot_verts / sizeof *teapot_verts)
+
+#define NUM_TEAPOT_PATCHES (NUM_TEAPOT_INDICES / 16)
+
+#define PATCH_SUBDIV 7
+
+static float teapot_part_flip[] = {
+ 1, 1, 1, 1, /* rim flip */
+ 1, 1, 1, 1, /* body1 flip */
+ 1, 1, 1, 1, /* body2 flip */
+ 1, 1, 1, 1, /* lid patch 1 flip */
+ 1, 1, 1, 1, /* lid patch 2 flip */
+ 1, -1, /* handle 1 flip */
+ 1, -1, /* handle 2 flip */
+ 1, -1, /* spout 1 flip */
+ 1, -1, /* spout 2 flip */
+ 1, 1, 1, 1 /* bottom flip */
+};
+
+static float teapot_part_rot[] = {
+ 0, 90, 180, 270, /* rim rotations */
+ 0, 90, 180, 270, /* body patch 1 rotations */
+ 0, 90, 180, 270, /* body patch 2 rotations */
+ 0, 90, 180, 270, /* lid patch 1 rotations */
+ 0, 90, 180, 270, /* lid patch 2 rotations */
+ 0, 0, /* handle 1 rotations */
+ 0, 0, /* handle 2 rotations */
+ 0, 0, /* spout 1 rotations */
+ 0, 0, /* spout 2 rotations */
+ 0, 90, 180, 270 /* bottom rotations */
+};
+
+
+static int teapot_index[] = {
+ /* rim */
+ 102, 103, 104, 105, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 102, 103, 104, 105, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 102, 103, 104, 105, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 102, 103, 104, 105, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ /* body1 */
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
+ 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
+ /* body 2 */
+ 24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ /* lid 1 */
+ 96, 96, 96, 96, 97, 98, 99, 100, 101, 101, 101, 101, 0, 1, 2, 3,
+ 96, 96, 96, 96, 97, 98, 99, 100, 101, 101, 101, 101, 0, 1, 2, 3,
+ 96, 96, 96, 96, 97, 98, 99, 100, 101, 101, 101, 101, 0, 1, 2, 3,
+ 96, 96, 96, 96, 97, 98, 99, 100, 101, 101, 101, 101, 0, 1, 2, 3,
+ /* lid 2 */
+ 0, 1, 2, 3, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
+ 0, 1, 2, 3, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
+ 0, 1, 2, 3, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
+ 0, 1, 2, 3, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
+ /* handle 1 */
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
+ /* handle 2 */
+ 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 28, 65, 66, 67,
+ 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 28, 65, 66, 67,
+ /* spout 1 */
+ 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
+ 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
+ /* spout 2 */
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+ /* bottom */
+ 118, 118, 118, 118, 124, 122, 119, 121, 123, 126, 125, 120, 40, 39, 38, 37,
+ 118, 118, 118, 118, 124, 122, 119, 121, 123, 126, 125, 120, 40, 39, 38, 37,
+ 118, 118, 118, 118, 124, 122, 119, 121, 123, 126, 125, 120, 40, 39, 38, 37,
+ 118, 118, 118, 118, 124, 122, 119, 121, 123, 126, 125, 120, 40, 39, 38, 37
+};
+
+
+static float teapot_verts[][3] = {
+ { 0.2000, 0.0000, 2.70000 }, { 0.2000, -0.1120, 2.70000 },
+ { 0.1120, -0.2000, 2.70000 }, { 0.0000, -0.2000, 2.70000 },
+ { 1.3375, 0.0000, 2.53125 }, { 1.3375, -0.7490, 2.53125 },
+ { 0.7490, -1.3375, 2.53125 }, { 0.0000, -1.3375, 2.53125 },
+ { 1.4375, 0.0000, 2.53125 }, { 1.4375, -0.8050, 2.53125 },
+ { 0.8050, -1.4375, 2.53125 }, { 0.0000, -1.4375, 2.53125 },
+ { 1.5000, 0.0000, 2.40000 }, { 1.5000, -0.8400, 2.40000 },
+ { 0.8400, -1.5000, 2.40000 }, { 0.0000, -1.5000, 2.40000 },
+ { 1.7500, 0.0000, 1.87500 }, { 1.7500, -0.9800, 1.87500 },
+ { 0.9800, -1.7500, 1.87500 }, { 0.0000, -1.7500, 1.87500 },
+ { 2.0000, 0.0000, 1.35000 }, { 2.0000, -1.1200, 1.35000 },
+ { 1.1200, -2.0000, 1.35000 }, { 0.0000, -2.0000, 1.35000 },
+ { 2.0000, 0.0000, 0.90000 }, { 2.0000, -1.1200, 0.90000 },
+ { 1.1200, -2.0000, 0.90000 }, { 0.0000, -2.0000, 0.90000 },
+ { -2.0000, 0.0000, 0.90000 }, { 2.0000, 0.0000, 0.45000 },
+ { 2.0000, -1.1200, 0.45000 }, { 1.1200, -2.0000, 0.45000 },
+ { 0.0000, -2.0000, 0.45000 }, { 1.5000, 0.0000, 0.22500 },
+ { 1.5000, -0.8400, 0.22500 }, { 0.8400, -1.5000, 0.22500 },
+ { 0.0000, -1.5000, 0.22500 }, { 1.5000, 0.0000, 0.15000 },
+ { 1.5000, -0.8400, 0.15000 }, { 0.8400, -1.5000, 0.15000 },
+ { 0.0000, -1.5000, 0.15000 }, { -1.6000, 0.0000, 2.02500 },
+ { -1.6000, -0.3000, 2.02500 }, { -1.5000, -0.3000, 2.25000 },
+ { -1.5000, 0.0000, 2.25000 }, { -2.3000, 0.0000, 2.02500 },
+ { -2.3000, -0.3000, 2.02500 }, { -2.5000, -0.3000, 2.25000 },
+ { -2.5000, 0.0000, 2.25000 }, { -2.7000, 0.0000, 2.02500 },
+ { -2.7000, -0.3000, 2.02500 }, { -3.0000, -0.3000, 2.25000 },
+ { -3.0000, 0.0000, 2.25000 }, { -2.7000, 0.0000, 1.80000 },
+ { -2.7000, -0.3000, 1.80000 }, { -3.0000, -0.3000, 1.80000 },
+ { -3.0000, 0.0000, 1.80000 }, { -2.7000, 0.0000, 1.57500 },
+ { -2.7000, -0.3000, 1.57500 }, { -3.0000, -0.3000, 1.35000 },
+ { -3.0000, 0.0000, 1.35000 }, { -2.5000, 0.0000, 1.12500 },
+ { -2.5000, -0.3000, 1.12500 }, { -2.6500, -0.3000, 0.93750 },
+ { -2.6500, 0.0000, 0.93750 }, { -2.0000, -0.3000, 0.90000 },
+ { -1.9000, -0.3000, 0.60000 }, { -1.9000, 0.0000, 0.60000 },
+ { 1.7000, 0.0000, 1.42500 }, { 1.7000, -0.6600, 1.42500 },
+ { 1.7000, -0.6600, 0.60000 }, { 1.7000, 0.0000, 0.60000 },
+ { 2.6000, 0.0000, 1.42500 }, { 2.6000, -0.6600, 1.42500 },
+ { 3.1000, -0.6600, 0.82500 }, { 3.1000, 0.0000, 0.82500 },
+ { 2.3000, 0.0000, 2.10000 }, { 2.3000, -0.2500, 2.10000 },
+ { 2.4000, -0.2500, 2.02500 }, { 2.4000, 0.0000, 2.02500 },
+ { 2.7000, 0.0000, 2.40000 }, { 2.7000, -0.2500, 2.40000 },
+ { 3.3000, -0.2500, 2.40000 }, { 3.3000, 0.0000, 2.40000 },
+ { 2.8000, 0.0000, 2.47500 }, { 2.8000, -0.2500, 2.47500 },
+ { 3.5250, -0.2500, 2.49375 }, { 3.5250, 0.0000, 2.49375 },
+ { 2.9000, 0.0000, 2.47500 }, { 2.9000, -0.1500, 2.47500 },
+ { 3.4500, -0.1500, 2.51250 }, { 3.4500, 0.0000, 2.51250 },
+ { 2.8000, 0.0000, 2.40000 }, { 2.8000, -0.1500, 2.40000 },
+ { 3.2000, -0.1500, 2.40000 }, { 3.2000, 0.0000, 2.40000 },
+ { 0.0000, 0.0000, 3.15000 }, { 0.8000, 0.0000, 3.15000 },
+ { 0.8000, -0.4500, 3.15000 }, { 0.4500, -0.8000, 3.15000 },
+ { 0.0000, -0.8000, 3.15000 }, { 0.0000, 0.0000, 2.85000 },
+ { 1.4000, 0.0000, 2.40000 }, { 1.4000, -0.7840, 2.40000 },
+ { 0.7840, -1.4000, 2.40000 }, { 0.0000, -1.4000, 2.40000 },
+ { 0.4000, 0.0000, 2.55000 }, { 0.4000, -0.2240, 2.55000 },
+ { 0.2240, -0.4000, 2.55000 }, { 0.0000, -0.4000, 2.55000 },
+ { 1.3000, 0.0000, 2.55000 }, { 1.3000, -0.7280, 2.55000 },
+ { 0.7280, -1.3000, 2.55000 }, { 0.0000, -1.3000, 2.55000 },
+ { 1.3000, 0.0000, 2.40000 }, { 1.3000, -0.7280, 2.40000 },
+ { 0.7280, -1.3000, 2.40000 }, { 0.0000, -1.3000, 2.40000 },
+ { 0.0000, 0.0000, 0.00000 }, { 1.4250, -0.7980, 0.00000 },
+ { 1.5000, 0.0000, 0.07500 }, { 1.4250, 0.0000, 0.00000 },
+ { 0.7980, -1.4250, 0.00000 }, { 0.0000, -1.5000, 0.07500 },
+ { 0.0000, -1.4250, 0.00000 }, { 1.5000, -0.8400, 0.07500 },
+ { 0.8400, -1.5000, 0.07500 }
+};
+
+static void draw_patch(int *index, int flip, float scale);
+static float bernstein(int i, float x);
+
void glutSolidTeapot(float size)
{
+ int i;
+
+ size /= 2.0;
+
+ for(i=0; i<NUM_TEAPOT_PATCHES; i++) {
+ float flip = teapot_part_flip[i];
+ float rot = teapot_part_rot[i];
+
+ glMatrixMode(GL_MODELVIEW);
+ glPushMatrix();
+ glTranslatef(0, -3.15 * size * 0.5, 0);
+ glRotatef(rot, 0, 1, 0);
+ glScalef(1, 1, flip);
+ glRotatef(-90, 1, 0, 0);
+
+ draw_patch(teapot_index + i * 16, flip < 0.0 ? 1 : 0, size);
+
+ glPopMatrix();
+ }
}
void glutWireTeapot(float size)
{
}
+
+
+static void bezier_patch(float *res, float *cp, float u, float v)
+{
+ int i, j;
+
+ res[0] = res[1] = res[2] = 0.0f;
+
+ for(j=0; j<4; j++) {
+ for(i=0; i<4; i++) {
+ float bu = bernstein(i, u);
+ float bv = bernstein(j, v);
+
+ res[0] += cp[0] * bu * bv;
+ res[1] += cp[1] * bu * bv;
+ res[2] += cp[2] * bu * bv;
+
+ cp += 3;
+ }
+ }
+}
+
+static float rsqrt(float x)
+{
+ float xhalf = x * 0.5f;
+ int32_t i = *(int32_t*)&x;
+ i = 0x5f3759df - (i >> 1);
+ x = *(float*)&i;
+ x = x * (1.5f - xhalf * x * x);
+ return x;
+}
+
+
+#define CROSS(res, a, b) \
+ do { \
+ (res)[0] = (a)[1] * (b)[2] - (a)[2] * (b)[1]; \
+ (res)[1] = (a)[2] * (b)[0] - (a)[0] * (b)[2]; \
+ (res)[2] = (a)[0] * (b)[1] - (a)[1] * (b)[0]; \
+ } while(0)
+
+#define NORMALIZE(v) \
+ do { \
+ float s = rsqrt((v)[0] * (v)[0] + (v)[1] * (v)[1] + (v)[2] * (v)[2]); \
+ (v)[0] *= s; \
+ (v)[1] *= s; \
+ (v)[2] *= s; \
+ } while(0)
+
+#define DT 0.001
+
+static void bezier_patch_norm(float *res, float *cp, float u, float v)
+{
+ float tang[3], bitan[3], tmp[3];
+
+ bezier_patch(tang, cp, u + DT, v);
+ bezier_patch(tmp, cp, u - DT, v);
+ tang[0] -= tmp[0];
+ tang[1] -= tmp[1];
+ tang[2] -= tmp[2];
+
+ bezier_patch(bitan, cp, u, v + DT);
+ bezier_patch(tmp, cp, u, v - DT);
+ bitan[0] -= tmp[0];
+ bitan[1] -= tmp[1];
+ bitan[2] -= tmp[2];
+
+ CROSS(res, tang, bitan);
+ NORMALIZE(res);
+}
+
+
+
+static float bernstein(int i, float x)
+{
+ float invx = 1.0f - x;
+
+ switch(i) {
+ case 0:
+ return invx * invx * invx;
+ case 1:
+ return 3.0f * x * invx * invx;
+ case 2:
+ return 3.0f * x * x * invx;
+ case 3:
+ return x * x * x;
+ default:
+ break;
+ }
+ return 0.0f;
+}
+
+static void draw_patch(int *index, int flip, float scale)
+{
+ static const float uoffs[2][4] = {{0, 0, 1, 1}, {1, 1, 0, 0}};
+ static const float voffs[4] = {0, 1, 1, 0};
+
+ int i, j, k;
+ float cp[16 * 3];
+ float pt[3], n[3];
+ float u, v;
+ float du = 1.0 / PATCH_SUBDIV;
+ float dv = 1.0 / PATCH_SUBDIV;
+
+ /* collect control points */
+ for(i=0; i<16; i++) {
+ cp[i * 3] = teapot_verts[index[i]][0];
+ cp[i * 3 + 1] = teapot_verts[index[i]][1];
+ cp[i * 3 + 2] = teapot_verts[index[i]][2];
+ }
+
+ glBegin(GL_QUADS);
+ glColor3f(1, 1, 1);
+
+ u = 0;
+ for(i=0; i<PATCH_SUBDIV; i++) {
+ v = 0;
+ for(j=0; j<PATCH_SUBDIV; j++) {
+
+ for(k=0; k<4; k++) {
+ bezier_patch(pt, cp, u + uoffs[flip][k] * du, v + voffs[k] * dv);
+
+ /* top/bottom normal hack */
+ if(pt[2] > 3.14) {
+ n[0] = n[1] = 0.0f;
+ n[2] = 1.0f;
+ } else if(pt[2] < 0.00001) {
+ n[0] = n[1] = 0.0f;
+ n[2] = -1.0f;
+ } else {
+ bezier_patch_norm(n, cp, u + uoffs[flip][k] * du, v + voffs[k] * dv);
+ }
+
+ glTexCoord2f(u, v);
+ glNormal3fv(n);
+ glVertex3f(pt[0] * scale, pt[1] * scale, pt[2] * scale);
+ }
+
+ v += dv;
+ }
+ u += du;
+ }
+
+ glEnd();
+}