*** empty log message ***
git-svn-id: svn://svn.code.sf.net/p/actiongame/code/trunk/ac@38 e016b1c5-ed68-44aa-a2f7-31cac88cffde
This commit is contained in:
+283
-356
@@ -1,81 +1,34 @@
|
||||
// code for loading, linking and rendering md3 models
|
||||
// See http://www.draekko.org/documentation/md3format.html for informations about the md3 format
|
||||
|
||||
#include "cube.h"
|
||||
|
||||
// loading and rendering code for the MD3 model format
|
||||
// parts of the code are from gamedev.net
|
||||
|
||||
const int FIRSTMD3 = 20;
|
||||
int nummodels = 0;
|
||||
int numskins = 0;
|
||||
enum { MDL_LOWER = 0, MDL_UPPER, MDL_HEAD };
|
||||
|
||||
struct vec2
|
||||
#define MD3_DEFAULT_SCALE 0.08f
|
||||
|
||||
struct vec2
|
||||
{
|
||||
float x, y;
|
||||
};
|
||||
|
||||
struct md3header
|
||||
{
|
||||
char fileID[4];
|
||||
int version;
|
||||
char filename[68];
|
||||
int numFrames, numTags, numMeshes;
|
||||
int maxSkins;
|
||||
int headersize;
|
||||
int tagStart, tagEnd;
|
||||
int filesize;
|
||||
};
|
||||
|
||||
struct md3meshinfo
|
||||
{
|
||||
char meshId[4];
|
||||
char name[68];
|
||||
int numMeshFrames, numSkins, numVertices, numTriangles;
|
||||
int triStart;
|
||||
int headersize;
|
||||
int uvStart;
|
||||
int vertexStart;
|
||||
int meshSize;
|
||||
};
|
||||
|
||||
struct md3tag
|
||||
{
|
||||
char name[64];
|
||||
vec pos;
|
||||
float rotation[3][3];
|
||||
char name[64];
|
||||
float pos[3];
|
||||
float rotation[3][3];
|
||||
};
|
||||
|
||||
struct md3bone
|
||||
struct md3vertex
|
||||
{
|
||||
float mins[3], maxs[3];
|
||||
float position[3];
|
||||
float scale;
|
||||
char creator[16];
|
||||
signed short vertex[3];
|
||||
uchar normal[2];
|
||||
};
|
||||
|
||||
struct md3triangle
|
||||
{
|
||||
signed short vertex[3];
|
||||
unsigned char normal[2];
|
||||
};
|
||||
|
||||
struct md3face
|
||||
{
|
||||
int vertexindices[3];
|
||||
};
|
||||
|
||||
struct md3texcoord
|
||||
{
|
||||
float texturecoord[2];
|
||||
};
|
||||
|
||||
struct md3skin
|
||||
{
|
||||
char name[68];
|
||||
};
|
||||
|
||||
struct md3tface
|
||||
{
|
||||
int vertindex[3];
|
||||
int coordindex[3];
|
||||
int vertexindices[3];
|
||||
};
|
||||
|
||||
struct md3animinfo
|
||||
@@ -86,33 +39,47 @@ struct md3animinfo
|
||||
int fps;
|
||||
};
|
||||
|
||||
struct md3object
|
||||
struct md3header
|
||||
{
|
||||
int numVerts, numFaces, numTexVertex;
|
||||
int tex;
|
||||
char name[255];
|
||||
vec *verts;
|
||||
vec *normals;
|
||||
vec2 *texVerts;
|
||||
md3tface *faces;
|
||||
int numTags;//EDIT: AH
|
||||
char id[4];
|
||||
int version;
|
||||
char name[64];
|
||||
int flags;
|
||||
int numframes, numtags, nummeshes, numskins;
|
||||
int ofs_frames, ofs_tags, ofs_meshes, ofs_eof; // offsets
|
||||
};
|
||||
|
||||
struct md3model
|
||||
struct md3meshheader
|
||||
{
|
||||
vector<md3object> objects;
|
||||
char id[4];
|
||||
char name[64];
|
||||
int flags;
|
||||
int numframes, numshaders, numvertices, numtriangles;
|
||||
int ofs_triangles, ofs_shaders, ofs_uv, ofs_vertices, meshsize; // offsets
|
||||
};
|
||||
|
||||
struct md3mesh
|
||||
{
|
||||
char name[64];
|
||||
md3triangle *triangles;
|
||||
vec *vertices;
|
||||
vec2 *uv;
|
||||
int numtriangles, numvertices; // numvertices == numUV
|
||||
int tex;
|
||||
};
|
||||
|
||||
struct md3model
|
||||
{
|
||||
vector<md3mesh> meshes;
|
||||
vector<md3animinfo> animations;
|
||||
md3model **links;
|
||||
md3tag *tags;
|
||||
int numTags;
|
||||
/* int curAnim, curFrame, nextFrame;
|
||||
int lastTime; */
|
||||
md3state *animstate;
|
||||
md3model **links;
|
||||
md3tag *tags;
|
||||
int numframes, numtags;
|
||||
bool loaded;
|
||||
int modelnum;
|
||||
float scale;
|
||||
bool load(char *mdlpath);
|
||||
void link(md3model *link, char *tag);
|
||||
vec scale;
|
||||
bool link(md3model *link, char *tag);
|
||||
bool load(char *path);
|
||||
void render();
|
||||
void draw(float x, float y, float z, float yaw, float pitch, float rad);
|
||||
md3model();
|
||||
@@ -122,229 +89,169 @@ struct md3model
|
||||
md3model::md3model()
|
||||
{
|
||||
loaded = false;
|
||||
scale = 0.08f;
|
||||
scale.x = scale.y = scale.z = MD3_DEFAULT_SCALE;
|
||||
animstate = NULL;
|
||||
};
|
||||
|
||||
md3model::~md3model()
|
||||
{
|
||||
loopv(objects){
|
||||
if(objects[i].verts) delete [] objects[i].verts;
|
||||
if(objects[i].normals) delete [] objects[i].normals;
|
||||
if(objects[i].texVerts) delete [] objects[i].texVerts;
|
||||
if(objects[i].faces) delete [] objects[i].faces;
|
||||
loopv(meshes){
|
||||
if(meshes[i].vertices) delete [] meshes[i].vertices;
|
||||
if(meshes[i].triangles) delete [] meshes[i].triangles;
|
||||
if(meshes[i].uv) delete [] meshes[i].uv;
|
||||
};
|
||||
if(links) free(links);
|
||||
if(tags) delete [] tags;
|
||||
};
|
||||
|
||||
bool md3model::load(char *mdlpath)
|
||||
bool md3model::link(md3model *link, char *tag)
|
||||
{
|
||||
loaded = false;
|
||||
if(!mdlpath) return false;
|
||||
loopi(numtags)
|
||||
if(strcmp(tags[i].name, tag) == 0)
|
||||
{
|
||||
links[i] = link;
|
||||
return true;
|
||||
};
|
||||
return false;
|
||||
};
|
||||
|
||||
FILE *f = fopen(mdlpath, "rb");
|
||||
if(!f) { conoutf("could not load md3 model: %s", (int)mdlpath); return false; };
|
||||
bool md3model::load(char *path)
|
||||
{
|
||||
if(!path) return false;
|
||||
FILE *f = fopen(path, "rb");
|
||||
if(!f) fatal("could not load md3 model: %s", path);
|
||||
md3header header;
|
||||
fread(&header, 1, sizeof(header), f);
|
||||
char *id = header.fileID;
|
||||
if(id[0] != 'I' || id[1] != 'D' || id[2] != 'P' || header.version != 15) { // check the header
|
||||
conoutf("wrong header in md3 model: %s", (int)mdlpath);
|
||||
return false;
|
||||
};
|
||||
fread(&header, sizeof(md3header), 1, f);
|
||||
if(header.id[0] != 'I' || header.id[1] != 'D' || header.id[2] != 'P' || header.id[3] != '3' || header.version != 15) // header check
|
||||
fatal("corruped header in md3 model: %s", path);
|
||||
|
||||
md3bone *bones = new md3bone[header.numFrames]; // read bones
|
||||
fread(bones, sizeof(md3bone), header.numFrames, f);
|
||||
delete [] bones;
|
||||
tags = new md3tag[header.numframes * header.numtags];
|
||||
fseek(f, header.ofs_tags, SEEK_SET);
|
||||
fread(tags, sizeof(md3tag), header.numframes * header.numtags, f);
|
||||
numframes = header.numframes;
|
||||
numtags = header.numtags;
|
||||
|
||||
tags = new md3tag[header.numFrames * header.numTags]; // read tags
|
||||
fread(tags, sizeof(md3tag), header.numFrames * header.numTags, f);
|
||||
numTags = header.numTags;
|
||||
links = (md3model **) malloc(sizeof(md3model) * header.numtags);
|
||||
loopi(header.numtags) links[i] = NULL;
|
||||
|
||||
int mesh_offset = ftell(f);
|
||||
|
||||
links = (md3model **) malloc(sizeof(md3model) * header.numTags); // alloc mem for the links
|
||||
loopi(header.numTags) links[i] = NULL;
|
||||
|
||||
long meshOffset = ftell(f);
|
||||
md3meshinfo meshHeader;
|
||||
|
||||
loopj(header.numMeshes) // go through all sub objects
|
||||
{
|
||||
fseek(f, meshOffset, SEEK_SET); // read header
|
||||
fread(&meshHeader, sizeof(md3meshinfo), 1, f);
|
||||
|
||||
md3skin *skins = new md3skin[meshHeader.numSkins];
|
||||
md3texcoord *texcoords = new md3texcoord[meshHeader.numVertices];
|
||||
md3face *triangles = new md3face[meshHeader.numTriangles];
|
||||
md3triangle *vertices = new md3triangle[meshHeader.numVertices * meshHeader.numMeshFrames];
|
||||
loopi(header.nummeshes)
|
||||
{
|
||||
md3mesh mesh;
|
||||
md3meshheader mheader;
|
||||
fseek(f, mesh_offset, SEEK_SET);
|
||||
fread(&mheader, sizeof(md3meshheader), 1, f);
|
||||
strn0cpy(mesh.name, mheader.name, 64);
|
||||
|
||||
mesh.triangles = new md3triangle[mheader.numtriangles];
|
||||
fseek(f, mesh_offset + mheader.ofs_triangles, SEEK_SET);
|
||||
fread(mesh.triangles, sizeof(md3triangle), mheader.numtriangles, f); // read the triangles
|
||||
mesh.numtriangles = mheader.numtriangles;
|
||||
|
||||
mesh.uv = new vec2[mheader.numvertices];
|
||||
fseek(f, mesh_offset + mheader.ofs_uv , SEEK_SET);
|
||||
fread(mesh.uv, sizeof(vec2), mheader.numvertices, f); // read the UV data
|
||||
|
||||
fread(skins, sizeof(md3skin), meshHeader.numSkins, f); // read skin information
|
||||
|
||||
fseek(f, meshOffset + meshHeader.triStart, SEEK_SET); // read triangles/face data
|
||||
fread(triangles, sizeof(md3face), meshHeader.numTriangles, f);
|
||||
|
||||
fseek(f, meshOffset + meshHeader.uvStart, SEEK_SET); // read UV data
|
||||
fread(texcoords, sizeof(md3texcoord), meshHeader.numVertices, f);
|
||||
|
||||
fseek(f, meshOffset + meshHeader.vertexStart, SEEK_SET); // read vertex/face index information
|
||||
fread(vertices, sizeof(md3triangle), meshHeader.numMeshFrames * meshHeader.numVertices, f);
|
||||
|
||||
md3object currentMesh = {0};
|
||||
strcpy(currentMesh.name, meshHeader.name);
|
||||
|
||||
currentMesh.numVerts = meshHeader.numVertices;
|
||||
currentMesh.numTexVertex = meshHeader.numVertices;
|
||||
currentMesh.numFaces = meshHeader.numTriangles;
|
||||
|
||||
currentMesh.verts = new vec[currentMesh.numVerts * meshHeader.numMeshFrames];
|
||||
currentMesh.texVerts = new vec2 [currentMesh.numVerts];
|
||||
currentMesh.faces = new md3tface [currentMesh.numFaces];
|
||||
|
||||
loopi(currentMesh.numVerts * meshHeader.numMeshFrames)
|
||||
md3vertex *vertices = new md3vertex[mheader.numframes * mheader.numvertices];
|
||||
fseek(f, mesh_offset + mheader.ofs_vertices, SEEK_SET);
|
||||
fread(vertices, sizeof(md3vertex), mheader.numframes * mheader.numvertices, f); // read the vertices
|
||||
mesh.vertices = new vec[mheader.numframes * mheader.numvertices]; // transform to our own structure
|
||||
loopj(mheader.numframes * mheader.numvertices)
|
||||
{
|
||||
currentMesh.verts[i].x = vertices[i].vertex[0] / 64.0f;
|
||||
currentMesh.verts[i].y = vertices[i].vertex[1] / 64.0f;
|
||||
currentMesh.verts[i].z = vertices[i].vertex[2] / 64.0f;
|
||||
}
|
||||
|
||||
loopi(currentMesh.numTexVertex)
|
||||
{
|
||||
currentMesh.texVerts[i].x = texcoords[i].texturecoord[0];
|
||||
currentMesh.texVerts[i].y = -texcoords[i].texturecoord[1];
|
||||
}
|
||||
|
||||
loopi(currentMesh.numFaces)
|
||||
{
|
||||
currentMesh.faces[i].vertindex[0] = triangles[i].vertexindices[0];
|
||||
currentMesh.faces[i].vertindex[1] = triangles[i].vertexindices[1];
|
||||
currentMesh.faces[i].vertindex[2] = triangles[i].vertexindices[2];
|
||||
|
||||
currentMesh.faces[i].coordindex[0] = triangles[i].vertexindices[0];
|
||||
currentMesh.faces[i].coordindex[1] = triangles[i].vertexindices[1];
|
||||
currentMesh.faces[i].coordindex[2] = triangles[i].vertexindices[2];
|
||||
}
|
||||
mesh.vertices[j].x = vertices[j].vertex[0] / 64.0f;
|
||||
mesh.vertices[j].y = vertices[j].vertex[1] / 64.0f;
|
||||
mesh.vertices[j].z = vertices[j].vertex[2] / 64.0f;
|
||||
};
|
||||
mesh.numvertices = mheader.numvertices;
|
||||
|
||||
objects.add(currentMesh);
|
||||
|
||||
delete [] skins;
|
||||
delete [] texcoords;
|
||||
delete [] triangles;
|
||||
delete [] vertices;
|
||||
meshOffset += meshHeader.meshSize;
|
||||
meshes.add(mesh);
|
||||
mesh_offset += mheader.meshsize;
|
||||
delete [] vertices;
|
||||
};
|
||||
|
||||
loaded = true;
|
||||
return true;
|
||||
};
|
||||
|
||||
void md3model::link(md3model *link, char *tag)
|
||||
{
|
||||
loopi(numTags)
|
||||
if(strcmp(tags[i].name, tag) == 0)
|
||||
{
|
||||
links[i] = link;
|
||||
return;
|
||||
};
|
||||
};
|
||||
VAR(anim, 0, 0, 100);
|
||||
|
||||
void md3model::render()
|
||||
{
|
||||
int startfrm = 0;
|
||||
int endfrm = 1;
|
||||
if(!loaded || meshes.length() <= 0) return;
|
||||
float t = 0.0f;
|
||||
|
||||
int nextfrm;
|
||||
md3state *a = animstate;
|
||||
md3animinfo *anim = NULL;
|
||||
|
||||
if(animations.length())
|
||||
if(a && animations.length() > a->anim)
|
||||
{
|
||||
anim = &animations[a->anim];
|
||||
/*if(a->frm < anim->start || a->frm > anim->end)
|
||||
md3animinfo *info = &animations[a->anim];
|
||||
if(a->frm < info->start || a->frm > info->end) // we switched to a new animation, jump to the start
|
||||
a->frm = info->start;
|
||||
t = (float) (lastmillis - a->lastTime) / (1000.0f / info->fps); // t has a value from 0.0f to 1.0f - used for interpolation
|
||||
if(t >= 1.0f) // jump to the next keyframe
|
||||
{
|
||||
a->frm = anim->start;
|
||||
a->lastTime = lastmillis;
|
||||
};*/
|
||||
startfrm = anim->start;
|
||||
endfrm = anim->end;
|
||||
}
|
||||
|
||||
int nextfrm = (a->frm + 1) % endfrm;
|
||||
if(nextfrm == 0)
|
||||
{
|
||||
if(anim && anim->loop) nextfrm = startfrm;
|
||||
else
|
||||
a->frm++;
|
||||
a->lastTime = lastmillis;
|
||||
};
|
||||
int elapsedtime = 0;
|
||||
|
||||
if(animations.length())
|
||||
{
|
||||
elapsedtime = lastmillis - a->lastTime;
|
||||
t = (float) elapsedtime / (1000 / anim->fps);
|
||||
if(t >= 1.0f)
|
||||
{
|
||||
t = 0.0f;
|
||||
a->frm = nextfrm;
|
||||
a->lastTime = lastmillis;
|
||||
};
|
||||
};
|
||||
|
||||
loopv(objects)
|
||||
if(a->frm >= info->end)
|
||||
{
|
||||
if(info->loop)
|
||||
a->frm = info->start;
|
||||
else
|
||||
{
|
||||
a->frm = info->end;
|
||||
t = 0.0f; // stops the animation
|
||||
};
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
md3object *obj = &objects[i];
|
||||
|
||||
int currentIndex = a->frm * obj->numVerts;
|
||||
int nextIndex = nextfrm * obj->numVerts;
|
||||
a = new md3state();
|
||||
a->frm = 0;
|
||||
}
|
||||
a->frm = anim; //fixme
|
||||
nextfrm = a->frm + 1;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, obj->tex + FIRSTMD3);
|
||||
#define interpolate(p1,p2) ((p1) + t * ((p2) - (p1)))
|
||||
|
||||
loopv(meshes)
|
||||
{
|
||||
md3mesh *mesh = &meshes[i];
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, FIRSTMD3 + mesh->tex);
|
||||
|
||||
glBegin(GL_TRIANGLES);
|
||||
loopj(obj->numFaces)
|
||||
loopj(mesh->numtriangles) // triangles
|
||||
{
|
||||
loop(whichVertex, 3)
|
||||
loopk(3) // vertices
|
||||
{
|
||||
int index = obj->faces[j].vertindex[whichVertex];
|
||||
|
||||
if(obj->texVerts)
|
||||
glTexCoord2f(obj->texVerts[index].x, -obj->texVerts[index].y);
|
||||
|
||||
vec point1 = obj->verts[ currentIndex + index ];
|
||||
vec point2 = obj->verts[ nextIndex + index];
|
||||
|
||||
glVertex3f(point1.x + t * (point2.x - point1.x),
|
||||
point1.y + t * (point2.y - point1.y),
|
||||
point1.z + t * (point2.z - point1.z));
|
||||
}
|
||||
}
|
||||
int index = mesh->triangles[j].vertexindices[k];
|
||||
vec *point1 = &mesh->vertices[index + a->frm * mesh->numvertices];
|
||||
vec *point2 = &mesh->vertices[index + nextfrm * mesh->numvertices];
|
||||
|
||||
if(mesh->uv)
|
||||
glTexCoord2f(mesh->uv[index].x, mesh->uv[index].y);
|
||||
|
||||
glVertex3f( interpolate(point1->x, point2->x),
|
||||
interpolate(point1->y, point2->y),
|
||||
interpolate(point1->z, point2->z));
|
||||
};
|
||||
};
|
||||
glEnd();
|
||||
}
|
||||
|
||||
#define ip(r, c,n) (r) = (c) + t * ((n) - (c))
|
||||
#define ip_vec(c,n) ip(c.x,c.x,n.x); ip(c.y,c.y,n.y); ip(c.z,c.z,n.z);
|
||||
loopi(numTags)
|
||||
};
|
||||
|
||||
loopi(numtags) // render the linked models - interpolate rotation and position of the 'link-tags'
|
||||
{
|
||||
md3model *link = links[i];
|
||||
if(!link) continue;
|
||||
vec pos = tags[a->frm * numTags + i].pos;
|
||||
vec nextpos = tags[nextfrm * numTags + i].pos;
|
||||
ip_vec(pos, nextpos);
|
||||
float rot[3][3];
|
||||
loop(j, 3) loop(k, 3) ip(rot[j][k], tags[a->frm * numTags + i].rotation[j][k], tags[nextfrm * numTags + i].rotation[j][k]);
|
||||
GLfloat matrix[16];
|
||||
matrix[0] = rot[0][0];
|
||||
matrix[1] = rot[0][1];
|
||||
matrix[2] = rot[0][2];
|
||||
matrix[3] = 0;
|
||||
matrix[4] = rot[1][0];
|
||||
matrix[5] = rot[1][1];
|
||||
matrix[6] = rot[1][2];
|
||||
matrix[7] = 0;
|
||||
matrix[8] = rot[2][0];
|
||||
matrix[9] = rot[2][1];
|
||||
matrix[10]= rot[2][2];
|
||||
matrix[11]= 0;
|
||||
matrix[12] = pos.x;
|
||||
matrix[13] = pos.y;
|
||||
matrix[14] = pos.z;
|
||||
matrix[15] = 1;
|
||||
GLfloat matrix[16] = {0}; // fixme: un-obfuscate it!
|
||||
loopj(3) matrix[j] = interpolate(tags[a->frm * numtags + i].rotation[0][j], tags[nextfrm * numtags + i].rotation[0][j]); // rotation
|
||||
loopj(3) matrix[4 + j] = interpolate(tags[a->frm * numtags + i].rotation[1][j], tags[nextfrm * numtags + i].rotation[1][j]);
|
||||
loopj(3) matrix[8 + j] = interpolate(tags[a->frm * numtags + i].rotation[2][j], tags[nextfrm * numtags + i].rotation[2][j]);
|
||||
loopj(3) matrix[12 + j] = interpolate(tags[a->frm * numtags + i].pos[j] , tags[nextfrm * numtags + i].pos[j]); // position
|
||||
matrix[15] = 1.0f;
|
||||
glPushMatrix();
|
||||
glMultMatrixf(matrix);
|
||||
link->render();
|
||||
@@ -354,33 +261,17 @@ void md3model::render()
|
||||
|
||||
void md3model::draw(float x, float y, float z, float yaw, float pitch, float rad)
|
||||
{
|
||||
if(!loaded || objects.length() <= 0) return;
|
||||
//if(isoccluded(player1->o.x, player1->o.y, x-rad, z-rad, rad*2)) return;
|
||||
|
||||
glPushMatrix();
|
||||
|
||||
int ix = (int)x;
|
||||
int iy = (int)z;
|
||||
vec light = { 1.0f, 1.0f, 1.0f };
|
||||
if(!OUTBORD(ix, iy))
|
||||
{
|
||||
sqr *s = S(ix,iy);
|
||||
float ll = 256.0f; // 0.96f;
|
||||
float of = 0.0f; // 0.1f;
|
||||
light.x = 0.75f * s->r/ll+of;
|
||||
light.y = 0.75f * s->g/ll+of;
|
||||
light.z = 0.75f * s->b/ll+of;
|
||||
};
|
||||
glColor3fv((float *)&light);
|
||||
|
||||
glTranslatef(x, y, z); // avoid models above ground
|
||||
glTranslatef(x, y, z);
|
||||
|
||||
glRotatef(yaw+180, 0, -1, 0);
|
||||
glRotatef(pitch, 0, 0, 1);
|
||||
|
||||
glRotatef(-90, 0, 1, 0);
|
||||
glRotatef(-90, 1, 0, 0);
|
||||
|
||||
glScalef( scale, scale, scale);
|
||||
glTranslatef( 0.0f, 0.0f, 24.0f );
|
||||
glScalef( scale.x, scale.y, scale.z);
|
||||
|
||||
render();
|
||||
|
||||
@@ -400,23 +291,24 @@ void md3setanim(dynent *d, int anim)
|
||||
d->animstate[MDL_LOWER].anim = anim - 7;
|
||||
};
|
||||
|
||||
vector<md3model *> playermodels;
|
||||
vector<md3model *> weaponmodels;
|
||||
vector<md3model *> models;
|
||||
vector<md3animinfo> tmp_animations;
|
||||
int firstweapon = -1;
|
||||
int numskins = 0;
|
||||
char basedir[_MAXDEFSTR]; // necessary for relative path's
|
||||
|
||||
void md3skin(char *objname, char *skin) // called by the {lower|upper|head}.cfg (originally .skin in Q3A)
|
||||
{
|
||||
md3model *mdl = playermodels.last();
|
||||
loopv(mdl->objects)
|
||||
md3model *mdl = models.last();
|
||||
loopv(mdl->meshes)
|
||||
{
|
||||
md3object *obj = &mdl->objects[i];
|
||||
if(strcmp(obj->name, objname) == 0)
|
||||
md3mesh *mesh = &mdl->meshes[i];
|
||||
if(strcmp(mesh->name, objname) == 0)
|
||||
{
|
||||
int xs, ys;
|
||||
sprintf_sd(path)("%s/%s", basedir, skin); // 'skin' is a relative url
|
||||
installtex(FIRSTMD3 + numskins, path, xs, ys);
|
||||
obj->tex = numskins;
|
||||
mesh->tex = numskins;
|
||||
numskins++;
|
||||
};
|
||||
};
|
||||
@@ -428,86 +320,39 @@ void md3animation(char *first, char *nums, char *loopings, char *fps) /* configu
|
||||
{
|
||||
md3animinfo &a = tmp_animations.add();
|
||||
a.start = atoi(first);
|
||||
a.end = a.start + atoi(nums);
|
||||
a.end = a.start + atoi(nums) - 1;
|
||||
(atoi(loopings) > 0) ? a.loop = true : a.loop = false;
|
||||
a.fps = atoi(fps);
|
||||
};
|
||||
|
||||
COMMAND(md3animation, ARG_5STR);
|
||||
|
||||
/*
|
||||
void rendermd3(char *mdl, float x, float y, float z, float yaw, float pitch, float rad)
|
||||
{
|
||||
if(playermodels.length()) playermodels[MDL_LOWER]->draw(x, y, z, yaw, pitch, rad);
|
||||
};*/
|
||||
|
||||
VAR(anim, 0, 0, 1000);
|
||||
|
||||
void rendermd3player(dynent *d)
|
||||
{
|
||||
if(playermodels.length() >= 3 && d->mdl[MDL_LOWER] == 0)
|
||||
{
|
||||
loopi(3) playermodels[d->mdl[i]]->animstate = &d->animstate[i]; // get d's current
|
||||
|
||||
md3setanim(d, anim);
|
||||
|
||||
int n;
|
||||
float mz = d->o.z-d->eyeheight+1.55f;
|
||||
/*if(d->state==CS_DEAD)
|
||||
{
|
||||
|
||||
md3setanim(d, BOTH_DEATH1 + rnd(2) * 2);
|
||||
//mdl = (((int)d>>6)&1)+1;
|
||||
//mz = d->o.z-d->eyeheight+0.2f;
|
||||
//scale = 1.2f;
|
||||
}
|
||||
else if(d->state==CS_EDITING) { md3setanim(d, TORSO_STAND); }
|
||||
else if(d->state==CS_LAGGED) { md3setanim(d, LEGS_IDLE); md3setanim(d, TORSO_GESTURE); }
|
||||
else if(d->monsterstate==M_ATTACKING) { n = 8; }
|
||||
else if(d->monsterstate==M_PAIN) { n = 10; }
|
||||
else if((!d->move && !d->strafe) || !d->moving) { md3setanim(d, LEGS_IDLE); md3setanim(d, TORSO_STAND); }
|
||||
else if(!d->onfloor && d->timeinair>100) { md3setanim(d, LEGS_JUMP ); }
|
||||
else { n = 14; }; */
|
||||
|
||||
playermodels[d->mdl[MDL_LOWER]]->draw(d->o.x, mz, d->o.y, d->yaw+90, d->pitch, d->radius);
|
||||
};
|
||||
};
|
||||
|
||||
void testrender(float x, float y, float z, float yaw, float pitch, float radius)
|
||||
{
|
||||
if(playermodels.length())
|
||||
{
|
||||
playermodels[0]->draw(x, z, y, yaw+90, pitch, radius);
|
||||
};
|
||||
};
|
||||
|
||||
md3model *loadmd3(char *path) // loads a single md3 model and the skins for its objects (cfg file)
|
||||
{
|
||||
md3model *mdl = new md3model();
|
||||
playermodels.add(mdl);
|
||||
sprintf_sd(mdl_path)("%s.md3", path);
|
||||
sprintf_sd(cfg_path)("%s.cfg", path);
|
||||
playermodels.last()->load(mdl_path);
|
||||
exec(cfg_path);
|
||||
return playermodels.last();
|
||||
};
|
||||
|
||||
char pl_objects[3][6] = {"lower", "upper", "head"};
|
||||
|
||||
void loadplayermdl(char *model)
|
||||
{
|
||||
char pl_objects[3][6] = {"lower", "upper", "head"};
|
||||
tmp_animations.setsize(0);
|
||||
sprintf(basedir, "packages/models/playermodels/%s", model);
|
||||
sprintf(basedir, "packages/models/players/%s", model);
|
||||
md3model *mdls[3];
|
||||
loopi(3) // load lower,upper and head objects
|
||||
loopi(3) // load lower,upper and head models
|
||||
{
|
||||
sprintf_sd(path)("%s/%s", basedir, pl_objects[i]);
|
||||
mdls[i] = loadmd3(path);
|
||||
mdls[i] = new md3model();
|
||||
models.add(mdls[i]);
|
||||
sprintf_sd(mdl_path)("%s.md3", path);
|
||||
sprintf_sd(cfg_path)("%s.cfg", path);
|
||||
mdls[i]->load(mdl_path);
|
||||
exec(cfg_path);
|
||||
};
|
||||
//mdls[MDL_LOWER]->link(mdls[MDL_UPPER], "tag_torso");
|
||||
//mdls[MDL_UPPER]->link(mdls[MDL_HEAD], "tag_head");
|
||||
sprintf_sd(modelcfg)("%s/model.cfg", basedir);
|
||||
mdls[MDL_LOWER]->link(mdls[MDL_UPPER], "tag_torso");
|
||||
mdls[MDL_UPPER]->link(mdls[MDL_HEAD], "tag_head");
|
||||
sprintf_sd(modelcfg)("%s/animation.cfg", basedir);
|
||||
exec(modelcfg); // load animations to tmp_animation
|
||||
int skip_gap = tmp_animations[LEGS_WALKCR].start - tmp_animations[TORSO_GESTURE].start;
|
||||
for(int i = LEGS_WALKCR; i < tmp_animations.length(); i++) // the upper and lower mdl frames are independent
|
||||
{
|
||||
tmp_animations[i].start -= skip_gap;
|
||||
tmp_animations[i].end -= skip_gap;
|
||||
};
|
||||
loopv(tmp_animations) // assign the loaded animations to the lower,upper or head model
|
||||
{
|
||||
md3animinfo &anim = tmp_animations[i];
|
||||
@@ -525,8 +370,90 @@ void loadplayermdl(char *model)
|
||||
|
||||
COMMAND(loadplayermdl, ARG_1STR);
|
||||
|
||||
void test1()
|
||||
enum {MDL_GUN_IDLE, MDL_GUN_RELOAD, NUM_MDL_GUN};
|
||||
/*md3animinfo weaponsanim[] = { {0, 8, 8, 25},
|
||||
{8, 15, 0, 25},
|
||||
{16,25, 0, 25} };*/
|
||||
|
||||
md3animinfo weaponsanim[] = { {0, 8, 8, 25},
|
||||
{8, 25, 0, 25} };
|
||||
|
||||
void loadweapons()
|
||||
{
|
||||
md3model test;
|
||||
test.load("packages/models/playermodels/lara/lower.md3");
|
||||
}; COMMAND(test1, ARG_NONE);
|
||||
firstweapon = models.length();
|
||||
loopi(NUMGUNS)
|
||||
{
|
||||
sprintf(basedir, "packages/models/weapons/%s", hudgunnames[i]);
|
||||
md3model *mdl = new md3model();
|
||||
models.add(mdl);
|
||||
sprintf_sd(mdl_path)("%s/tris_high.md3", basedir);
|
||||
sprintf_sd(cfg_path)("%s/default.skin", basedir);
|
||||
mdl->load(mdl_path);
|
||||
exec(cfg_path);
|
||||
loopj(NUM_MDL_GUN) mdl->animations.add(weaponsanim[j]);
|
||||
}
|
||||
};
|
||||
|
||||
COMMAND(loadweapons, ARG_NONE);
|
||||
|
||||
void rendermd3gun()
|
||||
{
|
||||
if(firstweapon >= 0)
|
||||
{
|
||||
md3model *weapon = models[firstweapon + player1->gunselect];
|
||||
int rtime = reloadtime(player1->gunselect);
|
||||
if(player1->reloading)
|
||||
{
|
||||
weapon->animstate = new md3state();
|
||||
weapon->animstate->anim = MDL_GUN_RELOAD;
|
||||
}
|
||||
else
|
||||
{
|
||||
weapon->animstate = new md3state();
|
||||
weapon->animstate->anim = MDL_GUN_IDLE;
|
||||
};
|
||||
float kick = 0.0f;
|
||||
if(player1->gunselect==player1->lastattackgun)
|
||||
{
|
||||
int percent_done = (lastmillis-player1->lastaction)*100/reloadtime(player1->gunselect);
|
||||
if(percent_done > 100) percent_done = 100.0;
|
||||
// f(x) = -sin(x-1.5)^3
|
||||
kick = -sin(pow((1.5f/100*percent_done)-1.5f,3));
|
||||
};
|
||||
vdist(dist, unitv, player1->o, worldpos);
|
||||
vdiv(unitv, dist);
|
||||
float k_rot = kick_rot(player1->gunselect)*kick;
|
||||
float k_back = kick_back(player1->gunselect)*kick/10;
|
||||
weapon->draw(player1->o.x-unitv.x*k_back, player1->o.z-unitv.z*k_back, player1->o.y-unitv.y*k_back, player1->yaw + 90, player1->pitch+k_rot, 1.0f);
|
||||
};
|
||||
};
|
||||
|
||||
void rendermd3player(dynent *d)
|
||||
{
|
||||
if(models.length() >= 3)
|
||||
{
|
||||
loopi(3) models[i]->animstate = &d->animstate[i];
|
||||
|
||||
float mz = d->o.z-d->eyeheight+1.55f;
|
||||
|
||||
if(d->state == CS_DEAD) { md3setanim(d, BOTH_DEATH1); }
|
||||
else if(d->state == CS_EDITING) { md3setanim(d, LEGS_IDLECR); md3setanim(d, TORSO_GESTURE); }
|
||||
else if(d->state == CS_LAGGED) { md3setanim(d, LEGS_IDLECR); md3setanim(d, TORSO_DROP); }
|
||||
else
|
||||
{
|
||||
if(!d->onfloor && d->timeinair>100) { md3setanim(d, LEGS_JUMP); }
|
||||
else if((!d->move && !d->strafe)) { md3setanim(d, LEGS_IDLE); }
|
||||
else { md3setanim(d, LEGS_RUN); }
|
||||
|
||||
if(d->attacking) { md3setanim(d, TORSO_ATTACK2); }
|
||||
else { md3setanim(d, TORSO_STAND); }
|
||||
};
|
||||
if(d->gunselect >= models.length())
|
||||
models[MDL_UPPER]->link(NULL, "tag_weapon"); // no weapon model
|
||||
else
|
||||
models[MDL_UPPER]->link(models[d->gunselect], "tag_weapon"); // show current weapon
|
||||
|
||||
models[MDL_LOWER]->draw(d->o.x, mz, d->o.y, d->yaw+90, d->pitch/2, d->radius);
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user