1 /*
2 	sw32_rmain.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 #ifdef HAVE_STRING_H
35 # include <string.h>
36 #endif
37 #ifdef HAVE_STRINGS_H
38 # include <strings.h>
39 #endif
40 
41 #include <math.h>
42 
43 #include "QF/cmd.h"
44 #include "QF/cvar.h"
45 #include "QF/locs.h"
46 #include "QF/mathlib.h"
47 #include "QF/render.h"
48 #include "QF/screen.h"
49 #include "QF/sound.h"
50 #include "QF/sys.h"
51 
52 #include "compat.h"
53 #include "mod_internal.h"
54 #include "r_internal.h"
55 #include "vid_internal.h"
56 
57 //define    PASSAGES
58 
59 static vec3_t      viewlightvec;
60 static alight_t    r_viewlighting = { 128, 192, viewlightvec };
61 int         sw32_r_numallocatededges;
62 qboolean    sw32_r_drawpolys;
63 qboolean    sw32_r_drawculledpolys;
64 qboolean    sw32_r_worldpolysbacktofront;
65 int         sw32_r_pixbytes = 1;
66 float       sw32_r_aliasuvscale = 1.0;
67 int         sw32_r_outofsurfaces;
68 int         sw32_r_outofedges;
69 
70 qboolean    sw32_r_dowarp, sw32_r_dowarpold, sw32_r_viewchanged;
71 
72 int         sw32_c_surf;
73 int         sw32_r_maxsurfsseen, sw32_r_maxedgesseen;
74 static int  r_cnumsurfs;
75 static qboolean    r_surfsonstack;
76 int         sw32_r_clipflags;
77 
78 byte       *sw32_r_warpbuffer;
79 
80 static byte       *r_stack_start;
81 
82 // screen size info
83 float       sw32_xcenter, sw32_ycenter;
84 float       sw32_xscale, sw32_yscale;
85 float       sw32_xscaleinv, sw32_yscaleinv;
86 float       sw32_xscaleshrink, sw32_yscaleshrink;
87 float       sw32_aliasxscale, sw32_aliasyscale, sw32_aliasxcenter, sw32_aliasycenter;
88 
89 int         sw32_screenwidth;
90 
91 float       sw32_pixelAspect;
92 static float       screenAspect;
93 static float       verticalFieldOfView;
94 static float       xOrigin, yOrigin;
95 
96 plane_t     sw32_screenedge[4];
97 
98 // refresh flags
99 int         sw32_r_polycount;
100 int         sw32_r_drawnpolycount;
101 
102 int        *sw32_pfrustum_indexes[4];
103 int         sw32_r_frustum_indexes[4 * 6];
104 
105 float       sw32_r_aliastransition, sw32_r_resfudge;
106 
107 static float dp_time1, dp_time2, db_time1, db_time2, rw_time1, rw_time2;
108 static float se_time1, se_time2, de_time1, de_time2, dv_time1, dv_time2;
109 
110 void
sw32_R_Textures_Init(void)111 sw32_R_Textures_Init (void)
112 {
113 	int         x, y, m;
114 	byte       *dest;
115 
116 	// create a simple checkerboard texture for the default
117 	r_notexture_mip =
118 		Hunk_AllocName (sizeof (texture_t) + 16 * 16 + 8 * 8 + 4 * 4 + 2 * 2,
119 						"notexture");
120 
121 	r_notexture_mip->width = r_notexture_mip->height = 16;
122 	r_notexture_mip->offsets[0] = sizeof (texture_t);
123 
124 	r_notexture_mip->offsets[1] = r_notexture_mip->offsets[0] + 16 * 16;
125 	r_notexture_mip->offsets[2] = r_notexture_mip->offsets[1] + 8 * 8;
126 	r_notexture_mip->offsets[3] = r_notexture_mip->offsets[2] + 4 * 4;
127 
128 	for (m = 0; m < 4; m++) {
129 		dest = (byte *) r_notexture_mip + r_notexture_mip->offsets[m];
130 		for (y = 0; y < (16 >> m); y++)
131 			for (x = 0; x < (16 >> m); x++) {
132 				if ((y < (8 >> m)) ^ (x < (8 >> m)))
133 					*dest++ = 0;
134 				else
135 					*dest++ = 0xff;
136 			}
137 	}
138 }
139 
140 void
sw32_R_Init(void)141 sw32_R_Init (void)
142 {
143 	int         dummy;
144 
145 	// get stack position so we can guess if we are going to overflow
146 	r_stack_start = (byte *) & dummy;
147 
148 	R_Init_Cvars ();
149 	sw32_R_Particles_Init_Cvars ();
150 
151 	sw32_Draw_Init ();
152 	SCR_Init ();
153 	sw32_R_InitTurb ();
154 
155 	Cmd_AddCommand ("timerefresh", sw32_R_TimeRefresh_f, "Tests the current "
156 					"refresh rate for the current location");
157 	Cmd_AddCommand ("pointfile", sw32_R_ReadPointFile_f, "Load a pointfile to "
158 					"determine map leaks");
159 	Cmd_AddCommand ("loadsky", sw32_R_LoadSky_f, "Load a skybox");
160 
161 	Cvar_SetValue (r_maxedges, (float) NUMSTACKEDGES);
162 	Cvar_SetValue (r_maxsurfs, (float) NUMSTACKSURFACES);
163 
164 	sw32_view_clipplanes[0].leftedge = true;
165 	sw32_view_clipplanes[1].rightedge = true;
166 	sw32_view_clipplanes[1].leftedge = sw32_view_clipplanes[2].leftedge =
167 		sw32_view_clipplanes[3].leftedge = false;
168 	sw32_view_clipplanes[0].rightedge = sw32_view_clipplanes[2].rightedge =
169 		sw32_view_clipplanes[3].rightedge = false;
170 
171 	r_refdef.xOrigin = XCENTERING;
172 	r_refdef.yOrigin = YCENTERING;
173 
174 	sw32_D_Init ();
175 
176 	Skin_Init ();
177 }
178 
179 void
sw32_R_NewMap(model_t * worldmodel,struct model_s ** models,int num_models)180 sw32_R_NewMap (model_t *worldmodel, struct model_s **models, int num_models)
181 {
182 	int         i;
183 
184 	memset (&r_worldentity, 0, sizeof (r_worldentity));
185 	r_worldentity.model = worldmodel;
186 
187 	R_FreeAllEntities ();
188 
189 	// clear out efrags in case the level hasn't been reloaded
190 	// FIXME: is this one short?
191 	for (i = 0; i < r_worldentity.model->numleafs; i++)
192 		r_worldentity.model->leafs[i].efrags = NULL;
193 
194 	if (worldmodel->skytexture)
195 		sw32_R_InitSky (worldmodel->skytexture);
196 
197 	// Force a vis update
198 	r_viewleaf = NULL;
199 	R_MarkLeaves ();
200 
201 	sw32_R_ClearParticles ();
202 
203 	r_cnumsurfs = r_maxsurfs->int_val;
204 
205 	if (r_cnumsurfs <= MINSURFACES)
206 		r_cnumsurfs = MINSURFACES;
207 
208 	if (r_cnumsurfs > NUMSTACKSURFACES) {
209 		sw32_surfaces = Hunk_AllocName (r_cnumsurfs * sizeof (surf_t), "surfaces");
210 
211 		sw32_surface_p = sw32_surfaces;
212 		sw32_surf_max = &sw32_surfaces[r_cnumsurfs];
213 		r_surfsonstack = false;
214 		// surface 0 doesn't really exist; it's just a dummy because index 0
215 		// is used to indicate no edge attached to surface
216 		sw32_surfaces--;
217 	} else {
218 		r_surfsonstack = true;
219 	}
220 
221 	sw32_r_maxedgesseen = 0;
222 	sw32_r_maxsurfsseen = 0;
223 
224 	sw32_r_numallocatededges = r_maxedges->int_val;
225 
226 	if (sw32_r_numallocatededges < MINEDGES)
227 		sw32_r_numallocatededges = MINEDGES;
228 
229 	if (sw32_r_numallocatededges <= NUMSTACKEDGES) {
230 		sw32_auxedges = NULL;
231 	} else {
232 		sw32_auxedges = Hunk_AllocName (sw32_r_numallocatededges * sizeof (edge_t),
233 								   "edges");
234 	}
235 
236 	sw32_r_dowarpold = false;
237 	sw32_r_viewchanged = false;
238 }
239 
240 /*
241 	R_ViewChanged
242 
243 	Called every time the vid structure or r_refdef changes.
244 	Guaranteed to be called before the first refresh
245 */
246 void
sw32_R_ViewChanged(float aspect)247 sw32_R_ViewChanged (float aspect)
248 {
249 	int         i;
250 	float       res_scale;
251 
252 	sw32_r_viewchanged = true;
253 
254 	r_refdef.horizontalFieldOfView = 2.0 * tan (r_refdef.fov_x / 360 * M_PI);
255 	r_refdef.fvrectx = (float) r_refdef.vrect.x;
256 	r_refdef.fvrectx_adj = (float) r_refdef.vrect.x - 0.5;
257 	r_refdef.vrect_x_adj_shift20 = (r_refdef.vrect.x << 20) + (1 << 19) - 1;
258 	r_refdef.fvrecty = (float) r_refdef.vrect.y;
259 	r_refdef.fvrecty_adj = (float) r_refdef.vrect.y - 0.5;
260 	r_refdef.vrectright = r_refdef.vrect.x + r_refdef.vrect.width;
261 	r_refdef.vrectright_adj_shift20 =
262 		(r_refdef.vrectright << 20) + (1 << 19) - 1;
263 	r_refdef.fvrectright = (float) r_refdef.vrectright;
264 	r_refdef.fvrectright_adj = (float) r_refdef.vrectright - 0.5;
265 	r_refdef.vrectrightedge = (float) r_refdef.vrectright - 0.99;
266 	r_refdef.vrectbottom = r_refdef.vrect.y + r_refdef.vrect.height;
267 	r_refdef.fvrectbottom = (float) r_refdef.vrectbottom;
268 	r_refdef.fvrectbottom_adj = (float) r_refdef.vrectbottom - 0.5;
269 
270 	r_refdef.aliasvrect.x = (int) (r_refdef.vrect.x * sw32_r_aliasuvscale);
271 	r_refdef.aliasvrect.y = (int) (r_refdef.vrect.y * sw32_r_aliasuvscale);
272 	r_refdef.aliasvrect.width = (int) (r_refdef.vrect.width * sw32_r_aliasuvscale);
273 	r_refdef.aliasvrect.height = (int) (r_refdef.vrect.height *
274 										sw32_r_aliasuvscale);
275 	r_refdef.aliasvrectright = r_refdef.aliasvrect.x +
276 		r_refdef.aliasvrect.width;
277 	r_refdef.aliasvrectbottom = r_refdef.aliasvrect.y +
278 		r_refdef.aliasvrect.height;
279 
280 	sw32_pixelAspect = aspect;
281 	xOrigin = r_refdef.xOrigin;
282 	yOrigin = r_refdef.yOrigin;
283 
284 	screenAspect = r_refdef.vrect.width * sw32_pixelAspect / r_refdef.vrect.height;
285 	// 320*200 1.0 sw32_pixelAspect = 1.6 screenAspect
286 	// 320*240 1.0 sw32_pixelAspect = 1.3333 screenAspect
287 	// proper 320*200 sw32_pixelAspect = 0.8333333
288 
289 	verticalFieldOfView = r_refdef.horizontalFieldOfView / screenAspect;
290 
291 	// values for perspective projection
292 	// if math were exact, the values would range from 0.5 to to range+0.5
293 	// hopefully they wll be in the 0.000001 to range+.999999 and truncate
294 	// the polygon rasterization will never render in the first row or column
295 	// but will definately render in the [range] row and column, so adjust the
296 	// buffer origin to get an exact edge to edge fill
297 	sw32_xcenter = ((float) r_refdef.vrect.width * XCENTERING) +
298 		r_refdef.vrect.x - 0.5;
299 	sw32_aliasxcenter = sw32_xcenter * sw32_r_aliasuvscale;
300 	sw32_ycenter = ((float) r_refdef.vrect.height * YCENTERING) +
301 		r_refdef.vrect.y - 0.5;
302 	sw32_aliasycenter = sw32_ycenter * sw32_r_aliasuvscale;
303 
304 	sw32_xscale = r_refdef.vrect.width / r_refdef.horizontalFieldOfView;
305 	sw32_aliasxscale = sw32_xscale * sw32_r_aliasuvscale;
306 	sw32_xscaleinv = 1.0 / sw32_xscale;
307 	sw32_yscale = sw32_xscale * sw32_pixelAspect;
308 	sw32_aliasyscale = sw32_yscale * sw32_r_aliasuvscale;
309 	sw32_yscaleinv = 1.0 / sw32_yscale;
310 	sw32_xscaleshrink = (r_refdef.vrect.width - 6) / r_refdef.horizontalFieldOfView;
311 	sw32_yscaleshrink = sw32_xscaleshrink * sw32_pixelAspect;
312 
313 	// left side clip
314 	sw32_screenedge[0].normal[0] = -1.0 / (xOrigin *
315 									  r_refdef.horizontalFieldOfView);
316 	sw32_screenedge[0].normal[1] = 0;
317 	sw32_screenedge[0].normal[2] = 1;
318 	sw32_screenedge[0].type = PLANE_ANYZ;
319 
320 	// right side clip
321 	sw32_screenedge[1].normal[0] = 1.0 / ((1.0 - xOrigin) *
322 									 r_refdef.horizontalFieldOfView);
323 	sw32_screenedge[1].normal[1] = 0;
324 	sw32_screenedge[1].normal[2] = 1;
325 	sw32_screenedge[1].type = PLANE_ANYZ;
326 
327 	// top side clip
328 	sw32_screenedge[2].normal[0] = 0;
329 	sw32_screenedge[2].normal[1] = -1.0 / (yOrigin * verticalFieldOfView);
330 	sw32_screenedge[2].normal[2] = 1;
331 	sw32_screenedge[2].type = PLANE_ANYZ;
332 
333 	// bottom side clip
334 	sw32_screenedge[3].normal[0] = 0;
335 	sw32_screenedge[3].normal[1] = 1.0 / ((1.0 - yOrigin) * verticalFieldOfView);
336 	sw32_screenedge[3].normal[2] = 1;
337 	sw32_screenedge[3].type = PLANE_ANYZ;
338 
339 	for (i = 0; i < 4; i++)
340 		VectorNormalize (sw32_screenedge[i].normal);
341 
342 	res_scale = sqrt ((double) (r_refdef.vrect.width * r_refdef.vrect.height) /
343 					  (320.0 * 152.0)) * (2.0 /
344 										  r_refdef.horizontalFieldOfView);
345 	sw32_r_aliastransition = r_aliastransbase->value * res_scale;
346 	sw32_r_resfudge = r_aliastransadj->value * res_scale;
347 
348 	sw32_D_ViewChanged ();
349 }
350 
351 static void
R_DrawEntitiesOnList(void)352 R_DrawEntitiesOnList (void)
353 {
354 	int         j;
355 	unsigned int lnum;
356 	alight_t    lighting;
357 	entity_t   *ent;
358 
359 	// FIXME: remove and do real lighting
360 	float       lightvec[3] = { -1, 0, 0 };
361 	vec3_t      dist;
362 	float       add;
363 	float       minlight;
364 
365 	if (!r_drawentities->int_val)
366 		return;
367 
368 	for (ent = r_ent_queue; ent; ent = ent->next) {
369 		currententity = ent;
370 
371 		switch (currententity->model->type) {
372 			case mod_sprite:
373 				VectorCopy (currententity->origin, r_entorigin);
374 				VectorSubtract (r_origin, r_entorigin, modelorg);
375 				sw32_R_DrawSprite ();
376 				break;
377 
378 			case mod_alias:
379 			case mod_iqm:
380 				VectorCopy (currententity->origin, r_entorigin);
381 				VectorSubtract (r_origin, r_entorigin, modelorg);
382 
383 				minlight = max (currententity->min_light, currententity->model->min_light);
384 
385 				// see if the bounding box lets us trivially reject, also
386 				// sets trivial accept status
387 				currententity->trivial_accept = 0;	//FIXME
388 				if (currententity->model->type == mod_iqm//FIXME
389 					|| sw32_R_AliasCheckBBox ()) {
390 					// 128 instead of 255 due to clamping below
391 					j = max (R_LightPoint (currententity->origin), minlight * 128);
392 
393 					lighting.ambientlight = j;
394 					lighting.shadelight = j;
395 
396 					lighting.plightvec = lightvec;
397 
398 					for (lnum = 0; lnum < r_maxdlights; lnum++) {
399 						if (r_dlights[lnum].die >= vr_data.realtime) {
400 							VectorSubtract (currententity->origin,
401 											r_dlights[lnum].origin, dist);
402 							add = r_dlights[lnum].radius - VectorLength (dist);
403 
404 							if (add > 0)
405 								lighting.ambientlight += add;
406 						}
407 					}
408 
409 					// clamp lighting so it doesn't overbright as much
410 					if (lighting.ambientlight > 128)
411 						lighting.ambientlight = 128;
412 					if (lighting.ambientlight + lighting.shadelight > 192)
413 						lighting.shadelight = 192 - lighting.ambientlight;
414 
415 					if (currententity->model->type == mod_iqm)
416 						sw32_R_IQMDrawModel (&lighting);
417 					else
418 						sw32_R_AliasDrawModel (&lighting);
419 				}
420 
421 				break;
422 
423 			default:
424 				break;
425 		}
426 	}
427 }
428 
429 static void
R_DrawViewModel(void)430 R_DrawViewModel (void)
431 {
432 	// FIXME: remove and do real lighting
433 	float       lightvec[3] = { -1, 0, 0 };
434 	int         j;
435 	unsigned int lnum;
436 	vec3_t      dist;
437 	float       add;
438 	float       minlight;
439 	dlight_t   *dl;
440 
441 	if (vr_data.inhibit_viewmodel || !r_drawviewmodel->int_val
442 		|| !r_drawentities->int_val)
443 		return;
444 
445 	currententity = vr_data.view_model;
446 	if (!currententity->model)
447 		return;
448 
449 	VectorCopy (currententity->origin, r_entorigin);
450 	VectorSubtract (r_origin, r_entorigin, modelorg);
451 
452 	VectorCopy (vup, viewlightvec);
453 	VectorNegate (viewlightvec, viewlightvec);
454 
455 	minlight = max (currententity->min_light, currententity->model->min_light);
456 
457 	j = max (R_LightPoint (currententity->origin), minlight * 128);
458 
459 	r_viewlighting.ambientlight = j;
460 	r_viewlighting.shadelight = j;
461 
462 	// add dynamic lights
463 	for (lnum = 0; lnum < r_maxdlights; lnum++) {
464 		dl = &r_dlights[lnum];
465 		if (!dl->radius)
466 			continue;
467 		if (!dl->radius)
468 			continue;
469 		if (dl->die < vr_data.realtime)
470 			continue;
471 
472 		VectorSubtract (currententity->origin, dl->origin, dist);
473 		add = dl->radius - VectorLength (dist);
474 		if (add > 0)
475 			r_viewlighting.ambientlight += add;
476 	}
477 
478 	// clamp lighting so it doesn't overbright as much
479 	if (r_viewlighting.ambientlight > 128)
480 		r_viewlighting.ambientlight = 128;
481 	if (r_viewlighting.ambientlight + r_viewlighting.shadelight > 192)
482 		r_viewlighting.shadelight = 192 - r_viewlighting.ambientlight;
483 
484 	r_viewlighting.plightvec = lightvec;
485 
486 	sw32_R_AliasDrawModel (&r_viewlighting);
487 }
488 
489 static int
R_BmodelCheckBBox(model_t * clmodel,float * minmaxs)490 R_BmodelCheckBBox (model_t *clmodel, float *minmaxs)
491 {
492 	int         i, *pindex, clipflags;
493 	vec3_t      acceptpt, rejectpt;
494 	double      d;
495 
496 	clipflags = 0;
497 
498 	if (currententity->transform[0] != 1 || currententity->transform[5] != 1
499 		|| currententity->transform[10] != 1) {
500 		for (i = 0; i < 4; i++) {
501 			d = DotProduct (currententity->origin, sw32_view_clipplanes[i].normal);
502 			d -= sw32_view_clipplanes[i].dist;
503 
504 			if (d <= -clmodel->radius)
505 				return BMODEL_FULLY_CLIPPED;
506 
507 			if (d <= clmodel->radius)
508 				clipflags |= (1 << i);
509 		}
510 	} else {
511 		for (i = 0; i < 4; i++) {
512 			// generate accept and reject points
513 			// FIXME: do with fast look-ups or integer tests based on the
514 			// sign bit of the floating point values
515 
516 			pindex = sw32_pfrustum_indexes[i];
517 
518 			rejectpt[0] = minmaxs[pindex[0]];
519 			rejectpt[1] = minmaxs[pindex[1]];
520 			rejectpt[2] = minmaxs[pindex[2]];
521 
522 			d = DotProduct (rejectpt, sw32_view_clipplanes[i].normal);
523 			d -= sw32_view_clipplanes[i].dist;
524 
525 			if (d <= 0)
526 				return BMODEL_FULLY_CLIPPED;
527 
528 			acceptpt[0] = minmaxs[pindex[3 + 0]];
529 			acceptpt[1] = minmaxs[pindex[3 + 1]];
530 			acceptpt[2] = minmaxs[pindex[3 + 2]];
531 
532 			d = DotProduct (acceptpt, sw32_view_clipplanes[i].normal);
533 			d -= sw32_view_clipplanes[i].dist;
534 
535 			if (d <= 0)
536 				clipflags |= (1 << i);
537 		}
538 	}
539 
540 	return clipflags;
541 }
542 
543 static void
R_DrawBEntitiesOnList(void)544 R_DrawBEntitiesOnList (void)
545 {
546 	int         j, clipflags;
547 	unsigned int k;
548 	vec3_t      oldorigin;
549 	model_t    *clmodel;
550 	float       minmaxs[6];
551 	entity_t   *ent;
552 
553 	if (!r_drawentities->int_val)
554 		return;
555 
556 	VectorCopy (modelorg, oldorigin);
557 	insubmodel = true;
558 
559 	for (ent = r_ent_queue; ent; ent = ent->next) {
560 		currententity = ent;
561 
562 		switch (currententity->model->type) {
563 			case mod_brush:
564 				clmodel = currententity->model;
565 
566 				// see if the bounding box lets us trivially reject, also
567 				// sets trivial accept status
568 				for (j = 0; j < 3; j++) {
569 					minmaxs[j] = currententity->origin[j] + clmodel->mins[j];
570 					minmaxs[3 + j] = currententity->origin[j] +
571 						clmodel->maxs[j];
572 				}
573 
574 				clipflags = R_BmodelCheckBBox (clmodel, minmaxs);
575 
576 				if (clipflags != BMODEL_FULLY_CLIPPED) {
577 					VectorCopy (currententity->origin, r_entorigin);
578 					VectorSubtract (r_origin, r_entorigin, modelorg);
579 
580 					// FIXME: is this needed?
581 					VectorCopy (modelorg, sw32_r_worldmodelorg);
582 					r_pcurrentvertbase = clmodel->vertexes;
583 
584 					// FIXME: stop transforming twice
585 					sw32_R_RotateBmodel ();
586 
587 					// calculate dynamic lighting for bmodel if it's not an
588 					// instanced model
589 					if (clmodel->firstmodelsurface != 0) {
590 						vec3_t      lightorigin;
591 
592 						for (k = 0; k < r_maxdlights; k++) {
593 							if ((r_dlights[k].die < vr_data.realtime) ||
594 								(!r_dlights[k].radius)) continue;
595 
596 							VectorSubtract (r_dlights[k].origin,
597 											currententity->origin,
598 											lightorigin);
599 							R_RecursiveMarkLights (lightorigin, &r_dlights[k],
600 												   1 << k, clmodel->nodes +
601 										  clmodel->hulls[0].firstclipnode);
602 						}
603 					}
604 					// if the driver wants polygons, deliver those.
605 					// Z-buffering is on at this point, so no clipping to the
606 					// world tree is needed, just frustum clipping
607 					if (sw32_r_drawpolys | sw32_r_drawculledpolys) {
608 						sw32_R_ZDrawSubmodelPolys (clmodel);
609 					} else {
610 						if (currententity->topnode) {
611 							mnode_t    *topnode = currententity->topnode;
612 
613 							if (topnode->contents >= 0) {
614 								// not a leaf; has to be clipped to the world
615 								// BSP
616 								sw32_r_clipflags = clipflags;
617 								sw32_R_DrawSolidClippedSubmodelPolygons (clmodel);
618 							} else {
619 								// falls entirely in one leaf, so we just put
620 								// all the edges in the edge list and let 1/z
621 								// sorting handle drawing order
622 								sw32_R_DrawSubmodelPolygons (clmodel, clipflags);
623 							}
624 						}
625 					}
626 
627 					// put back world rotation and frustum clipping
628 					// FIXME: sw32_R_RotateBmodel should just work off base_vxx
629 					VectorCopy (base_vpn, vpn);
630 					VectorCopy (base_vup, vup);
631 					VectorCopy (base_vright, vright);
632 					VectorCopy (base_modelorg, modelorg);
633 					VectorCopy (oldorigin, modelorg);
634 					sw32_R_TransformFrustum ();
635 				}
636 				break;
637 			default:
638 				break;
639 		}
640 	}
641 
642 	insubmodel = false;
643 }
644 
645 static void
R_PrintDSpeeds(void)646 R_PrintDSpeeds (void)
647 {
648 	float       ms, dp_time, r_time2, rw_time, db_time, se_time, de_time,
649 
650 		dv_time;
651 
652 	r_time2 = Sys_DoubleTime ();
653 
654 	dp_time = (dp_time2 - dp_time1) * 1000;
655 	rw_time = (rw_time2 - rw_time1) * 1000;
656 	db_time = (db_time2 - db_time1) * 1000;
657 	se_time = (se_time2 - se_time1) * 1000;
658 	de_time = (de_time2 - de_time1) * 1000;
659 	dv_time = (dv_time2 - dv_time1) * 1000;
660 	ms = (r_time2 - r_time1) * 1000;
661 
662 	Sys_Printf ("%3i %4.1fp %3iw %4.1fb %3is %4.1fe %4.1fv\n",
663 				(int) ms, dp_time, (int) rw_time, db_time, (int) se_time,
664 				de_time, dv_time);
665 }
666 
667 static void
R_EdgeDrawing(void)668 R_EdgeDrawing (void)
669 {
670 	edge_t      ledges[NUMSTACKEDGES +
671 					   ((CACHE_SIZE - 1) / sizeof (edge_t)) + 1];
672 	surf_t      lsurfs[NUMSTACKSURFACES +
673 					   ((CACHE_SIZE - 1) / sizeof (surf_t)) + 1];
674 
675 	if (sw32_auxedges) {
676 		sw32_r_edges = sw32_auxedges;
677 	} else {
678 		sw32_r_edges = (edge_t *)
679 			(((intptr_t) &ledges[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
680 	}
681 
682 	if (r_surfsonstack) {
683 		sw32_surfaces = (surf_t *)
684 			(((intptr_t) &lsurfs[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
685 		sw32_surf_max = &sw32_surfaces[r_cnumsurfs];
686 		// surface 0 doesn't really exist; it's just a dummy because index 0
687 		// is used to indicate no edge attached to surface
688 		sw32_surfaces--;
689 	}
690 
691 	sw32_R_BeginEdgeFrame ();
692 
693 	if (r_dspeeds->int_val) {
694 		rw_time1 = Sys_DoubleTime ();
695 	}
696 
697 	sw32_R_RenderWorld ();
698 
699 	if (sw32_r_drawculledpolys)
700 		sw32_R_ScanEdges ();
701 
702 	// only the world can be drawn back to front with no z reads or compares,
703 	// just z writes, so have the driver turn z compares on now
704 	sw32_D_TurnZOn ();
705 
706 	if (r_dspeeds->int_val) {
707 		rw_time2 = Sys_DoubleTime ();
708 		db_time1 = rw_time2;
709 	}
710 
711 	R_DrawBEntitiesOnList ();
712 
713 	if (r_dspeeds->int_val) {
714 		db_time2 = Sys_DoubleTime ();
715 		se_time1 = db_time2;
716 	}
717 
718 	if (!r_dspeeds->int_val) {
719 		VID_UnlockBuffer ();
720 		S_ExtraUpdate ();		// don't let sound get messed up if going slow
721 		VID_LockBuffer ();
722 	}
723 
724 	if (!(sw32_r_drawpolys | sw32_r_drawculledpolys))
725 		sw32_R_ScanEdges ();
726 }
727 
728 // LordHavoc: took out of stack and made 4x size for 32bit capacity
729 static byte warpbuffer[WARP_WIDTH * WARP_HEIGHT * 4];
730 
731 /*
732 	R_RenderView
733 
734 	r_refdef must be set before the first call
735 */
736 static void
R_RenderView_(void)737 R_RenderView_ (void)
738 {
739 	if (r_norefresh->int_val)
740 		return;
741 
742 	sw32_r_warpbuffer = warpbuffer;
743 
744 	if (r_timegraph->int_val || r_speeds->int_val || r_dspeeds->int_val)
745 		r_time1 = Sys_DoubleTime ();
746 
747 	sw32_R_SetupFrame ();
748 
749 #ifdef PASSAGES
750 	SetVisibilityByPassages ();
751 #else
752 	R_MarkLeaves ();				// done here so we know if we're in water
753 #endif
754 	R_PushDlights (vec3_origin);
755 
756 	if (!r_worldentity.model)
757 		Sys_Error ("R_RenderView: NULL worldmodel");
758 
759 	if (!r_dspeeds->int_val) {
760 		VID_UnlockBuffer ();
761 		S_ExtraUpdate ();		// don't let sound get messed up if going slow
762 		VID_LockBuffer ();
763 	}
764 
765 	R_EdgeDrawing ();
766 
767 	if (!r_dspeeds->int_val) {
768 		VID_UnlockBuffer ();
769 		S_ExtraUpdate ();		// don't let sound get messed up if going slow
770 		VID_LockBuffer ();
771 	}
772 
773 	if (r_dspeeds->int_val) {
774 		se_time2 = Sys_DoubleTime ();
775 		de_time1 = se_time2;
776 	}
777 
778 	R_DrawEntitiesOnList ();
779 
780 	if (r_dspeeds->int_val) {
781 		de_time2 = Sys_DoubleTime ();
782 		dv_time1 = de_time2;
783 	}
784 
785 	R_DrawViewModel ();
786 
787 	if (r_dspeeds->int_val) {
788 		dv_time2 = Sys_DoubleTime ();
789 		dp_time1 = Sys_DoubleTime ();
790 	}
791 
792 	sw32_R_DrawParticles ();
793 
794 	if (r_dspeeds->int_val)
795 		dp_time2 = Sys_DoubleTime ();
796 
797 	if (sw32_r_dowarp)
798 		sw32_D_WarpScreen ();
799 
800 	if (r_timegraph->int_val)
801 		R_TimeGraph ();
802 
803 	if (r_zgraph->int_val)
804 		R_ZGraph ();
805 
806 	if (r_aliasstats->int_val)
807 		sw32_R_PrintAliasStats ();
808 
809 	if (r_speeds->int_val)
810 		sw32_R_PrintTimes ();
811 
812 	if (r_dspeeds->int_val)
813 		R_PrintDSpeeds ();
814 
815 	if (r_reportsurfout->int_val && sw32_r_outofsurfaces)
816 		Sys_Printf ("Short %d surfaces\n", sw32_r_outofsurfaces);
817 
818 	if (r_reportedgeout->int_val && sw32_r_outofedges)
819 		Sys_Printf ("Short roughly %d edges\n", sw32_r_outofedges * 2 / 3);
820 }
821 
822 void
sw32_R_RenderView(void)823 sw32_R_RenderView (void)
824 {
825 	int         dummy;
826 	int         delta;
827 
828 	delta = (byte *) & dummy - r_stack_start;
829 	if (delta < -10000 || delta > 10000)
830 		Sys_Error ("R_RenderView: called without enough stack");
831 
832 	if (Hunk_LowMark () & 3)
833 		Sys_Error ("Hunk is missaligned");
834 
835 	if ((intptr_t) (&dummy) & 3)
836 		Sys_Error ("Stack is missaligned");
837 
838 	if ((intptr_t) (&sw32_r_warpbuffer) & 3)
839 		Sys_Error ("Globals are missaligned");
840 
841 	R_RenderView_ ();
842 }
843 
844 void
sw32_R_InitTurb(void)845 sw32_R_InitTurb (void)
846 {
847 	int         i;
848 
849 	for (i = 0; i < MAXWIDTH; i++) {
850 		sw32_sintable[i] = AMP + sin (i * 3.14159 * 2 / CYCLE) * AMP;
851 		sw32_intsintable[i] = AMP2 + sin (i * 3.14159 * 2 / CYCLE) * AMP2;
852 		// AMP2 not 20
853 	}
854 }
855 
856 void
sw32_R_ClearState(void)857 sw32_R_ClearState (void)
858 {
859 	R_ClearEfrags ();
860 	R_ClearDlights ();
861 	sw32_R_ClearParticles ();
862 }
863