📄 r_misc.pas
字号:
Called every time the vid structure or r_refdef changes.
Guaranteed to be called before the first refresh
===============
*)
procedure R_ViewChanged(vr: vrect_p);
var
i: Integer;
begin
r_refdef.vrect := vr^;
r_refdef.horizontalFieldOfView := 2 * tan(r_newrefdef.fov_x / 360 * M_PI);
verticalFieldOfView := 2 * tan(r_newrefdef.fov_y / 360 * M_PI);
r_refdef.fvrectx := r_refdef.vrect.x;
r_refdef.fvrectx_adj := r_refdef.vrect.x - 0.5;
r_refdef.vrect_x_adj_shift20 := (r_refdef.vrect.x shl 20) + (1 shl 19) - 1;
r_refdef.fvrecty := r_refdef.vrect.y;
r_refdef.fvrecty_adj := r_refdef.vrect.y - 0.5;
r_refdef.vrectright := r_refdef.vrect.x + r_refdef.vrect.width;
r_refdef.vrectright_adj_shift20 := (r_refdef.vrectright shl 20) + (1 shl 19) - 1;
r_refdef.fvrectright := r_refdef.vrectright;
r_refdef.fvrectright_adj := r_refdef.vrectright - 0.5;
r_refdef.vrectrightedge := r_refdef.vrectright - 0.99;
r_refdef.vrectbottom := r_refdef.vrect.y + r_refdef.vrect.height;
r_refdef.fvrectbottom := r_refdef.vrectbottom;
r_refdef.fvrectbottom_adj := r_refdef.vrectbottom - 0.5;
r_refdef.aliasvrect.x := Trunc(r_refdef.vrect.x * r_aliasuvscale);
r_refdef.aliasvrect.y := Trunc(r_refdef.vrect.y * r_aliasuvscale);
r_refdef.aliasvrect.width := Trunc(r_refdef.vrect.width * r_aliasuvscale);
r_refdef.aliasvrect.height := Trunc(r_refdef.vrect.height * r_aliasuvscale);
r_refdef.aliasvrectright := r_refdef.aliasvrect.x + r_refdef.aliasvrect.width;
r_refdef.aliasvrectbottom := r_refdef.aliasvrect.y + r_refdef.aliasvrect.height;
xOrigin := r_refdef.xOrigin;
yOrigin := r_refdef.yOrigin;
// values for perspective projection
// if math were exact, the values would range from 0.5 to to range+0.5
// hopefully they wll be in the 0.000001 to range+.999999 and truncate
// the polygon rasterization will never render in the first row or column
// but will definately render in the [range] row and column, so adjust the
// buffer origin to get an exact edge to edge fill
xcenter := (r_refdef.vrect.width * XCENTERING) + r_refdef.vrect.x - 0.5;
aliasxcenter := xcenter * r_aliasuvscale;
ycenter := (r_refdef.vrect.height * YCENTERING) + r_refdef.vrect.y - 0.5;
aliasycenter := ycenter * r_aliasuvscale;
xscale := r_refdef.vrect.width / r_refdef.horizontalFieldOfView;
aliasxscale := xscale * r_aliasuvscale;
xscaleinv := 1.0 / xscale;
yscale := xscale;
aliasyscale := yscale * r_aliasuvscale;
yscaleinv := 1.0 / yscale;
xscaleshrink := (r_refdef.vrect.width - 6) / r_refdef.horizontalFieldOfView;
yscaleshrink := xscaleshrink;
// left side clip
screenedge[0].normal[0] := -1.0 / (xOrigin * r_refdef.horizontalFieldOfView);
screenedge[0].normal[1] := 0;
screenedge[0].normal[2] := 1;
screenedge[0]._type := PLANE_ANYZ;
// right side clip
screenedge[1].normal[0] := 1.0 / ((1.0 - xOrigin) * r_refdef.horizontalFieldOfView);
screenedge[1].normal[1] := 0;
screenedge[1].normal[2] := 1;
screenedge[1]._type := PLANE_ANYZ;
// top side clip
screenedge[2].normal[0] := 0;
screenedge[2].normal[1] := -1.0 / (yOrigin * verticalFieldOfView);
screenedge[2].normal[2] := 1;
screenedge[2]._type := PLANE_ANYZ;
// bottom side clip
screenedge[3].normal[0] := 0;
screenedge[3].normal[1] := 1.0 / ((1.0 - yOrigin) * verticalFieldOfView);
screenedge[3].normal[2] := 1;
screenedge[3]._type := PLANE_ANYZ;
for i := 0 to 3 do
VectorNormalize(screenedge[i].normal);
D_ViewChanged;
end;
(*
===============
R_SetupFrame
===============
*)
procedure R_SetupFrame;
var
i: Integer;
vrect: vrect_t;
begin
if (r_fullbright^.modified) then
begin
r_fullbright^.modified := false;
D_FlushCaches; // so all lighting changes
end;
Inc(r_framecount);
// build the transformation matrix for the given view angles
VectorCopy(r_refdef.vieworg, modelorg);
VectorCopy(r_refdef.vieworg, r_origin);
AngleVectors(r_refdef.viewangles, @vpn, @vright, @vup);
// current viewleaf
if ((r_newrefdef.rdflags and RDF_NOWORLDMODEL) = 0) then
begin
r_viewleaf := Mod_PointInLeaf(r_origin, r_worldmodel);
r_viewcluster := r_viewleaf^.cluster;
end;
if ((sw_waterwarp^.value <> 0) and ((r_newrefdef.rdflags and RDF_UNDERWATER) <> 0)) then
r_dowarp := true
else
r_dowarp := false;
if (r_dowarp) then
begin // warp into off screen buffer
vrect.x := 0;
vrect.y := 0;
if r_newrefdef.width < WARP_WIDTH then
vrect.width := r_newrefdef.width
else
vrect.width := WARP_WIDTH;
if r_newrefdef.height < WARP_HEIGHT then
vrect.height := r_newrefdef.height
else
vrect.height := WARP_HEIGHT;
d_viewbuffer := @r_warpbuffer;
r_screenwidth := WARP_WIDTH;
end
else
begin
vrect.x := r_newrefdef.x;
vrect.y := r_newrefdef.y;
vrect.width := r_newrefdef.width;
vrect.height := r_newrefdef.height;
d_viewbuffer := vid.buffer;
r_screenwidth := vid.rowbytes;
end;
R_ViewChanged(@vrect);
// start off with just the four screen edge clip planes
R_TransformFrustum;
R_SetUpFrustumIndexes;
// save base values
VectorCopy(vpn, base_vpn);
VectorCopy(vright, base_vright);
VectorCopy(vup, base_vup);
// clear frame counts
c_faceclip := 0;
d_spanpixcount := 0;
r_polycount := 0;
r_drawnpolycount := 0;
r_wholepolycount := 0;
r_amodels_drawn := 0;
r_outofsurfaces := 0;
r_outofedges := 0;
// d_setup
d_roverwrapped := false;
d_initial_rover := sc_rover;
d_minmip := Trunc(sw_mipcap^.value);
if (d_minmip > 3) then
d_minmip := 3
else
if (d_minmip < 0) then
d_minmip := 0;
for I := 0 to NUM_MIPS - 2 do
d_scalemip[i] := basemip[i] * sw_mipscale^.value;
d_aflatcolor := 0;
end;
{$IFNDEF id386}
(*
================
R_SurfacePatch
================
*)
procedure R_SurfacePatch;
begin
// we only patch code on Intel
end;
{$ENDIF}
(*
==============================================================================
SCREEN SHOTS
==============================================================================
*)
(*
==============
WritePCXfile
==============
*)
procedure WritePCXfile(filename: PChar; data: PByte; width, height,
rowbytes: Integer; palette: PByte);
var
i, j, length: Integer;
pcx: pcx_p;
pack: PByte;
f: Integer; // was File;
begin
//pcx := AllocMem(width*height*2+1000);
pcx := pcx_p(malloc(width * height * 2 + 1000)); // changed by fab
if (pcx = nil) then
Exit;
pcx^.manufacturer := #$0A; // PCX id
pcx^.version := #5; // 256 color
pcx^.encoding := #1; // uncompressed
pcx^.bits_per_pixel := #8; // 256 color
pcx^.xmin := 0;
pcx^.ymin := 0;
pcx^.xmax := LittleShort(width - 1);
pcx^.ymax := LittleShort(height - 1);
pcx^.hres := LittleShort(width);
pcx^.vres := LittleShort(height);
//FillChar(pcx^.palette,SizeOf(pcx^.palette),0);
memset(@pcx^.palette, 0, SizeOf(pcx^.palette)); //changed by fab
pcx^.color_planes := 1; // chunky image
pcx^.bytes_per_line := LittleShort(width);
pcx^.palette_type := LittleShort(2); // not a grey scale
//FillChar(pcx^.filler,SizeOf(pcx^.filler),0);
memset(@pcx^.filler, 0, SizeOf(pcx^.filler)); //changed by fab
// pack the image
pack := @pcx^.data;
for I := 0 to height - 1 do
begin
for j := 0 to width - 1 do
begin
if ((data^ and $C0) <> $C0) then
begin
pack^ := data^;
Inc(Integer(pack));
Inc(Integer(data));
end
else
begin
pack^ := $C1;
Inc(Integer(pack));
pack^ := data^;
Inc(Integer(pack));
Inc(Integer(data));
end;
end;
Inc(Integer(data), rowbytes - width);
end;
// write the palette
pack^ := $0C; // palette ID byte
Inc(Integer(pack));
for i := 0 to 768 - 1 do
begin
pack^ := palette^;
Inc(Integer(pack));
Inc(Integer(palette));
end;
// write output file
length := Integer(pack) - Integer(pcx);
f := FileCreate(filename);
if f < 0 then
ri.Con_Printf(PRINT_ALL, 'Failed to create %s'#10, filename) //changed by Fab
else
begin
FileWrite(f, pcx^, length);
FileClose(f);
end;
FreeMem(pcx);
end;
procedure R_ScreenShot_f; cdecl;
var
i: integer;
pcxname: array[0..80 - 1] of Char;
checkname: array[0..MAX_OSPATH - 1] of Char;
palette: array[0..768 - 1] of Byte;
f: Integer;
begin
// create the scrnshots directory if it doesn't exist
Com_sprintf(checkname, SizeOf(checkname), '%s/scrnshot', [ri.FS_Gamedir]);
MkDir(checkname);
//
// find a file name to save it to
//
strcpy(pcxname, 'quake00.pcx');
for i := 0 to 99 do
begin
pcxname[5] := Char(i div 10 + Byte('0'));
pcxname[6] := Char(i mod 10 + Byte('0'));
Com_sprintf(checkname, sizeof(checkname), '%s/scrnshot/%s', [ri.FS_Gamedir, pcxname]);
f := fileOpen(checkname, fmOpenRead);
if f < 0 then
Break; // file doesn't exist
Fileclose(f);
end;
if i = 100 then
begin
ri.Con_Printf(PRINT_ALL, 'R_ScreenShot_f: Couldn''t create a PCX'#10);
exit;
end;
// turn the current 32 bit palette into a 24 bit palette
for i := 0 to 255 do
begin
palette[i * 3 + 0] := sw_state.currentpalette[i * 4 + 0];
palette[i * 3 + 1] := sw_state.currentpalette[i * 4 + 1];
palette[i * 3 + 2] := sw_state.currentpalette[i * 4 + 2];
end;
//
// save the pcx file
//
WritePCXfile(checkname, vid.buffer, vid.width, vid.height, vid.rowbytes, @palette);
ri.Con_Printf(PRINT_ALL, 'Wrote %s'#10, checkname);
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -