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 + -
显示快捷键?