]>
Dogcows Code - chaz/rasterize/blob - scene.c
3 * CS5600 University of Utah
5 * mcgarvey@eng.utah.edu
20 #define IF_RENDER_PROGRESS(X) X
22 #define IF_RENDER_PROGRESS(X)
28 DECLARE_AND_DEFINE_MAP_TYPE3(vec_t
, list_t
*, vnorm
, vec_compare(*a
, *b
));
32 * Associate a triangle with one of its vertices.
34 static void _find_normals_add_vertex(map_t
* m
, vec_t v
, tri_t
* t
)
36 list_t
** l
= map_vnorm_search(m
, v
);
38 map_vnorm_data_t
* d
= map_vnorm_insert(m
, v
, NULL
);
45 * Associate a triangle with all of its vertices.
47 static void _find_normals_add_triangle(map_t
* m
, tri_t
* t
)
49 _find_normals_add_vertex(m
, t
->a
.v
, t
);
50 _find_normals_add_vertex(m
, t
->b
.v
, t
);
51 _find_normals_add_vertex(m
, t
->c
.v
, t
);
55 * Calculate an averaged normal from a list of triangles that share a common
58 static void _find_normals_average(const vec_t
* v
, list_t
** l
)
60 // first, compute the average normal
62 for (list_t
* i
= *l
; i
; i
= i
->link
) {
63 tri_t
* t
= (tri_t
*)i
->val
;
64 n
= vec_add(n
, tri_normal(*t
));
68 // set the normal on each triangle's vertex that is shared
70 tri_t
* t
= (tri_t
*)(*l
)->val
;
71 if (vec_isequal(*v
, t
->a
.v
)) {
74 else if (vec_isequal(*v
, t
->b
.v
)) {
77 else if (vec_isequal(*v
, t
->c
.v
)) {
88 * A group of triangles and a transformation.
97 typedef struct _group _group_t
;
100 #define _CHECK_IO(X) if ((X) <= 0) goto fail
103 * Try to read the triangle geometry from the cache file.
105 static int _group_try_read_cache(const char* filename
, list_t
** l
)
107 char* cachename
= mem_strcat(".", filename
);
108 FILE* file
= fopen(cachename
, "rb");
114 _CHECK_IO(fread(&count
, sizeof(count
), 1, file
));
116 float x1
, y1
, z1
, x2
, y2
, z2
, x3
, y3
, z3
;
117 for (int i
= 0; i
< count
; ++i
) {
118 _CHECK_IO(fread(&x1
, sizeof(float), 1, file
));
119 _CHECK_IO(fread(&y1
, sizeof(float), 1, file
));
120 _CHECK_IO(fread(&z1
, sizeof(float), 1, file
));
121 _CHECK_IO(fread(&x2
, sizeof(float), 1, file
));
122 _CHECK_IO(fread(&y2
, sizeof(float), 1, file
));
123 _CHECK_IO(fread(&z2
, sizeof(float), 1, file
));
124 _CHECK_IO(fread(&x3
, sizeof(float), 1, file
));
125 _CHECK_IO(fread(&y3
, sizeof(float), 1, file
));
126 _CHECK_IO(fread(&z3
, sizeof(float), 1, file
));
127 tri_t
* t
= tri_alloc(
128 vert_new2((scal_t
)x1
, (scal_t
)y1
, (scal_t
)z1
),
129 vert_new2((scal_t
)x2
, (scal_t
)y2
, (scal_t
)z2
),
130 vert_new2((scal_t
)x3
, (scal_t
)y3
, (scal_t
)z3
)
132 _CHECK_IO(fread(&x1
, sizeof(float), 1, file
));
133 _CHECK_IO(fread(&y1
, sizeof(float), 1, file
));
134 _CHECK_IO(fread(&z1
, sizeof(float), 1, file
));
135 _CHECK_IO(fread(&x2
, sizeof(float), 1, file
));
136 _CHECK_IO(fread(&y2
, sizeof(float), 1, file
));
137 _CHECK_IO(fread(&z2
, sizeof(float), 1, file
));
138 _CHECK_IO(fread(&x3
, sizeof(float), 1, file
));
139 _CHECK_IO(fread(&y3
, sizeof(float), 1, file
));
140 _CHECK_IO(fread(&z3
, sizeof(float), 1, file
));
141 t
->a
.n
= vec_new((scal_t
)x1
, (scal_t
)y1
, (scal_t
)z1
);
142 t
->b
.n
= vec_new((scal_t
)x2
, (scal_t
)y2
, (scal_t
)z2
);
143 t
->c
.n
= vec_new((scal_t
)x3
, (scal_t
)y3
, (scal_t
)z3
);
145 list_push2(l
, t
, mem_free
);
156 * Write the triangle data to the cache.
158 static void _group_write_cache(const char* filename
, int count
, list_t
* l
)
160 char* cachename
= mem_strcat(".", filename
);
161 FILE* file
= fopen(cachename
, "wb");
163 fprintf(stderr
, "Cannot write %s: %s\n", cachename
, strerror(errno
));
167 _CHECK_IO(fwrite(&count
, sizeof(count
), 1, file
));
168 for (list_t
* i
= l
; i
; i
= i
->link
) {
169 tri_t
* t
= (tri_t
*)i
->val
;
170 _CHECK_IO(fwrite(&t
->a
.v
.x
, sizeof(float), 1, file
));
171 _CHECK_IO(fwrite(&t
->a
.v
.y
, sizeof(float), 1, file
));
172 _CHECK_IO(fwrite(&t
->a
.v
.z
, sizeof(float), 1, file
));
173 _CHECK_IO(fwrite(&t
->b
.v
.x
, sizeof(float), 1, file
));
174 _CHECK_IO(fwrite(&t
->b
.v
.y
, sizeof(float), 1, file
));
175 _CHECK_IO(fwrite(&t
->b
.v
.z
, sizeof(float), 1, file
));
176 _CHECK_IO(fwrite(&t
->c
.v
.x
, sizeof(float), 1, file
));
177 _CHECK_IO(fwrite(&t
->c
.v
.y
, sizeof(float), 1, file
));
178 _CHECK_IO(fwrite(&t
->c
.v
.z
, sizeof(float), 1, file
));
179 _CHECK_IO(fwrite(&t
->a
.n
.x
, sizeof(float), 1, file
));
180 _CHECK_IO(fwrite(&t
->a
.n
.y
, sizeof(float), 1, file
));
181 _CHECK_IO(fwrite(&t
->a
.n
.z
, sizeof(float), 1, file
));
182 _CHECK_IO(fwrite(&t
->b
.n
.x
, sizeof(float), 1, file
));
183 _CHECK_IO(fwrite(&t
->b
.n
.y
, sizeof(float), 1, file
));
184 _CHECK_IO(fwrite(&t
->b
.n
.z
, sizeof(float), 1, file
));
185 _CHECK_IO(fwrite(&t
->c
.n
.x
, sizeof(float), 1, file
));
186 _CHECK_IO(fwrite(&t
->c
.n
.y
, sizeof(float), 1, file
));
187 _CHECK_IO(fwrite(&t
->c
.n
.z
, sizeof(float), 1, file
));
198 * Allocate a group by reading raw triangle coordinates from a file.
200 static _group_t
* _group_alloc(const char* filename
)
202 _group_t
* g
= (_group_t
*)mem_alloc(sizeof(_group_t
));
204 g
->model
= MAT_IDENTITY
;
205 g
->name
= mem_strdup(filename
);
209 int r
= _group_try_read_cache(filename
, &g
->triangles
);
216 FILE* file
= fopen(filename
, "r");
218 fprintf(stderr
, "Cannot read %s: %s\n", filename
, strerror(errno
));
223 map_t
* m
= map_vnorm_alloc();
226 double x1
, y1
, z1
, x2
, y2
, z2
, x3
, y3
, z3
;
227 while (fscanf(file
, " %lf %lf %lf %lf %lf %lf %lf %lf %lf",
228 &x1
, &y1
, &z1
, &x2
, &y2
, &z2
, &x3
, &y3
, &z3
) == 9) {
229 tri_t
* t
= tri_alloc(
230 vert_new2((scal_t
)x1
, (scal_t
)y1
, (scal_t
)z1
),
231 vert_new2((scal_t
)x2
, (scal_t
)y2
, (scal_t
)z2
),
232 vert_new2((scal_t
)x3
, (scal_t
)y3
, (scal_t
)z3
)
234 list_push2(&g
->triangles
, t
, mem_free
);
238 vec_t n
= vec_normalize(tri_normal(*t
));
242 #elif PRE_NORMALS >= 2
243 _find_normals_add_triangle(m
, t
);
248 map_vnorm_call(m
, _find_normals_average
);
251 list_reverse(&g
->triangles
);
252 _group_write_cache(filename
, g
->count
, g
->triangles
);
258 if (g
->triangles
== NULL
) {
259 fprintf(stderr
, "No triangles coordinates read from %s\n", filename
);
270 static void _group_destroy(_group_t
* g
)
273 list_destroy(g
->triangles
);
279 * Set the colors of the triangles in the group as defined in a file.
281 static int _group_set_colors(_group_t
* g
, FILE* file
)
283 double r1
, g1
, b1
, r2
, g2
, b2
, r3
, g3
, b3
;
284 if (fscanf(file
, " %lf %lf %lf %lf %lf %lf %lf %lf %lf",
285 &r1
, &g1
, &b1
, &r2
, &g2
, &b2
, &r3
, &g3
, &b3
) != 9) {
286 fprintf(stderr
, "Cannot read color values from scene file.\n");
290 for (list_t
* i
= g
->triangles
; i
; i
= i
->link
) {
291 tri_t
* t
= (tri_t
*)i
->val
;
292 t
->a
.c
= color_new((colorchan_t
)r1
, (colorchan_t
)g1
, (colorchan_t
)b1
, S(1.0));
293 t
->b
.c
= color_new((colorchan_t
)r2
, (colorchan_t
)g2
, (colorchan_t
)b2
, S(1.0));
294 t
->c
.c
= color_new((colorchan_t
)r3
, (colorchan_t
)g3
, (colorchan_t
)b3
, S(1.0));
300 * Concat a translation matrix to the transformation as defined in a file.
302 static int _group_add_translate(_group_t
* g
, FILE* file
)
305 if (fscanf(file
, " %lf %lf %lf", &tx
, &ty
, &tz
) != 3) {
306 fprintf(stderr
, "Cannot read translate coordinates from scene file.\n");
309 g
->model
= mat_mult(g
->model
, MAT_TRANSLATE((scal_t
)tx
, (scal_t
)ty
, (scal_t
)tz
));
314 * Concat a rotation matrix to the transformation as defined in a file.
316 static int _group_add_rotate(_group_t
* g
, FILE* file
)
318 double theta
, ax
, ay
, az
;
319 if (fscanf(file
, " %lf %lf %lf %lf", &theta
, &ax
, &ay
, &az
) != 4) {
320 fprintf(stderr
, "Cannot read rotation angle from scene file.\n");
323 g
->model
= mat_mult(g
->model
, MAT_ROTATE((scal_t
)theta
, (scal_t
)ax
, (scal_t
)ay
, (scal_t
)az
));
328 * Concat a scale matrix to the transformation as defined in a file.
330 static int _group_add_scale(_group_t
* g
, FILE* file
)
333 if (fscanf(file
, " %lf %lf %lf", &sx
, &sy
, &sz
) != 3) {
334 fprintf(stderr
, "Cannot read scale factors from scene file.\n");
337 g
->model
= mat_mult(g
->model
, MAT_SCALE((scal_t
)sx
, (scal_t
)sy
, (scal_t
)sz
));
352 scene_t
* scene_alloc(const char* filename
)
355 if (strcmp(filename
, "-") == 0) {
359 file
= fopen(filename
, "r");
362 fprintf(stderr
, "Cannot read %s: %s\n", filename
, strerror(errno
));
367 double eyeX
, eyeY
, eyeZ
, spotX
, spotY
, spotZ
, upX
, upY
, upZ
;
368 double fovy
, aspect
, near
, far
;
369 if (fscanf(file
, "U3 %d %d %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
371 &eyeX
, &eyeY
, &eyeZ
, &spotX
, &spotY
, &spotZ
, &upX
, &upY
, &upZ
,
372 &fovy
, &aspect
, &near
, &far
) != 15) {
373 fprintf(stderr
, "Cannot read scene file header.\n");
377 scene_t
* s
= (scene_t
*)mem_alloc(sizeof(scene_t
));
381 s
->view
= MAT_LOOKAT(vec_new( (scal_t
)eyeX
, (scal_t
)eyeY
, (scal_t
)eyeZ
),
382 vec_new((scal_t
)spotX
, (scal_t
)spotY
, (scal_t
)spotZ
),
383 vec_new( (scal_t
)upX
, (scal_t
)upY
, (scal_t
)upZ
));
384 s
->eye
= vec_new(eyeX
, eyeY
, eyeZ
);
385 s
->projection
= MAT_PERSPECTIVE((scal_t
)fovy
, (scal_t
)aspect
, (scal_t
)near
, (scal_t
)far
);
387 char grp_filename
[4096];
392 fprintf(stderr, "Unexpected line before group is specified.\n"); \
397 while (fscanf(file
, " %c", &type
) == 1) {
400 if (fgets(grp_filename
, 4096, file
) == NULL
) {
401 fprintf(stderr
, "Cannot read raw triangle filename.\n");
404 g
= _group_alloc(grp_filename
);
408 list_push2(&s
->groups
, g
, DTOR(_group_destroy
));
413 if (_group_set_colors(g
, file
) != 0) {
420 if (_group_add_translate(g
, file
) != 0) {
426 if (_group_add_rotate(g
, file
) != 0) {
433 if (_group_add_scale(g
, file
) != 0) {
439 fprintf(stderr
, "Unknown identifier: %c\n", type
);
453 void scene_destroy(scene_t
* s
)
455 list_destroy(s
->groups
);
460 raster_t
* scene_render(scene_t
* s
)
466 raster_t
* p
= raster_alloc(s
->w
, s
->h
, COLOR_BLACK
);
467 raster_view(p
, &s
->view
);
468 raster_projection(p
, &s
->projection
);
469 raster_eye(p
, s
->eye
);
471 raster_light(p
, light_new(COLOR_WHITE
, vec_new(S(5.0), S(3.0), S(6.0))));
472 raster_light(p
, light_new(COLOR_MAGENTA
, vec_new(S(-2.0), S(2.0), S(-2.0))));
475 #define PROGRESS_FMT "\033[80D\033[2K %s\t %9d / %d"
477 printf("render scene:\n");
480 for (list_t
* gi
= s
->groups
; gi
; gi
= gi
->link
) {
481 _group_t
* g
= (_group_t
*)gi
->val
;
482 raster_model(p
, &g
->model
);
483 IF_RENDER_PROGRESS(tri
= 0);
484 for (list_t
* ti
= g
->triangles
; ti
; ti
= ti
->link
) {
486 if (++tri
% 100 == 0) {
487 printf(PROGRESS_FMT
, g
->name
, tri
, g
->count
);
491 raster_draw_tri(p
, (tri_t
*)ti
->val
);
494 printf(PROGRESS_FMT
"\n", g
->name
, tri
, g
->count
);
497 IF_RENDER_PROGRESS(printf("render complete!\n"));
500 long dt
= timer_stop();
501 printf("time\t%.3fms\n", (float)dt
/ 1000.0f
);
This page took 0.054802 seconds and 4 git commands to generate.