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