1835 lines · 38.8 KB · C
RawDownload
// models.c -- model loading and caching // models are the only shared resource between a client and server running// on the same machine. #include <math.h>#include "quakedef.h"#include "r_shared.h"#include "r_local.h" model_t *loadmodel;char loadname[32]; // for hunk tags void Mod_LoadSpriteModel (model_t *mod, void *buffer);void Mod_LoadBrushModel (model_t *mod, void *buffer);void Mod_LoadAliasModel (model_t *mod, void *buffer);model_t *Mod_LoadModel (model_t *mod, bool crash); uint8_t mod_novis[MAX_MAP_LEAFS/8]; #define MAX_MOD_KNOWN 512model_t mod_known[MAX_MOD_KNOWN];int mod_numknown; // values for model_t's needload#define NL_PRESENT 0#define NL_NEEDS_LOADED 1#define NL_UNREFERENCED 2 /*===============Mod_Init===============*/void Mod_Init (void){	memset (mod_novis, 0xff, sizeof(mod_novis));} /*===============Mod_Extradata Caches the data if needed===============*/void *Mod_Extradata (model_t *mod){	void *r; 	r = Cache_Check (&mod->cache);	if (r)		return r; 	Mod_LoadModel (mod, true); 	if (!mod->cache.data)		Sys_Error ("Mod_Extradata: caching failed");	return mod->cache.data;} /*===============Mod_PointInLeaf===============*/mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model){	mnode_t *node;	float d;	mplane_t *plane; 	if (!model || !model->nodes)		Sys_Error ("Mod_PointInLeaf: bad model"); 	node = model->nodes;	while (1)	{		if (node->contents < 0)			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===================*/uint8_t *Mod_DecompressVis (uint8_t *in, model_t *model){	static uint8_t decompressed[MAX_MAP_LEAFS/8];	int c;	uint8_t *out;	int row; 	row = (model->numleafs+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;} uint8_t *Mod_LeafPVS (mleaf_t *leaf, model_t *model){	if (leaf == model->leafs)		return mod_novis;	return Mod_DecompressVis (leaf->compressed_vis, model);} /*===================Mod_ClearAll===================*/void Mod_ClearAll (void){	int i;	model_t *mod; 	for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++) {		mod->needload = NL_UNREFERENCED;//FIX FOR CACHE_ALLOC ERRORS:		if (mod->type == mod_sprite) mod->cache.data = NULL;	}} /*==================Mod_FindName ==================*/model_t *Mod_FindName (char *name){	int i;	model_t *mod;	model_t *avail = NULL; 	if (!name[0])		Sys_Error ("Mod_ForName: NULL name"); //// search the currently loaded models//	for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)	{		if (!strcmp (mod->name, name) )			break;		if (mod->needload == NL_UNREFERENCED)			if (!avail || mod->type != mod_alias)				avail = mod;	} 	if (i == mod_numknown)	{		if (mod_numknown == MAX_MOD_KNOWN)		{			if (avail)			{				mod = avail;				if (mod->type == mod_alias)					if (Cache_Check (&mod->cache))						Cache_Free (&mod->cache);			}			else				Sys_Error ("mod_numknown == MAX_MOD_KNOWN");		}		else			mod_numknown++;		strcpy (mod->name, name);		mod->needload = NL_NEEDS_LOADED;	} 	return mod;} /*==================Mod_TouchModel ==================*/void Mod_TouchModel (char *name){	model_t *mod; 	mod = Mod_FindName (name); 	if (mod->needload == NL_PRESENT)	{		if (mod->type == mod_alias)			Cache_Check (&mod->cache);	}} /*==================Mod_LoadModel Loads a model into the cache==================*/model_t *Mod_LoadModel (model_t *mod, bool crash){	unsigned *buf;	uint8_t stackbuf[1024]; // avoid dirtying the cache heap 	if (mod->type == mod_alias)	{		if (Cache_Check (&mod->cache))		{			mod->needload = NL_PRESENT;			return mod;		}	}	else	{		if (mod->needload == NL_PRESENT)			return mod;	} //// because the world is so huge, load it one piece at a time// //// load the file//	buf = (unsigned *)COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf));	if (!buf)	{		if (crash)			Sys_Error ("Mod_NumForName: %s not found", mod->name);		return NULL;	} //// allocate a new model//	COM_FileBase (mod->name, loadname); 	loadmodel = mod; //// fill it in// // call the apropriate loader	mod->needload = NL_PRESENT; 	switch (LittleLong(*(unsigned *)buf))	{	case IDPOLYHEADER:		Mod_LoadAliasModel (mod, buf);		break; 	case IDSPRITEHEADER:		Mod_LoadSpriteModel (mod, buf);		break; 	default:		Mod_LoadBrushModel (mod, buf);		break;	} 	return mod;} /*==================Mod_ForName Loads in a model for the given name==================*/model_t *Mod_ForName (char *name, bool crash){	model_t *mod; 	mod = Mod_FindName (name); 	return Mod_LoadModel (mod, crash);} /*=============================================================================== 					BRUSHMODEL LOADING ===============================================================================*/ uint8_t *mod_base; /*=================Mod_LoadTextures=================*/void Mod_LoadTextures (lump_t *l){	int i, j, pixels, num, max, altmax;	miptex_t *mt;	texture_t *tx, *tx2;	texture_t *anims[10];	texture_t *altanims[10];	dmiptexlump_t *m; 	if (!l->filelen)	{		loadmodel->textures = NULL;		return;	}	m = (dmiptexlump_t *)(mod_base + l->fileofs); 	m->nummiptex = LittleLong (m->nummiptex); 	loadmodel->numtextures = m->nummiptex;	loadmodel->textures = Hunk_AllocName (m->nummiptex * sizeof(*loadmodel->textures) , loadname); 	for (i=0 ; i<m->nummiptex ; i++)	{		m->dataofs[i] = LittleLong(m->dataofs[i]);		if (m->dataofs[i] == -1)			continue;		mt = (miptex_t *)((uint8_t *)m + m->dataofs[i]);		mt->width = LittleLong (mt->width);		mt->height = LittleLong (mt->height);		for (j=0 ; j<MIPLEVELS ; j++)			mt->offsets[j] = LittleLong (mt->offsets[j]); 		if ( (mt->width & 15) || (mt->height & 15) )			Sys_Error ("Texture %s is not 16 aligned", mt->name);		pixels = mt->width*mt->height/64*85;		tx = Hunk_AllocName (sizeof(texture_t) +pixels, loadname );		loadmodel->textures[i] = tx; 		memmove (tx->name, mt->name, sizeof(tx->name));		tx->width = mt->width;		tx->height = mt->height;		for (j=0 ; j<MIPLEVELS ; j++)			tx->offsets[j] = mt->offsets[j] + sizeof(texture_t) - sizeof(miptex_t);		// the pixels immediately follow the structures		memmove ( tx+1, mt+1, pixels); 		if (!strncmp(mt->name,"sky",3))			R_InitSky (tx);	} //// sequence the animations//	for (i=0 ; i<m->nummiptex ; i++)	{		tx = loadmodel->textures[i];		if (!tx || tx->name[0] != '+')			continue;		if (tx->anim_next)			continue; // allready sequenced 	// find the number of frames in the animation		memset (anims, 0, sizeof(anims));		memset (altanims, 0, sizeof(altanims)); 		max = tx->name[1];		altmax = 0;		if (max >= 'a' && max <= 'z')			max -= 'a' - 'A';		if (max >= '0' && max <= '9')		{			max -= '0';			altmax = 0;			anims[max] = tx;			max++;		}		else if (max >= 'A' && max <= 'J')		{			altmax = max - 'A';			max = 0;			altanims[altmax] = tx;			altmax++;		}		else			Sys_Error ("Bad animating texture %s", tx->name); 		for (j=i+1 ; j<m->nummiptex ; j++)		{			tx2 = loadmodel->textures[j];			if (!tx2 || tx2->name[0] != '+')				continue;			if (strcmp (tx2->name+2, tx->name+2))				continue; 			num = tx2->name[1];			if (num >= 'a' && num <= 'z')				num -= 'a' - 'A';			if (num >= '0' && num <= '9')			{				num -= '0';				anims[num] = tx2;				if (num+1 > max)					max = num + 1;			}			else if (num >= 'A' && num <= 'J')			{				num = num - 'A';				altanims[num] = tx2;				if (num+1 > altmax)					altmax = num+1;			}			else				Sys_Error ("Bad animating texture %s", tx->name);		} #define ANIM_CYCLE 2	// link them all together		for (j=0 ; j<max ; j++)		{			tx2 = anims[j];			if (!tx2)				Sys_Error ("Missing frame %i of %s",j, tx->name);			tx2->anim_total = max * ANIM_CYCLE;			tx2->anim_min = j * ANIM_CYCLE;			tx2->anim_max = (j+1) * ANIM_CYCLE;			tx2->anim_next = anims[ (j+1)%max ];			if (altmax)				tx2->alternate_anims = altanims[0];		}		for (j=0 ; j<altmax ; j++)		{			tx2 = altanims[j];			if (!tx2)				Sys_Error ("Missing frame %i of %s",j, tx->name);			tx2->anim_total = altmax * ANIM_CYCLE;			tx2->anim_min = j * ANIM_CYCLE;			tx2->anim_max = (j+1) * ANIM_CYCLE;			tx2->anim_next = altanims[ (j+1)%altmax ];			if (max)				tx2->alternate_anims = anims[0];		}	}} /*=================Mod_LoadLighting=================*/void Mod_LoadLighting (lump_t *l){	if (!l->filelen)	{		loadmodel->lightdata = NULL;		return;	}	loadmodel->lightdata = Hunk_AllocName ( l->filelen, loadname);	memmove (loadmodel->lightdata, mod_base + l->fileofs, l->filelen);} /*=================Mod_LoadVisibility=================*/void Mod_LoadVisibility (lump_t *l){

Lines 1–500 of 1835.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t