aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRadosław Kujawa <radoslaw.kujawa@c0ff33.net>2026-07-18 00:14:46 +0200
committerRadosław Kujawa <radoslaw.kujawa@c0ff33.net>2026-07-18 00:14:46 +0200
commitb3d6f168c17ebd60acc673ddfb2e71494054b599 (patch)
tree8b62eaa189ce6d738604ab0a4ad02b8f2be2415b
parent14f2715c3d07953168cda37eab60db4d6d05e046 (diff)
TEAPOT TIME!
-rw-r--r--README.md6
-rw-r--r--examples/Makefile4
-rw-r--r--examples/teapot.c288
-rw-r--r--examples/teapot_data.inc192
4 files changed, 486 insertions, 4 deletions
diff --git a/README.md b/README.md
index 6012a9f..1886dba 100644
--- a/README.md
+++ b/README.md
@@ -55,9 +55,9 @@ context. See examples for usage.
cc -Iinclude your_app.c lib/libGL.a -lm -o your_app
```
-The `examples/` (`cube`, `rave`) contain runnable programs. Buidl and run
-as the user with permissions to `/dev/verite3d`, point `VERITE_UCODE`
-evironment variable at the `v2000gl.uc` 3D microcode.
+The `examples/` contain runnable programs. Build
+and run as the user with permissions to `/dev/verite3d`, point `VERITE_UCODE`
+environment variable at the `v2000gl.uc` 3D microcode.
If the `/dev/verite3d` does not exist on your system, despite running a
kernel with `veritefb(4)` driver loaded, create it using `MAKEDEV`.
diff --git a/examples/Makefile b/examples/Makefile
index c2d2176..ee05725 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -7,7 +7,7 @@ GLINC = -I$(TOP)/include
LIBGL = $(TOP)/lib/libGL.a
LIBS = -lm
-PROGS = cube rave
+PROGS = cube rave teapot
.PHONY: all clean
all: $(PROGS)
@@ -15,6 +15,8 @@ all: $(PROGS)
$(PROGS): %: %.c $(LIBGL)
$(CC) $(CFLAGS) $(GLINC) $< $(LIBGL) $(LIBS) -o $@
+teapot: teapot_data.inc
+
clean:
rm -f $(PROGS)
diff --git a/examples/teapot.c b/examples/teapot.c
new file mode 100644
index 0000000..ff67f95
--- /dev/null
+++ b/examples/teapot.c
@@ -0,0 +1,288 @@
+/*
+ * teapot - the Utah teapot, lit and spinning
+ *
+ * Build:
+ * cc -O2 -I../include -o teapot teapot.c ../lib/libGL.a -lm
+ *
+ * Run: VERITE_UCODE=$HOME/v2000gl.uc \
+ * ./teapot [seconds] (0 = spin until ^C)
+ *
+ * Tessellation density is TEAPOT_GRID (default 8)...
+ */
+#include <sys/time.h>
+#include <math.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <GL/gl.h>
+#include <GL/vrmesa.h>
+
+static const GLfloat teapot_patch[32][4][4][3] = {
+#include "teapot_data.inc"
+};
+
+static volatile sig_atomic_t stop;
+
+static void
+onint(int sig)
+{
+
+ (void)sig;
+ stop = 1;
+}
+
+/* Cubic Bernstein basis and its derivative at t. */
+static void
+bernstein(float t, float b[4], float db[4])
+{
+ float it = 1.0f - t;
+
+ b[0] = it * it * it;
+ b[1] = 3.0f * t * it * it;
+ b[2] = 3.0f * t * t * it;
+ b[3] = t * t * t;
+
+ db[0] = -3.0f * it * it;
+ db[1] = 3.0f * it * it - 6.0f * t * it;
+ db[2] = 6.0f * t * it - 3.0f * t * t;
+ db[3] = 3.0f * t * t;
+}
+
+/*
+ * Evaluate patch p at (u,v)
+ */
+static void
+eval_patch(int p, float u, float v, float pos[3], float nrm[3])
+{
+ float bu[4], dbu[4], bv[4], dbv[4];
+ float du[3], dv[3], len;
+ int i, j, k;
+
+ if (u < 1e-4f)
+ u = 1e-4f;
+ else if (u > 1.0f - 1e-4f)
+ u = 1.0f - 1e-4f;
+ if (v < 1e-4f)
+ v = 1e-4f;
+ else if (v > 1.0f - 1e-4f)
+ v = 1.0f - 1e-4f;
+
+ bernstein(u, bu, dbu);
+ bernstein(v, bv, dbv);
+
+ for (k = 0; k < 3; k++)
+ pos[k] = du[k] = dv[k] = 0.0f;
+
+ for (i = 0; i < 4; i++)
+ for (j = 0; j < 4; j++) {
+ const GLfloat *cp = teapot_patch[p][i][j];
+ float w = bu[i] * bv[j];
+ float wu = dbu[i] * bv[j];
+ float wv = bu[i] * dbv[j];
+
+ for (k = 0; k < 3; k++) {
+ pos[k] += w * cp[k];
+ du[k] += wu * cp[k];
+ dv[k] += wv * cp[k];
+ }
+ }
+
+ /* normal = du x dv (points outward across the whole teaset) */
+ nrm[0] = du[1] * dv[2] - du[2] * dv[1];
+ nrm[1] = du[2] * dv[0] - du[0] * dv[2];
+ nrm[2] = du[0] * dv[1] - du[1] * dv[0];
+ len = sqrtf(nrm[0] * nrm[0] + nrm[1] * nrm[1] + nrm[2] * nrm[2]);
+ if (len > 1e-8f) {
+ nrm[0] /= len;
+ nrm[1] /= len;
+ nrm[2] /= len;
+ } else {
+ nrm[0] = nrm[1] = 0.0f;
+ nrm[2] = 1.0f;
+ }
+}
+
+struct vtx {
+ GLfloat p[3];
+ GLfloat n[3];
+};
+
+static int grid; /* steps per patch edge */
+static int row; /* vertices per patch edge = grid + 1 */
+static struct vtx *mesh; /* [32][row*row], contiguous */
+
+static void
+build_mesh(void)
+{
+ GLfloat lo[3], hi[3];
+ GLfloat cx, cy, cz, dim, m, gscale;
+ int p, a, b, k, n, nverts;
+
+ row = grid + 1;
+ nverts = 32 * row * row;
+ mesh = malloc((size_t)nverts * sizeof(*mesh));
+ if (mesh == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+
+ for (k = 0; k < 3; k++) {
+ lo[k] = 1e30f;
+ hi[k] = -1e30f;
+ }
+
+ for (p = 0; p < 32; p++)
+ for (a = 0; a < row; a++)
+ for (b = 0; b < row; b++) {
+ struct vtx *vp = &mesh[(p * row + a) * row + b];
+
+ eval_patch(p, (float)a / grid, (float)b / grid,
+ vp->p, vp->n);
+ for (k = 0; k < 3; k++) {
+ if (vp->p[k] < lo[k])
+ lo[k] = vp->p[k];
+ if (vp->p[k] > hi[k])
+ hi[k] = vp->p[k];
+ }
+ }
+
+ /* Bake centre + uniform scale into the vertices so the modelview needs
+ * no scale and the unit normals need no GL_NORMALIZE. */
+ cx = 0.5f * (lo[0] + hi[0]);
+ cy = 0.5f * (lo[1] + hi[1]);
+ cz = 0.5f * (lo[2] + hi[2]);
+ dim = hi[0] - lo[0];
+ m = hi[1] - lo[1];
+ if (m > dim)
+ dim = m;
+ m = hi[2] - lo[2];
+ if (m > dim)
+ dim = m;
+ gscale = 3.0f / dim;
+ for (n = 0; n < nverts; n++) {
+ mesh[n].p[0] = (mesh[n].p[0] - cx) * gscale;
+ mesh[n].p[1] = (mesh[n].p[1] - cy) * gscale;
+ mesh[n].p[2] = (mesh[n].p[2] - cz) * gscale;
+ }
+}
+
+static void
+draw_teapot(void)
+{
+ int p, a, b;
+
+ for (p = 0; p < 32; p++)
+ for (a = 0; a < grid; a++) {
+ const struct vtx *r0 = &mesh[(p * row + a) * row];
+ const struct vtx *r1 = &mesh[(p * row + a + 1) * row];
+
+ glBegin(GL_TRIANGLE_STRIP);
+ for (b = 0; b < row; b++) {
+ glNormal3fv(r0[b].n);
+ glVertex3fv(r0[b].p);
+ glNormal3fv(r1[b].n);
+ glVertex3fv(r1[b].p);
+ }
+ glEnd();
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ static const GLfloat lightpos[4] = { -0.4f, 0.7f, 1.0f, 0.0f };
+ static const GLfloat lightamb[4] = { 0.15f, 0.15f, 0.18f, 1.0f };
+ static const GLfloat lightdif[4] = { 0.9f, 0.9f, 0.85f, 1.0f };
+ static const GLfloat lightspc[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
+ static const GLfloat matdif[4] = { 0.75f, 0.42f, 0.16f, 1.0f };
+ static const GLfloat matspc[4] = { 0.85f, 0.85f, 0.75f, 1.0f };
+ static const GLfloat matamb[4] = { 0.25f, 0.14f, 0.06f, 1.0f };
+ vrMesaContext ctx;
+ struct timeval t0, t1, tstart;
+ const char *genv = getenv("TEAPOT_GRID");
+ double secs = 30.0;
+ float spin = 0.0f;
+ int frame = 0;
+
+ if (argc > 1)
+ secs = atof(argv[1]);
+ grid = genv != NULL ? atoi(genv) : 8;
+ if (grid < 2)
+ grid = 2;
+ else if (grid > 40)
+ grid = 40;
+ signal(SIGINT, onint);
+
+ build_mesh();
+
+ ctx = vrMesaCreateContext(NULL);
+ if (ctx == NULL)
+ return 1;
+ vrMesaMakeCurrent(ctx);
+ printf("GL_RENDERER: %s (%s)\n", glGetString(GL_RENDERER),
+ glGetString(GL_VERSION));
+ printf("teapot: 32 patches, grid %d -> %d triangles\n",
+ grid, 32 * grid * grid * 2);
+
+ glEnable(GL_DEPTH_TEST);
+ glShadeModel(GL_SMOOTH);
+ /* cross(du,dv) points outward across the whole teaset, so single-sided
+ * lighting shades the exterior correctly and stays on the hardware
+ * triangle path (two-sided lighting would force a swrast fallback).
+ * Back faces fall behind the depth buffer, so culling is unnecessary. */
+ glEnable(GL_LIGHTING);
+ glEnable(GL_LIGHT0);
+ glLightfv(GL_LIGHT0, GL_AMBIENT, lightamb);
+ glLightfv(GL_LIGHT0, GL_DIFFUSE, lightdif);
+ glLightfv(GL_LIGHT0, GL_SPECULAR, lightspc);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, matamb);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, matdif);
+ glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, matspc);
+ glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 32.0f);
+
+ glClearColor(0.07f, 0.08f, 0.11f, 1.0f);
+ glViewport(0, 0, 640, 480);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glFrustum(-1.0, 1.0, -0.75, 0.75, 2.0, 80.0);
+
+ gettimeofday(&tstart, NULL);
+ t0 = tstart;
+ while (!stop) {
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glTranslatef(0.0f, -0.3f, -7.0f);
+ /* Fixed light, pinned in eye space before any model rotation. */
+ glLightfv(GL_LIGHT0, GL_POSITION, lightpos);
+ /* Stand the Z-up model upright (-90) and look slightly down (+15). */
+ glRotatef(-75.0f, 1.0f, 0.0f, 0.0f);
+ glRotatef(spin, 0.0f, 0.0f, 1.0f); /* spin about the model axis */
+
+ draw_teapot();
+
+ vrMesaSwapBuffers();
+ spin += 1.3f;
+ if (++frame % 100 == 0) {
+ double dt;
+
+ gettimeofday(&t1, NULL);
+ dt = (t1.tv_sec - t0.tv_sec) +
+ (t1.tv_usec - t0.tv_usec) / 1e6;
+ printf("%d frames, %.1f fps\n", frame, 100.0 / dt);
+ t0 = t1;
+ }
+ if (secs > 0) {
+ gettimeofday(&t1, NULL);
+ if ((t1.tv_sec - tstart.tv_sec) +
+ (t1.tv_usec - tstart.tv_usec) / 1e6 >= secs)
+ break;
+ }
+ }
+
+ printf("teapot done after %d frames\n", frame);
+ vrMesaDestroyContext(ctx);
+ free(mesh);
+ return 0;
+}
diff --git a/examples/teapot_data.inc b/examples/teapot_data.inc
new file mode 100644
index 0000000..eb89c04
--- /dev/null
+++ b/examples/teapot_data.inc
@@ -0,0 +1,192 @@
+ { /* patch 1 */
+ { { -80.000f, 0.000f, 30.000f}, { -80.000f, -44.800f, 30.000f}, { -44.800f, -80.000f, 30.000f}, { 0.000f, -80.000f, 30.000f} },
+ { { -80.000f, 0.000f, 12.000f}, { -80.000f, -44.800f, 12.000f}, { -44.800f, -80.000f, 12.000f}, { 0.000f, -80.000f, 12.000f} },
+ { { -60.000f, 0.000f, 3.000f}, { -60.000f, -33.600f, 3.000f}, { -33.600f, -60.000f, 3.000f}, { 0.000f, -60.000f, 3.000f} },
+ { { -60.000f, 0.000f, 0.000f}, { -60.000f, -33.600f, 0.000f}, { -33.600f, -60.000f, 0.000f}, { 0.000f, -60.000f, 0.000f} },
+ },
+ { /* patch 2 */
+ { { 0.000f, -80.000f, 30.000f}, { 44.800f, -80.000f, 30.000f}, { 80.000f, -44.800f, 30.000f}, { 80.000f, 0.000f, 30.000f} },
+ { { 0.000f, -80.000f, 12.000f}, { 44.800f, -80.000f, 12.000f}, { 80.000f, -44.800f, 12.000f}, { 80.000f, 0.000f, 12.000f} },
+ { { 0.000f, -60.000f, 3.000f}, { 33.600f, -60.000f, 3.000f}, { 60.000f, -33.600f, 3.000f}, { 60.000f, 0.000f, 3.000f} },
+ { { 0.000f, -60.000f, 0.000f}, { 33.600f, -60.000f, 0.000f}, { 60.000f, -33.600f, 0.000f}, { 60.000f, 0.000f, 0.000f} },
+ },
+ { /* patch 3 */
+ { { -60.000f, 0.000f, 90.000f}, { -60.000f, -33.600f, 90.000f}, { -33.600f, -60.000f, 90.000f}, { 0.000f, -60.000f, 90.000f} },
+ { { -70.000f, 0.000f, 69.000f}, { -70.000f, -39.200f, 69.000f}, { -39.200f, -70.000f, 69.000f}, { 0.000f, -70.000f, 69.000f} },
+ { { -80.000f, 0.000f, 48.000f}, { -80.000f, -44.800f, 48.000f}, { -44.800f, -80.000f, 48.000f}, { 0.000f, -80.000f, 48.000f} },
+ { { -80.000f, 0.000f, 30.000f}, { -80.000f, -44.800f, 30.000f}, { -44.800f, -80.000f, 30.000f}, { 0.000f, -80.000f, 30.000f} },
+ },
+ { /* patch 4 */
+ { { 0.000f, -60.000f, 90.000f}, { 33.600f, -60.000f, 90.000f}, { 60.000f, -33.600f, 90.000f}, { 60.000f, 0.000f, 90.000f} },
+ { { 0.000f, -70.000f, 69.000f}, { 39.200f, -70.000f, 69.000f}, { 70.000f, -39.200f, 69.000f}, { 70.000f, 0.000f, 69.000f} },
+ { { 0.000f, -80.000f, 48.000f}, { 44.800f, -80.000f, 48.000f}, { 80.000f, -44.800f, 48.000f}, { 80.000f, 0.000f, 48.000f} },
+ { { 0.000f, -80.000f, 30.000f}, { 44.800f, -80.000f, 30.000f}, { 80.000f, -44.800f, 30.000f}, { 80.000f, 0.000f, 30.000f} },
+ },
+ { /* patch 5 */
+ { { -56.000f, 0.000f, 90.000f}, { -56.000f, -31.360f, 90.000f}, { -31.360f, -56.000f, 90.000f}, { 0.000f, -56.000f, 90.000f} },
+ { { -53.500f, 0.000f, 95.250f}, { -53.500f, -29.960f, 95.250f}, { -29.960f, -53.500f, 95.250f}, { 0.000f, -53.500f, 95.250f} },
+ { { -57.500f, 0.000f, 95.250f}, { -57.500f, -32.200f, 95.250f}, { -32.200f, -57.500f, 95.250f}, { 0.000f, -57.500f, 95.250f} },
+ { { -60.000f, 0.000f, 90.000f}, { -60.000f, -33.600f, 90.000f}, { -33.600f, -60.000f, 90.000f}, { 0.000f, -60.000f, 90.000f} },
+ },
+ { /* patch 6 */
+ { { 0.000f, -56.000f, 90.000f}, { 31.360f, -56.000f, 90.000f}, { 56.000f, -31.360f, 90.000f}, { 56.000f, 0.000f, 90.000f} },
+ { { 0.000f, -53.500f, 95.250f}, { 29.960f, -53.500f, 95.250f}, { 53.500f, -29.960f, 95.250f}, { 53.500f, 0.000f, 95.250f} },
+ { { 0.000f, -57.500f, 95.250f}, { 32.200f, -57.500f, 95.250f}, { 57.500f, -32.200f, 95.250f}, { 57.500f, 0.000f, 95.250f} },
+ { { 0.000f, -60.000f, 90.000f}, { 33.600f, -60.000f, 90.000f}, { 60.000f, -33.600f, 90.000f}, { 60.000f, 0.000f, 90.000f} },
+ },
+ { /* patch 7 */
+ { { 80.000f, 0.000f, 30.000f}, { 80.000f, 44.800f, 30.000f}, { 44.800f, 80.000f, 30.000f}, { 0.000f, 80.000f, 30.000f} },
+ { { 80.000f, 0.000f, 12.000f}, { 80.000f, 44.800f, 12.000f}, { 44.800f, 80.000f, 12.000f}, { 0.000f, 80.000f, 12.000f} },
+ { { 60.000f, 0.000f, 3.000f}, { 60.000f, 33.600f, 3.000f}, { 33.600f, 60.000f, 3.000f}, { 0.000f, 60.000f, 3.000f} },
+ { { 60.000f, 0.000f, 0.000f}, { 60.000f, 33.600f, 0.000f}, { 33.600f, 60.000f, 0.000f}, { 0.000f, 60.000f, 0.000f} },
+ },
+ { /* patch 8 */
+ { { 0.000f, 80.000f, 30.000f}, { -44.800f, 80.000f, 30.000f}, { -80.000f, 44.800f, 30.000f}, { -80.000f, 0.000f, 30.000f} },
+ { { 0.000f, 80.000f, 12.000f}, { -44.800f, 80.000f, 12.000f}, { -80.000f, 44.800f, 12.000f}, { -80.000f, 0.000f, 12.000f} },
+ { { 0.000f, 60.000f, 3.000f}, { -33.600f, 60.000f, 3.000f}, { -60.000f, 33.600f, 3.000f}, { -60.000f, 0.000f, 3.000f} },
+ { { 0.000f, 60.000f, 0.000f}, { -33.600f, 60.000f, 0.000f}, { -60.000f, 33.600f, 0.000f}, { -60.000f, 0.000f, 0.000f} },
+ },
+ { /* patch 9 */
+ { { 60.000f, 0.000f, 90.000f}, { 60.000f, 33.600f, 90.000f}, { 33.600f, 60.000f, 90.000f}, { 0.000f, 60.000f, 90.000f} },
+ { { 70.000f, 0.000f, 69.000f}, { 70.000f, 39.200f, 69.000f}, { 39.200f, 70.000f, 69.000f}, { 0.000f, 70.000f, 69.000f} },
+ { { 80.000f, 0.000f, 48.000f}, { 80.000f, 44.800f, 48.000f}, { 44.800f, 80.000f, 48.000f}, { 0.000f, 80.000f, 48.000f} },
+ { { 80.000f, 0.000f, 30.000f}, { 80.000f, 44.800f, 30.000f}, { 44.800f, 80.000f, 30.000f}, { 0.000f, 80.000f, 30.000f} },
+ },
+ { /* patch 10 */
+ { { 0.000f, 60.000f, 90.000f}, { -33.600f, 60.000f, 90.000f}, { -60.000f, 33.600f, 90.000f}, { -60.000f, 0.000f, 90.000f} },
+ { { 0.000f, 70.000f, 69.000f}, { -39.200f, 70.000f, 69.000f}, { -70.000f, 39.200f, 69.000f}, { -70.000f, 0.000f, 69.000f} },
+ { { 0.000f, 80.000f, 48.000f}, { -44.800f, 80.000f, 48.000f}, { -80.000f, 44.800f, 48.000f}, { -80.000f, 0.000f, 48.000f} },
+ { { 0.000f, 80.000f, 30.000f}, { -44.800f, 80.000f, 30.000f}, { -80.000f, 44.800f, 30.000f}, { -80.000f, 0.000f, 30.000f} },
+ },
+ { /* patch 11 */
+ { { 56.000f, 0.000f, 90.000f}, { 56.000f, 31.360f, 90.000f}, { 31.360f, 56.000f, 90.000f}, { 0.000f, 56.000f, 90.000f} },
+ { { 53.500f, 0.000f, 95.250f}, { 53.500f, 29.960f, 95.250f}, { 29.960f, 53.500f, 95.250f}, { 0.000f, 53.500f, 95.250f} },
+ { { 57.500f, 0.000f, 95.250f}, { 57.500f, 32.200f, 95.250f}, { 32.200f, 57.500f, 95.250f}, { 0.000f, 57.500f, 95.250f} },
+ { { 60.000f, 0.000f, 90.000f}, { 60.000f, 33.600f, 90.000f}, { 33.600f, 60.000f, 90.000f}, { 0.000f, 60.000f, 90.000f} },
+ },
+ { /* patch 12 */
+ { { 0.000f, 56.000f, 90.000f}, { -31.360f, 56.000f, 90.000f}, { -56.000f, 31.360f, 90.000f}, { -56.000f, 0.000f, 90.000f} },
+ { { 0.000f, 53.500f, 95.250f}, { -29.960f, 53.500f, 95.250f}, { -53.500f, 29.960f, 95.250f}, { -53.500f, 0.000f, 95.250f} },
+ { { 0.000f, 57.500f, 95.250f}, { -32.200f, 57.500f, 95.250f}, { -57.500f, 32.200f, 95.250f}, { -57.500f, 0.000f, 95.250f} },
+ { { 0.000f, 60.000f, 90.000f}, { -33.600f, 60.000f, 90.000f}, { -60.000f, 33.600f, 90.000f}, { -60.000f, 0.000f, 90.000f} },
+ },
+ { /* patch 13 */
+ { { -64.000f, 0.000f, 75.000f}, { -64.000f, 12.000f, 75.000f}, { -60.000f, 12.000f, 84.000f}, { -60.000f, 0.000f, 84.000f} },
+ { { -92.000f, 0.000f, 75.000f}, { -92.000f, 12.000f, 75.000f}, {-100.000f, 12.000f, 84.000f}, {-100.000f, 0.000f, 84.000f} },
+ { {-108.000f, 0.000f, 75.000f}, {-108.000f, 12.000f, 75.000f}, {-120.000f, 12.000f, 84.000f}, {-120.000f, 0.000f, 84.000f} },
+ { {-108.000f, 0.000f, 66.000f}, {-108.000f, 12.000f, 66.000f}, {-120.000f, 12.000f, 66.000f}, {-120.000f, 0.000f, 66.000f} },
+ },
+ { /* patch 14 */
+ { { -60.000f, 0.000f, 84.000f}, { -60.000f, -12.000f, 84.000f}, { -64.000f, -12.000f, 75.000f}, { -64.000f, 0.000f, 75.000f} },
+ { {-100.000f, 0.000f, 84.000f}, {-100.000f, -12.000f, 84.000f}, { -92.000f, -12.000f, 75.000f}, { -92.000f, 0.000f, 75.000f} },
+ { {-120.000f, 0.000f, 84.000f}, {-120.000f, -12.000f, 84.000f}, {-108.000f, -12.000f, 75.000f}, {-108.000f, 0.000f, 75.000f} },
+ { {-120.000f, 0.000f, 66.000f}, {-120.000f, -12.000f, 66.000f}, {-108.000f, -12.000f, 66.000f}, {-108.000f, 0.000f, 66.000f} },
+ },
+ { /* patch 15 */
+ { {-108.000f, 0.000f, 66.000f}, {-108.000f, 12.000f, 66.000f}, {-120.000f, 12.000f, 66.000f}, {-120.000f, 0.000f, 66.000f} },
+ { {-108.000f, 0.000f, 57.000f}, {-108.000f, 12.000f, 57.000f}, {-120.000f, 12.000f, 48.000f}, {-120.000f, 0.000f, 48.000f} },
+ { {-100.000f, 0.000f, 39.000f}, {-100.000f, 12.000f, 39.000f}, {-106.000f, 12.000f, 31.500f}, {-106.000f, 0.000f, 31.500f} },
+ { { -80.000f, 0.000f, 30.000f}, { -80.000f, 12.000f, 30.000f}, { -76.000f, 12.000f, 18.000f}, { -76.000f, 0.000f, 18.000f} },
+ },
+ { /* patch 16 */
+ { {-120.000f, 0.000f, 66.000f}, {-120.000f, -12.000f, 66.000f}, {-108.000f, -12.000f, 66.000f}, {-108.000f, 0.000f, 66.000f} },
+ { {-120.000f, 0.000f, 48.000f}, {-120.000f, -12.000f, 48.000f}, {-108.000f, -12.000f, 57.000f}, {-108.000f, 0.000f, 57.000f} },
+ { {-106.000f, 0.000f, 31.500f}, {-106.000f, -12.000f, 31.500f}, {-100.000f, -12.000f, 39.000f}, {-100.000f, 0.000f, 39.000f} },
+ { { -76.000f, 0.000f, 18.000f}, { -76.000f, -12.000f, 18.000f}, { -80.000f, -12.000f, 30.000f}, { -80.000f, 0.000f, 30.000f} },
+ },
+ { /* patch 17 */
+ { { 68.000f, 0.000f, 51.000f}, { 68.000f, 26.400f, 51.000f}, { 68.000f, 26.400f, 18.000f}, { 68.000f, 0.000f, 18.000f} },
+ { { 104.000f, 0.000f, 51.000f}, { 104.000f, 26.400f, 51.000f}, { 124.000f, 26.400f, 27.000f}, { 124.000f, 0.000f, 27.000f} },
+ { { 92.000f, 0.000f, 78.000f}, { 92.000f, 10.000f, 78.000f}, { 96.000f, 10.000f, 75.000f}, { 96.000f, 0.000f, 75.000f} },
+ { { 108.000f, 0.000f, 90.000f}, { 108.000f, 10.000f, 90.000f}, { 132.000f, 10.000f, 90.000f}, { 132.000f, 0.000f, 90.000f} },
+ },
+ { /* patch 18 */
+ { { 68.000f, 0.000f, 18.000f}, { 68.000f, -26.400f, 18.000f}, { 68.000f, -26.400f, 51.000f}, { 68.000f, 0.000f, 51.000f} },
+ { { 124.000f, 0.000f, 27.000f}, { 124.000f, -26.400f, 27.000f}, { 104.000f, -26.400f, 51.000f}, { 104.000f, 0.000f, 51.000f} },
+ { { 96.000f, 0.000f, 75.000f}, { 96.000f, -10.000f, 75.000f}, { 92.000f, -10.000f, 78.000f}, { 92.000f, 0.000f, 78.000f} },
+ { { 132.000f, 0.000f, 90.000f}, { 132.000f, -10.000f, 90.000f}, { 108.000f, -10.000f, 90.000f}, { 108.000f, 0.000f, 90.000f} },
+ },
+ { /* patch 19 */
+ { { 108.000f, 0.000f, 90.000f}, { 108.000f, 10.000f, 90.000f}, { 132.000f, 10.000f, 90.000f}, { 132.000f, 0.000f, 90.000f} },
+ { { 112.000f, 0.000f, 93.000f}, { 112.000f, 10.000f, 93.000f}, { 141.000f, 10.000f, 93.750f}, { 141.000f, 0.000f, 93.750f} },
+ { { 116.000f, 0.000f, 93.000f}, { 116.000f, 6.000f, 93.000f}, { 138.000f, 6.000f, 94.500f}, { 138.000f, 0.000f, 94.500f} },
+ { { 112.000f, 0.000f, 90.000f}, { 112.000f, 6.000f, 90.000f}, { 128.000f, 6.000f, 90.000f}, { 128.000f, 0.000f, 90.000f} },
+ },
+ { /* patch 20 */
+ { { 132.000f, 0.000f, 90.000f}, { 132.000f, -10.000f, 90.000f}, { 108.000f, -10.000f, 90.000f}, { 108.000f, 0.000f, 90.000f} },
+ { { 141.000f, 0.000f, 93.750f}, { 141.000f, -10.000f, 93.750f}, { 112.000f, -10.000f, 93.000f}, { 112.000f, 0.000f, 93.000f} },
+ { { 138.000f, 0.000f, 94.500f}, { 138.000f, -6.000f, 94.500f}, { 116.000f, -6.000f, 93.000f}, { 116.000f, 0.000f, 93.000f} },
+ { { 128.000f, 0.000f, 90.000f}, { 128.000f, -6.000f, 90.000f}, { 112.000f, -6.000f, 90.000f}, { 112.000f, 0.000f, 90.000f} },
+ },
+ { /* patch 21 */
+ { { 50.000f, 0.000f, 90.000f}, { 50.000f, 28.000f, 90.000f}, { 28.000f, 50.000f, 90.000f}, { 0.000f, 50.000f, 90.000f} },
+ { { 52.000f, 0.000f, 90.000f}, { 52.000f, 29.120f, 90.000f}, { 29.120f, 52.000f, 90.000f}, { 0.000f, 52.000f, 90.000f} },
+ { { 54.000f, 0.000f, 90.000f}, { 54.000f, 30.240f, 90.000f}, { 30.240f, 54.000f, 90.000f}, { 0.000f, 54.000f, 90.000f} },
+ { { 56.000f, 0.000f, 90.000f}, { 56.000f, 31.360f, 90.000f}, { 31.360f, 56.000f, 90.000f}, { 0.000f, 56.000f, 90.000f} },
+ },
+ { /* patch 22 */
+ { { 0.000f, 50.000f, 90.000f}, { -28.000f, 50.000f, 90.000f}, { -50.000f, 28.000f, 90.000f}, { -50.000f, 0.000f, 90.000f} },
+ { { 0.000f, 52.000f, 90.000f}, { -29.120f, 52.000f, 90.000f}, { -52.000f, 29.120f, 90.000f}, { -52.000f, 0.000f, 90.000f} },
+ { { 0.000f, 54.000f, 90.000f}, { -30.240f, 54.000f, 90.000f}, { -54.000f, 30.240f, 90.000f}, { -54.000f, 0.000f, 90.000f} },
+ { { 0.000f, 56.000f, 90.000f}, { -31.360f, 56.000f, 90.000f}, { -56.000f, 31.360f, 90.000f}, { -56.000f, 0.000f, 90.000f} },
+ },
+ { /* patch 23 */
+ { { -50.000f, 0.000f, 90.000f}, { -50.000f, -28.000f, 90.000f}, { -28.000f, -50.000f, 90.000f}, { 0.000f, -50.000f, 90.000f} },
+ { { -52.000f, 0.000f, 90.000f}, { -52.000f, -29.120f, 90.000f}, { -29.120f, -52.000f, 90.000f}, { 0.000f, -52.000f, 90.000f} },
+ { { -54.000f, 0.000f, 90.000f}, { -54.000f, -30.240f, 90.000f}, { -30.240f, -54.000f, 90.000f}, { 0.000f, -54.000f, 90.000f} },
+ { { -56.000f, 0.000f, 90.000f}, { -56.000f, -31.360f, 90.000f}, { -31.360f, -56.000f, 90.000f}, { 0.000f, -56.000f, 90.000f} },
+ },
+ { /* patch 24 */
+ { { 0.000f, -50.000f, 90.000f}, { 28.000f, -50.000f, 90.000f}, { 50.000f, -28.000f, 90.000f}, { 50.000f, 0.000f, 90.000f} },
+ { { 0.000f, -52.000f, 90.000f}, { 29.120f, -52.000f, 90.000f}, { 52.000f, -29.120f, 90.000f}, { 52.000f, 0.000f, 90.000f} },
+ { { 0.000f, -54.000f, 90.000f}, { 30.240f, -54.000f, 90.000f}, { 54.000f, -30.240f, 90.000f}, { 54.000f, 0.000f, 90.000f} },
+ { { 0.000f, -56.000f, 90.000f}, { 31.360f, -56.000f, 90.000f}, { 56.000f, -31.360f, 90.000f}, { 56.000f, 0.000f, 90.000f} },
+ },
+ { /* patch 25 */
+ { { 8.000f, 0.000f, 102.000f}, { 8.000f, 4.480f, 102.000f}, { 4.480f, 8.000f, 102.000f}, { 0.000f, 8.000f, 102.000f} },
+ { { 16.000f, 0.000f, 96.000f}, { 16.000f, 8.960f, 96.000f}, { 8.960f, 16.000f, 96.000f}, { 0.000f, 16.000f, 96.000f} },
+ { { 52.000f, 0.000f, 96.000f}, { 52.000f, 29.120f, 96.000f}, { 29.120f, 52.000f, 96.000f}, { 0.000f, 52.000f, 96.000f} },
+ { { 52.000f, 0.000f, 90.000f}, { 52.000f, 29.120f, 90.000f}, { 29.120f, 52.000f, 90.000f}, { 0.000f, 52.000f, 90.000f} },
+ },
+ { /* patch 26 */
+ { { 0.000f, 8.000f, 102.000f}, { -4.480f, 8.000f, 102.000f}, { -8.000f, 4.480f, 102.000f}, { -8.000f, 0.000f, 102.000f} },
+ { { 0.000f, 16.000f, 96.000f}, { -8.960f, 16.000f, 96.000f}, { -16.000f, 8.960f, 96.000f}, { -16.000f, 0.000f, 96.000f} },
+ { { 0.000f, 52.000f, 96.000f}, { -29.120f, 52.000f, 96.000f}, { -52.000f, 29.120f, 96.000f}, { -52.000f, 0.000f, 96.000f} },
+ { { 0.000f, 52.000f, 90.000f}, { -29.120f, 52.000f, 90.000f}, { -52.000f, 29.120f, 90.000f}, { -52.000f, 0.000f, 90.000f} },
+ },
+ { /* patch 27 */
+ { { -8.000f, 0.000f, 102.000f}, { -8.000f, -4.480f, 102.000f}, { -4.480f, -8.000f, 102.000f}, { 0.000f, -8.000f, 102.000f} },
+ { { -16.000f, 0.000f, 96.000f}, { -16.000f, -8.960f, 96.000f}, { -8.960f, -16.000f, 96.000f}, { 0.000f, -16.000f, 96.000f} },
+ { { -52.000f, 0.000f, 96.000f}, { -52.000f, -29.120f, 96.000f}, { -29.120f, -52.000f, 96.000f}, { 0.000f, -52.000f, 96.000f} },
+ { { -52.000f, 0.000f, 90.000f}, { -52.000f, -29.120f, 90.000f}, { -29.120f, -52.000f, 90.000f}, { 0.000f, -52.000f, 90.000f} },
+ },
+ { /* patch 28 */
+ { { 0.000f, -8.000f, 102.000f}, { 4.480f, -8.000f, 102.000f}, { 8.000f, -4.480f, 102.000f}, { 8.000f, 0.000f, 102.000f} },
+ { { 0.000f, -16.000f, 96.000f}, { 8.960f, -16.000f, 96.000f}, { 16.000f, -8.960f, 96.000f}, { 16.000f, 0.000f, 96.000f} },
+ { { 0.000f, -52.000f, 96.000f}, { 29.120f, -52.000f, 96.000f}, { 52.000f, -29.120f, 96.000f}, { 52.000f, 0.000f, 96.000f} },
+ { { 0.000f, -52.000f, 90.000f}, { 29.120f, -52.000f, 90.000f}, { 52.000f, -29.120f, 90.000f}, { 52.000f, 0.000f, 90.000f} },
+ },
+ { /* patch 29 */
+ { { 0.000f, 0.000f, 120.000f}, { 0.000f, 0.000f, 120.000f}, { 0.000f, 0.000f, 120.000f}, { 0.000f, 0.000f, 120.000f} },
+ { { 32.000f, 0.000f, 120.000f}, { 32.000f, 18.000f, 120.000f}, { 18.000f, 32.000f, 120.000f}, { 0.000f, 32.000f, 120.000f} },
+ { { 0.000f, 0.000f, 108.000f}, { 0.000f, 0.000f, 108.000f}, { 0.000f, 0.000f, 108.000f}, { 0.000f, 0.000f, 108.000f} },
+ { { 8.000f, 0.000f, 102.000f}, { 8.000f, 4.480f, 102.000f}, { 4.480f, 8.000f, 102.000f}, { 0.000f, 8.000f, 102.000f} },
+ },
+ { /* patch 30 */
+ { { 0.000f, 0.000f, 120.000f}, { 0.000f, 0.000f, 120.000f}, { 0.000f, 0.000f, 120.000f}, { 0.000f, 0.000f, 120.000f} },
+ { { 0.000f, 32.000f, 120.000f}, { -18.000f, 32.000f, 120.000f}, { -32.000f, 18.000f, 120.000f}, { -32.000f, 0.000f, 120.000f} },
+ { { 0.000f, 0.000f, 108.000f}, { 0.000f, 0.000f, 108.000f}, { 0.000f, 0.000f, 108.000f}, { 0.000f, 0.000f, 108.000f} },
+ { { 0.000f, 8.000f, 102.000f}, { -4.480f, 8.000f, 102.000f}, { -8.000f, 4.480f, 102.000f}, { -8.000f, 0.000f, 102.000f} },
+ },
+ { /* patch 31 */
+ { { 0.000f, 0.000f, 120.000f}, { 0.000f, 0.000f, 120.000f}, { 0.000f, 0.000f, 120.000f}, { 0.000f, 0.000f, 120.000f} },
+ { { -32.000f, 0.000f, 120.000f}, { -32.000f, -18.000f, 120.000f}, { -18.000f, -32.000f, 120.000f}, { 0.000f, -32.000f, 120.000f} },
+ { { 0.000f, 0.000f, 108.000f}, { 0.000f, 0.000f, 108.000f}, { 0.000f, 0.000f, 108.000f}, { 0.000f, 0.000f, 108.000f} },
+ { { -8.000f, 0.000f, 102.000f}, { -8.000f, -4.480f, 102.000f}, { -4.480f, -8.000f, 102.000f}, { 0.000f, -8.000f, 102.000f} },
+ },
+ { /* patch 32 */
+ { { 0.000f, 0.000f, 120.000f}, { 0.000f, 0.000f, 120.000f}, { 0.000f, 0.000f, 120.000f}, { 0.000f, 0.000f, 120.000f} },
+ { { 0.000f, -32.000f, 120.000f}, { 18.000f, -32.000f, 120.000f}, { 32.000f, -18.000f, 120.000f}, { 32.000f, 0.000f, 120.000f} },
+ { { 0.000f, 0.000f, 108.000f}, { 0.000f, 0.000f, 108.000f}, { 0.000f, 0.000f, 108.000f}, { 0.000f, 0.000f, 108.000f} },
+ { { 0.000f, -8.000f, 102.000f}, { 4.480f, -8.000f, 102.000f}, { 8.000f, -4.480f, 102.000f}, { 8.000f, 0.000f, 102.000f} },
+ },