X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=model_alias.c;h=960de7ae644ea9cd4d7fd2c89fe7581f1971cec0;hp=590ee02d77b55a25ba8f6b498addbda90966bf28;hb=7a96ec58916ceea50684acf4c00eaef551199fef;hpb=ded16fd66f1a999d35ee57f989f881f205a428c7 diff --git a/model_alias.c b/model_alias.c index 590ee02d..960de7ae 100644 --- a/model_alias.c +++ b/model_alias.c @@ -44,320 +44,356 @@ void Mod_AliasInit (void) 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, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f) { #define MAX_BONES 256 - if (model->surfmesh.data_vertexweightindex4i) - { - // 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++) + // 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++) { - int blends; - float *matrix, m[12], bonepose[MAX_BONES][12]; + matrix = model->data_poses + (frameblend[blends].frame * model->num_bones + i) * 12; + for (k = 0;k < 12;k++) + m[k] += matrix[k] * frameblend[blends].lerp; + } + if (i == r_skeletal_debugbone.integer) + m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value; + m[3] *= r_skeletal_debugtranslatex.value; + m[7] *= r_skeletal_debugtranslatey.value; + m[11] *= r_skeletal_debugtranslatez.value; + 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++) - m[k] = 0; - for (blends = 0;blends < 4 && frameblend[blends].lerp > 0;blends++) + 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]); + } + // 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 + { + 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) { - matrix = model->data_poses + (frameblend[blends].frame * model->num_bones + i) * 12; - for (k = 0;k < 12;k++) - m[k] += matrix[k] * frameblend[blends].lerp; + 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]); } - if (i == r_skeletal_debugbone.integer) - m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value; - m[3] *= r_skeletal_debugtranslatex.value; - m[7] *= r_skeletal_debugtranslatey.value; - m[11] *= r_skeletal_debugtranslatez.value; - 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]); - } - // 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 - { - const float *v = model->surfmesh.data_vertex3f; - const int *wi = model->surfmesh.data_vertexweightindex4i; - const float *wf = model->surfmesh.data_vertexweightinfluence4f; - for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, wi += 4, wf += 4, vertex3f += 3) { - 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]]; + 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; - 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; - 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; - 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) - { - // vertex morph - int i, numblends, blendnum; - int numverts = model->surfmesh.num_vertices; - numblends = 0; - for (blendnum = 0;blendnum < 4;blendnum++) +} + +void Mod_MD3_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f) +{ + // vertex morph + int i, numblends, blendnum; + int numverts = model->surfmesh.num_vertices; + numblends = 0; + for (blendnum = 0;blendnum < 4;blendnum++) + { + //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].frame; + float scale = frameblend[blendnum].lerp * (1.0f / 64.0f); + if (blendnum == 0) { - //VectorMA(translate, model->surfmesh.num_morphmdlframetranslate, frameblend[blendnum].lerp, translate); - if (frameblend[blendnum].lerp > 0) - numblends = blendnum + 1; + 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; + } } - // 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++) + 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 + // 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) { - const md3vertex_t *verts = model->surfmesh.data_morphmd3vertex + numverts * frameblend[blendnum].frame; - float scale = frameblend[blendnum].lerp * (1.0f / 64.0f); + float lerp = frameblend[blendnum].lerp; if (blendnum == 0) { 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; + 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++) { - 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; + 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; } } - // 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) + } + if (svector3f) + { + const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].frame; + float f = frameblend[blendnum].lerp * (1.0f / 127.0f); + if (blendnum == 0) { - float lerp = frameblend[blendnum].lerp; - if (blendnum == 0) + for (i = 0;i < numverts;i++, texvecvert++) { - 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; - } + 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++) - { - 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; - } + VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3); + VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3); } } } - // 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); - } - 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++) + } +} + +void Mod_MDL_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f) +{ + // vertex morph + int i, numblends, blendnum; + 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++) + { + const trivertx_t *verts = model->surfmesh.data_morphmdlvertex + numverts * frameblend[blendnum].frame; + float scale[3]; + if (model->surfmesh.data_morphmd2framesize6f) + VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].frame * 6, frameblend[blendnum].lerp, scale); + else + VectorScale(model->surfmesh.num_morphmdlframescale, frameblend[blendnum].lerp, scale); + if (blendnum == 0) { - 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; + 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]; + } } - // 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++) + else { - const trivertx_t *verts = model->surfmesh.data_morphmdlvertex + numverts * frameblend[blendnum].frame; - float scale[3]; - if (model->surfmesh.data_morphmd2framesize6f) - VectorScale(model->surfmesh.data_morphmd2framesize6f + frameblend[blendnum].frame * 6, frameblend[blendnum].lerp, scale); - else - VectorScale(model->surfmesh.num_morphmdlframescale, frameblend[blendnum].lerp, scale); + 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 + // 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) { 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]; + const float *vn = m_bytenormals[verts[i].lightnormalindex]; + VectorScale(vn, lerp, normal3f + i*3); } } else { 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]; + const float *vn = m_bytenormals[verts[i].lightnormalindex]; + VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3); } } - // 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) + } + if (svector3f) + { + const texvecvertex_t *texvecvert = model->surfmesh.data_morphtexvecvertex + numverts * frameblend[blendnum].frame; + float f = frameblend[blendnum].lerp * (1.0f / 127.0f); + if (blendnum == 0) { - float lerp = frameblend[blendnum].lerp; - if (blendnum == 0) + for (i = 0;i < numverts;i++, texvecvert++) { - for (i = 0;i < numverts;i++) - { - const float *vn = m_bytenormals[verts[i].lightnormalindex]; - VectorScale(vn, lerp, normal3f + 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++) - { - const float *vn = m_bytenormals[verts[i].lightnormalindex]; - VectorMA(normal3f + i*3, lerp, vn, normal3f + i*3); - } + VectorMA(svector3f + i*3, f, texvecvert->svec, svector3f + i*3); + VectorMA(tvector3f + i*3, f, texvecvert->tvec, tvector3f + i*3); } } } - 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); } - 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, int poseframe, int tagindex, matrix4x4_t *outmatrix) { const float *boneframe; float tempbonematrix[12], bonematrix[12]; @@ -389,13 +425,11 @@ int Mod_Alias_GetTagMatrix(const model_t *model, int poseframe, int tagindex, ma return 0; } -int Mod_Alias_GetTagIndexForName(const model_t *model, unsigned int skin, const char *tagname) +int Mod_Alias_GetTagIndexForName(const dp_model_t *model, unsigned int skin, const char *tagname) { int i; - 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(skin >= (unsigned int)model->numskins) + skin = 0; if (model->num_bones) for (i = 0;i < model->num_bones;i++) if (!strcasecmp(tagname, model->data_bones[i].name)) @@ -411,13 +445,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]; @@ -447,11 +482,11 @@ 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) { - int i, j; int vnum; qboolean firstvertex = true; float dist, yawradius, radius; @@ -465,35 +500,32 @@ static void Mod_Alias_CalculateBoundingBox(void) VectorClear(loadmodel->normalmaxs); yawradius = 0; radius = 0; - for (i = 0;i < loadmodel->numframes;i++) + for (frameblend[0].frame = 0;frameblend[0].frame < loadmodel->num_poses;frameblend[0].frame++) { - for (j = 0, frameblend[0].frame = loadmodel->animscenes[i].firstframe;j < loadmodel->animscenes[i].framecount;j++, frameblend[0].frame++) + loadmodel->AnimateVertices(loadmodel, frameblend, 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); @@ -509,17 +541,33 @@ static void Mod_Alias_CalculateBoundingBox(void) loadmodel->radius2 = radius * radius; } -static void Mod_Alias_Mesh_CompileFrameZero(void) +static void Mod_Alias_MorphMesh_CompileFrames(void) { + int i, j; frameblend_t frameblend[4] = {{0, 1}, {0, 0}, {0, 0}, {0, 0}}; - loadmodel->surfmesh.data_vertex3f = (float *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3][4])); - 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, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f); + unsigned char *datapointer; + 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]); + loadmodel->surfmesh.data_tvector3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]); + loadmodel->surfmesh.data_normal3f = (float *)datapointer;datapointer += loadmodel->surfmesh.num_vertices * sizeof(float[3]); + loadmodel->surfmesh.data_morphtexvecvertex = (texvecvertex_t *)datapointer;datapointer += loadmodel->surfmesh.num_morphframes * loadmodel->surfmesh.num_vertices * sizeof(texvecvertex_t); + // 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; + loadmodel->AnimateVertices(loadmodel, frameblend, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL); + Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, r_smoothnormals_areaweighting.integer); + // 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); + } + } } -static void Mod_MDLMD2MD3_TraceBox(model_t *model, int frame, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask) +static void Mod_MDLMD2MD3_TraceBox(dp_model_t *model, int frame, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask) { int i; float segmentmins[3], segmentmaxs[3]; @@ -552,7 +600,7 @@ static void Mod_MDLMD2MD3_TraceBox(model_t *model, int frame, trace_t *trace, co 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); + model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL); Collision_TraceLineTriangleMeshFloat(trace, start, end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, SUPERCONTENTS_SOLID, 0, surface->texture, segmentmins, segmentmaxs); } } @@ -582,7 +630,7 @@ 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])); } - Mod_Alias_GetMesh_Vertices(model, frameblend, vertex3f, NULL, NULL, NULL); + model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL); Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, SUPERCONTENTS_SOLID, 0, surface->texture, segmentmins, segmentmaxs); } } @@ -668,22 +716,29 @@ static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *ve static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *skinframe) { + if (cls.state == ca_dedicated) + return; + // hack + if (!skinframe) + skinframe = R_SkinFrame_LoadMissing(); + memset(texture, 0, sizeof(*texture)); texture->currentframe = texture; + //texture->animated = false; texture->numskinframes = 1; texture->skinframerate = 1; - texture->currentskinframe = texture->skinframes + 0; - if (skinframe) - texture->skinframes[0] = *skinframe; - else - { - // hack - memset(texture->skinframes, 0, sizeof(texture->skinframes)); - texture->skinframes[0].base = r_texture_notexture; - } + texture->skinframes[0] = skinframe; + texture->currentskinframe = skinframe; + //texture->backgroundnumskinframes = 0; + //texture->customblendfunc[0] = 0; + //texture->customblendfunc[1] = 0; + //texture->surfaceflags = 0; + //texture->supercontents = 0; + //texture->surfaceparms = 0; + //texture->textureflags = 0; texture->basematerialflags = MATERIALFLAG_WALL; if (texture->currentskinframe->fog) - texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_TRANSPARENT | MATERIALFLAG_NOSHADOW; + texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; texture->currentmaterialflags = texture->basematerialflags; } @@ -691,43 +746,37 @@ static void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfi { 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] 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")) + if (!strcmp(skinfileitem->name, meshname)) { - if (!Mod_LoadSkinFrame(&tempskinframe, skinfileitem->replacement, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP, true, true)) - 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; } } + if (!skinfileitem) + { + // don't render unmentioned meshes + Mod_BuildAliasSkinFromSkinFrame(skin, NULL); + skin->basematerialflags = skin->currentmaterialflags = 0; + } } } else - { - if (!Mod_LoadSkinFrame(&tempskinframe, shadername, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP, true, true)) - 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; @@ -743,7 +792,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; @@ -759,13 +808,20 @@ void Mod_IDP0_Load(model_t *mod, void *buffer, void *bufferend) Host_Error ("%s has wrong version number (%i should be %i)", loadmodel->name, version, ALIAS_VERSION); + 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->CompileShadowVolume = R_Q1BSP_CompileShadowVolume; loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume; loadmodel->DrawLight = R_Q1BSP_DrawLight; loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox; + loadmodel->PointSuperContents = NULL; loadmodel->num_surfaces = 1; loadmodel->nummodelsurfaces = loadmodel->num_surfaces; @@ -788,7 +844,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++) { @@ -848,6 +906,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) @@ -913,6 +972,14 @@ 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); + 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); @@ -920,7 +987,7 @@ void Mod_IDP0_Load(model_t *mod, void *buffer, void *bufferend) Mod_MDL_LoadFrames (startframes, numverts, vertremap); Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles); Mod_Alias_CalculateBoundingBox(); - Mod_Alias_Mesh_CompileFrameZero(); + Mod_Alias_MorphMesh_CompileFrames(); Mem_Free(vertst); Mem_Free(vertremap); @@ -928,7 +995,8 @@ 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; + 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) { @@ -986,16 +1054,16 @@ 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); + if (!Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, name, false, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS)) + Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + totalskins * loadmodel->num_surfaces, R_SkinFrame_LoadInternalQuake(name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP, true, r_fullbrights.integer, (unsigned char *)datapointer, skinwidth, skinheight)); datapointer += skinwidth * skinheight; 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)) + // TODO: support shaders here? + while ((tempskinframe = R_SkinFrame_LoadExternal(va("%s_%i", loadmodel->name, loadmodel->numskins), (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS, false))) { // expand the arrays to make room tempskinscenes = loadmodel->skinscenes; @@ -1009,7 +1077,7 @@ 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); + 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; @@ -1019,6 +1087,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]; } } @@ -1032,7 +1105,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; @@ -1051,7 +1124,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; @@ -1062,13 +1134,20 @@ void Mod_IDP2_Load(model_t *mod, void *buffer, void *bufferend) Host_Error ("%s has wrong version number (%i should be %i)", loadmodel->name, version, MD2ALIAS_VERSION); + 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->CompileShadowVolume = R_Q1BSP_CompileShadowVolume; loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume; loadmodel->DrawLight = R_Q1BSP_DrawLight; loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox; + loadmodel->PointSuperContents = NULL; if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536) Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris)); @@ -1097,6 +1176,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; @@ -1113,7 +1193,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 @@ -1121,7 +1200,8 @@ void Mod_IDP2_Load(model_t *mod, void *buffer, void *bufferend) skinfiles = Mod_LoadSkinFiles(); if (skinfiles) { - loadmodel->num_textures = loadmodel->num_surfaces; + 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); @@ -1129,20 +1209,18 @@ void Mod_IDP2_Load(model_t *mod, void *buffer, void *bufferend) else if (loadmodel->numskins) { // skins found (most likely not a player model) - loadmodel->num_textures = loadmodel->num_surfaces; + loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins; + loadmodel->num_texturesperskin = loadmodel->num_surfaces; loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t)); for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME) - { - if (!Mod_LoadSkinFrame(&tempskinframe, inskin, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP, true, true)) - 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 { // no skins (most likely a player model) loadmodel->numskins = 1; - loadmodel->num_textures = loadmodel->num_surfaces; + loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins; + loadmodel->num_texturesperskin = loadmodel->num_surfaces; loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t)); Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL); } @@ -1219,6 +1297,14 @@ 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); + 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++) @@ -1252,7 +1338,7 @@ void Mod_IDP2_Load(model_t *mod, void *buffer, void *bufferend) Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles); Mod_Alias_CalculateBoundingBox(); - Mod_Alias_Mesh_CompileFrameZero(); + Mod_Alias_MorphMesh_CompileFrames(); surface = loadmodel->data_surfaces; surface->texture = loadmodel->data_textures; @@ -1264,7 +1350,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; @@ -1288,15 +1374,24 @@ void Mod_IDP3_Load(model_t *mod, void *buffer, void *bufferend) if (loadmodel->numskins < 1) loadmodel->numskins = 1; + 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->CompileShadowVolume = R_Q1BSP_CompileShadowVolume; loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume; loadmodel->DrawLight = R_Q1BSP_DrawLight; loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox; - loadmodel->flags = LittleLong(pinmodel->flags); + loadmodel->PointSuperContents = NULL; 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); @@ -1351,18 +1446,26 @@ void Mod_IDP3_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[2]) + meshvertices * loadmodel->numframes * sizeof(md3vertex_t)); + 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 <= 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->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]); + for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++) + loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i]; + } meshvertices = 0; meshtriangles = 0; @@ -1401,23 +1504,20 @@ 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__); } Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles); - Mod_Alias_Mesh_CompileFrameZero(); + Mod_Alias_MorphMesh_CompileFrames(); Mod_Alias_CalculateBoundingBox(); Mod_FreeSkinFiles(skinfiles); - loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 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; @@ -1438,8 +1538,9 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer, void *bufferend) if (BigLong(pinmodel->type) != 1) Host_Error ("Mod_ZYMOTICMODEL_Load: only type 1 (skeletal pose) models are currently supported (name = %s)", loadmodel->name); + loadmodel->modeldatatypestring = "ZYM"; + loadmodel->type = mod_alias; - loadmodel->flags = 0; // there are no flags on zym models loadmodel->synctype = ST_RAND; // byteswap header @@ -1488,12 +1589,17 @@ 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->CompileShadowVolume = R_Q1BSP_CompileShadowVolume; loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume; loadmodel->DrawLight = R_Q1BSP_DrawLight; loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox; + loadmodel->PointSuperContents = NULL; loadmodel->numframes = pheader->numscenes; loadmodel->num_surfaces = pheader->numshaders; @@ -1583,8 +1689,9 @@ void Mod_ZYMOTICMODEL_Load(model_t *mod, void *buffer, void *bufferend) meshtriangles = pheader->numtris; 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])); + 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 <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + 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); @@ -1600,8 +1707,13 @@ 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]); + if (loadmodel->surfmesh.num_vertices <= 65536) + { + loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]); + for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++) + loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i]; + } //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data poses = (float *) (pheader->lump_poses.start + pbase); @@ -1709,11 +1821,7 @@ 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); @@ -1729,7 +1837,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; @@ -1748,8 +1856,9 @@ void Mod_DARKPLACESMODEL_Load(model_t *mod, void *buffer, void *bufferend) 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->modeldatatypestring = "DPM"; + loadmodel->type = mod_alias; - loadmodel->flags = 0; // there are no flags on zym models loadmodel->synctype = ST_RAND; // byteswap header @@ -1781,12 +1890,17 @@ 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->CompileShadowVolume = R_Q1BSP_CompileShadowVolume; loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume; loadmodel->DrawLight = R_Q1BSP_DrawLight; loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox; + loadmodel->PointSuperContents = NULL; // model bbox for (i = 0;i < 3;i++) @@ -1822,9 +1936,11 @@ void Mod_DARKPLACESMODEL_Load(model_t *mod, void *buffer, void *bufferend) loadmodel->numframes = pheader->num_frames; loadmodel->num_bones = pheader->num_bones; loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes; - loadmodel->num_textures = loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs; + 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[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]) + (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 * 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); @@ -1840,11 +1956,16 @@ 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); + if (meshvertices <= 65536) + { + loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]); + for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++) + loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i]; + } for (i = 0;i < loadmodel->numskins;i++) { @@ -2002,11 +2123,7 @@ 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__); } @@ -2023,7 +2140,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; @@ -2047,14 +2164,20 @@ void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend) if (strcmp(pchunk->id, "ACTRHEAD")) Host_Error ("Mod_PSKMODEL_Load: %s is not an Unreal Engine ActorX (.psk + .psa) model", loadmodel->name); + 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->CompileShadowVolume = R_Q1BSP_CompileShadowVolume; 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->PointSuperContents = NULL; loadmodel->synctype = ST_RAND; FS_StripExtension(loadmodel->name, animname, sizeof(animname)); @@ -2399,9 +2522,11 @@ void Mod_PSKMODEL_Load(model_t *mod, void *buffer, void *bufferend) loadmodel->numskins = 1; loadmodel->num_bones = numbones; loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes; - loadmodel->num_textures = loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts; + loadmodel->nummodelsurfaces = loadmodel->num_surfaces = nummatts; + 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[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]) + (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 * 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); @@ -2417,11 +2542,16 @@ 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); + if (meshvertices <= 65536) + { + loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]); + for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++) + loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i]; + } for (i = 0;i < loadmodel->numskins;i++) { @@ -2435,11 +2565,7 @@ 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); + Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures + index, skinfiles, matts[index].name, matts[index].name); loadmodel->surfacelist[index] = index; loadmodel->data_surfaces[index].texture = loadmodel->data_textures + index; loadmodel->data_surfaces[index].num_firstvertex = 0;