summaryrefslogtreecommitdiff
path: root/src/engine/smd.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/smd.h')
-rw-r--r--src/engine/smd.h447
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;
-