deepstone

annotate src/scene.c @ 16:cb676ff89e69

added missing cvec and scene files
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 29 Nov 2011 07:23:57 +0200
parents
children 1e9f0b3616fa
rev   line source
nuclear@16 1 #include <stdio.h>
nuclear@16 2 #include <stdlib.h>
nuclear@16 3 #include <string.h>
nuclear@16 4 #include <ctype.h>
nuclear@16 5 #include <errno.h>
nuclear@16 6 #include "scene.h"
nuclear@16 7 #include "cvec.h"
nuclear@16 8 #include "mingl.h"
nuclear@16 9
nuclear@16 10
nuclear@16 11 struct face {
nuclear@16 12 int v[3], n[3], t[3];
nuclear@16 13 };
nuclear@16 14
nuclear@16 15 static int load_materials(struct scene *scn, const char *fname);
nuclear@16 16 static int parse_face(struct face *face, char *buf);
nuclear@16 17
nuclear@16 18
nuclear@16 19 /* --- scene --- */
nuclear@16 20 int scn_init(struct scene *scn)
nuclear@16 21 {
nuclear@16 22 memset(scn, 0, sizeof *scn);
nuclear@16 23 return 0;
nuclear@16 24 }
nuclear@16 25
nuclear@16 26 void scn_destroy(struct scene *scn)
nuclear@16 27 {
nuclear@16 28 while(scn->matlist) {
nuclear@16 29 struct material *tmp = scn->matlist;
nuclear@16 30 scn->matlist = scn->matlist->next;
nuclear@16 31
nuclear@16 32 mtl_destroy(tmp);
nuclear@16 33 free(tmp);
nuclear@16 34 }
nuclear@16 35 while(scn->meshlist) {
nuclear@16 36 struct mesh *tmp = scn->meshlist;
nuclear@16 37 scn->meshlist = scn->meshlist->next;
nuclear@16 38
nuclear@16 39 mesh_destroy(tmp);
nuclear@16 40 free(tmp);
nuclear@16 41 }
nuclear@16 42 }
nuclear@16 43
nuclear@16 44
nuclear@16 45 void scn_add_mesh(struct scene *scn, struct mesh *m)
nuclear@16 46 {
nuclear@16 47 printf("adding mesh: %d faces\n", m->nface);
nuclear@16 48 m->next = scn->meshlist;
nuclear@16 49 scn->meshlist = m;
nuclear@16 50 }
nuclear@16 51
nuclear@16 52 void scn_add_material(struct scene *scn, struct material *m)
nuclear@16 53 {
nuclear@16 54 printf("adding material: %s\n", m->name);
nuclear@16 55 m->next = scn->matlist;
nuclear@16 56 scn->matlist = m;
nuclear@16 57 }
nuclear@16 58
nuclear@16 59 struct material *scn_find_material(struct scene *scn, const char *name)
nuclear@16 60 {
nuclear@16 61 struct material *mtl = scn->matlist;
nuclear@16 62
nuclear@16 63 while(mtl) {
nuclear@16 64 if(strcmp(mtl->name, name) == 0) {
nuclear@16 65 break;
nuclear@16 66 }
nuclear@16 67 mtl = mtl->next;
nuclear@16 68 }
nuclear@16 69 return mtl;
nuclear@16 70 }
nuclear@16 71
nuclear@16 72 #define SEP " \t\n\r"
nuclear@16 73 int scn_load(struct scene *scn, const char *fname)
nuclear@16 74 {
nuclear@16 75 FILE *fp;
nuclear@16 76 char buf[256];
nuclear@16 77 struct mesh *m;
nuclear@16 78 vec3_t *varr, *vnarr;
nuclear@16 79 vec2_t *vtarr;
nuclear@16 80
nuclear@16 81 if(!(fp = fopen(fname, "rb"))) {
nuclear@16 82 fprintf(stderr, "failed to open scene file: %s: %s\n", fname, strerror(errno));
nuclear@16 83 return -1;
nuclear@16 84 }
nuclear@16 85
nuclear@16 86 varr = cvec_alloc(0, sizeof *varr);
nuclear@16 87 vnarr = cvec_alloc(0, sizeof *vnarr);
nuclear@16 88 vtarr = cvec_alloc(0, sizeof *vtarr);
nuclear@16 89
nuclear@16 90 if(!(m = malloc(sizeof *m)) || mesh_init(m) == -1) {
nuclear@16 91 fprintf(stderr, "meshed up\n");
nuclear@16 92 fclose(fp);
nuclear@16 93 return -1;
nuclear@16 94 }
nuclear@16 95
nuclear@16 96 while(fgets(buf, sizeof buf, fp)) {
nuclear@16 97 char *line = buf;
nuclear@16 98 char *tok, *rest, *tmp;
nuclear@16 99
nuclear@16 100 while(*line && isspace(*line)) {
nuclear@16 101 line++;
nuclear@16 102 }
nuclear@16 103 if(*line == 0 || *line == '#') {
nuclear@16 104 continue;
nuclear@16 105 }
nuclear@16 106
nuclear@16 107 if(!(tok = strtok(line, SEP))) {
nuclear@16 108 continue;
nuclear@16 109 }
nuclear@16 110 rest = tok + strlen(tok) + 1;
nuclear@16 111
nuclear@16 112 if((tmp = strchr(rest, '\r')) || (tmp = strchr(rest, '\n'))) {
nuclear@16 113 *tmp = 0;
nuclear@16 114 }
nuclear@16 115
nuclear@16 116 if(strcmp(tok, "mtllib") == 0) {
nuclear@16 117 if(!rest) {
nuclear@16 118 fprintf(stderr, "invalid mtllib directive\n");
nuclear@16 119 continue;
nuclear@16 120 }
nuclear@16 121 load_materials(scn, rest);
nuclear@16 122
nuclear@16 123 } else if(strcmp(tok, "usemtl") == 0) {
nuclear@16 124 if(rest) {
nuclear@16 125 m->mtl = scn_find_material(scn, rest);
nuclear@16 126 }
nuclear@16 127
nuclear@16 128 } else if(strcmp(tok, "o") == 0 || strcmp(tok, "g") == 0) {
nuclear@16 129 if(cvec_size(m->vert) > 0) {
nuclear@16 130 scn_add_mesh(scn, m);
nuclear@16 131
nuclear@16 132 if(!(m = malloc(sizeof *m)) || mesh_init(m) == -1) {
nuclear@16 133 fprintf(stderr, "meshed up\n");
nuclear@16 134 fclose(fp);
nuclear@16 135 return -1;
nuclear@16 136 }
nuclear@16 137 }
nuclear@16 138
nuclear@16 139 } else if(strcmp(tok, "v") == 0) {
nuclear@16 140 vec3_t v;
nuclear@16 141
nuclear@16 142 if(!rest || sscanf(rest, "%f %f %f\n", &v.x, &v.y, &v.z) != 3) {
nuclear@16 143 continue;
nuclear@16 144 }
nuclear@16 145 varr = cvec_append(varr, &v);
nuclear@16 146
nuclear@16 147 } else if(strcmp(tok, "vn") == 0) {
nuclear@16 148 vec3_t v;
nuclear@16 149
nuclear@16 150 if(!rest || sscanf(rest, "%f %f %f\n", &v.x, &v.y, &v.z) != 3) {
nuclear@16 151 continue;
nuclear@16 152 }
nuclear@16 153 vnarr = cvec_append(vnarr, &v);
nuclear@16 154
nuclear@16 155 } else if(strcmp(tok, "vt") == 0) {
nuclear@16 156 vec3_t v;
nuclear@16 157
nuclear@16 158 if(!rest || sscanf(rest, "%f %f %f\n", &v.x, &v.y, &v.z) != 3) {
nuclear@16 159 continue;
nuclear@16 160 }
nuclear@16 161 vtarr = cvec_append(vtarr, &v);
nuclear@16 162
nuclear@16 163 } else if(strcmp(tok, "f") == 0) {
nuclear@16 164 int i;
nuclear@16 165 struct face face;
nuclear@16 166
nuclear@16 167 if(!rest || parse_face(&face, rest) == -1) {
nuclear@16 168 continue;
nuclear@16 169 }
nuclear@16 170
nuclear@16 171 for(i=0; i<3; i++) {
nuclear@16 172 int vidx = face.v[i];
nuclear@16 173 int nidx = face.n[i];
nuclear@16 174 int tidx = face.t[i];
nuclear@16 175
nuclear@16 176 mesh_add_vertex(m, varr[vidx]);
nuclear@16 177 if(nidx >= 0) {
nuclear@16 178 mesh_add_normal(m, vnarr[nidx]);
nuclear@16 179 }
nuclear@16 180 if(tidx >= 0) {
nuclear@16 181 mesh_add_texcoord(m, vtarr[tidx]);
nuclear@16 182 }
nuclear@16 183 m->nface++;
nuclear@16 184 }
nuclear@16 185 }
nuclear@16 186
nuclear@16 187 }
nuclear@16 188 fclose(fp);
nuclear@16 189
nuclear@16 190 if(cvec_size(m->vert) > 0) {
nuclear@16 191 scn_add_mesh(scn, m);
nuclear@16 192 }
nuclear@16 193
nuclear@16 194 cvec_free(varr);
nuclear@16 195 cvec_free(vnarr);
nuclear@16 196 cvec_free(vtarr);
nuclear@16 197
nuclear@16 198 return 0;
nuclear@16 199 }
nuclear@16 200
nuclear@16 201 static int load_materials(struct scene *scn, const char *fname)
nuclear@16 202 {
nuclear@16 203 FILE *fp;
nuclear@16 204 struct material *m = 0;
nuclear@16 205 char buf[256];
nuclear@16 206
nuclear@16 207 if(!(fp = fopen(fname, "r"))) {
nuclear@16 208 fprintf(stderr, "failed to load material file: %s: %s\n", fname, strerror(errno));
nuclear@16 209 return -1;
nuclear@16 210 }
nuclear@16 211
nuclear@16 212 while(fgets(buf, sizeof buf, fp)) {
nuclear@16 213 char *line = buf;
nuclear@16 214 char *tok, *rest, *tmp;
nuclear@16 215
nuclear@16 216 while(*line && isspace(*line)) {
nuclear@16 217 line++;
nuclear@16 218 }
nuclear@16 219 if(*line == 0 || *line == '#') {
nuclear@16 220 continue;
nuclear@16 221 }
nuclear@16 222
nuclear@16 223 if(!(tok = strtok(line, SEP))) {
nuclear@16 224 continue;
nuclear@16 225 }
nuclear@16 226 rest = tok + strlen(tok) + 1;
nuclear@16 227
nuclear@16 228 if((tmp = strchr(rest, '\r')) || (tmp = strchr(rest, '\n'))) {
nuclear@16 229 *tmp = 0;
nuclear@16 230 }
nuclear@16 231
nuclear@16 232 if(strcmp(tok, "newmtl") == 0) {
nuclear@16 233 if(m) {
nuclear@16 234 scn_add_material(scn, m);
nuclear@16 235 }
nuclear@16 236 if(!(m = malloc(sizeof *m)) || mtl_init(m) == -1) {
nuclear@16 237 continue;
nuclear@16 238 }
nuclear@16 239 mtl_set_name(m, rest);
nuclear@16 240
nuclear@16 241 } else if(strcmp(tok, "Kd") == 0) {
nuclear@16 242 if(sscanf(rest, "%f %f %f", &m->kd.x, &m->kd.y, &m->kd.z) != 3) {
nuclear@16 243 continue;
nuclear@16 244 }
nuclear@16 245 } else if(strcmp(tok, "map_Kd") == 0) {
nuclear@16 246 printf("ignoring texture: `%s'\n", rest);
nuclear@16 247 }
nuclear@16 248 }
nuclear@16 249
nuclear@16 250 if(m) {
nuclear@16 251 scn_add_material(scn, m);
nuclear@16 252 }
nuclear@16 253
nuclear@16 254 fclose(fp);
nuclear@16 255 return 0;
nuclear@16 256 }
nuclear@16 257
nuclear@16 258 static int parse_face(struct face *face, char *buf)
nuclear@16 259 {
nuclear@16 260 int i, found;
nuclear@16 261 char *tok;
nuclear@16 262
nuclear@16 263 for(i=0; i<3; i++) {
nuclear@16 264 tok = strtok(i > 0 ? 0 : buf, SEP);
nuclear@16 265 found = sscanf(tok, "%d/%d/%d", &face->v[i], &face->t[i], &face->n[i]);
nuclear@16 266
nuclear@16 267 face->v[i]--;
nuclear@16 268
nuclear@16 269 if(found > 1) {
nuclear@16 270 face->t[i]--;
nuclear@16 271 } else {
nuclear@16 272 face->t[i] = -1;
nuclear@16 273 }
nuclear@16 274 if(found > 2) {
nuclear@16 275 face->n[i]--;
nuclear@16 276 } else {
nuclear@16 277 face->n[i] = -1;
nuclear@16 278 }
nuclear@16 279 }
nuclear@16 280 return 0;
nuclear@16 281 }
nuclear@16 282
nuclear@16 283 void scn_render(struct scene *scn)
nuclear@16 284 {
nuclear@16 285 struct mesh *m = scn->meshlist;
nuclear@16 286
nuclear@16 287 while(m) {
nuclear@16 288 mesh_draw(m);
nuclear@16 289 m = m->next;
nuclear@16 290 }
nuclear@16 291 }
nuclear@16 292
nuclear@16 293 /* --- material --- */
nuclear@16 294 int mtl_init(struct material *mtl)
nuclear@16 295 {
nuclear@16 296 memset(mtl, 0, sizeof *mtl);
nuclear@16 297 return 0;
nuclear@16 298 }
nuclear@16 299
nuclear@16 300 void mtl_destroy(struct material *mtl)
nuclear@16 301 {
nuclear@16 302 free(mtl->name);
nuclear@16 303
nuclear@16 304 if(mtl->tex) {
nuclear@16 305 free_texture(mtl->tex);
nuclear@16 306 }
nuclear@16 307 }
nuclear@16 308
nuclear@16 309
nuclear@16 310 int mtl_set_name(struct material *mtl, const char *name)
nuclear@16 311 {
nuclear@16 312 char *tmp;
nuclear@16 313 int len = strlen(name);
nuclear@16 314
nuclear@16 315 if(!(tmp = malloc(len + 1))) {
nuclear@16 316 perror("failed to allocate material name");
nuclear@16 317 return -1;
nuclear@16 318 }
nuclear@16 319 memcpy(tmp, name, len);
nuclear@16 320 tmp[len] = 0;
nuclear@16 321
nuclear@16 322 free(mtl->name);
nuclear@16 323 mtl->name = tmp;
nuclear@16 324 return 0;
nuclear@16 325 }
nuclear@16 326
nuclear@16 327
nuclear@16 328 /* --- mesh --- */
nuclear@16 329 int mesh_init(struct mesh *m)
nuclear@16 330 {
nuclear@16 331 memset(m, 0, sizeof *m);
nuclear@16 332
nuclear@16 333 m->vert = cvec_alloc(0, sizeof *m->vert);
nuclear@16 334 m->norm = cvec_alloc(0, sizeof *m->norm);
nuclear@16 335 m->texcoord = cvec_alloc(0, sizeof *m->texcoord);
nuclear@16 336
nuclear@16 337 if(!m->vert || !m->norm || !m->texcoord) {
nuclear@16 338 return -1;
nuclear@16 339 }
nuclear@16 340 return 0;
nuclear@16 341 }
nuclear@16 342
nuclear@16 343 void mesh_destroy(struct mesh *m)
nuclear@16 344 {
nuclear@16 345 cvec_free(m->vert);
nuclear@16 346 cvec_free(m->norm);
nuclear@16 347 cvec_free(m->texcoord);
nuclear@16 348 }
nuclear@16 349
nuclear@16 350 void mesh_add_vertex(struct mesh *m, vec3_t v)
nuclear@16 351 {
nuclear@16 352 m->vert = cvec_append(m->vert, &v);
nuclear@16 353 }
nuclear@16 354
nuclear@16 355 void mesh_add_normal(struct mesh *m, vec3_t n)
nuclear@16 356 {
nuclear@16 357 m->norm = cvec_append(m->norm, &n);
nuclear@16 358 }
nuclear@16 359
nuclear@16 360 void mesh_add_texcoord(struct mesh *m, vec2_t tc)
nuclear@16 361 {
nuclear@16 362 m->texcoord = cvec_append(m->texcoord, &tc);
nuclear@16 363 }
nuclear@16 364
nuclear@16 365 void mesh_draw(struct mesh *m)
nuclear@16 366 {
nuclear@16 367 int i, numv;
nuclear@16 368
nuclear@16 369 mgl_begin(MGL_TRIANGLES);
nuclear@16 370
nuclear@16 371 numv = cvec_size(m->vert);
nuclear@16 372 for(i=0; i<numv; i++) {
nuclear@16 373 mgl_normal(m->norm[i].x, m->norm[i].y, m->norm[i].z);
nuclear@16 374 mgl_texcoord2f(m->texcoord[i].x, m->texcoord[i].y);
nuclear@16 375 mgl_vertex3f(m->vert[i].x, m->vert[i].y, m->vert[i].z);
nuclear@16 376 }
nuclear@16 377
nuclear@16 378 mgl_end();
nuclear@16 379 }