-
-void raster_draw_model(raster_t* p, const model_t* model)
-{
-#if VERBOSITY >= 4
-#define PROGRESS_FMT "\033[80D\033[2K %s\t %9d / %d"
- int tri;
-#endif
-
- model_transformation(model, &p->model);
- p->dirty = true;
- raster_material(p, model_specular(model), model_shininess(model));
- p->current = model;
- IF_RENDER_PROGRESS(tri = 0);
- array_it_t it = array_begin(model_geometry(model));
- for (tri_t* t; t = array_it_tri_next(&it);) {
-#if VERBOSITY >= 4
- if (++tri % 100 == 0) {
- printf(PROGRESS_FMT, model_name(model), tri, model_size(model));
- fflush(stdout);
- }
-#endif
- raster_draw_tri(p, t);
- }
-#if VERBOSITY >= 4
- printf(PROGRESS_FMT"\n", model_name(model), tri, model_size(model));
-#endif
-}
-
-
-/*
- * See if the triangle is at all visible in the viewport. Also, minimize the
- * rectangle around the area that includes the triangle.
- */
-INLINE_MAYBE
-bool _try_clip(tri_t t, int* left, int* right, int* bottom, int* top)
-{
-#if CLIPPING
- aabb_t box = tri_aabb(t);
- if (box.min.z < S(-1.0) || S(1.0) < box.max.z) {
- return false;
- }
- *left = imax((int)scal_floor(box.min.x), *left);
- *right = imin((int)scal_ceil(box.max.x), *right);
- if (*right <= *left) {
- return false;
- }
- *bottom = imax((int)scal_floor(box.min.y), *bottom);
- *top = imin((int)scal_ceil(box.max.y), *top);
- if (*top <= *bottom) {
- return false;
- }
-#endif // CLIPPING
- return true;
-}
-
-/*
- * See whether or not we need to draw based on the orientation of the
- * triangle.
- */
-INLINE_MAYBE
-bool _try_cull_backface(tri_t t)
-{
-#if BACKFACE_CULLING
- vec_t n = tri_normal(t);
- if (n.z < S(0.0)) {
- return false;
- }
-#endif
- return true;
-}
-
-/*
- * Determine what color is associated with the given vertex.
- */
-INLINE_MAYBE
-color_t _do_phong_lighting(raster_t* p, vert_t vert)
-{
-#if TEXTURING
- vert.c = color_mult(vert.c, model_tcolor(p->current, vert.t));
-#endif
-#if LIGHTING
- color_t color = COLOR_BLACK;
- color.a = vert.c.a;
- for (list_t* i = p->lights; i; i = i->link) {
- light_t light = *(light_t*)i->val;
- vec_t mpos = vert.v;
- vec_t lpos = light.v;
- vec_t vpos = p->eye;
- vec_t n = vert.n;
- vec_t l = vec_normalize(vec_sub(lpos, mpos));
- vec_t r = vec_normalize(vec_sub(vec_scale(n, S(2.0) * vec_dot(n, l)), l));
- vec_t v = vec_normalize(vec_sub(vpos, mpos));
-
- scal_t kd = scal_max(vec_dot(l, n), S(0.0));
- color_t Id = color_scale2(light.d, vert.c, kd);
- scal_t ks = scal_pow(scal_max(vec_dot(r, v), S(0.0)), p->shininess);
- color_t Is = color_scale2(light.s, p->specular, ks);
-
- color = color_add2(color, Id, Is);
- }
- color_t Ia = color_mult(p->ambient, vert.c);
- return color_clamp(color_add(color, Ia));
-#else
- return vert.c;
-#endif // LIGHTING
-}
-
-void raster_draw_tri(raster_t* p, const tri_t* triangle)
-{
- IF_RASTER_STATS(++p->total);
- tri_t t = *triangle;
-
- // need to recalculate the model-view-projection matrix if any one of its
- // composing matrices have been changed
- if (p->dirty) {
- p->modelviewprojection = mat_mult(p->view, p->model);
- p->modelviewprojection = mat_mult(p->projection, p->modelviewprojection);
- p->dirty = false;
- }
-
- t = tri_transform(t, p->modelviewprojection);
-
- // save w-values for texture mapping perspective correction
- scal_t w1 = t.a.v.w;
- scal_t w2 = t.b.v.w;
- scal_t w3 = t.c.v.w;
-
- t = tri_homodiv(t);
-
- if (!_try_cull_backface(t)) {
- IF_RASTER_STATS(++p->culled);
- return;
- }
-
- t = tri_transform(t, p->viewport);
-
- int left = p->left;
- int right = p->right;
- int bottom = p->bottom;
- int top = p->top;
-
- if (!_try_clip(t, &left, &right, &bottom, &top)) {
- IF_RASTER_STATS(++p->clipped);
- return;
- }
-
-#if LIGHTING >= 1
- tri_t tl = tri_transform(*triangle, p->model);
- tl.a.t.w = w1;
- tl.b.t.w = w2;
- tl.c.t.w = w3;
-#endif
-
-#if LIGHTING == 1
- vert_t tv = vert_new(tri_midpoint(tl));
- tv.n = vec_normalize(tri_normal(tl));
- tv.c = tri_color(tl);
- color_t color = _do_phong_lighting(p, tv);
-#elif LIGHTING == 2 && SMOOTH_COLOR
- color_t color1 = _do_phong_lighting(p, tl.a);
- color_t color2 = _do_phong_lighting(p, tl.b);
- color_t color3 = _do_phong_lighting(p, tl.c);
-#elif LIGHTING == 2 && !SMOOTH_COLOR
- color_t c = tri_color(t);
- tl.a.c = tl.b.c = tl.c.c = c;
- color_t color1 = _do_phong_lighting(p, tl.a);
- color_t color2 = _do_phong_lighting(p, tl.b);
- color_t color3 = _do_phong_lighting(p, tl.c);
-#elif !LIGHTING && SMOOTH_COLOR
- color_t color1 = t.a.c;
- color_t color2 = t.b.c;
- color_t color3 = t.c.c;
-#else
- color_t color = tri_color(t);
-#endif
-
- for (int y = bottom; y < top; ++y) {
- for (int x = left; x < right; ++x) {
- vec_t v = vec_new((scal_t)x, (scal_t)y, S(0.0));
- scal_t b[3];
- if (tri_barycentric(t, b, v)) {
-#if DEPTH_TEST
- v.z = tri_z(t, b);
- scal_t* n = p->zbuf + y * p->w + x;
- if (S(-1.0) < v.z && v.z < *n) {
-#endif
- color_t* c = p->pixels + y * p->w + x;
- color_t newC;
-
-#if LIGHTING == 2 || (!LIGHTING && SMOOTH_COLOR)
- newC = color_interp2(color1, color2, color3, b);
-#elif LIGHTING == 3 && SMOOTH_COLOR
- newC = _do_phong_lighting(p, tri_interp(tl, b));
-#elif LIGHTING == 3 && !SMOOTH_COLOR
- vert_t d = vert_new(tri_point(t, b));
- d.c = tri_color(t);
- d.n = tri_normal2(t, b);
- newC = _do_phong_lighting(p, d);
-#else
- newC = color;
-#endif
-
-#if BLENDING
- *c = color_blend(*c, newC);
-#else
- *c = newC;
-#endif
-
-#if DEPTH_TEST
- *n = v.z;
- }
-#endif
- }
- }
- }
-}
-