mirror of
https://github.com/nzp-team/fteqw.git
synced 2025-02-17 01:11:18 +00:00
fix the iqm loader to be more versatile, so we now support more exotic forms of iqm.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4918 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
f35aa1d123
commit
f7b61a1dd8
1 changed files with 319 additions and 113 deletions
|
@ -6026,114 +6026,114 @@ qboolean QDECL Mod_LoadDarkPlacesModel(model_t *mod, void *buffer, size_t fsize)
|
||||||
|
|
||||||
struct iqmheader
|
struct iqmheader
|
||||||
{
|
{
|
||||||
char magic[16];
|
char magic[16];
|
||||||
unsigned int version;
|
unsigned int version;
|
||||||
unsigned int filesize;
|
unsigned int filesize;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
unsigned int num_text, ofs_text;
|
unsigned int num_text, ofs_text;
|
||||||
unsigned int num_meshes, ofs_meshes;
|
unsigned int num_meshes, ofs_meshes;
|
||||||
unsigned int num_vertexarrays, num_vertexes, ofs_vertexarrays;
|
unsigned int num_vertexarrays, num_vertexes, ofs_vertexarrays;
|
||||||
unsigned int num_triangles, ofs_triangles, ofs_adjacency;
|
unsigned int num_triangles, ofs_triangles, ofs_adjacency;
|
||||||
unsigned int num_joints, ofs_joints;
|
unsigned int num_joints, ofs_joints;
|
||||||
unsigned int num_poses, ofs_poses;
|
unsigned int num_poses, ofs_poses;
|
||||||
unsigned int num_anims, ofs_anims;
|
unsigned int num_anims, ofs_anims;
|
||||||
unsigned int num_frames, num_framechannels, ofs_frames, ofs_bounds;
|
unsigned int num_frames, num_framechannels, ofs_frames, ofs_bounds;
|
||||||
unsigned int num_comment, ofs_comment;
|
unsigned int num_comment, ofs_comment;
|
||||||
unsigned int num_extensions, ofs_extensions;
|
unsigned int num_extensions, ofs_extensions;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct iqmmesh
|
struct iqmmesh
|
||||||
{
|
{
|
||||||
unsigned int name;
|
unsigned int name;
|
||||||
unsigned int material;
|
unsigned int material;
|
||||||
unsigned int first_vertex, num_vertexes;
|
unsigned int first_vertex, num_vertexes;
|
||||||
unsigned int first_triangle, num_triangles;
|
unsigned int first_triangle, num_triangles;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
IQM_POSITION = 0,
|
IQM_POSITION = 0,
|
||||||
IQM_TEXCOORD = 1,
|
IQM_TEXCOORD = 1,
|
||||||
IQM_NORMAL = 2,
|
IQM_NORMAL = 2,
|
||||||
IQM_TANGENT = 3,
|
IQM_TANGENT = 3,
|
||||||
IQM_BLENDINDEXES = 4,
|
IQM_BLENDINDEXES = 4,
|
||||||
IQM_BLENDWEIGHTS = 5,
|
IQM_BLENDWEIGHTS = 5,
|
||||||
IQM_COLOR = 6,
|
IQM_COLOR = 6,
|
||||||
IQM_CUSTOM = 0x10
|
IQM_CUSTOM = 0x10
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
IQM_BYTE = 0,
|
IQM_BYTE = 0,
|
||||||
IQM_UBYTE = 1,
|
IQM_UBYTE = 1,
|
||||||
IQM_SHORT = 2,
|
IQM_SHORT = 2,
|
||||||
IQM_USHORT = 3,
|
IQM_USHORT = 3,
|
||||||
IQM_INT = 4,
|
IQM_INT = 4,
|
||||||
IQM_UINT = 5,
|
IQM_UINT = 5,
|
||||||
IQM_HALF = 6,
|
IQM_HALF = 6,
|
||||||
IQM_FLOAT = 7,
|
IQM_FLOAT = 7,
|
||||||
IQM_DOUBLE = 8,
|
IQM_DOUBLE = 8,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct iqmtriangle
|
struct iqmtriangle
|
||||||
{
|
{
|
||||||
unsigned int vertex[3];
|
unsigned int vertex[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct iqmjoint1
|
struct iqmjoint1
|
||||||
{
|
{
|
||||||
unsigned int name;
|
unsigned int name;
|
||||||
int parent;
|
int parent;
|
||||||
float translate[3], rotate[3], scale[3];
|
float translate[3], rotate[3], scale[3];
|
||||||
};
|
};
|
||||||
struct iqmjoint2
|
struct iqmjoint2
|
||||||
{
|
{
|
||||||
unsigned int name;
|
unsigned int name;
|
||||||
int parent;
|
int parent;
|
||||||
float translate[3], rotate[4], scale[3];
|
float translate[3], rotate[4], scale[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct iqmpose1
|
struct iqmpose1
|
||||||
{
|
{
|
||||||
int parent;
|
int parent;
|
||||||
unsigned int mask;
|
unsigned int mask;
|
||||||
float channeloffset[9];
|
float channeloffset[9];
|
||||||
float channelscale[9];
|
float channelscale[9];
|
||||||
};
|
};
|
||||||
struct iqmpose2
|
struct iqmpose2
|
||||||
{
|
{
|
||||||
int parent;
|
int parent;
|
||||||
unsigned int mask;
|
unsigned int mask;
|
||||||
float channeloffset[10];
|
float channeloffset[10];
|
||||||
float channelscale[10];
|
float channelscale[10];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct iqmanim
|
struct iqmanim
|
||||||
{
|
{
|
||||||
unsigned int name;
|
unsigned int name;
|
||||||
unsigned int first_frame, num_frames;
|
unsigned int first_frame, num_frames;
|
||||||
float framerate;
|
float framerate;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
IQM_LOOP = 1<<0
|
IQM_LOOP = 1<<0
|
||||||
};
|
};
|
||||||
|
|
||||||
struct iqmvertexarray
|
struct iqmvertexarray
|
||||||
{
|
{
|
||||||
unsigned int type;
|
unsigned int type;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
unsigned int format;
|
unsigned int format;
|
||||||
unsigned int size;
|
unsigned int size;
|
||||||
unsigned int offset;
|
unsigned int offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct iqmbounds
|
struct iqmbounds
|
||||||
{
|
{
|
||||||
float bbmin[3], bbmax[3];
|
float bbmin[3], bbmax[3];
|
||||||
float xyradius, radius;
|
float xyradius, radius;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -6166,6 +6166,214 @@ galisskeletaltransforms_t *IQM_ImportTransforms(int *resultcount, int inverts, f
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static qboolean IQM_ImportArray4B(qbyte *base, struct iqmvertexarray *src, byte_vec4_t *out, size_t count, unsigned int maxval)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
unsigned int j;
|
||||||
|
unsigned int sz = LittleLong(src->size);
|
||||||
|
unsigned int fmt = LittleLong(src->format);
|
||||||
|
unsigned int offset = LittleLong(src->offset);
|
||||||
|
qboolean invalid = false;
|
||||||
|
maxval = min(256,maxval);
|
||||||
|
if (!offset)
|
||||||
|
{
|
||||||
|
sz = 0;
|
||||||
|
fmt = IQM_UBYTE;
|
||||||
|
}
|
||||||
|
switch(fmt)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
sz = 0;
|
||||||
|
invalid = true;
|
||||||
|
break;
|
||||||
|
case IQM_BYTE: //FIXME: should be signed, but this makes no sense for our uses
|
||||||
|
case IQM_UBYTE:
|
||||||
|
{
|
||||||
|
qbyte *in = (qbyte*)(base+offset);
|
||||||
|
/*if (sz == 4)
|
||||||
|
memcpy(out, in, count * sizeof(*out)); //the fast path.
|
||||||
|
else*/ for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
for (j = 0; j < 4 && j < sz; j++)
|
||||||
|
{
|
||||||
|
if (in[i*sz+j] >= maxval)
|
||||||
|
{
|
||||||
|
out[i][j] = 0;
|
||||||
|
invalid = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
out[i][j] = in[i*sz+j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IQM_SHORT://FIXME: should be signed, but this makes no sense for our uses
|
||||||
|
case IQM_USHORT:
|
||||||
|
{
|
||||||
|
unsigned short *in = (unsigned short*)(base+offset);
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
for (j = 0; j < 4 && j < sz; j++)
|
||||||
|
{
|
||||||
|
if (in[i*sz+j] >= maxval)
|
||||||
|
{
|
||||||
|
out[i][j] = 0;
|
||||||
|
invalid = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
out[i][j] = in[i*sz+j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IQM_INT://FIXME: should be signed, but this makes no sense for our uses
|
||||||
|
case IQM_UINT:
|
||||||
|
{
|
||||||
|
unsigned int *in = (unsigned int*)(base+offset);
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
for (j = 0; j < 4 && j < sz; j++)
|
||||||
|
{
|
||||||
|
if (in[i*sz+j] >= maxval)
|
||||||
|
{
|
||||||
|
out[i][j] = 0;
|
||||||
|
invalid = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
out[i][j] = in[i*sz+j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
//float types don't really make sense
|
||||||
|
}
|
||||||
|
|
||||||
|
//if there were not enough elements, pad it.
|
||||||
|
if (sz < 4)
|
||||||
|
{
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
for (j = sz; j < 4; j++)
|
||||||
|
out[i][j] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return !invalid;
|
||||||
|
}
|
||||||
|
static void IQM_ImportArrayF(qbyte *base, struct iqmvertexarray *src, float *out, size_t e, size_t count, float *def)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
unsigned int j;
|
||||||
|
unsigned int sz = LittleLong(src->size);
|
||||||
|
unsigned int fmt = LittleLong(src->format);
|
||||||
|
unsigned int offset = LittleLong(src->offset);
|
||||||
|
if (!offset)
|
||||||
|
{
|
||||||
|
sz = 0;
|
||||||
|
fmt = IQM_FLOAT;
|
||||||
|
}
|
||||||
|
switch(fmt)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
sz = 0;
|
||||||
|
break;
|
||||||
|
case IQM_BYTE: //FIXME: should be signed
|
||||||
|
{
|
||||||
|
char *in = (qbyte*)(base+offset);
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
for (j = 0; j < e && j < sz; j++)
|
||||||
|
out[i*e+j] = in[i*sz+j] * (1.0/127);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IQM_UBYTE:
|
||||||
|
{
|
||||||
|
qbyte *in = (qbyte*)(base+offset);
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
for (j = 0; j < e && j < sz; j++)
|
||||||
|
out[i*e+j] = in[i*sz+j] * (1.0/255);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IQM_SHORT:
|
||||||
|
{
|
||||||
|
short *in = (short*)(base+offset);
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
for (j = 0; j < e && j < sz; j++)
|
||||||
|
out[i*e+j] = in[i*sz+j] * (1.0/32767);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IQM_USHORT:
|
||||||
|
{
|
||||||
|
unsigned short *in = (unsigned short*)(base+offset);
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
for (j = 0; j < e && j < sz; j++)
|
||||||
|
out[i*e+j] = in[i*sz+j] * (1.0/65535);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IQM_INT://FIXME: should be signed
|
||||||
|
case IQM_UINT:
|
||||||
|
{
|
||||||
|
unsigned int *in = (unsigned int*)(base+offset);
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
for (j = 0; j < e && j < sz; j++)
|
||||||
|
out[i*e+j] = in[i*sz+j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
/*case IQM_HALF:
|
||||||
|
{
|
||||||
|
__fp16 *in = (qbyte*)(base+offset);
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
for (j = 0; j < e && j < sz; j++)
|
||||||
|
out[i*e+j] = in[i*sz+j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;*/
|
||||||
|
case IQM_FLOAT:
|
||||||
|
{
|
||||||
|
float *in = (float*)(base+offset);
|
||||||
|
if (e == sz)
|
||||||
|
memcpy(out, in, e * sizeof(float) * count);
|
||||||
|
else for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
for (j = 0; j < e && j < sz; j++)
|
||||||
|
out[i*e+j] = in[i*sz+j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IQM_DOUBLE:
|
||||||
|
{
|
||||||
|
double *in = (double*)(base+offset);
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
for (j = 0; j < e && j < sz; j++)
|
||||||
|
out[i*e+j] = in[i*sz+j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//if there were not enough elements, pad it.
|
||||||
|
if (sz < e)
|
||||||
|
{
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
for (j = sz; j < e; j++)
|
||||||
|
out[i*e+j] = def[j];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer, size_t fsize)
|
galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer, size_t fsize)
|
||||||
{
|
{
|
||||||
struct iqmheader *h = (struct iqmheader *)buffer;
|
struct iqmheader *h = (struct iqmheader *)buffer;
|
||||||
|
@ -6177,10 +6385,13 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer, size_t fsize)
|
||||||
|
|
||||||
char *strings;
|
char *strings;
|
||||||
|
|
||||||
float *vpos = NULL, *vtcoord = NULL, *vnorm = NULL, *vtang = NULL, *vrgbaf = NULL;
|
float *vtang = NULL;
|
||||||
unsigned char *vbone = NULL, *vweight = NULL, *vrgbaub = NULL;
|
struct iqmvertexarray vpos = {0}, vnorm = {0}, vtcoord = {0}, vbone = {0}, vweight = {0}, vrgba = {0};
|
||||||
unsigned int type, fmt, size, offset;
|
unsigned int type, fmt, size, offset;
|
||||||
unsigned short *framedata;
|
unsigned short *framedata;
|
||||||
|
vec4_t defaultcolour = {1,1,1,1};
|
||||||
|
vec4_t defaultweight = {0,0,0,0};
|
||||||
|
vec4_t defaultvert = {0,0,0,1};
|
||||||
|
|
||||||
int memsize;
|
int memsize;
|
||||||
qbyte *obase=NULL;
|
qbyte *obase=NULL;
|
||||||
|
@ -6230,24 +6441,22 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer, size_t fsize)
|
||||||
fmt = LittleLong(varray[i].format);
|
fmt = LittleLong(varray[i].format);
|
||||||
size = LittleLong(varray[i].size);
|
size = LittleLong(varray[i].size);
|
||||||
offset = LittleLong(varray[i].offset);
|
offset = LittleLong(varray[i].offset);
|
||||||
if (type == IQM_POSITION && fmt == IQM_FLOAT && size == 3)
|
if (type == IQM_POSITION)
|
||||||
vpos = (float*)(buffer + offset);
|
vpos = varray[i];
|
||||||
else if (type == IQM_TEXCOORD && fmt == IQM_FLOAT && size == 2)
|
else if (type == IQM_TEXCOORD)
|
||||||
vtcoord = (float*)(buffer + offset);
|
vtcoord = varray[i];
|
||||||
else if (type == IQM_NORMAL && fmt == IQM_FLOAT && size == 3)
|
else if (type == IQM_NORMAL)
|
||||||
vnorm = (float*)(buffer + offset);
|
vnorm = varray[i];
|
||||||
else if (type == IQM_TANGENT && fmt == IQM_FLOAT && size == 4) /*yup, 4*/
|
else if (type == IQM_TANGENT && fmt == IQM_FLOAT && size == 4) /*yup, 4, extra is side, for the bitangent*/
|
||||||
vtang = (float*)(buffer + offset);
|
vtang = (float*)(buffer + offset);
|
||||||
else if (type == IQM_BLENDINDEXES && fmt == IQM_UBYTE && size == 4)
|
else if (type == IQM_BLENDINDEXES)
|
||||||
vbone = (unsigned char *)(buffer + offset);
|
vbone = varray[i];
|
||||||
else if (type == IQM_BLENDWEIGHTS && fmt == IQM_UBYTE && size == 4)
|
else if (type == IQM_BLENDWEIGHTS)
|
||||||
vweight = (unsigned char *)(buffer + offset);
|
vweight = varray[i];
|
||||||
else if (type == IQM_COLOR && fmt == IQM_UBYTE && size == 4)
|
else if (type == IQM_COLOR)
|
||||||
vrgbaub = (qbyte *)(buffer + offset);
|
vrgba = varray[i];
|
||||||
else if (type == IQM_COLOR && fmt == IQM_FLOAT && size == 4)
|
|
||||||
vrgbaf = (float *)(buffer + offset);
|
|
||||||
else
|
else
|
||||||
Con_Printf("Unrecognised iqm info\n");
|
Con_Printf("Unrecognised iqm info (type=%i, fmt=%i, size=%i)\n", type, fmt, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!h->num_meshes)
|
if (!h->num_meshes)
|
||||||
|
@ -6260,12 +6469,12 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer, size_t fsize)
|
||||||
//we also require texcoords because we can.
|
//we also require texcoords because we can.
|
||||||
//we don't require normals
|
//we don't require normals
|
||||||
//we don't require weights, but such models won't animate.
|
//we don't require weights, but such models won't animate.
|
||||||
if (h->num_vertexes > 0 && (!vpos || !vtcoord))
|
if (h->num_vertexes > 0 && (!vpos.offset || !vtcoord.offset))
|
||||||
{
|
{
|
||||||
Con_Printf("%s is missing vertex array data\n", mod->name);
|
Con_Printf("%s is missing vertex array data\n", mod->name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
noweights = !vbone || !vweight;
|
noweights = !vbone.offset || !vweight.offset;
|
||||||
if (noweights)
|
if (noweights)
|
||||||
{
|
{
|
||||||
if (h->num_frames || h->num_anims || h->num_joints)
|
if (h->num_frames || h->num_anims || h->num_joints)
|
||||||
|
@ -6348,11 +6557,11 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer, size_t fsize)
|
||||||
oweight = NULL;
|
oweight = NULL;
|
||||||
}
|
}
|
||||||
#ifndef SERVERONLY
|
#ifndef SERVERONLY
|
||||||
if (vtcoord)
|
if (vtcoord.offset)
|
||||||
dalloc(otcoords, h->num_vertexes);
|
dalloc(otcoords, h->num_vertexes);
|
||||||
else
|
else
|
||||||
otcoords = NULL;
|
otcoords = NULL;
|
||||||
if (vrgbaf || vrgbaub)
|
if (vrgba.offset)
|
||||||
dalloc(orgbaf, h->num_vertexes);
|
dalloc(orgbaf, h->num_vertexes);
|
||||||
else
|
else
|
||||||
orgbaf = NULL;
|
orgbaf = NULL;
|
||||||
|
@ -6545,45 +6754,30 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer, size_t fsize)
|
||||||
gai[i].shares_verts = i;
|
gai[i].shares_verts = i;
|
||||||
gai[i].numverts = LittleLong(mesh[i].num_vertexes);
|
gai[i].numverts = LittleLong(mesh[i].num_vertexes);
|
||||||
gai[i].ofs_skel_xyz = (opos+offset);
|
gai[i].ofs_skel_xyz = (opos+offset);
|
||||||
gai[i].ofs_skel_norm = vnorm?(onorm1+offset):NULL;
|
gai[i].ofs_skel_norm = (onorm1+offset);
|
||||||
gai[i].ofs_skel_svect = (vnorm&&vtang)?(onorm2+offset):NULL;
|
gai[i].ofs_skel_svect = (onorm2+offset);
|
||||||
gai[i].ofs_skel_tvect = (vnorm&&vtang)?(onorm3+offset):NULL;
|
gai[i].ofs_skel_tvect = (onorm3+offset);
|
||||||
gai[i].ofs_skel_idx = oindex?(oindex+offset):NULL;
|
gai[i].ofs_skel_idx = oindex?(oindex+offset):NULL;
|
||||||
gai[i].ofs_skel_weight = oweight?(oweight+offset):NULL;
|
gai[i].ofs_skel_weight = oweight?(oweight+offset):NULL;
|
||||||
}
|
}
|
||||||
if (!noweights)
|
if (!noweights)
|
||||||
{
|
{
|
||||||
for (i = 0; i < h->num_vertexes; i++)
|
if (!IQM_ImportArray4B(buffer, &vbone, oindex, h->num_vertexes, h->num_joints))
|
||||||
{
|
Con_Printf(CON_WARNING "Invalid bone indexes detected inside %s\n", mod->name);
|
||||||
Vector4Copy(vbone+i*4, oindex[i]);
|
IQM_ImportArrayF(buffer, &vweight, (float*)oweight, 4, h->num_vertexes, defaultweight);
|
||||||
Vector4Scale(vweight+i*4, 1/255.0, oweight[i]);
|
|
||||||
|
|
||||||
//FIXME: should we be normalising?
|
|
||||||
if (!oweight[i][0] && !oweight[i][1] && !oweight[i][2] && !oweight[i][3])
|
|
||||||
oweight[i][0] = 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (otcoords)
|
if (otcoords)
|
||||||
memcpy(otcoords, vtcoord, h->num_vertexes*sizeof(*otcoords));
|
IQM_ImportArrayF(buffer, &vtcoord, (float*)otcoords, 2, h->num_vertexes, defaultweight);
|
||||||
if (orgbaf)
|
if (orgbaf)
|
||||||
|
IQM_ImportArrayF(buffer, &vrgba, (float*)orgbaf, 4, h->num_vertexes, defaultcolour);
|
||||||
|
|
||||||
|
IQM_ImportArrayF(buffer, &vnorm, (float*)onorm1, 3, h->num_vertexes, defaultcolour);
|
||||||
|
IQM_ImportArrayF(buffer, &vpos, (float*)opos, sizeof(opos[0])/sizeof(float), h->num_vertexes, defaultvert);
|
||||||
|
|
||||||
|
if (vnorm.offset && vtang)
|
||||||
{
|
{
|
||||||
if (vrgbaf)
|
for (i = 0; i < h->num_vertexes; i++)
|
||||||
memcpy(orgbaf, vrgbaf, h->num_vertexes*sizeof(*orgbaf));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (i = 0; i < h->num_vertexes; i++)
|
|
||||||
Vector4Scale(vrgbaub+i*4, 1/255.0f, orgbaf[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (i = 0; i < h->num_vertexes; i++)
|
|
||||||
{
|
|
||||||
VectorCopy(vpos+i*3, opos[i]);
|
|
||||||
if (vnorm)
|
|
||||||
{
|
|
||||||
VectorCopy(vnorm+i*3, onorm1[i]);
|
|
||||||
}
|
|
||||||
if (vnorm && vtang)
|
|
||||||
{
|
{
|
||||||
VectorCopy(vtang+i*4, onorm2[i]);
|
VectorCopy(vtang+i*4, onorm2[i]);
|
||||||
if(LittleFloat(vtang[i*4 + 3]) < 0)
|
if(LittleFloat(vtang[i*4 + 3]) < 0)
|
||||||
|
@ -6592,6 +6786,18 @@ galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, char *buffer, size_t fsize)
|
||||||
CrossProduct(onorm1[i], onorm2[i], onorm3[i]);
|
CrossProduct(onorm1[i], onorm2[i], onorm3[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (h->num_vertexes)
|
||||||
|
{ //make something up
|
||||||
|
for (i = 0; i < h->num_meshes; i++)
|
||||||
|
{
|
||||||
|
Mod_AccumulateTextureVectors(gai[i].ofs_skel_xyz, gai[i].ofs_st_array, gai[i].ofs_skel_norm, gai[i].ofs_skel_svect, gai[i].ofs_skel_tvect, gai[i].ofs_indexes, gai[i].numindexes);
|
||||||
|
}
|
||||||
|
for (i = 0; i < h->num_meshes; i++)
|
||||||
|
{
|
||||||
|
Mod_NormaliseTextureVectors(gai[i].ofs_skel_norm, gai[i].ofs_skel_svect, gai[i].ofs_skel_tvect, gai[i].numverts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return gai;
|
return gai;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue