X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=model_alias.c;h=7a2c8d60f27515a38f9388c76ad31f8dec278967;hb=484246eea9f6b28b015a4772fca0ba1c6207a719;hp=cf0bdc3ef49e21deb38ec2159451f09d9724870b;hpb=d0f5b29b731a23f5bc0fb268012de5a56902950a;p=xonotic%2Fdarkplaces.git diff --git a/model_alias.c b/model_alias.c index cf0bdc3e..7a2c8d60 100644 --- a/model_alias.c +++ b/model_alias.c @@ -46,51 +46,85 @@ 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, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f) +void Mod_Skeletal_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f) { #define MAX_BONES 256 // vertex weighted skeletal int i, k; int blends; - float desiredscale[3]; float boneposerelative[MAX_BONES][12]; - float *matrix, m[12], bonepose[MAX_BONES][12]; + float m[12], bonepose[MAX_BONES][12]; - // interpolate matrices and concatenate them to their parents - for (i = 0;i < model->num_bones;i++) + if (skeleton && !skeleton->relativetransforms) + skeleton = NULL; + + // interpolate matrices + if (skeleton) { - for (k = 0;k < 12;k++) - m[k] = 0; - VectorClear(desiredscale); - for (blends = 0;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++) + for (i = 0;i < model->num_bones;i++) { - matrix = model->data_poses + (frameblend[blends].subframe * model->num_bones + i) * 12; - for (k = 0;k < 12;k++) - m[k] += matrix[k] * frameblend[blends].lerp; - desiredscale[0] += frameblend[blends].lerp * VectorLength(matrix ); - desiredscale[1] += frameblend[blends].lerp * VectorLength(matrix + 4); - desiredscale[2] += frameblend[blends].lerp * VectorLength(matrix + 8); + Matrix4x4_ToArray12FloatD3D(&skeleton->relativetransforms[i], m); + if (model->data_bones[i].parent >= 0) + R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]); + else + for (k = 0;k < 12;k++) + bonepose[i][k] = m[k]; + + // create a relative deformation matrix to describe displacement + // from the base mesh, which is used by the actual weighting + R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]); } - VectorNormalize(m ); - VectorNormalize(m + 4); - VectorNormalize(m + 8); - VectorScale(m , desiredscale[0], m ); - VectorScale(m + 4, desiredscale[1], m + 4); - VectorScale(m + 8, desiredscale[2], m + 8); - if (i == r_skeletal_debugbone.integer) - m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value; - m[3] *= r_skeletal_debugtranslatex.value; - m[7] *= r_skeletal_debugtranslatey.value; - m[11] *= r_skeletal_debugtranslatez.value; - if (model->data_bones[i].parent >= 0) - R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]); - else + } + else + { + float originscale = model->num_posescale; + float x,y,z,w,lerp; + const short *pose6s; + for (i = 0;i < model->num_bones;i++) + { for (k = 0;k < 12;k++) - bonepose[i][k] = m[k]; - // create a relative deformation matrix to describe displacement - // from the base mesh, which is used by the actual weighting - R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]); + m[k] = 0; + for (blends = 0;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++) + { + pose6s = model->data_poses6s + 6 * (frameblend[blends].subframe * model->num_bones + i); + lerp = frameblend[blends].lerp; + x = pose6s[3] * (1.0f / 32767.0f); + y = pose6s[4] * (1.0f / 32767.0f); + z = pose6s[5] * (1.0f / 32767.0f); + w = 1.0f - (x*x+y*y+z*z); + w = w > 0.0f ? -sqrt(w) : 0.0f; + m[ 0] += (1-2*(y*y+z*z)) * lerp; + m[ 1] += ( 2*(x*y-z*w)) * lerp; + m[ 2] += ( 2*(x*z+y*w)) * lerp; + m[ 3] += (pose6s[0] * originscale) * lerp; + m[ 4] += ( 2*(x*y+z*w)) * lerp; + m[ 5] += (1-2*(x*x+z*z)) * lerp; + m[ 6] += ( 2*(y*z-x*w)) * lerp; + m[ 7] += (pose6s[1] * originscale) * lerp; + m[ 8] += ( 2*(x*z-y*w)) * lerp; + m[ 9] += ( 2*(y*z+x*w)) * lerp; + m[10] += (1-2*(x*x+y*y)) * lerp; + m[11] += (pose6s[2] * originscale) * lerp; + } + VectorNormalize(m ); + VectorNormalize(m + 4); + VectorNormalize(m + 8); + if (i == r_skeletal_debugbone.integer) + m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value; + m[3] *= r_skeletal_debugtranslatex.value; + m[7] *= r_skeletal_debugtranslatey.value; + m[11] *= r_skeletal_debugtranslatez.value; + if (model->data_bones[i].parent >= 0) + R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]); + else + for (k = 0;k < 12;k++) + bonepose[i][k] = m[k]; + // create a relative deformation matrix to describe displacement + // from the base mesh, which is used by the actual weighting + R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative[i]); + } } + // blend the vertex bone weights // special case for the extremely common wf[0] == 1 because it saves 3 multiplies per array when compared to the other case (w[0] is always 1 if only one bone controls this vertex, artists only use multiple bones for certain special cases) // special case for the first bone because it avoids the need to memset the arrays before filling @@ -228,7 +262,7 @@ void Mod_Skeletal_AnimateVertices(const dp_model_t *model, const frameblend_t *f } } -void Mod_MD3_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f) +void Mod_MD3_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f) { // vertex morph int i, numblends, blendnum; @@ -317,7 +351,7 @@ void Mod_MD3_AnimateVertices(const dp_model_t *model, const frameblend_t *frameb } } -void Mod_MDL_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f) +void Mod_MDL_AnimateVertices(const dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, float *vertex3f, float *normal3f, float *svector3f, float *tvector3f) { // vertex morph int i, numblends, blendnum; @@ -414,34 +448,65 @@ void Mod_MDL_AnimateVertices(const dp_model_t *model, const frameblend_t *frameb } } -int Mod_Alias_GetTagMatrix(const dp_model_t *model, int poseframe, int tagindex, matrix4x4_t *outmatrix) +int Mod_Alias_GetTagMatrix(const dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, int tagindex, matrix4x4_t *outmatrix) { - const float *boneframe; - float tempbonematrix[12], bonematrix[12]; + matrix4x4_t temp; + matrix4x4_t parentbonematrix; + matrix4x4_t tempbonematrix; + matrix4x4_t bonematrix; + matrix4x4_t blendmatrix; + int blendindex; + int parenttagindex; + int k; + float lerp; + const float *input; + float blendtag[12]; *outmatrix = identitymatrix; - if (model->num_bones) + if (skeleton && skeleton->relativetransforms) + { + if (tagindex < 0 || tagindex >= skeleton->model->num_bones) + return 4; + *outmatrix = skeleton->relativetransforms[tagindex]; + while ((tagindex = model->data_bones[tagindex].parent) >= 0) + { + temp = *outmatrix; + Matrix4x4_Concat(outmatrix, &skeleton->relativetransforms[tagindex], &temp); + } + } + else if (model->num_bones) { if (tagindex < 0 || tagindex >= model->num_bones) return 4; - if (poseframe >= model->num_poses) - return 6; - boneframe = model->data_poses + poseframe * model->num_bones * 12; - memcpy(bonematrix, boneframe + tagindex * 12, sizeof(float[12])); - while (model->data_bones[tagindex].parent >= 0) + Matrix4x4_Clear(&blendmatrix); + for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++) { - memcpy(tempbonematrix, bonematrix, sizeof(float[12])); - R_ConcatTransforms(boneframe + model->data_bones[tagindex].parent * 12, tempbonematrix, bonematrix); - tagindex = model->data_bones[tagindex].parent; + lerp = frameblend[blendindex].lerp; + Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (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)); + tempbonematrix = bonematrix; + Matrix4x4_Concat(&bonematrix, &parentbonematrix, &tempbonematrix); + } + Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp); } - Matrix4x4_FromArray12FloatD3D(outmatrix, bonematrix); + *outmatrix = blendmatrix; } else if (model->num_tags) { if (tagindex < 0 || tagindex >= model->num_tags) return 4; - if (poseframe >= model->num_tagframes) - return 6; - Matrix4x4_FromArray12FloatGL(outmatrix, model->data_tags[poseframe * model->num_tags + tagindex].matrixgl); + for (k = 0;k < 12;k++) + blendtag[k] = 0; + for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++) + { + lerp = frameblend[blendindex].lerp; + input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl; + for (k = 0;k < 12;k++) + blendtag[k] += input[k] * lerp; + } + Matrix4x4_FromArray12FloatGL(outmatrix, blendtag); } if(!mod_alias_supporttagscale.integer) @@ -450,35 +515,57 @@ int Mod_Alias_GetTagMatrix(const dp_model_t *model, int poseframe, int tagindex, return 0; } -int Mod_Alias_GetExtendedTagInfoForIndex(const dp_model_t *model, unsigned int skin, int poseframe, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix) +int Mod_Alias_GetExtendedTagInfoForIndex(const dp_model_t *model, unsigned int skin, const frameblend_t *frameblend, const skeleton_t *skeleton, int tagindex, int *parentindex, const char **tagname, matrix4x4_t *tag_localmatrix) { - const float *boneframe; + int blendindex; + int k; + float lerp; + matrix4x4_t bonematrix; + matrix4x4_t blendmatrix; + const float *input; + float blendtag[12]; - if(skin >= (unsigned int)model->numskins) - skin = 0; - - if (model->num_bones) + if (skeleton && skeleton->relativetransforms) { - if(tagindex >= model->num_bones || tagindex < 0) + if (tagindex < 0 || tagindex >= skeleton->model->num_bones) + return 1; + *parentindex = skeleton->model->data_bones[tagindex].parent; + *tagname = skeleton->model->data_bones[tagindex].name; + *tag_localmatrix = skeleton->relativetransforms[tagindex]; + return 0; + } + else if (model->num_bones) + { + if (tagindex < 0 || tagindex >= model->num_bones) return 1; - if (poseframe >= model->num_poses) - return 2; - - boneframe = model->data_poses + poseframe * model->num_bones * 12; *parentindex = model->data_bones[tagindex].parent; *tagname = model->data_bones[tagindex].name; - Matrix4x4_FromArray12FloatD3D(tag_localmatrix, boneframe + tagindex * 12); + Matrix4x4_Clear(&blendmatrix); + 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_Accumulate(&blendmatrix, &bonematrix, lerp); + } + *tag_localmatrix = blendmatrix; return 0; } - - if (model->num_tags) + else if (model->num_tags) { - if(tagindex >= model->num_tags || tagindex < 0) + if (tagindex < 0 || tagindex >= model->num_tags) return 1; - if (poseframe >= model->num_tagframes) - return 2; + *parentindex = -1; *tagname = model->data_tags[tagindex].name; - Matrix4x4_FromArray12FloatGL(tag_localmatrix, model->data_tags[poseframe * model->num_tags + tagindex].matrixgl); + for (k = 0;k < 12;k++) + blendtag[k] = 0; + for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++) + { + lerp = frameblend[blendindex].lerp; + input = model->data_tags[frameblend[blendindex].subframe * model->num_tags + tagindex].matrixgl; + for (k = 0;k < 12;k++) + blendtag[k] += input[k] * lerp; + } + Matrix4x4_FromArray12FloatGL(tag_localmatrix, blendtag); return 0; } @@ -503,47 +590,25 @@ int Mod_Alias_GetTagIndexForName(const dp_model_t *model, unsigned int skin, con static void Mod_BuildBaseBonePoses(void) { - int i, k; - double scale; - float *basebonepose; - float *in12f = loadmodel->data_poses; - float *out12f; - float *outinv12f = loadmodel->data_baseboneposeinverse; + int boneindex; + matrix4x4_t *basebonepose; + float *outinvmatrix = loadmodel->data_baseboneposeinverse; + matrix4x4_t bonematrix; + matrix4x4_t tempbonematrix; if (!loadmodel->num_bones) return; - out12f = basebonepose = (float *) Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(float[12])) - for (i = 0;i < loadmodel->num_bones;i++, in12f += 12, out12f += 12, outinv12f += 12) + basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t)); + for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++) { - if (loadmodel->data_bones[i].parent >= 0) - R_ConcatTransforms(basebonepose + 12 * loadmodel->data_bones[i].parent, in12f, out12f); - else - for (k = 0;k < 12;k++) - out12f[k] = in12f[k]; - - // invert The Matrix - - // we only support uniform scaling, so assume the first row is enough - // (note the lack of sqrt here, because we're trying to undo the scaling, - // this means multiplying by the inverse scale twice - squaring it, which - // makes the sqrt a waste of time) - scale = 1.0 / (out12f[ 0] * out12f[ 0] + out12f[ 1] * out12f[ 1] + out12f[ 2] * out12f[ 2]); - - // invert the rotation by transposing and multiplying by the squared - // recipricol of the input matrix scale as described above - outinv12f[ 0] = (float)(out12f[ 0] * scale); - outinv12f[ 1] = (float)(out12f[ 4] * scale); - outinv12f[ 2] = (float)(out12f[ 8] * scale); - outinv12f[ 4] = (float)(out12f[ 1] * scale); - outinv12f[ 5] = (float)(out12f[ 5] * scale); - outinv12f[ 6] = (float)(out12f[ 9] * scale); - outinv12f[ 8] = (float)(out12f[ 2] * scale); - outinv12f[ 9] = (float)(out12f[ 6] * scale); - outinv12f[10] = (float)(out12f[10] * scale); - - // invert the translate - outinv12f[ 3] = -(out12f[ 3] * outinv12f[ 0] + out12f[ 7] * outinv12f[ 1] + out12f[11] * outinv12f[ 2]); - outinv12f[ 7] = -(out12f[ 3] * outinv12f[ 4] + out12f[ 7] * outinv12f[ 5] + out12f[11] * outinv12f[ 6]); - outinv12f[11] = -(out12f[ 3] * outinv12f[ 8] + out12f[ 7] * outinv12f[ 9] + out12f[11] * outinv12f[10]); + Matrix4x4_FromBonePose6s(&bonematrix, loadmodel->num_posescale, loadmodel->data_poses6s + 6 * boneindex); + 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); } @@ -565,7 +630,7 @@ static void Mod_Alias_CalculateBoundingBox(void) radius = 0; for (frameblend[0].subframe = 0;frameblend[0].subframe < loadmodel->num_poses;frameblend[0].subframe++) { - loadmodel->AnimateVertices(loadmodel, frameblend, vertex3f, NULL, NULL, NULL); + loadmodel->AnimateVertices(loadmodel, frameblend, NULL, vertex3f, NULL, NULL, NULL); for (vnum = 0, v = vertex3f;vnum < loadmodel->surfmesh.num_vertices;vnum++, v += 3) { if (firstvertex) @@ -622,8 +687,8 @@ static void Mod_Alias_MorphMesh_CompileFrames(void) for (i = loadmodel->surfmesh.num_morphframes-1;i >= 0;i--) { frameblend[0].subframe = i; - loadmodel->AnimateVertices(loadmodel, frameblend, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL); - Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, r_smoothnormals_areaweighting.integer); + loadmodel->AnimateVertices(loadmodel, frameblend, NULL, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_normal3f, NULL, NULL); + Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, r_smoothnormals_areaweighting.integer != 0); // encode the svector and tvector in 3 byte format for permanent storage for (j = 0;j < loadmodel->surfmesh.num_vertices;j++) { @@ -633,12 +698,10 @@ static void Mod_Alias_MorphMesh_CompileFrames(void) } } -static void Mod_MDLMD2MD3_TraceBox(dp_model_t *model, int frame, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask) +static void Mod_MDLMD2MD3_TraceLine(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t end, int hitsupercontentsmask) { int i; - vec3_t shiftstart, shiftend; float segmentmins[3], segmentmaxs[3]; - frameblend_t frameblend[MAX_FRAMEBLENDS]; msurface_t *surface; static int maxvertices = 0; static float *vertex3f = NULL; @@ -646,9 +709,6 @@ static void Mod_MDLMD2MD3_TraceBox(dp_model_t *model, int frame, trace_t *trace, trace->fraction = 1; trace->realfraction = 1; trace->hitsupercontentsmask = hitsupercontentsmask; - memset(frameblend, 0, sizeof(frameblend)); - frameblend[0].subframe = frame; - frameblend[0].lerp = 1; if (maxvertices < model->surfmesh.num_vertices) { if (vertex3f) @@ -656,53 +716,72 @@ static void Mod_MDLMD2MD3_TraceBox(dp_model_t *model, int frame, trace_t *trace, maxvertices = (model->surfmesh.num_vertices + 255) & ~255; vertex3f = (float *)Z_Malloc(maxvertices * 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; + segmentmaxs[0] = max(start[0], end[0]) + 1; + segmentmaxs[1] = max(start[1], end[1]) + 1; + segmentmaxs[2] = max(start[2], end[2]) + 1; + model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL); + for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++) + Collision_TraceLineTriangleMeshFloat(trace, start, end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs); +} + +static int maxvertices = 0; +static float *vertex3f = NULL; + +static void Mod_MDLMD2MD3_TraceBox(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask) +{ + int i; + vec3_t shiftstart, shiftend; + float segmentmins[3], segmentmaxs[3]; + msurface_t *surface; + colboxbrushf_t thisbrush_start, thisbrush_end; + vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs; + if (VectorCompare(boxmins, boxmaxs)) { - // line trace VectorAdd(start, boxmins, shiftstart); VectorAdd(end, boxmins, shiftend); - segmentmins[0] = min(shiftstart[0], shiftend[0]) - 1; - segmentmins[1] = min(shiftstart[1], shiftend[1]) - 1; - segmentmins[2] = min(shiftstart[2], shiftend[2]) - 1; - segmentmaxs[0] = max(shiftstart[0], shiftend[0]) + 1; - segmentmaxs[1] = max(shiftstart[1], shiftend[1]) + 1; - segmentmaxs[2] = max(shiftstart[2], shiftend[2]) + 1; - for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++) - { - model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL); - Collision_TraceLineTriangleMeshFloat(trace, shiftstart, shiftend, 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); - } + Mod_MDLMD2MD3_TraceLine(model, frameblend, skeleton, trace, start, end, hitsupercontentsmask); + VectorSubtract(trace->endpos, boxmins, trace->endpos); + return; } - else + + // box trace, performed as brush trace + memset(trace, 0, sizeof(*trace)); + trace->fraction = 1; + trace->realfraction = 1; + trace->hitsupercontentsmask = hitsupercontentsmask; + if (maxvertices < model->surfmesh.num_vertices) { - // box trace, performed as brush trace - colbrushf_t *thisbrush_start, *thisbrush_end; - vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs; - segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1; - segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1; - segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1; - segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1; - segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1; - segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1; - VectorAdd(start, boxmins, boxstartmins); - VectorAdd(start, boxmaxs, boxstartmaxs); - VectorAdd(end, boxmins, boxendmins); - VectorAdd(end, boxmaxs, boxendmaxs); - thisbrush_start = Collision_BrushForBox(&identitymatrix, boxstartmins, boxstartmaxs, 0, 0, NULL); - thisbrush_end = Collision_BrushForBox(&identitymatrix, boxendmins, boxendmaxs, 0, 0, NULL); - for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++) - { - if (maxvertices < model->surfmesh.num_vertices) - { - if (vertex3f) - Z_Free(vertex3f); - maxvertices = (model->surfmesh.num_vertices + 255) & ~255; - vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3])); - } - model->AnimateVertices(model, frameblend, vertex3f, NULL, NULL, NULL); - Collision_TraceBrushTriangleMeshFloat(trace, thisbrush_start, thisbrush_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) + Z_Free(vertex3f); + maxvertices = (model->surfmesh.num_vertices + 255) & ~255; + vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3])); + } + segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1; + segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1; + segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1; + segmentmaxs[0] = max(start[0], end[0]) + boxmaxs[0] + 1; + segmentmaxs[1] = max(start[1], end[1]) + boxmaxs[1] + 1; + segmentmaxs[2] = max(start[2], end[2]) + boxmaxs[2] + 1; + VectorAdd(start, boxmins, boxstartmins); + VectorAdd(start, boxmaxs, boxstartmaxs); + VectorAdd(end, boxmins, boxendmins); + VectorAdd(end, boxmaxs, boxendmaxs); + Collision_BrushForBox(&thisbrush_start, boxstartmins, boxstartmaxs, 0, 0, NULL); + Collision_BrushForBox(&thisbrush_end, boxendmins, boxendmaxs, 0, 0, NULL); + if (maxvertices < model->surfmesh.num_vertices) + { + if (vertex3f) + Z_Free(vertex3f); + maxvertices = (model->surfmesh.num_vertices + 255) & ~255; + vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3])); } + model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL); + for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++) + Collision_TraceBrushTriangleMeshFloat(trace, &thisbrush_start.brush, &thisbrush_end.brush, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs); } static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap) @@ -806,12 +885,14 @@ static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *ski //texture->textureflags = 0; texture->basematerialflags = MATERIALFLAG_WALL; - if (texture->currentskinframe->fog) + if (texture->currentskinframe->hasalpha) texture->basematerialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; texture->currentmaterialflags = texture->basematerialflags; + texture->specularscalemod = 1; + texture->specularpowermod = 1; } -static void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername) +void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername) { int i; skinfileitem_t *skinfileitem; @@ -827,7 +908,7 @@ static void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfi // leave the skin unitialized (nodraw) if the replacement is "common/nodraw" or "textures/common/nodraw" if (!strcmp(skinfileitem->name, meshname)) { - Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS); + Mod_LoadTextureFromQ3Shader(skin, skinfileitem->replacement, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS); break; } } @@ -840,7 +921,7 @@ static void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfi } } else - Mod_LoadTextureFromQ3Shader(skin, shadername, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS); + Mod_LoadTextureFromQ3Shader(skin, shadername, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS); } #define BOUNDI(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid ##VALUE (%d exceeds %d - %d)", loadmodel->name, VALUE, MIN, MAX); @@ -886,10 +967,14 @@ void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend) loadmodel->Draw = R_Q1BSP_Draw; loadmodel->DrawDepth = R_Q1BSP_DrawDepth; loadmodel->DrawDebug = R_Q1BSP_DrawDebug; + loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass; + loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap; + loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap; loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume; loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume; loadmodel->DrawLight = R_Q1BSP_DrawLight; loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox; + loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine; loadmodel->PointSuperContents = NULL; loadmodel->num_surfaces = 1; @@ -1043,11 +1128,10 @@ void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend) // generate ushort elements array if possible if (loadmodel->surfmesh.num_vertices <= 65536) - { loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles); + if (loadmodel->surfmesh.data_element3s) for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++) loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i]; - } // load the frames loadmodel->animscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes); @@ -1216,10 +1300,14 @@ void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend) loadmodel->Draw = R_Q1BSP_Draw; loadmodel->DrawDepth = R_Q1BSP_DrawDepth; loadmodel->DrawDebug = R_Q1BSP_DrawDebug; + loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass; + loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap; + loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap; loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume; loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume; loadmodel->DrawLight = R_Q1BSP_DrawLight; loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox; + loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine; loadmodel->PointSuperContents = NULL; if (LittleLong(pinmodel->num_tris) < 1 || LittleLong(pinmodel->num_tris) > 65536) @@ -1286,7 +1374,7 @@ void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend) loadmodel->num_texturesperskin = loadmodel->num_surfaces; loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t)); for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME) - Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS); + Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS); } else { @@ -1372,11 +1460,10 @@ void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend) // generate ushort elements array if possible if (loadmodel->surfmesh.num_vertices <= 65536) - { loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles); + if (loadmodel->surfmesh.data_element3s) for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++) loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i]; - } // load the frames datapointer = (base + LittleLong(pinmodel->ofs_frames)); @@ -1456,10 +1543,14 @@ void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend) loadmodel->Draw = R_Q1BSP_Draw; loadmodel->DrawDepth = R_Q1BSP_DrawDepth; loadmodel->DrawDebug = R_Q1BSP_DrawDebug; + loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass; + loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap; + loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap; loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume; loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume; loadmodel->DrawLight = R_Q1BSP_DrawLight; loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox; + loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine; loadmodel->PointSuperContents = NULL; loadmodel->synctype = ST_RAND; // convert model flags to EF flags (MF_ROCKET becomes EF_ROCKET, etc) @@ -1534,11 +1625,7 @@ void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend) loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]); loadmodel->surfmesh.data_morphmd3vertex = (md3vertex_t *)data;data += meshvertices * loadmodel->numframes * sizeof(md3vertex_t); if (meshvertices <= 65536) - { loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]); - for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++) - loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i]; - } meshvertices = 0; meshtriangles = 0; @@ -1581,6 +1668,9 @@ void Mod_IDP3_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.data_element3s) + for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++) + loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i]; Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles); Mod_Alias_MorphMesh_CompileFrames(); Mod_Alias_CalculateBoundingBox(); @@ -1596,7 +1686,7 @@ void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) zymtype1header_t *pinmodel, *pheader; unsigned char *pbase; int i, j, k, numposes, meshvertices, meshtriangles, *bonecount, *vertbonecounts, count, *renderlist, *renderlistend, *outelements; - float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose; + float modelradius, corner[2], *poses, *intexcoord2f, *outtexcoord2f, *bonepose, f, biggestorigin, tempvec[3], modelscale; zymvertex_t *verts, *vertdata; zymscene_t *scene; zymbone_t *bone; @@ -1669,10 +1759,14 @@ void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) loadmodel->Draw = R_Q1BSP_Draw; loadmodel->DrawDepth = R_Q1BSP_DrawDepth; loadmodel->DrawDebug = R_Q1BSP_DrawDebug; + loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass; + loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap; + loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap; loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume; loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume; loadmodel->DrawLight = R_Q1BSP_DrawLight; loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox; + loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine; loadmodel->PointSuperContents = NULL; loadmodel->numframes = pheader->numscenes; @@ -1765,7 +1859,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(float[12]) + loadmodel->num_bones * sizeof(float[12])); + data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshvertices * sizeof(float[14]) + meshvertices * sizeof(int[4]) + meshvertices * sizeof(float[4]) + loadmodel->num_poses * loadmodel->num_bones * sizeof(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); @@ -1780,19 +1874,52 @@ void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]); loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]); loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]); - loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]); loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]); if (loadmodel->surfmesh.num_vertices <= 65536) - { loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]); - for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++) - loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i]; - } + loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]); //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data poses = (float *) (pheader->lump_poses.start + pbase); - for (i = 0;i < pheader->lump_poses.length / 4;i++) - loadmodel->data_poses[i] = BigFloat(poses[i]); + // figure out scale of model from root bone, for compatibility with old zmodel versions + tempvec[0] = BigFloat(poses[0]); + tempvec[1] = BigFloat(poses[1]); + tempvec[2] = BigFloat(poses[2]); + modelscale = VectorLength(tempvec); + biggestorigin = 0; + for (i = 0;i < loadmodel->num_bones * numposes * 12;i++) + { + f = fabs(BigFloat(poses[i])); + biggestorigin = max(biggestorigin, f); + } + loadmodel->num_posescale = biggestorigin / 32767.0f; + loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale; + for (i = 0;i < numposes;i++) + { + const float *frameposes = (float *) (pheader->lump_poses.start + pbase) + 12*i*loadmodel->num_bones; + for (j = 0;j < loadmodel->num_bones;j++) + { + float pose[12]; + matrix4x4_t posematrix; + for (k = 0;k < 12;k++) + pose[k] = BigFloat(frameposes[j*12+k]); + //if (j < loadmodel->num_bones) + // Con_Printf("%s: bone %i = %f %f %f %f : %f %f %f %f : %f %f %f %f : scale = %f\n", loadmodel->name, j, pose[0], pose[1], pose[2], pose[3], pose[4], pose[5], pose[6], pose[7], pose[8], pose[9], pose[10], pose[11], VectorLength(pose)); + // scale child bones to match the root scale + if (loadmodel->data_bones[j].parent >= 0) + { + pose[3] *= modelscale; + pose[7] *= modelscale; + pose[11] *= modelscale; + } + // normalize rotation matrix + VectorNormalize(pose + 0); + 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)); + } + } //zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct verts = (zymvertex_t *)Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length); @@ -1803,7 +1930,9 @@ void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12])); for (i = 0;i < loadmodel->num_bones;i++) { - const float *m = loadmodel->data_poses + i * 12; + float m[12]; + for (k = 0;k < 12;k++) + m[k] = BigFloat(poses[i*12+k]); if (loadmodel->data_bones[i].parent >= 0) R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i); else @@ -1903,6 +2032,9 @@ void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) Mod_MakeSortedSurfaces(loadmodel); // compute all the mesh information that was not loaded from the file + if (loadmodel->surfmesh.data_element3s) + for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++) + loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i]; Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__); Mod_BuildBaseBonePoses(); Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true); @@ -1915,7 +2047,7 @@ void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) { dpmheader_t *pheader; - dpmframe_t *frame; + dpmframe_t *frames; dpmbone_t *bone; dpmmesh_t *dpmmesh; unsigned char *pbase; @@ -1923,6 +2055,9 @@ void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) skinfile_t *skinfiles; unsigned char *data; float *bonepose; + float biggestorigin, tempvec[3], modelscale; + float f; + float *poses; pheader = (dpmheader_t *)buffer; pbase = (unsigned char *)buffer; @@ -1971,10 +2106,14 @@ void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) loadmodel->Draw = R_Q1BSP_Draw; loadmodel->DrawDepth = R_Q1BSP_DrawDepth; loadmodel->DrawDebug = R_Q1BSP_DrawDebug; + loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass; + loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap; + loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap; loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume; loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume; loadmodel->DrawLight = R_Q1BSP_DrawLight; loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox; + loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine; loadmodel->PointSuperContents = NULL; // model bbox @@ -2015,7 +2154,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(float[12]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t)); + data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + meshtriangles * sizeof(int[3]) + meshvertices * (sizeof(float[14]) + sizeof(int[4]) + sizeof(float[4])) + loadmodel->num_poses * loadmodel->num_bones * sizeof(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); @@ -2030,17 +2169,13 @@ void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]); loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]); loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]); - loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]); loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]); loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t); loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t); loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t); if (meshvertices <= 65536) - { loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]); - for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++) - loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i]; - } + loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]); for (i = 0;i < loadmodel->numskins;i++) { @@ -2062,21 +2197,55 @@ void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) } // load the frames - frame = (dpmframe_t *) (pbase + pheader->ofs_frames); + frames = (dpmframe_t *) (pbase + pheader->ofs_frames); + // figure out scale of model from root bone, for compatibility with old dpmodel versions + poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions)); + tempvec[0] = BigFloat(poses[0]); + tempvec[1] = BigFloat(poses[1]); + tempvec[2] = BigFloat(poses[2]); + modelscale = VectorLength(tempvec); + biggestorigin = 0; for (i = 0;i < loadmodel->numframes;i++) { - const float *poses; - memcpy(loadmodel->animscenes[i].name, frame->name, sizeof(frame->name)); + memcpy(loadmodel->animscenes[i].name, frames[i].name, sizeof(frames[i].name)); loadmodel->animscenes[i].firstframe = i; loadmodel->animscenes[i].framecount = 1; loadmodel->animscenes[i].loop = true; loadmodel->animscenes[i].framerate = 10; // load the bone poses for this frame - poses = (float *) (pbase + BigLong(frame->ofs_bonepositions)); + poses = (float *) (pbase + BigLong(frames[i].ofs_bonepositions)); for (j = 0;j < loadmodel->num_bones*12;j++) - loadmodel->data_poses[i * loadmodel->num_bones*12 + j] = BigFloat(poses[j]); + { + f = fabs(BigFloat(poses[j])); + biggestorigin = max(biggestorigin, f); + } // stuff not processed here: mins, maxs, yawradius, allradius - frame++; + } + loadmodel->num_posescale = biggestorigin / 32767.0f; + loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale; + for (i = 0;i < loadmodel->numframes;i++) + { + const float *frameposes = (float *) (pbase + BigLong(frames[i].ofs_bonepositions)); + for (j = 0;j < loadmodel->num_bones;j++) + { + float pose[12]; + matrix4x4_t posematrix; + for (k = 0;k < 12;k++) + pose[k] = BigFloat(frameposes[j*12+k]); + // scale child bones to match the root scale + if (loadmodel->data_bones[j].parent >= 0) + { + pose[3] *= modelscale; + pose[7] *= modelscale; + pose[11] *= modelscale; + } + // normalize rotation matrix + VectorNormalize(pose + 0); + 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)); + } } // load the meshes now @@ -2086,10 +2255,13 @@ void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) // reconstruct frame 0 matrices to allow reconstruction of the base mesh // (converting from weight-blending skeletal animation to // deformation-based skeletal animation) + poses = (float *) (pbase + BigLong(frames[0].ofs_bonepositions)); bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12])); for (i = 0;i < loadmodel->num_bones;i++) { - const float *m = loadmodel->data_poses + i * 12; + float m[12]; + for (k = 0;k < 12;k++) + m[k] = BigFloat(poses[i*12+k]); if (loadmodel->data_bones[i].parent >= 0) R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i); else @@ -2207,6 +2379,9 @@ void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) Mod_MakeSortedSurfaces(loadmodel); // compute all the mesh information that was not loaded from the file + if (loadmodel->surfmesh.data_element3s) + for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++) + loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i]; Mod_BuildBaseBonePoses(); Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, true); Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles); @@ -2236,6 +2411,7 @@ void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) skinfile_t *skinfiles; char animname[MAX_QPATH]; size_t size; + float biggestorigin; pchunk = (pskchunk_t *)buffer; if (strcmp(pchunk->id, "ACTRHEAD")) @@ -2250,10 +2426,14 @@ void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) loadmodel->Draw = R_Q1BSP_Draw; loadmodel->DrawDepth = R_Q1BSP_DrawDepth; loadmodel->DrawDebug = R_Q1BSP_DrawDebug; + loadmodel->DrawPrepass = R_Q1BSP_DrawPrepass; + loadmodel->CompileShadowMap = R_Q1BSP_CompileShadowMap; + loadmodel->DrawShadowMap = R_Q1BSP_DrawShadowMap; loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume; loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume; loadmodel->DrawLight = R_Q1BSP_DrawLight; loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox; + loadmodel->TraceLine = Mod_MDLMD2MD3_TraceLine; loadmodel->PointSuperContents = NULL; loadmodel->synctype = ST_RAND; @@ -2288,8 +2468,8 @@ void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) version = LittleLong(pchunk->version); recordsize = LittleLong(pchunk->recordsize); numrecords = LittleLong(pchunk->numrecords); - if (developer.integer >= 100) - Con_Printf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords); + if (developer_extra.integer) + Con_DPrintf("%s: %s %x: %i * %i = %i\n", loadmodel->name, pchunk->id, version, recordsize, numrecords, recordsize * numrecords); if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0) Con_Printf ("%s: chunk %s has unknown version %x (0x1e83b9, 0x1e9179, 0x2e, 0x12f2bc, 0x12f2f0 are currently supported), trying to load anyway!\n", loadmodel->name, pchunk->id, version); if (!strcmp(pchunk->id, "ACTRHEAD")) @@ -2459,8 +2639,8 @@ void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) version = LittleLong(pchunk->version); recordsize = LittleLong(pchunk->recordsize); numrecords = LittleLong(pchunk->numrecords); - if (developer.integer >= 100) - Con_Printf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords); + if (developer_extra.integer) + Con_DPrintf("%s: %s %x: %i * %i = %i\n", animname, pchunk->id, version, recordsize, numrecords, recordsize * numrecords); if (version != 0x1e83b9 && version != 0x1e9179 && version != 0x2e && version != 0x12f2bc && version != 0x12f2f0) Con_Printf ("%s: chunk %s has unknown version %x (0x1e83b9, 0x1e9179, 0x2e, 0x12f2bc, 0x12f2f0 are currently supported), trying to load anyway!\n", animname, pchunk->id, version); if (!strcmp(pchunk->id, "ANIMHEAD")) @@ -2605,7 +2785,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(float[12]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t) + ((loadmodel->surfmesh.num_vertices <= 65536) ? (loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3])) : 0); + 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); 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); @@ -2619,17 +2799,13 @@ void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]); loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += loadmodel->surfmesh.num_vertices * sizeof(int[4]); loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[4]); - loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(float[12]); loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]); loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t); loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t); loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t); if (loadmodel->surfmesh.num_vertices <= 65536) - { loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]); - for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++) - loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i]; - } + loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]); for (i = 0;i < loadmodel->numskins;i++) { @@ -2741,13 +2917,34 @@ void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) } } + // 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; - matrix4x4_t matrix; - Matrix4x4_FromOriginQuat(&matrix, k->origin[0], k->origin[1], k->origin[2], k->quat[0], k->quat[1], k->quat[2], k->quat[3]); - Matrix4x4_ToArray12FloatD3D(&matrix, loadmodel->data_poses + index*12); + 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; } Mod_FreeSkinFiles(skinfiles); Mem_Free(animfilebuffer); @@ -2755,6 +2952,9 @@ void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) // compute all the mesh information that was not loaded from the file // TODO: honor smoothing groups somehow? + if (loadmodel->surfmesh.data_element3s) + for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++) + loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i]; Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__); Mod_BuildBaseBonePoses(); Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, true); @@ -2764,430 +2964,3 @@ void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend) loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1; } - -void Mod_OBJ_Load(dp_model_t *mod, void *buffer, void *bufferend) -{ -#if 0 - const char *textbase = (char *)buffer, *text = textbase; - char *s; - char *argv[512]; - char line[1024]; - char materialname[MAX_QPATH]; - int j, index1, index2, index3, first, prev, index; - int argc; - int linelen; - int numtriangles = 0; - int maxtriangles = 32768; - int *element3i = Mem_Alloc(tempmempool, maxtriangles * sizeof(int[3])); - int *oldelement3i; - int numsurfaces = 0; - int maxsurfaces = 0; - msurface_t *surfaces = NULL; - int linenumber = 0; - int hashindex; - float *v, *vt, *vn; - float *oldv, *oldvt, *oldvn; - int maxv = 65536, numv = 1; - int maxvt = 65536, numvt = 1; - int maxvn = 65536, numvn = 1; - int maxverthash = 65536, numverthash = 0; - int numhashindex = 65536; - struct objverthash_s - { - struct objverthash_s *next; - int s; - int v; - int vt; - int vn; - } - *hash, **verthash = Mem_Alloc(tempmempool, numhashindex * sizeof(*verthash)), *verthashdata = Mem_Alloc(tempmempool, maxverthash * sizeof(*verthashdata)), *oldverthashdata; - skinfile_t *skinfiles; - - dpsnprintf(materialname, sizeof(materialname), "%s", loadmodel->name); - - skinfiles = Mod_LoadSkinFiles(); - - loadmodel->modeldatatypestring = "OBJ"; - - loadmodel->type = mod_alias; - loadmodel->AnimateVertices = NULL; - loadmodel->DrawSky = NULL; - loadmodel->DrawAddWaterPlanes = NULL; - loadmodel->Draw = R_Q1BSP_Draw; - loadmodel->DrawDepth = R_Q1BSP_DrawDepth; - loadmodel->DrawDebug = R_Q1BSP_DrawDebug; - loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume; - loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume; - loadmodel->DrawLight = R_Q1BSP_DrawLight; - loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox; - loadmodel->PointSuperContents = NULL; - - // parse the OBJ text now - for(;;) - { - if (!*text) - break; - linenumber++; - linelen = 0; - for (linelen = 0;text[linelen] && text[linelen] != '\r' && text[linelen] != '\n';linelen++) - line[linelen] = text[linelen]; - line[linelen] = 0; - for (argc = 0;argc < (int)(sizeof(argv)/sizeof(argv[0]));argc++) - argv[argc] = ""; - argc = 0; - s = line; - while (*s == ' ' || *s == '\t') - s++; - while (*s) - { - argv[argc++] = s; - while (*s > ' ') - s++; - if (!*s) - break; - *s++ = 0; - while (*s == ' ' || *s == '\t') - s++; - } - if (!argc) - continue; - if (argv[0][0] == '#') - continue; - if (!strcmp(argv[0], "v")) - { - if (maxv <= numv) - { - maxv *= 2; - oldv = v; - v = Mem_Alloc(tempmempool, maxv * sizeof(float[3])); - if (oldv) - { - memcpy(v, oldv, numv * sizeof(float[3])); - Mem_Free(oldv); - } - } - v[numv*3+0] = atof(argv[1]); - v[numv*3+1] = atof(argv[2]); - v[numv*3+2] = atof(argv[3]); - numv++; - } - else if (!strcmp(argv[0], "vt")) - { - if (maxvt <= numvt) - { - maxvt *= 2; - oldvt = vt; - vt = Mem_Alloc(tempmempool, maxvt * sizeof(float[2])); - if (oldvt) - { - memcpy(vt, oldvt, numvt * sizeof(float[2])); - Mem_Free(oldvt); - } - } - vt[numvt*2+0] = atof(argv[1]); - vt[numvt*2+1] = atof(argv[2]); - numvt++; - } - else if (!strcmp(argv[0], "vn")) - { - if (maxvn <= numvn) - { - maxvn *= 2; - oldvn = vn; - vn = Mem_Alloc(tempmempool, maxvn * sizeof(float[3])); - if (oldvn) - { - memcpy(vn, oldvn, numvn * sizeof(float[3])); - Mem_Free(oldvn); - } - } - vn[numvn*3+0] = atof(argv[1]); - vn[numvn*3+1] = atof(argv[2]); - vn[numvn*3+2] = atof(argv[3]); - numvn++; - } - else if (!strcmp(argv[0], "f")) - { - if (!surface) - { - if (maxsurfaces <= numsurfaces) - { - maxsurfaces++; - oldsurfaces = surfaces; - surfaces = Mem_Alloc(tempmempool, maxsurfaces * sizeof(*surfaces)); - if (oldsurfaces) - { - memcpy(surfaces, oldsurfaces, numsurfaces * sizeof(*surfaces)); - Mem_Free(oldsurfaces); - } - } - surface = surfaces + numsurfaces++; - surface-> - } - for (j = 1;j < argc;j++) - { - index1 = atoi(argv[j]); - while(argv[j][0] && argv[j][0] != '/') - argv[j]++; - if (argv[j][0]) - argv[j]++; - if (index1 < 0) - index1 = numv + 1 - index1; - index2 = atoi(argv[j]); - if (index2 < 0) - index2 = numvt + 1 - index2; - while(argv[j][0] && argv[j][0] != '/') - argv[j]++; - if (argv[j][0]) - argv[j]++; - index3 = atoi(argv[j]); - if (index3 < 0) - index3 = numvn + 1 - index3; - hashindex = (index1 + index2 * 3571 + index3 * 42589) & (numhashindex - 1); - for (hash = verthash[hashindex];hash;hash = hash->next) - if (hash->surface == numsurfaces-1 && hash->v == index1 && hash->vt == index2 && hash->vn == index3) - break; - if (!hash) - { - if (maxverthash <= numverthash) - { - maxverthash *= 2; - oldverthashdata = verthashdata; - verthashdata = Mem_Alloc(tempmempool, maxverthash * sizeof(*verthashdata)); - if (oldverthashdata) - { - memcpy(verthashdata, oldverthashdata, numverthash * sizeof(*verthashdata)); - Mem_Free(oldverthashdata); - } - } - hash = verthashdata + numverthash++; - hash->next = verthash[hashindex]; - hash->s = numsurfaces; - hash->v = index1; - hash->vt = index2; - hash->vn = index3; - verthash[hashindex] = hash; - } - index = (int)((size_t)(hash - verthashdata)); - if (j == 1) - first = index; - else if (j >= 3) - { - if (maxtriangles <= numtriangles) - { - maxtriangles *= 2; - oldelement3i = element3i; - element3i = Mem_Alloc(tempmempool, numtriangles * sizeof(int[3])); - if (oldelement3i) - { - memcpy(element3i, oldelement3i, numtriangles * sizeof(int[3])); - Mem_Free(oldelement3i); - } - } - element3i[numtriangles*3+0] = first; - element3i[numtriangles*3+1] = prev; - element3i[numtriangles*3+2] = index; - numtriangles++; - } - prev = index; - } - } - else if (!strcmp(argv[0], "o") || !strcmp(argv[0], "g")) - surface = NULL; - else if (!!strcmp(argv[0], "usemtl")) - { - surface = NULL; - strlcpy(materialname, argv[1], sizeof(materialname); - } - text += linelen; - if (*text == '\r') - text++; - if (*text == '\n') - text++; - } - - if (skinfiles) - Mod_FreeSkinFiles(skinfiles); - - // now that we have the OBJ data loaded as-is, we can convert it - loadmodel->numskins = LittleLong(pinmodel->num_skins); - numxyz = LittleLong(pinmodel->num_xyz); - numst = LittleLong(pinmodel->num_st); - loadmodel->surfmesh.num_triangles = LittleLong(pinmodel->num_tris); - loadmodel->numframes = LittleLong(pinmodel->num_frames); - loadmodel->surfmesh.num_morphframes = loadmodel->numframes; - loadmodel->num_poses = loadmodel->surfmesh.num_morphframes; - skinwidth = LittleLong(pinmodel->skinwidth); - skinheight = LittleLong(pinmodel->skinheight); - iskinwidth = 1.0f / skinwidth; - iskinheight = 1.0f / skinheight; - - loadmodel->num_surfaces = 1; - loadmodel->nummodelsurfaces = loadmodel->num_surfaces; - data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->numframes * sizeof(animscene_t) + loadmodel->numframes * sizeof(float[6]) + loadmodel->surfmesh.num_triangles * sizeof(int[3]) + loadmodel->surfmesh.num_triangles * sizeof(int[3])); - loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t); - loadmodel->sortedmodelsurfaces = (int *)data;data += loadmodel->num_surfaces * sizeof(int); - loadmodel->sortedmodelsurfaces[0] = 0; - loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t); - loadmodel->surfmesh.data_morphmd2framesize6f = (float *)data;data += loadmodel->numframes * sizeof(float[6]); - loadmodel->surfmesh.data_element3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]); - loadmodel->surfmesh.data_neighbor3i = (int *)data;data += loadmodel->surfmesh.num_triangles * sizeof(int[3]); - - loadmodel->synctype = ST_RAND; - - // load the skins - inskin = (char *)(base + LittleLong(pinmodel->ofs_skins)); - skinfiles = Mod_LoadSkinFiles(); - if (skinfiles) - { - loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins; - loadmodel->num_texturesperskin = loadmodel->num_surfaces; - loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t)); - Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", ""); - Mod_FreeSkinFiles(skinfiles); - } - else if (loadmodel->numskins) - { - // skins found (most likely not a player model) - loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins; - loadmodel->num_texturesperskin = loadmodel->num_surfaces; - loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t)); - for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME) - Mod_LoadTextureFromQ3Shader(loadmodel->data_textures + i * loadmodel->num_surfaces, inskin, true, true, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE | TEXF_PICMIP | TEXF_COMPRESS); - } - else - { - // no skins (most likely a player model) - loadmodel->numskins = 1; - loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins; - loadmodel->num_texturesperskin = loadmodel->num_surfaces; - loadmodel->data_textures = (texture_t *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t)); - Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL); - } - - loadmodel->skinscenes = (animscene_t *)Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins); - for (i = 0;i < loadmodel->numskins;i++) - { - loadmodel->skinscenes[i].firstframe = i; - loadmodel->skinscenes[i].framecount = 1; - loadmodel->skinscenes[i].loop = true; - loadmodel->skinscenes[i].framerate = 10; - } - - // load the triangles and stvert data - inst = (unsigned short *)(base + LittleLong(pinmodel->ofs_st)); - intri = (md2triangle_t *)(base + LittleLong(pinmodel->ofs_tris)); - md2verthash = (struct md2verthash_s **)Mem_Alloc(tempmempool, 65536 * sizeof(hash)); - md2verthashdata = (struct md2verthash_s *)Mem_Alloc(tempmempool, loadmodel->surfmesh.num_triangles * 3 * sizeof(*hash)); - // swap the triangle list - loadmodel->surfmesh.num_vertices = 0; - for (i = 0;i < loadmodel->surfmesh.num_triangles;i++) - { - for (j = 0;j < 3;j++) - { - xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]); - st = (unsigned short) LittleShort (intri[i].index_st[j]); - if (xyz >= numxyz) - { - Con_Printf("%s has an invalid xyz index (%i) on triangle %i, resetting to 0\n", loadmodel->name, xyz, i); - xyz = 0; - } - if (st >= numst) - { - Con_Printf("%s has an invalid st index (%i) on triangle %i, resetting to 0\n", loadmodel->name, st, i); - st = 0; - } - hashindex = (xyz * 256 + st) & 65535; - for (hash = md2verthash[hashindex];hash;hash = hash->next) - if (hash->xyz == xyz && hash->st == st) - break; - if (hash == NULL) - { - hash = md2verthashdata + loadmodel->surfmesh.num_vertices++; - hash->xyz = xyz; - hash->st = st; - hash->next = md2verthash[hashindex]; - md2verthash[hashindex] = hash; - } - loadmodel->surfmesh.data_element3i[i*3+j] = (hash - md2verthashdata); - } - } - - vertremap = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(int)); - data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(float[2]) + loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t)); - loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += loadmodel->surfmesh.num_vertices * sizeof(float[2]); - loadmodel->surfmesh.data_morphmdlvertex = (trivertx_t *)data;data += loadmodel->surfmesh.num_vertices * loadmodel->surfmesh.num_morphframes * sizeof(trivertx_t); - for (i = 0;i < loadmodel->surfmesh.num_vertices;i++) - { - int sts, stt; - hash = md2verthashdata + i; - vertremap[i] = hash->xyz; - sts = LittleShort(inst[hash->st*2+0]); - stt = LittleShort(inst[hash->st*2+1]); - if (sts < 0 || sts >= skinwidth || stt < 0 || stt >= skinheight) - { - Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, sts, stt, i); - sts = 0; - stt = 0; - } - loadmodel->surfmesh.data_texcoordtexture2f[i*2+0] = sts * iskinwidth; - loadmodel->surfmesh.data_texcoordtexture2f[i*2+1] = stt * iskinheight; - } - - Mem_Free(md2verthash); - Mem_Free(md2verthashdata); - - // generate ushort elements array if possible - if (loadmodel->surfmesh.num_vertices <= 65536) - { - loadmodel->surfmesh.data_element3s = (unsigned short *)Mem_Alloc(loadmodel->mempool, sizeof(unsigned short[3]) * loadmodel->surfmesh.num_triangles); - for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++) - loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i]; - } - - // load the frames - datapointer = (base + LittleLong(pinmodel->ofs_frames)); - for (i = 0;i < loadmodel->surfmesh.num_morphframes;i++) - { - int k; - trivertx_t *v; - trivertx_t *out; - pinframe = (md2frame_t *)datapointer; - datapointer += sizeof(md2frame_t); - // store the frame scale/translate into the appropriate array - for (j = 0;j < 3;j++) - { - loadmodel->surfmesh.data_morphmd2framesize6f[i*6+j] = LittleFloat(pinframe->scale[j]); - loadmodel->surfmesh.data_morphmd2framesize6f[i*6+3+j] = LittleFloat(pinframe->translate[j]); - } - // convert the vertices - v = (trivertx_t *)datapointer; - out = loadmodel->surfmesh.data_morphmdlvertex + i * loadmodel->surfmesh.num_vertices; - for (k = 0;k < loadmodel->surfmesh.num_vertices;k++) - out[k] = v[vertremap[k]]; - datapointer += numxyz * sizeof(trivertx_t); - - strlcpy(loadmodel->animscenes[i].name, pinframe->name, sizeof(loadmodel->animscenes[i].name)); - loadmodel->animscenes[i].firstframe = i; - loadmodel->animscenes[i].framecount = 1; - loadmodel->animscenes[i].framerate = 10; - loadmodel->animscenes[i].loop = true; - } - - Mem_Free(vertremap); - - Mod_MakeSortedSurfaces(loadmodel); - Mod_BuildTriangleNeighbors(loadmodel->surfmesh.data_neighbor3i, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles); - Mod_Alias_CalculateBoundingBox(); - Mod_Alias_MorphMesh_CompileFrames(); - - surface = loadmodel->data_surfaces; - surface->texture = loadmodel->data_textures; - surface->num_firsttriangle = 0; - surface->num_triangles = loadmodel->surfmesh.num_triangles; - surface->num_firstvertex = 0; - surface->num_vertices = loadmodel->surfmesh.num_vertices; - - loadmodel->surfmesh.isanimated = false; -#endif -}