summaryrefslogtreecommitdiff
path: root/apps/plugins/sdl/progs/quake/r_alias.c
diff options
context:
space:
mode:
authorFranklin Wei <git@fwei.tk>2018-02-11 15:34:30 -0500
committerFranklin Wei <git@fwei.tk>2019-07-19 22:37:40 -0400
commit5d05b9d3e920a6aa5fcb553758e98ed0da8c91e4 (patch)
tree84406e21639529a185556a33e5de7f43cffc277b /apps/plugins/sdl/progs/quake/r_alias.c
parentb70fecf21ddc21877ec1ae7888d9c18a979e37ad (diff)
downloadrockbox-5d05b9d3e920a6aa5fcb553758e98ed0da8c91e4.tar.gz
rockbox-5d05b9d3e920a6aa5fcb553758e98ed0da8c91e4.zip
Quake!
This ports id Software's Quake to run on the SDL plugin runtime. The source code originated from id under the GPLv2 license. I used https://github.com/ahefner/sdlquake as the base of my port. Performance is, unsurprisingly, not on par with what you're probably used to on PC. I average about 10FPS on ipod6g, but it's still playable. Sound works well enough, but in-game music is not supported. I've written ARM assembly routines for the inner sound loop. Make sure you turn the "brightness" all the way down, or colors will look funky. To run, extract Quake's data files to /.rockbox/quake. Have fun! Change-Id: I4285036e967d7f0722802d43cf2096c808ca5799
Diffstat (limited to 'apps/plugins/sdl/progs/quake/r_alias.c')
-rw-r--r--apps/plugins/sdl/progs/quake/r_alias.c753
1 files changed, 753 insertions, 0 deletions
diff --git a/apps/plugins/sdl/progs/quake/r_alias.c b/apps/plugins/sdl/progs/quake/r_alias.c
new file mode 100644
index 0000000000..86074199bc
--- /dev/null
+++ b/apps/plugins/sdl/progs/quake/r_alias.c
@@ -0,0 +1,753 @@
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