⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cmodel.pas

📁 雷神之锤2(Quake2)Delphi源码
💻 PAS
📖 第 1 页 / 共 4 页
字号:
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 + -