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 show_parent = 1; |
int show_parent = 1; |
||
int wireframe_mode = |
int wireframe_mode = 1; |
||
int face_mode = 1; |
|||
int model_idx = 0; |
int model_idx = 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 model_add_face_v(model m, list vl) |
||
{ |
{ |
||
int i |
int i, n = len(vl); |
||
vertex |
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) { |
|||
⚫ | |||
if (v == v0) break; |
|||
⚫ | |||
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); |
||
} |
} |
||
⚫ | |||
vnormalize(vcross( |
|||
⚫ | |||
⚫ | |||
⚫ | |||
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 |
x = model_add_face_v(m, lst); |
||
list_del(lst); |
list_del(lst); |
||
return x; |
return x; |
||
} |
|||
void model_norms(model m) |
|||
{ |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
foreach(i, v, f->v) { |
|||
v0 = elem(f->v, i ? i - 1 : n - 1); |
|||
v1 = elem(f->v, (i + 1) % n); |
|||
⚫ | |||
⚫ | |||
vcross(&d1, &d2, &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, 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) { |
|||
⚫ | |||
⚫ | |||
⚫ | |||
if (interp_norm) |
|||
glNormal3fv(&(v->avg_norm.x)); |
|||
⚫ | |||
} |
|||
⚫ | |||
} |
|||
} |
} |
||
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( |
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) |
||
{ |
{ |
||
⚫ | |||
⚫ | |||
⚫ | |||
glPushMatrix(); |
glPushMatrix(); |
||
glLoadIdentity(); |
glLoadIdentity(); |
||
Line 552: | Line 584: | ||
glPopMatrix(); |
glPopMatrix(); |
||
if (wireframe_mode) { |
|||
⚫ | |||
glEnable(GL_POLYGON_OFFSET_FILL); |
|||
⚫ | |||
glPolygonOffset(1.0, 1.0); |
|||
⚫ | |||
⚫ | |||
⚫ | |||
} |
} |
||
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 + 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(); |