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