summaryrefslogtreecommitdiff
path: root/src/engine/skelmodel.h
diff options
context:
space:
mode:
authorxolatile2025-08-06 22:54:55 +0200
committerxolatile2025-08-06 22:54:55 +0200
commit0a1172b75f571685c264a8b9d8ee224bbf11381f (patch)
treed041fdc68a60f0ebb48a3852bbcce6d9432f83d5 /src/engine/skelmodel.h
parentaffde05dc07a94643f1fd2751b2b441f57f73d7d (diff)
downloadxolatile-badassbug-0a1172b75f571685c264a8b9d8ee224bbf11381f.tar.xz
xolatile-badassbug-0a1172b75f571685c264a8b9d8ee224bbf11381f.tar.zst
Please do not hate me, it makes sense...
Diffstat (limited to 'src/engine/skelmodel.h')
-rw-r--r--src/engine/skelmodel.h975
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");