dos3d

view src/scantmpl.h @ 7:3239511d1a76

random change
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 21 Nov 2011 12:12:23 +0200
parents f04884489bad
children bce78aaafc68
line source
1 /*
2 256-color 3D graphics hack for real-mode DOS.
3 Copyright (C) 2011 John Tsiombikas <nuclear@member.fsf.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 static void SCAN_EDGE(struct vertex *v0, struct vertex *v1)
19 {
20 int i, start, end;
21 float dx, dy, dfdx;
22 #ifdef INTERP_DEPTH
23 float z, dz, dfdz;
24 #endif
25 #ifdef INTERP_ENERGY
26 float e, de, dfde;
27 #endif
28 #ifdef INTERP_TEX
29 float u, v, du, dv, dfdu, dfdv;
30 #endif
31 float x;
32 struct vertex *edge;
34 dy = v1->pos.y - v0->pos.y;
35 if(dy < 1e-6 && dy > -1e-6) {
36 return;
37 }
39 dx = v1->pos.x - v0->pos.x;
40 dfdx = dx / dy;
42 #ifdef INTERP_DEPTH
43 dz = v1->pos.z - v0->pos.z;
44 dfdz = dz / dy;
45 #endif
46 #ifdef INTERP_ENERGY
47 de = v1->energy - v0->energy;
48 dfde = de / dy;
49 #endif
50 #ifdef INTERP_TEX
51 du = v1->tc.x - v0->tc.x;
52 dv = v1->tc.y - v0->tc.y;
53 dfdu = du / dy;
54 dfdv = dv / dy;
55 #endif
57 if(dy < 0.0) {
58 struct vertex *tmp = v0;
59 v0 = v1;
60 v1 = tmp;
61 edge = (st->ord == MGL_CCW) ? vright : vleft;
62 } else {
63 edge = (st->ord == MGL_CCW) ? vleft : vright;
64 }
66 start = (int)ROUND(v0->pos.y);
67 end = (int)ROUND(v1->pos.y);
69 x = v0->pos.x;
70 #ifdef INTERP_DEPTH
71 z = v0->pos.z;
72 #endif
73 #ifdef INTERP_ENERGY
74 e = v0->energy;
75 #endif
76 #ifdef INTERP_TEX
77 u = v0->tc.x;
78 v = v0->tc.y;
79 #endif
80 for(i=start; i<end; i++) {
81 edge[i].pos.x = x;
82 x += dfdx;
84 edge[i].cidx = v0->cidx;
85 #ifdef INTERP_DEPTH
86 edge[i].pos.z = z;
87 z += dfdz;
88 #endif
90 #ifdef INTERP_ENERGY
91 edge[i].energy = e;
92 e += dfde;
93 #else
94 edge[i].energy = v0->energy;
95 #endif
97 #ifdef INTERP_TEX
98 edge[i].tc.x = u;
99 edge[i].tc.y = v;
100 u += dfdu;
101 v += dfdv;
102 #endif
103 }
104 }
106 static void SCAN_LINE(int y, unsigned char *sline)
107 {
108 int x0, x1, len, tmp, cidx;
109 #if defined(INTERP_DEPTH) || defined(INTERP_ENERGY) || defined(INTERP_TEX)
110 int i;
111 float x, dx;
112 #endif
113 #ifdef INTERP_DEPTH
114 float z, dz, dfdz;
115 #endif
116 #ifdef INTERP_ENERGY
117 float e, de, dfde;
118 #endif
119 #ifdef INTERP_TEX
120 int tx, ty;
121 float u, v, du, dv, dfdu, dfdv;
122 #endif
123 struct vertex *left, *right;
125 x0 = (int)ROUND(vleft[y].pos.x);
126 x1 = (int)ROUND(vright[y].pos.x);
127 len = x1 - x0;
129 if(x1 < x0) {
130 if(st->flags & MGL_CULL_FACE) {
131 return;
132 }
133 tmp = x0;
134 x0 = x1;
135 x1 = tmp;
136 len = -len;
138 left = vright;
139 right = vleft;
140 } else {
141 left = vleft;
142 right = vright;
143 }
145 if(x0 < 0) x0 = 0;
146 if(x1 >= fb->width) x1 = fb->width - 1;
148 assert(len >= 0);
150 cidx = left[y].cidx;
151 #if !defined(INTERP_DEPTH) && !defined(INTERP_ENERGY) && !defined(INTERP_TEX)
152 /* no interpolation at all, just memset the whole scanline */
153 memset(sline + x0, cidx + left[y].energy * st->col_range, len);
154 #else
155 /* otherwise do a loop and interpolate whatever needs interpolating */
156 x = left[y].pos.x;
157 dx = right[y].pos.x - x;
159 if(dx < 0.5 && dx > -0.5) {
160 return;
161 }
163 #ifdef INTERP_DEPTH
164 z = left[y].pos.z;
165 dz = right[y].pos.z - z;
166 dfdz = dz / dx;
167 #endif
168 #ifdef INTERP_ENERGY
169 e = left[y].energy;
170 de = right[y].energy - e;
171 dfde = de / dx;
172 #endif
173 #ifdef INTERP_TEX
174 u = left[y].tc.x;
175 v = left[y].tc.y;
176 du = right[y].tc.x - u;
177 dv = right[y].tc.y - v;
178 dfdu = du / dx;
179 dfdv = dv / dx;
180 #endif
182 for(i=0; i<len; i++) {
183 int c = cidx;
185 #ifdef INTERP_DEPTH
186 z += dfdz;
187 #endif
188 #ifdef INTERP_TEX
189 tx = (int)(u * st->tex.width) & st->tex.xmask;
190 ty = (int)(v * st->tex.height) & st->tex.ymask;
191 c = st->tex.pixels[(ty << st->tex.xshift) + tx];
193 u += dfdu;
194 v += dfdv;
195 #endif
196 #ifdef INTERP_ENERGY
197 c += e * st->col_range;
198 e += dfde;
199 #else
200 c += left[y].energy * st->col_range;
201 #endif
202 sline[x0 + i] = c;
203 }
204 #endif /* flat */
205 }