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// r_alias.c: routines for setting up to draw alias models
21
22#include "quakedef.h"
23#include "r_local.h"
24#include "d_local.h"	// FIXME: shouldn't be needed (is needed for patch
25						// right now, but that should move)
26
27#define LIGHT_MIN	5		// lowest light value we'll allow, to avoid the
28							//  need for inner-loop light clamping
29
30mtriangle_t		*ptriangles;
31affinetridesc_t	r_affinetridesc;
32
33void *			acolormap;	// FIXME: should go away
34
35trivertx_t		*r_apverts;
36
37// TODO: these probably will go away with optimized rasterization
38mdl_t				*pmdl;
39vec3_t				r_plightvec;
40int					r_ambientlight;
41float				r_shadelight;
42aliashdr_t			*paliashdr;
43finalvert_t			*pfinalverts;
44auxvert_t			*pauxverts;
45static float		ziscale;
46static model_t		*pmodel;
47
48static vec3_t		alias_forward, alias_right, alias_up;
49
50static maliasskindesc_t	*pskindesc;
51
52int				r_amodels_drawn;
53int				a_skinwidth;
54int				r_anumverts;
55
56float	aliastransform[3][4];
57
58typedef struct {
59	int	index0;
60	int	index1;
61} aedge_t;
62
63static aedge_t	aedges[12] = {
64{0, 1}, {1, 2}, {2, 3}, {3, 0},
65{4, 5}, {5, 6}, {6, 7}, {7, 4},
66{0, 5}, {1, 4}, {2, 7}, {3, 6}
67};
68
69#define NUMVERTEXNORMALS	162
70
71float	r_avertexnormals[NUMVERTEXNORMALS][3] = {
72#include "anorms.h"
73};
74
75void R_AliasTransformAndProjectFinalVerts (finalvert_t *fv,
76	stvert_t *pstverts);
77void R_AliasSetUpTransform (int trivial_accept);
78void R_AliasTransformVector (vec3_t in, vec3_t out);
79void R_AliasTransformFinalVert (finalvert_t *fv, auxvert_t *av,
80	trivertx_t *pverts, stvert_t *pstverts);
81void R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av);
82
83
84/*
85================
86R_AliasCheckBBox
87================
88*/
89qboolean R_AliasCheckBBox (void)
90{
91	int					i, flags, frame, numv;
92	aliashdr_t			*pahdr;
93	float				zi, basepts[8][3], v0, v1, frac;
94	finalvert_t			*pv0, *pv1, viewpts[16];
95	auxvert_t			*pa0, *pa1, viewaux[16];
96	maliasframedesc_t	*pframedesc;
97	qboolean			zclipped, zfullyclipped;
98	unsigned			anyclip, allclip;
99	int					minz;
100
101// expand, rotate, and translate points into worldspace
102
103	currententity->trivial_accept = 0;
104	pmodel = currententity->model;
105	pahdr = Mod_Extradata (pmodel);
106	pmdl = (mdl_t *)((byte *)pahdr + pahdr->model);
107
108	R_AliasSetUpTransform (0);
109
110// construct the base bounding box for this frame
111	frame = currententity->frame;
112// TODO: don't repeat this check when drawing?
113	if ((frame >= pmdl->numframes) || (frame < 0))
114	{
115		Con_DPrintf ("No such frame %d %s\n", frame,
116				pmodel->name);
117		frame = 0;
118	}
119
120	pframedesc = &pahdr->frames[frame];
121
122// x worldspace coordinates
123	basepts[0][0] = basepts[1][0] = basepts[2][0] = basepts[3][0] =
124			(float)pframedesc->bboxmin.v[0];
125	basepts[4][0] = basepts[5][0] = basepts[6][0] = basepts[7][0] =
126			(float)pframedesc->bboxmax.v[0];
127
128// y worldspace coordinates
129	basepts[0][1] = basepts[3][1] = basepts[5][1] = basepts[6][1] =
130			(float)pframedesc->bboxmin.v[1];
131	basepts[1][1] = basepts[2][1] = basepts[4][1] = basepts[7][1] =
132			(float)pframedesc->bboxmax.v[1];
133
134// z worldspace coordinates
135	basepts[0][2] = basepts[1][2] = basepts[4][2] = basepts[5][2] =
136			(float)pframedesc->bboxmin.v[2];
137	basepts[2][2] = basepts[3][2] = basepts[6][2] = basepts[7][2] =
138			(float)pframedesc->bboxmax.v[2];
139
140	zclipped = false;
141	zfullyclipped = true;
142
143	minz = 9999;
144	for (i=0; i<8 ; i++)
145	{
146		R_AliasTransformVector  (&basepts[i][0], &viewaux[i].fv[0]);
147
148		if (viewaux[i].fv[2] < ALIAS_Z_CLIP_PLANE)
149		{
150		// we must clip points that are closer than the near clip plane
151			viewpts[i].flags = ALIAS_Z_CLIP;
152			zclipped = true;
153		}
154		else
155		{
156			if (viewaux[i].fv[2] < minz)
157				minz = viewaux[i].fv[2];
158			viewpts[i].flags = 0;
159			zfullyclipped = false;
160		}
161	}
162
163
164	if (zfullyclipped)
165	{
166		return false;	// everything was near-z-clipped
167	}
168
169	numv = 8;
170
171	if (zclipped)
172	{
173	// organize points by edges, use edges to get new points (possible trivial
174	// reject)
175		for (i=0 ; i<12 ; i++)
176		{
177		// edge endpoints
178			pv0 = &viewpts[aedges[i].index0];
179			pv1 = &viewpts[aedges[i].index1];
180			pa0 = &viewaux[aedges[i].index0];
181			pa1 = &viewaux[aedges[i].index1];
182
183		// if one end is clipped and the other isn't, make a new point
184			if (pv0->flags ^ pv1->flags)
185			{
186				frac = (ALIAS_Z_CLIP_PLANE - pa0->fv[2]) /
187					   (pa1->fv[2] - pa0->fv[2]);
188				viewaux[numv].fv[0] = pa0->fv[0] +
189						(pa1->fv[0] - pa0->fv[0]) * frac;
190				viewaux[numv].fv[1] = pa0->fv[1] +
191						(pa1->fv[1] - pa0->fv[1]) * frac;
192				viewaux[numv].fv[2] = ALIAS_Z_CLIP_PLANE;
193				viewpts[numv].flags = 0;
194				numv++;
195			}
196		}
197	}
198
199// project the vertices that remain after clipping
200	anyclip = 0;
201	allclip = ALIAS_XY_CLIP_MASK;
202
203// TODO: probably should do this loop in ASM, especially if we use floats
204	for (i=0 ; i<numv ; i++)
205	{
206	// we don't need to bother with vertices that were z-clipped
207		if (viewpts[i].flags & ALIAS_Z_CLIP)
208			continue;
209
210		zi = 1.0 / viewaux[i].fv[2];
211
212	// FIXME: do with chop mode in ASM, or convert to float
213		v0 = (viewaux[i].fv[0] * xscale * zi) + xcenter;
214		v1 = (viewaux[i].fv[1] * yscale * zi) + ycenter;
215
216		flags = 0;
217
218		if (v0 < r_refdef.fvrectx)
219			flags |= ALIAS_LEFT_CLIP;
220		if (v1 < r_refdef.fvrecty)
221			flags |= ALIAS_TOP_CLIP;
222		if (v0 > r_refdef.fvrectright)
223			flags |= ALIAS_RIGHT_CLIP;
224		if (v1 > r_refdef.fvrectbottom)
225			flags |= ALIAS_BOTTOM_CLIP;
226
227		anyclip |= flags;
228		allclip &= flags;
229	}
230
231	if (allclip)
232		return false;	// trivial reject off one side
233
234	currententity->trivial_accept = !anyclip & !zclipped;
235
236	if (currententity->trivial_accept)
237	{
238		if (minz > (r_aliastransition + (pmdl->size * r_resfudge)))
239		{
240			currententity->trivial_accept |= 2;
241		}
242	}
243
244	return true;
245}
246
247
248/*
249================
250R_AliasTransformVector
251================
252*/
253void R_AliasTransformVector (vec3_t in, vec3_t out)
254{
255	out[0] = DotProduct(in, aliastransform[0]) + aliastransform[0][3];
256	out[1] = DotProduct(in, aliastransform[1]) + aliastransform[1][3];
257	out[2] = DotProduct(in, aliastransform[2]) + aliastransform[2][3];
258}
259
260
261/*
262================
263R_AliasPreparePoints
264
265General clipped case
266================
267*/
268void R_AliasPreparePoints (void)
269{
270	int			i;
271	stvert_t	*pstverts;
272	finalvert_t	*fv;
273	auxvert_t	*av;
274	mtriangle_t	*ptri;
275	finalvert_t	*pfv[3];
276
277	pstverts = (stvert_t *)((byte *)paliashdr + paliashdr->stverts);
278	r_anumverts = pmdl->numverts;
279 	fv = pfinalverts;
280	av = pauxverts;
281
282	for (i=0 ; i<r_anumverts ; i++, fv++, av++, r_apverts++, pstverts++)
283	{
284		R_AliasTransformFinalVert (fv, av, r_apverts, pstverts);
285		if (av->fv[2] < ALIAS_Z_CLIP_PLANE)
286			fv->flags |= ALIAS_Z_CLIP;
287		else
288		{
289			 R_AliasProjectFinalVert (fv, av);
290
291			if (fv->v[0] < r_refdef.aliasvrect.x)
292				fv->flags |= ALIAS_LEFT_CLIP;
293			if (fv->v[1] < r_refdef.aliasvrect.y)
294				fv->flags |= ALIAS_TOP_CLIP;
295			if (fv->v[0] > r_refdef.aliasvrectright)
296				fv->flags |= ALIAS_RIGHT_CLIP;
297			if (fv->v[1] > r_refdef.aliasvrectbottom)
298				fv->flags |= ALIAS_BOTTOM_CLIP;
299		}
300	}
301
302//
303// clip and draw all triangles
304//
305	r_affinetridesc.numtriangles = 1;
306
307	ptri = (mtriangle_t *)((byte *)paliashdr + paliashdr->triangles);
308	for (i=0 ; i<pmdl->numtris ; i++, ptri++)
309	{
310		pfv[0] = &pfinalverts[ptri->vertindex[0]];
311		pfv[1] = &pfinalverts[ptri->vertindex[1]];
312		pfv[2] = &pfinalverts[ptri->vertindex[2]];
313
314		if ( pfv[0]->flags & pfv[1]->flags & pfv[2]->flags & (ALIAS_XY_CLIP_MASK | ALIAS_Z_CLIP) )
315			continue;		// completely clipped
316
317		if ( ! ( (pfv[0]->flags | pfv[1]->flags | pfv[2]->flags) &
318			(ALIAS_XY_CLIP_MASK | ALIAS_Z_CLIP) ) )
319		{	// totally unclipped
320			r_affinetridesc.pfinalverts = pfinalverts;
321			r_affinetridesc.ptriangles = ptri;
322			D_PolysetDraw ();
323		}
324		else
325		{	// partially clipped
326			R_AliasClipTriangle (ptri);
327		}
328	}
329}
330
331
332/*
333================
334R_AliasSetUpTransform
335================
336*/
337void R_AliasSetUpTransform (int trivial_accept)
338{
339	int				i;
340	float			rotationmatrix[3][4], t2matrix[3][4];
341	static float	tmatrix[3][4];
342	static float	viewmatrix[3][4];
343	vec3_t			angles;
344
345// TODO: should really be stored with the entity instead of being reconstructed
346// TODO: should use a look-up table
347// TODO: could cache lazily, stored in the entity
348
349	angles[ROLL] = currententity->angles[ROLL];
350	angles[PITCH] = -currententity->angles[PITCH];
351	angles[YAW] = currententity->angles[YAW];
352	AngleVectors (angles, alias_forward, alias_right, alias_up);
353
354	tmatrix[0][0] = pmdl->scale[0];
355	tmatrix[1][1] = pmdl->scale[1];
356	tmatrix[2][2] = pmdl->scale[2];
357
358	tmatrix[0][3] = pmdl->scale_origin[0];
359	tmatrix[1][3] = pmdl->scale_origin[1];
360	tmatrix[2][3] = pmdl->scale_origin[2];
361
362// TODO: can do this with simple matrix rearrangement
363
364	for (i=0 ; i<3 ; i++)
365	{
366		t2matrix[i][0] = alias_forward[i];
367		t2matrix[i][1] = -alias_right[i];
368		t2matrix[i][2] = alias_up[i];
369	}
370
371	t2matrix[0][3] = -modelorg[0];
372	t2matrix[1][3] = -modelorg[1];
373	t2matrix[2][3] = -modelorg[2];
374
375// FIXME: can do more efficiently than full concatenation
376	R_ConcatTransforms (t2matrix, tmatrix, rotationmatrix);
377
378// TODO: should be global, set when vright, etc., set
379	VectorCopy (vright, viewmatrix[0]);
380	VectorCopy (vup, viewmatrix[1]);
381	VectorInverse (viewmatrix[1]);
382	VectorCopy (vpn, viewmatrix[2]);
383
384//	viewmatrix[0][3] = 0;
385//	viewmatrix[1][3] = 0;
386//	viewmatrix[2][3] = 0;
387
388	R_ConcatTransforms (viewmatrix, rotationmatrix, aliastransform);
389
390// do the scaling up of x and y to screen coordinates as part of the transform
391// for the unclipped case (it would mess up clipping in the clipped case).
392// Also scale down z, so 1/z is scaled 31 bits for free, and scale down x and y
393// correspondingly so the projected x and y come out right
394// FIXME: make this work for clipped case too?
395	if (trivial_accept)
396	{
397		for (i=0 ; i<4 ; i++)
398		{
399			aliastransform[0][i] *= aliasxscale *
400					(1.0 / ((float)0x8000 * 0x10000));
401			aliastransform[1][i] *= aliasyscale *
402					(1.0 / ((float)0x8000 * 0x10000));
403			aliastransform[2][i] *= 1.0 / ((float)0x8000 * 0x10000);
404
405		}
406	}
407}
408
409
410/*
411================
412R_AliasTransformFinalVert
413================
414*/
415void R_AliasTransformFinalVert (finalvert_t *fv, auxvert_t *av,
416	trivertx_t *pverts, stvert_t *pstverts)
417{
418	int		temp;
419	float	lightcos, *plightnormal;
420
421	av->fv[0] = DotProduct(pverts->v, aliastransform[0]) +
422			aliastransform[0][3];
423	av->fv[1] = DotProduct(pverts->v, aliastransform[1]) +
424			aliastransform[1][3];
425	av->fv[2] = DotProduct(pverts->v, aliastransform[2]) +
426			aliastransform[2][3];
427
428	fv->v[2] = pstverts->s;
429	fv->v[3] = pstverts->t;
430
431	fv->flags = pstverts->onseam;
432
433// lighting
434	plightnormal = r_avertexnormals[pverts->lightnormalindex];
435	lightcos = DotProduct (plightnormal, r_plightvec);
436	temp = r_ambientlight;
437
438	if (lightcos < 0)
439	{
440		temp += (int)(r_shadelight * lightcos);
441
442	// clamp; because we limited the minimum ambient and shading light, we
443	// don't have to clamp low light, just bright
444		if (temp < 0)
445			temp = 0;
446	}
447
448	fv->v[4] = temp;
449}
450
451
452#if	!id386
453
454/*
455================
456R_AliasTransformAndProjectFinalVerts
457================
458*/
459void R_AliasTransformAndProjectFinalVerts (finalvert_t *fv, stvert_t *pstverts)
460{
461	int			i, temp;
462	float		lightcos, *plightnormal, zi;
463	trivertx_t	*pverts;
464
465	pverts = r_apverts;
466
467	for (i=0 ; i<r_anumverts ; i++, fv++, pverts++, pstverts++)
468	{
469	// transform and project
470		zi = 1.0 / (DotProduct(pverts->v, aliastransform[2]) +
471				aliastransform[2][3]);
472
473	// x, y, and z are scaled down by 1/2**31 in the transform, so 1/z is
474	// scaled up by 1/2**31, and the scaling cancels out for x and y in the
475	// projection
476		fv->v[5] = zi;
477
478		fv->v[0] = ((DotProduct(pverts->v, aliastransform[0]) +
479				aliastransform[0][3]) * zi) + aliasxcenter;
480		fv->v[1] = ((DotProduct(pverts->v, aliastransform[1]) +
481				aliastransform[1][3]) * zi) + aliasycenter;
482
483		fv->v[2] = pstverts->s;
484		fv->v[3] = pstverts->t;
485		fv->flags = pstverts->onseam;
486
487	// lighting
488		plightnormal = r_avertexnormals[pverts->lightnormalindex];
489		lightcos = DotProduct (plightnormal, r_plightvec);
490		temp = r_ambientlight;
491
492		if (lightcos < 0)
493		{
494			temp += (int)(r_shadelight * lightcos);
495
496		// clamp; because we limited the minimum ambient and shading light, we
497		// don't have to clamp low light, just bright
498			if (temp < 0)
499				temp = 0;
500		}
501
502		fv->v[4] = temp;
503	}
504}
505
506#endif
507
508
509/*
510================
511R_AliasProjectFinalVert
512================
513*/
514void R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av)
515{
516	float	zi;
517
518// project points
519	zi = 1.0 / av->fv[2];
520
521	fv->v[5] = zi * ziscale;
522
523	fv->v[0] = (av->fv[0] * aliasxscale * zi) + aliasxcenter;
524	fv->v[1] = (av->fv[1] * aliasyscale * zi) + aliasycenter;
525}
526
527
528/*
529================
530R_AliasPrepareUnclippedPoints
531================
532*/
533void R_AliasPrepareUnclippedPoints (void)
534{
535	stvert_t	*pstverts;
536	finalvert_t	*fv;
537
538	pstverts = (stvert_t *)((byte *)paliashdr + paliashdr->stverts);
539	r_anumverts = pmdl->numverts;
540// FIXME: just use pfinalverts directly?
541	fv = pfinalverts;
542
543	R_AliasTransformAndProjectFinalVerts (fv, pstverts);
544
545	if (r_affinetridesc.drawtype)
546		D_PolysetDrawFinalVerts (fv, r_anumverts);
547
548	r_affinetridesc.pfinalverts = pfinalverts;
549	r_affinetridesc.ptriangles = (mtriangle_t *)
550			((byte *)paliashdr + paliashdr->triangles);
551	r_affinetridesc.numtriangles = pmdl->numtris;
552
553	D_PolysetDraw ();
554}
555
556/*
557===============
558R_AliasSetupSkin
559===============
560*/
561void R_AliasSetupSkin (void)
562{
563	int					skinnum;
564	int					i, numskins;
565	maliasskingroup_t	*paliasskingroup;
566	float				*pskinintervals, fullskininterval;
567	float				skintargettime, skintime;
568
569	skinnum = currententity->skinnum;
570	if ((skinnum >= pmdl->numskins) || (skinnum < 0))
571	{
572		Con_DPrintf ("R_AliasSetupSkin: no such skin # %d\n", skinnum);
573		skinnum = 0;
574	}
575
576	pskindesc = ((maliasskindesc_t *)
577			((byte *)paliashdr + paliashdr->skindesc)) + skinnum;
578	a_skinwidth = pmdl->skinwidth;
579
580	if (pskindesc->type == ALIAS_SKIN_GROUP)
581	{
582		paliasskingroup = (maliasskingroup_t *)((byte *)paliashdr +
583				pskindesc->skin);
584		pskinintervals = (float *)
585				((byte *)paliashdr + paliasskingroup->intervals);
586		numskins = paliasskingroup->numskins;
587		fullskininterval = pskinintervals[numskins-1];
588
589		skintime = cl.time + currententity->syncbase;
590
591	// when loading in Mod_LoadAliasSkinGroup, we guaranteed all interval
592	// values are positive, so we don't have to worry about division by 0
593		skintargettime = skintime -
594				((int)(skintime / fullskininterval)) * fullskininterval;
595
596		for (i=0 ; i<(numskins-1) ; i++)
597		{
598			if (pskinintervals[i] > skintargettime)
599				break;
600		}
601
602		pskindesc = &paliasskingroup->skindescs[i];
603	}
604
605	r_affinetridesc.pskindesc = pskindesc;
606	r_affinetridesc.pskin = (void *)((byte *)paliashdr + pskindesc->skin);
607	r_affinetridesc.skinwidth = a_skinwidth;
608	r_affinetridesc.seamfixupX16 =  (a_skinwidth >> 1) << 16;
609	r_affinetridesc.skinheight = pmdl->skinheight;
610}
611
612/*
613================
614R_AliasSetupLighting
615================
616*/
617void R_AliasSetupLighting (alight_t *plighting)
618{
619
620// guarantee that no vertex will ever be lit below LIGHT_MIN, so we don't have
621// to clamp off the bottom
622	r_ambientlight = plighting->ambientlight;
623
624	if (r_ambientlight < LIGHT_MIN)
625		r_ambientlight = LIGHT_MIN;
626
627	r_ambientlight = (255 - r_ambientlight) << VID_CBITS;
628
629	if (r_ambientlight < LIGHT_MIN)
630		r_ambientlight = LIGHT_MIN;
631
632	r_shadelight = plighting->shadelight;
633
634	if (r_shadelight < 0)
635		r_shadelight = 0;
636
637	r_shadelight *= VID_GRADES;
638
639// rotate the lighting vector into the model's frame of reference
640	r_plightvec[0] = DotProduct (plighting->plightvec, alias_forward);
641	r_plightvec[1] = -DotProduct (plighting->plightvec, alias_right);
642	r_plightvec[2] = DotProduct (plighting->plightvec, alias_up);
643}
644
645/*
646=================
647R_AliasSetupFrame
648
649set r_apverts
650=================
651*/
652void R_AliasSetupFrame (void)
653{
654	int				frame;
655	int				i, numframes;
656	maliasgroup_t	*paliasgroup;
657	float			*pintervals, fullinterval, targettime, time;
658
659	frame = currententity->frame;
660	if ((frame >= pmdl->numframes) || (frame < 0))
661	{
662		Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame);
663		frame = 0;
664	}
665
666	if (paliashdr->frames[frame].type == ALIAS_SINGLE)
667	{
668		r_apverts = (trivertx_t *)
669				((byte *)paliashdr + paliashdr->frames[frame].frame);
670		return;
671	}
672
673	paliasgroup = (maliasgroup_t *)
674				((byte *)paliashdr + paliashdr->frames[frame].frame);
675	pintervals = (float *)((byte *)paliashdr + paliasgroup->intervals);
676	numframes = paliasgroup->numframes;
677	fullinterval = pintervals[numframes-1];
678
679	time = cl.time + currententity->syncbase;
680
681//
682// when loading in Mod_LoadAliasGroup, we guaranteed all interval values
683// are positive, so we don't have to worry about division by 0
684//
685	targettime = time - ((int)(time / fullinterval)) * fullinterval;
686
687	for (i=0 ; i<(numframes-1) ; i++)
688	{
689		if (pintervals[i] > targettime)
690			break;
691	}
692
693	r_apverts = (trivertx_t *)
694				((byte *)paliashdr + paliasgroup->frames[i].frame);
695}
696
697
698/*
699================
700R_AliasDrawModel
701================
702*/
703void R_AliasDrawModel (alight_t *plighting)
704{
705	finalvert_t		finalverts[MAXALIASVERTS +
706						((CACHE_SIZE - 1) / sizeof(finalvert_t)) + 1];
707	auxvert_t		auxverts[MAXALIASVERTS];
708
709	r_amodels_drawn++;
710
711// cache align
712	pfinalverts = (finalvert_t *)
713			(((long)&finalverts[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
714	pauxverts = &auxverts[0];
715
716	paliashdr = (aliashdr_t *)Mod_Extradata (currententity->model);
717	pmdl = (mdl_t *)((byte *)paliashdr + paliashdr->model);
718
719	R_AliasSetupSkin ();
720	R_AliasSetUpTransform (currententity->trivial_accept);
721	R_AliasSetupLighting (plighting);
722	R_AliasSetupFrame ();
723
724	if (!currententity->colormap)
725		Sys_Error ("R_AliasDrawModel: !currententity->colormap");
726
727	r_affinetridesc.drawtype = (currententity->trivial_accept == 3) &&
728			r_recursiveaffinetriangles;
729
730	if (r_affinetridesc.drawtype)
731	{
732		D_PolysetUpdateTables ();		// FIXME: precalc...
733	}
734	else
735	{
736#if	id386
737		D_Aff8Patch (currententity->colormap);
738#endif
739	}
740
741	acolormap = currententity->colormap;
742
743	if (currententity != &cl.viewent)
744		ziscale = (float)0x8000 * (float)0x10000;
745	else
746		ziscale = (float)0x8000 * (float)0x10000 * 3.0;
747
748	if (currententity->trivial_accept)
749		R_AliasPrepareUnclippedPoints ();
750	else
751		R_AliasPreparePoints ();
752}
753
754