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