2005-02-28 07:16:19 +00:00
# include "quakedef.h"
2004-08-22 22:29:09 +00:00
# ifdef HALFLIFEMODELS
2012-07-05 19:42:36 +00:00
# include "shader.h"
2004-08-22 22:29:09 +00:00
/*
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Half - Life Model Renderer ( Experimental ) Copyright ( C ) 2001 James ' Ender ' Brown [ ender @ quakesrc . org ] 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 . fromquake . h -
2011-05-19 13:34:07 +00:00
render . c - apart from calculations ( mostly range checking or value conversion code is a mix of standard Quake 1
2004-08-22 22:29:09 +00:00
meshing , and vertex deforms . The rendering loop uses standard Quake 1 drawing , after SetupBones deforms the vertex .
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Also , please note that it won ' t do all hl models . . . .
Nor will it work 100 %
*/
# include "model_hl.h"
void QuaternionGLMatrix ( float x , float y , float z , float w , vec4_t * GLM )
{
GLM [ 0 ] [ 0 ] = 1 - 2 * y * y - 2 * z * z ;
GLM [ 1 ] [ 0 ] = 2 * x * y + 2 * w * z ;
GLM [ 2 ] [ 0 ] = 2 * x * z - 2 * w * y ;
GLM [ 0 ] [ 1 ] = 2 * x * y - 2 * w * z ;
GLM [ 1 ] [ 1 ] = 1 - 2 * x * x - 2 * z * z ;
GLM [ 2 ] [ 1 ] = 2 * y * z + 2 * w * x ;
GLM [ 0 ] [ 2 ] = 2 * x * z + 2 * w * y ;
GLM [ 1 ] [ 2 ] = 2 * y * z - 2 * w * x ;
GLM [ 2 ] [ 2 ] = 1 - 2 * x * x - 2 * y * y ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
QuaternionGLAngle - Convert a GL angle to a quaternion matrix
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
void QuaternionGLAngle ( const vec3_t angles , vec4_t quaternion )
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
float yaw = angles [ 2 ] * 0.5 ;
float pitch = angles [ 1 ] * 0.5 ;
float roll = angles [ 0 ] * 0.5 ;
float siny = sin ( yaw ) ;
float cosy = cos ( yaw ) ;
float sinp = sin ( pitch ) ;
float cosp = cos ( pitch ) ;
float sinr = sin ( roll ) ;
float cosr = cos ( roll ) ;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
quaternion [ 0 ] = sinr * cosp * cosy - cosr * sinp * siny ;
quaternion [ 1 ] = cosr * sinp * cosy + sinr * cosp * siny ;
quaternion [ 2 ] = cosr * cosp * siny - sinr * sinp * cosy ;
quaternion [ 3 ] = cosr * cosp * cosy + sinr * sinp * siny ;
}
2008-12-23 02:55:20 +00:00
matrix3x4 transform_matrix [ MAX_BONES ] ; /* Vertex transformation matrix */
2004-08-22 22:29:09 +00:00
void GL_Draw_HL_AliasFrame ( short * order , vec3_t * transformed , float tex_w , float tex_h ) ;
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Mod_LoadHLModel - read in the model ' s constituent parts
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
extern char loadname [ ] ;
2013-10-29 17:38:22 +00:00
qboolean QDECL Mod_LoadHLModel ( model_t * mod , void * buffer )
2004-08-22 22:29:09 +00:00
{
/*~~*/
int i ;
2011-05-19 13:34:07 +00:00
2004-08-22 22:29:09 +00:00
hlmodelcache_t * model ;
hlmdl_header_t * header ;
2009-02-22 13:45:35 +00:00
hlmdl_header_t * texheader ;
2004-08-22 22:29:09 +00:00
hlmdl_tex_t * tex ;
hlmdl_bone_t * bones ;
hlmdl_bonecontroller_t * bonectls ;
2012-07-05 19:42:36 +00:00
shader_t * * shaders ;
2013-07-14 12:22:51 +00:00
void * texmem = NULL ;
2004-08-22 22:29:09 +00:00
/*~~*/
//checksum the model
2006-03-06 00:19:46 +00:00
if ( mod - > engineflags & MDLF_DOCRC )
{
2004-08-22 22:29:09 +00:00
unsigned short crc ;
qbyte * p ;
int len ;
char st [ 40 ] ;
2005-09-08 22:52:46 +00:00
QCRC_Init ( & crc ) ;
2004-08-22 22:29:09 +00:00
for ( len = com_filesize , p = buffer ; len ; len - - , p + + )
2005-09-08 22:52:46 +00:00
QCRC_ProcessByte ( & crc , * p ) ;
2011-05-19 13:34:07 +00:00
2004-08-22 22:29:09 +00:00
sprintf ( st , " %d " , ( int ) crc ) ;
2011-05-19 13:34:07 +00:00
Info_SetValueForKey ( cls . userinfo [ 0 ] ,
2006-03-06 00:19:46 +00:00
( mod - > engineflags & MDLF_PLAYER ) ? pmodel_name : emodel_name ,
2010-08-14 03:17:33 +00:00
st , sizeof ( cls . userinfo [ 0 ] ) ) ;
2004-08-22 22:29:09 +00:00
2005-02-28 07:16:19 +00:00
if ( cls . state > = ca_connected )
{
2011-05-19 13:34:07 +00:00
CL_SendClientCommand ( true , " setinfo %s %d " ,
2006-03-06 00:19:46 +00:00
( mod - > engineflags & MDLF_PLAYER ) ? pmodel_name : emodel_name ,
2004-08-22 22:29:09 +00:00
( int ) crc ) ;
}
}
2011-05-19 13:34:07 +00:00
2004-08-22 22:29:09 +00:00
//load the model into hunk
2013-07-14 12:22:51 +00:00
model = ZG_Malloc ( & mod - > memgroup , sizeof ( hlmodelcache_t ) ) ;
2004-08-22 22:29:09 +00:00
2013-07-14 12:22:51 +00:00
header = ZG_Malloc ( & mod - > memgroup , com_filesize ) ;
2004-08-22 22:29:09 +00:00
memcpy ( header , buffer , com_filesize ) ;
2009-02-22 13:45:35 +00:00
# if defined(HLSERVER) && (defined(__powerpc__) || defined(__ppc__))
//this is to let bigfoot know when he comes to port it all... And I'm lazy.
2011-10-27 16:16:29 +00:00
# ifdef warningmsg
# pragma warningmsg("-----------------------------------------")
# pragma warningmsg("FIXME: No byteswapping on halflife models")
# pragma warningmsg("-----------------------------------------")
# endif
2009-02-22 13:45:35 +00:00
# endif
2004-08-22 22:29:09 +00:00
if ( header - > version ! = 10 )
2006-03-12 09:19:31 +00:00
{
2007-09-23 15:28:06 +00:00
Con_Printf ( CON_ERROR " Cannot load model %s - unknown version %i \n " , mod - > name , header - > version ) ;
2006-03-12 09:19:31 +00:00
return false ;
}
2004-08-22 22:29:09 +00:00
2008-11-09 22:29:28 +00:00
if ( header - > numcontrollers > MAX_BONE_CONTROLLERS )
{
Con_Printf ( CON_ERROR " Cannot load model %s - too many controllers %i \n " , mod - > name , header - > numcontrollers ) ;
return false ;
}
2008-12-23 02:55:20 +00:00
if ( header - > numbones > MAX_BONES )
{
Con_Printf ( CON_ERROR " Cannot load model %s - too many bones %i \n " , mod - > name , header - > numbones ) ;
return false ;
}
2008-11-09 22:29:28 +00:00
2009-02-22 13:45:35 +00:00
texheader = NULL ;
if ( ! header - > numtextures )
{
char texmodelname [ MAX_QPATH ] ;
COM_StripExtension ( mod - > name , texmodelname , sizeof ( texmodelname ) ) ;
//no textures? eesh. They must be stored externally.
2013-07-14 12:22:51 +00:00
texheader = texmem = ( hlmdl_header_t * ) FS_LoadMallocFile ( va ( " %st.mdl " , texmodelname ) ) ;
2009-02-22 13:45:35 +00:00
if ( texheader )
{
if ( texheader - > version ! = 10 )
texheader = NULL ;
}
}
if ( ! texheader )
texheader = header ;
else
header - > numtextures = texheader - > numtextures ;
2011-05-19 13:34:07 +00:00
2009-02-22 13:45:35 +00:00
tex = ( hlmdl_tex_t * ) ( ( qbyte * ) texheader + texheader - > textures ) ;
2004-08-22 22:29:09 +00:00
bones = ( hlmdl_bone_t * ) ( ( qbyte * ) header + header - > boneindex ) ;
bonectls = ( hlmdl_bonecontroller_t * ) ( ( qbyte * ) header + header - > controllerindex ) ;
/* won't work - doesn't know exact sizes.
header = Hunk_Alloc ( sizeof ( hlmdl_header_t ) ) ;
memcpy ( header , ( hlmdl_header_t * ) buffer , sizeof ( hlmdl_header_t ) ) ;
tex = Hunk_Alloc ( sizeof ( hlmdl_tex_t ) * header - > numtextures ) ;
memcpy ( tex , ( hlmdl_tex_t * ) buffer , sizeof ( hlmdl_tex_t ) * header - > numtextures ) ;
bones = Hunk_Alloc ( sizeof ( hlmdl_bone_t ) * header - > numtextures ) ;
memcpy ( bones , ( hlmdl_bone_t * ) buffer , sizeof ( hlmdl_bone_t ) * header - > numbones ) ;
bonectls = Hunk_Alloc ( sizeof ( hlmdl_bonecontroller_t ) * header - > numcontrollers ) ;
memcpy ( bonectls , ( hlmdl_bonecontroller_t * ) buffer , sizeof ( hlmdl_bonecontroller_t ) * header - > numcontrollers ) ;
*/
model - > header = ( char * ) header - ( char * ) model ;
2009-02-22 13:45:35 +00:00
model - > texheader = ( char * ) texheader - ( char * ) model ;
2004-08-22 22:29:09 +00:00
model - > textures = ( char * ) tex - ( char * ) model ;
model - > bones = ( char * ) bones - ( char * ) model ;
model - > bonectls = ( char * ) bonectls - ( char * ) model ;
2013-07-14 12:22:51 +00:00
shaders = ZG_Malloc ( & mod - > memgroup , texheader - > numtextures * sizeof ( shader_t ) ) ;
2012-07-05 19:42:36 +00:00
model - > shaders = ( char * ) shaders - ( char * ) model ;
2009-02-22 13:45:35 +00:00
for ( i = 0 ; i < texheader - > numtextures ; i + + )
2004-08-22 22:29:09 +00:00
{
2012-07-05 19:42:36 +00:00
shaders [ i ] = R_RegisterSkin ( va ( " %s_%i.tga " , mod - > name , i ) , mod - > name ) ;
shaders [ i ] - > defaulttextures . base = R_LoadTexture8Pal24 ( " " , tex [ i ] . w , tex [ i ] . h , ( qbyte * ) texheader + tex [ i ] . offset , ( qbyte * ) texheader + tex [ i ] . w * tex [ i ] . h + tex [ i ] . offset , IF_NOALPHA | IF_NOGAMMA ) ;
2004-08-22 22:29:09 +00:00
}
2013-12-29 22:48:28 +00:00
model - > numskins = texheader - > numtextures ;
model - > skins = ZG_Malloc ( & mod - > memgroup , model - > numskins * sizeof ( * model - > skins ) ) ;
memcpy ( model - > skins , ( short * ) ( ( qbyte * ) texheader + texheader - > skins ) , model - > numskins * sizeof ( * model - > skins ) ) ;
2013-07-14 12:22:51 +00:00
if ( texmem )
Z_Free ( texmem ) ;
2004-08-22 22:29:09 +00:00
mod - > type = mod_halflife ;
2013-07-14 12:22:51 +00:00
mod - > meshinfo = model ;
2006-03-12 09:19:31 +00:00
return true ;
2004-08-22 22:29:09 +00:00
}
2009-02-22 13:45:35 +00:00
# ifdef HLSERVER
void * Mod_GetHalfLifeModelData ( model_t * mod )
{
hlmodelcache_t * mc ;
if ( ! mod | | mod - > type ! = mod_halflife )
return NULL ; //halflife models only, please
mc = Mod_Extradata ( mod ) ;
return ( void * ) ( ( char * ) mc + mc - > header ) ;
}
# endif
2009-04-01 22:03:56 +00:00
int HLMod_FrameForName ( model_t * mod , char * name )
{
int i ;
hlmdl_header_t * h ;
hlmdl_sequencelist_t * seqs ;
hlmodelcache_t * mc ;
if ( ! mod | | mod - > type ! = mod_halflife )
return - 1 ; //halflife models only, please
mc = Mod_Extradata ( mod ) ;
h = ( hlmdl_header_t * ) ( ( char * ) mc + mc - > header ) ;
seqs = ( hlmdl_sequencelist_t * ) ( ( char * ) h + h - > seqindex ) ;
for ( i = 0 ; i < h - > numseq ; i + + )
{
if ( ! strcmp ( seqs [ i ] . name , name ) )
return i ;
}
return - 1 ;
}
int HLMod_BoneForName ( model_t * mod , char * name )
{
int i ;
hlmdl_header_t * h ;
hlmdl_bone_t * bones ;
hlmodelcache_t * mc ;
if ( ! mod | | mod - > type ! = mod_halflife )
return - 1 ; //halflife models only, please
mc = Mod_Extradata ( mod ) ;
h = ( hlmdl_header_t * ) ( ( char * ) mc + mc - > header ) ;
bones = ( hlmdl_bone_t * ) ( ( char * ) h + h - > boneindex ) ;
for ( i = 0 ; i < h - > numbones ; i + + )
{
if ( ! strcmp ( bones [ i ] . name , name ) )
return i + 1 ;
}
return 0 ;
}
2004-08-22 22:29:09 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
HL_CalculateBones - calculate bone positions - quaternion + vector in one function
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
2008-11-09 22:29:28 +00:00
note , while ender may be proud of this function , it lacks the fact that interpolating eular angles is not as acurate as interpolating quaternions .
it is faster though .
2004-08-22 22:29:09 +00:00
*/
void HL_CalculateBones
(
int offset ,
int frame ,
2008-11-09 22:29:28 +00:00
float lerpfrac ,
2004-08-22 22:29:09 +00:00
vec4_t adjust ,
hlmdl_bone_t * bone ,
hlmdl_anim_t * animation ,
float * destination
)
{
/*~~~~~~~~~~*/
int i ;
vec3_t angle ;
2008-11-09 22:29:28 +00:00
float lerpifrac = 1 - lerpfrac ;
float t ;
2004-08-22 22:29:09 +00:00
/*~~~~~~~~~~*/
/* For each vector */
for ( i = 0 ; i < 3 ; i + + )
{
/*~~~~~~~~~~~~~~~*/
int o = i + offset ; /* Take the value offset - allows quaternion & vector in one function */
/*~~~~~~~~~~~~~~~*/
angle [ i ] = bone - > value [ o ] ; /* Take the bone value */
if ( animation - > offset [ o ] ! = 0 )
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
int tempframe = frame ;
hlmdl_animvalue_t * animvalue = ( hlmdl_animvalue_t * ) ( ( qbyte * ) animation + animation - > offset [ o ] ) ;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/* find values including the required frame */
while ( animvalue - > num . total < = tempframe )
{
tempframe - = animvalue - > num . total ;
animvalue + = animvalue - > num . valid + 1 ;
}
if ( animvalue - > num . valid > tempframe )
{
if ( animvalue - > num . valid > ( tempframe + 1 ) )
2008-11-09 22:29:28 +00:00
{
//we can lerp that
t = animvalue [ tempframe + 1 ] . value * lerpifrac + lerpfrac * animvalue [ tempframe + 2 ] . value ;
}
2004-08-22 22:29:09 +00:00
else
2008-11-09 22:29:28 +00:00
t = animvalue [ animvalue - > num . valid ] . value ;
angle [ i ] = bone - > value [ o ] + t * bone - > scale [ o ] ;
2004-08-22 22:29:09 +00:00
}
else
{
2008-11-09 22:29:28 +00:00
if ( animvalue - > num . total < tempframe + 1 )
2004-08-22 22:29:09 +00:00
{
angle [ i ] + =
2008-11-09 22:29:28 +00:00
( animvalue [ animvalue - > num . valid ] . value * lerpifrac +
lerpfrac * animvalue [ animvalue - > num . valid + 2 ] . value ) *
2004-08-22 22:29:09 +00:00
bone - > scale [ o ] ;
}
else
{
angle [ i ] + = animvalue [ animvalue - > num . valid ] . value * bone - > scale [ o ] ;
}
}
}
2008-11-09 22:29:28 +00:00
if ( bone - > bonecontroller [ o ] ! = - 1 )
{ /* Add the programmable offset. */
2004-08-22 22:29:09 +00:00
angle [ i ] + = adjust [ bone - > bonecontroller [ o ] ] ;
}
}
if ( offset < 3 )
{
VectorCopy ( angle , destination ) ; /* Just a standard vector */
}
else
{
QuaternionGLAngle ( angle , destination ) ; /* A quaternion */
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
HL_CalcBoneAdj - Calculate the adjustment values for the programmable controllers
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
void HL_CalcBoneAdj ( hlmodel_t * model )
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
int i ;
float value ;
hlmdl_bonecontroller_t * control = ( hlmdl_bonecontroller_t * )
( ( qbyte * ) model - > header + model - > header - > controllerindex ) ;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
for ( i = 0 ; i < model - > header - > numcontrollers ; i + + )
{
/*~~~~~~~~~~~~~~~~~~~~~*/
int j = control [ i ] . index ;
/*~~~~~~~~~~~~~~~~~~~~~*/
if ( control [ i ] . type & 0x8000 )
{
2005-04-16 16:21:27 +00:00
value = model - > controller [ j ] + control [ i ] . start ;
2004-08-22 22:29:09 +00:00
}
else
{
2008-11-09 22:29:28 +00:00
value = ( model - > controller [ j ] + 1 ) * 0.5 ; //shifted to give a valid range between -1 and 1, with 0 being mid-range.
2004-08-22 22:29:09 +00:00
if ( value < 0 )
value = 0 ;
else if ( value > 1.0 )
value = 1.0 ;
value = ( 1.0 - value ) * control [ i ] . start + value * control [ i ] . end ;
}
/* Rotational controllers need their values converted */
if ( control [ i ] . type > = 0x0008 & & control [ i ] . type < = 0x0020 )
model - > adjust [ i ] = M_PI * value / 180 ;
else
model - > adjust [ i ] = value ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
HL_SetupBones - determine where vertex should be using bone movements
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
2008-11-09 22:29:28 +00:00
void QuaternionSlerp ( const vec4_t p , vec4_t q , float t , vec4_t qt ) ;
2009-02-22 13:45:35 +00:00
void HL_SetupBones ( hlmodel_t * model , int seqnum , int firstbone , int lastbone , float subblendfrac , float frametime )
2004-08-22 22:29:09 +00:00
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
int i ;
float matrix [ 3 ] [ 4 ] ;
2008-11-09 22:29:28 +00:00
static vec3_t positions [ 2 ] ;
static vec4_t quaternions [ 2 ] , blended ;
int frame ;
2004-08-22 22:29:09 +00:00
hlmdl_sequencelist_t * sequence = ( hlmdl_sequencelist_t * ) ( ( qbyte * ) model - > header + model - > header - > seqindex ) +
2008-11-09 22:29:28 +00:00
( ( unsigned int ) seqnum > = model - > header - > numseq ? 0 : seqnum ) ;
2004-08-22 22:29:09 +00:00
hlmdl_sequencedata_t * sequencedata = ( hlmdl_sequencedata_t * )
( ( qbyte * ) model - > header + model - > header - > seqgroups ) +
sequence - > seqindex ;
hlmdl_anim_t * animation = ( hlmdl_anim_t * )
( ( qbyte * ) model - > header + sequencedata - > data + sequence - > index ) ;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2009-02-22 13:45:35 +00:00
frametime * = sequence - > timing ;
2009-03-03 01:52:30 +00:00
if ( frametime < 0 )
frametime = 0 ;
2008-11-09 22:29:28 +00:00
frame = ( int ) frametime ;
frametime - = frame ;
if ( ! sequence - > numframes )
return ;
if ( frame > = sequence - > numframes )
{
2009-04-01 22:03:56 +00:00
if ( sequence - > loop )
2008-11-09 22:29:28 +00:00
frame % = sequence - > numframes ;
2009-04-01 22:03:56 +00:00
else
frame = sequence - > numframes - 1 ;
2008-11-09 22:29:28 +00:00
}
if ( lastbone > model - > header - > numbones )
lastbone = model - > header - > numbones ;
2004-08-22 22:29:09 +00:00
HL_CalcBoneAdj ( model ) ; /* Deal with programmable controllers */
2008-11-09 22:29:28 +00:00
/*FIXME:this is useless*/
/*
if ( sequence - > motiontype & 0x0001 )
positions [ sequence - > motionbone ] [ 0 ] = 0.0 ;
if ( sequence - > motiontype & 0x0002 )
positions [ sequence - > motionbone ] [ 1 ] = 0.0 ;
if ( sequence - > motiontype & 0x0004 )
positions [ sequence - > motionbone ] [ 2 ] = 0.0 ;
*/
/*
this is hellish .
a hl model blends :
4 controllers ( on a player , it seems each one of them twists a separate bone in the chest )
a mouth ( not used on players )
its a sequence ( to be smooth we need to blend between two frames in the sequence )
up to four source animations ( ironically used to pitch up / down )
alternate sequence ( walking + firing )
frame2 ( quake expectations . )
this is madness , quite frankly .
luckily . . .
controllers and mouth control the entire thing . they should be interpolated outside , and have no affect on blending here
alternate sequences replace . we can just call this function twice ( so long as bone ranges are incremental ) .
autoanimating sequence is handled inside HL_CalculateBones ( sequences are weird and it has to be handled there anyway )
this means we only have sources and alternate frames left to cope with .
FIXME : we don ' t handle frame2 .
*/
if ( sequence - > hasblendseq > 1 )
{
if ( subblendfrac < 0 )
subblendfrac = 0 ;
if ( subblendfrac > 1 )
subblendfrac = 1 ;
for ( i = firstbone ; i < lastbone ; i + + )
{
HL_CalculateBones ( 0 , frame , frametime , model - > adjust , model - > bones + i , animation + i , positions [ 0 ] ) ;
HL_CalculateBones ( 3 , frame , frametime , model - > adjust , model - > bones + i , animation + i , quaternions [ 0 ] ) ;
2011-05-19 13:34:07 +00:00
2008-11-09 22:29:28 +00:00
HL_CalculateBones ( 3 , frame , frametime , model - > adjust , model - > bones + i , animation + i + model - > header - > numbones , quaternions [ 1 ] ) ;
QuaternionSlerp ( quaternions [ 0 ] , quaternions [ 1 ] , subblendfrac , blended ) ;
QuaternionGLMatrix ( blended [ 0 ] , blended [ 1 ] , blended [ 2 ] , blended [ 3 ] , matrix ) ;
matrix [ 0 ] [ 3 ] = positions [ 0 ] [ 0 ] ;
matrix [ 1 ] [ 3 ] = positions [ 0 ] [ 1 ] ;
matrix [ 2 ] [ 3 ] = positions [ 0 ] [ 2 ] ;
/* If we have a parent, take the addition. Otherwise just copy the values */
if ( model - > bones [ i ] . parent > = 0 )
{
R_ConcatTransforms ( transform_matrix [ model - > bones [ i ] . parent ] , matrix , transform_matrix [ i ] ) ;
}
else
{
memcpy ( transform_matrix [ i ] , matrix , 12 * sizeof ( float ) ) ;
}
}
2004-08-22 22:29:09 +00:00
2008-11-09 22:29:28 +00:00
}
else
{
for ( i = firstbone ; i < lastbone ; i + + )
{
/*
* There are two vector offsets in the structure . The first seems to be the
* positions of the bones , the second the quats of the bone matrix itself . We
* convert it inside the routine - Inconsistant , but hey . . so ' s the whole model
* format .
*/
HL_CalculateBones ( 0 , frame , frametime , model - > adjust , model - > bones + i , animation + i , positions [ 0 ] ) ;
HL_CalculateBones ( 3 , frame , frametime , model - > adjust , model - > bones + i , animation + i , quaternions [ 0 ] ) ;
QuaternionGLMatrix ( quaternions [ 0 ] [ 0 ] , quaternions [ 0 ] [ 1 ] , quaternions [ 0 ] [ 2 ] , quaternions [ 0 ] [ 3 ] , matrix ) ;
matrix [ 0 ] [ 3 ] = positions [ 0 ] [ 0 ] ;
matrix [ 1 ] [ 3 ] = positions [ 0 ] [ 1 ] ;
matrix [ 2 ] [ 3 ] = positions [ 0 ] [ 2 ] ;
/* If we have a parent, take the addition. Otherwise just copy the values */
if ( model - > bones [ i ] . parent > = 0 )
{
R_ConcatTransforms ( transform_matrix [ model - > bones [ i ] . parent ] , matrix , transform_matrix [ i ] ) ;
}
else
{
memcpy ( transform_matrix [ i ] , matrix , 12 * sizeof ( float ) ) ;
}
}
}
2004-08-22 22:29:09 +00:00
}
2012-07-05 19:42:36 +00:00
void R_HL_BuildFrame ( hlmodel_t * model , hlmdl_model_t * amodel , entity_t * curent , short * order , float tex_s , float tex_t , mesh_t * mesh )
{
static vecV_t xyz [ 2048 ] ;
static vec3_t norm [ 2048 ] ;
static vec2_t st [ 2048 ] ;
static index_t index [ 4096 ] ;
int count ;
int b ;
int cbone ;
int bgroup ;
int lastbone ;
int v , i ;
vec3_t * verts ;
qbyte * bone ;
vec3_t transformed [ 2048 ] ;
int idx = 0 ;
int vert = 0 ;
mesh - > xyz_array = xyz ;
mesh - > st_array = st ;
mesh - > normals_array = norm ; //for lighting algos to not crash
mesh - > snormals_array = norm ; //for rtlighting
mesh - > tnormals_array = norm ; //for rtlighting
mesh - > indexes = index ;
for ( b = 0 ; b < MAX_BONE_CONTROLLERS ; b + + )
model - > controller [ b ] = curent - > framestate . bonecontrols [ b ] ;
// Con_Printf("%s %i\n", sequence->name, sequence->unknown1[0]);
cbone = 0 ;
for ( bgroup = 0 ; bgroup < FS_COUNT ; bgroup + + )
{
lastbone = curent - > framestate . g [ bgroup ] . endbone ;
if ( bgroup = = FS_COUNT - 1 )
lastbone = model - > header - > numbones ;
if ( cbone > = lastbone )
continue ;
HL_SetupBones ( model , curent - > framestate . g [ bgroup ] . frame [ 0 ] , cbone , lastbone , ( curent - > framestate . g [ bgroup ] . subblendfrac + 1 ) * 0.5 , curent - > framestate . g [ bgroup ] . frametime [ 0 ] ) ; /* Setup the bones */
cbone = lastbone ;
}
verts = ( vec3_t * ) ( ( qbyte * ) model - > header + amodel - > vertindex ) ;
bone = ( ( qbyte * ) model - > header + amodel - > vertinfoindex ) ;
for ( v = 0 ; v < amodel - > numverts ; v + + )
{
VectorTransform ( verts [ v ] , ( void * ) transform_matrix [ bone [ v ] ] , transformed [ v ] ) ;
}
for ( ; ; )
{
count = * order + + ; /* get the vertex count and primitive type */
if ( ! count ) break ; /* done */
if ( count < 0 )
{
count = - count ;
//emit (count-2)*3 indicies as a fan
for ( i = 0 ; i < count - 2 ; i + + )
{
index [ idx + + ] = vert + 0 ;
index [ idx + + ] = vert + i + 1 ;
index [ idx + + ] = vert + i + 2 ;
}
}
else
{
//emit (count-2)*3 indicies as a strip
for ( i = 0 ; ; )
{
if ( i = = count - 2 )
break ;
index [ idx + + ] = vert + i ;
index [ idx + + ] = vert + i + 1 ;
index [ idx + + ] = vert + i + 2 ;
i + + ;
if ( i = = count - 2 )
break ;
index [ idx + + ] = vert + i ;
index [ idx + + ] = vert + i + 2 ;
index [ idx + + ] = vert + i + 1 ;
i + + ;
}
}
do
{
VectorCopy ( transformed [ order [ 0 ] ] , xyz [ vert ] ) ;
//FIXME: what's order[1]?
/* texture coordinates come from the draw list */
st [ vert ] [ 0 ] = order [ 2 ] * tex_s ;
st [ vert ] [ 1 ] = order [ 3 ] * tex_t ;
norm [ vert ] [ 1 ] = 1 ;
order + = 4 ;
vert + + ;
} while ( - - count ) ;
}
mesh - > numindexes = idx ;
mesh - > numvertexes = vert ;
}
void R_HalfLife_WalkMeshes ( entity_t * rent , batch_t * b , batch_t * * batches ) ;
void R_HL_BuildMesh ( struct batch_s * b )
{
R_HalfLife_WalkMeshes ( b - > ent , b , NULL ) ;
}
void R_HalfLife_WalkMeshes ( entity_t * rent , batch_t * b , batch_t * * batches )
{
hlmodelcache_t * modelc = Mod_Extradata ( rent - > model ) ;
hlmodel_t model ;
2012-08-04 01:35:52 +00:00
int body , m ;
2012-07-05 19:42:36 +00:00
int batchid = 0 ;
static mesh_t bmesh , * mptr = & bmesh ;
//general model
model . header = ( hlmdl_header_t * ) ( ( char * ) modelc + modelc - > header ) ;
2013-12-29 22:48:28 +00:00
// model.texheader = (hlmdl_header_t *) ((char *)modelc + modelc->texheader);
2012-07-05 19:42:36 +00:00
model . textures = ( hlmdl_tex_t * ) ( ( char * ) modelc + modelc - > textures ) ;
model . bones = ( hlmdl_bone_t * ) ( ( char * ) modelc + modelc - > bones ) ;
model . bonectls = ( hlmdl_bonecontroller_t * ) ( ( char * ) modelc + modelc - > bonectls ) ;
model . shaders = ( shader_t * * ) ( ( char * ) modelc + modelc - > shaders ) ;
for ( body = 0 ; body < model . header - > numbodyparts ; body + + )
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
hlmdl_bodypart_t * bodypart = ( hlmdl_bodypart_t * ) ( ( qbyte * ) model . header + model . header - > bodypartindex ) + body ;
int bodyindex = ( 0 / bodypart - > base ) % bodypart - > nummodels ;
hlmdl_model_t * amodel = ( hlmdl_model_t * ) ( ( qbyte * ) model . header + bodypart - > modelindex ) + bodyindex ;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/* Draw each mesh */
for ( m = 0 ; m < amodel - > nummesh ; m + + )
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
hlmdl_mesh_t * mesh = ( hlmdl_mesh_t * ) ( ( qbyte * ) model . header + amodel - > meshindex ) + m ;
float tex_w ;
float tex_h ;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2013-12-29 22:48:28 +00:00
if ( mesh - > skinindex > = modelc - > numskins )
continue ;
2012-07-05 19:42:36 +00:00
if ( batches )
{
shader_t * shader ;
int sort ;
b = BE_GetTempBatch ( ) ;
if ( ! b )
return ;
2013-12-29 22:48:28 +00:00
shader = model . shaders [ modelc - > skins [ mesh - > skinindex ] ] ;
2012-07-05 19:42:36 +00:00
b - > buildmeshes = R_HL_BuildMesh ;
b - > ent = rent ;
b - > mesh = NULL ;
b - > firstmesh = 0 ;
b - > meshes = 1 ;
b - > skin = & shader - > defaulttextures ;
b - > texture = NULL ;
b - > shader = shader ;
b - > lightmap [ 0 ] = - 1 ;
b - > lightmap [ 1 ] = - 1 ;
b - > lightmap [ 2 ] = - 1 ;
b - > lightmap [ 3 ] = - 1 ;
b - > surf_first = batchid ;
b - > flags = 0 ;
sort = shader - > sort ;
//fixme: we probably need to force some blend modes based on the surface flags.
if ( rent - > flags & RF_FORCECOLOURMOD )
b - > flags | = BEF_FORCECOLOURMOD ;
if ( rent - > flags & Q2RF_ADDITIVE )
{
b - > flags | = BEF_FORCEADDITIVE ;
if ( sort < SHADER_SORT_ADDITIVE )
sort = SHADER_SORT_ADDITIVE ;
}
if ( rent - > flags & Q2RF_TRANSLUCENT )
{
b - > flags | = BEF_FORCETRANSPARENT ;
if ( SHADER_SORT_PORTAL < sort & & sort < SHADER_SORT_BLEND )
sort = SHADER_SORT_BLEND ;
}
if ( rent - > flags & RF_NODEPTHTEST )
{
b - > flags | = BEF_FORCENODEPTH ;
if ( sort < SHADER_SORT_NEAREST )
sort = SHADER_SORT_NEAREST ;
}
if ( rent - > flags & RF_NOSHADOW )
b - > flags | = BEF_NOSHADOWS ;
b - > vbo = NULL ;
b - > next = batches [ sort ] ;
batches [ sort ] = b ;
}
else
{
if ( batchid = = b - > surf_first )
{
2013-12-29 22:48:28 +00:00
tex_w = 1.0f / model . textures [ modelc - > skins [ mesh - > skinindex ] ] . w ;
tex_h = 1.0f / model . textures [ modelc - > skins [ mesh - > skinindex ] ] . h ;
2012-07-05 19:42:36 +00:00
b - > mesh = & mptr ;
R_HL_BuildFrame ( & model , amodel , b - > ent , ( short * ) ( ( qbyte * ) model . header + mesh - > index ) , tex_w , tex_h , b - > mesh [ 0 ] ) ;
return ;
}
}
batchid + + ;
}
}
}
qboolean R_CalcModelLighting ( entity_t * e , model_t * clmodel ) ;
void R_HalfLife_GenerateBatches ( entity_t * e , batch_t * * batches )
{
R_CalcModelLighting ( e , e - > model ) ;
R_HalfLife_WalkMeshes ( e , NULL , batches ) ;
}
2004-08-22 22:29:09 +00:00
# endif