added Utah teapot
authorJohn Tsiombikas <nuclear@member.fsf.org>
Thu, 6 Aug 2020 22:46:44 +0000 (01:46 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Thu, 6 Aug 2020 22:46:44 +0000 (01:46 +0300)
miniglut.c
test.c

index b098651..631aac4 100644 (file)
@@ -2095,10 +2095,323 @@ void glutWireTorus(float inner_rad, float outer_rad, int sides, int rings)
        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();
+}
diff --git a/test.c b/test.c
index 762fea6..bac41ea 100644 (file)
--- a/test.c
+++ b/test.c
@@ -124,6 +124,13 @@ void display(void)
        glutSolidCone(1.1, 2, 16, 2);
        glPopMatrix();
 
+       glPushMatrix();
+       glTranslatef(0, -0.5, 2.5);
+       glFrontFace(GL_CW);
+       glutSolidTeapot(1.0);
+       glFrontFace(GL_CCW);
+       glPopMatrix();
+
        glBegin(GL_QUADS);
        glNormal3f(0, 1, 0);
        glVertex3f(-5, -1.3, 5);