1/*
2Copyright (C) 1996-1997 Id Software, Inc.
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13See the GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with this program; if not, write to the Free Software
17Foundation, 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
25static int	miplevel;
26
27float		scale_for_mip;
28int			screenwidth;
29int			ubasestep, errorterm, erroradjustup, erroradjustdown;
30int			vstartscan;
31
32// FIXME: should go away
33extern void			R_RotateBmodel (void);
34extern void			R_TransformFrustum (void);
35
36vec3_t		transformed_modelorg;
37
38/*
39==============
40D_DrawPoly
41
42==============
43*/
44void D_DrawPoly (void)
45{
46// this driver takes spans, not polygons
47}
48
49
50/*
51=============
52D_MipLevelForScale
53=============
54*/
55int 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==============
77D_DrawSolidSurface
78==============
79*/
80
81// FIXME: clean this up
82
83void 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==============
120D_CalcGradients
121==============
122*/
123void 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==============
171D_DrawSurfaces
172==============
173*/
174void 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 = &cl_entities[0];
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			D_DrawSolidSurface (s, (int)s->data & 0xFF);
199			D_DrawZSpans (s->spans);
200		}
201	}
202	else
203	{
204		for (s = &surfaces[1] ; s<surface_p ; s++)
205		{
206			if (!s->spans)
207				continue;
208
209			r_drawnpolycount++;
210
211			d_zistepu = s->d_zistepu;
212			d_zistepv = s->d_zistepv;
213			d_ziorigin = s->d_ziorigin;
214
215			if (s->flags & SURF_DRAWSKY)
216			{
217				if (!r_skymade)
218				{
219					R_MakeSky ();
220				}
221
222				D_DrawSkyScans8 (s->spans);
223				D_DrawZSpans (s->spans);
224			}
225			else if (s->flags & SURF_DRAWBACKGROUND)
226			{
227			// set up a gradient for the background surface that places it
228			// effectively at infinity distance from the viewpoint
229				d_zistepu = 0;
230				d_zistepv = 0;
231				d_ziorigin = -0.9;
232
233				D_DrawSolidSurface (s, (int)r_clearcolor.value & 0xFF);
234				D_DrawZSpans (s->spans);
235			}
236			else if (s->flags & SURF_DRAWTURB)
237			{
238				pface = s->data;
239				miplevel = 0;
240				cacheblock = (pixel_t *)
241						((byte *)pface->texinfo->texture +
242						pface->texinfo->texture->offsets[0]);
243				cachewidth = 64;
244
245				if (s->insubmodel)
246				{
247				// FIXME: we don't want to do all this for every polygon!
248				// TODO: store once at start of frame
249					currententity = s->entity;	//FIXME: make this passed in to
250												// R_RotateBmodel ()
251					VectorSubtract (r_origin, currententity->origin,
252							local_modelorg);
253					TransformVector (local_modelorg, transformed_modelorg);
254
255					R_RotateBmodel ();	// FIXME: don't mess with the frustum,
256										// make entity passed in
257				}
258
259				D_CalcGradients (pface);
260				Turbulent8 (s->spans);
261				D_DrawZSpans (s->spans);
262
263				if (s->insubmodel)
264				{
265				//
266				// restore the old drawing state
267				// FIXME: we don't want to do this every time!
268				// TODO: speed up
269				//
270					currententity = &cl_entities[0];
271					VectorCopy (world_transformed_modelorg,
272								transformed_modelorg);
273					VectorCopy (base_vpn, vpn);
274					VectorCopy (base_vup, vup);
275					VectorCopy (base_vright, vright);
276					VectorCopy (base_modelorg, modelorg);
277					R_TransformFrustum ();
278				}
279			}
280			else
281			{
282				if (s->insubmodel)
283				{
284				// FIXME: we don't want to do all this for every polygon!
285				// TODO: store once at start of frame
286					currententity = s->entity;	//FIXME: make this passed in to
287												// R_RotateBmodel ()
288					VectorSubtract (r_origin, currententity->origin, local_modelorg);
289					TransformVector (local_modelorg, transformed_modelorg);
290
291					R_RotateBmodel ();	// FIXME: don't mess with the frustum,
292										// make entity passed in
293				}
294
295				pface = s->data;
296				miplevel = D_MipLevelForScale (s->nearzi * scale_for_mip
297				* pface->texinfo->mipadjust);
298
299			// FIXME: make this passed in to D_CacheSurface
300				pcurrentcache = D_CacheSurface (pface, miplevel);
301
302				cacheblock = (pixel_t *)pcurrentcache->data;
303				cachewidth = pcurrentcache->width;
304
305				D_CalcGradients (pface);
306
307				(*d_drawspans) (s->spans);
308
309				D_DrawZSpans (s->spans);
310
311				if (s->insubmodel)
312				{
313				//
314				// restore the old drawing state
315				// FIXME: we don't want to do this every time!
316				// TODO: speed up
317				//
318					currententity = &cl_entities[0];
319					VectorCopy (world_transformed_modelorg,
320								transformed_modelorg);
321					VectorCopy (base_vpn, vpn);
322					VectorCopy (base_vup, vup);
323					VectorCopy (base_vright, vright);
324					VectorCopy (base_modelorg, modelorg);
325					R_TransformFrustum ();
326				}
327			}
328		}
329	}
330}
331
332