cube

Dependencies:   mbed

Fork of manworm_tv_gpu by Jared DiCarlo

raster.cpp

Committer:
bwang
Date:
2019-01-15
Revision:
14:cd89c3c9978a
Parent:
13:9cf720873bf6

File content as of revision 14:cd89c3c9978a:

#include "mbed.h"
#include "main.h"

int8_t zbuf[XL][YL];

void clear_zbuf() {
    for (int i = 0; i < XL; i++) {
        for (int j = 0; j < YL; j++) {
            zbuf[i][j] = 127;
        }
    }
}

void hline(int16_t xmin, int16_t xmax, int16_t y, uint8_t color, int8_t zmin, int8_t zmax) {
    if (xmin < 0) xmin = 0;
    if (xmin >= XL) xmin = XL - 1;
    if (xmax < 0) xmax = 0;
    if (xmax >= XL) xmax = XL - 1;
    if (y < 0) y = 0;
    if (y >= YL) y = YL - 1;

    int tmp;
    if (xmax < xmin) {
        tmp = xmin;
        xmin = xmax;
        xmax = tmp;
        tmp = zmin;
        zmin = zmax;
        zmax = tmp;
    }

    if (xmin == xmax) { zbuf[xmin][y] = zmin; return; }
    int32_t u = ((zmax - zmin) << 16) / (xmax - xmin);
    int32_t z = zmin << 16;
    
    for (int16_t x = xmin; x <= xmax; x++) {
        z += u;
        int8_t z8 = (int8_t)(z >> 16);
        if (z8 < zbuf[x][y]) {
            zbuf[x][y] = z8;
            set_pixel(x, y, color);
        }
    }
}

//y2 == y3
void bottom_triangle(int16_t x1, int16_t y1, int16_t x2, int16_t y2, int16_t x3, int16_t y3, uint8_t color, int8_t z1, int8_t z2, int8_t z3) {
    if (y1 == y2) return;

    int32_t del1 = ((x2 - x1) << 16) / (y2 - y1);
    int32_t del2 = ((x3 - x1) << 16) / (y3 - y1);

    int32_t u1 = ((z2 - z1) << 16) / (y2 - y1), u2 = ((z3 - z1) << 16) / (y3 - y1);
    int32_t zl = z1 << 16, zr = z1 << 16;

    int32_t c1 = x1 << 16, c2 = x1 << 16;
    for (int y = y1; y <= y2; y++) {
        hline((int16_t)(c1 >> 16), (int16_t)(c2 >> 16), y, color, (int8_t)(zl >> 16), (int8_t)(zr >> 16));
        c1 += del1;
        c2 += del2;
        zl += u1;
        zr += u2;
    }
}

//y1 == y2
void top_triangle(int16_t x1, int16_t y1, int16_t x2, int16_t y2, int16_t x3, int16_t y3, uint8_t color, int8_t z1, int8_t z2, int8_t z3) {
    if (y2 == y3) return;

    int32_t del1 = ((x3 - x1) << 16) / (y3 - y1);
    int32_t del2 = ((x3 - x2) << 16) / (y3 - y2);

    int32_t u1 = ((z3 - z1) << 16) / (y3 - y1), u2 = ((z3 - z2) << 16) / (y3 - y2);
    int32_t zl = z3 << 16, zr = z3 << 16;

    int32_t c1 = x3 << 16, c2 = x3 << 16;
    for (int y = y3; y > y1; y--) {
        hline((int16_t)(c1 >> 16), (int16_t)(c2 >> 16), y, color, (int8_t)(zl >> 16), (int8_t)(zr >> 16));
        c1 -= del1;
        c2 -= del2;
        zl -= u1;
        zr -= u2;
    }
}

//y1 < y2 < y3
void sorted_triangle(int16_t x1, int16_t y1, int16_t x2, int16_t y2, int16_t x3, int16_t y3, uint8_t color, int8_t z1, int8_t z2, int8_t z3) {
    if (y2 == y3) {
        bottom_triangle(x1, y1, x2, y2, x3, y3, color, z1, z2, z3);
    }
    else if (y1 == y2) {
        top_triangle(x1, y1, x2, y2, x3, y3, color, z1, z2, z3);
    }
    else {
        int16_t x4 = (int16_t)(x1 + ((float)(y2 - y1) / (float)(y3 - y1))*(x3 - x1));
        int8_t z4 = (int8_t)(z1 + ((float)(y2 - y1) / (float)(y3 - y1))*(z3 - z1));
        bottom_triangle(x1, y1, x2, y2, x4, y2, color, z1, z2, z4);
        top_triangle(x2, y2, x4, y2, x3, y3, color, z2, z4, z3);
    }
}

void fill_triangle(int16_t x1, int16_t y1, int16_t x2, int16_t y2, int16_t x3, int16_t y3, uint8_t color, int8_t z1, int8_t z2, int8_t z3) {
    int16_t tx, ty;
    int8_t tz;
    if (y1 > y3) {
        tx = x1; ty = y1; tz = z1;
        x1 = x3; y1 = y3; z1 = z3;
        x3 = tx; y3 = ty; z3 = tz;
    }
    if (y1 > y2) {
        tx = x1; ty = y1; tz = z1;
        x1 = x2; y1 = y2; z1 = z2;
        x2 = tx; y2 = ty; z2 = tz;
    }
    if (y2 > y3) {
        tx = x2; ty = y2; tz = z2;
        x2 = x3; y2 = y3; z2 = z3;
        x3 = tx; y3 = ty; z3 = tz;
    }
    sorted_triangle(x1, y1, x2, y2, x3, y3, color, z1, z2, z3);
}

void fill_quad(int16_t x1, int16_t y1, int16_t x2, int16_t y2, int16_t x3, int16_t y3, int16_t x4, int16_t y4, uint8_t color, int8_t z1, int8_t z2, int8_t z3, int8_t z4) {
    fill_triangle(x1, y1, x2, y2, x3, y3, color, z1, z2, z3);
    fill_triangle(x1, y1, x3, y3, x4, y4, color, z1, z3, z4);
}

float qx[32];
float qy[32];
float qz[32];
int geom_index = 0;

uint8_t qcolor[32];
int color_index = 0;

void add_quad(float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3, float x4, float y4, float z4, uint8_t color) {
    qx[geom_index] = x1; qy[geom_index] = y1; qz[geom_index] = z1;
    geom_index++;
    qx[geom_index] = x2; qy[geom_index] = y2; qz[geom_index] = z2;
    geom_index++;
    qx[geom_index] = x3; qy[geom_index] = y3; qz[geom_index] = z3;
    geom_index++;
    qx[geom_index] = x4; qy[geom_index] = y4; qz[geom_index] = z4;
    geom_index++;
    
    qcolor[color_index] = color;
    color_index++;
}

float theta, phi, cx, cy, cz;

void project(float x, float y, float z, float cost, float sint, float cosp, float sinp, int16_t *xs, int16_t *ys, int8_t *zs) {
    float xo, yo, zo;
    xo = x; yo = y;
    x = xo * cost - yo * sint;
    y = xo * sint + yo * cost;
    yo = y; zo = z;
    y = yo * cosp - zo * sinp;
    z = yo * sinp + zo * cosp;
    z = cz - z;

    float scale = fabsf(z) / 256.f + 0.5f;

    *xs = (int16_t)(x / scale) + XL/2;
    *ys = (int16_t)(y / scale) + YL/2;
    if (z < -120) z = -120;
    if (z > 120) z = 120;
    *zs = (int8_t)z;
}

int16_t screen_x[4];
int16_t screen_y[4];
int8_t screen_z[4];

void render_quads() {
    float cost = cosf(theta);
    float sint = sinf(theta);
    float cosp = cosf(phi);
    float sinp = sinf(phi);

    for (int i = 0; i < geom_index / 4; i++) {
        for (int j = 0; j < 4; j++) {
            project(qx[4 * i + j], qy[4 * i + j], qz[4 * i + j], cost, sint, cosp, sinp, &screen_x[j], &screen_y[j], &screen_z[j]);
        }
        fill_quad(screen_x[0], screen_y[0], screen_x[1], screen_y[1], screen_x[2], screen_y[2], screen_x[3], screen_y[3], qcolor[i], screen_z[0], screen_z[1], screen_z[2], screen_z[3]);
    }
}