📄 r_bsp_c.pas
字号:
ptedge^.v[1] := pfrontexit;
Inc(numbedges);
end;
// draw or recurse further
for I := 0 to 1 do
begin
if (psideedges[i] <> nil) then
begin
// draw if we've reached a non-solid leaf, done if all that's left is a
// solid leaf, and continue down the tree if it's not a leaf
pn := pnode^.children[i];
// we're done with this branch if the node or leaf isn't in the PVS
if (pn^.visframe = r_visframecount) then
begin
if (pn^.contents <> CONTENTS_NODE) then
begin
if (pn^.contents <> CONTENTS_SOLID) then
begin
if (r_newrefdef.areabits <> nil) then
begin
area := mleaf_p(pn)^.area;
if ((PByte(Integer(r_newrefdef.areabits) + (area shr 3))^ and (1 shl (area and 7))) = 0) then
continue; // not visible
end;
r_currentbkey := mleaf_p(pn)^.key;
R_RenderBmodelFace(psideedges[i], psurf);
end;
end
else
begin
R_RecursiveClipBPoly(psideedges[i], pnode^.children[i], psurf);
end;
end;
end;
end;
end;
(*
================
R_DrawSolidClippedSubmodelPolygons
Bmodel crosses multiple leafs
================
*)
procedure R_DrawSolidClippedSubmodelPolygons(pmodel : model_p; topnode : mnode_p);
var
i, j, lindex : Integer;
dot : vec_t;
psurf : msurface_p;
numsurfaces : Integer;
pplane : mplane_p;
bverts : array[0..MAX_BMODEL_VERTS] of mvertex_t;
bedges : array[0..MAX_BMODEL_EDGES] of bedge_t;
pbedge : bedge_p;
pedge : medge_p;
pedges : medge_p;
begin
// FIXME: use bounding-box-based frustum clipping info?
psurf := @msurface_arrp(pmodel^.surfaces)^[pmodel^.firstmodelsurface];
// psurf := msurface_p(Integer(pmodel^.surfaces)+(pmodel^.firstmodelsurface*SizeOf(msurface_t)));
numsurfaces := pmodel^.nummodelsurfaces;
pedges := pmodel^.edges;
// for (i=0 ; i<numsurfaces ; i++, psurf++)
for I := 0 to numsurfaces - 1 do
begin
// find which side of the node we are on
pplane := psurf^.plane;
dot := DotProduct(modelorg, pplane^.normal) - pplane^.dist;
// draw the polygon
if (((psurf^.flags and SURF_PLANEBACK) = 0) and (dot < -BACKFACE_EPSILON)) or
(((psurf^.flags and SURF_PLANEBACK) <> 0) and (dot > BACKFACE_EPSILON)) then
begin
//psurf := msurface_p(Integer(psurf)+SizeOf(msurface_t));
Inc(Integer(psurf), SizeOf(msurface_t));
continue;
end;
// FIXME: use bounding-box-based frustum clipping info?
// copy the edges to bedges, flipping if necessary so always
// clockwise winding
// FIXME: if edges and vertices get caches, these assignments must move
// outside the loop, and overflow checking must be done here
pbverts := @bverts;
pbedges := @bedges;
numbverts := 0;
numbedges := 0;
pbedge := @bedges[numbedges];
Inc(numbedges, psurf^.numedges);
for j := 0 to psurf^.numedges-1 do
begin // check here.
lindex := PIntegerArray(pmodel^.surfedges)^[psurf^.firstedge+j];
if (lindex > 0) then
begin
pedge := @medge_arrp(pedges)^[lindex];
PBedge_tArray(pbedge)^[j].v[0] := @mvertex_arrp(r_pcurrentvertbase)^[pedge^.v[0]];
PBedge_tArray(pbedge)^[j].v[1] := @mvertex_arrp(r_pcurrentvertbase)^[pedge^.v[1]];
end
else
begin
lindex := abs(lindex);
pedge := @medge_arrp(pedges)^[lindex];
PBedge_tArray(pbedge)^[j].v[0] := @mvertex_arrp(r_pcurrentvertbase)^[pedge^.v[0]];
PBedge_tArray(pbedge)^[j].v[1] := @mvertex_arrp(r_pcurrentvertbase)^[pedge^.v[1]];
end;
PBedge_tArray(pbedge)^[j].pnext := @PBedge_tArray(pbedge)^[j + 1];
end;
PBedge_tArray(pbedge)^[psurf^.numedges - 1].pnext := nil; // mark end of edges
if ((psurf^.texinfo^.flags and (SURF_TRANS66 or SURF_TRANS33)) = 0) then
R_RecursiveClipBPoly(pbedge, topnode, psurf)
else
R_RenderBmodelFace(pbedge, psurf);
Inc(Integer(psurf), SizeOf(msurface_t));
end;
end;
(*
================
R_DrawSubmodelPolygons
All in one leaf
================
*)
procedure R_DrawSubmodelPolygons(pmodel: model_p; clipflags: Integer; topnode: mnode_p);
var
i: Integer;
dot: vec_t;
psurf: msurface_p;
numsurfaces: Integer;
pplane: mplane_p;
begin
// FIXME: use bounding-box-based frustum clipping info?
psurf := @msurface_arrp(pmodel^.surfaces)^[pmodel^.firstmodelsurface];
numsurfaces := pmodel^.nummodelsurfaces;
// for (i=0 ; i<numsurfaces ; i++, psurf++)
for I := 0 to numsurfaces - 1 do
begin
// find which side of the node we are on
pplane := psurf^.plane;
dot := DotProduct(modelorg, pplane^.normal) - pplane^.dist;
// draw the polygon
if (((psurf^.flags and SURF_PLANEBACK) <> 0) and (dot < -BACKFACE_EPSILON)) or
(((psurf^.flags and SURF_PLANEBACK) = 0) and (dot > BACKFACE_EPSILON)) then
begin
r_currentkey := mleaf_p(topnode)^.key;
// FIXME: use bounding-box-based frustum clipping info?
R_RenderFace(psurf, clipflags);
end;
Inc(Integer(psurf), SizeOf(msurface_t));
end;
end;
(*
================
R_RecursiveWorldNode
================
*)
procedure R_RecursiveWorldNode(node: mnode_p; clipflags: Integer);
var
i, c, side: Integer;
pindex: PInteger;
acceptpt: vec3_t;
rejectpt: vec3_t;
plane: mplane_p;
surf: msurface_p;
mark: msurface_pp;
d, dot: Single;
pleaf: mleaf_p;
begin
if (node^.contents = CONTENTS_SOLID) then
Exit; // solid
if (node^.visframe <> r_visframecount) then
Exit;
// cull the clipping planes if not trivial accept
// FIXME: the compiler is doing a lousy job of optimizing here; it could be
// twice as fast in ASM
if (clipflags <> 0) then
begin
for I := 0 to 3 do
begin
if ((clipflags and (1 shl i)) = 0) then
continue; // don't need to clip against it
// generate accept and reject points
// FIXME: do with fast look-ups or integer tests based on the sign bit
// of the floating point values
pindex := pfrustum_indexes[i];
rejectpt[0] := node^.minmaxs[PIntegerArray(pindex)^[0]];
rejectpt[1] := node^.minmaxs[PIntegerArray(pindex)^[1]];
rejectpt[2] := node^.minmaxs[PIntegerArray(pindex)^[2]];
d := DotProduct(rejectpt, view_clipplanes[i].normal);
d := d - view_clipplanes[i].dist;
if (d <= 0) then
Exit;
acceptpt[0] := node^.minmaxs[PIntegerArray(pindex)^[3]];
acceptpt[1] := node^.minmaxs[PIntegerArray(pindex)^[4]];
acceptpt[2] := node^.minmaxs[PIntegerArray(pindex)^[5]];
d := DotProduct(acceptpt, view_clipplanes[i].normal);
d := d - view_clipplanes[i].dist;
if (d >= 0) then
clipflags := clipflags and ($FFFFFFFF xor (1 shl i)); // node is entirely on screen
end;
end;
Inc(c_drawnode);
// if a leaf node, draw stuff
if (node^.contents <> -1) then
begin
pleaf := mleaf_p(node);
// check for door connected areas
if (r_newrefdef.areabits <> nil) then
begin
if ((PByteArray(r_newrefdef.areabits)^[pleaf^.area shr 3] and (1 shl (pleaf^.area and 7))) = 0) then
Exit; // not visible
end;
mark := pleaf^.firstmarksurface;
c := pleaf^.nummarksurfaces;
if (c <> 0) then
begin
while (c <> 0) do
begin
(mark^)^.visframe := r_framecount;
Inc(Integer(mark), Sizeof(msurface_p));
Dec(c);
end;
end;
pleaf^.key := r_currentkey;
Inc(r_currentkey); // all bmodels in a leaf share the same key
end
else
begin
// node is just a decision point, so go down the apropriate sides
// find which side of the node we are on
plane := node^.plane;
case (plane^._type) of
PLANE_X:
dot := modelorg[0] - plane^.dist;
PLANE_Y:
dot := modelorg[1] - plane^.dist;
PLANE_Z:
dot := modelorg[2] - plane^.dist;
else
dot := DotProduct(modelorg, plane^.normal) - plane^.dist;
end;
if (dot >= 0.0) then
side := 0
else
side := 1;
// recurse down the children, front side first
R_RecursiveWorldNode(node^.children[side], clipflags);
// draw stuff
c := node^.numsurfaces;
if (c <> 0) then
begin
surf := @msurface_arrp(r_worldmodel^.surfaces)^[node^.firstsurface];
if (dot < -BACKFACE_EPSILON) then
begin
while (c <> 0) do
begin
if (((surf^.flags and SURF_PLANEBACK) <> 0) and (surf^.visframe = r_framecount)) then
begin
R_RenderFace(surf, clipflags);
end;
Inc(Integer(surf), SizeOf(msurface_t));
Dec(c);
end;
end
else
begin
if (dot > BACKFACE_EPSILON) then
begin
while (c <> 0) do
begin
if (((surf^.flags and SURF_PLANEBACK) = 0) and (surf^.visframe = r_framecount)) then
begin
R_RenderFace(surf, clipflags);
end;
Inc(Integer(surf), SizeOf(msurface_t));
Dec(c);
end;
end;
end;
// all surfaces on the same node share the same sequence number
Inc(r_currentkey);
end;
// recurse down the back side
R_RecursiveWorldNode(node^.children[side xor 1], clipflags);
end;
end;
(*
================
R_RenderWorld
================
*)
procedure R_RenderWorld;
begin
if (r_drawworld^.value = 0.0) then
Exit;
if (r_newrefdef.rdflags and RDF_NOWORLDMODEL) <> 0 then
Exit;
c_drawnode := 0;
// auto cycle the world frame for texture animation
r_worldentity.frame := Trunc(r_newrefdef.time * 2);
currententity := @r_worldentity;
VectorCopy(r_origin, modelorg);
currentmodel := r_worldmodel;
r_pcurrentvertbase := currentmodel^.vertexes;
R_RecursiveWorldNode(currentmodel^.nodes, 15);
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -