diff options
| author | xolatile | 2025-08-04 22:53:42 +0200 |
|---|---|---|
| committer | xolatile | 2025-08-04 22:53:42 +0200 |
| commit | d309df4ce4d8ad0ed995a8e1c4267412a7782021 (patch) | |
| tree | 999ca8d785ecc1681e5eb7538ce2e6a18d244fa5 /src/engine/iqm.h | |
| parent | 29d613d9cb65a0faa7e3f80e75bea0b6d910cb9a (diff) | |
| download | xolatile-badassbug-d309df4ce4d8ad0ed995a8e1c4267412a7782021.tar.xz xolatile-badassbug-d309df4ce4d8ad0ed995a8e1c4267412a7782021.tar.zst | |
Bunch of small changes...
Diffstat (limited to 'src/engine/iqm.h')
| -rw-r--r-- | src/engine/iqm.h | 708 |
1 files changed, 354 insertions, 354 deletions
diff --git a/src/engine/iqm.h b/src/engine/iqm.h index f426a6b..e36a628 100644 --- a/src/engine/iqm.h +++ b/src/engine/iqm.h @@ -2,394 +2,394 @@ struct iqm; struct iqmheader { - char magic[16]; - uint version; - uint filesize; - uint flags; - uint num_text, ofs_text; - uint num_meshes, ofs_meshes; - uint num_vertexarrays, num_vertexes, ofs_vertexarrays; - uint num_triangles, ofs_triangles, ofs_adjacency; - uint num_joints, ofs_joints; - uint num_poses, ofs_poses; - uint num_anims, ofs_anims; - uint num_frames, num_framechannels, ofs_frames, ofs_bounds; - uint num_comment, ofs_comment; - uint num_extensions, ofs_extensions; + char magic[16]; + uint version; + uint filesize; + uint flags; + uint num_text, ofs_text; + uint num_meshes, ofs_meshes; + uint num_vertexarrays, num_vertexes, ofs_vertexarrays; + uint num_triangles, ofs_triangles, ofs_adjacency; + uint num_joints, ofs_joints; + uint num_poses, ofs_poses; + uint num_anims, ofs_anims; + uint num_frames, num_framechannels, ofs_frames, ofs_bounds; + uint num_comment, ofs_comment; + uint num_extensions, ofs_extensions; }; struct iqmmesh { - uint name; - uint material; - uint first_vertex, num_vertexes; - uint first_triangle, num_triangles; + uint name; + uint material; + uint first_vertex, num_vertexes; + uint 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 -}; +{ + 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, + 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 { - uint vertex[3]; + uint vertex[3]; }; struct iqmjoint { - uint name; - int parent; - vec pos; - quat orient; - vec size; + uint name; + int parent; + vec pos; + quat orient; + vec size; }; struct iqmpose { - int parent; - uint mask; - vec offsetpos; - vec4 offsetorient; - vec offsetsize; - vec scalepos; - vec4 scaleorient; - vec scalesize; + int parent; + uint mask; + vec offsetpos; + vec4 offsetorient; + vec offsetsize; + vec scalepos; + vec4 scaleorient; + vec scalesize; }; struct iqmanim { - uint name; - uint first_frame, num_frames; - float framerate; - uint flags; + uint name; + uint first_frame, num_frames; + float framerate; + uint flags; }; struct iqmvertexarray { - uint type; - uint flags; - uint format; - uint size; - uint offset; + uint type; + uint flags; + uint format; + uint size; + uint offset; }; struct iqm : skelloader<iqm> { - iqm(const char *name) : skelloader(name) {} - - static const char *formatname() { return "iqm"; } - int type() const { return MDL_IQM; } - - struct iqmmeshgroup : skelmeshgroup - { - iqmmeshgroup() - { - } - - bool loadiqmmeshes(const char *filename, const iqmheader &hdr, uchar *buf) - { - lilswap((uint *)&buf[hdr.ofs_vertexarrays], hdr.num_vertexarrays*sizeof(iqmvertexarray)/sizeof(uint)); - lilswap((uint *)&buf[hdr.ofs_triangles], hdr.num_triangles*sizeof(iqmtriangle)/sizeof(uint)); - lilswap((uint *)&buf[hdr.ofs_meshes], hdr.num_meshes*sizeof(iqmmesh)/sizeof(uint)); - lilswap((uint *)&buf[hdr.ofs_joints], hdr.num_joints*sizeof(iqmjoint)/sizeof(uint)); - - const char *str = hdr.ofs_text ? (char *)&buf[hdr.ofs_text] : ""; - float *vpos = NULL, *vnorm = NULL, *vtan = NULL, *vtc = NULL; - uchar *vindex = NULL, *vweight = NULL; - iqmvertexarray *vas = (iqmvertexarray *)&buf[hdr.ofs_vertexarrays]; - loopi(hdr.num_vertexarrays) - { - iqmvertexarray &va = vas[i]; - switch(va.type) - { - case IQM_POSITION: if(va.format != IQM_FLOAT || va.size != 3) return false; vpos = (float *)&buf[va.offset]; lilswap(vpos, 3*hdr.num_vertexes); break; - case IQM_NORMAL: if(va.format != IQM_FLOAT || va.size != 3) return false; vnorm = (float *)&buf[va.offset]; lilswap(vnorm, 3*hdr.num_vertexes); break; - case IQM_TANGENT: if(va.format != IQM_FLOAT || va.size != 4) return false; vtan = (float *)&buf[va.offset]; lilswap(vtan, 4*hdr.num_vertexes); break; - case IQM_TEXCOORD: if(va.format != IQM_FLOAT || va.size != 2) return false; vtc = (float *)&buf[va.offset]; lilswap(vtc, 2*hdr.num_vertexes); break; - case IQM_BLENDINDEXES: if(va.format != IQM_UBYTE || va.size != 4) return false; vindex = (uchar *)&buf[va.offset]; break; - case IQM_BLENDWEIGHTS: if(va.format != IQM_UBYTE || va.size != 4) return false; vweight = (uchar *)&buf[va.offset]; break; - } - } - if(!vpos) return false; - - iqmtriangle *tris = (iqmtriangle *)&buf[hdr.ofs_triangles]; - iqmmesh *imeshes = (iqmmesh *)&buf[hdr.ofs_meshes]; - iqmjoint *joints = (iqmjoint *)&buf[hdr.ofs_joints]; - - if(hdr.num_joints) - { - if(skel->numbones <= 0) - { - skel->numbones = hdr.num_joints; - skel->bones = new boneinfo[skel->numbones]; - loopi(hdr.num_joints) - { - iqmjoint &j = joints[i]; - boneinfo &b = skel->bones[i]; - if(!b.name) b.name = newstring(&str[j.name]); - b.parent = j.parent; - if(skel->shared <= 1) - { - j.pos.y = -j.pos.y; - j.orient.x = -j.orient.x; - j.orient.z = -j.orient.z; - j.orient.normalize(); - b.base = dualquat(j.orient, j.pos); - if(b.parent >= 0) b.base.mul(skel->bones[b.parent].base, dualquat(b.base)); - (b.invbase = b.base).invert(); - } - } - } - - if(skel->shared <= 1) - skel->linkchildren(); - } - - loopi(hdr.num_meshes) - { - iqmmesh &im = imeshes[i]; - skelmesh *m = new skelmesh; - m->group = this; - meshes.add(m); - m->name = newstring(&str[im.name]); - m->numverts = im.num_vertexes; - int noblend = -1; - if(m->numverts) - { - m->verts = new vert[m->numverts]; - if(vtan) m->bumpverts = new bumpvert[m->numverts]; - if(!vindex || !vweight) - { - blendcombo c; - c.finalize(0); - noblend = m->addblendcombo(c); - } - } - int fv = im.first_vertex; - float *mpos = vpos + 3*fv, - *mnorm = vnorm ? vnorm + 3*fv : NULL, - *mtan = vtan ? vtan + 4*fv : NULL, - *mtc = vtc ? vtc + 2*fv : NULL; - uchar *mindex = vindex ? vindex + 4*fv : NULL, *mweight = vweight ? vweight + 4*fv : NULL; - loopj(im.num_vertexes) - { - vert &v = m->verts[j]; - v.pos = vec(mpos[0], -mpos[1], mpos[2]); - mpos += 3; - if(mtc) - { - v.tc = vec2(mtc[0], mtc[1]); - mtc += 2; - } - else v.tc = vec2(0, 0); - if(mnorm) - { - v.norm = vec(mnorm[0], -mnorm[1], mnorm[2]); - mnorm += 3; - if(mtan) - { - m->calctangent(m->bumpverts[j], v.norm, vec(mtan[0], -mtan[1], mtan[2]), mtan[3]); - mtan += 4; - } - } - else v.norm = vec(0, 0, 0); - if(noblend < 0) - { - blendcombo c; - int sorted = 0; - loopk(4) sorted = c.addweight(sorted, mweight[k], mindex[k]); - mweight += 4; - mindex += 4; - c.finalize(sorted); - v.blend = m->addblendcombo(c); - } - else v.blend = noblend; - } - m->numtris = im.num_triangles; - if(m->numtris) m->tris = new tri[m->numtris]; - iqmtriangle *mtris = tris + im.first_triangle; - loopj(im.num_triangles) - { - tri &t = m->tris[j]; - t.vert[0] = mtris->vertex[0] - fv; - t.vert[1] = mtris->vertex[1] - fv; - t.vert[2] = mtris->vertex[2] - fv; - ++mtris; - } - if(!m->numtris || !m->numverts) - { - conoutf(CON_WARN, "empty mesh in %s", filename); - meshes.removeobj(m); - delete m; - } - } - - sortblendcombos(); - - return true; - } - - bool loadiqmanims(const char *filename, const iqmheader &hdr, uchar *buf) - { - lilswap((uint *)&buf[hdr.ofs_poses], hdr.num_poses*sizeof(iqmpose)/sizeof(uint)); - lilswap((uint *)&buf[hdr.ofs_anims], hdr.num_anims*sizeof(iqmanim)/sizeof(uint)); - lilswap((ushort *)&buf[hdr.ofs_frames], hdr.num_frames*hdr.num_framechannels); - - const char *str = hdr.ofs_text ? (char *)&buf[hdr.ofs_text] : ""; - iqmpose *poses = (iqmpose *)&buf[hdr.ofs_poses]; - iqmanim *anims = (iqmanim *)&buf[hdr.ofs_anims]; - ushort *frames = (ushort *)&buf[hdr.ofs_frames]; - loopi(hdr.num_anims) - { - iqmanim &a = anims[i]; - string name; - copystring(name, filename); - concatstring(name, ":"); - concatstring(name, &str[a.name]); - skelanimspec *sa = skel->findskelanim(name); - if(sa) continue; - sa = &skel->addskelanim(name); - sa->frame = skel->numframes; - sa->range = a.num_frames; - dualquat *animbones = new dualquat[(skel->numframes+a.num_frames)*skel->numbones]; - if(skel->bones) - { - memcpy(animbones, skel->framebones, skel->numframes*skel->numbones*sizeof(dualquat)); - delete[] skel->framebones; - } - skel->framebones = animbones; - animbones += skel->numframes*skel->numbones; - skel->numframes += a.num_frames; - ushort *animdata = &frames[a.first_frame*hdr.num_framechannels]; - loopj(a.num_frames) - { - dualquat *frame = &animbones[j*skel->numbones]; - loopk(skel->numbones) - { - iqmpose &p = poses[k]; - vec pos; - quat orient; - pos.x = p.offsetpos.x; if(p.mask&0x01) pos.x += *animdata++ * p.scalepos.x; - pos.y = -p.offsetpos.y; if(p.mask&0x02) pos.y -= *animdata++ * p.scalepos.y; - pos.z = p.offsetpos.z; if(p.mask&0x04) pos.z += *animdata++ * p.scalepos.z; - orient.x = -p.offsetorient.x; if(p.mask&0x08) orient.x -= *animdata++ * p.scaleorient.x; - orient.y = p.offsetorient.y; if(p.mask&0x10) orient.y += *animdata++ * p.scaleorient.y; - orient.z = -p.offsetorient.z; if(p.mask&0x20) orient.z -= *animdata++ * p.scaleorient.z; - orient.w = p.offsetorient.w; if(p.mask&0x40) orient.w += *animdata++ * p.scaleorient.w; - orient.normalize(); - if(p.mask&0x380) - { - if(p.mask&0x80) animdata++; - if(p.mask&0x100) animdata++; - if(p.mask&0x200) animdata++; - } - frame[k] = dualquat(orient, pos); - if(adjustments.inrange(k)) adjustments[k].adjust(frame[k]); - boneinfo &b = skel->bones[k]; - frame[k].mul(b.invbase); - if(b.parent >= 0) frame[k].mul(skel->bones[b.parent].base, dualquat(frame[k])); - frame[k].fixantipodal(skel->framebones[k]); - } - } - } - - return true; - } - - bool loadiqm(const char *filename, bool doloadmesh, bool doloadanim) - { - stream *f = openfile(filename, "rb"); - if(!f) return false; - - uchar *buf = NULL; - iqmheader hdr; - if(f->read(&hdr, sizeof(hdr)) != sizeof(hdr) || memcmp(hdr.magic, "INTERQUAKEMODEL", sizeof(hdr.magic))) goto error; - lilswap(&hdr.version, (sizeof(hdr) - sizeof(hdr.magic))/sizeof(uint)); - if(hdr.version != 2) goto error; - if(hdr.filesize > (16<<20)) goto error; // sanity check... don't load files bigger than 16 MB - buf = new (false) uchar[hdr.filesize]; - if(!buf || f->read(buf + sizeof(hdr), hdr.filesize - sizeof(hdr)) != hdr.filesize - sizeof(hdr)) goto error; - - if(doloadmesh && !loadiqmmeshes(filename, hdr, buf)) goto error; - if(doloadanim && !loadiqmanims(filename, hdr, buf)) goto error; - - delete[] buf; - delete f; - return true; - - error: - if(buf) delete[] buf; - delete f; - return false; - } - - bool loadmesh(const char *filename) - { - name = newstring(filename); - - return loadiqm(filename, true, false); - } - - skelanimspec *loadanim(const char *animname) - { - const char *sep = strchr(animname, ':'); - skelanimspec *sa = skel->findskelanim(animname, sep ? '\0' : ':'); - if(!sa) - { - string filename; - copystring(filename, animname); - if(sep) filename[sep - animname] = '\0'; - if(loadiqm(filename, false, true)) - sa = skel->findskelanim(animname, sep ? '\0' : ':'); - } - return sa; - } - }; - - meshgroup *loadmeshes(const char *name, va_list args) - { - iqmmeshgroup *group = new iqmmeshgroup; - group->shareskeleton(va_arg(args, char *)); - if(!group->loadmesh(name)) { delete group; return NULL; } - return group; - } - - bool loaddefaultparts() - { - skelpart &mdl = addpart(); - mdl.pitchscale = mdl.pitchoffset = mdl.pitchmin = mdl.pitchmax = 0; - adjustments.setsize(0); - const char *fname = name + strlen(name); - do --fname; while(fname >= name && *fname!='/' && *fname!='\\'); - fname++; - defformatstring(meshname, "packages/models/%s/%s.iqm", name, fname); - mdl.meshes = sharemeshes(path(meshname), NULL); - if(!mdl.meshes) return false; - mdl.initanimparts(); - mdl.initskins(); - return true; - } + iqm(const char *name) : skelloader(name) {} + + static const char *formatname() { return "iqm"; } + int type() const { return MDL_IQM; } + + struct iqmmeshgroup : skelmeshgroup + { + iqmmeshgroup() + { + } + + bool loadiqmmeshes(const char *filename, const iqmheader &hdr, uchar *buf) + { + lilswap((uint *)&buf[hdr.ofs_vertexarrays], hdr.num_vertexarrays*sizeof(iqmvertexarray)/sizeof(uint)); + lilswap((uint *)&buf[hdr.ofs_triangles], hdr.num_triangles*sizeof(iqmtriangle)/sizeof(uint)); + lilswap((uint *)&buf[hdr.ofs_meshes], hdr.num_meshes*sizeof(iqmmesh)/sizeof(uint)); + lilswap((uint *)&buf[hdr.ofs_joints], hdr.num_joints*sizeof(iqmjoint)/sizeof(uint)); + + const char *str = hdr.ofs_text ? (char *)&buf[hdr.ofs_text] : ""; + float *vpos = NULL, *vnorm = NULL, *vtan = NULL, *vtc = NULL; + uchar *vindex = NULL, *vweight = NULL; + iqmvertexarray *vas = (iqmvertexarray *)&buf[hdr.ofs_vertexarrays]; + loopi(hdr.num_vertexarrays) + { + iqmvertexarray &va = vas[i]; + switch(va.type) + { + case IQM_POSITION: if(va.format != IQM_FLOAT || va.size != 3) return false; vpos = (float *)&buf[va.offset]; lilswap(vpos, 3*hdr.num_vertexes); break; + case IQM_NORMAL: if(va.format != IQM_FLOAT || va.size != 3) return false; vnorm = (float *)&buf[va.offset]; lilswap(vnorm, 3*hdr.num_vertexes); break; + case IQM_TANGENT: if(va.format != IQM_FLOAT || va.size != 4) return false; vtan = (float *)&buf[va.offset]; lilswap(vtan, 4*hdr.num_vertexes); break; + case IQM_TEXCOORD: if(va.format != IQM_FLOAT || va.size != 2) return false; vtc = (float *)&buf[va.offset]; lilswap(vtc, 2*hdr.num_vertexes); break; + case IQM_BLENDINDEXES: if(va.format != IQM_UBYTE || va.size != 4) return false; vindex = (uchar *)&buf[va.offset]; break; + case IQM_BLENDWEIGHTS: if(va.format != IQM_UBYTE || va.size != 4) return false; vweight = (uchar *)&buf[va.offset]; break; + } + } + if(!vpos) return false; + + iqmtriangle *tris = (iqmtriangle *)&buf[hdr.ofs_triangles]; + iqmmesh *imeshes = (iqmmesh *)&buf[hdr.ofs_meshes]; + iqmjoint *joints = (iqmjoint *)&buf[hdr.ofs_joints]; + + if(hdr.num_joints) + { + if(skel->numbones <= 0) + { + skel->numbones = hdr.num_joints; + skel->bones = new boneinfo[skel->numbones]; + loopi(hdr.num_joints) + { + iqmjoint &j = joints[i]; + boneinfo &b = skel->bones[i]; + if(!b.name) b.name = newstring(&str[j.name]); + b.parent = j.parent; + if(skel->shared <= 1) + { + j.pos.y = -j.pos.y; + j.orient.x = -j.orient.x; + j.orient.z = -j.orient.z; + j.orient.normalize(); + b.base = dualquat(j.orient, j.pos); + if(b.parent >= 0) b.base.mul(skel->bones[b.parent].base, dualquat(b.base)); + (b.invbase = b.base).invert(); + } + } + } + + if(skel->shared <= 1) + skel->linkchildren(); + } + + loopi(hdr.num_meshes) + { + iqmmesh &im = imeshes[i]; + skelmesh *m = new skelmesh; + m->group = this; + meshes.add(m); + m->name = newstring(&str[im.name]); + m->numverts = im.num_vertexes; + int noblend = -1; + if(m->numverts) + { + m->verts = new vert[m->numverts]; + if(vtan) m->bumpverts = new bumpvert[m->numverts]; + if(!vindex || !vweight) + { + blendcombo c; + c.finalize(0); + noblend = m->addblendcombo(c); + } + } + int fv = im.first_vertex; + float *mpos = vpos + 3*fv, + *mnorm = vnorm ? vnorm + 3*fv : NULL, + *mtan = vtan ? vtan + 4*fv : NULL, + *mtc = vtc ? vtc + 2*fv : NULL; + uchar *mindex = vindex ? vindex + 4*fv : NULL, *mweight = vweight ? vweight + 4*fv : NULL; + loopj(im.num_vertexes) + { + vert &v = m->verts[j]; + v.pos = vec(mpos[0], -mpos[1], mpos[2]); + mpos += 3; + if(mtc) + { + v.tc = vec2(mtc[0], mtc[1]); + mtc += 2; + } + else v.tc = vec2(0, 0); + if(mnorm) + { + v.norm = vec(mnorm[0], -mnorm[1], mnorm[2]); + mnorm += 3; + if(mtan) + { + m->calctangent(m->bumpverts[j], v.norm, vec(mtan[0], -mtan[1], mtan[2]), mtan[3]); + mtan += 4; + } + } + else v.norm = vec(0, 0, 0); + if(noblend < 0) + { + blendcombo c; + int sorted = 0; + loopk(4) sorted = c.addweight(sorted, mweight[k], mindex[k]); + mweight += 4; + mindex += 4; + c.finalize(sorted); + v.blend = m->addblendcombo(c); + } + else v.blend = noblend; + } + m->numtris = im.num_triangles; + if(m->numtris) m->tris = new tri[m->numtris]; + iqmtriangle *mtris = tris + im.first_triangle; + loopj(im.num_triangles) + { + tri &t = m->tris[j]; + t.vert[0] = mtris->vertex[0] - fv; + t.vert[1] = mtris->vertex[1] - fv; + t.vert[2] = mtris->vertex[2] - fv; + ++mtris; + } + if(!m->numtris || !m->numverts) + { + conoutf(CON_WARN, "empty mesh in %s", filename); + meshes.removeobj(m); + delete m; + } + } + + sortblendcombos(); + + return true; + } + + bool loadiqmanims(const char *filename, const iqmheader &hdr, uchar *buf) + { + lilswap((uint *)&buf[hdr.ofs_poses], hdr.num_poses*sizeof(iqmpose)/sizeof(uint)); + lilswap((uint *)&buf[hdr.ofs_anims], hdr.num_anims*sizeof(iqmanim)/sizeof(uint)); + lilswap((ushort *)&buf[hdr.ofs_frames], hdr.num_frames*hdr.num_framechannels); + + const char *str = hdr.ofs_text ? (char *)&buf[hdr.ofs_text] : ""; + iqmpose *poses = (iqmpose *)&buf[hdr.ofs_poses]; + iqmanim *anims = (iqmanim *)&buf[hdr.ofs_anims]; + ushort *frames = (ushort *)&buf[hdr.ofs_frames]; + loopi(hdr.num_anims) + { + iqmanim &a = anims[i]; + string name; + copystring(name, filename); + concatstring(name, ":"); + concatstring(name, &str[a.name]); + skelanimspec *sa = skel->findskelanim(name); + if(sa) continue; + sa = &skel->addskelanim(name); + sa->frame = skel->numframes; + sa->range = a.num_frames; + dualquat *animbones = new dualquat[(skel->numframes+a.num_frames)*skel->numbones]; + if(skel->bones) + { + memcpy(animbones, skel->framebones, skel->numframes*skel->numbones*sizeof(dualquat)); + delete[] skel->framebones; + } + skel->framebones = animbones; + animbones += skel->numframes*skel->numbones; + skel->numframes += a.num_frames; + ushort *animdata = &frames[a.first_frame*hdr.num_framechannels]; + loopj(a.num_frames) + { + dualquat *frame = &animbones[j*skel->numbones]; + loopk(skel->numbones) + { + iqmpose &p = poses[k]; + vec pos; + quat orient; + pos.x = p.offsetpos.x; if(p.mask&0x01) pos.x += *animdata++ * p.scalepos.x; + pos.y = -p.offsetpos.y; if(p.mask&0x02) pos.y -= *animdata++ * p.scalepos.y; + pos.z = p.offsetpos.z; if(p.mask&0x04) pos.z += *animdata++ * p.scalepos.z; + orient.x = -p.offsetorient.x; if(p.mask&0x08) orient.x -= *animdata++ * p.scaleorient.x; + orient.y = p.offsetorient.y; if(p.mask&0x10) orient.y += *animdata++ * p.scaleorient.y; + orient.z = -p.offsetorient.z; if(p.mask&0x20) orient.z -= *animdata++ * p.scaleorient.z; + orient.w = p.offsetorient.w; if(p.mask&0x40) orient.w += *animdata++ * p.scaleorient.w; + orient.normalize(); + if(p.mask&0x380) + { + if(p.mask&0x80) animdata++; + if(p.mask&0x100) animdata++; + if(p.mask&0x200) animdata++; + } + frame[k] = dualquat(orient, pos); + if(adjustments.inrange(k)) adjustments[k].adjust(frame[k]); + boneinfo &b = skel->bones[k]; + frame[k].mul(b.invbase); + if(b.parent >= 0) frame[k].mul(skel->bones[b.parent].base, dualquat(frame[k])); + frame[k].fixantipodal(skel->framebones[k]); + } + } + } + + return true; + } + + bool loadiqm(const char *filename, bool doloadmesh, bool doloadanim) + { + stream *f = openfile(filename, "rb"); + if(!f) return false; + + uchar *buf = NULL; + iqmheader hdr; + if(f->read(&hdr, sizeof(hdr)) != sizeof(hdr) || memcmp(hdr.magic, "INTERQUAKEMODEL", sizeof(hdr.magic))) goto error; + lilswap(&hdr.version, (sizeof(hdr) - sizeof(hdr.magic))/sizeof(uint)); + if(hdr.version != 2) goto error; + if(hdr.filesize > (16<<20)) goto error; // sanity check... don't load files bigger than 16 MB + buf = new (false) uchar[hdr.filesize]; + if(!buf || f->read(buf + sizeof(hdr), hdr.filesize - sizeof(hdr)) != hdr.filesize - sizeof(hdr)) goto error; + + if(doloadmesh && !loadiqmmeshes(filename, hdr, buf)) goto error; + if(doloadanim && !loadiqmanims(filename, hdr, buf)) goto error; + + delete[] buf; + delete f; + return true; + + error: + if(buf) delete[] buf; + delete f; + return false; + } + + bool loadmesh(const char *filename) + { + name = newstring(filename); + + return loadiqm(filename, true, false); + } + + skelanimspec *loadanim(const char *animname) + { + const char *sep = strchr(animname, ':'); + skelanimspec *sa = skel->findskelanim(animname, sep ? '\0' : ':'); + if(!sa) + { + string filename; + copystring(filename, animname); + if(sep) filename[sep - animname] = '\0'; + if(loadiqm(filename, false, true)) + sa = skel->findskelanim(animname, sep ? '\0' : ':'); + } + return sa; + } + }; + + meshgroup *loadmeshes(const char *name, va_list args) + { + iqmmeshgroup *group = new iqmmeshgroup; + group->shareskeleton(va_arg(args, char *)); + if(!group->loadmesh(name)) { delete group; return NULL; } + return group; + } + + bool loaddefaultparts() + { + skelpart &mdl = addpart(); + mdl.pitchscale = mdl.pitchoffset = mdl.pitchmin = mdl.pitchmax = 0; + adjustments.setsize(0); + const char *fname = name + strlen(name); + do --fname; while(fname >= name && *fname!='/' && *fname!='\\'); + fname++; + defformatstring(meshname, "packages/models/%s/%s.iqm", name, fname); + mdl.meshes = sharemeshes(path(meshname), NULL); + if(!mdl.meshes) return false; + mdl.initanimparts(); + mdl.initskins(); + return true; + } }; skelcommands<iqm> iqmcommands; |
