1 /*
2 d_edge.c
3
4 (description)
5
6 Copyright (C) 1996-1997 Id Software, Inc.
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
17 See the GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to:
21
22 Free Software Foundation, Inc.
23 59 Temple Place - Suite 330
24 Boston, MA 02111-1307, USA
25
26 */
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #define NH_DEFINE
32 #include "namehack.h"
33
34 #include "QF/cvar.h"
35 #include "QF/render.h"
36 #include "QF/sys.h"
37
38 #include "d_local.h"
39 #include "r_internal.h"
40 #include "vid_internal.h"
41
42 static int miplevel;
43
44 float sw32_scale_for_mip;
45
46 static vec3_t transformed_modelorg;
47
48
49 void
sw32_D_DrawPoly(void)50 sw32_D_DrawPoly (void)
51 {
52 // this driver takes spans, not polygons
53 }
54
55
56 int
sw32_D_MipLevelForScale(float scale)57 sw32_D_MipLevelForScale (float scale)
58 {
59 int lmiplevel;
60
61 if (scale >= sw32_d_scalemip[0])
62 lmiplevel = 0;
63 else if (scale >= sw32_d_scalemip[1])
64 lmiplevel = 1;
65 else if (scale >= sw32_d_scalemip[2])
66 lmiplevel = 2;
67 else
68 lmiplevel = 3;
69
70 if (lmiplevel < sw32_d_minmip)
71 lmiplevel = sw32_d_minmip;
72
73 return lmiplevel;
74 }
75
76 // FIXME: clean this up
77
78 static void
D_DrawSolidSurface(surf_t * surf,int color)79 D_DrawSolidSurface (surf_t *surf, int color)
80 {
81 espan_t *span;
82
83 switch(sw32_r_pixbytes) {
84 case 1:
85 {
86 byte *pdest, pix;
87 int u, u2;
88
89 pix = color;
90 for (span = surf->spans; span; span = span->pnext)
91 {
92 pdest = (byte *) sw32_d_viewbuffer + sw32_screenwidth * span->v;
93 u = span->u;
94 u2 = span->u + span->count - 1;
95 for (;u <= u2; u++)
96 pdest[u] = pix;
97 }
98 }
99 break;
100 case 2:
101 {
102 short *pdest, pix;
103 int u, u2;
104
105 pix = sw32_8to16table[color];
106 for (span = surf->spans; span; span = span->pnext)
107 {
108 pdest = (short *) sw32_d_viewbuffer + sw32_screenwidth * span->v;
109 u = span->u;
110 u2 = span->u + span->count - 1;
111 for (;u <= u2; u++)
112 pdest[u] = pix;
113 }
114 }
115 break;
116 case 4:
117 {
118 int *pdest, pix;
119 int u, u2;
120
121 pix = d_8to24table[color];
122 for (span = surf->spans; span; span = span->pnext)
123 {
124 pdest = (int *) sw32_d_viewbuffer + sw32_screenwidth * span->v;
125 u = span->u;
126 u2 = span->u + span->count - 1;
127 for (;u <= u2; u++)
128 pdest[u] = pix;
129 }
130 }
131 break;
132 default:
133 Sys_Error("D_DrawSolidSurface: unsupported r_pixbytes %i",
134 sw32_r_pixbytes);
135 }
136 }
137
138
139 static void
D_CalcGradients(msurface_t * pface)140 D_CalcGradients (msurface_t *pface)
141 {
142 float mipscale, t;
143 vec3_t p_temp1, p_saxis, p_taxis;
144
145 mipscale = 1.0 / (float) (1 << miplevel);
146
147 sw32_TransformVector (pface->texinfo->vecs[0], p_saxis);
148 sw32_TransformVector (pface->texinfo->vecs[1], p_taxis);
149
150 t = sw32_xscaleinv * mipscale;
151 sw32_d_sdivzstepu = p_saxis[0] * t;
152 sw32_d_tdivzstepu = p_taxis[0] * t;
153
154 t = sw32_yscaleinv * mipscale;
155 sw32_d_sdivzstepv = -p_saxis[1] * t;
156 sw32_d_tdivzstepv = -p_taxis[1] * t;
157
158 sw32_d_sdivzorigin = p_saxis[2] * mipscale -
159 sw32_xcenter * sw32_d_sdivzstepu -
160 sw32_ycenter * sw32_d_sdivzstepv;
161 sw32_d_tdivzorigin = p_taxis[2] * mipscale -
162 sw32_xcenter * sw32_d_tdivzstepu -
163 sw32_ycenter * sw32_d_tdivzstepv;
164
165 VectorScale (transformed_modelorg, mipscale, p_temp1);
166
167 t = 0x10000 * mipscale;
168 sw32_sadjust = ((fixed16_t) (DotProduct (p_temp1, p_saxis) * 0x10000 + 0.5)) -
169 ((pface->texturemins[0] << 16) >> miplevel)
170 + pface->texinfo->vecs[0][3] * t;
171 sw32_tadjust = ((fixed16_t) (DotProduct (p_temp1, p_taxis) * 0x10000 + 0.5)) -
172 ((pface->texturemins[1] << 16) >> miplevel)
173 + pface->texinfo->vecs[1][3] * t;
174
175 // -1 (-epsilon) so we never wander off the edge of the texture
176 sw32_bbextents = ((pface->extents[0] << 16) >> miplevel) - 1;
177 sw32_bbextentt = ((pface->extents[1] << 16) >> miplevel) - 1;
178 }
179
180
181 void
sw32_D_DrawSurfaces(void)182 sw32_D_DrawSurfaces (void)
183 {
184 surf_t *s;
185 msurface_t *pface;
186 surfcache_t *pcurrentcache;
187 vec3_t world_transformed_modelorg;
188 vec3_t local_modelorg;
189
190 currententity = &r_worldentity;
191 sw32_TransformVector (modelorg, transformed_modelorg);
192 VectorCopy (transformed_modelorg, world_transformed_modelorg);
193
194 // TODO: could preset a lot of this at mode set time
195 if (r_drawflat->int_val) {
196 for (s = &sw32_surfaces[1]; s < sw32_surface_p; s++) {
197 if (!s->spans)
198 continue;
199
200 d_zistepu = s->d_zistepu;
201 d_zistepv = s->d_zistepv;
202 d_ziorigin = s->d_ziorigin;
203
204 D_DrawSolidSurface (s, ((intptr_t) s->data & 0xFF));
205 sw32_D_DrawZSpans (s->spans);
206 }
207 } else {
208 for (s = &sw32_surfaces[1]; s < sw32_surface_p; s++) {
209 if (!s->spans)
210 continue;
211
212 sw32_r_drawnpolycount++;
213
214 d_zistepu = s->d_zistepu;
215 d_zistepv = s->d_zistepv;
216 d_ziorigin = s->d_ziorigin;
217
218 if (s->flags & SURF_DRAWSKY) {
219 if (!sw32_r_skymade) {
220 sw32_R_MakeSky ();
221 }
222
223 sw32_D_DrawSkyScans (s->spans);
224 sw32_D_DrawZSpans (s->spans);
225 } else if (s->flags & SURF_DRAWBACKGROUND) {
226 // set up a gradient for the background surface that places
227 // it effectively at infinity distance from the viewpoint
228 d_zistepu = 0;
229 d_zistepv = 0;
230 d_ziorigin = -0.9;
231
232 D_DrawSolidSurface (s, r_clearcolor->int_val & 0xFF);
233 sw32_D_DrawZSpans (s->spans);
234 } else if (s->flags & SURF_DRAWTURB) {
235 pface = s->data;
236 miplevel = 0;
237 sw32_cacheblock = ((byte *) pface->texinfo->texture +
238 pface->texinfo->texture->offsets[0]);
239 sw32_cachewidth = 64;
240
241 if (s->insubmodel) {
242 // FIXME: we don't want to do all this for every polygon!
243 // TODO: store once at start of frame
244 currententity = s->entity; // FIXME: make this passed in
245 // to sw32_R_RotateBmodel ()
246 VectorSubtract (r_origin, currententity->origin,
247 local_modelorg);
248 sw32_TransformVector (local_modelorg, transformed_modelorg);
249
250 sw32_R_RotateBmodel (); // FIXME: don't mess with the
251 // frustum, make entity passed in
252 }
253
254 D_CalcGradients (pface);
255
256 sw32_Turbulent (s->spans);
257 sw32_D_DrawZSpans (s->spans);
258
259 if (s->insubmodel) {
260 // restore the old drawing state
261 // FIXME: we don't want to do this every time!
262 // TODO: speed up
263
264 currententity = &r_worldentity;
265 VectorCopy (world_transformed_modelorg,
266 transformed_modelorg);
267 VectorCopy (base_vpn, vpn);
268 VectorCopy (base_vup, vup);
269 VectorCopy (base_vright, vright);
270 VectorCopy (base_modelorg, modelorg);
271 sw32_R_TransformFrustum ();
272 }
273 } else {
274 if (s->insubmodel) {
275 // FIXME: we don't want to do all this for every polygon!
276 // TODO: store once at start of frame
277 currententity = s->entity; // FIXME: make this passed in
278 // to sw32_R_RotateBmodel ()
279 VectorSubtract (r_origin, currententity->origin,
280 local_modelorg);
281 sw32_TransformVector (local_modelorg, transformed_modelorg);
282
283 sw32_R_RotateBmodel (); // FIXME: don't mess with the
284 // frustum, make entity passed in
285 }
286
287 pface = s->data;
288 miplevel = sw32_D_MipLevelForScale (s->nearzi * sw32_scale_for_mip
289 * pface->texinfo->mipadjust);
290
291 // FIXME: make this passed in to D_CacheSurface
292 pcurrentcache = sw32_D_CacheSurface (pface, miplevel);
293
294 sw32_cacheblock = (byte *) pcurrentcache->data;
295 sw32_cachewidth = pcurrentcache->width;
296
297 D_CalcGradients (pface);
298
299 sw32_D_DrawSpans (s->spans);
300
301 sw32_D_DrawZSpans (s->spans);
302
303 if (s->insubmodel) {
304 // restore the old drawing state
305 // FIXME: we don't want to do this every time!
306 // TODO: speed up
307
308 VectorCopy (world_transformed_modelorg,
309 transformed_modelorg);
310 VectorCopy (base_vpn, vpn);
311 VectorCopy (base_vup, vup);
312 VectorCopy (base_vright, vright);
313 VectorCopy (base_modelorg, modelorg);
314 sw32_R_TransformFrustum ();
315 currententity = &r_worldentity;
316 }
317 }
318 }
319 }
320 }
321