X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=model_alias.c;h=f6cae93252a8816885e4031105d1e315110a4bdd;hb=c3b6c163e7c8f4d9e5b188958f0e075a5530b47d;hp=7fdf187371e312a9b714a023a6c3bf30fda55bb3;hpb=45c1c09489bc22a7b9cd6540a2cbc7d7ff459794;p=xonotic%2Fdarkplaces.git diff --git a/model_alias.c b/model_alias.c index 7fdf1873..f6cae932 100644 --- a/model_alias.c +++ b/model_alias.c @@ -28,6 +28,7 @@ cvar_t r_skeletal_debugbonevalue = {0, "r_skeletal_debugbonevalue", "100", "deve 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]; @@ -40,31 +41,63 @@ void Mod_AliasInit (void) 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_Alias_GetMesh_Vertices(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, const skeleton_t *skeleton, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f) { #define MAX_BONES 256 - if (model->surfmesh.data_vertexweightindex4i) + // vertex weighted skeletal + int i, k; + int blends; + float desiredscale[3]; + float boneposerelative[MAX_BONES][12]; + float *matrix, m[12], bonepose[MAX_BONES][12]; + + if (skeleton && !skeleton->relativetransforms) + skeleton = NULL; + + // interpolate matrices + if (skeleton) + { + for (i = 0;i < model->num_bones;i++) + { + Matrix4x4_ToArray12FloatD3D(&skeleton->relativetransforms[i], m); + if (model->data_bones[i].parent >= 0) + R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]); + else + for (k = 0;k < 12;k++) + bonepose[i][k] = m[k]; + + // create a relative deformation matrix to describe displacement + // from the base mesh, which is used by the actual weighting + R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]); + } + } + else { - // vertex weighted skeletal - 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++) + 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; @@ -79,157 +112,163 @@ void Mod_Alias_GetMesh_Vertices(const model_t *model, const frameblend_t *frameb // from the base mesh, which is used by the actual weighting R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]); } - // 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 + } + + // 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; + 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) { - 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) + if (wf[0] == 1) { - if (wf[0] == 1) - { - 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]]; + 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[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]); - } + 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]); } } } - if (normal3f) + } + if (normal3f) + { + 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) { - 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) + if (wf[0] == 1) { - if (wf[0] == 1) - { - 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]]; + 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[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]); - } + 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]); } } } - if (svector3f) + } + if (svector3f) + { + 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) { - 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) + if (wf[0] == 1) { - 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[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[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[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]); - } + 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) + } + 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) { - 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) { - 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]]; + 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[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]); - } + 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]); } } } } - else if (model->surfmesh.data_morphmd3vertex) +} + +void Mod_MD3_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, 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 < MAX_FRAMEBLENDS;blendnum++) { - // vertex morph - int i, numblends, blendnum; - int numverts = model->surfmesh.num_vertices; - numblends = 0; - for (blendnum = 0;blendnum < 4;blendnum++) - { - //VectorMA(translate, model->surfmesh.num_morphmdlframetranslate, frameblend[blendnum].lerp, translate); - if (frameblend[blendnum].lerp > 0) - numblends = blendnum + 1; - } - // 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++) + //VectorMA(translate, model->surfmesh.num_morphmdlframetranslate, frameblend[blendnum].lerp, translate); + if (frameblend[blendnum].lerp > 0) + numblends = blendnum + 1; + } + // 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].subframe; + if (vertex3f) { - const md3vertex_t *verts = model->surfmesh.data_morphmd3vertex + numverts * frameblend[blendnum].frame; float scale = frameblend[blendnum].lerp * (1.0f / 64.0f); if (blendnum == 0) { @@ -249,82 +288,86 @@ void Mod_Alias_GetMesh_Vertices(const model_t *model, const frameblend_t *frameb 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 - // decoding them, and since cosine is equivilant to sine with an - // extra 45 degree rotation, this uses one lookup table for both - // sine and cosine with a +64 bias to get cosine. - if (normal3f) + } + // 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 + // decoding them, and since cosine is equivilant to sine with an + // extra 45 degree rotation, this uses one lookup table for both + // sine and cosine with a +64 bias to get cosine. + if (normal3f) + { + float lerp = frameblend[blendnum].lerp; + if (blendnum == 0) { - float lerp = frameblend[blendnum].lerp; - if (blendnum == 0) + for (i = 0;i < numverts;i++) { - 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; - } + 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 + } + else + { + for (i = 0;i < numverts;i++) { - 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; - } + 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; } } - if (svector3f) + } + if (svector3f) + { + const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe; + float f = frameblend[blendnum].lerp * (1.0f / 127.0f); + if (blendnum == 0) { - const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].frame; - float f = frameblend[blendnum].lerp * (1.0f / 127.0f); - if (blendnum == 0) + for (i = 0;i < numverts;i++, texvecvert++) { - for (i = 0;i < numverts;i++, texvecvert++) - { - VectorScale(texvecvert->svec, f, svector3f + i*3); - VectorScale(texvecvert->tvec, f, tvector3f + i*3); - } + VectorScale(texvecvert->svec, f, svector3f + i*3); + VectorScale(texvecvert->tvec, f, tvector3f + i*3); } - else + } + else + { + for (i = 0;i < numverts;i++, texvecvert++) { - for (i = 0;i < numverts;i++, texvecvert++) - { - VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3); - VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3); - } + VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3); + VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3); } } } } - else if (model->surfmesh.data_morphmdlvertex) - { - // vertex morph - int i, numblends, blendnum; - int numverts = model->surfmesh.num_vertices; - 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) - VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].frame * 6 + 3, translate); - else - VectorMA(translate, frameblend[blendnum].lerp, model->surfmesh.num_morphmdlframetranslate, translate); - if (frameblend[blendnum].lerp > 0) - numblends = blendnum + 1; - } - // 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++) +} + +void Mod_MDL_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f) +{ + // vertex morph + int i, numblends, blendnum; + int numverts = model->surfmesh.num_vertices; + 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 < MAX_FRAMEBLENDS;blendnum++) + { + if (model->surfmesh.data_morphmd2framesize6f) + 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) + numblends = blendnum + 1; + } + // 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].subframe; + if (vertex3f) { - 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); + 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) @@ -345,98 +388,185 @@ void Mod_Alias_GetMesh_Vertices(const model_t *model, const frameblend_t *frameb 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 - // vertex normal to only one byte, which saves a lot of space but - // also makes lighting pretty coarse - if (normal3f) + } + // the vertex normals in mdl models are an index into a table of + // 162 unique values, this very crude quantization reduces the + // vertex normal to only one byte, which saves a lot of space but + // also makes lighting pretty coarse + if (normal3f) + { + float lerp = frameblend[blendnum].lerp; + if (blendnum == 0) { - float lerp = frameblend[blendnum].lerp; - if (blendnum == 0) + for (i = 0;i < numverts;i++) { - for (i = 0;i < numverts;i++) - { - const float *vn = m_bytenormals[verts[i].lightnormalindex]; - VectorScale(vn, lerp, normal3f + i*3); - } + const float *vn = m_bytenormals[verts[i].lightnormalindex]; + VectorScale(vn, lerp, normal3f + i*3); } - else + } + else + { + for (i = 0;i < numverts;i++) { - for (i = 0;i < numverts;i++) - { - const float *vn = m_bytenormals[verts[i].lightnormalindex]; - VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3); - } + const float *vn = m_bytenormals[verts[i].lightnormalindex]; + VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3); } } - if (svector3f) + } + if (svector3f) + { + const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].subframe; + float f = frameblend[blendnum].lerp * (1.0f / 127.0f); + if (blendnum == 0) { - const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].frame; - float f = frameblend[blendnum].lerp * (1.0f / 127.0f); - if (blendnum == 0) + for (i = 0;i < numverts;i++, texvecvert++) { - for (i = 0;i < numverts;i++, texvecvert++) - { - VectorScale(texvecvert->svec, f, svector3f + i*3); - VectorScale(texvecvert->tvec, f, tvector3f + i*3); - } + VectorScale(texvecvert->svec, f, svector3f + i*3); + VectorScale(texvecvert->tvec, f, tvector3f + i*3); } - else + } + else + { + for (i = 0;i < numverts;i++, texvecvert++) { - for (i = 0;i < numverts;i++, texvecvert++) - { - VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3); - VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3); - } + VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3); + VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3); } } } } - else - Host_Error("model %s has no skeletal or vertex morph animation data", model->name); } -int Mod_Alias_GetTagMatrix(const model_t *model, int poseframe, int tagindex, matrix4x4_t *outmatrix) +int Mod_Alias_GetTagMatrix(const dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, int tagindex, matrix4x4_t *outmatrix) { + matrix4x4_t temp; const float *boneframe; - float tempbonematrix[12], bonematrix[12]; + const float *input; + int blendindex; + int parenttagindex; + int k; + float lerp; + float tempbonematrix[12], bonematrix[12], blendmatrix[12]; *outmatrix = identitymatrix; - if (model->num_bones) + if (skeleton && skeleton->relativetransforms) + { + if (tagindex < 0 || tagindex >= skeleton->model->num_bones) + return 4; + *outmatrix = skeleton->relativetransforms[tagindex]; + while ((tagindex = model->data_bones[tagindex].parent) >= 0) + { + temp = *outmatrix; + Matrix4x4_Concat(outmatrix, &skeleton->relativetransforms[tagindex], &temp); + } + } + else if (model->num_bones) { if (tagindex < 0 || tagindex >= model->num_bones) return 4; - if (poseframe >= model->num_poses) - return 6; - boneframe = model->data_poses + poseframe * model->num_bones * 12; - memcpy(bonematrix, boneframe + tagindex * 12, sizeof(float[12])); - while (model->data_bones[tagindex].parent >= 0) + for (k = 0;k < 12;k++) + blendmatrix[k] = 0; + for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++) { - memcpy(tempbonematrix, bonematrix, sizeof(float[12])); - R_ConcatTransforms(boneframe + model->data_bones[tagindex].parent * 12, tempbonematrix, bonematrix); - tagindex = model->data_bones[tagindex].parent; + lerp = frameblend[blendindex].lerp; + boneframe = model->data_poses + frameblend[blendindex].subframe * model->num_bones * 12; + input = boneframe + tagindex * 12; + for (k = 0;k < 12;k++) + bonematrix[k] = input[k]; + parenttagindex = tagindex; + while ((parenttagindex = model->data_bones[parenttagindex].parent) >= 0) + { + for (k = 0;k < 12;k++) + tempbonematrix[k] = bonematrix[k]; + input = boneframe + parenttagindex * 12; + R_ConcatTransforms(input, tempbonematrix, bonematrix); + } + for (k = 0;k < 12;k++) + blendmatrix[k] += bonematrix[k] * lerp; } - Matrix4x4_FromArray12FloatD3D(outmatrix, bonematrix); + Matrix4x4_FromArray12FloatD3D(outmatrix, blendmatrix); } else if (model->num_tags) { if (tagindex < 0 || tagindex >= model->num_tags) return 4; - if (poseframe >= model->num_tagframes) - return 6; - Matrix4x4_FromArray12FloatGL(outmatrix, model->data_tags[poseframe * model->num_tags + tagindex].matrixgl); + for (k = 0;k < 12;k++) + blendmatrix[k] = 0; + for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++) + { + lerp = frameblend[blendindex].lerp; + input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl; + for (k = 0;k < 12;k++) + blendmatrix[k] += input[k] * lerp; + } + Matrix4x4_FromArray12FloatGL(outmatrix, blendmatrix); } + + 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, const frameblend_t *frameblend, const skeleton_t *skeleton, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix) +{ + const float *boneframe; + const float *input; + int blendindex; + int k; + float lerp; + float blendmatrix[12]; + + if (skeleton && skeleton->relativetransforms) + { + if (tagindex < 0 || tagindex >= skeleton->model->num_bones) + return 1; + *parentindex = skeleton->model->data_bones[tagindex].parent; + *tagname = skeleton->model->data_bones[tagindex].name; + *tag_localmatrix = skeleton->relativetransforms[tagindex]; + return 0; + } + else if (model->num_bones) + { + if(tagindex >= model->num_bones || tagindex < 0) + return 1; + *parentindex = model->data_bones[tagindex].parent; + *tagname = model->data_bones[tagindex].name; + for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++) + { + lerp = frameblend[blendindex].lerp; + boneframe = model->data_poses + frameblend[blendindex].subframe * model->num_bones * 12; + input = boneframe + tagindex * 12; + for (k = 0;k < 12;k++) + blendmatrix[k] += input[k] * lerp; + } + Matrix4x4_FromArray12FloatD3D(tag_localmatrix, blendmatrix); + return 0; + } + else if (model->num_tags) + { + if(tagindex >= model->num_tags || tagindex < 0) + return 1; + *parentindex = -1; + *tagname = model->data_tags[tagindex].name; + for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++) + { + lerp = frameblend[blendindex].lerp; + input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl; + for (k = 0;k < 12;k++) + blendmatrix[k] += input[k] * lerp; + } + Matrix4x4_FromArray12FloatGL(tag_localmatrix, blendmatrix); + 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)) @@ -452,10 +582,13 @@ static void Mod_BuildBaseBonePoses(void) { 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) @@ -494,52 +627,49 @@ static void Mod_BuildBaseBonePoses(void) static void Mod_Alias_CalculateBoundingBox(void) { - int i, j; int vnum; qboolean firstvertex = true; 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 (i = 0;i < loadmodel->numframes;i++) + for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++) { - for (j = 0, frameblend[0].frame = loadmodel->animscenes[i].firstframe;j < loadmodel->animscenes[i].framecount;j++, frameblend[0].frame++) + loadmodel->AnimateVertices(loadmodel, frameblend, NULL, vertex3f, NULL, NULL, NULL); + for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3) { - Mod_Alias_GetMesh_Vertices(loadmodel, frameblend, vertex3f, NULL, NULL, NULL); - for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3) + if (firstvertex) { - if (firstvertex) - { - firstvertex = false; - VectorCopy(v, loadmodel->normalmins); - VectorCopy(v, loadmodel->normalmaxs); - } - else - { - if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0]; - if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1]; - if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2]; - if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0]; - if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1]; - if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2]; - } - dist = v[0] * v[0] + v[1] * v[1]; - if (yawradius < dist) - yawradius = dist; - dist += v[2] * v[2]; - if (radius < dist) - radius = dist; + firstvertex = false; + VectorCopy(v, loadmodel->normalmins); + VectorCopy(v, loadmodel->normalmaxs); + } + else + { + if (loadmodel->normalmins[0] > v[0]) loadmodel->normalmins[0] = v[0]; + if (loadmodel->normalmins[1] > v[1]) loadmodel->normalmins[1] = v[1]; + if (loadmodel->normalmins[2] > v[2]) loadmodel->normalmins[2] = v[2]; + if (loadmodel->normalmaxs[0] < v[0]) loadmodel->normalmaxs[0] = v[0]; + if (loadmodel->normalmaxs[1] < v[1]) loadmodel->normalmaxs[1] = v[1]; + if (loadmodel->normalmaxs[2] < v[2]) loadmodel->normalmaxs[2] = v[2]; } + dist = v[0] * v[0] + v[1] * v[1]; + if (yawradius < dist) + yawradius = dist; + dist += v[2] * v[2]; + if (radius < dist) + radius = dist; } } - Mem_Free(vertex3f); + if (vertex3f) + Mem_Free(vertex3f); radius = sqrt(radius); yawradius = sqrt(yawradius); loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius; @@ -555,8 +685,10 @@ static void Mod_Alias_CalculateBoundingBox(void) 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]); @@ -566,23 +698,22 @@ static void Mod_Alias_MorphMesh_CompileFrames(void) // 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; - Mod_Alias_GetMesh_Vertices(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); + frameblend[0].subframe = i; + loadmodel->AnimateVertices(loadmodel, frameblend, NULL, 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 != 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_TraceLine(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask) { int i; float segmentmins[3], segmentmaxs[3]; - frameblend_t frameblend[4]; msurface_t *surface; static int maxvertices = 0; static float *vertex3f = NULL; @@ -590,9 +721,6 @@ static void Mod_MDLMD2MD3_TraceBox(model_t *model, int frame, trace_t *trace, co trace->fraction = 1; trace->realfraction = 1; trace->hitsupercontentsmask = hitsupercontentsmask; - memset(frameblend, 0, sizeof(frameblend)); - frameblend[0].frame = frame; - frameblend[0].lerp = 1; if (maxvertices < model->surfmesh.num_vertices) { if (vertex3f) @@ -600,51 +728,72 @@ static void Mod_MDLMD2MD3_TraceBox(model_t *model, int frame, trace_t *trace, co maxvertices = (model->surfmesh.num_vertices + 255) & ~255; vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3])); } - if (VectorLength2(boxmins) + VectorLength2(boxmaxs) == 0) + 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; + model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL); + for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++) + Collision_TraceLineTriangleMeshFloat(trace, start, 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); +} + +static int maxvertices = 0; +static float *vertex3f = NULL; + +static void Mod_MDLMD2MD3_TraceBox(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, 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]; + msurface_t *surface; + colboxbrushf_t thisbrush_start, thisbrush_end; + vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs; + + 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; - for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++) - { - Mod_Alias_GetMesh_Vertices(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); - } + VectorAdd(start, boxmins, shiftstart); + VectorAdd(end, boxmins, shiftend); + Mod_MDLMD2MD3_TraceLine(model, frameblend, skeleton, trace, start, end, hitsupercontentsmask); + VectorSubtract(trace->endpos, boxmins, trace->endpos); + return; } - else + + // box trace, performed as brush trace + memset(trace, 0, sizeof(*trace)); + trace->fraction = 1; + trace->realfraction = 1; + trace->hitsupercontentsmask = hitsupercontentsmask; + if (maxvertices < model->surfmesh.num_vertices) { - // box trace, performed as brush trace - colbrushf_t *thisbrush_start, *thisbrush_end; - vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs; - segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1; - segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1; - segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1; - segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1; - segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1; - segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1; - VectorAdd(start, boxmins, boxstartmins); - VectorAdd(start, boxmaxs, boxstartmaxs); - VectorAdd(end, boxmins, boxendmins); - VectorAdd(end, boxmaxs, boxendmaxs); - thisbrush_start = Collision_BrushForBox(&identitymatrix, boxstartmins, boxstartmaxs, 0, 0, NULL); - thisbrush_end = Collision_BrushForBox(&identitymatrix, boxendmins, boxendmaxs, 0, 0, NULL); - for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++) - { - if (maxvertices < model->surfmesh.num_vertices) - { - if (vertex3f) - Z_Free(vertex3f); - maxvertices = (model->surfmesh.num_vertices + 255) & ~255; - vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3])); - } - Mod_Alias_GetMesh_Vertices(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); - } + if (vertex3f) + Z_Free(vertex3f); + maxvertices = (model->surfmesh.num_vertices + 255) & ~255; + vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3])); + } + segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1; + segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1; + segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1; + segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1; + segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1; + segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1; + VectorAdd(start, boxmins, boxstartmins); + VectorAdd(start, boxmaxs, boxstartmaxs); + VectorAdd(end, boxmins, boxendmins); + VectorAdd(end, boxmaxs, boxendmaxs); + Collision_BrushForBox(&thisbrush_start, boxstartmins, boxstartmaxs, 0, 0, NULL); + Collision_BrushForBox(&thisbrush_end, boxendmins, boxendmaxs, 0, 0, NULL); + if (maxvertices < model->surfmesh.num_vertices) + { + if (vertex3f) + Z_Free(vertex3f); + maxvertices = (model->surfmesh.num_vertices + 255) & ~255; + vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3])); } + model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL); + for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++) + Collision_TraceBrushTriangleMeshFloat(trace, &thisbrush_start.brush, &thisbrush_end.brush, 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); } static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap) @@ -748,16 +897,17 @@ static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *ski //texture->textureflags = 0; texture->basematerialflags = MATERIALFLAG_WALL; - if (texture->currentskinframe->fog) + if (texture->currentskinframe->hasalpha) texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; texture->currentmaterialflags = texture->basematerialflags; + texture->specularscalemod = 1; + texture->specularpowermod = 1; } -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; - 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] @@ -768,16 +918,9 @@ static void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfi 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")) + if (!strcmp(skinfileitem->name, meshname)) { - if (!Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, false, false, true)) - { - tempskinframe = R_SkinFrame_LoadExternal(skinfileitem->replacement, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS, false); - if (!tempskinframe) - if (cls.state != ca_dedicated) - Con_Printf("mesh \"%s\": failed to load skin #%i \"%s\"\n", meshname, i, skinfileitem->replacement); - Mod_BuildAliasSkinFromSkinFrame(skin, tempskinframe); - } + Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS); break; } } @@ -785,26 +928,17 @@ static void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfi { // don't render unmentioned meshes Mod_BuildAliasSkinFromSkinFrame(skin, NULL); - skin->basematerialflags = skin->currentmaterialflags = 0; + skin->basematerialflags = skin->currentmaterialflags = MATERIALFLAG_NOSHADOW | MATERIALFLAG_NODRAW; } } } else - { - if (!Mod_LoadTextureFromQ3Shader(skin, shadername, false, false, true)) - { - tempskinframe = R_SkinFrame_LoadExternal(shadername, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS, false); - 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, tempskinframe); - } - } + Mod_LoadTextureFromQ3Shader(skin, shadername, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS); } #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; @@ -839,23 +973,28 @@ void Mod_IDP0_Load(model_t *mod, void *buffer, void *bufferend) loadmodel->modeldatatypestring = "MDL"; loadmodel->type = mod_alias; + loadmodel->AnimateVertices = Mod_MDL_AnimateVertices; loadmodel->DrawSky = NULL; loadmodel->DrawAddWaterPlanes = NULL; loadmodel->Draw = R_Q1BSP_Draw; loadmodel->DrawDepth = R_Q1BSP_DrawDepth; loadmodel->DrawDebug = R_Q1BSP_DrawDebug; + loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass; + loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap; + 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->TraceLine = Mod_MDLMD2MD3_TraceLine; loadmodel->PointSuperContents = NULL; 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->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); @@ -933,6 +1072,7 @@ void Mod_IDP0_Load(model_t *mod, void *buffer, void *bufferend) loadmodel->surfmesh.num_morphframes++; } } + loadmodel->num_poses = loadmodel->surfmesh.num_morphframes; // store texture coordinates into temporary array, they will be stored // after usage is determined (triangle data) @@ -998,6 +1138,13 @@ void Mod_IDP0_Load(model_t *mod, void *buffer, void *bufferend) 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); + if (loadmodel->surfmesh.data_element3s) + 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); @@ -1012,12 +1159,12 @@ void Mod_IDP0_Load(model_t *mod, void *buffer, void *bufferend) // 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++) @@ -1030,6 +1177,10 @@ void Mod_IDP0_Load(model_t *mod, void *buffer, void *bufferend) } 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++) @@ -1060,7 +1211,7 @@ void Mod_IDP0_Load(model_t *mod, void *buffer, void *bufferend) } } - 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; @@ -1069,16 +1220,11 @@ void Mod_IDP0_Load(model_t *mod, void *buffer, void *bufferend) 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); - if (!Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, name, false, false, true)) - { - tempskinframe = R_SkinFrame_LoadExternal(name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS, false); - if (!tempskinframe) - tempskinframe = R_SkinFrame_LoadInternalQuake(name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP, true, r_fullbrights.integer, (unsigned char *)datapointer, skinwidth, skinheight); - Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, tempskinframe); - } + 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 | TEXF_PRECACHE)) + Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, R_SkinFrame_LoadInternalQuake(name, TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP, true, r_fullbrights.integer, (unsigned char *)datapointer, skinwidth, skinheight)); datapointer += skinwidth * skinheight; totalskins++; } @@ -1128,7 +1274,7 @@ void Mod_IDP0_Load(model_t *mod, void *buffer, void *bufferend) 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; @@ -1147,7 +1293,6 @@ void Mod_IDP2_Load(model_t *mod, void *buffer, void *bufferend) unsigned short st; } *hash, **md2verthash, *md2verthashdata; - skinframe_t *tempskinframe; skinfile_t *skinfiles; pinmodel = (md2_t *)buffer; @@ -1161,15 +1306,20 @@ void Mod_IDP2_Load(model_t *mod, void *buffer, void *bufferend) loadmodel->modeldatatypestring = "MD2"; loadmodel->type = mod_alias; + loadmodel->AnimateVertices = Mod_MDL_AnimateVertices; loadmodel->DrawSky = NULL; loadmodel->DrawAddWaterPlanes = NULL; loadmodel->Draw = R_Q1BSP_Draw; loadmodel->DrawDepth = R_Q1BSP_DrawDepth; loadmodel->DrawDebug = R_Q1BSP_DrawDebug; + loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass; + loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap; + 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->TraceLine = Mod_MDLMD2MD3_TraceLine; loadmodel->PointSuperContents = NULL; if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536) @@ -1199,6 +1349,7 @@ void Mod_IDP2_Load(model_t *mod, void *buffer, void *bufferend) 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; @@ -1208,8 +1359,8 @@ void Mod_IDP2_Load(model_t *mod, void *buffer, void *bufferend) 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]); @@ -1235,15 +1386,7 @@ void Mod_IDP2_Load(model_t *mod, void *buffer, void *bufferend) 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) - { - if (!Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, false, false, true)) - { - tempskinframe = R_SkinFrame_LoadExternal(inskin, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS, false); - if (!tempskinframe) - Con_Printf("%s is missing skin \"%s\"\n", loadmodel->name, inskin); - Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i * loadmodel->num_surfaces, tempskinframe); - } - } + 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 { @@ -1327,6 +1470,13 @@ void Mod_IDP2_Load(model_t *mod, void *buffer, void *bufferend) 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); + if (loadmodel->surfmesh.data_element3s) + 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++) @@ -1372,7 +1522,7 @@ void Mod_IDP2_Load(model_t *mod, void *buffer, void *bufferend) 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; @@ -1399,15 +1549,20 @@ void Mod_IDP3_Load(model_t *mod, void *buffer, void *bufferend) loadmodel->modeldatatypestring = "MD3"; loadmodel->type = mod_alias; + loadmodel->AnimateVertices = Mod_MD3_AnimateVertices; loadmodel->DrawSky = NULL; loadmodel->DrawAddWaterPlanes = NULL; loadmodel->Draw = R_Q1BSP_Draw; loadmodel->DrawDepth = R_Q1BSP_DrawDepth; loadmodel->DrawDebug = R_Q1BSP_DrawDebug; + loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass; + loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap; + 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->TraceLine = Mod_MDLMD2MD3_TraceLine; loadmodel->PointSuperContents = NULL; loadmodel->synctype = ST_RAND; // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc) @@ -1469,17 +1624,20 @@ void Mod_IDP3_Load(model_t *mod, void *buffer, void *bufferend) 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.num_morphframes = loadmodel->numframes; // TODO: remove? + loadmodel->num_poses = loadmodel->surfmesh.num_morphframes; 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_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]); meshvertices = 0; meshtriangles = 0; @@ -1487,7 +1645,7 @@ void Mod_IDP3_Load(model_t *mod, void *buffer, void *bufferend) { 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; @@ -1518,24 +1676,24 @@ void Mod_IDP3_Load(model_t *mod, void *buffer, void *bufferend) } } - if (LittleLong(pinmesh->num_shaders) >= 1) - Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name); - else - for (j = 0;j < loadmodel->numskins;j++) - Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i + j * loadmodel->num_surfaces, NULL); + Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, pinmesh->name, LittleLong(pinmesh->num_shaders) >= 1 ? ((md3shader_t *)((unsigned char *) pinmesh + LittleLong(pinmesh->lump_shaders)))->name : ""); Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__); } + if (loadmodel->surfmesh.data_element3s) + for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++) + loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i]; Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles); Mod_Alias_MorphMesh_CompileFrames(); Mod_Alias_CalculateBoundingBox(); Mod_FreeSkinFiles(skinfiles); + Mod_MakeSortedSurfaces(loadmodel); - loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 + 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; @@ -1607,15 +1765,20 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer, void *bufferend) return; } + loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices; loadmodel->DrawSky = NULL; loadmodel->DrawAddWaterPlanes = NULL; loadmodel->Draw = R_Q1BSP_Draw; loadmodel->DrawDepth = R_Q1BSP_DrawDepth; loadmodel->DrawDebug = R_Q1BSP_DrawDebug; + loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass; + loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap; + 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->TraceLine = Mod_MDLMD2MD3_TraceLine; loadmodel->PointSuperContents = NULL; loadmodel->numframes = pheader->numscenes; @@ -1679,7 +1842,7 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer, void *bufferend) //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++) { @@ -1700,7 +1863,7 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer, void *bufferend) 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; @@ -1708,9 +1871,9 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer, void *bufferend) 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; @@ -1723,8 +1886,10 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer, void *bufferend) 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]); //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data poses = (float *) (pheader->lump_poses.start + pbase); @@ -1801,7 +1966,7 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer, void *bufferend) 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; @@ -1832,17 +1997,17 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer, void *bufferend) // since zym models do not have named sections, reuse their shader // name as the section name shadername = (char *) (pheader->lump_shaders.start + pbase) + i * 32; - if (shadername[0]) - Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername); - else - for (j = 0;j < loadmodel->numskins;j++) - Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i + j * loadmodel->num_surfaces, NULL); + Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, shadername, shadername); } Mod_FreeSkinFiles(skinfiles); Mem_Free(vertbonecounts); Mem_Free(verts); + Mod_MakeSortedSurfaces(loadmodel); // compute all the mesh information that was not loaded from the file + if (loadmodel->surfmesh.data_element3s) + for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++) + loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i]; Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__); Mod_BuildBaseBonePoses(); Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true); @@ -1852,7 +2017,7 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer, void *bufferend) 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; @@ -1905,15 +2070,20 @@ void Mod_DARKPLACESMODEL_Load(model_t *mod, void *buffer, void *bufferend) return; } + loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices; loadmodel->DrawSky = NULL; loadmodel->DrawAddWaterPlanes = NULL; loadmodel->Draw = R_Q1BSP_Draw; loadmodel->DrawDepth = R_Q1BSP_DrawDepth; loadmodel->DrawDebug = R_Q1BSP_DrawDebug; + loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass; + loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap; + 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->TraceLine = Mod_MDLMD2MD3_TraceLine; loadmodel->PointSuperContents = NULL; // model bbox @@ -1942,21 +2112,21 @@ void Mod_DARKPLACESMODEL_Load(model_t *mod, void *buffer, void *bufferend) 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; @@ -1969,11 +2139,13 @@ void Mod_DARKPLACESMODEL_Load(model_t *mod, void *buffer, void *bufferend) 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->numskins;i++) { @@ -2036,7 +2208,7 @@ void Mod_DARKPLACESMODEL_Load(model_t *mod, void *buffer, void *bufferend) 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; @@ -2131,18 +2303,18 @@ void Mod_DARKPLACESMODEL_Load(model_t *mod, void *buffer, void *bufferend) } // since dpm models do not have named sections, reuse their shader name as the section name - if (dpmmesh->shadername[0]) - Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername); - else - for (j = 0;j < loadmodel->numskins;j++) - Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i + j * loadmodel->num_surfaces, NULL); + Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + i, skinfiles, dpmmesh->shadername, dpmmesh->shadername); Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__); } Z_Free(bonepose); Mod_FreeSkinFiles(skinfiles); + Mod_MakeSortedSurfaces(loadmodel); // compute all the mesh information that was not loaded from the file + if (loadmodel->surfmesh.data_element3s) + for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++) + loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i]; Mod_BuildBaseBonePoses(); 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_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles); @@ -2152,7 +2324,7 @@ void Mod_DARKPLACESMODEL_Load(model_t *mod, void *buffer, void *bufferend) // 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; @@ -2171,6 +2343,7 @@ void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend) pskchunk_t *pchunk; skinfile_t *skinfiles; char animname[MAX_QPATH]; + size_t size; pchunk = (pskchunk_t *)buffer; if (strcmp(pchunk->id, "ACTRHEAD")) @@ -2179,15 +2352,20 @@ void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend) loadmodel->modeldatatypestring = "PSK"; loadmodel->type = mod_alias; + loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices; loadmodel->DrawSky = NULL; loadmodel->DrawAddWaterPlanes = NULL; loadmodel->Draw = R_Q1BSP_Draw; loadmodel->DrawDepth = R_Q1BSP_DrawDepth; loadmodel->DrawDebug = R_Q1BSP_DrawDebug; + loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass; + loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap; + 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->TraceLine = Mod_MDLMD2MD3_TraceLine; loadmodel->PointSuperContents = NULL; loadmodel->synctype = ST_RAND; @@ -2532,31 +2710,34 @@ void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend) 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->numskins;i++) { @@ -2570,12 +2751,8 @@ void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend) for (index = 0, i = 0;index < nummatts;index++) { // since psk models do not have named sections, reuse their shader name as the section name - if (matts[index].name[0]) - Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name); - else - for (j = 0;j < loadmodel->numskins;j++) - Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + index + j * loadmodel->num_surfaces, NULL); - loadmodel->surfacelist[index] = index; + Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name); + 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; @@ -2682,9 +2859,13 @@ void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend) } 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? + if (loadmodel->surfmesh.data_element3s) + for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++) + loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i]; Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__); Mod_BuildBaseBonePoses(); Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true); @@ -2694,4 +2875,3 @@ void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend) loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1; } -