+ mat_t transform = MAT_ROTATE((scal_t)theta, (scal_t)ax, (scal_t)ay, (scal_t)az);
+ model_transform(m, &transform);
+ return 0;
+}
+
+/*
+ * Concat a scale matrix to the transformation as defined in a file.
+ */
+static int _model_add_scale(model_t* m, FILE* file)
+{
+ double sx, sy, sz;
+ if (fscanf(file, " %lf %lf %lf", &sx, &sy, &sz) != 3) {
+ fprintf(stderr, "Cannot read scale factors from scene.\n");
+ return -1;
+ }
+ mat_t transform = MAT_SCALE((scal_t)sx, (scal_t)sy, (scal_t)sz);
+ model_transform(m, &transform);
+ return 0;
+}
+
+/*
+ * Set the specular highlight and shininess factor for the group.
+ */
+static int _model_set_material(model_t* m, FILE* file)
+{
+ double sr, sg, sb, shininess;
+ if (fscanf(file, " %lf %lf %lf %lf", &sr, &sg, &sb, &shininess) != 4) {
+ fprintf(stderr, "Cannot read material information from scene.\n");
+ return -1;
+ }
+ model_material(m, color_new((scal_t)sr, (scal_t)sg, (scal_t)sb, S(1.0)), (scal_t)shininess);
+ return 0;
+}
+
+/*
+ * Set the texture to be used while drawing the current model.
+ */
+static int _model_set_texture(model_t* m, FILE* file)
+{
+ char filename[4096];
+ if (fgets(filename, 4096, file) == NULL) {
+ fprintf(stderr, "Cannot read texture filename from scene.\n");
+ return -1;
+ }
+#if TEXTURING
+ model_texture(m, (const void*)raster_import(trim(filename)));
+#endif
+ return 0;
+}
+
+/*
+ * Add a light to the scene.
+ */
+static int _scene_add_light(scene_t* s, FILE* file)
+{
+ double lx, ly, lz, r, g, b;
+ if (fscanf(file, " %lf %lf %lf %lf %lf %lf",
+ &lx, &ly, &lz, &r, &g, &b) != 6) {
+ fprintf(stderr, "Cannot read light values from scene.\n");
+ return -1;
+ }
+ light_t* l = light_alloc(
+ vec_new(lx, ly, lz),
+ color_new((scal_t)r, (scal_t)g, (scal_t)b, S(1.0)),
+ color_new((scal_t)r, (scal_t)g, (scal_t)b, S(1.0))
+ );
+ list_push2(&s->lights, l, mem_free);
+ return 0;
+}
+
+
+raster_t* scene_render(scene_t* s)
+{
+#if VERBOSITY >= 3
+ timer_start();
+#endif
+
+ raster_t* p = raster_alloc(s->w, s->h, COLOR_BLACK);
+ raster_view(p, &s->view);
+ raster_projection(p, &s->projection);
+ raster_eye(p, s->eye);
+ raster_ambient(p, s->ambient);
+
+ for (list_t* i = s->lights; i; i = i->link) {
+ raster_light(p, *(light_t*)i->val);
+ }
+
+#if VERBOSITY >= 3
+ printf("rendering scene...\n");
+#endif
+
+ for (list_t* gi = s->models; gi; gi = gi->link) {
+ model_t* m = (model_t*)gi->val;
+ raster_draw_model(p, m);
+ }
+
+#if VERBOSITY >= 3
+ long dt = timer_stop();
+ printf("render complete!\ntime\t%.3fms\n", (float)dt / 1000.0f);
+#endif