diff options
Diffstat (limited to 'src/engine/skelmodel.h')
| -rw-r--r-- | src/engine/skelmodel.h | 975 |
1 files changed, 272 insertions, 703 deletions
diff --git a/src/engine/skelmodel.h b/src/engine/skelmodel.h index c8d14d0..e823337 100644 --- a/src/engine/skelmodel.h +++ b/src/engine/skelmodel.h @@ -7,8 +7,7 @@ VAR(testtags, 0, 0, 1); #define BONEMASK_END 0xFFFF #define BONEMASK_BONE 0x7FFF -struct skelmodel : animmodel -{ +struct skelmodel : animmodel { struct vert { vec pos, norm; vec2 tc; int blend, interpindex; }; struct vvert { vec pos; vec2 tc; }; struct vvertn : vvert { vec norm; }; @@ -18,37 +17,25 @@ struct skelmodel : animmodel struct vvertbumpw : vvertbump, vvertw {}; struct bumpvert { quat tangent; }; struct tri { ushort vert[3]; }; - - struct blendcombo - { + struct blendcombo { int uses, interpindex; float weights[4]; uchar bones[4], interpbones[4]; - - blendcombo() : uses(1) - { + blendcombo() : uses(1) { } - - bool operator==(const blendcombo &c) const - { + bool operator==(const blendcombo &c) const { loopk(4) if(bones[k] != c.bones[k]) return false; loopk(4) if(weights[k] != c.weights[k]) return false; return true; } - - int size() const - { + int size() const { int i = 1; while(i < 4 && weights[i]) i++; return i; } - - static bool sortcmp(const blendcombo &x, const blendcombo &y) - { - loopi(4) - { - if(x.weights[i]) - { + static bool sortcmp(const blendcombo &x, const blendcombo &y) { + loopi(4) { + if(x.weights[i]) { if(!y.weights[i]) return true; } else if(y.weights[i]) return false; @@ -56,14 +43,10 @@ struct skelmodel : animmodel } return false; } - - int addweight(int sorted, float weight, int bone) - { + int addweight(int sorted, float weight, int bone) { if(weight <= 1e-3f) return sorted; - loopk(sorted) if(weight > weights[k]) - { - for(int l = min(sorted-1, 2); l >= k; l--) - { + loopk(sorted) if(weight > weights[k]) { + for(int l = min(sorted-1, 2); l >= k; l--) { weights[l+1] = weights[l]; bones[l+1] = bones[l]; } @@ -76,9 +59,7 @@ struct skelmodel : animmodel bones[sorted] = bone; return sorted+1; } - - void finalize(int sorted) - { + void finalize(int sorted) { loopj(4-sorted) { weights[sorted+j] = 0; bones[sorted+j] = 0; } if(sorted <= 0) return; float total = 0; @@ -86,26 +67,20 @@ struct skelmodel : animmodel total = 1.0f/total; loopj(sorted) weights[j] *= total; } - - void serialize(vvertw &v) - { - if(interpindex >= 0) - { + void serialize(vvertw &v) { + if(interpindex >= 0) { v.weights[0] = 255; loopk(3) v.weights[k+1] = 0; v.bones[0] = 2*interpindex; loopk(3) v.bones[k+1] = v.bones[0]; } - else - { + else { int total = 0; loopk(4) total += (v.weights[k] = uchar(0.5f + weights[k]*255)); - while(total > 255) - { + while(total > 255) { loopk(4) if(v.weights[k] > 0 && total > 255) { v.weights[k]--; total--; } } - while(total < 255) - { + while(total < 255) { loopk(4) if(v.weights[k] < 255 && total < 255) { v.weights[k]++; total++; } } loopk(4) v.bones[k] = 2*interpbones[k]; @@ -113,118 +88,79 @@ struct skelmodel : animmodel } }; - - struct animcacheentry - { + struct animcacheentry { animstate as[MAXANIMPARTS]; float pitch; int millis; uchar *partmask; ragdolldata *ragdoll; - - animcacheentry() : ragdoll(NULL) - { + animcacheentry() : ragdoll(NULL) { loopk(MAXANIMPARTS) as[k].cur.fr1 = as[k].prev.fr1 = -1; } - - bool operator==(const animcacheentry &c) const - { + bool operator==(const animcacheentry &c) const { loopi(MAXANIMPARTS) if(as[i]!=c.as[i]) return false; return pitch==c.pitch && partmask==c.partmask && ragdoll==c.ragdoll && (!ragdoll || min(millis, c.millis) >= ragdoll->lastmove); } }; - - struct vbocacheentry : animcacheentry - { + struct vbocacheentry : animcacheentry { GLuint vbuf; int owner; - vbocacheentry() : vbuf(0), owner(-1) {} }; - - struct skelcacheentry : animcacheentry - { + struct skelcacheentry : animcacheentry { dualquat *bdata; int version; bool dirty; - skelcacheentry() : bdata(NULL), version(-1), dirty(false) {} - - void nextversion() - { + void nextversion() { version = Shader::uniformlocversion(); dirty = true; } }; - - struct blendcacheentry : skelcacheentry - { + struct blendcacheentry : skelcacheentry { int owner; - blendcacheentry() : owner(-1) {} }; - struct skelmeshgroup; - - struct skelmesh : mesh - { + struct skelmesh : mesh { vert *verts; bumpvert *bumpverts; tri *tris; int numverts, numtris, maxweights; - int voffset, eoffset, elen; ushort minvert, maxvert; - - skelmesh() : verts(NULL), bumpverts(NULL), tris(NULL), numverts(0), numtris(0), maxweights(0) - { + skelmesh() : verts(NULL), bumpverts(NULL), tris(NULL), numverts(0), numtris(0), maxweights(0) { } - - virtual ~skelmesh() - { + virtual ~skelmesh() { DELETEA(verts); DELETEA(bumpverts); DELETEA(tris); } - - int addblendcombo(const blendcombo &c) - { + int addblendcombo(const blendcombo &c) { maxweights = max(maxweights, c.size()); return ((skelmeshgroup *)group)->addblendcombo(c); } - - void smoothnorms(float limit = 0, bool areaweight = true) - { + void smoothnorms(float limit = 0, bool areaweight = true) { mesh::smoothnorms(verts, numverts, tris, numtris, limit, areaweight); } - - void buildnorms(bool areaweight = true) - { + void buildnorms(bool areaweight = true) { mesh::buildnorms(verts, numverts, tris, numtris, areaweight); } - - void calctangents(bool areaweight = true) - { + void calctangents(bool areaweight = true) { if(bumpverts) return; bumpverts = new bumpvert[numverts]; mesh::calctangents(bumpverts, verts, verts, numverts, tris, numtris, areaweight); } - - void calcbb(vec &bbmin, vec &bbmax, const matrix4x3 &m) - { - loopj(numverts) - { + void calcbb(vec &bbmin, vec &bbmax, const matrix4x3 &m) { + loopj(numverts) { vec v = m.transform(verts[j].pos); - loopi(3) - { + loopi(3) { bbmin[i] = min(bbmin[i], v[i]); bbmax[i] = max(bbmax[i], v[i]); } } } - - void genBIH(BIH::mesh &m) - { + void genBIH(BIH::mesh &m) { m.tris = (const BIH::tri *)tris; m.numtris = numtris; m.pos = (const uchar *)&verts->pos; @@ -232,44 +168,33 @@ struct skelmodel : animmodel m.tc = (const uchar *)&verts->tc; m.tcstride = sizeof(vert); } - - static inline void assignvert(vvertn &vv, int j, vert &v, blendcombo &c) - { + static inline void assignvert(vvertn &vv, int j, vert &v, blendcombo &c) { vv.pos = v.pos; vv.norm = v.norm; vv.tc = v.tc; } - - inline void assignvert(vvertbump &vv, int j, vert &v, blendcombo &c) - { + inline void assignvert(vvertbump &vv, int j, vert &v, blendcombo &c) { vv.pos = v.pos; vv.tc = v.tc; vv.tangent = bumpverts[j].tangent; } - - static inline void assignvert(vvertnw &vv, int j, vert &v, blendcombo &c) - { + static inline void assignvert(vvertnw &vv, int j, vert &v, blendcombo &c) { vv.pos = v.pos; vv.norm = v.norm; vv.tc = v.tc; c.serialize(vv); } - - inline void assignvert(vvertbumpw &vv, int j, vert &v, blendcombo &c) - { + inline void assignvert(vvertbumpw &vv, int j, vert &v, blendcombo &c) { vv.pos = v.pos; vv.tc = v.tc; vv.tangent = bumpverts[j].tangent; c.serialize(vv); } - template<class T> - int genvbo(vector<ushort> &idxs, int offset, vector<T> &vverts) - { + int genvbo(vector<ushort> &idxs, int offset, vector<T> &vverts) { voffset = offset; eoffset = idxs.length(); - loopi(numverts) - { + loopi(numverts) { vert &v = verts[i]; assignvert(vverts.add(), i, v, ((skelmeshgroup *)group)->blendcombos[v.blend]); } @@ -279,25 +204,20 @@ struct skelmodel : animmodel maxvert = voffset + numverts-1; return numverts; } - template<class T> - int genvbo(vector<ushort> &idxs, int offset, vector<T> &vverts, int *htdata, int htlen) - { + int genvbo(vector<ushort> &idxs, int offset, vector<T> &vverts, int *htdata, int htlen) { voffset = offset; eoffset = idxs.length(); minvert = 0xFFFF; - loopi(numtris) - { + loopi(numtris) { tri &t = tris[i]; - loopj(3) - { + loopj(3) { int index = t.vert[j]; vert &v = verts[index]; T vv; assignvert(vv, index, v, ((skelmeshgroup *)group)->blendcombos[v.blend]); int htidx = hthash(v.pos)&(htlen-1); - loopk(htlen) - { + loopk(htlen) { int &vidx = htdata[(htidx+k)&(htlen-1)]; if(vidx < 0) { vidx = idxs.add(ushort(vverts.length())); vverts.add(vv); break; } else if(!memcmp(&vverts[vidx], &vv, sizeof(vv))) { minvert = min(minvert, idxs.add(ushort(vidx))); break; } @@ -309,15 +229,11 @@ struct skelmodel : animmodel maxvert = max(minvert, ushort(vverts.length()-1)); return vverts.length()-voffset; } - - int genvbo(vector<ushort> &idxs, int offset) - { + int genvbo(vector<ushort> &idxs, int offset) { loopi(numverts) verts[i].interpindex = ((skelmeshgroup *)group)->remapblend(verts[i].blend); - voffset = offset; eoffset = idxs.length(); - loopi(numtris) - { + loopi(numtris) { tri &t = tris[i]; loopj(3) idxs.add(voffset+t.vert[j]); } @@ -326,28 +242,21 @@ struct skelmodel : animmodel elen = idxs.length()-eoffset; return numverts; } - template<class T> - static inline void fillvert(T &vv, int j, vert &v) - { + static inline void fillvert(T &vv, int j, vert &v) { vv.tc = v.tc; } - template<class T> - void fillverts(T *vdata) - { + void fillverts(T *vdata) { vdata += voffset; loopi(numverts) fillvert(vdata[i], i, verts[i]); } - - void interpverts(const dualquat * RESTRICT bdata1, const dualquat * RESTRICT bdata2, bool tangents, void * RESTRICT vdata, skin &s) - { + void interpverts(const dualquat * RESTRICT bdata1, const dualquat * RESTRICT bdata2, bool tangents, void * RESTRICT vdata, skin &s) { const int blendoffset = ((skelmeshgroup *)group)->skel->numgpubones; bdata2 -= blendoffset; - #define IPLOOP(type, dosetup, dotransform) \ - loopi(numverts) \ - { \ + loopi(numverts) { \ + \ const vert &src = verts[i]; \ type &dst = ((type * RESTRICT)vdata)[i]; \ dosetup; \ @@ -355,36 +264,26 @@ struct skelmodel : animmodel dst.pos = b.transform(src.pos); \ dotransform; \ } - - if(tangents) - { - IPLOOP(vvertbump, bumpvert &bsrc = bumpverts[i], - { + if(tangents) { + IPLOOP(vvertbump, bumpvert &bsrc = bumpverts[i], { quat q = b.transform(bsrc.tangent); fixqtangent(q, bsrc.tangent.w); dst.tangent = q; }); } - else - { - IPLOOP(vvertn, , - { + else { + IPLOOP(vvertn, , { dst.norm = b.transformnormal(src.norm); }); } - #undef IPLOOP } - - void setshader(Shader *s) - { + void setshader(Shader *s) { skelmeshgroup *g = (skelmeshgroup *)group; if(!g->skel->usegpuskel) s->set(); else s->setvariant(min(maxweights, g->vweights)-1, 0); } - - void render(const animstate *as, skin &s, vbocacheentry &vc) - { + void render(const animstate *as, skin &s, vbocacheentry &vc) { if(!Shader::lastshader) return; glDrawRangeElements_(GL_TRIANGLES, minvert, maxvert, elen, GL_UNSIGNED_SHORT, &((skelmeshgroup *)group)->edata[eoffset]); glde++; @@ -392,73 +291,50 @@ struct skelmodel : animmodel } }; - - struct tag - { + struct tag { char *name; int bone; matrix4x3 matrix; - tag() : name(NULL) {} ~tag() { DELETEA(name); } }; - - struct skelanimspec - { + struct skelanimspec { char *name; int frame, range; - skelanimspec() : name(NULL), frame(0), range(0) {} - ~skelanimspec() - { + ~skelanimspec() { DELETEA(name); } }; - - struct boneinfo - { + struct boneinfo { const char *name; int parent, children, next, group, scheduled, interpindex, interpparent, ragdollindex, correctindex; float pitchscale, pitchoffset, pitchmin, pitchmax; dualquat base, invbase; - boneinfo() : name(NULL), parent(-1), children(-1), next(-1), group(INT_MAX), scheduled(-1), interpindex(-1), interpparent(-1), ragdollindex(-1), correctindex(-1), pitchscale(0), pitchoffset(0), pitchmin(0), pitchmax(0) {} - ~boneinfo() - { + ~boneinfo() { DELETEA(name); } }; - - struct antipode - { + struct antipode { int parent, child; - antipode(int parent, int child) : parent(parent), child(child) {} }; - - struct pitchdep - { + struct pitchdep { int bone, parent; dualquat pose; }; - - struct pitchtarget - { + struct pitchtarget { int bone, frame, corrects, deps; float pitchmin, pitchmax, deviated; dualquat pose; }; - - struct pitchcorrect - { + struct pitchcorrect { int bone, target, parent; float pitchmin, pitchmax, pitchscale, pitchangle, pitchtotal; - pitchcorrect() : parent(-1), pitchangle(0), pitchtotal(0) {} }; - - struct skeleton - { + struct skeleton { char *name; int shared; vector<skelmeshgroup *> users; @@ -472,36 +348,25 @@ struct skelmodel : animmodel vector<pitchdep> pitchdeps; vector<pitchtarget> pitchtargets; vector<pitchcorrect> pitchcorrects; - bool usegpuskel; vector<skelcacheentry> skelcache; hashtable<GLuint, int> blendoffsets; - - skeleton() : name(NULL), shared(0), bones(NULL), numbones(0), numinterpbones(0), numgpubones(0), numframes(0), framebones(NULL), ragdoll(NULL), usegpuskel(false), blendoffsets(32) - { + skeleton() : name(NULL), shared(0), bones(NULL), numbones(0), numinterpbones(0), numgpubones(0), numframes(0), framebones(NULL), ragdoll(NULL), usegpuskel(false), blendoffsets(32) { } - - ~skeleton() - { + ~skeleton() { DELETEA(name); DELETEA(bones); DELETEA(framebones); DELETEP(ragdoll); - loopv(skelcache) - { + loopv(skelcache) { DELETEA(skelcache[i].bdata); } } - - skelanimspec *findskelanim(const char *name, char sep = '\0') - { + skelanimspec *findskelanim(const char *name, char sep = '\0') { int len = sep ? strlen(name) : 0; - loopv(skelanims) - { - if(skelanims[i].name) - { - if(sep) - { + loopv(skelanims) { + if(skelanims[i].name) { + if(sep) { const char *end = strchr(skelanims[i].name, ':'); if(end && end - skelanims[i].name == len && !memcmp(name, skelanims[i].name, len)) return &skelanims[i]; } @@ -510,38 +375,28 @@ struct skelmodel : animmodel } return NULL; } - - skelanimspec &addskelanim(const char *name) - { + skelanimspec &addskelanim(const char *name) { skelanimspec &sa = skelanims.add(); sa.name = name ? newstring(name) : NULL; return sa; } - - int findbone(const char *name) - { + int findbone(const char *name) { loopi(numbones) if(bones[i].name && !strcmp(bones[i].name, name)) return i; return -1; } - - int findtag(const char *name) - { + int findtag(const char *name) { loopv(tags) if(!strcmp(tags[i].name, name)) return i; return -1; } - - bool addtag(const char *name, int bone, const matrix4x3 &matrix) - { + bool addtag(const char *name, int bone, const matrix4x3 &matrix) { int idx = findtag(name); - if(idx >= 0) - { + if(idx >= 0) { if(!testtags) return false; tag &t = tags[idx]; t.bone = bone; t.matrix = matrix; } - else - { + else { tag &t = tags.add(); t.name = newstring(name); t.bone = bone; @@ -549,67 +404,52 @@ struct skelmodel : animmodel } return true; } - - void calcantipodes() - { + void calcantipodes() { antipodes.shrink(0); vector<int> schedule; - loopi(numbones) - { - if(bones[i].group >= numbones) - { + loopi(numbones) { + if(bones[i].group >= numbones) { bones[i].scheduled = schedule.length(); schedule.add(i); } else bones[i].scheduled = -1; } - loopv(schedule) - { + loopv(schedule) { int bone = schedule[i]; const boneinfo &info = bones[bone]; - loopj(numbones) if(abs(bones[j].group) == bone && bones[j].scheduled < 0) - { + loopj(numbones) if(abs(bones[j].group) == bone && bones[j].scheduled < 0) { antipodes.add(antipode(info.interpindex, bones[j].interpindex)); bones[j].scheduled = schedule.length(); schedule.add(j); } - if(i + 1 == schedule.length()) - { + if(i + 1 == schedule.length()) { int conflict = INT_MAX; loopj(numbones) if(bones[j].group < numbones && bones[j].scheduled < 0) conflict = min(conflict, abs(bones[j].group)); - if(conflict < numbones) - { + if(conflict < numbones) { bones[conflict].scheduled = schedule.length(); schedule.add(conflict); } } } } - - void remapbones() - { - loopi(numbones) - { + void remapbones() { + loopi(numbones) { boneinfo &info = bones[i]; info.interpindex = -1; info.ragdollindex = -1; } numgpubones = 0; - loopv(users) - { + loopv(users) { skelmeshgroup *group = users[i]; - loopvj(group->blendcombos) - { + loopvj(group->blendcombos) { blendcombo &c = group->blendcombos[j]; - loopk(4) - { + loopk(4) { if(!c.weights[k]) { c.interpbones[k] = k > 0 ? c.interpbones[k-1] : 0; continue; } boneinfo &info = bones[c.bones[k]]; if(info.interpindex < 0) info.interpindex = numgpubones++; c.interpbones[k] = info.interpindex; if(info.group < 0) continue; - loopl(4) - { + loopl(4) { if(!c.weights[l]) break; if(l == k) continue; int parent = c.bones[l]; @@ -623,41 +463,33 @@ struct skelmodel : animmodel } } numinterpbones = numgpubones; - loopv(tags) - { + loopv(tags) { boneinfo &info = bones[tags[i].bone]; if(info.interpindex < 0) info.interpindex = numinterpbones++; } - if(ragdoll) - { - loopv(ragdoll->joints) - { + if(ragdoll) { + loopv(ragdoll->joints) { boneinfo &info = bones[ragdoll->joints[i].bone]; if(info.interpindex < 0) info.interpindex = numinterpbones++; info.ragdollindex = i; } } - loopi(numbones) - { + loopi(numbones) { boneinfo &info = bones[i]; if(info.interpindex < 0) continue; for(int parent = info.parent; parent >= 0 && bones[parent].interpindex < 0; parent = bones[parent].parent) bones[parent].interpindex = numinterpbones++; } - loopi(numbones) - { + loopi(numbones) { boneinfo &info = bones[i]; if(info.interpindex < 0) continue; info.interpparent = info.parent >= 0 ? bones[info.parent].interpindex : -1; } - if(ragdoll) - { - loopi(numbones) - { + if(ragdoll) { + loopi(numbones) { boneinfo &info = bones[i]; if(info.interpindex < 0 || info.ragdollindex >= 0) continue; - for(int parent = info.parent; parent >= 0; parent = bones[parent].parent) - { + for(int parent = info.parent; parent >= 0; parent = bones[parent].parent) { if(bones[parent].ragdollindex >= 0) { ragdoll->addreljoint(i, bones[parent].ragdollindex); break; } } } @@ -665,19 +497,14 @@ struct skelmodel : animmodel calcantipodes(); } - - void addpitchdep(int bone, int frame) - { - for(; bone >= 0; bone = bones[bone].parent) - { + void addpitchdep(int bone, int frame) { + for(; bone >= 0; bone = bones[bone].parent) { int pos = pitchdeps.length(); - loopvj(pitchdeps) if(bone <= pitchdeps[j].bone) - { + loopvj(pitchdeps) if(bone <= pitchdeps[j].bone) { if(bone == pitchdeps[j].bone) goto nextbone; pos = j; break; - } - { + } { pitchdep d; d.bone = bone; d.parent = -1; @@ -687,66 +514,51 @@ struct skelmodel : animmodel nextbone:; } } - - int findpitchdep(int bone) - { + int findpitchdep(int bone) { loopv(pitchdeps) if(bone <= pitchdeps[i].bone) return bone == pitchdeps[i].bone ? i : -1; return -1; } - - int findpitchcorrect(int bone) - { + int findpitchcorrect(int bone) { loopv(pitchcorrects) if(bone <= pitchcorrects[i].bone) return bone == pitchcorrects[i].bone ? i : -1; return -1; } - - void initpitchdeps() - { + void initpitchdeps() { pitchdeps.setsize(0); if(pitchtargets.empty()) return; - loopv(pitchtargets) - { + loopv(pitchtargets) { pitchtarget &t = pitchtargets[i]; t.deps = -1; addpitchdep(t.bone, t.frame); } - loopv(pitchdeps) - { + loopv(pitchdeps) { pitchdep &d = pitchdeps[i]; int parent = bones[d.bone].parent; - if(parent >= 0) - { + if(parent >= 0) { int j = findpitchdep(parent); - if(j >= 0) - { + if(j >= 0) { d.parent = j; d.pose.mul(pitchdeps[j].pose, dualquat(d.pose)); } } } - loopv(pitchtargets) - { + loopv(pitchtargets) { pitchtarget &t = pitchtargets[i]; int j = findpitchdep(t.bone); - if(j >= 0) - { + if(j >= 0) { t.deps = j; t.pose = pitchdeps[j].pose; } t.corrects = -1; - for(int parent = t.bone; parent >= 0; parent = bones[parent].parent) - { + for(int parent = t.bone; parent >= 0; parent = bones[parent].parent) { t.corrects = findpitchcorrect(parent); if(t.corrects >= 0) break; } } - loopv(pitchcorrects) - { + loopv(pitchcorrects) { pitchcorrect &c = pitchcorrects[i]; bones[c.bone].correctindex = i; c.parent = -1; - for(int parent = c.bone;;) - { + for(int parent = c.bone;;) { parent = bones[parent].parent; if(parent < 0) break; c.parent = findpitchcorrect(parent); @@ -754,56 +566,42 @@ struct skelmodel : animmodel } } } - - void optimize() - { + void optimize() { cleanup(); if(ragdoll) ragdoll->setup(); remapbones(); initpitchdeps(); } - - void expandbonemask(uchar *expansion, int bone, int val) - { + void expandbonemask(uchar *expansion, int bone, int val) { expansion[bone] = val; bone = bones[bone].children; while(bone>=0) { expandbonemask(expansion, bone, val); bone = bones[bone].next; } } - - void applybonemask(ushort *mask, uchar *partmask, int partindex) - { + void applybonemask(ushort *mask, uchar *partmask, int partindex) { if(!mask || *mask==BONEMASK_END) return; uchar *expansion = new uchar[numbones]; memset(expansion, *mask&BONEMASK_NOT ? 1 : 0, numbones); - while(*mask!=BONEMASK_END) - { + while(*mask!=BONEMASK_END) { expandbonemask(expansion, *mask&BONEMASK_BONE, *mask&BONEMASK_NOT ? 0 : 1); mask++; } loopi(numbones) if(expansion[i]) partmask[i] = partindex; delete[] expansion; } - - void linkchildren() - { - loopi(numbones) - { + void linkchildren() { + loopi(numbones) { boneinfo &b = bones[i]; b.children = -1; if(b.parent<0) b.next = -1; - else - { + else { b.next = bones[b.parent].children; bones[b.parent].children = i; } } } - int availgpubones() const { return min(maxvsuniforms - reservevpparams - 10, maxskelanimdata) / 2; } bool gpuaccelerate() const { return numframes && gpuskel && numgpubones<=availgpubones(); } - - float calcdeviation(const vec &axis, const vec &forward, const dualquat &pose1, const dualquat &pose2) - { + float calcdeviation(const vec &axis, const vec &forward, const dualquat &pose1, const dualquat &pose2) { vec forward1 = pose1.transformnormal(forward).project(axis).normalize(), forward2 = pose2.transformnormal(forward).project(axis).normalize(), daxis = vec().cross(forward1, forward2); @@ -811,35 +609,28 @@ struct skelmodel : animmodel if(daxis.dot(axis) < 0) dy = -dy; return atan2f(dy, dx)/RAD; } - - void calcpitchcorrects(float pitch, const vec &axis, const vec &forward) - { - loopv(pitchtargets) - { + void calcpitchcorrects(float pitch, const vec &axis, const vec &forward) { + loopv(pitchtargets) { pitchtarget &t = pitchtargets[i]; t.deviated = calcdeviation(axis, forward, t.pose, pitchdeps[t.deps].pose); } - loopv(pitchcorrects) - { + loopv(pitchcorrects) { pitchcorrect &c = pitchcorrects[i]; c.pitchangle = c.pitchtotal = 0; } - loopvj(pitchtargets) - { + loopvj(pitchtargets) { pitchtarget &t = pitchtargets[j]; float tpitch = pitch - t.deviated; for(int parent = t.corrects; parent >= 0; parent = pitchcorrects[parent].parent) tpitch -= pitchcorrects[parent].pitchangle; if(t.pitchmin || t.pitchmax) tpitch = clamp(tpitch, t.pitchmin, t.pitchmax); - loopv(pitchcorrects) - { + loopv(pitchcorrects) { pitchcorrect &c = pitchcorrects[i]; if(c.target != j) continue; float total = c.parent >= 0 ? pitchcorrects[c.parent].pitchtotal : 0, avail = tpitch - total, used = tpitch*c.pitchscale; - if(c.pitchmin || c.pitchmax) - { + if(c.pitchmin || c.pitchmax) { if(used < 0) used = clamp(c.pitchmin, used, 0.0f); else used = clamp(c.pitchmax, 0.0f, used); } @@ -850,39 +641,32 @@ struct skelmodel : animmodel } } } - #define INTERPBONE(bone) \ const animstate &s = as[partmask[bone]]; \ const framedata &f = partframes[partmask[bone]]; \ dualquat d; \ (d = f.fr1[bone]).mul((1-s.cur.t)*s.interp); \ d.accumulate(f.fr2[bone], s.cur.t*s.interp); \ - if(s.interp<1) \ - { \ + if(s.interp<1) { \ + \ d.accumulate(f.pfr1[bone], (1-s.prev.t)*(1-s.interp)); \ d.accumulate(f.pfr2[bone], s.prev.t*(1-s.interp)); \ } - - void interpbones(const animstate *as, float pitch, const vec &axis, const vec &forward, int numanimparts, const uchar *partmask, skelcacheentry &sc) - { + void interpbones(const animstate *as, float pitch, const vec &axis, const vec &forward, int numanimparts, const uchar *partmask, skelcacheentry &sc) { if(!sc.bdata) sc.bdata = new dualquat[numinterpbones]; sc.nextversion(); - struct framedata - { + struct framedata { const dualquat *fr1, *fr2, *pfr1, *pfr2; } partframes[MAXANIMPARTS]; - loopi(numanimparts) - { + loopi(numanimparts) { partframes[i].fr1 = &framebones[as[i].cur.fr1*numbones]; partframes[i].fr2 = &framebones[as[i].cur.fr2*numbones]; - if(as[i].interp<1) - { + if(as[i].interp<1) { partframes[i].pfr1 = &framebones[as[i].prev.fr1*numbones]; partframes[i].pfr2 = &framebones[as[i].prev.fr2*numbones]; } } - loopv(pitchdeps) - { + loopv(pitchdeps) { pitchdep &p = pitchdeps[i]; INTERPBONE(p.bone); d.normalize(); @@ -890,8 +674,7 @@ struct skelmodel : animmodel else p.pose = d; } calcpitchcorrects(pitch, axis, forward); - loopi(numbones) if(bones[i].interpindex>=0) - { + loopi(numbones) if(bones[i].interpindex>=0) { INTERPBONE(i); const boneinfo &b = bones[i]; d.normalize(); @@ -907,49 +690,39 @@ struct skelmodel : animmodel } loopv(antipodes) sc.bdata[antipodes[i].child].fixantipodal(sc.bdata[antipodes[i].parent]); } - - void initragdoll(ragdolldata &d, skelcacheentry &sc, part *p) - { + void initragdoll(ragdolldata &d, skelcacheentry &sc, part *p) { const dualquat *bdata = sc.bdata; - loopv(ragdoll->joints) - { + loopv(ragdoll->joints) { const ragdollskel::joint &j = ragdoll->joints[i]; const boneinfo &b = bones[j.bone]; const dualquat &q = bdata[b.interpindex]; - loopk(3) if(j.vert[k] >= 0) - { + loopk(3) if(j.vert[k] >= 0) { ragdollskel::vert &v = ragdoll->verts[j.vert[k]]; ragdolldata::vert &dv = d.verts[j.vert[k]]; dv.pos.add(q.transform(v.pos).mul(v.weight)); } } - if(ragdoll->animjoints) loopv(ragdoll->joints) - { + if(ragdoll->animjoints) loopv(ragdoll->joints) { const ragdollskel::joint &j = ragdoll->joints[i]; const boneinfo &b = bones[j.bone]; const dualquat &q = bdata[b.interpindex]; d.calcanimjoint(i, matrix4x3(q)); } - loopv(ragdoll->verts) - { + loopv(ragdoll->verts) { ragdolldata::vert &dv = d.verts[i]; matrixstack[matrixpos].transform(vec(dv.pos).add(p->translate).mul(p->model->scale), dv.pos); } - loopv(ragdoll->reljoints) - { + loopv(ragdoll->reljoints) { const ragdollskel::reljoint &r = ragdoll->reljoints[i]; const ragdollskel::joint &j = ragdoll->joints[r.parent]; const boneinfo &br = bones[r.bone], &bj = bones[j.bone]; d.reljoints[i].mul(dualquat(bdata[bj.interpindex]).invert(), bdata[br.interpindex]); } } - - void genragdollbones(ragdolldata &d, skelcacheentry &sc, part *p) - { + void genragdollbones(ragdolldata &d, skelcacheentry &sc, part *p) { if(!sc.bdata) sc.bdata = new dualquat[numinterpbones]; sc.nextversion(); - loopv(ragdoll->joints) - { + loopv(ragdoll->joints) { const ragdollskel::joint &j = ragdoll->joints[i]; const boneinfo &b = bones[j.bone]; vec pos(0, 0, 0); @@ -959,8 +732,7 @@ struct skelmodel : animmodel m.mul(d.tris[j.tri], pos, d.animjoints ? d.animjoints[i] : j.orient); sc.bdata[b.interpindex] = dualquat(m); } - loopv(ragdoll->reljoints) - { + loopv(ragdoll->reljoints) { const ragdollskel::reljoint &r = ragdoll->reljoints[i]; const ragdollskel::joint &j = ragdoll->joints[r.parent]; const boneinfo &br = bones[r.bone], &bj = bones[j.bone]; @@ -968,19 +740,14 @@ struct skelmodel : animmodel } loopv(antipodes) sc.bdata[antipodes[i].child].fixantipodal(sc.bdata[antipodes[i].parent]); } - - void concattagtransform(part *p, int i, const matrix4x3 &m, matrix4x3 &n) - { + void concattagtransform(part *p, int i, const matrix4x3 &m, matrix4x3 &n) { matrix4x3 t; t.mul(bones[tags[i].bone].base, tags[i].matrix); t.posttranslate(p->translate, p->model->scale); n.mul(m, t); } - - void calctags(part *p, skelcacheentry *sc = NULL) - { - loopv(p->links) - { + void calctags(part *p, skelcacheentry *sc = NULL) { + loopv(p->links) { linkedpart &l = p->links[i]; tag &t = tags[l.tag]; dualquat q; @@ -992,11 +759,8 @@ struct skelmodel : animmodel l.matrix = m; } } - - void cleanup(bool full = true) - { - loopv(skelcache) - { + void cleanup(bool full = true) { + loopv(skelcache) { skelcacheentry &sc = skelcache[i]; loopj(MAXANIMPARTS) sc.as[j].cur.fr1 = -1; DELETEA(sc.bdata); @@ -1005,31 +769,22 @@ struct skelmodel : animmodel blendoffsets.clear(); if(full) loopv(users) users[i]->cleanup(); } - bool canpreload() { return !numframes || gpuaccelerate(); } - - void preload() - { + void preload() { if(!numframes) return; - if(skelcache.empty()) - { + if(skelcache.empty()) { usegpuskel = gpuaccelerate(); } } - - skelcacheentry &checkskelcache(part *p, const animstate *as, float pitch, const vec &axis, const vec &forward, ragdolldata *rdata) - { - if(skelcache.empty()) - { + skelcacheentry &checkskelcache(part *p, const animstate *as, float pitch, const vec &axis, const vec &forward, ragdolldata *rdata) { + if(skelcache.empty()) { usegpuskel = gpuaccelerate(); } - int numanimparts = ((skelpart *)as->owner)->numanimparts; uchar *partmask = ((skelpart *)as->owner)->partmask; skelcacheentry *sc = NULL; bool match = false; - loopv(skelcache) - { + loopv(skelcache) { skelcacheentry &c = skelcache[i]; loopj(numanimparts) if(c.as[j]!=as[j]) goto mismatch; if(c.pitch != pitch || c.partmask != partmask || c.ragdoll != rdata || (rdata && c.millis < rdata->lastmove)) goto mismatch; @@ -1040,8 +795,7 @@ struct skelmodel : animmodel if(c.millis < lastmillis) { sc = &c; break; } } if(!sc) sc = &skelcache.add(); - if(!match) - { + if(!match) { loopi(numanimparts) sc->as[i] = as[i]; sc->pitch = pitch; sc->partmask = partmask; @@ -1052,101 +806,73 @@ struct skelmodel : animmodel sc->millis = lastmillis; return *sc; } - - int getblendoffset(UniformLoc &u) - { + int getblendoffset(UniformLoc &u) { int &offset = blendoffsets.access(Shader::lastshader->program, -1); - if(offset < 0) - { + if(offset < 0) { defformatstring(offsetname, "%s[%d]", u.name, 2*numgpubones); offset = glGetUniformLocation_(Shader::lastshader->program, offsetname); } return offset; } - - void setglslbones(UniformLoc &u, skelcacheentry &sc, skelcacheentry &bc, int count) - { + void setglslbones(UniformLoc &u, skelcacheentry &sc, skelcacheentry &bc, int count) { if(u.version == bc.version && u.data == bc.bdata) return; glUniform4fv_(u.loc, 2*numgpubones, sc.bdata[0].real.v); - if(count > 0) - { + if(count > 0) { int offset = getblendoffset(u); if(offset >= 0) glUniform4fv_(offset, 2*count, bc.bdata[0].real.v); } u.version = bc.version; u.data = bc.bdata; } - - void setgpubones(skelcacheentry &sc, blendcacheentry *bc, int count) - { + void setgpubones(skelcacheentry &sc, blendcacheentry *bc, int count) { if(!Shader::lastshader) return; if(Shader::lastshader->uniformlocs.length() < 1) return; UniformLoc &u = Shader::lastshader->uniformlocs[0]; setglslbones(u, sc, bc ? *bc : sc, count); } - - bool shouldcleanup() const - { + bool shouldcleanup() const { return numframes && (skelcache.empty() || gpuaccelerate()!=usegpuskel); } }; - - struct skelmeshgroup : meshgroup - { + struct skelmeshgroup : meshgroup { skeleton *skel; - vector<blendcombo> blendcombos; int numblends[4]; - static const int MAXBLENDCACHE = 16; blendcacheentry blendcache[MAXBLENDCACHE]; - static const int MAXVBOCACHE = 16; vbocacheentry vbocache[MAXVBOCACHE]; - ushort *edata; GLuint ebuf; bool vtangents; int vlen, vertsize, vblends, vweights; uchar *vdata; - - skelmeshgroup() : skel(NULL), edata(NULL), ebuf(0), vtangents(false), vlen(0), vertsize(0), vblends(0), vweights(0), vdata(NULL) - { + skelmeshgroup() : skel(NULL), edata(NULL), ebuf(0), vtangents(false), vlen(0), vertsize(0), vblends(0), vweights(0), vdata(NULL) { memset(numblends, 0, sizeof(numblends)); } - - virtual ~skelmeshgroup() - { - if(skel) - { + virtual ~skelmeshgroup() { + if(skel) { if(skel->shared) skel->users.removeobj(this); else DELETEP(skel); } if(ebuf) glDeleteBuffers_(1, &ebuf); - loopi(MAXBLENDCACHE) - { + loopi(MAXBLENDCACHE) { DELETEA(blendcache[i].bdata); } - loopi(MAXVBOCACHE) - { + loopi(MAXVBOCACHE) { if(vbocache[i].vbuf) glDeleteBuffers_(1, &vbocache[i].vbuf); } DELETEA(vdata); } - - void shareskeleton(char *name) - { - if(!name) - { + void shareskeleton(char *name) { + if(!name) { skel = new skeleton; skel->users.add(this); return; } - static hashnameset<skeleton *> skeletons; if(skeletons.access(name)) skel = skeletons[name]; - else - { + else { skel = new skeleton; skel->name = newstring(name); skeletons.add(skel); @@ -1154,38 +880,26 @@ struct skelmodel : animmodel skel->users.add(this); skel->shared++; } - - int findtag(const char *name) - { + int findtag(const char *name) { return skel->findtag(name); } - void *animkey() { return skel; } int totalframes() const { return max(skel->numframes, 1); } - virtual skelanimspec *loadanim(const char *filename) { (void) filename; return NULL; } - - void genvbo(bool tangents, vbocacheentry &vc) - { + void genvbo(bool tangents, vbocacheentry &vc) { if(!vc.vbuf) glGenBuffers_(1, &vc.vbuf); if(ebuf) return; - vector<ushort> idxs; - if(tangents) loopv(meshes) ((skelmesh *)meshes[i])->calctangents(); - vtangents = tangents; vlen = 0; vblends = 0; - if(skel->numframes && !skel->usegpuskel) - { + if(skel->numframes && !skel->usegpuskel) { vweights = 1; - loopv(blendcombos) - { + loopv(blendcombos) { blendcombo &c = blendcombos[i]; c.interpindex = c.weights[1] ? skel->numgpubones + vblends++ : -1; } - vertsize = tangents ? sizeof(vvertbump) : sizeof(vvertn); loopv(meshes) vlen += ((skelmesh *)meshes[i])->genvbo(idxs, vlen); DELETEA(vdata); @@ -1197,25 +911,20 @@ struct skelmodel : animmodel else FILLVDATA(vvertn); #undef FILLVDATA } - else - { - if(skel->numframes) - { + else { + if(skel->numframes) { vweights = 4; int availbones = skel->availgpubones() - skel->numgpubones; while(vweights > 1 && availbones >= numblends[vweights-1]) availbones -= numblends[--vweights]; - loopv(blendcombos) - { + loopv(blendcombos) { blendcombo &c = blendcombos[i]; c.interpindex = c.size() > vweights ? skel->numgpubones + vblends++ : -1; } } - else - { + else { vweights = 0; loopv(blendcombos) blendcombos[i].interpindex = -1; } - gle::bindvbo(vc.vbuf); #define GENVBO(type, args) do { \ vertsize = sizeof(type); \ @@ -1225,13 +934,11 @@ struct skelmodel : animmodel } while(0) #define GENVBOANIM(type) GENVBO(type, (idxs, vlen, vverts)) #define GENVBOSTAT(type) GENVBO(type, (idxs, vlen, vverts, htdata, htlen)) - if(skel->numframes) - { + if(skel->numframes) { if(tangents) GENVBOANIM(vvertbumpw); else GENVBOANIM(vvertnw); } - else - { + else { int numverts = 0, htlen = 128; loopv(meshes) numverts += ((skelmesh *)meshes[i])->numverts; while(htlen < numverts) htlen *= 2; @@ -1247,68 +954,51 @@ struct skelmodel : animmodel #undef GENVBOSTAT gle::clearvbo(); } - glGenBuffers_(1, &ebuf); gle::bindebo(ebuf); glBufferData_(GL_ELEMENT_ARRAY_BUFFER, idxs.length()*sizeof(ushort), idxs.getbuf(), GL_STATIC_DRAW); gle::clearebo(); } - - void bindvbo(const animstate *as, vbocacheentry &vc, skelcacheentry *sc = NULL, blendcacheentry *bc = NULL) - { + void bindvbo(const animstate *as, vbocacheentry &vc, skelcacheentry *sc = NULL, blendcacheentry *bc = NULL) { vvert *vverts = 0; bindpos(ebuf, vc.vbuf, &vverts->pos, vertsize); - if(as->cur.anim&ANIM_NOSKIN) - { + if(as->cur.anim&ANIM_NOSKIN) { if(enabletc) disabletc(); if(enablenormals) disablenormals(); if(enabletangents) disabletangents(); } - else - { - if(vtangents) - { + else { + if(vtangents) { if(enablenormals) disablenormals(); vvertbump *vvertbumps = 0; bindtangents(&vvertbumps->tangent, vertsize); } - else - { + else { if(enabletangents) disabletangents(); vvertn *vvertns = 0; bindnormals(&vvertns->norm, vertsize); } - bindtc(&vverts->tc, vertsize); } - if(!sc || !skel->usegpuskel) - { + if(!sc || !skel->usegpuskel) { if(enablebones) disablebones(); } - else - { - if(vtangents) - { + else { + if(vtangents) { vvertbumpw *vvertbumpws = 0; bindbones(vvertbumpws->weights, vvertbumpws->bones, vertsize); } - else - { + else { vvertnw *vvertnws = 0; bindbones(vvertnws->weights, vvertnws->bones, vertsize); } } } - - void concattagtransform(part *p, int i, const matrix4x3 &m, matrix4x3 &n) - { + void concattagtransform(part *p, int i, const matrix4x3 &m, matrix4x3 &n) { skel->concattagtransform(p, i, m, n); } - - int addblendcombo(const blendcombo &c) - { - loopv(blendcombos) if(blendcombos[i]==c) - { + int addblendcombo(const blendcombo &c) { + loopv(blendcombos) if(blendcombos[i]==c) { blendcombos[i].uses += c.uses; return i; } @@ -1316,50 +1006,38 @@ struct skelmodel : animmodel blendcombo &a = blendcombos.add(c); return a.interpindex = blendcombos.length()-1; } - - void sortblendcombos() - { + void sortblendcombos() { blendcombos.sort(blendcombo::sortcmp); int *remap = new int[blendcombos.length()]; loopv(blendcombos) remap[blendcombos[i].interpindex] = i; - loopv(meshes) - { + loopv(meshes) { skelmesh *m = (skelmesh *)meshes[i]; - loopj(m->numverts) - { + loopj(m->numverts) { vert &v = m->verts[j]; v.blend = remap[v.blend]; } } delete[] remap; } - - int remapblend(int blend) - { + int remapblend(int blend) { const blendcombo &c = blendcombos[blend]; return c.weights[1] ? c.interpindex : c.interpbones[0]; } - - static inline void blendbones(dualquat &d, const dualquat *bdata, const blendcombo &c) - { + static inline void blendbones(dualquat &d, const dualquat *bdata, const blendcombo &c) { d = bdata[c.interpbones[0]]; d.mul(c.weights[0]); d.accumulate(bdata[c.interpbones[1]], c.weights[1]); - if(c.weights[2]) - { + if(c.weights[2]) { d.accumulate(bdata[c.interpbones[2]], c.weights[2]); if(c.weights[3]) d.accumulate(bdata[c.interpbones[3]], c.weights[3]); } } - - void blendbones(const skelcacheentry &sc, blendcacheentry &bc) - { + void blendbones(const skelcacheentry &sc, blendcacheentry &bc) { bc.nextversion(); if(!bc.bdata) bc.bdata = new dualquat[vblends]; dualquat *dst = bc.bdata - skel->numgpubones; bool normalize = !skel->usegpuskel || vweights<=1; - loopv(blendcombos) - { + loopv(blendcombos) { const blendcombo &c = blendcombos[i]; if(c.interpindex<0) break; dualquat &d = dst[c.interpindex]; @@ -1367,17 +1045,13 @@ struct skelmodel : animmodel if(normalize) d.normalize(); } } - - void cleanup() - { - loopi(MAXBLENDCACHE) - { + void cleanup() { + loopi(MAXBLENDCACHE) { blendcacheentry &c = blendcache[i]; DELETEA(c.bdata); c.owner = -1; } - loopi(MAXVBOCACHE) - { + loopi(MAXVBOCACHE) { vbocacheentry &c = vbocache[i]; if(c.vbuf) { glDeleteBuffers_(1, &c.vbuf); c.vbuf = 0; } c.owner = -1; @@ -1385,38 +1059,31 @@ struct skelmodel : animmodel if(ebuf) { glDeleteBuffers_(1, &ebuf); ebuf = 0; } if(skel) skel->cleanup(false); } - #define SEARCHCACHE(cachesize, cacheentry, cache, reusecheck) \ - loopi(cachesize) \ - { \ + loopi(cachesize) { \ + \ cacheentry &c = cache[i]; \ - if(c.owner==owner) \ - { \ + if(c.owner==owner) { \ + \ if(c==sc) return c; \ else c.owner = -1; \ break; \ } \ } \ - loopi(cachesize-1) \ - { \ + loopi(cachesize-1) { \ + \ cacheentry &c = cache[i]; \ if(reusecheck c.owner < 0 || c.millis < lastmillis) \ return c; \ } \ return cache[cachesize-1]; - - vbocacheentry &checkvbocache(skelcacheentry &sc, int owner) - { + vbocacheentry &checkvbocache(skelcacheentry &sc, int owner) { SEARCHCACHE(MAXVBOCACHE, vbocacheentry, vbocache, !c.vbuf || ); } - - blendcacheentry &checkblendcache(skelcacheentry &sc, int owner) - { + blendcacheentry &checkblendcache(skelcacheentry &sc, int owner) { SEARCHCACHE(MAXBLENDCACHE, blendcacheentry, blendcache, ) } - - void preload(part *p) - { + void preload(part *p) { if(!skel->canpreload()) return; bool tangents = false; loopv(p->skins) if(p->skins[i].tangents()) tangents = true; @@ -1425,22 +1092,16 @@ struct skelmodel : animmodel skel->preload(); if(!vbocache->vbuf) genvbo(tangents, *vbocache); } - - void render(const animstate *as, float pitch, const vec &axis, const vec &forward, dynent *d, part *p) - { + void render(const animstate *as, float pitch, const vec &axis, const vec &forward, dynent *d, part *p) { bool tangents = false; loopv(p->skins) if(p->skins[i].tangents()) tangents = true; if(skel->shouldcleanup()) { skel->cleanup(); disablevbo(); } else if(tangents!=vtangents) { cleanup(); disablevbo(); } - - if(!skel->numframes) - { - if(!(as->cur.anim&ANIM_NORENDER)) - { + if(!skel->numframes) { + if(!(as->cur.anim&ANIM_NORENDER)) { if(!vbocache->vbuf) genvbo(tangents, *vbocache); bindvbo(as, *vbocache); - loopv(meshes) - { + loopv(meshes) { skelmesh *m = (skelmesh *)meshes[i]; p->skins[i].bind(m, as); m->render(as, p->skins[i], *vbocache); @@ -1449,153 +1110,110 @@ struct skelmodel : animmodel skel->calctags(p); return; } - skelcacheentry &sc = skel->checkskelcache(p, as, pitch, axis, forward, as->cur.anim&ANIM_RAGDOLL || !d || !d->ragdoll || d->ragdoll->skel != skel->ragdoll ? NULL : d->ragdoll); - if(!(as->cur.anim&ANIM_NORENDER)) - { + if(!(as->cur.anim&ANIM_NORENDER)) { int owner = &sc-&skel->skelcache[0]; vbocacheentry &vc = skel->usegpuskel ? *vbocache : checkvbocache(sc, owner); vc.millis = lastmillis; if(!vc.vbuf) genvbo(tangents, vc); blendcacheentry *bc = NULL; - if(vblends) - { + if(vblends) { bc = &checkblendcache(sc, owner); bc->millis = lastmillis; - if(bc->owner!=owner) - { + if(bc->owner!=owner) { bc->owner = owner; *(animcacheentry *)bc = sc; blendbones(sc, *bc); } } - if(!skel->usegpuskel && vc.owner!=owner) - { + if(!skel->usegpuskel && vc.owner!=owner) { vc.owner = owner; (animcacheentry &)vc = sc; - loopv(meshes) - { + loopv(meshes) { skelmesh &m = *(skelmesh *)meshes[i]; m.interpverts(sc.bdata, bc ? bc->bdata : NULL, tangents, vdata + m.voffset*vertsize, p->skins[i]); } gle::bindvbo(vc.vbuf); glBufferData_(GL_ARRAY_BUFFER, vlen*vertsize, vdata, GL_STREAM_DRAW); } - bindvbo(as, vc, &sc, bc); - loopv(meshes) - { + loopv(meshes) { skelmesh *m = (skelmesh *)meshes[i]; p->skins[i].bind(m, as); if(skel->usegpuskel) skel->setgpubones(sc, bc, vblends); m->render(as, p->skins[i], vc); } } - skel->calctags(p, &sc); - - if(as->cur.anim&ANIM_RAGDOLL && skel->ragdoll && !d->ragdoll) - { + if(as->cur.anim&ANIM_RAGDOLL && skel->ragdoll && !d->ragdoll) { d->ragdoll = new ragdolldata(skel->ragdoll, p->model->scale); skel->initragdoll(*d->ragdoll, sc, p); d->ragdoll->init(d); } } }; - - struct animpartmask - { + struct animpartmask { animpartmask *next; int numbones; uchar bones[1]; }; - - struct skelpart : part - { + struct skelpart : part { animpartmask *buildingpartmask; - uchar *partmask; - - skelpart(animmodel *model, int index = 0) : part(model, index), buildingpartmask(NULL), partmask(NULL) - { + skelpart(animmodel *model, int index = 0) : part(model, index), buildingpartmask(NULL), partmask(NULL) { } - - virtual ~skelpart() - { + virtual ~skelpart() { DELETEA(buildingpartmask); } - - uchar *sharepartmask(animpartmask *o) - { + uchar *sharepartmask(animpartmask *o) { static animpartmask *partmasks = NULL; animpartmask *p = partmasks; - for(; p; p = p->next) if(p->numbones==o->numbones && !memcmp(p->bones, o->bones, p->numbones)) - { + for(; p; p = p->next) if(p->numbones==o->numbones && !memcmp(p->bones, o->bones, p->numbones)) { delete[] (uchar *)o; return p->bones; } - o->next = p; partmasks = o; return o->bones; } - - animpartmask *newpartmask() - { + animpartmask *newpartmask() { animpartmask *p = (animpartmask *)new uchar[sizeof(animpartmask) + ((skelmeshgroup *)meshes)->skel->numbones-1]; p->numbones = ((skelmeshgroup *)meshes)->skel->numbones; memset(p->bones, 0, p->numbones); return p; } - - void initanimparts() - { + void initanimparts() { DELETEA(buildingpartmask); buildingpartmask = newpartmask(); } - - bool addanimpart(ushort *bonemask) - { + bool addanimpart(ushort *bonemask) { if(!buildingpartmask || numanimparts>=MAXANIMPARTS) return false; ((skelmeshgroup *)meshes)->skel->applybonemask(bonemask, buildingpartmask->bones, numanimparts); numanimparts++; return true; } - - void endanimparts() - { - if(buildingpartmask) - { + void endanimparts() { + if(buildingpartmask) { partmask = sharepartmask(buildingpartmask); buildingpartmask = NULL; } - ((skelmeshgroup *)meshes)->skel->optimize(); } - - void loaded() - { + void loaded() { endanimparts(); part::loaded(); } }; - - skelmodel(const char *name) : animmodel(name) - { + skelmodel(const char *name) : animmodel(name) { } - - int linktype(animmodel *m) const - { + int linktype(animmodel *m) const { return type()==m->type() && ((skelmeshgroup *)parts[0]->meshes)->skel == ((skelmeshgroup *)m->parts[0]->meshes)->skel ? LINK_REUSE : LINK_TAG; } - bool skeletal() const { return true; } - - skelpart &addpart() - { + skelpart &addpart() { flushpart(); skelpart *p = new skelpart(this, parts.length()); parts.add(p); @@ -1603,15 +1221,11 @@ struct skelmodel : animmodel } }; -struct skeladjustment -{ +struct skeladjustment { float yaw, pitch, roll; vec translate; - skeladjustment(float yaw, float pitch, float roll, const vec &translate) : yaw(yaw), pitch(pitch), roll(roll), translate(translate) {} - - void adjust(dualquat &dq) - { + void adjust(dualquat &dq) { if(yaw) dq.mulorient(quat(vec(0, 0, 1), yaw*RAD)); if(pitch) dq.mulorient(quat(vec(0, -1, 0), pitch*RAD)); if(roll) dq.mulorient(quat(vec(-1, 0, 0), roll*RAD)); @@ -1619,22 +1233,17 @@ struct skeladjustment } }; -template<class MDL> struct skelloader : modelloader<MDL, skelmodel> -{ +template<class MDL> struct skelloader : modelloader<MDL, skelmodel> { static vector<skeladjustment> adjustments; - skelloader(const char *name) : modelloader<MDL, skelmodel>(name) {} - - void flushpart() - { + void flushpart() { adjustments.setsize(0); } }; template<class MDL> vector<skeladjustment> skelloader<MDL>::adjustments; -template<class MDL> struct skelcommands : modelcommands<MDL, struct MDL::skelmesh> -{ +template<class MDL> struct skelcommands : modelcommands<MDL, struct MDL::skelmesh> { typedef modelcommands<MDL, struct MDL::skelmesh> commands; typedef struct MDL::skeleton skeleton; typedef struct MDL::skelmeshgroup meshgroup; @@ -1645,29 +1254,23 @@ template<class MDL> struct skelcommands : modelcommands<MDL, struct MDL::skelmes typedef struct MDL::pitchdep pitchdep; typedef struct MDL::pitchtarget pitchtarget; typedef struct MDL::pitchcorrect pitchcorrect; - - static void loadpart(char *meshfile, char *skelname, float *smooth) - { + static void loadpart(char *meshfile, char *skelname, float *smooth) { if(!MDL::loading) { conoutf(CON_ERROR, "not loading an %s", MDL::formatname()); return; } defformatstring(filename, "%s/%s", MDL::dir, meshfile); part &mdl = MDL::loading->addpart(); mdl.pitchscale = mdl.pitchoffset = mdl.pitchmin = mdl.pitchmax = 0; mdl.meshes = MDL::loading->sharemeshes(path(filename), skelname[0] ? skelname : NULL, double(*smooth > 0 ? cos(clamp(*smooth, 0.0f, 180.0f)*RAD) : 2)); if(!mdl.meshes) conoutf(CON_ERROR, "could not load %s", filename); - else - { + else { mdl.initanimparts(); mdl.initskins(); } } - - static void settag(char *name, char *tagname, float *tx, float *ty, float *tz, float *rx, float *ry, float *rz) - { + static void settag(char *name, char *tagname, float *tx, float *ty, float *tz, float *rx, float *ry, float *rz) { if(!MDL::loading || MDL::loading->parts.empty()) { conoutf(CON_ERROR, "not loading an %s", MDL::formatname()); return; } part &mdl = *(part *)MDL::loading->parts.last(); int i = mdl.meshes ? ((meshgroup *)mdl.meshes)->skel->findbone(name) : -1; - if(i >= 0) - { + if(i >= 0) { float cx = *rx ? cosf(*rx/2*RAD) : 1, sx = *rx ? sinf(*rx/2*RAD) : 0, cy = *ry ? cosf(*ry/2*RAD) : 1, sy = *ry ? sinf(*ry/2*RAD) : 0, cz = *rz ? cosf(*rz/2*RAD) : 1, sz = *rz ? sinf(*rz/2*RAD) : 0; @@ -1678,27 +1281,20 @@ template<class MDL> struct skelcommands : modelcommands<MDL, struct MDL::skelmes } conoutf(CON_ERROR, "could not find bone %s for tag %s", name, tagname); } - - static void setpitch(char *name, float *pitchscale, float *pitchoffset, float *pitchmin, float *pitchmax) - { + static void setpitch(char *name, float *pitchscale, float *pitchoffset, float *pitchmin, float *pitchmax) { if(!MDL::loading || MDL::loading->parts.empty()) { conoutf(CON_ERROR, "not loading an %s", MDL::formatname()); return; } part &mdl = *(part *)MDL::loading->parts.last(); - - if(name[0]) - { + if(name[0]) { int i = mdl.meshes ? ((meshgroup *)mdl.meshes)->skel->findbone(name) : -1; - if(i>=0) - { + if(i>=0) { boneinfo &b = ((meshgroup *)mdl.meshes)->skel->bones[i]; b.pitchscale = *pitchscale; b.pitchoffset = *pitchoffset; - if(*pitchmin || *pitchmax) - { + if(*pitchmin || *pitchmax) { b.pitchmin = *pitchmin; b.pitchmax = *pitchmax; } - else - { + else { b.pitchmin = -360*fabs(b.pitchscale) + b.pitchoffset; b.pitchmax = 360*fabs(b.pitchscale) + b.pitchoffset; } @@ -1707,23 +1303,18 @@ template<class MDL> struct skelcommands : modelcommands<MDL, struct MDL::skelmes conoutf(CON_ERROR, "could not find bone %s to pitch", name); return; } - mdl.pitchscale = *pitchscale; mdl.pitchoffset = *pitchoffset; - if(*pitchmin || *pitchmax) - { + if(*pitchmin || *pitchmax) { mdl.pitchmin = *pitchmin; mdl.pitchmax = *pitchmax; } - else - { + else { mdl.pitchmin = -360*fabs(mdl.pitchscale) + mdl.pitchoffset; mdl.pitchmax = 360*fabs(mdl.pitchscale) + mdl.pitchoffset; } } - - static void setpitchtarget(char *name, char *animfile, int *frameoffset, float *pitchmin, float *pitchmax) - { + static void setpitchtarget(char *name, char *animfile, int *frameoffset, float *pitchmin, float *pitchmax) { if(!MDL::loading || MDL::loading->parts.empty()) { conoutf(CON_ERROR, "not loading an %s", MDL::formatname()); return; } part &mdl = *(part *)MDL::loading->parts.last(); if(!mdl.meshes) return; @@ -1732,8 +1323,7 @@ template<class MDL> struct skelcommands : modelcommands<MDL, struct MDL::skelmes if(!sa) { conoutf(CON_ERROR, "could not load %s anim file %s", MDL::formatname(), filename); return; } skeleton *skel = ((meshgroup *)mdl.meshes)->skel; int bone = skel ? skel->findbone(name) : -1; - if(bone < 0) - { + if(bone < 0) { conoutf(CON_ERROR, "could not find bone %s to pitch target", name); return; } @@ -1744,24 +1334,20 @@ template<class MDL> struct skelcommands : modelcommands<MDL, struct MDL::skelmes t.pitchmin = *pitchmin; t.pitchmax = *pitchmax; } - - static void setpitchcorrect(char *name, char *targetname, float *scale, float *pitchmin, float *pitchmax) - { + static void setpitchcorrect(char *name, char *targetname, float *scale, float *pitchmin, float *pitchmax) { if(!MDL::loading || MDL::loading->parts.empty()) { conoutf(CON_ERROR, "not loading an %s", MDL::formatname()); return; } part &mdl = *(part *)MDL::loading->parts.last(); if(!mdl.meshes) return; skeleton *skel = ((meshgroup *)mdl.meshes)->skel; int bone = skel ? skel->findbone(name) : -1; - if(bone < 0) - { + if(bone < 0) { conoutf(CON_ERROR, "could not find bone %s to pitch correct", name); return; } if(skel->findpitchcorrect(bone) >= 0) return; int targetbone = skel->findbone(targetname), target = -1; if(targetbone >= 0) loopv(skel->pitchtargets) if(skel->pitchtargets[i].bone == targetbone) { target = i; break; } - if(target < 0) - { + if(target < 0) { conoutf(CON_ERROR, "could not find pitch target %s to pitch correct %s", targetname, name); return; } @@ -1775,23 +1361,18 @@ template<class MDL> struct skelcommands : modelcommands<MDL, struct MDL::skelmes loopv(skel->pitchcorrects) if(bone <= skel->pitchcorrects[i].bone) { pos = i; break; } skel->pitchcorrects.insert(pos, c); } - - static void setanim(char *anim, char *animfile, float *speed, int *priority, int *startoffset, int *endoffset) - { + static void setanim(char *anim, char *animfile, float *speed, int *priority, int *startoffset, int *endoffset) { if(!MDL::loading || MDL::loading->parts.empty()) { conoutf(CON_ERROR, "not loading an %s", MDL::formatname()); return; } - vector<int> anims; findanims(anim, anims); if(anims.empty()) conoutf(CON_ERROR, "could not find animation %s", anim); - else - { + else { part *p = (part *)MDL::loading->parts.last(); if(!p->meshes) return; defformatstring(filename, "%s/%s", MDL::dir, animfile); animspec *sa = ((meshgroup *)p->meshes)->loadanim(path(filename)); if(!sa) conoutf(CON_ERROR, "could not load %s anim file %s", MDL::formatname(), filename); - else loopv(anims) - { + else loopv(anims) { int start = sa->frame, end = sa->range; if(*startoffset > 0) start += min(*startoffset, end-1); else if(*startoffset < 0) start += max(end + *startoffset, 0); @@ -1802,18 +1383,13 @@ template<class MDL> struct skelcommands : modelcommands<MDL, struct MDL::skelmes } } } - - static void setanimpart(char *maskstr) - { + static void setanimpart(char *maskstr) { if(!MDL::loading || MDL::loading->parts.empty()) { conoutf(CON_ERROR, "not loading an %s", MDL::formatname()); return; } - part *p = (part *)MDL::loading->parts.last(); - vector<char *> bonestrs; explodelist(maskstr, bonestrs); vector<ushort> bonemask; - loopv(bonestrs) - { + loopv(bonestrs) { char *bonestr = bonestrs[i]; int bone = p->meshes ? ((meshgroup *)p->meshes)->skel->findbone(bonestr[0]=='!' ? bonestr+1 : bonestr) : -1; if(bone<0) { conoutf(CON_ERROR, "could not find bone %s for anim part mask [%s]", bonestr, maskstr); bonestrs.deletearrays(); return; } @@ -1822,31 +1398,24 @@ template<class MDL> struct skelcommands : modelcommands<MDL, struct MDL::skelmes bonestrs.deletearrays(); bonemask.sort(); if(bonemask.length()) bonemask.add(BONEMASK_END); - if(!p->addanimpart(bonemask.getbuf())) conoutf(CON_ERROR, "too many animation parts"); } - - static void setadjust(char *name, float *yaw, float *pitch, float *roll, float *tx, float *ty, float *tz) - { + static void setadjust(char *name, float *yaw, float *pitch, float *roll, float *tx, float *ty, float *tz) { if(!MDL::loading || MDL::loading->parts.empty()) { conoutf(CON_ERROR, "not loading an %s", MDL::formatname()); return; } part &mdl = *(part *)MDL::loading->parts.last(); - if(!name[0]) return; int i = mdl.meshes ? ((meshgroup *)mdl.meshes)->skel->findbone(name) : -1; if(i < 0) { conoutf(CON_ERROR, "could not find bone %s to adjust", name); return; } while(!MDL::adjustments.inrange(i)) MDL::adjustments.add(skeladjustment(0, 0, 0, vec(0, 0, 0))); MDL::adjustments[i] = skeladjustment(*yaw, *pitch, *roll, vec(*tx/4, *ty/4, *tz/4)); } - - skelcommands() - { + skelcommands() { if(MDL::multiparted()) this->modelcommand(loadpart, "load", "ssf"); this->modelcommand(settag, "tag", "ssffffff"); this->modelcommand(setpitch, "pitch", "sffff"); this->modelcommand(setpitchtarget, "pitchtarget", "ssiff"); this->modelcommand(setpitchcorrect, "pitchcorrect", "ssfff"); - if(MDL::animated()) - { + if(MDL::animated()) { this->modelcommand(setanim, "anim", "ssfiii"); this->modelcommand(setanimpart, "animpart", "s"); this->modelcommand(setadjust, "adjust", "sffffff"); |
