📄 r_edge.pas
字号:
// must be two bmodels in the same leaf; don't care which is really
// in front, because they'll never be farthest anyway
end;
goto gotposition;
newtop:
// emit a span (obscures current top)
iu := _SAR(edge^.u, 20);
if (iu > surf2^.last_u) then
begin
span := span_p;
Inc(Integer(span_p), SizeOf(espan_t));
span^.u := surf2^.last_u;
span^.count := iu - span^.u;
span^.v := current_iv;
span^.pnext := surf2^.spans;
surf2^.spans := span;
end;
// set last_u on the new span
surf^.last_u := iu;
gotposition:
// insert before surf2
surf^.next := surf2;
surf^.prev := surf2^.prev;
surf2^.prev^.next := surf;
surf2^.prev := surf;
end;
end;
(*
==============
R_TrailingEdge
==============
*)
procedure R_TrailingEdge(surf: surf_p; edge: edge_p);
var
span: espan_p;
iu: Integer;
begin
// don't generate a span if this is an inverted span, with the end
// edge preceding the start edge (that is, we haven't seen the
// start edge yet)
Dec(surf^.spanstate, 1);
if (surf^.spanstate = 0) then
begin
if (Integer(surf) = Integer(@PSurf_tArray(surfaces)^[1].next)) then
begin
// emit a span (current top going away)
iu := _SAR(edge^.u, 20);
if (iu > surf^.last_u) then
begin
span := span_p;
Inc(Integer(span_p), SizeOf(espan_t));
span^.u := surf^.last_u;
span^.count := iu - span^.u;
span^.v := current_iv;
span^.pnext := surf^.spans;
surf^.spans := span;
end;
// set last_u on the surface below
surf^.next^.last_u := iu;
end;
surf^.prev^.next := surf^.next;
surf^.next^.prev := surf^.prev;
end;
end;
{$IFNDEF id386}
(*
==============
R_LeadingEdge
==============
*)
procedure R_LeadingEdge(edge: edge_p);
label
gotposition;
label
newtop;
label
continue_search;
var
span: espan_p;
surf: surf_p;
surf2: surf_p;
iu: Integer;
fu, newzi: Single;
testzi: Single;
newzitop: Single;
newzibottom: Single;
begin
if (edge^.surfs[1] <> 0) then
begin
// it's adding a new surface in, so find the correct place
surf := @PSurf_tArray(surfaces)^[1];
// don't start a span if this is an inverted span, with the end
// edge preceding the start edge (that is, we've already seen the
// end edge)
Inc(surf^.spanstate, 1);
if (surf^.spanstate = 1) then
begin
surf2 := PSurf_tArray(surfaces)^[1].next;
if (surf^.key < surf2^.key) then
goto newtop;
// if it's two surfaces on the same plane, the one that's already
// active is in front, so keep going unless it's a bmodel
if ((surf^.insubmodel) and (surf^.key = surf2^.key)) then
begin
// must be two bmodels in the same leaf; sort on 1/z
fu := edge^.u;
fu := (fu - $FFFFF) * (1.0 / $100000);
newzi := surf^.d_ziorigin + fv * surf^.d_zistepv + fu * surf^.d_zistepu;
newzibottom := newzi * 0.99;
testzi := surf2^.d_ziorigin + fv * surf2^.d_zistepv + fu * surf2^.d_zistepu;
if (newzibottom >= testzi) then
begin
goto newtop;
end;
newzitop := newzi * 1.01;
if (newzitop >= testzi) then
begin
if (surf^.d_zistepu >= surf2^.d_zistepu) then
begin
goto newtop;
end;
end;
end;
continue_search:
repeat
surf2 := surf2^.next;
until (surf^.key <= surf2^.key);
if (surf^.key = surf2^.key) then
begin
// if it's two surfaces on the same plane, the one that's already
// active is in front, so keep going unless it's a bmodel
if not (surf^.insubmodel) then
goto continue_search;
// must be two bmodels in the same leaf; sort on 1/z
fu := edge^.u;
fu := (fu - $FFFFF) * (1.0 / $100000);
newzi := surf^.d_ziorigin + fv * surf^.d_zistepv + fu * surf^.d_zistepu;
newzibottom := newzi * 0.99;
testzi := surf2^.d_ziorigin + fv * surf2^.d_zistepv + fu * surf2^.d_zistepu;
if (newzibottom >= testzi) then
begin
goto gotposition;
end;
newzitop := newzi * 1.01;
if (newzitop >= testzi) then
begin
if (surf^.d_zistepu >= surf2^.d_zistepu) then
begin
goto gotposition;
end;
end;
goto continue_search;
end;
goto gotposition;
newtop:
// emit a span (obscures current top)
iu := _SAR(edge^.u, 20);
if (iu > surf2^.last_u) then
begin
span := span_p;
Inc(Integer(span_p), SizeOf(espan_t));
span^.u := surf2^.last_u;
span^.count := iu - span^.u;
span^.v := current_iv;
span^.pnext := surf2^.spans;
surf2^.spans := span;
end;
// set last_u on the new span
surf^.last_u := iu;
gotposition:
// insert before surf2
surf^.next := surf2;
surf^.prev := surf2^.prev;
surf2^.prev^.next := surf;
surf2^.prev := surf;
end;
end;
end;
(*
==============
R_GenerateSpans
==============
*)
procedure R_GenerateSpans;
var
edge: edge_p;
surf: surf_p;
begin
// clear active surfaces to just the background surface
PSurf_tArray(surfaces)^[1].next := @PSurf_tArray(surfaces)^[1];
PSurf_tArray(surfaces)^[1].prev := @PSurf_tArray(surfaces)^[1];
PSurf_tArray(surfaces)^[1].last_u := edge_head_u_shift20;
// generate spans
edge := edge_head.next;
while (Integer(edge) <> Integer(@edge_tail)) do
// for (edge=edge_head.next ; edge != &edge_tail; edge=edge->next) then
begin
if (edge^.surfs[0] <> 0) then
begin
// it has a left surface, so a surface is going away for this span
surf := @PSurf_tArray(surfaces)^[edge^.surfs[0]];
R_TrailingEdge(surf, edge);
if (edge^.surfs[1] = 0) then
begin
edge := edge^.next;
continue;
end;
end;
R_LeadingEdge(edge);
edge := edge^.next;
end;
R_CleanupSpan;
end;
{$ENDIF} // !id386
(*
==============
R_GenerateSpansBackward
==============
*)
procedure R_GenerateSpansBackward;
var
edge: edge_p;
surf: surf_p;
begin
// clear active surfaces to just the background surface
PSurf_tArray(surfaces)^[1].next := @PSurf_tArray(surfaces)^[1];
PSurf_tArray(surfaces)^[1].prev := @PSurf_tArray(surfaces)^[1];
PSurf_tArray(surfaces)^[1].last_u := edge_head_u_shift20;
// generate spans
edge := edge_head.next;
while (Integer(edge) <> Integer(@edge_tail)) do
// for (edge=edge_head.next ; edge != &edge_tail; edge=edge->next) then
begin
if (edge^.surfs[0] <> 0) then
begin
// it has a left surface, so a surface is going away for this span
surf := @PSurf_tArray(surfaces)^[edge^.surfs[0]];
R_TrailingEdge(surf, edge);
end;
if (edge^.surfs[1] <> 0) then
R_LeadingEdgeBackwards(edge);
edge := edge^.next;
end;
R_CleanupSpan;
end;
(*
==============
R_ScanEdges
Input:
newedges[] array
this has links to edges, which have links to surfaces
Output:
Each surface has a linked list of its visible spans
==============
*)
procedure R_ScanEdges;
var
iv, bottom: Integer;
basespans: array[0..(MAXSPANS * sizeof(espan_t) + CACHE_SIZE) - 1] of Byte;
basespan_p: espan_p;
s: surf_p;
begin
// basespan_p = (espan_t *)((long)(basespans + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
basespan_p := espan_p(Integer(@basespans[(CACHE_SIZE - 1) * sizeof(espan_t)]) and ($FFFFFFFF xor (CACHE_SIZE - 1)));
// max_span_p = &basespan_p[MAXSPANS - r_refdef.vrect.width];
max_span_p := @PEspan_tArray(basespan_p)^[MAXSPANS - r_refdef.vrect.width];
span_p := basespan_p;
// clear active edges to just the background edges around the whole screen
// FIXME: most of this only needs to be set up once
edge_head.u := _SAL(r_refdef.vrect.x, 20);
edge_head_u_shift20 := _SAR(edge_head.u, 20);
edge_head.u_step := 0;
edge_head.prev := nil;
edge_head.next := @edge_tail;
edge_head.surfs[0] := 0;
edge_head.surfs[1] := 1;
edge_tail.u := _SAL(r_refdef.vrectright, 20) + $FFFFF;
edge_tail_u_shift20 := _SAR(edge_tail.u, 20);
edge_tail.u_step := 0;
edge_tail.prev := @edge_head;
edge_tail.next := @edge_aftertail;
edge_tail.surfs[0] := 1;
edge_tail.surfs[1] := 0;
edge_aftertail.u := -1; // force a move
edge_aftertail.u_step := 0;
edge_aftertail.next := @edge_sentinel;
edge_aftertail.prev := @edge_tail;
// FIXME: do we need this now that we clamp x in r_draw.c?
edge_sentinel.u := 125 shl 24; //2000 shl 24; // make sure nothing sorts past this
edge_sentinel.prev := @edge_aftertail;
//
// process all scan lines
//
bottom := r_refdef.vrectbottom - 1;
// for (iv=r_refdef.vrect.y ; iv<bottom ; iv++) do
for iv := r_refdef.vrect.y to bottom - 1 do
begin
current_iv := iv;
fv := iv;
// mark that the head (background start) span is pre-included
PSurf_tArray(surfaces)^[1].spanstate := 1;
if (newedges[iv] <> nil) then
begin
R_InsertNewEdges(newedges[iv], edge_head.next);
end;
pdrawfunc;
// flush the span list if we can't be sure we have enough spans left for
// the next scan
if (Integer(span_p) > Integer(max_span_p)) then
begin
D_DrawSurfaces;
// clear the surface span pointers
// for (s = &surfaces[1] ; s<surface_p ; s++) do
s := @PSurf_tArray(surfaces)^[1];
while (Integer(s) < Integer(surface_p)) do
begin
s^.spans := nil;
Inc(Integer(s), SizeOf(surf_t));
end;
span_p := basespan_p;
end;
if (removeedges[iv] <> nil) then
R_RemoveEdges(removeedges[iv]);
if (Integer(edge_head.next) <> Integer(@edge_tail)) then
R_StepActiveU(edge_head.next);
end;
// do the last scan (no need to step or sort or remove on the last scan)
iv := bottom;
current_iv := iv;
fv := iv;
// mark that the head (background start) span is pre-included
PSurf_tArray(surfaces)^[1].spanstate := 1;
if (newedges[iv] <> nil) then
R_InsertNewEdges(newedges[iv], edge_head.next);
pdrawfunc;
// draw whatever's left in the span list
D_DrawSurfaces;
end;
(*
=========================================================================
SURFACE FILLING
=========================================================================
*)
var
pface: msurface_p;
pcurrentcache: surfcache_p;
transformed_modelorg: vec3_t;
world_transformed_modelorg: vec3_t;
local_modelorg: vec3_t;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -