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 void Mod_CalcAliasModelBBoxes (void)
35 float dist, yawradius, radius;
38 VectorClear(loadmodel->normalmins);
39 VectorClear(loadmodel->normalmaxs);
42 for (meshnum = 0, mesh = loadmodel->aliasdata_meshes;meshnum < loadmodel->aliasnum_meshes;meshnum++, mesh++)
44 for (vnum = 0, v = mesh->data_aliasvertex;vnum < mesh->num_vertices * mesh->num_frames;vnum++, v++)
46 if (loadmodel->normalmins[0] > v->origin[0]) loadmodel->normalmins[0] = v->origin[0];
47 if (loadmodel->normalmins[1] > v->origin[1]) loadmodel->normalmins[1] = v->origin[1];
48 if (loadmodel->normalmins[2] > v->origin[2]) loadmodel->normalmins[2] = v->origin[2];
49 if (loadmodel->normalmaxs[0] < v->origin[0]) loadmodel->normalmaxs[0] = v->origin[0];
50 if (loadmodel->normalmaxs[1] < v->origin[1]) loadmodel->normalmaxs[1] = v->origin[1];
51 if (loadmodel->normalmaxs[2] < v->origin[2]) loadmodel->normalmaxs[2] = v->origin[2];
52 dist = v->origin[0] * v->origin[0] + v->origin[1] * v->origin[1];
55 dist += v->origin[2] * v->origin[2];
60 radius = sqrt(radius);
61 yawradius = sqrt(yawradius);
62 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -yawradius;
63 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = yawradius;
64 loadmodel->yawmins[2] = loadmodel->normalmins[2];
65 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
66 loadmodel->rotatedmins[0] = loadmodel->rotatedmins[1] = loadmodel->rotatedmins[2] = -radius;
67 loadmodel->rotatedmaxs[0] = loadmodel->rotatedmaxs[1] = loadmodel->rotatedmaxs[2] = radius;
68 loadmodel->radius = radius;
69 loadmodel->radius2 = radius * radius;
72 static void Mod_ConvertAliasVerts (int inverts, vec3_t scale, vec3_t translate, trivertx_t *v, aliasvertex_t *out, int *vertremap)
76 for (i = 0;i < inverts;i++)
78 if (vertremap[i] < 0 && vertremap[i+inverts] < 0) // only used vertices need apply...
80 temp[0] = v[i].v[0] * scale[0] + translate[0];
81 temp[1] = v[i].v[1] * scale[1] + translate[1];
82 temp[2] = v[i].v[2] * scale[2] + translate[2];
83 j = vertremap[i]; // not onseam
85 VectorCopy(temp, out[j].origin);
86 j = vertremap[i+inverts]; // onseam
88 VectorCopy(temp, out[j].origin);
92 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)
95 for (i = 0;i < numverts;i++)
96 VectorCopy(vertices[i].origin, &vertexbuffer[i * 3]);
97 Mod_BuildTextureVectorsAndNormals(numverts, numtriangles, vertexbuffer, texcoords, elements, svectorsbuffer, tvectorsbuffer, normalsbuffer);
98 for (i = 0;i < numverts;i++)
100 vertices[i].normal[0] = normalsbuffer[i * 3 + 0];
101 vertices[i].normal[1] = normalsbuffer[i * 3 + 1];
102 vertices[i].normal[2] = normalsbuffer[i * 3 + 2];
103 vertices[i].svector[0] = svectorsbuffer[i * 3 + 0];
104 vertices[i].svector[1] = svectorsbuffer[i * 3 + 1];
105 vertices[i].svector[2] = svectorsbuffer[i * 3 + 2];
109 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, int *vertremap)
111 int i, f, pose, groupframes;
112 float interval, *vertexbuffer, *svectorsbuffer, *tvectorsbuffer, *normalsbuffer;
113 daliasframetype_t *pframetype;
114 daliasframe_t *pinframe;
115 daliasgroup_t *group;
116 daliasinterval_t *intervals;
119 scene = loadmodel->animscenes;
120 vertexbuffer = Mem_Alloc(tempmempool, outverts * sizeof(float[3+3+3+3]));
121 svectorsbuffer = vertexbuffer + outverts * 3;
122 tvectorsbuffer = svectorsbuffer + outverts * 3;
123 normalsbuffer = tvectorsbuffer + outverts * 3;
124 for (f = 0;f < loadmodel->numframes;f++)
126 pframetype = (daliasframetype_t *)datapointer;
127 datapointer += sizeof(daliasframetype_t);
128 if (LittleLong (pframetype->type) == ALIAS_SINGLE)
130 // a single frame is still treated as a group
137 group = (daliasgroup_t *)datapointer;
138 datapointer += sizeof(daliasgroup_t);
139 groupframes = LittleLong (group->numframes);
141 // intervals (time per frame)
142 intervals = (daliasinterval_t *)datapointer;
143 datapointer += sizeof(daliasinterval_t) * groupframes;
145 interval = LittleFloat (intervals->interval); // FIXME: support variable framerate groups
146 if (interval < 0.01f)
147 Host_Error("Mod_MDL_LoadFrames: invalid interval");
150 // get scene name from first frame
151 pinframe = (daliasframe_t *)datapointer;
153 strcpy(scene->name, pinframe->name);
154 scene->firstframe = pose;
155 scene->framecount = groupframes;
156 scene->framerate = 1.0f / interval;
161 for (i = 0;i < groupframes;i++)
163 pinframe = (daliasframe_t *)datapointer;
164 datapointer += sizeof(daliasframe_t);
165 Mod_ConvertAliasVerts(inverts, scale, translate, (trivertx_t *)datapointer, posedata + pose * outverts, vertremap);
166 Mod_BuildAliasVertexTextureVectors(outverts, posedata + pose * outverts, texcoords, vertexbuffer, svectorsbuffer, tvectorsbuffer, normalsbuffer, numtris, elements);
167 datapointer += sizeof(trivertx_t) * inverts;
171 Mem_Free(vertexbuffer);
174 void Mod_BuildAliasSkinFromSkinFrame(aliasskin_t *skin, skinframe_t *skinframe)
178 // fog texture only exists if some pixels are transparent...
179 if (skinframe->fog != NULL)
180 skin->flags |= ALIASSKIN_TRANSPARENT;
181 // fog and gloss layers always exist
182 skin->num_layers = 2;
183 if (skinframe->glow != NULL)
185 if (skinframe->merged != NULL)
186 skin->num_layers += 2;
187 if (skinframe->base != NULL)
188 skin->num_layers += 2;
189 if (skinframe->pants != NULL)
190 skin->num_layers += 2;
191 if (skinframe->shirt != NULL)
192 skin->num_layers += 2;
193 layer = skin->data_layers = Mem_Alloc(loadmodel->mempool, skin->num_layers * sizeof(aliaslayer_t));
194 if (skinframe->glow != NULL)
197 layer->texture = skinframe->glow;
200 if (skinframe->merged != NULL)
202 layer->flags = ALIASLAYER_NODRAW_IF_COLORMAPPED | ALIASLAYER_DIFFUSE;
203 if (skinframe->glow != NULL)
204 layer->flags |= ALIASLAYER_ADD;
205 layer->texture = skinframe->merged;
206 layer->nmap = skinframe->nmap;
209 if (skinframe->base != NULL)
211 layer->flags = (skinframe->merged != NULL ? ALIASLAYER_NODRAW_IF_NOTCOLORMAPPED : 0) | ALIASLAYER_DIFFUSE;
212 if (skinframe->glow != NULL)
213 layer->flags |= ALIASLAYER_ADD;
214 layer->texture = skinframe->base;
215 layer->nmap = skinframe->nmap;
218 if (skinframe->pants != NULL)
220 layer->flags = ALIASLAYER_NODRAW_IF_NOTCOLORMAPPED | ALIASLAYER_DIFFUSE | ALIASLAYER_COLORMAP_SHIRT;
221 if (skinframe->glow != NULL || skinframe->base != NULL)
222 layer->flags |= ALIASLAYER_ADD;
223 layer->texture = skinframe->pants;
224 layer->nmap = skinframe->nmap;
227 if (skinframe->shirt != NULL)
229 layer->flags = ALIASLAYER_NODRAW_IF_NOTCOLORMAPPED | ALIASLAYER_DIFFUSE | ALIASLAYER_COLORMAP_SHIRT;
230 if (skinframe->glow != NULL || skinframe->base != NULL || skinframe->pants != NULL)
231 layer->flags |= ALIASLAYER_ADD;
232 layer->texture = skinframe->shirt;
233 layer->nmap = skinframe->nmap;
236 layer->flags = ALIASLAYER_FOG;
237 layer->texture = skinframe->fog;
239 layer->flags = ALIASLAYER_DRAW_PER_LIGHT | ALIASLAYER_SPECULAR;
240 layer->texture = skinframe->gloss;
241 layer->nmap = skinframe->nmap;
243 if (skinframe->merged != NULL)
245 layer->flags = ALIASLAYER_DRAW_PER_LIGHT | ALIASLAYER_NODRAW_IF_COLORMAPPED | ALIASLAYER_DIFFUSE;
246 layer->texture = skinframe->merged;
247 layer->nmap = skinframe->nmap;
250 if (skinframe->base != NULL)
252 layer->flags = ALIASLAYER_DRAW_PER_LIGHT | (skinframe->merged != NULL ? ALIASLAYER_NODRAW_IF_NOTCOLORMAPPED : 0) | ALIASLAYER_DIFFUSE;
253 layer->texture = skinframe->base;
254 layer->nmap = skinframe->nmap;
257 if (skinframe->pants != NULL)
259 layer->flags = ALIASLAYER_DRAW_PER_LIGHT | ALIASLAYER_NODRAW_IF_NOTCOLORMAPPED | ALIASLAYER_DIFFUSE | ALIASLAYER_COLORMAP_PANTS;
260 layer->texture = skinframe->pants;
261 layer->nmap = skinframe->nmap;
264 if (skinframe->shirt != NULL)
266 layer->flags = ALIASLAYER_DRAW_PER_LIGHT | ALIASLAYER_NODRAW_IF_NOTCOLORMAPPED | ALIASLAYER_DIFFUSE | ALIASLAYER_COLORMAP_SHIRT;
267 layer->texture = skinframe->shirt;
268 layer->nmap = skinframe->nmap;
273 void Mod_BuildMDLMD2MeshInfo(int numverts, int numtris, int *elements, float *texcoord2f, aliasvertex_t *posedata)
278 loadmodel->aliasnum_meshes = 1;
279 mesh = loadmodel->aliasdata_meshes = Mem_Alloc(loadmodel->mempool, loadmodel->aliasnum_meshes * sizeof(aliasmesh_t));
281 mesh->num_frames = 0;
282 for (i = 0;i < loadmodel->numframes;i++)
283 mesh->num_frames += loadmodel->animscenes[i].framecount;
284 for (i = 0;i < loadmodel->numskins;i++)
285 mesh->num_skins += loadmodel->skinscenes[i].framecount;
286 mesh->num_triangles = numtris;
287 mesh->num_vertices = numverts;
288 mesh->data_skins = Mem_Alloc(loadmodel->mempool, mesh->num_skins * sizeof(aliasskin_t));
289 mesh->data_element3i = elements;
290 mesh->data_neighbor3i = Mem_Alloc(loadmodel->mempool, numtris * sizeof(int[3]));
291 Mod_ValidateElements(mesh->data_element3i, mesh->num_triangles, mesh->num_vertices, __FILE__, __LINE__);
292 Mod_BuildTriangleNeighbors(mesh->data_neighbor3i, mesh->data_element3i, mesh->num_triangles);
293 mesh->data_texcoord2f = texcoord2f;
294 mesh->data_aliasvertex = posedata;
295 for (i = 0;i < mesh->num_skins;i++)
296 Mod_BuildAliasSkinFromSkinFrame(mesh->data_skins + i, loadmodel->skinframes + i);
297 Mod_CalcAliasModelBBoxes();
300 #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);
301 #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);
302 extern void R_Model_Alias_Draw(entity_render_t *ent);
303 extern void R_Model_Alias_DrawFakeShadow(entity_render_t *ent);
304 extern void R_Model_Alias_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius);
305 extern void R_Model_Alias_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltofilter, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz);
306 void Mod_LoadQ1AliasModel (model_t *mod, void *buffer)
308 int i, j, version, totalposes, totalskins, skinwidth, skinheight, totalverts, groupframes, groupskins, *elements, numverts, numtris;
309 float scales, scalet, scale[3], translate[3], interval, *texcoords;
311 stvert_t *pinstverts;
312 dtriangle_t *pintriangles;
313 daliasskintype_t *pinskintype;
314 daliasskingroup_t *pinskingroup;
315 daliasskininterval_t *pinskinintervals;
316 daliasframetype_t *pinframetype;
317 daliasgroup_t *pinframegroup;
318 aliasvertex_t *posedata;
319 qbyte *datapointer, *startframes, *startskins;
320 char name[MAX_QPATH];
321 skinframe_t tempskinframe;
322 animscene_t *tempskinscenes;
323 skinframe_t *tempskinframes;
325 int *vertonseam, *vertusage, *vertremap, *temptris;
327 datapointer = buffer;
328 pinmodel = (mdl_t *)datapointer;
329 datapointer += sizeof(mdl_t);
331 version = LittleLong (pinmodel->version);
332 if (version != ALIAS_VERSION)
333 Host_Error ("%s has wrong version number (%i should be %i)",
334 loadmodel->name, version, ALIAS_VERSION);
336 loadmodel->type = mod_alias;
337 loadmodel->aliastype = ALIASTYPE_ALIAS;
338 loadmodel->DrawSky = NULL;
339 loadmodel->Draw = R_Model_Alias_Draw;
340 loadmodel->DrawFakeShadow = R_Model_Alias_DrawFakeShadow;
341 loadmodel->DrawShadowVolume = R_Model_Alias_DrawShadowVolume;
342 loadmodel->DrawLight = R_Model_Alias_DrawLight;
344 loadmodel->numskins = LittleLong(pinmodel->numskins);
345 BOUNDI(loadmodel->numskins,0,256);
346 skinwidth = LittleLong (pinmodel->skinwidth);
347 BOUNDI(skinwidth,0,4096);
348 skinheight = LittleLong (pinmodel->skinheight);
349 BOUNDI(skinheight,0,4096);
350 numverts = LittleLong(pinmodel->numverts);
351 BOUNDI(numverts,0,65536);
352 numtris = LittleLong(pinmodel->numtris);
353 BOUNDI(numtris,0,65536 / 3); // max elements limit, rather than max triangles limit
354 loadmodel->numframes = LittleLong(pinmodel->numframes);
355 BOUNDI(loadmodel->numframes,0,65536);
356 loadmodel->synctype = LittleLong (pinmodel->synctype);
357 BOUNDI(loadmodel->synctype,0,2);
358 loadmodel->flags = LittleLong (pinmodel->flags);
360 for (i = 0;i < 3;i++)
362 scale[i] = LittleFloat (pinmodel->scale[i]);
363 translate[i] = LittleFloat (pinmodel->scale_origin[i]);
366 startskins = datapointer;
368 for (i = 0;i < loadmodel->numskins;i++)
370 pinskintype = (daliasskintype_t *)datapointer;
371 datapointer += sizeof(daliasskintype_t);
372 if (LittleLong(pinskintype->type) == ALIAS_SKIN_SINGLE)
376 pinskingroup = (daliasskingroup_t *)datapointer;
377 datapointer += sizeof(daliasskingroup_t);
378 groupskins = LittleLong(pinskingroup->numskins);
379 datapointer += sizeof(daliasskininterval_t) * groupskins;
382 for (j = 0;j < groupskins;j++)
384 datapointer += skinwidth * skinheight;
389 pinstverts = (stvert_t *)datapointer;
390 datapointer += sizeof(stvert_t) * numverts;
392 pintriangles = (dtriangle_t *)datapointer;
393 datapointer += sizeof(dtriangle_t) * numtris;
395 startframes = datapointer;
397 for (i = 0;i < loadmodel->numframes;i++)
399 pinframetype = (daliasframetype_t *)datapointer;
400 datapointer += sizeof(daliasframetype_t);
401 if (LittleLong (pinframetype->type) == ALIAS_SINGLE)
405 pinframegroup = (daliasgroup_t *)datapointer;
406 datapointer += sizeof(daliasgroup_t);
407 groupframes = LittleLong(pinframegroup->numframes);
408 datapointer += sizeof(daliasinterval_t) * groupframes;
411 for (j = 0;j < groupframes;j++)
413 datapointer += sizeof(daliasframe_t);
414 datapointer += sizeof(trivertx_t) * numverts;
420 loadmodel->skinscenes = Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
421 loadmodel->skinframes = Mem_Alloc(loadmodel->mempool, totalskins * sizeof(skinframe_t));
423 datapointer = startskins;
424 for (i = 0;i < loadmodel->numskins;i++)
426 pinskintype = (daliasskintype_t *)datapointer;
427 datapointer += sizeof(daliasskintype_t);
429 if (pinskintype->type == ALIAS_SKIN_SINGLE)
436 pinskingroup = (daliasskingroup_t *)datapointer;
437 datapointer += sizeof(daliasskingroup_t);
439 groupskins = LittleLong (pinskingroup->numskins);
441 pinskinintervals = (daliasskininterval_t *)datapointer;
442 datapointer += sizeof(daliasskininterval_t) * groupskins;
444 interval = LittleFloat(pinskinintervals[0].interval);
445 if (interval < 0.01f)
446 Host_Error("Mod_LoadQ1AliasModel: invalid interval\n");
449 sprintf(loadmodel->skinscenes[i].name, "skin %i", i);
450 loadmodel->skinscenes[i].firstframe = totalskins;
451 loadmodel->skinscenes[i].framecount = groupskins;
452 loadmodel->skinscenes[i].framerate = 1.0f / interval;
453 loadmodel->skinscenes[i].loop = true;
455 for (j = 0;j < groupskins;j++)
458 sprintf (name, "%s_%i_%i", loadmodel->name, i, j);
460 sprintf (name, "%s_%i", loadmodel->name, i);
461 if (!Mod_LoadSkinFrame(loadmodel->skinframes + totalskins, name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA, true, false, true))
462 Mod_LoadSkinFrame_Internal(loadmodel->skinframes + totalskins, name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA, true, false, true, (qbyte *)datapointer, skinwidth, skinheight);
463 datapointer += skinwidth * skinheight;
467 // check for skins that don't exist in the model, but do exist as external images
468 // (this was added because yummyluv kept pestering me about support for it)
471 sprintf (name, "%s_%i", loadmodel->name, loadmodel->numskins);
472 if (Mod_LoadSkinFrame (&tempskinframe, name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA, true, false, true))
474 // expand the arrays to make room
475 tempskinscenes = loadmodel->skinscenes;
476 tempskinframes = loadmodel->skinframes;
477 loadmodel->skinscenes = Mem_Alloc(loadmodel->mempool, (loadmodel->numskins + 1) * sizeof(animscene_t));
478 loadmodel->skinframes = Mem_Alloc(loadmodel->mempool, (totalskins + 1) * sizeof(skinframe_t));
479 memcpy(loadmodel->skinscenes, tempskinscenes, loadmodel->numskins * sizeof(animscene_t));
480 memcpy(loadmodel->skinframes, tempskinframes, totalskins * sizeof(skinframe_t));
481 Mem_Free(tempskinscenes);
482 Mem_Free(tempskinframes);
483 // store the info about the new skin
484 strcpy(loadmodel->skinscenes[loadmodel->numskins].name, name);
485 loadmodel->skinscenes[loadmodel->numskins].firstframe = totalskins;
486 loadmodel->skinscenes[loadmodel->numskins].framecount = 1;
487 loadmodel->skinscenes[loadmodel->numskins].framerate = 10.0f;
488 loadmodel->skinscenes[loadmodel->numskins].loop = true;
489 loadmodel->skinframes[totalskins] = tempskinframe;
490 loadmodel->numskins++;
497 // store texture coordinates into temporary array, they will be stored after usage is determined (triangle data)
498 vertst = Mem_Alloc(tempmempool, numverts * 2 * sizeof(float[2]));
499 vertonseam = Mem_Alloc(tempmempool, numverts * sizeof(int));
500 vertusage = Mem_Alloc(tempmempool, numverts * 2 * sizeof(int));
501 vertremap = Mem_Alloc(tempmempool, numverts * 2 * sizeof(int));
502 temptris = Mem_Alloc(tempmempool, numtris * sizeof(int[3]));
504 scales = 1.0 / skinwidth;
505 scalet = 1.0 / skinheight;
506 for (i = 0;i < numverts;i++)
508 vertonseam[i] = LittleLong(pinstverts[i].onseam);
509 vertst[i*2+0] = (LittleLong(pinstverts[i].s) + 0.5) * scales;
510 vertst[i*2+1] = (LittleLong(pinstverts[i].t) + 0.5) * scalet;
511 vertst[(i+numverts)*2+0] = vertst[i*2+0] + 0.5;
512 vertst[(i+numverts)*2+1] = vertst[i*2+1];
514 vertusage[i+numverts] = 0;
517 // load triangle data
518 elements = Mem_Alloc(loadmodel->mempool, sizeof(int[3]) * numtris);
520 // count the vertices used
521 for (i = 0;i < numverts*2;i++)
523 for (i = 0;i < numtris;i++)
525 temptris[i*3+0] = LittleLong(pintriangles[i].vertindex[0]);
526 temptris[i*3+1] = LittleLong(pintriangles[i].vertindex[1]);
527 temptris[i*3+2] = LittleLong(pintriangles[i].vertindex[2]);
528 if (!LittleLong(pintriangles[i].facesfront)) // backface
530 if (vertonseam[temptris[i*3+0]]) temptris[i*3+0] += numverts;
531 if (vertonseam[temptris[i*3+1]]) temptris[i*3+1] += numverts;
532 if (vertonseam[temptris[i*3+2]]) temptris[i*3+2] += numverts;
534 vertusage[temptris[i*3+0]]++;
535 vertusage[temptris[i*3+1]]++;
536 vertusage[temptris[i*3+2]]++;
538 // build remapping table and compact array
540 for (i = 0;i < numverts*2;i++)
544 vertremap[i] = totalverts;
545 vertst[totalverts*2+0] = vertst[i*2+0];
546 vertst[totalverts*2+1] = vertst[i*2+1];
550 vertremap[i] = -1; // not used at all
552 // remap the triangle references
553 for (i = 0;i < numtris * 3;i++)
554 elements[i] = vertremap[temptris[i]];
555 // store the texture coordinates
556 texcoords = Mem_Alloc(loadmodel->mempool, sizeof(float[2]) * totalverts);
557 for (i = 0;i < totalverts;i++)
559 texcoords[i*2+0] = vertst[i*2+0];
560 texcoords[i*2+1] = vertst[i*2+1];
564 loadmodel->animscenes = Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
565 posedata = Mem_Alloc(loadmodel->mempool, sizeof(aliasvertex_t) * totalposes * totalverts);
566 Mod_MDL_LoadFrames (startframes, numverts, totalverts, scale, translate, texcoords, posedata, numtris, elements, vertremap);
567 Mod_BuildMDLMD2MeshInfo(totalverts, numtris, elements, texcoords, posedata);
570 Mem_Free(vertonseam);
576 static void Mod_MD2_ConvertVerts (vec3_t scale, vec3_t translate, trivertx_t *v, aliasvertex_t *out, int numverts, int *vertremap)
580 for (i = 0;i < numverts;i++)
582 in = v + vertremap[i];
583 out[i].origin[0] = in->v[0] * scale[0] + translate[0];
584 out[i].origin[1] = in->v[1] * scale[1] + translate[1];
585 out[i].origin[2] = in->v[2] * scale[2] + translate[2];
589 void Mod_LoadQ2AliasModel (model_t *mod, void *buffer)
591 int i, j, k, hashindex, num, numxyz, numst, xyz, st, skinwidth, skinheight, *vertremap, version, end, *elements, numverts, numtris;
592 float *stverts, s, t, scale[3], translate[3], *vertexbuffer, *svectorsbuffer, *tvectorsbuffer, *normalsbuffer, *texcoords;
593 aliasvertex_t *posedata;
595 qbyte *base, *datapointer;
596 md2frame_t *pinframe;
598 md2triangle_t *intri;
599 unsigned short *inst;
602 struct md2verthash_s *next;
606 *hash, **md2verthash, *md2verthashdata;
611 version = LittleLong (pinmodel->version);
612 if (version != MD2ALIAS_VERSION)
613 Host_Error ("%s has wrong version number (%i should be %i)",
614 loadmodel->name, version, MD2ALIAS_VERSION);
616 loadmodel->type = mod_alias;
617 loadmodel->aliastype = ALIASTYPE_ALIAS;
618 loadmodel->DrawSky = NULL;
619 loadmodel->Draw = R_Model_Alias_Draw;
620 loadmodel->DrawFakeShadow = R_Model_Alias_DrawFakeShadow;
621 loadmodel->DrawShadowVolume = R_Model_Alias_DrawShadowVolume;
622 loadmodel->DrawLight = R_Model_Alias_DrawLight;
624 if (LittleLong(pinmodel->num_tris < 1) || LittleLong(pinmodel->num_tris) > (65536 / 3))
625 Host_Error ("%s has invalid number of triangles: %i", loadmodel->name, LittleLong(pinmodel->num_tris));
626 if (LittleLong(pinmodel->num_xyz < 1) || LittleLong(pinmodel->num_xyz) > 65536)
627 Host_Error ("%s has invalid number of vertices: %i", loadmodel->name, LittleLong(pinmodel->num_xyz));
628 if (LittleLong(pinmodel->num_frames < 1) || LittleLong(pinmodel->num_frames) > 65536)
629 Host_Error ("%s has invalid number of frames: %i", loadmodel->name, LittleLong(pinmodel->num_frames));
630 if (LittleLong(pinmodel->num_skins < 0) || LittleLong(pinmodel->num_skins) > 256)
631 Host_Error ("%s has invalid number of skins: %i", loadmodel->name, LittleLong(pinmodel->num_skins));
633 end = LittleLong(pinmodel->ofs_end);
634 if (LittleLong(pinmodel->num_skins) >= 1 && (LittleLong(pinmodel->ofs_skins <= 0) || LittleLong(pinmodel->ofs_skins) >= end))
635 Host_Error ("%s is not a valid model", loadmodel->name);
636 if (LittleLong(pinmodel->ofs_st <= 0) || LittleLong(pinmodel->ofs_st) >= end)
637 Host_Error ("%s is not a valid model", loadmodel->name);
638 if (LittleLong(pinmodel->ofs_tris <= 0) || LittleLong(pinmodel->ofs_tris) >= end)
639 Host_Error ("%s is not a valid model", loadmodel->name);
640 if (LittleLong(pinmodel->ofs_frames <= 0) || LittleLong(pinmodel->ofs_frames) >= end)
641 Host_Error ("%s is not a valid model", loadmodel->name);
642 if (LittleLong(pinmodel->ofs_glcmds <= 0) || LittleLong(pinmodel->ofs_glcmds) >= end)
643 Host_Error ("%s is not a valid model", loadmodel->name);
645 loadmodel->numskins = LittleLong(pinmodel->num_skins);
646 numxyz = LittleLong(pinmodel->num_xyz);
647 numst = LittleLong(pinmodel->num_st);
648 numtris = LittleLong(pinmodel->num_tris);
649 loadmodel->numframes = LittleLong(pinmodel->num_frames);
651 loadmodel->flags = 0; // there are no MD2 flags
652 loadmodel->synctype = ST_RAND;
655 inskin = (void*)(base + LittleLong(pinmodel->ofs_skins));
656 if (loadmodel->numskins)
658 loadmodel->skinscenes = Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numskins + sizeof(skinframe_t) * loadmodel->numskins);
659 loadmodel->skinframes = (void *)(loadmodel->skinscenes + loadmodel->numskins);
660 for (i = 0;i < loadmodel->numskins;i++)
662 loadmodel->skinscenes[i].firstframe = i;
663 loadmodel->skinscenes[i].framecount = 1;
664 loadmodel->skinscenes[i].loop = true;
665 loadmodel->skinscenes[i].framerate = 10;
666 Mod_LoadSkinFrame (loadmodel->skinframes + i, inskin, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE, true, false, true);
667 inskin += MD2_SKINNAME;
671 // load the triangles and stvert data
672 inst = (void*)(base + LittleLong(pinmodel->ofs_st));
673 intri = (void*)(base + LittleLong(pinmodel->ofs_tris));
674 skinwidth = LittleLong(pinmodel->skinwidth);
675 skinheight = LittleLong(pinmodel->skinheight);
677 stverts = Mem_Alloc(tempmempool, numst * sizeof(float[2]));
678 s = 1.0f / skinwidth;
679 t = 1.0f / skinheight;
680 for (i = 0;i < numst;i++)
682 j = (unsigned short) LittleShort(inst[i*2+0]);
683 k = (unsigned short) LittleShort(inst[i*2+1]);
684 if (j >= skinwidth || k >= skinheight)
687 Host_Error("Mod_MD2_LoadGeometry: invalid skin coordinate (%i %i) on vert %i of model %s\n", j, k, i, loadmodel->name);
689 stverts[i*2+0] = j * s;
690 stverts[i*2+1] = k * t;
693 md2verthash = Mem_Alloc(tempmempool, 256 * sizeof(hash));
694 md2verthashdata = Mem_Alloc(tempmempool, numtris * 3 * sizeof(*hash));
695 // swap the triangle list
697 elements = Mem_Alloc(loadmodel->mempool, numtris * sizeof(int[3]));
698 for (i = 0;i < numtris;i++)
700 for (j = 0;j < 3;j++)
702 xyz = (unsigned short) LittleShort (intri[i].index_xyz[j]);
703 st = (unsigned short) LittleShort (intri[i].index_st[j]);
704 if (xyz >= numxyz || st >= numst)
706 Mem_Free(md2verthash);
707 Mem_Free(md2verthashdata);
710 Host_Error("Mod_MD2_LoadGeometry: invalid xyz index (%i) on triangle %i of model %s\n", xyz, i, loadmodel->name);
712 Host_Error("Mod_MD2_LoadGeometry: invalid st index (%i) on triangle %i of model %s\n", st, i, loadmodel->name);
716 hashindex = (xyz * 17 + st) & 255;
717 for (hash = md2verthash[hashindex];hash;hash = hash->next)
718 if (hash->xyz == xyz && hash->st[0] == s && hash->st[1] == t)
722 hash = md2verthashdata + num++;
726 hash->next = md2verthash[hashindex];
727 md2verthash[hashindex] = hash;
729 elements[i*3+j] = (hash - md2verthashdata);
736 vertremap = Mem_Alloc(loadmodel->mempool, num * sizeof(int));
737 texcoords = Mem_Alloc(loadmodel->mempool, num * sizeof(float[2]));
738 for (i = 0;i < num;i++)
740 hash = md2verthashdata + i;
741 vertremap[i] = hash->xyz;
742 texcoords[i*2+0] = hash->st[0];
743 texcoords[i*2+1] = hash->st[1];
746 Mem_Free(md2verthash);
747 Mem_Free(md2verthashdata);
750 datapointer = (base + LittleLong(pinmodel->ofs_frames));
751 loadmodel->animscenes = Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
752 posedata = Mem_Alloc(loadmodel->mempool, numverts * loadmodel->numframes * sizeof(trivertx_t));
754 vertexbuffer = Mem_Alloc(tempmempool, numverts * sizeof(float[3+3+3+3]));
755 svectorsbuffer = vertexbuffer + numverts * 3;
756 tvectorsbuffer = svectorsbuffer + numverts * 3;
757 normalsbuffer = tvectorsbuffer + numverts * 3;
758 for (i = 0;i < loadmodel->numframes;i++)
760 pinframe = (md2frame_t *)datapointer;
761 datapointer += sizeof(md2frame_t);
762 for (j = 0;j < 3;j++)
764 scale[j] = LittleFloat(pinframe->scale[j]);
765 translate[j] = LittleFloat(pinframe->translate[j]);
767 Mod_MD2_ConvertVerts(scale, translate, (void *)datapointer, posedata + i * numverts, numverts, vertremap);
768 Mod_BuildAliasVertexTextureVectors(numverts, posedata + i * numverts, texcoords, vertexbuffer, svectorsbuffer, tvectorsbuffer, normalsbuffer, numtris, elements);
769 datapointer += numxyz * sizeof(trivertx_t);
771 strcpy(loadmodel->animscenes[i].name, pinframe->name);
772 loadmodel->animscenes[i].firstframe = i;
773 loadmodel->animscenes[i].framecount = 1;
774 loadmodel->animscenes[i].framerate = 10;
775 loadmodel->animscenes[i].loop = true;
777 Mem_Free(vertexbuffer);
781 Mod_BuildMDLMD2MeshInfo(numverts, numtris, elements, texcoords, posedata);
784 void Mod_LoadQ3AliasModel(model_t *mod, void *buffer)
787 float *vertexbuffer, *svectorsbuffer, *tvectorsbuffer, *normalsbuffer;
788 md3modelheader_t *pinmodel;
789 md3frameinfo_t *pinframe;
792 skinframe_t tempskinframe;
796 if (memcmp(pinmodel->identifier, "IDP3", 4))
797 Host_Error ("%s is not a MD3 (IDP3) file\n", loadmodel->name);
798 version = LittleLong (pinmodel->version);
799 if (version != MD3VERSION)
800 Host_Error ("%s has wrong version number (%i should be %i)",
801 loadmodel->name, version, MD3VERSION);
803 loadmodel->type = mod_alias;
804 loadmodel->aliastype = ALIASTYPE_ALIAS;
805 loadmodel->DrawSky = NULL;
806 loadmodel->Draw = R_Model_Alias_Draw;
807 loadmodel->DrawFakeShadow = R_Model_Alias_DrawFakeShadow;
808 loadmodel->DrawShadowVolume = R_Model_Alias_DrawShadowVolume;
809 loadmodel->DrawLight = R_Model_Alias_DrawLight;
810 loadmodel->flags = 0;
811 loadmodel->synctype = ST_RAND;
813 // set up some global info about the model
814 loadmodel->numframes = LittleLong(pinmodel->num_frames);
815 loadmodel->numskins = 1;
816 loadmodel->aliasnum_meshes = LittleLong(pinmodel->num_meshes);
817 loadmodel->skinscenes = Mem_Alloc(loadmodel->mempool, loadmodel->numskins * sizeof(animscene_t));
818 loadmodel->skinscenes[0].firstframe = 0;
819 loadmodel->skinscenes[0].framecount = 1;
820 loadmodel->skinscenes[0].loop = true;
821 loadmodel->skinscenes[0].framerate = 10;
824 loadmodel->animscenes = Mem_Alloc(loadmodel->mempool, loadmodel->numframes * sizeof(animscene_t));
825 for (i = 0, pinframe = (md3frameinfo_t *)((qbyte *)pinmodel + LittleLong(pinmodel->lump_frameinfo));i < loadmodel->numframes;i++, pinframe++)
827 strcpy(loadmodel->animscenes[i].name, pinframe->name);
828 loadmodel->animscenes[i].firstframe = i;
829 loadmodel->animscenes[i].framecount = 1;
830 loadmodel->animscenes[i].framerate = 10;
831 loadmodel->animscenes[i].loop = true;
834 // tags are not loaded yet
837 loadmodel->aliasdata_meshes = Mem_Alloc(loadmodel->mempool, loadmodel->aliasnum_meshes * sizeof(aliasmesh_t));
838 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)))
840 if (memcmp(pinmesh->identifier, "IDP3", 4))
841 Host_Error("Mod_LoadQ3AliasModel: invalid mesh identifier (not IDP3)\n");
842 mesh = loadmodel->aliasdata_meshes + i;
843 mesh->num_skins = loadmodel->numskins;
844 mesh->num_frames = LittleLong(pinmesh->num_frames);
845 mesh->num_vertices = LittleLong(pinmesh->num_vertices);
846 mesh->num_triangles = LittleLong(pinmesh->num_triangles);
847 mesh->data_skins = Mem_Alloc(loadmodel->mempool, mesh->num_skins * sizeof(aliasskin_t));
848 mesh->data_element3i = Mem_Alloc(loadmodel->mempool, mesh->num_triangles * sizeof(int[3]));
849 mesh->data_neighbor3i = Mem_Alloc(loadmodel->mempool, mesh->num_triangles * sizeof(int[3]));
850 mesh->data_texcoord2f = Mem_Alloc(loadmodel->mempool, mesh->num_vertices * sizeof(float[2]));
851 mesh->data_aliasvertex = Mem_Alloc(loadmodel->mempool, mesh->num_vertices * mesh->num_frames * sizeof(aliasvertex_t));
852 for (j = 0;j < mesh->num_triangles * 3;j++)
853 mesh->data_element3i[j] = LittleLong(((int *)((qbyte *)pinmesh + pinmesh->lump_elements))[j]);
854 for (j = 0;j < mesh->num_vertices;j++)
856 mesh->data_texcoord2f[j * 2 + 0] = LittleLong(((float *)((qbyte *)pinmesh + pinmesh->lump_texcoords))[j * 2 + 0]);
857 mesh->data_texcoord2f[j * 2 + 1] = LittleLong(((float *)((qbyte *)pinmesh + pinmesh->lump_texcoords))[j * 2 + 1]);
859 for (j = 0;j < mesh->num_vertices * mesh->num_frames;j++)
861 mesh->data_aliasvertex[j].origin[0] = LittleShort(((short *)((qbyte *)pinmesh + pinmesh->lump_framevertices))[j * 4 + 0]) * (1.0f / 64.0f);
862 mesh->data_aliasvertex[j].origin[1] = LittleShort(((short *)((qbyte *)pinmesh + pinmesh->lump_framevertices))[j * 4 + 1]) * (1.0f / 64.0f);
863 mesh->data_aliasvertex[j].origin[2] = LittleShort(((short *)((qbyte *)pinmesh + pinmesh->lump_framevertices))[j * 4 + 2]) * (1.0f / 64.0f);
865 vertexbuffer = Mem_Alloc(tempmempool, mesh->num_vertices * sizeof(float[3+3+3+3]));
866 svectorsbuffer = vertexbuffer + mesh->num_vertices * 3;
867 tvectorsbuffer = svectorsbuffer + mesh->num_vertices * 3;
868 normalsbuffer = tvectorsbuffer + mesh->num_vertices * 3;
869 for (j = 0;j < mesh->num_frames;j++)
870 Mod_BuildAliasVertexTextureVectors(mesh->num_vertices, mesh->data_aliasvertex + j * mesh->num_vertices, mesh->data_texcoord2f, vertexbuffer, svectorsbuffer, tvectorsbuffer, normalsbuffer, mesh->num_triangles, mesh->data_element3i);
871 Mem_Free(vertexbuffer);
873 memset(&tempskinframe, 0, sizeof(tempskinframe));
874 if (LittleLong(pinmesh->num_shaders) >= 1 && ((md3shader_t *)((qbyte *) pinmesh + pinmesh->lump_shaders))->name[0])
875 Mod_LoadSkinFrame (&tempskinframe, ((md3shader_t *)((qbyte *) pinmesh + pinmesh->lump_shaders))->name, (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_ALPHA | TEXF_PRECACHE, true, false, true);
876 Mod_ValidateElements(mesh->data_element3i, mesh->num_triangles, mesh->num_vertices, __FILE__, __LINE__);
877 Mod_BuildTriangleNeighbors(mesh->data_neighbor3i, mesh->data_element3i, mesh->num_triangles);
878 Mod_BuildAliasSkinFromSkinFrame(mesh->data_skins, &tempskinframe);
880 Mod_CalcAliasModelBBoxes();
883 extern void R_Model_Zymotic_DrawSky(entity_render_t *ent);
884 extern void R_Model_Zymotic_Draw(entity_render_t *ent);
885 extern void R_Model_Zymotic_DrawFakeShadow(entity_render_t *ent);
886 extern void R_Model_Zymotic_DrawShadowVolume(entity_render_t *ent, vec3_t relativelightorigin, float lightradius);
887 extern void R_Model_Zymotic_DrawLight(entity_render_t *ent, vec3_t relativelightorigin, vec3_t relativeeyeorigin, float lightradius, float *lightcolor, const matrix4x4_t *matrix_modeltofilter, const matrix4x4_t *matrix_modeltoattenuationxyz, const matrix4x4_t *matrix_modeltoattenuationz);
888 void Mod_LoadZymoticModel(model_t *mod, void *buffer)
890 zymtype1header_t *pinmodel, *pheader;
893 pinmodel = (void *)buffer;
895 if (memcmp(pinmodel->id, "ZYMOTICMODEL", 12))
896 Host_Error ("Mod_LoadZymoticModel: %s is not a zymotic model\n");
897 if (BigLong(pinmodel->type) != 1)
898 Host_Error ("Mod_LoadZymoticModel: only type 1 (skeletal pose) models are currently supported (name = %s)\n", loadmodel->name);
900 loadmodel->type = mod_alias;
901 loadmodel->aliastype = ALIASTYPE_ZYM;
902 loadmodel->DrawSky = NULL;
903 loadmodel->Draw = R_Model_Zymotic_Draw;
904 loadmodel->DrawFakeShadow = NULL;//R_Model_Zymotic_DrawFakeShadow;
905 loadmodel->DrawShadowVolume = NULL;//R_Model_Zymotic_DrawShadowVolume;
906 loadmodel->DrawLight = NULL;//R_Model_Zymotic_DrawLight;
910 pheader->type = BigLong(pinmodel->type);
911 pheader->filesize = BigLong(pinmodel->filesize);
912 pheader->mins[0] = BigFloat(pinmodel->mins[0]);
913 pheader->mins[1] = BigFloat(pinmodel->mins[1]);
914 pheader->mins[2] = BigFloat(pinmodel->mins[2]);
915 pheader->maxs[0] = BigFloat(pinmodel->maxs[0]);
916 pheader->maxs[1] = BigFloat(pinmodel->maxs[1]);
917 pheader->maxs[2] = BigFloat(pinmodel->maxs[2]);
918 pheader->radius = BigFloat(pinmodel->radius);
919 pheader->numverts = loadmodel->zymnum_verts = BigLong(pinmodel->numverts);
920 pheader->numtris = loadmodel->zymnum_tris = BigLong(pinmodel->numtris);
921 pheader->numshaders = loadmodel->zymnum_shaders = BigLong(pinmodel->numshaders);
922 pheader->numbones = loadmodel->zymnum_bones = BigLong(pinmodel->numbones);
923 pheader->numscenes = loadmodel->zymnum_scenes = BigLong(pinmodel->numscenes);
924 pheader->lump_scenes.start = BigLong(pinmodel->lump_scenes.start);
925 pheader->lump_scenes.length = BigLong(pinmodel->lump_scenes.length);
926 pheader->lump_poses.start = BigLong(pinmodel->lump_poses.start);
927 pheader->lump_poses.length = BigLong(pinmodel->lump_poses.length);
928 pheader->lump_bones.start = BigLong(pinmodel->lump_bones.start);
929 pheader->lump_bones.length = BigLong(pinmodel->lump_bones.length);
930 pheader->lump_vertbonecounts.start = BigLong(pinmodel->lump_vertbonecounts.start);
931 pheader->lump_vertbonecounts.length = BigLong(pinmodel->lump_vertbonecounts.length);
932 pheader->lump_verts.start = BigLong(pinmodel->lump_verts.start);
933 pheader->lump_verts.length = BigLong(pinmodel->lump_verts.length);
934 pheader->lump_texcoords.start = BigLong(pinmodel->lump_texcoords.start);
935 pheader->lump_texcoords.length = BigLong(pinmodel->lump_texcoords.length);
936 pheader->lump_render.start = BigLong(pinmodel->lump_render.start);
937 pheader->lump_render.length = BigLong(pinmodel->lump_render.length);
938 pheader->lump_shaders.start = BigLong(pinmodel->lump_shaders.start);
939 pheader->lump_shaders.length = BigLong(pinmodel->lump_shaders.length);
940 pheader->lump_trizone.start = BigLong(pinmodel->lump_trizone.start);
941 pheader->lump_trizone.length = BigLong(pinmodel->lump_trizone.length);
943 loadmodel->flags = 0; // there are no flags
944 loadmodel->numframes = pheader->numscenes;
945 loadmodel->synctype = ST_SYNC;
946 //loadmodel->numtris = pheader->numtris;
947 //loadmodel->numverts = 0;
951 float modelradius, corner[2];
953 modelradius = pheader->radius;
954 for (i = 0;i < 3;i++)
956 loadmodel->normalmins[i] = pheader->mins[i];
957 loadmodel->normalmaxs[i] = pheader->maxs[i];
958 loadmodel->rotatedmins[i] = -modelradius;
959 loadmodel->rotatedmaxs[i] = modelradius;
961 corner[0] = max(fabs(loadmodel->normalmins[0]), fabs(loadmodel->normalmaxs[0]));
962 corner[1] = max(fabs(loadmodel->normalmins[1]), fabs(loadmodel->normalmaxs[1]));
963 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = sqrt(corner[0]*corner[0]+corner[1]*corner[1]);
964 if (loadmodel->yawmaxs[0] > modelradius)
965 loadmodel->yawmaxs[0] = loadmodel->yawmaxs[1] = modelradius;
966 loadmodel->yawmins[0] = loadmodel->yawmins[1] = -loadmodel->yawmaxs[0];
967 loadmodel->yawmins[2] = loadmodel->normalmins[2];
968 loadmodel->yawmaxs[2] = loadmodel->normalmaxs[2];
969 loadmodel->radius = modelradius;
970 loadmodel->radius2 = modelradius * modelradius;
974 // FIXME: add shaders, and make them switchable shader sets and...
975 loadmodel->skinscenes = Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) + sizeof(skinframe_t));
976 loadmodel->skinscenes[0].firstframe = 0;
977 loadmodel->skinscenes[0].framecount = 1;
978 loadmodel->skinscenes[0].loop = true;
979 loadmodel->skinscenes[0].framerate = 10;
980 loadmodel->skinframes = (void *)(loadmodel->skinscenes + 1);
981 loadmodel->numskins = 1;
984 // go through the lumps, swapping things
989 // zymlump_t lump_scenes; // zymscene_t scene[numscenes]; // name and other information for each scene (see zymscene struct)
990 loadmodel->animscenes = Mem_Alloc(loadmodel->mempool, sizeof(animscene_t) * loadmodel->numframes);
991 scene = (void *) (pheader->lump_scenes.start + pbase);
992 numposes = pheader->lump_poses.length / pheader->numbones / sizeof(float[3][4]);
993 for (i = 0;i < pheader->numscenes;i++)
995 memcpy(loadmodel->animscenes[i].name, scene->name, 32);
996 loadmodel->animscenes[i].firstframe = BigLong(scene->start);
997 loadmodel->animscenes[i].framecount = BigLong(scene->length);
998 loadmodel->animscenes[i].framerate = BigFloat(scene->framerate);
999 loadmodel->animscenes[i].loop = (BigLong(scene->flags) & ZYMSCENEFLAG_NOLOOP) == 0;
1000 if ((unsigned int) loadmodel->animscenes[i].firstframe >= (unsigned int) numposes)
1001 Host_Error("Mod_LoadZymoticModel: scene firstframe (%i) >= numposes (%i)\n", loadmodel->animscenes[i].firstframe, numposes);
1002 if ((unsigned int) loadmodel->animscenes[i].firstframe + (unsigned int) loadmodel->animscenes[i].framecount > (unsigned int) numposes)
1003 Host_Error("Mod_LoadZymoticModel: scene firstframe (%i) + framecount (%i) >= numposes (%i)\n", loadmodel->animscenes[i].firstframe, loadmodel->animscenes[i].framecount, numposes);
1004 if (loadmodel->animscenes[i].framerate < 0)
1005 Host_Error("Mod_LoadZymoticModel: scene framerate (%f) < 0\n", loadmodel->animscenes[i].framerate);
1013 // zymlump_t lump_poses; // float pose[numposes][numbones][3][4]; // animation data
1014 loadmodel->zymdata_poses = Mem_Alloc(loadmodel->mempool, pheader->lump_poses.length);
1015 poses = (void *) (pheader->lump_poses.start + pbase);
1016 for (i = 0;i < pheader->lump_poses.length / 4;i++)
1017 loadmodel->zymdata_poses[i] = BigFloat(poses[i]);
1023 // zymlump_t lump_bones; // zymbone_t bone[numbones];
1024 loadmodel->zymdata_bones = Mem_Alloc(loadmodel->mempool, pheader->numbones * sizeof(zymbone_t));
1025 bone = (void *) (pheader->lump_bones.start + pbase);
1026 for (i = 0;i < pheader->numbones;i++)
1028 memcpy(loadmodel->zymdata_bones[i].name, bone[i].name, sizeof(bone[i].name));
1029 loadmodel->zymdata_bones[i].flags = BigLong(bone[i].flags);
1030 loadmodel->zymdata_bones[i].parent = BigLong(bone[i].parent);
1031 if (loadmodel->zymdata_bones[i].parent >= i)
1032 Host_Error("Mod_LoadZymoticModel: bone[%i].parent >= %i in %s\n", i, i, loadmodel->name);
1038 // zymlump_t lump_vertbonecounts; // int vertbonecounts[numvertices]; // how many bones influence each vertex (separate mainly to make this compress better)
1039 loadmodel->zymdata_vertbonecounts = Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(int));
1040 bonecount = (void *) (pheader->lump_vertbonecounts.start + pbase);
1041 for (i = 0;i < pheader->numverts;i++)
1043 loadmodel->zymdata_vertbonecounts[i] = BigLong(bonecount[i]);
1044 if (loadmodel->zymdata_vertbonecounts[i] < 1)
1045 Host_Error("Mod_LoadZymoticModel: bone vertex count < 1 in %s\n", loadmodel->name);
1051 zymvertex_t *vertdata;
1052 // zymlump_t lump_verts; // zymvertex_t vert[numvertices]; // see vertex struct
1053 loadmodel->zymdata_verts = Mem_Alloc(loadmodel->mempool, pheader->lump_verts.length);
1054 vertdata = (void *) (pheader->lump_verts.start + pbase);
1055 for (i = 0;i < pheader->lump_verts.length / (int) sizeof(zymvertex_t);i++)
1057 loadmodel->zymdata_verts[i].bonenum = BigLong(vertdata[i].bonenum);
1058 loadmodel->zymdata_verts[i].origin[0] = BigFloat(vertdata[i].origin[0]);
1059 loadmodel->zymdata_verts[i].origin[1] = BigFloat(vertdata[i].origin[1]);
1060 loadmodel->zymdata_verts[i].origin[2] = BigFloat(vertdata[i].origin[2]);
1066 float *intexcoord2f, *outtexcoord2f;
1067 // zymlump_t lump_texcoords; // float texcoords[numvertices][2];
1068 loadmodel->zymdata_texcoords = outtexcoord2f = Mem_Alloc(loadmodel->mempool, pheader->numverts * sizeof(float[2]));
1069 intexcoord2f = (void *) (pheader->lump_texcoords.start + pbase);
1070 for (i = 0;i < pheader->numverts;i++)
1072 outtexcoord2f[i*2+0] = BigFloat(intexcoord2f[i*2+0]);
1073 // flip T coordinate for OpenGL
1074 outtexcoord2f[i*2+1] = 1 - BigFloat(intexcoord2f[i*2+1]);
1079 int i, count, *renderlist, *renderlistend, *outrenderlist;
1080 // 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)
1081 loadmodel->zymdata_renderlist = Mem_Alloc(loadmodel->mempool, pheader->lump_render.length);
1082 // byteswap, validate, and swap winding order of tris
1083 count = pheader->numshaders * sizeof(int) + pheader->numtris * sizeof(int[3]);
1084 if (pheader->lump_render.length != count)
1085 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);
1086 outrenderlist = loadmodel->zymdata_renderlist = Mem_Alloc(loadmodel->mempool, count);
1087 renderlist = (void *) (pheader->lump_render.start + pbase);
1088 renderlistend = (void *) ((qbyte *) renderlist + pheader->lump_render.length);
1089 for (i = 0;i < pheader->numshaders;i++)
1091 if (renderlist >= renderlistend)
1092 Host_Error("Mod_LoadZymoticModel: corrupt renderlist in %s (wrong size)\n", loadmodel->name);
1093 count = BigLong(*renderlist);renderlist++;
1094 if (renderlist + count * 3 > renderlistend)
1095 Host_Error("Mod_LoadZymoticModel: corrupt renderlist in %s (wrong size)\n", loadmodel->name);
1096 *outrenderlist++ = count;
1099 outrenderlist[2] = BigLong(renderlist[0]);
1100 outrenderlist[1] = BigLong(renderlist[1]);
1101 outrenderlist[0] = BigLong(renderlist[2]);
1102 if ((unsigned int)outrenderlist[0] >= (unsigned int)pheader->numverts
1103 || (unsigned int)outrenderlist[1] >= (unsigned int)pheader->numverts
1104 || (unsigned int)outrenderlist[2] >= (unsigned int)pheader->numverts)
1105 Host_Error("Mod_LoadZymoticModel: corrupt renderlist in %s (out of bounds index)\n", loadmodel->name);
1115 // zymlump_t lump_shaders; // char shadername[numshaders][32]; // shaders used on this model
1116 loadmodel->zymdata_textures = Mem_Alloc(loadmodel->mempool, pheader->numshaders * sizeof(rtexture_t *));
1117 shadername = (void *) (pheader->lump_shaders.start + pbase);
1118 for (i = 0;i < pheader->numshaders;i++)
1119 loadmodel->zymdata_textures[i] = loadtextureimage(loadmodel->texturepool, shadername + i * 32, 0, 0, true, TEXF_ALPHA | TEXF_PRECACHE | (r_mipskins.integer ? TEXF_MIPMAP : 0));
1123 // zymlump_t lump_trizone; // byte trizone[numtris]; // see trizone explanation
1124 loadmodel->zymdata_trizone = Mem_Alloc(loadmodel->mempool, pheader->numtris);
1125 memcpy(loadmodel->zymdata_trizone, (void *) (pheader->lump_trizone.start + pbase), pheader->numtris);