#include <errno.h>
#include "array.h"
-#include "tri.h"
#include "model.h"
+#include "raster.h"
+#include "tri.h"
// create an interface for a vector array
struct model
{
- list_t* triangles;
- mat_t model;
- color_t specular;
- scal_t shininess;
- char* name;
- int count;
+ list_t* triangles;
+ mat_t model;
+ color_t specular;
+ scal_t shininess;
+ const raster_t* texture;
+ char* name;
+ int count;
};
model_t* m = (model_t*)mem_alloc(sizeof(model_t));
m->triangles = NULL;
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
void model_destroy(model_t* m)
{
list_destroy(&m->triangles);
+ if (m->texture) {
+ raster_destroy((raster_t*)m->texture);
+ }
mem_free(m->name);
mem_free(m);
}
*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_transform(model_t* m, const mat_t* transform)
{
m->shininess = shininess;
}
+void model_texture(model_t* m, const void* p)
+{
+ m->texture = (const raster_t*)p;
+}
+
#if CALC_NORMALS
while (fgets(line, 4096, file)) {
char name[4096];
double f1, f2, f3, f4;
- int meh;
int i1, i2, i3, i4, i5, i6, i7, i8, i9;
if (sscanf(line, "v %lf %lf %lf %lf ", &f1, &f2, &f3, &f4) == 4) {
array_vec_push(v, vec_new2((scal_t)f1, (scal_t)f2, (scal_t)f3, (scal_t)f4));
t->c.n = n;
#endif
}
- else if (sscanf(line, "f %d/%d %d/%d %d/%d ", &i1, &i4, &i2, &i4, &i3, &i4) == 6) {
+ else if (sscanf(line, "f %d/%d %d/%d %d/%d ", &i1, &i2, &i3, &i4, &i5, &i6) == 6) {
tri_t* t = tri_alloc(
vert_new(*array_vec_index(v, i1)),
- vert_new(*array_vec_index(v, i2)),
- vert_new(*array_vec_index(v, i3))
+ vert_new(*array_vec_index(v, i3)),
+ vert_new(*array_vec_index(v, i5))
);
list_push2(&m->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
t->c.n = *array_vec_index(vn, i6);
}
else if (sscanf(line, "f %d/%d/%d %d/%d/%d %d/%d/%d ",
- &i1, &meh, &i2, &i3, &meh, &i4, &i5, &meh, &i6) == 9) {
+ &i1, &i2, &i3, &i4, &i5, &i6, &i7, &i8, &i9) == 9) {
tri_t* t = tri_alloc(
vert_new(*array_vec_index(v, i1)),
- vert_new(*array_vec_index(v, i3)),
- vert_new(*array_vec_index(v, i5))
+ vert_new(*array_vec_index(v, i4)),
+ vert_new(*array_vec_index(v, i7))
);
list_push2(&m->triangles, t, mem_free);
++m->count;
- t->a.n = *array_vec_index(vn, i2);
- t->b.n = *array_vec_index(vn, i4);
- t->c.n = *array_vec_index(vn, i6);
+ 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);
}
- // f 1/2 3/4 5/6
- // f 1/2/3 4/5/6 7/8/9
}
array_destroy(v);
}
-#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.
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));
+ 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_alloc(
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)
);
+ ++count;
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));
+ _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));
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);
+ _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));
+ t->a.t = vec_new((scal_t)x1, (scal_t)y1, S(0.0));
+ t->b.t = vec_new((scal_t)x2, (scal_t)y2, S(0.0));
+ t->c.t = vec_new((scal_t)x3, (scal_t)y3, S(0.0));
}
-fail:
+done:
mem_free(cachename);
if (file != NULL) {
fclose(file);
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));
+ float x1, y1, z1, x2, y2, z2, x3, y3, z3;
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));
+ 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