📄 gl_model.cpp
字号:
//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// Purpose:
//
// $Workfile: $
// $Date: $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================
// gl_model.cpp -- model loading and caching
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include "qfiles.h"
#include "mathlib.h"
#include "gl_model.h"
#include "cmdlib.h"
#include "map_entity.h"
#include "gl_image.h"
#include "engine.h"
#pragma warning(disable : 4244) // float->double
char *wadpath = NULL; // Path of wad files associated with current BSP
void Mod_LoadMap( void *buffer );
model_t *Mod_LoadModel( model_t *mod, qboolean crash );
// JAY: Later
#if 0
void Mod_LoadSpriteModel( model_t *mod, void *buffer );
#endif
#define MAX_MOD_KNOWN 512
model_t mod_known[MAX_MOD_KNOWN];
int mod_numknown;
// the inline * models from the current map are kept seperate
model_t mod_inline[MAX_MOD_KNOWN];
byte mod_novis[MAX_MAP_LEAFS/8];
/*
===============
Mod_PointInLeaf
===============
*/
mleaf_t *Mod_PointInLeaf (Vector& p, model_t *model)
{
mnode_t *node;
float d;
cplane_t *plane;
if (!model || !model->nodes)
engine.Error( "Mod_PointInLeaf: bad model" );
node = model->nodes;
while (1)
{
if (node->contents != -1)
return (mleaf_t *)node;
plane = node->plane;
d = DotProduct( p, plane->normal ) - plane->dist;
if (d > 0)
node = node->children[0];
else
node = node->children[1];
}
return NULL; // never reached
}
/*
===================
Mod_DecompressVis
===================
*/
byte *Mod_DecompressVis (byte *in, model_t *model)
{
static byte decompressed[MAX_MAP_LEAFS/8];
int c;
byte *out;
int row;
row = (model->vis->numclusters+7)>>3;
out = decompressed;
if (!in)
{ // no vis info, so make all visible
while (row)
{
*out++ = 0xff;
row--;
}
return decompressed;
}
do
{
if (*in)
{
*out++ = *in++;
continue;
}
c = in[1];
in += 2;
while (c)
{
*out++ = 0;
c--;
}
} while (out - decompressed < row);
return decompressed;
}
/*
==============
Mod_ClusterPVS
==============
*/
byte *Mod_ClusterPVS (int cluster, model_t *model)
{
if (cluster == -1 || !model->vis)
return mod_novis;
return Mod_DecompressVis ( (byte *)model->vis + model->vis->bitofs[cluster][DVIS_PVS],
model);
}
//===============================================================================
#if 0
/*
================
Mod_Modellist_f
================
*/
void Mod_Modellist_f (void)
{
int i;
model_t *mod;
int total;
total = 0;
engine.Con_Printf( PRINT_ALL,"Loaded models:\n");
for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++)
{
if (!mod->name[0])
continue;
engine.Con_Printf( PRINT_ALL, "%8i : %s\n",mod->extradatasize, mod->name );
total += mod->extradatasize;
}
engine.Con_Printf( PRINT_ALL, "Total resident: %i\n", total );
}
#endif
/*
===============
Mod_Init
===============
*/
void Mod_Init (void)
{
memset (mod_novis, 0xff, sizeof(mod_novis));
}
/*
==================
Mod_ForName
Loads in a model for the given name
==================
*/
model_t *Mod_ForName (char *name, qboolean crash)
{
model_t *mod;
// unsigned *buf;
int i;
if (!name[0])
engine.Error("Mod_ForName: NULL name");
//
// inline models are grabbed only from worldmodel
//
if (name[0] == '*')
{
i = atoi(name+1);
if (i < 1 || !r_worldmodel || i >= r_worldmodel->numsubmodels)
engine.Error ("bad inline model number");
return &mod_inline[i];
}
//
// search the currently loaded models
//
for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
{
if (!mod->name[0])
continue;
if (!strcmp (mod->name, name) )
return mod;
}
//
// find a free model slot spot
//
for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
{
if (!mod->name[0])
break; // free spot
}
if (i == mod_numknown)
{
if (mod_numknown == MAX_MOD_KNOWN)
engine.Error ("mod_numknown == MAX_MOD_KNOWN");
mod_numknown++;
}
strcpy (mod->name, name);
#if 0
//
// load the file
//
modfilelen = ri.FS_LoadFile (mod->name, &buf);
if (!buf)
{
if (crash)
engine.Error ("Mod_NumForName: %s not found", mod->name);
memset (mod->name, 0, sizeof(mod->name));
return NULL;
}
loadmodel = mod;
//
// fill it in
//
// call the apropriate loader
switch (LittleLong(*(unsigned *)buf))
{
case IDALIASHEADER:
loadmodel->extradata = Hunk_Begin (0x200000);
Mod_LoadAliasModel (mod, buf);
break;
case IDSPRITEHEADER:
loadmodel->extradata = Hunk_Begin (0x10000);
Mod_LoadSpriteModel (mod, buf);
break;
case IDBSPHEADER:
engine.Error( "Can't load a BSP model (%s)!\n", mod->name );
break;
default:
engine.Error ("Mod_NumForName: unknown fileid for %s", mod->name);
break;
}
loadmodel->extradatasize = Hunk_End ();
ri.FS_FreeFile (buf);
#endif
return mod;
}
/*
===============================================================================
BRUSHMODEL LOADING
===============================================================================
*/
byte *mod_base;
/*
=================
Mod_LoadLighting
=================
*/
void Mod_LoadLighting( model_t *loadmodel, lump_t *l )
{
if (!l->filelen)
{
loadmodel->lightdata = NULL;
return;
}
loadmodel->lightdata = (colorRGBExp32 *)engine.MemAlloc( l->filelen );
memcpy (loadmodel->lightdata, mod_base + l->fileofs, l->filelen);
}
/*
=================
Mod_LoadWorldlights
=================
*/
void Mod_LoadWorldlights( model_t *loadmodel, lump_t *l )
{
#if 0
int i;
int vissize;
byte *plightvis;
#endif
if (!l->filelen)
{
loadmodel->numworldlights = 0;
loadmodel->worldlights = NULL;
return;
}
loadmodel->numworldlights = l->filelen / sizeof( dworldlight_t );
loadmodel->worldlights = (dworldlight_t *)engine.MemAlloc( l->filelen );
memcpy (loadmodel->worldlights, mod_base + l->fileofs, l->filelen);
#if 0
// preexpand vis data
vissize = (loadmodel->numleafs + 7) / 8;
loadmodel->worldlightvis = (byte *)Hunk_AllocName( loadmodel->numworldlights * vissize, loadname );
plightvis = loadmodel->worldlightvis;
for (i = 0; i < loadmodel->numworldlights; i++)
{
byte *vis = Mod_LeafPVS( &loadmodel->leafs[loadmodel->worldlights[i].leaf], loadmodel );
memcpy( plightvis, vis, (loadmodel->numleafs + 7) / 8 );
plightvis += vissize;
}
#endif
}
struct MapEntities_t
{
int count;
mapentity_t list[ MAX_MAP_ENTITIES ];
} g_MapEntities;
void StripTrailing (char *e)
{
char *s;
s = e + strlen(e)-1;
while (s >= e && *s <= 32)
{
*s = 0;
s--;
}
}
/*
=================
ParseEpair
=================
*/
char *ParseKeypair( char *pString, mapentity_t *pEntity )
{
keypair_t *e;
e = (keypair_t *)malloc (sizeof(epair_t));
memset (e, 0, sizeof(epair_t));
StripTrailing (com_token);
if (strlen(com_token) >= MAX_KEY-1)
return NULL;
e->key = strdup(com_token);
pString = COM_Parse(pString);
// strip trailing spaces
StripTrailing (com_token);
if (strlen(com_token) >= MAX_VALUE-1)
return NULL;
e->value = strdup(com_token);
// link it in
e->next = pEntity->pKeyValues;
pEntity->pKeyValues = e;
return pString;
}
/*
================
ParseEntity
================
*/
char *ParseEntity( char *pString )
{
mapentity_t *mapent;
if (! (pString = COM_Parse(pString)) )
return NULL;
if (strcmp (com_token, "{") )
return NULL;
if (g_MapEntities.count == MAX_MAP_ENTITIES)
Error ("g_MapEntities.count == MAX_MAP_ENTITIES");
mapent = g_MapEntities.list + g_MapEntities.count;
g_MapEntities.count++;
do
{
pString = COM_Parse( pString );
if ( !pString )
return NULL;
if (!strcmp (com_token, "}") )
break;
pString = ParseKeypair( pString, mapent );
if ( mapent->pKeyValues )
{
if ( !strcmp(mapent->pKeyValues->key, "classname") )
{
mapent->pClassName = mapent->pKeyValues->value;
}
else if ( !strcmp( mapent->pKeyValues->key, "origin") )
{
sscanf( mapent->pKeyValues->value, "%f %f %f", &mapent->origin[0], &mapent->origin[1], &mapent->origin[2] );
}
else if ( !strcmp( mapent->pKeyValues->key, "angles") )
{
sscanf( mapent->pKeyValues->value, "%f %f %f", &mapent->angles[0], &mapent->angles[1], &mapent->angles[2] );
}
else if ( !strcmp(mapent->pKeyValues->key, "model") )
{
mapent->pModelName = mapent->pKeyValues->value;
}
}
} while (1);
return pString;
}
mapentity_t *Map_EntityIndex( int index )
{
if ( index >= 0 && index < g_MapEntities.count )
return g_MapEntities.list + index;
return NULL;
}
mapentity_t *Map_FindEntity( const char *pClassName )
{
for ( int i = 0; i < g_MapEntities.count; i++ )
{
if ( !strcmp( g_MapEntities.list[i].pClassName, pClassName ) )
return g_MapEntities.list + i;
}
return NULL;
}
int Map_EntityCount( void )
{
return g_MapEntities.count;
}
const char *Map_EntityValue( const mapentity_t *pEntity, const char *pKeyName )
{
keypair_t *pKeys = pEntity->pKeyValues;
while ( pKeys )
{
if ( !strcmp( pKeys->key, pKeyName ) )
return pKeys->value;
pKeys = pKeys->next;
}
return NULL;
}
void Map_ParseEntities( char *pEntData )
{
g_MapEntities.count = 0;
while ( pEntData = ParseEntity( pEntData ) )
{
}
}
/*
=================
Mod_LoadEntities
=================
*/
void Mod_LoadEntities( model_t *loadmodel, lump_t *l )
{
char *pszInputStream, *pEntities;
loadmodel->entities = NULL;
pEntities = (char *) (mod_base + l->fileofs);
if ( pEntities )
{
// Parse the WAD file name from the entity lump
for ( pszInputStream = COM_Parse(pEntities); // '{' this is here to fix DevStudio's brace matching
*pszInputStream && *com_token != '}';
pszInputStream = COM_Parse(pszInputStream) )
{
if ( strcmp(com_token,"wad") == 0 )
{
pszInputStream = COM_Parse(pszInputStream);
if ( wadpath )
free(wadpath);
wadpath = strdup( com_token );
break;
}
}
Map_ParseEntities( pEntities );
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -