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];
return Mod_Skeletal_AnimateVertices_bonepose;
}
+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)
{
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
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);
}
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;
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;
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;
+ qboolean isanimated = false;
VectorClear(loadmodel->normalmins);
VectorClear(loadmodel->normalmaxs);
yawradius = 0;
radius = 0;
if (loadmodel->AnimateVertices)
{
- float *vertex3f;
+ 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]));
+ 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)
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)
}
}
-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)
+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 skipsupercontentsmask, int skipmaterialflagsmask)
{
int i;
float segmentmins[3], segmentmaxs[3];
msurface_t *surface;
- float vertex3fbuf[1024*3];
+ float vertex3fbuf[1024 * 3];
float *vertex3f = vertex3fbuf;
+ float *freevertex3f = NULL;
+ // for static cases we can just call CollisionBIH which is much faster
+ if ((frameblend == NULL || (frameblend[0].subframe == 0 && frameblend[1].lerp == 0)) && (skeleton == NULL || skeleton->relativetransforms == NULL))
+ {
+ Mod_CollisionBIH_TraceLine(model, frameblend, skeleton, trace, start, end, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
+ return;
+ }
memset(trace, 0, sizeof(*trace));
trace->fraction = 1;
- trace->realfraction = 1;
trace->hitsupercontentsmask = hitsupercontentsmask;
- if (model->surfmesh.num_vertices > 1024)
- vertex3f = Mem_Alloc(tempmempool, model->surfmesh.num_vertices * sizeof(float[3]));
+ trace->skipsupercontentsmask = skipsupercontentsmask;
+ trace->skipmaterialflagsmask = skipmaterialflagsmask;
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);
+ if (frameblend == NULL || frameblend[0].subframe != 0 || frameblend[0].lerp != 0 || skeleton != NULL)
+ {
+ if (model->surfmesh.num_vertices > 1024)
+ vertex3f = freevertex3f = (float *)Mem_Alloc(tempmempool, model->surfmesh.num_vertices * sizeof(float[3]));
+ model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
+ }
+ else
+ vertex3f = model->surfmesh.data_vertex3f;
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);
+ if (freevertex3f)
+ Mem_Free(freevertex3f);
}
-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)
+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 skipsupercontentsmask, int skipmaterialflagsmask)
{
int i;
vec3_t shiftstart, shiftend;
{
VectorAdd(start, boxmins, shiftstart);
VectorAdd(end, boxmins, shiftend);
- Mod_MDLMD2MD3_TraceLine(model, frameblend, skeleton, trace, shiftstart, shiftend, hitsupercontentsmask);
+ Mod_MDLMD2MD3_TraceLine(model, frameblend, skeleton, trace, shiftstart, shiftend, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
VectorSubtract(trace->endpos, boxmins, trace->endpos);
return;
}
+ // for static cases we can just call CollisionBIH which is much faster
+ if ((frameblend == NULL || (frameblend[0].subframe == 0 && frameblend[1].lerp == 0)) && (skeleton == NULL || skeleton->relativetransforms == NULL))
+ {
+ Mod_CollisionBIH_TraceBox(model, frameblend, skeleton, trace, start, boxmins, boxmaxs, end, hitsupercontentsmask, skipsupercontentsmask, skipmaterialflagsmask);
+ return;
+ }
+
// box trace, performed as brush trace
memset(trace, 0, sizeof(*trace));
trace->fraction = 1;
- trace->realfraction = 1;
trace->hitsupercontentsmask = hitsupercontentsmask;
+ trace->skipsupercontentsmask = skipsupercontentsmask;
+ trace->skipmaterialflagsmask = skipmaterialflagsmask;
if (model->surfmesh.num_vertices > 1024)
- vertex3f = Mem_Alloc(tempmempool, model->surfmesh.num_vertices * sizeof(float[3]));
+ 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;
// 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;
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;
//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;
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)
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;
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];
}
loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
}
Mod_MDL_LoadFrames (startframes, numverts, vertremap);
- loadmodel->AnimateVertices = Mod_MDL_AnimateVertices; // needed during loading, may be cleared by code later in this function
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();
- loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_MDL_AnimateVertices : NULL;
Mem_Free(vertst);
Mem_Free(vertremap);
loadmodel->skinscenes[loadmodel->numskins].loop = true;
//increase skin counts
+ loadmodel->num_textures++;
loadmodel->numskins++;
totalskins++;
surface->num_firstvertex = 0;
surface->num_vertices = loadmodel->surfmesh.num_vertices;
- loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
- loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_MDL_AnimateVertices : NULL;
+ if(mod_alias_force_animated.string[0])
+ loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
+ // Always make a BIH for the first frame, we can use it where possible.
+ Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
if (!loadmodel->surfmesh.isanimated)
{
- Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
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));
Mem_Free(vertremap);
- loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
- loadmodel->AnimateVertices = Mod_MDL_AnimateVertices; // needed during loading, may be cleared by code later in this function
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();
- loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_MDL_AnimateVertices : NULL;
+ 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;
surface->num_firstvertex = 0;
surface->num_vertices = loadmodel->surfmesh.num_vertices;
+ // Always make a BIH for the first frame, we can use it where possible.
+ Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
if (!loadmodel->surfmesh.isanimated)
{
- Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
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);
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];
- loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
- loadmodel->AnimateVertices = Mod_MD3_AnimateVertices; // needed during loading, may be cleared by code later in this function
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->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_MD3_AnimateVertices : NULL;
+ if(mod_alias_force_animated.string[0])
+ loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
+ // Always make a BIH for the first frame, we can use it where possible.
+ Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
if (!loadmodel->surfmesh.isanimated)
{
- Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
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;
}
// model bbox
+ // LordHavoc: actually we blow this away later with Mod_Alias_CalculateBoundingBox()
modelradius = pheader->radius;
for (i = 0;i < 3;i++)
{
meshvertices = pheader->numverts;
meshtriangles = pheader->numtris;
- loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
- loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
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);
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);
{
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
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));
}
}
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
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 = Mod_Alias_CalculateBoundingBox();
+ if(mod_alias_force_animated.string[0])
+ loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
+ // Always make a BIH for the first frame, we can use it where possible.
+ Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
if (!loadmodel->surfmesh.isanimated)
{
- Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
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];
loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
loadmodel->num_texturesperskin = loadmodel->num_surfaces;
- loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
- loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
// 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);
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);
{
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++)
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));
}
}
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
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 = Mod_Alias_CalculateBoundingBox();
+ if(mod_alias_force_animated.string[0])
+ loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
+ // Always make a BIH for the first frame, we can use it where possible.
+ Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
if (!loadmodel->surfmesh.isanimated)
{
- Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
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));
loadmodel->num_texturesperskin = loadmodel->num_surfaces;
loadmodel->surfmesh.num_vertices = meshvertices;
loadmodel->surfmesh.num_triangles = meshtriangles;
- loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
- loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
// 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);
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);
{
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++)
}
}
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));
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;
+ // 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;
}
}
else
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] = p->basepose.origin[0] * loadmodel->num_poseinvscale;
- loadmodel->data_poses6s[index*6+1] = p->basepose.origin[1] * loadmodel->num_poseinvscale;
- loadmodel->data_poses6s[index*6+2] = p->basepose.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;
+ // 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_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 = Mod_Alias_CalculateBoundingBox();
+ if(mod_alias_force_animated.string[0])
+ loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
+ // Always make a BIH for the first frame, we can use it where possible.
+ Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
if (!loadmodel->surfmesh.isanimated)
{
- Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;
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();
loadmodel->nummodelsurfaces = loadmodel->num_surfaces = header.num_meshes;
loadmodel->num_textures = loadmodel->num_surfaces * loadmodel->numskins;
loadmodel->num_texturesperskin = loadmodel->num_surfaces;
- loadmodel->AnimateVertices = Mod_Skeletal_AnimateVertices; // updated later
meshvertices = header.num_vertexes;
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]) + (vcolor4f || vcolor4ub ? sizeof(float[4]) : 0)) + (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);
{
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);
{
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));
}
loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
- loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_Skeletal_AnimateVertices : NULL;
+ if(mod_alias_force_animated.string[0])
+ loadmodel->surfmesh.isanimated = mod_alias_force_animated.integer != 0;
biggestorigin = 0;
if (header.version == 1)
{
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++;
{
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;
}
}
}
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);
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++;
{
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];
}
}
}
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 (!header.ofs_bounds)
Mod_Alias_CalculateBoundingBox();
- if (!loadmodel->surfmesh.isanimated && loadmodel->surfmesh.num_triangles >= 1)
+ // Always make a BIH for the first frame, we can use it where possible.
+ Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
+ if (!loadmodel->surfmesh.isanimated)
{
- Mod_MakeCollisionBIH(loadmodel, true, &loadmodel->collision_bih);
loadmodel->TraceBox = Mod_CollisionBIH_TraceBox;
loadmodel->TraceBrush = Mod_CollisionBIH_TraceBrush;
loadmodel->TraceLine = Mod_CollisionBIH_TraceLine;