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

📄 gl_model.cpp

📁 hl2 source code. Do not use it illegal.
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//=========== (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 + -