X-Git-Url: http://git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=model_alias.c;h=68f19b8db914fadc0cbe76128bb7c1131a2d44f6;hp=4ddcfc975cfbd8c0c1b1f0d939df658d4e8b5d0b;hb=f5e4d031fd609e6a6ab36559e599211aa9ac51c3;hpb=d67118fd26deb0852127704246098681e0ac5399 diff --git a/model_alias.c b/model_alias.c index 4ddcfc97..68f19b8d 100644 --- a/model_alias.c +++ b/model_alias.c @@ -37,6 +37,7 @@ cvar_t r_skeletal_debugtranslatex = {0, "r_skeletal_debugtranslatex", "1", "deve cvar_t r_skeletal_debugtranslatey = {0, "r_skeletal_debugtranslatey", "1", "development cvar for testing skeletal model code"}; cvar_t r_skeletal_debugtranslatez = {0, "r_skeletal_debugtranslatez", "1", "development cvar for testing skeletal model code"}; cvar_t mod_alias_supporttagscale = {0, "mod_alias_supporttagscale", "1", "support scaling factors in bone/tag attachment matrices as supported by MD3"}; +cvar_t mod_alias_force_animated = {0, "mod_alias_force_animated", "", "if set to an non-empty string, overrides the is-animated flag of any alias models (for benchmarking)"}; float mod_md3_sin[320]; @@ -61,7 +62,105 @@ void *Mod_Skeletal_AnimateVertices_AllocBuffers(size_t nbytes) return Mod_Skeletal_AnimateVertices_bonepose; } -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) +void Mod_Skeletal_BuildTransforms(const dp_model_t * RESTRICT model, const frameblend_t * RESTRICT frameblend, const skeleton_t *skeleton, float * RESTRICT bonepose, float * RESTRICT boneposerelative) +{ + int i, blends; + float m[12]; + + if (!bonepose) + bonepose = (float * RESTRICT) Mod_Skeletal_AnimateVertices_AllocBuffers(sizeof(float[12]) * model->num_bones); + + if (skeleton && !skeleton->relativetransforms) + skeleton = NULL; + + // interpolate matrices + if (skeleton) + { + for (i = 0;i < model->num_bones;i++) + { + Matrix4x4_ToArray12FloatD3D(&skeleton->relativetransforms[i], m); + if (model->data_bones[i].parent >= 0) + R_ConcatTransforms(bonepose + model->data_bones[i].parent * 12, m, bonepose + i * 12); + else + memcpy(bonepose + i * 12, 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 * 12, model->data_baseboneposeinverse + i * 12, boneposerelative + i * 12); + } + } + else + { + for (i = 0;i < model->num_bones;i++) + { + // blend by transform each quaternion/translation into a dual-quaternion first, then blending + const short * RESTRICT firstpose7s = model->data_poses7s + 7 * (frameblend[0].subframe * model->num_bones + i); + float firstlerp = frameblend[0].lerp, + firsttx = firstpose7s[0], firstty = firstpose7s[1], firsttz = firstpose7s[2], + rx = firstpose7s[3] * firstlerp, + ry = firstpose7s[4] * firstlerp, + rz = firstpose7s[5] * firstlerp, + rw = firstpose7s[6] * firstlerp, + dx = firsttx*rw + firstty*rz - firsttz*ry, + dy = -firsttx*rz + firstty*rw + firsttz*rx, + dz = firsttx*ry - firstty*rx + firsttz*rw, + dw = -firsttx*rx - firstty*ry - firsttz*rz, + scale, sx, sy, sz, sw; + for (blends = 1;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++) + { + const short * RESTRICT blendpose7s = model->data_poses7s + 7 * (frameblend[blends].subframe * model->num_bones + i); + float blendlerp = frameblend[blends].lerp, + blendtx = blendpose7s[0], blendty = blendpose7s[1], blendtz = blendpose7s[2], + qx = blendpose7s[3], qy = blendpose7s[4], qz = blendpose7s[5], qw = blendpose7s[6]; + if(rx*qx + ry*qy + rz*qz + rw*qw < 0) blendlerp = -blendlerp; + qx *= blendlerp; + qy *= blendlerp; + qz *= blendlerp; + qw *= blendlerp; + rx += qx; + ry += qy; + rz += qz; + rw += qw; + dx += blendtx*qw + blendty*qz - blendtz*qy; + dy += -blendtx*qz + blendty*qw + blendtz*qx; + dz += blendtx*qy - blendty*qx + blendtz*qw; + dw += -blendtx*qx - blendty*qy - blendtz*qz; + } + // generate a matrix from the dual-quaternion, implicitly normalizing it in the process + scale = 1.0f / (rx*rx + ry*ry + rz*rz + rw*rw); + sx = rx * scale; + sy = ry * scale; + sz = rz * scale; + sw = rw * scale; + m[0] = sw*rw + sx*rx - sy*ry - sz*rz; + m[1] = 2*(sx*ry - sw*rz); + m[2] = 2*(sx*rz + sw*ry); + m[3] = model->num_posescale*(dx*sw - dy*sz + dz*sy - dw*sx); + m[4] = 2*(sx*ry + sw*rz); + m[5] = sw*rw + sy*ry - sx*rx - sz*rz; + m[6] = 2*(sy*rz - sw*rx); + m[7] = model->num_posescale*(dx*sz + dy*sw - dz*sx - dw*sy); + m[8] = 2*(sx*rz - sw*ry); + m[9] = 2*(sy*rz + sw*rx); + m[10] = sw*rw + sz*rz - sx*rx - sy*ry; + m[11] = model->num_posescale*(dy*sx + dz*sw - dx*sy - dw*sz); + 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 * 12, m, bonepose + i * 12); + else + memcpy(bonepose + i * 12, 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 * 12, model->data_baseboneposeinverse + i * 12, boneposerelative + i * 12); + } + } +} + +static 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) { if (!model->surfmesh.num_vertices) @@ -97,6 +196,7 @@ void Mod_AliasInit (void) Cvar_RegisterVariable(&r_skeletal_debugtranslatey); Cvar_RegisterVariable(&r_skeletal_debugtranslatez); Cvar_RegisterVariable(&mod_alias_supporttagscale); + Cvar_RegisterVariable(&mod_alias_force_animated); for (i = 0;i < 320;i++) mod_md3_sin[i] = sin(i * M_PI * 2.0f / 256.0); #ifdef SSE_POSSIBLE @@ -113,7 +213,7 @@ void Mod_AliasInit (void) #endif } -int Mod_Skeletal_AddBlend(dp_model_t *model, const blendweights_t *newweights) +static int Mod_Skeletal_AddBlend(dp_model_t *model, const blendweights_t *newweights) { int i; blendweights_t *weights; @@ -130,7 +230,7 @@ int Mod_Skeletal_AddBlend(dp_model_t *model, const blendweights_t *newweights) return model->num_bones + i; } -int Mod_Skeletal_CompressBlend(dp_model_t *model, const int *newindex, const float *newinfluence) +static int Mod_Skeletal_CompressBlend(dp_model_t *model, const int *newindex, const float *newinfluence) { int i, total; float scale; @@ -173,7 +273,7 @@ int Mod_Skeletal_CompressBlend(dp_model_t *model, const int *newindex, const flo return Mod_Skeletal_AddBlend(model, &newweights); } -void Mod_MD3_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) +static void Mod_MD3_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) { // vertex morph int i, numblends, blendnum; @@ -261,7 +361,7 @@ void Mod_MD3_AnimateVertices(const dp_model_t * RESTRICT model, const frameblend } } } -void Mod_MDL_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) +static void Mod_MDL_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) { // vertex morph int i, numblends, blendnum; @@ -391,11 +491,11 @@ int Mod_Alias_GetTagMatrix(const dp_model_t *model, const frameblend_t *frameble for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++) { lerp = frameblend[blendindex].lerp; - Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex)); + Matrix4x4_FromBonePose7s(&bonematrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + tagindex)); parenttagindex = tagindex; while ((parenttagindex = model->data_bones[parenttagindex].parent) >= 0) { - Matrix4x4_FromBonePose6s(&parentbonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + parenttagindex)); + Matrix4x4_FromBonePose7s(&parentbonematrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + parenttagindex)); tempbonematrix = bonematrix; Matrix4x4_Concat(&bonematrix, &parentbonematrix, &tempbonematrix); } @@ -454,7 +554,7 @@ int Mod_Alias_GetExtendedTagInfoForIndex(const dp_model_t *model, unsigned int s for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++) { lerp = frameblend[blendindex].lerp; - Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex)); + Matrix4x4_FromBonePose7s(&bonematrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + tagindex)); Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp); } *tag_localmatrix = blendmatrix; @@ -510,7 +610,7 @@ static void Mod_BuildBaseBonePoses(void) basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t)); for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++) { - Matrix4x4_FromBonePose6s(&bonematrix, loadmodel->num_posescale, loadmodel->data_poses6s + 6 * boneindex); + Matrix4x4_FromBonePose7s(&bonematrix, loadmodel->num_posescale, loadmodel->data_poses7s + 7 * boneindex); if (loadmodel->data_bones[boneindex].parent >= 0) { tempbonematrix = bonematrix; @@ -523,25 +623,70 @@ static void Mod_BuildBaseBonePoses(void) Mem_Free(basebonepose); } -static void Mod_Alias_CalculateBoundingBox(void) +static qboolean Mod_Alias_CalculateBoundingBox(void) { int vnum; qboolean firstvertex = true; float dist, yawradius, radius; float *v; - float *vertex3f; - frameblend_t frameblend[MAX_FRAMEBLENDS]; - memset(frameblend, 0, sizeof(frameblend)); - frameblend[0].lerp = 1; - vertex3f = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3])); + qboolean isanimated = false; VectorClear(loadmodel->normalmins); VectorClear(loadmodel->normalmaxs); yawradius = 0; radius = 0; - for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++) + if (loadmodel->AnimateVertices) + { + float *vertex3f, *refvertex3f; + frameblend_t frameblend[MAX_FRAMEBLENDS]; + memset(frameblend, 0, sizeof(frameblend)); + frameblend[0].lerp = 1; + vertex3f = (float *) Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[3]) * 2); + refvertex3f = NULL; + for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++) + { + loadmodel->AnimateVertices(loadmodel, frameblend, NULL, vertex3f, NULL, NULL, NULL); + if (!refvertex3f) + { + // make a copy of the first frame for comparing all others + refvertex3f = vertex3f + loadmodel->surfmesh.num_vertices * 3; + memcpy(refvertex3f, vertex3f, loadmodel->surfmesh.num_vertices * sizeof(float[3])); + } + else + { + if (!isanimated && memcmp(refvertex3f, vertex3f, loadmodel->surfmesh.num_vertices * sizeof(float[3]))) + isanimated = true; + } + for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3) + { + 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; + } + } + if (vertex3f) + Mem_Free(vertex3f); + } + else { - loadmodel->AnimateVertices(loadmodel, frameblend, NULL, vertex3f, NULL, NULL, NULL); - for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3) + for (vnum = 0, v = loadmodel->surfmesh.data_vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3) { if (firstvertex) { @@ -566,8 +711,6 @@ static void Mod_Alias_CalculateBoundingBox(void) radius = dist; } } - if (vertex3f) - Mem_Free(vertex3f); radius = sqrt(radius); yawradius = sqrt(yawradius); loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius; @@ -578,6 +721,7 @@ static void Mod_Alias_CalculateBoundingBox(void) loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius; loadmodel->radius = radius; loadmodel->radius2 = radius * radius; + return isanimated; } static void Mod_Alias_MorphMesh_CompileFrames(void) @@ -613,19 +757,13 @@ static void Mod_MDLMD2MD3_TraceLine(dp_model_t *model, const frameblend_t *frame int i; float segmentmins[3], segmentmaxs[3]; msurface_t *surface; - static int maxvertices = 0; - static float *vertex3f = NULL; + float vertex3fbuf[1024*3]; + float *vertex3f = vertex3fbuf; memset(trace, 0, sizeof(*trace)); trace->fraction = 1; - trace->realfraction = 1; trace->hitsupercontentsmask = hitsupercontentsmask; - if (maxvertices < model->surfmesh.num_vertices) - { - if (vertex3f) - Z_Free(vertex3f); - maxvertices = (model->surfmesh.num_vertices + 255) & ~255; - vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3])); - } + if (model->surfmesh.num_vertices > 1024) + vertex3f = (float *)Mem_Alloc(tempmempool, model->surfmesh.num_vertices * sizeof(float[3])); segmentmins[0] = min(start[0], end[0]) - 1; segmentmins[1] = min(start[1], end[1]) - 1; segmentmins[2] = min(start[2], end[2]) - 1; @@ -635,17 +773,18 @@ static void Mod_MDLMD2MD3_TraceLine(dp_model_t *model, const frameblend_t *frame model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL); for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++) Collision_TraceLineTriangleMeshFloat(trace, start, end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs); + if (vertex3f != vertex3fbuf) + Mem_Free(vertex3f); } -static int maxvertices = 0; -static float *vertex3f = NULL; - static void Mod_MDLMD2MD3_TraceBox(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask) { int i; vec3_t shiftstart, shiftend; float segmentmins[3], segmentmaxs[3]; msurface_t *surface; + float vertex3fbuf[1024*3]; + float *vertex3f = vertex3fbuf; colboxbrushf_t thisbrush_start, thisbrush_end; vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs; @@ -661,15 +800,9 @@ static void Mod_MDLMD2MD3_TraceBox(dp_model_t *model, const frameblend_t *frameb // box trace, performed as brush trace memset(trace, 0, sizeof(*trace)); trace->fraction = 1; - trace->realfraction = 1; trace->hitsupercontentsmask = hitsupercontentsmask; - if (maxvertices < model->surfmesh.num_vertices) - { - if (vertex3f) - Z_Free(vertex3f); - maxvertices = (model->surfmesh.num_vertices + 255) & ~255; - vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3])); - } + if (model->surfmesh.num_vertices > 1024) + vertex3f = (float *)Mem_Alloc(tempmempool, model->surfmesh.num_vertices * sizeof(float[3])); segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1; segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1; segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1; @@ -682,16 +815,11 @@ static void Mod_MDLMD2MD3_TraceBox(dp_model_t *model, const frameblend_t *frameb VectorAdd(end, boxmaxs, boxendmaxs); Collision_BrushForBox(&thisbrush_start, boxstartmins, boxstartmaxs, 0, 0, NULL); Collision_BrushForBox(&thisbrush_end, boxendmins, boxendmaxs, 0, 0, NULL); - if (maxvertices < model->surfmesh.num_vertices) - { - if (vertex3f) - Z_Free(vertex3f); - maxvertices = (model->surfmesh.num_vertices + 255) & ~255; - vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3])); - } model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL); for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++) Collision_TraceBrushTriangleMeshFloat(trace, &thisbrush_start.brush, &thisbrush_end.brush, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs); + if (vertex3f != vertex3fbuf) + Mem_Free(vertex3f); } static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap) @@ -763,7 +891,6 @@ static void Mod_MDL_LoadFrames (unsigned char* datapointer, int inverts, int *ve // read frames for (i = 0;i < groupframes;i++) { - pinframe = (daliasframe_t *)datapointer; datapointer += sizeof(daliasframe_t); Mod_ConvertAliasVerts(inverts, (trivertx_t *)datapointer, loadmodel->surfmesh.data_morphmdlvertex + pose * loadmodel->surfmesh.num_vertices, vertremap); datapointer += sizeof(trivertx_t) * inverts; @@ -782,9 +909,7 @@ static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *ski memset(texture, 0, sizeof(*texture)); texture->currentframe = texture; //texture->animated = false; - texture->numskinframes = 1; - texture->skinframerate = 1; - texture->skinframes[0] = skinframe; + texture->materialshaderpass = texture->shaderpasses[0] = Mod_CreateShaderPass(skinframe); texture->currentskinframe = skinframe; //texture->backgroundnumskinframes = 0; //texture->customblendfunc[0] = 0; @@ -795,6 +920,7 @@ static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *ski //texture->textureflags = 0; texture->basematerialflags = MATERIALFLAG_WALL; + texture->basealpha = 1.0f; if (texture->currentskinframe->hasalpha) texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; texture->currentmaterialflags = texture->basematerialflags; @@ -807,12 +933,15 @@ static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *ski texture->supercontents = SUPERCONTENTS_SOLID; if (!(texture->basematerialflags & MATERIALFLAG_BLENDED)) texture->supercontents |= SUPERCONTENTS_OPAQUE; + texture->transparentsort = TRANSPARENTSORT_DISTANCE; + // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS + // JUST GREP FOR "specularscalemod = 1". } void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername) { int i; - static char stripbuf[MAX_QPATH]; + char stripbuf[MAX_QPATH]; skinfileitem_t *skinfileitem; if(developer_extra.integer) Con_DPrintf("Looking up texture for %s (default: %s)\n", meshname, shadername); @@ -878,6 +1007,7 @@ void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend) float *vertst; int *vertonseam, *vertremap; skinfile_t *skinfiles; + char vabuf[1024]; datapointer = (unsigned char *)buffer; pinmodel = (mdl_t *)datapointer; @@ -891,7 +1021,6 @@ void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend) loadmodel->modeldatatypestring = "MDL"; loadmodel->type = mod_alias; - loadmodel->AnimateVertices = Mod_MDL_AnimateVertices; loadmodel->DrawSky = NULL; loadmodel->DrawAddWaterPlanes = NULL; loadmodel->Draw = R_Q1BSP_Draw; @@ -907,6 +1036,7 @@ void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend) loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine; // FIXME add TraceBrush! loadmodel->PointSuperContents = NULL; + loadmodel->AnimateVertices = Mod_MDL_AnimateVertices; loadmodel->num_surfaces = 1; loadmodel->nummodelsurfaces = loadmodel->num_surfaces; @@ -1004,8 +1134,8 @@ void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend) for (i = 0;i < numverts;i++) { vertonseam[i] = LittleLong(pinstverts[i].onseam); - vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales; - vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet; + vertst[i*2+0] = LittleLong(pinstverts[i].s) * scales; + vertst[i*2+1] = LittleLong(pinstverts[i].t) * scalet; vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5; vertst[(i+numverts)*2+1] = vertst[i*2+1]; } @@ -1074,7 +1204,7 @@ void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend) Mod_MDL_LoadFrames (startframes, numverts, vertremap); if (loadmodel->surfmesh.data_neighbor3i) Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles); - Mod_Alias_CalculateBoundingBox(); + loadmodel->surfmesh.isanimated = Mod_Alias_CalculateBoundingBox(); Mod_Alias_MorphMesh_CompileFrames(); Mem_Free(vertst); @@ -1155,7 +1285,7 @@ void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend) // 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) // 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))) + while ((tempskinframe = R_SkinFrame_LoadExternal(va(vabuf, sizeof(vabuf), "%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; @@ -1194,7 +1324,8 @@ void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend) surface->num_firstvertex = 0; surface->num_vertices = loadmodel->surfmesh.num_vertices; - loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1; + if(mod_alias_force_animated.string[0]) + loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0; if (!loadmodel->surfmesh.isanimated) { @@ -1248,7 +1379,6 @@ void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend) loadmodel->modeldatatypestring = "MD2"; loadmodel->type = mod_alias; - loadmodel->AnimateVertices = Mod_MDL_AnimateVertices; loadmodel->DrawSky = NULL; loadmodel->DrawAddWaterPlanes = NULL; loadmodel->Draw = R_Q1BSP_Draw; @@ -1263,6 +1393,7 @@ void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend) loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox; loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine; loadmodel->PointSuperContents = NULL; + loadmodel->AnimateVertices = Mod_MDL_AnimateVertices; 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)); @@ -1455,8 +1586,10 @@ void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend) if (loadmodel->surfmesh.data_neighbor3i) Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles); - Mod_Alias_CalculateBoundingBox(); + loadmodel->surfmesh.isanimated = Mod_Alias_CalculateBoundingBox(); Mod_Alias_MorphMesh_CompileFrames(); + if(mod_alias_force_animated.string[0]) + loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0; surface = loadmodel->data_surfaces; surface->texture = loadmodel->data_textures; @@ -1465,8 +1598,6 @@ void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend) surface->num_firstvertex = 0; 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->collision_bih); @@ -1514,7 +1645,6 @@ void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend) loadmodel->modeldatatypestring = "MD3"; loadmodel->type = mod_alias; - loadmodel->AnimateVertices = Mod_MD3_AnimateVertices; loadmodel->DrawSky = NULL; loadmodel->DrawAddWaterPlanes = NULL; loadmodel->Draw = R_Q1BSP_Draw; @@ -1529,6 +1659,7 @@ void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend) loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox; loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine; loadmodel->PointSuperContents = NULL; + loadmodel->AnimateVertices = Mod_MD3_AnimateVertices; loadmodel->synctype = ST_RAND; // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc) i = LittleLong (pinmodel->flags); @@ -1656,12 +1787,11 @@ void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend) if (loadmodel->surfmesh.data_neighbor3i) Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles); Mod_Alias_MorphMesh_CompileFrames(); - Mod_Alias_CalculateBoundingBox(); + loadmodel->surfmesh.isanimated = Mod_Alias_CalculateBoundingBox(); Mod_FreeSkinFiles(skinfiles); Mod_MakeSortedSurfaces(loadmodel); - - loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 - || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1); + if(mod_alias_force_animated.string[0]) + loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0; if (!loadmodel->surfmesh.isanimated) { @@ -1755,7 +1885,6 @@ void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) return; } - loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices; loadmodel->DrawSky = NULL; loadmodel->DrawAddWaterPlanes = NULL; loadmodel->Draw = R_Q1BSP_Draw; @@ -1770,6 +1899,7 @@ void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox; loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine; loadmodel->PointSuperContents = NULL; + loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices; loadmodel->numframes = pheader->numscenes; loadmodel->num_surfaces = pheader->numshaders; @@ -1789,6 +1919,7 @@ void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) } // model bbox + // LordHavoc: actually we blow this away later with Mod_Alias_CalculateBoundingBox() modelradius = pheader->radius; for (i = 0;i < 3;i++) { @@ -1861,7 +1992,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]) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[3]) : 0) + (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])); + 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]) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[3]) : 0) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshvertices * (sizeof(float[14]) + sizeof(unsigned short) + sizeof(unsigned char[2][4])) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]) + 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); @@ -1877,6 +2008,8 @@ 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_skeletalindex4ub = (unsigned char *)data;data += meshvertices * sizeof(unsigned char[4]); + loadmodel->surfmesh.data_skeletalweight4ub = (unsigned char *)data;data += meshvertices * sizeof(unsigned char[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); @@ -1884,7 +2017,7 @@ void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) { 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->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]); loadmodel->surfmesh.data_blendweights = NULL; //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data @@ -1925,7 +2058,7 @@ void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) VectorNormalize(pose + 4); VectorNormalize(pose + 8); Matrix4x4_FromArray12FloatD3D(&posematrix, pose); - Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j)); + Matrix4x4_ToBonePose7s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses7s + 7*(i*loadmodel->num_bones+j)); } } @@ -1964,6 +2097,14 @@ void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) 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.blends[j] = boneindex; + loadmodel->surfmesh.data_skeletalindex4ub[j*4 ] = boneindex; + loadmodel->surfmesh.data_skeletalindex4ub[j*4+1] = 0; + loadmodel->surfmesh.data_skeletalindex4ub[j*4+2] = 0; + loadmodel->surfmesh.data_skeletalindex4ub[j*4+3] = 0; + loadmodel->surfmesh.data_skeletalweight4ub[j*4 ] = 255; + loadmodel->surfmesh.data_skeletalweight4ub[j*4+1] = 0; + loadmodel->surfmesh.data_skeletalweight4ub[j*4+2] = 0; + loadmodel->surfmesh.data_skeletalweight4ub[j*4+3] = 0; } Z_Free(bonepose); // normals and tangents are calculated after elements are loaded @@ -2048,8 +2189,9 @@ void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, r_smoothnormals_areaweighting.integer != 0); if (loadmodel->surfmesh.data_neighbor3i) 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; + loadmodel->surfmesh.isanimated = Mod_Alias_CalculateBoundingBox(); + if(mod_alias_force_animated.string[0]) + loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0; if (!loadmodel->surfmesh.isanimated) { @@ -2127,7 +2269,6 @@ void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) return; } - loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices; loadmodel->DrawSky = NULL; loadmodel->DrawAddWaterPlanes = NULL; loadmodel->Draw = R_Q1BSP_Draw; @@ -2142,8 +2283,10 @@ void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox; loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine; loadmodel->PointSuperContents = NULL; + loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices; // model bbox + // LordHavoc: actually we blow this away later with Mod_Alias_CalculateBoundingBox() for (i = 0;i < 3;i++) { loadmodel->normalmins[i] = pheader->mins[i]; @@ -2181,7 +2324,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) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[3]) : 0) + 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)); + 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) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[3]) : 0) + meshvertices * (sizeof(float[14]) + sizeof(unsigned short) + sizeof(unsigned char[2][4])) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]) + 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); @@ -2197,6 +2340,8 @@ 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_skeletalindex4ub = (unsigned char *)data;data += meshvertices * sizeof(unsigned char[4]); + loadmodel->surfmesh.data_skeletalweight4ub = (unsigned char *)data;data += meshvertices * sizeof(unsigned char[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); @@ -2207,7 +2352,7 @@ void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) { 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->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]); loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t)); for (i = 0;i < loadmodel->numskins;i++) @@ -2277,7 +2422,7 @@ void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) VectorNormalize(pose + 4); VectorNormalize(pose + 8); Matrix4x4_FromArray12FloatD3D(&posematrix, pose); - Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j)); + Matrix4x4_ToBonePose7s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses7s + 7*(i*loadmodel->num_bones+j)); } } @@ -2393,6 +2538,14 @@ void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) data += sizeof(dpmbonevert_t); } loadmodel->surfmesh.blends[j] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence); + loadmodel->surfmesh.data_skeletalindex4ub[j*4 ] = weightindex[0]; + loadmodel->surfmesh.data_skeletalindex4ub[j*4+1] = weightindex[1]; + loadmodel->surfmesh.data_skeletalindex4ub[j*4+2] = weightindex[2]; + loadmodel->surfmesh.data_skeletalindex4ub[j*4+3] = weightindex[3]; + loadmodel->surfmesh.data_skeletalweight4ub[j*4 ] = (unsigned char)(weightinfluence[0]*255.0f); + loadmodel->surfmesh.data_skeletalweight4ub[j*4+1] = (unsigned char)(weightinfluence[1]*255.0f); + loadmodel->surfmesh.data_skeletalweight4ub[j*4+2] = (unsigned char)(weightinfluence[2]*255.0f); + loadmodel->surfmesh.data_skeletalweight4ub[j*4+3] = (unsigned char)(weightinfluence[3]*255.0f); } // since dpm models do not have named sections, reuse their shader name as the section name @@ -2414,8 +2567,9 @@ void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, r_smoothnormals_areaweighting.integer != 0); if (loadmodel->surfmesh.data_neighbor3i) 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; + loadmodel->surfmesh.isanimated = Mod_Alias_CalculateBoundingBox(); + if(mod_alias_force_animated.string[0]) + loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0; if (!loadmodel->surfmesh.isanimated) { @@ -2468,7 +2622,6 @@ void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) loadmodel->modeldatatypestring = "PSK"; loadmodel->type = mod_alias; - loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices; loadmodel->DrawSky = NULL; loadmodel->DrawAddWaterPlanes = NULL; loadmodel->Draw = R_Q1BSP_Draw; @@ -2483,14 +2636,15 @@ void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox; loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine; loadmodel->PointSuperContents = NULL; + loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices; loadmodel->synctype = ST_RAND; FS_StripExtension(loadmodel->name, animname, sizeof(animname)); strlcat(animname, ".psa", sizeof(animname)); animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize); animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize); - if (animbuffer == NULL) - Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname); + if (!animbuffer) + animbufferend = animbuffer; numpnts = 0; pnts = NULL; @@ -2808,15 +2962,19 @@ void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id); } - if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys) + if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights) Host_Error("%s: missing required chunks", loadmodel->name); - loadmodel->numframes = 0; - for (index = 0;index < numanims;index++) - loadmodel->numframes += anims[index].numframes; - - if (numanimkeys != numbones * loadmodel->numframes) - Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id); + if (numanims) + { + loadmodel->numframes = 0; + for (index = 0;index < numanims;index++) + loadmodel->numframes += anims[index].numframes; + if (numanimkeys != numbones * loadmodel->numframes) + Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id); + } + else + loadmodel->numframes = loadmodel->num_poses = 1; meshvertices = numvtxw; meshtriangles = numfaces; @@ -2833,7 +2991,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]) + (r_enableshadowvolumes.integer ? loadmodel->surfmesh.num_triangles * sizeof(int[3]) : 0) + 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); + 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]) + (r_enableshadowvolumes.integer ? loadmodel->surfmesh.num_triangles * sizeof(int[3]) : 0) + 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 char[4]) + loadmodel->surfmesh.num_vertices * sizeof(unsigned char[4]) + loadmodel->surfmesh.num_vertices * sizeof(unsigned short) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]) + 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); @@ -2848,6 +3006,8 @@ 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_skeletalindex4ub = (unsigned char *)data;data += loadmodel->surfmesh.num_vertices * sizeof(unsigned char[4]); + loadmodel->surfmesh.data_skeletalweight4ub = (unsigned char *)data;data += loadmodel->surfmesh.num_vertices * sizeof(unsigned char[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); @@ -2858,7 +3018,7 @@ void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) { 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->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]); loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(blendweights_t)); for (i = 0;i < loadmodel->numskins;i++) @@ -2916,6 +3076,30 @@ void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index); } + // convert the basepose data + if (loadmodel->num_bones) + { + int boneindex; + matrix4x4_t *basebonepose; + float *outinvmatrix = loadmodel->data_baseboneposeinverse; + matrix4x4_t bonematrix; + matrix4x4_t tempbonematrix; + basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t)); + for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++) + { + Matrix4x4_FromOriginQuat(&bonematrix, bones[boneindex].basepose.origin[0], bones[boneindex].basepose.origin[1], bones[boneindex].basepose.origin[2], bones[boneindex].basepose.quat[0], bones[boneindex].basepose.quat[1], bones[boneindex].basepose.quat[2], bones[boneindex].basepose.quat[3]); + if (loadmodel->data_bones[boneindex].parent >= 0) + { + tempbonematrix = bonematrix; + Matrix4x4_Concat(&bonematrix, basebonepose + loadmodel->data_bones[boneindex].parent, &tempbonematrix); + } + basebonepose[boneindex] = bonematrix; + Matrix4x4_Invert_Simple(&tempbonematrix, basebonepose + boneindex); + Matrix4x4_ToArray12FloatD3D(&tempbonematrix, outinvmatrix + 12*boneindex); + } + Mem_Free(basebonepose); + } + // sort the psk point weights into the vertex weight tables // (which only accept up to 4 bones per vertex) for (index = 0;index < numvtxw;index++) @@ -2949,54 +3133,106 @@ void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) } } loadmodel->surfmesh.blends[index] = Mod_Skeletal_CompressBlend(loadmodel, weightindex, weightinfluence); + loadmodel->surfmesh.data_skeletalindex4ub[index*4 ] = weightindex[0]; + loadmodel->surfmesh.data_skeletalindex4ub[index*4+1] = weightindex[1]; + loadmodel->surfmesh.data_skeletalindex4ub[index*4+2] = weightindex[2]; + loadmodel->surfmesh.data_skeletalindex4ub[index*4+3] = weightindex[3]; + loadmodel->surfmesh.data_skeletalweight4ub[index*4 ] = (unsigned char)(weightinfluence[0]*255.0f); + loadmodel->surfmesh.data_skeletalweight4ub[index*4+1] = (unsigned char)(weightinfluence[1]*255.0f); + loadmodel->surfmesh.data_skeletalweight4ub[index*4+2] = (unsigned char)(weightinfluence[2]*255.0f); + loadmodel->surfmesh.data_skeletalweight4ub[index*4+3] = (unsigned char)(weightinfluence[3]*255.0f); } 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++) + if (numanims) { - for (j = 0;j < anims[index].numframes;j++, i++) + for (index = 0, i = 0;index < numanims;index++) { - dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j); - loadmodel->animscenes[i].firstframe = i; - loadmodel->animscenes[i].framecount = 1; - loadmodel->animscenes[i].loop = true; - loadmodel->animscenes[i].framerate = anims[index].fps; + for (j = 0;j < anims[index].numframes;j++, i++) + { + dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j); + loadmodel->animscenes[i].firstframe = i; + loadmodel->animscenes[i].framecount = 1; + loadmodel->animscenes[i].loop = true; + loadmodel->animscenes[i].framerate = anims[index].fps; + } + } + // calculate the scaling value for bone origins so they can be compressed to short + biggestorigin = 0; + for (index = 0;index < numanimkeys;index++) + { + pskanimkeys_t *k = animkeys + index; + biggestorigin = max(biggestorigin, fabs(k->origin[0])); + biggestorigin = max(biggestorigin, fabs(k->origin[1])); + biggestorigin = max(biggestorigin, fabs(k->origin[2])); + } + loadmodel->num_posescale = biggestorigin / 32767.0f; + loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale; + + // load the poses from the animkeys + for (index = 0;index < numanimkeys;index++) + { + pskanimkeys_t *k = animkeys + index; + float quat[4]; + Vector4Copy(k->quat, quat); + if (quat[3] > 0) + Vector4Negate(quat, quat); + Vector4Normalize2(quat, quat); + // compress poses to the short[7] format for longterm storage + loadmodel->data_poses7s[index*7+0] = k->origin[0] * loadmodel->num_poseinvscale; + loadmodel->data_poses7s[index*7+1] = k->origin[1] * loadmodel->num_poseinvscale; + loadmodel->data_poses7s[index*7+2] = k->origin[2] * loadmodel->num_poseinvscale; + loadmodel->data_poses7s[index*7+3] = quat[0] * 32767.0f; + loadmodel->data_poses7s[index*7+4] = quat[1] * 32767.0f; + loadmodel->data_poses7s[index*7+5] = quat[2] * 32767.0f; + loadmodel->data_poses7s[index*7+6] = quat[3] * 32767.0f; } } - - // calculate the scaling value for bone origins so they can be compressed to short - biggestorigin = 0; - for (index = 0;index < numanimkeys;index++) + else { - pskanimkeys_t *k = animkeys + index; - biggestorigin = max(biggestorigin, fabs(k->origin[0])); - biggestorigin = max(biggestorigin, fabs(k->origin[1])); - biggestorigin = max(biggestorigin, fabs(k->origin[2])); - } - loadmodel->num_posescale = biggestorigin / 32767.0f; - loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale; + strlcpy(loadmodel->animscenes[0].name, "base", sizeof(loadmodel->animscenes[0].name)); + loadmodel->animscenes[0].firstframe = 0; + loadmodel->animscenes[0].framecount = 1; + loadmodel->animscenes[0].loop = true; + loadmodel->animscenes[0].framerate = 10; - // load the poses from the animkeys - for (index = 0;index < numanimkeys;index++) - { - pskanimkeys_t *k = animkeys + index; - float quat[4]; - Vector4Copy(k->quat, quat); - if (quat[3] > 0) - Vector4Negate(quat, quat); - Vector4Normalize2(quat, quat); - // compress poses to the short[6] format for longterm storage - loadmodel->data_poses6s[index*6+0] = k->origin[0] * loadmodel->num_poseinvscale; - loadmodel->data_poses6s[index*6+1] = k->origin[1] * loadmodel->num_poseinvscale; - loadmodel->data_poses6s[index*6+2] = k->origin[2] * loadmodel->num_poseinvscale; - loadmodel->data_poses6s[index*6+3] = quat[0] * 32767.0f; - loadmodel->data_poses6s[index*6+4] = quat[1] * 32767.0f; - loadmodel->data_poses6s[index*6+5] = quat[2] * 32767.0f; + // calculate the scaling value for bone origins so they can be compressed to short + biggestorigin = 0; + for (index = 0;index < numbones;index++) + { + pskboneinfo_t *p = bones + index; + biggestorigin = max(biggestorigin, fabs(p->basepose.origin[0])); + biggestorigin = max(biggestorigin, fabs(p->basepose.origin[1])); + biggestorigin = max(biggestorigin, fabs(p->basepose.origin[2])); + } + loadmodel->num_posescale = biggestorigin / 32767.0f; + loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale; + + // load the basepose as a frame + for (index = 0;index < numbones;index++) + { + pskboneinfo_t *p = bones + index; + float quat[4]; + Vector4Copy(p->basepose.quat, quat); + if (quat[3] > 0) + Vector4Negate(quat, quat); + Vector4Normalize2(quat, quat); + // compress poses to the short[7] format for longterm storage + loadmodel->data_poses7s[index*7+0] = p->basepose.origin[0] * loadmodel->num_poseinvscale; + loadmodel->data_poses7s[index*7+1] = p->basepose.origin[1] * loadmodel->num_poseinvscale; + loadmodel->data_poses7s[index*7+2] = p->basepose.origin[2] * loadmodel->num_poseinvscale; + loadmodel->data_poses7s[index*7+3] = quat[0] * 32767.0f; + loadmodel->data_poses7s[index*7+4] = quat[1] * 32767.0f; + loadmodel->data_poses7s[index*7+5] = quat[2] * 32767.0f; + loadmodel->data_poses7s[index*7+6] = quat[3] * 32767.0f; + } } + Mod_FreeSkinFiles(skinfiles); - Mem_Free(animfilebuffer); + if (animfilebuffer) + Mem_Free(animfilebuffer); Mod_MakeSortedSurfaces(loadmodel); // compute all the mesh information that was not loaded from the file @@ -3005,14 +3241,13 @@ void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++) loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i]; Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__); - Mod_BuildBaseBonePoses(); Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, r_smoothnormals_areaweighting.integer != 0); Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, r_smoothnormals_areaweighting.integer != 0); if (loadmodel->surfmesh.data_neighbor3i) Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles); - Mod_Alias_CalculateBoundingBox(); - - loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1; + loadmodel->surfmesh.isanimated = Mod_Alias_CalculateBoundingBox(); + if(mod_alias_force_animated.string[0]) + loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0; if (!loadmodel->surfmesh.isanimated) { @@ -3047,14 +3282,16 @@ void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) int *outelements; const int *inneighbors; int *outneighbors; - float *outvertex, *outnormal, *outtexcoord, *outsvector, *outtvector; + float *outvertex, *outnormal, *outtexcoord, *outsvector, *outtvector, *outcolor; // this pointers into the file data are read only through Little* functions so they can be unaligned memory const float *vnormal = NULL; const float *vposition = NULL; const float *vtangent = NULL; const float *vtexcoord = NULL; + const float *vcolor4f = NULL; const unsigned char *vblendindexes = NULL; const unsigned char *vblendweights = NULL; + const unsigned char *vcolor4ub = NULL; const unsigned short *framedata = NULL; // temporary memory allocations (because the data in the file may be misaligned) iqmanim_t *anims = NULL; @@ -3115,12 +3352,6 @@ void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) header.num_extensions = LittleLong(header.num_extensions); header.ofs_extensions = LittleLong(header.ofs_extensions); - if (header.num_triangles < 1 || header.num_vertexes < 3 || header.num_vertexarrays < 1 || header.num_meshes < 1) - { - Con_Printf("%s has no geometry\n", loadmodel->name); - return; - } - if (header.version == 1) { if (pbase + header.ofs_joints + header.num_joints*sizeof(iqmjoint1_t) > pend || @@ -3208,6 +3439,12 @@ void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) if (va.format == IQM_UBYTE && va.size == 4) vblendweights = (const unsigned char *)(pbase + va.offset); break; + case IQM_COLOR: + if (va.format == IQM_FLOAT && va.size == 4) + vcolor4f = (const float *)(pbase + va.offset); + if (va.format == IQM_UBYTE && va.size == 4) + vcolor4ub = (const unsigned char *)(pbase + va.offset); + break; } } if (header.num_vertexes > 0 && (!vposition || !vtexcoord || ((header.num_frames > 0 || header.num_anims > 0) && (!vblendindexes || !vblendweights)))) @@ -3218,7 +3455,6 @@ void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) text = header.num_text && header.ofs_text ? (const char *)(pbase + header.ofs_text) : ""; - loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices; loadmodel->DrawSky = NULL; loadmodel->DrawAddWaterPlanes = NULL; loadmodel->Draw = R_Q1BSP_Draw; @@ -3233,6 +3469,7 @@ void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox; loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine; loadmodel->PointSuperContents = NULL; + loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices; // load external .skin files if present skinfiles = Mod_LoadSkinFiles(); @@ -3250,7 +3487,7 @@ void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) meshtriangles = header.num_triangles; // 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) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[3]) : 0) + meshvertices * sizeof(float[14]) + (vblendindexes && vblendweights ? meshvertices * sizeof(unsigned short) : 0) + 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) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[3]) : 0) + meshvertices * (sizeof(float[14]) + (vcolor4f || vcolor4ub ? sizeof(float[4]) : 0)) + (vblendindexes && vblendweights ? meshvertices * (sizeof(unsigned short) + sizeof(unsigned char[2][4])) : 0) + loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]) + 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); @@ -3266,6 +3503,15 @@ void Mod_INTERQUAKEMODEL_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]); + if (vcolor4f || vcolor4ub) + { + loadmodel->surfmesh.data_lightmapcolor4f = (float *)data;data += meshvertices * sizeof(float[4]); + } + if (vblendindexes && vblendweights) + { + loadmodel->surfmesh.data_skeletalindex4ub = (unsigned char *)data;data += meshvertices * sizeof(unsigned char[4]); + loadmodel->surfmesh.data_skeletalweight4ub = (unsigned char *)data;data += meshvertices * sizeof(unsigned char[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); @@ -3279,7 +3525,7 @@ void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) { 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->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]); if (vblendindexes && vblendweights) loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t)); @@ -3383,6 +3629,10 @@ void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) loadmodel->animscenes[0].framerate = 10; } + loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1); + if(mod_alias_force_animated.string[0]) + loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0; + biggestorigin = 0; if (header.version == 1) { @@ -3462,12 +3712,19 @@ void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) { for (j = 0;j < (int)header.num_poses;j++, k++) { - loadmodel->data_poses6s[k*6 + 0] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[0] + (pose1[j].channelmask&1 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[0] : 0)); - loadmodel->data_poses6s[k*6 + 1] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[1] + (pose1[j].channelmask&2 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[1] : 0)); - loadmodel->data_poses6s[k*6 + 2] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[2] + (pose1[j].channelmask&4 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[2] : 0)); - loadmodel->data_poses6s[k*6 + 3] = 32767.0f * (pose1[j].channeloffset[3] + (pose1[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[3] : 0)); - loadmodel->data_poses6s[k*6 + 4] = 32767.0f * (pose1[j].channeloffset[4] + (pose1[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[4] : 0)); - loadmodel->data_poses6s[k*6 + 5] = 32767.0f * (pose1[j].channeloffset[5] + (pose1[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[5] : 0)); + float qx, qy, qz, qw; + loadmodel->data_poses7s[k*7 + 0] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[0] + (pose1[j].channelmask&1 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[0] : 0)); + loadmodel->data_poses7s[k*7 + 1] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[1] + (pose1[j].channelmask&2 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[1] : 0)); + loadmodel->data_poses7s[k*7 + 2] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[2] + (pose1[j].channelmask&4 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[2] : 0)); + qx = pose1[j].channeloffset[3] + (pose1[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[3] : 0); + qy = pose1[j].channeloffset[4] + (pose1[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[4] : 0); + qz = pose1[j].channeloffset[5] + (pose1[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[5] : 0); + qw = 1.0f - (qx*qx + qy*qy + qz*qz); + qw = qw > 0.0f ? -sqrt(qw) : 0.0f; + loadmodel->data_poses7s[k*7 + 3] = 32767.0f * qx; + loadmodel->data_poses7s[k*7 + 4] = 32767.0f * qy; + loadmodel->data_poses7s[k*7 + 5] = 32767.0f * qz; + loadmodel->data_poses7s[k*7 + 6] = 32767.0f * qw; // skip scale data for now if(pose1[j].channelmask&64) framedata++; if(pose1[j].channelmask&128) framedata++; @@ -3478,12 +3735,19 @@ void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) { for (i = 0;i < loadmodel->num_bones;i++) { - loadmodel->data_poses6s[i*6 + 0] = loadmodel->num_poseinvscale * joint1[i].origin[0]; - loadmodel->data_poses6s[i*6 + 1] = loadmodel->num_poseinvscale * joint1[i].origin[1]; - loadmodel->data_poses6s[i*6 + 2] = loadmodel->num_poseinvscale * joint1[i].origin[2]; - loadmodel->data_poses6s[i*6 + 3] = 32767.0f * joint1[i].rotation[0]; - loadmodel->data_poses6s[i*6 + 4] = 32767.0f * joint1[i].rotation[1]; - loadmodel->data_poses6s[i*6 + 5] = 32767.0f * joint1[i].rotation[2]; + float qx, qy, qz, qw; + loadmodel->data_poses7s[i*7 + 0] = loadmodel->num_poseinvscale * joint1[i].origin[0]; + loadmodel->data_poses7s[i*7 + 1] = loadmodel->num_poseinvscale * joint1[i].origin[1]; + loadmodel->data_poses7s[i*7 + 2] = loadmodel->num_poseinvscale * joint1[i].origin[2]; + qx = joint1[i].rotation[0]; + qy = joint1[i].rotation[1]; + qz = joint1[i].rotation[2]; + qw = 1.0f - (qx*qx + qy*qy + qz*qz); + qw = qw > 0.0f ? -sqrt(qw) : 0.0f; + loadmodel->data_poses7s[i*7 + 3] = 32767.0f * qx; + loadmodel->data_poses7s[i*7 + 4] = 32767.0f * qy; + loadmodel->data_poses7s[i*7 + 5] = 32767.0f * qz; + loadmodel->data_poses7s[i*7 + 6] = 32767.0f * qw; } } } @@ -3494,9 +3758,9 @@ void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) for (j = 0;j < (int)header.num_poses;j++, k++) { float rot[4]; - loadmodel->data_poses6s[k*6 + 0] = loadmodel->num_poseinvscale * (pose[j].channeloffset[0] + (pose[j].channelmask&1 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[0] : 0)); - loadmodel->data_poses6s[k*6 + 1] = loadmodel->num_poseinvscale * (pose[j].channeloffset[1] + (pose[j].channelmask&2 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[1] : 0)); - loadmodel->data_poses6s[k*6 + 2] = loadmodel->num_poseinvscale * (pose[j].channeloffset[2] + (pose[j].channelmask&4 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[2] : 0)); + loadmodel->data_poses7s[k*7 + 0] = loadmodel->num_poseinvscale * (pose[j].channeloffset[0] + (pose[j].channelmask&1 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[0] : 0)); + loadmodel->data_poses7s[k*7 + 1] = loadmodel->num_poseinvscale * (pose[j].channeloffset[1] + (pose[j].channelmask&2 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[1] : 0)); + loadmodel->data_poses7s[k*7 + 2] = loadmodel->num_poseinvscale * (pose[j].channeloffset[2] + (pose[j].channelmask&4 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[2] : 0)); rot[0] = pose[j].channeloffset[3] + (pose[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[3] : 0); rot[1] = pose[j].channeloffset[4] + (pose[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[4] : 0); rot[2] = pose[j].channeloffset[5] + (pose[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[5] : 0); @@ -3504,9 +3768,10 @@ void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) if (rot[3] > 0) Vector4Negate(rot, rot); Vector4Normalize2(rot, rot); - loadmodel->data_poses6s[k*6 + 3] = 32767.0f * rot[0]; - loadmodel->data_poses6s[k*6 + 4] = 32767.0f * rot[1]; - loadmodel->data_poses6s[k*6 + 5] = 32767.0f * rot[2]; + loadmodel->data_poses7s[k*7 + 3] = 32767.0f * rot[0]; + loadmodel->data_poses7s[k*7 + 4] = 32767.0f * rot[1]; + loadmodel->data_poses7s[k*7 + 5] = 32767.0f * rot[2]; + loadmodel->data_poses7s[k*7 + 6] = 32767.0f * rot[3]; // skip scale data for now if(pose[j].channelmask&128) framedata++; if(pose[j].channelmask&256) framedata++; @@ -3517,12 +3782,13 @@ void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) { for (i = 0;i < loadmodel->num_bones;i++) { - loadmodel->data_poses6s[i*6 + 0] = loadmodel->num_poseinvscale * joint[i].origin[0]; - loadmodel->data_poses6s[i*6 + 1] = loadmodel->num_poseinvscale * joint[i].origin[1]; - loadmodel->data_poses6s[i*6 + 2] = loadmodel->num_poseinvscale * joint[i].origin[2]; - loadmodel->data_poses6s[i*6 + 3] = 32767.0f * joint[i].rotation[0]; - loadmodel->data_poses6s[i*6 + 4] = 32767.0f * joint[i].rotation[1]; - loadmodel->data_poses6s[i*6 + 5] = 32767.0f * joint[i].rotation[2]; + loadmodel->data_poses7s[i*7 + 0] = loadmodel->num_poseinvscale * joint[i].origin[0]; + loadmodel->data_poses7s[i*7 + 1] = loadmodel->num_poseinvscale * joint[i].origin[1]; + loadmodel->data_poses7s[i*7 + 2] = loadmodel->num_poseinvscale * joint[i].origin[2]; + loadmodel->data_poses7s[i*7 + 3] = 32767.0f * joint[i].rotation[0]; + loadmodel->data_poses7s[i*7 + 4] = 32767.0f * joint[i].rotation[1]; + loadmodel->data_poses7s[i*7 + 5] = 32767.0f * joint[i].rotation[2]; + loadmodel->data_poses7s[i*7 + 6] = 32767.0f * joint[i].rotation[3]; } } } @@ -3669,6 +3935,43 @@ void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) memcpy(weights.index, vblendindexes + i*4, 4); memcpy(weights.influence, vblendweights + i*4, 4); loadmodel->surfmesh.blends[i] = Mod_Skeletal_AddBlend(loadmodel, &weights); + loadmodel->surfmesh.data_skeletalindex4ub[i*4 ] = weights.index[0]; + loadmodel->surfmesh.data_skeletalindex4ub[i*4+1] = weights.index[1]; + loadmodel->surfmesh.data_skeletalindex4ub[i*4+2] = weights.index[2]; + loadmodel->surfmesh.data_skeletalindex4ub[i*4+3] = weights.index[3]; + loadmodel->surfmesh.data_skeletalweight4ub[i*4 ] = weights.influence[0]; + loadmodel->surfmesh.data_skeletalweight4ub[i*4+1] = weights.influence[1]; + loadmodel->surfmesh.data_skeletalweight4ub[i*4+2] = weights.influence[2]; + loadmodel->surfmesh.data_skeletalweight4ub[i*4+3] = weights.influence[3]; + } + } + + if (vcolor4f) + { + outcolor = loadmodel->surfmesh.data_lightmapcolor4f; + // this unaligned memory access is safe (LittleFloat reads as bytes) + for (i = 0;i < (int)header.num_vertexes;i++) + { + outcolor[0] = LittleFloat(vcolor4f[0]); + outcolor[1] = LittleFloat(vcolor4f[1]); + outcolor[2] = LittleFloat(vcolor4f[2]); + outcolor[3] = LittleFloat(vcolor4f[3]); + vcolor4f += 4; + outcolor += 4; + } + } + else if (vcolor4ub) + { + outcolor = loadmodel->surfmesh.data_lightmapcolor4f; + // this unaligned memory access is safe (all bytes) + for (i = 0;i < (int)header.num_vertexes;i++) + { + outcolor[0] = vcolor4ub[0] * (1.0f / 255.0f); + outcolor[1] = vcolor4ub[1] * (1.0f / 255.0f); + outcolor[2] = vcolor4ub[2] * (1.0f / 255.0f); + outcolor[3] = vcolor4ub[3] * (1.0f / 255.0f); + vcolor4ub += 4; + outcolor += 4; } } @@ -3712,9 +4015,7 @@ void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) if (!header.ofs_bounds) Mod_Alias_CalculateBoundingBox(); - loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1; - - if (!loadmodel->surfmesh.isanimated) + if (!loadmodel->surfmesh.isanimated && loadmodel->surfmesh.num_triangles >= 1) { Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih); loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;