2019-09-04 08:32:22 +00:00
# ifndef GLQUAKE
# define GLQUAKE //this is shit.
# endif
# include "quakedef.h"
# include "../plugin.h"
# include "com_mesh.h"
extern plugmodfuncs_t * modfuncs ;
extern plugfsfuncs_t * filefuncs ;
# define IQM_MAGIC "INTERQUAKEMODEL"
# define IQM_VERSION2 2
struct iqmheader
{
char magic [ 16 ] ;
unsigned int version ;
unsigned int filesize ;
unsigned int flags ;
unsigned int num_text , ofs_text ;
unsigned int num_meshes , ofs_meshes ;
unsigned int num_vertexarrays , num_vertexes , ofs_vertexarrays ;
unsigned int num_triangles , ofs_triangles , ofs_adjacency ;
unsigned int num_joints , ofs_joints ;
unsigned int num_poses , ofs_poses ;
unsigned int num_anims , ofs_anims ;
unsigned int num_frames , num_framechannels , ofs_frames , ofs_bounds ;
unsigned int num_comment , ofs_comment ;
unsigned int num_extensions , ofs_extensions ;
} ;
struct iqmmesh
{
unsigned int name ;
unsigned int material ;
unsigned int first_vertex , num_vertexes ;
unsigned int first_triangle , num_triangles ;
} ;
enum
{
IQM_POSITION = 0 ,
IQM_TEXCOORD = 1 ,
IQM_NORMAL = 2 ,
IQM_TANGENT = 3 ,
IQM_BLENDINDEXES = 4 ,
IQM_BLENDWEIGHTS = 5 ,
IQM_COLOR = 6 ,
IQM_CUSTOM = 0x10
} ;
enum
{
IQM_BYTE = 0 ,
IQM_UBYTE = 1 ,
IQM_SHORT = 2 ,
IQM_USHORT = 3 ,
IQM_INT = 4 ,
IQM_UINT = 5 ,
IQM_HALF = 6 ,
IQM_FLOAT = 7 ,
IQM_DOUBLE = 8 ,
} ;
struct iqmtriangle
{
unsigned int vertex [ 3 ] ;
} ;
struct iqmjoint2
{
unsigned int name ;
int parent ;
float translate [ 3 ] , rotate [ 4 ] , scale [ 3 ] ;
} ;
struct iqmpose2
{
int parent ;
unsigned int mask ;
float channeloffset [ 10 ] ;
float channelscale [ 10 ] ;
} ;
struct iqmanim
{
unsigned int name ;
unsigned int first_frame , num_frames ;
float framerate ;
unsigned int flags ;
} ;
enum
{
IQM_LOOP = 1 < < 0
} ;
struct iqmvertexarray
{
unsigned int type ;
unsigned int flags ;
unsigned int format ;
unsigned int size ;
unsigned int offset ;
} ;
struct iqmbounds
{
float bbmin [ 3 ] , bbmax [ 3 ] ;
float xyradius , radius ;
} ;
struct iqmextension
{
unsigned int name ;
unsigned int num_data , ofs_data ;
unsigned int ofs_extensions ; // pointer to next extension. wtf is up with this? how is this not redundant due to ofs_data?
} ;
struct iqmext_fte_mesh
{
unsigned int contents ; //default CONTENTS_BODY
unsigned int surfaceflags ; //propagates to trace_surfaceflags
unsigned int surfaceid ; //the body reported to qc via trace_surface
unsigned int geomset ;
unsigned int geomid ;
float mindist ;
float maxdist ;
} ;
struct iqmext_fte_event
{
unsigned int anim ;
float timestamp ;
unsigned int evcode ;
unsigned int evdata_str ; //stringtable
} ;
static void CrossProduct_ ( const vec3_t v1 , const vec3_t v2 , vec3_t cross )
{
cross [ 0 ] = v1 [ 1 ] * v2 [ 2 ] - v1 [ 2 ] * v2 [ 1 ] ;
cross [ 1 ] = v1 [ 2 ] * v2 [ 0 ] - v1 [ 0 ] * v2 [ 2 ] ;
cross [ 2 ] = v1 [ 0 ] * v2 [ 1 ] - v1 [ 1 ] * v2 [ 0 ] ;
}
static void Bone_To_PosQuat4 ( const float * matrix , float * pos , float * quat4 , float * scale )
{ //I originally ripped this function out of DP. tweaked slightly.
//http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
float origininvscale = 1 ;
float origin [ 3 ] ;
float quat [ 4 ] ;
float quatscale ;
float trace = matrix [ 0 * 4 + 0 ] + matrix [ 1 * 4 + 1 ] + matrix [ 2 * 4 + 2 ] ;
origin [ 0 ] = matrix [ 0 * 4 + 0 ] ;
origin [ 1 ] = matrix [ 1 * 4 + 0 ] ;
origin [ 2 ] = matrix [ 2 * 4 + 0 ] ;
scale [ 0 ] = sqrt ( DotProduct ( origin , origin ) ) ;
origin [ 0 ] = matrix [ 0 * 4 + 1 ] ;
origin [ 1 ] = matrix [ 1 * 4 + 1 ] ;
origin [ 2 ] = matrix [ 2 * 4 + 1 ] ;
scale [ 1 ] = sqrt ( DotProduct ( origin , origin ) ) ;
origin [ 1 ] = matrix [ 0 * 4 + 2 ] ;
origin [ 1 ] = matrix [ 1 * 4 + 2 ] ;
origin [ 2 ] = matrix [ 2 * 4 + 2 ] ;
scale [ 2 ] = sqrt ( DotProduct ( origin , origin ) ) ;
origin [ 0 ] = matrix [ 0 * 4 + 3 ] ;
origin [ 1 ] = matrix [ 1 * 4 + 3 ] ;
origin [ 2 ] = matrix [ 2 * 4 + 3 ] ;
if ( trace > 0 )
{
float r = sqrt ( 1.0f + trace ) , inv = 0.5f / r ;
quat [ 0 ] = ( matrix [ 2 * 4 + 1 ] - matrix [ 1 * 4 + 2 ] ) * inv ;
quat [ 1 ] = ( matrix [ 0 * 4 + 2 ] - matrix [ 2 * 4 + 0 ] ) * inv ;
quat [ 2 ] = ( matrix [ 1 * 4 + 0 ] - matrix [ 0 * 4 + 1 ] ) * inv ;
quat [ 3 ] = 0.5f * r ;
}
else if ( matrix [ 0 * 4 + 0 ] > matrix [ 1 * 4 + 1 ] & & matrix [ 0 * 4 + 0 ] > matrix [ 2 * 4 + 2 ] )
{
float r = sqrt ( 1.0f + matrix [ 0 * 4 + 0 ] - matrix [ 1 * 4 + 1 ] - matrix [ 2 * 4 + 2 ] ) , inv = 0.5f / r ;
quat [ 0 ] = 0.5f * r ;
quat [ 1 ] = ( matrix [ 1 * 4 + 0 ] + matrix [ 0 * 4 + 1 ] ) * inv ;
quat [ 2 ] = ( matrix [ 0 * 4 + 2 ] + matrix [ 2 * 4 + 0 ] ) * inv ;
quat [ 3 ] = ( matrix [ 2 * 4 + 1 ] - matrix [ 1 * 4 + 2 ] ) * inv ;
}
else if ( matrix [ 1 * 4 + 1 ] > matrix [ 2 * 4 + 2 ] )
{
float r = sqrt ( 1.0f + matrix [ 1 * 4 + 1 ] - matrix [ 0 * 4 + 0 ] - matrix [ 2 * 4 + 2 ] ) , inv = 0.5f / r ;
quat [ 0 ] = ( matrix [ 1 * 4 + 0 ] + matrix [ 0 * 4 + 1 ] ) * inv ;
quat [ 1 ] = 0.5f * r ;
quat [ 2 ] = ( matrix [ 2 * 4 + 1 ] + matrix [ 1 * 4 + 2 ] ) * inv ;
quat [ 3 ] = ( matrix [ 0 * 4 + 2 ] - matrix [ 2 * 4 + 0 ] ) * inv ;
}
else
{
float r = sqrt ( 1.0f + matrix [ 2 * 4 + 2 ] - matrix [ 0 * 4 + 0 ] - matrix [ 1 * 4 + 1 ] ) , inv = 0.5f / r ;
quat [ 0 ] = ( matrix [ 0 * 4 + 2 ] + matrix [ 2 * 4 + 0 ] ) * inv ;
quat [ 1 ] = ( matrix [ 2 * 4 + 1 ] + matrix [ 1 * 4 + 2 ] ) * inv ;
quat [ 2 ] = 0.5f * r ;
quat [ 3 ] = ( matrix [ 1 * 4 + 0 ] - matrix [ 0 * 4 + 1 ] ) * inv ;
}
// normalize quaternion so that it is unit length
quatscale = quat [ 0 ] * quat [ 0 ] + quat [ 1 ] * quat [ 1 ] + quat [ 2 ] * quat [ 2 ] + quat [ 3 ] * quat [ 3 ] ;
if ( quatscale )
quatscale = ( quat [ 3 ] > = 0 ? - 1.0f : 1.0f ) / sqrt ( quatscale ) ;
// use a negative scale on the quat because the above function produces a
// positive quat[3] and canonical quaternions have negative quat[3]
VectorScale ( origin , origininvscale , pos ) ;
Vector4Scale ( quat , quatscale , quat4 ) ;
}
void Mod_ExportIQM ( char * fname , int flags , galiasinfo_t * mesh )
{
int i , j , k ;
vfsfile_t * f ;
galiasinfo_t * m ;
qbyte * data = NULL ;
char * otext ;
struct iqmvertexarray * ovarr ;
struct iqmtriangle * otri ;
struct iqmmesh * omesh ;
2019-09-04 09:15:13 +00:00
struct iqmjoint2 * ojoint = NULL ;
struct iqmanim * oanim = NULL ;
struct iqmpose2 * opose = NULL ;
2019-09-04 08:32:22 +00:00
struct
{
float min [ 10 ] , max [ 10 ] , scale [ 10 ] ;
int flags ;
} * poseinfo = NULL , * pi ; //per bone
struct
{ //pos3, quat4, scale3
float posquatscale [ 10 ] ; //raw values, used to calibrate ranges
} * posedata = NULL , * pd ; //per bone*joint
avec4_t * ivert ;
vec2_t * ist ;
vec3_t * overt ;
vec3_t * onorm = NULL ;
vec4_t * otang = NULL ;
vec2_t * ost ;
2019-09-04 09:15:13 +00:00
bone_vec4_t * oboneidx = NULL ;
byte_vec4_t * oboneweight = NULL ;
unsigned short * oposedata = NULL ;
2019-09-04 08:32:22 +00:00
struct iqmheader hdr = { IQM_MAGIC , IQM_VERSION2 } , * oh ;
hdr . flags = flags ;
hdr . num_vertexarrays = 4 ;
hdr . num_triangles = 0 ;
hdr . ofs_adjacency = 0 ; //noone actually uses this...
hdr . num_poses = 0 ;
// hdr.ofs_poses = 0;
hdr . num_anims = 0 ;
// hdr.ofs_anims = 0;
hdr . num_frames = 0 ;
hdr . num_framechannels = 0 ;
// hdr.ofs_frames = 0;
// hdr.ofs_bounds = 0;
hdr . num_comment = 0 ;
// hdr.ofs_comment = 0;
hdr . num_extensions = 0 ;
// hdr.ofs_extensions = 0;
hdr . num_joints = mesh - > numbones ;
if ( hdr . num_joints )
{
float * matrix ;
hdr . num_vertexarrays + = 2 ;
hdr . num_anims = mesh - > numanimations ;
for ( i = 0 ; i < hdr . num_anims ; i + + )
{
hdr . num_text + = strlen ( mesh - > ofsanimations [ i ] . name ) + 1 ;
hdr . num_frames + = mesh - > ofsanimations [ i ] . numposes ;
}
if ( hdr . num_frames )
{
poseinfo = malloc ( sizeof ( * poseinfo ) * hdr . num_joints ) ;
hdr . num_poses = hdr . num_joints ;
posedata = malloc ( sizeof ( * posedata ) * hdr . num_joints * hdr . num_poses ) ;
//pull out the raw data and convert to the quats that we need
for ( i = 0 , pd = posedata ; i < hdr . num_anims ; i + + )
for ( j = 0 , matrix = mesh - > ofsanimations [ i ] . boneofs ; j < mesh - > ofsanimations [ i ] . numposes ; j + + )
for ( k = 0 ; k < hdr . num_joints ; k + + )
{
Bone_To_PosQuat4 ( matrix , & pd - > posquatscale [ 0 ] , & pd - > posquatscale [ 3 ] , & pd - > posquatscale [ 7 ] ) ;
pd + + ;
matrix + = 12 ;
}
//now figure out each poseinfo's min+max
for ( i = 0 , pi = poseinfo ; i < hdr . num_joints ; i + + , pi + + )
for ( j = 0 , pd = posedata + i ; j < hdr . num_poses ; j + + , pd + = hdr . num_joints )
for ( k = 0 ; k < 10 ; k + + )
{
if ( ! i | | pd - > posquatscale [ k ] < pi - > min [ k ] )
pi - > min [ k ] = pd - > posquatscale [ k ] ;
if ( ! i | | pi [ i ] . max [ k ] < pd - > posquatscale [ k ] )
pi - > max [ k ] = pd - > posquatscale [ k ] ;
}
//figure out the offset+range+flags
for ( i = 0 , pi = poseinfo ; i < hdr . num_joints ; i + + , pi + + )
for ( k = 0 ; k < 10 ; k + + )
{
pi - > scale [ k ] = pi - > max [ k ] - pi - > min [ k ] ;
if ( pi - > scale [ k ] < 1e-10 f )
; //total range is tiny and won't make any real difference, drop this channel for a small saving.
else
{
pi - > scale [ k ] / = 0xffffu ; //compensate for the datatype's max
pi - > flags | = 1u < < k ;
hdr . num_framechannels + + ;
}
}
hdr . num_framechannels * = hdr . num_frames ; //there'll be one for each pose*channel*frame
}
}
hdr . num_text + = hdr . num_joints * 32 ; //gah
//count needed data
for ( m = mesh ; m ; m = m - > nextsurf )
{
//can't handle the surface if its verts are weird.
if ( m - > shares_verts & & m - > shares_verts ! = hdr . num_meshes )
continue ;
//can only handle one set of bones.
if ( m - > shares_bones ! = 0 )
continue ;
//and must have the same number of bones.
if ( hdr . num_joints ! = m - > numbones )
continue ;
hdr . num_text + = strlen ( m - > surfacename ) + 1 ;
if ( m - > ofsskins & & m - > ofsskins - > frame )
hdr . num_text + = strlen ( m - > ofsskins - > frame - > shadername ) + 1 ;
hdr . num_triangles + = m - > numindexes / 3 ;
hdr . num_vertexes + = m - > numverts ;
hdr . num_meshes + + ;
}
//allocate our output buffer
# define ALLOCSPACE hdr.filesize = 0; \
ALLOC ( oh , sizeof ( * oh ) ) ; \
ALLOC ( otext , sizeof ( * otext ) * hdr . num_text ) ; \
ALLOC ( ovarr , sizeof ( * ovarr ) * hdr . num_vertexarrays ) ; \
ALLOC ( otri , sizeof ( * otri ) * hdr . num_triangles ) ; \
ALLOC ( overt , sizeof ( * overt ) * hdr . num_vertexes ) ; \
ALLOC ( ost , sizeof ( * ost ) * hdr . num_vertexes ) ; \
if ( mesh - > ofs_skel_norm ) { ALLOC ( onorm , sizeof ( * onorm ) * hdr . num_vertexes ) ; } \
if ( mesh - > ofs_skel_svect & & mesh - > ofs_skel_tvect ) { ALLOC ( otang , sizeof ( * otang ) * hdr . num_vertexes ) ; } \
if ( hdr . num_joints ) { ALLOC ( oboneweight , sizeof ( * oboneweight ) * hdr . num_vertexes ) ; } \
if ( hdr . num_joints ) { ALLOC ( oboneidx , sizeof ( * oboneidx ) * hdr . num_vertexes ) ; } \
if ( hdr . num_joints ) { ALLOC ( ojoint , sizeof ( * ojoint ) * hdr . num_joints ) ; } \
if ( hdr . num_anims ) { ALLOC ( oanim , sizeof ( * oanim ) * hdr . num_anims ) ; } \
if ( hdr . num_poses ) { ALLOC ( opose , sizeof ( * opose ) * hdr . num_poses ) ; } \
if ( hdr . num_framechannels ) { ALLOC ( oposedata , sizeof ( * oposedata ) * hdr . num_framechannels ) ; } \
ALLOC ( omesh , sizeof ( * omesh ) * hdr . num_meshes ) ;
# define ALLOC(p,s) p=(void*)(data+hdr.filesize);hdr.filesize+=s;
ALLOCSPACE ; //figure out how much space we need
data = malloc ( hdr . filesize ) ;
memset ( data , 0xFE , hdr . filesize ) ;
ALLOCSPACE ; //and assign everything to the right offsets.
# undef ALLOC
# undef ALLOCSPACE
//copy over the preliminary header
* oh = hdr ;
# define hdr hdr
if ( omesh ) oh - > ofs_meshes = ( qbyte * ) omesh - data ;
if ( otext ) oh - > ofs_text = ( qbyte * ) otext - data ;
if ( ovarr ) oh - > ofs_vertexarrays = ( qbyte * ) ovarr - data ;
if ( otri ) oh - > ofs_triangles = ( qbyte * ) otri - data ;
if ( ojoint ) oh - > ofs_joints = ( qbyte * ) ojoint - data ;
if ( opose ) oh - > ofs_poses = ( qbyte * ) opose - data ;
if ( oposedata ) oh - > ofs_frames = ( qbyte * ) oposedata - data ;
if ( oanim ) oh - > ofs_anims = ( qbyte * ) oanim - data ;
//set up vertex array data. we might add some padding here, in case the extra data isn't availble.
memset ( ovarr , 0 , sizeof ( * ovarr ) * oh - > num_vertexarrays ) ;
oh - > num_vertexarrays = 0 ;
ovarr - > type = IQM_POSITION ;
ovarr - > flags = 0 ;
ovarr - > format = IQM_FLOAT ;
ovarr - > size = 3 ;
ovarr - > offset = ( qbyte * ) overt - data ;
ovarr + + ;
oh - > num_vertexarrays + + ;
ovarr - > type = IQM_TEXCOORD ;
ovarr - > flags = 0 ;
ovarr - > format = IQM_FLOAT ;
ovarr - > size = 2 ;
ovarr - > offset = ( qbyte * ) ost - data ;
ovarr + + ;
oh - > num_vertexarrays + + ;
if ( onorm )
{
ovarr - > type = IQM_NORMAL ;
ovarr - > flags = 0 ;
ovarr - > format = IQM_FLOAT ;
ovarr - > size = 3 ;
ovarr - > offset = ( qbyte * ) onorm - data ;
ovarr + + ;
oh - > num_vertexarrays + + ;
}
if ( otang )
{
ovarr - > type = IQM_TANGENT ;
ovarr - > flags = 0 ;
ovarr - > format = IQM_FLOAT ;
ovarr - > size = 4 ;
ovarr - > offset = ( qbyte * ) otang - data ;
ovarr + + ;
oh - > num_vertexarrays + + ;
}
if ( oboneidx )
{
ovarr - > type = IQM_BLENDINDEXES ;
ovarr - > flags = 0 ;
ovarr - > format = ( MAX_BONES > 65536 ) ? IQM_UINT : ( ( MAX_BONES > 256 ) ? IQM_USHORT : IQM_UBYTE ) ;
ovarr - > size = 4 ;
ovarr - > offset = ( qbyte * ) oboneidx - data ;
ovarr + + ;
oh - > num_vertexarrays + + ;
}
if ( oboneweight )
{
ovarr - > type = IQM_BLENDWEIGHTS ;
ovarr - > flags = 0 ;
ovarr - > format = IQM_BYTE ;
ovarr - > size = 4 ;
ovarr - > offset = ( qbyte * ) oboneweight - data ;
ovarr + + ;
oh - > num_vertexarrays + + ;
}
/*if (orgba)
{
ovarr - > type = IQM_COLOR ;
ovarr - > flags = 0 ;
ovarr - > format = IQM_FLOAT ;
ovarr - > size = 4 ;
ovarr - > offset = ( qbyte * ) orgba - data ;
ovarr + + ;
oh - > num_vertexarrays + + ;
} */
if ( ojoint )
{
for ( i = 0 ; i < hdr . num_joints ; i + + )
{
ojoint [ i ] . parent = mesh - > ofsbones [ i ] . parent ;
ojoint [ i ] . name = ( qbyte * ) otext - ( data + oh - > ofs_text ) ;
strcpy ( otext , mesh - > ofsbones [ i ] . name ) ;
otext + = strlen ( otext ) + 1 ;
Bone_To_PosQuat4 ( mesh - > ofsbones [ i ] . inverse , ojoint [ i ] . translate , ojoint [ i ] . rotate , ojoint [ i ] . scale ) ;
}
}
if ( opose )
{
int c ;
for ( i = 0 , pi = poseinfo ; i < hdr . num_joints ; i + + , pi + + )
{
opose [ i ] . parent = mesh - > ofsbones [ i ] . parent ;
opose [ i ] . mask = pi - > flags ;
for ( k = 0 ; k < 10 ; k + + )
{
opose [ i ] . channeloffset [ k ] = pi - > min [ k ] ;
opose [ i ] . channelscale [ k ] = pi - > scale [ k ] ;
}
for ( j = 0 , pd = posedata + i ; j < hdr . num_frames ; j + + , pd + = hdr . num_joints )
{
for ( k = 0 ; k < 10 ; k + + )
{
if ( opose [ i ] . mask & ( 1 < < k ) )
{
c = ( pd - > posquatscale [ k ] - pi - > min [ k ] ) / pi - > scale [ k ] ;
c = bound ( 0 , c , 0xffff ) ; //clamp it just in case (floats can be annoying)
* oposedata + + = c ;
}
}
}
}
}
if ( oposedata )
{
for ( i = 0 ; i < hdr . num_joints ; i + + )
{
opose [ i ] . parent = mesh - > ofsbones [ i ] . parent ;
opose [ i ] . mask = poseinfo [ i ] . flags ;
for ( k = 0 ; k < 10 ; k + + )
{
opose [ i ] . channeloffset [ k ] = poseinfo [ i ] . min [ k ] ;
opose [ i ] . channelscale [ k ] = poseinfo [ i ] . scale [ k ] ;
}
}
}
hdr . num_frames = 0 ;
for ( i = 0 ; i < hdr . num_anims ; i + + , oanim + + )
{
oanim - > first_frame = hdr . num_frames ;
oanim - > num_frames = mesh - > ofsanimations [ i ] . numposes ;
oanim - > framerate = mesh - > ofsanimations [ i ] . rate ;
oanim - > flags = mesh - > ofsanimations [ i ] . loop ? IQM_LOOP : 0 ;
oanim - > name = ( qbyte * ) otext - ( data + oh - > ofs_text ) ;
strcpy ( otext , mesh - > ofsanimations [ i ] . name ) ;
otext + = strlen ( otext ) + 1 ;
hdr . num_frames + = mesh - > ofsanimations [ i ] . numposes ;
}
oh - > num_anims = i ;
oh - > num_frames = hdr . num_frames ;
//count needed data
hdr . num_triangles = 0 ;
hdr . num_vertexes = 0 ;
for ( m = mesh ; m ; m = m - > nextsurf )
{
//can't handle the surface if its verts are weird.
if ( m - > shares_verts & & m - > shares_verts ! = hdr . num_meshes )
continue ;
//can only handle one set of bones.
if ( m - > shares_bones ! = 0 )
continue ;
if ( hdr . num_joints ! = m - > numbones )
continue ;
omesh - > name = ( qbyte * ) otext - ( data + oh - > ofs_text ) ;
strcpy ( otext , m - > surfacename ) ;
otext + = strlen ( otext ) + 1 ;
omesh - > material = ( qbyte * ) otext - ( data + oh - > ofs_text ) ;
if ( m - > ofsskins & & m - > ofsskins - > frame )
strcpy ( otext , m - > ofsskins - > frame - > shadername ) ;
else
strcpy ( otext , " " ) ;
otext + = strlen ( otext ) + 1 ;
omesh - > first_vertex = hdr . num_vertexes ;
omesh - > num_vertexes = m - > numverts ;
omesh - > first_triangle = hdr . num_triangles ;
omesh - > num_triangles = m - > numindexes / 3 ;
if ( m - > ofs_skel_xyz )
ivert = m - > ofs_skel_xyz ;
2019-09-17 19:49:39 +00:00
# ifdef NONSKELETALMODELS
2019-09-04 08:32:22 +00:00
else if ( m - > numanimations & & m - > ofsanimations - > numposes )
ivert = m - > ofsanimations - > poseofs - > ofsverts ;
2019-09-17 19:49:39 +00:00
# endif
2019-09-04 08:32:22 +00:00
else
ivert = NULL ;
if ( ivert )
{
for ( i = 0 ; i < omesh - > num_vertexes ; i + + )
VectorCopy ( ivert [ i ] , overt [ i ] ) ;
}
else
{
for ( i = 0 ; i < omesh - > num_vertexes ; i + + )
VectorClear ( overt [ i ] ) ;
}
overt + = i ;
if ( oboneidx )
{
bone_vec4_t * iidx = m - > ofs_skel_idx ;
vec4_t * iweight = m - > ofs_skel_weight ;
for ( i = 0 ; i < omesh - > num_vertexes ; i + + )
{
Vector4Copy ( iidx [ i ] , oboneidx [ i ] ) ;
Vector4Scale ( iweight [ i ] , 255 , oboneweight [ i ] ) ;
}
oboneidx + = i ;
oboneweight + = i ;
}
if ( ost )
{
ist = m - > ofs_st_array ;
for ( i = 0 ; i < omesh - > num_vertexes ; i + + )
Vector2Copy ( ist [ i ] , ost [ i ] ) ;
ost + = i ;
}
if ( onorm )
{
vec3_t * inorm , * isdir , * itdir , t ;
if ( m - > ofs_skel_norm )
{
inorm = m - > ofs_skel_norm ;
isdir = m - > ofs_skel_svect ;
itdir = m - > ofs_skel_tvect ;
}
2019-09-17 19:49:39 +00:00
# ifdef NONSKELETALMODELS
2019-09-04 08:32:22 +00:00
else if ( m - > numanimations & & m - > ofsanimations - > numposes )
{
inorm = m - > ofsanimations - > poseofs - > ofsnormals ;
isdir = m - > ofsanimations - > poseofs - > ofssvector ;
itdir = m - > ofsanimations - > poseofs - > ofstvector ;
}
2019-09-17 19:49:39 +00:00
# endif
2019-09-04 08:32:22 +00:00
else
{
inorm = NULL ;
isdir = NULL ;
itdir = NULL ;
}
if ( otang )
{
if ( inorm & & isdir & & itdir )
{
for ( i = 0 ; i < omesh - > num_vertexes ; i + + )
{
VectorCopy ( isdir [ i ] , otang [ i ] ) ;
CrossProduct_ ( isdir [ i ] , inorm [ i ] , t ) ;
otang [ i ] [ 3 ] = DotProduct ( itdir [ i ] , t ) < 0 ; //fourth part is simply a flag that says which direction the bitangent is in, should otherwise be a nice crossproduct result.
}
}
else
{
for ( i = 0 ; i < omesh - > num_vertexes ; i + + )
{
VectorClear ( otang [ i ] ) ;
otang [ i ] [ 3 ] = 0 ;
}
}
otang + = i ;
}
if ( inorm )
{
for ( i = 0 ; i < omesh - > num_vertexes ; i + + )
VectorCopy ( ivert [ i ] , onorm [ i ] ) ;
}
else
{
for ( i = 0 ; i < omesh - > num_vertexes ; i + + )
VectorClear ( onorm [ i ] ) ;
}
otang + = i ;
onorm + = i ;
}
for ( i = 0 ; i < omesh - > num_triangles ; i + + )
{
otri [ i ] . vertex [ 0 ] = m - > ofs_indexes [ i * 3 + 0 ] + hdr . num_vertexes ;
otri [ i ] . vertex [ 1 ] = m - > ofs_indexes [ i * 3 + 1 ] + hdr . num_vertexes ;
otri [ i ] . vertex [ 2 ] = m - > ofs_indexes [ i * 3 + 2 ] + hdr . num_vertexes ;
}
otri + = i ;
hdr . num_vertexes + = omesh - > num_vertexes ;
hdr . num_triangles + = omesh - > num_triangles ;
}
//and write it out
f = filefuncs - > OpenVFS ( fname , " wb " , FS_GAMEONLY ) ;
if ( f )
{
VFS_WRITE ( f , oh , oh - > filesize ) ;
VFS_CLOSE ( f ) ;
}
free ( data ) ;
free ( poseinfo ) ;
# undef hdr
}