X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=model.c;h=9c6678701bb674c434221deaf8858a48e5d904a8;hb=bc662e293c854e1bdc9d46e9a410fe220247e6d4;hp=522527348bccd90dcee20433373b868adf7b1bf0;hpb=95850b98f73ad7033af60a30e324e9c3cda55389;p=chaz%2Frasterize diff --git a/model.c b/model.c index 5225273..9c66787 100644 --- a/model.c +++ b/model.c @@ -7,9 +7,9 @@ #include -#include "array.h" -#include "tri.h" +#include "list.h" #include "model.h" +#include "raster.h" // create an interface for a vector array @@ -18,20 +18,21 @@ DEFINE_ARRAY_TYPE(vec); struct model { - list_t* triangles; - mat_t model; - color_t specular; - scal_t shininess; - char* name; - int count; + array_t* triangles; + mat_t model; + color_t specular; + scal_t shininess; + const raster_t* texture; + char* name; + int count; }; static int _model_read_raw(model_t* m, const char* filename); static int _model_read_obj(model_t* m, const char* filename); -static int _model_try_read_cache(const char* filename, list_t** l); -static void _model_write_cache(const char* filename, int count, list_t* l); +static int _model_try_read_cache(const char* filename, array_t* l); +static void _model_write_cache(const char* filename, int count, const array_t* l); model_t* model_alloc(const char* filename) @@ -58,16 +59,17 @@ fail: model_t* model_alloc2(const char* filename, int type) { model_t* m = (model_t*)mem_alloc(sizeof(model_t)); - m->triangles = NULL; + m->triangles = array_tri_alloc(); m->model = MAT_IDENTITY; - m->specular = COLOR_WHITE; + m->specular = COLOR_BLACK; m->shininess = S(64.0); + m->texture = NULL; m->name = mem_strdup(filename); m->count = 0; #if CACHE_GEOMETRY - int count = _model_try_read_cache(filename, &m->triangles); - if (0 < count) { + m->count = _model_try_read_cache(filename, m->triangles); + if (0 < m->count) { return m; } #endif @@ -95,13 +97,16 @@ model_t* model_alloc2(const char* filename, int type) void model_destroy(model_t* m) { - list_destroy(&m->triangles); + array_destroy(m->triangles); + if (m->texture) { + raster_destroy((raster_t*)m->texture); + } mem_free(m->name); mem_free(m); } -const list_t* model_geometry(const model_t* m) +const array_t* model_geometry(const model_t* m) { return m->triangles; } @@ -131,6 +136,24 @@ void model_transformation(const model_t* m, mat_t* transform) *transform = m->model; } +color_t model_tcolor(const model_t* m, vec_t pt) +{ + if (m->texture) { + return raster_color(m->texture, pt); + } + return COLOR_WHITE; +} + +void* model_tdata(const model_t* m, int* width, int* height) +{ + if (m->texture) { + if (width) *width = raster_width(m->texture); + if (height) *height = raster_height(m->texture); + return raster_data(m->texture); + } + return NULL; +} + void model_transform(model_t* m, const mat_t* transform) { @@ -143,6 +166,11 @@ void model_material(model_t* m, color_t specular, scal_t shininess) m->shininess = shininess; } +void model_texture(model_t* m, const void* p) +{ + m->texture = (const raster_t*)p; +} + #if CALC_NORMALS @@ -214,6 +242,8 @@ static int _model_read_raw(model_t* m, const char* filename) return -1; } + list_t* triangles = NULL; + #if CALC_NORMALS map_t* nlookup = map_vnorm_alloc(); #endif @@ -226,7 +256,7 @@ static int _model_read_raw(model_t* m, const char* filename) vert_new2((scal_t)x2, (scal_t)y2, (scal_t)z2), vert_new2((scal_t)x3, (scal_t)y3, (scal_t)z3) ); - list_push2(&m->triangles, t, mem_free); + list_push2(&triangles, t, mem_free); ++m->count; #if CALC_NORMALS @@ -245,10 +275,16 @@ static int _model_read_raw(model_t* m, const char* filename) #endif fclose(file); - if (m->triangles == NULL) { + if (triangles == NULL) { fprintf(stderr, "No triangles read from %s\n", filename); return -1; } + + while (triangles) { + array_tri_push(m->triangles, *(tri_t*)triangles->val); + list_pop(&triangles); + } + return 0; } @@ -260,6 +296,8 @@ static int _model_read_obj(model_t* m, const char* filename) return -1; } + list_t* triangles = NULL; + #if CALC_NORMALS map_t* nlookup = map_vnorm_alloc(); #endif @@ -295,7 +333,7 @@ static int _model_read_obj(model_t* m, const char* filename) vert_new(*array_vec_index(v, i2)), vert_new(*array_vec_index(v, i3)) ); - list_push2(&m->triangles, t, mem_free); + list_push2(&triangles, t, mem_free); ++m->count; #if CALC_NORMALS @@ -313,9 +351,11 @@ static int _model_read_obj(model_t* m, const char* filename) vert_new(*array_vec_index(v, i3)), vert_new(*array_vec_index(v, i5)) ); - list_push2(&m->triangles, t, mem_free); + list_push2(&triangles, t, mem_free); ++m->count; - + t->a.t = *array_vec_index(vt, i2); + t->b.t = *array_vec_index(vt, i4); + t->c.t = *array_vec_index(vt, i6); #if CALC_NORMALS _find_normals_add_triangle(nlookup, t); #else @@ -332,7 +372,7 @@ static int _model_read_obj(model_t* m, const char* filename) vert_new(*array_vec_index(v, i3)), vert_new(*array_vec_index(v, i5)) ); - list_push2(&m->triangles, t, mem_free); + list_push2(&triangles, t, mem_free); ++m->count; t->a.n = *array_vec_index(vn, i2); t->b.n = *array_vec_index(vn, i4); @@ -345,8 +385,11 @@ static int _model_read_obj(model_t* m, const char* filename) vert_new(*array_vec_index(v, i4)), vert_new(*array_vec_index(v, i7)) ); - list_push2(&m->triangles, t, mem_free); + list_push2(&triangles, t, mem_free); ++m->count; + t->a.t = *array_vec_index(vt, i2); + t->b.t = *array_vec_index(vt, i5); + t->c.t = *array_vec_index(vt, i8); t->a.n = *array_vec_index(vn, i3); t->b.n = *array_vec_index(vn, i6); t->c.n = *array_vec_index(vn, i9); @@ -363,62 +406,77 @@ static int _model_read_obj(model_t* m, const char* filename) #endif fclose(file); - if (m->triangles == NULL) { + if (triangles == NULL) { fprintf(stderr, "No triangles read from %s\n", filename); return -1; } + + while (triangles) { + array_tri_push(m->triangles, *(tri_t*)triangles->val); + list_pop(&triangles); + } + return 0; } -#define _CHECK_IO(X) if ((X) <= 0) goto fail +#define _DO_OR_DONE(X) if ((X) <= 0) goto done /* * Try to read the triangle geometry from the cache file. */ -static int _model_try_read_cache(const char* filename, list_t** l) +static int _model_try_read_cache(const char* filename, array_t* l) { int count = 0; char* cachename = mem_strcat(".", filename); FILE* file = fopen(cachename, "rb"); if (file == NULL) { - goto fail; + goto done; } - _CHECK_IO(fread(&count, sizeof(count), 1, file)); - float x1, y1, z1, x2, y2, z2, x3, y3, z3; - for (int i = 0; i < count; ++i) { - _CHECK_IO(fread(&x1, sizeof(float), 1, file)); - _CHECK_IO(fread(&y1, sizeof(float), 1, file)); - _CHECK_IO(fread(&z1, sizeof(float), 1, file)); - _CHECK_IO(fread(&x2, sizeof(float), 1, file)); - _CHECK_IO(fread(&y2, sizeof(float), 1, file)); - _CHECK_IO(fread(&z2, sizeof(float), 1, file)); - _CHECK_IO(fread(&x3, sizeof(float), 1, file)); - _CHECK_IO(fread(&y3, sizeof(float), 1, file)); - _CHECK_IO(fread(&z3, sizeof(float), 1, file)); - tri_t* t = tri_alloc( + while (1) { + _DO_OR_DONE(fread(&x1, sizeof(float), 1, file)); + _DO_OR_DONE(fread(&y1, sizeof(float), 1, file)); + _DO_OR_DONE(fread(&z1, sizeof(float), 1, file)); + _DO_OR_DONE(fread(&x2, sizeof(float), 1, file)); + _DO_OR_DONE(fread(&y2, sizeof(float), 1, file)); + _DO_OR_DONE(fread(&z2, sizeof(float), 1, file)); + _DO_OR_DONE(fread(&x3, sizeof(float), 1, file)); + _DO_OR_DONE(fread(&y3, sizeof(float), 1, file)); + _DO_OR_DONE(fread(&z3, sizeof(float), 1, file)); + tri_t t = tri_new( vert_new2((scal_t)x1, (scal_t)y1, (scal_t)z1), vert_new2((scal_t)x2, (scal_t)y2, (scal_t)z2), vert_new2((scal_t)x3, (scal_t)y3, (scal_t)z3) ); - list_push2(l, t, mem_free); - _CHECK_IO(fread(&x1, sizeof(float), 1, file)); - _CHECK_IO(fread(&y1, sizeof(float), 1, file)); - _CHECK_IO(fread(&z1, sizeof(float), 1, file)); - _CHECK_IO(fread(&x2, sizeof(float), 1, file)); - _CHECK_IO(fread(&y2, sizeof(float), 1, file)); - _CHECK_IO(fread(&z2, sizeof(float), 1, file)); - _CHECK_IO(fread(&x3, sizeof(float), 1, file)); - _CHECK_IO(fread(&y3, sizeof(float), 1, file)); - _CHECK_IO(fread(&z3, sizeof(float), 1, file)); - t->a.n = vec_new((scal_t)x1, (scal_t)y1, (scal_t)z1); - t->b.n = vec_new((scal_t)x2, (scal_t)y2, (scal_t)z2); - t->c.n = vec_new((scal_t)x3, (scal_t)y3, (scal_t)z3); + ++count; + array_tri_push(l, t); + tri_t* tp = array_tri_back(l); + _DO_OR_DONE(fread(&x1, sizeof(float), 1, file)); + _DO_OR_DONE(fread(&y1, sizeof(float), 1, file)); + _DO_OR_DONE(fread(&z1, sizeof(float), 1, file)); + _DO_OR_DONE(fread(&x2, sizeof(float), 1, file)); + _DO_OR_DONE(fread(&y2, sizeof(float), 1, file)); + _DO_OR_DONE(fread(&z2, sizeof(float), 1, file)); + _DO_OR_DONE(fread(&x3, sizeof(float), 1, file)); + _DO_OR_DONE(fread(&y3, sizeof(float), 1, file)); + _DO_OR_DONE(fread(&z3, sizeof(float), 1, file)); + tp->a.n = vec_new((scal_t)x1, (scal_t)y1, (scal_t)z1); + tp->b.n = vec_new((scal_t)x2, (scal_t)y2, (scal_t)z2); + tp->c.n = vec_new((scal_t)x3, (scal_t)y3, (scal_t)z3); + _DO_OR_DONE(fread(&x1, sizeof(float), 1, file)); + _DO_OR_DONE(fread(&y1, sizeof(float), 1, file)); + _DO_OR_DONE(fread(&x2, sizeof(float), 1, file)); + _DO_OR_DONE(fread(&y2, sizeof(float), 1, file)); + _DO_OR_DONE(fread(&x3, sizeof(float), 1, file)); + _DO_OR_DONE(fread(&y3, sizeof(float), 1, file)); + tp->a.t = vec_new((scal_t)x1, (scal_t)y1, S(0.0)); + tp->b.t = vec_new((scal_t)x2, (scal_t)y2, S(0.0)); + tp->c.t = vec_new((scal_t)x3, (scal_t)y3, S(0.0)); } -fail: +done: mem_free(cachename); if (file != NULL) { fclose(file); @@ -430,45 +488,59 @@ fail: /* * Write the triangle data to the cache. */ -static void _model_write_cache(const char* filename, int count, list_t* l) +static void _model_write_cache(const char* filename, int count, const array_t* l) { char* cachename = mem_strcat(".", filename); FILE* file = fopen(cachename, "wb"); if (file == NULL) { fprintf(stderr, "Cannot write %s: %s\n", cachename, strerror(errno)); - goto fail; + goto done; } - _CHECK_IO(fwrite(&count, sizeof(count), 1, file)); - for (list_t* i = l; i; i = i->link) { - tri_t* t = (tri_t*)i->val; - _CHECK_IO(fwrite(&t->a.v.x, sizeof(float), 1, file)); - _CHECK_IO(fwrite(&t->a.v.y, sizeof(float), 1, file)); - _CHECK_IO(fwrite(&t->a.v.z, sizeof(float), 1, file)); - _CHECK_IO(fwrite(&t->b.v.x, sizeof(float), 1, file)); - _CHECK_IO(fwrite(&t->b.v.y, sizeof(float), 1, file)); - _CHECK_IO(fwrite(&t->b.v.z, sizeof(float), 1, file)); - _CHECK_IO(fwrite(&t->c.v.x, sizeof(float), 1, file)); - _CHECK_IO(fwrite(&t->c.v.y, sizeof(float), 1, file)); - _CHECK_IO(fwrite(&t->c.v.z, sizeof(float), 1, file)); - _CHECK_IO(fwrite(&t->a.n.x, sizeof(float), 1, file)); - _CHECK_IO(fwrite(&t->a.n.y, sizeof(float), 1, file)); - _CHECK_IO(fwrite(&t->a.n.z, sizeof(float), 1, file)); - _CHECK_IO(fwrite(&t->b.n.x, sizeof(float), 1, file)); - _CHECK_IO(fwrite(&t->b.n.y, sizeof(float), 1, file)); - _CHECK_IO(fwrite(&t->b.n.z, sizeof(float), 1, file)); - _CHECK_IO(fwrite(&t->c.n.x, sizeof(float), 1, file)); - _CHECK_IO(fwrite(&t->c.n.y, sizeof(float), 1, file)); - _CHECK_IO(fwrite(&t->c.n.z, sizeof(float), 1, file)); + float x1, y1, z1, x2, y2, z2, x3, y3, z3; + array_it_t it = array_begin(l); + for (tri_t* t; t = array_it_tri_next(&it);) { + x1 = (float)t->a.v.x; y1 = (float)t->a.v.y; z1 = (float)t->a.v.z; + x2 = (float)t->b.v.x; y2 = (float)t->b.v.y; z2 = (float)t->b.v.z; + x3 = (float)t->c.v.x; y3 = (float)t->c.v.y; z3 = (float)t->c.v.z; + _DO_OR_DONE(fwrite(&x1, sizeof(float), 1, file)); + _DO_OR_DONE(fwrite(&y1, sizeof(float), 1, file)); + _DO_OR_DONE(fwrite(&z1, sizeof(float), 1, file)); + _DO_OR_DONE(fwrite(&x2, sizeof(float), 1, file)); + _DO_OR_DONE(fwrite(&y2, sizeof(float), 1, file)); + _DO_OR_DONE(fwrite(&z2, sizeof(float), 1, file)); + _DO_OR_DONE(fwrite(&x3, sizeof(float), 1, file)); + _DO_OR_DONE(fwrite(&y3, sizeof(float), 1, file)); + _DO_OR_DONE(fwrite(&z3, sizeof(float), 1, file)); + x1 = (float)t->a.n.x; y1 = (float)t->a.n.y; z1 = (float)t->a.n.z; + x2 = (float)t->b.n.x; y2 = (float)t->b.n.y; z2 = (float)t->b.n.z; + x3 = (float)t->c.n.x; y3 = (float)t->c.n.y; z3 = (float)t->c.n.z; + _DO_OR_DONE(fwrite(&x1, sizeof(float), 1, file)); + _DO_OR_DONE(fwrite(&y1, sizeof(float), 1, file)); + _DO_OR_DONE(fwrite(&z1, sizeof(float), 1, file)); + _DO_OR_DONE(fwrite(&x2, sizeof(float), 1, file)); + _DO_OR_DONE(fwrite(&y2, sizeof(float), 1, file)); + _DO_OR_DONE(fwrite(&z2, sizeof(float), 1, file)); + _DO_OR_DONE(fwrite(&x3, sizeof(float), 1, file)); + _DO_OR_DONE(fwrite(&y3, sizeof(float), 1, file)); + _DO_OR_DONE(fwrite(&z3, sizeof(float), 1, file)); + x1 = (float)t->a.t.x; y1 = (float)t->a.t.y; + x2 = (float)t->b.t.x; y2 = (float)t->b.t.y; + x3 = (float)t->c.t.x; y3 = (float)t->c.t.y; + _DO_OR_DONE(fwrite(&x1, sizeof(float), 1, file)); + _DO_OR_DONE(fwrite(&y1, sizeof(float), 1, file)); + _DO_OR_DONE(fwrite(&x2, sizeof(float), 1, file)); + _DO_OR_DONE(fwrite(&y2, sizeof(float), 1, file)); + _DO_OR_DONE(fwrite(&x3, sizeof(float), 1, file)); + _DO_OR_DONE(fwrite(&y3, sizeof(float), 1, file)); } -fail: +done: mem_free(cachename); if (file != NULL) { fclose(file); } } -#undef _CHECK_IO - +#undef _DO_OR_DIE