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 }
|