home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / quake_src / r_alias.c < prev    next >
C/C++ Source or Header  |  2000-06-17  |  20KB  |  769 lines

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