]> Dogcows Code - chaz/rasterize/blob - scene.c
add texture mapping with perspective correction
[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 for (const list_t* i = model_geometry(m); i; i = i->link) {
174 tri_t* t = (tri_t*)i->val;
175 t->a.c = color;
176 t->b.c = color;
177 t->c.c = color;
178 }
179 return 0;
180 }
181
182 /*
183 * Concat a translation matrix to the transformation as defined in a file.
184 */
185 static int _model_add_translate(model_t* m, FILE* file)
186 {
187 double tx, ty, tz;
188 if (fscanf(file, " %lf %lf %lf", &tx, &ty, &tz) != 3) {
189 fprintf(stderr, "Cannot read translate coordinates from scene.\n");
190 return -1;
191 }
192 mat_t transform = MAT_TRANSLATE((scal_t)tx, (scal_t)ty, (scal_t)tz);
193 model_transform(m, &transform);
194 return 0;
195 }
196
197 /*
198 * Concat a rotation matrix to the transformation as defined in a file.
199 */
200 static int _model_add_rotate(model_t* m, FILE* file)
201 {
202 double theta, ax, ay, az;
203 if (fscanf(file, " %lf %lf %lf %lf", &theta, &ax, &ay, &az) != 4) {
204 fprintf(stderr, "Cannot read rotation angle from scene.\n");
205 return -1;
206 }
207 mat_t transform = MAT_ROTATE((scal_t)theta, (scal_t)ax, (scal_t)ay, (scal_t)az);
208 model_transform(m, &transform);
209 return 0;
210 }
211
212 /*
213 * Concat a scale matrix to the transformation as defined in a file.
214 */
215 static int _model_add_scale(model_t* m, FILE* file)
216 {
217 double sx, sy, sz;
218 if (fscanf(file, " %lf %lf %lf", &sx, &sy, &sz) != 3) {
219 fprintf(stderr, "Cannot read scale factors from scene.\n");
220 return -1;
221 }
222 mat_t transform = MAT_SCALE((scal_t)sx, (scal_t)sy, (scal_t)sz);
223 model_transform(m, &transform);
224 return 0;
225 }
226
227 /*
228 * Set the specular highlight and shininess factor for the group.
229 */
230 static int _model_set_material(model_t* m, FILE* file)
231 {
232 double sr, sg, sb, shininess;
233 if (fscanf(file, " %lf %lf %lf %lf", &sr, &sg, &sb, &shininess) != 4) {
234 fprintf(stderr, "Cannot read material information from scene.\n");
235 return -1;
236 }
237 model_material(m, color_new((scal_t)sr, (scal_t)sg, (scal_t)sb, S(1.0)), (scal_t)shininess);
238 return 0;
239 }
240
241 /*
242 * Set the texture to be used while drawing the current model.
243 */
244 static int _model_set_texture(model_t* m, FILE* file)
245 {
246 char filename[4096];
247 if (fgets(filename, 4096, file) == NULL) {
248 fprintf(stderr, "Cannot read texture filename from scene.\n");
249 return -1;
250 }
251 #if TEXTURING
252 model_texture(m, (const void*)raster_import(trim(filename)));
253 #endif
254 return 0;
255 }
256
257 /*
258 * Add a light to the scene.
259 */
260 static int _scene_add_light(scene_t* s, FILE* file)
261 {
262 double lx, ly, lz, r, g, b;
263 if (fscanf(file, " %lf %lf %lf %lf %lf %lf",
264 &lx, &ly, &lz, &r, &g, &b) != 6) {
265 fprintf(stderr, "Cannot read light values from scene.\n");
266 return -1;
267 }
268 light_t* l = light_alloc(
269 vec_new(lx, ly, lz),
270 color_new((scal_t)r, (scal_t)g, (scal_t)b, S(1.0)),
271 color_new((scal_t)r, (scal_t)g, (scal_t)b, S(1.0))
272 );
273 list_push2(&s->lights, l, mem_free);
274 return 0;
275 }
276
277
278 raster_t* scene_render(scene_t* s)
279 {
280 #if VERBOSITY >= 3
281 timer_start();
282 #endif
283
284 raster_t* p = raster_alloc(s->w, s->h, COLOR_BLACK);
285 raster_view(p, &s->view);
286 raster_projection(p, &s->projection);
287 raster_eye(p, s->eye);
288 raster_ambient(p, s->ambient);
289
290 for (list_t* i = s->lights; i; i = i->link) {
291 raster_light(p, *(light_t*)i->val);
292 }
293
294 #if VERBOSITY >= 3
295 printf("rendering scene...\n");
296 #endif
297
298 for (list_t* gi = s->models; gi; gi = gi->link) {
299 model_t* m = (model_t*)gi->val;
300 raster_draw_model(p, m);
301 }
302
303 #if VERBOSITY >= 3
304 long dt = timer_stop();
305 printf("render complete!\ntime\t%.3fms\n", (float)dt / 1000.0f);
306 #endif
307
308 return p;
309 }
310
This page took 0.044452 seconds and 4 git commands to generate.