📄 cmodel.pas
字号:
var
i: Integer;
_out: PWord;
_in: PWord;
count: Integer;
begin
//_in = (void *)(cmod_base + l->fileofs);
_in := Pointer(Integer(cmod_base) + l.fileofs);
if (l.filelen mod SizeOf(_in^)) <> 0 then
Com_Error(ERR_DROP, 'MOD_LoadBmodel: funny lump size', []);
count := l.filelen div SizeOf(_in^);
if (count < 1) then
Com_Error(ERR_DROP, 'Map with no planes', []);
// need to save space for box planes
if (count > MAX_MAP_LEAFBRUSHES) then
Com_Error(ERR_DROP, 'Map has too many leafbrushes', []);
_out := @map_leafbrushes;
numleafbrushes := count;
// for ( i=0 ; i<count ; i++, in++, out++)
for i:= 0 to count - 1 do // i++, in++, out++
begin
_out^ := LittleShort(_in^);
Inc(_in);
Inc(_out);
end;
end;
(*
=================
CMod_LoadBrushSides
=================
*)
procedure CMod_LoadBrushSides(l: lump_p);
var
i, j: Integer;
_out: cbrushside_p;
_in: dbrushside_p;
count: Integer;
num: Integer;
begin
//_in = (void *)(cmod_base + l->fileofs);
_in := Pointer(Integer(cmod_base) + l.fileofs);
if (l.filelen mod SizeOf(_in^)) <> 0 then
Com_Error(ERR_DROP, 'MOD_LoadBmodel: funny lump size', []);
count := l.filelen div SizeOf(_in^);
// need to save space for box planes
if (count > MAX_MAP_BRUSHSIDES) then
Com_Error(ERR_DROP, 'Map has too many planes', []);
_out := @map_brushsides;
numbrushsides := count;
// for ( i=0 ; i<count ; i++, in++, out++)
for i:= 0 to count - 1 do // i++, in++, out++
begin
num := LittleShort(_in.planenum);
_out.plane := @map_planes[num];
j := LittleShort(_in.texinfo);
if (j >= numtexinfo) then
Com_Error(ERR_DROP, 'Bad brushside texinfo', []);
_out.surface := @map_surfaces[j];
Inc(_in);
Inc(_out);
end;
end;
(*
=================
CMod_LoadAreas
=================
*)
procedure CMod_LoadAreas(l: lump_p);
var
i: Integer;
_out: carea_p;
_in: darea_p;
count: Integer;
begin
//_in = (void *)(cmod_base + l->fileofs);
_in := Pointer(Integer(cmod_base) + l.fileofs);
if (l.filelen mod SizeOf(_in^)) <> 0 then
Com_Error(ERR_DROP, 'MOD_LoadBmodel: funny lump size', []);
count := l.filelen div SizeOf(_in^);
if (count > MAX_MAP_AREAS) then
Com_Error(ERR_DROP, 'Map has too many areas', []);
_out := @map_areas;
numareas := count;
// for ( i=0 ; i<count ; i++, in++, out++)
for i:= 0 to count - 1 do // i++, in++, out++
begin
_out.numareaportals := LittleLong(_in.numareaportals);
_out.firstareaportal := LittleLong(_in.firstareaportal);
_out.floodvalid := 0;
_out.floodnum := 0;
Inc(_in);
Inc(_out);
end;
end;
(*
=================
CMod_LoadAreaPortals
=================
*)
procedure CMod_LoadAreaPortals(l: lump_p);
var
i: Integer;
_out: dareaportal_p;
_in: dareaportal_p;
count: Integer;
begin
//_in = (void *)(cmod_base + l->fileofs);
_in := Pointer(Integer(cmod_base) + l.fileofs);
if (l.filelen mod SizeOf(_in^)) <> 0 then
Com_Error(ERR_DROP, 'MOD_LoadBmodel: funny lump size', []);
count := l.filelen div SizeOf(_in^);
if (count > MAX_MAP_AREAS) then
Com_Error(ERR_DROP, 'Map has too many areas', []);
_out := @map_areaportals;
numareaportals := count;
// for ( i=0 ; i<count ; i++, in++, out++)
for i:= 0 to count - 1 do // i++, in++, out++
begin
_out.portalnum := LittleLong(_in.portalnum);
_out.otherarea := LittleLong(_in.otherarea);
Inc(_in);
Inc(_out);
end;
end;
(*
=================
CMod_LoadVisibility
=================
*)
procedure CMod_LoadVisibility(l: lump_p);
var
i: Integer;
begin
numvisibility := l.filelen;
if (l.filelen > MAX_MAP_VISIBILITY) then
Com_Error (ERR_DROP, 'Map has too large visibility lump', []);
// memcpy (map_visibility, cmod_base + l->fileofs, l->filelen);
Move(Pointer(Integer(cmod_base) + l.fileofs)^, map_visibility, l.filelen);
map_vis.numclusters := LittleLong(map_vis.numclusters);
for i:= 0 to map_vis.numclusters - 1 do
begin
map_vis.bitofs[i][0] := LittleLong(map_vis.bitofs[i][0]);
map_vis.bitofs[i][1] := LittleLong(map_vis.bitofs[i][1]);
end;
end;
(*
=================
CMod_LoadEntityString
=================
*)
procedure CMod_LoadEntityString(l: lump_p);
begin
numentitychars := l.filelen;
if (l.filelen > MAX_MAP_ENTSTRING) then
Com_Error(ERR_DROP, 'Map has too large entity lump', []);
// memcpy (map_entitystring, cmod_base + l->fileofs, l->filelen);
Move(Pointer(Cardinal(cmod_base) + l.fileofs)^, map_entitystring, l.filelen);
end;
(*
==================
CM_LoadMap
Loads in the map and all submodels
==================
*)
function CM_LoadMap(name: PChar; clientload: qboolean; var checksum: Cardinal): cmodel_p;
{$IFNDEF COMPILER6_UP}
type
PCardinal = ^Cardinal;
{$ENDIF}
var
buf: PCardinal;
i: Integer;
header: dheader_t;
length: Integer;
{$IFDEF COMPILER6_UP}{$WRITEABLECONST ON}{$ENDIF}
const
last_checksum: Cardinal = 0;
{$IFDEF COMPILER6_UP}{$WRITEABLECONST OFF}{$ENDIF}
type
PCardinalArray = ^TCardinalArray;
TCardinalArray = array[0..MaxInt div SizeOf(Cardinal)-1] of Cardinal;
begin
map_noareas := Cvar_Get('map_noareas', '0', 0);
if (strcmp(map_name, name) = 0) and
(clientload or (Cvar_VariableValue('flushmap') = 0)) then
begin
checksum := last_checksum;
if clientload then
begin
FillChar(portalopen, SizeOf(portalopen), 0);
FloodAreaConnections;
end;
Result:= @map_cmodels[0]; // still have the right version
Exit;
end;
// free old stuff
numplanes := 0;
numnodes := 0;
numleafs := 0;
numcmodels := 0;
numvisibility := 0;
numentitychars := 0;
map_entitystring[0] := #0;
map_name[0] := #0;
if (name = nil) or (name[0] = #0) then
begin
numleafs := 1;
numclusters := 1;
numareas := 1;
checksum := 0;
Result:= @map_cmodels[0]; // cinematic servers won't have anything at all
Exit;
end;
//
// load the file
//
length := FS_LoadFile(name, @buf);
if (buf = nil) then
Com_Error(ERR_DROP, 'Couldn''t load %s', [name]);
last_checksum := LittleLong(Com_BlockChecksum(buf, length));
checksum := last_checksum;
header := dheader_p(buf)^;
for i:= 0 to (SizeOf(dheader_t) div 4) - 1 do
PCardinalArray(@header)[i] := LittleLong(PCardinalArray(@header)[i]);
if (header.version <> BSPVERSION) then
Com_Error(ERR_DROP, 'CMod_LoadBrushModel: %s has wrong version number (%d should be %d)',
[name, header.version, BSPVERSION]);
cmod_base := PByte(buf);
// load into heap
CMod_LoadSurfaces(@header.lumps[LUMP_TEXINFO]);
CMod_LoadLeafs(@header.lumps[LUMP_LEAFS]);
CMod_LoadLeafBrushes(@header.lumps[LUMP_LEAFBRUSHES]);
CMod_LoadPlanes(@header.lumps[LUMP_PLANES]);
CMod_LoadBrushes(@header.lumps[LUMP_BRUSHES]);
CMod_LoadBrushSides(@header.lumps[LUMP_BRUSHSIDES]);
CMod_LoadSubmodels(@header.lumps[LUMP_MODELS]);
CMod_LoadNodes(@header.lumps[LUMP_NODES]);
CMod_LoadAreas(@header.lumps[LUMP_AREAS]);
CMod_LoadAreaPortals(@header.lumps[LUMP_AREAPORTALS]);
CMod_LoadVisibility(@header.lumps[LUMP_VISIBILITY]);
CMod_LoadEntityString(@header.lumps[LUMP_ENTITIES]);
FS_FreeFile(buf);
CM_InitBoxHull;
FillChar(portalopen, SizeOf(portalopen), 0);
FloodAreaConnections;
StrCopy(map_name, name);
Result:= @map_cmodels[0];
end;
(*
==================
CM_InlineModel
==================
*)
function CM_InlineModel(name: PChar): cmodel_p;
var
num: Integer;
begin
if (name = nil) or (name[0] <> '*') then
Com_Error(ERR_DROP, 'CM_InlineModel: bad name', []);
try
num := StrToInt(name+1);
except
num:= -1;
end;
if (num < 1) or (num >= numcmodels) then
Com_Error(ERR_DROP, 'CM_InlineModel: bad number', []);
Result := @map_cmodels[num];
end;
function CM_NumClusters: Integer;
begin
Result := numclusters;
end;
function CM_NumInlineModels: Integer;
begin
Result := numcmodels;
end;
function CM_EntityString: PChar;
begin
Result := map_entitystring;
end;
function CM_LeafContents(leafnum: Integer): Integer;
begin
if (leafnum < 0) or (leafnum >= numleafs) then
Com_Error(ERR_DROP, 'CM_LeafContents: bad number', []);
Result := map_leafs[leafnum].contents;
end;
function CM_LeafCluster(leafnum: Integer): Integer;
begin
if (leafnum < 0) or (leafnum >= numleafs) then
Com_Error(ERR_DROP, 'CM_LeafCluster: bad number', []);
Result := map_leafs[leafnum].cluster;
end;
function CM_LeafArea(leafnum: Integer): Integer;
begin
if (leafnum < 0) or (leafnum >= numleafs) then
Com_Error(ERR_DROP, 'CM_LeafArea: bad number', []);
Result := map_leafs[leafnum].area;
end;
//=======================================================================
type
cplane_pa = ^cplane_ta;
cplane_ta = array[0..MaxInt div SizeOf(cplane_t) - 1] of cplane_t;
var
box_planes: cplane_pa;
box_headnode: Integer;
box_brush: cbrush_p;
box_leaf: cleaf_p;
(*
===================
CM_InitBoxHull
Set up the planes and nodes so that the six floats of a bounding box
can just be stored out and get a proper clipping hull structure.
===================
*)
procedure CM_InitBoxHull;
var
i: Integer;
side: Integer;
c: cnode_p;
p: cplane_p;
s: cbrushside_p;
begin
box_headnode := numnodes;
box_planes := @map_planes[numplanes];
if (numnodes+6 > MAX_MAP_NODES) or
(numbrushes+1 > MAX_MAP_BRUSHES) or
(numleafbrushes+1 > MAX_MAP_LEAFBRUSHES) or
(numbrushsides+6 > MAX_MAP_BRUSHSIDES) or
(numplanes+12 > MAX_MAP_PLANES)
then Com_Error(ERR_DROP, 'Not enough room for box tree', []);
box_brush := @map_brushes[numbrushes];
box_brush.numsides := 6;
box_brush.firstbrushside := numbrushsides;
box_brush.contents := CONTENTS_MONSTER;
box_leaf := @map_leafs[numleafs];
box_leaf.contents := CONTENTS_MONSTER;
box_leaf.firstleafbrush := numleafbrushes;
box_leaf.numleafbrushes := 1;
map_leafbrushes[numleafbrushes] := numbrushes;
for i:= 0 to 5 do
begin
side := i and 1;
// brush sides
s := @map_brushsides[numbrushsides+i];
s.plane := @map_planes[numplanes+i*2+side];
s.surface := @nullsurface;
// nodes
c := @map_nodes[box_headnode+i];
c.plane := @map_planes[numplanes+i*2];
c.children[side] := -1 - emptyleaf;
if (i <> 5) then
c.children[side xor 1] := box_headnode+i + 1
else
c.children[side xor 1] := -1 - numleafs;
// planes
p := @box_planes[i*2];
p._type := i shr 1;
p.signbits := 0;
VectorClear(p.normal);
p.normal[i shr 1] := 1;
p := @box_planes[i*2+1];
p._type := 3 + (i shr 1);
p.signbits := 0;
VectorClear(p.normal);
p.normal[i shr 1] := -1;
end;
end;
(*
===================
CM_HeadnodeForBox
To keep everything totally uniform, bounding boxes are turned into small
BSP trees instead of being compared directly.
===================
*)
function CM_HeadnodeForBox(const mins, maxs: vec3_t): Integer;
begin
box_planes[0].dist := maxs[0];
box_planes[1].dist := -maxs[0];
box_planes[2].dist := mins[0];
box_planes[3].dist := -mins[0];
box_planes[4].dist := maxs[1];
box_planes[5].dist := -maxs[1];
box_planes[6].dist := mins[1];
box_planes[7].dist := -mins[1];
box_planes[8].dist := maxs[2];
box_planes[9].dist := -maxs[2];
box_planes[10].dist := mins[2];
box_planes[11].dist := -mins[2];
Result:= box_headnode;
end;
(*
==================
CM_PointLeafnum_r
==================
*)
function CM_PointLeafnum_r(const p: vec3_t; num: Integer): Integer;
var
d: Single;
node: cnode_p;
plane: cplane_p;
begin
while (num >= 0) do
begin
node := @map_nodes[num];
plane := node.plane;
if (plane._type < 3) then
d := p[plane._type] - plane.dist
else
d := DotProduct(plane.normal, p) - plane.dist;
if (d < 0) then
num := node.children[1]
else
num := node.children[0];
end;
Inc(c_pointcontents); // optimize counter
Result:= -1 - num;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -