mirror of https://github.com/FWGS/xash3d-fwgs
engine: fix alias model loading
This commit is contained in:
parent
a133b1c2a9
commit
0f8f35b415
|
@ -488,7 +488,8 @@ typedef struct
|
|||
int flags;
|
||||
float size;
|
||||
|
||||
int reserved[8]; // VBO offsets
|
||||
const trivertex_t **pposeverts; // only valid during loading, used to build GL mesh
|
||||
intptr_t reserved[7]; // VBO offsets
|
||||
|
||||
int numposes;
|
||||
int poseverts;
|
||||
|
|
|
@ -0,0 +1,241 @@
|
|||
/*
|
||||
mod_alias.c - alias model loading
|
||||
Copyright (C) 2010 Uncle Mike
|
||||
Copyright (C) 2024 Alibek Omarov
|
||||
|
||||
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 3 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.
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "alias.h"
|
||||
#if !XASH_DEDICATED
|
||||
#include "ref_common.h"
|
||||
#endif // XASH_DEDICATED
|
||||
#include "mod_local.h"
|
||||
#include "xash3d_mathlib.h"
|
||||
|
||||
static int g_posenum = 0;
|
||||
static const trivertex_t *g_poseverts[MAXALIASFRAMES];
|
||||
|
||||
static const void *Mod_LoadAliasFrame( const daliasframe_t *pdaliasframe, maliasframedesc_t *frame, const aliashdr_t *aliashdr )
|
||||
{
|
||||
const trivertex_t *pinframe;
|
||||
int i;
|
||||
|
||||
Q_strncpy( frame->name, pdaliasframe->name, sizeof( frame->name ));
|
||||
frame->firstpose = g_posenum;
|
||||
frame->numposes = 1;
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
frame->bboxmin.v[i] = pdaliasframe->bboxmin.v[i];
|
||||
frame->bboxmax.v[i] = pdaliasframe->bboxmax.v[i];
|
||||
}
|
||||
|
||||
pinframe = (const trivertex_t *)(pdaliasframe + 1);
|
||||
|
||||
g_poseverts[g_posenum] = pinframe;
|
||||
g_posenum++;
|
||||
|
||||
pinframe += aliashdr->numverts;
|
||||
|
||||
return (void *)pinframe;
|
||||
}
|
||||
|
||||
static const void *Mod_LoadAliasGroup( const daliasgroup_t *pingroup, maliasframedesc_t *frame, const aliashdr_t *aliashdr )
|
||||
{
|
||||
const daliasinterval_t *pin_intervals;
|
||||
const void *ptemp;
|
||||
int i, numframes;
|
||||
|
||||
frame->firstpose = g_posenum;
|
||||
frame->numposes = numframes = pingroup->numframes;
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
frame->bboxmin.v[i] = pingroup->bboxmin.v[i];
|
||||
frame->bboxmax.v[i] = pingroup->bboxmax.v[i];
|
||||
}
|
||||
|
||||
pin_intervals = (const daliasinterval_t *)(pingroup + 1);
|
||||
|
||||
// all the intervals are always equal 0.1 so we don't care about them
|
||||
frame->interval = pin_intervals->interval;
|
||||
pin_intervals += numframes;
|
||||
ptemp = (void *)pin_intervals;
|
||||
|
||||
for( i = 0; i < numframes; i++ )
|
||||
{
|
||||
g_poseverts[g_posenum] = (const trivertex_t *)((const daliasframe_t *)ptemp + 1);
|
||||
ptemp = g_poseverts[g_posenum] + aliashdr->numverts;
|
||||
g_posenum++;
|
||||
}
|
||||
|
||||
return ptemp;
|
||||
}
|
||||
|
||||
static void Mod_CalcAliasBounds( model_t *mod, const aliashdr_t *aliashdr )
|
||||
{
|
||||
int i, j, k;
|
||||
float radius;
|
||||
float dist;
|
||||
vec3_t v;
|
||||
|
||||
ClearBounds( mod->mins, mod->maxs );
|
||||
radius = 0.0f;
|
||||
|
||||
// process verts
|
||||
for( i = 0; i < aliashdr->numposes; i++ )
|
||||
{
|
||||
for( j = 0; j < aliashdr->numverts; j++ )
|
||||
{
|
||||
for( k = 0; k < 3; k++ )
|
||||
v[k] = g_poseverts[i][j].v[k] * aliashdr->scale[k] + aliashdr->scale_origin[k];
|
||||
|
||||
AddPointToBounds( v, mod->mins, mod->maxs );
|
||||
dist = DotProduct( v, v );
|
||||
|
||||
if( radius < dist )
|
||||
radius = dist;
|
||||
}
|
||||
}
|
||||
|
||||
mod->radius = sqrt( radius );
|
||||
}
|
||||
|
||||
static const void *Mod_LoadAllSkins( model_t *mod, int numskins, const daliasskintype_t *pskintype, const aliashdr_t *aliashdr )
|
||||
{
|
||||
int i, size;
|
||||
|
||||
if(( numskins < 1 ) || ( numskins > MAX_SKINS ))
|
||||
Host_Error( "%s: Invalid # of skins: %d\n", __func__, numskins );
|
||||
|
||||
size = aliashdr->skinwidth * aliashdr->skinheight;
|
||||
|
||||
// just skipping textures, renderer will take care of them later
|
||||
for( i = 0; i < numskins; i++ )
|
||||
{
|
||||
if( pskintype->type == ALIAS_SKIN_SINGLE )
|
||||
{
|
||||
const byte *ptexture = (const byte *)&pskintype[1];
|
||||
|
||||
pskintype = (const daliasskintype_t *)( ptexture + size );
|
||||
}
|
||||
else
|
||||
{
|
||||
const daliasskingroup_t *pinskingroup = (const daliasskingroup_t *)&pskintype[1];
|
||||
const daliasskininterval_t *pinskinintervals = (const daliasskininterval_t *)&pinskingroup[1];
|
||||
const byte *ptexture = (const byte *)&pinskinintervals[pinskingroup->numskins];
|
||||
|
||||
pskintype = (const daliasskintype_t *)( ptexture + size );
|
||||
}
|
||||
}
|
||||
|
||||
return pskintype;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
====================
|
||||
Mod_LoadAliasModel
|
||||
|
||||
load alias model
|
||||
====================
|
||||
*/
|
||||
void Mod_LoadAliasModel( model_t *mod, const void *buffer, qboolean *loaded )
|
||||
{
|
||||
const daliasframetype_t *pframetype;
|
||||
const daliasskintype_t *pskintype;
|
||||
const dtriangle_t *pintriangles;
|
||||
const daliashdr_t *pinmodel;
|
||||
const stvert_t *pinstverts;
|
||||
aliashdr_t *m_pAliasHeader;
|
||||
size_t size;
|
||||
char poolname[MAX_VA_STRING];
|
||||
int i;
|
||||
|
||||
if( loaded ) *loaded = false;
|
||||
pinmodel = (const daliashdr_t *)buffer;
|
||||
i = pinmodel->version;
|
||||
|
||||
if( i != ALIAS_VERSION )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "%s has wrong version number (%i should be %i)\n", mod->name, i, ALIAS_VERSION );
|
||||
return;
|
||||
}
|
||||
|
||||
if( pinmodel->numverts <= 0 || pinmodel->numtris <= 0 || pinmodel->numframes <= 0 )
|
||||
return; // how is it possible to make that?
|
||||
|
||||
Q_snprintf( poolname, sizeof( poolname ), "^2%s^7", mod->name );
|
||||
mod->mempool = Mem_AllocPool( poolname );
|
||||
|
||||
size = sizeof( aliashdr_t ) + (pinmodel->numframes - 1) * sizeof( maliasframedesc_t );
|
||||
mod->cache.data = m_pAliasHeader = Mem_Calloc( mod->mempool, size );
|
||||
|
||||
// endian-adjust and copy the data, starting with the alias model header
|
||||
m_pAliasHeader->numverts = pinmodel->numverts;
|
||||
|
||||
if( m_pAliasHeader->numverts > MAXALIASVERTS )
|
||||
{
|
||||
Con_DPrintf( S_ERROR "model %s has too many vertices\n", mod->name );
|
||||
return;
|
||||
}
|
||||
|
||||
mod->flags = pinmodel->flags; // share effects flags
|
||||
m_pAliasHeader->boundingradius = pinmodel->boundingradius;
|
||||
m_pAliasHeader->numskins = pinmodel->numskins;
|
||||
m_pAliasHeader->skinwidth = pinmodel->skinwidth;
|
||||
m_pAliasHeader->skinheight = pinmodel->skinheight;
|
||||
m_pAliasHeader->numtris = pinmodel->numtris;
|
||||
mod->numframes = m_pAliasHeader->numframes = pinmodel->numframes;
|
||||
m_pAliasHeader->size = pinmodel->size;
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
m_pAliasHeader->scale[i] = pinmodel->scale[i];
|
||||
m_pAliasHeader->scale_origin[i] = pinmodel->scale_origin[i];
|
||||
m_pAliasHeader->eyeposition[i] = pinmodel->eyeposition[i];
|
||||
}
|
||||
|
||||
// load the skins
|
||||
pskintype = (const daliasskintype_t *)&pinmodel[1];
|
||||
pskintype = Mod_LoadAllSkins( mod, m_pAliasHeader->numskins, pskintype, m_pAliasHeader );
|
||||
// will be done at renderer side...
|
||||
|
||||
// load base s and t vertices
|
||||
pinstverts = (const stvert_t *)pskintype;
|
||||
// will be done at renderer side...
|
||||
|
||||
// load triangle lists
|
||||
pintriangles = (const dtriangle_t *)&pinstverts[m_pAliasHeader->numverts];
|
||||
// will be done at renderer side
|
||||
|
||||
// load the frames
|
||||
pframetype = (const daliasframetype_t *)&pintriangles[m_pAliasHeader->numtris];
|
||||
m_pAliasHeader->pposeverts = g_poseverts; // store the pointer to be accessed by renderer
|
||||
g_posenum = 0;
|
||||
|
||||
for( i = 0; i < m_pAliasHeader->numframes; i++ )
|
||||
{
|
||||
aliasframetype_t frametype = pframetype->type;
|
||||
|
||||
if( frametype == ALIAS_SINGLE )
|
||||
pframetype = (const daliasframetype_t *)Mod_LoadAliasFrame((const daliasframe_t *)&pframetype[1], &m_pAliasHeader->frames[i], m_pAliasHeader );
|
||||
else pframetype = (const daliasframetype_t *)Mod_LoadAliasGroup(( const daliasgroup_t *)&pframetype[1], &m_pAliasHeader->frames[i], m_pAliasHeader );
|
||||
}
|
||||
|
||||
m_pAliasHeader->numposes = g_posenum;
|
||||
Mod_CalcAliasBounds( mod, m_pAliasHeader );
|
||||
mod->type = mod_alias;
|
||||
|
||||
if( loaded ) *loaded = true; // done
|
||||
}
|
|
@ -149,6 +149,11 @@ qboolean Mod_ValidateCRC( const char *name, CRC32_t crc );
|
|||
void Mod_NeedCRC( const char *name, qboolean needCRC );
|
||||
void Mod_FreeUnused( void );
|
||||
|
||||
//
|
||||
// mod_alias.c
|
||||
//
|
||||
void Mod_LoadAliasModel( model_t *mod, const void *buffer, qboolean *loaded );
|
||||
|
||||
//
|
||||
// mod_bmodel.c
|
||||
//
|
||||
|
|
|
@ -303,8 +303,7 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash )
|
|||
Mod_LoadSpriteModel( mod, buf, &loaded );
|
||||
break;
|
||||
case IDALIASHEADER:
|
||||
// REFTODO: move server-related code here
|
||||
loaded = true;
|
||||
Mod_LoadAliasModel( mod, buf, &loaded );
|
||||
break;
|
||||
case Q1BSP_VERSION:
|
||||
case HLBSP_VERSION:
|
||||
|
@ -317,6 +316,7 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash )
|
|||
else Con_Printf( S_ERROR "%s has unknown format\n", tempname );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if( loaded )
|
||||
{
|
||||
if( world.loading )
|
||||
|
@ -338,6 +338,13 @@ model_t *Mod_LoadModel( model_t *mod, qboolean crash )
|
|||
#endif
|
||||
}
|
||||
|
||||
if( mod->type == mod_alias )
|
||||
{
|
||||
aliashdr_t *hdr = mod->cache.data;
|
||||
if( hdr ) // clean up temporary pointer after passing the alias model to the renderer
|
||||
hdr->pposeverts = NULL;
|
||||
}
|
||||
|
||||
if( !loaded )
|
||||
{
|
||||
Mod_FreeModel( mod );
|
||||
|
|
|
@ -52,15 +52,10 @@ ALIAS MODEL DISPLAY LIST GENERATION
|
|||
*/
|
||||
static qboolean m_fDoRemap;
|
||||
static aliashdr_t *m_pAliasHeader;
|
||||
static trivertex_t *g_poseverts[MAXALIASFRAMES];
|
||||
static dtriangle_t g_triangles[MAXALIASTRIS];
|
||||
static stvert_t g_stverts[MAXALIASVERTS];
|
||||
static int g_used[8192];
|
||||
|
||||
// a pose is a single set of vertexes. a frame may be
|
||||
// an animating sequence of poses
|
||||
static int g_posenum;
|
||||
|
||||
// the command list holds counts and s/t values that are valid for
|
||||
// every frame
|
||||
static int g_commands[8192];
|
||||
|
@ -324,7 +319,7 @@ static void GL_MakeAliasModelDisplayLists( model_t *m )
|
|||
for( i = 0; i < m_pAliasHeader->numposes; i++ )
|
||||
{
|
||||
for( j = 0; j < g_numorder; j++ )
|
||||
*verts++ = g_poseverts[i][g_vertexorder[j]];
|
||||
*verts++ = m_pAliasHeader->pposeverts[i][g_vertexorder[j]];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -335,85 +330,14 @@ ALIAS MODELS
|
|||
|
||||
==============================================================================
|
||||
*/
|
||||
/*
|
||||
=================
|
||||
Mod_LoadAliasFrame
|
||||
=================
|
||||
*/
|
||||
static void *Mod_LoadAliasFrame( void *pin, maliasframedesc_t *frame )
|
||||
{
|
||||
daliasframe_t *pdaliasframe;
|
||||
trivertex_t *pinframe;
|
||||
int i;
|
||||
|
||||
pdaliasframe = (daliasframe_t *)pin;
|
||||
|
||||
Q_strncpy( frame->name, pdaliasframe->name, sizeof( frame->name ));
|
||||
frame->firstpose = g_posenum;
|
||||
frame->numposes = 1;
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
frame->bboxmin.v[i] = pdaliasframe->bboxmin.v[i];
|
||||
frame->bboxmax.v[i] = pdaliasframe->bboxmax.v[i];
|
||||
}
|
||||
|
||||
pinframe = (trivertex_t *)(pdaliasframe + 1);
|
||||
|
||||
g_poseverts[g_posenum] = (trivertex_t *)pinframe;
|
||||
pinframe += m_pAliasHeader->numverts;
|
||||
g_posenum++;
|
||||
|
||||
return (void *)pinframe;
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
Mod_LoadAliasGroup
|
||||
=================
|
||||
*/
|
||||
static void *Mod_LoadAliasGroup( void *pin, maliasframedesc_t *frame )
|
||||
{
|
||||
daliasgroup_t *pingroup;
|
||||
int i, numframes;
|
||||
daliasinterval_t *pin_intervals;
|
||||
void *ptemp;
|
||||
|
||||
pingroup = (daliasgroup_t *)pin;
|
||||
numframes = pingroup->numframes;
|
||||
|
||||
frame->firstpose = g_posenum;
|
||||
frame->numposes = numframes;
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
frame->bboxmin.v[i] = pingroup->bboxmin.v[i];
|
||||
frame->bboxmax.v[i] = pingroup->bboxmax.v[i];
|
||||
}
|
||||
|
||||
pin_intervals = (daliasinterval_t *)(pingroup + 1);
|
||||
|
||||
// all the intervals are always equal 0.1 so we don't care about them
|
||||
frame->interval = pin_intervals->interval;
|
||||
pin_intervals += numframes;
|
||||
ptemp = (void *)pin_intervals;
|
||||
|
||||
for( i = 0; i < numframes; i++ )
|
||||
{
|
||||
g_poseverts[g_posenum] = (trivertex_t *)((daliasframe_t *)ptemp + 1);
|
||||
ptemp = (trivertex_t *)((daliasframe_t *)ptemp + 1) + m_pAliasHeader->numverts;
|
||||
g_posenum++;
|
||||
}
|
||||
|
||||
return ptemp;
|
||||
}
|
||||
|
||||
/*
|
||||
===============
|
||||
Mod_CreateSkinData
|
||||
===============
|
||||
*/
|
||||
static rgbdata_t *Mod_CreateSkinData( model_t *mod, byte *data, int width, int height )
|
||||
static rgbdata_t *Mod_CreateSkinData( model_t *mod, const byte *data, int width, int height )
|
||||
{
|
||||
static rgbdata_t skin;
|
||||
char name[MAX_QPATH];
|
||||
|
@ -426,7 +350,7 @@ static rgbdata_t *Mod_CreateSkinData( model_t *mod, byte *data, int width, int h
|
|||
skin.flags = IMAGE_HAS_COLOR|IMAGE_QUAKEPAL;
|
||||
skin.encode = DXT_ENCODE_DEFAULT;
|
||||
skin.numMips = 1;
|
||||
skin.buffer = data;
|
||||
skin.buffer = (byte *)data;
|
||||
skin.palette = (byte *)tr.palette;
|
||||
skin.size = width * height;
|
||||
|
||||
|
@ -475,67 +399,68 @@ static rgbdata_t *Mod_CreateSkinData( model_t *mod, byte *data, int width, int h
|
|||
return gEngfuncs.FS_CopyImage( &skin );
|
||||
}
|
||||
|
||||
static void *Mod_LoadSingleSkin( model_t *loadmodel, daliasskintype_t *pskintype, int skinnum, int size )
|
||||
static const void *Mod_LoadSingleSkin( model_t *loadmodel, const daliasskintype_t *pskintype, int skinnum, int size )
|
||||
{
|
||||
string name, lumaname;
|
||||
string checkname;
|
||||
rgbdata_t *pic;
|
||||
const byte *ptexture = (const byte *)&pskintype[1];
|
||||
rgbdata_t *pic;
|
||||
string name, lumaname, checkname;
|
||||
|
||||
Q_snprintf( name, sizeof( name ), "%s:frame%i", loadmodel->name, skinnum );
|
||||
Q_snprintf( lumaname, sizeof( lumaname ), "%s:luma%i", loadmodel->name, skinnum );
|
||||
Q_snprintf( checkname, sizeof( checkname ), "%s_%i.tga", loadmodel->name, skinnum );
|
||||
if( !gEngfuncs.fsapi->FileExists( checkname, false ) || ( pic = gEngfuncs.FS_LoadImage( checkname, NULL, 0 )) == NULL )
|
||||
pic = Mod_CreateSkinData( loadmodel, (byte *)(pskintype + 1), m_pAliasHeader->skinwidth, m_pAliasHeader->skinheight );
|
||||
pic = Mod_CreateSkinData( loadmodel, ptexture, m_pAliasHeader->skinwidth, m_pAliasHeader->skinheight );
|
||||
|
||||
m_pAliasHeader->gl_texturenum[skinnum][0] =
|
||||
m_pAliasHeader->gl_texturenum[skinnum][1] =
|
||||
m_pAliasHeader->gl_texturenum[skinnum][2] =
|
||||
m_pAliasHeader->gl_texturenum[skinnum][3] = GL_LoadTextureInternal( name, pic, 0 );
|
||||
m_pAliasHeader->gl_texturenum[skinnum][1] =
|
||||
m_pAliasHeader->gl_texturenum[skinnum][2] =
|
||||
m_pAliasHeader->gl_texturenum[skinnum][3] = GL_LoadTextureInternal( name, pic, 0 );
|
||||
gEngfuncs.FS_FreeImage( pic );
|
||||
|
||||
if( R_GetTexture( m_pAliasHeader->gl_texturenum[skinnum][0] )->flags & TF_HAS_LUMA )
|
||||
if( FBitSet( R_GetTexture( m_pAliasHeader->gl_texturenum[skinnum][0] )->flags, TF_HAS_LUMA ))
|
||||
{
|
||||
pic = Mod_CreateSkinData( NULL, (byte *)(pskintype + 1), m_pAliasHeader->skinwidth, m_pAliasHeader->skinheight );
|
||||
Q_snprintf( lumaname, sizeof( lumaname ), "%s:luma%i", loadmodel->name, skinnum );
|
||||
|
||||
pic = Mod_CreateSkinData( NULL, ptexture, m_pAliasHeader->skinwidth, m_pAliasHeader->skinheight );
|
||||
m_pAliasHeader->fb_texturenum[skinnum][0] =
|
||||
m_pAliasHeader->fb_texturenum[skinnum][1] =
|
||||
m_pAliasHeader->fb_texturenum[skinnum][2] =
|
||||
m_pAliasHeader->fb_texturenum[skinnum][3] = GL_LoadTextureInternal( lumaname, pic, TF_MAKELUMA );
|
||||
m_pAliasHeader->fb_texturenum[skinnum][1] =
|
||||
m_pAliasHeader->fb_texturenum[skinnum][2] =
|
||||
m_pAliasHeader->fb_texturenum[skinnum][3] = GL_LoadTextureInternal( lumaname, pic, TF_MAKELUMA );
|
||||
gEngfuncs.FS_FreeImage( pic );
|
||||
}
|
||||
|
||||
return ((byte *)(pskintype + 1) + size);
|
||||
return ptexture + size;
|
||||
}
|
||||
|
||||
static void *Mod_LoadGroupSkin( model_t *loadmodel, daliasskintype_t *pskintype, int skinnum, int size )
|
||||
static const void *Mod_LoadGroupSkin( model_t *loadmodel, const daliasskintype_t *pskintype, int skinnum, int size )
|
||||
{
|
||||
daliasskininterval_t *pinskinintervals;
|
||||
daliasskingroup_t *pinskingroup;
|
||||
string name, lumaname;
|
||||
rgbdata_t *pic;
|
||||
int i, j;
|
||||
const daliasskininterval_t *pinskinintervals;
|
||||
const daliasskingroup_t *pinskingroup;
|
||||
const byte *ptexture;
|
||||
rgbdata_t *pic;
|
||||
string name, lumaname;
|
||||
int i, j;
|
||||
|
||||
// animating skin group. yuck.
|
||||
pskintype++;
|
||||
pinskingroup = (daliasskingroup_t *)pskintype;
|
||||
pinskinintervals = (daliasskininterval_t *)(pinskingroup + 1);
|
||||
pskintype = (void *)(pinskinintervals + pinskingroup->numskins);
|
||||
pinskingroup = (const daliasskingroup_t *)&pskintype[1];
|
||||
pinskinintervals = (const daliasskininterval_t *)(&pinskingroup[1]);
|
||||
ptexture = (const byte *)&pinskinintervals[pinskingroup->numskins];
|
||||
|
||||
for( i = 0; i < pinskingroup->numskins; i++ )
|
||||
{
|
||||
Q_snprintf( name, sizeof( name ), "%s_%i_%i", loadmodel->name, skinnum, i );
|
||||
pic = Mod_CreateSkinData( loadmodel, (byte *)(pskintype), m_pAliasHeader->skinwidth, m_pAliasHeader->skinheight );
|
||||
pic = Mod_CreateSkinData( loadmodel, ptexture, m_pAliasHeader->skinwidth, m_pAliasHeader->skinheight );
|
||||
m_pAliasHeader->gl_texturenum[skinnum][i & 3] = GL_LoadTextureInternal( name, pic, 0 );
|
||||
gEngfuncs.FS_FreeImage( pic );
|
||||
|
||||
if( R_GetTexture( m_pAliasHeader->gl_texturenum[skinnum][i & 3] )->flags & TF_HAS_LUMA )
|
||||
if( FBitSet( R_GetTexture( m_pAliasHeader->gl_texturenum[skinnum][i & 3] )->flags, TF_HAS_LUMA ))
|
||||
{
|
||||
Q_snprintf( lumaname, sizeof( lumaname ), "%s_%i_%i_luma", loadmodel->name, skinnum, i );
|
||||
pic = Mod_CreateSkinData( NULL, (byte *)(pskintype), m_pAliasHeader->skinwidth, m_pAliasHeader->skinheight );
|
||||
pic = Mod_CreateSkinData( NULL, ptexture, m_pAliasHeader->skinwidth, m_pAliasHeader->skinheight );
|
||||
m_pAliasHeader->fb_texturenum[skinnum][i & 3] = GL_LoadTextureInternal( lumaname, pic, TF_MAKELUMA );
|
||||
gEngfuncs.FS_FreeImage( pic );
|
||||
}
|
||||
|
||||
pskintype = (daliasskintype_t *)((byte *)(pskintype) + size);
|
||||
ptexture += size;
|
||||
}
|
||||
|
||||
for( j = i; i < 4; i++ )
|
||||
|
@ -544,7 +469,7 @@ static void *Mod_LoadGroupSkin( model_t *loadmodel, daliasskintype_t *pskintype,
|
|||
m_pAliasHeader->fb_texturenum[skinnum][i & 3] = m_pAliasHeader->fb_texturenum[skinnum][i - j];
|
||||
}
|
||||
|
||||
return pskintype;
|
||||
return ptexture;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -552,66 +477,25 @@ static void *Mod_LoadGroupSkin( model_t *loadmodel, daliasskintype_t *pskintype,
|
|||
Mod_LoadAllSkins
|
||||
===============
|
||||
*/
|
||||
static void *Mod_LoadAllSkins( model_t *mod, int numskins, daliasskintype_t *pskintype )
|
||||
static const void *Mod_LoadAllSkins( model_t *mod, int numskins, const daliasskintype_t *pskintype )
|
||||
{
|
||||
int i, size;
|
||||
|
||||
if( numskins < 1 || numskins > MAX_SKINS )
|
||||
gEngfuncs.Host_Error( "%s: Invalid # of skins: %d\n", __func__, numskins );
|
||||
|
||||
size = m_pAliasHeader->skinwidth * m_pAliasHeader->skinheight;
|
||||
|
||||
// TODO: texture replacement support here
|
||||
|
||||
for( i = 0; i < numskins; i++ )
|
||||
{
|
||||
if( pskintype->type == ALIAS_SKIN_SINGLE )
|
||||
{
|
||||
pskintype = (daliasskintype_t *)Mod_LoadSingleSkin( mod, pskintype, i, size );
|
||||
}
|
||||
pskintype = Mod_LoadSingleSkin( mod, pskintype, i, size );
|
||||
else
|
||||
{
|
||||
pskintype = (daliasskintype_t *)Mod_LoadGroupSkin( mod, pskintype, i, size );
|
||||
}
|
||||
pskintype = Mod_LoadGroupSkin( mod, pskintype, i, size );
|
||||
}
|
||||
|
||||
return (void *)pskintype;
|
||||
return pskintype;
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
/*
|
||||
=================
|
||||
Mod_CalcAliasBounds
|
||||
=================
|
||||
*/
|
||||
static void Mod_CalcAliasBounds( model_t *mod )
|
||||
{
|
||||
int i, j, k;
|
||||
float radius;
|
||||
float dist;
|
||||
vec3_t v;
|
||||
|
||||
ClearBounds( mod->mins, mod->maxs );
|
||||
radius = 0.0f;
|
||||
|
||||
// process verts
|
||||
for( i = 0; i < m_pAliasHeader->numposes; i++ )
|
||||
{
|
||||
for( j = 0; j < m_pAliasHeader->numverts; j++ )
|
||||
{
|
||||
for( k = 0; k < 3; k++ )
|
||||
v[k] = g_poseverts[i][j].v[k] * m_pAliasHeader->scale[k] + m_pAliasHeader->scale_origin[k];
|
||||
|
||||
AddPointToBounds( v, mod->mins, mod->maxs );
|
||||
dist = DotProduct( v, v );
|
||||
|
||||
if( radius < dist )
|
||||
radius = dist;
|
||||
}
|
||||
}
|
||||
|
||||
mod->radius = sqrt( radius );
|
||||
}
|
||||
|
||||
/*
|
||||
=================
|
||||
|
@ -620,111 +504,34 @@ Mod_LoadAliasModel
|
|||
*/
|
||||
void Mod_LoadAliasModel( model_t *mod, const void *buffer, qboolean *loaded )
|
||||
{
|
||||
daliashdr_t *pinmodel;
|
||||
stvert_t *pinstverts;
|
||||
dtriangle_t *pintriangles;
|
||||
daliasframetype_t *pframetype;
|
||||
daliasskintype_t *pskintype;
|
||||
int i, j, size;
|
||||
char poolname[MAX_VA_STRING];
|
||||
const daliasskintype_t *pskintype;
|
||||
const dtriangle_t *pintriangles;
|
||||
const daliashdr_t *pinmodel;
|
||||
const stvert_t *pinstverts;
|
||||
|
||||
if( loaded ) *loaded = false;
|
||||
pinmodel = (daliashdr_t *)buffer;
|
||||
i = pinmodel->version;
|
||||
|
||||
if( i != ALIAS_VERSION )
|
||||
{
|
||||
gEngfuncs.Con_DPrintf( S_ERROR "%s has wrong version number (%i should be %i)\n", mod->name, i, ALIAS_VERSION );
|
||||
return;
|
||||
}
|
||||
|
||||
if( pinmodel->numverts <= 0 || pinmodel->numtris <= 0 || pinmodel->numframes <= 0 )
|
||||
return; // how to possible is make that?
|
||||
|
||||
Q_snprintf( poolname, sizeof( poolname ), "^2%s^7", mod->name );
|
||||
mod->mempool = Mem_AllocPool( poolname );
|
||||
|
||||
// allocate space for a working header, plus all the data except the frames,
|
||||
// skin and group info
|
||||
size = sizeof( aliashdr_t ) + (pinmodel->numframes - 1) * sizeof( maliasframedesc_t );
|
||||
|
||||
m_pAliasHeader = Mem_Calloc( mod->mempool, size );
|
||||
mod->flags = pinmodel->flags; // share effects flags
|
||||
|
||||
// endian-adjust and copy the data, starting with the alias model header
|
||||
m_pAliasHeader->boundingradius = pinmodel->boundingradius;
|
||||
m_pAliasHeader->numskins = pinmodel->numskins;
|
||||
m_pAliasHeader->skinwidth = pinmodel->skinwidth;
|
||||
m_pAliasHeader->skinheight = pinmodel->skinheight;
|
||||
m_pAliasHeader->numverts = pinmodel->numverts;
|
||||
m_pAliasHeader->numtris = pinmodel->numtris;
|
||||
m_pAliasHeader->numframes = pinmodel->numframes;
|
||||
|
||||
if( m_pAliasHeader->numverts > MAXALIASVERTS )
|
||||
{
|
||||
gEngfuncs.Con_DPrintf( S_ERROR "model %s has too many vertices\n", mod->name );
|
||||
return;
|
||||
}
|
||||
|
||||
m_pAliasHeader->size = pinmodel->size;
|
||||
// mod->synctype = pinmodel->synctype;
|
||||
mod->numframes = m_pAliasHeader->numframes;
|
||||
|
||||
for( i = 0; i < 3; i++ )
|
||||
{
|
||||
m_pAliasHeader->scale[i] = pinmodel->scale[i];
|
||||
m_pAliasHeader->scale_origin[i] = pinmodel->scale_origin[i];
|
||||
m_pAliasHeader->eyeposition[i] = pinmodel->eyeposition[i];
|
||||
}
|
||||
pinmodel = (const daliashdr_t *)buffer;
|
||||
m_pAliasHeader = mod->cache.data;
|
||||
if( !m_pAliasHeader ) return;
|
||||
|
||||
// load the skins
|
||||
pskintype = (daliasskintype_t *)&pinmodel[1];
|
||||
pskintype = (const daliasskintype_t *)&pinmodel[1];
|
||||
pskintype = Mod_LoadAllSkins( mod, m_pAliasHeader->numskins, pskintype );
|
||||
|
||||
// load base s and t vertices
|
||||
pinstverts = (stvert_t *)pskintype;
|
||||
|
||||
for( i = 0; i < m_pAliasHeader->numverts; i++ )
|
||||
{
|
||||
g_stverts[i].onseam = pinstverts[i].onseam;
|
||||
g_stverts[i].s = pinstverts[i].s;
|
||||
g_stverts[i].t = pinstverts[i].t;
|
||||
}
|
||||
pinstverts = (const stvert_t *)pskintype;
|
||||
memset( g_stverts, 0, sizeof( g_stverts ));
|
||||
memcpy( g_stverts, pinstverts, sizeof( g_stverts[0] ) * m_pAliasHeader->numverts );
|
||||
|
||||
// load triangle lists
|
||||
pintriangles = (dtriangle_t *)&pinstverts[m_pAliasHeader->numverts];
|
||||
|
||||
for( i = 0; i < m_pAliasHeader->numtris; i++ )
|
||||
{
|
||||
g_triangles[i].facesfront = pintriangles[i].facesfront;
|
||||
|
||||
for( j = 0; j < 3; j++ )
|
||||
g_triangles[i].vertindex[j] = pintriangles[i].vertindex[j];
|
||||
}
|
||||
|
||||
// load the frames
|
||||
pframetype = (daliasframetype_t *)&pintriangles[m_pAliasHeader->numtris];
|
||||
g_posenum = 0;
|
||||
|
||||
for( i = 0; i < m_pAliasHeader->numframes; i++ )
|
||||
{
|
||||
aliasframetype_t frametype = pframetype->type;
|
||||
|
||||
if( frametype == ALIAS_SINGLE )
|
||||
pframetype = (daliasframetype_t *)Mod_LoadAliasFrame( pframetype + 1, &m_pAliasHeader->frames[i] );
|
||||
else pframetype = (daliasframetype_t *)Mod_LoadAliasGroup( pframetype + 1, &m_pAliasHeader->frames[i] );
|
||||
}
|
||||
|
||||
m_pAliasHeader->numposes = g_posenum;
|
||||
|
||||
Mod_CalcAliasBounds( mod );
|
||||
mod->type = mod_alias;
|
||||
pintriangles = (const dtriangle_t *)&pinstverts[m_pAliasHeader->numverts];
|
||||
memset( g_triangles, 0, sizeof( g_triangles ));
|
||||
memcpy( g_triangles, pintriangles, sizeof( g_triangles[0] ) * m_pAliasHeader->numtris );
|
||||
|
||||
// build the draw lists
|
||||
GL_MakeAliasModelDisplayLists( mod );
|
||||
|
||||
// move the complete, relocatable alias model to the cache
|
||||
mod->cache.data = m_pAliasHeader;
|
||||
m_pAliasHeader = NULL;
|
||||
|
||||
if( loaded ) *loaded = true; // done
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue