diff options
| author | xolatile | 2025-07-20 22:24:08 +0200 |
|---|---|---|
| committer | xolatile | 2025-07-20 22:24:08 +0200 |
| commit | 54fb6d630222e0baf52ed223500dff4cf8da0f19 (patch) | |
| tree | 416446961e24e5b9e8f8adc03c702dcb71961992 /src/engine/smd.h | |
| parent | c46daa31f8e0339aed12736699d0003d27f1fc7e (diff) | |
| download | xolatile-badassbug-54fb6d630222e0baf52ed223500dff4cf8da0f19.tar.xz xolatile-badassbug-54fb6d630222e0baf52ed223500dff4cf8da0f19.tar.zst | |
Armour, respawn, executable, recorder, SMD format...
Diffstat (limited to 'src/engine/smd.h')
| -rw-r--r-- | src/engine/smd.h | 447 |
1 files changed, 0 insertions, 447 deletions
diff --git a/src/engine/smd.h b/src/engine/smd.h deleted file mode 100644 index 771ec9a..0000000 --- a/src/engine/smd.h +++ /dev/null @@ -1,447 +0,0 @@ -struct smd; - -struct smdbone -{ - string name; - int parent; - smdbone() : parent(-1) { name[0] = '\0'; } -}; - -struct smd : skelloader<smd> -{ - smd(const char *name) : skelloader(name) {} - - static const char *formatname() { return "smd"; } - int type() const { return MDL_SMD; } - - struct smdmesh : skelmesh - { - }; - - struct smdmeshgroup : skelmeshgroup - { - smdmeshgroup() - { - } - - bool skipcomment(char *&curbuf) - { - while(*curbuf && isspace(*curbuf)) curbuf++; - switch(*curbuf) - { - case '#': - case ';': - case '\r': - case '\n': - case '\0': - return true; - case '/': - if(curbuf[1] == '/') return true; - break; - } - return false; - } - - void skipsection(stream *f, char *buf, size_t bufsize) - { - while(f->getline(buf, bufsize)) - { - char *curbuf = buf; - if(skipcomment(curbuf)) continue; - if(!strncmp(curbuf, "end", 3)) break; - } - } - - void readname(char *&curbuf, char *name, size_t namesize) - { - char *curname = name; - while(*curbuf && isspace(*curbuf)) curbuf++; - bool allowspace = false; - if(*curbuf == '"') { curbuf++; allowspace = true; } - while(*curbuf) - { - char c = *curbuf++; - if(c == '"') break; - if(isspace(c) && !allowspace) break; - if(curname < &name[namesize-1]) *curname++ = c; - } - *curname = '\0'; - } - - void readnodes(stream *f, char *buf, size_t bufsize, vector<smdbone> &bones) - { - while(f->getline(buf, bufsize)) - { - char *curbuf = buf; - if(skipcomment(curbuf)) continue; - if(!strncmp(curbuf, "end", 3)) break; - int id = strtol(curbuf, &curbuf, 10); - string name; - readname(curbuf, name, sizeof(name)); - int parent = strtol(curbuf, &curbuf, 10); - if(id < 0 || id > 255 || parent > 255 || !name[0]) continue; - while(!bones.inrange(id)) bones.add(); - smdbone &bone = bones[id]; - copystring(bone.name, name); - bone.parent = parent; - } - } - - void readmaterial(char *&curbuf, char *name, size_t namesize) - { - char *curname = name; - while(*curbuf && isspace(*curbuf)) curbuf++; - while(*curbuf) - { - char c = *curbuf++; - if(isspace(c)) break; - if(c == '.') - { - while(*curbuf && !isspace(*curbuf)) curbuf++; - break; - } - if(curname < &name[namesize-1]) *curname++ = c; - } - *curname = '\0'; - } - - struct smdmeshdata - { - smdmesh *mesh; - vector<vert> verts; - vector<tri> tris; - - void finalize() - { - if(verts.empty() || tris.empty()) return; - vert *mverts = new vert[mesh->numverts + verts.length()]; - if(mesh->numverts) - { - memcpy(mverts, mesh->verts, mesh->numverts*sizeof(vert)); - delete[] mesh->verts; - } - memcpy(&mverts[mesh->numverts], verts.getbuf(), verts.length()*sizeof(vert)); - mesh->numverts += verts.length(); - mesh->verts = mverts; - tri *mtris = new tri[mesh->numtris + tris.length()]; - if(mesh->numtris) - { - memcpy(mtris, mesh->tris, mesh->numtris*sizeof(tri)); - delete[] mesh->tris; - } - memcpy(&mtris[mesh->numtris], tris.getbuf(), tris.length()*sizeof(tri)); - mesh->numtris += tris.length(); - mesh->tris = mtris; - } - }; - - struct smdvertkey : vert - { - smdmeshdata *mesh; - - smdvertkey(smdmeshdata *mesh) : mesh(mesh) {} - }; - - void readtriangles(stream *f, char *buf, size_t bufsize) - { - smdmeshdata *curmesh = NULL; - hashtable<const char *, smdmeshdata> materials(1<<6); - hashset<int> verts(1<<12); - while(f->getline(buf, bufsize)) - { - char *curbuf = buf; - if(skipcomment(curbuf)) continue; - if(!strncmp(curbuf, "end", 3)) break; - string material; - readmaterial(curbuf, material, sizeof(material)); - if(!curmesh || strcmp(curmesh->mesh->name, material)) - { - curmesh = materials.access(material); - if(!curmesh) - { - smdmesh *m = new smdmesh; - m->group = this; - m->name = newstring(material); - meshes.add(m); - curmesh = &materials[m->name]; - curmesh->mesh = m; - } - } - tri curtri; - loopi(3) - { - char *curbuf; - do - { - if(!f->getline(buf, bufsize)) goto endsection; - curbuf = buf; - } while(skipcomment(curbuf)); - smdvertkey key(curmesh); - int parent = -1, numlinks = 0, len = 0; - if(sscanf(curbuf, " %d %f %f %f %f %f %f %f %f %d%n", &parent, &key.pos.x, &key.pos.y, &key.pos.z, &key.norm.x, &key.norm.y, &key.norm.z, &key.tc.x, &key.tc.y, &numlinks, &len) < 9) goto endsection; - curbuf += len; - key.pos.y = -key.pos.y; - key.norm.y = -key.norm.y; - key.tc.y = 1 - key.tc.y; - blendcombo c; - int sorted = 0; - float pweight = 0, tweight = 0; - for(; numlinks > 0; numlinks--) - { - int bone = -1, len = 0; - float weight = 0; - if(sscanf(curbuf, " %d %f%n", &bone, &weight, &len) < 2) break; - curbuf += len; - tweight += weight; - if(bone == parent) pweight += weight; - else sorted = c.addweight(sorted, weight, bone); - } - if(tweight < 1) pweight += 1 - tweight; - if(pweight > 0) sorted = c.addweight(sorted, pweight, parent); - c.finalize(sorted); - key.blend = curmesh->mesh->addblendcombo(c); - int index = verts.access(key, curmesh->verts.length()); - if(index == curmesh->verts.length()) curmesh->verts.add(key); - curtri.vert[2-i] = index; - } - curmesh->tris.add(curtri); - } - endsection: - enumerate(materials, smdmeshdata, data, data.finalize()); - } - - void readskeleton(stream *f, char *buf, size_t bufsize) - { - int frame = -1; - while(f->getline(buf, bufsize)) - { - char *curbuf = buf; - if(skipcomment(curbuf)) continue; - if(sscanf(curbuf, " time %d", &frame) == 1) continue; - else if(!strncmp(curbuf, "end", 3)) break; - else if(frame != 0) continue; - int bone; - vec pos, rot; - if(sscanf(curbuf, " %d %f %f %f %f %f %f", &bone, &pos.x, &pos.y, &pos.z, &rot.x, &rot.y, &rot.z) != 7) - continue; - if(bone < 0 || bone >= skel->numbones) - continue; - rot.x = -rot.x; - rot.z = -rot.z; - float cx = cosf(rot.x/2), sx = sinf(rot.x/2), - cy = cosf(rot.y/2), sy = sinf(rot.y/2), - cz = cosf(rot.z/2), sz = sinf(rot.z/2); - pos.y = -pos.y; - dualquat dq(quat(sx*cy*cz - cx*sy*sz, - cx*sy*cz + sx*cy*sz, - cx*cy*sz - sx*sy*cz, - cx*cy*cz + sx*sy*sz), - pos); - boneinfo &b = skel->bones[bone]; - if(b.parent < 0) b.base = dq; - else b.base.mul(skel->bones[b.parent].base, dq); - (b.invbase = b.base).invert(); - } - } - - bool loadmesh(const char *filename) - { - stream *f = openfile(filename, "r"); - if(!f) return false; - - char buf[512]; - int version = -1; - while(f->getline(buf, sizeof(buf))) - { - char *curbuf = buf; - if(skipcomment(curbuf)) continue; - if(sscanf(curbuf, " version %d", &version) == 1) - { - if(version != 1) { delete f; return false; } - } - else if(!strncmp(curbuf, "nodes", 5)) - { - if(skel->numbones > 0) { skipsection(f, buf, sizeof(buf)); continue; } - vector<smdbone> bones; - readnodes(f, buf, sizeof(buf), bones); - if(bones.empty()) continue; - skel->numbones = bones.length(); - skel->bones = new boneinfo[skel->numbones]; - loopv(bones) - { - boneinfo &dst = skel->bones[i]; - smdbone &src = bones[i]; - dst.name = newstring(src.name); - dst.parent = src.parent; - } - skel->linkchildren(); - } - else if(!strncmp(curbuf, "triangles", 9)) - readtriangles(f, buf, sizeof(buf)); - else if(!strncmp(curbuf, "skeleton", 8)) - { - if(skel->shared > 1) skipsection(f, buf, sizeof(buf)); - else readskeleton(f, buf, sizeof(buf)); - } - else if(!strncmp(curbuf, "vertexanimation", 15)) - skipsection(f, buf, sizeof(buf)); - } - - sortblendcombos(); - - delete f; - return true; - } - - int readframes(stream *f, char *buf, size_t bufsize, vector<dualquat> &animbones) - { - int frame = -1, numframes = 0, lastbone = skel->numbones; - while(f->getline(buf, bufsize)) - { - char *curbuf = buf; - if(skipcomment(curbuf)) continue; - int nextframe = -1; - if(sscanf(curbuf, " time %d", &nextframe) == 1) - { - for(; lastbone < skel->numbones; lastbone++) animbones[frame*skel->numbones + lastbone] = animbones[lastbone]; - if(nextframe >= numframes) - { - databuf<dualquat> framebones = animbones.reserve(skel->numbones * (nextframe + 1 - numframes)); - loopi(nextframe - numframes) framebones.put(animbones.getbuf(), skel->numbones); - animbones.addbuf(framebones); - animbones.advance(skel->numbones); - numframes = nextframe + 1; - } - frame = nextframe; - lastbone = 0; - continue; - } - else if(!strncmp(curbuf, "end", 3)) break; - int bone; - vec pos, rot; - if(sscanf(curbuf, " %d %f %f %f %f %f %f", &bone, &pos.x, &pos.y, &pos.z, &rot.x, &rot.y, &rot.z) != 7) - continue; - if(bone < 0 || bone >= skel->numbones) - continue; - for(; lastbone < bone; lastbone++) animbones[frame*skel->numbones + lastbone] = animbones[lastbone]; - lastbone++; - float cx = cosf(rot.x/2), sx = sinf(rot.x/2), - cy = cosf(rot.y/2), sy = sinf(rot.y/2), - cz = cosf(rot.z/2), sz = sinf(rot.z/2); - pos.y = -pos.y; - dualquat dq(quat(-(sx*cy*cz - cx*sy*sz), - cx*sy*cz + sx*cy*sz, - -(cx*cy*sz - sx*sy*cz), - cx*cy*cz + sx*sy*sz), - pos); - if(adjustments.inrange(bone)) adjustments[bone].adjust(dq); - dq.mul(skel->bones[bone].invbase); - dualquat &dst = animbones[frame*skel->numbones + bone]; - if(skel->bones[bone].parent < 0) dst = dq; - else dst.mul(skel->bones[skel->bones[bone].parent].base, dq); - dst.fixantipodal(skel->numframes > 0 ? skel->framebones[bone] : animbones[bone]); - } - for(; lastbone < skel->numbones; lastbone++) animbones[frame*skel->numbones + lastbone] = animbones[lastbone]; - return numframes; - } - - skelanimspec *loadanim(const char *filename) - { - skelanimspec *sa = skel->findskelanim(filename); - if(sa || skel->numbones <= 0) return sa; - - stream *f = openfile(filename, "r"); - if(!f) return NULL; - - char buf[512]; - int version = -1; - vector<dualquat> animbones; - while(f->getline(buf, sizeof(buf))) - { - char *curbuf = buf; - if(skipcomment(curbuf)) continue; - if(sscanf(curbuf, " version %d", &version) == 1) - { - if(version != 1) { delete f; return NULL; } - } - else if(!strncmp(curbuf, "nodes", 5)) - { - vector<smdbone> bones; - readnodes(f, buf, sizeof(buf), bones); - if(bones.length() != skel->numbones) { delete f; return NULL; } - } - else if(!strncmp(curbuf, "triangles", 9)) - skipsection(f, buf, sizeof(buf)); - else if(!strncmp(curbuf, "skeleton", 8)) - readframes(f, buf, sizeof(buf), animbones); - else if(!strncmp(curbuf, "vertexanimation", 15)) - skipsection(f, buf, sizeof(buf)); - } - int numframes = animbones.length() / skel->numbones; - dualquat *framebones = new dualquat[(skel->numframes+numframes)*skel->numbones]; - if(skel->framebones) - { - memcpy(framebones, skel->framebones, skel->numframes*skel->numbones*sizeof(dualquat)); - delete[] skel->framebones; - } - memcpy(&framebones[skel->numframes*skel->numbones], animbones.getbuf(), numframes*skel->numbones*sizeof(dualquat)); - skel->framebones = framebones; - sa = &skel->addskelanim(filename); - sa->frame = skel->numframes; - sa->range = numframes; - skel->numframes += numframes; - - delete f; - - return sa; - } - - bool load(const char *meshfile) - { - name = newstring(meshfile); - - if(!loadmesh(meshfile)) return false; - - return true; - } - }; - - meshgroup *loadmeshes(const char *name, va_list args) - { - smdmeshgroup *group = new smdmeshgroup; - group->shareskeleton(va_arg(args, char *)); - if(!group->load(name)) { delete group; return NULL; } - return group; - } - - bool loaddefaultparts() - { - skelpart &mdl = addpart(); - mdl.pitchscale = mdl.pitchoffset = mdl.pitchmin = mdl.pitchmax = 0; - adjustments.setsize(0); - const char *fname = name + strlen(name); - do --fname; while(fname >= name && *fname!='/' && *fname!='\\'); - fname++; - defformatstring(meshname, "packages/models/%s/%s.smd", name, fname); - mdl.meshes = sharemeshes(path(meshname), NULL); - if(!mdl.meshes) return false; - mdl.initanimparts(); - mdl.initskins(); - return true; - } -}; - -static inline uint hthash(const smd::smdmeshgroup::smdvertkey &k) -{ - return hthash(k.pos); -} - -static inline bool htcmp(const smd::smdmeshgroup::smdvertkey &k, int index) -{ - if(!k.mesh->verts.inrange(index)) return false; - const smd::vert &v = k.mesh->verts[index]; - return k.pos == v.pos && k.norm == v.norm && k.tc == v.tc && k.blend == v.blend; -} - -skelcommands<smd> smdcommands; - |
