gl_model.c

来自「quake1 dos源代码最新版本」· C语言 代码 · 共 1,400 行 · 第 1/3 页

C
1,400
字号
/*
Copyright (C) 1996-1997 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.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/
// model.c -- model loading and caching

// models are the only shared resource between a client and server running
// on the same machine.

#include "quakedef.h"

extern	cvar_t	*gl_glowmap;	// 1999-12-28 OpenGL fullbright fix by Neal White III

#define	MAX_MOD_KNOWN	512
model_t	mod_known[MAX_MOD_KNOWN];
int		mod_numknown;

/*
===================
Mod_ClearAll
===================
*/
void Mod_ClearAll (void)
{
	int		i;
	model_t	*mod;

	for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
		if (mod->type != mod_alias)
			mod->needload = true;
}

/*
==================
Mod_FindName

==================
*/
model_t *Mod_FindName (char *name)
{
	int		i;
	model_t	*mod;

	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 (i == mod_numknown)
	{
		if (mod_numknown == MAX_MOD_KNOWN)
			Sys_Error ("mod_numknown == MAX_MOD_KNOWN");
		strcpy (mod->name, name);
		mod->needload = true;
		mod_numknown++;
	}

	return mod;
}

/*
==================
Mod_TouchModel

==================
*/
void Mod_TouchModel (char *name)
{
	model_t	*mod;

	mod = Mod_FindName (name);

	if (!mod->needload)
	{
		if (mod->type == mod_alias)
			Cache_Check (&mod->cache);
	}
}

/*
==================
Mod_LoadModel

Loads a model into the cache
==================
*/
model_t *Mod_LoadModel (model_t *mod, qboolean crash)
{
	void		*d;
	unsigned	*buf;
	byte		stackbuf[1024];	// avoid dirtying the cache heap
	loadedfile_t	*fileinfo;	// 2001-09-12 Returning information about loaded file by Maddes

	if (!mod->needload)
	{
		if (mod->type == mod_alias)
		{
			d = Cache_Check (&mod->cache);
			if (d)
				return mod;
		}
		else
			return mod;		// not cached at all
	}

//
// because the world is so huge, load it one piece at a time
//
	if (!crash)
	{

	}

//
// load the file
//
// 2001-09-12 Returning information about loaded file by Maddes  start
/*
	buf = (unsigned *)COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf));
	if (!buf)
*/
	fileinfo = COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf));
	if (!fileinfo)
// 2001-09-12 Returning information about loaded file by Maddes  end
	{
		if (crash)
			Sys_Error ("Mod_NumForName: %s not found", mod->name);
		return NULL;
	}
	buf = (unsigned *)fileinfo->data;	// 2001-09-12 Returning information about loaded file by Maddes

//
// allocate a new model
//
	COM_FileBase (mod->name, loadname);

	loadmodel = mod;

//
// fill it in
//

// call the apropriate loader
	mod->needload = false;

	switch (LittleLong(*(unsigned *)buf))
	{
	case IDPOLYHEADER:
		Mod_LoadAliasModel (mod, buf);
		break;

	case IDSPRITEHEADER:
		Mod_LoadSpriteModel (mod, buf);
		break;

	default:
		Mod_LoadBrushModel (mod, buf, fileinfo);	// 2001-09-12 .ENT support by Maddes
		break;
	}

	return mod;
}


/*
===============================================================================

					BRUSHMODEL LOADING

===============================================================================
*/

/*
=================
Mod_LoadTextures
=================
*/
void Mod_LoadTextures (lump_t *l)
{
// 1999-12-28 OpenGL fullbright fix by Neal White III  start
	// Neal White III - 12-28-1999 - OpenGL fullbright bugfix
	// nwhite@softblox.com
	// http://home.telefragged.com/wally/
	//
	// Problem:
	//
	// There was a problem in the original glquake with fullbright texels.
	// In the software renderer, fullbrights glow brightly in the dark.
	// Essentially, the fullbrights were ignored.  I've fixed it by
	// adding another rendering pass and creating a new glowmap texture.
	//
	// Fix:
	//
	// When a texture with fullbright (FB) texels is loaded, a copy is made,
	// then the FB pixels are cleared to black in the original texture.  In
	// the copy, all normal colors are cleared and only the FBs remain.  When
	// it comes time to render the polygons, I do an additional pass and ADD
	// the glowmap on top of the current polygon.

	byte		*ptexel;
	qboolean	hasfullbrights;
//	qboolean	noglow = COM_CheckParm("-noglow");

//	int		i, j, pixels, num, max, altmax;
	int		i, num, max, altmax;
	unsigned long	j, pixels;
// 1999-12-28 OpenGL fullbright fix by Neal White III  end

	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 *)((byte *)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;

// 1999-12-28 OpenGL fullbright fix by Neal White III  start
		hasfullbrights = false;

		if ((!strncmp(mt->name,"sky",3)) ||
				(!strncmp(mt->name,"*",1)) || 	// turbulent (liquid)
				(!gl_glowmap->value) || (! gl_mtexable) )
		{
			// sky has no lightmap, nor do liquids (so never needs a glowmap),
			// -noglow command line parameter, or no multi-texture support
			//
			// hasfullbrights is already false
		}
		else					// check this texture for fullbright texels
		{
			ptexel = (byte *)(mt+1);

			for (j=0 ; j<pixels ; j++)
			{
				if (ptexel[j] >= 256-32)	// 32 fullbright colors
				{
					hasfullbrights = true;
					break;
				}
			}
		}

		if (hasfullbrights)
		{
			tx = Hunk_AllocName (sizeof(texture_t) +pixels*2, loadname );
		}
		else
		{
// 1999-12-28 OpenGL fullbright fix by Neal White III  end
			tx = Hunk_AllocName (sizeof(texture_t) +pixels, loadname );
		}	// 1999-12-28 OpenGL fullbright fix by Neal White III

		loadmodel->textures[i] = tx;

		memcpy (tx->name, mt->name, sizeof(tx->name));
		tx->width = mt->width;
		tx->height = mt->height;
		for (j=0 ; j<MIPLEVELS ; j++)
		{	// 1999-12-28 OpenGL fullbright fix by Neal White III
			tx->offsets[j] = mt->offsets[j] + sizeof(texture_t) - sizeof(miptex_t);
// 1999-12-28 OpenGL fullbright fix by Neal White III  start
			if (hasfullbrights)
			{
				tx->glowoffsets[j] = mt->offsets[j] + sizeof(texture_t) - sizeof(miptex_t) + pixels;
			}
			else
			{
				tx->glowoffsets[j] = 0;
			}
		}
// 1999-12-28 OpenGL fullbright fix by Neal White III  end

		// the pixels immediately follow the structures
		memcpy ( tx+1, mt+1, pixels);

// 1999-12-28 OpenGL fullbright fix by Neal White III  start
		if (hasfullbrights)
		{
			ptexel = (byte *)(tx+1);
			memcpy ( ptexel+pixels, mt+1, pixels);
		}

		tx->flags = 0;
// 1999-12-28 OpenGL fullbright fix by Neal White III  end

		if (!strncmp(mt->name,"sky",3))
// 2000-07-09 Dedicated server bug in GLQuake fix by Nathan Cline  start
		{
			if (cls.state != ca_dedicated)
			{
// 2000-07-09 Dedicated server bug in GLQuake fix by Nathan Cline  end
				R_InitSky (tx);
// 2000-07-09 Dedicated server bug in GLQuake fix by Nathan Cline  start
			}
		}
// 2000-07-09 Dedicated server bug in GLQuake fix by Nathan Cline  end
		else
		{
			texture_mode = GL_LINEAR_MIPMAP_NEAREST; //_LINEAR;
// 1999-12-28 OpenGL fullbright fix by Neal White III  start
			// remove glowing fullbright colors from base texture (make black)
			if (hasfullbrights)
			{
#ifdef _DEBUG
				qboolean	bColorUsed[256];
				Con_DPrintf ("*** Fullbright Texture: \"%s\", %dx%d, %d pixels\n", mt->name, mt->width, mt->height, pixels);
				for (j=0 ; j<256 ; j++) bColorUsed[j] = false;
#endif

				ptexel = (byte *)(tx+1);

				for (j=0 ; j<pixels ; j++)
				{
#ifdef _DEBUG
					bColorUsed[ptexel[j]] = true;
#endif

					if (ptexel[j] >= 256-32)	// 32 fullbright colors
					{
						ptexel[j] = 0;		// make fullbrights black
					}
				}

#ifdef _DEBUG
				Con_DPrintf ("*** Normal colors: ");
				for (j=0 ; j<256-32 ; j++)
				{
					if (bColorUsed[j])
						Con_DPrintf ("%d ", j);
				}
				Con_DPrintf ("\n");

				Con_DPrintf ("*** Fullbrights: ");
				for (j=256-32 ; j<256 ; j++)
				{
					if (bColorUsed[j])
						Con_DPrintf ("%d ", j);
				}
				Con_DPrintf ("\n");
#endif
			}
#ifdef _DEBUG
			else
			{
				Con_DPrintf ("*** Normal Texture: \"%s\", %dx%d\n", mt->name, mt->width, mt->height);
			}
#endif
// 1999-12-28 OpenGL fullbright fix by Neal White III  end
			tx->gl_texturenum = GL_LoadTexture (mt->name, tx->width, tx->height, (byte *)(tx+1), true, false);
// 1999-12-28 OpenGL fullbright fix by Neal White III  start
			// create glowmap texture (all black except for glowing fullbright colors)
			if (hasfullbrights)
			{
#ifdef _DEBUG
				qboolean bGlowDoubleCheck = false;
#endif
				char glowname[32];
				memcpy (glowname, mt->name, sizeof(mt->name));

				glowname[16] = '\0';
				for (j=0 ; glowname[j] != '\0'; j++)
					;
				glowname[j++] = '<';
				glowname[j++] = 'G';
				glowname[j++] = 'L';
				glowname[j++] = 'O';
				glowname[j++] = 'W';
				glowname[j++] = '>';
				glowname[j++] = '\0';

				ptexel = (byte *)(tx+1) + pixels;

				for (j=0 ; j<pixels ; j++)
				{
					if (ptexel[j] < 256-32)		// build glowmap
					{
						ptexel[j] = 0;			// make non-fullbrights black
					}
#ifdef _DEBUG
					else
					{
						bGlowDoubleCheck = true;
					}
#endif
				}
				tx->gl_glowtexnum = GL_LoadTexture (glowname, tx->width, tx->height, ptexel, true, false);
				tx->flags |= FLAG_HAS_GLOWMAP;

#ifdef _DEBUG
				if (! bGlowDoubleCheck)
					Con_DPrintf ("INTERNAL ERROR: Mod_LoadTextures - FullBright texture \"%s\" has no FullBright colors!\n", glowname);
#endif
			}
// 1999-12-28 OpenGL fullbright fix by Neal White III  end
			texture_mode = GL_LINEAR;
		}
	}

//
// 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;	// already 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;

⌨️ 快捷键说明

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