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"
2016-12-07 18:45:25 +00:00
# include "com_mesh.h"
2004-08-22 22:29:09 +00:00
/*
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
2016-12-19 13:31:05 +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 .
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
2016-12-19 13:31:05 +00:00
Note : this code has since been greatly modified to fix skin , submodels , hitboxes , attachments , etc .
2004-08-22 22:29:09 +00:00
Also , please note that it won ' t do all hl models . . . .
Nor will it work 100 %
*/
2016-12-19 13:31:05 +00:00
qboolean HLMDL_Trace ( struct model_s * model , int hulloverride , framestate_t * framestate , vec3_t axis [ 3 ] , vec3_t p1 , vec3_t p2 , vec3_t mins , vec3_t maxs , qboolean capsule , unsigned int against , struct trace_s * trace ) ;
unsigned int HLMDL_Contents ( struct model_s * model , int hulloverride , framestate_t * framestate , vec3_t axis [ 3 ] , vec3_t p , vec3_t mins , vec3_t maxs ) ;
2004-08-22 22:29:09 +00:00
void QuaternionGLMatrix ( float x , float y , float z , float w , vec4_t * GLM )
{
2017-03-06 15:30:45 +00:00
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 ;
2004-08-22 22:29:09 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
2017-03-06 15:30:45 +00:00
QuaternionGLAngle - Convert a GL angle to a quaternion matrix
2004-08-22 22:29:09 +00:00
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
void QuaternionGLAngle ( const vec3_t angles , vec4_t quaternion )
{
2017-03-06 15:30:45 +00:00
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
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 ;
2004-08-22 22:29:09 +00:00
}
2008-12-23 02:55:20 +00:00
matrix3x4 transform_matrix [ MAX_BONES ] ; /* Vertex transformation matrix */
2004-08-22 22:29:09 +00:00
2016-12-19 13:31:05 +00:00
# ifndef SERVERONLY
2004-08-22 22:29:09 +00:00
void GL_Draw_HL_AliasFrame ( short * order , vec3_t * transformed , float tex_w , float tex_h ) ;
2016-12-07 18:45:25 +00:00
struct hlvremaps
{
unsigned short vertidx ;
unsigned short normalidx ;
unsigned short scoord ;
unsigned short tcoord ;
} ;
2016-12-09 09:09:12 +00:00
static index_t HLMDL_DeDupe ( unsigned short * order , struct hlvremaps * rem , size_t * count , size_t max )
2016-12-07 18:45:25 +00:00
{
size_t i ;
for ( i = * count ; i - - > 0 ; )
{
if ( rem [ i ] . vertidx = = order [ 0 ] & & rem [ i ] . normalidx = = order [ 1 ] & & rem [ i ] . scoord = = order [ 2 ] & & rem [ i ] . tcoord = = order [ 3 ] )
return i ;
}
i = * count ;
2016-12-09 09:09:12 +00:00
if ( i < max )
{
rem [ i ] . vertidx = order [ 0 ] ;
rem [ i ] . normalidx = order [ 1 ] ;
rem [ i ] . scoord = order [ 2 ] ;
rem [ i ] . tcoord = order [ 3 ] ;
}
2016-12-07 18:45:25 +00:00
* count + = 1 ;
return i ;
}
//parse the vertex info, pull out what we can
static void HLMDL_PrepareVerticies ( hlmodel_t * model , hlmdl_submodel_t * amodel , struct hlalternative_s * submodel )
{
struct hlvremaps * uvert ;
2016-12-09 09:09:12 +00:00
size_t uvertcount , uvertstart ;
2016-12-07 18:45:25 +00:00
unsigned short count ;
int i ;
2016-12-09 09:09:12 +00:00
size_t idx = 0 , v , m , maxidx = 65536 * 3 ;
size_t maxverts = 65536 ;
2016-12-07 18:45:25 +00:00
mesh_t * mesh = & submodel - > mesh ;
index_t * index ;
vec3_t * verts = ( vec3_t * ) ( ( qbyte * ) model - > header + amodel - > vertindex ) ;
qbyte * bone = ( ( qbyte * ) model - > header + amodel - > vertinfoindex ) ;
vec3_t * norms = ( vec3_t * ) ( ( qbyte * ) model - > header + amodel - > normindex ) ;
uvertcount = 0 ;
2016-12-09 09:09:12 +00:00
uvert = malloc ( sizeof ( * uvert ) * maxverts ) ;
index = malloc ( sizeof ( * mesh - > colors4b_array ) * maxidx ) ;
2016-12-07 18:45:25 +00:00
for ( m = 0 ; m < amodel - > nummesh ; m + + )
{
hlmdl_mesh_t * inmesh = ( hlmdl_mesh_t * ) ( ( qbyte * ) model - > header + amodel - > meshindex ) + m ;
unsigned short * order = ( unsigned short * ) ( ( qbyte * ) model - > header + inmesh - > index ) ;
2016-12-09 09:09:12 +00:00
uvertstart = uvertcount ;
2016-12-07 18:45:25 +00:00
submodel - > submesh [ m ] . firstindex = mesh - > numindexes ;
submodel - > submesh [ m ] . numindexes = 0 ;
for ( ; ; )
{
count = * order + + ; /* get the vertex count and primitive type */
if ( ! count ) break ; /* done */
if ( count & 0x8000 )
{ //fan
2016-12-09 09:09:12 +00:00
int first = HLMDL_DeDupe ( order + 0 * 4 , uvert , & uvertcount , maxverts ) ;
int prev = HLMDL_DeDupe ( order + 1 * 4 , uvert , & uvertcount , maxverts ) ;
count = ( unsigned short ) - ( short ) count ;
if ( idx + ( count - 2 ) * 3 > maxidx )
break ; //would overflow. fixme: extend
for ( i = min ( 2 , count ) ; i < count ; i + + )
2016-12-07 18:45:25 +00:00
{
index [ idx + + ] = first ;
index [ idx + + ] = prev ;
2016-12-09 09:09:12 +00:00
index [ idx + + ] = prev = HLMDL_DeDupe ( order + i * 4 , uvert , & uvertcount , maxverts ) ;
2016-12-07 18:45:25 +00:00
}
}
else
{
2016-12-09 09:09:12 +00:00
int v0 = HLMDL_DeDupe ( order + 0 * 4 , uvert , & uvertcount , maxverts ) ;
int v1 = HLMDL_DeDupe ( order + 1 * 4 , uvert , & uvertcount , maxverts ) ;
2016-12-07 18:45:25 +00:00
//emit (count-2)*3 indicies as a strip
//012 213, etc
2016-12-09 09:09:12 +00:00
if ( idx + ( count - 2 ) * 3 > maxidx )
break ; //would overflow. fixme: extend
2016-12-07 18:45:25 +00:00
for ( i = min ( 2 , count ) ; i < count ; i + + )
{
if ( i & 1 )
{
index [ idx + + ] = v1 ;
index [ idx + + ] = v0 ;
}
else
{
index [ idx + + ] = v0 ;
index [ idx + + ] = v1 ;
}
v0 = v1 ;
2016-12-09 09:09:12 +00:00
index [ idx + + ] = v1 = HLMDL_DeDupe ( order + i * 4 , uvert , & uvertcount , maxverts ) ;
2016-12-07 18:45:25 +00:00
}
}
order + = i * 4 ;
}
2016-12-09 09:09:12 +00:00
if ( uvertcount > = maxverts )
{
//if we're overflowing our verts, rewind, as we cannot generate this mesh. we'll just end up with a 0-index mesh, with no extra verts either
uvertcount = uvertstart ;
idx = submodel - > submesh [ m ] . firstindex ;
}
2016-12-07 18:45:25 +00:00
2016-12-09 09:09:12 +00:00
submodel - > submesh [ m ] . numindexes = idx - submodel - > submesh [ m ] . firstindex ;
2016-12-07 18:45:25 +00:00
}
2016-12-09 09:09:12 +00:00
2016-12-07 18:45:25 +00:00
mesh - > numindexes = idx ;
mesh - > numvertexes = uvertcount ;
2016-12-09 09:09:12 +00:00
mesh - > indexes = ZG_Malloc ( model - > memgroup , sizeof ( * mesh - > indexes ) * idx ) ;
memcpy ( mesh - > indexes , index , sizeof ( * mesh - > indexes ) * idx ) ;
2016-12-07 18:45:25 +00:00
mesh - > colors4b_array = ZG_Malloc ( model - > memgroup , sizeof ( * mesh - > colors4b_array ) * uvertcount ) ;
mesh - > st_array = ZG_Malloc ( model - > memgroup , sizeof ( * mesh - > st_array ) * uvertcount ) ;
mesh - > lmst_array [ 0 ] = ZG_Malloc ( model - > memgroup , sizeof ( * mesh - > lmst_array [ 0 ] ) * uvertcount ) ;
mesh - > xyz_array = ZG_Malloc ( model - > memgroup , sizeof ( * mesh - > xyz_array ) * uvertcount ) ;
mesh - > normals_array = ZG_Malloc ( model - > memgroup , sizeof ( * mesh - > normals_array ) * uvertcount ) ;
2016-12-21 15:48:52 +00:00
# if defined(RTLIGHTS)
2016-12-07 18:45:25 +00:00
mesh - > snormals_array = ZG_Malloc ( model - > memgroup , sizeof ( * mesh - > snormals_array ) * uvertcount ) ;
mesh - > tnormals_array = ZG_Malloc ( model - > memgroup , sizeof ( * mesh - > tnormals_array ) * uvertcount ) ;
2016-12-21 15:48:52 +00:00
# endif
2016-12-07 18:45:25 +00:00
mesh - > bonenums = ZG_Malloc ( model - > memgroup , sizeof ( * mesh - > bonenums ) * uvertcount ) ;
mesh - > boneweights = ZG_Malloc ( model - > memgroup , sizeof ( * mesh - > boneweights ) * uvertcount ) ;
//prepare the verticies now that we have the mappings
for ( v = 0 ; v < uvertcount ; v + + )
{
mesh - > bonenums [ v ] [ 0 ] = mesh - > bonenums [ v ] [ 1 ] = mesh - > bonenums [ v ] [ 2 ] = mesh - > bonenums [ v ] [ 3 ] = bone [ uvert [ v ] . vertidx ] ;
Vector4Set ( mesh - > boneweights [ v ] , 1 , 0 , 0 , 0 ) ;
Vector4Set ( mesh - > colors4b_array [ v ] , 255 , 255 , 255 , 255 ) ; //why bytes? why not?
mesh - > lmst_array [ 0 ] [ v ] [ 0 ] = uvert [ v ] . scoord ;
mesh - > lmst_array [ 0 ] [ v ] [ 1 ] = uvert [ v ] . tcoord ;
VectorCopy ( verts [ uvert [ v ] . vertidx ] , mesh - > xyz_array [ v ] ) ;
//Warning: these models use different tables for vertex and normals.
//this means they might be transformed by different bones. we ignore that and just assume that the normals will want the same bone.
VectorCopy ( norms [ uvert [ v ] . normalidx ] , mesh - > normals_array [ v ] ) ;
}
//don't need that mapping any more
free ( uvert ) ;
2016-12-09 09:09:12 +00:00
free ( index ) ;
2016-12-07 18:45:25 +00:00
2016-12-21 15:48:52 +00:00
# if defined(RTLIGHTS)
2016-12-07 18:45:25 +00:00
//treat this as the base pose, and calculate the sdir+tdir for bumpmaps.
R_Generate_Mesh_ST_Vectors ( mesh ) ;
2016-12-21 15:48:52 +00:00
# endif
2016-12-07 18:45:25 +00:00
}
2016-12-19 13:31:05 +00:00
# endif
2016-12-07 18:45:25 +00:00
2004-08-22 22:29:09 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
2017-03-06 15:30:45 +00:00
Mod_LoadHLModel - read in the model ' s constituent parts
2004-08-22 22:29:09 +00:00
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
2014-03-30 08:55:06 +00:00
qboolean QDECL Mod_LoadHLModel ( model_t * mod , void * buffer , size_t fsize )
2004-08-22 22:29:09 +00:00
{
2016-12-19 13:31:05 +00:00
# ifndef SERVERONLY
2016-12-07 18:45:25 +00:00
int i ;
2016-12-19 13:31:05 +00:00
int body ;
struct hlmodelshaders_s * shaders ;
2017-02-19 00:15:42 +00:00
hlmdl_tex_t * tex ;
2016-12-19 13:31:05 +00:00
# endif
2011-05-19 13:34:07 +00:00
2016-12-07 18:45:25 +00:00
hlmodel_t * model ;
2004-08-22 22:29:09 +00:00
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_bone_t * bones ;
hlmdl_bonecontroller_t * bonectls ;
2013-07-14 12:22:51 +00:00
void * texmem = NULL ;
2004-08-22 22:29:09 +00:00
//load the model into hunk
2016-12-07 18:45:25 +00:00
model = ZG_Malloc ( & mod - > memgroup , sizeof ( hlmodel_t ) ) ;
model - > memgroup = & mod - > memgroup ;
2004-08-22 22:29:09 +00:00
2015-10-11 11:34:58 +00:00
header = ZG_Malloc ( & mod - > memgroup , fsize ) ;
memcpy ( header , buffer , fsize ) ;
2004-08-22 22:29:09 +00:00
2009-02-22 13:45:35 +00:00
# if defined(HLSERVER) && (defined(__powerpc__) || defined(__ppc__))
2016-12-19 13:31:05 +00:00
//this is to let anyone who tries porting it know that there is a serious issue. And I'm lazy.
2011-10-27 16:16:29 +00:00
# ifdef warningmsg
# pragma warningmsg("-----------------------------------------")
2016-12-07 18:45:25 +00:00
# pragma warningmsg("FIXME: No byteswapping on halflife models") //hah, yeah, good luck with that, you'll need it.
2011-10-27 16:16:29 +00:00
# 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
{
2018-11-27 16:48:19 +00:00
Con_Printf ( CON_ERROR " Cannot load halflife 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 )
{
2015-10-11 11:34:58 +00:00
size_t fz ;
2009-02-22 13:45:35 +00:00
char texmodelname [ MAX_QPATH ] ;
COM_StripExtension ( mod - > name , texmodelname , sizeof ( texmodelname ) ) ;
2015-10-11 11:34:58 +00:00
Q_strncatz ( texmodelname , " t.mdl " , sizeof ( texmodelname ) ) ;
2009-02-22 13:45:35 +00:00
//no textures? eesh. They must be stored externally.
2015-10-11 11:34:58 +00:00
texheader = texmem = ( hlmdl_header_t * ) FS_LoadMallocFile ( texmodelname , & fz ) ;
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
2016-12-07 18:45:25 +00:00
bones = ( hlmdl_bone_t * ) ( ( qbyte * ) header + header - > boneindex ) ;
bonectls = ( hlmdl_bonecontroller_t * ) ( ( qbyte * ) header + header - > controllerindex ) ;
2004-08-22 22:29:09 +00:00
2015-10-11 11:34:58 +00:00
model - > header = header ;
model - > bones = bones ;
model - > bonectls = bonectls ;
2004-08-22 22:29:09 +00:00
2016-12-19 13:31:05 +00:00
# ifndef SERVERONLY
2017-02-19 00:15:42 +00:00
tex = ( hlmdl_tex_t * ) ( ( qbyte * ) texheader + texheader - > textures ) ;
2013-07-14 12:22:51 +00:00
shaders = ZG_Malloc ( & mod - > memgroup , texheader - > numtextures * sizeof ( shader_t ) ) ;
2015-10-11 11:34:58 +00:00
model - > shaders = shaders ;
2016-12-07 18:45:25 +00:00
for ( i = 0 ; i < texheader - > numtextures ; i + + )
{
Q_snprintfz ( shaders [ i ] . name , sizeof ( shaders [ i ] . name ) , " %s/%s " , mod - > name , COM_SkipPath ( tex [ i ] . name ) ) ;
2019-01-22 00:52:35 +00:00
/* handle the special textures - eukara */
2019-01-29 20:38:12 +00:00
if ( tex [ i ] . flags )
{
2019-01-22 00:52:35 +00:00
char * shader ;
2019-01-29 20:38:12 +00:00
if ( tex [ i ] . flags & HLMDLFL_FULLBRIGHT )
{
if ( tex [ i ] . flags & HLMDLFL_CHROME )
2019-01-22 00:52:35 +00:00
shader = HLSHADER_FULLBRIGHTCHROME ;
2019-01-29 20:38:12 +00:00
else
2019-01-22 00:52:35 +00:00
shader = HLSHADER_FULLBRIGHT ;
}
2019-01-29 20:38:12 +00:00
else if ( tex [ i ] . flags & HLMDLFL_CHROME )
shader = HLSHADER_CHROME ;
else
shader = " " ;
2019-03-12 06:41:52 +00:00
shaders [ i ] . defaultshadertext = shader ;
2019-01-22 00:52:35 +00:00
}
2019-03-13 02:35:08 +00:00
else
shaders [ i ] . defaultshadertext = NULL ;
2019-03-12 06:41:52 +00:00
memset ( & shaders [ i ] . defaulttex , 0 , sizeof ( shaders [ i ] . defaulttex ) ) ;
shaders [ i ] . defaulttex . base = Image_GetTexture ( shaders [ i ] . name , " " , IF_NOALPHA , ( qbyte * ) texheader + tex [ i ] . offset , ( qbyte * ) texheader + tex [ i ] . w * tex [ i ] . h + tex [ i ] . offset , tex [ i ] . w , tex [ i ] . h , TF_8PAL24 ) ;
shaders [ i ] . w = tex [ i ] . w ;
shaders [ i ] . h = tex [ i ] . h ;
2016-12-07 18:45:25 +00:00
}
2004-08-22 22:29:09 +00:00
2016-12-07 18:45:25 +00:00
model - > numskinrefs = texheader - > skinrefs ;
model - > numskingroups = texheader - > skingroups ;
model - > skinref = ZG_Malloc ( & mod - > memgroup , model - > numskinrefs * model - > numskingroups * sizeof ( * model - > skinref ) ) ;
memcpy ( model - > skinref , ( short * ) ( ( qbyte * ) texheader + texheader - > skins ) , model - > numskinrefs * model - > numskingroups * sizeof ( * model - > skinref ) ) ;
2016-12-19 13:31:05 +00:00
# endif
2013-12-29 22:48:28 +00:00
2013-07-14 12:22:51 +00:00
if ( texmem )
Z_Free ( texmem ) ;
2004-08-22 22:29:09 +00:00
2016-12-19 13:31:05 +00:00
mod - > funcs . NativeContents = HLMDL_Contents ;
mod - > funcs . NativeTrace = HLMDL_Trace ;
2004-08-22 22:29:09 +00:00
mod - > type = mod_halflife ;
2016-12-13 11:50:15 +00:00
mod - > numframes = model - > header - > numseq ;
2013-07-14 12:22:51 +00:00
mod - > meshinfo = model ;
2016-12-07 18:45:25 +00:00
2016-12-19 13:31:05 +00:00
# ifndef SERVERONLY
2016-12-07 18:45:25 +00:00
model - > numgeomsets = model - > header - > numbodyparts ;
model - > geomset = ZG_Malloc ( & mod - > memgroup , sizeof ( * model - > geomset ) * model - > numgeomsets ) ;
2016-12-19 13:31:05 +00:00
for ( body = 0 ; body < model - > numgeomsets ; body + + )
2016-12-07 18:45:25 +00:00
{
hlmdl_bodypart_t * bodypart = ( hlmdl_bodypart_t * ) ( ( qbyte * ) model - > header + model - > header - > bodypartindex ) + body ;
int bodyindex ;
model - > geomset [ body ] . numalternatives = bodypart - > nummodels ;
model - > geomset [ body ] . alternatives = ZG_Malloc ( & mod - > memgroup , sizeof ( * model - > geomset [ body ] . alternatives ) * bodypart - > nummodels ) ;
for ( bodyindex = 0 ; bodyindex < bodypart - > nummodels ; bodyindex + + )
{
hlmdl_submodel_t * amodel = ( hlmdl_submodel_t * ) ( ( qbyte * ) model - > header + bodypart - > modelindex ) + bodyindex ;
model - > geomset [ body ] . alternatives [ bodyindex ] . numsubmeshes = amodel - > nummesh ;
model - > geomset [ body ] . alternatives [ bodyindex ] . submesh = ZG_Malloc ( & mod - > memgroup , sizeof ( * model - > geomset [ body ] . alternatives [ bodyindex ] . submesh ) * amodel - > nummesh ) ;
HLMDL_PrepareVerticies ( model , amodel , & model - > geomset [ body ] . alternatives [ bodyindex ] ) ;
}
}
2016-12-19 13:31:05 +00:00
//FIXME: No VBOs used.
# endif
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 ) ;
2015-10-11 11:34:58 +00:00
return ( void * ) mc - > header ;
2009-02-22 13:45:35 +00:00
}
# endif
2016-12-07 18:45:25 +00:00
int HLMDL_FrameForName ( model_t * mod , const char * name )
2009-04-01 22:03:56 +00:00
{
int i ;
hlmdl_header_t * h ;
hlmdl_sequencelist_t * seqs ;
2016-12-07 18:45:25 +00:00
hlmodel_t * mc ;
2009-04-01 22:03:56 +00:00
if ( ! mod | | mod - > type ! = mod_halflife )
return - 1 ; //halflife models only, please
mc = Mod_Extradata ( mod ) ;
2015-10-11 11:34:58 +00:00
h = mc - > header ;
2009-04-01 22:03:56 +00:00
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 ;
}
2017-01-13 00:39:50 +00:00
qboolean HLMDL_GetModelEvent ( model_t * model , int animation , int eventidx , float * timestamp , int * eventcode , char * * eventdata )
{
hlmodel_t * mc = Mod_Extradata ( model ) ;
hlmdl_header_t * h = mc - > header ;
hlmdl_event_t * ev ;
hlmdl_sequencelist_t * seq = animation + ( hlmdl_sequencelist_t * ) ( ( char * ) h + h - > seqindex ) ;
if ( animation < 0 | | animation > = h - > numseq | | eventidx < 0 | | eventidx > = seq - > num_events )
return false ;
ev = eventidx + ( hlmdl_event_t * ) ( ( char * ) h + seq - > ofs_events ) ;
* timestamp = ev - > pose / seq - > timing ;
* eventcode = ev - > code ;
* eventdata = ev - > data ;
return true ;
}
2016-12-07 18:45:25 +00:00
int HLMDL_BoneForName ( model_t * mod , const char * name )
2009-04-01 22:03:56 +00:00
{
int i ;
hlmdl_header_t * h ;
hlmdl_bone_t * bones ;
2016-12-07 18:45:25 +00:00
hlmodel_t * mc ;
2009-04-01 22:03:56 +00:00
if ( ! mod | | mod - > type ! = mod_halflife )
return - 1 ; //halflife models only, please
mc = Mod_Extradata ( mod ) ;
2015-10-11 11:34:58 +00:00
h = mc - > header ;
2009-04-01 22:03:56 +00:00
bones = ( hlmdl_bone_t * ) ( ( char * ) h + h - > boneindex ) ;
for ( i = 0 ; i < h - > numbones ; i + + )
{
if ( ! strcmp ( bones [ i ] . name , name ) )
return i + 1 ;
}
2016-12-13 11:50:15 +00:00
//FIXME: hlmdl has tags as well as bones.
2009-04-01 22:03:56 +00:00
return 0 ;
}
2004-08-22 22:29:09 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
2017-03-06 15:30:45 +00:00
HL_CalculateBones - calculate bone positions - quaternion + vector in one function
2004-08-22 22:29:09 +00:00
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
void HL_CalculateBones
(
2016-12-05 13:35:10 +00:00
int frame ,
vec4_t adjust ,
hlmdl_bone_t * bone ,
hlmdl_anim_t * animation ,
float * organg
2004-08-22 22:29:09 +00:00
)
{
2016-12-05 13:35:10 +00:00
int i ;
/* For each vector */
for ( i = 0 ; i < 6 ; i + + )
{
organg [ i ] = bone - > value [ i ] ; /* Take the bone value */
if ( animation - > offset [ i ] ! = 0 )
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
int tempframe ;
hlmdl_animvalue_t * animvalue = ( hlmdl_animvalue_t * ) ( ( qbyte * ) animation + animation - > offset [ i ] ) ;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/* find values including the required frame */
tempframe = frame ;
2015-10-11 11:34:58 +00:00
while ( animvalue - > num . total < = tempframe )
2016-12-05 13:35:10 +00:00
{
tempframe - = animvalue - > num . total ;
animvalue + = animvalue - > num . valid + 1 ;
}
if ( tempframe > = animvalue - > num . valid )
tempframe = animvalue - > num . valid ;
else
tempframe + = 1 ;
2015-10-11 11:34:58 +00:00
2016-12-05 13:35:10 +00:00
organg [ i ] + = animvalue [ tempframe ] . value * bone - > scale [ i ] ;
}
2004-08-22 22:29:09 +00:00
2016-12-05 13:35:10 +00:00
if ( bone - > bonecontroller [ i ] ! = - 1 )
2008-11-09 22:29:28 +00:00
{ /* Add the programmable offset. */
2016-12-05 13:35:10 +00:00
organg [ i ] + = adjust [ bone - > bonecontroller [ i ] ] ;
}
}
2004-08-22 22:29:09 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
2017-03-06 15:30:45 +00:00
HL_CalcBoneAdj - Calculate the adjustment values for the programmable controllers
2004-08-22 22:29:09 +00:00
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
void HL_CalcBoneAdj ( hlmodel_t * model )
{
2016-12-05 13:35:10 +00:00
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
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 )
2016-12-07 18:45:25 +00:00
{ //wraps normally
value = model - > controller [ j ] ; // + control[i].start;
2016-12-05 13:35:10 +00:00
}
else
{
2016-12-07 18:45:25 +00:00
// value = (model->controller[j]+1)*0.5; //shifted to give a valid range between -1 and 1, with 0 being mid-range.
// if(value < 0)
// value = 0;
// else if(value > 1.0)
// value = 1.0;
// value = (1.0 - value) * control[i].start + value * control[i].end;
value = model - > controller [ j ] ;
if ( value < control [ i ] . start )
value = control [ i ] . start ;
if ( value > control [ i ] . end )
value = control [ i ] . end ;
2016-12-05 13:35:10 +00:00
}
/* 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 ;
}
2004-08-22 22:29:09 +00:00
}
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
2017-03-06 15:30:45 +00:00
HL_SetupBones - determine where vertex should be using bone movements
2004-08-22 22:29:09 +00:00
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
2008-11-09 22:29:28 +00:00
void QuaternionSlerp ( const vec4_t p , vec4_t q , float t , vec4_t qt ) ;
2017-11-30 17:59:11 +00:00
void HL_SetupBones ( hlmodel_t * model , int seqnum , int firstbone , int lastbone , float subblendfrac1 , float subblendfrac2 , float frametime , float * matrix )
2004-08-22 22:29:09 +00:00
{
2016-12-05 13:35:10 +00:00
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2017-11-30 17:59:11 +00:00
int i , j ;
2016-12-05 13:35:10 +00:00
vec3_t organg1 [ 2 ] ;
vec3_t organg2 [ 2 ] ;
vec3_t organgb [ 2 ] ;
2017-11-30 17:59:11 +00:00
vec4_t quat1 , quat2 ;
2008-11-09 22:29:28 +00:00
2015-10-11 11:34:58 +00:00
int frame1 , frame2 ;
2008-11-09 22:29:28 +00:00
2016-12-05 13:35:10 +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 ) ;
2016-12-05 13:35:10 +00:00
hlmdl_sequencedata_t * sequencedata = ( hlmdl_sequencedata_t * )
( ( qbyte * ) model - > header + model - > header - > seqgroups ) +
sequence - > seqindex ;
hlmdl_anim_t * animation ;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2004-08-22 22:29:09 +00:00
2016-12-07 18:45:25 +00:00
matrix + = firstbone * 12 ;
2015-10-11 11:34:58 +00:00
if ( sequencedata - > name [ 32 ] )
{
size_t fz ;
if ( sequence - > seqindex > = MAX_ANIM_GROUPS )
{
Sys_Error ( " Too many animation sequence cache groups \n " ) ;
return ;
}
if ( ! model - > animcache [ sequence - > seqindex ] )
model - > animcache [ sequence - > seqindex ] = FS_LoadMallocGroupFile ( model - > memgroup , sequencedata - > name + 32 , & fz ) ;
2017-01-29 13:10:53 +00:00
if ( ! model - > animcache [ sequence - > seqindex ] | | model - > animcache [ sequence - > seqindex ] - > magic ! = ( ( ' I ' < < 0 ) | ( ' D ' < < 8 ) | ( ' S ' < < 16 ) | ( ' Q ' < < 24 ) ) | | model - > animcache [ sequence - > seqindex ] - > version ! = 10 )
2015-10-11 11:34:58 +00:00
{
Sys_Error ( " Unable to load %s \n " , sequencedata - > name + 32 ) ;
return ;
}
animation = ( hlmdl_anim_t * ) ( ( qbyte * ) model - > animcache [ sequence - > seqindex ] + sequence - > index ) ;
}
else
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 ;
2015-10-11 11:34:58 +00:00
frame1 = ( int ) frametime ;
frametime - = frame1 ;
frame2 = frame1 + 1 ;
2008-11-09 22:29:28 +00:00
if ( ! sequence - > numframes )
return ;
2016-12-19 13:31:05 +00:00
//halflife seems to dupe the last frame in looping animations, so don't use it.
2016-12-05 13:35:10 +00:00
if ( frame1 > = sequence - > numframes )
2008-11-09 22:29:28 +00:00
{
2009-04-01 22:03:56 +00:00
if ( sequence - > loop )
2019-01-17 09:27:09 +00:00
frame1 % = sequence - > numframes ;
2009-04-01 22:03:56 +00:00
else
2015-10-11 11:34:58 +00:00
frame1 = sequence - > numframes - 1 ;
}
if ( frame2 > = sequence - > numframes )
{
if ( sequence - > loop )
2019-01-17 09:27:09 +00:00
frame2 % = sequence - > numframes ;
2015-10-11 11:34:58 +00:00
else
frame2 = sequence - > numframes - 1 ;
}
if ( frame2 < frame1 )
{
i = frame2 ;
frame2 = frame1 ;
frame1 = i ;
frametime = 1 - frametime ;
2008-11-09 22:29:28 +00:00
}
if ( lastbone > model - > header - > numbones )
lastbone = model - > header - > numbones ;
2016-12-05 13:35:10 +00:00
HL_CalcBoneAdj ( model ) ; /* Deal with programmable controllers */
2004-08-22 22:29:09 +00:00
2008-11-09 22:29:28 +00:00
/*FIXME:this is useless*/
/*
2016-12-05 13:35:10 +00:00
if ( sequence - > motiontype & 0x0001 )
2008-11-09 22:29:28 +00:00
positions [ sequence - > motionbone ] [ 0 ] = 0.0 ;
2016-12-05 13:35:10 +00:00
if ( sequence - > motiontype & 0x0002 )
2008-11-09 22:29:28 +00:00
positions [ sequence - > motionbone ] [ 1 ] = 0.0 ;
2016-12-05 13:35:10 +00:00
if ( sequence - > motiontype & 0x0004 )
2008-11-09 22:29:28 +00:00
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 .
*/
2017-11-30 17:59:11 +00:00
if ( sequence - > hasblendseq > 1 )
2008-11-09 22:29:28 +00:00
{
2017-11-30 17:59:11 +00:00
int bf0 , bf1 ;
2018-03-04 14:41:16 +00:00
unsigned int bweights ;
2017-11-30 17:59:11 +00:00
struct
2008-11-09 22:29:28 +00:00
{
2017-11-30 17:59:11 +00:00
int frame ;
float weight ;
hlmdl_anim_t * anim ;
} blend [ 8 ] ;
//right, so, this stuff is annoying.
//we have two different blend factors.
//we have up to 9 blend weights. figure out which frames are what
switch ( sequence - > hasblendseq )
{
case 0 : //erk?
return ;
case 1 : //no blending.
bf0 = bf1 = 1 ;
break ;
default :
case 2 : //mix(0, 1, weight0)
case 3 : //mix(0, 1, 2, weight0);
case 8 : //weight0 only...
bf0 = sequence - > hasblendseq ;
bf1 = 1 ;
break ;
case 4 : //mix(mix(0, 1, weight0), mix(2, 3, weight0), weight1)
bf0 = bf1 = 2 ;
break ;
//case 6: //???
// bf[0] = 3; bf[1] = 2;
// break;
case 9 : //mix(mix(0, 1, 2, weight0), mix(2, 3, 4, weight0), mix(5, 6, 7, weight0), weight1)
bf0 = bf1 = 3 ;
break ;
}
subblendfrac1 = ( subblendfrac1 + 1 ) / 2 ;
subblendfrac2 = ( subblendfrac2 + 1 ) / 2 ;
bweights = 0 ;
if ( bf0 > 1 )
{
float frac = ( bf0 - 1 ) * bound ( 0 , subblendfrac1 , 1 ) ;
int f1 = bound ( 0 , frac , bf0 - 1 ) ;
int f2 = bound ( 0 , f1 + 1 , bf0 - 1 ) ;
frac = ( frac - f1 ) ;
frac = bound ( 0 , frac , 1 ) ;
if ( bf1 > 1 )
2016-12-05 13:35:10 +00:00
{
2017-11-30 17:59:11 +00:00
float frac2 = ( bf1 - 1 ) * bound ( 0 , subblendfrac2 , 1 ) ;
int a1 = bound ( 0 , frac2 , bf1 - 1 ) ;
int a2 = bound ( 0 , a1 + 1 , bf1 - 1 ) ;
frac2 = ( frac2 - a1 ) ;
frac2 = bound ( 0 , frac2 , 1 ) ;
if ( frac2 )
{
if ( frac )
{
blend [ bweights ] . frame = frame1 ;
blend [ bweights ] . anim = animation + model - > header - > numbones * ( f2 + a2 * bf0 ) ;
blend [ bweights + + ] . weight = frac * frac2 ;
}
if ( 1 - frac )
{
blend [ bweights ] . frame = frame1 ;
blend [ bweights ] . anim = animation + model - > header - > numbones * ( f1 + a2 * bf0 ) ;
blend [ bweights + + ] . weight = ( 1 - frac ) * frac2 ;
}
}
if ( 1 - frac2 )
{
if ( frac )
{
blend [ bweights ] . frame = frame1 ;
blend [ bweights ] . anim = animation + model - > header - > numbones * ( f2 + a1 * bf0 ) ;
blend [ bweights + + ] . weight = frac * ( 1 - frac2 ) ;
}
if ( 1 - frac )
{
blend [ bweights ] . frame = frame1 ;
blend [ bweights ] . anim = animation + model - > header - > numbones * ( f1 + a1 * bf0 ) ;
blend [ bweights + + ] . weight = ( 1 - frac ) * ( 1 - frac2 ) ;
}
}
}
else
{
if ( frac )
{
blend [ bweights ] . frame = frame1 ;
blend [ bweights ] . anim = animation + model - > header - > numbones * f1 ;
blend [ bweights + + ] . weight = frac ;
}
if ( 1 - frac )
{
blend [ bweights ] . frame = frame1 ;
blend [ bweights ] . anim = animation + model - > header - > numbones * f2 ;
blend [ bweights + + ] . weight = 1 - frac ;
}
}
}
else
{
blend [ bweights ] . frame = frame1 ;
blend [ bweights ] . anim = animation ;
blend [ bweights + + ] . weight = 1 ;
}
if ( frame1 ! = frame2 )
{
2018-03-04 14:41:16 +00:00
//bweights can be 0-4 here..
2017-11-30 17:59:11 +00:00
for ( i = 0 ; i < bweights ; i + + )
{
blend [ bweights + i ] . frame = frame2 ;
blend [ bweights + i ] . anim = blend [ i ] . anim ;
blend [ bweights + i ] . weight = blend [ i ] . weight ;
2011-05-19 13:34:07 +00:00
2017-11-30 17:59:11 +00:00
blend [ i ] . weight * = 1 - frametime ;
blend [ bweights + i ] . weight * = frametime ;
2016-12-05 13:35:10 +00:00
}
2017-11-30 17:59:11 +00:00
bweights * = 2 ;
}
2008-11-09 22:29:28 +00:00
2017-11-30 17:59:11 +00:00
for ( i = firstbone ; i < lastbone ; i + + , matrix + = 12 )
{
vec3_t t ;
float len ;
HL_CalculateBones ( blend [ 0 ] . frame , model - > adjust , model - > bones + i , blend [ 0 ] . anim + i , organgb [ 0 ] ) ;
QuaternionGLAngle ( organgb [ 1 ] , quat2 ) ;
Vector4Scale ( quat2 , blend [ 0 ] . weight , quat1 ) ;
VectorScale ( organgb [ 0 ] , blend [ 0 ] . weight , t ) ;
for ( j = 1 ; j < bweights ; j + + )
2016-12-05 13:35:10 +00:00
{
2017-11-30 17:59:11 +00:00
HL_CalculateBones ( blend [ j ] . frame , model - > adjust , model - > bones + i , blend [ j ] . anim + i , organgb [ 0 ] ) ;
QuaternionGLAngle ( organgb [ 1 ] , quat2 ) ;
if ( DotProduct4 ( quat2 , quat1 ) < 0 ) //negative quats are annoying
Vector4MA ( quat1 , - blend [ j ] . weight , quat2 , quat1 ) ;
else
Vector4MA ( quat1 , blend [ j ] . weight , quat2 , quat1 ) ;
VectorMA ( t , blend [ j ] . weight , organgb [ 0 ] , t ) ;
}
2016-12-05 13:35:10 +00:00
2017-11-30 17:59:11 +00:00
//we were lame and didn't use slerp. boo hiss. now we need to normalise the things and hope we didn't hit any singularities
len = sqrt ( DotProduct4 ( quat1 , quat1 ) ) ;
if ( len & & len ! = 1 )
{
len = 1 / len ;
quat1 [ 0 ] * = len ;
quat1 [ 1 ] * = len ;
quat1 [ 2 ] * = len ;
quat1 [ 3 ] * = len ;
2016-12-05 13:35:10 +00:00
}
2016-12-07 18:45:25 +00:00
QuaternionGLMatrix ( quat1 [ 0 ] , quat1 [ 1 ] , quat1 [ 2 ] , quat1 [ 3 ] , ( vec4_t * ) matrix ) ;
2017-11-30 17:59:11 +00:00
matrix [ 0 * 4 + 3 ] = t [ 0 ] ;
matrix [ 1 * 4 + 3 ] = t [ 1 ] ;
matrix [ 2 * 4 + 3 ] = t [ 2 ] ;
2008-11-09 22:29:28 +00:00
}
}
else
{
2016-12-07 18:45:25 +00:00
for ( i = firstbone ; i < lastbone ; i + + , matrix + = 12 )
2008-11-09 22:29:28 +00:00
{
2016-12-05 13:35:10 +00:00
HL_CalculateBones ( frame1 , model - > adjust , model - > bones + i , animation + i , organg1 [ 0 ] ) ;
QuaternionGLAngle ( organg1 [ 1 ] , quat1 ) ; /* A quaternion */
if ( frame1 ! = frame2 )
{
HL_CalculateBones ( frame2 , model - > adjust , model - > bones + i , animation + i , organg2 [ 0 ] ) ;
QuaternionGLAngle ( organg2 [ 1 ] , quat2 ) ; /* A quaternion */
//lerp the quats properly rather than poorly lerping eular angles.
QuaternionSlerp ( quat1 , quat2 , frametime , quat1 ) ;
VectorInterpolate ( organg1 [ 0 ] , frametime , organg2 [ 0 ] , organg1 [ 0 ] ) ;
}
2016-12-07 18:45:25 +00:00
//figure out the relative bone matrix.
2016-12-05 13:35:10 +00:00
//we probably ought to keep them as quats or something.
2016-12-07 18:45:25 +00:00
QuaternionGLMatrix ( quat1 [ 0 ] , quat1 [ 1 ] , quat1 [ 2 ] , quat1 [ 3 ] , ( vec4_t * ) matrix ) ;
matrix [ 0 * 4 + 3 ] = organg1 [ 0 ] [ 0 ] ;
matrix [ 1 * 4 + 3 ] = organg1 [ 0 ] [ 1 ] ;
matrix [ 2 * 4 + 3 ] = organg1 [ 0 ] [ 2 ] ;
2008-11-09 22:29:28 +00:00
}
}
2004-08-22 22:29:09 +00:00
}
2016-12-19 13:31:05 +00:00
int HLMDL_GetNumBones ( model_t * mod , qboolean tags )
2012-07-05 19:42:36 +00:00
{
2016-12-07 18:45:25 +00:00
hlmodel_t * mc ;
if ( ! mod | | mod - > type ! = mod_halflife )
return - 1 ; //halflife models only, please
2012-07-05 19:42:36 +00:00
2016-12-07 18:45:25 +00:00
mc = Mod_Extradata ( mod ) ;
2016-12-19 13:31:05 +00:00
if ( tags )
return mc - > header - > numbones + mc - > header - > num_attachments ;
2016-12-07 18:45:25 +00:00
return mc - > header - > numbones ;
}
2012-07-05 19:42:36 +00:00
2016-12-13 11:50:15 +00:00
int HLMDL_GetBoneParent ( model_t * mod , int bonenum )
{
hlmodel_t * model = Mod_Extradata ( mod ) ;
if ( bonenum > = 0 & & bonenum < model - > header - > numbones )
return model - > bones [ bonenum ] . parent ;
2016-12-19 13:31:05 +00:00
bonenum - = model - > header - > numbones ;
if ( bonenum > = 0 & & bonenum < model - > header - > num_attachments )
{
hlmdl_attachment_t * attachments = bonenum + ( hlmdl_attachment_t * ) ( ( char * ) model - > header + model - > header - > ofs_attachments ) ;
return attachments - > bone ;
}
2016-12-13 11:50:15 +00:00
return - 1 ;
}
const char * HLMDL_GetBoneName ( model_t * mod , int bonenum )
{
hlmodel_t * model = Mod_Extradata ( mod ) ;
if ( bonenum > = 0 & & bonenum < model - > header - > numbones )
return model - > bones [ bonenum ] . name ;
2016-12-19 13:31:05 +00:00
bonenum - = model - > header - > numbones ;
if ( bonenum > = 0 & & bonenum < model - > header - > num_attachments )
{
hlmdl_attachment_t * attachments = bonenum + ( hlmdl_attachment_t * ) ( ( char * ) model - > header + model - > header - > ofs_attachments ) ;
if ( * attachments - > name )
return attachments - > name ;
return " Unnamed Attachment " ;
}
2016-12-13 11:50:15 +00:00
return NULL ;
}
2016-12-19 13:31:05 +00:00
int HLMDL_GetAttachment ( model_t * mod , int tagnum , float * resultmatrix )
2016-12-07 18:45:25 +00:00
{
hlmodel_t * model = Mod_Extradata ( mod ) ;
2016-12-19 13:31:05 +00:00
if ( tagnum > = 0 & & tagnum < model - > header - > num_attachments )
{
hlmdl_attachment_t * attachments = tagnum + ( hlmdl_attachment_t * ) ( ( char * ) model - > header + model - > header - > ofs_attachments ) ;
resultmatrix [ 3 ] = attachments - > org [ 0 ] ;
resultmatrix [ 7 ] = attachments - > org [ 1 ] ;
resultmatrix [ 11 ] = attachments - > org [ 2 ] ;
return attachments - > bone ;
}
return - 1 ;
}
static int HLMDL_GetBoneData_Internal ( hlmodel_t * model , int firstbone , int lastbone , framestate_t * fstate , float * result )
{
int b , cbone , bgroup ;
2012-07-05 19:42:36 +00:00
2016-12-07 18:45:25 +00:00
for ( b = 0 ; b < MAX_BONE_CONTROLLERS ; b + + )
model - > controller [ b ] = fstate - > bonecontrols [ b ] ;
for ( cbone = 0 , bgroup = 0 ; bgroup < FS_COUNT ; bgroup + + )
2012-07-05 19:42:36 +00:00
{
2016-12-07 18:45:25 +00:00
lastbone = fstate - > g [ bgroup ] . endbone ;
2012-07-05 19:42:36 +00:00
if ( bgroup = = FS_COUNT - 1 )
lastbone = model - > header - > numbones ;
if ( cbone > = lastbone )
continue ;
2017-11-30 17:59:11 +00:00
HL_SetupBones ( model , fstate - > g [ bgroup ] . frame [ 0 ] , cbone , lastbone , fstate - > g [ bgroup ] . subblendfrac , fstate - > g [ bgroup ] . subblend2frac , fstate - > g [ bgroup ] . frametime [ 0 ] , result ) ; /* Setup the bones */
2012-07-05 19:42:36 +00:00
cbone = lastbone ;
}
2016-12-07 18:45:25 +00:00
return cbone ;
}
2016-12-19 13:31:05 +00:00
int HLMDL_GetBoneData ( model_t * mod , int firstbone , int lastbone , framestate_t * fstate , float * result )
{
return HLMDL_GetBoneData_Internal ( Mod_Extradata ( mod ) , firstbone , lastbone , fstate , result ) ;
}
2012-07-05 19:42:36 +00:00
2016-12-07 18:45:25 +00:00
const char * HLMDL_FrameNameForNum ( model_t * mod , int surfaceidx , int seqnum )
{
hlmodel_t * model = Mod_Extradata ( mod ) ;
hlmdl_sequencelist_t * sequence = ( hlmdl_sequencelist_t * ) ( ( qbyte * ) model - > header + model - > header - > seqindex ) +
( ( unsigned int ) seqnum > = model - > header - > numseq ? 0 : seqnum ) ;
return sequence - > name ;
}
qboolean HLMDL_FrameInfoForNum ( model_t * mod , int surfaceidx , int seqnum , char * * name , int * numframes , float * duration , qboolean * loop )
{
hlmodel_t * model = Mod_Extradata ( mod ) ;
hlmdl_sequencelist_t * sequence = ( hlmdl_sequencelist_t * ) ( ( qbyte * ) model - > header + model - > header - > seqindex ) +
( ( unsigned int ) seqnum > = model - > header - > numseq ? 0 : seqnum ) ;
2012-07-05 19:42:36 +00:00
2016-12-07 18:45:25 +00:00
* name = sequence - > name ;
* numframes = sequence - > numframes ;
2016-12-19 13:31:05 +00:00
* duration = ( sequence - > numframes - 1 ) / sequence - > timing ;
2016-12-07 18:45:25 +00:00
* loop = sequence - > loop ;
return true ;
}
2012-07-05 19:42:36 +00:00
2016-12-19 13:31:05 +00:00
qboolean HLMDL_Trace ( model_t * model , int hulloverride , framestate_t * framestate , vec3_t axis [ 3 ] , vec3_t p1 , vec3_t p2 , vec3_t mins , vec3_t maxs , qboolean capsule , unsigned int against , struct trace_s * trace )
{
hlmodel_t * hm = Mod_Extradata ( model ) ;
float * relbones ;
float calcrelbones [ MAX_BONES * 12 ] ;
int bonecount ;
int b , i ;
vec3_t norm , p1l , p2l ;
float inverse [ 12 ] ;
hlmdl_hitbox_t * hitbox = ( hlmdl_hitbox_t * ) ( ( char * ) hm - > header + hm - > header - > ofs_hitboxes ) ;
float dist , d1 , d2 , f , enterfrac , enterdist , exitfrac ;
qboolean startout , endout ;
int enterplane ;
memset ( trace , 0 , sizeof ( trace_t ) ) ;
trace - > fraction = trace - > truefraction = 1 ;
2019-01-17 09:27:09 +00:00
if ( ! ( against & FTECONTENTS_BODY ) | | ! framestate )
2016-12-19 13:31:05 +00:00
return false ;
if ( framestate - > bonestate & & framestate - > skeltype = = SKEL_ABSOLUTE )
{
relbones = framestate - > bonestate ;
bonecount = framestate - > bonecount ;
if ( axis )
{
for ( b = 0 ; b < bonecount ; b + + )
R_ConcatTransformsAxis ( axis , ( void * ) ( relbones + b * 12 ) , transform_matrix [ b ] ) ;
}
else
memcpy ( transform_matrix , relbones , bonecount * 12 * sizeof ( float ) ) ;
}
else
{
//get relative bones from th emodel.
if ( framestate - > bonestate )
{
relbones = framestate - > bonestate ;
bonecount = framestate - > bonecount ;
}
else
{
relbones = calcrelbones ;
bonecount = HLMDL_GetBoneData ( model , 0 , MAX_BONES , framestate , calcrelbones ) ;
}
//convert relative to absolutes
for ( b = 0 ; b < bonecount ; b + + )
{
/* If we have a parent, take the addition. Otherwise just copy the values */
if ( hm - > bones [ b ] . parent > = 0 )
2019-03-04 19:24:51 +00:00
R_ConcatTransforms ( ( void * ) transform_matrix [ hm - > bones [ b ] . parent ] , ( void * ) ( relbones + b * 12 ) , transform_matrix [ b ] ) ;
2016-12-19 13:31:05 +00:00
else if ( axis )
R_ConcatTransformsAxis ( axis , ( void * ) ( relbones + b * 12 ) , transform_matrix [ b ] ) ;
else
memcpy ( transform_matrix [ b ] , relbones + b * 12 , 12 * sizeof ( float ) ) ;
}
}
for ( b = 0 ; b < hm - > header - > num_hitboxes ; b + + , hitbox + + )
{
startout = false ;
endout = false ;
2016-12-21 15:48:52 +00:00
enterplane = 0 ;
2016-12-19 13:31:05 +00:00
enterfrac = - 1 ;
exitfrac = 10 ;
2016-12-21 15:48:52 +00:00
enterdist = 0 ;
2016-12-19 13:31:05 +00:00
//fixme: would be nice to check if there's a possible collision a bit faster, without needing to do lots of excess maths.
//transform start+end into the bbox, so everything is axial and simple.
Matrix3x4_Invert_Simple ( ( void * ) transform_matrix [ hitbox - > bone ] , inverse ) ;
Matrix3x4_RM_Transform3 ( inverse , p1 , p1l ) ;
Matrix3x4_RM_Transform3 ( inverse , p2 , p2l ) ;
//fixme: would it be faster to just generate the plane and transform that, colliding non-axially? would probably be better for sized impactors.
//clip against the 6 axial faces
for ( i = 0 ; i < 6 ; i + + )
{
if ( i < 3 )
{ //normal>0
dist = hitbox - > maxs [ i ] - mins [ i ] ;
d1 = p1l [ i ] - dist ;
d2 = p2l [ i ] - dist ;
}
else
{ //normal<0
dist = maxs [ i - 3 ] - hitbox - > mins [ i - 3 ] ;
d1 = - p1l [ i - 3 ] - dist ;
d2 = - p2l [ i - 3 ] - dist ;
}
//FIXME: if the trace has size, we should insert 6 extra planes for the shape of the impactor
//FIXME: capsules
if ( d1 > = 0 )
startout = true ;
if ( d2 > 0 )
endout = true ;
//if we're fully outside any plane, then we cannot possibly enter the brush, skip to the next one
if ( d1 > 0 & & d2 > = 0 )
goto nextbrush ;
//if we're fully inside the plane, then whatever is happening is not relevent for this plane
if ( d1 < 0 & & d2 < = 0 )
continue ;
f = d1 / ( d1 - d2 ) ;
if ( d1 > d2 )
{
//entered the brush. favour the furthest fraction to avoid extended edges (yay for convex shapes)
if ( enterfrac < f )
{
enterfrac = f ;
enterplane = i ;
enterdist = dist ;
}
}
else
{
//left the brush, favour the nearest plane (smallest frac)
if ( exitfrac > f )
{
exitfrac = f ;
}
}
}
if ( ! startout )
{
trace - > startsolid = true ;
if ( ! endout )
trace - > allsolid = true ;
trace - > contents = FTECONTENTS_BODY ;
trace - > brush_face = 0 ;
trace - > bone_id = hitbox - > bone + 1 ;
trace - > brush_id = b + 1 ;
trace - > surface_id = hitbox - > body ;
break ;
}
if ( enterfrac ! = - 1 & & enterfrac < exitfrac )
{
//impact!
if ( enterfrac < trace - > fraction )
{
trace - > fraction = trace - > truefraction = enterfrac ;
trace - > plane . dist = enterdist ;
trace - > contents = FTECONTENTS_BODY ;
trace - > brush_face = enterplane + 1 ;
trace - > bone_id = hitbox - > bone + 1 ;
trace - > brush_id = b + 1 ;
trace - > surface_id = hitbox - > body ;
}
}
nextbrush :
;
}
if ( trace - > brush_face )
{
VectorClear ( norm ) ;
if ( trace - > brush_face < 4 )
norm [ trace - > brush_face - 1 ] = 1 ;
else
norm [ trace - > brush_face - 4 ] = - 1 ;
Matrix3x4_RM_Transform3x3 ( ( void * ) transform_matrix [ trace - > bone_id - 1 ] , norm , trace - > plane . normal ) ;
}
else
VectorClear ( trace - > plane . normal ) ;
VectorInterpolate ( p1 , trace - > fraction , p2 , trace - > endpos ) ;
return trace - > truefraction ! = 1 ;
}
unsigned int HLMDL_Contents ( model_t * model , int hulloverride , framestate_t * framestate , vec3_t axis [ 3 ] , vec3_t p , vec3_t mins , vec3_t maxs )
{
trace_t tr ;
HLMDL_Trace ( model , hulloverride , framestate , axis , p , p , mins , maxs , false , ~ 0 , & tr ) ;
return tr . contents ;
}
# ifndef SERVERONLY
2016-12-07 18:45:25 +00:00
void R_HL_BuildFrame ( hlmodel_t * model , hlmdl_submodel_t * amodel , entity_t * curent , int bodypart , int bodyidx , int meshidx , float tex_s , float tex_t , mesh_t * mesh , qboolean gpubones )
{
int b ;
int cbone ;
2016-12-19 13:31:05 +00:00
// int bgroup;
// int lastbone;
2016-12-07 18:45:25 +00:00
int v ;
2012-07-05 19:42:36 +00:00
2016-12-07 18:45:25 +00:00
* mesh = model - > geomset [ bodypart ] . alternatives [ bodyidx ] . mesh ;
2012-07-05 19:42:36 +00:00
2016-12-07 18:45:25 +00:00
//FIXME: cache this!
if ( curent - > framestate . bonecount > = model - > header - > numbones )
{
if ( curent - > framestate . skeltype = = SKEL_RELATIVE )
{
mesh - > numbones = model - > header - > numbones ;
for ( b = 0 ; b < mesh - > numbones ; b + + )
2012-07-05 19:42:36 +00:00
{
2016-12-07 18:45:25 +00:00
/* If we have a parent, take the addition. Otherwise just copy the values */
if ( model - > bones [ b ] . parent > = 0 )
{
2019-03-04 19:24:51 +00:00
R_ConcatTransforms ( ( void * ) transform_matrix [ model - > bones [ b ] . parent ] , ( void * ) ( curent - > framestate . bonestate + b * 12 ) , transform_matrix [ b ] ) ;
2016-12-07 18:45:25 +00:00
}
else
{
memcpy ( transform_matrix [ b ] , curent - > framestate . bonestate + b * 12 , 12 * sizeof ( float ) ) ;
}
2012-07-05 19:42:36 +00:00
}
2016-12-07 18:45:25 +00:00
mesh - > bones = transform_matrix [ 0 ] [ 0 ] ;
2012-07-05 19:42:36 +00:00
}
else
{
2016-12-07 18:45:25 +00:00
mesh - > bones = curent - > framestate . bonestate ;
mesh - > numbones = curent - > framestate . bonecount ;
}
}
else
{
float relatives [ 12 * MAX_BONES ] ;
mesh - > bones = transform_matrix [ 0 ] [ 0 ] ;
mesh - > numbones = model - > header - > numbones ;
2016-12-19 13:31:05 +00:00
/* //FIXME: needs caching.
2016-12-07 18:45:25 +00:00
for ( b = 0 ; b < MAX_BONE_CONTROLLERS ; b + + )
model - > controller [ b ] = curent - > framestate . bonecontrols [ b ] ;
for ( cbone = 0 , 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 ;
2017-11-30 17:59:11 +00:00
HL_SetupBones ( model , curent - > framestate . g [ bgroup ] . frame [ 0 ] , cbone , lastbone , curent - > framestate . g [ bgroup ] . subblendfrac , curent - > framestate . g [ bgroup ] . frametime [ 0 ] , relatives ) ; // Setup the bones
2016-12-07 18:45:25 +00:00
cbone = lastbone ;
}
2016-12-19 13:31:05 +00:00
*/
cbone = HLMDL_GetBoneData_Internal ( model , 0 , model - > header - > numbones , & curent - > framestate , relatives ) ;
2012-07-05 19:42:36 +00:00
2016-12-07 18:45:25 +00:00
//convert relative to absolutes
for ( b = 0 ; b < cbone ; b + + )
{
/* If we have a parent, take the addition. Otherwise just copy the values */
if ( model - > bones [ b ] . parent > = 0 )
2012-07-05 19:42:36 +00:00
{
2019-03-04 19:24:51 +00:00
R_ConcatTransforms ( ( void * ) transform_matrix [ model - > bones [ b ] . parent ] , ( void * ) ( relatives + b * 12 ) , transform_matrix [ b ] ) ;
2016-12-07 18:45:25 +00:00
}
else
{
memcpy ( transform_matrix [ b ] , relatives + b * 12 , 12 * sizeof ( float ) ) ;
2012-07-05 19:42:36 +00:00
}
}
2016-12-07 18:45:25 +00:00
}
2012-07-05 19:42:36 +00:00
2016-12-07 18:45:25 +00:00
mesh - > indexes + = model - > geomset [ bodypart ] . alternatives [ bodyidx ] . submesh [ meshidx ] . firstindex ;
mesh - > numindexes = model - > geomset [ bodypart ] . alternatives [ bodyidx ] . submesh [ meshidx ] . numindexes ;
if ( gpubones )
{ //get the backend to do the skeletal stuff (read: glsl)
for ( v = 0 ; v < mesh - > numvertexes ; v + + )
{ //should really come up with a better way to deal with this, like rect textures.
mesh - > st_array [ v ] [ 0 ] = mesh - > lmst_array [ 0 ] [ v ] [ 0 ] * tex_s ;
mesh - > st_array [ v ] [ 1 ] = mesh - > lmst_array [ 0 ] [ v ] [ 1 ] * tex_t ;
}
2016-12-05 13:35:10 +00:00
}
2016-12-07 18:45:25 +00:00
else
{ //backend can't handle it, apparently. do it in software.
static vecV_t nxyz [ 2048 ] ;
static vec3_t nnorm [ 2048 ] ;
for ( v = 0 ; v < mesh - > numvertexes ; v + + )
{ //should really come up with a better way to deal with this, like rect textures.
mesh - > st_array [ v ] [ 0 ] = mesh - > lmst_array [ 0 ] [ v ] [ 0 ] * tex_s ;
mesh - > st_array [ v ] [ 1 ] = mesh - > lmst_array [ 0 ] [ v ] [ 1 ] * tex_t ;
2012-07-05 19:42:36 +00:00
2016-12-07 18:45:25 +00:00
VectorTransform ( mesh - > xyz_array [ v ] , ( void * ) transform_matrix [ mesh - > bonenums [ v ] [ 0 ] ] , nxyz [ v ] ) ;
nnorm [ v ] [ 0 ] = DotProduct ( mesh - > normals_array [ v ] , transform_matrix [ mesh - > bonenums [ v ] [ 0 ] ] [ 0 ] ) ;
nnorm [ v ] [ 1 ] = DotProduct ( mesh - > normals_array [ v ] , transform_matrix [ mesh - > bonenums [ v ] [ 0 ] ] [ 1 ] ) ;
nnorm [ v ] [ 2 ] = DotProduct ( mesh - > normals_array [ v ] , transform_matrix [ mesh - > bonenums [ v ] [ 0 ] ] [ 2 ] ) ;
//FIXME: svector, tvector!
}
mesh - > xyz_array = nxyz ;
mesh - > normals_array = nnorm ;
mesh - > bonenums = NULL ;
mesh - > boneweights = NULL ;
mesh - > bones = NULL ;
mesh - > numbones = 0 ;
}
2012-07-05 19:42:36 +00:00
}
2016-12-19 13:31:05 +00:00
static void R_HalfLife_WalkMeshes ( entity_t * rent , batch_t * b , batch_t * * batches ) ;
static void R_HL_BuildMesh ( struct batch_s * b )
2012-07-05 19:42:36 +00:00
{
R_HalfLife_WalkMeshes ( b - > ent , b , NULL ) ;
}
2016-12-19 13:31:05 +00:00
static void R_HalfLife_WalkMeshes ( entity_t * rent , batch_t * b , batch_t * * batches )
2012-07-05 19:42:36 +00:00
{
2016-12-07 18:45:25 +00:00
hlmodel_t * model = Mod_Extradata ( rent - > 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 ;
2016-12-07 18:45:25 +00:00
skinfile_t * sk = NULL ;
2012-07-05 19:42:36 +00:00
2016-12-13 11:50:15 +00:00
unsigned int entity_body = 0 ;
2012-07-05 19:42:36 +00:00
2016-12-07 18:45:25 +00:00
if ( rent - > customskin )
sk = Mod_LookupSkin ( rent - > customskin ) ;
//entity_body = rent->body; //hey, if its there, lets use it.
2016-12-19 13:31:05 +00:00
for ( body = 0 ; body < model - > numgeomsets ; body + + )
2016-12-05 13:35:10 +00:00
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2016-12-07 18:45:25 +00:00
hlmdl_bodypart_t * bodypart = ( hlmdl_bodypart_t * ) ( ( qbyte * ) model - > header + model - > header - > bodypartindex ) + body ;
int bodyindex = ( ( sk & & body < MAX_GEOMSETS & & sk - > geomset [ body ] > = 1 ) ? sk - > geomset [ body ] - 1 : ( entity_body / bodypart - > base ) ) % bodypart - > nummodels ;
hlmdl_submodel_t * amodel = ( hlmdl_submodel_t * ) ( ( qbyte * ) model - > header + bodypart - > modelindex ) + bodyindex ;
2016-12-05 13:35:10 +00:00
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/* Draw each mesh */
for ( m = 0 ; m < amodel - > nummesh ; m + + )
{
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2016-12-07 18:45:25 +00:00
hlmdl_mesh_t * mesh = ( hlmdl_mesh_t * ) ( ( qbyte * ) model - > header + amodel - > meshindex ) + m ;
2016-12-05 13:35:10 +00:00
float tex_w ;
float tex_h ;
2015-10-11 11:34:58 +00:00
struct hlmodelshaders_s * s ;
2016-12-07 18:45:25 +00:00
int skinidx = mesh - > skinindex ;
2016-12-05 13:35:10 +00:00
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
2012-07-05 19:42:36 +00:00
2016-12-07 18:45:25 +00:00
if ( skinidx > = model - > numskinrefs )
continue ; //can happen from bad mesh/skin mixing
if ( rent - > skinnum < model - > numskingroups )
skinidx + = rent - > skinnum * model - > numskinrefs ;
s = & model - > shaders [ model - > skinref [ skinidx ] ] ;
2015-10-11 11:34:58 +00:00
2012-07-05 19:42:36 +00:00
if ( batches )
{
2015-10-11 11:34:58 +00:00
int sort , j ;
2012-07-05 19:42:36 +00:00
b = BE_GetTempBatch ( ) ;
if ( ! b )
return ;
2016-12-07 18:45:25 +00:00
2015-10-11 11:34:58 +00:00
if ( ! s - > shader )
{
2019-03-12 06:41:52 +00:00
if ( s - > defaultshadertext )
s - > shader = R_RegisterShader ( s - > name , SUF_NONE , s - > defaultshadertext ) ;
else
s - > shader = R_RegisterSkin ( s - > name , rent - > model - > name ) ;
2018-09-29 17:31:58 +00:00
R_BuildDefaultTexnums ( & s - > defaulttex , s - > shader , 0 ) ;
2015-10-11 11:34:58 +00:00
}
2016-12-07 18:45:25 +00:00
b - > skin = NULL ;
b - > shader = s - > shader ;
if ( sk )
{
int i ;
for ( i = 0 ; i < sk - > nummappings ; i + + )
{
if ( ! strcmp ( sk - > mappings [ i ] . surface , s - > name ) )
{
b - > skin = & sk - > mappings [ i ] . texnums ;
b - > shader = sk - > mappings [ i ] . shader ;
break ;
}
}
}
2017-07-02 18:59:27 +00:00
if ( rent - > forcedshader ) {
b - > shader = rent - > forcedshader ;
}
2016-12-07 18:45:25 +00:00
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 - > texture = NULL ;
2015-06-22 11:49:15 +00:00
for ( j = 0 ; j < MAXRLIGHTMAPS ; j + + )
b - > lightmap [ j ] = - 1 ;
2012-07-05 19:42:36 +00:00
b - > surf_first = batchid ;
b - > flags = 0 ;
2015-10-11 11:34:58 +00:00
sort = b - > shader - > sort ;
2012-07-05 19:42:36 +00:00
//fixme: we probably need to force some blend modes based on the surface flags.
if ( rent - > flags & RF_FORCECOLOURMOD )
b - > flags | = BEF_FORCECOLOURMOD ;
2014-03-31 17:06:41 +00:00
if ( rent - > flags & RF_ADDITIVE )
2012-07-05 19:42:36 +00:00
{
b - > flags | = BEF_FORCEADDITIVE ;
if ( sort < SHADER_SORT_ADDITIVE )
sort = SHADER_SORT_ADDITIVE ;
}
2014-03-31 17:06:41 +00:00
if ( rent - > flags & RF_TRANSLUCENT )
2012-07-05 19:42:36 +00:00
{
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 ;
}
2016-12-07 18:45:25 +00:00
else
2012-07-05 19:42:36 +00:00
{
if ( batchid = = b - > surf_first )
{
2015-10-11 11:34:58 +00:00
tex_w = 1.0f / s - > w ;
tex_h = 1.0f / s - > h ;
2012-07-05 19:42:36 +00:00
b - > mesh = & mptr ;
2016-12-07 18:45:25 +00:00
R_HL_BuildFrame ( model , amodel , b - > ent , body , bodyindex , m , tex_w , tex_h , b - > mesh [ 0 ] , b - > shader - > prog & & ( b - > shader - > prog - > supportedpermutations & PERMUTATION_SKELETAL ) ) ;
2012-07-05 19:42:36 +00:00
return ;
}
}
batchid + + ;
2016-12-05 13:35:10 +00:00
}
}
2012-07-05 19:42:36 +00:00
}
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
2016-12-19 13:31:05 +00:00
void HLMDL_DrawHitBoxes ( entity_t * rent )
{
hlmodel_t * model = Mod_Extradata ( rent - > model ) ;
hlmdl_hitbox_t * hitbox = ( hlmdl_hitbox_t * ) ( ( char * ) model - > header + model - > header - > ofs_hitboxes ) ;
matrix3x4 entitymatrix ;
shader_t * shader = R_RegisterShader ( " hitbox_nodepth " , SUF_NONE ,
" { \n "
" polygonoffset \n "
" { \n "
" map $whiteimage \n "
" blendfunc gl_src_alpha gl_one \n "
" rgbgen vertex \n "
" alphagen vertex \n "
" nodepthtest \n "
" } \n "
" } \n " ) ;
float relbones [ MAX_BONES * 12 ] ;
int bonecount = HLMDL_GetBoneData ( rent - > model , 0 , MAX_BONES , & rent - > framestate , relbones ) ;
int b ;
2017-03-06 15:30:45 +00:00
entitymatrix [ 0 ] [ 0 ] = rent - > axis [ 0 ] [ 0 ] ;
entitymatrix [ 0 ] [ 1 ] = rent - > axis [ 1 ] [ 0 ] ;
entitymatrix [ 0 ] [ 2 ] = rent - > axis [ 2 ] [ 0 ] ;
entitymatrix [ 1 ] [ 0 ] = rent - > axis [ 0 ] [ 1 ] ;
entitymatrix [ 1 ] [ 1 ] = rent - > axis [ 1 ] [ 1 ] ;
entitymatrix [ 1 ] [ 2 ] = rent - > axis [ 2 ] [ 1 ] ;
entitymatrix [ 2 ] [ 0 ] = rent - > axis [ 0 ] [ 2 ] ;
entitymatrix [ 2 ] [ 1 ] = rent - > axis [ 1 ] [ 2 ] ;
entitymatrix [ 2 ] [ 2 ] = rent - > axis [ 2 ] [ 2 ] ;
2016-12-19 13:31:05 +00:00
entitymatrix [ 0 ] [ 3 ] = rent - > origin [ 0 ] ;
entitymatrix [ 1 ] [ 3 ] = rent - > origin [ 1 ] ;
entitymatrix [ 2 ] [ 3 ] = rent - > origin [ 2 ] ;
//convert relative to absolutes
for ( b = 0 ; b < bonecount ; b + + )
{
//If we have a parent, take the addition. Otherwise just copy the values
if ( model - > bones [ b ] . parent > = 0 )
2019-03-04 19:24:51 +00:00
R_ConcatTransforms ( ( void * ) transform_matrix [ model - > bones [ b ] . parent ] , ( void * ) ( relbones + b * 12 ) , transform_matrix [ b ] ) ;
2016-12-19 13:31:05 +00:00
else
2019-03-04 19:24:51 +00:00
R_ConcatTransforms ( ( void * ) entitymatrix , ( void * ) ( relbones + b * 12 ) , transform_matrix [ b ] ) ;
2016-12-19 13:31:05 +00:00
}
for ( b = 0 ; b < model - > header - > num_hitboxes ; b + + , hitbox + + )
CLQ1_AddOrientedCube ( shader , hitbox - > mins , hitbox - > maxs , transform_matrix [ hitbox - > bone ] [ 0 ] , 1 , 1 , 1 , 0.2 ) ;
}
# endif
2004-08-22 22:29:09 +00:00
# endif