deepstone

annotate src/scantmpl.h @ 28:11d14f688485

added clipping
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 22 Sep 2013 06:38:08 +0300
parents 5ff8ce78059a
children 17a5107b6fa4
rev   line source
nuclear@25 1 static void SCAN_EDGE(VERTEX *v0, VERTEX *v1)
nuclear@0 2 {
nuclear@0 3 int i, start, end;
nuclear@25 4 fixed dx, dy, dfdx;
nuclear@0 5 #ifdef INTERP_DEPTH
nuclear@25 6 fixed z, dz, dfdz;
nuclear@0 7 #endif
nuclear@0 8 #ifdef INTERP_ENERGY
nuclear@25 9 fixed e, de, dfde;
nuclear@0 10 #endif
nuclear@3 11 #ifdef INTERP_TEX
nuclear@25 12 fixed u, v, du, dv, dfdu, dfdv;
nuclear@3 13 #endif
nuclear@25 14 fixed x;
nuclear@25 15 VERTEX *edge;
nuclear@0 16
nuclear@0 17 dy = v1->pos.y - v0->pos.y;
nuclear@25 18 if(dy < FIXED_EPSILON && dy > -FIXED_EPSILON) {
nuclear@0 19 return;
nuclear@0 20 }
nuclear@0 21
nuclear@0 22 dx = v1->pos.x - v0->pos.x;
nuclear@25 23 dfdx = fixed_div(dx, dy);
nuclear@0 24
nuclear@0 25 #ifdef INTERP_DEPTH
nuclear@0 26 dz = v1->pos.z - v0->pos.z;
nuclear@25 27 dfdz = fixed_div(dz, dy);
nuclear@0 28 #endif
nuclear@0 29 #ifdef INTERP_ENERGY
nuclear@0 30 de = v1->energy - v0->energy;
nuclear@25 31 dfde = fixed_div(de, dy);
nuclear@0 32 #endif
nuclear@3 33 #ifdef INTERP_TEX
nuclear@3 34 du = v1->tc.x - v0->tc.x;
nuclear@3 35 dv = v1->tc.y - v0->tc.y;
nuclear@25 36 dfdu = fixed_div(du, dy);
nuclear@25 37 dfdv = fixed_div(dv, dy);
nuclear@3 38 #endif
nuclear@0 39
nuclear@25 40 if(dy < 0) {
nuclear@25 41 VERTEX *tmp = v0;
nuclear@0 42 v0 = v1;
nuclear@0 43 v1 = tmp;
nuclear@0 44 edge = (st->ord == MGL_CCW) ? vright : vleft;
nuclear@0 45 } else {
nuclear@0 46 edge = (st->ord == MGL_CCW) ? vleft : vright;
nuclear@0 47 }
nuclear@0 48
nuclear@25 49 start = (int)fixed_round(v0->pos.y);
nuclear@25 50 end = (int)fixed_round(v1->pos.y);
nuclear@0 51
nuclear@9 52 if(start >= 0) {
nuclear@9 53
nuclear@9 54 x = v0->pos.x;
nuclear@0 55 #ifdef INTERP_DEPTH
nuclear@9 56 z = v0->pos.z;
nuclear@0 57 #endif
nuclear@0 58 #ifdef INTERP_ENERGY
nuclear@9 59 e = v0->energy;
nuclear@0 60 #endif
nuclear@3 61 #ifdef INTERP_TEX
nuclear@9 62 u = v0->tc.x;
nuclear@9 63 v = v0->tc.y;
nuclear@3 64 #endif
nuclear@9 65 } else {
nuclear@25 66 fixed lines = -v0->pos.y;
nuclear@9 67
nuclear@25 68 x = v0->pos.x + fixed_mul(dfdx, lines);
nuclear@9 69 #ifdef INTERP_DEPTH
nuclear@25 70 z = v0->pos.z + fixed_mul(dfdz, lines);
nuclear@9 71 #endif
nuclear@9 72 #ifdef INTERP_ENERGY
nuclear@25 73 e = v0->energy + fixed_mul(dfde, lines);
nuclear@9 74 #endif
nuclear@9 75 #ifdef INTERP_TEX
nuclear@25 76 u = v0->tc.x + fixed_mul(dfdu, lines);
nuclear@25 77 v = v0->tc.y + fixed_mul(dfdv, lines);
nuclear@9 78 #endif
nuclear@9 79 start = 0;
nuclear@9 80 }
nuclear@9 81
nuclear@9 82 if(end >= fb->height) {
nuclear@9 83 end = fb->height - 1;
nuclear@9 84 }
nuclear@9 85
nuclear@9 86
nuclear@0 87 for(i=start; i<end; i++) {
nuclear@0 88 edge[i].pos.x = x;
nuclear@0 89 x += dfdx;
nuclear@0 90
nuclear@0 91 edge[i].cidx = v0->cidx;
nuclear@0 92 #ifdef INTERP_DEPTH
nuclear@0 93 edge[i].pos.z = z;
nuclear@0 94 z += dfdz;
nuclear@0 95 #endif
nuclear@0 96
nuclear@0 97 #ifdef INTERP_ENERGY
nuclear@0 98 edge[i].energy = e;
nuclear@0 99 e += dfde;
nuclear@0 100 #else
nuclear@0 101 edge[i].energy = v0->energy;
nuclear@0 102 #endif
nuclear@3 103
nuclear@3 104 #ifdef INTERP_TEX
nuclear@3 105 edge[i].tc.x = u;
nuclear@3 106 edge[i].tc.y = v;
nuclear@3 107 u += dfdu;
nuclear@3 108 v += dfdv;
nuclear@3 109 #endif
nuclear@0 110 }
nuclear@0 111 }
nuclear@0 112
nuclear@0 113 static void SCAN_LINE(int y, unsigned char *sline)
nuclear@0 114 {
nuclear@3 115 int x0, x1, len, tmp, cidx;
nuclear@3 116 #if defined(INTERP_DEPTH) || defined(INTERP_ENERGY) || defined(INTERP_TEX)
nuclear@3 117 int i;
nuclear@25 118 fixed x, dx;
nuclear@0 119 #endif
nuclear@0 120 #ifdef INTERP_DEPTH
nuclear@25 121 fixed z, dz, dfdz;
nuclear@0 122 #endif
nuclear@0 123 #ifdef INTERP_ENERGY
nuclear@25 124 fixed e, de, dfde;
nuclear@0 125 #endif
nuclear@3 126 #ifdef INTERP_TEX
nuclear@17 127 unsigned int tx, ty;
nuclear@25 128 fixed u, v, du, dv, dfdu, dfdv;
nuclear@3 129 #endif
nuclear@25 130 VERTEX *left, *right;
nuclear@0 131
nuclear@25 132 x0 = (int)fixed_round(vleft[y].pos.x);
nuclear@25 133 x1 = (int)fixed_round(vright[y].pos.x);
nuclear@0 134
nuclear@0 135 if(x1 < x0) {
nuclear@28 136 if(IS_ENABLED(st->flags, MGL_CULL_FACE)) {
nuclear@0 137 return;
nuclear@0 138 }
nuclear@0 139 tmp = x0;
nuclear@0 140 x0 = x1;
nuclear@0 141 x1 = tmp;
nuclear@0 142
nuclear@0 143 left = vright;
nuclear@0 144 right = vleft;
nuclear@0 145 } else {
nuclear@0 146 left = vleft;
nuclear@0 147 right = vright;
nuclear@0 148 }
nuclear@0 149
nuclear@9 150 if(x1 >= fb->width) {
nuclear@9 151 x1 = fb->width - 1;
nuclear@9 152 }
nuclear@0 153
nuclear@0 154 cidx = left[y].cidx;
nuclear@3 155 #if !defined(INTERP_DEPTH) && !defined(INTERP_ENERGY) && !defined(INTERP_TEX)
nuclear@9 156 if(x0 < 0) x0 = 0;
nuclear@9 157 len = x1 - x0;
nuclear@9 158 assert(len >= 0);
nuclear@0 159 /* no interpolation at all, just memset the whole scanline */
nuclear@25 160 memset(sline + x0, cidx + fixed_int(fixed_mul(left[y].energy, fixedi(st->col_range))), len);
nuclear@0 161 #else
nuclear@0 162 /* otherwise do a loop and interpolate whatever needs interpolating */
nuclear@0 163 x = left[y].pos.x;
nuclear@0 164 dx = right[y].pos.x - x;
nuclear@0 165
nuclear@25 166 if(dx < fixedf(0.5) && dx > -fixedf(0.5)) {
nuclear@0 167 return;
nuclear@0 168 }
nuclear@0 169
nuclear@9 170 if(x0 >= 0) {
nuclear@0 171 #ifdef INTERP_DEPTH
nuclear@9 172 z = left[y].pos.z;
nuclear@9 173 dz = right[y].pos.z - z;
nuclear@25 174 dfdz = fixed_div(dz, dx);
nuclear@0 175 #endif
nuclear@0 176 #ifdef INTERP_ENERGY
nuclear@9 177 e = left[y].energy;
nuclear@9 178 de = right[y].energy - e;
nuclear@25 179 dfde = fixed_div(de, dx);
nuclear@0 180 #endif
nuclear@3 181 #ifdef INTERP_TEX
nuclear@9 182 u = left[y].tc.x;
nuclear@9 183 v = left[y].tc.y;
nuclear@9 184 du = right[y].tc.x - u;
nuclear@9 185 dv = right[y].tc.y - v;
nuclear@25 186 dfdu = fixed_div(du, dx);
nuclear@25 187 dfdv = fixed_div(dv, dx);
nuclear@3 188 #endif
nuclear@9 189 } else {
nuclear@25 190 fixed dist = -left[y].pos.x;
nuclear@9 191
nuclear@9 192 #ifdef INTERP_DEPTH
nuclear@9 193 dz = right[y].pos.z - left[y].pos.z;
nuclear@25 194 dfdz = fixed_div(dz, dx);
nuclear@25 195 z = left[y].pos.z + fixed_mul(dfdz, dist);
nuclear@9 196 #endif
nuclear@9 197 #ifdef INTERP_ENERGY
nuclear@9 198 de = right[y].energy - left[y].energy;
nuclear@25 199 dfde = fixed_div(de, dx);
nuclear@25 200 e = left[y].energy + fixed_mul(dfde, dist);
nuclear@9 201 #endif
nuclear@9 202 #ifdef INTERP_TEX
nuclear@9 203 du = right[y].tc.x - left[y].tc.x;
nuclear@9 204 dv = right[y].tc.y - left[y].tc.y;
nuclear@25 205 dfdu = fixed_div(du, dx);
nuclear@25 206 dfdv = fixed_div(dv, dx);
nuclear@25 207 u = left[y].tc.x + fixed_mul(dfdu, dist);
nuclear@25 208 v = left[y].tc.y + fixed_mul(dfdv, dist);
nuclear@9 209 #endif
nuclear@9 210 x0 = 0;
nuclear@9 211 }
nuclear@9 212
nuclear@9 213 len = x1 - x0;
nuclear@0 214
nuclear@0 215 for(i=0; i<len; i++) {
nuclear@3 216 int c = cidx;
nuclear@3 217
nuclear@3 218 #ifdef INTERP_DEPTH
nuclear@10 219 long pix = (sline + x0 + i) - fb->pixels;
nuclear@25 220 #ifdef RAST_FLOAT
nuclear@9 221 unsigned short zval = (unsigned short)(z * USHRT_MAX);
nuclear@25 222 #else
nuclear@25 223 unsigned short zval = (unsigned short)((z >> 1) & 0xffff);
nuclear@25 224 #endif
nuclear@9 225 unsigned short *zptr = fb->zbuf[ZTILE(pix)] + ZTILE_OFFS(pix);
nuclear@9 226
nuclear@25 227 if(z < 0 || z >= fixedi(1) || zval > *zptr) {
nuclear@9 228 # ifdef INTERP_TEX
nuclear@9 229 u += dfdu;
nuclear@9 230 v += dfdv;
nuclear@9 231 # endif
nuclear@9 232 # ifdef INTERP_ENERGY
nuclear@9 233 e += dfde;
nuclear@9 234 # endif
nuclear@9 235 z += dfdz;
nuclear@9 236 continue;
nuclear@9 237 }
nuclear@9 238
nuclear@9 239 *zptr = zval;
nuclear@3 240 z += dfdz;
nuclear@3 241 #endif
nuclear@3 242 #ifdef INTERP_TEX
nuclear@25 243 tx = (unsigned int)fixed_int(fixed_mul(u, fixedi(st->tex.width))) & st->tex.xmask;
nuclear@25 244 ty = (unsigned int)fixed_int(fixed_mul(v, fixedi(st->tex.height))) & st->tex.ymask;
nuclear@3 245 c = st->tex.pixels[(ty << st->tex.xshift) + tx];
nuclear@3 246
nuclear@3 247 u += dfdu;
nuclear@3 248 v += dfdv;
nuclear@3 249 #endif
nuclear@0 250 #ifdef INTERP_ENERGY
nuclear@25 251 c += fixed_int(fixed_mul(e, fixedi(st->col_range)));
nuclear@0 252 e += dfde;
nuclear@3 253 #else
nuclear@25 254 c += fixed_int(fixed_mul(left[y].energy, fixedi(st->col_range)));
nuclear@0 255 #endif
nuclear@3 256 sline[x0 + i] = c;
nuclear@0 257 }
nuclear@0 258 #endif /* flat */
nuclear@0 259 }