X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=model_alias.c;h=a0621802747fccfdd910166a644058f99606aaa2;hp=df2d5c03cb4f067d235597b79cbd23092d6186e2;hb=397530aecdd5492236e3dc5620ee7126078c07f3;hpb=6083bf03e54784cb921a0ed5cbddaca25c65d83f diff --git a/model_alias.c b/model_alias.c index df2d5c03..a0621802 100644 --- a/model_alias.c +++ b/model_alias.c @@ -46,28 +46,17 @@ void Mod_AliasInit (void) void Mod_Alias_GetMesh_Vertices(const model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f) { +#define MAX_BONES 256 if (model->surfmesh.data_vertexweightindex4i) { - int i, k, blends; - const float *v = model->surfmesh.data_vertex3f; - const float *n = model->surfmesh.data_normal3f; - const float *sv = model->surfmesh.data_svector3f; - const float *tv = model->surfmesh.data_tvector3f; - const int *wi = model->surfmesh.data_vertexweightindex4i; - const float *wf = model->surfmesh.data_vertexweightinfluence4f; - float *matrix, m[12], bonepose[256][12], boneposerelative[256][12]; // vertex weighted skeletal - memset(vertex3f, 0, model->surfmesh.num_vertices * sizeof(float[3])); - if (normal3f) - memset(normal3f, 0, model->surfmesh.num_vertices * sizeof(float[3])); - if (svector3f) - { - memset(svector3f, 0, model->surfmesh.num_vertices * sizeof(float[3])); - memset(tvector3f, 0, model->surfmesh.num_vertices * sizeof(float[3])); - } + int i, k; + float boneposerelative[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++) @@ -91,57 +80,136 @@ void Mod_Alias_GetMesh_Vertices(const model_t *model, const frameblend_t *frameb R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]); } // blend the vertex bone weights - if (svector3f) + // 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 { - for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, n += 3, sv += 3, tv += 3, wi += 4, wf += 4, vertex3f += 3, normal3f += 3, svector3f += 3, tvector3f += 3) + const float *v = model->surfmesh.data_vertex3f; + const int *wi = model->surfmesh.data_vertexweightindex4i; + const float *wf = model->surfmesh.data_vertexweightinfluence4f; + memset(vertex3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices); + for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, wi += 4, wf += 4, vertex3f += 3) { - for (k = 0;k < 4 && wf[k];k++) + if (wf[0] == 1) { - const float *m = boneposerelative[wi[k]]; - float f = wf[k]; - vertex3f[0] += f * (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]); - vertex3f[1] += f * (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]); - vertex3f[2] += f * (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]); - normal3f[0] += f * (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]); - normal3f[1] += f * (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]); - normal3f[2] += f * (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]); - svector3f[0] += f * (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]); - svector3f[1] += f * (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]); - svector3f[2] += f * (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]); - tvector3f[0] += f * (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]); - tvector3f[1] += f * (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]); - tvector3f[2] += f * (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]); + const float *m = boneposerelative[wi[0]]; + vertex3f[0] = (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]); + vertex3f[1] = (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]); + vertex3f[2] = (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]); + } + else + { + const float *m = boneposerelative[wi[0]]; + float f = wf[0]; + vertex3f[0] = f * (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]); + vertex3f[1] = f * (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]); + vertex3f[2] = f * (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]); + for (k = 1;k < 4 && wf[k];k++) + { + const float *m = boneposerelative[wi[k]]; + float f = wf[k]; + vertex3f[0] += f * (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]); + vertex3f[1] += f * (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]); + vertex3f[2] += f * (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]); + } } } } - else if (normal3f) + if (normal3f) { - for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, n += 3, wi += 4, wf += 4, vertex3f += 3, normal3f += 3) + const float *n = model->surfmesh.data_normal3f; + const int *wi = model->surfmesh.data_vertexweightindex4i; + const float *wf = model->surfmesh.data_vertexweightinfluence4f; + memset(normal3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices); + for (i = 0;i < model->surfmesh.num_vertices;i++, n += 3, wi += 4, wf += 4, normal3f += 3) { - for (k = 0;k < 4 && wf[k];k++) + if (wf[0] == 1) { - const float *m = boneposerelative[wi[k]]; - float f = wf[k]; - vertex3f[0] += f * (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]); - vertex3f[1] += f * (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]); - vertex3f[2] += f * (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]); - normal3f[0] += f * (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]); - normal3f[1] += f * (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]); - normal3f[2] += f * (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]); + const float *m = boneposerelative[wi[0]]; + normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]); + normal3f[1] = (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]); + normal3f[2] = (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]); + } + else + { + const float *m = boneposerelative[wi[0]]; + float f = wf[0]; + normal3f[0] = f * (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]); + normal3f[1] = f * (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]); + normal3f[2] = f * (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]); + for (k = 1;k < 4 && wf[k];k++) + { + const float *m = boneposerelative[wi[k]]; + float f = wf[k]; + normal3f[0] += f * (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]); + normal3f[1] += f * (n[0] * m[4] + n[1] * m[5] + n[2] * m[ 6]); + normal3f[2] += f * (n[0] * m[8] + n[1] * m[9] + n[2] * m[10]); + } } } } - else + if (svector3f) { - for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, wi += 4, wf += 4, vertex3f += 3) + const float *sv = model->surfmesh.data_svector3f; + const int *wi = model->surfmesh.data_vertexweightindex4i; + const float *wf = model->surfmesh.data_vertexweightinfluence4f; + memset(svector3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices); + for (i = 0;i < model->surfmesh.num_vertices;i++, sv += 3, wi += 4, wf += 4, svector3f += 3) { - for (k = 0;k < 4 && wf[k];k++) + if (wf[0] == 1) + { + const float *m = boneposerelative[wi[0]]; + svector3f[0] = (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]); + svector3f[1] = (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]); + svector3f[2] = (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]); + } + else { - const float *m = boneposerelative[wi[k]]; - float f = wf[k]; - vertex3f[0] += f * (v[0] * m[0] + v[1] * m[1] + v[2] * m[ 2] + m[ 3]); - vertex3f[1] += f * (v[0] * m[4] + v[1] * m[5] + v[2] * m[ 6] + m[ 7]); - vertex3f[2] += f * (v[0] * m[8] + v[1] * m[9] + v[2] * m[10] + m[11]); + const float *m = boneposerelative[wi[0]]; + float f = wf[0]; + svector3f[0] = f * (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]); + svector3f[1] = f * (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]); + svector3f[2] = f * (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]); + for (k = 1;k < 4 && wf[k];k++) + { + const float *m = boneposerelative[wi[k]]; + float f = wf[k]; + svector3f[0] += f * (sv[0] * m[0] + sv[1] * m[1] + sv[2] * m[ 2]); + svector3f[1] += f * (sv[0] * m[4] + sv[1] * m[5] + sv[2] * m[ 6]); + svector3f[2] += f * (sv[0] * m[8] + sv[1] * m[9] + sv[2] * m[10]); + } + } + } + } + if (tvector3f) + { + const float *tv = model->surfmesh.data_tvector3f; + const int *wi = model->surfmesh.data_vertexweightindex4i; + const float *wf = model->surfmesh.data_vertexweightinfluence4f; + memset(tvector3f, 0, sizeof(float[3]) * model->surfmesh.num_vertices); + for (i = 0;i < model->surfmesh.num_vertices;i++, tv += 3, wi += 4, wf += 4, tvector3f += 3) + { + if (wf[0] == 1) + { + const float *m = boneposerelative[wi[0]]; + tvector3f[0] = (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]); + tvector3f[1] = (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]); + tvector3f[2] = (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]); + } + else + { + const float *m = boneposerelative[wi[0]]; + float f = wf[0]; + tvector3f[0] = f * (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]); + tvector3f[1] = f * (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]); + tvector3f[2] = f * (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]); + for (k = 1;k < 4 && wf[k];k++) + { + const float *m = boneposerelative[wi[k]]; + float f = wf[k]; + tvector3f[0] += f * (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]); + tvector3f[1] += f * (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]); + tvector3f[2] += f * (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]); + } } } } @@ -158,19 +226,28 @@ void Mod_Alias_GetMesh_Vertices(const model_t *model, const frameblend_t *frameb if (frameblend[blendnum].lerp > 0) numblends = blendnum + 1; } - memset(vertex3f, 0, numverts * sizeof(float[3])); - if (normal3f) - for (i = 0;i < numverts;i++) - VectorClear(normal3f + i * 3); + // 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); - for (i = 0;i < numverts;i++) + 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++) + { + 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 // (0-255), and as such a lookup table is very well suited to @@ -180,14 +257,27 @@ void Mod_Alias_GetMesh_Vertices(const model_t *model, const frameblend_t *frameb if (normal3f) { float lerp = frameblend[blendnum].lerp; - for (i = 0;i < numverts;i++) + if (blendnum == 0) { - normal3f[i * 3 + 0] += mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp; - normal3f[i * 3 + 1] += mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp; - normal3f[i * 3 + 2] += mod_md3_sin[verts[i].pitch + 64] * lerp; + for (i = 0;i < numverts;i++) + { + normal3f[i * 3 + 0] = mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp; + normal3f[i * 3 + 1] = mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp; + normal3f[i * 3 + 2] = mod_md3_sin[verts[i].pitch + 64] * lerp; + } + } + else + { + for (i = 0;i < numverts;i++) + { + normal3f[i * 3 + 0] += mod_md3_sin[verts[i].yaw + 64] * mod_md3_sin[verts[i].pitch ] * lerp; + normal3f[i * 3 + 1] += mod_md3_sin[verts[i].yaw ] * mod_md3_sin[verts[i].pitch ] * lerp; + normal3f[i * 3 + 2] += mod_md3_sin[verts[i].pitch + 64] * lerp; + } } } } + // md3 model vertices do not include tangents, so we have to generate them (extremely slow) if (normal3f) if (svector3f) Mod_BuildTextureVectorsFromNormals(0, model->surfmesh.num_vertices, model->surfmesh.num_triangles, vertex3f, model->surfmesh.data_texcoordtexture2f, normal3f, model->surfmesh.data_element3i, svector3f, tvector3f, r_smoothnormals_areaweighting.integer); @@ -200,6 +290,8 @@ void Mod_Alias_GetMesh_Vertices(const model_t *model, const frameblend_t *frameb float translate[3]; VectorClear(translate); 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++) { if (model->surfmesh.data_morphmd2framesize6f) @@ -209,11 +301,7 @@ void Mod_Alias_GetMesh_Vertices(const model_t *model, const frameblend_t *frameb if (frameblend[blendnum].lerp > 0) numblends = blendnum + 1; } - for (i = 0;i < numverts;i++) - VectorCopy(translate, vertex3f + i * 3); - if (normal3f) - for (i = 0;i < numverts;i++) - VectorClear(normal3f + i * 3); + // 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; @@ -222,11 +310,23 @@ void Mod_Alias_GetMesh_Vertices(const model_t *model, const frameblend_t *frameb VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].frame * 6, frameblend[blendnum].lerp, scale); else VectorScale(model->surfmesh.num_morphmdlframescale, frameblend[blendnum].lerp, scale); - for (i = 0;i < numverts;i++) + if (blendnum == 0) + { + 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 { - 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 // 162 unique values, this very crude quantization reduces the @@ -235,10 +335,21 @@ void Mod_Alias_GetMesh_Vertices(const model_t *model, const frameblend_t *frameb if (normal3f) { float lerp = frameblend[blendnum].lerp; - for (i = 0;i < numverts;i++) + if (blendnum == 0) + { + for (i = 0;i < numverts;i++) + { + const float *vn = m_bytenormals[verts[i].lightnormalindex]; + VectorScale(vn, lerp, normal3f + i*3); + } + } + else { - const float *vn = m_bytenormals[verts[i].lightnormalindex]; - VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3); + for (i = 0;i < numverts;i++) + { + const float *vn = m_bytenormals[verts[i].lightnormalindex]; + VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3); + } } } } @@ -269,22 +380,7 @@ int Mod_Alias_GetTagMatrix(const model_t *model, int poseframe, int tagindex, ma R_ConcatTransforms(boneframe + model->data_bones[tagindex].parent * 12, tempbonematrix, bonematrix); tagindex = model->data_bones[tagindex].parent; } - outmatrix->m[0][0] = bonematrix[0]; - outmatrix->m[0][1] = bonematrix[1]; - outmatrix->m[0][2] = bonematrix[2]; - outmatrix->m[0][3] = bonematrix[3]; - outmatrix->m[1][0] = bonematrix[4]; - outmatrix->m[1][1] = bonematrix[5]; - outmatrix->m[1][2] = bonematrix[6]; - outmatrix->m[1][3] = bonematrix[7]; - outmatrix->m[2][0] = bonematrix[8]; - outmatrix->m[2][1] = bonematrix[9]; - outmatrix->m[2][2] = bonematrix[10]; - outmatrix->m[2][3] = bonematrix[11]; - outmatrix->m[3][0] = 0; - outmatrix->m[3][1] = 0; - outmatrix->m[3][2] = 0; - outmatrix->m[3][3] = 1; + Matrix4x4_FromArray12FloatD3D(outmatrix, bonematrix); } else if (model->num_tags) { @@ -292,7 +388,7 @@ int Mod_Alias_GetTagMatrix(const model_t *model, int poseframe, int tagindex, ma return 4; if (poseframe >= model->num_tagframes) return 6; - *outmatrix = model->data_tags[poseframe * model->num_tags + tagindex].matrix; + Matrix4x4_FromArray12FloatGL(outmatrix, model->data_tags[poseframe * model->num_tags + tagindex].matrixgl); } return 0; } @@ -319,13 +415,14 @@ static void Mod_BuildBaseBonePoses(void) { int i, k; double scale; + float *basebonepose = Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(float[12])); float *in12f = loadmodel->data_poses; - float *out12f = loadmodel->data_basebonepose; + float *out12f = basebonepose; float *outinv12f = loadmodel->data_baseboneposeinverse; for (i = 0;i < loadmodel->num_bones;i++, in12f += 12, out12f += 12, outinv12f += 12) { if (loadmodel->data_bones[i].parent >= 0) - R_ConcatTransforms(loadmodel->data_basebonepose + 12 * loadmodel->data_bones[i].parent, in12f, out12f); + R_ConcatTransforms(basebonepose + 12 * loadmodel->data_bones[i].parent, in12f, out12f); else for (k = 0;k < 12;k++) out12f[k] = in12f[k]; @@ -355,6 +452,7 @@ static void Mod_BuildBaseBonePoses(void) outinv12f[ 7] = -(out12f[ 3] * outinv12f[ 4] + out12f[ 7] * outinv12f[ 5] + out12f[11] * outinv12f[ 6]); outinv12f[11] = -(out12f[ 3] * outinv12f[ 8] + out12f[ 7] * outinv12f[ 9] + out12f[11] * outinv12f[10]); } + Mem_Free(basebonepose); } static void Mod_Alias_CalculateBoundingBox(void) @@ -424,9 +522,7 @@ static void Mod_Alias_Mesh_CompileFrameZero(void) loadmodel->surfmesh.data_svector3f = loadmodel->surfmesh.data_vertex3f + loadmodel->surfmesh.num_vertices * 3; loadmodel->surfmesh.data_tvector3f = loadmodel->surfmesh.data_vertex3f + loadmodel->surfmesh.num_vertices * 6; loadmodel->surfmesh.data_normal3f = loadmodel->surfmesh.data_vertex3f + loadmodel->surfmesh.num_vertices * 9; - Mod_Alias_GetMesh_Vertices(loadmodel, frameblend, loadmodel->surfmesh.data_vertex3f, NULL, NULL, NULL); - Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true); - 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, true); + Mod_Alias_GetMesh_Vertices(loadmodel, frameblend, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f); } 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) @@ -557,7 +653,7 @@ static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *ve // get scene name from first frame pinframe = (daliasframe_t *)datapointer; - strcpy(scene->name, pinframe->name); + strlcpy(scene->name, pinframe->name, sizeof(scene->name)); scene->firstframe = pose; scene->framecount = groupframes; scene->framerate = 1.0f / interval; @@ -576,72 +672,62 @@ static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *ve } } -static skinframe_t missingskinframe; -static void Mod_BuildAliasSkinFromSkinFrame(texture_t *skin, skinframe_t *skinframe) +static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe) { + if (cls.state == ca_dedicated) + return; // hack - if (skinframe == NULL) - { - skinframe = &missingskinframe; - memset(skinframe, 0, sizeof(*skinframe)); - skinframe->base = r_texture_notexture; - } - - skin->skin = *skinframe; - skin->currentframe = skin; - skin->basematerialflags = MATERIALFLAG_WALL; - if (skin->skin.fog) - skin->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT; - skin->currentmaterialflags = skin->basematerialflags; + if (!skinframe) + skinframe = R_SkinFrame_LoadMissing(); + texture->currentframe = texture; + texture->numskinframes = 1; + texture->skinframerate = 1; + texture->skinframes[0] = skinframe; + texture->currentskinframe = skinframe; + + texture->basematerialflags = MATERIALFLAG_WALL; + if (texture->currentskinframe->fog) + texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; + texture->currentmaterialflags = texture->basematerialflags; } static void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, char *meshname, char *shadername) { int i; skinfileitem_t *skinfileitem; - skinframe_t tempskinframe; + skinframe_t *tempskinframe; if (skinfile) { // the skin += loadmodel->num_surfaces part of this is because data_textures on alias models is arranged as [numskins][numsurfaces] for (i = 0;skinfile;skinfile = skinfile->next, i++, skin += loadmodel->num_surfaces) { memset(skin, 0, sizeof(*skin)); + Mod_BuildAliasSkinFromSkinFrame(skin, NULL); + // don't render unmentioned meshes + skin->basematerialflags = skin->currentmaterialflags = 0; + // see if a mesh for (skinfileitem = skinfile->items;skinfileitem;skinfileitem = skinfileitem->next) { // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw" if (!strcmp(skinfileitem->name, meshname) && strcmp(skinfileitem->replacement, "common/nodraw") && strcmp(skinfileitem->replacement, "textures/common/nodraw")) { - memset(&tempskinframe, 0, sizeof(tempskinframe)); - if (Mod_LoadSkinFrame(&tempskinframe, skinfileitem->replacement, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP, true, true)) - Mod_BuildAliasSkinFromSkinFrame(skin, &tempskinframe); - else - { + tempskinframe = R_SkinFrame_LoadExternal(skinfileitem->replacement, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP); + if (!tempskinframe) if (cls.state != ca_dedicated) - Con_Printf("mesh \"%s\": failed to load skin #%i \"%s\", falling back to mesh's internal shader name \"%s\"\n", meshname, i, skinfileitem->replacement, shadername); - if (Mod_LoadSkinFrame(&tempskinframe, shadername, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP, true, true)) - Mod_BuildAliasSkinFromSkinFrame(skin, &tempskinframe); - else - { - if (cls.state != ca_dedicated) - Con_Printf("failed to load skin \"%s\"\n", shadername); - Mod_BuildAliasSkinFromSkinFrame(skin, NULL); - } - } + Con_DPrintf("mesh \"%s\": failed to load skin #%i \"%s\"\n", meshname, i, skinfileitem->replacement); + Mod_BuildAliasSkinFromSkinFrame(skin, tempskinframe); + break; } } } } else { - memset(&tempskinframe, 0, sizeof(tempskinframe)); - if (Mod_LoadSkinFrame(&tempskinframe, shadername, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP, true, true)) - Mod_BuildAliasSkinFromSkinFrame(skin, &tempskinframe); - else - { + tempskinframe = R_SkinFrame_LoadExternal(shadername, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP); + if (!tempskinframe) if (cls.state != ca_dedicated) Con_Printf("Can't find texture \"%s\" for mesh \"%s\", using grey checkerboard\n", shadername, meshname); - Mod_BuildAliasSkinFromSkinFrame(skin, NULL); - } + Mod_BuildAliasSkinFromSkinFrame(skin, tempskinframe); } } @@ -663,7 +749,7 @@ void Mod_IDP0_Load(model_t *mod, void *buffer, void *bufferend) daliasgroup_t *pinframegroup; unsigned char *datapointer, *startframes, *startskins; char name[MAX_QPATH]; - skinframe_t tempskinframe; + skinframe_t *tempskinframe; animscene_t *tempskinscenes; texture_t *tempaliasskins; float *vertst; @@ -708,7 +794,9 @@ void Mod_IDP0_Load(model_t *mod, void *buffer, void *bufferend) BOUNDI(loadmodel->numframes,0,65536); loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype); BOUNDI(loadmodel->synctype,0,2); - loadmodel->flags = LittleLong (pinmodel->flags); + // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc) + i = LittleLong (pinmodel->flags); + loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00); for (i = 0;i < 3;i++) { @@ -906,16 +994,17 @@ void Mod_IDP0_Load(model_t *mod, void *buffer, void *bufferend) sprintf (name, "%s_%i_%i", loadmodel->name, i, j); else sprintf (name, "%s_%i", loadmodel->name, i); - if (!Mod_LoadSkinFrame(&tempskinframe, name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP, true, true)) - Mod_LoadSkinFrame_Internal(&tempskinframe, name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP, true, r_fullbrights.integer, (unsigned char *)datapointer, skinwidth, skinheight, 8, NULL, NULL); - Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, &tempskinframe); + tempskinframe = R_SkinFrame_LoadExternal(name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP); + if (!tempskinframe) + tempskinframe = R_SkinFrame_LoadInternal(name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP, true, r_fullbrights.integer, (unsigned char *)datapointer, skinwidth, skinheight, 8, NULL, NULL); + Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe); datapointer += skinwidth * skinheight; totalskins++; } } // check for skins that don't exist in the model, but do exist as external images // (this was added because yummyluv kept pestering me about support for it) - while (Mod_LoadSkinFrame(&tempskinframe, va("%s_%i", loadmodel->name, loadmodel->numskins), (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP, true, true)) + while ((tempskinframe = R_SkinFrame_LoadExternal(va("%s_%i", loadmodel->name, loadmodel->numskins), (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP))) { // expand the arrays to make room tempskinscenes = loadmodel->skinscenes; @@ -929,8 +1018,8 @@ void Mod_IDP0_Load(model_t *mod, void *buffer, void *bufferend) Mem_Free(tempaliasskins); // store the info about the new skin - Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, &tempskinframe); - strcpy(loadmodel->skinscenes[loadmodel->numskins].name, name); + Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe); + strlcpy(loadmodel->skinscenes[loadmodel->numskins].name, name, sizeof(loadmodel->skinscenes[loadmodel->numskins].name)); loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins; loadmodel->skinscenes[loadmodel->numskins].framecount = 1; loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f; @@ -939,6 +1028,11 @@ void Mod_IDP0_Load(model_t *mod, void *buffer, void *bufferend) //increase skin counts loadmodel->numskins++; totalskins++; + + // fix up the pointers since they are pointing at the old textures array + // FIXME: this is a hack! + for (j = 0;j < loadmodel->numskins * loadmodel->num_surfaces;j++) + loadmodel->data_textures[j].currentframe = &loadmodel->data_textures[j]; } } @@ -971,7 +1065,7 @@ void Mod_IDP2_Load(model_t *mod, void *buffer, void *bufferend) unsigned short st; } *hash, **md2verthash, *md2verthashdata; - skinframe_t tempskinframe; + skinframe_t *tempskinframe; skinfile_t *skinfiles; pinmodel = (md2_t *)buffer; @@ -1033,7 +1127,6 @@ void Mod_IDP2_Load(model_t *mod, void *buffer, void *bufferend) 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->flags = 0; // there are no MD2 flags loadmodel->synctype = ST_RAND; // load the skins @@ -1053,13 +1146,10 @@ void Mod_IDP2_Load(model_t *mod, void *buffer, void *bufferend) 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) { - if (Mod_LoadSkinFrame(&tempskinframe, inskin, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP, true, true)) - Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i * loadmodel->num_surfaces, &tempskinframe); - else - { + tempskinframe = R_SkinFrame_LoadExternal(inskin, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP); + if (!tempskinframe) Con_Printf("%s is missing skin \"%s\"\n", loadmodel->name, inskin); - Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i * loadmodel->num_surfaces, NULL); - } + Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i * loadmodel->num_surfaces, tempskinframe); } } else @@ -1165,7 +1255,7 @@ void Mod_IDP2_Load(model_t *mod, void *buffer, void *bufferend) out[k] = v[vertremap[k]]; datapointer += numxyz * sizeof(trivertx_t); - strcpy(loadmodel->animscenes[i].name, pinframe->name); + 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; @@ -1219,8 +1309,10 @@ void Mod_IDP3_Load(model_t *mod, void *buffer, void *bufferend) loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume; loadmodel->DrawLight = R_Q1BSP_DrawLight; loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox; - loadmodel->flags = LittleLong(pinmodel->flags); loadmodel->synctype = ST_RAND; + // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc) + i = LittleLong (pinmodel->flags); + loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00); // set up some global info about the model loadmodel->numframes = LittleLong(pinmodel->num_frames); @@ -1240,7 +1332,7 @@ void Mod_IDP3_Load(model_t *mod, void *buffer, void *bufferend) loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t)); for (i = 0, pinframe = (md3frameinfo_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++) { - strcpy(loadmodel->animscenes[i].name, pinframe->name); + 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; @@ -1253,14 +1345,11 @@ void Mod_IDP3_Load(model_t *mod, void *buffer, void *bufferend) loadmodel->data_tags = (aliastag_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_tagframes * loadmodel->num_tags * sizeof(aliastag_t)); for (i = 0, pintag = (md3tag_t *)((unsigned char *)pinmodel + LittleLong(pinmodel->lump_tags));i < loadmodel->num_tagframes * loadmodel->num_tags;i++, pintag++) { - strcpy(loadmodel->data_tags[i].name, pintag->name); - loadmodel->data_tags[i].matrix = identitymatrix; + strlcpy(loadmodel->data_tags[i].name, pintag->name, sizeof(loadmodel->data_tags[i].name)); + for (j = 0;j < 9;j++) + loadmodel->data_tags[i].matrixgl[j] = LittleFloat(pintag->rotationmatrix[j]); for (j = 0;j < 3;j++) - { - for (k = 0;k < 3;k++) - loadmodel->data_tags[i].matrix.m[j][k] = LittleFloat(pintag->rotationmatrix[k * 3 + j]); - loadmodel->data_tags[i].matrix.m[j][3] = LittleFloat(pintag->origin[j]); - } + loadmodel->data_tags[i].matrixgl[9+j] = LittleFloat(pintag->origin[j]); //Con_Printf("model \"%s\" frame #%i tag #%i \"%s\"\n", loadmodel->name, i / loadmodel->num_tags, i % loadmodel->num_tags, loadmodel->data_tags[i].name); } @@ -1361,12 +1450,11 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer, void *bufferend) pinmodel = (zymtype1header_t *)buffer; pbase = (unsigned char *)buffer; if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12)) - Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model"); + Host_Error ("Mod_ZYMOTICMODEL_Load: %s is not a zymotic model", loadmodel->name); if (BigLong(pinmodel->type) != 1) Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name); loadmodel->type = mod_alias; - loadmodel->flags = 0; // there are no flags on zym models loadmodel->synctype = ST_RAND; // byteswap header @@ -1406,12 +1494,12 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer, void *bufferend) if (pheader->numtris < 1 || pheader->numverts < 3 || pheader->numshaders < 1) { - Con_Printf("%s has no geometry\n"); + Con_Printf("%s has no geometry\n", loadmodel->name); return; } if (pheader->numscenes < 1 || pheader->lump_poses.length < (int)sizeof(float[3][4])) { - Con_Printf("%s has no animations\n"); + Con_Printf("%s has no animations\n", loadmodel->name); return; } @@ -1511,7 +1599,7 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer, void *bufferend) loadmodel->nummodelsurfaces = loadmodel->num_surfaces; loadmodel->num_textures = 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[36])); + 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])); loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t); loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int); loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t); @@ -1527,8 +1615,7 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer, void *bufferend) 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_basebonepose = (float *)data;data += loadmodel->num_poses * sizeof(float[12]); - loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_poses * sizeof(float[12]); + loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]); //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data poses = (float *) (pheader->lump_poses.start + pbase); @@ -1671,12 +1758,11 @@ void Mod_DARKPLACESMODEL_Load(model_t *mod, void *buffer, void *bufferend) pheader = (dpmheader_t *)buffer; pbase = (unsigned char *)buffer; if (memcmp(pheader->id, "DARKPLACESMODEL\0", 16)) - Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model"); + Host_Error ("Mod_DARKPLACESMODEL_Load: %s is not a darkplaces model", loadmodel->name); if (BigLong(pheader->type) != 2) Host_Error ("Mod_DARKPLACESMODEL_Load: only type 2 (hierarchical skeletal pose) models are currently supported (name = %s)", loadmodel->name); loadmodel->type = mod_alias; - loadmodel->flags = 0; // there are no flags on zym models loadmodel->synctype = ST_RAND; // byteswap header @@ -1699,12 +1785,12 @@ void Mod_DARKPLACESMODEL_Load(model_t *mod, void *buffer, void *bufferend) if (pheader->num_bones < 1 || pheader->num_meshs < 1) { - Con_Printf("%s has no geometry\n"); + Con_Printf("%s has no geometry\n", loadmodel->name); return; } if (pheader->num_frames < 1) { - Con_Printf("%s has no frames\n"); + Con_Printf("%s has no frames\n", loadmodel->name); return; } @@ -1751,7 +1837,7 @@ void Mod_DARKPLACESMODEL_Load(model_t *mod, void *buffer, void *bufferend) loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes; loadmodel->num_textures = loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs; // 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[36]) + 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]) + 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)); loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t); loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int); loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t); @@ -1767,8 +1853,7 @@ void Mod_DARKPLACESMODEL_Load(model_t *mod, void *buffer, void *bufferend) 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_basebonepose = (float *)data;data += loadmodel->num_poses * sizeof(float[12]); - loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_poses * 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); @@ -1948,15 +2033,6 @@ void Mod_DARKPLACESMODEL_Load(model_t *mod, void *buffer, void *bufferend) loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1; } -static void Mod_PSKMODEL_AnimKeyToMatrix(float *origin, float *quat, matrix4x4_t *m) -{ - float x = quat[0], y = quat[1], z = quat[2], w = quat[3]; - m->m[0][0]=1-2*(y*y+z*z);m->m[0][1]= 2*(x*y-z*w);m->m[0][2]= 2*(x*z+y*w);m->m[0][3]=origin[0]; - m->m[1][0]= 2*(x*y+z*w);m->m[1][1]=1-2*(x*x+z*z);m->m[1][2]= 2*(y*z-x*w);m->m[1][3]=origin[1]; - m->m[2][0]= 2*(x*z-y*w);m->m[2][1]= 2*(y*z+x*w);m->m[2][2]=1-2*(x*x+y*y);m->m[2][3]=origin[2]; - m->m[3][0]= 0 ;m->m[3][1]= 0 ;m->m[3][2]= 0 ;m->m[3][3]=1; -} - // 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) @@ -1981,7 +2057,7 @@ void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend) pchunk = (pskchunk_t *)buffer; if (strcmp(pchunk->id, "ACTRHEAD")) - Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model"); + Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name); loadmodel->type = mod_alias; loadmodel->DrawSky = NULL; @@ -1990,7 +2066,6 @@ void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend) loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume; loadmodel->DrawLight = R_Q1BSP_DrawLight; loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox; - loadmodel->flags = 0; // there are no flags on zym models loadmodel->synctype = ST_RAND; FS_StripExtension(loadmodel->name, animname, sizeof(animname)); @@ -2216,7 +2291,7 @@ void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend) // positions from the psk, but this is hard for me to implement // and people can easily make animations that match. if (numanimbones != numbones) - Host_Error("%s: this loader only supports animations with the same bones as the mesh"); + Host_Error("%s: this loader only supports animations with the same bones as the mesh", loadmodel->name); for (index = 0, p = (pskboneinfo_t *)animbuffer;index < numrecords;index++, p++) { p->numchildren = LittleLong(p->numchildren); @@ -2337,7 +2412,7 @@ void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend) loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes; loadmodel->num_textures = loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts; // 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[36]) + 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]) + 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)); loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t); loadmodel->surfacelist = (int *)data;data += loadmodel->num_surfaces * sizeof(int); loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t); @@ -2353,8 +2428,7 @@ void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend) 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_basebonepose = (float *)data;data += loadmodel->num_poses * sizeof(float[12]); - loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_poses * 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); @@ -2476,20 +2550,10 @@ void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend) // load the poses from the animkeys for (index = 0;index < numanimkeys;index++) { + pskanimkeys_t *k = animkeys + index; matrix4x4_t matrix; - Mod_PSKMODEL_AnimKeyToMatrix(animkeys[index].origin, animkeys[index].quat, &matrix); - loadmodel->data_poses[index*12+0] = matrix.m[0][0]; - loadmodel->data_poses[index*12+1] = matrix.m[0][1]; - loadmodel->data_poses[index*12+2] = matrix.m[0][2]; - loadmodel->data_poses[index*12+3] = matrix.m[0][3]; - loadmodel->data_poses[index*12+4] = matrix.m[1][0]; - loadmodel->data_poses[index*12+5] = matrix.m[1][1]; - loadmodel->data_poses[index*12+6] = matrix.m[1][2]; - loadmodel->data_poses[index*12+7] = matrix.m[1][3]; - loadmodel->data_poses[index*12+8] = matrix.m[2][0]; - loadmodel->data_poses[index*12+9] = matrix.m[2][1]; - loadmodel->data_poses[index*12+10] = matrix.m[2][2]; - loadmodel->data_poses[index*12+11] = matrix.m[2][3]; + Matrix4x4_FromOriginQuat(&matrix, k->origin[0], k->origin[1], k->origin[2], k->quat[0], k->quat[1], k->quat[2], k->quat[3]); + Matrix4x4_ToArray12FloatD3D(&matrix, loadmodel->data_poses + index*12); } Mod_FreeSkinFiles(skinfiles); Mem_Free(animfilebuffer);