📄 r_main.pas
字号:
r_cnumsurfs := Trunc(sw_maxsurfs^.value);
if (r_cnumsurfs <= MINSURFACES) then
r_cnumsurfs := MINSURFACES;
if (r_cnumsurfs > NUMSTACKSURFACES) then
begin
surfaces := AllocMem(r_cnumsurfs * sizeof(surf_t));
surface_p := surfaces;
surf_max := surf_p(Integer(surfaces) + (r_cnumsurfs * sizeof(surf_t)));
r_surfsonstack := false;
// surface 0 doesn't really exist; it's just a dummy because index 0
// is used to indicate no edge attached to surface
Dec(Integer(surfaces), SizeOf(surf_t));
R_SurfacePatch;
end
else
begin
r_surfsonstack := true;
end;
r_maxedgesseen := 0;
r_maxsurfsseen := 0;
r_numallocatededges := Trunc(sw_maxedges^.value);
if (r_numallocatededges < MINEDGES) then
r_numallocatededges := MINEDGES;
if (r_numallocatededges <= NUMSTACKEDGES) then
begin
auxedges := nil;
end
else
begin
auxedges := AllocMem(r_numallocatededges * sizeof(edge_t));
end;
end;
(*
===============
R_MarkLeaves
Mark the leaves and nodes that are in the PVS for the current
cluster
===============
*)
procedure R_MarkLeaves;
var
vis: PByte;
node: mnode_p;
i: Integer;
leaf: mleaf_p;
cluster: Integer;
begin
if ((r_oldviewcluster = r_viewcluster) and (r_novis^.value = 0.0) and (r_viewcluster <> -1)) then
Exit;
// development aid to let you run around and see exactly where
// the pvs ends
if (sw_lockpvs^.value <> 0.0) then
Exit;
Inc(r_visframecount);
r_oldviewcluster := r_viewcluster;
if (r_novis^.value <> 0.0) or (r_viewcluster = -1) or (r_worldmodel^.vis = nil) then
begin
// mark everything
for i := 0 to r_worldmodel^.numleafs - 1 do
mleaf_arrp(r_worldmodel^.leafs)^[i].visframe := r_visframecount;
for i := 0 to r_worldmodel^.numnodes - 1 do
mnode_arrp(r_worldmodel^.nodes)^[i].visframe := r_visframecount;
Exit;
end;
vis := Mod_ClusterPVS(r_viewcluster, r_worldmodel);
leaf := r_worldmodel^.leafs;
for I := 0 to r_worldmodel^.numleafs - 1 do
begin
cluster := leaf^.cluster;
if (cluster = -1) then
begin
Inc(Integer(leaf), Sizeof(mleaf_t));
continue;
end;
if (PByteArray(vis)^[cluster shr 3] and (1 shl (cluster and 7))) <> 0 then
begin
node := mnode_p(leaf);
repeat
if (node^.visframe = r_visframecount) then
break;
node^.visframe := r_visframecount;
node := node^.parent;
until (node = nil);
end;
Inc(Cardinal(leaf), Sizeof(mleaf_t));
end;
end;
(*
** R_DrawNullModel
**
** IMPLEMENT THIS!
*)
procedure R_DrawNullModel;
begin
end;
(*
=============
R_DrawEntitiesOnList
=============
*)
procedure R_DrawEntitiesOnList;
var
i: Integer;
translucent_entities: qboolean;
begin
translucent_entities := False;
if (r_drawentities^.value = 0.0) then
Exit;
// all bmodels have already been drawn by the edge list
for I := 0 to r_newrefdef.num_entities - 1 do
begin
currententity := @entity_arrp(r_newrefdef.entities)^[i];
if (currententity^.flags and RF_TRANSLUCENT) <> 0 then
begin
translucent_entities := true;
continue;
end;
if (currententity^.flags and RF_BEAM) <> 0 then
begin
modelorg[0] := -r_origin[0];
modelorg[1] := -r_origin[1];
modelorg[2] := -r_origin[2];
VectorCopy(vec3_origin, r_entorigin);
R_DrawBeam(currententity);
end
else
begin
currentmodel := currententity^.model;
if (currentmodel = nil) then
begin
R_DrawNullModel;
continue;
end;
VectorCopy(vec3_p(@currententity^.origin)^, r_entorigin);
VectorSubtract(r_origin, r_entorigin, modelorg);
case (currentmodel^._type) of
mod_sprite:
R_DrawSprite;
mod_alias:
R_AliasDrawModel;
end;
end
end;
if (not translucent_entities) then
Exit;
for I := 0 to r_newrefdef.num_entities - 1 do
begin
currententity := @entity_arrp(r_newrefdef.entities)^[i];
if ((currententity^.flags and RF_TRANSLUCENT) = 0) then
continue;
if (currententity^.flags and RF_BEAM) <> 0 then
begin
modelorg[0] := -r_origin[0];
modelorg[1] := -r_origin[1];
modelorg[2] := -r_origin[2];
VectorCopy(vec3_origin, r_entorigin);
R_DrawBeam(currententity);
end
else
begin
currentmodel := currententity^.model;
if (currentmodel = nil) then
begin
R_DrawNullModel;
continue;
end;
VectorCopy(vec3_p(@currententity^.origin)^, r_entorigin);
VectorSubtract(r_origin, r_entorigin, modelorg);
case (currentmodel^._type) of
mod_sprite:
R_DrawSprite;
mod_alias:
R_AliasDrawModel;
end;
end;
end;
end;
(*
=============
R_BmodelCheckBBox
=============
*)
function R_BmodelCheckBBox(minmaxs: PSingle): Integer;
var
i: Integer;
pindex: PInteger;
clipflags: Integer;
acceptpt: vec3_t;
rejectpt: vec3_t;
d: Single;
begin
clipflags := 0;
for I := 0 to 4 - 1 do
begin
// 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] := PSingleArray(minmaxs)^[PIntegerArray(pindex)^[0]];
rejectpt[1] := PSingleArray(minmaxs)^[PIntegerArray(pindex)^[1]];
rejectpt[2] := PSingleArray(minmaxs)^[PIntegerArray(pindex)^[2]];
d := DotProduct(rejectpt, view_clipplanes[i].normal);
d := d - view_clipplanes[i].dist;
if (d <= 0) then
begin
Result := BMODEL_FULLY_CLIPPED;
Exit;
end;
acceptpt[0] := PSingleArray(minmaxs)^[PIntegerArray(pindex)^[3 + 0]];
acceptpt[1] := PSingleArray(minmaxs)^[PIntegerArray(pindex)^[3 + 1]];
acceptpt[2] := PSingleArray(minmaxs)^[PIntegerArray(pindex)^[3 + 2]];
d := DotProduct(acceptpt, view_clipplanes[i].normal);
d := d - view_clipplanes[i].dist;
if (d <= 0) then
clipflags := clipflags or (1 shl i);
end;
Result := clipflags;
end;
(*
===================
R_FindTopnode
Find the first node that splits the given box
===================
*)
function R_FindTopnode(var mins: vec3_t; var maxs: vec3_t): mnode_p;
var
splitplane: mplane_p;
sides: Integer;
node: mnode_p;
begin
node := r_worldmodel^.nodes;
while (True) do
begin
if (node^.visframe <> r_visframecount) then
begin
Result := nil; // not visible at all
Exit;
end;
if (node^.contents <> CONTENTS_NODE) then
begin
if (node^.contents <> CONTENTS_SOLID) then
begin
Result := node; // we've reached a non-solid leaf, so it's
Exit; // visible and not BSP clipped
end;
Result := nil; // in solid, so not visible
Exit;
end;
splitplane := node^.plane;
sides := BOX_ON_PLANE_SIDE(mins, maxs, cplane_p(splitplane));
if (sides = 3) then
begin
Result := node; // this is the splitter
Exit;
end;
// not split yet; recurse down the contacted side
if (sides and 1) = 1 then
node := node^.children[0]
else
node := node^.children[1];
end;
end;
(*
=============
RotatedBBox
Returns an axially aligned box that contains the input box at the given rotation
=============
*)
procedure RotatedBBox(var mins: vec3_t; var maxs: vec3_t; var angles: vec3_t; var tmins: vec3_t; var tmaxs: vec3_t);
var
tmp, v: vec3_t;
i, j: Integer;
_forward: vec3_t;
right: vec3_t;
up: vec3_t;
begin
if ((angles[0] = 0.0) and (angles[1] = 0.0) and (angles[2] = 0.0)) then
begin
VectorCopy(mins, tmins);
VectorCopy(maxs, tmaxs);
Exit;
end;
for I := 0 to 2 do
begin
tmins[i] := 99999;
tmaxs[i] := -99999;
end;
AngleVectors(angles, @_forward, @right, @up);
for I := 0 to 7 do
begin
if (i and 1) = 1 then
tmp[0] := mins[0]
else
tmp[0] := maxs[0];
if (i and 2) = 2 then
tmp[1] := mins[1]
else
tmp[1] := maxs[1];
if (i and 4) = 4 then
tmp[2] := mins[2]
else
tmp[2] := maxs[2];
VectorScale(_forward, tmp[0], v);
VectorMA(v, -tmp[1], right, v);
VectorMA(v, tmp[2], up, v);
for j := 0 to 2 do
begin
if (v[j] < tmins[j]) then
tmins[j] := v[j];
if (v[j] > tmaxs[j]) then
tmaxs[j] := v[j];
end;
end;
end;
(*
=============
R_DrawBEntitiesOnList
=============
*)
procedure R_DrawBEntitiesOnList;
var
i, clipflags: Integer;
oldorigin: vec3_t;
mins, maxs: vec3_t;
minmaxs: array[0..6 - 1] of Single;
topnode: mnode_p;
begin
if (r_drawentities^.value = 0.0) then
Exit;
VectorCopy(modelorg, oldorigin);
insubmodel := true;
r_dlightframecount := r_framecount;
for I := 0 to r_newrefdef.num_entities - 1 do
begin
currententity := @entity_arrp(r_newrefdef.entities)^[i];
currentmodel := currententity^.model;
if (currentmodel = nil) then
continue;
if (currentmodel^.nummodelsurfaces = 0) then
continue; // clip brush only
if (currententity^.flags and RF_BEAM) = RF_BEAM then
continue;
if (currentmodel^._type <> mod_brush) then
continue;
// see if the bounding box lets us trivially reject, also sets
// trivial accept status
RotatedBBox(currentmodel^.mins, currentmodel^.maxs, vec3_p(@currententity^.angles)^, mins, maxs);
VectorAdd(mins, vec3_p(@currententity^.origin)^, vec3_p(@minmaxs)^);
VectorAdd(maxs, vec3_p(@currententity^.origin)^, vec3_p(@minmaxs[3])^);
clipflags := R_BmodelCheckBBox(@minmaxs[0]);
if (clipflags = BMODEL_FULLY_CLIPPED) then
continue; // off the edge of the screen
topnode := R_FindTopnode(vec3_p(@minmaxs)^, vec3_p(@minmaxs[3])^);
if (topnode = nil) then
continue; // no part in a visible leaf
VectorCopy(vec3_p(@currententity^.origin)^, r_entorigin);
VectorSubtract(r_origin, r_entorigin, modelorg);
r_pcurrentvertbase := currentmodel^.vertexes;
// FIXME: stop transforming twice
R_RotateBmodel;
// calculate dynamic lighting for bmodel
R_PushDlights(currentmodel);
if (topnode^.contents = CONTENTS_NODE) then
begin
// not a leaf; has to be clipped to the world BSP
r_clipflags := clipflags;
R_DrawSolidClippedSubmodelPolygons(currentmodel, topnode);
end
else
begin
// falls entirely in one leaf, so we just put all the
// edges in the edge list and let 1/z sorting handle
// drawing order
R_DrawSubmodelPolygons(currentmodel, clipflags, topnode);
end;
// put back world rotation and frustum clipping
// FIXME: R_RotateBmodel should just work off base_vxx
VectorCopy(base_vpn, vpn);
VectorCopy(base_vup, vup);
VectorCopy(base_vright, vright);
VectorCopy(oldorigin, modelorg);
R_TransformFrustum;
end;
insubmodel := false;
end;
(*
================
R_EdgeDrawing
================
*)
procedure R_EdgeDrawing;
var
ledges : array[0..(NUMSTACKEDGES+Trunc((CACHE_SIZE-1) / sizeof(edge_t)))] of edge_t;
lsurfs : array[0..(NUMSTACKSURFACES+Trunc((CACHE_SIZE-1) / sizeof(surf_t)))] of surf_t;
begin
(*********
CODEFUSION:
Somewhere in here the walls are not drawn.
**********)
if (r_newrefdef.rdflags and RDF_NOWORLDMODEL) <> 0 then
Exit;
if (auxedges <> nil) then
begin
r_edges := auxedges;
end
else
begin
r_edges := edge_p((Cardinal(@ledges[0])+CACHE_SIZE-1) and (not Cardinal(CACHE_SIZE-1)));
end;
if (r_surfsonstack) then
begin
surfaces := surf_p((Cardinal(@lsurfs[0])+CACHE_SIZE-1) and (not Cardinal(CACHE_SIZE-1)));
surf_max := surf_p(Integer(surfaces)+(r_cnumsurfs*SizeOf(surf_t)));
// surface 0 doesn't really exist; it's just a dummy because index 0
// is used to indicate no edge attached to surface
Dec(Integer(surfaces), Sizeof(surf_t));
R_SurfacePatch;
end;
R_BeginEdgeFrame;
if (r_dspeeds^.value <> 0.0) then
begin
rw_time1 := Sys_Milliseconds;
end;
R_RenderWorld;
if (r_dspeeds^.value <> 0.0) then
begin
rw_time2 := Sys_Milliseconds;
db_time1 := rw_time2;
end;
R_DrawBEntitiesOnList;
if (r_dspeeds^.value <> 0.0) then
begin
db_time2 := Sys_Milliseconds;
se_time1 := db_time2;
end;
R_ScanEdges;
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -