cvar_t r_skeletal_debugtranslatex = {0, "r_skeletal_debugtranslatex", "1", "development cvar for testing skeletal model code"};
cvar_t r_skeletal_debugtranslatey = {0, "r_skeletal_debugtranslatey", "1", "development cvar for testing skeletal model code"};
cvar_t r_skeletal_debugtranslatez = {0, "r_skeletal_debugtranslatez", "1", "development cvar for testing skeletal model code"};
+cvar_t mod_alias_supporttagscale = {0, "mod_alias_supporttagscale", "1", "support scaling factors in bone/tag attachment matrices as supported by MD3"};
float mod_md3_sin[320];
Cvar_RegisterVariable(&r_skeletal_debugtranslatex);
Cvar_RegisterVariable(&r_skeletal_debugtranslatey);
Cvar_RegisterVariable(&r_skeletal_debugtranslatez);
+ Cvar_RegisterVariable(&mod_alias_supporttagscale);
for (i = 0;i < 320;i++)
mod_md3_sin[i] = sin(i * M_PI * 2.0f / 256.0);
}
-void Mod_Skeletal_AnimateVertices(const model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
+void Mod_Skeletal_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
{
#define MAX_BONES 256
// vertex weighted skeletal
int i, k;
+ int blends;
+ float desiredscale[3];
float boneposerelative[MAX_BONES][12];
+ float *matrix, m[12], bonepose[MAX_BONES][12];
+
// interpolate matrices and concatenate them to their parents
for (i = 0;i < model->num_bones;i++)
{
- int blends;
- float *matrix, m[12], bonepose[MAX_BONES][12];
for (k = 0;k < 12;k++)
m[k] = 0;
- for (blends = 0;blends < 4 && frameblend[blends].lerp > 0;blends++)
+ VectorClear(desiredscale);
+ for (blends = 0;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
{
- matrix = model->data_poses + (frameblend[blends].frame * model->num_bones + i) * 12;
+ matrix = model->data_poses + (frameblend[blends].subframe * model->num_bones + i) * 12;
for (k = 0;k < 12;k++)
m[k] += matrix[k] * frameblend[blends].lerp;
+ desiredscale[0] += frameblend[blends].lerp * VectorLength(matrix );
+ desiredscale[1] += frameblend[blends].lerp * VectorLength(matrix + 4);
+ desiredscale[2] += frameblend[blends].lerp * VectorLength(matrix + 8);
}
+ VectorNormalize(m );
+ VectorNormalize(m + 4);
+ VectorNormalize(m + 8);
+ VectorScale(m , desiredscale[0], m );
+ VectorScale(m + 4, desiredscale[1], m + 4);
+ VectorScale(m + 8, desiredscale[2], m + 8);
if (i == r_skeletal_debugbone.integer)
m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
m[3] *= r_skeletal_debugtranslatex.value;
// blend the vertex bone weights
// special case for the extremely common wf[0] == 1 because it saves 3 multiplies per array when compared to the other case (w[0] is always 1 if only one bone controls this vertex, artists only use multiple bones for certain special cases)
// special case for the first bone because it avoids the need to memset the arrays before filling
+ if (vertex3f)
{
const float *v = model->surfmesh.data_vertex3f;
const int *wi = model->surfmesh.data_vertexweightindex4i;
}
}
-void Mod_MD3_AnimateVertices(const model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
+void Mod_MD3_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
{
// vertex morph
int i, numblends, blendnum;
int numverts = model->surfmesh.num_vertices;
numblends = 0;
- for (blendnum = 0;blendnum < 4;blendnum++)
+ for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
{
//VectorMA(translate, model->surfmesh.num_morphmdlframetranslate, frameblend[blendnum].lerp, translate);
if (frameblend[blendnum].lerp > 0)
// special case for the first blend because it avoids some adds and the need to memset the arrays first
for (blendnum = 0;blendnum < numblends;blendnum++)
{
- const md3vertex_t *verts = model->surfmesh.data_morphmd3vertex + numverts * frameblend[blendnum].frame;
- float scale = frameblend[blendnum].lerp * (1.0f / 64.0f);
- if (blendnum == 0)
+ const md3vertex_t *verts = model->surfmesh.data_morphmd3vertex + numverts * frameblend[blendnum].subframe;
+ if (vertex3f)
{
- for (i = 0;i < numverts;i++)
+ float scale = frameblend[blendnum].lerp * (1.0f / 64.0f);
+ if (blendnum == 0)
{
- vertex3f[i * 3 + 0] = verts[i].origin[0] * scale;
- vertex3f[i * 3 + 1] = verts[i].origin[1] * scale;
- vertex3f[i * 3 + 2] = verts[i].origin[2] * scale;
+ for (i = 0;i < numverts;i++)
+ {
+ vertex3f[i * 3 + 0] = verts[i].origin[0] * scale;
+ vertex3f[i * 3 + 1] = verts[i].origin[1] * scale;
+ vertex3f[i * 3 + 2] = verts[i].origin[2] * scale;
+ }
}
- }
- else
- {
- for (i = 0;i < numverts;i++)
+ else
{
- vertex3f[i * 3 + 0] += verts[i].origin[0] * scale;
- vertex3f[i * 3 + 1] += verts[i].origin[1] * scale;
- vertex3f[i * 3 + 2] += verts[i].origin[2] * scale;
+ for (i = 0;i < numverts;i++)
+ {
+ vertex3f[i * 3 + 0] += verts[i].origin[0] * scale;
+ vertex3f[i * 3 + 1] += verts[i].origin[1] * scale;
+ vertex3f[i * 3 + 2] += verts[i].origin[2] * scale;
+ }
}
}
// the yaw and pitch stored in md3 models are 8bit quantized angles
}
if (svector3f)
{
- const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].frame;
+ const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
if (blendnum == 0)
{
}
}
-void Mod_MDL_AnimateVertices(const model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
+void Mod_MDL_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f)
{
// vertex morph
int i, numblends, blendnum;
numblends = 0;
// blend the frame translates to avoid redundantly doing so on each vertex
// (a bit of a brain twister but it works)
- for (blendnum = 0;blendnum < 4;blendnum++)
+ for (blendnum = 0;blendnum < MAX_FRAMEBLENDS;blendnum++)
{
if (model->surfmesh.data_morphmd2framesize6f)
- VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].frame * 6 + 3, translate);
+ VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6 + 3, translate);
else
VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.num_morphmdlframetranslate, translate);
if (frameblend[blendnum].lerp > 0)
// special case for the first blend because it avoids some adds and the need to memset the arrays first
for (blendnum = 0;blendnum < numblends;blendnum++)
{
- const trivertx_t *verts = model->surfmesh.data_morphmdlvertex + numverts * frameblend[blendnum].frame;
- float scale[3];
- if (model->surfmesh.data_morphmd2framesize6f)
- VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].frame * 6, frameblend[blendnum].lerp, scale);
- else
- VectorScale(model->surfmesh.num_morphmdlframescale, frameblend[blendnum].lerp, scale);
- if (blendnum == 0)
+ const trivertx_t *verts = model->surfmesh.data_morphmdlvertex + numverts * frameblend[blendnum].subframe;
+ if (vertex3f)
{
- for (i = 0;i < numverts;i++)
+ float scale[3];
+ if (model->surfmesh.data_morphmd2framesize6f)
+ VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].subframe * 6, frameblend[blendnum].lerp, scale);
+ else
+ VectorScale(model->surfmesh.num_morphmdlframescale, frameblend[blendnum].lerp, scale);
+ if (blendnum == 0)
{
- vertex3f[i * 3 + 0] = translate[0] + verts[i].v[0] * scale[0];
- vertex3f[i * 3 + 1] = translate[1] + verts[i].v[1] * scale[1];
- vertex3f[i * 3 + 2] = translate[2] + verts[i].v[2] * scale[2];
+ for (i = 0;i < numverts;i++)
+ {
+ vertex3f[i * 3 + 0] = translate[0] + verts[i].v[0] * scale[0];
+ vertex3f[i * 3 + 1] = translate[1] + verts[i].v[1] * scale[1];
+ vertex3f[i * 3 + 2] = translate[2] + verts[i].v[2] * scale[2];
+ }
}
- }
- else
- {
- for (i = 0;i < numverts;i++)
+ else
{
- vertex3f[i * 3 + 0] += verts[i].v[0] * scale[0];
- vertex3f[i * 3 + 1] += verts[i].v[1] * scale[1];
- vertex3f[i * 3 + 2] += verts[i].v[2] * scale[2];
+ for (i = 0;i < numverts;i++)
+ {
+ vertex3f[i * 3 + 0] += verts[i].v[0] * scale[0];
+ vertex3f[i * 3 + 1] += verts[i].v[1] * scale[1];
+ vertex3f[i * 3 + 2] += verts[i].v[2] * scale[2];
+ }
}
}
// the vertex normals in mdl models are an index into a table of
}
if (svector3f)
{
- const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].frame;
+ const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe;
float f = frameblend[blendnum].lerp * (1.0f / 127.0f);
if (blendnum == 0)
{
}
}
-int Mod_Alias_GetTagMatrix(const model_t *model, int poseframe, int tagindex, matrix4x4_t *outmatrix)
+int Mod_Alias_GetTagMatrix(const dp_model_t *model, int poseframe, int tagindex, matrix4x4_t *outmatrix)
{
const float *boneframe;
float tempbonematrix[12], bonematrix[12];
return 6;
Matrix4x4_FromArray12FloatGL(outmatrix, model->data_tags[poseframe * model->num_tags + tagindex].matrixgl);
}
+
+ if(!mod_alias_supporttagscale.integer)
+ Matrix4x4_Normalize3(outmatrix, outmatrix);
+
return 0;
}
-int Mod_Alias_GetTagIndexForName(const model_t *model, unsigned int skin, const char *tagname)
+int Mod_Alias_GetExtendedTagInfoForIndex(const dp_model_t *model, unsigned int skin, int poseframe, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix)
+{
+ const float *boneframe;
+
+ if(skin >= (unsigned int)model->numskins)
+ skin = 0;
+
+ if (model->num_bones)
+ {
+ if(tagindex >= model->num_bones || tagindex < 0)
+ return 1;
+ if (poseframe >= model->num_poses)
+ return 2;
+
+ boneframe = model->data_poses + poseframe * model->num_bones * 12;
+ *parentindex = model->data_bones[tagindex].parent;
+ *tagname = model->data_bones[tagindex].name;
+ Matrix4x4_FromArray12FloatD3D(tag_localmatrix, boneframe + tagindex * 12);
+ return 0;
+ }
+
+ if (model->num_tags)
+ {
+ if(tagindex >= model->num_tags || tagindex < 0)
+ return 1;
+ if (poseframe >= model->num_tagframes)
+ return 2;
+ *tagname = model->data_tags[tagindex].name;
+ Matrix4x4_FromArray12FloatGL(tag_localmatrix, model->data_tags[poseframe * model->num_tags + tagindex].matrixgl);
+ return 0;
+ }
+
+ return 2;
+}
+
+int Mod_Alias_GetTagIndexForName(const dp_model_t *model, unsigned int skin, const char *tagname)
{
int i;
if(skin >= (unsigned int)model->numskins)
skin = 0;
- if (model->data_overridetagnamesforskin && skin < (unsigned int)model->numskins && model->data_overridetagnamesforskin[(unsigned int)skin].num_overridetagnames)
- for (i = 0;i < model->data_overridetagnamesforskin[skin].num_overridetagnames;i++)
- if (!strcasecmp(tagname, model->data_overridetagnamesforskin[skin].data_overridetagnames[i].name))
- return i + 1;
if (model->num_bones)
for (i = 0;i < model->num_bones;i++)
if (!strcasecmp(tagname, model->data_bones[i].name))
{
int i, k;
double scale;
- float *basebonepose = Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(float[12]));
+ float *basebonepose;
float *in12f = loadmodel->data_poses;
- float *out12f = basebonepose;
+ float *out12f;
float *outinv12f = loadmodel->data_baseboneposeinverse;
+ if (!loadmodel->num_bones)
+ return;
+ out12f = basebonepose = (float *) Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(float[12]));
for (i = 0;i < loadmodel->num_bones;i++, in12f += 12, out12f += 12, outinv12f += 12)
{
if (loadmodel->data_bones[i].parent >= 0)
float dist, yawradius, radius;
float *v;
float *vertex3f;
- frameblend_t frameblend[4];
+ frameblend_t frameblend[MAX_FRAMEBLENDS];
memset(frameblend, 0, sizeof(frameblend));
frameblend[0].lerp = 1;
- vertex3f = Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
+ vertex3f = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]));
VectorClear(loadmodel->normalmins);
VectorClear(loadmodel->normalmaxs);
yawradius = 0;
radius = 0;
- for (frameblend[0].frame = 0;frameblend[0].frame < loadmodel->num_poses;frameblend[0].frame++)
+ for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++)
{
loadmodel->AnimateVertices(loadmodel, frameblend, vertex3f, NULL, NULL, NULL);
for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3)
radius = dist;
}
}
- Mem_Free(vertex3f);
+ if (vertex3f)
+ Mem_Free(vertex3f);
radius = sqrt(radius);
yawradius = sqrt(yawradius);
loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
static void Mod_Alias_MorphMesh_CompileFrames(void)
{
int i, j;
- frameblend_t frameblend[4] = {{0, 1}, {0, 0}, {0, 0}, {0, 0}};
+ frameblend_t frameblend[MAX_FRAMEBLENDS];
unsigned char *datapointer;
+ memset(frameblend, 0, sizeof(frameblend));
+ frameblend[0].lerp = 1;
datapointer = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * (sizeof(float[3]) * 4 + loadmodel->surfmesh.num_morphframes * sizeof(texvecvertex_t)));
loadmodel->surfmesh.data_vertex3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
loadmodel->surfmesh.data_svector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
// this counts down from the last frame to the first so that the final data in surfmesh is for frame zero (which is what the renderer expects to be there)
for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--)
{
- frameblend[0].frame = i;
+ frameblend[0].subframe = i;
loadmodel->AnimateVertices(loadmodel, frameblend, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL);
- Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, r_smoothnormals_areaweighting.integer);
+ Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, r_smoothnormals_areaweighting.integer != 0);
// encode the svector and tvector in 3 byte format for permanent storage
for (j = 0;j < loadmodel->surfmesh.num_vertices;j++)
{
- VectorScale(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
- VectorScale(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
+ VectorScaleCast(loadmodel->surfmesh.data_svector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].svec);
+ VectorScaleCast(loadmodel->surfmesh.data_tvector3f + j * 3, 127.0f, signed char, loadmodel->surfmesh.data_morphtexvecvertex[i*loadmodel->surfmesh.num_vertices+j].tvec);
}
}
}
-static void Mod_MDLMD2MD3_TraceBox(model_t *model, int frame, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask)
+static void Mod_MDLMD2MD3_TraceBox(dp_model_t *model, int frame, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask)
{
int i;
+ vec3_t shiftstart, shiftend;
float segmentmins[3], segmentmaxs[3];
- frameblend_t frameblend[4];
+ frameblend_t frameblend[MAX_FRAMEBLENDS];
msurface_t *surface;
static int maxvertices = 0;
static float *vertex3f = NULL;
trace->realfraction = 1;
trace->hitsupercontentsmask = hitsupercontentsmask;
memset(frameblend, 0, sizeof(frameblend));
- frameblend[0].frame = frame;
+ frameblend[0].subframe = frame;
frameblend[0].lerp = 1;
if (maxvertices < model->surfmesh.num_vertices)
{
maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
}
- if (VectorLength2(boxmins) + VectorLength2(boxmaxs) == 0)
+ if (VectorCompare(boxmins, boxmaxs))
{
// line trace
- segmentmins[0] = min(start[0], end[0]) - 1;
- segmentmins[1] = min(start[1], end[1]) - 1;
- segmentmins[2] = min(start[2], end[2]) - 1;
- segmentmaxs[0] = max(start[0], end[0]) + 1;
- segmentmaxs[1] = max(start[1], end[1]) + 1;
- segmentmaxs[2] = max(start[2], end[2]) + 1;
+ VectorAdd(start, boxmins, shiftstart);
+ VectorAdd(end, boxmins, shiftend);
+ segmentmins[0] = min(shiftstart[0], shiftend[0]) - 1;
+ segmentmins[1] = min(shiftstart[1], shiftend[1]) - 1;
+ segmentmins[2] = min(shiftstart[2], shiftend[2]) - 1;
+ segmentmaxs[0] = max(shiftstart[0], shiftend[0]) + 1;
+ segmentmaxs[1] = max(shiftstart[1], shiftend[1]) + 1;
+ segmentmaxs[2] = max(shiftstart[2], shiftend[2]) + 1;
for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
{
model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
- Collision_TraceLineTriangleMeshFloat(trace, start, end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, SUPERCONTENTS_SOLID, 0, surface->texture, segmentmins, segmentmaxs);
+ Collision_TraceLineTriangleMeshFloat(trace, shiftstart, shiftend, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
}
}
else
vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
}
model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL);
- Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, SUPERCONTENTS_SOLID, 0, surface->texture, segmentmins, segmentmaxs);
+ Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
}
}
}
texture->currentmaterialflags = texture->basematerialflags;
}
-static void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, char *meshname, char *shadername)
+static void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
{
int i;
skinfileitem_t *skinfileitem;
{
// don't render unmentioned meshes
Mod_BuildAliasSkinFromSkinFrame(skin, NULL);
- skin->basematerialflags = skin->currentmaterialflags = 0;
+ skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW;
}
}
}
#define BOUNDI(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid ##VALUE (%d exceeds %d - %d)", loadmodel->name, VALUE, MIN, MAX);
#define BOUNDF(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid ##VALUE (%f exceeds %f - %f)", loadmodel->name, VALUE, MIN, MAX);
-void Mod_IDP0_Load(model_t *mod, void *buffer, void *bufferend)
+void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
{
int i, j, version, totalskins, skinwidth, skinheight, groupframes, groupskins, numverts;
float scales, scalet, interval;
loadmodel->Draw = R_Q1BSP_Draw;
loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
+ loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
loadmodel->DrawLight = R_Q1BSP_DrawLight;
loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int));
loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
- loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
- loadmodel->surfacelist[0] = 0;
+ loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
+ loadmodel->sortedmodelsurfaces[0] = 0;
loadmodel->numskins = LittleLong(pinmodel->numskins);
BOUNDI(loadmodel->numskins,0,65536);
loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = vertst[i*2+1];
}
+ // generate ushort elements array if possible
+ if (loadmodel->surfmesh.num_vertices <= 65536)
+ {
+ loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
+ for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
+ loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
+ }
+
// load the frames
loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)Mem_Alloc(loadmodel->mempool, sizeof(trivertx_t) * loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices);
// load the skins
skinfiles = Mod_LoadSkinFiles();
- loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
- loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
- loadmodel->num_texturesperskin = loadmodel->num_surfaces;
- loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
if (skinfiles)
{
+ loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
+ loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
+ loadmodel->num_texturesperskin = loadmodel->num_surfaces;
+ loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
Mod_FreeSkinFiles(skinfiles);
for (i = 0;i < loadmodel->numskins;i++)
}
else
{
+ loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
+ loadmodel->num_textures = loadmodel->num_surfaces * totalskins;
+ loadmodel->num_texturesperskin = loadmodel->num_surfaces;
+ loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * totalskins * sizeof(texture_t));
totalskins = 0;
datapointer = startskins;
for (i = 0;i < loadmodel->numskins;i++)
}
}
- sprintf(loadmodel->skinscenes[i].name, "skin %i", i);
+ dpsnprintf(loadmodel->skinscenes[i].name, sizeof(loadmodel->skinscenes[i].name), "skin %i", i);
loadmodel->skinscenes[i].firstframe = totalskins;
loadmodel->skinscenes[i].framecount = groupskins;
loadmodel->skinscenes[i].framerate = 1.0f / interval;
for (j = 0;j < groupskins;j++)
{
if (groupskins > 1)
- sprintf (name, "%s_%i_%i", loadmodel->name, i, j);
+ dpsnprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i, j);
else
- sprintf (name, "%s_%i", loadmodel->name, i);
+ dpsnprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
if (!Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, name, false, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS))
Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, R_SkinFrame_LoadInternalQuake(name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP, true, r_fullbrights.integer, (unsigned char *)datapointer, skinwidth, skinheight));
datapointer += skinwidth * skinheight;
loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
}
-void Mod_IDP2_Load(model_t *mod, void *buffer, void *bufferend)
+void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
{
int i, j, hashindex, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end;
float iskinwidth, iskinheight;
loadmodel->Draw = R_Q1BSP_Draw;
loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
+ loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
loadmodel->DrawLight = R_Q1BSP_DrawLight;
loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->numframes * sizeof(animscene_t) + loadmodel->numframes * sizeof(float[6]) + loadmodel->surfmesh.num_triangles * sizeof(int[3]) + loadmodel->surfmesh.num_triangles * sizeof(int[3]));
loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
- loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
- loadmodel->surfacelist[0] = 0;
+ loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
+ loadmodel->sortedmodelsurfaces[0] = 0;
loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
Mem_Free(md2verthash);
Mem_Free(md2verthashdata);
+ // generate ushort elements array if possible
+ if (loadmodel->surfmesh.num_vertices <= 65536)
+ {
+ loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
+ for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
+ loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
+ }
+
// load the frames
datapointer = (base + LittleLong(pinmodel->ofs_frames));
for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
}
-void Mod_IDP3_Load(model_t *mod, void *buffer, void *bufferend)
+void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
{
int i, j, k, version, meshvertices, meshtriangles;
unsigned char *data;
loadmodel->Draw = R_Q1BSP_Draw;
loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
+ loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
loadmodel->DrawLight = R_Q1BSP_DrawLight;
loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
loadmodel->num_texturesperskin = loadmodel->num_surfaces;
- data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + meshtriangles * sizeof(int[3]) + meshvertices * sizeof(float[2]) + meshvertices * loadmodel->numframes * sizeof(md3vertex_t));
+ data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshvertices * sizeof(float[2]) + meshvertices * loadmodel->numframes * sizeof(md3vertex_t));
loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
- loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
+ loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
loadmodel->surfmesh.num_vertices = meshvertices;
loadmodel->surfmesh.num_triangles = meshtriangles;
loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t);
+ if (meshvertices <= 65536)
+ {
+ loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
+ for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
+ loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
+ }
meshvertices = 0;
meshtriangles = 0;
{
if (memcmp(pinmesh->identifier, "IDP3", 4))
Host_Error("Mod_IDP3_Load: invalid mesh identifier (not IDP3)");
- loadmodel->surfacelist[i] = i;
+ loadmodel->sortedmodelsurfaces[i] = i;
surface = loadmodel->data_surfaces + i;
surface->texture = loadmodel->data_textures + i;
surface->num_firsttriangle = meshtriangles;
Mod_Alias_MorphMesh_CompileFrames();
Mod_Alias_CalculateBoundingBox();
Mod_FreeSkinFiles(skinfiles);
+ Mod_MakeSortedSurfaces(loadmodel);
loadmodel->surfmesh.isanimated = loadmodel->numframes > 1
|| (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
}
-void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer, void *bufferend)
+void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
{
zymtype1header_t *pinmodel, *pheader;
unsigned char *pbase;
loadmodel->Draw = R_Q1BSP_Draw;
loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
+ loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
loadmodel->DrawLight = R_Q1BSP_DrawLight;
//zymlump_t lump_bones; // zymbone_t bone[numbones];
loadmodel->num_bones = pheader->numbones;
- loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, pheader->numbones * sizeof(aliasbone_t));
+ loadmodel->data_bones = (aliasbone_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_bones * sizeof(aliasbone_t));
bone = (zymbone_t *) (pheader->lump_bones.start + pbase);
for (i = 0;i < pheader->numbones;i++)
{
Host_Error("%s bonecount[%i] != 1 (vertex weight support is impossible in this format)", loadmodel->name, i);
}
- loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]);
+ loadmodel->num_poses = pheader->lump_poses.length / sizeof(float[3][4]) / loadmodel->num_bones;
meshvertices = pheader->numverts;
meshtriangles = pheader->numtris;
loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
loadmodel->num_texturesperskin = loadmodel->num_surfaces;
- data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + meshtriangles * sizeof(int[3]) + meshvertices * sizeof(float[14]) + meshvertices * sizeof(int[4]) + meshvertices * sizeof(float[4]) + loadmodel->num_poses * sizeof(float[12]) + loadmodel->num_bones * sizeof(float[12]));
+ data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshvertices * sizeof(float[14]) + meshvertices * sizeof(int[4]) + meshvertices * sizeof(float[4]) + loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]) + loadmodel->num_bones * sizeof(float[12]));
loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
- loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
+ loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
loadmodel->surfmesh.num_vertices = meshvertices;
loadmodel->surfmesh.num_triangles = meshtriangles;
loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
- loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
+ loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
+ if (loadmodel->surfmesh.num_vertices <= 65536)
+ {
+ loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
+ for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
+ loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
+ }
//zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
poses = (float *) (pheader->lump_poses.start + pbase);
if (renderlist + count * 3 > renderlistend || (i == pheader->numshaders - 1 && renderlist + count * 3 != renderlistend))
Host_Error("%s corrupt renderlist (wrong size)", loadmodel->name);
- loadmodel->surfacelist[i] = i;
+ loadmodel->sortedmodelsurfaces[i] = i;
surface = loadmodel->data_surfaces + i;
surface->texture = loadmodel->data_textures + i;
surface->num_firsttriangle = meshtriangles;
Mod_FreeSkinFiles(skinfiles);
Mem_Free(vertbonecounts);
Mem_Free(verts);
+ Mod_MakeSortedSurfaces(loadmodel);
// compute all the mesh information that was not loaded from the file
Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
}
-void Mod_DARKPLACESMODEL_Load(model_t *mod, void *buffer, void *bufferend)
+void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
{
dpmheader_t *pheader;
dpmframe_t *frame;
loadmodel->Draw = R_Q1BSP_Draw;
loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
+ loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
loadmodel->DrawLight = R_Q1BSP_DrawLight;
for (i = 0;i < (int)pheader->num_meshs;i++)
{
int numverts = BigLong(dpmmesh->num_verts);
- meshvertices += numverts;;
+ meshvertices += numverts;
meshtriangles += BigLong(dpmmesh->num_tris);
dpmmesh++;
}
loadmodel->numframes = pheader->num_frames;
loadmodel->num_bones = pheader->num_bones;
- loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
+ loadmodel->num_poses = loadmodel->numframes;
loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
loadmodel->num_texturesperskin = loadmodel->num_surfaces;
// do most allocations as one merged chunk
- data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + meshtriangles * sizeof(int[3]) + meshvertices * (sizeof(float[14]) + sizeof(int[4]) + sizeof(float[4])) + loadmodel->num_poses * sizeof(float[12]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
+ data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshtriangles * sizeof(int[3]) + meshvertices * (sizeof(float[14]) + sizeof(int[4]) + sizeof(float[4])) + loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
- loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
+ loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
loadmodel->surfmesh.num_vertices = meshvertices;
loadmodel->surfmesh.num_triangles = meshtriangles;
loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
- loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
+ loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
+ if (meshvertices <= 65536)
+ {
+ loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
+ for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
+ loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
+ }
for (i = 0;i < loadmodel->numskins;i++)
{
const float *intexcoord;
msurface_t *surface;
- loadmodel->surfacelist[i] = i;
+ loadmodel->sortedmodelsurfaces[i] = i;
surface = loadmodel->data_surfaces + i;
surface->texture = loadmodel->data_textures + i;
surface->num_firsttriangle = meshtriangles;
}
Z_Free(bonepose);
Mod_FreeSkinFiles(skinfiles);
+ Mod_MakeSortedSurfaces(loadmodel);
// compute all the mesh information that was not loaded from the file
Mod_BuildBaseBonePoses();
// no idea why PSK/PSA files contain weird quaternions but they do...
#define PSKQUATNEGATIONS
-void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend)
+void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
{
int i, j, index, version, recordsize, numrecords, meshvertices, meshtriangles;
int numpnts, numvtxw, numfaces, nummatts, numbones, numrawweights, numanimbones, numanims, numanimkeys;
pskchunk_t *pchunk;
skinfile_t *skinfiles;
char animname[MAX_QPATH];
+ size_t size;
pchunk = (pskchunk_t *)buffer;
if (strcmp(pchunk->id, "ACTRHEAD"))
loadmodel->Draw = R_Q1BSP_Draw;
loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
+ loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
loadmodel->DrawLight = R_Q1BSP_DrawLight;
if (loadmodel->numskins < 1)
loadmodel->numskins = 1;
loadmodel->num_bones = numbones;
- loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
+ loadmodel->num_poses = loadmodel->numframes;
loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts;
loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
loadmodel->num_texturesperskin = loadmodel->num_surfaces;
+ loadmodel->surfmesh.num_vertices = meshvertices;
+ loadmodel->surfmesh.num_triangles = meshtriangles;
// do most allocations as one merged chunk
- data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + meshtriangles * sizeof(int[3]) + meshvertices * (sizeof(float[14]) + sizeof(int[4]) + sizeof(float[4])) + loadmodel->num_poses * sizeof(float[12]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
+ size = loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + loadmodel->surfmesh.num_triangles * sizeof(int[3]) + loadmodel->surfmesh.num_triangles * sizeof(int[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[3]) + loadmodel->surfmesh.num_vertices * sizeof(float[2]) + loadmodel->surfmesh.num_vertices * sizeof(int[4]) + loadmodel->surfmesh.num_vertices * sizeof(float[4]) + loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t) + ((loadmodel->surfmesh.num_vertices <= 65536) ? (loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3])) : 0);
+ data = (unsigned char *)Mem_Alloc(loadmodel->mempool, size);
loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
- loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
+ loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t);
- loadmodel->surfmesh.num_vertices = meshvertices;
- loadmodel->surfmesh.num_triangles = meshtriangles;
- loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
- loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
- loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
- loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
- loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
- loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
- loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
- loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
- loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
- loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
+ loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
+ loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
+ loadmodel->surfmesh.data_vertex3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
+ loadmodel->surfmesh.data_svector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
+ loadmodel->surfmesh.data_tvector3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
+ loadmodel->surfmesh.data_normal3f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[3]);
+ loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
+ loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += loadmodel->surfmesh.num_vertices * sizeof(int[4]);
+ loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[4]);
+ loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]);
loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
+ if (loadmodel->surfmesh.num_vertices <= 65536)
+ {
+ loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
+ for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
+ loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
+ }
for (i = 0;i < loadmodel->numskins;i++)
{
{
// since psk models do not have named sections, reuse their shader name as the section name
Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name);
- loadmodel->surfacelist[index] = index;
+ loadmodel->sortedmodelsurfaces[index] = index;
loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index;
loadmodel->data_surfaces[index].num_firstvertex = 0;
loadmodel->data_surfaces[index].num_vertices = loadmodel->surfmesh.num_vertices;
}
Mod_FreeSkinFiles(skinfiles);
Mem_Free(animfilebuffer);
+ Mod_MakeSortedSurfaces(loadmodel);
// compute all the mesh information that was not loaded from the file
// TODO: honor smoothing groups somehow?
loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
}
+void Mod_OBJ_Load(dp_model_t *mod, void *buffer, void *bufferend)
+{
+#if 0
+ const char *textbase = (char *)buffer, *text = textbase;
+ char *s;
+ char *argv[512];
+ char line[1024];
+ char materialname[MAX_QPATH];
+ int j, index1, index2, index3, first, prev, index;
+ int argc;
+ int linelen;
+ int numtriangles = 0;
+ int maxtriangles = 32768;
+ int *element3i = Mem_Alloc(tempmempool, maxtriangles * sizeof(int[3]));
+ int *oldelement3i;
+ int numsurfaces = 0;
+ int maxsurfaces = 0;
+ msurface_t *surfaces = NULL;
+ int linenumber = 0;
+ int hashindex;
+ float *v, *vt, *vn;
+ float *oldv, *oldvt, *oldvn;
+ int maxv = 65536, numv = 1;
+ int maxvt = 65536, numvt = 1;
+ int maxvn = 65536, numvn = 1;
+ int maxverthash = 65536, numverthash = 0;
+ int numhashindex = 65536;
+ struct objverthash_s
+ {
+ struct objverthash_s *next;
+ int s;
+ int v;
+ int vt;
+ int vn;
+ }
+ *hash, **verthash = Mem_Alloc(tempmempool, numhashindex * sizeof(*verthash)), *verthashdata = Mem_Alloc(tempmempool, maxverthash * sizeof(*verthashdata)), *oldverthashdata;
+ skinfile_t *skinfiles;
+
+ dpsnprintf(materialname, sizeof(materialname), "%s", loadmodel->name);
+
+ skinfiles = Mod_LoadSkinFiles();
+
+ loadmodel->modeldatatypestring = "OBJ";
+
+ loadmodel->type = mod_alias;
+ loadmodel->AnimateVertices = NULL;
+ loadmodel->DrawSky = NULL;
+ loadmodel->DrawAddWaterPlanes = NULL;
+ loadmodel->Draw = R_Q1BSP_Draw;
+ loadmodel->DrawDepth = R_Q1BSP_DrawDepth;
+ loadmodel->DrawDebug = R_Q1BSP_DrawDebug;
+ loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap;
+ loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
+ loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
+ loadmodel->DrawLight = R_Q1BSP_DrawLight;
+ loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
+ loadmodel->PointSuperContents = NULL;
+
+ // parse the OBJ text now
+ for(;;)
+ {
+ if (!*text)
+ break;
+ linenumber++;
+ linelen = 0;
+ for (linelen = 0;text[linelen] && text[linelen] != '\r' && text[linelen] != '\n';linelen++)
+ line[linelen] = text[linelen];
+ line[linelen] = 0;
+ for (argc = 0;argc < (int)(sizeof(argv)/sizeof(argv[0]));argc++)
+ argv[argc] = "";
+ argc = 0;
+ s = line;
+ while (*s == ' ' || *s == '\t')
+ s++;
+ while (*s)
+ {
+ argv[argc++] = s;
+ while (*s > ' ')
+ s++;
+ if (!*s)
+ break;
+ *s++ = 0;
+ while (*s == ' ' || *s == '\t')
+ s++;
+ }
+ if (!argc)
+ continue;
+ if (argv[0][0] == '#')
+ continue;
+ if (!strcmp(argv[0], "v"))
+ {
+ if (maxv <= numv)
+ {
+ maxv *= 2;
+ oldv = v;
+ v = Mem_Alloc(tempmempool, maxv * sizeof(float[3]));
+ if (oldv)
+ {
+ memcpy(v, oldv, numv * sizeof(float[3]));
+ Mem_Free(oldv);
+ }
+ }
+ v[numv*3+0] = atof(argv[1]);
+ v[numv*3+1] = atof(argv[2]);
+ v[numv*3+2] = atof(argv[3]);
+ numv++;
+ }
+ else if (!strcmp(argv[0], "vt"))
+ {
+ if (maxvt <= numvt)
+ {
+ maxvt *= 2;
+ oldvt = vt;
+ vt = Mem_Alloc(tempmempool, maxvt * sizeof(float[2]));
+ if (oldvt)
+ {
+ memcpy(vt, oldvt, numvt * sizeof(float[2]));
+ Mem_Free(oldvt);
+ }
+ }
+ vt[numvt*2+0] = atof(argv[1]);
+ vt[numvt*2+1] = atof(argv[2]);
+ numvt++;
+ }
+ else if (!strcmp(argv[0], "vn"))
+ {
+ if (maxvn <= numvn)
+ {
+ maxvn *= 2;
+ oldvn = vn;
+ vn = Mem_Alloc(tempmempool, maxvn * sizeof(float[3]));
+ if (oldvn)
+ {
+ memcpy(vn, oldvn, numvn * sizeof(float[3]));
+ Mem_Free(oldvn);
+ }
+ }
+ vn[numvn*3+0] = atof(argv[1]);
+ vn[numvn*3+1] = atof(argv[2]);
+ vn[numvn*3+2] = atof(argv[3]);
+ numvn++;
+ }
+ else if (!strcmp(argv[0], "f"))
+ {
+ if (!surface)
+ {
+ if (maxsurfaces <= numsurfaces)
+ {
+ maxsurfaces++;
+ oldsurfaces = surfaces;
+ surfaces = Mem_Alloc(tempmempool, maxsurfaces * sizeof(*surfaces));
+ if (oldsurfaces)
+ {
+ memcpy(surfaces, oldsurfaces, numsurfaces * sizeof(*surfaces));
+ Mem_Free(oldsurfaces);
+ }
+ }
+ surface = surfaces + numsurfaces++;
+ surface->
+ }
+ for (j = 1;j < argc;j++)
+ {
+ index1 = atoi(argv[j]);
+ while(argv[j][0] && argv[j][0] != '/')
+ argv[j]++;
+ if (argv[j][0])
+ argv[j]++;
+ if (index1 < 0)
+ index1 = numv + 1 - index1;
+ index2 = atoi(argv[j]);
+ if (index2 < 0)
+ index2 = numvt + 1 - index2;
+ while(argv[j][0] && argv[j][0] != '/')
+ argv[j]++;
+ if (argv[j][0])
+ argv[j]++;
+ index3 = atoi(argv[j]);
+ if (index3 < 0)
+ index3 = numvn + 1 - index3;
+ hashindex = (index1 + index2 * 3571 + index3 * 42589) & (numhashindex - 1);
+ for (hash = verthash[hashindex];hash;hash = hash->next)
+ if (hash->surface == numsurfaces-1 && hash->v == index1 && hash->vt == index2 && hash->vn == index3)
+ break;
+ if (!hash)
+ {
+ if (maxverthash <= numverthash)
+ {
+ maxverthash *= 2;
+ oldverthashdata = verthashdata;
+ verthashdata = Mem_Alloc(tempmempool, maxverthash * sizeof(*verthashdata));
+ if (oldverthashdata)
+ {
+ memcpy(verthashdata, oldverthashdata, numverthash * sizeof(*verthashdata));
+ Mem_Free(oldverthashdata);
+ }
+ }
+ hash = verthashdata + numverthash++;
+ hash->next = verthash[hashindex];
+ hash->s = numsurfaces;
+ hash->v = index1;
+ hash->vt = index2;
+ hash->vn = index3;
+ verthash[hashindex] = hash;
+ }
+ index = (int)((size_t)(hash - verthashdata));
+ if (j == 1)
+ first = index;
+ else if (j >= 3)
+ {
+ if (maxtriangles <= numtriangles)
+ {
+ maxtriangles *= 2;
+ oldelement3i = element3i;
+ element3i = Mem_Alloc(tempmempool, numtriangles * sizeof(int[3]));
+ if (oldelement3i)
+ {
+ memcpy(element3i, oldelement3i, numtriangles * sizeof(int[3]));
+ Mem_Free(oldelement3i);
+ }
+ }
+ element3i[numtriangles*3+0] = first;
+ element3i[numtriangles*3+1] = prev;
+ element3i[numtriangles*3+2] = index;
+ numtriangles++;
+ }
+ prev = index;
+ }
+ }
+ else if (!strcmp(argv[0], "o") || !strcmp(argv[0], "g"))
+ surface = NULL;
+ else if (!!strcmp(argv[0], "usemtl"))
+ {
+ surface = NULL;
+ strlcpy(materialname, argv[1], sizeof(materialname);
+ }
+ text += linelen;
+ if (*text == '\r')
+ text++;
+ if (*text == '\n')
+ text++;
+ }
+
+ if (skinfiles)
+ Mod_FreeSkinFiles(skinfiles);
+
+ // now that we have the OBJ data loaded as-is, we can convert it
+ loadmodel->numskins = LittleLong(pinmodel->num_skins);
+ numxyz = LittleLong(pinmodel->num_xyz);
+ numst = LittleLong(pinmodel->num_st);
+ loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris);
+ loadmodel->numframes = LittleLong(pinmodel->num_frames);
+ loadmodel->surfmesh.num_morphframes = loadmodel->numframes;
+ loadmodel->num_poses = loadmodel->surfmesh.num_morphframes;
+ skinwidth = LittleLong(pinmodel->skinwidth);
+ skinheight = LittleLong(pinmodel->skinheight);
+ iskinwidth = 1.0f / skinwidth;
+ iskinheight = 1.0f / skinheight;
+
+ loadmodel->num_surfaces = 1;
+ loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
+ data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->numframes * sizeof(animscene_t) + loadmodel->numframes * sizeof(float[6]) + loadmodel->surfmesh.num_triangles * sizeof(int[3]) + loadmodel->surfmesh.num_triangles * sizeof(int[3]));
+ loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
+ loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int);
+ loadmodel->sortedmodelsurfaces[0] = 0;
+ loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
+ loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]);
+ loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
+ loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]);
+
+ loadmodel->synctype = ST_RAND;
+
+ // load the skins
+ inskin = (char *)(base + LittleLong(pinmodel->ofs_skins));
+ skinfiles = Mod_LoadSkinFiles();
+ if (skinfiles)
+ {
+ loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
+ loadmodel->num_texturesperskin = loadmodel->num_surfaces;
+ loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
+ Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
+ Mod_FreeSkinFiles(skinfiles);
+ }
+ else if (loadmodel->numskins)
+ {
+ // skins found (most likely not a player model)
+ loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
+ loadmodel->num_texturesperskin = loadmodel->num_surfaces;
+ loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
+ for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
+ Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS);
+ }
+ else
+ {
+ // no skins (most likely a player model)
+ loadmodel->numskins = 1;
+ loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
+ loadmodel->num_texturesperskin = loadmodel->num_surfaces;
+ loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
+ Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
+ }
+
+ loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
+ for (i = 0;i < loadmodel->numskins;i++)
+ {
+ loadmodel->skinscenes[i].firstframe = i;
+ loadmodel->skinscenes[i].framecount = 1;
+ loadmodel->skinscenes[i].loop = true;
+ loadmodel->skinscenes[i].framerate = 10;
+ }
+
+ // load the triangles and stvert data
+ inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st));
+ intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris));
+ md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash));
+ md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash));
+ // swap the triangle list
+ loadmodel->surfmesh.num_vertices = 0;
+ for (i = 0;i < loadmodel->surfmesh.num_triangles;i++)
+ {
+ for (j = 0;j < 3;j++)
+ {
+ xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
+ st = (unsigned short) LittleShort (intri[i].index_st[j]);
+ if (xyz >= numxyz)
+ {
+ Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i);
+ xyz = 0;
+ }
+ if (st >= numst)
+ {
+ Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i);
+ st = 0;
+ }
+ hashindex = (xyz * 256 + st) & 65535;
+ for (hash = md2verthash[hashindex];hash;hash = hash->next)
+ if (hash->xyz == xyz && hash->st == st)
+ break;
+ if (hash == NULL)
+ {
+ hash = md2verthashdata + loadmodel->surfmesh.num_vertices++;
+ hash->xyz = xyz;
+ hash->st = st;
+ hash->next = md2verthash[hashindex];
+ md2verthash[hashindex] = hash;
+ }
+ loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata);
+ }
+ }
+
+ vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int));
+ data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[2]) + loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t));
+ loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]);
+ loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t);
+ for (i = 0;i < loadmodel->surfmesh.num_vertices;i++)
+ {
+ int sts, stt;
+ hash = md2verthashdata + i;
+ vertremap[i] = hash->xyz;
+ sts = LittleShort(inst[hash->st*2+0]);
+ stt = LittleShort(inst[hash->st*2+1]);
+ if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight)
+ {
+ Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i);
+ sts = 0;
+ stt = 0;
+ }
+ loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth;
+ loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight;
+ }
+
+ Mem_Free(md2verthash);
+ Mem_Free(md2verthashdata);
+
+ // generate ushort elements array if possible
+ if (loadmodel->surfmesh.num_vertices <= 65536)
+ {
+ loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles);
+ for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
+ loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
+ }
+
+ // load the frames
+ datapointer = (base + LittleLong(pinmodel->ofs_frames));
+ for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++)
+ {
+ int k;
+ trivertx_t *v;
+ trivertx_t *out;
+ pinframe = (md2frame_t *)datapointer;
+ datapointer += sizeof(md2frame_t);
+ // store the frame scale/translate into the appropriate array
+ for (j = 0;j < 3;j++)
+ {
+ loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]);
+ loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]);
+ }
+ // convert the vertices
+ v = (trivertx_t *)datapointer;
+ out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices;
+ for (k = 0;k < loadmodel->surfmesh.num_vertices;k++)
+ out[k] = v[vertremap[k]];
+ datapointer += numxyz * sizeof(trivertx_t);
+
+ strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name));
+ loadmodel->animscenes[i].firstframe = i;
+ loadmodel->animscenes[i].framecount = 1;
+ loadmodel->animscenes[i].framerate = 10;
+ loadmodel->animscenes[i].loop = true;
+ }
+
+ Mem_Free(vertremap);
+
+ Mod_MakeSortedSurfaces(loadmodel);
+ Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles);
+ Mod_Alias_CalculateBoundingBox();
+ Mod_Alias_MorphMesh_CompileFrames();
+
+ surface = loadmodel->data_surfaces;
+ surface->texture = loadmodel->data_textures;
+ surface->num_firsttriangle = 0;
+ surface->num_triangles = loadmodel->surfmesh.num_triangles;
+ surface->num_firstvertex = 0;
+ surface->num_vertices = loadmodel->surfmesh.num_vertices;
+
+ loadmodel->surfmesh.isanimated = false;
+#endif
+}