📄 r_poly.pas
字号:
Inc(Integer(pspan), SizeOf(espan_t));
end;
end;
vtop := vbottom;
Dec(i);
if (i = 0) then
i := r_polydesc.nump;
until (i = lmaxindex);
end;
{
** R_PolygonScanRightEdge
**
** Goes through the polygon and scans the right edge, filling in
** count values.
}
procedure R_PolygonScanRightEdge;
var
i, v, itop: Integer;
ibottom: Integer;
pvert, pnext: emitpoint_p;
pspan: espan_p;
du, dv, vtop: Single;
vbottom: Single;
slope, uvert: Single;
unext, vvert: Single;
vnext: Single;
u, u_step: fixed16_t;
begin
pspan := s_polygon_spans;
i := s_minindex;
vvert := emitpoint_arrp(r_polydesc.pverts)^[i].v;
if (vvert < r_refdef.fvrecty_adj) then
vvert := r_refdef.fvrecty_adj;
if (vvert > r_refdef.fvrectbottom_adj) then
vvert := r_refdef.fvrectbottom_adj;
vtop := q_shared.ceil(vvert);
repeat
pvert := @emitpoint_arrp(r_polydesc.pverts)^[i];
pnext := Pointer(Integer(pvert) + SizeOf(emitpoint_t));
vnext := pnext^.v;
if (vnext < r_refdef.fvrecty_adj) then
vnext := r_refdef.fvrecty_adj;
if (vnext > r_refdef.fvrectbottom_adj) then
vnext := r_refdef.fvrectbottom_adj;
vbottom := q_shared.ceil(vnext);
if (vtop < vbottom) then
begin
uvert := pvert^.u;
if (uvert < r_refdef.fvrectx_adj) then
uvert := r_refdef.fvrectx_adj;
if (uvert > r_refdef.fvrectright_adj) then
uvert := r_refdef.fvrectright_adj;
unext := pnext^.u;
if (unext < r_refdef.fvrectx_adj) then
unext := r_refdef.fvrectx_adj;
if (unext > r_refdef.fvrectright_adj) then
unext := r_refdef.fvrectright_adj;
du := unext - uvert;
dv := vnext - vvert;
slope := du / dv;
u_step := Trunc(slope * $10000);
// adjust u to ceil the integer portion
u := Trunc((uvert + (slope * (vtop - vvert))) * $10000) + ($10000 - 1);
itop := Trunc(vtop);
ibottom := Trunc(vbottom);
for v := itop to ibottom - 1 do
begin
pspan^.count := _SAR(u, 16) - pspan^.u;
Inc(u, u_step);
Inc(Integer(pspan), SizeOf(espan_t));
end;
end;
vtop := vbottom;
vvert := vnext;
Inc(i);
if (i = r_polydesc.nump) then
i := 0;
until (i = s_maxindex);
pspan^.count := DS_SPAN_LIST_END; // mark the end of the span list
end;
{
** R_ClipAndDrawPoly
}
// PGM - isturbulent was qboolean. changed to int to allow passing more flags
procedure R_ClipAndDrawPoly(alpha: single; isturbulent: integer; textured: qboolean);
var
outverts: array[0..MAXWORKINGVERTS + 3 - 1] of emitpoint_t;
pout: emitpoint_p;
pv: PSingle;
i, nump: integer;
scale: single;
transformed: vec3_t;
local: vec3_t;
begin
FillChar(outverts, SizeOf(outverts), 0);
if not textured then
begin
r_polydesc.drawspanlet := R_DrawSpanletConstant33;
end
else
begin
{
** choose the correct spanlet routine based on alpha
}
if (alpha = 1) then
begin
// isturbulent is ignored because we know that turbulent surfaces
// can't be opaque
r_polydesc.drawspanlet := R_DrawSpanletOpaque;
end
else
begin
if sw_stipplealpha^.value <> 0.0 then
begin
if (isturbulent <> 0) then
begin
if (alpha > 0.33) then
r_polydesc.drawspanlet := R_DrawSpanletTurbulentStipple66
else
r_polydesc.drawspanlet := R_DrawSpanletTurbulentStipple33;
end
else
begin
if (alpha > 0.33) then
r_polydesc.drawspanlet := R_DrawSpanlet66Stipple
else
r_polydesc.drawspanlet := R_DrawSpanlet33Stipple;
end;
end
else
begin
if (isturbulent <> 0) then
begin
if (alpha > 0.33) then
r_polydesc.drawspanlet := R_DrawSpanletTurbulentBlended66
else
r_polydesc.drawspanlet := R_DrawSpanletTurbulentBlended33;
end
else
begin
if (alpha > 0.33) then
r_polydesc.drawspanlet := R_DrawSpanlet66
else
r_polydesc.drawspanlet := R_DrawSpanlet33;
end;
end;
end;
end;
// clip to the frustum in worldspace
nump := r_polydesc.nump;
clip_current := 0;
for i := 0 to 3 do
begin
nump := R_ClipPolyFace(nump, @view_clipplanes[i]);
if (nump < 3) then
exit;
if (nump > MAXWORKINGVERTS) then
ri.Sys_Error(ERR_DROP, PChar('R_ClipAndDrawPoly: too many points: ' + IntToStr(nump)));
end;
// transform vertices into viewspace and project
pv := @r_clip_verts[clip_current][0];
for i := 0 to nump - 1 do
begin
VectorSubtract(vec3_p(pv)^, r_origin, local);
TransformVector(local, transformed);
if (transformed[2] < NEAR_CLIP) then
transformed[2] := NEAR_CLIP;
pout := @outverts[i];
pout^.zi := 1.0 / transformed[2];
pout^.s := vec5_p(pv)^[3];
pout^.t := vec5_p(pv)^[4];
scale := xscale * pout^.zi;
pout^.u := (xcenter + scale * transformed[0]);
scale := yscale * pout^.zi;
pout^.v := (ycenter - scale * transformed[1]);
Inc(Integer(pv), SizeOf(vec5_t));
end;
// draw it
r_polydesc.nump := nump;
r_polydesc.pverts := @outverts[0]; // C pointer can be converted as Pascal's 1st address element
R_DrawPoly(isturbulent);
end;
{
** R_BuildPolygonFromSurface
}
procedure R_BuildPolygonFromSurface(fa: msurface_p);
var
i, lindex: Integer;
lnumverts: Integer;
pedges: medge_p;
r_pedge: medge_p;
// vertpage : Integer; // never used
vec: PSingle;
pverts: vec5_p;
tmins: array[0..2 - 1] of Single;
scache: surfcache_p;
begin
tmins[0] := 0;
tmins[1] := 0;
r_polydesc.nump := 0;
// reconstruct the polygon
pedges := currentmodel^.edges;
lnumverts := fa^.numedges;
// vertpage := 0; // never used
pverts := @r_clip_verts[0][0];
for i := 0 to lnumverts - 1 do
begin
lindex := PIntegerArray(currentmodel^.surfedges)^[fa^.firstedge + i];
if (lindex > 0) then
begin
r_pedge := @medge_arrp(pedges)^[lindex];
vec := @mvertex_arrp(currentmodel^.vertexes)^[r_pedge^.v[0]].position;
end
else
begin
r_pedge := @medge_arrp(pedges)^[-lindex];
vec := @mvertex_arrp(currentmodel^.vertexes)^[r_pedge^.v[1]].position;
end;
VectorCopy(vec3_p(vec)^, vec3_p(@vec5_arrp(pverts)^[i])^);
end;
VectorCopy(vec3_p(@fa^.texinfo^.vecs[0])^, r_polydesc.vright);
VectorCopy(vec3_p(@fa^.texinfo^.vecs[1])^, r_polydesc.vup);
VectorCopy(fa^.plane^.normal, r_polydesc.vpn);
VectorCopy(r_origin, vec3_p(@r_polydesc.viewer_position)^);
if (fa^.flags and SURF_PLANEBACK) <> 0 then
begin
VectorSubtract(vec3_origin, r_polydesc.vpn, r_polydesc.vpn);
end;
// PGM 09/16/98
if (fa^.texinfo^.flags and (SURF_WARP or SURF_FLOWING)) <> 0 then
begin
r_polydesc.pixels := fa^.texinfo^.image^.pixels[0];
r_polydesc.pixel_width := fa^.texinfo^.image^.width;
r_polydesc.pixel_height := fa^.texinfo^.image^.height;
end
// PGM 09/16/98
else
begin
scache := D_CacheSurface(fa, 0);
r_polydesc.pixels := @scache^.data[0];
r_polydesc.pixel_width := scache^.width;
r_polydesc.pixel_height := scache^.height;
tmins[0] := fa^.texturemins[0];
tmins[1] := fa^.texturemins[1];
end;
r_polydesc.dist := DotProduct(r_polydesc.vpn, vec3_p(pverts)^);
r_polydesc.s_offset := fa^.texinfo^.vecs[0, 3] - tmins[0];
r_polydesc.t_offset := fa^.texinfo^.vecs[1, 3] - tmins[1];
// scrolling texture addition
if (fa^.texinfo^.flags and SURF_FLOWING) <> 0 then
begin
r_polydesc.s_offset := r_polydesc.s_offset + (-128 * ((r_newrefdef.time * 0.25) - Trunc(r_newrefdef.time * 0.25)));
end;
r_polydesc.nump := lnumverts;
end;
{
** R_PolygonCalculateGradients
}
procedure R_PolygonCalculateGradients;
var
p_normal: vec3_t;
p_saxis: vec3_t;
p_taxis: vec3_t;
distinv: single;
begin
TransformVector(r_polydesc.vpn, p_normal);
TransformVector(r_polydesc.vright, p_saxis);
TransformVector(r_polydesc.vup, p_taxis);
distinv := 1.0 / (-(DotProduct(vec3_t(r_polydesc.viewer_position), r_polydesc.vpn)) + r_polydesc.dist);
d_sdivzstepu := p_saxis[0] * xscaleinv;
d_sdivzstepv := -p_saxis[1] * yscaleinv;
d_sdivzorigin := p_saxis[2] - xcenter * d_sdivzstepu - ycenter * d_sdivzstepv;
d_tdivzstepu := p_taxis[0] * xscaleinv;
d_tdivzstepv := -p_taxis[1] * yscaleinv;
d_tdivzorigin := p_taxis[2] - xcenter * d_tdivzstepu - ycenter * d_tdivzstepv;
d_zistepu := p_normal[0] * xscaleinv * distinv;
d_zistepv := -p_normal[1] * yscaleinv * distinv;
d_ziorigin := p_normal[2] * distinv - xcenter * d_zistepu - ycenter * d_zistepv;
sadjust := fixed16_t(Trunc((DotProduct(vec3_p(@r_polydesc.viewer_position)^, r_polydesc.vright) + r_polydesc.s_offset) * $10000));
tadjust := fixed16_t(Trunc((DotProduct(vec3_p(@r_polydesc.viewer_position)^, r_polydesc.vup) + r_polydesc.t_offset) * $10000));
// -1 (-epsilon) so we never wander off the edge of the texture
bbextents := (r_polydesc.pixel_width shl 16) - 1;
bbextentt := (r_polydesc.pixel_height shl 16) - 1;
end;
{
** R_DrawPoly
**
** Polygon drawing function. Uses the polygon described in r_polydesc
** to calculate edges and gradients, then renders the resultant spans.
**
** This should NOT be called externally since it doesn't do clipping!
}
// PGM - iswater was qboolean. changed to support passing more flags
procedure R_DrawPoly(iswater: Integer);
var
i, nump: integer;
ymin, ymax: single;
pverts: emitpoint_p;
spans: array[0..MAXHEIGHT + 1 - 1] of espan_t;
begin
FillChar(spans, SizeOf(spans), 0);
s_polygon_spans := @spans[0];
// find the top and bottom vertices, and make sure there's at least one scan to
// draw
ymin := 999999.9;
ymax := -999999.9;
pverts := r_polydesc.pverts;
for i := 0 to r_polydesc.nump - 1 do
begin
if (pverts^.v < ymin) then
begin
ymin := pverts^.v;
s_minindex := i;
end;
if (pverts^.v > ymax) then
begin
ymax := pverts^.v;
s_maxindex := i;
end;
Inc(Integer(pverts), SizeOf(emitpoint_p));
end;
ymin := q_shared.ceil(ymin);
ymax := q_shared.ceil(ymax);
if (ymin >= ymax) then
Exit; // doesn't cross any scans at all
cachewidth := r_polydesc.pixel_width;
cacheblock := r_polydesc.pixels;
// copy the first vertex to the last vertex, so we don't have to deal with
// wrapping
nump := r_polydesc.nump;
pverts := r_polydesc.pverts;
emitpoint_arrp(pverts)^[nump] := pverts^;
R_PolygonCalculateGradients;
R_PolygonScanLeftEdge;
R_PolygonScanRightEdge;
R_PolygonDrawSpans(s_polygon_spans, iswater);
end;
{
** R_DrawAlphaSurfaces
}
procedure R_DrawAlphaSurfaces;
var
s: msurface_p;
begin
s := r_alpha_surfaces;
currentmodel := r_worldmodel;
modelorg[0] := -r_origin[0];
modelorg[1] := -r_origin[1];
modelorg[2] := -r_origin[2];
while s <> nil do
begin
R_BuildPolygonFromSurface(s);
//=======
//PGM
// if (s->texinfo->flags & SURF_TRANS66)
// R_ClipAndDrawPoly( 0.60f, ( s->texinfo->flags & SURF_WARP) != 0, true );
// else
// R_ClipAndDrawPoly( 0.30f, ( s->texinfo->flags & SURF_WARP) != 0, true );
// PGM - pass down all the texinfo flags, not just SURF_WARP.
if (s^.texinfo^.flags and SURF_TRANS66) <> 0 then
R_ClipAndDrawPoly(0.60, (s^.texinfo^.flags and (SURF_WARP or SURF_FLOWING)), true)
else
R_ClipAndDrawPoly(0.30, (s^.texinfo^.flags and (SURF_WARP or SURF_FLOWING)), true);
//PGM
//=======
s := s^.nextalphasurface;
end;
r_alpha_surfaces := nil;
end;
{
** R_IMFlatShadedQuad
}
procedure R_IMFlatShadedQuad(a, b, c, d: vec3_t; color: integer; alpha: single);
var
s0, s1: vec3_t;
begin
r_polydesc.nump := 4;
VectorCopy(r_origin, vec3_p(@r_polydesc.viewer_position)^);
VectorCopy(a, vec3_p(@r_clip_verts[0][0])^);
VectorCopy(b, vec3_p(@r_clip_verts[0][1])^);
VectorCopy(c, vec3_p(@r_clip_verts[0][2])^);
VectorCopy(d, vec3_p(@r_clip_verts[0][3])^);
r_clip_verts[0][0][3] := 0;
r_clip_verts[0][1][3] := 0;
r_clip_verts[0][2][3] := 0;
r_clip_verts[0][3][3] := 0;
r_clip_verts[0][0][4] := 0;
r_clip_verts[0][1][4] := 0;
r_clip_verts[0][2][4] := 0;
r_clip_verts[0][3][4] := 0;
VectorSubtract(d, c, s0);
VectorSubtract(c, b, s1);
CrossProduct(s0, s1, r_polydesc.vpn);
VectorNormalize(r_polydesc.vpn);
//???? DotProduct expects vec3_t instead vec5_t
r_polydesc.dist := DotProduct(r_polydesc.vpn, vec3_p(@r_clip_verts[0][0])^);
r_polyblendcolor := color;
R_ClipAndDrawPoly(alpha, 0, false);
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -