/* * ===================== * D_DrawSprite * ===================== */ public static void D_DrawSprite() { int i, nump; double ymin, ymax; emitpoint_t[] pverts; sspan_t[] spans = new sspan_t[render.MAXHEIGHT + 1]; for (int kk = 0; kk < render.MAXHEIGHT + 1; kk++) { spans[kk] = new sspan_t(); } sprite_spans = spans; // find the top and bottom vertices, and make sure there's at least one scan to // draw ymin = 999999.9; ymax = -999999.9; pverts = render.r_spritedesc.pverts; for (i = 0; i < render.r_spritedesc.nump; i++) { if (pverts[i].v < ymin) { ymin = pverts[i].v; minindex = i; } if (pverts[i].v > ymax) { ymax = pverts[i].v; maxindex = i; } } ymin = Math.Ceiling(ymin); ymax = Math.Ceiling(ymax); if (ymin >= ymax) { return; // doesn't cross any scans at all } cachewidth = render.r_spritedesc.pspriteframe.width; sprite_height = render.r_spritedesc.pspriteframe.height; cacheblock = (byte[])render.r_spritedesc.pspriteframe.pixels; // copy the first vertex to the last vertex, so we don't have to deal with // wrapping nump = render.r_spritedesc.nump; pverts = render.r_spritedesc.pverts; pverts[nump] = pverts[0]; D_SpriteCalculateGradients(); D_SpriteScanLeftEdge(); D_SpriteScanRightEdge(); D_SpriteDrawSpans(sprite_spans); }
/* ===================== D_DrawSprite ===================== */ public static void D_DrawSprite() { int i, nump; double ymin, ymax; emitpoint_t[] pverts; sspan_t[] spans = new sspan_t[render.MAXHEIGHT+1]; for (int kk = 0; kk < render.MAXHEIGHT + 1; kk++) spans[kk] = new sspan_t(); sprite_spans = spans; // find the top and bottom vertices, and make sure there's at least one scan to // draw ymin = 999999.9; ymax = -999999.9; pverts = render.r_spritedesc.pverts; for (i=0 ; i<render.r_spritedesc.nump ; i++) { if (pverts[i].v < ymin) { ymin = pverts[i].v; minindex = i; } if (pverts[i].v > ymax) { ymax = pverts[i].v; maxindex = i; } } ymin = Math.Ceiling(ymin); ymax = Math.Ceiling(ymax); if (ymin >= ymax) return; // doesn't cross any scans at all cachewidth = render.r_spritedesc.pspriteframe.width; sprite_height = render.r_spritedesc.pspriteframe.height; cacheblock = (byte[])render.r_spritedesc.pspriteframe.pixels; // copy the first vertex to the last vertex, so we don't have to deal with // wrapping nump = render.r_spritedesc.nump; pverts = render.r_spritedesc.pverts; pverts[nump] = pverts[0]; D_SpriteCalculateGradients (); D_SpriteScanLeftEdge (); D_SpriteScanRightEdge (); D_SpriteDrawSpans (sprite_spans); }
/* ===================== D_SpriteDrawSpans ===================== */ static void D_SpriteDrawSpans(sspan_t[] span) { int pspan = 0; int count, spancount, izistep; int izi; byte[] pbase; int pdest; int s, t, snext, tnext, sstep, tstep; double sdivz, tdivz, zi, z, du, dv, spancountminus1; double sdivz8stepu, tdivz8stepu, zi8stepu; byte btemp; int pz; sstep = 0; // keep compiler happy tstep = 0; // ditto pbase = cacheblock; sdivz8stepu = d_sdivzstepu * 8; tdivz8stepu = d_tdivzstepu * 8; zi8stepu = d_zistepu * 8; // we count on FP exceptions being turned off to avoid range problems izistep = (int)(d_zistepu * 0x8000 * 0x10000); do { pdest = (screenwidth * span[pspan].v) + span[pspan].u; pz = (int)((d_zwidth * span[pspan].v) + span[pspan].u); count = span[pspan].count; if (count <= 0) goto NextSpan; // calculate the initial s/z, t/z, 1/z, s, and t and clamp du = (double)span[pspan].u; dv = (double)span[pspan].v; sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu; tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu; zi = d_ziorigin + dv*d_zistepv + du*d_zistepu; z = (double)0x10000 / zi; // prescale to 16.16 fixed-point // we count on FP exceptions being turned off to avoid range problems izi = (int)(zi * 0x8000 * 0x10000); s = (int)(sdivz * z) + sadjust; if (s > bbextents) s = bbextents; else if (s < 0) s = 0; t = (int)(tdivz * z) + tadjust; if (t > bbextentt) t = bbextentt; else if (t < 0) t = 0; do { // calculate s and t at the far end of the span if (count >= 8) spancount = 8; else spancount = count; count -= spancount; if (count != 0) { // calculate s/z, t/z, zi.fixed s and t at far end of span, // calculate s and t steps across span by shifting sdivz += sdivz8stepu; tdivz += tdivz8stepu; zi += zi8stepu; z = (double)0x10000 / zi; // prescale to 16.16 fixed-point snext = (int)(sdivz * z) + sadjust; if (snext > bbextents) snext = bbextents; else if (snext < 8) snext = 8; // prevent round-off error on <0 steps from // from causing overstepping & running off the // edge of the texture tnext = (int)(tdivz * z) + tadjust; if (tnext > bbextentt) tnext = bbextentt; else if (tnext < 8) tnext = 8; // guard against round-off error on <0 steps sstep = (snext - s) >> 3; tstep = (tnext - t) >> 3; } else { // calculate s/z, t/z, zi.fixed s and t at last pixel in span (so // can't step off polygon), clamp, calculate s and t steps across // span by division, biasing steps low so we don't run off the // texture spancountminus1 = (double)(spancount - 1); sdivz += d_sdivzstepu * spancountminus1; tdivz += d_tdivzstepu * spancountminus1; zi += d_zistepu * spancountminus1; z = (double)0x10000 / zi; // prescale to 16.16 fixed-point snext = (int)(sdivz * z) + sadjust; if (snext > bbextents) snext = bbextents; else if (snext < 8) snext = 8; // prevent round-off error on <0 steps from // from causing overstepping & running off the // edge of the texture tnext = (int)(tdivz * z) + tadjust; if (tnext > bbextentt) tnext = bbextentt; else if (tnext < 8) tnext = 8; // guard against round-off error on <0 steps if (spancount > 1) { sstep = (snext - s) / (spancount - 1); tstep = (tnext - t) / (spancount - 1); } } do { btemp = pbase[(s >> 16) + (t >> 16) * cachewidth]; if (btemp != 255) { if (d_pzbuffer[pz] <= (izi >> 16)) { d_pzbuffer[pz] = (short)(izi >> 16); d_viewbuffer[pdest] = btemp; } } izi += izistep; pdest++; pz++; s += sstep; t += tstep; } while (--spancount > 0); s = snext; t = tnext; } while (count > 0); NextSpan: pspan++; } while (span[pspan].count != DS_SPAN_LIST_END); }