dos3d
view src/scantmpl.h @ 1:0b7f840afe4a
palette management
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Mon, 21 Nov 2011 08:35:58 +0200 |
parents | |
children | 0e781cc43178 |
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 float x, y;
29 struct vertex *edge;
31 dy = v1->pos.y - v0->pos.y;
32 if(dy < 1e-6 && dy > -1e-6) {
33 return;
34 }
36 dx = v1->pos.x - v0->pos.x;
37 dfdx = dx / dy;
39 #ifdef INTERP_DEPTH
40 assert(fb->zbuf);
41 dz = v1->pos.z - v0->pos.z;
42 dfdz = dz / dy;
43 #endif
44 #ifdef INTERP_ENERGY
45 de = v1->energy - v0->energy;
46 dfde = de / dy;
47 #endif
49 if(dy < 0.0) {
50 struct vertex *tmp = v0;
51 v0 = v1;
52 v1 = tmp;
53 edge = (st->ord == MGL_CCW) ? vright : vleft;
54 } else {
55 edge = (st->ord == MGL_CCW) ? vleft : vright;
56 }
58 start = (int)ROUND(v0->pos.y);
59 end = (int)ROUND(v1->pos.y);
61 x = v0->pos.x;
62 #ifdef INTERP_DEPTH
63 z = v0->pos.z;
64 #endif
65 #ifdef INTERP_ENERGY
66 e = v0->energy;
67 #endif
68 for(i=start; i<end; i++) {
69 edge[i].pos.x = x;
70 x += dfdx;
72 edge[i].cidx = v0->cidx;
73 #ifdef INTERP_DEPTH
74 edge[i].pos.z = z;
75 z += dfdz;
76 #endif
78 #ifdef INTERP_ENERGY
79 edge[i].energy = e;
80 e += dfde;
81 #else
82 edge[i].energy = v0->energy;
83 #endif
84 }
85 }
87 static void SCAN_LINE(int y, unsigned char *sline)
88 {
89 int i, x0, x1, len, tmp, cidx;
90 #if defined(INTERP_DEPTH) || defined(INTERP_ENERGY)
91 float x, dx;
92 #endif
93 #ifdef INTERP_DEPTH
94 float z, dz, dfdz;
95 #endif
96 #ifdef INTERP_ENERGY
97 float e, de, dfde;
98 #endif
99 struct vertex *left, *right;
101 x0 = (int)ROUND(vleft[y].pos.x);
102 x1 = (int)ROUND(vright[y].pos.x);
103 len = x1 - x0;
105 if(x1 < x0) {
106 if(st->flags & MGL_CULL_FACE) {
107 return;
108 }
109 tmp = x0;
110 x0 = x1;
111 x1 = tmp;
112 len = -len;
114 left = vright;
115 right = vleft;
116 } else {
117 left = vleft;
118 right = vright;
119 }
121 if(x0 < 0) x0 = 0;
122 if(x1 >= fb->width) x1 = fb->width - 1;
124 assert(len >= 0);
126 cidx = left[y].cidx;
127 #if !defined(INTERP_DEPTH) && !defined(INTERP_ENERGY)
128 /* no interpolation at all, just memset the whole scanline */
129 memset(sline + x0, cidx + left[y].energy * st->col_range, len);
130 #else
131 /* otherwise do a loop and interpolate whatever needs interpolating */
132 x = left[y].pos.x;
133 dx = right[y].pos.x - x;
135 if(dx < 0.5 && dx > -0.5) {
136 return;
137 }
139 #ifdef INTERP_DEPTH
140 z = left[y].pos.z;
141 dz = right[y].pos.z - z;
142 dfdz = dz / dx;
143 #endif
144 #ifdef INTERP_ENERGY
145 e = left[y].energy;
146 de = right[y].energy - e;
147 dfde = de / dx;
148 #endif
150 for(i=0; i<len; i++) {
151 #ifdef INTERP_ENERGY
152 cidx = left[y].cidx + e * st->col_range;
153 e += dfde;
154 #endif
155 sline[x0 + i] = cidx;
156 }
157 #endif /* flat */
158 }