deepstone

view src/scantmpl.h @ 38:17a5107b6fa4

- added perspective correct interpolation - added recording functionality - added video capture functionality
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 10 Mar 2014 17:24:42 +0200
parents 11d14f688485
children 1fa939507d8b
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 #ifdef TEXMAP_PERSP_CORRECT
13 fixed w, dw, dfdw;
14 #endif
15 fixed u, v, du, dv, dfdu, dfdv;
16 #endif
17 fixed x;
18 VERTEX *edge;
20 dy = v1->pos.y - v0->pos.y;
21 if(dy < FIXED_EPSILON && dy > -FIXED_EPSILON) {
22 return;
23 }
25 dx = v1->pos.x - v0->pos.x;
26 dfdx = fixed_div(dx, dy);
28 #ifdef INTERP_DEPTH
29 dz = v1->pos.z - v0->pos.z;
30 dfdz = fixed_div(dz, dy);
31 #endif
32 #ifdef INTERP_ENERGY
33 de = v1->energy - v0->energy;
34 dfde = fixed_div(de, dy);
35 #endif
36 #ifdef INTERP_TEX
37 #ifdef TEXMAP_PERSP_CORRECT
38 dw = v1->pos.w - v0->pos.w;
39 dfdw = fixed_div(dw, dy);
40 #endif
42 du = v1->tc.x - v0->tc.x;
43 dv = v1->tc.y - v0->tc.y;
44 dfdu = fixed_div(du, dy);
45 dfdv = fixed_div(dv, dy);
46 #endif
48 if(dy < 0) {
49 VERTEX *tmp = v0;
50 v0 = v1;
51 v1 = tmp;
52 edge = (st->ord == MGL_CCW) ? vright : vleft;
53 } else {
54 edge = (st->ord == MGL_CCW) ? vleft : vright;
55 }
57 start = (int)fixed_round(v0->pos.y);
58 end = (int)fixed_round(v1->pos.y);
60 if(start >= 0) {
62 x = v0->pos.x;
63 #ifdef INTERP_DEPTH
64 z = v0->pos.z;
65 #endif
66 #ifdef INTERP_ENERGY
67 e = v0->energy;
68 #endif
69 #ifdef INTERP_TEX
70 #ifdef TEXMAP_PERSP_CORRECT
71 w = v0->pos.w;
72 #endif
73 u = v0->tc.x;
74 v = v0->tc.y;
75 #endif
76 } else {
77 fixed lines = -v0->pos.y;
79 x = v0->pos.x + fixed_mul(dfdx, lines);
80 #ifdef INTERP_DEPTH
81 z = v0->pos.z + fixed_mul(dfdz, lines);
82 #endif
83 #ifdef INTERP_ENERGY
84 e = v0->energy + fixed_mul(dfde, lines);
85 #endif
86 #ifdef INTERP_TEX
87 #ifdef TEXMAP_PERSP_CORRECT
88 w = v0->pos.w + fixed_mul(dfdw, lines);
89 #endif
90 u = v0->tc.x + fixed_mul(dfdu, lines);
91 v = v0->tc.y + fixed_mul(dfdv, lines);
92 #endif
93 start = 0;
94 }
96 if(end >= fb->height) {
97 end = fb->height - 1;
98 }
101 for(i=start; i<end; i++) {
102 edge[i].pos.x = x;
103 x += dfdx;
105 edge[i].cidx = v0->cidx;
106 #ifdef INTERP_DEPTH
107 edge[i].pos.z = z;
108 z += dfdz;
109 #endif
111 #ifdef INTERP_ENERGY
112 edge[i].energy = e;
113 e += dfde;
114 #else
115 edge[i].energy = v0->energy;
116 #endif
118 #ifdef INTERP_TEX
119 #ifdef TEXMAP_PERSP_CORRECT
120 edge[i].pos.w = w;
121 w += dfdw;
122 #endif
124 edge[i].tc.x = u;
125 edge[i].tc.y = v;
126 u += dfdu;
127 v += dfdv;
128 #endif
129 }
130 }
132 static void SCAN_LINE(int y, unsigned char *sline)
133 {
134 int x0, x1, len, tmp, cidx;
135 #if defined(INTERP_DEPTH) || defined(INTERP_ENERGY) || defined(INTERP_TEX)
136 int i;
137 fixed x, dx;
138 #endif
139 #ifdef INTERP_DEPTH
140 fixed z, dz, dfdz;
141 #endif
142 #ifdef INTERP_ENERGY
143 fixed e, de, dfde;
144 #endif
145 #ifdef INTERP_TEX
146 unsigned int tx, ty;
147 fixed u, v, du, dv, dfdu, dfdv;
148 fixed w, dw, dfdw;
149 fixed tu, tv;
150 #endif
151 VERTEX *left, *right;
153 x0 = (int)fixed_round(vleft[y].pos.x);
154 x1 = (int)fixed_round(vright[y].pos.x);
156 if(x1 < x0) {
157 if(IS_ENABLED(st->flags, MGL_CULL_FACE)) {
158 return;
159 }
160 tmp = x0;
161 x0 = x1;
162 x1 = tmp;
164 left = vright;
165 right = vleft;
166 } else {
167 left = vleft;
168 right = vright;
169 }
171 if(x1 >= fb->width) {
172 x1 = fb->width - 1;
173 }
175 cidx = left[y].cidx;
176 #if !defined(INTERP_DEPTH) && !defined(INTERP_ENERGY) && !defined(INTERP_TEX)
177 if(x0 < 0) x0 = 0;
178 len = x1 - x0;
179 assert(len >= 0);
180 /* no interpolation at all, just memset the whole scanline */
181 memset(sline + x0, cidx + fixed_int(fixed_mul(left[y].energy, fixedi(st->col_range))), len);
182 #else
183 /* otherwise do a loop and interpolate whatever needs interpolating */
184 x = left[y].pos.x;
185 dx = right[y].pos.x - x;
187 if(dx < fixedf(0.5) && dx > -fixedf(0.5)) {
188 return;
189 }
191 if(x0 >= 0) {
192 #ifdef INTERP_DEPTH
193 z = left[y].pos.z;
194 dz = right[y].pos.z - z;
195 dfdz = fixed_div(dz, dx);
196 #endif
197 #ifdef INTERP_ENERGY
198 e = left[y].energy;
199 de = right[y].energy - e;
200 dfde = fixed_div(de, dx);
201 #endif
202 #ifdef INTERP_TEX
203 #ifdef TEXMAP_PERSP_CORRECT
204 w = left[y].pos.w;
205 dw = right[y].pos.w - w;
206 dfdw = fixed_div(dw, dx);
207 #endif
209 u = left[y].tc.x;
210 v = left[y].tc.y;
211 du = right[y].tc.x - u;
212 dv = right[y].tc.y - v;
213 dfdu = fixed_div(du, dx);
214 dfdv = fixed_div(dv, dx);
215 #endif
216 } else {
217 fixed dist = -left[y].pos.x;
219 #ifdef INTERP_DEPTH
220 dz = right[y].pos.z - left[y].pos.z;
221 dfdz = fixed_div(dz, dx);
222 z = left[y].pos.z + fixed_mul(dfdz, dist);
223 #endif
224 #ifdef INTERP_ENERGY
225 de = right[y].energy - left[y].energy;
226 dfde = fixed_div(de, dx);
227 e = left[y].energy + fixed_mul(dfde, dist);
228 #endif
229 #ifdef INTERP_TEX
230 #ifdef TEXMAP_PERSP_CORRECT
231 dw = right[y].pos.w - left[y].pos.w;
232 dfdw = fixed_div(dw, dx);
233 w = left[y].pos.w + fixed_mul(dfdw, dist);
234 #endif
236 du = right[y].tc.x - left[y].tc.x;
237 dv = right[y].tc.y - left[y].tc.y;
238 dfdu = fixed_div(du, dx);
239 dfdv = fixed_div(dv, dx);
240 u = left[y].tc.x + fixed_mul(dfdu, dist);
241 v = left[y].tc.y + fixed_mul(dfdv, dist);
242 #endif
243 x0 = 0;
244 }
246 len = x1 - x0;
248 for(i=0; i<len; i++) {
249 int c = cidx;
251 #ifdef INTERP_DEPTH
252 long pix = (sline + x0 + i) - fb->pixels;
253 #ifdef RAST_FLOAT
254 unsigned short zval = (unsigned short)(z * USHRT_MAX);
255 #else
256 unsigned short zval = (unsigned short)((z >> 1) & 0xffff);
257 #endif
258 unsigned short *zptr = fb->zbuf[ZTILE(pix)] + ZTILE_OFFS(pix);
260 if(z < 0 || z >= fixedi(1) || zval > *zptr) {
261 #ifdef INTERP_TEX
262 u += dfdu;
263 v += dfdv;
264 #ifdef TEXMAP_PERSP_CORRECT
265 w += dfdw;
266 #endif
267 #endif /* INTERP_TEX */
268 #ifdef INTERP_ENERGY
269 e += dfde;
270 #endif
271 z += dfdz;
272 continue;
273 }
275 *zptr = zval;
276 z += dfdz;
277 #endif
278 #ifdef INTERP_TEX
279 #ifdef TEXMAP_PERSP_CORRECT
280 tu = fixed_div(u, w);
281 tv = fixed_div(v, w);
282 #else
283 tu = u;
284 tv = v;
285 #endif
286 tx = (unsigned int)fixed_int(fixed_mul(tu, fixedi(st->tex.width))) & st->tex.xmask;
287 ty = (unsigned int)fixed_int(fixed_mul(tv, fixedi(st->tex.height))) & st->tex.ymask;
288 c = st->tex.pixels[(ty << st->tex.xshift) + tx];
290 u += dfdu;
291 v += dfdv;
292 #ifdef TEXMAP_PERSP_CORRECT
293 w += dfdw;
294 #endif
295 #endif /* INTERP_TEX */
296 #ifdef INTERP_ENERGY
297 c += fixed_int(fixed_mul(e, fixedi(st->col_range)));
298 e += dfde;
299 #else
300 c += fixed_int(fixed_mul(left[y].energy, fixedi(st->col_range)));
301 #endif
302 sline[x0 + i] = c;
303 }
304 #endif /* flat */
305 }