+ {
+ int i, numposes;
+ zymscene_t *scene;
+ // zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
+ loadmodel->animscenes = Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
+ scene = (void *) (pheader->lump_scenes.start + pbase);
+ numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
+ for (i = 0;i < pheader->numscenes;i++)
+ {
+ memcpy(loadmodel->animscenes[i].name, scene->name, 32);
+ loadmodel->animscenes[i].firstframe = BigLong(scene->start);
+ loadmodel->animscenes[i].framecount = BigLong(scene->length);
+ loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
+ loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
+ if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
+ Host_Error("Mod_LoadZymoticModel: scene firstframe (%i) >= numposes (%i)\n", loadmodel->animscenes[i].firstframe, numposes);
+ if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
+ Host_Error("Mod_LoadZymoticModel: scene firstframe (%i) + framecount (%i) >= numposes (%i)\n", loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
+ if (loadmodel->animscenes[i].framerate < 0)
+ Host_Error("Mod_LoadZymoticModel: scene framerate (%f) < 0\n", loadmodel->animscenes[i].framerate);
+ scene++;
+ }
+ }
+
+ {
+ int i;
+ float *poses;
+ // zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
+ loadmodel->zymdata_poses = Mem_Alloc(loadmodel->mempool, pheader->lump_poses.length);
+ poses = (void *) (pheader->lump_poses.start + pbase);
+ for (i = 0;i < pheader->lump_poses.length / 4;i++)
+ loadmodel->zymdata_poses[i] = BigFloat(poses[i]);
+ }
+
+ {
+ int i;
+ zymbone_t *bone;
+ // zymlump_t lump_bones; // zymbone_t bone[numbones];
+ loadmodel->zymdata_bones = Mem_Alloc(loadmodel->mempool, pheader->numbones * sizeof(zymbone_t));
+ bone = (void *) (pheader->lump_bones.start + pbase);
+ for (i = 0;i < pheader->numbones;i++)
+ {
+ memcpy(loadmodel->zymdata_bones[i].name, bone[i].name, sizeof(bone[i].name));
+ loadmodel->zymdata_bones[i].flags = BigLong(bone[i].flags);
+ loadmodel->zymdata_bones[i].parent = BigLong(bone[i].parent);
+ if (loadmodel->zymdata_bones[i].parent >= i)
+ Host_Error("Mod_LoadZymoticModel: bone[%i].parent >= %i in %s\n", i, i, loadmodel->name);
+ }
+ }
+
+ {
+ int i, *bonecount;
+ // zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
+ loadmodel->zymdata_vertbonecounts = Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
+ bonecount = (void *) (pheader->lump_vertbonecounts.start + pbase);
+ for (i = 0;i < pheader->numverts;i++)
+ {
+ loadmodel->zymdata_vertbonecounts[i] = BigLong(bonecount[i]);
+ if (loadmodel->zymdata_vertbonecounts[i] < 1)
+ Host_Error("Mod_LoadZymoticModel: bone vertex count < 1 in %s\n", loadmodel->name);
+ }
+ }
+
+ {
+ int i;
+ zymvertex_t *vertdata;
+ // zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
+ loadmodel->zymdata_verts = Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
+ vertdata = (void *) (pheader->lump_verts.start + pbase);
+ for (i = 0;i < pheader->lump_verts.length / (int) sizeof(zymvertex_t);i++)
+ {
+ loadmodel->zymdata_verts[i].bonenum = BigLong(vertdata[i].bonenum);
+ loadmodel->zymdata_verts[i].origin[0] = BigFloat(vertdata[i].origin[0]);
+ loadmodel->zymdata_verts[i].origin[1] = BigFloat(vertdata[i].origin[1]);
+ loadmodel->zymdata_verts[i].origin[2] = BigFloat(vertdata[i].origin[2]);
+ }
+ }
+
+ {
+ int i;
+ float *intexcoord, *outtexcoord;
+ // zymlump_t lump_texcoords; // float texcoords[numvertices][2];
+ loadmodel->zymdata_texcoords = outtexcoord = Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(float[4]));
+ intexcoord = (void *) (pheader->lump_texcoords.start + pbase);
+ for (i = 0;i < pheader->numverts;i++)
+ {
+ outtexcoord[i*4+0] = BigFloat(intexcoord[i*2+0]);
+ // flip T coordinate for OpenGL
+ outtexcoord[i*4+1] = 1 - BigFloat(intexcoord[i*2+1]);
+ }
+ }
+
+ {
+ int i, count, *renderlist, *renderlistend, *outrenderlist;
+ // zymlump_t lump_render; // int renderlist[rendersize]; // sorted by shader with run lengths (int count), shaders are sequentially used, each run can be used with glDrawElements (each triangle is 3 int indices)
+ loadmodel->zymdata_renderlist = Mem_Alloc(loadmodel->mempool, pheader->lump_render.length);
+ // byteswap, validate, and swap winding order of tris
+ count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
+ if (pheader->lump_render.length != count)
+ Host_Error("Mod_LoadZymoticModel: renderlist is wrong size in %s (is %i bytes, should be %i bytes)\n", loadmodel->name, pheader->lump_render.length, count);
+ outrenderlist = loadmodel->zymdata_renderlist = Mem_Alloc(loadmodel->mempool, count);
+ renderlist = (void *) (pheader->lump_render.start + pbase);
+ renderlistend = (void *) ((qbyte *) renderlist + pheader->lump_render.length);
+ for (i = 0;i < pheader->numshaders;i++)
+ {
+ if (renderlist >= renderlistend)
+ Host_Error("Mod_LoadZymoticModel: corrupt renderlist in %s (wrong size)\n", loadmodel->name);
+ count = BigLong(*renderlist);renderlist++;
+ if (renderlist + count * 3 > renderlistend)
+ Host_Error("Mod_LoadZymoticModel: corrupt renderlist in %s (wrong size)\n", loadmodel->name);
+ *outrenderlist++ = count;
+ while (count--)
+ {
+ outrenderlist[2] = BigLong(renderlist[0]);
+ outrenderlist[1] = BigLong(renderlist[1]);
+ outrenderlist[0] = BigLong(renderlist[2]);
+ if ((unsigned int)outrenderlist[0] >= (unsigned int)pheader->numverts
+ || (unsigned int)outrenderlist[1] >= (unsigned int)pheader->numverts
+ || (unsigned int)outrenderlist[2] >= (unsigned int)pheader->numverts)
+ Host_Error("Mod_LoadZymoticModel: corrupt renderlist in %s (out of bounds index)\n", loadmodel->name);
+ renderlist += 3;
+ outrenderlist += 3;
+ }
+ }
+ }
+
+ {
+ int i;
+ char *shadername;
+ // zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
+ loadmodel->zymdata_textures = Mem_Alloc(loadmodel->mempool, pheader->numshaders * sizeof(rtexture_t *));
+ shadername = (void *) (pheader->lump_shaders.start + pbase);
+ for (i = 0;i < pheader->numshaders;i++)
+ loadmodel->zymdata_textures[i] = loadtextureimage(loadmodel->texturepool, shadername + i * 32, 0, 0, true, TEXF_ALPHA | TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0));
+ }
+
+ {
+ // zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
+ loadmodel->zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
+ memcpy(loadmodel->zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);
+ }