Basic 3D graphics for the MBED application-shield on-board LCD (initial/incomplete).

Dependents:   co657_lcdplay

Committer:
co657_frmb
Date:
Sun Nov 29 00:03:41 2015 +0000
Revision:
9:db4ec6f7d8b2
Parent:
8:55ee7af49f47
Font updates.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
co657_frmb 5:2aaaf4e78a53 1 /*
co657_frmb 5:2aaaf4e78a53 2 * g3d_render.cpp -- rendering stuff for G3D library
co657_frmb 5:2aaaf4e78a53 3 * Copyright (C) 2015 Fred Barnes, University of Kent
co657_frmb 5:2aaaf4e78a53 4 * GPL >= 2.0
co657_frmb 5:2aaaf4e78a53 5 */
co657_frmb 5:2aaaf4e78a53 6
co657_frmb 5:2aaaf4e78a53 7
co657_frmb 5:2aaaf4e78a53 8 #include "mbed.h"
co657_frmb 5:2aaaf4e78a53 9 #include "C12832.h"
co657_frmb 5:2aaaf4e78a53 10 #include "gfx3d.h"
co657_frmb 5:2aaaf4e78a53 11
co657_frmb 5:2aaaf4e78a53 12 #define DISPLAY_WIDTH (128)
co657_frmb 5:2aaaf4e78a53 13 #define DISPLAY_HEIGHT (32)
co657_frmb 5:2aaaf4e78a53 14
co657_frmb 5:2aaaf4e78a53 15 #define ZB_YSHIFT (7)
co657_frmb 5:2aaaf4e78a53 16
co657_frmb 5:2aaaf4e78a53 17 /* grotty: single global Z buffer that matches the LCD size */
co657_frmb 5:2aaaf4e78a53 18 static int16_t zbuffer[DISPLAY_HEIGHT * DISPLAY_WIDTH];
co657_frmb 5:2aaaf4e78a53 19
co657_frmb 5:2aaaf4e78a53 20 #define ZBUFFER(X,Y) zbuffer[(Y << ZB_YSHIFT) | X]
co657_frmb 5:2aaaf4e78a53 21
co657_frmb 5:2aaaf4e78a53 22 /**
co657_frmb 5:2aaaf4e78a53 23 * clears the Z buffer (sets all to maximum)
co657_frmb 5:2aaaf4e78a53 24 */
co657_frmb 5:2aaaf4e78a53 25 void gfx3d_clear_zb (void)
co657_frmb 5:2aaaf4e78a53 26 {
co657_frmb 5:2aaaf4e78a53 27 int i;
co657_frmb 5:2aaaf4e78a53 28 int lim = (DISPLAY_HEIGHT * DISPLAY_WIDTH) >> 1;
co657_frmb 5:2aaaf4e78a53 29 uint32_t *halfbuf = (uint32_t *)zbuffer;
co657_frmb 5:2aaaf4e78a53 30
co657_frmb 5:2aaaf4e78a53 31 for (i=0; i<lim; i++) {
co657_frmb 5:2aaaf4e78a53 32 halfbuf[i] = 0x7fff7fff;
co657_frmb 5:2aaaf4e78a53 33 }
co657_frmb 5:2aaaf4e78a53 34 }
co657_frmb 5:2aaaf4e78a53 35
co657_frmb 5:2aaaf4e78a53 36 #if 0
co657_frmb 5:2aaaf4e78a53 37 /**
co657_frmb 5:2aaaf4e78a53 38 * fixes scan-line starts/ends in a g3d_polyscan_t structure based on edge
co657_frmb 5:2aaaf4e78a53 39 */
co657_frmb 5:2aaaf4e78a53 40 static void gfx3d_polyfix (g3d_polyscan_t *dst, int16_t x1, int16_t y1, int32_t z1, int16_t x2, int16_t y2, int32_t z2, const float co_a, const float co_b, const float co_c, const float co_d)
co657_frmb 5:2aaaf4e78a53 41 {
co657_frmb 5:2aaaf4e78a53 42 if (y2 < y1) {
co657_frmb 5:2aaaf4e78a53 43 /* swap around: make sure we go in the same direction (down) */
co657_frmb 5:2aaaf4e78a53 44 int16_t t16;
co657_frmb 5:2aaaf4e78a53 45 int32_t t32;
co657_frmb 5:2aaaf4e78a53 46
co657_frmb 5:2aaaf4e78a53 47 t16 = x1;
co657_frmb 5:2aaaf4e78a53 48 x1 = x2;
co657_frmb 5:2aaaf4e78a53 49 x2 = t16;
co657_frmb 5:2aaaf4e78a53 50
co657_frmb 5:2aaaf4e78a53 51 t16 = y1;
co657_frmb 5:2aaaf4e78a53 52 y1 = y2;
co657_frmb 5:2aaaf4e78a53 53 y2 = t16;
co657_frmb 5:2aaaf4e78a53 54
co657_frmb 5:2aaaf4e78a53 55 t32 = z1;
co657_frmb 5:2aaaf4e78a53 56 z1 = z2;
co657_frmb 5:2aaaf4e78a53 57 z2 = t32;
co657_frmb 5:2aaaf4e78a53 58 }
co657_frmb 5:2aaaf4e78a53 59
co657_frmb 5:2aaaf4e78a53 60 /* scan limit */
co657_frmb 5:2aaaf4e78a53 61 if (y1 < dst->scan_s) {
co657_frmb 5:2aaaf4e78a53 62 dst->scan_s = y1;
co657_frmb 5:2aaaf4e78a53 63 }
co657_frmb 5:2aaaf4e78a53 64 if (y2 > dst->scan_e) {
co657_frmb 5:2aaaf4e78a53 65 dst->scan_e = y2;
co657_frmb 5:2aaaf4e78a53 66 }
co657_frmb 5:2aaaf4e78a53 67 if (y1 == y2) {
co657_frmb 5:2aaaf4e78a53 68 /* flat polygon */
co657_frmb 5:2aaaf4e78a53 69 dst->scans[y1][0] = x1;
co657_frmb 5:2aaaf4e78a53 70 dst->scans[y1][1] = x2;
co657_frmb 5:2aaaf4e78a53 71 dst->zscan[y1][0] = z1;
co657_frmb 5:2aaaf4e78a53 72 dst->zscan[y1][1] = z2;
co657_frmb 5:2aaaf4e78a53 73 } else {
co657_frmb 5:2aaaf4e78a53 74 /* vaguely complex polygon */
co657_frmb 5:2aaaf4e78a53 75 int x, y, z, step, z_step;
co657_frmb 5:2aaaf4e78a53 76
co657_frmb 5:2aaaf4e78a53 77 x = (int)x1 << 16;
co657_frmb 5:2aaaf4e78a53 78 step = ((int)(x2 - x1) << 16) / (int)(y2 - y1);
co657_frmb 5:2aaaf4e78a53 79 x += step;
co657_frmb 5:2aaaf4e78a53 80
co657_frmb 5:2aaaf4e78a53 81 z = z1;
co657_frmb 5:2aaaf4e78a53 82 z_step = (z2 - z1) / ((y2 - y1) + 1);
co657_frmb 5:2aaaf4e78a53 83 y1++;
co657_frmb 5:2aaaf4e78a53 84
co657_frmb 5:2aaaf4e78a53 85 for (y=y1; y<=y2; y++) {
co657_frmb 5:2aaaf4e78a53 86 if ((y >= 0) && (y < 32)) {
co657_frmb 5:2aaaf4e78a53 87 int shx = x >> 16;
co657_frmb 5:2aaaf4e78a53 88
co657_frmb 5:2aaaf4e78a53 89 if (x < 0) {
co657_frmb 5:2aaaf4e78a53 90 shx = shx - 65536;
co657_frmb 5:2aaaf4e78a53 91 }
co657_frmb 5:2aaaf4e78a53 92 if (dst->scans[y][0] == 0xff) {
co657_frmb 5:2aaaf4e78a53 93 /* start of scan */
co657_frmb 5:2aaaf4e78a53 94 uint8_t x8 = (uint8_t)(shx & 0xff);
co657_frmb 5:2aaaf4e78a53 95
co657_frmb 5:2aaaf4e78a53 96 if (x8 == 0xff) {
co657_frmb 5:2aaaf4e78a53 97 x8 = 128;
co657_frmb 5:2aaaf4e78a53 98 }
co657_frmb 5:2aaaf4e78a53 99 dst->scans[y][0] = x8;
co657_frmb 5:2aaaf4e78a53 100 if (co_c != 0.0f) {
co657_frmb 5:2aaaf4e78a53 101 dst->zscan[y][0] = (int32_t)(((-(co_a * (float)shx) - (co_b * (float)y)) - co_d) / co_c);
co657_frmb 5:2aaaf4e78a53 102 } else {
co657_frmb 5:2aaaf4e78a53 103 dst->zscan[y][0] = z;
co657_frmb 5:2aaaf4e78a53 104 }
co657_frmb 5:2aaaf4e78a53 105 } else {
co657_frmb 5:2aaaf4e78a53 106 /* end of scan */
co657_frmb 5:2aaaf4e78a53 107 uint8_t x8 = (uint8_t)(shx & 0xff);
co657_frmb 5:2aaaf4e78a53 108
co657_frmb 5:2aaaf4e78a53 109 if (x8 == 0xff) {
co657_frmb 5:2aaaf4e78a53 110 x8 = 128;
co657_frmb 5:2aaaf4e78a53 111 }
co657_frmb 5:2aaaf4e78a53 112 dst->scans[y][1] = x8;
co657_frmb 5:2aaaf4e78a53 113 if (co_c != 0.0f) {
co657_frmb 5:2aaaf4e78a53 114 dst->zscan[y][1] = (int32_t)(((-(co_a * (float)shx) - (co_b * (float)y)) - co_d) / co_c);
co657_frmb 5:2aaaf4e78a53 115 } else {
co657_frmb 5:2aaaf4e78a53 116 dst->zscan[y][1] = z;
co657_frmb 5:2aaaf4e78a53 117 }
co657_frmb 5:2aaaf4e78a53 118 }
co657_frmb 5:2aaaf4e78a53 119 }
co657_frmb 5:2aaaf4e78a53 120 x += step;
co657_frmb 5:2aaaf4e78a53 121 z += z_step;
co657_frmb 5:2aaaf4e78a53 122 }
co657_frmb 5:2aaaf4e78a53 123 }
co657_frmb 5:2aaaf4e78a53 124 }
co657_frmb 5:2aaaf4e78a53 125
co657_frmb 5:2aaaf4e78a53 126
co657_frmb 5:2aaaf4e78a53 127 /**
co657_frmb 5:2aaaf4e78a53 128 * takes a polygon structure and generates a set of scanline data from it
co657_frmb 5:2aaaf4e78a53 129 */
co657_frmb 5:2aaaf4e78a53 130 void gfx3d_polyscan (const g3d_poly_t *src, g3d_polyscan_t *dst)
co657_frmb 5:2aaaf4e78a53 131 {
co657_frmb 5:2aaaf4e78a53 132 int i;
co657_frmb 5:2aaaf4e78a53 133 float co_a, co_b, co_c, co_d;
co657_frmb 5:2aaaf4e78a53 134 float x1 = (float)src->x[0];
co657_frmb 5:2aaaf4e78a53 135 float y1 = (float)src->y[0];
co657_frmb 5:2aaaf4e78a53 136 float z1 = (float)src->z[0];
co657_frmb 5:2aaaf4e78a53 137 float x2 = (float)src->x[1];
co657_frmb 5:2aaaf4e78a53 138 float y2 = (float)src->y[1];
co657_frmb 5:2aaaf4e78a53 139 float z2 = (float)src->z[1];
co657_frmb 5:2aaaf4e78a53 140 float x3 = (float)src->x[2];
co657_frmb 5:2aaaf4e78a53 141 float y3 = (float)src->y[2];
co657_frmb 5:2aaaf4e78a53 142 float z3 = (float)src->z[2];
co657_frmb 5:2aaaf4e78a53 143
co657_frmb 5:2aaaf4e78a53 144 for (i=0; i<32; i++) {
co657_frmb 5:2aaaf4e78a53 145 dst->scans[i][0] = 0xff;
co657_frmb 5:2aaaf4e78a53 146 dst->scans[i][1] = 0xff;
co657_frmb 5:2aaaf4e78a53 147 dst->zscan[i][0] = 0;
co657_frmb 5:2aaaf4e78a53 148 dst->zscan[i][1] = 0;
co657_frmb 5:2aaaf4e78a53 149 }
co657_frmb 5:2aaaf4e78a53 150 dst->scan_s = 32;
co657_frmb 5:2aaaf4e78a53 151 dst->scan_e = 0;
co657_frmb 5:2aaaf4e78a53 152 dst->norm = src->norm;
co657_frmb 5:2aaaf4e78a53 153
co657_frmb 5:2aaaf4e78a53 154 /* coefficients for plane equations, Herne & Baker p308 */
co657_frmb 5:2aaaf4e78a53 155 co_a = ((y1 * (z2 - z3)) + (y2 * (z3 - z1))) + (y3 * (z1 - z2));
co657_frmb 5:2aaaf4e78a53 156 co_b = ((z1 * (x2 - x3)) + (z2 * (x3 - x1))) + (z3 * (x1 - x2));
co657_frmb 5:2aaaf4e78a53 157 co_c = ((x1 * (y2 - y3)) + (x2 * (y3 - y1))) + (x3 * (y1 - y2));
co657_frmb 5:2aaaf4e78a53 158 co_d = ((-x1 * ((y2 * z3) - (y3 * z2))) - (x2 * ((y3 * z1) - (y1 * z3)))) - (x3 * ((y1 * z2) - (y2 * z1)));
co657_frmb 5:2aaaf4e78a53 159
co657_frmb 5:2aaaf4e78a53 160 gfx3d_polyfix (dst, src->x[0], src->y[0], src->z[0], src->x[1], src->y[1], src->z[1], co_a, co_b, co_c, co_d);
co657_frmb 5:2aaaf4e78a53 161 gfx3d_polyfix (dst, src->x[1], src->y[1], src->z[1], src->x[2], src->y[2], src->z[2], co_a, co_b, co_c, co_d);
co657_frmb 5:2aaaf4e78a53 162 gfx3d_polyfix (dst, src->x[2], src->y[2], src->z[2], src->x[0], src->y[0], src->z[0], co_a, co_b, co_c, co_d);
co657_frmb 5:2aaaf4e78a53 163
co657_frmb 5:2aaaf4e78a53 164 if (dst->scan_s < 0) {
co657_frmb 5:2aaaf4e78a53 165 dst->scan_s = 0;
co657_frmb 5:2aaaf4e78a53 166 } else if (dst->scan_s >= 32) {
co657_frmb 5:2aaaf4e78a53 167 dst->scan_s = 31;
co657_frmb 5:2aaaf4e78a53 168 }
co657_frmb 5:2aaaf4e78a53 169 if (dst->scan_e < 0) {
co657_frmb 5:2aaaf4e78a53 170 dst->scan_e = 0;
co657_frmb 5:2aaaf4e78a53 171 } else if (dst->scan_e >= 32) {
co657_frmb 5:2aaaf4e78a53 172 dst->scan_e = 31;
co657_frmb 5:2aaaf4e78a53 173 }
co657_frmb 5:2aaaf4e78a53 174
co657_frmb 5:2aaaf4e78a53 175 }
co657_frmb 5:2aaaf4e78a53 176 #endif
co657_frmb 5:2aaaf4e78a53 177
co657_frmb 5:2aaaf4e78a53 178 static inline void gfx3d_swap_points (g3d_2p3_t *p1, g3d_2p3_t *p2)
co657_frmb 5:2aaaf4e78a53 179 {
co657_frmb 5:2aaaf4e78a53 180 uint32_t *v1 = (uint32_t *)p1;
co657_frmb 5:2aaaf4e78a53 181 uint32_t *v2 = (uint32_t *)p2;
co657_frmb 5:2aaaf4e78a53 182 uint32_t tmp;
co657_frmb 5:2aaaf4e78a53 183
co657_frmb 5:2aaaf4e78a53 184 tmp = *v1;
co657_frmb 5:2aaaf4e78a53 185 *v1 = *v2;
co657_frmb 5:2aaaf4e78a53 186 *v2 = tmp;
co657_frmb 5:2aaaf4e78a53 187
co657_frmb 5:2aaaf4e78a53 188 v1++, v2++;
co657_frmb 5:2aaaf4e78a53 189 tmp = *v1;
co657_frmb 5:2aaaf4e78a53 190 *v1 = *v2;
co657_frmb 5:2aaaf4e78a53 191 *v2 = tmp;
co657_frmb 5:2aaaf4e78a53 192 }
co657_frmb 5:2aaaf4e78a53 193
co657_frmb 5:2aaaf4e78a53 194 static inline void gfx3d_swap_txpoints (uint16_t *p1, uint16_t *p2)
co657_frmb 5:2aaaf4e78a53 195 {
co657_frmb 5:2aaaf4e78a53 196 uint16_t tmp = *p1;
co657_frmb 5:2aaaf4e78a53 197
co657_frmb 5:2aaaf4e78a53 198 *p1 = *p2;
co657_frmb 5:2aaaf4e78a53 199 *p2 = tmp;
co657_frmb 5:2aaaf4e78a53 200 return;
co657_frmb 5:2aaaf4e78a53 201 }
co657_frmb 5:2aaaf4e78a53 202
co657_frmb 5:2aaaf4e78a53 203 void gfx3d_sort_poly (g3d_poly_t *p)
co657_frmb 5:2aaaf4e78a53 204 {
co657_frmb 5:2aaaf4e78a53 205 /* arranges points in the polygon into left->right order -- crude */
co657_frmb 5:2aaaf4e78a53 206 if (p->pts[1].x < p->pts[0].x) {
co657_frmb 5:2aaaf4e78a53 207 /* point in 1 left of 0, swap */
co657_frmb 5:2aaaf4e78a53 208 gfx3d_swap_points (&(p->pts[0]), &(p->pts[1]));
co657_frmb 5:2aaaf4e78a53 209 gfx3d_swap_txpoints (&(p->tx_pts[0]), &(p->tx_pts[1]));
co657_frmb 5:2aaaf4e78a53 210 }
co657_frmb 5:2aaaf4e78a53 211 if (p->pts[2].x < p->pts[0].x) {
co657_frmb 5:2aaaf4e78a53 212 /* point in 2 left of 0, swap */
co657_frmb 5:2aaaf4e78a53 213 gfx3d_swap_points (&(p->pts[0]), &(p->pts[2]));
co657_frmb 5:2aaaf4e78a53 214 gfx3d_swap_txpoints (&(p->tx_pts[0]), &(p->tx_pts[2]));
co657_frmb 5:2aaaf4e78a53 215 }
co657_frmb 5:2aaaf4e78a53 216 if (p->pts[2].x < p->pts[1].x) {
co657_frmb 5:2aaaf4e78a53 217 /* point in 2 left of 1, swap */
co657_frmb 5:2aaaf4e78a53 218 gfx3d_swap_points (&(p->pts[1]), &(p->pts[2]));
co657_frmb 5:2aaaf4e78a53 219 gfx3d_swap_txpoints (&(p->tx_pts[1]), &(p->tx_pts[2]));
co657_frmb 5:2aaaf4e78a53 220 }
co657_frmb 5:2aaaf4e78a53 221 }
co657_frmb 5:2aaaf4e78a53 222
co657_frmb 5:2aaaf4e78a53 223
co657_frmb 5:2aaaf4e78a53 224 static inline void gfx3d_edgebuf_z_fixin (const g3d_2p3_t *p0, const g3d_2p3_t *p1, uint8_t *yedge, uint16_t *zedge, uint16_t xoff)
co657_frmb 5:2aaaf4e78a53 225 {
co657_frmb 5:2aaaf4e78a53 226 int32_t y = (p0->y << 16) | 0x8000; /* half-way... */
co657_frmb 5:2aaaf4e78a53 227 int32_t ydelta;
co657_frmb 5:2aaaf4e78a53 228 int32_t z = (p0->z << 16) | 0x8000; /* half-way... */
co657_frmb 5:2aaaf4e78a53 229 int32_t zdelta;
co657_frmb 5:2aaaf4e78a53 230 int x;
co657_frmb 5:2aaaf4e78a53 231
co657_frmb 5:2aaaf4e78a53 232 if (p0->x == p1->x) {
co657_frmb 5:2aaaf4e78a53 233 /* same X position -- should have been dealt with */
co657_frmb 5:2aaaf4e78a53 234 return;
co657_frmb 5:2aaaf4e78a53 235 }
co657_frmb 5:2aaaf4e78a53 236
co657_frmb 5:2aaaf4e78a53 237 ydelta = ((int32_t)(p1->y - p0->y) << 16) / (int32_t)(p1->x - p0->x);
co657_frmb 5:2aaaf4e78a53 238 zdelta = ((int32_t)(p1->z - p0->z) << 16) / (int32_t)(p1->x - p0->x);
co657_frmb 5:2aaaf4e78a53 239
co657_frmb 5:2aaaf4e78a53 240 for (x = p0->x; x <= p1->x; x++) {
co657_frmb 5:2aaaf4e78a53 241 int16_t rc_y;
co657_frmb 5:2aaaf4e78a53 242 int16_t rc_z;
co657_frmb 5:2aaaf4e78a53 243
co657_frmb 5:2aaaf4e78a53 244 if (x < 0) {
co657_frmb 5:2aaaf4e78a53 245 y += ydelta;
co657_frmb 5:2aaaf4e78a53 246 z += zdelta;
co657_frmb 5:2aaaf4e78a53 247 continue;
co657_frmb 5:2aaaf4e78a53 248 }
co657_frmb 5:2aaaf4e78a53 249 if (x >= DISPLAY_WIDTH) {
co657_frmb 5:2aaaf4e78a53 250 /* can't have any more */
co657_frmb 5:2aaaf4e78a53 251 return;
co657_frmb 5:2aaaf4e78a53 252 }
co657_frmb 5:2aaaf4e78a53 253
co657_frmb 5:2aaaf4e78a53 254 rc_y = (y >> 16);
co657_frmb 5:2aaaf4e78a53 255 if (rc_y < 0) {
co657_frmb 5:2aaaf4e78a53 256 y += ydelta;
co657_frmb 5:2aaaf4e78a53 257 z += zdelta;
co657_frmb 5:2aaaf4e78a53 258 continue;
co657_frmb 5:2aaaf4e78a53 259 }
co657_frmb 5:2aaaf4e78a53 260 if (rc_y >= DISPLAY_HEIGHT) {
co657_frmb 5:2aaaf4e78a53 261 y += ydelta;
co657_frmb 5:2aaaf4e78a53 262 z += zdelta;
co657_frmb 5:2aaaf4e78a53 263 continue;
co657_frmb 5:2aaaf4e78a53 264 }
co657_frmb 5:2aaaf4e78a53 265 yedge[x - xoff] = rc_y;
co657_frmb 5:2aaaf4e78a53 266 y += ydelta;
co657_frmb 5:2aaaf4e78a53 267
co657_frmb 5:2aaaf4e78a53 268 rc_z = (z >> 16);
co657_frmb 5:2aaaf4e78a53 269 zedge[x - xoff] = rc_z;
co657_frmb 5:2aaaf4e78a53 270 z += zdelta;
co657_frmb 5:2aaaf4e78a53 271 }
co657_frmb 5:2aaaf4e78a53 272 }
co657_frmb 5:2aaaf4e78a53 273
co657_frmb 5:2aaaf4e78a53 274
co657_frmb 5:2aaaf4e78a53 275 /**
co657_frmb 5:2aaaf4e78a53 276 * takes a polygon and fills an edge-buffer with it. Assumes triangular and sorted poly.
co657_frmb 5:2aaaf4e78a53 277 */
co657_frmb 5:2aaaf4e78a53 278 void gfx3d_edgebuf_z (const g3d_poly_t *src, g3d_edgebuf_t *dst)
co657_frmb 5:2aaaf4e78a53 279 {
co657_frmb 5:2aaaf4e78a53 280 if (src->pts[0].x < 0) {
co657_frmb 5:2aaaf4e78a53 281 /* left-hand point off-screen */
co657_frmb 5:2aaaf4e78a53 282 dst->xoff = 0;
co657_frmb 5:2aaaf4e78a53 283 } else {
co657_frmb 5:2aaaf4e78a53 284 dst->xoff = src->pts[0].x;
co657_frmb 5:2aaaf4e78a53 285 }
co657_frmb 5:2aaaf4e78a53 286 dst->s_end = (src->pts[2].x - src->pts[0].x) + 1;
co657_frmb 5:2aaaf4e78a53 287
co657_frmb 5:2aaaf4e78a53 288 if (src->pts[0].x == src->pts[2].x) {
co657_frmb 5:2aaaf4e78a53 289 /* vertical line only */
co657_frmb 5:2aaaf4e78a53 290 if (src->pts[0].y <= src->pts[1].y) {
co657_frmb 5:2aaaf4e78a53 291 /* p0 is above p1 */
co657_frmb 5:2aaaf4e78a53 292 if (src->pts[1].y < 0) {
co657_frmb 5:2aaaf4e78a53 293 /* off top */
co657_frmb 5:2aaaf4e78a53 294 dst->s_end = 0;
co657_frmb 5:2aaaf4e78a53 295 } else if (src->pts[0].y >= DISPLAY_HEIGHT) {
co657_frmb 5:2aaaf4e78a53 296 /* off bottom */
co657_frmb 5:2aaaf4e78a53 297 dst->s_end = 0;
co657_frmb 5:2aaaf4e78a53 298 } else {
co657_frmb 5:2aaaf4e78a53 299 if (src->pts[0].y < 0) {
co657_frmb 5:2aaaf4e78a53 300 dst->start[0] = 0;
co657_frmb 5:2aaaf4e78a53 301 } else {
co657_frmb 5:2aaaf4e78a53 302 dst->start[0] = src->pts[0].y;
co657_frmb 5:2aaaf4e78a53 303 }
co657_frmb 5:2aaaf4e78a53 304 if (src->pts[1].y >= DISPLAY_HEIGHT) {
co657_frmb 5:2aaaf4e78a53 305 dst->end[0] = DISPLAY_HEIGHT - 1;
co657_frmb 5:2aaaf4e78a53 306 } else {
co657_frmb 5:2aaaf4e78a53 307 dst->end[0] = src->pts[1].y;
co657_frmb 5:2aaaf4e78a53 308 }
co657_frmb 5:2aaaf4e78a53 309 /* if we over-shot, this will be wrong */
co657_frmb 5:2aaaf4e78a53 310 dst->zstart[0] = src->pts[0].z;
co657_frmb 5:2aaaf4e78a53 311 dst->zend[0] = src->pts[1].z;
co657_frmb 5:2aaaf4e78a53 312 }
co657_frmb 5:2aaaf4e78a53 313 } else {
co657_frmb 5:2aaaf4e78a53 314 if (src->pts[0].y < 0) {
co657_frmb 5:2aaaf4e78a53 315 /* off top */
co657_frmb 5:2aaaf4e78a53 316 dst->s_end = 0;
co657_frmb 5:2aaaf4e78a53 317 } else if (src->pts[1].y >= DISPLAY_HEIGHT) {
co657_frmb 5:2aaaf4e78a53 318 /* off bottom */
co657_frmb 5:2aaaf4e78a53 319 dst->s_end = 0;
co657_frmb 5:2aaaf4e78a53 320 } else {
co657_frmb 5:2aaaf4e78a53 321 if (src->pts[1].y < 0) {
co657_frmb 5:2aaaf4e78a53 322 dst->start[0] = 0;
co657_frmb 5:2aaaf4e78a53 323 } else {
co657_frmb 5:2aaaf4e78a53 324 dst->start[0] = src->pts[1].y;
co657_frmb 5:2aaaf4e78a53 325 }
co657_frmb 5:2aaaf4e78a53 326 if (src->pts[0].y >= DISPLAY_HEIGHT) {
co657_frmb 5:2aaaf4e78a53 327 dst->end[0] = DISPLAY_HEIGHT - 1;
co657_frmb 5:2aaaf4e78a53 328 } else {
co657_frmb 5:2aaaf4e78a53 329 dst->end[0] = src->pts[0].y;
co657_frmb 5:2aaaf4e78a53 330 }
co657_frmb 5:2aaaf4e78a53 331 /* if we over-shot, this will be wrong */
co657_frmb 5:2aaaf4e78a53 332 dst->zstart[0] = src->pts[1].z;
co657_frmb 5:2aaaf4e78a53 333 dst->zend[0] = src->pts[0].z;
co657_frmb 5:2aaaf4e78a53 334 }
co657_frmb 5:2aaaf4e78a53 335 }
co657_frmb 5:2aaaf4e78a53 336 return;
co657_frmb 5:2aaaf4e78a53 337 }
co657_frmb 5:2aaaf4e78a53 338
co657_frmb 5:2aaaf4e78a53 339 /* figure out whether the middle point belongs above or below the longest edge */
co657_frmb 5:2aaaf4e78a53 340 if (((src->pts[2].y - src->pts[0].y) * (src->pts[1].x - src->pts[0].x)) < ((src->pts[1].y - src->pts[0].y) * (src->pts[2].x - src->pts[0].x))) {
co657_frmb 5:2aaaf4e78a53 341 /* middle point is on the top-portion */
co657_frmb 5:2aaaf4e78a53 342 gfx3d_edgebuf_z_fixin (&(src->pts[0]), &(src->pts[1]), dst->start, dst->zstart, dst->xoff);
co657_frmb 5:2aaaf4e78a53 343 gfx3d_edgebuf_z_fixin (&(src->pts[1]), &(src->pts[2]), dst->start, dst->zstart, dst->xoff);
co657_frmb 5:2aaaf4e78a53 344 gfx3d_edgebuf_z_fixin (&(src->pts[0]), &(src->pts[2]), dst->end, dst->zend, dst->xoff);
co657_frmb 5:2aaaf4e78a53 345 } else {
co657_frmb 5:2aaaf4e78a53 346 /* middle point is on the bottom-portion */
co657_frmb 5:2aaaf4e78a53 347 gfx3d_edgebuf_z_fixin (&(src->pts[0]), &(src->pts[2]), dst->start, dst->zstart, dst->xoff);
co657_frmb 5:2aaaf4e78a53 348 gfx3d_edgebuf_z_fixin (&(src->pts[0]), &(src->pts[1]), dst->end, dst->zend, dst->xoff);
co657_frmb 5:2aaaf4e78a53 349 gfx3d_edgebuf_z_fixin (&(src->pts[1]), &(src->pts[2]), dst->end, dst->zend, dst->xoff);
co657_frmb 5:2aaaf4e78a53 350 }
co657_frmb 5:2aaaf4e78a53 351 }
co657_frmb 5:2aaaf4e78a53 352
co657_frmb 5:2aaaf4e78a53 353
co657_frmb 5:2aaaf4e78a53 354 /**
co657_frmb 8:55ee7af49f47 355 * takes a polygon (containing a texture) and an LCD and draws it.
co657_frmb 6:0bd002c936bb 356 *
co657_frmb 6:0bd002c936bb 357 * @param src Source polygon.
co657_frmb 6:0bd002c936bb 358 * @param lcd Display LCD to use (size fixed in various places..).
co657_frmb 5:2aaaf4e78a53 359 */
co657_frmb 8:55ee7af49f47 360 void gfx3d_polytxmap (const g3d_poly_t *src, C12832 &lcd)
co657_frmb 5:2aaaf4e78a53 361 {
co657_frmb 5:2aaaf4e78a53 362 /* assert: polygon points are in order left-to-right */
co657_frmb 5:2aaaf4e78a53 363 int16_t x, use_z = src->pts[0].z;
co657_frmb 5:2aaaf4e78a53 364 int32_t dydx_ab, dydx_ac, dydx_bc;
co657_frmb 5:2aaaf4e78a53 365 int32_t dudx_ab, dudx_ac, dudx_bc;
co657_frmb 5:2aaaf4e78a53 366 int32_t dvdx_ab, dvdx_ac, dvdx_bc;
co657_frmb 5:2aaaf4e78a53 367
co657_frmb 5:2aaaf4e78a53 368 if (src->pts[1].x > src->pts[0].x) {
co657_frmb 5:2aaaf4e78a53 369 /* we have a left-hand side */
co657_frmb 5:2aaaf4e78a53 370 dydx_ab = ((src->pts[1].y - src->pts[0].y) << 16) / (src->pts[1].x - src->pts[0].x);
co657_frmb 5:2aaaf4e78a53 371 dudx_ab = (((int32_t)(src->tx_pts[1] & 0xff) - (int32_t)(src->tx_pts[0] & 0xff)) << 16) / (int32_t)(src->pts[1].x - src->pts[0].x);
co657_frmb 5:2aaaf4e78a53 372 dvdx_ab = (((int32_t)(src->tx_pts[1] >> 8) - (int32_t)(src->tx_pts[0] >> 8)) << 16) / (int32_t)(src->pts[1].x - src->pts[0].x);
co657_frmb 5:2aaaf4e78a53 373 } else {
co657_frmb 5:2aaaf4e78a53 374 dydx_ab = 0;
co657_frmb 5:2aaaf4e78a53 375 dudx_ab = 0;
co657_frmb 5:2aaaf4e78a53 376 dvdx_ab = 0;
co657_frmb 5:2aaaf4e78a53 377 }
co657_frmb 5:2aaaf4e78a53 378 if (src->pts[2].x > src->pts[0].x) {
co657_frmb 5:2aaaf4e78a53 379 /* we have the long X edge */
co657_frmb 5:2aaaf4e78a53 380 dydx_ac = ((src->pts[2].y - src->pts[0].y) << 16) / (src->pts[2].x - src->pts[0].x);
co657_frmb 5:2aaaf4e78a53 381 dudx_ac = (((int32_t)(src->tx_pts[2] & 0xff) - (int32_t)(src->tx_pts[0] & 0xff)) << 16) / (int32_t)(src->pts[2].x - src->pts[0].x);
co657_frmb 5:2aaaf4e78a53 382 dvdx_ac = (((int32_t)(src->tx_pts[2] >> 8) - (int32_t)(src->tx_pts[0] >> 8)) << 16) / (int32_t)(src->pts[2].x - src->pts[0].x);
co657_frmb 5:2aaaf4e78a53 383 } else {
co657_frmb 5:2aaaf4e78a53 384 dydx_ac = 0;
co657_frmb 5:2aaaf4e78a53 385 dudx_ac = 0;
co657_frmb 5:2aaaf4e78a53 386 dvdx_ac = 0;
co657_frmb 5:2aaaf4e78a53 387 }
co657_frmb 5:2aaaf4e78a53 388 if (src->pts[2].x > src->pts[1].x) {
co657_frmb 5:2aaaf4e78a53 389 /* we have a right-hand side */
co657_frmb 5:2aaaf4e78a53 390 dydx_bc = ((src->pts[2].y - src->pts[1].y) << 16) / (src->pts[2].x - src->pts[1].x);
co657_frmb 5:2aaaf4e78a53 391 dudx_bc = (((int32_t)(src->tx_pts[2] & 0xff) - (int32_t)(src->tx_pts[1] & 0xff)) << 16) / (int32_t)(src->pts[2].x - src->pts[1].x);
co657_frmb 5:2aaaf4e78a53 392 dvdx_bc = (((int32_t)(src->tx_pts[2] >> 8) - (int32_t)(src->tx_pts[1] >> 8)) << 16) / (int32_t)(src->pts[2].x - src->pts[1].x);
co657_frmb 5:2aaaf4e78a53 393 } else {
co657_frmb 5:2aaaf4e78a53 394 dydx_bc = 0;
co657_frmb 5:2aaaf4e78a53 395 dudx_bc = 0;
co657_frmb 5:2aaaf4e78a53 396 dvdx_bc = 0;
co657_frmb 5:2aaaf4e78a53 397 }
co657_frmb 6:0bd002c936bb 398
co657_frmb 6:0bd002c936bb 399 /* Note:
co657_frmb 6:0bd002c936bb 400 * - mostly 16.16 fixpoint stuff.
co657_frmb 6:0bd002c936bb 401 * - could optimise more by better pixel plotting (directly into the buffer).
co657_frmb 6:0bd002c936bb 402 */
co657_frmb 6:0bd002c936bb 403
co657_frmb 5:2aaaf4e78a53 404 int32_t y_top = (src->pts[0].y << 16) + 0x8000;
co657_frmb 5:2aaaf4e78a53 405 int32_t y_bot = (src->pts[0].y << 16) + 0x8000;
co657_frmb 5:2aaaf4e78a53 406 int32_t tx_top_x = (src->tx_pts[0] & 0xff) << 16;
co657_frmb 5:2aaaf4e78a53 407 int32_t tx_top_y = (src->tx_pts[0] >> 8) << 16;
co657_frmb 5:2aaaf4e78a53 408 int32_t tx_bot_x = (src->tx_pts[0] & 0xff) << 16;
co657_frmb 5:2aaaf4e78a53 409 int32_t tx_bot_y = (src->tx_pts[0] >> 8) << 16;
co657_frmb 6:0bd002c936bb 410 int32_t tx_dudy, tx_dvdy;
co657_frmb 6:0bd002c936bb 411 int16_t ys;
co657_frmb 6:0bd002c936bb 412
co657_frmb 6:0bd002c936bb 413 /* the texture gradients (tx_dudy, tx_dvdy) are constant for any particular triangle */
co657_frmb 5:2aaaf4e78a53 414
co657_frmb 6:0bd002c936bb 415 int32_t tx_ctemp, tx_tall, p_y, tp_x, tp_y;
co657_frmb 6:0bd002c936bb 416
co657_frmb 6:0bd002c936bb 417 if (src->pts[2].x == src->pts[0].x) {
co657_frmb 6:0bd002c936bb 418 /* skinny */
co657_frmb 6:0bd002c936bb 419 tx_ctemp = 0;
co657_frmb 6:0bd002c936bb 420 } else {
co657_frmb 6:0bd002c936bb 421 tx_ctemp = ((src->pts[1].x - src->pts[0].x) << 16) / (src->pts[2].x - src->pts[0].x); /* factor of AB to AC, (fixpoint 0->1) */
co657_frmb 6:0bd002c936bb 422 }
co657_frmb 6:0bd002c936bb 423
co657_frmb 6:0bd002c936bb 424 p_y = y_top + ((src->pts[2].y - src->pts[0].y) * tx_ctemp);
co657_frmb 6:0bd002c936bb 425 tp_x = ((int32_t)(src->tx_pts[0] & 0xff) << 16) + ((int32_t)((src->tx_pts[2] & 0xff) - (src->tx_pts[0] & 0xff)) * tx_ctemp);
co657_frmb 6:0bd002c936bb 426 tp_y = ((int32_t)(src->tx_pts[0] >> 8) << 16) + ((int32_t)((src->tx_pts[2] >> 8) - (src->tx_pts[0] >> 8)) * tx_ctemp);
co657_frmb 6:0bd002c936bb 427
co657_frmb 6:0bd002c936bb 428 tx_tall = abs ((p_y - (src->pts[1].y << 16)) >> 8); /* height of tallest scan -- positive 24.8 fixpoint */
co657_frmb 6:0bd002c936bb 429
co657_frmb 6:0bd002c936bb 430 if (tx_tall == 0) {
co657_frmb 6:0bd002c936bb 431 /* flat in effect */
co657_frmb 6:0bd002c936bb 432 tx_dudy = 0;
co657_frmb 6:0bd002c936bb 433 tx_dvdy = 0;
co657_frmb 6:0bd002c936bb 434 ys = 1;
co657_frmb 6:0bd002c936bb 435 } else {
co657_frmb 6:0bd002c936bb 436 tx_dudy = (tp_x - ((int32_t)(src->tx_pts[1] & 0xff) << 16));
co657_frmb 6:0bd002c936bb 437 tx_dudy = (tx_dudy / tx_tall) << 8;
co657_frmb 6:0bd002c936bb 438 tx_dvdy = (tp_y - ((int32_t)(src->tx_pts[1] >> 8) << 16));
co657_frmb 6:0bd002c936bb 439 tx_dvdy = (tx_dvdy / tx_tall) << 8;
co657_frmb 6:0bd002c936bb 440 ys = (p_y > (src->pts[1].y << 16)) ? 1 : -1;
co657_frmb 6:0bd002c936bb 441 }
co657_frmb 6:0bd002c936bb 442
co657_frmb 5:2aaaf4e78a53 443 /* left-hand side */
co657_frmb 5:2aaaf4e78a53 444 for (x=src->pts[0].x; x<src->pts[1].x; x++) {
co657_frmb 5:2aaaf4e78a53 445 int16_t pix_y = (y_top >> 16);
co657_frmb 5:2aaaf4e78a53 446 int16_t bpix_y = (y_bot >> 16) + ys; /* make sure we include the bottom pixel */
co657_frmb 5:2aaaf4e78a53 447 int16_t y;
co657_frmb 6:0bd002c936bb 448 int16_t tpix_y, tpix_x;
co657_frmb 5:2aaaf4e78a53 449
co657_frmb 5:2aaaf4e78a53 450 int32_t stx_y = tx_top_y;
co657_frmb 5:2aaaf4e78a53 451 int32_t stx_x = tx_top_x;
co657_frmb 5:2aaaf4e78a53 452
co657_frmb 5:2aaaf4e78a53 453 y_top += dydx_ab; y_bot += dydx_ac;
co657_frmb 5:2aaaf4e78a53 454 tx_top_x += dudx_ab; tx_top_y += dvdx_ab;
co657_frmb 5:2aaaf4e78a53 455 tx_bot_x += dudx_ac; tx_bot_y += dvdx_ac;
co657_frmb 5:2aaaf4e78a53 456
co657_frmb 5:2aaaf4e78a53 457 if ((x < 0) || (x >= DISPLAY_WIDTH)) {
co657_frmb 5:2aaaf4e78a53 458 continue;
co657_frmb 5:2aaaf4e78a53 459 }
co657_frmb 5:2aaaf4e78a53 460
co657_frmb 5:2aaaf4e78a53 461 for (y=pix_y; y != bpix_y; y += ys) {
co657_frmb 5:2aaaf4e78a53 462 if ((y < 0) || (y >= DISPLAY_HEIGHT)) {
co657_frmb 6:0bd002c936bb 463 goto yl_loop_advance;
co657_frmb 5:2aaaf4e78a53 464 }
co657_frmb 5:2aaaf4e78a53 465 if (use_z > ZBUFFER (x, y)) {
co657_frmb 6:0bd002c936bb 466 goto yl_loop_advance;
co657_frmb 5:2aaaf4e78a53 467 }
co657_frmb 5:2aaaf4e78a53 468 ZBUFFER (x, y) = use_z;
co657_frmb 5:2aaaf4e78a53 469
co657_frmb 6:0bd002c936bb 470 tpix_y = (stx_y >> 16) & (DISPLAY_HEIGHT - 1);
co657_frmb 6:0bd002c936bb 471 tpix_x = (stx_x >> 16) & (DISPLAY_WIDTH - 1);
co657_frmb 5:2aaaf4e78a53 472
co657_frmb 8:55ee7af49f47 473 lcd.pixel_nochk_norm (x, y, g3d_texture_bit (src->txptr, tpix_x, tpix_y));
co657_frmb 6:0bd002c936bb 474 yl_loop_advance:
co657_frmb 5:2aaaf4e78a53 475 stx_x += tx_dudy;
co657_frmb 5:2aaaf4e78a53 476 stx_y += tx_dvdy;
co657_frmb 5:2aaaf4e78a53 477 }
co657_frmb 5:2aaaf4e78a53 478 }
co657_frmb 5:2aaaf4e78a53 479
co657_frmb 5:2aaaf4e78a53 480 y_top = (src->pts[1].y << 16) + 0x8000;
co657_frmb 5:2aaaf4e78a53 481 tx_top_x = (src->tx_pts[1] & 0xff) << 16;
co657_frmb 5:2aaaf4e78a53 482 tx_top_y = (src->tx_pts[1] >> 8) << 16;
co657_frmb 5:2aaaf4e78a53 483
co657_frmb 5:2aaaf4e78a53 484 /* right-hand side */
co657_frmb 5:2aaaf4e78a53 485 for (; x<src->pts[2].x; x++) {
co657_frmb 5:2aaaf4e78a53 486 int16_t pix_y = (y_top >> 16);
co657_frmb 5:2aaaf4e78a53 487 int16_t bpix_y = (y_bot >> 16) + ys;
co657_frmb 5:2aaaf4e78a53 488 int16_t y;
co657_frmb 6:0bd002c936bb 489 int16_t tpix_y, tpix_x;
co657_frmb 5:2aaaf4e78a53 490
co657_frmb 5:2aaaf4e78a53 491 int32_t stx_y = tx_top_y;
co657_frmb 5:2aaaf4e78a53 492 int32_t stx_x = tx_top_x;
co657_frmb 6:0bd002c936bb 493
co657_frmb 5:2aaaf4e78a53 494 y_top += dydx_bc; y_bot += dydx_ac;
co657_frmb 5:2aaaf4e78a53 495 tx_top_x += dudx_bc; tx_top_y += dvdx_bc;
co657_frmb 5:2aaaf4e78a53 496 tx_bot_x += dudx_ac; tx_bot_y += dvdx_ac;
co657_frmb 5:2aaaf4e78a53 497
co657_frmb 5:2aaaf4e78a53 498 if ((x < 0) || (x >= DISPLAY_WIDTH)) {
co657_frmb 5:2aaaf4e78a53 499 continue;
co657_frmb 5:2aaaf4e78a53 500 }
co657_frmb 5:2aaaf4e78a53 501
co657_frmb 5:2aaaf4e78a53 502 for (y=pix_y; y != bpix_y; y += ys) {
co657_frmb 5:2aaaf4e78a53 503 if ((y < 0) || (y >= DISPLAY_HEIGHT)) {
co657_frmb 6:0bd002c936bb 504 goto yr_loop_advance;
co657_frmb 5:2aaaf4e78a53 505 }
co657_frmb 5:2aaaf4e78a53 506 if (use_z > ZBUFFER (x, y)) {
co657_frmb 6:0bd002c936bb 507 goto yr_loop_advance;
co657_frmb 5:2aaaf4e78a53 508 }
co657_frmb 5:2aaaf4e78a53 509 ZBUFFER (x, y) = use_z;
co657_frmb 5:2aaaf4e78a53 510
co657_frmb 6:0bd002c936bb 511 tpix_y = (stx_y >> 16) & (DISPLAY_HEIGHT - 1);
co657_frmb 6:0bd002c936bb 512 tpix_x = (stx_x >> 16) & (DISPLAY_WIDTH - 1);
co657_frmb 5:2aaaf4e78a53 513
co657_frmb 8:55ee7af49f47 514 lcd.pixel_nochk_norm (x, y, g3d_texture_bit (src->txptr, tpix_x, tpix_y));
co657_frmb 5:2aaaf4e78a53 515
co657_frmb 6:0bd002c936bb 516 yr_loop_advance:
co657_frmb 5:2aaaf4e78a53 517 stx_x += tx_dudy;
co657_frmb 5:2aaaf4e78a53 518 stx_y += tx_dvdy;
co657_frmb 5:2aaaf4e78a53 519 }
co657_frmb 5:2aaaf4e78a53 520 }
co657_frmb 5:2aaaf4e78a53 521 }
co657_frmb 5:2aaaf4e78a53 522
co657_frmb 5:2aaaf4e78a53 523
co657_frmb 5:2aaaf4e78a53 524 /**
co657_frmb 6:0bd002c936bb 525 * takes a polygon, drawing it on the given LCD with shading based on normal value.
co657_frmb 6:0bd002c936bb 526 *
co657_frmb 6:0bd002c936bb 527 * @param src Source polygon.
co657_frmb 6:0bd002c936bb 528 * @param lcd Display LCD to use (size fixed in various places..).
co657_frmb 6:0bd002c936bb 529 */
co657_frmb 6:0bd002c936bb 530 void gfx3d_polynormmap (const g3d_poly_t *src, C12832 &lcd)
co657_frmb 6:0bd002c936bb 531 {
co657_frmb 6:0bd002c936bb 532 /* assert: polygon points are in order left-to-right */
co657_frmb 6:0bd002c936bb 533 int16_t x, use_z = src->pts[0].z;
co657_frmb 6:0bd002c936bb 534 int32_t dydx_ab, dydx_ac, dydx_bc;
co657_frmb 6:0bd002c936bb 535
co657_frmb 6:0bd002c936bb 536 if (src->pts[1].x > src->pts[0].x) {
co657_frmb 6:0bd002c936bb 537 /* we have a left-hand side */
co657_frmb 6:0bd002c936bb 538 dydx_ab = ((src->pts[1].y - src->pts[0].y) << 16) / (src->pts[1].x - src->pts[0].x);
co657_frmb 6:0bd002c936bb 539 } else {
co657_frmb 6:0bd002c936bb 540 dydx_ab = 0;
co657_frmb 6:0bd002c936bb 541 }
co657_frmb 6:0bd002c936bb 542 if (src->pts[2].x > src->pts[0].x) {
co657_frmb 6:0bd002c936bb 543 /* we have the long X edge */
co657_frmb 6:0bd002c936bb 544 dydx_ac = ((src->pts[2].y - src->pts[0].y) << 16) / (src->pts[2].x - src->pts[0].x);
co657_frmb 6:0bd002c936bb 545 } else {
co657_frmb 6:0bd002c936bb 546 dydx_ac = 0;
co657_frmb 6:0bd002c936bb 547 }
co657_frmb 6:0bd002c936bb 548 if (src->pts[2].x > src->pts[1].x) {
co657_frmb 6:0bd002c936bb 549 /* we have a right-hand side */
co657_frmb 6:0bd002c936bb 550 dydx_bc = ((src->pts[2].y - src->pts[1].y) << 16) / (src->pts[2].x - src->pts[1].x);
co657_frmb 6:0bd002c936bb 551 } else {
co657_frmb 6:0bd002c936bb 552 dydx_bc = 0;
co657_frmb 6:0bd002c936bb 553 }
co657_frmb 6:0bd002c936bb 554
co657_frmb 6:0bd002c936bb 555 /* Note:
co657_frmb 6:0bd002c936bb 556 * - mostly 16.16 fixpoint stuff.
co657_frmb 6:0bd002c936bb 557 * - could optimise more by better pixel plotting (directly into the buffer).
co657_frmb 6:0bd002c936bb 558 */
co657_frmb 6:0bd002c936bb 559
co657_frmb 6:0bd002c936bb 560 int32_t y_top = (src->pts[0].y << 16) + 0x8000;
co657_frmb 6:0bd002c936bb 561 int32_t y_bot = (src->pts[0].y << 16) + 0x8000;
co657_frmb 6:0bd002c936bb 562 int16_t ys;
co657_frmb 6:0bd002c936bb 563 int32_t tx_ctemp, tx_tall, p_y;
co657_frmb 6:0bd002c936bb 564 int bitstep = (32 - __CLZ (src->norm)) >> 2;
co657_frmb 6:0bd002c936bb 565 int pcount = 0;
co657_frmb 6:0bd002c936bb 566
co657_frmb 6:0bd002c936bb 567 if (bitstep == 0) {
co657_frmb 6:0bd002c936bb 568 bitstep = 1;
co657_frmb 6:0bd002c936bb 569 }
co657_frmb 6:0bd002c936bb 570 if (src->pts[2].x == src->pts[0].x) {
co657_frmb 6:0bd002c936bb 571 /* skinny */
co657_frmb 6:0bd002c936bb 572 tx_ctemp = 0;
co657_frmb 6:0bd002c936bb 573 } else {
co657_frmb 6:0bd002c936bb 574 tx_ctemp = ((src->pts[1].x - src->pts[0].x) << 16) / (src->pts[2].x - src->pts[0].x); /* factor of AB to AC, (fixpoint 0->1) */
co657_frmb 6:0bd002c936bb 575 }
co657_frmb 6:0bd002c936bb 576
co657_frmb 6:0bd002c936bb 577 p_y = y_top + ((src->pts[2].y - src->pts[0].y) * tx_ctemp);
co657_frmb 6:0bd002c936bb 578 tx_tall = abs ((p_y - (src->pts[1].y << 16)) >> 8); /* height of tallest scan -- positive 24.8 fixpoint */
co657_frmb 6:0bd002c936bb 579
co657_frmb 6:0bd002c936bb 580 if (tx_tall == 0) {
co657_frmb 6:0bd002c936bb 581 /* flat in effect */
co657_frmb 6:0bd002c936bb 582 ys = 1;
co657_frmb 6:0bd002c936bb 583 } else {
co657_frmb 6:0bd002c936bb 584 ys = (p_y > (src->pts[1].y << 16)) ? 1 : -1;
co657_frmb 6:0bd002c936bb 585 }
co657_frmb 6:0bd002c936bb 586
co657_frmb 6:0bd002c936bb 587 /* left-hand side */
co657_frmb 6:0bd002c936bb 588 for (x=src->pts[0].x; x<src->pts[1].x; x++) {
co657_frmb 6:0bd002c936bb 589 int16_t pix_y = (y_top >> 16);
co657_frmb 6:0bd002c936bb 590 int16_t bpix_y = (y_bot >> 16) + ys; /* make sure we include the bottom pixel */
co657_frmb 6:0bd002c936bb 591 int16_t y;
co657_frmb 6:0bd002c936bb 592
co657_frmb 6:0bd002c936bb 593 y_top += dydx_ab; y_bot += dydx_ac;
co657_frmb 6:0bd002c936bb 594
co657_frmb 6:0bd002c936bb 595 if ((x < 0) || (x >= DISPLAY_WIDTH)) {
co657_frmb 6:0bd002c936bb 596 continue;
co657_frmb 6:0bd002c936bb 597 }
co657_frmb 6:0bd002c936bb 598
co657_frmb 6:0bd002c936bb 599 pcount = 0;
co657_frmb 6:0bd002c936bb 600 for (y=pix_y; y != bpix_y; y += ys) {
co657_frmb 6:0bd002c936bb 601 if ((y < 0) || (y >= DISPLAY_HEIGHT)) {
co657_frmb 6:0bd002c936bb 602 continue;
co657_frmb 6:0bd002c936bb 603 }
co657_frmb 6:0bd002c936bb 604 if (use_z > ZBUFFER (x, y)) {
co657_frmb 6:0bd002c936bb 605 continue;
co657_frmb 6:0bd002c936bb 606 }
co657_frmb 6:0bd002c936bb 607 ZBUFFER (x, y) = use_z;
co657_frmb 6:0bd002c936bb 608
co657_frmb 7:393b963e7988 609 lcd.pixel_nochk_norm (x, y, (pcount == 0) ? 1 : 0);
co657_frmb 6:0bd002c936bb 610 if (!pcount) {
co657_frmb 6:0bd002c936bb 611 pcount = bitstep;
co657_frmb 6:0bd002c936bb 612 }
co657_frmb 6:0bd002c936bb 613 pcount--;
co657_frmb 6:0bd002c936bb 614 }
co657_frmb 6:0bd002c936bb 615 }
co657_frmb 6:0bd002c936bb 616
co657_frmb 6:0bd002c936bb 617 y_top = (src->pts[1].y << 16) + 0x8000;
co657_frmb 6:0bd002c936bb 618
co657_frmb 6:0bd002c936bb 619 /* right-hand side */
co657_frmb 6:0bd002c936bb 620 for (; x<src->pts[2].x; x++) {
co657_frmb 6:0bd002c936bb 621 int16_t pix_y = (y_top >> 16);
co657_frmb 6:0bd002c936bb 622 int16_t bpix_y = (y_bot >> 16) + ys;
co657_frmb 6:0bd002c936bb 623 int16_t y;
co657_frmb 6:0bd002c936bb 624
co657_frmb 6:0bd002c936bb 625 y_top += dydx_bc; y_bot += dydx_ac;
co657_frmb 6:0bd002c936bb 626
co657_frmb 6:0bd002c936bb 627 if ((x < 0) || (x >= DISPLAY_WIDTH)) {
co657_frmb 6:0bd002c936bb 628 continue;
co657_frmb 6:0bd002c936bb 629 }
co657_frmb 6:0bd002c936bb 630
co657_frmb 6:0bd002c936bb 631 pcount = 0;
co657_frmb 6:0bd002c936bb 632 for (y=pix_y; y != bpix_y; y += ys) {
co657_frmb 6:0bd002c936bb 633 if ((y < 0) || (y >= DISPLAY_HEIGHT)) {
co657_frmb 6:0bd002c936bb 634 continue;
co657_frmb 6:0bd002c936bb 635 }
co657_frmb 6:0bd002c936bb 636 if (use_z > ZBUFFER (x, y)) {
co657_frmb 6:0bd002c936bb 637 continue;
co657_frmb 6:0bd002c936bb 638 }
co657_frmb 6:0bd002c936bb 639 ZBUFFER (x, y) = use_z;
co657_frmb 6:0bd002c936bb 640
co657_frmb 7:393b963e7988 641 lcd.pixel_nochk_norm (x, y, (pcount == 0) ? 1 : 0);
co657_frmb 6:0bd002c936bb 642 if (!pcount) {
co657_frmb 6:0bd002c936bb 643 pcount = bitstep;
co657_frmb 6:0bd002c936bb 644 }
co657_frmb 6:0bd002c936bb 645 pcount--;
co657_frmb 6:0bd002c936bb 646 }
co657_frmb 6:0bd002c936bb 647 }
co657_frmb 6:0bd002c936bb 648 }
co657_frmb 6:0bd002c936bb 649
co657_frmb 6:0bd002c936bb 650
co657_frmb 6:0bd002c936bb 651 /**
co657_frmb 5:2aaaf4e78a53 652 * takes an edge-buffer and draws its wireframe on the given LCD (start and end).
co657_frmb 5:2aaaf4e78a53 653 */
co657_frmb 5:2aaaf4e78a53 654 void gfx3d_wireedge (const g3d_edgebuf_t *edge, C12832 &lcd)
co657_frmb 5:2aaaf4e78a53 655 {
co657_frmb 5:2aaaf4e78a53 656 int x;
co657_frmb 5:2aaaf4e78a53 657
co657_frmb 5:2aaaf4e78a53 658 if (edge->s_end == 1) {
co657_frmb 5:2aaaf4e78a53 659 /* special case: vertical line */
co657_frmb 5:2aaaf4e78a53 660 int xp = edge->xoff;
co657_frmb 5:2aaaf4e78a53 661 int y0 = edge->start[0];
co657_frmb 5:2aaaf4e78a53 662 int y1 = edge->end[0];
co657_frmb 5:2aaaf4e78a53 663 int ys = (y1 >= y0) ? 1 : -1;
co657_frmb 5:2aaaf4e78a53 664 int y;
co657_frmb 5:2aaaf4e78a53 665
co657_frmb 5:2aaaf4e78a53 666 int16_t z0 = edge->zstart[0];
co657_frmb 5:2aaaf4e78a53 667 int16_t z1 = edge->zend[0];
co657_frmb 5:2aaaf4e78a53 668 int32_t zval = (z0 << 16) | 0x8000; /* half-way.. */
co657_frmb 5:2aaaf4e78a53 669
co657_frmb 9:db4ec6f7d8b2 670 if (xp >= DISPLAY_WIDTH) {
co657_frmb 9:db4ec6f7d8b2 671 /* off right-hand edge */
co657_frmb 9:db4ec6f7d8b2 672 return;
co657_frmb 9:db4ec6f7d8b2 673 } else if (xp < 0) {
co657_frmb 9:db4ec6f7d8b2 674 /* off left-hand edge */
co657_frmb 9:db4ec6f7d8b2 675 return;
co657_frmb 9:db4ec6f7d8b2 676 }
co657_frmb 9:db4ec6f7d8b2 677
co657_frmb 5:2aaaf4e78a53 678 if ((y0 == y1) || ((y0 + ys) == y1)) {
co657_frmb 5:2aaaf4e78a53 679 /* one or two point, since we're narrow, just y0 */
co657_frmb 5:2aaaf4e78a53 680 if (z0 <= ZBUFFER (xp, y0)) {
co657_frmb 5:2aaaf4e78a53 681 ZBUFFER (xp, y0) = z0;
co657_frmb 7:393b963e7988 682 lcd.pixel_nochk_norm (xp, y0, 1);
co657_frmb 5:2aaaf4e78a53 683 }
co657_frmb 5:2aaaf4e78a53 684 } else {
co657_frmb 5:2aaaf4e78a53 685 /* long vertical poly, set all points except at y1 */
co657_frmb 5:2aaaf4e78a53 686 int32_t zdelta = ((int32_t)(z1 - z0) << 16) / (int32_t)(y1 - y0);
co657_frmb 5:2aaaf4e78a53 687 int16_t rc_z = z0;
co657_frmb 5:2aaaf4e78a53 688
co657_frmb 5:2aaaf4e78a53 689 for (y = y0; y != y1; y += ys) {
co657_frmb 5:2aaaf4e78a53 690 zval += zdelta;
co657_frmb 5:2aaaf4e78a53 691 rc_z = (zval >> 16);
co657_frmb 5:2aaaf4e78a53 692 if (rc_z <= ZBUFFER (xp, y)) {
co657_frmb 5:2aaaf4e78a53 693 ZBUFFER (xp, y) = rc_z;
co657_frmb 7:393b963e7988 694 lcd.pixel_nochk_norm (xp, y, 1);
co657_frmb 5:2aaaf4e78a53 695 }
co657_frmb 5:2aaaf4e78a53 696 }
co657_frmb 5:2aaaf4e78a53 697 }
co657_frmb 5:2aaaf4e78a53 698 return;
co657_frmb 5:2aaaf4e78a53 699 }
co657_frmb 5:2aaaf4e78a53 700
co657_frmb 5:2aaaf4e78a53 701 for (x=0; x<edge->s_end; x++) {
co657_frmb 5:2aaaf4e78a53 702 int xp = x + edge->xoff;
co657_frmb 5:2aaaf4e78a53 703 int y0 = edge->start[x];
co657_frmb 5:2aaaf4e78a53 704 int y1 = edge->end[x];
co657_frmb 5:2aaaf4e78a53 705 int ys = (y1 >= y0) ? 1 : -1;
co657_frmb 5:2aaaf4e78a53 706 int y;
co657_frmb 5:2aaaf4e78a53 707
co657_frmb 5:2aaaf4e78a53 708 int16_t z0 = edge->zstart[x];
co657_frmb 5:2aaaf4e78a53 709 int16_t z1 = edge->zend[x];
co657_frmb 5:2aaaf4e78a53 710
co657_frmb 5:2aaaf4e78a53 711 int32_t zval = (z0 << 16) | 0x8000; /* half-way.. */
co657_frmb 9:db4ec6f7d8b2 712
co657_frmb 9:db4ec6f7d8b2 713 if ((xp >= DISPLAY_WIDTH) || (xp < 0)) {
co657_frmb 9:db4ec6f7d8b2 714 continue;
co657_frmb 9:db4ec6f7d8b2 715 }
co657_frmb 9:db4ec6f7d8b2 716
co657_frmb 5:2aaaf4e78a53 717 if (y0 == y1) {
co657_frmb 5:2aaaf4e78a53 718 /* point, but we don't plot assuming it belongs to the adjoining polygon */
co657_frmb 5:2aaaf4e78a53 719 } else if ((y0 + ys) == y1) {
co657_frmb 5:2aaaf4e78a53 720 /* two-point poly, just plot y0 */
co657_frmb 5:2aaaf4e78a53 721 if (z0 <= ZBUFFER (xp, y0)) {
co657_frmb 5:2aaaf4e78a53 722 ZBUFFER (xp, y0) = z0;
co657_frmb 7:393b963e7988 723 lcd.pixel_nochk_norm (xp, y0, 1);
co657_frmb 5:2aaaf4e78a53 724 }
co657_frmb 5:2aaaf4e78a53 725 } else {
co657_frmb 5:2aaaf4e78a53 726 /* more than two points, shrink y1 to avoid plotting the last one here */
co657_frmb 5:2aaaf4e78a53 727 int32_t zdelta = ((int32_t)(z1 - z0) << 16) / (int32_t)(y1 - y0);
co657_frmb 5:2aaaf4e78a53 728 int16_t rc_z = z0;
co657_frmb 5:2aaaf4e78a53 729
co657_frmb 5:2aaaf4e78a53 730 y1 -= ys;
co657_frmb 5:2aaaf4e78a53 731
co657_frmb 5:2aaaf4e78a53 732 /* start at y0 */
co657_frmb 5:2aaaf4e78a53 733 y = y0;
co657_frmb 5:2aaaf4e78a53 734 if (rc_z <= ZBUFFER (xp, y)) {
co657_frmb 5:2aaaf4e78a53 735 ZBUFFER (xp, y) = rc_z;
co657_frmb 7:393b963e7988 736 lcd.pixel_nochk_norm (xp, y, 1);
co657_frmb 5:2aaaf4e78a53 737 }
co657_frmb 5:2aaaf4e78a53 738
co657_frmb 5:2aaaf4e78a53 739 for (y += ys; y != y1; y += ys) {
co657_frmb 5:2aaaf4e78a53 740 zval += zdelta;
co657_frmb 5:2aaaf4e78a53 741 rc_z = (zval >> 16);
co657_frmb 5:2aaaf4e78a53 742 if (rc_z <= ZBUFFER (xp, y)) {
co657_frmb 5:2aaaf4e78a53 743 ZBUFFER (xp, y) = rc_z;
co657_frmb 7:393b963e7988 744 lcd.pixel_nochk_norm (xp, y, 0);
co657_frmb 5:2aaaf4e78a53 745 }
co657_frmb 5:2aaaf4e78a53 746 }
co657_frmb 5:2aaaf4e78a53 747 /* last pixel at y1,z1 */
co657_frmb 5:2aaaf4e78a53 748 rc_z = z1;
co657_frmb 5:2aaaf4e78a53 749 if (rc_z <= ZBUFFER (xp, y1)) {
co657_frmb 5:2aaaf4e78a53 750 ZBUFFER (xp, y1) = rc_z;
co657_frmb 7:393b963e7988 751 lcd.pixel_nochk_norm (xp, y1, 1);
co657_frmb 5:2aaaf4e78a53 752 }
co657_frmb 5:2aaaf4e78a53 753 }
co657_frmb 5:2aaaf4e78a53 754
co657_frmb 5:2aaaf4e78a53 755 /* end of x-loop */
co657_frmb 5:2aaaf4e78a53 756 }
co657_frmb 5:2aaaf4e78a53 757 }
co657_frmb 5:2aaaf4e78a53 758