]> Dogcows Code - chaz/rasterize/blob - scene.c
refactor triangle group into a separate class
[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
10 #include "list.h"
11 #include "model.h"
12 #include "mat.h"
13 #include "scene.h"
14
15
16 static int _model_set_colors(model_t* m, FILE* file);
17 static int _model_add_translate(model_t* m, FILE* file);
18 static int _model_add_rotate(model_t* m, FILE* file);
19 static int _model_add_scale(model_t* m, FILE* file);
20 static int _model_set_material(model_t* m, FILE* file);
21 static int _scene_set_ambient(scene_t* s, FILE* file);
22 static int _scene_add_light(scene_t* s, FILE* file);
23
24
25 struct scene
26 {
27 list_t* models;
28 int w, h;
29 mat_t view;
30 mat_t projection;
31 vec_t eye;
32 list_t* lights;
33 color_t ambient;
34 };
35
36
37 scene_t* scene_alloc(FILE* file)
38 {
39 int w, h;
40 double eyeX, eyeY, eyeZ, spotX, spotY, spotZ, upX, upY, upZ;
41 double fovy, aspect, near, far;
42 if (fscanf(file, "U3 %d %d %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf",
43 &w, &h,
44 &eyeX, &eyeY, &eyeZ, &spotX, &spotY, &spotZ, &upX, &upY, &upZ,
45 &fovy, &aspect, &near, &far) != 15) {
46 fprintf(stderr, "Cannot read scene header.\n");
47 return NULL;
48 }
49
50 scene_t* s = (scene_t*)mem_alloc(sizeof(scene_t));
51 s->models = NULL;
52 s->w = w;
53 s->h = h;
54 s->view = MAT_LOOKAT(vec_new( (scal_t)eyeX, (scal_t)eyeY, (scal_t)eyeZ),
55 vec_new((scal_t)spotX, (scal_t)spotY, (scal_t)spotZ),
56 vec_new( (scal_t)upX, (scal_t)upY, (scal_t)upZ));
57 s->eye = vec_new(eyeX, eyeY, eyeZ);
58 s->projection = MAT_PERSPECTIVE((scal_t)fovy, (scal_t)aspect, (scal_t)near, (scal_t)far);
59 s->lights = NULL;
60 s->ambient = color_new(S(0.05), S(0.05), S(0.05), S(1.0));
61
62 char filename[4096];
63 model_t* m = NULL;
64
65 #define _ASSERT_G \
66 if (m == NULL) { \
67 fprintf(stderr, "Unexpected line before group is specified.\n"); \
68 goto fail; \
69 }
70
71 char type;
72 while (fscanf(file, " %c", &type) == 1) {
73 switch (type) {
74 case 'g':
75 if (fgets(filename, 4096, file) == NULL) {
76 fprintf(stderr, "Cannot read model filename.\n");
77 }
78 m = model_alloc(trim(filename));
79 if (m == NULL) {
80 goto fail;
81 }
82 list_push2(&s->models, m, DTOR(model_destroy));
83 break;
84
85 case 'c':
86 _ASSERT_G;
87 if (_model_set_colors(m, file) != 0) {
88 goto fail;
89 }
90 break;
91
92 case 't':
93 _ASSERT_G;
94 if (_model_add_translate(m, file) != 0) {
95 goto fail;
96 }
97 break;
98
99 case 'r':
100 if (_model_add_rotate(m, file) != 0) {
101 goto fail;
102 }
103 break;
104
105 case 's':
106 _ASSERT_G;
107 if (_model_add_scale(m, file) != 0) {
108 goto fail;
109 }
110 break;
111
112 case 'A':
113 if (_scene_set_ambient(s, file) != 0) {
114 goto fail;
115 }
116 break;
117
118 case 'L':
119 if (_scene_add_light(s, file) != 0) {
120 goto fail;
121 }
122 break;
123
124 case 'M':
125 _ASSERT_G;
126 if (_model_set_material(m, file) != 0) {
127 goto fail;
128 }
129 break;
130
131 case 'X':
132 goto done;
133
134 default:
135 fprintf(stderr, "Unknown identifier: %c\n", type);
136 }
137 }
138 #undef _ASSERT_G
139
140 done:
141 return s;
142
143 fail:
144 scene_destroy(s);
145 return NULL;
146 }
147
148 void scene_destroy(scene_t* s)
149 {
150 list_destroy(&s->models);
151 list_destroy(&s->lights);
152 mem_free(s);
153 }
154
155
156 /*
157 * Set the colors of the triangles in the group as defined in a file.
158 */
159 static int _model_set_colors(model_t* m, FILE* file)
160 {
161 double r1, g1, b1, r2, g2, b2, r3, g3, b3;
162 if (fscanf(file, " %lf %lf %lf %lf %lf %lf %lf %lf %lf",
163 &r1, &g1, &b1, &r2, &g2, &b2, &r3, &g3, &b3) != 9) {
164 fprintf(stderr, "Cannot read color values from scene.\n");
165 return -1;
166 }
167
168 for (const list_t* i = model_geometry(m); i; i = i->link) {
169 tri_t* t = (tri_t*)i->val;
170 t->a.c = color_new((colorchan_t)r1, (colorchan_t)g1, (colorchan_t)b1, S(1.0));
171 t->b.c = color_new((colorchan_t)r2, (colorchan_t)g2, (colorchan_t)b2, S(1.0));
172 t->c.c = color_new((colorchan_t)r3, (colorchan_t)g3, (colorchan_t)b3, S(1.0));
173 }
174 return 0;
175 }
176
177 /*
178 * Concat a translation matrix to the transformation as defined in a file.
179 */
180 static int _model_add_translate(model_t* m, FILE* file)
181 {
182 double tx, ty, tz;
183 if (fscanf(file, " %lf %lf %lf", &tx, &ty, &tz) != 3) {
184 fprintf(stderr, "Cannot read translate coordinates from scene.\n");
185 return -1;
186 }
187 mat_t transform = MAT_TRANSLATE((scal_t)tx, (scal_t)ty, (scal_t)tz);
188 model_transform(m, &transform);
189 return 0;
190 }
191
192 /*
193 * Concat a rotation matrix to the transformation as defined in a file.
194 */
195 static int _model_add_rotate(model_t* m, FILE* file)
196 {
197 double theta, ax, ay, az;
198 if (fscanf(file, " %lf %lf %lf %lf", &theta, &ax, &ay, &az) != 4) {
199 fprintf(stderr, "Cannot read rotation angle from scene.\n");
200 return -1;
201 }
202 mat_t transform = MAT_ROTATE((scal_t)theta, (scal_t)ax, (scal_t)ay, (scal_t)az);
203 model_transform(m, &transform);
204 return 0;
205 }
206
207 /*
208 * Concat a scale matrix to the transformation as defined in a file.
209 */
210 static int _model_add_scale(model_t* m, FILE* file)
211 {
212 double sx, sy, sz;
213 if (fscanf(file, " %lf %lf %lf", &sx, &sy, &sz) != 3) {
214 fprintf(stderr, "Cannot read scale factors from scene.\n");
215 return -1;
216 }
217 mat_t transform = MAT_SCALE((scal_t)sx, (scal_t)sy, (scal_t)sz);
218 model_transform(m, &transform);
219 return 0;
220 }
221
222 /*
223 * Set the specular highlight and shininess factor for the group.
224 */
225 static int _model_set_material(model_t* m, FILE* file)
226 {
227 double sr, sg, sb, shininess;
228 if (fscanf(file, " %lf %lf %lf %lf", &sr, &sg, &sb, &shininess) != 4) {
229 fprintf(stderr, "Cannot read material information from scene.\n");
230 return -1;
231 }
232 model_material(m, color_new((scal_t)sr, (scal_t)sg, (scal_t)sb, S(1.0)), (scal_t)shininess);
233 return 0;
234 }
235
236 /*
237 * Set the ambient light properties of a scene.
238 */
239 static int _scene_set_ambient(scene_t* s, FILE* file)
240 {
241 double r, g, b;
242 if (fscanf(file, " %lf %lf %lf", &r, &g, &b) != 3) {
243 fprintf(stderr, "Cannot read ambient light from scene.\n");
244 return -1;
245 }
246 s->ambient = color_new((scal_t)r, (scal_t)g, (scal_t)b, S(1.0));
247 return 0;
248 }
249
250 /*
251 * Add a light to the scene.
252 */
253 static int _scene_add_light(scene_t* s, FILE* file)
254 {
255 double lx, ly, lz, dr, dg, db, sr, sg, sb;
256 if (fscanf(file, " %lf %lf %lf %lf %lf %lf %lf %lf %lf",
257 &lx, &ly, &lz, &dr, &dg, &db, &sr, &sg, &sb) != 9) {
258 fprintf(stderr, "Cannot read light values from scene.\n");
259 return -1;
260 }
261 light_t* l = light_alloc(
262 vec_new(lx, ly, lz),
263 color_new(dr, dg, db, S(1.0)),
264 color_new(sr, sg, sb, S(1.0))
265 );
266 list_push2(&s->lights, l, mem_free);
267 return 0;
268 }
269
270
271 raster_t* scene_render(scene_t* s)
272 {
273 #if VERBOSITY >= 3
274 timer_start();
275 #endif
276
277 raster_t* p = raster_alloc(s->w, s->h, COLOR_BLACK);
278 raster_view(p, &s->view);
279 raster_projection(p, &s->projection);
280 raster_eye(p, s->eye);
281 raster_ambient(p, s->ambient);
282
283 for (list_t* i = s->lights; i; i = i->link) {
284 raster_light(p, *(light_t*)i->val);
285 }
286
287 #if VERBOSITY >= 3
288 printf("rendering scene...\n");
289 #endif
290
291 for (list_t* gi = s->models; gi; gi = gi->link) {
292 model_t* m = (model_t*)gi->val;
293 raster_draw_model(p, m);
294 }
295
296 #if VERBOSITY >= 3
297 long dt = timer_stop();
298 printf("render complete!\ntime\t%.3fms\n", (float)dt / 1000.0f);
299 #endif
300
301 return p;
302 }
303
This page took 0.053172 seconds and 5 git commands to generate.