* mcgarvey@eng.utah.edu
*/
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
+#include <cassert>
+#include <cerrno>
+#include <cstdio>
+#include <cstring>
-#include "list.h"
-#include "raster.h"
+#include "raster.hh"
struct raster
{
color_t* pixels;
- scal_t* zbuf;
int w, h;
int left, right, bottom, top;
- mat_t model;
- mat_t view;
- mat_t projection;
- mat_t modelviewprojection;
- mat_t viewport;
- bool dirty;
- const model_t* current;
-#if LIGHTING
- list_t* lights;
- color_t ambient;
- vec_t eye;
- color_t specular;
- scal_t shininess;
-#endif
-#if VERBOSITY >= 2
- unsigned total;
- unsigned clipped;
- unsigned culled;
-#endif
};
p->h = height;
raster_clear(p, fill);
raster_viewport(p, 0, 0, width, height);
- p->model = p->view = p->projection = MAT_IDENTITY;
- p->dirty = false;
- p->current = NULL;
-
-#if LIGHTING
- p->ambient = color_new(S(0.2), S(0.2), S(0.2), S(1.0));
- p->lights = NULL;
- p->specular = COLOR_WHITE;
- p->shininess = S(1.0);
-#endif
-
- p->zbuf = (scal_t*)mem_alloc(sizeof(scal_t) * size);
- for (size_t i = 0; i < size; ++i) {
- p->zbuf[i] = S(1.0);
- }
return p;
}
void raster_destroy(raster_t* p)
{
mem_free(p->pixels);
- mem_free(p->zbuf);
-#if LIGHTING
- list_destroy(&p->lights);
-#endif
mem_free(p);
}
-void raster_printstats(raster_t* p)
-{
-#if VERBOSITY >= 2
- unsigned drawn = p->total - p->clipped - p->culled;
- float percent = 100.0f * (float)drawn / (float)p->total;
- printf("culled\t%u\n"
- "clipped\t%u\n"
- "drawn\t%u (%6.2f%%)\n"
- "total\t%u\n", p->culled, p->clipped, drawn, percent, p->total);
-#endif
-}
-
-
-color_t raster_color(const raster_t* p, vec_t pt)
+color_t* raster_color(const raster_t* p, int x, int y)
{
- int u = (int)((scal_t)p->w * pt.x);
- int v = (int)((scal_t)p->h * pt.y);
- return p->pixels[p->w * (p->h - v - 1) + u];
+ return p->pixels + p->w * y + x;
}
int raster_width(const raster_t* p)
void* raster_data(const raster_t* p)
{
size_t size = p->w * p->h;
- rgba_t* data = mem_alloc(size * sizeof(rgba_t));
+ rgba_t* data = (rgba_t*)mem_alloc(size * sizeof(rgba_t));
for (int i = 0; i < size; ++i) {
data[i] = rgba_from_color(p->pixels[i]);
for (int i = 0; i < size; ++i) {
p->pixels[i] = fill;
}
-#if VERBOSITY >= 2
- p->total = 0;
- p->clipped = 0;
- p->culled = 0;
-#endif
}
p->right = x + width;
p->bottom = y;
p->top = y + height;
- p->viewport = MAT_VIEWPORT(x, y, width, height);
-}
-
-void raster_model(raster_t* p, const mat_t* transform)
-{
- p->model = *transform;
- p->dirty = true;
-}
-
-void raster_view(raster_t* p, const mat_t* transform)
-{
- p->view = *transform;
- p->dirty = true;
-}
-
-void raster_projection(raster_t* p, const mat_t* transform)
-{
- p->projection = *transform;
- p->dirty = true;
-}
-
-
-void raster_eye(raster_t* p, vec_t eye)
-{
-#if LIGHTING
- p->eye = eye;
-#endif
-}
-
-void raster_ambient(raster_t* p, color_t ambient)
-{
-#if LIGHTING
- p->ambient = ambient;
-#endif
-}
-
-void raster_light(raster_t* p, light_t light)
-{
-#if LIGHTING
- light_t* l = light_copy(light);
- list_push2(&p->lights, l, mem_free);
-#endif
-}
-
-void raster_material(raster_t* p, color_t specular, scal_t shininess)
-{
-#if LIGHTING
- p->specular = specular;
- p->shininess = shininess;
-#endif
}
raster_t* raster_import(const char* filename)
{
- int type = 0;
- char* ext = strrchr(filename, '.');
+ int type = 0;
+ const char* ext = strrchr(filename, '.');
if (ext == NULL) {
goto fail;
}
return NULL;
}
+ size_t size;
+
uint16_t magicNumber;
uint16_t reserved0;//0x4D41;
uint16_t reserved1;//0x5454;
p = raster_alloc((int)width, (int)height, COLOR_WHITE);
- size_t size = width * height;
+ size = width * height;
for (int i = 0; i < size; ++i)
{
union {
#undef _DO_OR_DIE
-
-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
- }
- }
- }
-}
-