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.
20 // models.c -- model loading and caching
22 // models are the only shared resource between a client and server running
23 // on the same machine.
27 cvar_t r_mipsprites = {CVAR_SAVE, "r_mipsprites", "1"};
34 void Mod_SpriteInit (void)
36 Cvar_RegisterVariable(&r_mipsprites);
39 void Mod_Sprite_StripExtension(char *in, char *out)
42 end = in + strlen(in);
44 if (strcmp(end - 6, ".spr32") == 0)
47 if (strcmp(end - 4, ".spr") == 0)
59 void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t *frame, int framenum, int bytesperpixel, byte *palette, float *modelradius)
61 dspriteframe_t *pinframe;
62 mspriteframe_t *pspriteframe;
64 int i, width, height, size, origin[2];
65 char name[256], tempname[256];
66 byte *pixbuf, *pixel, *inpixel;
68 pinframe = (dspriteframe_t *)pin;
70 origin[0] = LittleLong (pinframe->origin[0]);
71 origin[1] = LittleLong (pinframe->origin[1]);
72 width = LittleLong (pinframe->width);
73 height = LittleLong (pinframe->height);
74 size = width * height * bytesperpixel;
78 memset (pspriteframe, 0, sizeof (mspriteframe_t));
80 pspriteframe->left = origin[0];
81 pspriteframe->right = origin[0] + width;
82 pspriteframe->up = origin[1];
83 pspriteframe->down = origin[1] - height;
85 dist = pspriteframe->left*pspriteframe->left+pspriteframe->up*pspriteframe->up;
86 if (*modelradius < dist)
88 dist = pspriteframe->right*pspriteframe->right+pspriteframe->down*pspriteframe->down;
89 if (*modelradius < dist)
92 Mod_Sprite_StripExtension(loadmodel->name, tempname);
93 sprintf (name, "%s_%i", tempname, framenum);
94 pspriteframe->texture = loadtextureimagewithmask(name, 0, 0, false, r_mipsprites.value, true);
95 pspriteframe->fogtexture = image_masktex;
97 pixbuf = qmalloc(width*height*4);
99 inpixel = (byte *)(pinframe + 1);
101 if (bytesperpixel == 1)
103 for (i = 0;i < width * height;i++)
105 *pixel++ = palette[inpixel[i]*4+0];
106 *pixel++ = palette[inpixel[i]*4+1];
107 *pixel++ = palette[inpixel[i]*4+2];
108 *pixel++ = palette[inpixel[i]*4+3];
112 memcpy(pixel, inpixel, width*height*4);
114 if (!pspriteframe->texture)
116 pspriteframe->texture = R_LoadTexture (name, width, height, pixbuf, TEXF_ALPHA | TEXF_RGBA | (r_mipsprites.value ? TEXF_MIPMAP : 0) | TEXF_PRECACHE);
117 // make fog version (just alpha)
119 for (i = 0;i < width*height;i++)
126 sprintf (name, "%s_%ifog", loadmodel->name, framenum);
127 pspriteframe->fogtexture = R_LoadTexture (name, width, height, pixbuf, TEXF_ALPHA | TEXF_RGBA | (r_mipsprites.value ? TEXF_MIPMAP : 0) | TEXF_PRECACHE);
132 return (void *)((byte *)pinframe + sizeof (dspriteframe_t) + size);
142 void *Mod_LoadSpriteGroup (void * pin, mspriteframe_t *frame, int numframes, int framenum, int bytesperpixel)
147 ptemp = (void *)(sizeof(dspriteinterval_t) * numframes + sizeof(dspritegroup_t) + (int) pin);
149 for (i = 0;i < numframes;i++)
150 ptemp = Mod_LoadSpriteFrame (ptemp, frame++, framenum * 100 + i, bytesperpixel);
156 // this actually handles both quake sprite and darkplaces sprite32
157 void Mod_LoadQuakeSprite (model_t *mod, void *buffer)
159 int i, j, version, numframes, realframes, size, bytesperpixel, start, end, total;
162 dspriteframetype_t *pframetype;
163 dspriteframe_t *pframe;
164 animscene_t *animscenes;
165 mspriteframe_t *frames;
166 dspriteframe_t **framedata;
171 start = Hunk_LowMark ();
173 mod->flags = EF_FULLBRIGHT;
174 // LordHavoc: hack to allow sprites to be non-fullbright
175 for (i = 0;i < MAX_QPATH && mod->name[i];i++)
177 if (mod->name[i] == '!')
179 mod->flags &= ~EF_FULLBRIGHT;
184 // build a list of frames while parsing
185 framedata = qmalloc(65536*sizeof(dspriteframe_t));
187 pin = (dsprite_t *)buffer;
189 version = LittleLong (pin->version);
190 // LordHavoc: 32bit textures
192 if (version == SPRITE32_VERSION)
195 numframes = LittleLong (pin->numframes);
197 psprite = Hunk_AllocName (sizeof(msprite_t), va("%s info", loadname));
199 // mod->cache.data = psprite;
201 psprite->type = LittleLong (pin->type);
202 // maxwidth = LittleLong (pin->width);
203 // maxheight = LittleLong (pin->height);
204 // psprite->beamlength = LittleFloat (pin->beamlength);
205 mod->synctype = LittleLong (pin->synctype);
206 // psprite->numframes = numframes;
208 // mod->mins[0] = mod->mins[1] = -maxwidth/2;
209 // mod->maxs[0] = mod->maxs[1] = maxwidth/2;
210 // mod->mins[2] = -maxheight/2;
211 // mod->maxs[2] = maxheight/2;
217 Host_Error ("Mod_LoadQuakeSprite: Invalid # of frames: %d\n", numframes);
219 mod->numframes = numframes;
221 pframetype = (dspriteframetype_t *)(pin + 1);
223 animscenes = Hunk_AllocName(sizeof(animscene_t) * mod->numframes, va("%s sceneinfo", loadname));
227 for (i = 0;i < numframes;i++)
229 spriteframetype_t frametype;
231 frametype = LittleLong (pframetype->type);
233 sprintf(animscenes[i].name, "frame%i", i);
234 animscenes[i].firstframe = realframes;
235 animscenes[i].loop = true;
236 if (frametype == SPR_SINGLE)
238 animscenes[i].framecount = 1;
239 animscenes[i].framerate = 10;
240 pframe = (dspriteframe_t *) (pframetype + 1);
241 framedata[realframes] = pframe;
242 size = LittleLong(pframe->width) * LittleLong(pframe->height) * bytesperpixel;
243 pframetype = (dspriteframetype_t *) (size + sizeof(dspriteframe_t) + (int) pframe);
248 j = LittleLong(((dspritegroup_t *) (sizeof(dspriteframetype_t) + (int) pframetype))->numframes);
249 animscenes[i].framecount = j;
250 // FIXME: support variable framerate?
251 animscenes[i].framerate = 1.0f / LittleFloat(((dspriteinterval_t *) (sizeof(dspritegroup_t) + sizeof(dspriteframetype_t) + (int) pframetype))->interval);
252 pframe = (dspriteframe_t *) (sizeof(dspriteinterval_t) * j + sizeof(dspritegroup_t) + sizeof(dspriteframetype_t) + (int) pframetype);
255 framedata[realframes] = pframe;
256 size = LittleLong(pframe->width) * LittleLong(pframe->height) * bytesperpixel;
257 pframe = (dspriteframe_t *) (size + sizeof(dspriteframe_t) + (int) pframe);
260 pframetype = (dspriteframetype_t *) pframe;
264 mod->ofs_scenes = (int) animscenes - (int) psprite;
266 frames = Hunk_AllocName(sizeof(mspriteframe_t) * realframes, va("%s frames", loadname));
269 for (i = 0;i < numframes;i++)
271 for (j = 0;j < animscenes[i].framecount;j++)
273 Mod_LoadSpriteFrame (framedata[realframes], frames + realframes, i, bytesperpixel, (byte *)&d_8to24table, &modelradius);
278 psprite->ofs_frames = (int) frames - (int) psprite;
282 mod->type = mod_sprite;
284 modelradius = sqrt(modelradius);
285 for (i = 0;i < 3;i++)
287 mod->normalmins[i] = mod->yawmins[i] = mod->rotatedmins[i] = -modelradius;
288 mod->normalmaxs[i] = mod->yawmaxs[i] = mod->rotatedmaxs[i] = modelradius;
290 // mod->modelradius = modelradius;
292 // move the complete, relocatable sprite model to the cache
293 end = Hunk_LowMark ();
294 mod->cachesize = total = end - start;
296 Cache_Alloc (&mod->cache, total, loadname);
297 if (!mod->cache.data)
299 memcpy (mod->cache.data, psprite, total);
301 Hunk_FreeToLowMark (start);
304 void Mod_LoadHLSprite (model_t *mod, void *buffer)
306 int i, j, numframes, realframes, size, start, end, total, rendermode;
307 byte palette[256][4], *in;
310 dspriteframetype_t *pframetype;
311 dspriteframe_t *pframe;
312 animscene_t *animscenes;
313 mspriteframe_t *frames;
314 dspriteframe_t **framedata;
319 start = Hunk_LowMark ();
321 mod->flags = EF_FULLBRIGHT;
323 // build a list of frames while parsing
324 framedata = qmalloc(65536*sizeof(dspriteframe_t));
326 pin = (dspritehl_t *)buffer;
328 numframes = LittleLong (pin->numframes);
330 psprite = Hunk_AllocName (sizeof(msprite_t), va("%s info", loadname));
332 psprite->type = LittleLong (pin->type);
333 // maxwidth = LittleLong (pin->width);
334 // maxheight = LittleLong (pin->height);
335 mod->synctype = LittleLong (pin->synctype);
336 rendermode = pin->rendermode;
338 // mod->mins[0] = mod->mins[1] = -maxwidth/2;
339 // mod->maxs[0] = mod->maxs[1] = maxwidth/2;
340 // mod->mins[2] = -maxheight/2;
341 // mod->maxs[2] = maxheight/2;
347 Host_Error ("Mod_LoadHLSprite: Invalid # of frames: %d\n", numframes);
349 mod->numframes = numframes;
351 in = (byte *)(pin + 1);
352 i = in[0] + in[1] * 256;
354 Host_Error ("Mod_LoadHLSprite: unexpected number of palette colors %i (should be 256)", i);
359 for (i = 0;i < 256;i++)
361 palette[i][0] = *in++;
362 palette[i][1] = *in++;
363 palette[i][2] = *in++;
366 palette[255][0] = palette[255][1] = palette[255][2] = palette[255][3] = 0;
369 for (i = 0;i < 256;i++)
371 palette[i][0] = *in++;
372 palette[i][1] = *in++;
373 palette[i][2] = *in++;
376 // palette[255][0] = palette[255][1] = palette[255][2] = palette[255][3] = 0;
377 mod->flags |= EF_ADDITIVE;
379 case SPRHL_INDEXALPHA:
380 for (i = 0;i < 256;i++)
389 case SPRHL_ALPHATEST:
390 for (i = 0;i < 256;i++)
392 palette[i][0] = *in++;
393 palette[i][1] = *in++;
394 palette[i][2] = *in++;
397 palette[0][0] = palette[0][1] = palette[0][2] = palette[0][3] = 0;
400 Host_Error("Mod_LoadHLSprite: unknown texFormat (%i, should be 0, 1, 2, or 3)\n", i);
404 pframetype = (dspriteframetype_t *)in;
406 animscenes = Hunk_AllocName(sizeof(animscene_t) * mod->numframes, va("%s sceneinfo", loadname));
410 for (i = 0;i < numframes;i++)
412 spriteframetype_t frametype;
414 frametype = LittleLong (pframetype->type);
416 sprintf(animscenes[i].name, "frame%i", i);
417 animscenes[i].firstframe = realframes;
418 animscenes[i].loop = true;
419 if (frametype == SPR_SINGLE)
421 animscenes[i].framecount = 1;
422 animscenes[i].framerate = 10;
423 pframe = (dspriteframe_t *) (pframetype + 1);
424 framedata[realframes] = pframe;
425 size = LittleLong(pframe->width) * LittleLong(pframe->height);
426 pframetype = (dspriteframetype_t *) (size + sizeof(dspriteframe_t) + (int) pframe);
431 j = LittleLong(((dspritegroup_t *) (sizeof(dspriteframetype_t) + (int) pframetype))->numframes);
432 animscenes[i].framecount = j;
433 // FIXME: support variable framerate?
434 animscenes[i].framerate = 1.0f / LittleFloat(((dspriteinterval_t *) (sizeof(dspritegroup_t) + sizeof(dspriteframetype_t) + (int) pframetype))->interval);
435 pframe = (dspriteframe_t *) (sizeof(dspriteinterval_t) * j + sizeof(dspritegroup_t) + sizeof(dspriteframetype_t) + (int) pframetype);
438 framedata[realframes] = pframe;
439 size = LittleLong(pframe->width) * LittleLong(pframe->height);
440 pframe = (dspriteframe_t *) (size + sizeof(dspriteframe_t) + (int) pframe);
443 pframetype = (dspriteframetype_t *) pframe;
447 mod->ofs_scenes = (int) animscenes - (int) psprite;
449 frames = Hunk_AllocName(sizeof(mspriteframe_t) * realframes, va("%s frames", loadname));
452 for (i = 0;i < numframes;i++)
454 for (j = 0;j < animscenes[i].framecount;j++)
456 Mod_LoadSpriteFrame (framedata[realframes], frames + realframes, i, 1, &palette[0][0], &modelradius);
461 psprite->ofs_frames = (int) frames - (int) psprite;
465 mod->type = mod_sprite;
467 modelradius = sqrt(modelradius);
468 for (i = 0;i < 3;i++)
470 mod->normalmins[i] = mod->yawmins[i] = mod->rotatedmins[i] = -modelradius;
471 mod->normalmaxs[i] = mod->yawmaxs[i] = mod->rotatedmaxs[i] = modelradius;
474 // move the complete, relocatable sprite model to the cache
475 end = Hunk_LowMark ();
476 mod->cachesize = total = end - start;
478 Cache_Alloc (&mod->cache, total, loadname);
479 if (!mod->cache.data)
481 memcpy (mod->cache.data, psprite, total);
483 Hunk_FreeToLowMark (start);
486 void Mod_Sprite_SERAddEntity(void)
497 void Mod_LoadSpriteModel (model_t *mod, void *buffer)
500 version = ((dsprite_t *)buffer)->version;
503 case SPRITEHL_VERSION:
504 Mod_LoadHLSprite (mod, buffer);
507 case SPRITE32_VERSION:
508 Mod_LoadQuakeSprite(mod, buffer);
511 Host_Error ("Mod_LoadSpriteModel: %s has wrong version number (%i should be 1 (quake) or 32 (sprite32) or 2 (halflife)", mod->name, version);
514 mod->SERAddEntity = Mod_Sprite_SERAddEntity;
515 mod->DrawEarly = R_DrawSpriteModel;
516 mod->DrawLate = NULL;
517 mod->DrawShadow = NULL;