Catmull–Clark subdivision surface/C: Difference between revisions
Catmull–Clark subdivision surface/C (view source)
Revision as of 14:09, 1 September 2022
, 1 year agoFixed syntax highlighting.
(extremely long C code) |
m (Fixed syntax highlighting.) |
||
(5 intermediate revisions by 2 users not shown) | |||
Line 1:
{{libheader|GLUT}}
Full C code, OpenGL program. Looooong. Keybindings of interest: '<' and '>' for subdivision steps; 'w' toggles wireframe mode; arrow keys and space for rotation; 'm' for switching models; misc keys: p, l, a, z, s, p, q.
<syntaxhighlight lang="c">#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Line 6 ⟶ 7:
#include <stdarg.h>
#include <math.h>
#include <GL/gl.h>
Line 27:
GLfloat zpos = -6;
int max_depth =
int show_parent = 1;
int wireframe_mode =
int face_mode = 1;
int model_idx = 0;
int interp_norm = 0;
#define new_struct(type, var) type var = calloc(sizeof(type##_t), 1)
Line 131 ⟶ 132:
typedef struct vertex_t {
coord_t pos, avg_norm;
list e, f;
struct vertex_t * v_new;
Line 249 ⟶ 250:
int i;
edge e;
foreach(i, e,
if ((e->v[0] ==
return e;
}
Line 261:
#define tri_face(m, a, b, c) model_add_face(m, 3, a, b, c)
#define face_v(f, i) ((vertex)(f->v->buf[i]))
int model_add_face_v(model m, list vl
{
int i
vertex
edge e;
face f = face_new();
Line 271:
for (i = 1; i <= n; i++, v0 = v1) {
v1 = elem(vl, i % len(vl));
list_push(v1->f, f);
Line 287 ⟶ 279:
list_push(f->v, v1);
}
return list_push(m->f, f);
Line 311 ⟶ 297:
va_end(ap);
x = model_add_face_v(m, lst
list_del(lst);
return x;
}
void model_norms(model m)
{
int i, j, n;
face f;
vertex v, v0, v1;
coord_t d1, d2, norm;
foreach(j, f, m->f) {
n = len(f->v);
foreach(i, v, f->v) {
v0 = elem(f->v, i ? i - 1 : n - 1);
v1 = elem(f->v, (i + 1) % n);
vsub(&(v->pos), &(v0->pos), &d1);
vsub(&(v1->pos), &(v->pos), &d2);
vcross(&d1, &d2, &norm);
vadd(f->norm, norm);
}
if (i > 1) vnormalize(&f->norm);
}
foreach(i, v, m->v) {
foreach(j, f, v->f)
vadd(v->avg_norm, f->norm);
if (j > 1) vnormalize(&(v->avg_norm));
}
printf("New model: %d faces\n", len(m->f));
}
Line 410 ⟶ 424:
}
}
model_norms(nm);
return nm;
}
Line 423 ⟶ 439:
ang = i * 72;
rad = ang * 3.1415926 / 180;
v[i].x = 2.2 * cos(rad); v[i].
rad = (ang + 36) * 3.1415926 / 180;
v[i + 5].x = v[i + 10].x = cos(rad);
v[i + 5].
v[i + 5].
v[i + 10].
}
for (i = 0; i < 15; i++) model_add_vertex(m, v[i].x, v[i].y, v[i].z);
tri_face(m, 0,
tri_face(m, 1,
tri_face(m, 2,
tri_face(m, 3,
tri_face(m, 4,
tri_face(m, 0,
tri_face(m, 1,
tri_face(m, 2,
tri_face(m, 3,
tri_face(m, 0,
tri_face(m, 1,
tri_face(m, 1,
tri_face(m, 2,
tri_face(m, 2,
tri_face(m, 3,
tri_face(m, 3,
tri_face(m, 4,
tri_face(m, 4,
tri_face(m, 0,
//model_add_face(m, 5,
//model_add_face(m, 5,
model_norms(m);
return m;
}
Line 494 ⟶ 511:
quad_face(m, 15, 14, 6, 7);
model_norms(m);
return m;
}
Line 513 ⟶ 531:
quad_face(m, 0, 2, 6, 4);
quad_face(m, 5, 7, 3, 1);
model_norms(m);
return m;
}
void
{
int i, j;
face f;
vertex v;
foreach(i, f, m->f) {
glBegin(GL_POLYGON);
if (!interp_norm) glNormal3fv(&(f->norm.x));
foreach(j, v, f->v) {
if (interp_norm)
glNormal3fv(&(v->avg_norm.x));
glVertex3fv(&(v->pos.x));
}
glEnd();
}
}
Line 551 ⟶ 559:
glDisable(GL_LIGHTING);
foreach(i, e, m->e) {
if (e->f->n != 2) glColor3fv(hole_color);
Line 565 ⟶ 572:
void draw_faces(model m)
{
glPushMatrix();
glLoadIdentity();
glPopMatrix();
if (wireframe_mode) {
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(1.0, 1.0);
}
if (wireframe_mode)
glDisable(GL_POLYGON_OFFSET_FILL);
}
Line 637 ⟶ 638:
return;
case 'w':
wireframe_mode =
return;
case 'l':
Line 659 ⟶ 660:
return;
case 's':
interp_norm = !interp_norm;
break;
case 'p':
show_parent = (show_parent + 1) % 3;
Line 710 ⟶ 709:
model m = elem(models, model_pos);
if (wireframe_mode) draw_faces(m);
if (wireframe_mode < 2) draw_wireframe(m, color, hole);
glFlush();
glFinish();
glutSwapBuffers();
}
Line 733 ⟶ 729:
void init_gfx(int *c, char **v) {
glutInit(c, v);
glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE);
glutInitWindowSize(640, 480);
Line 767 ⟶ 763:
return 0;
}</
|