]>
Dogcows Code - chaz/rasterize/blob - scene.c
326091fea49b0b50e5a42f3d167c0af666f91d3b
3 * CS5600 University of Utah
5 * mcgarvey@eng.utah.edu
22 DECLARE_AND_DEFINE_MAP_TYPE3(vec_t
, list_t
*, vnorm
, vec_compare(*a
, *b
));
26 * Associate a triangle with one of its vertices.
28 static void _find_normals_add_vertex(map_t
* m
, vec_t v
, tri_t
* t
)
30 list_t
** l
= map_vnorm_search(m
, v
);
32 map_vnorm_data_t
* d
= map_vnorm_insert(m
, v
, NULL
);
39 * Associate a triangle with all of its vertices.
41 static void _find_normals_add_triangle(map_t
* m
, tri_t
* t
)
43 _find_normals_add_vertex(m
, t
->a
.v
, t
);
44 _find_normals_add_vertex(m
, t
->b
.v
, t
);
45 _find_normals_add_vertex(m
, t
->c
.v
, t
);
49 * Calculate an averaged normal from a list of triangles that share a common
52 static void _find_normals_average(const vec_t
* v
, list_t
** l
)
54 // first, compute the average normal
56 for (list_t
* i
= *l
; i
; i
= i
->link
) {
57 tri_t
* t
= (tri_t
*)i
->val
;
58 n
= vec_add(n
, tri_normal(*t
));
62 // set the normal on each triangle's vertex that is shared
64 tri_t
* t
= (tri_t
*)(*l
)->val
;
65 if (vec_isequal(*v
, t
->a
.v
)) {
68 else if (vec_isequal(*v
, t
->b
.v
)) {
71 else if (vec_isequal(*v
, t
->c
.v
)) {
82 * A group of triangles and a transformation.
93 typedef struct _group _group_t
;
96 #define _CHECK_IO(X) if ((X) <= 0) goto fail
99 * Try to read the triangle geometry from the cache file.
101 static int _group_try_read_cache(const char* filename
, list_t
** l
)
104 char* cachename
= mem_strcat(".", filename
);
105 FILE* file
= fopen(cachename
, "rb");
110 _CHECK_IO(fread(&count
, sizeof(count
), 1, file
));
112 float x1
, y1
, z1
, x2
, y2
, z2
, x3
, y3
, z3
;
113 for (int i
= 0; i
< count
; ++i
) {
114 _CHECK_IO(fread(&x1
, sizeof(float), 1, file
));
115 _CHECK_IO(fread(&y1
, sizeof(float), 1, file
));
116 _CHECK_IO(fread(&z1
, sizeof(float), 1, file
));
117 _CHECK_IO(fread(&x2
, sizeof(float), 1, file
));
118 _CHECK_IO(fread(&y2
, sizeof(float), 1, file
));
119 _CHECK_IO(fread(&z2
, sizeof(float), 1, file
));
120 _CHECK_IO(fread(&x3
, sizeof(float), 1, file
));
121 _CHECK_IO(fread(&y3
, sizeof(float), 1, file
));
122 _CHECK_IO(fread(&z3
, sizeof(float), 1, file
));
123 tri_t
* t
= tri_alloc(
124 vert_new2((scal_t
)x1
, (scal_t
)y1
, (scal_t
)z1
),
125 vert_new2((scal_t
)x2
, (scal_t
)y2
, (scal_t
)z2
),
126 vert_new2((scal_t
)x3
, (scal_t
)y3
, (scal_t
)z3
)
128 list_push2(l
, t
, mem_free
);
129 _CHECK_IO(fread(&x1
, sizeof(float), 1, file
));
130 _CHECK_IO(fread(&y1
, sizeof(float), 1, file
));
131 _CHECK_IO(fread(&z1
, sizeof(float), 1, file
));
132 _CHECK_IO(fread(&x2
, sizeof(float), 1, file
));
133 _CHECK_IO(fread(&y2
, sizeof(float), 1, file
));
134 _CHECK_IO(fread(&z2
, sizeof(float), 1, file
));
135 _CHECK_IO(fread(&x3
, sizeof(float), 1, file
));
136 _CHECK_IO(fread(&y3
, sizeof(float), 1, file
));
137 _CHECK_IO(fread(&z3
, sizeof(float), 1, file
));
138 t
->a
.n
= vec_new((scal_t
)x1
, (scal_t
)y1
, (scal_t
)z1
);
139 t
->b
.n
= vec_new((scal_t
)x2
, (scal_t
)y2
, (scal_t
)z2
);
140 t
->c
.n
= vec_new((scal_t
)x3
, (scal_t
)y3
, (scal_t
)z3
);
153 * Write the triangle data to the cache.
155 static void _group_write_cache(const char* filename
, int count
, list_t
* l
)
157 char* cachename
= mem_strcat(".", filename
);
158 FILE* file
= fopen(cachename
, "wb");
160 fprintf(stderr
, "Cannot write %s: %s\n", cachename
, strerror(errno
));
164 _CHECK_IO(fwrite(&count
, sizeof(count
), 1, file
));
165 for (list_t
* i
= l
; i
; i
= i
->link
) {
166 tri_t
* t
= (tri_t
*)i
->val
;
167 _CHECK_IO(fwrite(&t
->a
.v
.x
, sizeof(float), 1, file
));
168 _CHECK_IO(fwrite(&t
->a
.v
.y
, sizeof(float), 1, file
));
169 _CHECK_IO(fwrite(&t
->a
.v
.z
, sizeof(float), 1, file
));
170 _CHECK_IO(fwrite(&t
->b
.v
.x
, sizeof(float), 1, file
));
171 _CHECK_IO(fwrite(&t
->b
.v
.y
, sizeof(float), 1, file
));
172 _CHECK_IO(fwrite(&t
->b
.v
.z
, sizeof(float), 1, file
));
173 _CHECK_IO(fwrite(&t
->c
.v
.x
, sizeof(float), 1, file
));
174 _CHECK_IO(fwrite(&t
->c
.v
.y
, sizeof(float), 1, file
));
175 _CHECK_IO(fwrite(&t
->c
.v
.z
, sizeof(float), 1, file
));
176 _CHECK_IO(fwrite(&t
->a
.n
.x
, sizeof(float), 1, file
));
177 _CHECK_IO(fwrite(&t
->a
.n
.y
, sizeof(float), 1, file
));
178 _CHECK_IO(fwrite(&t
->a
.n
.z
, sizeof(float), 1, file
));
179 _CHECK_IO(fwrite(&t
->b
.n
.x
, sizeof(float), 1, file
));
180 _CHECK_IO(fwrite(&t
->b
.n
.y
, sizeof(float), 1, file
));
181 _CHECK_IO(fwrite(&t
->b
.n
.z
, sizeof(float), 1, file
));
182 _CHECK_IO(fwrite(&t
->c
.n
.x
, sizeof(float), 1, file
));
183 _CHECK_IO(fwrite(&t
->c
.n
.y
, sizeof(float), 1, file
));
184 _CHECK_IO(fwrite(&t
->c
.n
.z
, sizeof(float), 1, file
));
200 static void _group_destroy(_group_t
* g
)
203 list_destroy(&g
->triangles
);
208 * Allocate a group by reading raw triangle coordinates from a file.
210 static _group_t
* _group_alloc(const char* filename
)
212 _group_t
* g
= (_group_t
*)mem_alloc(sizeof(_group_t
));
214 g
->model
= MAT_IDENTITY
;
215 g
->name
= mem_strdup(filename
);
217 g
->specular
= COLOR_WHITE
;
218 g
->shininess
= S(64.0);
221 int r
= _group_try_read_cache(filename
, &g
->triangles
);
228 FILE* file
= fopen(filename
, "r");
230 fprintf(stderr
, "Cannot read %s: %s\n", filename
, strerror(errno
));
236 map_t
* m
= map_vnorm_alloc();
239 double x1
, y1
, z1
, x2
, y2
, z2
, x3
, y3
, z3
;
240 while (fscanf(file
, " %lf %lf %lf %lf %lf %lf %lf %lf %lf",
241 &x1
, &y1
, &z1
, &x2
, &y2
, &z2
, &x3
, &y3
, &z3
) == 9) {
242 tri_t
* t
= tri_alloc(
243 vert_new2((scal_t
)x1
, (scal_t
)y1
, (scal_t
)z1
),
244 vert_new2((scal_t
)x2
, (scal_t
)y2
, (scal_t
)z2
),
245 vert_new2((scal_t
)x3
, (scal_t
)y3
, (scal_t
)z3
)
247 list_push2(&g
->triangles
, t
, mem_free
);
251 vec_t n
= vec_normalize(tri_normal(*t
));
255 #elif PRE_NORMALS >= 2
256 _find_normals_add_triangle(m
, t
);
261 map_vnorm_call(m
, _find_normals_average
);
264 list_reverse(&g
->triangles
);
265 _group_write_cache(filename
, g
->count
, g
->triangles
);
271 if (g
->triangles
== NULL
) {
272 fprintf(stderr
, "No triangles read from %s\n", filename
);
282 * Set the colors of the triangles in the group as defined in a file.
284 static int _group_set_colors(_group_t
* g
, FILE* file
)
286 double r1
, g1
, b1
, r2
, g2
, b2
, r3
, g3
, b3
;
287 if (fscanf(file
, " %lf %lf %lf %lf %lf %lf %lf %lf %lf",
288 &r1
, &g1
, &b1
, &r2
, &g2
, &b2
, &r3
, &g3
, &b3
) != 9) {
289 fprintf(stderr
, "Cannot read color values from scene.\n");
293 for (list_t
* i
= g
->triangles
; i
; i
= i
->link
) {
294 tri_t
* t
= (tri_t
*)i
->val
;
295 t
->a
.c
= color_new((colorchan_t
)r1
, (colorchan_t
)g1
, (colorchan_t
)b1
, S(1.0));
296 t
->b
.c
= color_new((colorchan_t
)r2
, (colorchan_t
)g2
, (colorchan_t
)b2
, S(1.0));
297 t
->c
.c
= color_new((colorchan_t
)r3
, (colorchan_t
)g3
, (colorchan_t
)b3
, S(1.0));
303 * Concat a translation matrix to the transformation as defined in a file.
305 static int _group_add_translate(_group_t
* g
, FILE* file
)
308 if (fscanf(file
, " %lf %lf %lf", &tx
, &ty
, &tz
) != 3) {
309 fprintf(stderr
, "Cannot read translate coordinates from scene.\n");
312 g
->model
= mat_mult(g
->model
, MAT_TRANSLATE((scal_t
)tx
, (scal_t
)ty
, (scal_t
)tz
));
317 * Concat a rotation matrix to the transformation as defined in a file.
319 static int _group_add_rotate(_group_t
* g
, FILE* file
)
321 double theta
, ax
, ay
, az
;
322 if (fscanf(file
, " %lf %lf %lf %lf", &theta
, &ax
, &ay
, &az
) != 4) {
323 fprintf(stderr
, "Cannot read rotation angle from scene.\n");
326 g
->model
= mat_mult(g
->model
, MAT_ROTATE((scal_t
)theta
, (scal_t
)ax
, (scal_t
)ay
, (scal_t
)az
));
331 * Concat a scale matrix to the transformation as defined in a file.
333 static int _group_add_scale(_group_t
* g
, FILE* file
)
336 if (fscanf(file
, " %lf %lf %lf", &sx
, &sy
, &sz
) != 3) {
337 fprintf(stderr
, "Cannot read scale factors from scene.\n");
340 g
->model
= mat_mult(g
->model
, MAT_SCALE((scal_t
)sx
, (scal_t
)sy
, (scal_t
)sz
));
345 * Set the specular highlight and shininess factor for the group.
347 static int _group_set_material(_group_t
* g
, FILE* file
)
349 double sr
, sg
, sb
, shininess
;
350 if (fscanf(file
, " %lf %lf %lf %lf", &sr
, &sg
, &sb
, &shininess
) != 4) {
351 fprintf(stderr
, "Cannot read material information from scene.\n");
354 g
->specular
= color_new((scal_t
)sr
, (scal_t
)sg
, (scal_t
)sb
, S(1.0));
355 g
->shininess
= (scal_t
)shininess
;
373 * Set the ambient light properties of a scene.
375 static int _scene_set_ambient(scene_t
* s
, FILE* file
)
378 if (fscanf(file
, " %lf %lf %lf", &r
, &g
, &b
) != 3) {
379 fprintf(stderr
, "Cannot read ambient light from scene.\n");
382 s
->ambient
= color_new((scal_t
)r
, (scal_t
)g
, (scal_t
)b
, S(1.0));
386 static int _scene_add_light(scene_t
* s
, FILE* file
)
388 double lx
, ly
, lz
, dr
, dg
, db
, sr
, sg
, sb
;
389 if (fscanf(file
, " %lf %lf %lf %lf %lf %lf %lf %lf %lf",
390 &lx
, &ly
, &lz
, &dr
, &dg
, &db
, &sr
, &sg
, &sb
) != 9) {
391 fprintf(stderr
, "Cannot read light values from scene.\n");
394 light_t
* l
= light_alloc(
396 color_new(dr
, dg
, db
, S(1.0)),
397 color_new(sr
, sg
, sb
, S(1.0))
399 list_push2(&s
->lights
, l
, mem_free
);
404 scene_t
* scene_alloc(FILE* file
)
407 double eyeX
, eyeY
, eyeZ
, spotX
, spotY
, spotZ
, upX
, upY
, upZ
;
408 double fovy
, aspect
, near
, far
;
409 if (fscanf(file
, "U3 %d %d %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
411 &eyeX
, &eyeY
, &eyeZ
, &spotX
, &spotY
, &spotZ
, &upX
, &upY
, &upZ
,
412 &fovy
, &aspect
, &near
, &far
) != 15) {
413 fprintf(stderr
, "Cannot read scene header.\n");
417 scene_t
* s
= (scene_t
*)mem_alloc(sizeof(scene_t
));
421 s
->view
= MAT_LOOKAT(vec_new( (scal_t
)eyeX
, (scal_t
)eyeY
, (scal_t
)eyeZ
),
422 vec_new((scal_t
)spotX
, (scal_t
)spotY
, (scal_t
)spotZ
),
423 vec_new( (scal_t
)upX
, (scal_t
)upY
, (scal_t
)upZ
));
424 s
->eye
= vec_new(eyeX
, eyeY
, eyeZ
);
425 s
->projection
= MAT_PERSPECTIVE((scal_t
)fovy
, (scal_t
)aspect
, (scal_t
)near
, (scal_t
)far
);
427 s
->ambient
= color_new(S(0.05), S(0.05), S(0.05), S(1.0));
429 char grp_filename
[4096];
434 fprintf(stderr, "Unexpected line before group is specified.\n"); \
439 while (fscanf(file
, " %c", &type
) == 1) {
442 if (fgets(grp_filename
, 4096, file
) == NULL
) {
443 fprintf(stderr
, "Cannot read raw triangle filename.\n");
446 g
= _group_alloc(grp_filename
);
450 list_push2(&s
->groups
, g
, DTOR(_group_destroy
));
455 if (_group_set_colors(g
, file
) != 0) {
462 if (_group_add_translate(g
, file
) != 0) {
468 if (_group_add_rotate(g
, file
) != 0) {
475 if (_group_add_scale(g
, file
) != 0) {
481 if (_scene_set_ambient(s
, file
) != 0) {
487 if (_scene_add_light(s
, file
) != 0) {
494 if (_group_set_material(g
, file
) != 0) {
503 fprintf(stderr
, "Unknown identifier: %c\n", type
);
516 void scene_destroy(scene_t
* s
)
518 list_destroy(&s
->groups
);
519 list_destroy(&s
->lights
);
524 raster_t
* scene_render(scene_t
* s
)
530 raster_t
* p
= raster_alloc(s
->w
, s
->h
, COLOR_BLACK
);
531 raster_view(p
, &s
->view
);
532 raster_projection(p
, &s
->projection
);
533 raster_eye(p
, s
->eye
);
534 raster_ambient(p
, s
->ambient
);
536 for (list_t
* i
= s
->lights
; i
; i
= i
->link
) {
537 raster_light(p
, *(light_t
*)i
->val
);
541 #define PROGRESS_FMT "\033[80D\033[2K %s\t %9d / %d"
543 printf("render scene:\n");
546 for (list_t
* gi
= s
->groups
; gi
; gi
= gi
->link
) {
547 _group_t
* g
= (_group_t
*)gi
->val
;
548 raster_model(p
, &g
->model
);
549 raster_material(p
, g
->specular
, g
->shininess
);
550 IF_RENDER_PROGRESS(tri
= 0);
551 for (list_t
* ti
= g
->triangles
; ti
; ti
= ti
->link
) {
553 if (++tri
% 100 == 0) {
554 printf(PROGRESS_FMT
, g
->name
, tri
, g
->count
);
558 raster_draw_tri(p
, (tri_t
*)ti
->val
);
561 printf(PROGRESS_FMT
"\n", g
->name
, tri
, g
->count
);
564 IF_RENDER_PROGRESS(printf("render complete!\n"));
567 long dt
= timer_stop();
568 printf("time\t%.3fms\n", (float)dt
/ 1000.0f
);
This page took 0.062111 seconds and 4 git commands to generate.