mirror of
https://github.com/nzp-team/fteqw.git
synced 2024-11-25 13:21:36 +00:00
iqmtool now supports --static. Also embeds some multi-skin info.
git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@6056 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
parent
aa651c5059
commit
051442c041
3 changed files with 235 additions and 38 deletions
|
@ -7753,6 +7753,27 @@ struct iqmext_fte_event
|
||||||
unsigned int evcode;
|
unsigned int evcode;
|
||||||
unsigned int evdata_str; //stringtable
|
unsigned int evdata_str; //stringtable
|
||||||
};
|
};
|
||||||
|
//skin lump is made of 3 parts
|
||||||
|
struct iqmext_fte_skin
|
||||||
|
{
|
||||||
|
unsigned int numskinframes;
|
||||||
|
unsigned int nummeshskins;
|
||||||
|
//unsigned int numskins[nummeshes];
|
||||||
|
//iqmext_fte_skin_skinframe[numskinframes];
|
||||||
|
//iqmext_fte_skin_meshskin mesh0[numskins[0]];
|
||||||
|
//iqmext_fte_skin_meshskin mesh1[numskins[1]]; etc
|
||||||
|
};
|
||||||
|
struct iqmext_fte_skin_skinframe
|
||||||
|
{ //as many as needed
|
||||||
|
unsigned int material_idx;
|
||||||
|
unsigned int shadertext_idx;
|
||||||
|
};
|
||||||
|
struct iqmext_fte_skin_meshskin
|
||||||
|
{
|
||||||
|
unsigned int firstframe; //index into skinframes
|
||||||
|
unsigned int countframes; //skinframes
|
||||||
|
float interval;
|
||||||
|
};
|
||||||
/*struct iqmext_fte_shader
|
/*struct iqmext_fte_shader
|
||||||
{
|
{
|
||||||
unsigned int material;
|
unsigned int material;
|
||||||
|
@ -8093,6 +8114,10 @@ static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, siz
|
||||||
const struct iqmext_fte_event *fteevents;
|
const struct iqmext_fte_event *fteevents;
|
||||||
const char *strings;
|
const char *strings;
|
||||||
|
|
||||||
|
const unsigned int *fteskincount;
|
||||||
|
const struct iqmext_fte_skin_meshskin *fteskins;
|
||||||
|
const struct iqmext_fte_skin_skinframe *fteskinframes;
|
||||||
|
|
||||||
unsigned int i, j, t, numtris, numverts, firstvert, firsttri;
|
unsigned int i, j, t, numtris, numverts, firstvert, firsttri;
|
||||||
size_t extsize;
|
size_t extsize;
|
||||||
|
|
||||||
|
@ -8119,8 +8144,6 @@ static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, siz
|
||||||
|
|
||||||
galiasinfo_t *gai=NULL;
|
galiasinfo_t *gai=NULL;
|
||||||
#ifndef SERVERONLY
|
#ifndef SERVERONLY
|
||||||
galiasskin_t *skin=NULL;
|
|
||||||
skinframe_t *skinframe=NULL;
|
|
||||||
int skinfiles;
|
int skinfiles;
|
||||||
#endif
|
#endif
|
||||||
galiasanimation_t *fgroup=NULL;
|
galiasanimation_t *fgroup=NULL;
|
||||||
|
@ -8302,8 +8325,6 @@ static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, siz
|
||||||
dalloc(orgbaf, h->num_vertexes);
|
dalloc(orgbaf, h->num_vertexes);
|
||||||
else
|
else
|
||||||
orgbaf = NULL;
|
orgbaf = NULL;
|
||||||
dalloc(skin, h->num_meshes*skinfiles);
|
|
||||||
dalloc(skinframe, h->num_meshes*skinfiles);
|
|
||||||
#endif
|
#endif
|
||||||
dalloc(fgroup, numgroups);
|
dalloc(fgroup, numgroups);
|
||||||
dalloc(oposebase, 12*h->num_joints);
|
dalloc(oposebase, 12*h->num_joints);
|
||||||
|
@ -8483,6 +8504,17 @@ static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, siz
|
||||||
if (!extsize || extsize != sizeof(*ftemesh)*h->num_meshes)
|
if (!extsize || extsize != sizeof(*ftemesh)*h->num_meshes)
|
||||||
ftemesh = NULL; //erk.
|
ftemesh = NULL; //erk.
|
||||||
|
|
||||||
|
fteskincount = IQM_FindExtension(buffer, fsize, "FTE_SKINS", 0, &extsize);
|
||||||
|
if (extsize >= sizeof(unsigned int)*(2+h->num_meshes) && extsize == sizeof(struct iqmext_fte_skin) + sizeof(unsigned int)*h->num_meshes + LittleLong(fteskincount[0])*sizeof(*fteskinframes) + LittleLong(fteskincount[1])*sizeof(*fteskins))
|
||||||
|
{
|
||||||
|
unsigned int numskinframes = LittleLong(*fteskincount++);
|
||||||
|
/*unsigned int numskins = LittleLong(* */fteskincount++;
|
||||||
|
|
||||||
|
fteskinframes = (const struct iqmext_fte_skin_skinframe*)(fteskincount+h->num_meshes);
|
||||||
|
fteskins = (const struct iqmext_fte_skin_meshskin*)(fteskinframes+numskinframes);
|
||||||
|
}
|
||||||
|
else fteskincount = NULL, fteskins = NULL, fteskinframes = NULL;
|
||||||
|
|
||||||
for (i = 0; i < max(1, h->num_meshes); i++)
|
for (i = 0; i < max(1, h->num_meshes); i++)
|
||||||
{
|
{
|
||||||
if (h->num_meshes)
|
if (h->num_meshes)
|
||||||
|
@ -8519,22 +8551,55 @@ static galiasinfo_t *Mod_ParseIQMMeshModel(model_t *mod, const char *buffer, siz
|
||||||
/*skins*/
|
/*skins*/
|
||||||
if (h->num_meshes)
|
if (h->num_meshes)
|
||||||
{
|
{
|
||||||
gai[i].numskins = skinfiles;
|
galiasskin_t *skin;
|
||||||
gai[i].ofsskins = skin;
|
skinframe_t *skinframe;
|
||||||
|
unsigned int iqmskins = fteskincount?LittleLong(*fteskincount++):0;
|
||||||
|
gai[i].numskins = max(iqmskins,skinfiles);
|
||||||
|
gai[i].ofsskins = skin = ZG_Malloc(&mod->memgroup, sizeof(*gai[i].ofsskins)*gai[i].numskins);
|
||||||
|
|
||||||
for (j = 0; j < skinfiles; j++)
|
for (j = 0; j < gai[i].numskins; j++, skin++)
|
||||||
{
|
{
|
||||||
|
const struct iqmext_fte_skin_skinframe *sf;
|
||||||
|
if (j < iqmskins)
|
||||||
|
{
|
||||||
|
sf = fteskinframes + LittleLong(fteskins->firstframe);
|
||||||
|
fteskins++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
sf = NULL;
|
||||||
|
|
||||||
skin->skinwidth = 1;
|
skin->skinwidth = 1;
|
||||||
skin->skinheight = 1;
|
skin->skinheight = 1;
|
||||||
skin->skinspeed = 10; /*something to avoid div by 0*/
|
Q_snprintfz(gai[i].ofsskins[j].name, sizeof(gai[i].ofsskins[j].name), "%i", j);
|
||||||
skin->numframes = 1; //non-sequenced skins.
|
if (sf)
|
||||||
skin->frame = skinframe;
|
{
|
||||||
Q_strncpyz(skin->name, "", sizeof(skinframe->shadername));
|
skin->skinspeed = 1.0/LittleFloat(fteskins[-1].interval); /*something to avoid div by 0*/
|
||||||
skin++;
|
skin->numframes = LittleLong(fteskins[-1].countframes); //non-sequenced skins.
|
||||||
|
|
||||||
Q_strncpyz(skinframe->shadername, strings+mesh[i].material, sizeof(skinframe->shadername));
|
if (!skin->numframes)
|
||||||
skinframe++;
|
continue;
|
||||||
|
|
||||||
|
skin->frame = ZG_Malloc(&mod->memgroup, sizeof(*skin->frame)*skin->numframes);
|
||||||
|
for (t = 0; t < skin->numframes; t++, sf++)
|
||||||
|
{
|
||||||
|
Q_strncpyz(skin->frame[t].shadername, strings+sf->material_idx, sizeof(skin->frame[t].shadername));
|
||||||
|
if (sf->shadertext_idx && sf->shadertext_idx<h->num_text)
|
||||||
|
{
|
||||||
|
const char *stxt = strings+sf->shadertext_idx;
|
||||||
|
skin->frame[t].defaultshader = strcpy(ZG_Malloc(&mod->memgroup, strlen(stxt)+1), stxt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
skin->skinspeed = 10; //something to avoid div by 0
|
||||||
|
skin->numframes = 1; //non-sequenced skins.
|
||||||
|
|
||||||
|
skin->frame = skinframe = ZG_Malloc(&mod->memgroup, sizeof(*skin->frame)*skin->numframes);
|
||||||
|
Q_strncpyz(skinframe->shadername, strings+mesh[i].material, sizeof(skinframe->shadername));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
gai[i].numskins = skin-gai[i].ofsskins;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
157
iqm/iqm.cpp
157
iqm/iqm.cpp
|
@ -17,6 +17,7 @@
|
||||||
bool noext = false;
|
bool noext = false;
|
||||||
bool verbose = false;
|
bool verbose = false;
|
||||||
bool quiet = false;
|
bool quiet = false;
|
||||||
|
bool stripbones = false; //strip all bone+anim info.
|
||||||
|
|
||||||
struct ejoint
|
struct ejoint
|
||||||
{
|
{
|
||||||
|
@ -32,7 +33,7 @@ struct ejoint
|
||||||
struct triangle { uint vert[3]; triangle() {} triangle(uint v0, uint v1, uint v2) { vert[0] = v0; vert[1] = v1; vert[2] = v2; } };
|
struct triangle { uint vert[3]; triangle() {} triangle(uint v0, uint v1, uint v2) { vert[0] = v0; vert[1] = v1; vert[2] = v2; } };
|
||||||
vector<triangle> triangles, neighbors;
|
vector<triangle> triangles, neighbors;
|
||||||
|
|
||||||
struct mesh { uint name, material; uint firstvert, numverts; uint firsttri, numtris; mesh() : name(0), material(0), firstvert(0), numverts(0), firsttri(0), numtris(0) {} };
|
struct mesh { uint name, material, numskins; uint firstvert, numverts; uint firsttri, numtris; mesh() : name(0), material(0), firstvert(0), numverts(0), firsttri(0), numtris(0) {} };
|
||||||
vector<mesh> meshes;
|
vector<mesh> meshes;
|
||||||
|
|
||||||
struct meshprop
|
struct meshprop
|
||||||
|
@ -59,6 +60,9 @@ struct event_fte
|
||||||
};
|
};
|
||||||
vector<event_fte> events_fte;
|
vector<event_fte> events_fte;
|
||||||
|
|
||||||
|
vector<iqmext_fte_skin_meshskin> meshskins;
|
||||||
|
vector<iqmext_fte_skin_skinframe> skinframes;
|
||||||
|
|
||||||
struct anim { uint name; uint firstframe, numframes; float fps; uint flags; anim() : name(0), firstframe(0), numframes(0), fps(0), flags(0) {} };
|
struct anim { uint name; uint firstframe, numframes; float fps; uint flags; anim() : name(0), firstframe(0), numframes(0), fps(0), flags(0) {} };
|
||||||
vector<anim> anims;
|
vector<anim> anims;
|
||||||
|
|
||||||
|
@ -1127,8 +1131,8 @@ void printlastmesh(void)
|
||||||
return;
|
return;
|
||||||
mesh &m = meshes[meshes.length()-1];
|
mesh &m = meshes[meshes.length()-1];
|
||||||
meshprop &fm = meshes_fte[meshes.length()-1];
|
meshprop &fm = meshes_fte[meshes.length()-1];
|
||||||
printf(" %smesh %i:\tname=\"%s\",\tmat=\"%s\",\ttri=%i, vert=%i\n", fm.contents?"c":"r", meshes.length()-1,
|
printf(" %smesh %i:\tname=\"%s\",\tmat=\"%s\",\ttri=%i, vert=%i, skins=%i\n", fm.contents?"c":"r", meshes.length()-1,
|
||||||
&stringdata[m.name], &stringdata[m.material], m.numtris, m.numverts);
|
&stringdata[m.name], &stringdata[m.material], m.numtris, m.numverts, m.numskins);
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
{
|
{
|
||||||
|
@ -1232,6 +1236,41 @@ void makemeshes(const filespec &spec)
|
||||||
maketriangles(tinfo, mmap);
|
maketriangles(tinfo, mmap);
|
||||||
m.numtris = triangles.length() - m.firsttri;
|
m.numtris = triangles.length() - m.firsttri;
|
||||||
m.numverts = numfverts+vmap.length() - m.firstvert;
|
m.numverts = numfverts+vmap.length() - m.firstvert;
|
||||||
|
m.numskins = 0; //we have a default material, so no worries.
|
||||||
|
|
||||||
|
if (spec.materialsuffix && !strncmp(spec.materialsuffix, "_00_00", 6))
|
||||||
|
{ //for qex... populate our skins info
|
||||||
|
for (int s = 0; ; s++)
|
||||||
|
{
|
||||||
|
char matname[512];
|
||||||
|
formatstring(matname, "%s%s_%02d_%02d%s", spec.materialprefix?spec.materialprefix:"", em1.material, s, 0, spec.materialsuffix+6);
|
||||||
|
FILE *f = fopen(matname, "rb");
|
||||||
|
if (f)
|
||||||
|
{
|
||||||
|
fclose(f); //don't really care.
|
||||||
|
auto &skin = meshskins.add();
|
||||||
|
m.numskins++;
|
||||||
|
skin.firstframe = skinframes.length();
|
||||||
|
skin.countframes = 1;
|
||||||
|
skin.interval = 0.2;
|
||||||
|
|
||||||
|
auto &skinframe = skinframes.add();
|
||||||
|
skinframe.material_idx = sharestring(matname);
|
||||||
|
skinframe.shadertext_idx = 0;
|
||||||
|
for (skin.countframes = 1; ; skin.countframes++)
|
||||||
|
{
|
||||||
|
formatstring(matname, "%s%s_%02d_%02d%s", spec.materialprefix?spec.materialprefix:"", em1.material, s, skin.countframes, spec.materialsuffix+6);
|
||||||
|
f = fopen(matname, "rb");
|
||||||
|
if (!f)
|
||||||
|
break;
|
||||||
|
fclose(f);
|
||||||
|
auto &skinframe = skinframes.add();
|
||||||
|
skinframe.material_idx = sharestring(matname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
meshprop &mf = meshes_fte.add();
|
meshprop &mf = meshes_fte.add();
|
||||||
mf = em1.explicits;
|
mf = em1.explicits;
|
||||||
|
@ -1272,7 +1311,7 @@ void makemeshes(const filespec &spec)
|
||||||
calctangents(priortris);
|
calctangents(priortris);
|
||||||
setupvertexarray<IQM_TANGENT>(etangents, IQM_TANGENT, IQM_FLOAT, 4, priorverts);
|
setupvertexarray<IQM_TANGENT>(etangents, IQM_TANGENT, IQM_FLOAT, 4, priorverts);
|
||||||
}
|
}
|
||||||
if(eblends.length())
|
if(eblends.length() && !stripbones)
|
||||||
{
|
{
|
||||||
if (ejoints.length() > 65535)
|
if (ejoints.length() > 65535)
|
||||||
setupvertexarray<IQM_BLENDINDEXES>(eblends, IQM_BLENDINDEXES, IQM_UINT, 4, priorverts);
|
setupvertexarray<IQM_BLENDINDEXES>(eblends, IQM_BLENDINDEXES, IQM_UINT, 4, priorverts);
|
||||||
|
@ -4718,6 +4757,17 @@ bool writeiqm(const char *filename)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iqmextension *ext_skins_fte = NULL;
|
||||||
|
if (meshskins.length())
|
||||||
|
{
|
||||||
|
ext_skins_fte = &extensions.add();
|
||||||
|
ext_skins_fte->name = sharestring("FTE_SKINS");
|
||||||
|
ext_skins_fte->num_data = sizeof(iqmext_fte_skin);
|
||||||
|
ext_skins_fte->num_data += meshes.length()*sizeof(uint);
|
||||||
|
ext_skins_fte->num_data += skinframes.length()*sizeof(iqmext_fte_skin_skinframe);
|
||||||
|
ext_skins_fte->num_data += meshskins.length()*sizeof(iqmext_fte_skin_meshskin);
|
||||||
|
}
|
||||||
|
|
||||||
if(stringdata.length()) hdr.ofs_text = hdr.filesize, hdr.num_text = stringdata.length(), hdr.filesize += hdr.num_text;
|
if(stringdata.length()) hdr.ofs_text = hdr.filesize, hdr.num_text = stringdata.length(), hdr.filesize += hdr.num_text;
|
||||||
hdr.num_meshes = meshes.length(); if(meshes.length()) hdr.ofs_meshes = hdr.filesize; hdr.filesize += meshes.length() * sizeof(iqmmesh);
|
hdr.num_meshes = meshes.length(); if(meshes.length()) hdr.ofs_meshes = hdr.filesize; hdr.filesize += meshes.length() * sizeof(iqmmesh);
|
||||||
uint voffset = hdr.filesize + varrays.length() * sizeof(iqmvertexarray);
|
uint voffset = hdr.filesize + varrays.length() * sizeof(iqmvertexarray);
|
||||||
|
@ -4738,6 +4788,7 @@ bool writeiqm(const char *filename)
|
||||||
if (extensions.length()) hdr.ofs_extensions = hdr.filesize, hdr.num_extensions = extensions.length(), hdr.filesize += sizeof(iqmextension) * hdr.num_extensions;
|
if (extensions.length()) hdr.ofs_extensions = hdr.filesize, hdr.num_extensions = extensions.length(), hdr.filesize += sizeof(iqmextension) * hdr.num_extensions;
|
||||||
if (ext_meshes_fte) ext_meshes_fte->ofs_data = hdr.filesize, ext_meshes_fte->num_data = meshes_fte.length()*sizeof(iqmext_fte_mesh), hdr.filesize += ext_meshes_fte->num_data;
|
if (ext_meshes_fte) ext_meshes_fte->ofs_data = hdr.filesize, ext_meshes_fte->num_data = meshes_fte.length()*sizeof(iqmext_fte_mesh), hdr.filesize += ext_meshes_fte->num_data;
|
||||||
if (ext_events_fte) ext_events_fte->ofs_data = hdr.filesize, ext_events_fte->num_data = events_fte.length()*sizeof(iqmext_fte_events), hdr.filesize += ext_events_fte->num_data;
|
if (ext_events_fte) ext_events_fte->ofs_data = hdr.filesize, ext_events_fte->num_data = events_fte.length()*sizeof(iqmext_fte_events), hdr.filesize += ext_events_fte->num_data;
|
||||||
|
if (ext_skins_fte) ext_skins_fte->ofs_data = hdr.filesize, hdr.filesize += ext_skins_fte->num_data;
|
||||||
|
|
||||||
lilswap(&hdr.version, (sizeof(hdr) - sizeof(hdr.magic))/sizeof(uint));
|
lilswap(&hdr.version, (sizeof(hdr) - sizeof(hdr.magic))/sizeof(uint));
|
||||||
|
|
||||||
|
@ -4856,6 +4907,24 @@ bool writeiqm(const char *filename)
|
||||||
f->putlil(ev.evdata_idx);
|
f->putlil(ev.evdata_idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ext_skins_fte)
|
||||||
|
{
|
||||||
|
f->putlil(skinframes.length());
|
||||||
|
f->putlil(meshskins.length());
|
||||||
|
loopv(meshes) f->putlil(meshes[i].numskins);
|
||||||
|
loopv(skinframes)
|
||||||
|
{
|
||||||
|
f->putlil(skinframes[i].material_idx);
|
||||||
|
f->putlil(skinframes[i].shadertext_idx);
|
||||||
|
}
|
||||||
|
loopv(meshskins)
|
||||||
|
{
|
||||||
|
f->putlil(meshskins[i].firstframe);
|
||||||
|
f->putlil(meshskins[i].countframes);
|
||||||
|
f->putlil(meshskins[i].interval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
delete f;
|
delete f;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -5366,7 +5435,7 @@ static void help(bool exitstatus, bool fullhelp)
|
||||||
"./iqmtool [options] output.iqm mesh.fbx anim1.fbx ... animN.fbx\n"
|
"./iqmtool [options] output.iqm mesh.fbx anim1.fbx ... animN.fbx\n"
|
||||||
"./iqmtool [options] output.iqm mesh.obj\n"
|
"./iqmtool [options] output.iqm mesh.obj\n"
|
||||||
"./iqmtool [options] output.iqm source.gltf\n"
|
"./iqmtool [options] output.iqm source.gltf\n"
|
||||||
"./iqmtool [options] output.iqm --kex sources.md5\n"
|
"./iqmtool [options] output.iqm --qex sources.md5\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Basic commandline options:\n"
|
"Basic commandline options:\n"
|
||||||
" --help Show full help.\n"
|
" --help Show full help.\n"
|
||||||
|
@ -5392,7 +5461,7 @@ static void help(bool exitstatus, bool fullhelp)
|
||||||
" -j\n"
|
" -j\n"
|
||||||
" --forcejoints Forces the exporting of joint information in animation\n"
|
" --forcejoints Forces the exporting of joint information in animation\n"
|
||||||
" files without meshes.\n"
|
" files without meshes.\n"
|
||||||
" --kex Applies a set of fixups to work around the quirks in\n"
|
" --qex Applies a set of fixups to work around the quirks in\n"
|
||||||
" the quake rerelease's md5 files.\n"
|
" the quake rerelease's md5 files.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Legacy commandline options that affect the following animation file:\n"
|
"Legacy commandline options that affect the following animation file:\n"
|
||||||
|
@ -5516,7 +5585,6 @@ unsigned int parsebits(bitnames *names, char **line)
|
||||||
comma = strchr(value, ',');
|
comma = strchr(value, ',');
|
||||||
if (comma)
|
if (comma)
|
||||||
*comma++ = 0;
|
*comma++ = 0;
|
||||||
|
|
||||||
char *end;
|
char *end;
|
||||||
strtoul(value, &end, 0);
|
strtoul(value, &end, 0);
|
||||||
if (end && !*end)
|
if (end && !*end)
|
||||||
|
@ -5535,7 +5603,7 @@ unsigned int parsebits(bitnames *names, char **line)
|
||||||
}
|
}
|
||||||
for (i = 0; names[i].name; i++)
|
for (i = 0; names[i].name; i++)
|
||||||
{
|
{
|
||||||
if (!*std || !strcasecmp(names[i].std, std))
|
if (!strcasecmp(names[i].std, std))
|
||||||
{
|
{
|
||||||
if (!strcasecmp(names[i].name, value))
|
if (!strcasecmp(names[i].name, value))
|
||||||
{
|
{
|
||||||
|
@ -5546,7 +5614,7 @@ unsigned int parsebits(bitnames *names, char **line)
|
||||||
}
|
}
|
||||||
if (!names[i].name)
|
if (!names[i].name)
|
||||||
{ //stuff with no specific standard, mostly for consistency
|
{ //stuff with no specific standard, mostly for consistency
|
||||||
if (!*names[i].std)
|
for (i = 0; names[i].name; i++)
|
||||||
{
|
{
|
||||||
if (!strcasecmp(names[i].name, value))
|
if (!strcasecmp(names[i].name, value))
|
||||||
{
|
{
|
||||||
|
@ -5693,7 +5761,7 @@ bool parseanimfield(const char *tok, char **line, filespec &spec, bool defaults)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct
|
static struct
|
||||||
{
|
{
|
||||||
const char *extname;
|
const char *extname;
|
||||||
bool (*write)(const char *filename);
|
bool (*write)(const char *filename);
|
||||||
|
@ -5708,6 +5776,45 @@ struct
|
||||||
{".md3", writemd3, "output_md3"},
|
{".md3", writemd3, "output_md3"},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static bitnames modelflagnames[] = {
|
||||||
|
{"q1", "rocket", 1u<<0},
|
||||||
|
{"q1", "grenade", 1u<<1},
|
||||||
|
{"q1", "gib", 1u<<2},
|
||||||
|
{"q1", "rotate", 1u<<3},
|
||||||
|
{"q1", "tracer1", 1u<<4},
|
||||||
|
{"q1", "zomgib", 1u<<5},
|
||||||
|
{"q1", "tracer2", 1u<<6},
|
||||||
|
{"q1", "tracer3", 1u<<7},
|
||||||
|
{"q1", "holey", 1u<<14}, //common extension
|
||||||
|
|
||||||
|
{"h2", "spidergib", 1u<<0}, //conflicts with q1.
|
||||||
|
{"h2", "grenade", 1u<<1},
|
||||||
|
{"h2", "gib", 1u<<2},
|
||||||
|
{"h2", "rotate", 1u<<3},
|
||||||
|
{"h2", "tracer1", 1u<<4},
|
||||||
|
{"h2", "zomgib", 1u<<5},
|
||||||
|
{"h2", "tracer2", 1u<<6},
|
||||||
|
{"h2", "tracer3", 1u<<7},
|
||||||
|
{"h2", "fireball", 1u<<8},
|
||||||
|
{"h2", "ice", 1u<<9},
|
||||||
|
{"h2", "mipmap", 1u<<10},
|
||||||
|
{"h2", "spit", 1u<<11},
|
||||||
|
{"h2", "transparent", 1u<<12},
|
||||||
|
{"h2", "spell", 1u<<13},
|
||||||
|
{"h2", "holey", 1u<<14},
|
||||||
|
{"h2", "specialtrans", 1u<<15},
|
||||||
|
{"h2", "faceview", 1u<<16},
|
||||||
|
{"h2", "vorpmissile", 1u<<17},
|
||||||
|
{"h2", "setstaff", 1u<<18},
|
||||||
|
{"h2", "magicmissle", 1u<<19},
|
||||||
|
{"h2", "boneshard", 1u<<20},
|
||||||
|
{"h2", "scarab", 1u<<21},
|
||||||
|
{"h2", "acidball", 1u<<22},
|
||||||
|
{"h2", "bloodshot", 1u<<23},
|
||||||
|
|
||||||
|
{NULL}
|
||||||
|
};
|
||||||
|
|
||||||
void parsecommands(char *filename, const char *outfiles[countof(outputtypes)], vector<filespec> &infiles, vector<hitbox> &hitboxes)
|
void parsecommands(char *filename, const char *outfiles[countof(outputtypes)], vector<filespec> &infiles, vector<hitbox> &hitboxes)
|
||||||
{
|
{
|
||||||
filespec defaultspec;
|
filespec defaultspec;
|
||||||
|
@ -5753,20 +5860,9 @@ void parsecommands(char *filename, const char *outfiles[countof(outputtypes)], v
|
||||||
else if (!strcasecmp(tok, "exec"))
|
else if (!strcasecmp(tok, "exec"))
|
||||||
parsecommands(mystrtok(&line), outfiles, infiles, hitboxes);
|
parsecommands(mystrtok(&line), outfiles, infiles, hitboxes);
|
||||||
else if (!strcasecmp(tok, "modelflags"))
|
else if (!strcasecmp(tok, "modelflags"))
|
||||||
{
|
|
||||||
bitnames modelflagnames[] = {
|
|
||||||
{"q1", "rocket", 0x01},
|
|
||||||
{"q1", "grenade", 0x02},
|
|
||||||
{"q1", "gib", 0x04},
|
|
||||||
{"q1", "rotate", 0x08},
|
|
||||||
{"q1", "tracer1", 0x10},
|
|
||||||
{"q1", "zomgib", 0x20},
|
|
||||||
{"q1", "tracer2", 0x40},
|
|
||||||
{"q1", "tracer3", 0x80},
|
|
||||||
{NULL}
|
|
||||||
};
|
|
||||||
modelflags = parsebits(modelflagnames, &line);
|
modelflags = parsebits(modelflagnames, &line);
|
||||||
}
|
else if (!strcasecmp(tok, "static"))
|
||||||
|
stripbones = true;
|
||||||
|
|
||||||
else if (parseanimfield(tok, &line, defaultspec, true))
|
else if (parseanimfield(tok, &line, defaultspec, true))
|
||||||
;
|
;
|
||||||
|
@ -5905,7 +6001,9 @@ int main(int argc, char **argv)
|
||||||
else if(!strcasecmp(&argv[i][2], "forcejoints")) forcejoints = true;
|
else if(!strcasecmp(&argv[i][2], "forcejoints")) forcejoints = true;
|
||||||
else if(!strcasecmp(&argv[i][2], "materialprefix")) { if(i + 1 < argc) inspec.materialprefix = argv[++i]; }
|
else if(!strcasecmp(&argv[i][2], "materialprefix")) { if(i + 1 < argc) inspec.materialprefix = argv[++i]; }
|
||||||
else if(!strcasecmp(&argv[i][2], "materialsuffix")) { if(i + 1 < argc) inspec.materialsuffix = argv[++i]; }
|
else if(!strcasecmp(&argv[i][2], "materialsuffix")) { if(i + 1 < argc) inspec.materialsuffix = argv[++i]; }
|
||||||
else if(!strcasecmp(&argv[i][2], "kex")) inspec.materialprefix = "progs/", inspec.materialsuffix = "_00_00.lmp", inspec.flags |= IQM_UNPACK;
|
else if(!strcasecmp(&argv[i][2], "qex")) inspec.materialprefix = "progs/", inspec.materialsuffix = "_00_00.lmp", inspec.flags |= IQM_UNPACK;
|
||||||
|
else if(!strcasecmp(&argv[i][2], "modelflags")) { if(i + 1 < argc) { modelflags |= parsebits(modelflagnames, &argv[++i]); }}
|
||||||
|
else if(!strcasecmp(&argv[i][2], "static")) stripbones = true;
|
||||||
else if(!strcasecmp(&argv[i][2], "meshtrans"))
|
else if(!strcasecmp(&argv[i][2], "meshtrans"))
|
||||||
{
|
{
|
||||||
if(i + 1 < argc) switch(sscanf(argv[++i], "%lf , %lf , %lf", &gmeshtrans.x, &gmeshtrans.y, &gmeshtrans.z))
|
if(i + 1 < argc) switch(sscanf(argv[++i], "%lf , %lf , %lf", &gmeshtrans.x, &gmeshtrans.y, &gmeshtrans.z))
|
||||||
|
@ -6050,6 +6148,17 @@ int main(int argc, char **argv)
|
||||||
conoutf("warning: mesh \"%s\" overriden, but not present", meshoverrides[i].name);
|
conoutf("warning: mesh \"%s\" overriden, but not present", meshoverrides[i].name);
|
||||||
|
|
||||||
|
|
||||||
|
if (stripbones)
|
||||||
|
{
|
||||||
|
if (!quiet)
|
||||||
|
conoutf("static bones");
|
||||||
|
joints.setsize(0);
|
||||||
|
poses.setsize(0);
|
||||||
|
frames.setsize(0);
|
||||||
|
anims.setsize(0);
|
||||||
|
bounds.setsize(0);
|
||||||
|
}
|
||||||
|
|
||||||
calcanimdata();
|
calcanimdata();
|
||||||
|
|
||||||
if (!quiet)
|
if (!quiet)
|
||||||
|
|
23
iqm/iqm.h
23
iqm/iqm.h
|
@ -147,5 +147,28 @@ struct iqmext_fte_events
|
||||||
unsigned int evcode;
|
unsigned int evcode;
|
||||||
unsigned int evdata_str;
|
unsigned int evdata_str;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//skin lump is made of 3 parts
|
||||||
|
struct iqmext_fte_skin
|
||||||
|
{
|
||||||
|
unsigned int nummeshskins;
|
||||||
|
unsigned int numskinframes;
|
||||||
|
//unsigned int numskins[nummeshes];
|
||||||
|
//iqmext_fte_skin_skinframe[numskinframes];
|
||||||
|
//iqmext_fte_skin_meshskin mesh0[numskins[0]];
|
||||||
|
//iqmext_fte_skin_meshskin mesh1[numskins[1]]; etc
|
||||||
|
};
|
||||||
|
struct iqmext_fte_skin_skinframe
|
||||||
|
{ //as many as needed
|
||||||
|
unsigned int material_idx;
|
||||||
|
unsigned int shadertext_idx;
|
||||||
|
};
|
||||||
|
struct iqmext_fte_skin_meshskin
|
||||||
|
{
|
||||||
|
unsigned int firstframe; //index into skinframes
|
||||||
|
unsigned int countframes; //skinframes
|
||||||
|
float interval;
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue