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

📄 cmodel.pas

📁 雷神之锤2(Quake2)Delphi源码
💻 PAS
📖 第 1 页 / 共 4 页
字号:
{----------------------------------------------------------------------------}
{                                                                            }
{ File(s): QCommon.h (part), PMove.c                                         }
{ Content: Quake2\QCommon\ model loading                                     }
{                                                                            }
{ Initial conversion by : Clootie (Alexey Barkovoy) - clootie@reactor.ru     }
{ Initial conversion on : 03-Mar-2002                                        }
{                                                                            }
{ This File contains part of convertion of Quake2 source to ObjectPascal.    }
{ More information about this project can be found at:                       }
{ http://www.sulaco.co.za/quake2/                                            }
{                                                                            }
{ Copyright (C) 1997-2001 Id Software, Inc.                                  }
{                                                                            }
{ This program is free software; you can redistribute it and/or              }
{ modify it under the terms of the GNU General Public License                }
{ as published by the Free Software Foundation; either version 2             }
{ of the License, or (at your option) any later version.                     }
{                                                                            }
{ This program is distributed in the hope that it will be useful,            }
{ but WITHOUT ANY WARRANTY; without even the implied warranty of             }
{ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                       }
{                                                                            }
{ See the GNU General Public License for more details.                       }
{                                                                            }
{----------------------------------------------------------------------------}
{ * Updated:                                                                 }
{ 06-jun-2002 Juha Hartikainen (juha@linearteam.org) }
{ - Changed file handling to use SysUtils style of file handling }
{----------------------------------------------------------------------------}
{ * TODO:                                                                    }
{----------------------------------------------------------------------------}

{$Include ..\JEDI.inc}

unit CModel;

interface

uses
  QFiles,
  q_shared,
  SysUtils,
  Windows;

// cmodel.c -- model loading

function CM_LoadMap(name: PChar; clientload: qboolean; var checksum: Cardinal): cmodel_p;
function CM_InlineModel(name: PChar): cmodel_p; // *1, *2, etc

function CM_NumClusters: Integer;
function CM_NumInlineModels: Integer;
function CM_EntityString: PChar;

// creates a clipping hull for an arbitrary box
function CM_HeadnodeForBox(const mins, maxs: vec3_t): Integer;


// returns an ORed contents mask
function CM_PointContents(const p: vec3_t; headnode: Integer): Integer;
function CM_TransformedPointContents(const p: vec3_t; headnode: Integer;
  const origin, angles: vec3_t): Integer;

function CM_BoxTrace(const start, _end, mins, maxs: vec3_t;
  headnode, brushmask: Integer): trace_t;
function CM_TransformedBoxTrace(const start, _end, mins, maxs: vec3_t;
  headnode, brushmask: Integer; const origin, angles: vec3_t): trace_t;

function CM_ClusterPVS(cluster: Integer): PByte;
function CM_ClusterPHS(cluster: Integer): PByte;

function CM_PointLeafnum(p: vec3_p): Integer;

// call with topnode set to the headnode, returns with topnode
// set to the first node that splits the box
function CM_BoxLeafnums(var mins, maxs: vec3_t; list: PInteger;
  listsize: Integer; topnode: PInteger): Integer;

function CM_LeafContents(leafnum: Integer): Integer;
function CM_LeafCluster(leafnum: Integer): Integer;
function CM_LeafArea(leafnum: Integer): Integer;

procedure CM_SetAreaPortalState(portalnum: Integer; open: qboolean); cdecl;
function CM_AreasConnected(area1, area2: Integer): qboolean; cdecl;

function CM_WriteAreaBits(buffer: PByte; area: Integer): Integer;
function CM_HeadnodeVisible(nodenum: Integer; visbits: PByteArray): qboolean;

procedure CM_WritePortalState(var file_: integer); // (FILE *f);
procedure CM_ReadPortalState(var file_: integer); // (FILE *f);

var
  numtexinfo: Integer;
  map_surfaces: array[0..MAX_MAP_TEXINFO-1] of mapsurface_t;
  c_pointcontents: Integer;
  c_traces, c_brush_traces: Integer;

implementation

uses
  Common,
  CPas,
  CVar,
  Files,
  MD4;

type
  cnode_p = ^cnode_t;
  cnode_t = record
    plane       : cplane_p;
    children    : array[0..1] of Integer;	// negative numbers are leafs
  end;

  cbrushside_p = ^cbrushside_t;
  cbrushside_t = record
    plane       : cplane_p;
    surface     : mapsurface_p;
  end;

  cleaf_p = ^cleaf_t;
  cleaf_t = record
    contents    : Integer;
    cluster     : Integer;
    area        : Integer;
    firstleafbrush: Word;
    numleafbrushes: Word;
  end;

  cbrush_p = ^cbrush_t;
  cbrush_t = record
    contents    : Integer;
    numsides    : Integer;
    firstbrushside: Integer;
    checkcount  : Integer;	// to avoid repeated testings
  end;

  carea_p = ^carea_t;
  carea_t = record
    numareaportals      : Integer;
    firstareaportal     : Integer;
    floodnum            : Integer; // if two areas have equal floodnums, they are connected
    floodvalid          : Integer;
  end;

var
  checkcount: Integer;

  map_name: array[0..MAX_QPATH-1] of Char;

  numbrushsides: Integer;
  map_brushsides: array[0..MAX_MAP_BRUSHSIDES-1] of cbrushside_t;

  numplanes: Integer;
  map_planes: array[0..MAX_MAP_PLANES+6-1] of cplane_t;	// extra for box hull

  numnodes: Integer;
  map_nodes: array[0..MAX_MAP_NODES+6-1] of cnode_t;	// extra for box hull

  numleafs: Integer = 1;	// allow leaf funcs to be called without a map
  map_leafs: array[0..MAX_MAP_LEAFS-1] of cleaf_t;
  emptyleaf, solidleaf: Integer;


  numleafbrushes: Integer;
  map_leafbrushes: array[0..MAX_MAP_LEAFBRUSHES-1] of Word;

  numcmodels: Integer;
  map_cmodels: array[0..MAX_MAP_MODELS-1] of cmodel_t;

  numbrushes: Integer;
  map_brushes: array[0..MAX_MAP_BRUSHES-1] of cbrush_t;

  numvisibility: Integer;
  map_visibility: array[0..MAX_MAP_VISIBILITY-1] of Byte;
  map_vis: dvis_p = @map_visibility;

  numentitychars: Integer;
  map_entitystring: array[0..MAX_MAP_ENTSTRING-1] of Char;

  numareas: Integer = 1;
  map_areas: array[0..MAX_MAP_AREAS-1] of carea_t;

  numareaportals: Integer;

  map_areaportals: array[0..MAX_MAP_AREAPORTALS-1] of dareaportal_t;

  numclusters: Integer = 1;

  nullsurface: mapsurface_t;

  floodvalid: Integer;

  portalopen: array[0..MAX_MAP_AREAPORTALS-1] of qboolean;


  map_noareas: cvar_p;

procedure CM_InitBoxHull; forward;
procedure FloodAreaConnections; forward;




(*
===============================================================================

					MAP LOADING

===============================================================================
*)

var
  cmod_base: PByte;

(*
=================
CMod_LoadSubmodels
=================
*)
procedure CMod_LoadSubmodels(l: lump_p);
var
  _in: dmodel_p;
  _out: cmodel_p;
  i, j, 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 models', []);
  if (count > MAX_MAP_MODELS) then
    Com_Error(ERR_DROP, 'Map has too many models', []);

  numcmodels := count;

  // for ( i=0 ; i<count ; i++, in++, out++)
  for i:= 0 to count - 1 do // i++, in++, out++
  begin
    _out := @map_cmodels[i];

    for j:= 0 to 2 do
    begin // spread the mins / maxs by a pixel
      _out.mins[j] := LittleFloat(_in.mins[j]) - 1;
      _out.maxs[j] := LittleFloat(_in.maxs[j]) + 1;
      _out.origin[j] := LittleFloat(_in.origin[j]);
    end;
    _out.headnode := LittleLong(_in.headnode);
    Inc(_in);
    // Inc(_out); //Clootie: - never used 
  end;
end;


(*
=================
CMod_LoadSurfaces
=================
*)
procedure CMod_LoadSurfaces(l: lump_p);
var
  _in: texinfo_p;
  _out: mapsurface_p;
  i, 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 surfaces', []);
  if (count > MAX_MAP_TEXINFO) then
    Com_Error(ERR_DROP, 'Map has too many surfaces', []);

  numtexinfo := count;
  _out := @map_surfaces;

  // for ( i=0 ; i<count ; i++, in++, out++)
  for i:= 0 to count - 1 do // i++, in++, out++
  begin
    strncpy(_out.c.name, _in.texture, SizeOf(_out.c.name)-1);
    strncpy(_out.rname, _in.texture, SizeOf(_out.rname)-1);
    _out.c.flags := LittleLong(_in.flags);
    _out.c.value := LittleLong(_in.value);
    Inc(_in);
    Inc(_out);
  end;
end;


(*
=================
CMod_LoadNodes

=================
*)
procedure CMod_LoadNodes(l: lump_p);
var
  _in: dnode_p;
  child: Integer;
  _out: cnode_p;
  i, j, 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 has no nodes', []);
  if (count > MAX_MAP_NODES) then
    Com_Error(ERR_DROP, 'Map has too many nodes', []);

  _out := @map_nodes;

  numnodes := count;

  // for ( i=0 ; i<count ; i++, in++, out++)
  for i:= 0 to count - 1 do // i++, in++, out++
  begin
    _out.plane := @map_planes[LittleLong(_in.planenum)];
    for j:= 0 to 1 do
    begin
      child := LittleLong(_in.children[j]);
      _out.children[j] := child;
    end;
    Inc(_in);
    Inc(_out);
  end;

end;

(*
=================
CMod_LoadBrushes

=================
*)
procedure CMod_LoadBrushes(l: lump_p);
var
  _in: dbrush_p;
  _out: cbrush_p;
  i, 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_BRUSHES) then
    Com_Error(ERR_DROP, 'Map has too many brushes', []);

  _out := @map_brushes;

  numbrushes := count;

  // for ( i=0 ; i<count ; i++, in++, out++)
  for i:= 0 to count - 1 do // i++, in++, out++
  begin
    _out.firstbrushside := LittleLong(_in.firstside);
    _out.numsides := LittleLong(_in.numsides);
    _out.contents := LittleLong(_in.contents);
    Inc(_in);
    Inc(_out);
  end;

end;

(*
=================
CMod_LoadLeafs
=================
*)
procedure CMod_LoadLeafs(l: lump_p);
var
  i: Integer;
  _out: cleaf_p;
  _in: dleaf_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 < 1) then
    Com_Error(ERR_DROP, 'Map with no leafs', []);
  // need to save space for box planes
  if (count > MAX_MAP_PLANES) then
    Com_Error(ERR_DROP, 'Map has too many planes', []);

  _out := @map_leafs;
  numleafs := count;
  numclusters := 0;

  // for ( i=0 ; i<count ; i++, in++, out++)
  for i:= 0 to count - 1 do // i++, in++, out++
  begin
    _out.contents := LittleLong (_in.contents);
    _out.cluster := LittleShort (_in.cluster);
    _out.area := LittleShort (_in.area);
    _out.firstleafbrush := LittleShort (_in.firstleafbrush);
    _out.numleafbrushes := LittleShort (_in.numleafbrushes);

    if (_out.cluster >= numclusters) then
      numclusters := _out.cluster + 1;
    Inc(_in);
    Inc(_out);
  end;

  if (map_leafs[0].contents <> CONTENTS_SOLID) then
    Com_Error(ERR_DROP, 'Map leaf 0 is not CONTENTS_SOLID', []);
  solidleaf := 0;
  emptyleaf := -1;
  for i:= 1 to numleafs - 1 do
  begin
    if (map_leafs[i].contents = 0) then
    begin
      emptyleaf := i;
      Break;
    end;
  end;
  if (emptyleaf = -1) then
    Com_Error(ERR_DROP, 'Map does not have an empty leaf', []);
end;

(*
=================
CMod_LoadPlanes
=================
*)
procedure CMod_LoadPlanes(l: lump_p);
var
  i, j: Integer;
  _out: cplane_p;
  _in: dplane_p;
  count: Integer;
  bits: 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_PLANES) then
    Com_Error(ERR_DROP, 'Map has too many planes', []);

  _out := @map_planes;
  numplanes := count;

  // for ( i=0 ; i<count ; i++, in++, out++)
  for i:= 0 to count - 1 do // i++, in++, out++
  begin
    bits := 0;
    for j:= 0 to 2 do
    begin
      _out.normal[j] := LittleFloat(_in.normal[j]);
      if (_out.normal[j] < 0) then
        bits := bits or (1 shl j);
    end;

    _out.dist := LittleFloat(_in.dist);
    _out._type := LittleLong(_in._type);
    _out.signbits := bits;
    Inc(_in);
    Inc(_out);
  end;
end;

(*
=================
CMod_LoadLeafBrushes
=================
*)
procedure CMod_LoadLeafBrushes(l: lump_p);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -