+ in = v + vertremap[i];
+ out3f[0] = in->v[0] * scale[0] + translate[0];
+ out3f[1] = in->v[1] * scale[1] + translate[1];
+ out3f[2] = in->v[2] * scale[2] + translate[2];
+ }
+}
+
+void Mod_IDP2_Load(model_t *mod, void *buffer)
+{
+ int i, j, k, hashindex, num, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end, numverts;
+ float *stverts, s, t, scale[3], translate[3];
+ qbyte *data;
+ msurface_t *surface;
+ md2_t *pinmodel;
+ qbyte *base, *datapointer;
+ md2frame_t *pinframe;
+ char *inskin;
+ md2triangle_t *intri;
+ unsigned short *inst;
+ struct md2verthash_s
+ {
+ struct md2verthash_s *next;
+ int xyz;
+ float st[2];
+ }
+ *hash, **md2verthash, *md2verthashdata;
+ skinframe_t tempskinframe;
+ skinfile_t *skinfiles;
+
+ pinmodel = buffer;
+ base = buffer;
+
+ version = LittleLong (pinmodel->version);
+ if (version != MD2ALIAS_VERSION)
+ Host_Error ("%s has wrong version number (%i should be %i)",
+ loadmodel->name, version, MD2ALIAS_VERSION);
+
+ loadmodel->type = mod_alias;
+ loadmodel->DrawSky = NULL;
+ loadmodel->Draw = R_Q1BSP_Draw;
+ loadmodel->DrawShadowVolume = R_Q1BSP_DrawShadowVolume;
+ loadmodel->DrawLight = R_Q1BSP_DrawLight;
+ loadmodel->TraceBox = Mod_MDLMD2MD3_TraceBox;
+
+ 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));
+ if (LittleLong(pinmodel->num_xyz) < 1 || LittleLong(pinmodel->num_xyz) > 65536)
+ Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
+ if (LittleLong(pinmodel->num_frames) < 1 || LittleLong(pinmodel->num_frames) > 65536)
+ Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
+ if (LittleLong(pinmodel->num_skins) < 0 || LittleLong(pinmodel->num_skins) > 256)
+ Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
+
+ end = LittleLong(pinmodel->ofs_end);
+ if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins) <= 0 || LittleLong(pinmodel->ofs_skins) >= end))
+ Host_Error ("%s is not a valid model", loadmodel->name);
+ if (LittleLong(pinmodel->ofs_st) <= 0 || LittleLong(pinmodel->ofs_st) >= end)
+ Host_Error ("%s is not a valid model", loadmodel->name);
+ if (LittleLong(pinmodel->ofs_tris) <= 0 || LittleLong(pinmodel->ofs_tris) >= end)
+ Host_Error ("%s is not a valid model", loadmodel->name);
+ if (LittleLong(pinmodel->ofs_frames) <= 0 || LittleLong(pinmodel->ofs_frames) >= end)
+ Host_Error ("%s is not a valid model", loadmodel->name);
+ if (LittleLong(pinmodel->ofs_glcmds) <= 0 || LittleLong(pinmodel->ofs_glcmds) >= end)
+ Host_Error ("%s is not a valid model", loadmodel->name);
+
+ loadmodel->num_surfaces = 1;
+ loadmodel->nummodelsurfaces = loadmodel->num_surfaces;
+ loadmodel->nummeshes = loadmodel->num_surfaces;
+ data = Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * sizeof(msurface_t) + loadmodel->num_surfaces * sizeof(int) + loadmodel->nummeshes * sizeof(surfmesh_t *) + loadmodel->nummeshes * sizeof(surfmesh_t));
+ loadmodel->data_surfaces = (void *)data;data += loadmodel->num_surfaces * sizeof(msurface_t);
+ loadmodel->surfacelist = (void *)data;data += loadmodel->num_surfaces * sizeof(int);
+ loadmodel->meshlist = (void *)data;data += loadmodel->num_surfaces * sizeof(surfmesh_t *);
+ for (i = 0;i < loadmodel->num_surfaces;i++)
+ {
+ loadmodel->surfacelist[i] = i;
+ loadmodel->meshlist[i] = (void *)data;data += sizeof(surfmesh_t);
+ }
+
+ loadmodel->numskins = LittleLong(pinmodel->num_skins);
+ numxyz = LittleLong(pinmodel->num_xyz);
+ numst = LittleLong(pinmodel->num_st);
+ loadmodel->meshlist[0]->num_triangles = LittleLong(pinmodel->num_tris);
+ loadmodel->numframes = LittleLong(pinmodel->num_frames);
+ loadmodel->meshlist[0]->num_morphframes = loadmodel->numframes;
+ loadmodel->animscenes = Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
+
+ loadmodel->flags = 0; // there are no MD2 flags
+ loadmodel->synctype = ST_RAND;
+
+ // load the skins
+ inskin = (void*)(base + LittleLong(pinmodel->ofs_skins));
+ skinfiles = Mod_LoadSkinFiles();
+ if (skinfiles)
+ {
+ loadmodel->num_textures = loadmodel->num_surfaces;
+ loadmodel->data_textures = Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
+ Mod_BuildAliasSkinsFromSkinFiles(loadmodel->data_textures, skinfiles, "default", "");
+ Mod_FreeSkinFiles(skinfiles);
+ }
+ else if (loadmodel->numskins)
+ {
+ // skins found (most likely not a player model)
+ loadmodel->num_textures = loadmodel->num_surfaces;
+ loadmodel->data_textures = Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
+ for (i = 0;i < loadmodel->numskins;i++, inskin += MD2_SKINNAME)
+ {
+ if (Mod_LoadSkinFrame(&tempskinframe, inskin, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_CLAMP | TEXF_PRECACHE | TEXF_PICMIP, true, false, true))
+ Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i * loadmodel->num_surfaces, &tempskinframe);
+ else
+ {
+ Con_Printf("%s is missing skin \"%s\"\n", loadmodel->name, inskin);
+ Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures + i * loadmodel->num_surfaces, NULL);
+ }
+ }
+ }
+ else
+ {
+ // no skins (most likely a player model)
+ loadmodel->numskins = 1;
+ loadmodel->num_textures = loadmodel->num_surfaces;
+ loadmodel->data_textures = Mem_Alloc(loadmodel->mempool, loadmodel->num_surfaces * loadmodel->numskins * sizeof(texture_t));
+ Mod_BuildAliasSkinFromSkinFrame(loadmodel->data_textures, NULL);
+ }
+
+ loadmodel->skinscenes = Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins);
+ for (i = 0;i < loadmodel->numskins;i++)
+ {
+ loadmodel->skinscenes[i].firstframe = i;
+ loadmodel->skinscenes[i].framecount = 1;
+ loadmodel->skinscenes[i].loop = true;
+ loadmodel->skinscenes[i].framerate = 10;
+ }
+
+ // load the triangles and stvert data
+ inst = (void*)(base + LittleLong(pinmodel->ofs_st));
+ intri = (void*)(base + LittleLong(pinmodel->ofs_tris));
+ skinwidth = LittleLong(pinmodel->skinwidth);
+ skinheight = LittleLong(pinmodel->skinheight);
+
+ stverts = Mem_Alloc(tempmempool, numst * sizeof(float[2]));
+ s = 1.0f / skinwidth;
+ t = 1.0f / skinheight;
+ for (i = 0;i < numst;i++)
+ {
+ j = (unsigned short) LittleShort(inst[i*2+0]);
+ k = (unsigned short) LittleShort(inst[i*2+1]);
+ if (j >= skinwidth || k >= skinheight)
+ {
+ Con_Printf("%s has an invalid skin coordinate (%i %i) on vert %i, changing to 0 0\n", loadmodel->name, j, k, i);
+ j = 0;
+ k = 0;
+ }
+ stverts[i*2+0] = j * s;
+ stverts[i*2+1] = k * t;
+ }
+
+ md2verthash = Mem_Alloc(tempmempool, 256 * sizeof(hash));
+ md2verthashdata = Mem_Alloc(tempmempool, loadmodel->meshlist[0]->num_triangles * 3 * sizeof(*hash));
+ // swap the triangle list
+ num = 0;
+ loadmodel->meshlist[0]->data_element3i = Mem_Alloc(loadmodel->mempool, loadmodel->meshlist[0]->num_triangles * sizeof(int[3]));
+ for (i = 0;i < loadmodel->meshlist[0]->num_triangles;i++)