1 /*
2 	sw32_ralias.c
3 
4 	routines for setting up to draw alias models
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/image.h"
35 #include "QF/render.h"
36 #include "QF/skin.h"
37 #include "QF/sys.h"
38 
39 #include "d_ifacea.h"
40 #include "r_internal.h"
41 
42 #include "stdlib.h"
43 
44 #define LIGHT_MIN	5					// lowest light value we'll allow, to
45 										// avoid the need for inner-loop light
46 										// clamping
47 
48 affinetridesc_t sw32_r_affinetridesc;
49 
50 void       *sw32_acolormap;					// FIXME: should go away
51 
52 trivertx_t *sw32_r_apverts;
53 
54 // TODO: these probably will go away with optimized rasterization
55 static mdl_t      *pmdl;
56 vec3_t      sw32_r_plightvec;
57 int         sw32_r_ambientlight;
58 float       sw32_r_shadelight;
59 static aliashdr_t *paliashdr;
60 finalvert_t *sw32_pfinalverts;
61 auxvert_t  *sw32_pauxverts;
62 float sw32_ziscale;
63 static model_t *pmodel;
64 
65 static vec3_t alias_forward, alias_right, alias_up;
66 
67 static maliasskindesc_t *pskindesc;
68 
69 int         sw32_r_amodels_drawn;
70 static int         a_skinwidth;
71 static int         r_anumverts;
72 
73 float       sw32_aliastransform[3][4];
74 
75 typedef struct {
76 	int         index0;
77 	int         index1;
78 } aedge_t;
79 
80 static aedge_t aedges[12] = {
81 	{0, 1}, {1, 2}, {2, 3}, {3, 0},
82 	{4, 5}, {5, 6}, {6, 7}, {7, 4},
83 	{0, 5}, {1, 4}, {2, 7}, {3, 6}
84 };
85 
86 qboolean
sw32_R_AliasCheckBBox(void)87 sw32_R_AliasCheckBBox (void)
88 {
89 	int         i, flags, frame, numv;
90 	aliashdr_t *pahdr;
91 	float       zi, basepts[8][3], v0, v1, frac;
92 	finalvert_t *pv0, *pv1, viewpts[16];
93 	auxvert_t  *pa0, *pa1, viewaux[16];
94 	maliasframedesc_t *pframedesc;
95 	qboolean    zclipped, zfullyclipped;
96 	unsigned int anyclip, allclip;
97 	int         minz;
98 
99 	// expand, rotate, and translate points into worldspace
100 	currententity->trivial_accept = 0;
101 	pmodel = currententity->model;
102 	if (!(pahdr = pmodel->aliashdr))
103 		pahdr = Cache_Get (&pmodel->cache);
104 	pmdl = (mdl_t *) ((byte *) pahdr + pahdr->model);
105 
106 	sw32_R_AliasSetUpTransform (0);
107 
108 	// construct the base bounding box for this frame
109 	frame = currententity->frame;
110 // TODO: don't repeat this check when drawing?
111 	if ((frame >= pmdl->numframes) || (frame < 0)) {
112 		Sys_MaskPrintf (SYS_DEV, "No such frame %d %s\n", frame, pmodel->name);
113 		frame = 0;
114 	}
115 
116 	pframedesc = &pahdr->frames[frame];
117 
118 	// x worldspace coordinates
119 	basepts[0][0] = basepts[1][0] = basepts[2][0] = basepts[3][0] =
120 		(float) pframedesc->bboxmin.v[0];
121 	basepts[4][0] = basepts[5][0] = basepts[6][0] = basepts[7][0] =
122 		(float) pframedesc->bboxmax.v[0];
123 
124 	// y worldspace coordinates
125 	basepts[0][1] = basepts[3][1] = basepts[5][1] = basepts[6][1] =
126 		(float) pframedesc->bboxmin.v[1];
127 	basepts[1][1] = basepts[2][1] = basepts[4][1] = basepts[7][1] =
128 		(float) pframedesc->bboxmax.v[1];
129 
130 	// z worldspace coordinates
131 	basepts[0][2] = basepts[1][2] = basepts[4][2] = basepts[5][2] =
132 		(float) pframedesc->bboxmin.v[2];
133 	basepts[2][2] = basepts[3][2] = basepts[6][2] = basepts[7][2] =
134 		(float) pframedesc->bboxmax.v[2];
135 
136 	zclipped = false;
137 	zfullyclipped = true;
138 
139 	minz = 9999;
140 	for (i = 0; i < 8; i++) {
141 		sw32_R_AliasTransformVector (&basepts[i][0], &viewaux[i].fv[0]);
142 
143 		if (viewaux[i].fv[2] < ALIAS_Z_CLIP_PLANE) {
144 			// we must clip points that are closer than the near clip plane
145 			viewpts[i].flags = ALIAS_Z_CLIP;
146 			zclipped = true;
147 		} else {
148 			if (viewaux[i].fv[2] < minz)
149 				minz = viewaux[i].fv[2];
150 			viewpts[i].flags = 0;
151 			zfullyclipped = false;
152 		}
153 	}
154 
155 	if (zfullyclipped) {
156 		if (!pmodel->aliashdr)
157 			Cache_Release (&pmodel->cache);
158 		return false;					// everything was near-z-clipped
159 	}
160 
161 	numv = 8;
162 
163 	if (zclipped) {
164 		// organize points by edges, use edges to get new points (possible
165 		// trivial reject)
166 		for (i = 0; i < 12; i++) {
167 			// edge endpoints
168 			pv0 = &viewpts[aedges[i].index0];
169 			pv1 = &viewpts[aedges[i].index1];
170 			pa0 = &viewaux[aedges[i].index0];
171 			pa1 = &viewaux[aedges[i].index1];
172 
173 			// if one end is clipped and the other isn't, make a new point
174 			if (pv0->flags ^ pv1->flags) {
175 				frac = (ALIAS_Z_CLIP_PLANE - pa0->fv[2]) /
176 					(pa1->fv[2] - pa0->fv[2]);
177 				viewaux[numv].fv[0] = pa0->fv[0] +
178 					(pa1->fv[0] - pa0->fv[0]) * frac;
179 				viewaux[numv].fv[1] = pa0->fv[1] +
180 					(pa1->fv[1] - pa0->fv[1]) * frac;
181 				viewaux[numv].fv[2] = ALIAS_Z_CLIP_PLANE;
182 				viewpts[numv].flags = 0;
183 				numv++;
184 			}
185 		}
186 	}
187 	// project the vertices that remain after clipping
188 	anyclip = 0;
189 	allclip = ALIAS_XY_CLIP_MASK;
190 
191 // TODO: probably should do this loop in ASM, especially if we use floats
192 	for (i = 0; i < numv; i++) {
193 		// we don't need to bother with vertices that were z-clipped
194 		if (viewpts[i].flags & ALIAS_Z_CLIP)
195 			continue;
196 
197 		zi = 1.0 / viewaux[i].fv[2];
198 
199 		// FIXME: do with chop mode in ASM, or convert to float
200 		v0 = (viewaux[i].fv[0] * sw32_xscale * zi) + sw32_xcenter;
201 		v1 = (viewaux[i].fv[1] * sw32_yscale * zi) + sw32_ycenter;
202 
203 		flags = 0;
204 
205 		if (v0 < r_refdef.fvrectx)
206 			flags |= ALIAS_LEFT_CLIP;
207 		if (v1 < r_refdef.fvrecty)
208 			flags |= ALIAS_TOP_CLIP;
209 		if (v0 > r_refdef.fvrectright)
210 			flags |= ALIAS_RIGHT_CLIP;
211 		if (v1 > r_refdef.fvrectbottom)
212 			flags |= ALIAS_BOTTOM_CLIP;
213 
214 		anyclip |= flags;
215 		allclip &= flags;
216 	}
217 
218 	if (allclip) {
219 		if (!pmodel->aliashdr)
220 			Cache_Release (&pmodel->cache);
221 		return false;					// trivial reject off one side
222 	}
223 
224 	currententity->trivial_accept = !anyclip & !zclipped;
225 
226 	if (currententity->trivial_accept) {
227 		if (minz > (sw32_r_aliastransition + (pmdl->size * sw32_r_resfudge))) {
228 			currententity->trivial_accept |= 2;
229 		}
230 	}
231 
232 	if (!pmodel->aliashdr)
233 		Cache_Release (&pmodel->cache);
234 	return true;
235 }
236 
237 
238 void
sw32_R_AliasTransformVector(vec3_t in,vec3_t out)239 sw32_R_AliasTransformVector (vec3_t in, vec3_t out)
240 {
241 	out[0] = DotProduct (in, sw32_aliastransform[0])
242 		+ sw32_aliastransform[0][3];
243 	out[1] = DotProduct (in, sw32_aliastransform[1])
244 		+ sw32_aliastransform[1][3];
245 	out[2] = DotProduct (in, sw32_aliastransform[2])
246 		+ sw32_aliastransform[2][3];
247 }
248 
249 
250 void
sw32_R_AliasClipAndProjectFinalVert(finalvert_t * fv,auxvert_t * av)251 sw32_R_AliasClipAndProjectFinalVert (finalvert_t *fv, auxvert_t *av)
252 {
253 	if (av->fv[2] < ALIAS_Z_CLIP_PLANE) {
254 		fv->flags |= ALIAS_Z_CLIP;
255 		return;
256 	}
257 
258 	sw32_R_AliasProjectFinalVert (fv, av);
259 
260 	if (fv->v[0] < r_refdef.aliasvrect.x)
261 		fv->flags |= ALIAS_LEFT_CLIP;
262 	if (fv->v[1] < r_refdef.aliasvrect.y)
263 		fv->flags |= ALIAS_TOP_CLIP;
264 	if (fv->v[0] > r_refdef.aliasvrectright)
265 		fv->flags |= ALIAS_RIGHT_CLIP;
266 	if (fv->v[1] > r_refdef.aliasvrectbottom)
267 		fv->flags |= ALIAS_BOTTOM_CLIP;
268 }
269 
270 static void
R_AliasTransformFinalVert16(auxvert_t * av,trivertx_t * pverts)271 R_AliasTransformFinalVert16 (auxvert_t *av, trivertx_t *pverts)
272 {
273 	trivertx_t  * pextra;
274 	float       vextra[3];
275 
276 	pextra = pverts + pmdl->numverts;
277 	vextra[0] = pverts->v[0] + pextra->v[0] / (float)256;
278 	vextra[1] = pverts->v[1] + pextra->v[1] / (float)256;
279 	vextra[2] = pverts->v[2] + pextra->v[2] / (float)256;
280 	av->fv[0] = DotProduct (vextra, sw32_aliastransform[0]) +
281 		sw32_aliastransform[0][3];
282 	av->fv[1] = DotProduct (vextra, sw32_aliastransform[1]) +
283 		sw32_aliastransform[1][3];
284 	av->fv[2] = DotProduct (vextra, sw32_aliastransform[2]) +
285 		sw32_aliastransform[2][3];
286 }
287 
288 static void
R_AliasTransformFinalVert8(auxvert_t * av,trivertx_t * pverts)289 R_AliasTransformFinalVert8 (auxvert_t *av, trivertx_t *pverts)
290 {
291 	av->fv[0] = DotProduct (pverts->v, sw32_aliastransform[0]) +
292 		sw32_aliastransform[0][3];
293 	av->fv[1] = DotProduct (pverts->v, sw32_aliastransform[1]) +
294 		sw32_aliastransform[1][3];
295 	av->fv[2] = DotProduct (pverts->v, sw32_aliastransform[2]) +
296 		sw32_aliastransform[2][3];
297 }
298 
299 /*
300 	R_AliasPreparePoints
301 
302 	General clipped case
303 */
304 static void
R_AliasPreparePoints(void)305 R_AliasPreparePoints (void)
306 {
307 	int         i;
308 	stvert_t   *pstverts;
309 	finalvert_t *fv;
310 	auxvert_t  *av;
311 	mtriangle_t *ptri;
312 	finalvert_t *pfv[3];
313 
314 	pstverts = (stvert_t *) ((byte *) paliashdr + paliashdr->stverts);
315 	r_anumverts = pmdl->numverts;
316 	fv = pfinalverts;
317 	av = sw32_pauxverts;
318 
319 	if (pmdl->ident == HEADER_MDL16) {
320 		for (i = 0; i < r_anumverts; i++, fv++, av++, sw32_r_apverts++,
321 				pstverts++) {
322 			R_AliasTransformFinalVert16 (av, sw32_r_apverts);
323 			sw32_R_AliasTransformFinalVert (fv, sw32_r_apverts, pstverts);
324 			R_AliasClipAndProjectFinalVert (fv, av);
325 		}
326 	}
327 	else {
328 		for (i = 0; i < r_anumverts; i++, fv++, av++, sw32_r_apverts++,
329 				pstverts++) {
330 			R_AliasTransformFinalVert8 (av, sw32_r_apverts);
331 			sw32_R_AliasTransformFinalVert (fv, sw32_r_apverts, pstverts);
332 			R_AliasClipAndProjectFinalVert (fv, av);
333 		}
334 	}
335 
336 	// clip and draw all triangles
337 	sw32_r_affinetridesc.numtriangles = 1;
338 
339 	ptri = (mtriangle_t *) ((byte *) paliashdr + paliashdr->triangles);
340 	for (i = 0; i < pmdl->numtris; i++, ptri++) {
341 		pfv[0] = &pfinalverts[ptri->vertindex[0]];
342 		pfv[1] = &pfinalverts[ptri->vertindex[1]];
343 		pfv[2] = &pfinalverts[ptri->vertindex[2]];
344 
345 		if (pfv[0]->flags & pfv[1]->flags & pfv[2]->
346 			flags & (ALIAS_XY_CLIP_MASK | ALIAS_Z_CLIP))
347 			continue;					// completely clipped
348 
349 		if (!((pfv[0]->flags | pfv[1]->flags | pfv[2]->flags) &
350 			  (ALIAS_XY_CLIP_MASK | ALIAS_Z_CLIP))) {	// totally unclipped
351 			sw32_r_affinetridesc.pfinalverts = pfinalverts;
352 			sw32_r_affinetridesc.ptriangles = ptri;
353 			sw32_D_PolysetDraw ();
354 		} else {						// partially clipped
355 			sw32_R_AliasClipTriangle (ptri);
356 		}
357 	}
358 }
359 
360 
361 void
sw32_R_AliasSetUpTransform(int trivial_accept)362 sw32_R_AliasSetUpTransform (int trivial_accept)
363 {
364 	int         i;
365 	float       rotationmatrix[3][4], t2matrix[3][4];
366 	static float tmatrix[3][4];
367 	static float viewmatrix[3][4];
368 
369 	VectorCopy (currententity->transform + 0, alias_forward);
370 	VectorNegate (currententity->transform + 4, alias_right);
371 	VectorCopy (currententity->transform + 8, alias_up);
372 
373 	tmatrix[0][0] = pmdl->scale[0];
374 	tmatrix[1][1] = pmdl->scale[1];
375 	tmatrix[2][2] = pmdl->scale[2];
376 
377 	tmatrix[0][3] = pmdl->scale_origin[0];
378 	tmatrix[1][3] = pmdl->scale_origin[1];
379 	tmatrix[2][3] = pmdl->scale_origin[2];
380 
381 // TODO: can do this with simple matrix rearrangement
382 
383 	for (i = 0; i < 3; i++) {
384 		t2matrix[i][0] = alias_forward[i];
385 		t2matrix[i][1] = -alias_right[i];
386 		t2matrix[i][2] = alias_up[i];
387 	}
388 
389 	t2matrix[0][3] = -modelorg[0];
390 	t2matrix[1][3] = -modelorg[1];
391 	t2matrix[2][3] = -modelorg[2];
392 
393 // FIXME: can do more efficiently than full concatenation
394 	R_ConcatTransforms (t2matrix, tmatrix, rotationmatrix);
395 
396 // TODO: should be global, set when vright, etc., set
397 	VectorCopy (vright, viewmatrix[0]);
398 	VectorCopy (vup, viewmatrix[1]);
399 	VectorNegate (viewmatrix[1], viewmatrix[1]);
400 	VectorCopy (vpn, viewmatrix[2]);
401 
402 //	viewmatrix[0][3] = 0;
403 //	viewmatrix[1][3] = 0;
404 //	viewmatrix[2][3] = 0;
405 
406 	R_ConcatTransforms (viewmatrix, rotationmatrix, sw32_aliastransform);
407 
408 // do the scaling up of x and y to screen coordinates as part of the transform
409 // for the unclipped case (it would mess up clipping in the clipped case).
410 // Also scale down z, so 1/z is scaled 31 bits for free, and scale down x and y
411 // correspondingly so the projected x and y come out right
412 // FIXME: make this work for clipped case too?
413 	if (trivial_accept) {
414 		for (i = 0; i < 4; i++) {
415 			sw32_aliastransform[0][i] *= sw32_aliasxscale *
416 				(1.0 / ((float) 0x8000 * 0x10000));
417 			sw32_aliastransform[1][i] *= sw32_aliasyscale *
418 				(1.0 / ((float) 0x8000 * 0x10000));
419 			sw32_aliastransform[2][i] *= 1.0 / ((float) 0x8000 * 0x10000);
420 		}
421 	}
422 }
423 
424 /*
425 sw32_R_AliasTransformFinalVert
426 
427 now this function just copies the texture coordinates and calculates lighting
428 actual 3D transform is done by R_AliasTransformFinalVert8/16 functions above
429 */
430 void
sw32_R_AliasTransformFinalVert(finalvert_t * fv,trivertx_t * pverts,stvert_t * pstverts)431 sw32_R_AliasTransformFinalVert (finalvert_t *fv, trivertx_t *pverts,
432 								stvert_t *pstverts)
433 {
434 	int         temp;
435 	float       lightcos, *plightnormal;
436 
437 	fv->v[2] = pstverts->s;
438 	fv->v[3] = pstverts->t;
439 
440 	fv->flags = pstverts->onseam;
441 
442 	// lighting
443 	// LordHavoc: flipped lightcos so it is + for bright, not -
444 	plightnormal = r_avertexnormals[pverts->lightnormalindex];
445 	lightcos = -DotProduct (plightnormal, sw32_r_plightvec);
446 	temp = sw32_r_ambientlight;
447 
448 	if (lightcos > 0) {
449 		temp += (int) (sw32_r_shadelight * lightcos);
450 
451 		// clamp; because we limited the minimum ambient and shading light,
452 		// we don't have to clamp low light, just bright
453 		if (temp < 0)
454 			temp = 0;
455 	}
456 
457 	fv->v[4] = temp;
458 }
459 
460 void
sw32_R_AliasTransformAndProjectFinalVerts(finalvert_t * fv,stvert_t * pstverts)461 sw32_R_AliasTransformAndProjectFinalVerts (finalvert_t *fv, stvert_t *pstverts)
462 {
463 	int         i, temp;
464 	float       lightcos, *plightnormal, zi;
465 	trivertx_t *pverts;
466 
467 	pverts = sw32_r_apverts;
468 
469 	for (i = 0; i < r_anumverts; i++, fv++, pverts++, pstverts++) {
470 		// transform and project
471 		zi = 1.0 / (DotProduct (pverts->v, sw32_aliastransform[2]) +
472 					sw32_aliastransform[2][3]);
473 
474 		// x, y, and z are scaled down by 1/2**31 in the transform, so 1/z is
475 		// scaled up by 1/2**31, and the scaling cancels out for x and y in
476 		// the projection
477 		fv->v[5] = zi;
478 
479 		fv->v[0] = ((DotProduct (pverts->v, sw32_aliastransform[0]) +
480 					 sw32_aliastransform[0][3]) * zi) + sw32_aliasxcenter;
481 		fv->v[1] = ((DotProduct (pverts->v, sw32_aliastransform[1]) +
482 					 sw32_aliastransform[1][3]) * zi) + sw32_aliasycenter;
483 
484 		fv->v[2] = pstverts->s;
485 		fv->v[3] = pstverts->t;
486 		fv->flags = pstverts->onseam;
487 
488 		// lighting
489 		// LordHavoc: flipped lightcos so it is + for bright, not -
490 		plightnormal = r_avertexnormals[pverts->lightnormalindex];
491 		lightcos = -DotProduct (plightnormal, sw32_r_plightvec);
492 		temp = sw32_r_ambientlight;
493 
494 		if (lightcos > 0) {
495 			temp += (int) (sw32_r_shadelight * lightcos);
496 
497 			// clamp; because we limited the minimum ambient and shading
498 			// light, we don't have to clamp low light, just bright
499 			if (temp < 0)
500 				temp = 0;
501 		}
502 
503 		fv->v[4] = temp;
504 	}
505 }
506 
507 void
sw32_R_AliasProjectFinalVert(finalvert_t * fv,auxvert_t * av)508 sw32_R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av)
509 {
510 	float       zi;
511 
512 	// project points
513 	zi = 1.0 / av->fv[2];
514 
515 	fv->v[5] = zi * sw32_ziscale;
516 
517 	fv->v[0] = (av->fv[0] * sw32_aliasxscale * zi) + sw32_aliasxcenter;
518 	fv->v[1] = (av->fv[1] * sw32_aliasyscale * zi) + sw32_aliasycenter;
519 }
520 
521 
522 static void
R_AliasPrepareUnclippedPoints(void)523 R_AliasPrepareUnclippedPoints (void)
524 {
525 	stvert_t   *pstverts;
526 
527 	pstverts = (stvert_t *) ((byte *) paliashdr + paliashdr->stverts);
528 	r_anumverts = pmdl->numverts;
529 
530 	sw32_R_AliasTransformAndProjectFinalVerts (pfinalverts, pstverts);
531 
532 	sw32_r_affinetridesc.pfinalverts = pfinalverts;
533 	sw32_r_affinetridesc.ptriangles = (mtriangle_t *)
534 		((byte *) paliashdr + paliashdr->triangles);
535 	sw32_r_affinetridesc.numtriangles = pmdl->numtris;
536 
537 	sw32_D_PolysetDraw ();
538 }
539 
540 
541 static void
R_AliasSetupSkin(void)542 R_AliasSetupSkin (void)
543 {
544 	int         skinnum;
545 
546 	skinnum = currententity->skinnum;
547 	if ((skinnum >= pmdl->numskins) || (skinnum < 0)) {
548 		Sys_MaskPrintf (SYS_DEV, "R_AliasSetupSkin: no such skin # %d\n",
549 						skinnum);
550 		skinnum = 0;
551 	}
552 
553 	pskindesc = R_AliasGetSkindesc (skinnum, paliashdr);
554 	a_skinwidth = pmdl->skinwidth;
555 
556 	sw32_r_affinetridesc.pskin = (void *) ((byte *) paliashdr + pskindesc->skin);
557 	sw32_r_affinetridesc.skinwidth = a_skinwidth;
558 	sw32_r_affinetridesc.seamfixupX16 = (a_skinwidth >> 1) << 16;
559 	sw32_r_affinetridesc.skinheight = pmdl->skinheight;
560 
561 	sw32_acolormap = vid.colormap8;
562 	if (currententity->skin) {
563 		tex_t      *base;
564 
565 		base = currententity->skin->texels;
566 		if (base) {
567 			sw32_r_affinetridesc.pskin = base->data;
568 			sw32_r_affinetridesc.skinwidth = base->width;
569 			sw32_r_affinetridesc.skinheight = base->height;
570 		}
571 		sw32_acolormap = currententity->skin->colormap;
572 	}
573 }
574 
575 static void
R_AliasSetupLighting(alight_t * plighting)576 R_AliasSetupLighting (alight_t *plighting)
577 {
578 	// guarantee that no vertex will ever be lit below LIGHT_MIN, so we don't
579 	// have to clamp off the bottom
580 	sw32_r_ambientlight = plighting->ambientlight;
581 
582 	if (sw32_r_ambientlight < LIGHT_MIN)
583 		sw32_r_ambientlight = LIGHT_MIN;
584 
585 	sw32_r_ambientlight = (/*255 -*/ sw32_r_ambientlight) << VID_CBITS;
586 
587 //	if (sw32_r_ambientlight < LIGHT_MIN)
588 //		sw32_r_ambientlight = LIGHT_MIN;
589 
590 	sw32_r_shadelight = plighting->shadelight;
591 
592 	if (sw32_r_shadelight < 0)
593 		sw32_r_shadelight = 0;
594 
595 	sw32_r_shadelight *= VID_GRADES;
596 
597 	// rotate the lighting vector into the model's frame of reference
598 	sw32_r_plightvec[0] = DotProduct (plighting->plightvec, alias_forward);
599 	sw32_r_plightvec[1] = -DotProduct (plighting->plightvec, alias_right);
600 	sw32_r_plightvec[2] = DotProduct (plighting->plightvec, alias_up);
601 }
602 
603 
604 /*
605 	R_AliasSetupFrame
606 
607 	set sw32_r_apverts
608 */
609 static void
R_AliasSetupFrame(void)610 R_AliasSetupFrame (void)
611 {
612 	maliasframedesc_t *frame;
613 
614 	frame = R_AliasGetFramedesc (currententity->frame, paliashdr);
615 	sw32_r_apverts = (trivertx_t *) ((byte *) paliashdr + frame->frame);
616 }
617 
618 
619 void
sw32_R_AliasDrawModel(alight_t * plighting)620 sw32_R_AliasDrawModel (alight_t *plighting)
621 {
622 	int         size;
623 	finalvert_t *finalverts;
624 
625 	sw32_r_amodels_drawn++;
626 
627 	if (!(paliashdr = currententity->model->aliashdr))
628 		paliashdr = Cache_Get (&currententity->model->cache);
629 	pmdl = (mdl_t *) ((byte *) paliashdr + paliashdr->model);
630 
631 	size = (CACHE_SIZE - 1)
632 		   + sizeof (finalvert_t) * (pmdl->numverts + 1)
633 		   + sizeof (auxvert_t) * pmdl->numverts;
634 	finalverts = (finalvert_t *) Hunk_TempAlloc (size);
635 	if (!finalverts)
636 		Sys_Error ("R_AliasDrawModel: out of memory");
637 
638 	// cache align
639 	pfinalverts = (finalvert_t *)
640 		(((intptr_t) &finalverts[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
641 	sw32_pauxverts = (auxvert_t *) &pfinalverts[pmdl->numverts + 1];
642 
643 	R_AliasSetupSkin ();
644 	sw32_R_AliasSetUpTransform (currententity->trivial_accept);
645 	R_AliasSetupLighting (plighting);
646 	R_AliasSetupFrame ();
647 
648 	if (!sw32_acolormap)
649 		sw32_acolormap = vid.colormap8;
650 	if (sw32_acolormap == &vid.colormap8 && sw32_r_pixbytes != 1)
651 	{
652 		if (sw32_r_pixbytes == 2)
653 			sw32_acolormap = vid.colormap16;
654 		else if (sw32_r_pixbytes == 4)
655 			sw32_acolormap = vid.colormap32;
656 		else
657 			Sys_Error("R_AliasDrawmodel: unsupported r_pixbytes %i",
658 					  sw32_r_pixbytes);
659 	}
660 
661 	if (currententity != vr_data.view_model)
662 		sw32_ziscale = (float) 0x8000 *(float) 0x10000;
663 	else
664 		sw32_ziscale = (float) 0x8000 *(float) 0x10000 *3.0;
665 
666 	if (currententity->trivial_accept)
667 		R_AliasPrepareUnclippedPoints ();
668 	else
669 		R_AliasPreparePoints ();
670 
671 	if (!currententity->model->aliashdr)
672 		Cache_Release (&currententity->model->cache);
673 }
674