Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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. static float            ziscale;
  46. static model_t          *pmodel;
  47.  
  48. static vec3_t           alias_forward, alias_right, alias_up;
  49.  
  50. static maliasskindesc_t *pskindesc;
  51.  
  52. int                             r_amodels_drawn;
  53. int                             a_skinwidth;
  54. int                             r_anumverts;
  55.  
  56. float   aliastransform[3][4];
  57.  
  58. typedef struct {
  59.         int     index0;
  60.         int     index1;
  61. } aedge_t;
  62.  
  63. static 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.  
  71. float   r_avertexnormals[NUMVERTEXNORMALS][3] = {
  72. #include "anorms.h"
  73. };
  74.  
  75. void R_AliasTransformAndProjectFinalVerts (finalvert_t *fv,
  76.         stvert_t *pstverts);
  77. void R_AliasSetUpTransform (int trivial_accept);
  78. void R_AliasTransformVector (vec3_t in, vec3_t out);
  79. void R_AliasTransformFinalVert (finalvert_t *fv, auxvert_t *av,
  80.         trivertx_t *pverts, stvert_t *pstverts);
  81. void R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av);
  82.  
  83.  
  84. /*
  85. ================
  86. R_AliasCheckBBox
  87. ================
  88. */
  89. qboolean 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. ================
  250. R_AliasTransformVector
  251. ================
  252. */
  253. void 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. ================
  263. R_AliasPreparePoints
  264.  
  265. General clipped case
  266. ================
  267. */
  268. void 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. ================
  334. R_AliasSetUpTransform
  335. ================
  336. */
  337. void 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. ================
  412. R_AliasTransformFinalVert
  413. ================
  414. */
  415. void 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. ================
  456. R_AliasTransformAndProjectFinalVerts
  457. ================
  458. */
  459. void 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. ================
  511. R_AliasProjectFinalVert
  512. ================
  513. */
  514. void 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. ================
  530. R_AliasPrepareUnclippedPoints
  531. ================
  532. */
  533. void 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. ===============
  558. R_AliasSetupSkin
  559. ===============
  560. */
  561. void 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. ================
  614. R_AliasSetupLighting
  615. ================
  616. */
  617. void 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. =================
  647. R_AliasSetupFrame
  648.  
  649. set r_apverts
  650. =================
  651. */
  652. void 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. ================
  700. R_AliasDrawModel
  701. ================
  702. */
  703. void 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.