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