+ Con_Printf("%s has no geometry\n", loadmodel->name);
+ return;
+ }
+ if (pheader->num_frames < 1)
+ {
+ Con_Printf("%s has no frames\n", loadmodel->name);
+ return;
+ }
+
+ loadmodel->DrawSky = NULL;
+ loadmodel->Draw = R_Q1BSP_Draw;
+ loadmodel->CompileShadowVolume = R_Q1BSP_CompileShadowVolume;
+ loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
+ loadmodel->DrawLight = R_Q1BSP_DrawLight;
+ loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
+
+ // model bbox
+ for (i = 0;i < 3;i++)
+ {
+ loadmodel->normalmins[i] = pheader->mins[i];
+ loadmodel->normalmaxs[i] = pheader->maxs[i];
+ loadmodel->yawmins[i] = i != 2 ? -pheader->yawradius : pheader->mins[i];
+ loadmodel->yawmaxs[i] = i != 2 ? pheader->yawradius : pheader->maxs[i];
+ loadmodel->rotatedmins[i] = -pheader->allradius;
+ loadmodel->rotatedmaxs[i] = pheader->allradius;
+ }
+ loadmodel->radius = pheader->allradius;
+ loadmodel->radius2 = pheader->allradius * pheader->allradius;
+
+ // load external .skin files if present
+ skinfiles = Mod_LoadSkinFiles();
+ if (loadmodel->numskins < 1)
+ loadmodel->numskins = 1;
+
+ meshvertices = 0;
+ meshtriangles = 0;
+
+ // gather combined statistics from the meshes
+ dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
+ for (i = 0;i < (int)pheader->num_meshs;i++)
+ {
+ int numverts = BigLong(dpmmesh->num_verts);
+ meshvertices += numverts;;
+ meshtriangles += BigLong(dpmmesh->num_tris);
+ dpmmesh++;
+ }
+
+ loadmodel->numframes = pheader->num_frames;
+ loadmodel->num_bones = pheader->num_bones;
+ loadmodel->num_poses = loadmodel->num_bones * loadmodel->numframes;
+ loadmodel->num_textures = loadmodel->nummodelsurfaces = loadmodel->num_surfaces = pheader->num_meshs;
+ // 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]) + meshtriangles * sizeof(int[3]) + meshvertices * (sizeof(float[14]) + sizeof(int[4]) + sizeof(float[4])) + loadmodel->num_poses * sizeof(float[12]) + loadmodel->num_bones * sizeof(float[12]) + loadmodel->numskins * sizeof(animscene_t) + loadmodel->num_bones * sizeof(aliasbone_t) + loadmodel->numframes * sizeof(animscene_t));
+ loadmodel->data_surfaces = (msurface_t *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
+ loadmodel->surfacelist = (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.num_vertices = meshvertices;
+ loadmodel->surfmesh.num_triangles = meshtriangles;
+ loadmodel->surfmesh.data_element3i = (int *)data;data += meshtriangles * sizeof(int[3]);
+ loadmodel->surfmesh.data_neighbor3i = (int *)data;data += meshtriangles * sizeof(int[3]);
+ loadmodel->surfmesh.data_vertex3f = (float *)data;data += meshvertices * sizeof(float[3]);
+ loadmodel->surfmesh.data_svector3f = (float *)data;data += meshvertices * sizeof(float[3]);
+ loadmodel->surfmesh.data_tvector3f = (float *)data;data += meshvertices * sizeof(float[3]);
+ loadmodel->surfmesh.data_normal3f = (float *)data;data += meshvertices * sizeof(float[3]);
+ loadmodel->surfmesh.data_texcoordtexture2f = (float *)data;data += meshvertices * sizeof(float[2]);
+ loadmodel->surfmesh.data_vertexweightindex4i = (int *)data;data += meshvertices * sizeof(int[4]);
+ loadmodel->surfmesh.data_vertexweightinfluence4f = (float *)data;data += meshvertices * sizeof(float[4]);
+ loadmodel->data_poses = (float *)data;data += loadmodel->num_poses * sizeof(float[12]);
+ loadmodel->data_baseboneposeinverse = (float *)data;data += loadmodel->num_bones * sizeof(float[12]);
+ loadmodel->skinscenes = (animscene_t *)data;data += loadmodel->numskins * sizeof(animscene_t);
+ loadmodel->data_bones = (aliasbone_t *)data;data += loadmodel->num_bones * sizeof(aliasbone_t);
+ loadmodel->animscenes = (animscene_t *)data;data += loadmodel->numframes * sizeof(animscene_t);
+
+ for (i = 0;i < loadmodel->numskins;i++)
+ {
+ loadmodel->skinscenes[i].firstframe = i;
+ loadmodel->skinscenes[i].framecount = 1;
+ loadmodel->skinscenes[i].loop = true;
+ loadmodel->skinscenes[i].framerate = 10;
+ }
+
+ // load the bone info
+ bone = (dpmbone_t *) (pbase + pheader->ofs_bones);
+ for (i = 0;i < loadmodel->num_bones;i++)
+ {
+ memcpy(loadmodel->data_bones[i].name, bone[i].name, sizeof(bone[i].name));
+ loadmodel->data_bones[i].flags = BigLong(bone[i].flags);
+ loadmodel->data_bones[i].parent = BigLong(bone[i].parent);
+ if (loadmodel->data_bones[i].parent >= i)
+ Host_Error("%s bone[%i].parent >= %i", loadmodel->name, i, i);
+ }
+
+ // load the frames
+ frame = (dpmframe_t *) (pbase + pheader->ofs_frames);
+ for (i = 0;i < loadmodel->numframes;i++)
+ {
+ const float *poses;
+ memcpy(loadmodel->animscenes[i].name, frame->name, sizeof(frame->name));
+ loadmodel->animscenes[i].firstframe = i;
+ loadmodel->animscenes[i].framecount = 1;
+ loadmodel->animscenes[i].loop = true;
+ loadmodel->animscenes[i].framerate = 10;
+ // load the bone poses for this frame
+ poses = (float *) (pbase + BigLong(frame->ofs_bonepositions));
+ for (j = 0;j < loadmodel->num_bones*12;j++)
+ loadmodel->data_poses[i * loadmodel->num_bones*12 + j] = BigFloat(poses[j]);
+ // stuff not processed here: mins, maxs, yawradius, allradius
+ frame++;
+ }
+
+ // load the meshes now
+ dpmmesh = (dpmmesh_t *) (pbase + pheader->ofs_meshs);
+ meshvertices = 0;
+ meshtriangles = 0;
+ // reconstruct frame 0 matrices to allow reconstruction of the base mesh
+ // (converting from weight-blending skeletal animation to
+ // deformation-based skeletal animation)
+ bonepose = (float *)Z_Malloc(loadmodel->num_bones * sizeof(float[12]));
+ for (i = 0;i < loadmodel->num_bones;i++)
+ {
+ const float *m = loadmodel->data_poses + i * 12;
+ if (loadmodel->data_bones[i].parent >= 0)
+ R_ConcatTransforms(bonepose + 12 * loadmodel->data_bones[i].parent, m, bonepose + 12 * i);
+ else
+ for (k = 0;k < 12;k++)
+ bonepose[12*i+k] = m[k];
+ }
+ for (i = 0;i < loadmodel->num_surfaces;i++, dpmmesh++)
+ {
+ const int *inelements;
+ int *outelements;
+ const float *intexcoord;
+ msurface_t *surface;
+
+ loadmodel->surfacelist[i] = i;
+ surface = loadmodel->data_surfaces + i;
+ surface->texture = loadmodel->data_textures + i;
+ surface->num_firsttriangle = meshtriangles;
+ surface->num_triangles = BigLong(dpmmesh->num_tris);
+ surface->num_firstvertex = meshvertices;
+ surface->num_vertices = BigLong(dpmmesh->num_verts);
+ meshvertices += surface->num_vertices;
+ meshtriangles += surface->num_triangles;
+
+ inelements = (int *) (pbase + BigLong(dpmmesh->ofs_indices));
+ outelements = loadmodel->surfmesh.data_element3i + surface->num_firsttriangle * 3;
+ for (j = 0;j < surface->num_triangles;j++)