OctaCore/src/engine/md2.hh

243 lines
14 KiB
C++

struct md2;
static const float md2normaltable[256][3] =
{
{ -0.525731f, 0.000000f, 0.850651f }, { -0.442863f, 0.238856f, 0.864188f }, { -0.295242f, 0.000000f, 0.955423f }, { -0.309017f, 0.500000f, 0.809017f },
{ -0.162460f, 0.262866f, 0.951056f }, { 0.000000f, 0.000000f, 1.000000f }, { 0.000000f, 0.850651f, 0.525731f }, { -0.147621f, 0.716567f, 0.681718f },
{ 0.147621f, 0.716567f, 0.681718f }, { 0.000000f, 0.525731f, 0.850651f }, { 0.309017f, 0.500000f, 0.809017f }, { 0.525731f, 0.000000f, 0.850651f },
{ 0.295242f, 0.000000f, 0.955423f }, { 0.442863f, 0.238856f, 0.864188f }, { 0.162460f, 0.262866f, 0.951056f }, { -0.681718f, 0.147621f, 0.716567f },
{ -0.809017f, 0.309017f, 0.500000f }, { -0.587785f, 0.425325f, 0.688191f }, { -0.850651f, 0.525731f, 0.000000f }, { -0.864188f, 0.442863f, 0.238856f },
{ -0.716567f, 0.681718f, 0.147621f }, { -0.688191f, 0.587785f, 0.425325f }, { -0.500000f, 0.809017f, 0.309017f }, { -0.238856f, 0.864188f, 0.442863f },
{ -0.425325f, 0.688191f, 0.587785f }, { -0.716567f, 0.681718f, -0.147621f }, { -0.500000f, 0.809017f, -0.309017f }, { -0.525731f, 0.850651f, 0.000000f },
{ 0.000000f, 0.850651f, -0.525731f }, { -0.238856f, 0.864188f, -0.442863f }, { 0.000000f, 0.955423f, -0.295242f }, { -0.262866f, 0.951056f, -0.162460f },
{ 0.000000f, 1.000000f, 0.000000f }, { 0.000000f, 0.955423f, 0.295242f }, { -0.262866f, 0.951056f, 0.162460f }, { 0.238856f, 0.864188f, 0.442863f },
{ 0.262866f, 0.951056f, 0.162460f }, { 0.500000f, 0.809017f, 0.309017f }, { 0.238856f, 0.864188f, -0.442863f }, { 0.262866f, 0.951056f, -0.162460f },
{ 0.500000f, 0.809017f, -0.309017f }, { 0.850651f, 0.525731f, 0.000000f }, { 0.716567f, 0.681718f, 0.147621f }, { 0.716567f, 0.681718f, -0.147621f },
{ 0.525731f, 0.850651f, 0.000000f }, { 0.425325f, 0.688191f, 0.587785f }, { 0.864188f, 0.442863f, 0.238856f }, { 0.688191f, 0.587785f, 0.425325f },
{ 0.809017f, 0.309017f, 0.500000f }, { 0.681718f, 0.147621f, 0.716567f }, { 0.587785f, 0.425325f, 0.688191f }, { 0.955423f, 0.295242f, 0.000000f },
{ 1.000000f, 0.000000f, 0.000000f }, { 0.951056f, 0.162460f, 0.262866f }, { 0.850651f, -0.525731f, 0.000000f }, { 0.955423f, -0.295242f, 0.000000f },
{ 0.864188f, -0.442863f, 0.238856f }, { 0.951056f, -0.162460f, 0.262866f }, { 0.809017f, -0.309017f, 0.500000f }, { 0.681718f, -0.147621f, 0.716567f },
{ 0.850651f, 0.000000f, 0.525731f }, { 0.864188f, 0.442863f, -0.238856f }, { 0.809017f, 0.309017f, -0.500000f }, { 0.951056f, 0.162460f, -0.262866f },
{ 0.525731f, 0.000000f, -0.850651f }, { 0.681718f, 0.147621f, -0.716567f }, { 0.681718f, -0.147621f, -0.716567f }, { 0.850651f, 0.000000f, -0.525731f },
{ 0.809017f, -0.309017f, -0.500000f }, { 0.864188f, -0.442863f, -0.238856f }, { 0.951056f, -0.162460f, -0.262866f }, { 0.147621f, 0.716567f, -0.681718f },
{ 0.309017f, 0.500000f, -0.809017f }, { 0.425325f, 0.688191f, -0.587785f }, { 0.442863f, 0.238856f, -0.864188f }, { 0.587785f, 0.425325f, -0.688191f },
{ 0.688191f, 0.587785f, -0.425325f }, { -0.147621f, 0.716567f, -0.681718f }, { -0.309017f, 0.500000f, -0.809017f }, { 0.000000f, 0.525731f, -0.850651f },
{ -0.525731f, 0.000000f, -0.850651f }, { -0.442863f, 0.238856f, -0.864188f }, { -0.295242f, 0.000000f, -0.955423f }, { -0.162460f, 0.262866f, -0.951056f },
{ 0.000000f, 0.000000f, -1.000000f }, { 0.295242f, 0.000000f, -0.955423f }, { 0.162460f, 0.262866f, -0.951056f }, { -0.442863f, -0.238856f, -0.864188f },
{ -0.309017f, -0.500000f, -0.809017f }, { -0.162460f, -0.262866f, -0.951056f }, { 0.000000f, -0.850651f, -0.525731f }, { -0.147621f, -0.716567f, -0.681718f },
{ 0.147621f, -0.716567f, -0.681718f }, { 0.000000f, -0.525731f, -0.850651f }, { 0.309017f, -0.500000f, -0.809017f }, { 0.442863f, -0.238856f, -0.864188f },
{ 0.162460f, -0.262866f, -0.951056f }, { 0.238856f, -0.864188f, -0.442863f }, { 0.500000f, -0.809017f, -0.309017f }, { 0.425325f, -0.688191f, -0.587785f },
{ 0.716567f, -0.681718f, -0.147621f }, { 0.688191f, -0.587785f, -0.425325f }, { 0.587785f, -0.425325f, -0.688191f }, { 0.000000f, -0.955423f, -0.295242f },
{ 0.000000f, -1.000000f, 0.000000f }, { 0.262866f, -0.951056f, -0.162460f }, { 0.000000f, -0.850651f, 0.525731f }, { 0.000000f, -0.955423f, 0.295242f },
{ 0.238856f, -0.864188f, 0.442863f }, { 0.262866f, -0.951056f, 0.162460f }, { 0.500000f, -0.809017f, 0.309017f }, { 0.716567f, -0.681718f, 0.147621f },
{ 0.525731f, -0.850651f, 0.000000f }, { -0.238856f, -0.864188f, -0.442863f }, { -0.500000f, -0.809017f, -0.309017f }, { -0.262866f, -0.951056f, -0.162460f },
{ -0.850651f, -0.525731f, 0.000000f }, { -0.716567f, -0.681718f, -0.147621f }, { -0.716567f, -0.681718f, 0.147621f }, { -0.525731f, -0.850651f, 0.000000f },
{ -0.500000f, -0.809017f, 0.309017f }, { -0.238856f, -0.864188f, 0.442863f }, { -0.262866f, -0.951056f, 0.162460f }, { -0.864188f, -0.442863f, 0.238856f },
{ -0.809017f, -0.309017f, 0.500000f }, { -0.688191f, -0.587785f, 0.425325f }, { -0.681718f, -0.147621f, 0.716567f }, { -0.442863f, -0.238856f, 0.864188f },
{ -0.587785f, -0.425325f, 0.688191f }, { -0.309017f, -0.500000f, 0.809017f }, { -0.147621f, -0.716567f, 0.681718f }, { -0.425325f, -0.688191f, 0.587785f },
{ -0.162460f, -0.262866f, 0.951056f }, { 0.442863f, -0.238856f, 0.864188f }, { 0.162460f, -0.262866f, 0.951056f }, { 0.309017f, -0.500000f, 0.809017f },
{ 0.147621f, -0.716567f, 0.681718f }, { 0.000000f, -0.525731f, 0.850651f }, { 0.425325f, -0.688191f, 0.587785f }, { 0.587785f, -0.425325f, 0.688191f },
{ 0.688191f, -0.587785f, 0.425325f }, { -0.955423f, 0.295242f, 0.000000f }, { -0.951056f, 0.162460f, 0.262866f }, { -1.000000f, 0.000000f, 0.000000f },
{ -0.850651f, 0.000000f, 0.525731f }, { -0.955423f, -0.295242f, 0.000000f }, { -0.951056f, -0.162460f, 0.262866f }, { -0.864188f, 0.442863f, -0.238856f },
{ -0.951056f, 0.162460f, -0.262866f }, { -0.809017f, 0.309017f, -0.500000f }, { -0.864188f, -0.442863f, -0.238856f }, { -0.951056f, -0.162460f, -0.262866f },
{ -0.809017f, -0.309017f, -0.500000f }, { -0.681718f, 0.147621f, -0.716567f }, { -0.681718f, -0.147621f, -0.716567f }, { -0.850651f, 0.000000f, -0.525731f },
{ -0.688191f, 0.587785f, -0.425325f }, { -0.587785f, 0.425325f, -0.688191f }, { -0.425325f, 0.688191f, -0.587785f }, { -0.425325f, -0.688191f, -0.587785f },
{ -0.587785f, -0.425325f, -0.688191f }, { -0.688191f, -0.587785f, -0.425325f }
};
struct md2 : vertloader<md2>
{
struct md2_header
{
int magic;
int version;
int skinwidth, skinheight;
int framesize;
int numskins, numvertices, numtexcoords;
int numtriangles, numglcommands, numframes;
int offsetskins, offsettexcoords, offsettriangles;
int offsetframes, offsetglcommands, offsetend;
};
struct md2_vertex
{
uchar vertex[3], normalindex;
};
struct md2_frame
{
float scale[3];
float translate[3];
char name[16];
};
md2(const char *name) : vertloader(name) {}
static const char *formatname() { return "md2"; }
static bool multiparted() { return false; }
static bool multimeshed() { return false; }
bool flipy() const { return true; }
int type() const { return MDL_MD2; }
int linktype(animmodel *m, part *p) const { return LINK_COOP; }
struct md2meshgroup : vertmeshgroup
{
void genverts(int *glcommands, vector<tcvert> &tcverts, vector<ushort> &vindexes, vector<tri> &tris)
{
hashtable<ivec, int> tchash;
vector<ushort> idxs;
for(int *command = glcommands; (*command)!=0;)
{
int numvertex = *command++;
bool isfan = numvertex<0;
if(isfan) numvertex = -numvertex;
idxs.setsize(0);
loopi(numvertex)
{
union { int i; float f; } u, v;
u.i = *command++;
v.i = *command++;
int vindex = *command++;
ivec tckey(u.i, v.i, vindex);
int *idx = tchash.access(tckey);
if(!idx)
{
idx = &tchash[tckey];
*idx = tcverts.length();
tcvert &tc = tcverts.add();
tc.tc = vec2(u.f, v.f);
vindexes.add((ushort)vindex);
}
idxs.add(*idx);
}
loopi(numvertex-2)
{
tri &t = tris.add();
if(isfan)
{
t.vert[0] = idxs[0];
t.vert[1] = idxs[i+1];
t.vert[2] = idxs[i+2];
}
else loopk(3) t.vert[k] = idxs[i&1 && k ? i+(1-(k-1))+1 : i+k];
}
}
}
bool load(const char *filename, float smooth)
{
stream *file = openfile(filename, "rb");
if(!file) return false;
md2_header header;
file->read(&header, sizeof(md2_header));
lilswap(&header.magic, sizeof(md2_header)/sizeof(int));
if(header.magic!=844121161 || header.version!=8 ||
header.numframes <= 0 || header.numframes > 1000 ||
header.numglcommands <= 0 || header.numglcommands > (1<<20) ||
header.numvertices <= 0 || header.numvertices > (1<<20))
{
delete file;
return false;
}
name = newstring(filename);
numframes = header.numframes;
vertmesh &m = *new vertmesh;
m.group = this;
meshes.add(&m);
int *glcommands = new int[header.numglcommands];
file->seek(header.offsetglcommands, SEEK_SET);
int numglcommands = file->read(glcommands, header.numglcommands*sizeof(int))/sizeof(int);
lilswap(glcommands, numglcommands);
if(numglcommands < header.numglcommands) memset(&glcommands[numglcommands], 0, (header.numglcommands-numglcommands)*sizeof(int));
vector<tcvert> tcgen;
vector<ushort> vgen;
vector<tri> trigen;
genverts(glcommands, tcgen, vgen,trigen);
delete[] glcommands;
m.numverts = tcgen.length();
m.tcverts = new tcvert[m.numverts];
memcpy(m.tcverts, tcgen.getbuf(), m.numverts*sizeof(tcvert));
m.numtris = trigen.length();
m.tris = new tri[m.numtris];
memcpy(m.tris, trigen.getbuf(), m.numtris*sizeof(tri));
m.verts = new vert[m.numverts*numframes];
md2_vertex *tmpverts = new md2_vertex[header.numvertices];
int frame_offset = header.offsetframes;
vert *curvert = m.verts;
loopi(header.numframes)
{
md2_frame frame;
file->seek(frame_offset, SEEK_SET);
file->read(&frame, sizeof(md2_frame));
lilswap(frame.scale, 6);
file->read(tmpverts, header.numvertices*sizeof(md2_vertex));
loopj(m.numverts)
{
const md2_vertex &v = tmpverts[vgen[j]];
curvert->pos = vec(v.vertex[0]*frame.scale[0]+frame.translate[0],
-(v.vertex[1]*frame.scale[1]+frame.translate[1]),
v.vertex[2]*frame.scale[2]+frame.translate[2]);
const float *norm = md2normaltable[v.normalindex];
curvert->norm = vec(norm[0], -norm[1], norm[2]);
++curvert;
}
frame_offset += header.framesize;
}
delete[] tmpverts;
m.calctangents();
delete file;
return true;
}
};
vertmeshgroup *newmeshes() { return new md2meshgroup; }
bool loadconfig() { return false; }
bool loaddefaultparts()
{
part &mdl = addpart();
const char *pname = parentdir(name);
defformatstring(name1, "media/model/%s/tris.md2", name);
mdl.meshes = sharemeshes(path(name1));
if(!mdl.meshes)
{
defformatstring(name2, "media/model/%s/tris.md2", pname); // try md2 in parent folder (vert sharing)
mdl.meshes = sharemeshes(path(name2));
if(!mdl.meshes) return false;
}
Texture *tex, *masks;
loadskin(name, pname, tex, masks);
mdl.initskins(tex, masks);
if(tex==notexture) conoutf(CON_ERROR, "could not load model skin for %s", name1);
identflags &= ~IDF_PERSIST;
defformatstring(name3, "media/model/%s/md2.cfg", name);
if(!execfile(name3, false))
{
formatstring(name3, "media/model/%s/md2.cfg", pname);
execfile(name3, false);
}
identflags |= IDF_PERSIST;
return true;
}
};
vertcommands<md2> md2commands;