Catmull–Clark subdivision surface/C: Difference between revisions

m
Fixed 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; arrow keys and space for rotation; 'm' for switching models; misc keys: p, l, a, z, s, p, q.
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.
<lang c>#include <stdio.h>
<syntaxhighlight lang="c">#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Line 6 ⟶ 7:
#include <stdarg.h>
#include <math.h>
#include <unistd.h>
 
#include <GL/gl.h>
Line 27:
GLfloat zpos = -6;
 
int max_depth = 47;
int flat_shade = 0;
int show_parent = 1;
int wireframe_mode = 01;
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, mv1->e) {
if ((e->v[0] == v1v2 &&|| e->v[1] == v2) ||)
(e->v[0] == v2 && e->v[1] == v1) )
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 points_good)
{
int i, j, n = len(vl);
vertex v, v0, v1;
edge e;
face f = face_new();
Line 271:
for (i = 1; i <= n; i++, v0 = v1) {
v1 = elem(vl, i % len(vl));
 
if (!points_good) {
foreach(j, v, m->v)
if (v == v0) break;
if (j == len(m->v))
list_push(m->v, v0);
}
 
list_push(v1->f, f);
 
Line 287 ⟶ 279:
list_push(f->v, v1);
}
 
coord_t d1, d2;
vnormalize(vcross(
vsub(&(face_v(f, 1)->pos), &(face_v(f, 0)->pos), &d1),
vsub(&(face_v(f, 2)->pos), &(face_v(f, 1)->pos), &d2),
&(f->norm)));
 
return list_push(m->f, f);
Line 311 ⟶ 297:
 
va_end(ap);
x = model_add_face_v(m, lst, 1);
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].zy = 2.2 * sin(rad); v[i].yz = 0;
 
rad = (ang + 36) * 3.1415926 / 180;
v[i + 5].x = v[i + 10].x = cos(rad);
v[i + 5].zy = v[i + 10].zy = sin(rad);
v[i + 5].yz = .5;
v[i + 10].yz = -.5;
}
 
for (i = 0; i < 15; i++) model_add_vertex(m, v[i].x, v[i].y, v[i].z);
tri_face(m, 0, 95, 59);
tri_face(m, 1, 56, 65);
tri_face(m, 2, 67, 76);
tri_face(m, 3, 78, 87);
tri_face(m, 4, 89, 98);
 
tri_face(m, 0, 1014, 1410);
tri_face(m, 1, 1110, 1011);
tri_face(m, 2, 1211, 1112);
tri_face(m, 3, 1312, 1213);
//tri_face(m, 4, 1413, 1314);
 
tri_face(m, 0, 510, 10 5);
tri_face(m, 1, 10, 5, 10);
tri_face(m, 1, 611, 11 6);
tri_face(m, 2, 11, 6, 11);
tri_face(m, 2, 712, 12 7);
tri_face(m, 3, 12, 7, 12);
tri_face(m, 3, 813, 13 8);
tri_face(m, 4, 13, 8, 13);
tri_face(m, 4, 914, 14 9);
tri_face(m, 0, 14, 9, 14);
 
//model_add_face(m, 5, 1014, 1113, 12, 1311, 1410);
//model_add_face(m, 5, 95, 86, 7, 68, 59);
 
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 model_printdraw_model(model m)
{
int i, j;
face f;
vertex v;
edge e;
 
printf("faces:\n");
foreach(i, f, m->f) {
glBegin(GL_POLYGON);
printf("%d: %g %g %g\n", len(f->e), f->norm.x, f->norm.y, f->norm.z);
if (!interp_norm) glNormal3fv(&(f->norm.x));
 
foreach(j, v, f->v) {
if (interp_norm)
printf("\t(%3g, %3g, %3g)\n", v->pos.x, v->pos.y, v->pos.z);
glNormal3fv(&(v->avg_norm.x));
printf("\n");
glVertex3fv(&(v->pos.x));
}
glEnd();
}
printf("edges:\n");
foreach(i, e, m->e) {
v = e->v[0];
printf("%d \t(%3g, %3g, %3g)", i, v->pos.x, v->pos.y, v->pos.z);
v = e->v[1];
printf("\t(%3g, %3g, %3g)\n", v->pos.x, v->pos.y, v->pos.z);
}
 
printf("\n%d vertices:", len(m->v));
foreach(i, v, m->v)
printf(" (%g, %g, %g)", v->pos.x, v->pos.y, v->pos.z);
printf("\n");
}
 
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)
{
int i, j;
face f;
vertex v;
 
glPushMatrix();
glLoadIdentity();
glEnable(GL_LIGHTING);
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse);
glLightfv(GL_LIGHT0, GL_POSITION, litepos);
glEnable(GL_LIGHT0);
 
glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse);
glLightfv(GL_LIGHT1, GL_POSITION, litepos2);
glEnable(GL_LIGHT1);
glPopMatrix();
 
if (wireframe_mode) {
foreach(i, f, m->f) {
glEnable(GL_POLYGON_OFFSET_FILL);
glBegin(GL_POLYGON);
glPolygonOffset(1.0, 1.0);
 
glNormal3fv(&(f->norm.x));
foreach(j, v, f->v) glVertex3fv(&(v->pos.x));
 
glEnd();
}
glPopAttribdraw_model(m);
if (wireframe_mode)
glDisable(GL_POLYGON_OFFSET_FILL);
}
 
Line 637 ⟶ 638:
return;
case 'w':
wireframe_mode = !(wireframe_mode + 1) % 3;
return;
case 'l':
Line 659 ⟶ 660:
return;
case 's':
interp_norm = !interp_norm;
if ((flat_shade = !flat_shade)) glShadeModel(GL_FLAT);
else glShadeModel(GL_SMOOTH);
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);
draw_wireframe(m, color, hole);
else
draw_faces(m);
 
glFlush();
glFinish();
glutSwapBuffers();
usleep(10000);
}
 
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;
}</langsyntaxhighlight>
9,476

edits