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 (¤tentity->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 (¤tentity->model->cache);
673 }
674