initial commit
[chaz/rasterize] / scene.c
1
2 /*
3 * CS5600 University of Utah
4 * Charles McGarvey
5 * mcgarvey@eng.utah.edu
6 */
7
8 #include <errno.h>
9 #include <stdio.h>
10 #include <string.h>
11
12 #include "common.h"
13 #include "mat.h"
14 #include "list.h"
15 #include "scene.h"
16 #include "tri.h"
17
18
19 /*
20 * A group of triangles and a transformation.
21 */
22 struct _group
23 {
24 list_t* triangles;
25 mat_t modelview;
26 };
27 typedef struct _group _group_t;
28
29 /*
30 * Allocate a group by reading raw triangle coordinates from a file.
31 */
32 static _group_t* _group_alloc(const char* filename)
33 {
34 FILE* file = fopen(filename, "r");
35 if (file == NULL) {
36 fprintf(stderr, "Cannot read %s: %s\n", filename, strerror(errno));
37 return NULL;
38 }
39
40 _group_t* g = (_group_t*)mem_alloc(sizeof(_group_t));
41 g->triangles = NULL;
42 g->modelview = MAT_IDENTITY;
43
44 double x1, y1, z1, x2, y2, z2, x3, y3, z3;
45 while (fscanf(file, " %lf %lf %lf %lf %lf %lf %lf %lf %lf",
46 &x1, &y1, &z1, &x2, &y2, &z2, &x3, &y3, &z3) == 9) {
47 tri_t* t = tri_alloc(
48 vert_new2((scal_t)x1, (scal_t)y1, (scal_t)z1, COLOR_WHITE),
49 vert_new2((scal_t)x2, (scal_t)y2, (scal_t)z2, COLOR_WHITE),
50 vert_new2((scal_t)x3, (scal_t)y3, (scal_t)z3, COLOR_WHITE)
51 );
52 list_push2(&g->triangles, t, mem_free);
53 }
54 list_reverse(&g->triangles);
55
56 fclose(file);
57
58 if (g->triangles == NULL) {
59 fprintf(stderr, "No triangles coordinates read from %s\n", filename);
60 mem_free(g);
61 return NULL;
62 }
63
64 return g;
65 }
66
67 /*
68 * Destroy a group.
69 */
70 static void _group_destroy(_group_t* g)
71 {
72 list_destroy(g->triangles);
73 mem_free(g);
74 }
75
76
77 /*
78 * Set the colors of the triangles in the group as defined in a file.
79 */
80 static int _group_set_colors(_group_t* g, FILE* file)
81 {
82 double r1, g1, b1, r2, g2, b2, r3, g3, b3;
83 if (fscanf(file, " %lf %lf %lf %lf %lf %lf %lf %lf %lf",
84 &r1, &g1, &b1, &r2, &g2, &b2, &r3, &g3, &b3) != 9) {
85 fprintf(stderr, "Cannot read color values from scene file.\n");
86 return -1;
87 }
88
89 for (list_t* i = g->triangles; i; i = i->link) {
90 tri_t* t = (tri_t*)i->val;
91 t->a.c = color_new((colorchan_t)r1, (colorchan_t)g1, (colorchan_t)b1, S(1.0));
92 t->b.c = color_new((colorchan_t)r2, (colorchan_t)g2, (colorchan_t)b2, S(1.0));
93 t->c.c = color_new((colorchan_t)r3, (colorchan_t)g3, (colorchan_t)b3, S(1.0));
94 }
95 return 0;
96 }
97
98 /*
99 * Concat a translation matrix to the transformation as defined in a file.
100 */
101 static int _group_add_translate(_group_t* g, FILE* file)
102 {
103 double tx, ty;
104 if (fscanf(file, " %lf %lf", &tx, &ty) != 2) {
105 fprintf(stderr, "Cannot read translate coordinates from scene file.\n");
106 return -1;
107 }
108
109 g->modelview = mat_mult(g->modelview, MAT_TRANSLATE((scal_t)tx, (scal_t)ty, S(1.0)));
110 return 0;
111 }
112
113 /*
114 * Concat a rotation matrix to the transformation as defined in a file.
115 */
116 static int _group_add_rotate(_group_t* g, FILE* file)
117 {
118 double theta;
119 if (fscanf(file, " %lf", &theta) != 1) {
120 fprintf(stderr, "Cannot read rotation angle from scene file.\n");
121 return -1;
122 }
123
124 g->modelview = mat_mult(g->modelview, MAT_ROTATE_Z((scal_t)theta));
125 return 0;
126 }
127
128 /*
129 * Concat a scale matrix to the transformation as defined in a file.
130 */
131 static int _group_add_scale(_group_t* g, FILE* file)
132 {
133 double sx, sy;
134 if (fscanf(file, " %lf %lf", &sx, &sy) != 2) {
135 fprintf(stderr, "Cannot read scale factors from scene file.\n");
136 return -1;
137 }
138
139 g->modelview = mat_mult(g->modelview, MAT_SCALE((scal_t)sx, (scal_t)sy, S(1.0)));
140 return 0;
141 }
142
143
144 struct scene
145 {
146 list_t* groups;
147 int w;
148 int h;
149 mat_t projection;
150 };
151
152 scene_t* scene_alloc(const char* filename)
153 {
154 scene_t* s = (scene_t*)mem_alloc(sizeof(scene_t));
155 s->groups = NULL;
156
157 FILE* file = fopen(filename, "r");
158
159 int w, h;
160 double minX, minY, maxX, maxY;
161 if (fscanf(file, "U2 %d %d %lf %lf %lf %lf",
162 &w, &h, &minX, &minY, &maxX, &maxY) != 6) {
163 fprintf(stderr, "Cannot read scene file header.\n");
164 return NULL;
165 }
166
167 s->w = w;
168 s->h = h;
169 s->projection = MAT_ORTHO((scal_t)minX, (scal_t)maxX, (scal_t)minY, (scal_t)maxY);
170
171 char grp_filename[4096];
172 _group_t* g = NULL;
173
174 #define _ASSERT_G \
175 if (g == NULL) { \
176 fprintf(stderr, "Unexpected line before group is loaded.\n"); \
177 goto fail; \
178 }
179
180 char type;
181 while (fscanf(file, " %c", &type) == 1) {
182 switch (type) {
183 case 'g':
184 if (fgets(grp_filename, 4096, file) == NULL) {
185 fprintf(stderr, "Cannot read raw triangle filename.\n");
186 }
187 trim(grp_filename);
188 g = _group_alloc(grp_filename);
189 if (g == NULL) {
190 goto fail;
191 }
192 list_push2(&s->groups, g, DTOR(_group_destroy));
193 break;
194
195 case 'c':
196 _ASSERT_G;
197 if (_group_set_colors(g, file) != 0) {
198 goto fail;
199 }
200 break;
201
202 case 't':
203 _ASSERT_G;
204 if (_group_add_translate(g, file) != 0) {
205 goto fail;
206 }
207 break;
208
209 case 'r':
210 if (_group_add_rotate(g, file) != 0) {
211 goto fail;
212 }
213 break;
214
215 case 's':
216 _ASSERT_G;
217 if (_group_add_scale(g, file) != 0) {
218 goto fail;
219 }
220 break;
221
222 default:
223 fprintf(stderr, "Unknown identifier: %c\n", type);
224 }
225 }
226 list_reverse(&s->groups);
227
228 #undef _ASSERT_G
229
230 fclose(file);
231 return s;
232
233 fail:
234 scene_destroy(s);
235 return NULL;
236 }
237
238 void scene_destroy(scene_t* s)
239 {
240 list_destroy(s->groups);
241 mem_free(s);
242 }
243
244
245 pixmap_t* scene_render(scene_t* s)
246 {
247 pixmap_t* pix = pixmap_alloc(s->w, s->h, COLOR_BLACK);
248 pixmap_projection(pix, &s->projection);
249
250 for (list_t* gi = s->groups; gi; gi = gi->link) {
251 _group_t* g = (_group_t*)gi->val;
252 pixmap_modelview(pix, &g->modelview);
253 for (list_t* ti = g->triangles; ti; ti = ti->link) {
254 pixmap_draw_tri(pix, (tri_t*)ti->val);
255 }
256 }
257
258 return pix;
259 }
260
This page took 0.057575 seconds and 4 git commands to generate.