/* * ================ * R_Alias_clip_z * * pfv0 is the unclipped vertex, pfv1 is the z-clipped vertex * ================ */ static void R_Alias_clip_z(draw.finalvert_t pfv0, draw.finalvert_t pfv1, ref draw.finalvert_t @out) { double scale; auxvert_t pav0, pav1, avout = new auxvert_t(); pav0 = av[av0]; pav1 = av[av1]; if (pfv0.v[1] >= pfv1.v[1]) { scale = (ALIAS_Z_CLIP_PLANE - pav0.fv[2]) / (pav1.fv[2] - pav0.fv[2]); avout.fv[0] = pav0.fv[0] + (pav1.fv[0] - pav0.fv[0]) * scale; avout.fv[1] = pav0.fv[1] + (pav1.fv[1] - pav0.fv[1]) * scale; avout.fv[2] = ALIAS_Z_CLIP_PLANE; @out.v[2] = (int)(pfv0.v[2] + (pfv1.v[2] - pfv0.v[2]) * scale); @out.v[3] = (int)(pfv0.v[3] + (pfv1.v[3] - pfv0.v[3]) * scale); @out.v[4] = (int)(pfv0.v[4] + (pfv1.v[4] - pfv0.v[4]) * scale); } else { scale = (ALIAS_Z_CLIP_PLANE - pav1.fv[2]) / (pav0.fv[2] - pav1.fv[2]); avout.fv[0] = pav1.fv[0] + (pav0.fv[0] - pav1.fv[0]) * scale; avout.fv[1] = pav1.fv[1] + (pav0.fv[1] - pav1.fv[1]) * scale; avout.fv[2] = ALIAS_Z_CLIP_PLANE; @out.v[2] = (int)(pfv1.v[2] + (pfv0.v[2] - pfv1.v[2]) * scale); @out.v[3] = (int)(pfv1.v[3] + (pfv0.v[3] - pfv1.v[3]) * scale); @out.v[4] = (int)(pfv1.v[4] + (pfv0.v[4] - pfv1.v[4]) * scale); } R_AliasProjectFinalVert(@out, avout); if (@out.v[0] < r_refdef.aliasvrect.x) { @out.flags |= ALIAS_LEFT_CLIP; } if (@out.v[1] < r_refdef.aliasvrect.y) { @out.flags |= ALIAS_TOP_CLIP; } if (@out.v[0] > r_refdef.aliasvrectright) { @out.flags |= ALIAS_RIGHT_CLIP; } if (@out.v[1] > r_refdef.aliasvrectbottom) { @out.flags |= ALIAS_BOTTOM_CLIP; } }
static void r_alias_init() { finalverts = new draw.finalvert_t[MAXALIASVERTS]; auxverts = new auxvert_t[MAXALIASVERTS]; for (int kk = 0; kk < MAXALIASVERTS; kk++) { finalverts[kk] = new draw.finalvert_t(); auxverts[kk] = new auxvert_t(); } }
/* * ================ * R_AliasProjectFinalVert * ================ */ static void R_AliasProjectFinalVert(draw.finalvert_t fv, auxvert_t av) { double zi; // project points zi = 1.0 / av.fv[2]; fv.v[5] = (int)(zi * ziscale); fv.v[0] = (int)((av.fv[0] * aliasxscale * zi) + aliasxcenter); fv.v[1] = (int)((av.fv[1] * aliasyscale * zi) + aliasycenter); }
/* * ================ * R_AliasTransformFinalVert * ================ */ static void R_AliasTransformFinalVert(draw.finalvert_t fv, auxvert_t av, model.trivertx_t pverts, model.stvert_t pstverts) { int temp; double lightcos; double[] plightnormal; av.fv[0] = mathlib.DotProduct(pverts.v, aliastransform[0]) + aliastransform[0][3]; av.fv[1] = mathlib.DotProduct(pverts.v, aliastransform[1]) + aliastransform[1][3]; av.fv[2] = mathlib.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 = mathlib.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; }
static render() { int kk; int i, j; for (kk = 0; kk < 4; kk++) { screenedge[kk] = new model.mplane_t(); } for (kk = 0; kk < 4; kk++) { view_clipplanes[kk] = new render.clipplane_t(); } for (kk = 0; kk < 16; kk++) { world_clipplanes[kk] = new render.clipplane_t(); } for (i = 0; i < 2; i++) { for (j = 0; j < MAXWORKINGVERTS; j++) { clip_verts[i][j] = new double[5]; } } for (i = 0; i < 2; i++) { for (j = 0; j < 8; j++) { fva[i][j] = new draw.finalvert_t(); } } for (kk = 0; kk < 8; kk++) { av[kk] = new auxvert_t(); } r_alias_init(); }
/* ================ R_Alias_clip_z pfv0 is the unclipped vertex, pfv1 is the z-clipped vertex ================ */ static void R_Alias_clip_z(draw.finalvert_t pfv0, draw.finalvert_t pfv1, ref draw.finalvert_t @out) { double scale; auxvert_t pav0, pav1, avout = new auxvert_t(); pav0 = av[av0]; pav1 = av[av1]; if (pfv0.v[1] >= pfv1.v[1]) { scale = (ALIAS_Z_CLIP_PLANE - pav0.fv[2]) / (pav1.fv[2] - pav0.fv[2]); avout.fv[0] = pav0.fv[0] + (pav1.fv[0] - pav0.fv[0]) * scale; avout.fv[1] = pav0.fv[1] + (pav1.fv[1] - pav0.fv[1]) * scale; avout.fv[2] = ALIAS_Z_CLIP_PLANE; @out.v[2] = (int)(pfv0.v[2] + (pfv1.v[2] - pfv0.v[2]) * scale); @out.v[3] = (int)(pfv0.v[3] + (pfv1.v[3] - pfv0.v[3]) * scale); @out.v[4] = (int)(pfv0.v[4] + (pfv1.v[4] - pfv0.v[4]) * scale); } else { scale = (ALIAS_Z_CLIP_PLANE - pav1.fv[2]) / (pav0.fv[2] - pav1.fv[2]); avout.fv[0] = pav1.fv[0] + (pav0.fv[0] - pav1.fv[0]) * scale; avout.fv[1] = pav1.fv[1] + (pav0.fv[1] - pav1.fv[1]) * scale; avout.fv[2] = ALIAS_Z_CLIP_PLANE; @out.v[2] = (int)(pfv1.v[2] + (pfv0.v[2] - pfv1.v[2]) * scale); @out.v[3] = (int)(pfv1.v[3] + (pfv0.v[3] - pfv1.v[3]) * scale); @out.v[4] = (int)(pfv1.v[4] + (pfv0.v[4] - pfv1.v[4]) * scale); } R_AliasProjectFinalVert (@out, avout); if (@out.v[0] < r_refdef.aliasvrect.x) @out.flags |= ALIAS_LEFT_CLIP; if (@out.v[1] < r_refdef.aliasvrect.y) @out.flags |= ALIAS_TOP_CLIP; if (@out.v[0] > r_refdef.aliasvrectright) @out.flags |= ALIAS_RIGHT_CLIP; if (@out.v[1] > r_refdef.aliasvrectbottom) @out.flags |= ALIAS_BOTTOM_CLIP; }
static render() { int kk; int i,j; for(kk = 0; kk < 4; kk++) screenedge[kk] = new model.mplane_t(); for(kk = 0; kk < 4; kk++) view_clipplanes[kk] = new render.clipplane_t(); for(kk = 0; kk < 16; kk++) world_clipplanes[kk] = new render.clipplane_t(); for(i = 0; i < 2; i++) for(j = 0; j < MAXWORKINGVERTS; j++) clip_verts[i][j] = new double[5]; for(i = 0; i < 2; i++) for(j = 0; j < 8; j++) fva[i][j] = new draw.finalvert_t(); for(kk = 0; kk < 8; kk++) av[kk] = new auxvert_t(); r_alias_init(); }
/* ================ R_AliasTransformFinalVert ================ */ static void R_AliasTransformFinalVert(draw.finalvert_t fv, auxvert_t av, model.trivertx_t pverts, model.stvert_t pstverts) { int temp; double lightcos; double[] plightnormal; av.fv[0] = mathlib.DotProduct(pverts.v, aliastransform[0]) + aliastransform[0][3]; av.fv[1] = mathlib.DotProduct(pverts.v, aliastransform[1]) + aliastransform[1][3]; av.fv[2] = mathlib.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 = mathlib.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 ================ */ static void R_AliasProjectFinalVert(draw.finalvert_t fv, auxvert_t av) { double zi; // project points zi = 1.0 / av.fv[2]; fv.v[5] = (int)(zi * ziscale); fv.v[0] = (int)((av.fv[0] * aliasxscale * zi) + aliasxcenter); fv.v[1] = (int)((av.fv[1] * aliasyscale * zi) + aliasycenter); }
/* ================ R_AliasCheckBBox ================ */ static bool R_AliasCheckBBox() { int i, flags, frame, numv; model.aliashdr_t pahdr; double zi, v0, v1, frac; double[][] basepts = new double[8][]; draw.finalvert_t pv0, pv1; draw.finalvert_t[] viewpts = new draw.finalvert_t[16]; auxvert_t pa0, pa1; auxvert_t[] viewaux = new auxvert_t[16]; model.maliasframedesc_t pframedesc; bool zclipped, zfullyclipped; uint anyclip, allclip; int minz; int kk; for (kk = 0; kk < 16; kk++) viewpts[kk] = new draw.finalvert_t(); for (kk = 0; kk < 16; kk++) viewaux[kk] = new auxvert_t(); for (kk = 0; kk < 8; kk++) basepts[kk] = new double[3] {0, 0, 0}; // expand, rotate, and translate points into worldspace currententity.trivial_accept = 0; pmodel = currententity.model; pahdr = (model.aliashdr_t)model.Mod_Extradata (pmodel); pmdl = (model.mdl_t)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)) { console.Con_DPrintf ("No such frame " + frame + " " + pmodel.name + "\n"); frame = 0; } pframedesc = pahdr.frames[frame]; // x worldspace coordinates basepts[0][0] = basepts[1][0] = basepts[2][0] = basepts[3][0] = (double)pframedesc.bboxmin.v[0]; basepts[4][0] = basepts[5][0] = basepts[6][0] = basepts[7][0] = (double)pframedesc.bboxmax.v[0]; // y worldspace coordinates basepts[0][1] = basepts[3][1] = basepts[5][1] = basepts[6][1] = (double)pframedesc.bboxmin.v[1]; basepts[1][1] = basepts[2][1] = basepts[4][1] = basepts[7][1] = (double)pframedesc.bboxmax.v[1]; // z worldspace coordinates basepts[0][2] = basepts[1][2] = basepts[4][2] = basepts[5][2] = (double)pframedesc.bboxmin.v[2]; basepts[2][2] = basepts[3][2] = basepts[6][2] = basepts[7][2] = (double)pframedesc.bboxmax.v[2]; zclipped = false; zfullyclipped = true; minz = 9999; for (i=0; i<8 ; i++) { R_AliasTransformVector (basepts[i], viewaux[i].fv); 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 = (int)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) != 0) { 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) != 0) 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 |= (uint)flags; allclip &= (uint)flags; } if (allclip != 0) return false; // trivial reject off one side currententity.trivial_accept = ((anyclip == 0) && !zclipped) ? 1 : 0; if (currententity.trivial_accept != 0) { if (minz > (r_aliastransition + (pmdl.size * r_resfudge))) { currententity.trivial_accept |= 2; } } return true; }
/* * ================ * R_AliasCheckBBox * ================ */ static bool R_AliasCheckBBox() { int i, flags, frame, numv; model.aliashdr_t pahdr; double zi, v0, v1, frac; double[][] basepts = new double[8][]; draw.finalvert_t pv0, pv1; draw.finalvert_t[] viewpts = new draw.finalvert_t[16]; auxvert_t pa0, pa1; auxvert_t[] viewaux = new auxvert_t[16]; model.maliasframedesc_t pframedesc; bool zclipped, zfullyclipped; uint anyclip, allclip; int minz; int kk; for (kk = 0; kk < 16; kk++) { viewpts[kk] = new draw.finalvert_t(); } for (kk = 0; kk < 16; kk++) { viewaux[kk] = new auxvert_t(); } for (kk = 0; kk < 8; kk++) { basepts[kk] = new double[3]; } // expand, rotate, and translate points into worldspace currententity.trivial_accept = 0; pmodel = currententity.model; pahdr = (model.aliashdr_t)model.Mod_Extradata(pmodel); pmdl = (model.mdl_t)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)) { console.Con_DPrintf("No such frame " + frame + " " + pmodel.name + "\n"); frame = 0; } pframedesc = pahdr.frames[frame]; // x worldspace coordinates basepts[0][0] = basepts[1][0] = basepts[2][0] = basepts[3][0] = (double)pframedesc.bboxmin.v[0]; basepts[4][0] = basepts[5][0] = basepts[6][0] = basepts[7][0] = (double)pframedesc.bboxmax.v[0]; // y worldspace coordinates basepts[0][1] = basepts[3][1] = basepts[5][1] = basepts[6][1] = (double)pframedesc.bboxmin.v[1]; basepts[1][1] = basepts[2][1] = basepts[4][1] = basepts[7][1] = (double)pframedesc.bboxmax.v[1]; // z worldspace coordinates basepts[0][2] = basepts[1][2] = basepts[4][2] = basepts[5][2] = (double)pframedesc.bboxmin.v[2]; basepts[2][2] = basepts[3][2] = basepts[6][2] = basepts[7][2] = (double)pframedesc.bboxmax.v[2]; zclipped = false; zfullyclipped = true; minz = 9999; for (i = 0; i < 8; i++) { R_AliasTransformVector(basepts[i], ref viewaux[i].fv); 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 = (int)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) != 0) { 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) != 0) { 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 |= (uint)flags; allclip &= (uint)flags; } if (allclip != 0) { return(false); // trivial reject off one side } currententity.trivial_accept = ((anyclip == 0) && !zclipped) ? 1 : 0; if (currententity.trivial_accept != 0) { if (minz > (r_aliastransition + (pmdl.size * r_resfudge))) { currententity.trivial_accept |= 2; } } return(true); }