2 Copyright (C) 1996-1997 Id Software, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 See the GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 static cvar_t r_mipskins = {CVAR_SAVE, "r_mipskins", "0"};
27 void Mod_AliasInit (void)
29 Cvar_RegisterVariable(&r_mipskins);
32 static float vertst[MAXALIASVERTS][2];
33 static int vertusage[MAXALIASVERTS];
34 static int vertonseam[MAXALIASVERTS];
35 static int vertremap[MAXALIASVERTS];
36 static int temptris[MAXALIASTRIS][3];
38 static void Mod_CalcAliasModelBBoxes (void)
41 float dist, yawradius, radius;
44 VectorClear(loadmodel->normalmins);
45 VectorClear(loadmodel->normalmaxs);
48 for (meshnum = 0, mesh = loadmodel->aliasdata_meshes;meshnum < loadmodel->aliasnum_meshes;meshnum++, mesh++)
50 for (vnum = 0, v = mesh->data_vertices;vnum < mesh->num_vertices * mesh->num_frames;vnum++, v++)
52 if (loadmodel->normalmins[0] > v->origin[0]) loadmodel->normalmins[0] = v->origin[0];
53 if (loadmodel->normalmins[1] > v->origin[1]) loadmodel->normalmins[1] = v->origin[1];
54 if (loadmodel->normalmins[2] > v->origin[2]) loadmodel->normalmins[2] = v->origin[2];
55 if (loadmodel->normalmaxs[0] < v->origin[0]) loadmodel->normalmaxs[0] = v->origin[0];
56 if (loadmodel->normalmaxs[1] < v->origin[1]) loadmodel->normalmaxs[1] = v->origin[1];
57 if (loadmodel->normalmaxs[2] < v->origin[2]) loadmodel->normalmaxs[2] = v->origin[2];
58 dist = v->origin[0] * v->origin[0] + v->origin[1] * v->origin[1];
61 dist += v->origin[2] * v->origin[2];
66 radius = sqrt(radius);
67 yawradius = sqrt(yawradius);
68 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
69 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
70 loadmodel->yawmins[2] = loadmodel->normalmins[2];
71 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
72 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
73 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
74 loadmodel->radius = radius;
75 loadmodel->radius2 = radius * radius;
78 static void Mod_ConvertAliasVerts (int inverts, vec3_t scale, vec3_t translate, trivertx_t *v, aliasvertex_t *out)
82 for (i = 0;i < inverts;i++)
84 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
86 temp[0] = v[i].v[0] * scale[0] + translate[0];
87 temp[1] = v[i].v[1] * scale[1] + translate[1];
88 temp[2] = v[i].v[2] * scale[2] + translate[2];
89 j = vertremap[i]; // not onseam
91 VectorCopy(temp, out[j].origin);
92 j = vertremap[i+inverts]; // onseam
94 VectorCopy(temp, out[j].origin);
98 static void Mod_BuildAliasVertexTextureVectors(int numverts, aliasvertex_t *vertices, const float *texcoords, float *vertexbuffer, float *svectorsbuffer, float *tvectorsbuffer, float *normalsbuffer, int numtriangles, const int *elements)
101 for (i = 0;i < numverts;i++)
102 VectorCopy(vertices[i].origin, &vertexbuffer[i * 4]);
103 Mod_BuildTextureVectorsAndNormals(numverts, numtriangles, vertexbuffer, texcoords, elements, svectorsbuffer, tvectorsbuffer, normalsbuffer);
104 for (i = 0;i < numverts;i++)
106 // LordHavoc: alias models are backwards, apparently
107 vertices[i].normal[0] = normalsbuffer[i * 4 + 0];
108 vertices[i].normal[1] = normalsbuffer[i * 4 + 1];
109 vertices[i].normal[2] = normalsbuffer[i * 4 + 2];
110 vertices[i].svector[0] = svectorsbuffer[i * 4 + 0];
111 vertices[i].svector[1] = svectorsbuffer[i * 4 + 1];
112 vertices[i].svector[2] = svectorsbuffer[i * 4 + 2];
116 static void Mod_MDL_LoadFrames (qbyte* datapointer, int inverts, int outverts, vec3_t scale, vec3_t translate, float *texcoords, aliasvertex_t *posedata, int numtris, int *elements)
118 int i, f, pose, groupframes;
119 float interval, *vertexbuffer, *svectorsbuffer, *tvectorsbuffer, *normalsbuffer;
120 daliasframetype_t *pframetype;
121 daliasframe_t *pinframe;
122 daliasgroup_t *group;
123 daliasinterval_t *intervals;
126 scene = loadmodel->animscenes;
127 vertexbuffer = Mem_Alloc(tempmempool, outverts * sizeof(float[4]) * 4);
128 svectorsbuffer = vertexbuffer + outverts * 4;
129 tvectorsbuffer = svectorsbuffer + outverts * 4;
130 normalsbuffer = tvectorsbuffer + outverts * 4;
131 for (f = 0;f < loadmodel->numframes;f++)
133 pframetype = (daliasframetype_t *)datapointer;
134 datapointer += sizeof(daliasframetype_t);
135 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
137 // a single frame is still treated as a group
144 group = (daliasgroup_t *)datapointer;
145 datapointer += sizeof(daliasgroup_t);
146 groupframes = LittleLong (group->numframes);
148 // intervals (time per frame)
149 intervals = (daliasinterval_t *)datapointer;
150 datapointer += sizeof(daliasinterval_t) * groupframes;
152 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
153 if (interval < 0.01f)
154 Host_Error("Mod_MDL_LoadFrames: invalid interval");
157 // get scene name from first frame
158 pinframe = (daliasframe_t *)datapointer;
160 strcpy(scene->name, pinframe->name);
161 scene->firstframe = pose;
162 scene->framecount = groupframes;
163 scene->framerate = 1.0f / interval;
168 for (i = 0;i < groupframes;i++)
170 pinframe = (daliasframe_t *)datapointer;
171 datapointer += sizeof(daliasframe_t);
172 Mod_ConvertAliasVerts(inverts, scale, translate, (trivertx_t *)datapointer, posedata + pose * outverts);
173 Mod_BuildAliasVertexTextureVectors(outverts, posedata + pose * outverts, texcoords, vertexbuffer, svectorsbuffer, tvectorsbuffer, normalsbuffer, numtris, elements);
174 datapointer += sizeof(trivertx_t) * inverts;
178 Mem_Free(vertexbuffer);
181 void Mod_BuildAliasSkinFromSkinFrame(aliasskin_t *skin, skinframe_t *skinframe)
185 // fog texture only exists if some pixels are transparent...
186 if (skinframe->fog != NULL)
187 skin->flags |= ALIASSKIN_TRANSPARENT;
188 // fog and gloss layers always exist
189 skin->num_layers = 2;
190 if (skinframe->glow != NULL)
192 if (skinframe->merged != NULL)
193 skin->num_layers += 2;
194 if (skinframe->base != NULL)
195 skin->num_layers += 2;
196 if (skinframe->pants != NULL)
197 skin->num_layers += 2;
198 if (skinframe->shirt != NULL)
199 skin->num_layers += 2;
200 layer = skin->data_layers = Mem_Alloc(loadmodel->mempool, skin->num_layers * sizeof(aliaslayer_t));
201 if (skinframe->glow != NULL)
204 layer->texture = skinframe->glow;
207 if (skinframe->merged != NULL)
209 layer->flags = ALIASLAYER_NODRAW_IF_COLORMAPPED | ALIASLAYER_DIFFUSE;
210 if (skinframe->glow != NULL)
211 layer->flags |= ALIASLAYER_ADD;
212 layer->texture = skinframe->merged;
213 layer->nmap = skinframe->nmap;
216 if (skinframe->base != NULL)
218 layer->flags = ALIASLAYER_NODRAW_IF_NOTCOLORMAPPED | ALIASLAYER_DIFFUSE;
219 if (skinframe->glow != NULL)
220 layer->flags |= ALIASLAYER_ADD;
221 layer->texture = skinframe->base;
222 layer->nmap = skinframe->nmap;
225 if (skinframe->pants != NULL)
227 layer->flags = ALIASLAYER_NODRAW_IF_NOTCOLORMAPPED | ALIASLAYER_DIFFUSE | ALIASLAYER_COLORMAP_SHIRT;
228 if (skinframe->glow != NULL || skinframe->base != NULL)
229 layer->flags |= ALIASLAYER_ADD;
230 layer->texture = skinframe->pants;
231 layer->nmap = skinframe->nmap;
234 if (skinframe->shirt != NULL)
236 layer->flags = ALIASLAYER_NODRAW_IF_NOTCOLORMAPPED | ALIASLAYER_DIFFUSE | ALIASLAYER_COLORMAP_SHIRT;
237 if (skinframe->glow != NULL || skinframe->base != NULL || skinframe->pants != NULL)
238 layer->flags |= ALIASLAYER_ADD;
239 layer->texture = skinframe->shirt;
240 layer->nmap = skinframe->nmap;
243 layer->flags = ALIASLAYER_FOG;
244 layer->texture = skinframe->fog;
246 layer->flags = ALIASLAYER_DRAW_PER_LIGHT | ALIASLAYER_SPECULAR;
247 layer->texture = skinframe->gloss;
248 layer->nmap = skinframe->nmap;
250 if (skinframe->merged != NULL)
252 layer->flags = ALIASLAYER_DRAW_PER_LIGHT | ALIASLAYER_NODRAW_IF_COLORMAPPED | ALIASLAYER_DIFFUSE;
253 layer->texture = skinframe->merged;
254 layer->nmap = skinframe->nmap;
257 if (skinframe->base != NULL)
259 layer->flags = ALIASLAYER_DRAW_PER_LIGHT | ALIASLAYER_NODRAW_IF_NOTCOLORMAPPED | ALIASLAYER_DIFFUSE;
260 layer->texture = skinframe->base;
261 layer->nmap = skinframe->nmap;
264 if (skinframe->pants != NULL)
266 layer->flags = ALIASLAYER_DRAW_PER_LIGHT | ALIASLAYER_NODRAW_IF_NOTCOLORMAPPED | ALIASLAYER_DIFFUSE | ALIASLAYER_COLORMAP_PANTS;
267 layer->texture = skinframe->pants;
268 layer->nmap = skinframe->nmap;
271 if (skinframe->shirt != NULL)
273 layer->flags = ALIASLAYER_DRAW_PER_LIGHT | ALIASLAYER_NODRAW_IF_NOTCOLORMAPPED | ALIASLAYER_DIFFUSE | ALIASLAYER_COLORMAP_SHIRT;
274 layer->texture = skinframe->shirt;
275 layer->nmap = skinframe->nmap;
280 void Mod_BuildMDLMD2MeshInfo(int numverts, int numtris, int *elements, float *texcoords, aliasvertex_t *posedata)
285 loadmodel->aliasnum_meshes = 1;
286 mesh = loadmodel->aliasdata_meshes = Mem_Alloc(loadmodel->mempool, loadmodel->aliasnum_meshes * sizeof(aliasmesh_t));
288 mesh->num_frames = 0;
289 for (i = 0;i < loadmodel->numframes;i++)
290 mesh->num_frames += loadmodel->animscenes[i].framecount;
291 for (i = 0;i < loadmodel->numskins;i++)
292 mesh->num_skins += loadmodel->skinscenes[i].framecount;
293 mesh->num_triangles = numtris;
294 mesh->num_vertices = numverts;
295 mesh->data_skins = Mem_Alloc(loadmodel->mempool, mesh->num_skins * sizeof(aliasskin_t));
296 mesh->data_elements = elements;
297 mesh->data_neighbors = Mem_Alloc(loadmodel->mempool, numtris * sizeof(int[3]));
298 Mod_ValidateElements(mesh->data_elements, mesh->num_triangles, mesh->num_vertices, __FILE__, __LINE__);
299 Mod_BuildTriangleNeighbors(mesh->data_neighbors, mesh->data_elements, mesh->num_triangles);
300 mesh->data_texcoords = texcoords;
301 mesh->data_vertices = posedata;
302 for (i = 0;i < mesh->num_skins;i++)
303 Mod_BuildAliasSkinFromSkinFrame(mesh->data_skins + i, loadmodel->skinframes + i);
304 Mod_CalcAliasModelBBoxes();
307 #define BOUNDI(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid ##VALUE (%d exceeds %d - %d)\n", loadmodel->name, VALUE, MIN, MAX);
308 #define BOUNDF(VALUE,MIN,MAX) if (VALUE < MIN || VALUE >= MAX) Host_Error("model %s has an invalid ##VALUE (%f exceeds %f - %f)\n", loadmodel->name, VALUE, MIN, MAX);
309 extern void R_Model_Alias_Draw(entity_render_t *ent);
310 extern void R_Model_Alias_DrawFakeShadow(entity_render_t *ent);
311 extern void R_Model_Alias_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius);
312 extern void R_Model_Alias_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor);
313 void Mod_LoadQ1AliasModel (model_t *mod, void *buffer)
315 int i, j, version, totalposes, totalskins, skinwidth, skinheight, totalverts, groupframes, groupskins, *elements, numverts, numtris;
316 float scales, scalet, scale[3], translate[3], interval, *texcoords;
318 stvert_t *pinstverts;
319 dtriangle_t *pintriangles;
320 daliasskintype_t *pinskintype;
321 daliasskingroup_t *pinskingroup;
322 daliasskininterval_t *pinskinintervals;
323 daliasframetype_t *pinframetype;
324 daliasgroup_t *pinframegroup;
325 aliasvertex_t *posedata;
326 qbyte *datapointer, *startframes, *startskins;
327 char name[MAX_QPATH];
328 skinframe_t tempskinframe;
329 animscene_t *tempskinscenes;
330 skinframe_t *tempskinframes;
332 datapointer = buffer;
333 pinmodel = (mdl_t *)datapointer;
334 datapointer += sizeof(mdl_t);
336 version = LittleLong (pinmodel->version);
337 if (version != ALIAS_VERSION)
338 Host_Error ("%s has wrong version number (%i should be %i)",
339 loadmodel->name, version, ALIAS_VERSION);
341 loadmodel->type = mod_alias;
342 loadmodel->aliastype = ALIASTYPE_ALIAS;
343 loadmodel->DrawSky = NULL;
344 loadmodel->Draw = R_Model_Alias_Draw;
345 loadmodel->DrawFakeShadow = R_Model_Alias_DrawFakeShadow;
346 loadmodel->DrawShadowVolume = R_Model_Alias_DrawShadowVolume;
347 loadmodel->DrawLight = R_Model_Alias_DrawLight;
349 loadmodel->numskins = LittleLong(pinmodel->numskins);
350 BOUNDI(loadmodel->numskins,0,256);
351 skinwidth = LittleLong (pinmodel->skinwidth);
352 BOUNDI(skinwidth,0,4096);
353 skinheight = LittleLong (pinmodel->skinheight);
354 BOUNDI(skinheight,0,4096);
355 numverts = LittleLong(pinmodel->numverts);
356 BOUNDI(numverts,0,MAXALIASVERTS);
357 numtris = LittleLong(pinmodel->numtris);
358 BOUNDI(numtris,0,MAXALIASTRIS);
359 loadmodel->numframes = LittleLong(pinmodel->numframes);
360 BOUNDI(loadmodel->numframes,0,65536);
361 loadmodel->synctype = LittleLong (pinmodel->synctype);
362 BOUNDI(loadmodel->synctype,0,2);
363 loadmodel->flags = LittleLong (pinmodel->flags);
365 for (i = 0;i < 3;i++)
367 scale[i] = LittleFloat (pinmodel->scale[i]);
368 translate[i] = LittleFloat (pinmodel->scale_origin[i]);
371 startskins = datapointer;
373 for (i = 0;i < loadmodel->numskins;i++)
375 pinskintype = (daliasskintype_t *)datapointer;
376 datapointer += sizeof(daliasskintype_t);
377 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
381 pinskingroup = (daliasskingroup_t *)datapointer;
382 datapointer += sizeof(daliasskingroup_t);
383 groupskins = LittleLong(pinskingroup->numskins);
384 datapointer += sizeof(daliasskininterval_t) * groupskins;
387 for (j = 0;j < groupskins;j++)
389 datapointer += skinwidth * skinheight;
394 pinstverts = (stvert_t *)datapointer;
395 datapointer += sizeof(stvert_t) * numverts;
397 pintriangles = (dtriangle_t *)datapointer;
398 datapointer += sizeof(dtriangle_t) * numtris;
400 startframes = datapointer;
402 for (i = 0;i < loadmodel->numframes;i++)
404 pinframetype = (daliasframetype_t *)datapointer;
405 datapointer += sizeof(daliasframetype_t);
406 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
410 pinframegroup = (daliasgroup_t *)datapointer;
411 datapointer += sizeof(daliasgroup_t);
412 groupframes = LittleLong(pinframegroup->numframes);
413 datapointer += sizeof(daliasinterval_t) * groupframes;
416 for (j = 0;j < groupframes;j++)
418 datapointer += sizeof(daliasframe_t);
419 datapointer += sizeof(trivertx_t) * numverts;
425 loadmodel->skinscenes = Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
426 loadmodel->skinframes = Mem_Alloc(loadmodel->mempool, totalskins * sizeof(skinframe_t));
428 datapointer = startskins;
429 for (i = 0;i < loadmodel->numskins;i++)
431 pinskintype = (daliasskintype_t *)datapointer;
432 datapointer += sizeof(daliasskintype_t);
434 if (pinskintype->type == ALIAS_SKIN_SINGLE)
441 pinskingroup = (daliasskingroup_t *)datapointer;
442 datapointer += sizeof(daliasskingroup_t);
444 groupskins = LittleLong (pinskingroup->numskins);
446 pinskinintervals = (daliasskininterval_t *)datapointer;
447 datapointer += sizeof(daliasskininterval_t) * groupskins;
449 interval = LittleFloat(pinskinintervals[0].interval);
450 if (interval < 0.01f)
451 Host_Error("Mod_LoadQ1AliasModel: invalid interval\n");
454 sprintf(loadmodel->skinscenes[i].name, "skin %i", i);
455 loadmodel->skinscenes[i].firstframe = totalskins;
456 loadmodel->skinscenes[i].framecount = groupskins;
457 loadmodel->skinscenes[i].framerate = 1.0f / interval;
458 loadmodel->skinscenes[i].loop = true;
460 for (j = 0;j < groupskins;j++)
463 sprintf (name, "%s_%i_%i", loadmodel->name, i, j);
465 sprintf (name, "%s_%i", loadmodel->name, i);
466 if (!Mod_LoadSkinFrame(loadmodel->skinframes + totalskins, name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA, true, false, true))
467 Mod_LoadSkinFrame_Internal(loadmodel->skinframes + totalskins, name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA, true, false, true, (qbyte *)datapointer, skinwidth, skinheight);
468 datapointer += skinwidth * skinheight;
472 // check for skins that don't exist in the model, but do exist as external images
473 // (this was added because yummyluv kept pestering me about support for it)
476 sprintf (name, "%s_%i", loadmodel->name, loadmodel->numskins);
477 if (Mod_LoadSkinFrame (&tempskinframe, name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA, true, false, true))
479 // expand the arrays to make room
480 tempskinscenes = loadmodel->skinscenes;
481 tempskinframes = loadmodel->skinframes;
482 loadmodel->skinscenes = Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
483 loadmodel->skinframes = Mem_Alloc(loadmodel->mempool, (totalskins + 1) * sizeof(skinframe_t));
484 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
485 memcpy(loadmodel->skinframes, tempskinframes, totalskins * sizeof(skinframe_t));
486 Mem_Free(tempskinscenes);
487 Mem_Free(tempskinframes);
488 // store the info about the new skin
489 strcpy(loadmodel->skinscenes[loadmodel->numskins].name, name);
490 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
491 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
492 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
493 loadmodel->skinscenes[loadmodel->numskins].loop = true;
494 loadmodel->skinframes[totalskins] = tempskinframe;
495 loadmodel->numskins++;
502 // store texture coordinates into temporary array, they will be stored after usage is determined (triangle data)
503 scales = 1.0 / skinwidth;
504 scalet = 1.0 / skinheight;
505 for (i = 0;i < numverts;i++)
507 vertonseam[i] = LittleLong(pinstverts[i].onseam);
508 vertst[i][0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
509 vertst[i][1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
510 vertst[i+numverts][0] = vertst[i][0] + 0.5;
511 vertst[i+numverts][1] = vertst[i][1];
513 vertusage[i+numverts] = 0;
516 // load triangle data
517 elements = Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * numtris);
519 // count the vertices used
520 for (i = 0;i < numverts*2;i++)
522 for (i = 0;i < numtris;i++)
524 temptris[i][0] = LittleLong(pintriangles[i].vertindex[0]);
525 temptris[i][1] = LittleLong(pintriangles[i].vertindex[1]);
526 temptris[i][2] = LittleLong(pintriangles[i].vertindex[2]);
527 if (!LittleLong(pintriangles[i].facesfront)) // backface
529 if (vertonseam[temptris[i][0]]) temptris[i][0] += numverts;
530 if (vertonseam[temptris[i][1]]) temptris[i][1] += numverts;
531 if (vertonseam[temptris[i][2]]) temptris[i][2] += numverts;
533 vertusage[temptris[i][0]]++;
534 vertusage[temptris[i][1]]++;
535 vertusage[temptris[i][2]]++;
537 // build remapping table and compact array
539 for (i = 0;i < numverts*2;i++)
543 vertremap[i] = totalverts;
544 vertst[totalverts][0] = vertst[i][0];
545 vertst[totalverts][1] = vertst[i][1];
549 vertremap[i] = -1; // not used at all
551 // remap the triangle references
552 for (i = 0;i < numtris;i++)
554 elements[i*3+0] = vertremap[temptris[i][0]];
555 elements[i*3+1] = vertremap[temptris[i][1]];
556 elements[i*3+2] = vertremap[temptris[i][2]];
558 // store the texture coordinates
559 texcoords = Mem_Alloc(loadmodel->mempool, sizeof(float[4]) * totalverts);
560 for (i = 0;i < totalverts;i++)
562 texcoords[i*4+0] = vertst[i][0];
563 texcoords[i*4+1] = vertst[i][1];
567 loadmodel->animscenes = Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
568 posedata = Mem_Alloc(loadmodel->mempool, sizeof(aliasvertex_t) * totalposes * totalverts);
569 Mod_MDL_LoadFrames (startframes, numverts, totalverts, scale, translate, texcoords, posedata, numtris, elements);
570 Mod_BuildMDLMD2MeshInfo(totalverts, numtris, elements, texcoords, posedata);
573 static void Mod_MD2_ConvertVerts (vec3_t scale, vec3_t translate, trivertx_t *v, aliasvertex_t *out, int numverts, int *vertremap)
577 for (i = 0;i < numverts;i++)
579 in = v + vertremap[i];
580 out[i].origin[0] = in->v[0] * scale[0] + translate[0];
581 out[i].origin[1] = in->v[1] * scale[1] + translate[1];
582 out[i].origin[2] = in->v[2] * scale[2] + translate[2];
586 void Mod_LoadQ2AliasModel (model_t *mod, void *buffer)
588 int i, j, k, hashindex, num, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end, *elements, numverts, numtris;
589 float *stverts, s, t, scale[3], translate[3], *vertexbuffer, *svectorsbuffer, *tvectorsbuffer, *normalsbuffer, *texcoords;
590 aliasvertex_t *posedata;
592 qbyte *base, *datapointer;
593 md2frame_t *pinframe;
595 md2triangle_t *intri;
596 unsigned short *inst;
599 struct md2verthash_s *next;
603 *hash, **md2verthash, *md2verthashdata;
608 version = LittleLong (pinmodel->version);
609 if (version != MD2ALIAS_VERSION)
610 Host_Error ("%s has wrong version number (%i should be %i)",
611 loadmodel->name, version, MD2ALIAS_VERSION);
613 loadmodel->type = mod_alias;
614 loadmodel->aliastype = ALIASTYPE_ALIAS;
615 loadmodel->DrawSky = NULL;
616 loadmodel->Draw = R_Model_Alias_Draw;
617 loadmodel->DrawFakeShadow = R_Model_Alias_DrawFakeShadow;
618 loadmodel->DrawShadowVolume = R_Model_Alias_DrawShadowVolume;
619 loadmodel->DrawLight = R_Model_Alias_DrawLight;
621 if (LittleLong(pinmodel->num_tris < 1) || LittleLong(pinmodel->num_tris) > MD2MAX_TRIANGLES)
622 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
623 if (LittleLong(pinmodel->num_xyz < 1) || LittleLong(pinmodel->num_xyz) > MD2MAX_VERTS)
624 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
625 if (LittleLong(pinmodel->num_frames < 1) || LittleLong(pinmodel->num_frames) > MD2MAX_FRAMES)
626 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
627 if (LittleLong(pinmodel->num_skins < 0) || LittleLong(pinmodel->num_skins) > MAX_SKINS)
628 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
630 end = LittleLong(pinmodel->ofs_end);
631 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins <= 0) || LittleLong(pinmodel->ofs_skins) >= end))
632 Host_Error ("%s is not a valid model", loadmodel->name);
633 if (LittleLong(pinmodel->ofs_st <= 0) || LittleLong(pinmodel->ofs_st) >= end)
634 Host_Error ("%s is not a valid model", loadmodel->name);
635 if (LittleLong(pinmodel->ofs_tris <= 0) || LittleLong(pinmodel->ofs_tris) >= end)
636 Host_Error ("%s is not a valid model", loadmodel->name);
637 if (LittleLong(pinmodel->ofs_frames <= 0) || LittleLong(pinmodel->ofs_frames) >= end)
638 Host_Error ("%s is not a valid model", loadmodel->name);
639 if (LittleLong(pinmodel->ofs_glcmds <= 0) || LittleLong(pinmodel->ofs_glcmds) >= end)
640 Host_Error ("%s is not a valid model", loadmodel->name);
642 loadmodel->numskins = LittleLong(pinmodel->num_skins);
643 numxyz = LittleLong(pinmodel->num_xyz);
644 numst = LittleLong(pinmodel->num_st);
645 numtris = LittleLong(pinmodel->num_tris);
646 loadmodel->numframes = LittleLong(pinmodel->num_frames);
648 loadmodel->flags = 0; // there are no MD2 flags
649 loadmodel->synctype = ST_RAND;
652 inskin = (void*)(base + LittleLong(pinmodel->ofs_skins));
653 if (loadmodel->numskins)
655 loadmodel->skinscenes = Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins + sizeof(skinframe_t) * loadmodel->numskins);
656 loadmodel->skinframes = (void *)(loadmodel->skinscenes + loadmodel->numskins);
657 for (i = 0;i < loadmodel->numskins;i++)
659 loadmodel->skinscenes[i].firstframe = i;
660 loadmodel->skinscenes[i].framecount = 1;
661 loadmodel->skinscenes[i].loop = true;
662 loadmodel->skinscenes[i].framerate = 10;
663 Mod_LoadSkinFrame (loadmodel->skinframes + i, inskin, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE, true, false, true);
664 inskin += MD2MAX_SKINNAME;
668 // load the triangles and stvert data
669 inst = (void*)(base + LittleLong(pinmodel->ofs_st));
670 intri = (void*)(base + LittleLong(pinmodel->ofs_tris));
671 skinwidth = LittleLong(pinmodel->skinwidth);
672 skinheight = LittleLong(pinmodel->skinheight);
674 stverts = Mem_Alloc(tempmempool, numst * sizeof(float[2]));
675 s = 1.0f / skinwidth;
676 t = 1.0f / skinheight;
677 for (i = 0;i < numst;i++)
679 j = (unsigned short) LittleShort(inst[i*2+0]);
680 k = (unsigned short) LittleShort(inst[i*2+1]);
681 if (j >= skinwidth || k >= skinheight)
684 Host_Error("Mod_MD2_LoadGeometry: invalid skin coordinate (%i %i) on vert %i of model %s\n", j, k, i, loadmodel->name);
686 stverts[i*2+0] = j * s;
687 stverts[i*2+1] = k * t;
690 md2verthash = Mem_Alloc(tempmempool, 256 * sizeof(hash));
691 md2verthashdata = Mem_Alloc(tempmempool, numtris * 3 * sizeof(*hash));
692 // swap the triangle list
694 elements = Mem_Alloc(loadmodel->mempool, numtris * sizeof(int[3]));
695 for (i = 0;i < numtris;i++)
697 for (j = 0;j < 3;j++)
699 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
700 st = (unsigned short) LittleShort (intri[i].index_st[j]);
701 if (xyz >= numxyz || st >= numst)
703 Mem_Free(md2verthash);
704 Mem_Free(md2verthashdata);
707 Host_Error("Mod_MD2_LoadGeometry: invalid xyz index (%i) on triangle %i of model %s\n", xyz, i, loadmodel->name);
709 Host_Error("Mod_MD2_LoadGeometry: invalid st index (%i) on triangle %i of model %s\n", st, i, loadmodel->name);
713 hashindex = (xyz * 17 + st) & 255;
714 for (hash = md2verthash[hashindex];hash;hash = hash->next)
715 if (hash->xyz == xyz && hash->st[0] == s && hash->st[1] == t)
719 hash = md2verthashdata + num++;
723 hash->next = md2verthash[hashindex];
724 md2verthash[hashindex] = hash;
726 elements[i*3+j] = (hash - md2verthashdata);
733 vertremap = Mem_Alloc(loadmodel->mempool, num * sizeof(int));
734 texcoords = Mem_Alloc(loadmodel->mempool, num * sizeof(float[4]));
735 for (i = 0;i < num;i++)
737 hash = md2verthashdata + i;
738 vertremap[i] = hash->xyz;
739 texcoords[i*4+0] = hash->st[0];
740 texcoords[i*4+1] = hash->st[1];
743 Mem_Free(md2verthash);
744 Mem_Free(md2verthashdata);
747 datapointer = (base + LittleLong(pinmodel->ofs_frames));
748 loadmodel->animscenes = Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
749 posedata = Mem_Alloc(loadmodel->mempool, numverts * loadmodel->numframes * sizeof(trivertx_t));
751 vertexbuffer = Mem_Alloc(tempmempool, numverts * sizeof(float[4]) * 4);
752 svectorsbuffer = vertexbuffer + numverts * 4;
753 tvectorsbuffer = svectorsbuffer + numverts * 4;
754 normalsbuffer = tvectorsbuffer + numverts * 4;
755 for (i = 0;i < loadmodel->numframes;i++)
757 pinframe = (md2frame_t *)datapointer;
758 datapointer += sizeof(md2frame_t);
759 for (j = 0;j < 3;j++)
761 scale[j] = LittleFloat(pinframe->scale[j]);
762 translate[j] = LittleFloat(pinframe->translate[j]);
764 Mod_MD2_ConvertVerts(scale, translate, (void *)datapointer, posedata + i * numverts, numverts, vertremap);
765 Mod_BuildAliasVertexTextureVectors(numverts, posedata + i * numverts, texcoords, vertexbuffer, svectorsbuffer, tvectorsbuffer, normalsbuffer, numtris, elements);
766 datapointer += numxyz * sizeof(trivertx_t);
768 strcpy(loadmodel->animscenes[i].name, pinframe->name);
769 loadmodel->animscenes[i].firstframe = i;
770 loadmodel->animscenes[i].framecount = 1;
771 loadmodel->animscenes[i].framerate = 10;
772 loadmodel->animscenes[i].loop = true;
774 Mem_Free(vertexbuffer);
778 Mod_BuildMDLMD2MeshInfo(numverts, numtris, elements, texcoords, posedata);
781 void Mod_LoadQ3AliasModel(model_t *mod, void *buffer)
784 float *vertexbuffer, *svectorsbuffer, *tvectorsbuffer, *normalsbuffer;
785 md3modelheader_t *pinmodel;
786 md3frameinfo_t *pinframe;
789 skinframe_t tempskinframe;
793 if (memcmp(pinmodel->identifier, "IDP3", 4))
794 Host_Error ("%s is not a MD3 (IDP3) file\n", loadmodel->name);
795 version = LittleLong (pinmodel->version);
796 if (version != MD3VERSION)
797 Host_Error ("%s has wrong version number (%i should be %i)",
798 loadmodel->name, version, MD3VERSION);
800 loadmodel->type = mod_alias;
801 loadmodel->aliastype = ALIASTYPE_ALIAS;
802 loadmodel->DrawSky = NULL;
803 loadmodel->Draw = R_Model_Alias_Draw;
804 loadmodel->DrawFakeShadow = R_Model_Alias_DrawFakeShadow;
805 loadmodel->DrawShadowVolume = R_Model_Alias_DrawShadowVolume;
806 loadmodel->DrawLight = R_Model_Alias_DrawLight;
807 loadmodel->flags = 0;
808 loadmodel->synctype = ST_RAND;
810 // set up some global info about the model
811 loadmodel->numframes = LittleLong(pinmodel->num_frames);
812 loadmodel->numskins = 1;
813 loadmodel->aliasnum_meshes = LittleLong(pinmodel->num_meshes);
814 loadmodel->skinscenes = Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
815 loadmodel->skinscenes[0].firstframe = 0;
816 loadmodel->skinscenes[0].framecount = 1;
817 loadmodel->skinscenes[0].loop = true;
818 loadmodel->skinscenes[0].framerate = 10;
821 loadmodel->animscenes = Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
822 for (i = 0, pinframe = (md3frameinfo_t *)((qbyte *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
824 strcpy(loadmodel->animscenes[i].name, pinframe->name);
825 loadmodel->animscenes[i].firstframe = i;
826 loadmodel->animscenes[i].framecount = 1;
827 loadmodel->animscenes[i].framerate = 10;
828 loadmodel->animscenes[i].loop = true;
831 // tags are not loaded yet
834 loadmodel->aliasdata_meshes = Mem_Alloc(loadmodel->mempool, loadmodel->aliasnum_meshes * sizeof(aliasmesh_t));
835 for (i = 0, pinmesh = (md3mesh_t *)((qbyte *)pinmodel + LittleLong(pinmodel->lump_meshes));i < loadmodel->aliasnum_meshes;i++, pinmesh = (md3mesh_t *)((qbyte *)pinmesh + LittleLong(pinmesh->lump_end)))
837 if (memcmp(pinmesh->identifier, "IDP3", 4))
838 Host_Error("Mod_LoadQ3AliasModel: invalid mesh identifier (not IDP3)\n");
839 mesh = loadmodel->aliasdata_meshes + i;
840 mesh->num_skins = loadmodel->numskins;
841 mesh->num_frames = LittleLong(pinmesh->num_frames);
842 mesh->num_vertices = LittleLong(pinmesh->num_vertices);
843 mesh->num_triangles = LittleLong(pinmesh->num_triangles);
844 mesh->data_skins = Mem_Alloc(loadmodel->mempool, mesh->num_skins * sizeof(aliasskin_t));
845 mesh->data_elements = Mem_Alloc(loadmodel->mempool, mesh->num_triangles * sizeof(int[3]));
846 mesh->data_neighbors = Mem_Alloc(loadmodel->mempool, mesh->num_triangles * sizeof(int[3]));
847 mesh->data_texcoords = Mem_Alloc(loadmodel->mempool, mesh->num_vertices * sizeof(float[4]));
848 mesh->data_vertices = Mem_Alloc(loadmodel->mempool, mesh->num_vertices * mesh->num_frames * sizeof(aliasvertex_t));
849 for (j = 0;j < mesh->num_triangles * 3;j++)
850 mesh->data_elements[j] = LittleLong(((int *)((qbyte *)pinmesh + pinmesh->lump_elements))[j]);
851 for (j = 0;j < mesh->num_vertices;j++)
853 mesh->data_texcoords[j * 4 + 0] = LittleLong(((float *)((qbyte *)pinmesh + pinmesh->lump_texcoords))[j * 2 + 0]);
854 mesh->data_texcoords[j * 4 + 1] = LittleLong(((float *)((qbyte *)pinmesh + pinmesh->lump_texcoords))[j * 2 + 1]);
856 for (j = 0;j < mesh->num_vertices * mesh->num_frames;j++)
858 mesh->data_vertices[j].origin[0] = LittleShort(((short *)((qbyte *)pinmesh + pinmesh->lump_framevertices))[j * 4 + 0]) * (1.0f / 64.0f);
859 mesh->data_vertices[j].origin[1] = LittleShort(((short *)((qbyte *)pinmesh + pinmesh->lump_framevertices))[j * 4 + 1]) * (1.0f / 64.0f);
860 mesh->data_vertices[j].origin[2] = LittleShort(((short *)((qbyte *)pinmesh + pinmesh->lump_framevertices))[j * 4 + 2]) * (1.0f / 64.0f);
862 vertexbuffer = Mem_Alloc(tempmempool, mesh->num_vertices * sizeof(float[4]) * 4);
863 svectorsbuffer = vertexbuffer + mesh->num_vertices * 4;
864 tvectorsbuffer = svectorsbuffer + mesh->num_vertices * 4;
865 normalsbuffer = tvectorsbuffer + mesh->num_vertices * 4;
866 for (j = 0;j < mesh->num_frames;j++)
867 Mod_BuildAliasVertexTextureVectors(mesh->num_vertices, mesh->data_vertices + j * mesh->num_vertices, mesh->data_texcoords, vertexbuffer, svectorsbuffer, tvectorsbuffer, normalsbuffer, mesh->num_triangles, mesh->data_elements);
868 Mem_Free(vertexbuffer);
870 memset(&tempskinframe, 0, sizeof(tempskinframe));
871 if (LittleLong(pinmesh->num_shaders) >= 1 && ((md3shader_t *)((qbyte *) pinmesh + pinmesh->lump_shaders))->name[0])
872 Mod_LoadSkinFrame (&tempskinframe, ((md3shader_t *)((qbyte *) pinmesh + pinmesh->lump_shaders))->name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE, true, false, true);
873 Mod_ValidateElements(mesh->data_elements, mesh->num_triangles, mesh->num_vertices, __FILE__, __LINE__);
874 Mod_BuildTriangleNeighbors(mesh->data_neighbors, mesh->data_elements, mesh->num_triangles);
875 Mod_BuildAliasSkinFromSkinFrame(mesh->data_skins, &tempskinframe);
877 Mod_CalcAliasModelBBoxes();
880 extern void R_Model_Zymotic_DrawSky(entity_render_t *ent);
881 extern void R_Model_Zymotic_Draw(entity_render_t *ent);
882 extern void R_Model_Zymotic_DrawFakeShadow(entity_render_t *ent);
883 extern void R_Model_Zymotic_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius);
884 extern void R_Model_Zymotic_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor);
885 void Mod_LoadZymoticModel(model_t *mod, void *buffer)
887 zymtype1header_t *pinmodel, *pheader;
890 pinmodel = (void *)buffer;
892 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
893 Host_Error ("Mod_LoadZymoticModel: %s is not a zymotic model\n");
894 if (BigLong(pinmodel->type) != 1)
895 Host_Error ("Mod_LoadZymoticModel: only type 1 (skeletal pose) models are currently supported (name = %s)\n", loadmodel->name);
897 loadmodel->type = mod_alias;
898 loadmodel->aliastype = ALIASTYPE_ZYM;
899 loadmodel->DrawSky = NULL;
900 loadmodel->Draw = R_Model_Zymotic_Draw;
901 loadmodel->DrawFakeShadow = NULL;//R_Model_Zymotic_DrawFakeShadow;
902 loadmodel->DrawShadowVolume = NULL;//R_Model_Zymotic_DrawShadowVolume;
903 loadmodel->DrawLight = NULL;//R_Model_Zymotic_DrawLight;
907 pheader->type = BigLong(pinmodel->type);
908 pheader->filesize = BigLong(pinmodel->filesize);
909 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
910 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
911 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
912 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
913 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
914 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
915 pheader->radius = BigFloat(pinmodel->radius);
916 pheader->numverts = loadmodel->zymnum_verts = BigLong(pinmodel->numverts);
917 pheader->numtris = loadmodel->zymnum_tris = BigLong(pinmodel->numtris);
918 pheader->numshaders = loadmodel->zymnum_shaders = BigLong(pinmodel->numshaders);
919 pheader->numbones = loadmodel->zymnum_bones = BigLong(pinmodel->numbones);
920 pheader->numscenes = loadmodel->zymnum_scenes = BigLong(pinmodel->numscenes);
921 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
922 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
923 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
924 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
925 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
926 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
927 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
928 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
929 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
930 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
931 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
932 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
933 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
934 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
935 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
936 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
937 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
938 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
940 loadmodel->flags = 0; // there are no flags
941 loadmodel->numframes = pheader->numscenes;
942 loadmodel->synctype = ST_SYNC;
943 //loadmodel->numtris = pheader->numtris;
944 //loadmodel->numverts = 0;
948 float modelradius, corner[2];
950 modelradius = pheader->radius;
951 for (i = 0;i < 3;i++)
953 loadmodel->normalmins[i] = pheader->mins[i];
954 loadmodel->normalmaxs[i] = pheader->maxs[i];
955 loadmodel->rotatedmins[i] = -modelradius;
956 loadmodel->rotatedmaxs[i] = modelradius;
958 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
959 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
960 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
961 if (loadmodel->yawmaxs[0] > modelradius)
962 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
963 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
964 loadmodel->yawmins[2] = loadmodel->normalmins[2];
965 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
966 loadmodel->radius = modelradius;
967 loadmodel->radius2 = modelradius * modelradius;
971 // FIXME: add shaders, and make them switchable shader sets and...
972 loadmodel->skinscenes = Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) + sizeof(skinframe_t));
973 loadmodel->skinscenes[0].firstframe = 0;
974 loadmodel->skinscenes[0].framecount = 1;
975 loadmodel->skinscenes[0].loop = true;
976 loadmodel->skinscenes[0].framerate = 10;
977 loadmodel->skinframes = (void *)(loadmodel->skinscenes + 1);
978 loadmodel->numskins = 1;
981 // go through the lumps, swapping things
986 // zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
987 loadmodel->animscenes = Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
988 scene = (void *) (pheader->lump_scenes.start + pbase);
989 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
990 for (i = 0;i < pheader->numscenes;i++)
992 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
993 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
994 loadmodel->animscenes[i].framecount = BigLong(scene->length);
995 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
996 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
997 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
998 Host_Error("Mod_LoadZymoticModel: scene firstframe (%i) >= numposes (%i)\n", loadmodel->animscenes[i].firstframe, numposes);
999 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1000 Host_Error("Mod_LoadZymoticModel: scene firstframe (%i) + framecount (%i) >= numposes (%i)\n", loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1001 if (loadmodel->animscenes[i].framerate < 0)
1002 Host_Error("Mod_LoadZymoticModel: scene framerate (%f) < 0\n", loadmodel->animscenes[i].framerate);
1010 // zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1011 loadmodel->zymdata_poses = Mem_Alloc(loadmodel->mempool, pheader->lump_poses.length);
1012 poses = (void *) (pheader->lump_poses.start + pbase);
1013 for (i = 0;i < pheader->lump_poses.length / 4;i++)
1014 loadmodel->zymdata_poses[i] = BigFloat(poses[i]);
1020 // zymlump_t lump_bones; // zymbone_t bone[numbones];
1021 loadmodel->zymdata_bones = Mem_Alloc(loadmodel->mempool, pheader->numbones * sizeof(zymbone_t));
1022 bone = (void *) (pheader->lump_bones.start + pbase);
1023 for (i = 0;i < pheader->numbones;i++)
1025 memcpy(loadmodel->zymdata_bones[i].name, bone[i].name, sizeof(bone[i].name));
1026 loadmodel->zymdata_bones[i].flags = BigLong(bone[i].flags);
1027 loadmodel->zymdata_bones[i].parent = BigLong(bone[i].parent);
1028 if (loadmodel->zymdata_bones[i].parent >= i)
1029 Host_Error("Mod_LoadZymoticModel: bone[%i].parent >= %i in %s\n", i, i, loadmodel->name);
1035 // zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1036 loadmodel->zymdata_vertbonecounts = Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1037 bonecount = (void *) (pheader->lump_vertbonecounts.start + pbase);
1038 for (i = 0;i < pheader->numverts;i++)
1040 loadmodel->zymdata_vertbonecounts[i] = BigLong(bonecount[i]);
1041 if (loadmodel->zymdata_vertbonecounts[i] < 1)
1042 Host_Error("Mod_LoadZymoticModel: bone vertex count < 1 in %s\n", loadmodel->name);
1048 zymvertex_t *vertdata;
1049 // zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1050 loadmodel->zymdata_verts = Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1051 vertdata = (void *) (pheader->lump_verts.start + pbase);
1052 for (i = 0;i < pheader->lump_verts.length / (int) sizeof(zymvertex_t);i++)
1054 loadmodel->zymdata_verts[i].bonenum = BigLong(vertdata[i].bonenum);
1055 loadmodel->zymdata_verts[i].origin[0] = BigFloat(vertdata[i].origin[0]);
1056 loadmodel->zymdata_verts[i].origin[1] = BigFloat(vertdata[i].origin[1]);
1057 loadmodel->zymdata_verts[i].origin[2] = BigFloat(vertdata[i].origin[2]);
1063 float *intexcoord, *outtexcoord;
1064 // zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1065 loadmodel->zymdata_texcoords = outtexcoord = Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(float[4]));
1066 intexcoord = (void *) (pheader->lump_texcoords.start + pbase);
1067 for (i = 0;i < pheader->numverts;i++)
1069 outtexcoord[i*4+0] = BigFloat(intexcoord[i*2+0]);
1070 // flip T coordinate for OpenGL
1071 outtexcoord[i*4+1] = 1 - BigFloat(intexcoord[i*2+1]);
1076 int i, count, *renderlist, *renderlistend, *outrenderlist;
1077 // 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)
1078 loadmodel->zymdata_renderlist = Mem_Alloc(loadmodel->mempool, pheader->lump_render.length);
1079 // byteswap, validate, and swap winding order of tris
1080 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1081 if (pheader->lump_render.length != count)
1082 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);
1083 outrenderlist = loadmodel->zymdata_renderlist = Mem_Alloc(loadmodel->mempool, count);
1084 renderlist = (void *) (pheader->lump_render.start + pbase);
1085 renderlistend = (void *) ((qbyte *) renderlist + pheader->lump_render.length);
1086 for (i = 0;i < pheader->numshaders;i++)
1088 if (renderlist >= renderlistend)
1089 Host_Error("Mod_LoadZymoticModel: corrupt renderlist in %s (wrong size)\n", loadmodel->name);
1090 count = BigLong(*renderlist);renderlist++;
1091 if (renderlist + count * 3 > renderlistend)
1092 Host_Error("Mod_LoadZymoticModel: corrupt renderlist in %s (wrong size)\n", loadmodel->name);
1093 *outrenderlist++ = count;
1096 outrenderlist[2] = BigLong(renderlist[0]);
1097 outrenderlist[1] = BigLong(renderlist[1]);
1098 outrenderlist[0] = BigLong(renderlist[2]);
1099 if ((unsigned int)outrenderlist[0] >= (unsigned int)pheader->numverts
1100 || (unsigned int)outrenderlist[1] >= (unsigned int)pheader->numverts
1101 || (unsigned int)outrenderlist[2] >= (unsigned int)pheader->numverts)
1102 Host_Error("Mod_LoadZymoticModel: corrupt renderlist in %s (out of bounds index)\n", loadmodel->name);
1112 // zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1113 loadmodel->zymdata_textures = Mem_Alloc(loadmodel->mempool, pheader->numshaders * sizeof(rtexture_t *));
1114 shadername = (void *) (pheader->lump_shaders.start + pbase);
1115 for (i = 0;i < pheader->numshaders;i++)
1116 loadmodel->zymdata_textures[i] = loadtextureimage(loadmodel->texturepool, shadername + i * 32, 0, 0, true, TEXF_ALPHA | TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0));
1120 // zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1121 loadmodel->zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1122 memcpy(loadmodel->zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);