]> git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - model_alias.c
we don't use DGA any more, so why -lxxf86dga
[xonotic/darkplaces.git] / model_alias.c
index 715bb6c69507cb9f099daf37b0a3720bccdf3456..f2b9897397048c873f171c44364e9e0a9ce4795c 100644 (file)
@@ -61,7 +61,7 @@ void *Mod_Skeletal_AnimateVertices_AllocBuffers(size_t nbytes)
        return Mod_Skeletal_AnimateVertices_bonepose;
 }
 
-void Mod_Skeletal_AnimateVertices(const dp_model_t * RESTRICT model, const frameblend_t * RESTRICT frameblend, const skeleton_t *skeleton, float * RESTRICT vertex3f, float * RESTRICT normal3f, float * RESTRICT svector3f, float * RESTRICT tvector3f)
+static void Mod_Skeletal_AnimateVertices(const dp_model_t * RESTRICT model, const frameblend_t * RESTRICT frameblend, const skeleton_t *skeleton, float * RESTRICT vertex3f, float * RESTRICT normal3f, float * RESTRICT svector3f, float * RESTRICT tvector3f)
 {
 
        if (!model->surfmesh.num_vertices)
@@ -113,7 +113,7 @@ void Mod_AliasInit (void)
 #endif
 }
 
-int Mod_Skeletal_AddBlend(dp_model_t *model, const blendweights_t *newweights)
+static int Mod_Skeletal_AddBlend(dp_model_t *model, const blendweights_t *newweights)
 {
        int i;
        blendweights_t *weights;
@@ -130,7 +130,7 @@ int Mod_Skeletal_AddBlend(dp_model_t *model, const blendweights_t *newweights)
        return model->num_bones + i;
 }
 
-int Mod_Skeletal_CompressBlend(dp_model_t *model, const int *newindex, const float *newinfluence)
+static int Mod_Skeletal_CompressBlend(dp_model_t *model, const int *newindex, const float *newinfluence)
 {
        int i, total;
        float scale;
@@ -173,7 +173,7 @@ int Mod_Skeletal_CompressBlend(dp_model_t *model, const int *newindex, const flo
        return Mod_Skeletal_AddBlend(model, &newweights);
 }
 
-void Mod_MD3_AnimateVertices(const dp_model_t * RESTRICT model, const frameblend_t * RESTRICT frameblend, const skeleton_t *skeleton, float * RESTRICT vertex3f, float * RESTRICT normal3f, float * RESTRICT svector3f, float * RESTRICT tvector3f)
+static void Mod_MD3_AnimateVertices(const dp_model_t * RESTRICT model, const frameblend_t * RESTRICT frameblend, const skeleton_t *skeleton, float * RESTRICT vertex3f, float * RESTRICT normal3f, float * RESTRICT svector3f, float * RESTRICT tvector3f)
 {
        // vertex morph
        int i, numblends, blendnum;
@@ -261,7 +261,7 @@ void Mod_MD3_AnimateVertices(const dp_model_t * RESTRICT model, const frameblend
                }
        }
 }
-void Mod_MDL_AnimateVertices(const dp_model_t * RESTRICT model, const frameblend_t * RESTRICT frameblend, const skeleton_t *skeleton, float * RESTRICT vertex3f, float * RESTRICT normal3f, float * RESTRICT svector3f, float * RESTRICT tvector3f)
+static void Mod_MDL_AnimateVertices(const dp_model_t * RESTRICT model, const frameblend_t * RESTRICT frameblend, const skeleton_t *skeleton, float * RESTRICT vertex3f, float * RESTRICT normal3f, float * RESTRICT svector3f, float * RESTRICT tvector3f)
 {
        // vertex morph
        int i, numblends, blendnum;
@@ -391,11 +391,11 @@ int Mod_Alias_GetTagMatrix(const dp_model_t *model, const frameblend_t *frameble
                for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
                {
                        lerp = frameblend[blendindex].lerp;
-                       Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
+                       Matrix4x4_FromBonePose7s(&bonematrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
                        parenttagindex = tagindex;
                        while ((parenttagindex = model->data_bones[parenttagindex].parent) >= 0)
                        {
-                               Matrix4x4_FromBonePose6s(&parentbonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + parenttagindex));
+                               Matrix4x4_FromBonePose7s(&parentbonematrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + parenttagindex));
                                tempbonematrix = bonematrix;
                                Matrix4x4_Concat(&bonematrix, &parentbonematrix, &tempbonematrix);
                        }
@@ -454,7 +454,7 @@ int Mod_Alias_GetExtendedTagInfoForIndex(const dp_model_t *model, unsigned int s
                for (blendindex = 0;blendindex < MAX_FRAMEBLENDS && frameblend[blendindex].lerp > 0;blendindex++)
                {
                        lerp = frameblend[blendindex].lerp;
-                       Matrix4x4_FromBonePose6s(&bonematrix, model->num_posescale, model->data_poses6s + 6 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
+                       Matrix4x4_FromBonePose7s(&bonematrix, model->num_posescale, model->data_poses7s + 7 * (frameblend[blendindex].subframe * model->num_bones + tagindex));
                        Matrix4x4_Accumulate(&blendmatrix, &bonematrix, lerp);
                }
                *tag_localmatrix = blendmatrix;
@@ -510,7 +510,7 @@ static void Mod_BuildBaseBonePoses(void)
        basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t));
        for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++)
        {
-               Matrix4x4_FromBonePose6s(&bonematrix, loadmodel->num_posescale, loadmodel->data_poses6s + 6 * boneindex);
+               Matrix4x4_FromBonePose7s(&bonematrix, loadmodel->num_posescale, loadmodel->data_poses7s + 7 * boneindex);
                if (loadmodel->data_bones[boneindex].parent >= 0)
                {
                        tempbonematrix = bonematrix;
@@ -643,19 +643,14 @@ static void Mod_MDLMD2MD3_TraceLine(dp_model_t *model, const frameblend_t *frame
        int i;
        float segmentmins[3], segmentmaxs[3];
        msurface_t *surface;
-       static int maxvertices = 0;
-       static float *vertex3f = NULL;
+       float vertex3fbuf[1024*3];
+       float *vertex3f = vertex3fbuf;
        memset(trace, 0, sizeof(*trace));
        trace->fraction = 1;
        trace->realfraction = 1;
        trace->hitsupercontentsmask = hitsupercontentsmask;
-       if (maxvertices < model->surfmesh.num_vertices)
-       {
-               if (vertex3f)
-                       Z_Free(vertex3f);
-               maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
-               vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
-       }
+       if (model->surfmesh.num_vertices > 1024)
+               vertex3f = (float *)Mem_Alloc(tempmempool, model->surfmesh.num_vertices * sizeof(float[3]));
        segmentmins[0] = min(start[0], end[0]) - 1;
        segmentmins[1] = min(start[1], end[1]) - 1;
        segmentmins[2] = min(start[2], end[2]) - 1;
@@ -665,17 +660,18 @@ static void Mod_MDLMD2MD3_TraceLine(dp_model_t *model, const frameblend_t *frame
        model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
        for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
                Collision_TraceLineTriangleMeshFloat(trace, start, end, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
+       if (vertex3f != vertex3fbuf)
+               Mem_Free(vertex3f);
 }
 
-static int maxvertices = 0;
-static float *vertex3f = NULL;
-
 static void Mod_MDLMD2MD3_TraceBox(dp_model_t *model, const frameblend_t *frameblend, const skeleton_t *skeleton, trace_t *trace, const vec3_t start, const vec3_t boxmins, const vec3_t boxmaxs, const vec3_t end, int hitsupercontentsmask)
 {
        int i;
        vec3_t shiftstart, shiftend;
        float segmentmins[3], segmentmaxs[3];
        msurface_t *surface;
+       float vertex3fbuf[1024*3];
+       float *vertex3f = vertex3fbuf;
        colboxbrushf_t thisbrush_start, thisbrush_end;
        vec3_t boxstartmins, boxstartmaxs, boxendmins, boxendmaxs;
 
@@ -693,13 +689,8 @@ static void Mod_MDLMD2MD3_TraceBox(dp_model_t *model, const frameblend_t *frameb
        trace->fraction = 1;
        trace->realfraction = 1;
        trace->hitsupercontentsmask = hitsupercontentsmask;
-       if (maxvertices < model->surfmesh.num_vertices)
-       {
-               if (vertex3f)
-                       Z_Free(vertex3f);
-               maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
-               vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
-       }
+       if (model->surfmesh.num_vertices > 1024)
+               vertex3f = (float *)Mem_Alloc(tempmempool, model->surfmesh.num_vertices * sizeof(float[3]));
        segmentmins[0] = min(start[0], end[0]) + boxmins[0] - 1;
        segmentmins[1] = min(start[1], end[1]) + boxmins[1] - 1;
        segmentmins[2] = min(start[2], end[2]) + boxmins[2] - 1;
@@ -712,16 +703,11 @@ static void Mod_MDLMD2MD3_TraceBox(dp_model_t *model, const frameblend_t *frameb
        VectorAdd(end, boxmaxs, boxendmaxs);
        Collision_BrushForBox(&thisbrush_start, boxstartmins, boxstartmaxs, 0, 0, NULL);
        Collision_BrushForBox(&thisbrush_end, boxendmins, boxendmaxs, 0, 0, NULL);
-       if (maxvertices < model->surfmesh.num_vertices)
-       {
-               if (vertex3f)
-                       Z_Free(vertex3f);
-               maxvertices = (model->surfmesh.num_vertices + 255) & ~255;
-               vertex3f = (float *)Z_Malloc(maxvertices * sizeof(float[3]));
-       }
        model->AnimateVertices(model, frameblend, skeleton, vertex3f, NULL, NULL, NULL);
        for (i = 0, surface = model->data_surfaces;i < model->num_surfaces;i++, surface++)
                Collision_TraceBrushTriangleMeshFloat(trace, &thisbrush_start.brush, &thisbrush_end.brush, model->surfmesh.num_triangles, model->surfmesh.data_element3i, vertex3f, 0, NULL, SUPERCONTENTS_SOLID | (surface->texture->basematerialflags & MATERIALFLAGMASK_TRANSLUCENT ? 0 : SUPERCONTENTS_OPAQUE), 0, surface->texture, segmentmins, segmentmaxs);
+       if (vertex3f != vertex3fbuf)
+               Mem_Free(vertex3f);
 }
 
 static void Mod_ConvertAliasVerts (int inverts, trivertx_t *v, trivertx_t *out, int *vertremap)
@@ -842,7 +828,7 @@ static void Mod_BuildAliasSkinFromSkinFrame(texture_t *texture, skinframe_t *ski
 void Mod_BuildAliasSkinsFromSkinFiles(texture_t *skin, skinfile_t *skinfile, const char *meshname, const char *shadername)
 {
        int i;
-       static char stripbuf[MAX_QPATH];
+       char stripbuf[MAX_QPATH];
        skinfileitem_t *skinfileitem;
        if(developer_extra.integer)
                Con_DPrintf("Looking up texture for %s (default: %s)\n", meshname, shadername);
@@ -908,6 +894,7 @@ void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
        float *vertst;
        int *vertonseam, *vertremap;
        skinfile_t *skinfiles;
+       char vabuf[1024];
 
        datapointer = (unsigned char *)buffer;
        pinmodel = (mdl_t *)datapointer;
@@ -1033,8 +1020,8 @@ void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
        for (i = 0;i < numverts;i++)
        {
                vertonseam[i] = LittleLong(pinstverts[i].onseam);
-               vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
-               vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
+               vertst[i*2+0] = LittleLong(pinstverts[i].s) * scales;
+               vertst[i*2+1] = LittleLong(pinstverts[i].t) * scalet;
                vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
                vertst[(i+numverts)*2+1] = vertst[i*2+1];
        }
@@ -1101,7 +1088,6 @@ void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
                loadmodel->surfmesh.data_neighbor3i = (int *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_triangles * sizeof(int[3]));
        }
        Mod_MDL_LoadFrames (startframes, numverts, vertremap);
-       loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || 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);
@@ -1187,7 +1173,7 @@ void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
                // check for skins that don't exist in the model, but do exist as external images
                // (this was added because yummyluv kept pestering me about support for it)
                // TODO: support shaders here?
-               while ((tempskinframe = R_SkinFrame_LoadExternal(va("%s_%i", loadmodel->name, loadmodel->numskins), (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS, false)))
+               while ((tempskinframe = R_SkinFrame_LoadExternal(va(vabuf, sizeof(vabuf), "%s_%i", loadmodel->name, loadmodel->numskins), (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PICMIP | TEXF_COMPRESS, false)))
                {
                        // expand the arrays to make room
                        tempskinscenes = loadmodel->skinscenes;
@@ -1226,7 +1212,7 @@ void Mod_IDP0_Load(dp_model_t *mod, void *buffer, void *bufferend)
        surface->num_firstvertex = 0;
        surface->num_vertices = loadmodel->surfmesh.num_vertices;
 
-       loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
+       loadmodel->surfmesh.isanimated = loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
        loadmodel->AnimateVertices = loadmodel->surfmesh.isanimated ? Mod_MDL_AnimateVertices : NULL;
 
        if (!loadmodel->surfmesh.isanimated)
@@ -1485,7 +1471,7 @@ void Mod_IDP2_Load(dp_model_t *mod, void *buffer, void *bufferend)
 
        Mem_Free(vertremap);
 
-       loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
+       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);
@@ -1685,7 +1671,7 @@ void Mod_IDP3_Load(dp_model_t *mod, void *buffer, void *bufferend)
        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->num_bones > 1 || loadmodel->numframes > 1 || (loadmodel->animscenes && loadmodel->animscenes[0].framecount > 1);
+       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);
@@ -1889,12 +1875,12 @@ void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
        meshvertices = pheader->numverts;
        meshtriangles = pheader->numtris;
 
-       loadmodel->surfmesh.isanimated = loadmodel->num_bones > 1 || loadmodel->numframes > 1 || loadmodel->animscenes[0].framecount > 1;
+       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]) + meshvertices * sizeof(unsigned short) + 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);
@@ -1917,7 +1903,7 @@ void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
        {
                loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
        }
-       loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
+       loadmodel->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
        loadmodel->surfmesh.data_blendweights = NULL;
 
        //zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
@@ -1958,7 +1944,7 @@ void Mod_ZYMOTICMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
                        VectorNormalize(pose + 4);
                        VectorNormalize(pose + 8);
                        Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
-                       Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
+                       Matrix4x4_ToBonePose7s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses7s + 7*(i*loadmodel->num_bones+j));
                }
        }
 
@@ -2210,10 +2196,10 @@ void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
        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[0].framecount > 1;
+       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)) + 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);
@@ -2239,7 +2225,7 @@ void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
        {
                loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
        }
-       loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
+       loadmodel->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
        loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
 
        for (i = 0;i < loadmodel->numskins;i++)
@@ -2309,7 +2295,7 @@ void Mod_DARKPLACESMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
                        VectorNormalize(pose + 4);
                        VectorNormalize(pose + 8);
                        Matrix4x4_FromArray12FloatD3D(&posematrix, pose);
-                       Matrix4x4_ToBonePose6s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses6s + 6*(i*loadmodel->num_bones+j));
+                       Matrix4x4_ToBonePose7s(&posematrix, loadmodel->num_poseinvscale, loadmodel->data_poses7s + 7*(i*loadmodel->num_bones+j));
                }
        }
 
@@ -2518,8 +2504,8 @@ void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
        strlcat(animname, ".psa", sizeof(animname));
        animbuffer = animfilebuffer = FS_LoadFile(animname, loadmodel->mempool, false, &filesize);
        animbufferend = (void *)((unsigned char*)animbuffer + (int)filesize);
-       if (animbuffer == NULL)
-               Host_Error("%s: can't find .psa file (%s)", loadmodel->name, animname);
+       if (!animbuffer)
+               animbufferend = animbuffer;
 
        numpnts = 0;
        pnts = NULL;
@@ -2837,15 +2823,19 @@ void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
                        Con_Printf("%s: unknown chunk ID \"%s\"\n", animname, pchunk->id);
        }
 
-       if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights || !numanims || !anims || !numanimkeys || !animkeys)
+       if (!numpnts || !pnts || !numvtxw || !vtxw || !numfaces || !faces || !nummatts || !matts || !numbones || !bones || !numrawweights || !rawweights)
                Host_Error("%s: missing required chunks", loadmodel->name);
 
-       loadmodel->numframes = 0;
-       for (index = 0;index < numanims;index++)
-               loadmodel->numframes += anims[index].numframes;
-
-       if (numanimkeys != numbones * loadmodel->numframes)
-               Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
+       if (numanims)
+       {
+               loadmodel->numframes = 0;
+               for (index = 0;index < numanims;index++)
+                       loadmodel->numframes += anims[index].numframes;
+               if (numanimkeys != numbones * loadmodel->numframes)
+                       Host_Error("%s: %s has incorrect number of animation keys", animname, pchunk->id);
+       }
+       else
+               loadmodel->numframes = loadmodel->num_poses = 1;
 
        meshvertices = numvtxw;
        meshtriangles = numfaces;
@@ -2861,10 +2851,10 @@ void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
        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[0].framecount > 1;
+       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 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);
@@ -2889,7 +2879,7 @@ void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
        {
                loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += loadmodel->surfmesh.num_triangles * sizeof(unsigned short[3]);
        }
-       loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
+       loadmodel->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
        loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, loadmodel->surfmesh.num_vertices * sizeof(blendweights_t));
 
        for (i = 0;i < loadmodel->numskins;i++)
@@ -2947,6 +2937,30 @@ void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
                        Host_Error("%s bone[%i].parent >= %i", loadmodel->name, index, index);
        }
 
+       // convert the basepose data
+       if (loadmodel->num_bones)
+       {
+               int boneindex;
+               matrix4x4_t *basebonepose;
+               float *outinvmatrix = loadmodel->data_baseboneposeinverse;
+               matrix4x4_t bonematrix;
+               matrix4x4_t tempbonematrix;
+               basebonepose = (matrix4x4_t *)Mem_Alloc(tempmempool, loadmodel->num_bones * sizeof(matrix4x4_t));
+               for (boneindex = 0;boneindex < loadmodel->num_bones;boneindex++)
+               {
+                       Matrix4x4_FromOriginQuat(&bonematrix, bones[boneindex].basepose.origin[0], bones[boneindex].basepose.origin[1], bones[boneindex].basepose.origin[2], bones[boneindex].basepose.quat[0], bones[boneindex].basepose.quat[1], bones[boneindex].basepose.quat[2], bones[boneindex].basepose.quat[3]);
+                       if (loadmodel->data_bones[boneindex].parent >= 0)
+                       {
+                               tempbonematrix = bonematrix;
+                               Matrix4x4_Concat(&bonematrix, basebonepose + loadmodel->data_bones[boneindex].parent, &tempbonematrix);
+                       }
+                       basebonepose[boneindex] = bonematrix;
+                       Matrix4x4_Invert_Simple(&tempbonematrix, basebonepose + boneindex);
+                       Matrix4x4_ToArray12FloatD3D(&tempbonematrix, outinvmatrix + 12*boneindex);
+               }
+               Mem_Free(basebonepose);
+       }
+
        // sort the psk point weights into the vertex weight tables
        // (which only accept up to 4 bones per vertex)
        for (index = 0;index < numvtxw;index++)
@@ -2985,49 +2999,93 @@ void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
                loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Realloc(loadmodel->mempool, loadmodel->surfmesh.data_blendweights, loadmodel->surfmesh.num_blends * sizeof(blendweights_t));
 
        // set up the animscenes based on the anims
-       for (index = 0, i = 0;index < numanims;index++)
+       if (numanims)
        {
-               for (j = 0;j < anims[index].numframes;j++, i++)
+               for (index = 0, i = 0;index < numanims;index++)
                {
-                       dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
-                       loadmodel->animscenes[i].firstframe = i;
-                       loadmodel->animscenes[i].framecount = 1;
-                       loadmodel->animscenes[i].loop = true;
-                       loadmodel->animscenes[i].framerate = anims[index].fps;
+                       for (j = 0;j < anims[index].numframes;j++, i++)
+                       {
+                               dpsnprintf(loadmodel->animscenes[i].name, sizeof(loadmodel->animscenes[i].name), "%s_%d", anims[index].name, j);
+                               loadmodel->animscenes[i].firstframe = i;
+                               loadmodel->animscenes[i].framecount = 1;
+                               loadmodel->animscenes[i].loop = true;
+                               loadmodel->animscenes[i].framerate = anims[index].fps;
+                       }
+               }
+               // calculate the scaling value for bone origins so they can be compressed to short
+               biggestorigin = 0;
+               for (index = 0;index < numanimkeys;index++)
+               {
+                       pskanimkeys_t *k = animkeys + index;
+                       biggestorigin = max(biggestorigin, fabs(k->origin[0]));
+                       biggestorigin = max(biggestorigin, fabs(k->origin[1]));
+                       biggestorigin = max(biggestorigin, fabs(k->origin[2]));
+               }
+               loadmodel->num_posescale = biggestorigin / 32767.0f;
+               loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
+       
+               // load the poses from the animkeys
+               for (index = 0;index < numanimkeys;index++)
+               {
+                       pskanimkeys_t *k = animkeys + index;
+                       float quat[4];
+                       Vector4Copy(k->quat, quat);
+                       if (quat[3] > 0)
+                               Vector4Negate(quat, quat);
+                       Vector4Normalize2(quat, quat);
+                       // compress poses to the short[7] format for longterm storage
+                       loadmodel->data_poses7s[index*7+0] = k->origin[0] * loadmodel->num_poseinvscale;
+                       loadmodel->data_poses7s[index*7+1] = k->origin[1] * loadmodel->num_poseinvscale;
+                       loadmodel->data_poses7s[index*7+2] = k->origin[2] * loadmodel->num_poseinvscale;
+                       loadmodel->data_poses7s[index*7+3] = quat[0] * 32767.0f;
+                       loadmodel->data_poses7s[index*7+4] = quat[1] * 32767.0f;
+                       loadmodel->data_poses7s[index*7+5] = quat[2] * 32767.0f;
+                       loadmodel->data_poses7s[index*7+6] = quat[3] * 32767.0f;
                }
        }
-
-       // calculate the scaling value for bone origins so they can be compressed to short
-       biggestorigin = 0;
-       for (index = 0;index < numanimkeys;index++)
+       else
        {
-               pskanimkeys_t *k = animkeys + index;
-               biggestorigin = max(biggestorigin, fabs(k->origin[0]));
-               biggestorigin = max(biggestorigin, fabs(k->origin[1]));
-               biggestorigin = max(biggestorigin, fabs(k->origin[2]));
-       }
-       loadmodel->num_posescale = biggestorigin / 32767.0f;
-       loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
+               strlcpy(loadmodel->animscenes[0].name, "base", sizeof(loadmodel->animscenes[0].name));
+               loadmodel->animscenes[0].firstframe = 0;
+               loadmodel->animscenes[0].framecount = 1;
+               loadmodel->animscenes[0].loop = true;
+               loadmodel->animscenes[0].framerate = 10;
 
-       // load the poses from the animkeys
-       for (index = 0;index < numanimkeys;index++)
-       {
-               pskanimkeys_t *k = animkeys + index;
-               float quat[4];
-               Vector4Copy(k->quat, quat);
-               if (quat[3] > 0)
-                       Vector4Negate(quat, quat);
-               Vector4Normalize2(quat, quat);
-               // compress poses to the short[6] format for longterm storage
-               loadmodel->data_poses6s[index*6+0] = k->origin[0] * loadmodel->num_poseinvscale;
-               loadmodel->data_poses6s[index*6+1] = k->origin[1] * loadmodel->num_poseinvscale;
-               loadmodel->data_poses6s[index*6+2] = k->origin[2] * loadmodel->num_poseinvscale;
-               loadmodel->data_poses6s[index*6+3] = quat[0] * 32767.0f;
-               loadmodel->data_poses6s[index*6+4] = quat[1] * 32767.0f;
-               loadmodel->data_poses6s[index*6+5] = quat[2] * 32767.0f;
+               // calculate the scaling value for bone origins so they can be compressed to short
+               biggestorigin = 0;
+               for (index = 0;index < numbones;index++)
+               {
+                       pskboneinfo_t *p = bones + index;
+                       biggestorigin = max(biggestorigin, fabs(p->basepose.origin[0]));
+                       biggestorigin = max(biggestorigin, fabs(p->basepose.origin[1]));
+                       biggestorigin = max(biggestorigin, fabs(p->basepose.origin[2]));
+               }
+               loadmodel->num_posescale = biggestorigin / 32767.0f;
+               loadmodel->num_poseinvscale = 1.0f / loadmodel->num_posescale;
+       
+               // load the basepose as a frame
+               for (index = 0;index < numbones;index++)
+               {
+                       pskboneinfo_t *p = bones + index;
+                       float quat[4];
+                       Vector4Copy(p->basepose.quat, quat);
+                       if (quat[3] > 0)
+                               Vector4Negate(quat, quat);
+                       Vector4Normalize2(quat, quat);
+                       // compress poses to the short[7] format for longterm storage
+                       loadmodel->data_poses7s[index*7+0] = p->basepose.origin[0] * loadmodel->num_poseinvscale;
+                       loadmodel->data_poses7s[index*7+1] = p->basepose.origin[1] * loadmodel->num_poseinvscale;
+                       loadmodel->data_poses7s[index*7+2] = p->basepose.origin[2] * loadmodel->num_poseinvscale;
+                       loadmodel->data_poses7s[index*7+3] = quat[0] * 32767.0f;
+                       loadmodel->data_poses7s[index*7+4] = quat[1] * 32767.0f;
+                       loadmodel->data_poses7s[index*7+5] = quat[2] * 32767.0f;
+                       loadmodel->data_poses7s[index*7+6] = quat[3] * 32767.0f;
+               }
        }
+
        Mod_FreeSkinFiles(skinfiles);
-       Mem_Free(animfilebuffer);
+       if (animfilebuffer)
+               Mem_Free(animfilebuffer);
        Mod_MakeSortedSurfaces(loadmodel);
 
        // compute all the mesh information that was not loaded from the file
@@ -3036,7 +3094,6 @@ void Mod_PSKMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
                for (i = 0;i < loadmodel->surfmesh.num_triangles*3;i++)
                        loadmodel->surfmesh.data_element3s[i] = loadmodel->surfmesh.data_element3i[i];
        Mod_ValidateElements(loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.num_triangles, 0, loadmodel->surfmesh.num_vertices, __FILE__, __LINE__);
-       Mod_BuildBaseBonePoses();
        Mod_BuildNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_normal3f, r_smoothnormals_areaweighting.integer != 0);
        Mod_BuildTextureVectorsFromNormals(0, loadmodel->surfmesh.num_vertices, loadmodel->surfmesh.num_triangles, loadmodel->surfmesh.data_vertex3f, loadmodel->surfmesh.data_texcoordtexture2f, loadmodel->surfmesh.data_normal3f, loadmodel->surfmesh.data_element3i, loadmodel->surfmesh.data_svector3f, loadmodel->surfmesh.data_tvector3f, r_smoothnormals_areaweighting.integer != 0);
        if (loadmodel->surfmesh.data_neighbor3i)
@@ -3281,7 +3338,7 @@ void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
        meshtriangles = header.num_triangles;
 
        // do most allocations as one merged chunk
-       data = (unsigned char *)Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t) + meshtriangles * sizeof(int[3]) + (meshvertices <= 65536 ? meshtriangles * sizeof(unsigned short[3]) : 0) + (r_enableshadowvolumes.integer ? meshtriangles * sizeof(int[3]) : 0) + meshvertices * (sizeof(float[14]) + (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) : 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);
@@ -3314,7 +3371,7 @@ void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
        {
                loadmodel->surfmesh.data_element3s = (unsigned short *)data;data += meshtriangles * sizeof(unsigned short[3]);
        }
-       loadmodel->data_poses6s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[6]);
+       loadmodel->data_poses7s = (short *)data;data += loadmodel->num_poses * loadmodel->num_bones * sizeof(short[7]);
        if (vblendindexes && vblendweights)
                loadmodel->surfmesh.data_blendweights = (blendweights_t *)Mem_Alloc(loadmodel->mempool, meshvertices * sizeof(blendweights_t));
 
@@ -3500,12 +3557,19 @@ void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
                {
                        for (j = 0;j < (int)header.num_poses;j++, k++)
                        {
-                               loadmodel->data_poses6s[k*6 + 0] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[0] + (pose1[j].channelmask&1 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[0] : 0));
-                               loadmodel->data_poses6s[k*6 + 1] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[1] + (pose1[j].channelmask&2 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[1] : 0));
-                               loadmodel->data_poses6s[k*6 + 2] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[2] + (pose1[j].channelmask&4 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[2] : 0));
-                               loadmodel->data_poses6s[k*6 + 3] = 32767.0f * (pose1[j].channeloffset[3] + (pose1[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[3] : 0));
-                               loadmodel->data_poses6s[k*6 + 4] = 32767.0f * (pose1[j].channeloffset[4] + (pose1[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[4] : 0));
-                               loadmodel->data_poses6s[k*6 + 5] = 32767.0f * (pose1[j].channeloffset[5] + (pose1[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[5] : 0));
+                               float qx, qy, qz, qw;
+                               loadmodel->data_poses7s[k*7 + 0] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[0] + (pose1[j].channelmask&1 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[0] : 0));
+                               loadmodel->data_poses7s[k*7 + 1] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[1] + (pose1[j].channelmask&2 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[1] : 0));
+                               loadmodel->data_poses7s[k*7 + 2] = loadmodel->num_poseinvscale * (pose1[j].channeloffset[2] + (pose1[j].channelmask&4 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[2] : 0));
+                               qx = pose1[j].channeloffset[3] + (pose1[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[3] : 0);
+                               qy = pose1[j].channeloffset[4] + (pose1[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[4] : 0);
+                               qz = pose1[j].channeloffset[5] + (pose1[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose1[j].channelscale[5] : 0);
+                               qw = 1.0f - (qx*qx + qy*qy + qz*qz);
+                               qw = qw > 0.0f ? -sqrt(qw) : 0.0f;
+                               loadmodel->data_poses7s[k*7 + 3] = 32767.0f * qx;
+                               loadmodel->data_poses7s[k*7 + 4] = 32767.0f * qy;
+                               loadmodel->data_poses7s[k*7 + 5] = 32767.0f * qz;
+                               loadmodel->data_poses7s[k*7 + 6] = 32767.0f * qw;
                                // skip scale data for now
                                if(pose1[j].channelmask&64) framedata++;
                                if(pose1[j].channelmask&128) framedata++;
@@ -3516,12 +3580,19 @@ void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
                {
                        for (i = 0;i < loadmodel->num_bones;i++)
                        {
-                               loadmodel->data_poses6s[i*6 + 0] = loadmodel->num_poseinvscale * joint1[i].origin[0];
-                               loadmodel->data_poses6s[i*6 + 1] = loadmodel->num_poseinvscale * joint1[i].origin[1];
-                               loadmodel->data_poses6s[i*6 + 2] = loadmodel->num_poseinvscale * joint1[i].origin[2];
-                               loadmodel->data_poses6s[i*6 + 3] = 32767.0f * joint1[i].rotation[0];
-                               loadmodel->data_poses6s[i*6 + 4] = 32767.0f * joint1[i].rotation[1];
-                               loadmodel->data_poses6s[i*6 + 5] = 32767.0f * joint1[i].rotation[2];
+                               float qx, qy, qz, qw;
+                               loadmodel->data_poses7s[i*7 + 0] = loadmodel->num_poseinvscale * joint1[i].origin[0];
+                               loadmodel->data_poses7s[i*7 + 1] = loadmodel->num_poseinvscale * joint1[i].origin[1];
+                               loadmodel->data_poses7s[i*7 + 2] = loadmodel->num_poseinvscale * joint1[i].origin[2];
+                               qx = joint1[i].rotation[0];
+                               qy = joint1[i].rotation[1];
+                               qz = joint1[i].rotation[2];
+                               qw = 1.0f - (qx*qx + qy*qy + qz*qz);
+                               qw = qw > 0.0f ? -sqrt(qw) : 0.0f;
+                               loadmodel->data_poses7s[i*7 + 3] = 32767.0f * qx;
+                               loadmodel->data_poses7s[i*7 + 4] = 32767.0f * qy;
+                               loadmodel->data_poses7s[i*7 + 5] = 32767.0f * qz;
+                               loadmodel->data_poses7s[i*7 + 6] = 32767.0f * qw;
                        }
                }
        }
@@ -3532,9 +3603,9 @@ void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
                        for (j = 0;j < (int)header.num_poses;j++, k++)
                        {
                                float rot[4];
-                               loadmodel->data_poses6s[k*6 + 0] = loadmodel->num_poseinvscale * (pose[j].channeloffset[0] + (pose[j].channelmask&1 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[0] : 0));
-                               loadmodel->data_poses6s[k*6 + 1] = loadmodel->num_poseinvscale * (pose[j].channeloffset[1] + (pose[j].channelmask&2 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[1] : 0));
-                               loadmodel->data_poses6s[k*6 + 2] = loadmodel->num_poseinvscale * (pose[j].channeloffset[2] + (pose[j].channelmask&4 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[2] : 0));
+                               loadmodel->data_poses7s[k*7 + 0] = loadmodel->num_poseinvscale * (pose[j].channeloffset[0] + (pose[j].channelmask&1 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[0] : 0));
+                               loadmodel->data_poses7s[k*7 + 1] = loadmodel->num_poseinvscale * (pose[j].channeloffset[1] + (pose[j].channelmask&2 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[1] : 0));
+                               loadmodel->data_poses7s[k*7 + 2] = loadmodel->num_poseinvscale * (pose[j].channeloffset[2] + (pose[j].channelmask&4 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[2] : 0));
                                rot[0] = pose[j].channeloffset[3] + (pose[j].channelmask&8 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[3] : 0);
                                rot[1] = pose[j].channeloffset[4] + (pose[j].channelmask&16 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[4] : 0);
                                rot[2] = pose[j].channeloffset[5] + (pose[j].channelmask&32 ? (unsigned short)LittleShort(*framedata++) * pose[j].channelscale[5] : 0);
@@ -3542,9 +3613,10 @@ void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
                                if (rot[3] > 0)
                                        Vector4Negate(rot, rot);
                                Vector4Normalize2(rot, rot);
-                               loadmodel->data_poses6s[k*6 + 3] = 32767.0f * rot[0];
-                               loadmodel->data_poses6s[k*6 + 4] = 32767.0f * rot[1];
-                               loadmodel->data_poses6s[k*6 + 5] = 32767.0f * rot[2];
+                               loadmodel->data_poses7s[k*7 + 3] = 32767.0f * rot[0];
+                               loadmodel->data_poses7s[k*7 + 4] = 32767.0f * rot[1];
+                               loadmodel->data_poses7s[k*7 + 5] = 32767.0f * rot[2];
+                               loadmodel->data_poses7s[k*7 + 6] = 32767.0f * rot[3];
                                // skip scale data for now
                                if(pose[j].channelmask&128) framedata++;
                                if(pose[j].channelmask&256) framedata++;
@@ -3555,12 +3627,13 @@ void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
                {
                        for (i = 0;i < loadmodel->num_bones;i++)
                        {
-                               loadmodel->data_poses6s[i*6 + 0] = loadmodel->num_poseinvscale * joint[i].origin[0];
-                               loadmodel->data_poses6s[i*6 + 1] = loadmodel->num_poseinvscale * joint[i].origin[1];
-                               loadmodel->data_poses6s[i*6 + 2] = loadmodel->num_poseinvscale * joint[i].origin[2];
-                               loadmodel->data_poses6s[i*6 + 3] = 32767.0f * joint[i].rotation[0];
-                               loadmodel->data_poses6s[i*6 + 4] = 32767.0f * joint[i].rotation[1];
-                               loadmodel->data_poses6s[i*6 + 5] = 32767.0f * joint[i].rotation[2];
+                               loadmodel->data_poses7s[i*7 + 0] = loadmodel->num_poseinvscale * joint[i].origin[0];
+                               loadmodel->data_poses7s[i*7 + 1] = loadmodel->num_poseinvscale * joint[i].origin[1];
+                               loadmodel->data_poses7s[i*7 + 2] = loadmodel->num_poseinvscale * joint[i].origin[2];
+                               loadmodel->data_poses7s[i*7 + 3] = 32767.0f * joint[i].rotation[0];
+                               loadmodel->data_poses7s[i*7 + 4] = 32767.0f * joint[i].rotation[1];
+                               loadmodel->data_poses7s[i*7 + 5] = 32767.0f * joint[i].rotation[2];
+                               loadmodel->data_poses7s[i*7 + 6] = 32767.0f * joint[i].rotation[3];
                        }
                }
        }
@@ -3730,10 +3803,10 @@ void Mod_INTERQUAKEMODEL_Load(dp_model_t *mod, void *buffer, void *bufferend)
                // this unaligned memory access is safe (all bytes)
                for (i = 0;i < (int)header.num_vertexes;i++)
                {
-                       outcolor[0] = vcolor4ub[0] * (1.0f / 128.0f);
-                       outcolor[1] = vcolor4ub[1] * (1.0f / 128.0f);
-                       outcolor[2] = vcolor4ub[2] * (1.0f / 128.0f);
-                       outcolor[3] = vcolor4ub[3] * (1.0f / 128.0f);
+                       outcolor[0] = vcolor4ub[0] * (1.0f / 255.0f);
+                       outcolor[1] = vcolor4ub[1] * (1.0f / 255.0f);
+                       outcolor[2] = vcolor4ub[2] * (1.0f / 255.0f);
+                       outcolor[3] = vcolor4ub[3] * (1.0f / 255.0f);
                        vcolor4ub += 4;
                        outcolor += 4;
                }