📄 r_poly.pas
字号:
end;
Inc(s_spanletvars.izi, s_spanletvars.izistep);
Inc(Integer(s_spanletvars.pdest), 1);
Inc(Integer(s_spanletvars.pz), SizeOf(SmallInt));
Inc(s_spanletvars.s, s_spanletvars.sstep);
Inc(s_spanletvars.t, s_spanletvars.tstep);
Dec(s_spanletvars.spancount);
until not (s_spanletvars.spancount > 0);
end;
{
** R_DrawSpanlet33Stipple
}
procedure R_DrawSpanlet33Stipple;
var
btemp: cardinal;
pdest: PByte;
pz: PSmallInt;
izi: integer;
s, t: Integer;
begin
pdest := s_spanletvars.pdest;
pz := s_spanletvars.pz;
izi := s_spanletvars.izi;
if IntPower(r_polydesc.stipple_parity, (s_spanletvars.v and 1)) > 0 then
begin
Inc(Integer(s_spanletvars.pdest), s_spanletvars.spancount);
Inc(Integer(s_spanletvars.pz), s_spanletvars.spancount * SizeOf(SmallInt));
if s_spanletvars.spancount = AFFINE_SPANLET_SIZE then
Inc(s_spanletvars.izi, (s_spanletvars.izistep shl AFFINE_SPANLET_SIZE_BITS))
else
Inc(s_spanletvars.izi, (s_spanletvars.izistep * s_spanletvars.izistep));
if IntPower(r_polydesc.stipple_parity, (s_spanletvars.u and 1)) > 0 then
begin
Inc(izi, s_spanletvars.izistep);
Inc(s_spanletvars.s, s_spanletvars.sstep);
Inc(s_spanletvars.t, s_spanletvars.tstep);
Inc(Integer(pdest), 1);
Inc(Integer(pz), SizeOf(SmallInt));
Dec(s_spanletvars.spancount);
end;
s_spanletvars.sstep := s_spanletvars.sstep * 2;
s_spanletvars.tstep := s_spanletvars.tstep * 2;
while s_spanletvars.spancount > 0 do
begin
s := _SAR(s_spanletvars.s, 16);
t := _SAR(s_spanletvars.t, 16);
btemp := PByte(Integer(s_spanletvars.pbase) + (s) + (t * cachewidth))^;
if btemp <> 255 then
begin
if pz^ <= _SAR(izi, 16) then
pdest^ := btemp;
end;
Inc(izi, s_spanletvars.izistep_times_2);
Inc(s_spanletvars.s, s_spanletvars.sstep);
Inc(s_spanletvars.t, s_spanletvars.tstep);
Inc(Integer(pdest), 2);
Inc(Integer(pz), 2 * SizeOf(SmallInt));
Dec(s_spanletvars.spancount, 2);
end;
end;
end;
{
** R_DrawSpanlet66Stipple
}
procedure R_DrawSpanlet66Stipple;
var
btemp: cardinal;
pdest: PByte;
pz: PSmallInt;
izi: integer;
s, t: Integer;
begin
pdest := s_spanletvars.pdest;
pz := s_spanletvars.pz;
izi := s_spanletvars.izi;
Inc(Integer(s_spanletvars.pdest), s_spanletvars.spancount);
Inc(Integer(s_spanletvars.pz), s_spanletvars.spancount * SizeOf(SmallInt));
if (s_spanletvars.spancount = AFFINE_SPANLET_SIZE) then
Inc(s_spanletvars.izi, (s_spanletvars.izistep shl AFFINE_SPANLET_SIZE_BITS))
else
Inc(s_spanletvars.izi, s_spanletvars.izistep * s_spanletvars.izistep);
if IntPower(r_polydesc.stipple_parity, (s_spanletvars.v and 1)) <> 0 then
begin
if IntPower(r_polydesc.stipple_parity, (s_spanletvars.u and 1)) <> 0 then
begin
Inc(izi, s_spanletvars.izistep);
Inc(s_spanletvars.s, s_spanletvars.sstep);
Inc(s_spanletvars.t, s_spanletvars.tstep);
Inc(Integer(pdest), 1);
Inc(Integer(pz), SizeOf(SmallInt));
Dec(s_spanletvars.spancount);
end;
s_spanletvars.sstep := s_spanletvars.sstep * 2;
s_spanletvars.tstep := s_spanletvars.tstep * 2;
while (s_spanletvars.spancount > 0) do
begin
s := _SAR(s_spanletvars.s, 16);
t := _SAR(s_spanletvars.t, 16);
btemp := PByte(Integer(s_spanletvars.pbase) + (s) + (t * cachewidth))^;
if btemp <> 255 then
begin
if pz^ <= _SAR(izi, 16) then
pdest^ := btemp;
end;
Inc(izi, s_spanletvars.izistep_times_2);
Inc(s_spanletvars.s, s_spanletvars.sstep);
Inc(s_spanletvars.t, s_spanletvars.tstep);
Inc(Integer(pdest), 2);
Inc(Integer(pz), 2 * SizeOf(SmallInt));
Dec(s_spanletvars.spancount, 2);
end;
end
else
begin
while (s_spanletvars.spancount > 0) do
begin
s := _SAR(s_spanletvars.s, 16);
t := _SAR(s_spanletvars.t, 16);
btemp := PByte(Integer(s_spanletvars.pbase) + (s) + (t * cachewidth))^;
if (btemp <> 255) then
begin
if pz^ <= _SAR(izi, 16) then
pdest^ := btemp;
end;
Inc(izi, s_spanletvars.izistep);
Inc(s_spanletvars.s, s_spanletvars.sstep);
Inc(s_spanletvars.t, s_spanletvars.tstep);
Inc(Integer(pdest), 1);
Inc(Integer(pz), SizeOf(SmallInt));
Dec(s_spanletvars.spancount);
end;
end;
end;
{
** R_ClipPolyFace
**
** Clips the winding at clip_verts[clip_current] and changes clip_current
** Throws out the back side
}
function R_ClipPolyFace(nump: integer; pclipplane: clipplane_p): integer;
var
i, outcount: Integer;
dists: array[0..MAXWORKINGVERTS + 3 - 1] of Single;
frac, clipdist: Single;
pclipnormal: PSingle;
_in, instep: PSingle;
outstep, vert2: PSingle;
label
continue_;
begin
clipdist := pclipplane^.dist;
pclipnormal := @pclipplane^.normal;
// calc dists
if (clip_current <> 0) then
begin
_in := @r_clip_verts[1][0]; // Converted from "r_clip_verts[1][0]"
outstep := @r_clip_verts[0][0]; // Converted from "r_clip_verts[0][0]"
clip_current := 0;
end
else
begin
_in := @r_clip_verts[0][0]; // Converted from "r_clip_verts[0][0]"
outstep := @r_clip_verts[1][0]; // Converted from "r_clip_verts[1][0]"
clip_current := 1;
end;
instep := _in;
for i := 0 to nump - 1 do
begin
dists[i] := DotProduct(vec3_p(instep)^, vec3_p(pclipnormal)^) - clipdist;
Inc(Integer(instep), SizeOf(vec5_t));
end;
// handle wraparound case
dists[nump] := dists[0];
Move(_in^, instep^, sizeof(vec5_t));
// clip the winding
instep := _in;
outcount := 0;
for i := 0 to nump - 1 do
begin
if (dists[i] >= 0) then
begin
Move(instep^, outstep^, SizeOf(vec5_t));
Inc(Integer(outstep), SizeOf(vec5_t));
Inc(outcount);
end;
if (dists[i] = 0) or (dists[i + 1] = 0) then
goto continue_;
if (dists[i] > 0) = (dists[i + 1] > 0) then
goto continue_;
// split it into a new vertex
frac := dists[i] / (dists[i] - dists[i + 1]);
vert2 := PSingle(Integer(instep) + SizeOf(vec5_t));
vec5_p(outstep)^[0] := vec5_p(instep)^[0] + frac * (vec5_p(vert2)^[0] - vec5_p(instep)^[0]);
vec5_p(outstep)^[1] := vec5_p(instep)^[1] + frac * (vec5_p(vert2)^[1] - vec5_p(instep)^[1]);
vec5_p(outstep)^[2] := vec5_p(instep)^[2] + frac * (vec5_p(vert2)^[2] - vec5_p(instep)^[2]);
vec5_p(outstep)^[3] := vec5_p(instep)^[3] + frac * (vec5_p(vert2)^[3] - vec5_p(instep)^[3]);
vec5_p(outstep)^[4] := vec5_p(instep)^[4] + frac * (vec5_p(vert2)^[4] - vec5_p(instep)^[4]);
Inc(Integer(outstep), SizeOf(vec5_t)); // "/" operator has been changed to "div"
Inc(outcount);
continue_:
Inc(Integer(instep), SizeOf(vec5_t));
end;
result := outcount;
end;
{
** R_PolygonDrawSpans
}
// PGM - iswater was qboolean. changed to allow passing more flags
procedure R_PolygonDrawSpans(pspan: espan_p; iswater: integer);
var
count: integer;
snext, tnext: fixed16_t;
sdivz, tdivz: single;
zi, z, du, dv: single;
spancountminus1: single;
sdivzspanletstepu: single;
tdivzspanletstepu: single;
zispanletstepu: single;
label
NextSpan;
begin
s_spanletvars.pbase := cacheblock;
//PGM
if (iswater and SURF_WARP) <> 0 then
r_turb_turb := @sintable[(Trunc(r_newrefdef.time * SPEED) and (CYCLE - 1))] // removed innecesary cast
else
if (iswater and SURF_FLOWING) <> 0 then
r_turb_turb := @blanktable;
//PGM
sdivzspanletstepu := d_sdivzstepu * AFFINE_SPANLET_SIZE;
tdivzspanletstepu := d_tdivzstepu * AFFINE_SPANLET_SIZE;
zispanletstepu := d_zistepu * AFFINE_SPANLET_SIZE;
// we count on FP exceptions being turned off to avoid range problems
s_spanletvars.izistep := Trunc(d_zistepu * $8000 * $10000);
s_spanletvars.izistep_times_2 := s_spanletvars.izistep * 2;
s_spanletvars.pz := nil;
if (pspan^.count = DS_SPAN_LIST_END) then
exit;
repeat
s_spanletvars.pdest := PByte(Integer(d_viewbuffer) + d_scantable[pspan^.v] + pspan^.u);
s_spanletvars.pz := @PSmallIntArray(d_pzbuffer)^[(Integer(d_zwidth) * pspan^.v) + pspan^.u];
s_spanletvars.u := pspan^.u;
s_spanletvars.v := pspan^.v;
count := pspan^.count;
if (count <= 0) then
goto NextSpan;
// calculate the initial s/z, t/z, 1/z, s, and t and clamp
du := pspan^.u;
dv := 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 := $10000 / zi; // prescale to 16.16 fixed-point
// we count on FP exceptions being turned off to avoid range problems
s_spanletvars.izi := Trunc(zi * $8000 * $10000);
s_spanletvars.s := Trunc(sdivz * z) + sadjust;
s_spanletvars.t := Trunc(tdivz * z) + tadjust;
if iswater = 0 then
begin
if (s_spanletvars.s > bbextents) then
s_spanletvars.s := bbextents
else
if (s_spanletvars.s < 0) then
s_spanletvars.s := 0;
if (s_spanletvars.t > bbextentt) then
s_spanletvars.t := bbextentt
else
if (s_spanletvars.t < 0) then
s_spanletvars.t := 0;
end;
repeat
// calculate s and t at the far end of the span
if (count >= AFFINE_SPANLET_SIZE) then
s_spanletvars.spancount := AFFINE_SPANLET_SIZE
else
s_spanletvars.spancount := count;
Dec(count, s_spanletvars.spancount);
if count <> 0 then
begin
// 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 := sdivz + sdivzspanletstepu;
tdivz := tdivz + tdivzspanletstepu;
zi := zi + zispanletstepu;
z := z + ($10000 / zi); // prescale to 16.16 fixed-point
snext := Trunc(sdivz * z) + sadjust;
tnext := Trunc(tdivz * z) + tadjust;
if iswater = 0 then
begin
if (snext > bbextents) then
snext := bbextents
else
if (snext < AFFINE_SPANLET_SIZE) then
snext := AFFINE_SPANLET_SIZE; // prevent round-off error on <0 steps from
// from causing overstepping & running off the
// edge of the texture
if (tnext > bbextentt) then
tnext := bbextentt
else
if (tnext < AFFINE_SPANLET_SIZE) then
tnext := AFFINE_SPANLET_SIZE; // guard against round-off error on <0 steps
end;
s_spanletvars.sstep := _SAR(snext - s_spanletvars.s, AFFINE_SPANLET_SIZE_BITS);
s_spanletvars.tstep := _SAR(tnext - s_spanletvars.t, AFFINE_SPANLET_SIZE_BITS);
end
else
begin
// 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 := (s_spanletvars.spancount - 1);
sdivz := sdivz + (d_sdivzstepu * spancountminus1);
tdivz := tdivz + (d_tdivzstepu * spancountminus1);
zi := zi + (d_zistepu * spancountminus1);
z := $10000 / zi; // prescale to 16.16 fixed-point
snext := Trunc(sdivz * z) + sadjust;
tnext := Trunc(tdivz * z) + tadjust;
if iswater = 0 then
begin
if (snext > bbextents) then
snext := bbextents
else
if (snext < AFFINE_SPANLET_SIZE) then
snext := AFFINE_SPANLET_SIZE; // prevent round-off error on <0 steps from
// from causing overstepping & running off the
// edge of the texture
if (tnext > bbextentt) then
tnext := bbextentt
else
if (tnext < AFFINE_SPANLET_SIZE) then
tnext := AFFINE_SPANLET_SIZE; // guard against round-off error on <0 steps
end;
if (s_spanletvars.spancount > 1) then
begin
s_spanletvars.sstep := (snext - s_spanletvars.s) div (s_spanletvars.spancount - 1);
s_spanletvars.tstep := (tnext - s_spanletvars.t) div (s_spanletvars.spancount - 1);
end;
end;
if iswater <> 0 then
begin
s_spanletvars.s := s_spanletvars.s and ((CYCLE shl 16) - 1);
s_spanletvars.t := s_spanletvars.t and ((CYCLE shl 16) - 1);
end;
r_polydesc.drawspanlet;
s_spanletvars.s := snext;
s_spanletvars.t := tnext;
until (count <= 0);
NextSpan:
Inc(Integer(pspan), SizeOf(espan_t));
until (pspan^.count = DS_SPAN_LIST_END);
end;
{
**
** R_PolygonScanLeftEdge
**
** Goes through the polygon and scans the left edge, filling in
** screen coordinate data for the spans
}
procedure R_PolygonScanLeftEdge;
var
i, v, itop: integer;
ibottom: integer;
lmaxindex: integer;
pvert, pnext: emitpoint_p;
pspan: espan_p;
du, dv, vtop: single;
vbottom, slope: single;
u, u_step: fixed16_t;
begin
pspan := s_polygon_spans;
i := s_minindex;
if (i = 0) then
i := r_polydesc.nump;
lmaxindex := s_maxindex;
if (lmaxindex = 0) then
lmaxindex := r_polydesc.nump;
vtop := q_shared.ceil(emitpoint_arrp(r_polydesc.pverts)^[i].v);
repeat
pvert := @emitpoint_arrp(r_polydesc.pverts)^[i];
pnext := Pointer(Integer(pvert) - SizeOf(emitpoint_t));
vbottom := q_shared.ceil(pnext^.v);
if (vtop < vbottom) then
begin
du := pnext^.u - pvert^.u;
dv := pnext^.v - pvert^.v;
slope := du / dv;
u_step := trunc(slope * $10000);
//adjust u to ceil the integer portion
u := Trunc((pvert^.u + (slope * (vtop - pvert^.v))) * $10000) + ($10000 - 1);
itop := Trunc(vtop);
ibottom := Trunc(vbottom);
for v := itop to ibottom - 1 do
begin
pspan^.u := _SAR(u, 16);
pspan^.v := v;
Inc(u, u_step);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -