📄 model_common.c
字号:
/*
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_common.c -- model loading and caching
// 2001-12-28 Merged model functions by Maddes
// models are the only shared resource between a client and server running
// on the same machine.
#include "quakedef.h"
model_t *loadmodel;
char loadname[32]; // for hunk tags
byte mod_novis[MAX_MAP_LEAFS/8];
#ifdef GLQUAKE
cvar_t *gl_subdivide_size;
#endif
cvar_t *external_lit; // 2001-09-11 Colored lightning by LordHavoc/Sarcazm/Maddes
cvar_t *external_ent; // 2001-09-12 .ENT support by Maddes
cvar_t *external_vis; // 2001-12-28 .VIS support by Maddes
// 2001-09-18 New cvar system by Maddes (Init) start
/*
===============
Mod_Init_Cvars
===============
*/
void Mod_Init_Cvars (void)
{
#ifdef GLQUAKE
gl_subdivide_size = Cvar_Get ("gl_subdivide_size", "128", CVAR_ARCHIVE|CVAR_ORIGINAL);
#endif
// 2001-09-11 Colored lightning by LordHavoc/Sarcazm/Maddes start
external_lit = Cvar_Get ("external_lit", "1", CVAR_NONE);
Cvar_SetRangecheck (external_lit, Cvar_RangecheckBool, 0, 1);
Cvar_Set(external_lit, external_lit->string); // do rangecheck
// 2001-09-11 Colored lightning by LordHavoc/Sarcazm/Maddes end
// 2001-09-12 .ENT support by Maddes start
external_ent = Cvar_Get ("external_ent", "1", CVAR_NONE);
Cvar_SetRangecheck (external_ent, Cvar_RangecheckBool, 0, 1);
Cvar_Set(external_ent, external_ent->string); // do rangecheck
// 2001-09-12 .ENT support by Maddes end
// 2001-12-28 .VIS support by Maddes start
external_vis = Cvar_Get ("external_vis", "1", CVAR_NONE);
Cvar_SetRangecheck (external_vis, Cvar_RangecheckBool, 0, 1);
Cvar_Set(external_vis, external_vis->string); // do rangecheck
// 2001-12-28 .VIS support by Maddes end
}
// 2001-09-18 New cvar system by Maddes (Init) end
/*
===============
Mod_Init
===============
*/
void Mod_Init (void)
{
// 2001-09-18 New cvar system by Maddes (Init) start
/*
#ifdef GLQUAKE
gl_subdivide_size = Cvar_Get ("gl_subdivide_size", "128", CVAR_ARCHIVE|CVAR_ORIGINAL);
#endif
// 2001-09-11 Colored lightning by LordHavoc/Sarcazm/Maddes start
external_lit = Cvar_Get ("external_lit", "1", CVAR_NONE);
Cvar_SetRangecheck (external_lit, Cvar_RangecheckBool, 0, 1);
Cvar_Set(external_lit, external_lit->string); // do rangecheck
// 2001-09-11 Colored lightning by LordHavoc/Sarcazm/Maddes end
// 2001-09-12 .ENT support by Maddes start
external_ent = Cvar_Get ("external_ent", "1", CVAR_NONE);
Cvar_SetRangecheck (external_ent, Cvar_RangecheckBool, 0, 1);
Cvar_Set(external_ent, external_ent->string); // do rangecheck
// 2001-09-12 .ENT support by Maddes end
*/
// 2001-09-18 New cvar system by Maddes (Init) end
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
===================
*/
byte *Mod_DecompressVis (byte *in, model_t *model)
{
static byte decompressed[MAX_MAP_LEAFS/8];
int c;
byte *out;
int row;
row = (model->numleafs+7)>>3;
out = decompressed;
#if 0
memcpy (out, in, row);
#else
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);
#endif
return decompressed;
}
byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model)
{
if (leaf == model->leafs)
return mod_novis;
return Mod_DecompressVis (leaf->compressed_vis, model);
}
/*
==================
Mod_ForName
Loads in a model for the given name
==================
*/
model_t *Mod_ForName (char *name, qboolean crash)
{
model_t *mod;
mod = Mod_FindName (name);
return Mod_LoadModel (mod, crash);
}
/*
===============================================================================
BRUSHMODEL LOADING
===============================================================================
*/
byte *mod_base;
/*
=================
Mod_LoadVisibility
=================
*/
void Mod_LoadVisibility (lump_t *l)
{
if (!l->filelen)
{
loadmodel->visdata = NULL;
return;
}
// 2001-12-28 .VIS support by Maddes start
// loadmodel->visdata = Hunk_AllocName ( l->filelen, loadname);
loadmodel->visdata = Hunk_AllocName ( l->filelen, "INT_VIS");
// 2001-12-28 .VIS support by Maddes end
memcpy (loadmodel->visdata, mod_base + l->fileofs, l->filelen);
}
/*
=================
Mod_LoadEntities
=================
*/
void Mod_LoadEntities (lump_t *l, loadedfile_t *brush_fileinfo) // 2001-09-12 .ENT support by Maddes
{
// 2001-09-12 .ENT support by Maddes start
char entfilename[1024];
loadedfile_t *fileinfo;
searchpath_t *s_check;
loadmodel->entities = NULL;
if (external_ent->value)
{
// check for a .ENT file
strcpy(entfilename, loadmodel->name);
COM_StripExtension(entfilename, entfilename);
strcat(entfilename, ".ent");
fileinfo = COM_LoadHunkFile (entfilename);
if (fileinfo && fileinfo->filelen)
{
// .ENT file only allowed from same directory of map file or another directory before in the searchpath
s_check = COM_GetDirSearchPath(brush_fileinfo->path); // get last searchpath of map directory
while ( (s_check = s_check->next) ) // next searchpath
{
if (s_check == fileinfo->path) // found .ENT searchpath = after map directory
{
Con_DPrintf("%s not allowed from %s as map is from %s\n", entfilename, fileinfo->path->pack ? fileinfo->path->pack->filename : fileinfo->path->filename, brush_fileinfo->path->pack ? brush_fileinfo->path->pack->filename : brush_fileinfo->path->filename);
break;
}
}
if (!s_check) // .ENT searchpath not found = before map directory
{
Con_Printf("%s loaded from %s\n", entfilename, fileinfo->path->pack ? fileinfo->path->pack->filename : fileinfo->path->filename);
loadmodel->entities = fileinfo->data;
return;
}
}
// no .ENT found, use the original entity list
}
// 2001-09-12 .ENT support by Maddes end
if (!l->filelen)
{
loadmodel->entities = NULL;
return;
}
// 2001-09-12 .ENT support by Maddes start
// loadmodel->entities = Hunk_AllocName ( l->filelen, loadname);
loadmodel->entities = Hunk_AllocName ( l->filelen, "INT_ENT");
// 2001-09-12 .ENT support by Maddes end
memcpy (loadmodel->entities, mod_base + l->fileofs, l->filelen);
}
/*
=================
Mod_LoadVertexes
=================
*/
void Mod_LoadVertexes (lump_t *l)
{
dvertex_t *in;
mvertex_t *out;
int i, count;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( count*sizeof(*out), loadname);
loadmodel->vertexes = out;
loadmodel->numvertexes = count;
for ( i=0 ; i<count ; i++, in++, out++)
{
out->position[0] = LittleFloat (in->point[0]);
out->position[1] = LittleFloat (in->point[1]);
out->position[2] = LittleFloat (in->point[2]);
}
}
/*
=================
Mod_LoadSubmodels
=================
*/
void Mod_LoadSubmodels (lump_t *l)
{
dmodel_t *in;
dmodel_t *out;
int i, j, count;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( count*sizeof(*out), loadname);
loadmodel->submodels = out;
loadmodel->numsubmodels = count;
for ( i=0 ; i<count ; i++, in++, out++)
{
for (j=0 ; j<3 ; j++)
{ // spread the mins / maxs by a pixel
out->mins[j] = LittleFloat (in->mins[j]) - 1;
out->maxs[j] = LittleFloat (in->maxs[j]) + 1;
out->origin[j] = LittleFloat (in->origin[j]);
}
for (j=0 ; j<MAX_MAP_HULLS ; j++)
out->headnode[j] = LittleLong (in->headnode[j]);
out->visleafs = LittleLong (in->visleafs);
out->firstface = LittleLong (in->firstface);
out->numfaces = LittleLong (in->numfaces);
}
}
/*
=================
Mod_LoadEdges
=================
*/
void Mod_LoadEdges (lump_t *l)
{
dedge_t *in;
medge_t *out;
int i, count;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( (count + 1) * sizeof(*out), loadname);
loadmodel->edges = out;
loadmodel->numedges = count;
for ( i=0 ; i<count ; i++, in++, out++)
{
out->v[0] = (unsigned short)LittleShort(in->v[0]);
out->v[1] = (unsigned short)LittleShort(in->v[1]);
}
}
/*
=================
Mod_LoadTexinfo
=================
*/
void Mod_LoadTexinfo (lump_t *l)
{
texinfo_t *in;
mtexinfo_t *out;
int i, j, count;
int miptex;
float len1, len2;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( count*sizeof(*out), loadname);
loadmodel->texinfo = out;
loadmodel->numtexinfo = count;
for ( i=0 ; i<count ; i++, in++, out++)
{
for (j=0 ; j<8 ; j++)
out->vecs[0][j] = LittleFloat (in->vecs[0][j]);
len1 = Length (out->vecs[0]);
len2 = Length (out->vecs[1]);
len1 = (len1 + len2)/2;
if (len1 < 0.32)
out->mipadjust = 4;
else if (len1 < 0.49)
out->mipadjust = 3;
else if (len1 < 0.99)
out->mipadjust = 2;
else
out->mipadjust = 1;
#if 0
if (len1 + len2 < 0.001)
out->mipadjust = 1; // don't crash
else
out->mipadjust = 1 / floor( (len1+len2)/2 + 0.1 );
#endif
miptex = LittleLong (in->miptex);
out->flags = LittleLong (in->flags);
if (!loadmodel->textures)
{
out->texture = r_notexture_mip; // checkerboard texture
out->flags = 0;
}
else
{
if (miptex >= loadmodel->numtextures)
Sys_Error ("miptex >= loadmodel->numtextures");
out->texture = loadmodel->textures[miptex];
if (!out->texture)
{
out->texture = r_notexture_mip; // texture not found
out->flags = 0;
}
}
}
}
/*
=================
Mod_SetParent
=================
*/
void Mod_SetParent (mnode_t *node, mnode_t *parent)
{
node->parent = parent;
if (node->contents < 0)
return;
Mod_SetParent (node->children[0], node);
Mod_SetParent (node->children[1], node);
}
/*
=================
Mod_LoadNodes
=================
*/
void Mod_LoadNodes (lump_t *l)
{
int i, j, count, p;
dnode_t *in;
mnode_t *out;
in = (void *)(mod_base + l->fileofs);
if (l->filelen % sizeof(*in))
Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
count = l->filelen / sizeof(*in);
out = Hunk_AllocName ( count*sizeof(*out), loadname);
loadmodel->nodes = out;
loadmodel->numnodes = count;
for ( i=0 ; i<count ; i++, in++, out++)
{
for (j=0 ; j<3 ; j++)
{
out->minmaxs[j] = LittleShort (in->mins[j]);
out->minmaxs[3+j] = LittleShort (in->maxs[j]);
}
p = LittleLong(in->planenum);
out->plane = loadmodel->planes + p;
out->firstsurface = LittleShort (in->firstface);
out->numsurfaces = LittleShort (in->numfaces);
for (j=0 ; j<2 ; j++)
{
p = LittleShort (in->children[j]);
if (p >= 0)
out->children[j] = loadmodel->nodes + p;
else
out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p));
}
}
Mod_SetParent (loadmodel->nodes, NULL); // sets nodes and leafs
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -