scenefile
changeset 3:b30f83409769
foo
author | John Tsiombikas <nuclear@mutantstargoat.com> |
---|---|
date | Sat, 21 Jan 2012 04:14:24 +0200 |
parents | c15992cedec9 |
children | d251485d33d8 |
files | scnviewgl/scnviewgl.c src/file_milk.c src/mesh.c src/mesh.h src/scene.c src/scene.h |
diffstat | 6 files changed, 473 insertions(+), 7 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/scnviewgl/scnviewgl.c Sat Jan 21 04:14:24 2012 +0200 1.3 @@ -0,0 +1,262 @@ 1.4 +#include <stdio.h> 1.5 +#include <assert.h> 1.6 + 1.7 +#ifndef __APPLE__ 1.8 +#include <GL/glut.h> 1.9 +#else 1.10 +#include <GLUT/glut.h> 1.11 +#endif 1.12 + 1.13 +#include "scene.h" 1.14 + 1.15 +void disp(void); 1.16 +void render_scene(struct scenefile *scn); 1.17 +void render_mesh(struct mesh *m); 1.18 +void reshape(int x, int y); 1.19 +void keyb(unsigned char key, int x, int y); 1.20 +void mouse(int bn, int state, int x, int y); 1.21 +void motion(int x, int y); 1.22 +void sball_motion(int x, int y, int z); 1.23 +void sball_rotate(int x, int y, int z); 1.24 +void sball_button(int bn, int state); 1.25 +int parse_args(int argc, char **argv); 1.26 + 1.27 +struct scenefile *scn; 1.28 +float cam_theta, cam_phi, cam_dist = 10; 1.29 + 1.30 +int main(int argc, char **argv) 1.31 +{ 1.32 + float ldir[] = {-1, 1, 1, 0}; 1.33 + 1.34 + glutInitWindowSize(800, 600); 1.35 + glutInit(&argc, argv); 1.36 + 1.37 + if(parse_args(argc, argv) == -1) { 1.38 + return 1; 1.39 + } 1.40 + 1.41 + glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE); 1.42 + glutCreateWindow("OpenGL Scene Viewer"); 1.43 + 1.44 + glutDisplayFunc(disp); 1.45 + glutReshapeFunc(reshape); 1.46 + glutKeyboardFunc(keyb); 1.47 + glutMouseFunc(mouse); 1.48 + glutMotionFunc(motion); 1.49 + glutSpaceballMotionFunc(sball_motion); 1.50 + glutSpaceballRotateFunc(sball_rotate); 1.51 + glutSpaceballButtonFunc(sball_button); 1.52 + 1.53 + glEnable(GL_DEPTH_TEST); 1.54 + glEnable(GL_CULL_FACE); 1.55 + glEnable(GL_LIGHTING); 1.56 + glEnable(GL_LIGHT0); 1.57 + glLightfv(GL_LIGHT0, GL_POSITION, ldir); 1.58 + 1.59 + glutMainLoop(); 1.60 + return 0; 1.61 +} 1.62 + 1.63 + 1.64 +void disp(void) 1.65 +{ 1.66 + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 1.67 + 1.68 + glMatrixMode(GL_MODELVIEW); 1.69 + glLoadIdentity(); 1.70 + glRotatef(cam_theta, 0, 1, 0); 1.71 + glRotatef(cam_phi, 1, 0, 0); 1.72 + glTranslatef(0, 0, -cam_dist); 1.73 + 1.74 + render_scene(scn); 1.75 + 1.76 + glutSwapBuffers(); 1.77 +} 1.78 + 1.79 +void render_scene(struct scenefile *scn) 1.80 +{ 1.81 + int i, num = scnfile_count(scn); 1.82 + 1.83 + for(i=0; i<num; i++) { 1.84 + struct mesh *m = scnfile_mesh(scn, i); 1.85 + render_mesh(m); 1.86 + } 1.87 +} 1.88 + 1.89 +void render_mesh(struct mesh *m) 1.90 +{ 1.91 + int i, j, poly_verts, npoly; 1.92 + int vloc, nloc, tloc; 1.93 + int *vidx, *nidx, *tidx; 1.94 + 1.95 + npoly = mesh_poly_count(m); 1.96 + poly_verts = mesh_poly_type(m); 1.97 + 1.98 + if((vloc = mesh_find_attrib(m, "vertex")) == -1) { 1.99 + return; 1.100 + } 1.101 + vidx = mesh_poly_data(m, vloc); 1.102 + 1.103 + if((nloc = mesh_find_attrib(m, "normal")) != -1) { 1.104 + nidx = mesh_poly_data(m, nloc); 1.105 + } 1.106 + 1.107 + if((tloc = mesh_find_attrib(m, "texture")) != -1) { 1.108 + tidx = mesh_poly_data(m, tloc); 1.109 + } 1.110 + 1.111 + glBegin(poly_verts == 3 ? GL_TRIANGLES : GL_QUADS); 1.112 + for(i=0; i<npoly; i++) { 1.113 + for(j=0; j<poly_verts; j++) { 1.114 + void *ptr; 1.115 + if(nloc >= 0) { 1.116 + ptr = mesh_attrib_elem(m, nloc, *nidx++); 1.117 + assert(ptr); 1.118 + glNormal3fv(ptr); 1.119 + } 1.120 + if(tloc >= 0) { 1.121 + ptr = mesh_attrib_elem(m, tloc, *tidx++); 1.122 + assert(ptr); 1.123 + glTexCoord2fv(ptr); 1.124 + } 1.125 + ptr = mesh_attrib_elem(m, vloc, *vidx++); 1.126 + assert(ptr); 1.127 + glVertex3fv(ptr); 1.128 + } 1.129 + } 1.130 + glEnd(); 1.131 +} 1.132 + 1.133 + 1.134 +void reshape(int x, int y) 1.135 +{ 1.136 + glViewport(0, 0, x, y); 1.137 + 1.138 + glMatrixMode(GL_PROJECTION); 1.139 + glLoadIdentity(); 1.140 + gluPerspective(45.0, (float)x / (float)y, 0.5, 1000.0); 1.141 +} 1.142 + 1.143 +void keyb(unsigned char key, int x, int y) 1.144 +{ 1.145 + switch(key) { 1.146 + case 27: 1.147 + case 'q': 1.148 + exit(0); 1.149 + 1.150 + case 'c': 1.151 + { 1.152 + static int flip; 1.153 + if(++flip & 1) { 1.154 + glFrontFace(GL_CW); 1.155 + } else { 1.156 + glFrontFace(GL_CCW); 1.157 + } 1.158 + } 1.159 + break; 1.160 + 1.161 + case 'l': 1.162 + { 1.163 + static int lton = 1; 1.164 + if(++lton & 1) { 1.165 + glEnable(GL_LIGHTING); 1.166 + } else { 1.167 + glDisable(GL_LIGHTING); 1.168 + } 1.169 + } 1.170 + break; 1.171 + 1.172 + case 'w': 1.173 + { 1.174 + static int wire; 1.175 + if(++wire & 1) { 1.176 + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); 1.177 + } else { 1.178 + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 1.179 + } 1.180 + } 1.181 + break; 1.182 + 1.183 + default: 1.184 + break; 1.185 + } 1.186 +} 1.187 + 1.188 +int prev_x, prev_y; 1.189 +int bnstate[32]; 1.190 + 1.191 +void mouse(int bn, int state, int x, int y) 1.192 +{ 1.193 + bnstate[bn] = state == GLUT_DOWN ? 1 : 0; 1.194 + prev_x = x; 1.195 + prev_y = y; 1.196 +} 1.197 + 1.198 +void motion(int x, int y) 1.199 +{ 1.200 + int dx = x - prev_x; 1.201 + int dy = y - prev_y; 1.202 + prev_x = x; 1.203 + prev_y = y; 1.204 + 1.205 + if(bnstate[1]) { 1.206 + cam_theta += (float)dx; 1.207 + cam_phi += (float)dy; 1.208 + 1.209 + if(cam_phi < -90) 1.210 + cam_phi = -90; 1.211 + if(cam_phi > 90) 1.212 + cam_phi = 90; 1.213 + } 1.214 + if(bnstate[3]) { 1.215 + cam_dist += (float)dy * 0.1; 1.216 + 1.217 + if(cam_dist < 0) 1.218 + cam_dist = 0; 1.219 + } 1.220 +} 1.221 + 1.222 +void sball_motion(int x, int y, int z) 1.223 +{ 1.224 +} 1.225 + 1.226 +void sball_rotate(int x, int y, int z) 1.227 +{ 1.228 +} 1.229 + 1.230 +void sball_button(int bn, int state) 1.231 +{ 1.232 +} 1.233 + 1.234 +int parse_args(int argc, char **argv) 1.235 +{ 1.236 + int i, loaded_something = 0; 1.237 + 1.238 + for(i=0; i<argc; i++) { 1.239 + if(argv[i][0] == '-') { 1.240 + if(argv[i][2] != 0) { 1.241 + goto inval; 1.242 + } 1.243 + switch(argv[i][1]) { 1.244 + default: 1.245 + goto inval; 1.246 + } 1.247 + } else { 1.248 + if(scnfile_load(scn, argv[i])) { 1.249 + fprintf(stderr, "failed to load %s\n", argv[i]); 1.250 + return -1; 1.251 + } 1.252 + loaded_something = 1; 1.253 + } 1.254 + } 1.255 + 1.256 + if(!loaded_something) { 1.257 + fprintf(stderr, "pass the filename(s) of the scene(s) you wish to view\n"); 1.258 + return -1; 1.259 + } 1.260 + return 0; 1.261 + 1.262 +inval: 1.263 + fprintf(stderr, "invalid argument: %s\n", argv[i]); 1.264 + return -1; 1.265 +}
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/src/file_milk.c Sat Jan 21 04:14:24 2012 +0200 2.3 @@ -0,0 +1,32 @@ 2.4 +#include <stdio.h> 2.5 +#include <stdlib.h> 2.6 +#include "scene.h" 2.7 + 2.8 +#ifdef __GNUC__ 2.9 +#define PACKED __attribute__((packed)) 2.10 +#endif 2.11 + 2.12 + 2.13 +struct header { 2.14 + char magic[10]; 2.15 + int fmt_ver; 2.16 +} PACKED; 2.17 + 2.18 +struct vertex { 2.19 + char flags; 2.20 + float pos[3]; 2.21 + char bone_id; /* -1 means no bone */ 2.22 + char ref_count; 2.23 +} PACKED; 2.24 + 2.25 +struct triangle { 2.26 + uint16_t flags; 2.27 + uint16_t v[3]; 2.28 + float vnorm[3][3]; 2.29 + float s[3]; 2.30 + float t[3]; 2.31 + unsigned char smoothing_group; 2.32 + unsigned char group_idx; 2.33 +} PACKED; 2.34 + 2.35 +
3.1 --- a/src/mesh.c Sun Jan 15 08:32:19 2012 +0200 3.2 +++ b/src/mesh.c Sat Jan 21 04:14:24 2012 +0200 3.3 @@ -94,6 +94,14 @@ 3.4 return ma->elem_sz; 3.5 } 3.6 3.7 +void *vattr_elem(struct mesh_vertattr *ma, int elem) 3.8 +{ 3.9 + int count = dynarr_size(ma->data); 3.10 + if(elem >= count) { 3.11 + return 0; 3.12 + } 3.13 + return (char*)ma->data + elem * ma->elem_sz; 3.14 +} 3.15 3.16 3.17 /* -------- mesh -------- */ 3.18 @@ -116,7 +124,7 @@ 3.19 3.20 void mesh_destroy(struct mesh *m) 3.21 { 3.22 - int i, nattr = mesh_attr_count(m); 3.23 + int i, nattr = mesh_num_attribs(m); 3.24 3.25 for(i=0; i<nattr; i++) { 3.26 vattr_destroy(m->attr + i); 3.27 @@ -148,6 +156,11 @@ 3.28 return m->name ? m->name : "<unnamed mesh>"; 3.29 } 3.30 3.31 +int mesh_poly_type(struct mesh *m) 3.32 +{ 3.33 + return m->poly_nverts; 3.34 +} 3.35 + 3.36 int mesh_add_attrib(struct mesh *m, struct mesh_vertattr *attr) 3.37 { 3.38 struct mesh_polyidx pidx; 3.39 @@ -171,9 +184,14 @@ 3.40 return 0; 3.41 } 3.42 3.43 +int mesh_num_attribs(struct mesh *m) 3.44 +{ 3.45 + return dynarr_size(m->attr); 3.46 +} 3.47 + 3.48 int mesh_find_attrib(struct mesh *m, const char *name) 3.49 { 3.50 - int i, nattr = mesh_attr_count(m); 3.51 + int i, nattr = mesh_num_attribs(m); 3.52 3.53 for(i=0; i<nattr; i++) { 3.54 if(m->attr[i].name && strcmp(m->attr[i].name, name) == 0) { 3.55 @@ -183,14 +201,30 @@ 3.56 return -1; 3.57 } 3.58 3.59 -int mesh_attr_count(struct mesh *m) 3.60 +struct mesh_vertattr *mesh_attrib(struct mesh *m, int loc) 3.61 { 3.62 - return dynarr_size(m->attr); 3.63 + return loc >= 0 ? m->attr + loc : 0; 3.64 +} 3.65 + 3.66 +void *mesh_attrib_data(struct mesh *m, int loc) 3.67 +{ 3.68 + return loc >= 0 ? m->attr[loc].data : 0; 3.69 +} 3.70 + 3.71 +int *mesh_poly_data(struct mesh *m, int loc) 3.72 +{ 3.73 + return loc >= 0 ? m->polyidx[loc].data : 0; 3.74 +} 3.75 + 3.76 + 3.77 +int mesh_attrib_count(struct mesh *m, int loc) 3.78 +{ 3.79 + return loc >= 0 ? vattr_count(m->attr + loc) : 0; 3.80 } 3.81 3.82 int mesh_poly_count(struct mesh *m) 3.83 { 3.84 - int i, nattr = mesh_attr_count(m); 3.85 + int i, nattr = mesh_num_attribs(m); 3.86 3.87 for(i=0; i<nattr; i++) { 3.88 int count = dynarr_empty(m->polyidx[i].data); 3.89 @@ -201,9 +235,19 @@ 3.90 return 0; 3.91 } 3.92 3.93 +void *mesh_attrib_elem(struct mesh *m, int loc, int elem) 3.94 +{ 3.95 + return loc >= 0 ? vattr_elem(m->attr + loc, elem) : 0; 3.96 +} 3.97 + 3.98 +int mesh_attrib_elem_size(struct mesh *m, int loc) 3.99 +{ 3.100 + return loc >= 0 ? m->attr[loc].elem_sz : 0; 3.101 +} 3.102 + 3.103 int mesh_add_polyref(struct mesh *m, int attr_loc, ...) 3.104 { 3.105 - int i, nattr = mesh_attr_count(m); 3.106 + int i, nattr = mesh_num_attribs(m); 3.107 int *poly = alloca(m->poly_nverts * sizeof *poly); 3.108 va_list ap; 3.109 void *tmp;
4.1 --- a/src/mesh.h Sun Jan 15 08:32:19 2012 +0200 4.2 +++ b/src/mesh.h Sat Jan 21 04:14:24 2012 +0200 4.3 @@ -22,6 +22,7 @@ 4.4 void *vattr_pointer(struct mesh_vertattr *ma); 4.5 int vattr_count(struct mesh_vertattr *ma); 4.6 int vattr_elem_size(struct mesh_vertattr *ma); 4.7 +void *vattr_elem(struct mesh_vertattr *ma, int elem); 4.8 4.9 /* --- mesh --- */ 4.10 4.11 @@ -31,12 +32,23 @@ 4.12 int mesh_set_name(struct mesh *m, const char *name); 4.13 const char *mesh_get_name(struct mesh *m); 4.14 4.15 +/* 1 - points, 2 - lines, 3 - triangles, 4 - quads */ 4.16 +int mesh_poly_type(struct mesh *m); 4.17 + 4.18 int mesh_add_attrib(struct mesh *m, struct mesh_vertattr *attr); 4.19 +int mesh_num_attribs(struct mesh *m); 4.20 int mesh_find_attrib(struct mesh *m, const char *name); 4.21 4.22 -int mesh_attr_count(struct mesh *m); 4.23 +struct mesh_vertattr *mesh_attrib(struct mesh *m, int loc); 4.24 +void *mesh_attrib_data(struct mesh *m, int loc); 4.25 +int *mesh_poly_data(struct mesh *m, int loc); 4.26 + 4.27 +int mesh_attrib_count(struct mesh *m, int loc); 4.28 int mesh_poly_count(struct mesh *m); 4.29 4.30 +void *mesh_attrib_elem(struct mesh *m, int loc, int elem); 4.31 +int mesh_attrib_elem_size(struct mesh *m, int loc); 4.32 + 4.33 /* the variable arguments correspond to the N indices of the N-gon 4.34 * for this particular vertex attribute (attr_loc, retrieved by 4.35 * mesh_find_attrib)
5.1 --- a/src/scene.c Sun Jan 15 08:32:19 2012 +0200 5.2 +++ b/src/scene.c Sat Jan 21 04:14:24 2012 +0200 5.3 @@ -1,5 +1,7 @@ 5.4 +#include <stdio.h> 5.5 #include <stdlib.h> 5.6 #include <string.h> 5.7 +#include <errno.h> 5.8 #include "scene.h" 5.9 #include "dynarr.h" 5.10 5.11 @@ -7,6 +9,19 @@ 5.12 struct mesh **mesh; 5.13 }; 5.14 5.15 +struct scnfile_io { 5.16 + void *uptr; /* user-data */ 5.17 + 5.18 + size_t (*read)(void *buf, size_t bytes, void *uptr); 5.19 + size_t (*write)(void *buf, size_t bytes, void *uptr); 5.20 + long (*seek)(long offs, int whence, void *uptr); 5.21 +}; 5.22 + 5.23 +static size_t def_read(void *buf, size_t bytes, void *uptr); 5.24 +static size_t def_write(void *buf, size_t bytes, void *uptr); 5.25 +static long def_seek(long offset, int whence, void *uptr); 5.26 + 5.27 + 5.28 int scnfile_init(struct scenefile *scn) 5.29 { 5.30 if(!(scn->mesh = dynarr_alloc(0, sizeof *scn->mesh))) { 5.31 @@ -59,6 +74,27 @@ 5.32 5.33 int scnfile_load(struct scenefile *scn, const char *fname) 5.34 { 5.35 + FILE *fp; 5.36 + int res; 5.37 + 5.38 + if(!(fp = fopen(fname, "rb"))) { 5.39 + fprintf(stderr, "scenefile: failed to load: %s: %s\n", fname, strerror(errno)); 5.40 + return -1; 5.41 + } 5.42 + res = scnfile_read_file(scn, fp); 5.43 + fclose(fp); 5.44 + return res; 5.45 +} 5.46 + 5.47 +int scnfile_read_file(struct scenefile *scn, FILE *fp) 5.48 +{ 5.49 + struct scnfile_io io = {0, def_read, def_write, def_seek}; 5.50 + io.uptr = fp; 5.51 + return scnfile_read(scn, &io); 5.52 +} 5.53 + 5.54 +int scnfile_read(struct scenefile *scn, struct scnfile_io *io) 5.55 +{ 5.56 return -1; /* TODO */ 5.57 } 5.58 5.59 @@ -86,3 +122,44 @@ 5.60 { 5.61 return dynarr_size(scn->mesh); 5.62 } 5.63 + 5.64 + 5.65 +void scnfile_io_user_data(struct scnfile_io *io, void *uptr) 5.66 +{ 5.67 + io->uptr = uptr; 5.68 +} 5.69 + 5.70 +void scnfile_io_read_func(struct scnfile_io *io, size_t (*read)(void*, size_t, void*)) 5.71 +{ 5.72 + io->read = read; 5.73 +} 5.74 + 5.75 +void scnfile_io_write_func(struct scnfile_io *io, size_t (*write)(void*, size_t, void*)) 5.76 +{ 5.77 + io->write = write; 5.78 +} 5.79 + 5.80 +void scnfile_io_seek_func(struct scnfile_io *io, long (*seek)(long, int, void*)) 5.81 +{ 5.82 + io->seek = seek; 5.83 +} 5.84 + 5.85 + 5.86 +static size_t def_read(void *buf, size_t bytes, void *uptr) 5.87 +{ 5.88 + return uptr ? fread(buf, 1, bytes, uptr) : 0; 5.89 +} 5.90 + 5.91 +static size_t def_write(void *buf, size_t bytes, void *uptr) 5.92 +{ 5.93 + return uptr ? fwrite(buf, 1, bytes, uptr) : 0; 5.94 +} 5.95 + 5.96 +static long def_seek(long offset, int whence, void *uptr) 5.97 +{ 5.98 + if(!uptr || fseek(uptr, offset, whence) == -1) { 5.99 + return -1; 5.100 + } 5.101 + return ftell(uptr); 5.102 +} 5.103 +
6.1 --- a/src/scene.h Sun Jan 15 08:32:19 2012 +0200 6.2 +++ b/src/scene.h Sat Jan 21 04:14:24 2012 +0200 6.3 @@ -4,6 +4,7 @@ 6.4 #include "mesh.h" 6.5 6.6 struct scenefile; 6.7 +struct scnfile_io; 6.8 6.9 #ifdef __cplusplus 6.10 extern "C" { 6.11 @@ -20,11 +21,49 @@ 6.12 6.13 6.14 int scnfile_load(struct scenefile *scn, const char *fname); 6.15 +int scnfile_read_file(struct scenefile *scn, FILE *fp); 6.16 +int scnfile_read(struct scenefile *scn, struct scnfile_io *io); 6.17 6.18 int scnfile_find_mesh(struct scenefile *scn, const char *fname); 6.19 struct mesh *scnfile_mesh(struct scenefile *scn, int idx); 6.20 int scnfile_count(struct scenefile *scn); 6.21 6.22 + 6.23 +/* These functions can be used to fill an scnfile_io struct before it's passed to 6.24 + * one of the user-defined i/o image reading/writing functions (scnfile_read/scnfile_write). 6.25 + * 6.26 + * User-defined i/o functions: 6.27 + * 6.28 + * - size_t read_func(void *buffer, size_t bytes, void *user_ptr) 6.29 + * Must try to fill the buffer with the specified number of bytes, and return 6.30 + * the number of bytes actually read. 6.31 + * 6.32 + * - size_t write_func(void *buffer, size_t bytes, void *user_ptr) 6.33 + * Must write the specified number of bytes from the supplied buffer and return 6.34 + * the number of bytes actually written. 6.35 + * 6.36 + * - long seek_func(long offset, int whence, void *user_ptr) 6.37 + * Must seek offset bytes from: the beginning of the file if whence is SEEK_SET, 6.38 + * the current position if whence is SEEK_CUR, or the end of the file if whence is 6.39 + * SEEK_END, and return the resulting file offset from the beginning of the file. 6.40 + * (i.e. seek_func(0, SEEK_CUR, user_ptr); must be equivalent to an ftell). 6.41 + * 6.42 + * All three functions get the user-data pointer set through scnfile_io_set_user_data 6.43 + * as their last argument. 6.44 + * 6.45 + * Note: obviously you don't need to set a write function if you're only going 6.46 + * to call scnfile_read, or the read and seek function if you're only going to call 6.47 + * scnfile_write. 6.48 + * 6.49 + * Note: if the user-supplied write function is buffered, make sure to flush 6.50 + * (or close the file) after scnfile_write returns. 6.51 + */ 6.52 +void scnfile_io_user_data(struct scnfile_io *io, void *uptr); 6.53 +void scnfile_io_read_func(struct scnfile_io *io, size_t (*read)(void*, size_t, void*)); 6.54 +void scnfile_io_write_func(struct scnfile_io *io, size_t (*write)(void*, size_t, void*)); 6.55 +void scnfile_io_seek_func(struct scnfile_io *io, long (*seek)(long, int, void*)); 6.56 + 6.57 + 6.58 #ifdef __cplusplus 6.59 } 6.60 #endif