diff --git a/common/com_model.h b/common/com_model.h index 5f4b70c0..71212b70 100644 --- a/common/com_model.h +++ b/common/com_model.h @@ -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; diff --git a/engine/common/mod_alias.c b/engine/common/mod_alias.c new file mode 100644 index 00000000..8dceff63 --- /dev/null +++ b/engine/common/mod_alias.c @@ -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 +} diff --git a/engine/common/mod_local.h b/engine/common/mod_local.h index c8508407..b8050af7 100644 --- a/engine/common/mod_local.h +++ b/engine/common/mod_local.h @@ -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 // diff --git a/engine/common/model.c b/engine/common/model.c index 9bf52b99..bbd1a357 100644 --- a/engine/common/model.c +++ b/engine/common/model.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 ); diff --git a/ref/gl/gl_alias.c b/ref/gl/gl_alias.c index d1e46e2d..5fa1e66f 100644 --- a/ref/gl/gl_alias.c +++ b/ref/gl/gl_alias.c @@ -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 }