]>
Dogcows Code - chaz/rasterize/blob - scene.c
940767d4f339b6ea44478a8821c1cd6e4f7bd49f
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
);
50 * Calculate an averaged normal from a list of triangles that share a common
53 static void _find_normals_average(const vec_t
* v
, list_t
** l
)
55 // first, compute the average normal
57 for (list_t
* i
= *l
; i
; i
= i
->link
) {
58 tri_t
* t
= (tri_t
*)i
->val
;
59 n
= vec_add(n
, tri_normal(*t
));
63 // set the normal on each triangle's vertex that is shared
65 tri_t
* t
= (tri_t
*)(*l
)->val
;
66 if (vec_isequal(*v
, t
->a
.v
)) {
69 else if (vec_isequal(*v
, t
->b
.v
)) {
72 else if (vec_isequal(*v
, t
->c
.v
)) {
79 #endif // FIND_NORMALS
83 * A group of triangles and a transformation.
92 #define IF_RENDER_PROGRESS(X) X
94 #define IF_RENDER_PROGRESS(X)
97 typedef struct _group _group_t
;
100 * Allocate a group by reading raw triangle coordinates from a file.
102 static _group_t
* _group_alloc(const char* filename
)
104 FILE* file
= fopen(filename
, "r");
106 fprintf(stderr
, "Cannot read %s: %s\n", filename
, strerror(errno
));
110 _group_t
* g
= (_group_t
*)mem_alloc(sizeof(_group_t
));
112 g
->model
= MAT_IDENTITY
;
114 g
->name
= mem_strdup(filename
);
118 #if FIND_NORMALS == 2
119 map_t
* m
= map_vnorm_alloc();
122 double x1
, y1
, z1
, x2
, y2
, z2
, x3
, y3
, z3
;
123 while (fscanf(file
, " %lf %lf %lf %lf %lf %lf %lf %lf %lf",
124 &x1
, &y1
, &z1
, &x2
, &y2
, &z2
, &x3
, &y3
, &z3
) == 9) {
125 tri_t
* t
= tri_alloc(
126 vert_new2((scal_t
)x1
, (scal_t
)y1
, (scal_t
)z1
),
127 vert_new2((scal_t
)x2
, (scal_t
)y2
, (scal_t
)z2
),
128 vert_new2((scal_t
)x3
, (scal_t
)y3
, (scal_t
)z3
)
130 list_push2(&g
->triangles
, t
, mem_free
);
131 IF_RENDER_PROGRESS(++g
->count
);
133 #if FIND_NORMALS == 1
134 vec_t n
= vec_normalize(tri_normal(*t
));
138 #elif FIND_NORMALS == 2
139 _find_normals_add_triangle(m
, t
);
143 #if FIND_NORMALS == 2
144 map_vnorm_call(m
, _find_normals_average
);
150 if (g
->triangles
== NULL
) {
151 fprintf(stderr
, "No triangles coordinates read from %s\n", filename
);
162 static void _group_destroy(_group_t
* g
)
164 IF_RENDER_PROGRESS(mem_free(g
->name
));
165 list_destroy(g
->triangles
);
171 * Set the colors of the triangles in the group as defined in a file.
173 static int _group_set_colors(_group_t
* g
, FILE* file
)
175 double r1
, g1
, b1
, r2
, g2
, b2
, r3
, g3
, b3
;
176 if (fscanf(file
, " %lf %lf %lf %lf %lf %lf %lf %lf %lf",
177 &r1
, &g1
, &b1
, &r2
, &g2
, &b2
, &r3
, &g3
, &b3
) != 9) {
178 fprintf(stderr
, "Cannot read color values from scene file.\n");
182 for (list_t
* i
= g
->triangles
; i
; i
= i
->link
) {
183 tri_t
* t
= (tri_t
*)i
->val
;
184 t
->a
.c
= color_new((colorchan_t
)r1
, (colorchan_t
)g1
, (colorchan_t
)b1
, S(1.0));
185 t
->b
.c
= color_new((colorchan_t
)r2
, (colorchan_t
)g2
, (colorchan_t
)b2
, S(1.0));
186 t
->c
.c
= color_new((colorchan_t
)r3
, (colorchan_t
)g3
, (colorchan_t
)b3
, S(1.0));
192 * Concat a translation matrix to the transformation as defined in a file.
194 static int _group_add_translate(_group_t
* g
, FILE* file
)
197 if (fscanf(file
, " %lf %lf %lf", &tx
, &ty
, &tz
) != 3) {
198 fprintf(stderr
, "Cannot read translate coordinates from scene file.\n");
201 g
->model
= mat_mult(g
->model
, MAT_TRANSLATE((scal_t
)tx
, (scal_t
)ty
, (scal_t
)tz
));
206 * Concat a rotation matrix to the transformation as defined in a file.
208 static int _group_add_rotate(_group_t
* g
, FILE* file
)
210 double theta
, ax
, ay
, az
;
211 if (fscanf(file
, " %lf %lf %lf %lf", &theta
, &ax
, &ay
, &az
) != 4) {
212 fprintf(stderr
, "Cannot read rotation angle from scene file.\n");
215 g
->model
= mat_mult(g
->model
, MAT_ROTATE((scal_t
)theta
, (scal_t
)ax
, (scal_t
)ay
, (scal_t
)az
));
220 * Concat a scale matrix to the transformation as defined in a file.
222 static int _group_add_scale(_group_t
* g
, FILE* file
)
225 if (fscanf(file
, " %lf %lf %lf", &sx
, &sy
, &sz
) != 3) {
226 fprintf(stderr
, "Cannot read scale factors from scene file.\n");
229 g
->model
= mat_mult(g
->model
, MAT_SCALE((scal_t
)sx
, (scal_t
)sy
, (scal_t
)sz
));
244 scene_t
* scene_alloc(const char* filename
)
246 FILE* file
= fopen(filename
, "r");
248 fprintf(stderr
, "Cannot read %s: %s\n", filename
, strerror(errno
));
253 double eyeX
, eyeY
, eyeZ
, spotX
, spotY
, spotZ
, upX
, upY
, upZ
;
254 double fovy
, aspect
, near
, far
;
255 if (fscanf(file
, "U3 %d %d %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
257 &eyeX
, &eyeY
, &eyeZ
, &spotX
, &spotY
, &spotZ
, &upX
, &upY
, &upZ
,
258 &fovy
, &aspect
, &near
, &far
) != 15) {
259 fprintf(stderr
, "Cannot read scene file header.\n");
263 scene_t
* s
= (scene_t
*)mem_alloc(sizeof(scene_t
));
267 s
->view
= MAT_LOOKAT(vec_new( (scal_t
)eyeX
, (scal_t
)eyeY
, (scal_t
)eyeZ
),
268 vec_new((scal_t
)spotX
, (scal_t
)spotY
, (scal_t
)spotZ
),
269 vec_new( (scal_t
)upX
, (scal_t
)upY
, (scal_t
)upZ
));
270 s
->eye
= vec_new(eyeX
, eyeY
, eyeZ
);
271 s
->projection
= MAT_PERSPECTIVE((scal_t
)fovy
, (scal_t
)aspect
, (scal_t
)near
, (scal_t
)far
);
273 char grp_filename
[4096];
278 fprintf(stderr, "Unexpected line before group is specified.\n"); \
283 while (fscanf(file
, " %c", &type
) == 1) {
286 if (fgets(grp_filename
, 4096, file
) == NULL
) {
287 fprintf(stderr
, "Cannot read raw triangle filename.\n");
290 g
= _group_alloc(grp_filename
);
294 list_push2(&s
->groups
, g
, DTOR(_group_destroy
));
299 if (_group_set_colors(g
, file
) != 0) {
306 if (_group_add_translate(g
, file
) != 0) {
312 if (_group_add_rotate(g
, file
) != 0) {
319 if (_group_add_scale(g
, file
) != 0) {
325 fprintf(stderr
, "Unknown identifier: %c\n", type
);
339 void scene_destroy(scene_t
* s
)
341 list_destroy(s
->groups
);
346 raster_t
* scene_render(scene_t
* s
)
352 raster_t
* p
= raster_alloc(s
->w
, s
->h
, COLOR_BLACK
);
353 raster_view(p
, &s
->view
);
354 raster_projection(p
, &s
->projection
);
355 raster_eye(p
, s
->eye
);
357 raster_light(p
, light_new(COLOR_WHITE
, vec_new(S(5.0), S(3.0), S(6.0))));
358 raster_light(p
, light_new(COLOR_MAGENTA
, vec_new(S(-2.0), S(2.0), S(-2.0))));
361 #define PROGRESS_FMT "\033[80D\033[2K %s\t %9d / %d"
363 printf("render scene:\n");
366 for (list_t
* gi
= s
->groups
; gi
; gi
= gi
->link
) {
367 _group_t
* g
= (_group_t
*)gi
->val
;
368 raster_model(p
, &g
->model
);
369 IF_RENDER_PROGRESS(tri
= 0);
370 for (list_t
* ti
= g
->triangles
; ti
; ti
= ti
->link
) {
372 if (++tri
% 100 == 0) {
373 printf(PROGRESS_FMT
, g
->name
, tri
, g
->count
);
377 raster_draw_tri(p
, (tri_t
*)ti
->val
);
380 printf(PROGRESS_FMT
"\n", g
->name
, tri
, g
->count
);
383 IF_RENDER_PROGRESS(printf("render complete!\n"));
386 long dt
= timer_stop();
387 printf("time\t%.3fms\n", (float)dt
/ 1000.0f
);
This page took 0.045292 seconds and 4 git commands to generate.