// r_alias.c: routines for setting up to draw alias models #include "quakedef.h"#include "r_shared.h"#include "r_local.h"#include "d_local.h" // FIXME: shouldn't be needed (is needed for patch // right now, but that should move) #define LIGHT_MIN 5 // lowest light value we'll allow, to avoid the // need for inner-loop light clamping mtriangle_t *ptriangles;affinetridesc_t r_affinetridesc; void * acolormap; // FIXME: should go away trivertx_t *r_apverts; // TODO: these probably will go away with optimized rasterizationmdl_t *pmdl;vec3_t r_plightvec;int r_ambientlight;float r_shadelight;aliashdr_t *paliashdr;finalvert_t *pfinalverts;auxvert_t *pauxverts;static float ziscale;static model_t *pmodel; static vec3_t alias_forward, alias_right, alias_up; static maliasskindesc_t *pskindesc; int r_amodels_drawn;int a_skinwidth;int r_anumverts; float aliastransform[3][4]; typedef struct { int index0; int index1;} aedge_t; static aedge_t aedges[12] = {{0, 1}, {1, 2}, {2, 3}, {3, 0},{4, 5}, {5, 6}, {6, 7}, {7, 4},{0, 5}, {1, 4}, {2, 7}, {3, 6}}; #define NUMVERTEXNORMALS 162 float r_avertexnormals[NUMVERTEXNORMALS][3] = {#include "anorms.h"}; void R_AliasTransformAndProjectFinalVerts (finalvert_t *fv, stvert_t *pstverts);void R_AliasSetUpTransform (int trivial_accept);void R_AliasTransformVector (vec3_t in, vec3_t out);void R_AliasTransformFinalVert (finalvert_t *fv, auxvert_t *av, trivertx_t *pverts, stvert_t *pstverts);void R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av); /*================R_AliasCheckBBox================*/bool R_AliasCheckBBox (void){ int i, flags, frame, numv; aliashdr_t *pahdr; float zi, basepts[8][3], v0, v1, frac; finalvert_t *pv0, *pv1, viewpts[16]; auxvert_t *pa0, *pa1, viewaux[16]; maliasframedesc_t *pframedesc; bool zclipped, zfullyclipped; unsigned anyclip, allclip; int minz; // expand, rotate, and translate points into worldspace currententity->trivial_accept = 0; pmodel = currententity->model; pahdr = Mod_Extradata (pmodel); pmdl = (mdl_t *)((uint8_t *)pahdr + pahdr->model); R_AliasSetUpTransform (0); // construct the base bounding box for this frame frame = currententity->frame;// TODO: don't repeat this check when drawing? if ((frame >= pmdl->numframes) || (frame < 0)) { Con_DPrintf ("No such frame %d %s\n", frame, pmodel->name); frame = 0; } pframedesc = &pahdr->frames[frame]; // x worldspace coordinates basepts[0][0] = basepts[1][0] = basepts[2][0] = basepts[3][0] = (float)pframedesc->bboxmin.v[0]; basepts[4][0] = basepts[5][0] = basepts[6][0] = basepts[7][0] = (float)pframedesc->bboxmax.v[0]; // y worldspace coordinates basepts[0][1] = basepts[3][1] = basepts[5][1] = basepts[6][1] = (float)pframedesc->bboxmin.v[1]; basepts[1][1] = basepts[2][1] = basepts[4][1] = basepts[7][1] = (float)pframedesc->bboxmax.v[1]; // z worldspace coordinates basepts[0][2] = basepts[1][2] = basepts[4][2] = basepts[5][2] = (float)pframedesc->bboxmin.v[2]; basepts[2][2] = basepts[3][2] = basepts[6][2] = basepts[7][2] = (float)pframedesc->bboxmax.v[2]; zclipped = false; zfullyclipped = true; minz = 9999; for (i=0; i<8 ; i++) { R_AliasTransformVector (&basepts[i][0], &viewaux[i].fv[0]); if (viewaux[i].fv[2] < ALIAS_Z_CLIP_PLANE) { // we must clip points that are closer than the near clip plane viewpts[i].flags = ALIAS_Z_CLIP; zclipped = true; } else { if (viewaux[i].fv[2] < minz) minz = viewaux[i].fv[2]; viewpts[i].flags = 0; zfullyclipped = false; } } if (zfullyclipped) { return false; // everything was near-z-clipped } numv = 8; if (zclipped) { // organize points by edges, use edges to get new points (possible trivial // reject) for (i=0 ; i<12 ; i++) { // edge endpoints pv0 = &viewpts[aedges[i].index0]; pv1 = &viewpts[aedges[i].index1]; pa0 = &viewaux[aedges[i].index0]; pa1 = &viewaux[aedges[i].index1]; // if one end is clipped and the other isn't, make a new point if (pv0->flags ^ pv1->flags) { frac = (ALIAS_Z_CLIP_PLANE - pa0->fv[2]) / (pa1->fv[2] - pa0->fv[2]); viewaux[numv].fv[0] = pa0->fv[0] + (pa1->fv[0] - pa0->fv[0]) * frac; viewaux[numv].fv[1] = pa0->fv[1] + (pa1->fv[1] - pa0->fv[1]) * frac; viewaux[numv].fv[2] = ALIAS_Z_CLIP_PLANE; viewpts[numv].flags = 0; numv++; } } } // project the vertices that remain after clipping anyclip = 0; allclip = ALIAS_XY_CLIP_MASK; // TODO: probably should do this loop in ASM, especially if we use floats for (i=0 ; i<numv ; i++) { // we don't need to bother with vertices that were z-clipped if (viewpts[i].flags & ALIAS_Z_CLIP) continue; zi = 1.0 / viewaux[i].fv[2]; // FIXME: do with chop mode in ASM, or convert to float v0 = (viewaux[i].fv[0] * xscale * zi) + xcenter; v1 = (viewaux[i].fv[1] * yscale * zi) + ycenter; flags = 0; if (v0 < r_refdef.fvrectx) flags |= ALIAS_LEFT_CLIP; if (v1 < r_refdef.fvrecty) flags |= ALIAS_TOP_CLIP; if (v0 > r_refdef.fvrectright) flags |= ALIAS_RIGHT_CLIP; if (v1 > r_refdef.fvrectbottom) flags |= ALIAS_BOTTOM_CLIP; anyclip |= flags; allclip &= flags; } if (allclip) return false; // trivial reject off one side currententity->trivial_accept = !anyclip & !zclipped; if (currententity->trivial_accept) { if (minz > (r_aliastransition + (pmdl->size * r_resfudge))) { currententity->trivial_accept |= 2; } } return true;} /*================R_AliasTransformVector================*/void R_AliasTransformVector (vec3_t in, vec3_t out){ out[0] = DotProduct(in, aliastransform[0]) + aliastransform[0][3]; out[1] = DotProduct(in, aliastransform[1]) + aliastransform[1][3]; out[2] = DotProduct(in, aliastransform[2]) + aliastransform[2][3];} /*================R_AliasPreparePoints General clipped case================*/void R_AliasPreparePoints (void){ int i; stvert_t *pstverts; finalvert_t *fv; auxvert_t *av; mtriangle_t *ptri; finalvert_t *pfv[3]; pstverts = (stvert_t *)((uint8_t *)paliashdr + paliashdr->stverts); r_anumverts = pmdl->numverts; fv = pfinalverts; av = pauxverts; for (i=0 ; i<r_anumverts ; i++, fv++, av++, r_apverts++, pstverts++) { R_AliasTransformFinalVert (fv, av, r_apverts, pstverts); if (av->fv[2] < ALIAS_Z_CLIP_PLANE) fv->flags |= ALIAS_Z_CLIP; else { R_AliasProjectFinalVert (fv, av); if (fv->v[0] < r_refdef.aliasvrect.x) fv->flags |= ALIAS_LEFT_CLIP; if (fv->v[1] < r_refdef.aliasvrect.y) fv->flags |= ALIAS_TOP_CLIP; if (fv->v[0] > r_refdef.aliasvrectright) fv->flags |= ALIAS_RIGHT_CLIP; if (fv->v[1] > r_refdef.aliasvrectbottom) fv->flags |= ALIAS_BOTTOM_CLIP; } } //// clip and draw all triangles// r_affinetridesc.numtriangles = 1; ptri = (mtriangle_t *)((uint8_t *)paliashdr + paliashdr->triangles); for (i=0 ; i<pmdl->numtris ; i++, ptri++) { pfv[0] = &pfinalverts[ptri->vertindex[0]]; pfv[1] = &pfinalverts[ptri->vertindex[1]]; pfv[2] = &pfinalverts[ptri->vertindex[2]]; if ( pfv[0]->flags & pfv[1]->flags & pfv[2]->flags & (ALIAS_XY_CLIP_MASK | ALIAS_Z_CLIP) ) continue; // completely clipped if ( ! ( (pfv[0]->flags | pfv[1]->flags | pfv[2]->flags) & (ALIAS_XY_CLIP_MASK | ALIAS_Z_CLIP) ) ) { // totally unclipped r_affinetridesc.pfinalverts = pfinalverts; r_affinetridesc.ptriangles = ptri; D_PolysetDraw (); } else { // partially clipped R_AliasClipTriangle (ptri); } }} /*================R_AliasSetUpTransform================*/void R_AliasSetUpTransform (int trivial_accept){ int i; float rotationmatrix[3][4], t2matrix[3][4]; static float tmatrix[3][4]; static float viewmatrix[3][4]; vec3_t angles; // TODO: should really be stored with the entity instead of being reconstructed// TODO: should use a look-up table// TODO: could cache lazily, stored in the entity angles[ROLL] = currententity->angles[ROLL]; angles[PITCH] = -currententity->angles[PITCH]; angles[YAW] = currententity->angles[YAW]; AngleVectors (angles, alias_forward, alias_right, alias_up); tmatrix[0][0] = pmdl->scale[0]; tmatrix[1][1] = pmdl->scale[1]; tmatrix[2][2] = pmdl->scale[2]; tmatrix[0][3] = pmdl->scale_origin[0]; tmatrix[1][3] = pmdl->scale_origin[1]; tmatrix[2][3] = pmdl->scale_origin[2]; // TODO: can do this with simple matrix rearrangement for (i=0 ; i<3 ; i++) { t2matrix[i][0] = alias_forward[i]; t2matrix[i][1] = -alias_right[i]; t2matrix[i][2] = alias_up[i]; } t2matrix[0][3] = -modelorg[0]; t2matrix[1][3] = -modelorg[1]; t2matrix[2][3] = -modelorg[2]; // FIXME: can do more efficiently than full concatenation R_ConcatTransforms (t2matrix, tmatrix, rotationmatrix); // TODO: should be global, set when vright, etc., set VectorCopy (vright, viewmatrix[0]); VectorCopy (vup, viewmatrix[1]); VectorInverse (viewmatrix[1]); VectorCopy (vpn, viewmatrix[2]); // viewmatrix[0][3] = 0;// viewmatrix[1][3] = 0;// viewmatrix[2][3] = 0; R_ConcatTransforms (viewmatrix, rotationmatrix, aliastransform); // do the scaling up of x and y to screen coordinates as part of the transform// for the unclipped case (it would mess up clipping in the clipped case).// Also scale down z, so 1/z is scaled 31 bits for free, and scale down x and y// correspondingly so the projected x and y come out right// FIXME: make this work for clipped case too? if (trivial_accept) { for (i=0 ; i<4 ; i++) { aliastransform[0][i] *= aliasxscale * (1.0 / ((float)0x8000 * 0x10000)); aliastransform[1][i] *= aliasyscale * (1.0 / ((float)0x8000 * 0x10000)); aliastransform[2][i] *= 1.0 / ((float)0x8000 * 0x10000); } }} /*================R_AliasTransformFinalVert================*/void R_AliasTransformFinalVert (finalvert_t *fv, auxvert_t *av, trivertx_t *pverts, stvert_t *pstverts){ int temp; float lightcos, *plightnormal; av->fv[0] = DotProduct(pverts->v, aliastransform[0]) + aliastransform[0][3]; av->fv[1] = DotProduct(pverts->v, aliastransform[1]) + aliastransform[1][3]; av->fv[2] = DotProduct(pverts->v, aliastransform[2]) + aliastransform[2][3]; fv->v[2] = pstverts->s; fv->v[3] = pstverts->t; fv->flags = pstverts->onseam; // lighting plightnormal = r_avertexnormals[pverts->lightnormalindex]; lightcos = DotProduct (plightnormal, r_plightvec); temp = r_ambientlight; if (lightcos < 0) { temp += (int)(r_shadelight * lightcos); // clamp; because we limited the minimum ambient and shading light, we // don't have to clamp low light, just bright if (temp < 0) temp = 0; } fv->v[4] = temp;} /*================R_AliasTransformAndProjectFinalVerts================*/void R_AliasTransformAndProjectFinalVerts (finalvert_t *fv, stvert_t *pstverts){ int i, temp; float lightcos, *plightnormal, zi; trivertx_t *pverts; pverts = r_apverts; for (i=0 ; i<r_anumverts ; i++, fv++, pverts++, pstverts++) { // transform and project zi = 1.0 / (DotProduct(pverts->v, aliastransform[2]) + aliastransform[2][3]); // x, y, and z are scaled down by 1/2**31 in the transform, so 1/z is // scaled up by 1/2**31, and the scaling cancels out for x and y in the // projection fv->v[5] = zi; fv->v[0] = ((DotProduct(pverts->v, aliastransform[0]) + aliastransform[0][3]) * zi) + aliasxcenter; fv->v[1] = ((DotProduct(pverts->v, aliastransform[1]) + aliastransform[1][3]) * zi) + aliasycenter; fv->v[2] = pstverts->s; fv->v[3] = pstverts->t; fv->flags = pstverts->onseam; // lighting plightnormal = r_avertexnormals[pverts->lightnormalindex]; lightcos = DotProduct (plightnormal, r_plightvec); temp = r_ambientlight; if (lightcos < 0) { temp += (int)(r_shadelight * lightcos); // clamp; because we limited the minimum ambient and shading light, we // don't have to clamp low light, just bright if (temp < 0) temp = 0; } fv->v[4] = temp; }} /*================R_AliasProjectFinalVert================*/void R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av){ float zi; // project points zi = 1.0 / av->fv[2]; fv->v[5] = zi * ziscale; fv->v[0] = (av->fv[0] * aliasxscale * zi) + aliasxcenter; fv->v[1] = (av->fv[1] * aliasyscale * zi) + aliasycenter;} /*================R_AliasPrepareUnclippedPoints================Lines 1–500 of 713. Load more
// r_alias.c: routines for setting up to draw alias models #include "quakedef.h" #include "r_shared.h" #include "r_local.h" #include "d_local.h" // FIXME: shouldn't be needed (is needed for patch // right now, but that should move) #define LIGHT_MIN 5 // lowest light value we'll allow, to avoid the // need for inner-loop light clamping mtriangle_t *ptriangles; affinetridesc_t r_affinetridesc; void * acolormap; // FIXME: should go away trivertx_t *r_apverts; // TODO: these probably will go away with optimized rasterization mdl_t *pmdl; vec3_t r_plightvec; int r_ambientlight; float r_shadelight; aliashdr_t *paliashdr; finalvert_t *pfinalverts; auxvert_t *pauxverts; static float ziscale; static model_t *pmodel; static vec3_t alias_forward, alias_right, alias_up; static maliasskindesc_t *pskindesc; int r_amodels_drawn; int a_skinwidth; int r_anumverts; float aliastransform[3][4]; typedef struct { int index0; int index1; } aedge_t; static aedge_t aedges[12] = { {0, 1}, {1, 2}, {2, 3}, {3, 0}, {4, 5}, {5, 6}, {6, 7}, {7, 4}, {0, 5}, {1, 4}, {2, 7}, {3, 6} }; #define NUMVERTEXNORMALS 162 float r_avertexnormals[NUMVERTEXNORMALS][3] = { #include "anorms.h" }; void R_AliasTransformAndProjectFinalVerts (finalvert_t *fv, stvert_t *pstverts); void R_AliasSetUpTransform (int trivial_accept); void R_AliasTransformVector (vec3_t in, vec3_t out); void R_AliasTransformFinalVert (finalvert_t *fv, auxvert_t *av, trivertx_t *pverts, stvert_t *pstverts); void R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av); /* ================ R_AliasCheckBBox ================ */ bool R_AliasCheckBBox (void) { int i, flags, frame, numv; aliashdr_t *pahdr; float zi, basepts[8][3], v0, v1, frac; finalvert_t *pv0, *pv1, viewpts[16]; auxvert_t *pa0, *pa1, viewaux[16]; maliasframedesc_t *pframedesc; bool zclipped, zfullyclipped; unsigned anyclip, allclip; int minz; // expand, rotate, and translate points into worldspace currententity->trivial_accept = 0; pmodel = currententity->model; pahdr = Mod_Extradata (pmodel); pmdl = (mdl_t *)((uint8_t *)pahdr + pahdr->model); R_AliasSetUpTransform (0); // construct the base bounding box for this frame frame = currententity->frame; // TODO: don't repeat this check when drawing? if ((frame >= pmdl->numframes) || (frame < 0)) { Con_DPrintf ("No such frame %d %s\n", frame, pmodel->name); frame = 0; } pframedesc = &pahdr->frames[frame]; // x worldspace coordinates basepts[0][0] = basepts[1][0] = basepts[2][0] = basepts[3][0] = (float)pframedesc->bboxmin.v[0]; basepts[4][0] = basepts[5][0] = basepts[6][0] = basepts[7][0] = (float)pframedesc->bboxmax.v[0]; // y worldspace coordinates basepts[0][1] = basepts[3][1] = basepts[5][1] = basepts[6][1] = (float)pframedesc->bboxmin.v[1]; basepts[1][1] = basepts[2][1] = basepts[4][1] = basepts[7][1] = (float)pframedesc->bboxmax.v[1]; // z worldspace coordinates basepts[0][2] = basepts[1][2] = basepts[4][2] = basepts[5][2] = (float)pframedesc->bboxmin.v[2]; basepts[2][2] = basepts[3][2] = basepts[6][2] = basepts[7][2] = (float)pframedesc->bboxmax.v[2]; zclipped = false; zfullyclipped = true; minz = 9999; for (i=0; i<8 ; i++) { R_AliasTransformVector (&basepts[i][0], &viewaux[i].fv[0]); if (viewaux[i].fv[2] < ALIAS_Z_CLIP_PLANE) { // we must clip points that are closer than the near clip plane viewpts[i].flags = ALIAS_Z_CLIP; zclipped = true; } else { if (viewaux[i].fv[2] < minz) minz = viewaux[i].fv[2]; viewpts[i].flags = 0; zfullyclipped = false; } } if (zfullyclipped) { return false; // everything was near-z-clipped } numv = 8; if (zclipped) { // organize points by edges, use edges to get new points (possible trivial // reject) for (i=0 ; i<12 ; i++) { // edge endpoints pv0 = &viewpts[aedges[i].index0]; pv1 = &viewpts[aedges[i].index1]; pa0 = &viewaux[aedges[i].index0]; pa1 = &viewaux[aedges[i].index1]; // if one end is clipped and the other isn't, make a new point if (pv0->flags ^ pv1->flags) { frac = (ALIAS_Z_CLIP_PLANE - pa0->fv[2]) / (pa1->fv[2] - pa0->fv[2]); viewaux[numv].fv[0] = pa0->fv[0] + (pa1->fv[0] - pa0->fv[0]) * frac; viewaux[numv].fv[1] = pa0->fv[1] + (pa1->fv[1] - pa0->fv[1]) * frac; viewaux[numv].fv[2] = ALIAS_Z_CLIP_PLANE; viewpts[numv].flags = 0; numv++; } } } // project the vertices that remain after clipping anyclip = 0; allclip = ALIAS_XY_CLIP_MASK; // TODO: probably should do this loop in ASM, especially if we use floats for (i=0 ; i<numv ; i++) { // we don't need to bother with vertices that were z-clipped if (viewpts[i].flags & ALIAS_Z_CLIP) continue; zi = 1.0 / viewaux[i].fv[2]; // FIXME: do with chop mode in ASM, or convert to float v0 = (viewaux[i].fv[0] * xscale * zi) + xcenter; v1 = (viewaux[i].fv[1] * yscale * zi) + ycenter; flags = 0; if (v0 < r_refdef.fvrectx) flags |= ALIAS_LEFT_CLIP; if (v1 < r_refdef.fvrecty) flags |= ALIAS_TOP_CLIP; if (v0 > r_refdef.fvrectright) flags |= ALIAS_RIGHT_CLIP; if (v1 > r_refdef.fvrectbottom) flags |= ALIAS_BOTTOM_CLIP; anyclip |= flags; allclip &= flags; } if (allclip) return false; // trivial reject off one side currententity->trivial_accept = !anyclip & !zclipped; if (currententity->trivial_accept) { if (minz > (r_aliastransition + (pmdl->size * r_resfudge))) { currententity->trivial_accept |= 2; } } return true; } /* ================ R_AliasTransformVector ================ */ void R_AliasTransformVector (vec3_t in, vec3_t out) { out[0] = DotProduct(in, aliastransform[0]) + aliastransform[0][3]; out[1] = DotProduct(in, aliastransform[1]) + aliastransform[1][3]; out[2] = DotProduct(in, aliastransform[2]) + aliastransform[2][3]; } /* ================ R_AliasPreparePoints General clipped case ================ */ void R_AliasPreparePoints (void) { int i; stvert_t *pstverts; finalvert_t *fv; auxvert_t *av; mtriangle_t *ptri; finalvert_t *pfv[3]; pstverts = (stvert_t *)((uint8_t *)paliashdr + paliashdr->stverts); r_anumverts = pmdl->numverts; fv = pfinalverts; av = pauxverts; for (i=0 ; i<r_anumverts ; i++, fv++, av++, r_apverts++, pstverts++) { R_AliasTransformFinalVert (fv, av, r_apverts, pstverts); if (av->fv[2] < ALIAS_Z_CLIP_PLANE) fv->flags |= ALIAS_Z_CLIP; else { R_AliasProjectFinalVert (fv, av); if (fv->v[0] < r_refdef.aliasvrect.x) fv->flags |= ALIAS_LEFT_CLIP; if (fv->v[1] < r_refdef.aliasvrect.y) fv->flags |= ALIAS_TOP_CLIP; if (fv->v[0] > r_refdef.aliasvrectright) fv->flags |= ALIAS_RIGHT_CLIP; if (fv->v[1] > r_refdef.aliasvrectbottom) fv->flags |= ALIAS_BOTTOM_CLIP; } } // // clip and draw all triangles // r_affinetridesc.numtriangles = 1; ptri = (mtriangle_t *)((uint8_t *)paliashdr + paliashdr->triangles); for (i=0 ; i<pmdl->numtris ; i++, ptri++) { pfv[0] = &pfinalverts[ptri->vertindex[0]]; pfv[1] = &pfinalverts[ptri->vertindex[1]]; pfv[2] = &pfinalverts[ptri->vertindex[2]]; if ( pfv[0]->flags & pfv[1]->flags & pfv[2]->flags & (ALIAS_XY_CLIP_MASK | ALIAS_Z_CLIP) ) continue; // completely clipped if ( ! ( (pfv[0]->flags | pfv[1]->flags | pfv[2]->flags) & (ALIAS_XY_CLIP_MASK | ALIAS_Z_CLIP) ) ) { // totally unclipped r_affinetridesc.pfinalverts = pfinalverts; r_affinetridesc.ptriangles = ptri; D_PolysetDraw (); } else { // partially clipped R_AliasClipTriangle (ptri); } } } /* ================ R_AliasSetUpTransform ================ */ void R_AliasSetUpTransform (int trivial_accept) { int i; float rotationmatrix[3][4], t2matrix[3][4]; static float tmatrix[3][4]; static float viewmatrix[3][4]; vec3_t angles; // TODO: should really be stored with the entity instead of being reconstructed // TODO: should use a look-up table // TODO: could cache lazily, stored in the entity angles[ROLL] = currententity->angles[ROLL]; angles[PITCH] = -currententity->angles[PITCH]; angles[YAW] = currententity->angles[YAW]; AngleVectors (angles, alias_forward, alias_right, alias_up); tmatrix[0][0] = pmdl->scale[0]; tmatrix[1][1] = pmdl->scale[1]; tmatrix[2][2] = pmdl->scale[2]; tmatrix[0][3] = pmdl->scale_origin[0]; tmatrix[1][3] = pmdl->scale_origin[1]; tmatrix[2][3] = pmdl->scale_origin[2]; // TODO: can do this with simple matrix rearrangement for (i=0 ; i<3 ; i++) { t2matrix[i][0] = alias_forward[i]; t2matrix[i][1] = -alias_right[i]; t2matrix[i][2] = alias_up[i]; } t2matrix[0][3] = -modelorg[0]; t2matrix[1][3] = -modelorg[1]; t2matrix[2][3] = -modelorg[2]; // FIXME: can do more efficiently than full concatenation R_ConcatTransforms (t2matrix, tmatrix, rotationmatrix); // TODO: should be global, set when vright, etc., set VectorCopy (vright, viewmatrix[0]); VectorCopy (vup, viewmatrix[1]); VectorInverse (viewmatrix[1]); VectorCopy (vpn, viewmatrix[2]); // viewmatrix[0][3] = 0; // viewmatrix[1][3] = 0; // viewmatrix[2][3] = 0; R_ConcatTransforms (viewmatrix, rotationmatrix, aliastransform); // do the scaling up of x and y to screen coordinates as part of the transform // for the unclipped case (it would mess up clipping in the clipped case). // Also scale down z, so 1/z is scaled 31 bits for free, and scale down x and y // correspondingly so the projected x and y come out right // FIXME: make this work for clipped case too? if (trivial_accept) { for (i=0 ; i<4 ; i++) { aliastransform[0][i] *= aliasxscale * (1.0 / ((float)0x8000 * 0x10000)); aliastransform[1][i] *= aliasyscale * (1.0 / ((float)0x8000 * 0x10000)); aliastransform[2][i] *= 1.0 / ((float)0x8000 * 0x10000); } } } /* ================ R_AliasTransformFinalVert ================ */ void R_AliasTransformFinalVert (finalvert_t *fv, auxvert_t *av, trivertx_t *pverts, stvert_t *pstverts) { int temp; float lightcos, *plightnormal; av->fv[0] = DotProduct(pverts->v, aliastransform[0]) + aliastransform[0][3]; av->fv[1] = DotProduct(pverts->v, aliastransform[1]) + aliastransform[1][3]; av->fv[2] = DotProduct(pverts->v, aliastransform[2]) + aliastransform[2][3]; fv->v[2] = pstverts->s; fv->v[3] = pstverts->t; fv->flags = pstverts->onseam; // lighting plightnormal = r_avertexnormals[pverts->lightnormalindex]; lightcos = DotProduct (plightnormal, r_plightvec); temp = r_ambientlight; if (lightcos < 0) { temp += (int)(r_shadelight * lightcos); // clamp; because we limited the minimum ambient and shading light, we // don't have to clamp low light, just bright if (temp < 0) temp = 0; } fv->v[4] = temp; } /* ================ R_AliasTransformAndProjectFinalVerts ================ */ void R_AliasTransformAndProjectFinalVerts (finalvert_t *fv, stvert_t *pstverts) { int i, temp; float lightcos, *plightnormal, zi; trivertx_t *pverts; pverts = r_apverts; for (i=0 ; i<r_anumverts ; i++, fv++, pverts++, pstverts++) { // transform and project zi = 1.0 / (DotProduct(pverts->v, aliastransform[2]) + aliastransform[2][3]); // x, y, and z are scaled down by 1/2**31 in the transform, so 1/z is // scaled up by 1/2**31, and the scaling cancels out for x and y in the // projection fv->v[5] = zi; fv->v[0] = ((DotProduct(pverts->v, aliastransform[0]) + aliastransform[0][3]) * zi) + aliasxcenter; fv->v[1] = ((DotProduct(pverts->v, aliastransform[1]) + aliastransform[1][3]) * zi) + aliasycenter; fv->v[2] = pstverts->s; fv->v[3] = pstverts->t; fv->flags = pstverts->onseam; // lighting plightnormal = r_avertexnormals[pverts->lightnormalindex]; lightcos = DotProduct (plightnormal, r_plightvec); temp = r_ambientlight; if (lightcos < 0) { temp += (int)(r_shadelight * lightcos); // clamp; because we limited the minimum ambient and shading light, we // don't have to clamp low light, just bright if (temp < 0) temp = 0; } fv->v[4] = temp; } } /* ================ R_AliasProjectFinalVert ================ */ void R_AliasProjectFinalVert (finalvert_t *fv, auxvert_t *av) { float zi; // project points zi = 1.0 / av->fv[2]; fv->v[5] = zi * ziscale; fv->v[0] = (av->fv[0] * aliasxscale * zi) + aliasxcenter; fv->v[1] = (av->fv[1] * aliasyscale * zi) + aliasycenter; } /* ================ R_AliasPrepareUnclippedPoints ================