2
0
mirror of https://github.com/rehlds/rehlds.git synced 2025-01-07 20:45:34 +03:00
rehlds/rehlds/engine/model.cpp
dreamstalker ed575d9b7d Fixed: all functions that could be called from outside must realign the stack
Removed NOINLINE from MSG_Write*Bits functions since stack alignment issue is resolved
2015-06-30 17:09:22 +04:00

1904 lines
48 KiB
C++

/*
*
* 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
*
* In addition, as a special exception, the author gives permission to
* link the code of this program with the Half-Life Game Engine ("HL
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
* L.L.C ("Valve"). You must obey the GNU General Public License in all
* respects for all of the code used other than the HL Engine and MODs
* from Valve. If you modify this file, you may extend this exception
* to your version of the file, but you are not obligated to do so. If
* you do not wish to do so, delete this exception statement from your
* version.
*
*/
#include "precompiled.h"
model_t *loadmodel;
char loadname[32];
model_t mod_known[MAX_KNOWN_MODELS];
int mod_numknown;
unsigned char* mod_base;
char *wadpath;
int tested;
int ad_enabled;
cachewad_t ad_wad;
mod_known_info_t mod_known_info[MAX_KNOWN_MODELS];
// values for model_t's needload
#define NL_PRESENT 0
#define NL_NEEDS_LOADED 1
#define NL_UNREFERENCED 2
/* <51468> ../engine/model.c:147 */
void SW_Mod_Init(void)
{
#ifndef SWDS
// TODO: Add client-side code
#endif
}
/* <52f8d> ../engine/model.c:164 */
void* EXT_FUNC Mod_Extradata(model_t *mod)
{
void *r;
if (!mod)
{
return NULL;
}
r = Cache_Check(&mod->cache);
if (r)
{
return r;
}
if (mod->type == mod_brush)
{
Sys_Error(__FUNCTION__ ": called with mod_brush!\n");
}
Mod_LoadModel(mod, 1, 0);
if (mod->cache.data == NULL)
{
Sys_Error(__FUNCTION__ ": caching failed");
}
return mod->cache.data;
}
/* <5147c> ../engine/model.c:190 */
mleaf_t *Mod_PointInLeaf(vec_t *p, model_t *model)
{
mnode_t *node; // 192
float d; // 193
mplane_t *plane; // 194
if (!model || !model->nodes)
Sys_Error(__FUNCTION__ ": bad model");
node = model->nodes;
while (node->contents >= 0)
{
plane = node->plane;
if (plane->type >= 3u)
d = _DotProduct(plane->normal, p) - plane->dist;
else
d = p[plane->type] - plane->dist;
if (d <= 0.0)
node = node->children[1];
else
node = node->children[0];
}
return (mleaf_t *)node;
}
/* <514e5> ../engine/model.c:226 */
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 != (NL_NEEDS_LOADED | NL_UNREFERENCED))
{
mod->needload = NL_UNREFERENCED;
if (mod->type == mod_sprite)
mod->cache.data = NULL;
}
}
}
/* <5151a> ../engine/model.c:248 */
void Mod_FillInCRCInfo(qboolean trackCRC, int model_number)
{
mod_known_info_t *p;
p = &mod_known_info[model_number];
p->shouldCRC = trackCRC;
p->firstCRCDone = 0;
p->initialCRC = 0;
}
/* <51546> ../engine/model.c:264 */
model_t *Mod_FindName(qboolean trackCRC, const char *name)
{
model_t *avail;
int i;
model_t *mod;
avail = NULL;
if (!name[0])
Sys_Error("Mod_ForName: NULL name");
for (i = 0, mod = mod_known; i < mod_numknown; i++, mod++)
{
if (!Q_stricmp(mod->name, name))
break;
if (mod->needload == NL_UNREFERENCED)
{
if (!avail || mod->type != mod_alias && mod->type != mod_studio)
avail = mod;
}
}
if (i == mod_numknown)
{
if (mod_numknown < MAX_KNOWN_MODELS)
{
Mod_FillInCRCInfo(trackCRC, mod_numknown);
++mod_numknown;
}
else
{
if (!avail)
Sys_Error("mod_numknown >= MAX_KNOWN_MODELS");
mod = avail;
Mod_FillInCRCInfo(trackCRC, avail - mod_known);
}
Q_strncpy(mod->name, name, 63);
mod->name[63] = 0;
if (mod->needload != (NL_NEEDS_LOADED | NL_UNREFERENCED))
mod->needload = NL_NEEDS_LOADED;
}
return mod;
}
/* <51615> ../engine/model.c:329 */
NOXREF qboolean Mod_ValidateCRC(const char *name, CRC32_t crc)
{
model_t *mod;
mod_known_info_t *p;
mod = Mod_FindName(TRUE, name);
p = &mod_known_info[mod - mod_known];
if (p->firstCRCDone)
{
if (p->initialCRC != crc)
return FALSE;
}
return TRUE;
}
/* <5166e> ../engine/model.c:362 */
NOXREF void Mod_NeedCRC(const char *name, qboolean needCRC)
{
model_t *mod;
mod_known_info_t *p;
mod = Mod_FindName(FALSE, name);
p = &mod_known_info[mod - mod_known];
p->shouldCRC = needCRC;
}
//TODO: move to czmodelcheck.cpp
qboolean IsCZPlayerModel(uint32 crc, const char * filename)
{
if (crc == 0x27FB4D2F)
return Q_stricmp(filename, "models/player/spetsnaz/spetsnaz.mdl") ? 0 : 1;
if (crc == 0xEC43F76D || crc == 0x270FB2D7)
return Q_stricmp(filename, "models/player/terror/terror.mdl") ? 0 : 1;
if (crc == 0x1AAA3360 || crc == 0x35AC6FED)
return Q_stricmp(filename, "models/player/gign/gign.mdl") ? 0 : 1;
if (crc == 0x02B95E5F || crc == 0x72DB74E4)
return Q_stricmp(filename, "models/player/vip/vip.mdl") ? 0 : 1;
if (crc == 0x1F3CD80B || crc == 0x1B6C4115)
return Q_stricmp(filename, "models/player/guerilla/guerilla.mdl") ? 0 : 1;
if (crc == 0x3BCAA016)
return Q_stricmp(filename, "models/player/militia/militia.mdl") ? 0 : 1;
if (crc == 0x43E67FF3 || crc == 0xF141AE3F)
return Q_stricmp(filename, "models/player/sas/sas.mdl") ? 0 : 1;
if (crc == 0xDA8922A || crc == 0x56DD2D02)
return Q_stricmp(filename, "models/player/gsg9/gsg9.mdl") ? 0 : 1;
if (crc == 0xA37D8680 || crc == 0x4986827B)
return Q_stricmp(filename, "models/player/arctic/arctic.mdl") ? 0 : 1;
if (crc == 0xC37369F6 || crc == 0x29FE156C)
return Q_stricmp(filename, "models/player/leet/leet.mdl") ? 0 : 1;
if (crc == 0xC7F0DBF3 || crc == 0x068168DB)
return Q_stricmp(filename, "models/player/urban/urban.mdl") ? 0 : 1;
return 0;
}
/* <513ce> ../engine/model.c:394 */
model_t *Mod_LoadModel(model_t *mod, qboolean crash, qboolean trackCRC)
{
unsigned char *buf;
char tmpName[MAX_PATH];
int length;
CRC32_t currentCRC;
if (mod->type == mod_alias || mod->type == mod_studio)
{
if (Cache_Check(&mod->cache))
{
mod->needload = NL_PRESENT;
return mod;
}
}
else
{
if (mod->needload == NL_PRESENT || mod->needload == (NL_NEEDS_LOADED | NL_UNREFERENCED))
return mod;
}
if (COM_CheckParm("-steam") && mod->name[0] == '/')
{
char* p = mod->name;
while (*(p++) == '/')
;
Q_strncpy(tmpName, p, sizeof(tmpName) - 1);
tmpName[sizeof(tmpName) - 1] = '\0';
Q_strncpy(mod->name, tmpName, sizeof(mod->name) - 1);
mod->name[sizeof(mod->name) - 1] = '\0';
}
buf = COM_LoadFileForMe(mod->name, &length);
if (!buf)
{
if (crash)
Sys_Error("Mod_NumForName: %s not found", mod->name);
return 0;
}
if (trackCRC)
{
mod_known_info_t *p = &mod_known_info[mod - mod_known];
if (p->shouldCRC)
{
CRC32_Init(&currentCRC);
CRC32_ProcessBuffer(&currentCRC, buf, length);
currentCRC = CRC32_Final(currentCRC);
if (p->firstCRCDone)
{
if (currentCRC != p->initialCRC)
{
Sys_Error("%s has been modified since starting the engine. Consider running system diagnostics to check for faulty hardware.\n", mod->name);
}
}
else
{
p->firstCRCDone = 1;
p->initialCRC = currentCRC;
SetCStrikeFlags();
if (!IsGameSubscribed("czero") && g_bIsCStrike && IsCZPlayerModel(currentCRC, mod->name) && g_pcls.state)
{
COM_ExplainDisconnection(TRUE, "Cannot continue with altered model %s, disconnecting.", mod->name);
CL_Disconnect();
return 0;
}
}
}
}
if (developer.value > 1.0)
Con_DPrintf("loading %s\n", mod->name);
COM_FileBase(mod->name, loadname);
loadmodel = mod;
mod->needload = NL_PRESENT;
switch (LittleLong(*(uint32 *)buf))
{
case 'OPDI':
Sys_Error(__FUNCTION__ "Alias models are not supported");
break;
case 'PSDI':
Mod_LoadSpriteModel(mod, (dsprite_t *)buf);
break;
case 'TSDI':
Mod_LoadStudioModel(mod, (studiohdr_t *)buf);
break;
default:
Mod_LoadBrushModel(mod, (dheader_t *)buf);
break;
}
if (g_modfuncs.m_pfnModelLoad)
g_modfuncs.m_pfnModelLoad(mod, buf);
Mem_Free(buf);
return mod;
}
/* <516c5> ../engine/model.c:540 */
NOXREF void Mod_MarkClient(model_t *pModel)
{
pModel->needload = (NL_NEEDS_LOADED | NL_UNREFERENCED);
}
/* <52edc> ../engine/model.c:552 */
model_t *Mod_ForName(const char *name, qboolean crash, qboolean trackCRC)
{
model_t *mod;
mod = Mod_FindName(trackCRC, name);
if (!mod)
return NULL;
return Mod_LoadModel(mod, crash, trackCRC);
}
/* <516ee> ../engine/model.c:589 */
void Mod_AdInit(void)
{
int i;
char *s;
static char filename[MAX_PATH];
tested = 1;
i = COM_CheckParm("-ad");
if (i)
{
s = com_argv[i + 1];
if (s && *s)
{
Q_snprintf(filename, MAX_PATH, "%s", s);
if (FS_FileSize(filename) > 0)
{
Sys_Error("Mod_Init(): reverse me");
/*
Draw_CacheWadInit(filename, 16, &ad_wad);
sub_1D34290(&ad_wad, (void(__cdecl *)(cachewad_t *, unsigned __int8 *))sub_1D3A830, 24);
ad_enabled = 1;
*/
}
else
{
Con_Printf("No -ad file specified, skipping\n");
}
}
}
}
/* <51751> ../engine/model.c:621 */
void Mod_AdSwap(texture_t *src, int pixels, int entries)
{
// int j; // 623
// unsigned char *mippal; // 624
// short unsigned int *texpal; // 625
// texture_t *tex; // 626
Sys_Error(__FUNCTION__ ": Reverse me");
}
/* <51803> ../engine/model.c:656 */
void Mod_LoadTextures(lump_t *l)
{
dmiptexlump_t *m;
miptex_t *mt;
int palette;
int pixels;
uint8 *mippal;
uint16 *texpal;
int max;
texture_t *tx2;
int num;
char dtexdata[348996];
texture_t *anims[10];
texture_t *altanims[10];
double starttime;
qboolean wads_parsed;
texture_t *tx;
wads_parsed = 0;
starttime = Sys_FloatTime();
if (!tested)
Mod_AdInit();
if (!l->filelen)
{
loadmodel->textures = 0;
return;
}
m = (dmiptexlump_t *)(mod_base + l->fileofs);
m->_nummiptex = LittleLong(m->_nummiptex);
loadmodel->numtextures = m->_nummiptex;
loadmodel->textures = (texture_t **)Hunk_AllocName(4 * loadmodel->numtextures, loadname);
for (int i = 0; i < m->_nummiptex; i++)
{
m->dataofs[i] = LittleLong(m->dataofs[i]);
if (m->dataofs[i] == -1)
continue;
mt = (miptex_t *)((char *)m + m->dataofs[i]);
if (r_wadtextures.value != 0.0 || !LittleLong(mt->offsets[0]))
{
if (!wads_parsed)
{
TEX_InitFromWad(wadpath);
TEX_AddAnimatingTextures();
wads_parsed = 1;
}
if (!TEX_LoadLump(mt->name, (unsigned char *)dtexdata))
{
m->dataofs[i] = -1;
continue;
}
mt = (miptex_t *)dtexdata;
}
for (int j = 0; j < MIPLEVELS; j++)
mt->offsets[j] = LittleLong(mt->offsets[j]);
mt->width = LittleLong(mt->width);
mt->height = LittleLong(mt->height);
if (mt->width & 0xF || mt->height & 0xF)
Sys_Error("Texture %s is not 16 aligned", mt);
pixels = 85 * mt->height * mt->width / 64;
palette = *(uint16*)((char*)mt + sizeof(miptex_t) + pixels);
tx = (texture_t *)Hunk_AllocName(2 + 8 * palette + pixels + sizeof(texture_t), loadname);
loadmodel->textures[i] = tx;
Q_memcpy(tx->name, mt->name, sizeof(tx->name));
if (strchr(tx->name, '~'))
tx->name[2] = ' ';
tx->width = mt->width;
tx->height = mt->height;
for (int j = 0; j < MIPLEVELS; j++)
tx->offsets[j] = mt->offsets[j] + sizeof(texture_t) - sizeof(miptex_t);
tx->paloffset = sizeof(texture_t) + pixels + 2;
Q_memcpy(&tx[1], &mt[1], pixels + 2); //copy pixels & palette size (2)
if (!Q_strncmp(mt->name, "sky", 3))
{
//R_InitSky();
}
mippal = (uint8 *)&mt[1] + pixels + 2;
texpal = (uint16 *)((char*)&tx[1] + pixels + 2);
for (int j = 0; j < palette; j++, mippal += 3, texpal += 4)
{
texpal[0] = texgammatable[mippal[2]];
texpal[1] = texgammatable[mippal[1]];
texpal[2] = texgammatable[mippal[0]];
texpal[3] = 0;
}
if (ad_enabled && !Q_stricmp(tx->name, "DEFAULT"))
Mod_AdSwap(tx, pixels, palette);
}
if (wads_parsed)
TEX_CleanupWadInfo();
for (int i = 0; i < m->_nummiptex; i++)
{
tx = loadmodel->textures[i];
if (!tx)
continue;
if (tx->name[0] != '+' && tx->name[0] != '-')
continue;
if (tx->anim_next)
continue;
Q_memset(anims, 0, sizeof(anims));
Q_memset(altanims, 0, sizeof(altanims));
max = tx->name[1];
int altmax = 0;
if (max >= 'a' && max <= 'z')
max -= 32;
if (max < '0' || max > '9')
{
if (max < 'A' || max > 'J')
Sys_Error("Bad animating texture %s", tx);
altmax = max - 'A';
max = 0;
altanims[altmax] = tx;
altmax++;
}
else
{
max -= '0';
altmax = 0;
anims[max] = tx;
max++;
}
for (int j = i + 1; j < m->_nummiptex; j++)
{
tx2 = loadmodel->textures[j];
if (!tx2)
continue;
if (tx2->name[0] != '+' && tx2->name[0] != '-')
continue;
if (Q_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')
{
if (num < 'A' || num > 'J')
Sys_Error("Bad animating texture %s", tx);
num -= 'A';
altanims[num] = tx2;
if ((num + 1) > altmax)
altmax = num + 1;
}
else
{
num -= '0';
anims[num] = tx2;
if ((num + 1) > max)
max = num + 1;
}
}
for (int j = 0; j < max; j++)
{
tx2 = anims[j];
if (!tx2)
Sys_Error("Missing frame %i of %s", j, tx);
tx2->anim_min = j;
tx2->anim_total = max;
tx2->anim_max = j + 1;
tx2->anim_next = anims[(j + 1) % max];
if (altmax)
tx2->alternate_anims = altanims[0];
}
for (int j = 0; j < altmax; j++)
{
tx2 = altanims[j];
if (!tx2)
Sys_Error("Missing frame %i of %s", j, tx);
tx2->anim_min = j;
tx2->anim_total = altmax;
tx2->anim_max = j + 1;
tx2->anim_next = altanims[(j + 1) % altmax];
if (max)
tx2->alternate_anims = anims[0];
}
}
Con_DPrintf("Texture load: %6.1fms\n", (Sys_FloatTime() - starttime) * 1000.0);
}
/* <51386> ../engine/model.c:878 */
void Mod_LoadLighting(lump_t *l)
{
if (l->filelen)
{
loadmodel->lightdata = (color24 *)Hunk_AllocName(l->filelen, loadname);
Q_memcpy(loadmodel->lightdata, (const void *)(mod_base + l->fileofs), l->filelen);
}
else
{
loadmodel->lightdata = 0;
}
}
/* <519f8> ../engine/model.c:895 */
void Mod_LoadVisibility(lump_t *l)
{
if (!l->filelen)
{
loadmodel->visdata = NULL;
return;
}
loadmodel->visdata = (byte*) Hunk_AllocName(l->filelen, loadname);
Q_memcpy(loadmodel->visdata, mod_base + l->fileofs, l->filelen);
}
/* <513a6> ../engine/model.c:913 */
void Mod_LoadEntities(lump_t *l)
{
if (!l->filelen)
{
loadmodel->entities = NULL;
return;
}
loadmodel->entities = (char *)Hunk_AllocName(l->filelen, loadname);
Q_memcpy(loadmodel->entities, (const void *)(mod_base + l->fileofs), l->filelen);
if (loadmodel->entities)
{
char *pszInputStream = COM_Parse(loadmodel->entities);
if (*pszInputStream)
{
while (com_token[0] != '}')
{
if (!Q_strcmp(com_token, "wad"))
{
COM_Parse(pszInputStream);
if (wadpath)
Mem_Free(wadpath);
wadpath = Mem_Strdup(com_token);
return;
}
pszInputStream = COM_Parse(pszInputStream);
if (!*pszInputStream)
return;
}
}
}
}
/* <51a67> ../engine/model.c:950 */
void Mod_LoadVertexes(lump_t *l)
{
dvertex_t *in;
mvertex_t *out;
int i, count;
in = (dvertex_t *)(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 = (mvertex_t*) 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]);
}
}
/* <51ad2> ../engine/model.c:978 */
void Mod_LoadSubmodels(lump_t *l)
{
dmodel_t *in;
dmodel_t *out;
int i, j, count;
in = (dmodel_t *)(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 = (dmodel_t *)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);
}
}
/* <51b45> ../engine/model.c:1014 */
void Mod_LoadEdges(lump_t *l)
{
dedge_t *in;
medge_t *out;
int i, count;
in = (dedge_t *)(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 = (medge_t*) 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]);
}
}
/* <51bb0> ../engine/model.c:1041 */
void Mod_LoadTexinfo(lump_t *l)
{
texinfo_t *in;
mtexinfo_t *out;
int i, j, count;
int _miptex;
float len1, len2;
in = (texinfo_t *)(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 = (mtexinfo_t*) Hunk_AllocName(count*sizeof(*out), loadname);
loadmodel->texinfo = out;
loadmodel->numtexinfo = count;
for (i = 0; i < count; i++, in++, out++)
{
#ifdef REHLDS_FIXES
for (j = 0; j < 4; j++)
{
out->vecs[0][j] = LittleFloat(in->vecs[0][j]);
out->vecs[1][j] = LittleFloat(in->vecs[1][j]);
}
#else
for (j = 0; j < 8; j++)
out->vecs[0][j] = LittleFloat(in->vecs[0][j]);
#endif // REHLDS_FIXES
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;
_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;
}
}
}
}
/* <51c59> ../engine/model.c:1109 */
void CalcSurfaceExtents(msurface_t *s)
{
float mins[2], maxs[2], val;
int i, j, e;
mvertex_t *v;
mtexinfo_t *tex;
int bmins[2], bmaxs[2];
mins[0] = mins[1] = 999999;
maxs[0] = maxs[1] = -99999;
tex = s->texinfo;
for (i = 0; i < s->numedges; i++)
{
e = loadmodel->surfedges[s->firstedge + i];
if (e >= 0)
v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
else
v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
for (j = 0; j < 2; j++)
{
val = v->position[0] * tex->vecs[j][0] +
v->position[1] * tex->vecs[j][1] +
v->position[2] * tex->vecs[j][2] +
tex->vecs[j][3];
if (val < mins[j])
mins[j] = val;
if (val > maxs[j])
maxs[j] = val;
}
}
for (i = 0; i < 2; i++)
{
bmins[i] = (int) floor(mins[i] / 16);
bmaxs[i] = (int) ceil(maxs[i] / 16);
s->texturemins[i] = bmins[i] * 16;
s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
if (!(tex->flags & TEX_SPECIAL) && s->extents[i] > 256)
Sys_Error("Bad surface extents");
}
}
/* <51d09> ../engine/model.c:1161 */
void Mod_LoadFaces(lump_t *l)
{
dface_t *in;
msurface_t *out;
int i, count, surfnum;
int planenum, side;
in = (dface_t *)(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 = (msurface_t *) Hunk_AllocName(count*sizeof(*out), loadname);
loadmodel->surfaces = out;
loadmodel->numsurfaces = count;
for (surfnum = 0; surfnum < count; surfnum++, in++, out++)
{
out->firstedge = LittleLong(in->firstedge);
out->numedges = LittleShort(in->numedges);
out->flags = 0;
planenum = LittleShort(in->planenum);
side = LittleShort(in->side);
if (side)
out->flags |= SURF_PLANEBACK;
out->plane = loadmodel->planes + planenum;
out->texinfo = loadmodel->texinfo + LittleShort(in->texinfo);
CalcSurfaceExtents(out);
// lighting info
for (i = 0; i < MAXLIGHTMAPS; i++)
out->styles[i] = in->styles[i];
i = LittleLong(in->lightofs);
if (i == -1)
out->samples = NULL;
else
out->samples = loadmodel->lightdata + i;
// set the drawing flags flag
const char* texName = out->texinfo->texture->name;
if (!Q_strncmp(texName, "sky", 3)) // sky
{
out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED);
continue;
}
if (!Q_strncmp(texName, "scroll", 6))
{
out->flags |= SURF_DRAWTILED;
out->extents[0] = out->texinfo->texture->width;
out->extents[1] = out->texinfo->texture->height;
continue;
}
if (texName[0] == '!' || !Q_strnicmp(texName, "laser", 5) || !Q_strnicmp(texName, "water", 5)) // turbulent
{
out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED);
for (i = 0; i < 2; i++)
{
out->extents[i] = 16384;
out->texturemins[i] = -8192;
out->texinfo->flags |= TEX_SPECIAL;
}
continue;
}
if (out->texinfo->flags & TEX_SPECIAL)
{
out->flags |= SURF_DRAWTILED;
out->extents[0] = out->texinfo->texture->width;
out->extents[1] = out->texinfo->texture->height;
continue;
}
}
}
/* <51dcc> ../engine/model.c:1262 */
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);
}
/* <51f0a> ../engine/model.c:1276 */
void Mod_LoadNodes(lump_t *l)
{
int i, j, count, p;
dnode_t *in;
mnode_t *out;
in = (dnode_t *)(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 = (mnode_t*) 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
}
/* <51f91> ../engine/model.c:1324 */
void Mod_LoadLeafs(lump_t *l)
{
dleaf_t *in;
mleaf_t *out;
int i, j, count, p;
in = (dleaf_t *)(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 = (mleaf_t*) Hunk_AllocName(count*sizeof(*out), loadname);
loadmodel->leafs = out;
loadmodel->numleafs = 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->contents);
out->contents = p;
out->firstmarksurface = loadmodel->marksurfaces +
LittleShort(in->firstmarksurface);
out->nummarksurfaces = LittleShort(in->nummarksurfaces);
p = LittleLong(in->visofs);
if (p == -1)
out->compressed_vis = NULL;
else
out->compressed_vis = loadmodel->visdata + p;
out->efrags = NULL;
for (j = 0; j < 4; j++)
out->ambient_sound_level[j] = in->ambient_level[j];
}
}
/* <52018> ../engine/model.c:1373 */
void Mod_LoadClipnodes(lump_t *l)
{
dclipnode_t *in, *out;
int i, count;
hull_t *hull;
in = (dclipnode_t *)(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 = (dclipnode_t*) Hunk_AllocName(count*sizeof(*out), loadname);
loadmodel->clipnodes = out;
loadmodel->numclipnodes = count;
hull = &loadmodel->hulls[1];
hull->clipnodes = out;
hull->firstclipnode = 0;
hull->lastclipnode = count - 1;
hull->planes = loadmodel->planes;
hull->clip_mins[0] = -16;
hull->clip_mins[1] = -16;
hull->clip_mins[2] = -36;
hull->clip_maxs[0] = 16;
hull->clip_maxs[1] = 16;
hull->clip_maxs[2] = 36;
hull = &loadmodel->hulls[2];
hull->clipnodes = out;
hull->firstclipnode = 0;
hull->lastclipnode = count - 1;
hull->planes = loadmodel->planes;
hull->clip_mins[0] = -32;
hull->clip_mins[1] = -32;
hull->clip_mins[2] = -32;
hull->clip_maxs[0] = 32;
hull->clip_maxs[1] = 32;
hull->clip_maxs[2] = 32;
hull = &loadmodel->hulls[3];
hull->clipnodes = out;
hull->firstclipnode = 0;
hull->lastclipnode = count - 1;
hull->planes = loadmodel->planes;
hull->clip_mins[0] = -16;
hull->clip_mins[1] = -16;
hull->clip_mins[2] = -18;
hull->clip_maxs[0] = 16;
hull->clip_maxs[1] = 16;
hull->clip_maxs[2] = 18;
for (i = 0; i < count; i++, out++, in++)
{
out->planenum = LittleLong(in->planenum);
out->children[0] = LittleShort(in->children[0]);
out->children[1] = LittleShort(in->children[1]);
}
}
/* <52093> ../engine/model.c:1439 */
void Mod_MakeHull0(void)
{
mnode_t *in, *child;
dclipnode_t *out;
int i, j, count;
hull_t *hull;
hull = &loadmodel->hulls[0];
in = loadmodel->nodes;
count = loadmodel->numnodes;
out = (dclipnode_t*) Hunk_AllocName(count * sizeof(*out), loadname);
hull->clipnodes = out;
hull->firstclipnode = 0;
hull->lastclipnode = count - 1;
hull->planes = loadmodel->planes;
for (i = 0; i < count; i++, out++, in++)
{
out->planenum = in->plane - loadmodel->planes;
for (j = 0; j < 2; j++)
{
child = in->children[j];
if (child->contents < 0)
out->children[j] = child->contents;
else
out->children[j] = child - loadmodel->nodes;
}
}
}
/* <52119> ../engine/model.c:1476 */
void Mod_LoadMarksurfaces(lump_t *l)
{
int i, j, count;
short *in;
msurface_t **out;
in = (short *)(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 = (msurface_t **) Hunk_AllocName(count * sizeof(*out), loadname);
loadmodel->marksurfaces = out;
loadmodel->nummarksurfaces = count;
for (i = 0; i < count; i++)
{
j = LittleShort(in[i]);
if (j >= loadmodel->numsurfaces)
Sys_Error("Mod_ParseMarksurfaces: bad surface number");
out[i] = loadmodel->surfaces + j;
}
}
/* <5218c> ../engine/model.c:1505 */
void Mod_LoadSurfedges(lump_t *l)
{
int i, count;
int *in, *out;
in = (int *)(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 = (int*) Hunk_AllocName(count * sizeof(*out), loadname);
loadmodel->surfedges = out;
loadmodel->numsurfedges = count;
for (i = 0; i < count; i++)
out[i] = LittleLong(in[i]);
}
/* <52215> ../engine/model.c:1528 */
void Mod_LoadPlanes(lump_t *l)
{
int i, j;
mplane_t *out;
dplane_t *in;
int count;
int bits;
in = (dplane_t *)(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 = (mplane_t*) Hunk_AllocName(count * 2 * sizeof(*out), loadname);
loadmodel->planes = out;
loadmodel->numplanes = count;
for (i = 0; i < count; i++, in++, out++)
{
bits = 0;
for (j = 0; j < 3; j++)
{
out->normal[j] = LittleFloat(in->normal[j]);
if (out->normal[j] < 0)
bits |= 1 << j;
}
out->dist = LittleFloat(in->dist);
out->type = LittleLong(in->type);
out->signbits = bits;
}
}
/* <5229e> ../engine/model.c:1566 */
float RadiusFromBounds(vec_t *mins, vec_t *maxs)
{
int i;
vec3_t corner;
for (i = 0; i < 3; i++)
{
corner[i] = fabs(mins[i]) > fabs(maxs[i]) ? fabs(mins[i]) : fabs(maxs[i]);
}
return Length(corner);
}
void Mod_LoadBrushModel(model_t *mod, void *buffer)
{
g_RehldsHookchains.m_Mod_LoadBrushModel.callChain(&Mod_LoadBrushModel_internal, mod, buffer);
}
/* <52314> ../engine/model.c:1584 */
void EXT_FUNC Mod_LoadBrushModel_internal(model_t *mod, void *buffer)
{
dmodel_t *bm;
model_t *submodel;
char name[10];
dheader_t *header = (dheader_t *)buffer;
int i;
loadmodel->type = mod_brush;
i = LittleLong(header->version);
if (i != 29 && i != 30)
Sys_Error("Mod_LoadBrushModel: %s has wrong version number (%i should be %i)", mod, i, 30);
mod_base = (unsigned char*) buffer;
for (i = 0; i < sizeof(dheader_t) / 4; i++)
((int *)header)[i] = LittleLong(((int *)header)[i]);
Mod_LoadVertexes(&header->lumps[3]);
Mod_LoadEdges(&header->lumps[12]);
Mod_LoadSurfedges(&header->lumps[13]);
if (Q_stricmp(com_gamedir, "bshift"))
{
Mod_LoadEntities(&header->lumps[LUMP_ENTITIES]);
Mod_LoadTextures(&header->lumps[LUMP_TEXTURES]);
Mod_LoadLighting(&header->lumps[LUMP_LIGHTING]);
Mod_LoadPlanes(&header->lumps[LUMP_PLANES]);
}
else
{
Mod_LoadEntities(&header->lumps[LUMP_PLANES]);
Mod_LoadTextures(&header->lumps[LUMP_TEXTURES]);
Mod_LoadLighting(&header->lumps[LUMP_LIGHTING]);
Mod_LoadPlanes(&header->lumps[LUMP_ENTITIES]);
}
Mod_LoadTexinfo(&header->lumps[LUMP_TEXINFO]);
Mod_LoadFaces(&header->lumps[LUMP_FACES]);
Mod_LoadMarksurfaces(&header->lumps[LUMP_MARKSURFACES]);
Mod_LoadVisibility(&header->lumps[LUMP_VISIBILITY]);
Mod_LoadLeafs(&header->lumps[LUMP_LEAFS]);
Mod_LoadNodes(&header->lumps[LUMP_NODES]);
Mod_LoadClipnodes(&header->lumps[LUMP_CLIPNODES]);
Mod_LoadSubmodels(&header->lumps[LUMP_MODELS]);
Mod_MakeHull0();
mod->numframes = 2;
mod->flags = 0;
i = 0;
for (i = 0; i < mod->numsubmodels; i++)
{
bm = &mod->submodels[i];
mod->hulls[0].firstclipnode = bm->headnode[0];
for (int j = 1; j < MAX_MAP_HULLS; j++)
{
mod->hulls[j].firstclipnode = bm->headnode[j];
mod->hulls[j].lastclipnode = mod->numclipnodes - 1;
}
mod->firstmodelsurface = bm->firstface;
mod->nummodelsurfaces = bm->numfaces;
mod->maxs[0] = bm->maxs[0];
mod->maxs[2] = bm->maxs[2];
mod->maxs[1] = bm->maxs[1];
mod->mins[0] = bm->mins[0];
mod->mins[1] = bm->mins[1];
mod->mins[2] = bm->mins[2];
mod->radius = RadiusFromBounds(mod->mins, mod->maxs);
mod->numleafs = bm->visleafs;
if (i < mod->numsubmodels - 1)
{
Q_snprintf(name, 10, "*%i", i + 1);
submodel = Mod_FindName(0, name);
*submodel = *mod;
loadmodel = submodel;
Q_strncpy(submodel->name, name, 0x3Fu);
mod = loadmodel;
loadmodel->name[63] = 0;
}
}
}
/* <5255d> ../engine/model.c:1695 */
NOXREF void *Mod_LoadAliasFrame(void *pin, int *pframeindex, int numv, trivertx_t *pbboxmin, trivertx_t *pbboxmax, aliashdr_t *pheader, char *name)
{
trivertx_t *pframe;
trivertx_t *pinframe;
int i;
int j;
daliasframe_t *pdaliasframe = (daliasframe_t *)pin;
Q_strncpy(name, pdaliasframe->name, 15);
name[15] = 0;
for (i = 0; i < 3; i++)
{
pbboxmax->v[i] = pdaliasframe->bboxmax.v[i];
pbboxmin->v[i] = pdaliasframe->bboxmin.v[i];
}
pinframe = (trivertx_t *)(pdaliasframe + 1);
pframe = (trivertx_t *)Hunk_AllocName(sizeof(trivertx_t) * numv, loadname);
*pframeindex = (byte *)pframe - (byte *)pheader;
for (j = 0; j < numv; j++)
{
pframe[j].lightnormalindex = pinframe[j].lightnormalindex;
for (int k = 0; k < 3; k++)
pframe[j].v[k] = pinframe[j].v[k];
}
return (void *)&pinframe[numv];
}
/* <52656> ../engine/model.c:1743 */
NOXREF void *Mod_LoadAliasGroup(void *pin, int *pframeindex, int numv, trivertx_t *pbboxmin, trivertx_t *pbboxmax, aliashdr_t *pheader, char *name)
{
daliasgroup_t *pingroup;
maliasgroup_t *paliasgroup;
int i;
int numframes;
daliasinterval_t *pin_intervals;
float *poutintervals;
void *ptemp;
pingroup = (daliasgroup_t *)pin;
numframes = LittleLong(pingroup->numframes);
paliasgroup = (maliasgroup_t *)Hunk_AllocName(sizeof(paliasgroup->frames[0]) * (numframes - 1) + sizeof(maliasgroup_t), loadname);
paliasgroup->numframes = numframes;
for(i = 0; i < 3; i++)
{
pbboxmin->v[i] = pingroup->bboxmin.v[i];
pbboxmax->v[i] = pingroup->bboxmax.v[i];
}
*pframeindex = (byte *)paliasgroup - (byte *)pheader;
pin_intervals = (daliasinterval_t *)(pingroup + 1);
poutintervals = (float *)Hunk_AllocName(numframes * sizeof(float), loadname);
paliasgroup->intervals = (byte *)poutintervals - (byte *)pheader;
for (i = 0; i < numframes; i++)
{
*poutintervals = LittleFloat(pin_intervals->interval);
if (*poutintervals <= 0.0f)
Sys_Error(__FUNCTION__ ": interval<=0");
poutintervals++;
pin_intervals++;
}
ptemp = (void *)pin_intervals;
for(i = 0; i < numframes; i++)
ptemp = Mod_LoadAliasFrame(ptemp, &paliasgroup->frames[i].frame, numv, &paliasgroup->frames[i].bboxmin, &paliasgroup->frames[i].bboxmax, pheader, name);
return ptemp;
}
/* <5275d> ../engine/model.c:1808 */
NOXREF void *Mod_LoadAliasSkin(void *pin, int *pskinindex, int skinsize, aliashdr_t *pheader)
{
unsigned char *pskin;
unsigned char *pinskin;
//unsigned short *pusskin;
pskin = (unsigned char *)Hunk_AllocName(skinsize * r_pixbytes, loadname);
pinskin = (unsigned char *)pin;
*pskinindex = pskin - (unsigned char *)pheader;
if (r_pixbytes == 1)
Q_memcpy(pskin, pinskin, skinsize);
else if (r_pixbytes != 2)
Sys_Error(__FUNCTION__ ": driver set invalid r_pixbytes: %d\n", r_pixbytes);
return (void *)&pinskin[skinsize];
}
/* <52812> ../engine/model.c:1844 */
NOXREF void *Mod_LoadAliasSkinGroup(void *pin, int *pskinindex, int skinsize, aliashdr_t *pheader)
{
daliasskingroup_t *pinskingroup;
maliasskingroup_t *paliasskingroup;
int i;
int numskins;
daliasskininterval_t *pinskinintervals;
float *poutskinintervals;
void *ptemp;
pinskingroup = (daliasskingroup_t *)pin;
numskins = LittleLong(pinskingroup->numskins);
paliasskingroup = (maliasskingroup_t *)Hunk_AllocName(sizeof(paliasskingroup->skindescs[0]) * (numskins - 1) + sizeof(maliasskingroup_t), loadname);
paliasskingroup->numskins = numskins;
*pskinindex = (byte *)paliasskingroup - (byte *)pheader;
poutskinintervals = (float *)Hunk_AllocName(sizeof(float) * numskins, loadname);
paliasskingroup->intervals = (byte *)poutskinintervals - (byte *)pheader;
pinskinintervals = (daliasskininterval_t *)(pinskingroup + 1);
for(i = 0; i < numskins; i++)
{
*poutskinintervals = LittleFloat(pinskinintervals->interval);
if(*poutskinintervals <= 0.0f)
Sys_Error(__FUNCTION__ ": interval<=0");
poutskinintervals++;
pinskinintervals++;
}
ptemp = (void *)pinskinintervals;
for(i = 0; i < numskins; i++)
ptemp = Mod_LoadAliasSkin(ptemp, &paliasskingroup->skindescs[i].skin, skinsize, pheader);
return ptemp;
}
/* <52936> ../engine/model.c:1900 */
NOXREF void Mod_LoadAliasModel(model_t *mod, void *buffer)
{
int i;
mdl_t *pmodel;
mdl_t *pinmodel;
stvert_t *pstverts;
stvert_t *pinstverts;
aliashdr_t *pheader;
mtriangle_t *ptri;
dtriangle_t *pintriangles;
int version;
int numframes;
int numskins;
int size;
daliasframetype_t *pframetype;
daliasskintype_t *pskintype;
maliasskindesc_t *pskindesc;
int skinsize;
int start;
int end;
int total;
start = Hunk_LowMark();
pinmodel = (mdl_t *)buffer;
version = LittleLong(pinmodel->version);
if (version != ALIAS_MODEL_VERSION)
Sys_Error("%s has wrong version number (%i should be %i)", mod->name, version, ALIAS_MODEL_VERSION);
size = sizeof(mtriangle_t) * LittleLong(pinmodel->numtris) +
sizeof(stvert_t) * LittleLong(pinmodel->numverts) +
sizeof(mdl_t) + sizeof(aliashdr_t) +
sizeof(pheader->frames[0]) * (LittleLong(pinmodel->numframes) - 1);
pheader = (aliashdr_t *)Hunk_AllocName(size, loadname);
pmodel = (mdl_t *)&pheader->frames[LittleLong(pinmodel->numframes)];
mod->flags = LittleLong(pinmodel->flags);
pmodel->boundingradius = LittleFloat(pinmodel->boundingradius);
pmodel->numskins = LittleLong(pinmodel->numskins);
pmodel->skinwidth = LittleLong(pinmodel->skinwidth);
pmodel->skinheight = LittleLong(pinmodel->skinheight);
if (pmodel->skinheight > 480)
Sys_Error("model %s has a skin taller than %d", mod->name, 480);
pmodel->numverts = LittleLong(pinmodel->numverts);
if (pmodel->numverts < 1)
Sys_Error("model %s has no vertices", mod->name);
if (pmodel->numverts > 2000)
Sys_Error("model %s has too many vertices", mod->name);
pmodel->numtris = LittleLong(pinmodel->numtris);
if (pmodel->numtris < 1)
Sys_Error("model %s has no triangles", mod->name);
pmodel->numframes = LittleLong(pinmodel->numframes);
pmodel->size = LittleFloat(pinmodel->size) * 0.09090909090909091;
mod->synctype = (synctype_t)LittleLong(pinmodel->synctype);
mod->numframes = pmodel->numframes;
for (i = 0; i < 3; i++)
{
pmodel->scale[i] = LittleFloat(pinmodel->scale[i]);
pmodel->scale_origin[i] = LittleFloat(pinmodel->scale_origin[i]);
pmodel->eyeposition[i] = LittleFloat(pinmodel->eyeposition[i]);
}
numskins = pmodel->numskins;
numframes = pmodel->numframes;
if (pmodel->skinwidth & 3)
Sys_Error(__FUNCTION__ ": skinwidth not multiple of 4");
pheader->model = (byte *)pmodel - (byte *)pheader;
skinsize = pmodel->skinwidth * pmodel->skinheight;
if (numskins < 1)
Sys_Error(__FUNCTION__ ": Invalid # of skins: %d\n", numskins);
pskintype = (daliasskintype_t *)&pinmodel[1];
pskindesc = (maliasskindesc_t *)Hunk_AllocName(sizeof(maliasskindesc_t) * numskins, loadname);
pheader->skindesc = (byte *)pskintype - (byte *)pheader;
for(i = 0; i < numskins; i++)
{
aliasskintype_t skintype = (aliasskintype_t)LittleLong(pskintype->type);
pskindesc[i].type = skintype;
if(skintype == ALIAS_SKIN_SINGLE)
pskintype = (daliasskintype_t *)Mod_LoadAliasSkin(&pskintype[1], &pskindesc[i].skin, skinsize, pheader);
else
pskintype = (daliasskintype_t *)Mod_LoadAliasSkinGroup(&pskintype[1], &pskindesc[i].skin, skinsize, pheader);
}
pstverts = (stvert_t *)&pmodel[1];
pinstverts = (stvert_t *)pskintype;
pheader->stverts = (byte *)pstverts - (byte *)pheader;
for(i = 0; i < pmodel->numverts; i++)
{
pstverts[i].onseam = LittleLong(pinstverts[i].onseam);
pstverts[i].s = (LittleLong(pinstverts[i].s) << 16);
pstverts[i].t = (LittleLong(pinstverts[i].t) << 16);
}
ptri = (mtriangle_t *)&pstverts[pmodel->numverts];
pintriangles = (dtriangle_t *)&pinstverts[pmodel->numverts];
pheader->triangles = (byte *)ptri - (byte *)pheader;
for(i = 0; i < pmodel->numtris; i++)
{
ptri[i].facesfront = LittleLong(pintriangles[i].facesfront);
for(int j = 0; j < 3; j++)
ptri[i].vertindex[j] = LittleLong(pintriangles[i].vertindex[j]);
}
if(numframes < 1)
Sys_Error(__FUNCTION__ ": Invalid # of frames: %d\n", numframes);
pframetype = (daliasframetype_t *)&pintriangles[pmodel->numtris];
for(i = 0; i < numframes; i++)
{
aliasframetype_t frametype = (aliasframetype_t)LittleLong(pframetype->type);
pheader->frames[i].type = frametype;
if(frametype == ALIAS_SINGLE)
pframetype = (daliasframetype_t *)Mod_LoadAliasFrame(&pframetype[1], &pheader->frames[i].frame, pmodel->numverts, &pheader->frames[i].bboxmin, &pheader->frames[i].bboxmax, pheader, pheader->frames[i].name);
else
pframetype = (daliasframetype_t *)Mod_LoadAliasGroup(&pframetype[1], &pheader->frames[i].frame, pmodel->numverts, &pheader->frames[i].bboxmin, &pheader->frames[i].bboxmax, pheader, pheader->frames[i].name);
}
mod->type = mod_alias;
mod->mins[0] = -16.0f;
mod->mins[1] = -16.0f;
mod->mins[2] = -16.0f;
mod->maxs[0] = 16.0f;
mod->maxs[1] = 16.0f;
mod->maxs[2] = 16.0f;
const int dada = sizeof(color24);
PackedColorVec *pPal = (PackedColorVec *)Hunk_AllocName(sizeof(PackedColorVec) * 256, loadname);
color24 *pPalSrc = (color24 *)&pframetype[0];
for (i = 0; i < 256; i++)
{
pPal[i].b = pPalSrc->r;
pPal[i].g = pPalSrc->g;
pPal[i].r = pPalSrc->b;
pPal[i].a = 0;
pPalSrc++;
}
pheader->palette = (byte *)pPal - (byte *)pheader;
end = Hunk_LowMark();
total = end - start;
Cache_Alloc(&mod->cache, total, loadname);
if(mod->cache.data)
{
Q_memcpy(mod->cache.data, pheader, total);
Hunk_FreeToLowMark(start);
}
}
/* <52b76> ../engine/model.c:2150 */
void *Mod_LoadSpriteFrame(void *pin, mspriteframe_t **ppframe)
{
dspriteframe_t *pinframe;
mspriteframe_t *pspriteframe;
int width, height, size, origin[2];
unsigned short *ppixout;
byte *ppixin;
pinframe = (dspriteframe_t *)pin;
width = LittleLong(pinframe->width);
height = LittleLong(pinframe->height);
size = width * height;
pspriteframe = (mspriteframe_t*) Hunk_AllocName(sizeof(mspriteframe_t) + size * r_pixbytes, loadname);
Q_memset(pspriteframe, 0, sizeof(mspriteframe_t) + size);
*ppframe = pspriteframe;
pspriteframe->width = width;
pspriteframe->height = height;
origin[0] = LittleLong(pinframe->origin[0]);
origin[1] = LittleLong(pinframe->origin[1]);
pspriteframe->up = (float)origin[1];
pspriteframe->down = (float)(origin[1] - height);
pspriteframe->left = (float)origin[0];
pspriteframe->right = (float)(width + origin[0]);
if (r_pixbytes == 1)
{
Q_memcpy(&pspriteframe->pixels[0], (byte *)(pinframe + 1), size);
}
else if (r_pixbytes == 2)
{
ppixin = (byte *)(pinframe + 1);
ppixout = (unsigned short *)&pspriteframe->pixels[0];
/*
//seems to be disabled on server
for (i = 0; i < size; i++)
ppixout[i] = d_8to16table[ppixin[i]];
*/
}
else
{
Sys_Error("Mod_LoadSpriteFrame: driver set invalid r_pixbytes: %d\n", r_pixbytes);
}
return (void *)((byte *)pinframe + sizeof(dspriteframe_t) + size);
}
/* <52c36> ../engine/model.c:2204 */
void *Mod_LoadSpriteGroup(void *pin, mspriteframe_t **ppframe)
{
dspritegroup_t *pingroup;
mspritegroup_t *pspritegroup;
int i, numframes;
dspriteinterval_t *pin_intervals;
float *poutintervals;
void *ptemp;
pingroup = (dspritegroup_t *)pin;
numframes = LittleLong(pingroup->numframes);
pspritegroup = (mspritegroup_t*)Hunk_AllocName(sizeof(mspritegroup_t) + (numframes - 1) * sizeof(pspritegroup->frames[0]), loadname);
pspritegroup->numframes = numframes;
*ppframe = (mspriteframe_t *)pspritegroup;
pin_intervals = (dspriteinterval_t *)(pingroup + 1);
poutintervals = (float*)Hunk_AllocName(numframes * sizeof(float), loadname);
pspritegroup->intervals = poutintervals;
for (i = 0; i < numframes; i++)
{
*poutintervals = LittleFloat(pin_intervals->interval);
if (*poutintervals <= 0.0f)
Sys_Error(__FUNCTION__ ": interval<=0");
poutintervals++;
pin_intervals++;
}
ptemp = (void *)pin_intervals;
for (i = 0; i < numframes; i++)
{
ptemp = Mod_LoadSpriteFrame(ptemp, &pspritegroup->frames[i]);
}
return ptemp;
}
/* <52cf2> ../engine/model.c:2256 */
void Mod_LoadSpriteModel(model_t *mod, void *buffer)
{
int i;
int version;
dsprite_t *pin;
msprite_t *psprite;
int numframes;
int size;
dspriteframetype_t *pframetype;
pin = (dsprite_t *)buffer;
version = LittleLong(pin->version);
if (version != SPRITE_VERSION)
Sys_Error("%s has wrong version number "
"(%i should be %i)", mod->name, version, SPRITE_VERSION);
numframes = LittleLong(pin->numframes);
int palsize = *(uint16*)&pin[1];
size = sizeof(msprite_t) + (numframes - 1) * sizeof(psprite->frames) + 2 + 8 * palsize;
psprite = (msprite_t*) Hunk_AllocName(size, loadname);
mod->cache.data = psprite;
psprite->type = LittleLong(pin->type);
psprite->maxwidth = LittleLong(pin->width);
psprite->maxheight = LittleLong(pin->height);
psprite->beamlength = LittleFloat(pin->beamlength);
mod->synctype = (synctype_t) LittleLong(pin->synctype);
psprite->numframes = numframes;
mod->mins[0] = mod->mins[1] = float(-psprite->maxwidth / 2);
mod->maxs[0] = mod->maxs[1] = float(psprite->maxwidth / 2);
mod->mins[2] = float (- psprite->maxheight / 2);
mod->maxs[2] = float(psprite->maxheight / 2);
unsigned char *palsrc = (unsigned char*)(&pin[1]) + 2; //header + palette size
uint16* paldest = (uint16*)((char*)(psprite + 1) + sizeof(psprite->frames) * (numframes - 1)); //sprite + [frames-1]
*(paldest++) = palsize; //write palette size
for (i = 0; i < palsize; i++, paldest += 4, palsrc += 3)
{
paldest[3] = 0;
paldest[0] = palsrc[0];
paldest[1] = palsrc[1];
paldest[2] = palsrc[2];
}
//
// load the frames
//
if (numframes < 1)
Sys_Error(__FUNCTION__ ": Invalid # of frames: %d\n", numframes);
mod->numframes = numframes;
mod->flags = 0;
pframetype = (dspriteframetype_t *)((char*)(pin + 1) + 2 + 3*palsize);
for (i = 0; i < numframes; i++)
{
spriteframetype_t frametype;
frametype = (spriteframetype_t) LittleLong(pframetype->type);
psprite->frames[i].type = frametype;
if (frametype == SPR_SINGLE)
{
pframetype = (dspriteframetype_t *)
Mod_LoadSpriteFrame(pframetype + 1,
&psprite->frames[i].frameptr);
}
else
{
pframetype = (dspriteframetype_t *)
Mod_LoadSpriteGroup(pframetype + 1,
&psprite->frames[i].frameptr);
}
}
mod->type = mod_sprite;
}
/* <5300a> ../engine/model.c:2360 */
NOXREF void Mod_UnloadSpriteTextures(model_t *pModel)
{
if (!pModel)
return;
if (pModel->type == mod_sprite)
{
pModel->needload = NL_NEEDS_LOADED;
#ifndef SWDS
char name[256];
msprite_t *spt = (msprite_t *)pModel->cache.data;
if (spt)
{
for (int i = 0; i < spt->numframes; i++)
{
Q_sprintf(name, "%s_%i", pModel->name, i);
GL_UnloadTexture(name);
}
}
#endif // SWDS
}
}
/* <53033> ../engine/model.c:2376 */
void Mod_Print(void)
{
int i;
model_t *mod;
Con_Printf("Cached models:\n");
for (i = 0, mod = mod_known; i < mod_numknown; i++, mod++)
{
Con_Printf("%8p : %s", mod->cache.data, mod->name);
if (mod->needload & NL_UNREFERENCED)
Con_Printf(" (!R)");
if (mod->needload & NL_NEEDS_LOADED)
Con_Printf(" (!P)");
Con_Printf("\n");
}
}
/* <5306c> ../engine/model.c:2399 */
NOXREF void Mod_ChangeGame(void)
{
int i;
model_t *mod;
mod_known_info_t *p;
for (i = 0; i < mod_numknown; i++)
{
mod = &mod_known[i];
if (mod->type == mod_studio)
{
if (Cache_Check(&mod->cache))
Cache_Free(&mod->cache);
}
p = &mod_known_info[i];
p->firstCRCDone = FALSE;
p->initialCRC = 0;
}
}