X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=model_alias.c;h=9fd4d1cce97d4d622a7f580ee185f26c18099edc;hp=7a2c8d60f27515a38f9388c76ad31f8dec278967;hb=001e49ea761abfc2982a5999e102b6bfe83a4e50;hpb=f5352fd59b6c6bc5589229670655f77f9e6069ed diff --git a/model_alias.c b/model_alias.c index 7a2c8d60..9fd4d1cc 100644 --- a/model_alias.c +++ b/model_alias.c @@ -46,14 +46,93 @@ void Mod_AliasInit (void) mod_md3_sin[i] = sin(i * M_PI * 2.0f / 256.0); } -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) +int Mod_Skeletal_AddBlend(dp_model_t *model, const int *newindex, const float *newinfluence) +{ + int i, total; + float scale; + blendweights_t *weights; + blendweights_t newweights; + if(!newinfluence[1]) + return newindex[0]; + scale = 0; + for (i = 0;i < 4;i++) + scale += newinfluence[i]; + scale = 255.0f / scale; + total = 0; + for (i = 0;i < 4;i++) + { + newweights.index[i] = newindex[i]; + newweights.influence[i] = (unsigned char)(newinfluence[i] * scale); + total += newweights.influence[i]; + } + while (total > 255) + { + for (i = 0;i < 4;i++) + { + if(newweights.influence[i] > 0 && total > 255) + { + newweights.influence[i]--; + total--; + } + } + } + while (total < 255) + { + for (i = 0; i < 4;i++) + { + if(newweights.influence[i] < 255 && total < 255) + { + newweights.influence[i]++; + total++; + } + } + } + weights = model->surfmesh.data_blendweights; + for (i = 0;i < model->surfmesh.num_blends;i++, weights++) + { + if (!memcmp(weights, &newweights, sizeof(blendweights_t))) + return model->num_bones + i; + } + model->surfmesh.num_blends++; + memcpy(weights, &newweights, sizeof(blendweights_t)); + return model->num_bones + i; +} + +static int maxbonepose = 0; +static float (*bonepose)[12] = NULL; + +void Mod_Skeletal_FreeBuffers(void) +{ + if(bonepose) + Mem_Free(bonepose); + maxbonepose = 0; + bonepose = NULL; +} + +#if defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1400) +#define RESTRICT __restrict +#else +#define RESTRICT +#endif + +void Mod_Skeletal_AnimateVertices(const dp_model_t * RESTRICT model, const frameblend_t * RESTRICT frameblend, const skeleton_t *skeleton, float * RESTRICT vertex3f, float * RESTRICT normal3f, float * RESTRICT svector3f, float * RESTRICT tvector3f) { -#define MAX_BONES 256 // vertex weighted skeletal int i, k; int blends; - float boneposerelative[MAX_BONES][12]; - float m[12], bonepose[MAX_BONES][12]; + float m[12]; + float (*boneposerelative)[12]; + const blendweights_t * RESTRICT weights; + + if (maxbonepose < model->num_bones*2 + model->surfmesh.num_blends) + { + if (bonepose) + Mem_Free(bonepose); + maxbonepose = model->num_bones*2 + model->surfmesh.num_blends; + bonepose = (float (*)[12])Mem_Alloc(r_main_mempool, maxbonepose * sizeof(float[12])); + } + + boneposerelative = bonepose + model->num_bones; if (skeleton && !skeleton->relativetransforms) skeleton = NULL; @@ -67,9 +146,8 @@ void Mod_Skeletal_AnimateVertices(const dp_model_t *model, const frameblend_t *f 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]; - + memcpy(bonepose[i], m, sizeof(m)); + // 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]); @@ -79,11 +157,10 @@ void Mod_Skeletal_AnimateVertices(const dp_model_t *model, const frameblend_t *f { float originscale = model->num_posescale; float x,y,z,w,lerp; - const short *pose6s; + const short * RESTRICT pose6s; for (i = 0;i < model->num_bones;i++) { - for (k = 0;k < 12;k++) - m[k] = 0; + memset(m, 0, sizeof(m)); for (blends = 0;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++) { pose6s = model->data_poses6s + 6 * (frameblend[blends].subframe * model->num_bones + i); @@ -106,7 +183,7 @@ void Mod_Skeletal_AnimateVertices(const dp_model_t *model, const frameblend_t *f m[10] += (1-2*(x*x+y*y)) * lerp; m[11] += (pose6s[2] * originscale) * lerp; } - VectorNormalize(m ); + VectorNormalize(m ); VectorNormalize(m + 4); VectorNormalize(m + 8); if (i == r_skeletal_debugbone.integer) @@ -117,147 +194,122 @@ void Mod_Skeletal_AnimateVertices(const dp_model_t *model, const frameblend_t *f 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]; + memcpy(bonepose[i], m, sizeof(m)); // 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]); } } + + // generate matrices for all blend combinations + weights = model->surfmesh.data_blendweights; + for (i = 0;i < model->surfmesh.num_blends;i++, weights++) + { + float * RESTRICT b = boneposerelative[model->num_bones + i]; + const float * RESTRICT m = boneposerelative[weights->index[0]]; + float f = weights->influence[0] * (1.0f / 255.0f); + b[ 0] = f*m[ 0]; b[ 1] = f*m[ 1]; b[ 2] = f*m[ 2]; b[ 3] = f*m[ 3]; + b[ 4] = f*m[ 4]; b[ 5] = f*m[ 5]; b[ 6] = f*m[ 6]; b[ 7] = f*m[ 7]; + b[ 8] = f*m[ 8]; b[ 9] = f*m[ 9]; b[10] = f*m[10]; b[11] = f*m[11]; + for (k = 1;k < 4 && weights->influence[k];k++) + { + m = boneposerelative[weights->index[k]]; + f = weights->influence[k] * (1.0f / 255.0f); + b[ 0] += f*m[ 0]; b[ 1] += f*m[ 1]; b[ 2] += f*m[ 2]; b[ 3] += f*m[ 3]; + b[ 4] += f*m[ 4]; b[ 5] += f*m[ 5]; b[ 6] += f*m[ 6]; b[ 7] += f*m[ 7]; + b[ 8] += f*m[ 8]; b[ 9] += f*m[ 9]; b[10] += f*m[10]; b[11] += f*m[11]; + } + } - // 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 + // transform vertex attributes by blended matrices 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 * RESTRICT v = model->surfmesh.data_vertex3f; + const unsigned short * RESTRICT b = model->surfmesh.blends; + // special case common combinations of attributes to avoid repeated loading of matrices + if (normal3f) { - 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 * RESTRICT n = model->surfmesh.data_normal3f; + if (svector3f && tvector3f) { - 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 * RESTRICT sv = model->surfmesh.data_svector3f; + const float * RESTRICT tv = model->surfmesh.data_tvector3f; + for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, n += 3, sv += 3, tv += 3, b++, vertex3f += 3, normal3f += 3, svector3f += 3, tvector3f += 3) { - 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 * RESTRICT m = boneposerelative[*b]; + 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]); + 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]); + 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]); + 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]); } + return; } - } - } - 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) - { - if (wf[0] == 1) + for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, n += 3, b++, vertex3f += 3, normal3f += 3) { - const float *m = boneposerelative[wi[0]]; - normal3f[0] = (n[0] * m[0] + n[1] * m[1] + n[2] * m[ 2]); + const float * RESTRICT m = boneposerelative[*b]; + 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]); + 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 + } + else + { + for (i = 0;i < model->surfmesh.num_vertices;i++, v += 3, b++, vertex3f += 3) { - 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 * RESTRICT m = boneposerelative[*b]; + 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 if (normal3f) + { + const float * RESTRICT n = model->surfmesh.data_normal3f; + const unsigned short * RESTRICT b = model->surfmesh.blends; + for (i = 0;i < model->surfmesh.num_vertices;i++, n += 3, b++, normal3f += 3) + { + const float * RESTRICT m = boneposerelative[*b]; + 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]); + } + } + 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 * RESTRICT sv = model->surfmesh.data_svector3f; + const unsigned short * RESTRICT b = model->surfmesh.blends; + for (i = 0;i < model->surfmesh.num_vertices;i++, sv += 3, b++, svector3f += 3) { - 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]]; - 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 * RESTRICT m = boneposerelative[*b]; + 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]); } } + 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 * RESTRICT tv = model->surfmesh.data_tvector3f; + const unsigned short * RESTRICT b = model->surfmesh.blends; + for (i = 0;i < model->surfmesh.num_vertices;i++, tv += 3, b++, tvector3f += 3) { - if (wf[0] == 1) - { - const float *m = boneposerelative[wi[0]]; - tvector3f[0] = (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]); - tvector3f[1] = (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]); - tvector3f[2] = (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]); - } - else - { - const float *m = boneposerelative[wi[0]]; - float f = wf[0]; - tvector3f[0] = f * (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]); - tvector3f[1] = f * (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]); - tvector3f[2] = f * (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]); - for (k = 1;k < 4 && wf[k];k++) - { - const float *m = boneposerelative[wi[k]]; - float f = wf[k]; - tvector3f[0] += f * (tv[0] * m[0] + tv[1] * m[1] + tv[2] * m[ 2]); - tvector3f[1] += f * (tv[0] * m[4] + tv[1] * m[5] + tv[2] * m[ 6]); - tvector3f[2] += f * (tv[0] * m[8] + tv[1] * m[9] + tv[2] * m[10]); - } - } + const float * RESTRICT m = boneposerelative[*b]; + 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]); } } } @@ -743,7 +795,7 @@ static void Mod_MDLMD2MD3_TraceBox(dp_model_t *model, const frameblend_t *frameb { VectorAdd(start, boxmins, shiftstart); VectorAdd(end, boxmins, shiftend); - Mod_MDLMD2MD3_TraceLine(model, frameblend, skeleton, trace, start, end, hitsupercontentsmask); + Mod_MDLMD2MD3_TraceLine(model, frameblend, skeleton, trace, shiftstart, shiftend, hitsupercontentsmask); VectorSubtract(trace->endpos, boxmins, trace->endpos); return; } @@ -890,6 +942,10 @@ static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *ski texture->currentmaterialflags = texture->basematerialflags; texture->specularscalemod = 1; texture->specularpowermod = 1; + texture->surfaceflags = 0; + texture->supercontents = SUPERCONTENTS_SOLID; + if (!(texture->basematerialflags & MATERIALFLAG_BLENDED)) + texture->supercontents |= SUPERCONTENTS_OPAQUE; } void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername) @@ -997,7 +1053,7 @@ void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend) loadmodel->numframes = LittleLong(pinmodel->numframes); BOUNDI(loadmodel->numframes,0,65536); loadmodel->synctype = (synctype_t)LittleLong (pinmodel->synctype); - BOUNDI(loadmodel->synctype,0,2); + BOUNDI((int)loadmodel->synctype,0,2); // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc) i = LittleLong (pinmodel->flags); loadmodel->effects = ((i & 255) << 24) | (i & 0x00FFFF00); @@ -1260,6 +1316,15 @@ void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend) surface->num_vertices = loadmodel->surfmesh.num_vertices; loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1; + + if (!loadmodel->surfmesh.isanimated) + { + Mod_MakeCollisionBIH(loadmodel, true); + loadmodel->TraceBox = Mod_CollisionBIH_TraceBox; + loadmodel->TraceLine = Mod_CollisionBIH_TraceLine; + loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh; + loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh; + } } void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend) @@ -1508,6 +1573,15 @@ void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend) surface->num_vertices = loadmodel->surfmesh.num_vertices; loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1; + + if (!loadmodel->surfmesh.isanimated) + { + Mod_MakeCollisionBIH(loadmodel, true); + loadmodel->TraceBox = Mod_CollisionBIH_TraceBox; + loadmodel->TraceLine = Mod_CollisionBIH_TraceLine; + loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh; + loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh; + } } void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend) @@ -1679,6 +1753,15 @@ void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend) loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1); + + if (!loadmodel->surfmesh.isanimated) + { + Mod_MakeCollisionBIH(loadmodel, true); + loadmodel->TraceBox = Mod_CollisionBIH_TraceBox; + loadmodel->TraceLine = Mod_CollisionBIH_TraceLine; + loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh; + loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh; + } } void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) @@ -1859,7 +1942,7 @@ void Mod_ZYMOTICMODEL_Load(dp_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 <= 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(short[6]) + 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(unsigned short) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]) + loadmodel->num_bones * sizeof(float[12])); loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t); 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); @@ -1872,12 +1955,13 @@ void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) 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_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]); + loadmodel->surfmesh.num_blends = 0; + loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short); if (loadmodel->surfmesh.num_vertices <= 65536) loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]); loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]); + loadmodel->surfmesh.data_blendweights = NULL; //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data poses = (float *) (pheader->lump_poses.start + pbase); @@ -1955,8 +2039,7 @@ void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) loadmodel->surfmesh.data_vertex3f[j*3+1] = relativeorigin[0] * m[4] + relativeorigin[1] * m[5] + relativeorigin[2] * m[ 6] + m[ 7]; loadmodel->surfmesh.data_vertex3f[j*3+2] = relativeorigin[0] * m[8] + relativeorigin[1] * m[9] + relativeorigin[2] * m[10] + m[11]; // store the weight as the primary weight on this vertex - loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex; - loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = 1; + loadmodel->surfmesh.blends[j] = boneindex; } Z_Free(bonepose); // normals and tangents are calculated after elements are loaded @@ -2042,6 +2125,15 @@ void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles); loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1; + + if (!loadmodel->surfmesh.isanimated) + { + Mod_MakeCollisionBIH(loadmodel, true); + loadmodel->TraceBox = Mod_CollisionBIH_TraceBox; + loadmodel->TraceLine = Mod_CollisionBIH_TraceLine; + loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh; + loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh; + } } void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) @@ -2154,7 +2246,7 @@ void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) 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]) + (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(short[6]) + 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(unsigned short)) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]) + 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->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int); loadmodel->data_textures = (texture_t *)data;data += loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t); @@ -2167,15 +2259,16 @@ void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) 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_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); + loadmodel->surfmesh.num_blends = 0; + loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short); if (meshvertices <= 65536) loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]); loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]); + loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t)); for (i = 0;i < loadmodel->numskins;i++) { @@ -2304,7 +2397,8 @@ void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) data = (unsigned char *) (pbase + BigLong(dpmmesh->ofs_verts)); for (j = surface->num_firstvertex;j < surface->num_firstvertex + surface->num_vertices;j++) { - float sum; + int weightindex[4] = { 0, 0, 0, 0 }; + float weightinfluence[4] = { 0, 0, 0, 0 }; int l; int numweights = BigLong(((dpmvertex_t *)data)->numbones); data += sizeof(dpmvertex_t); @@ -2331,8 +2425,8 @@ void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) if (!k) { // store the first (and often only) weight - loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+0] = influence; - loadmodel->surfmesh.data_vertexweightindex4i[j*4+0] = boneindex; + weightinfluence[0] = influence; + weightindex[0] = boneindex; } else { @@ -2340,33 +2434,25 @@ void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) // (which only accepts up to 4 bones per vertex) for (l = 0;l < 4;l++) { - if (loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] < influence) + if (weightinfluence[l] < influence) { // move weaker influence weights out of the way first int l2; for (l2 = 3;l2 > l;l2--) { - loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l2-1]; - loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[j*4+l2-1]; + weightinfluence[l2] = weightinfluence[l2-1]; + weightindex[l2] = weightindex[l2-1]; } // store the new weight - loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] = influence; - loadmodel->surfmesh.data_vertexweightindex4i[j*4+l] = boneindex; + weightinfluence[l] = influence; + weightindex[l] = boneindex; break; } } } data += sizeof(dpmbonevert_t); } - sum = 0; - for (l = 0;l < 4;l++) - sum += loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l]; - if (sum && fabs(sum - 1) > (1.0f / 256.0f)) - { - float f = 1.0f / sum; - for (l = 0;l < 4;l++) - loadmodel->surfmesh.data_vertexweightinfluence4f[j*4+l] *= f; - } + loadmodel->surfmesh.blends[j] = Mod_Skeletal_AddBlend(loadmodel, weightindex, weightinfluence); } // since dpm models do not have named sections, reuse their shader name as the section name @@ -2374,6 +2460,8 @@ void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) Mod_ValidateElements(loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3, surface->num_triangles, surface->num_firstvertex, surface->num_vertices, __FILE__, __LINE__); } + if (loadmodel->surfmesh.num_blends < meshvertices) + loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t)); Z_Free(bonepose); Mod_FreeSkinFiles(skinfiles); Mod_MakeSortedSurfaces(loadmodel); @@ -2387,6 +2475,15 @@ void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles); loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1; + + if (!loadmodel->surfmesh.isanimated) + { + Mod_MakeCollisionBIH(loadmodel, true); + loadmodel->TraceBox = Mod_CollisionBIH_TraceBox; + loadmodel->TraceLine = Mod_CollisionBIH_TraceLine; + loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh; + loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh; + } } // no idea why PSK/PSA files contain weird quaternions but they do... @@ -2402,7 +2499,7 @@ void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) pskmatt_t *matts; pskboneinfo_t *bones; pskrawweights_t *rawweights; - pskboneinfo_t *animbones; + //pskboneinfo_t *animbones; pskaniminfo_t *anims; pskanimkeys_t *animkeys; void *animfilebuffer, *animbuffer, *animbufferend; @@ -2654,7 +2751,7 @@ void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) Host_Error("%s: %s has unsupported recordsize", animname, pchunk->id); // byteswap in place and keep the pointer numanimbones = numrecords; - animbones = (pskboneinfo_t *)animbuffer; + //animbones = (pskboneinfo_t *)animbuffer; // NOTE: supposedly psa does not need to match the psk model, the // bones missing from the psa would simply use their base // positions from the psk, but this is hard for me to implement @@ -2785,7 +2882,7 @@ void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) loadmodel->surfmesh.num_vertices = meshvertices; loadmodel->surfmesh.num_triangles = meshtriangles; // do most allocations as one merged chunk - 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(short[6]) + 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); + 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(unsigned short) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]) + 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->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int); @@ -2797,15 +2894,16 @@ void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) 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_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); + loadmodel->surfmesh.num_blends = 0; + loadmodel->surfmesh.blends = (unsigned short *)data;data += meshvertices * sizeof(unsigned short); if (loadmodel->surfmesh.num_vertices <= 65536) loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]); loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]); + loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(blendweights_t)); for (i = 0;i < loadmodel->numskins;i++) { @@ -2866,8 +2964,9 @@ void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) // (which only accept up to 4 bones per vertex) for (index = 0;index < numvtxw;index++) { + int weightindex[4] = { 0, 0, 0, 0 }; + float weightinfluence[4] = { 0, 0, 0, 0 }; int l; - float sum; for (j = 0;j < numrawweights;j++) { if (rawweights[j].pntsindex == vtxw[index].pntsindex) @@ -2876,33 +2975,27 @@ void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) float influence = rawweights[j].weight; for (l = 0;l < 4;l++) { - if (loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] < influence) + if (weightinfluence[l] < influence) { // move lower influence weights out of the way first int l2; for (l2 = 3;l2 > l;l2--) { - loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2] = loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l2-1]; - loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2] = loadmodel->surfmesh.data_vertexweightindex4i[index*4+l2-1]; + weightinfluence[l2] = weightinfluence[l2-1]; + weightindex[l2] = weightindex[l2-1]; } // store the new weight - loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] = influence; - loadmodel->surfmesh.data_vertexweightindex4i[index*4+l] = boneindex; + weightinfluence[l] = influence; + weightindex[l] = boneindex; break; } } } } - sum = 0; - for (l = 0;l < 4;l++) - sum += loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l]; - if (sum && fabs(sum - 1) > (1.0f / 256.0f)) - { - float f = 1.0f / sum; - for (l = 0;l < 4;l++) - loadmodel->surfmesh.data_vertexweightinfluence4f[index*4+l] *= f; - } + loadmodel->surfmesh.blends[index] = Mod_Skeletal_AddBlend(loadmodel, weightindex, weightinfluence); } + if (loadmodel->surfmesh.num_blends < loadmodel->surfmesh.num_vertices) + loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t)); // set up the animscenes based on the anims for (index = 0, i = 0;index < numanims;index++) @@ -2963,4 +3056,13 @@ void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) Mod_Alias_CalculateBoundingBox(); loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1; + + if (!loadmodel->surfmesh.isanimated) + { + Mod_MakeCollisionBIH(loadmodel, true); + loadmodel->TraceBox = Mod_CollisionBIH_TraceBox; + loadmodel->TraceLine = Mod_CollisionBIH_TraceLine; + loadmodel->TracePoint = Mod_CollisionBIH_TracePoint_Mesh; + loadmodel->PointSuperContents = Mod_CollisionBIH_PointSuperContents_Mesh; + } }