Catmull–Clark subdivision surface/C: Difference between revisions

Content added Content deleted
(performance fix)
(tweaks for better display)
Line 6: Line 6:
#include <stdarg.h>
#include <stdarg.h>
#include <math.h>
#include <math.h>
#include <unistd.h>


#include <GL/gl.h>
#include <GL/gl.h>
Line 28: Line 27:


int max_depth = 7;
int max_depth = 7;
int flat_shade = 0;
int show_parent = 1;
int show_parent = 1;
int wireframe_mode = 0;
int wireframe_mode = 1;
int face_mode = 1;
int model_idx = 0;
int model_idx = 0;
int interp_norm = 0;


#define new_struct(type, var) type var = calloc(sizeof(type##_t), 1)
#define new_struct(type, var) type var = calloc(sizeof(type##_t), 1)
Line 131: Line 131:


typedef struct vertex_t {
typedef struct vertex_t {
coord_t pos;
coord_t pos, avg_norm;
list e, f;
list e, f;
struct vertex_t * v_new;
struct vertex_t * v_new;
Line 260: Line 260:
#define tri_face(m, a, b, c) model_add_face(m, 3, a, b, c)
#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]))
#define face_v(f, i) ((vertex)(f->v->buf[i]))
int model_add_face_v(model m, list vl, int points_good)
int model_add_face_v(model m, list vl)
{
{
int i, j, n = len(vl);
int i, n = len(vl);
vertex v, v0, v1;
vertex v0, v1;
edge e;
edge e;
face f = face_new();
face f = face_new();
Line 270: Line 270:
for (i = 1; i <= n; i++, v0 = v1) {
for (i = 1; i <= n; i++, v0 = v1) {
v1 = elem(vl, i % len(vl));
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);
list_push(v1->f, f);


Line 286: Line 278:
list_push(f->v, v1);
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);
return list_push(m->f, f);
Line 310: Line 296:


va_end(ap);
va_end(ap);
x = model_add_face_v(m, lst, 1);
x = model_add_face_v(m, lst);
list_del(lst);
list_del(lst);
return x;
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 409: Line 423:
}
}
}
}

model_norms(nm);
return nm;
return nm;
}
}
Line 442: Line 458:
tri_face(m, 2, 11, 12);
tri_face(m, 2, 11, 12);
tri_face(m, 3, 12, 13);
tri_face(m, 3, 12, 13);
//tri_face(m, 4, 13, 14);
tri_face(m, 4, 13, 14);


tri_face(m, 0, 10, 5);
tri_face(m, 0, 10, 5);
Line 455: Line 471:
tri_face(m, 0, 9, 14);
tri_face(m, 0, 9, 14);


model_add_face(m, 5, 14, 13, 12, 11, 10);
//model_add_face(m, 5, 14, 13, 12, 11, 10);
//model_add_face(m, 5, 5, 6, 7, 8, 9);
//model_add_face(m, 5, 5, 6, 7, 8, 9);


model_norms(m);
return m;
return m;
}
}
Line 493: Line 510:
quad_face(m, 15, 14, 6, 7);
quad_face(m, 15, 14, 6, 7);


model_norms(m);
return m;
return m;
}
}
Line 512: Line 530:
quad_face(m, 0, 2, 6, 4);
quad_face(m, 0, 2, 6, 4);
quad_face(m, 5, 7, 3, 1);
quad_face(m, 5, 7, 3, 1);

model_norms(m);
return m;
return m;
}

void draw_model(model m)
{
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 521: Line 558:


glDisable(GL_LIGHTING);
glDisable(GL_LIGHTING);

foreach(i, e, m->e) {
foreach(i, e, m->e) {
if (e->f->n != 2) glColor3fv(hole_color);
if (e->f->n != 2) glColor3fv(hole_color);
else glColor3fv(color);
else glColor3fv(color);


glBegin(GL_LINES);
glBegin(GL_LINE);
glVertex3fv(&(e->v[0]->pos.x));
glVertex3fv(&(e->v[0]->pos.x));
glVertex3fv(&(e->v[1]->pos.x));
glVertex3fv(&(e->v[1]->pos.x));
Line 535: Line 571:
void draw_faces(model m)
void draw_faces(model m)
{
{
int i, j;
face f;
vertex v;

glPushMatrix();
glPushMatrix();
glLoadIdentity();
glLoadIdentity();
Line 552: Line 584:
glPopMatrix();
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();
}
}
draw_model(m);
if (wireframe_mode)
glDisable(GL_POLYGON_OFFSET_FILL);
}
}


Line 606: Line 637:
return;
return;
case 'w':
case 'w':
wireframe_mode = !wireframe_mode;
wireframe_mode = (wireframe_mode + 1) % 3;
return;
return;
case 'l':
case 'l':
Line 628: Line 659:
return;
return;
case 's':
case 's':
interp_norm = !interp_norm;
if ((flat_shade = !flat_shade)) glShadeModel(GL_FLAT);
else glShadeModel(GL_SMOOTH);
break;
break;

case 'p':
case 'p':
show_parent = (show_parent + 1) % 3;
show_parent = (show_parent + 1) % 3;
Line 679: Line 708:


model m = elem(models, model_pos);
model m = elem(models, model_pos);
if (wireframe_mode) draw_faces(m);

if (wireframe_mode)
if (wireframe_mode < 2) draw_wireframe(m, color, hole);
draw_wireframe(m, color, hole);
else
draw_faces(m);


glFlush();
glFlush();