deepstone

view src/scantmpl.h @ 34:c6406e4aa0fb

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