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)
61 dspriteframe_t *pinframe;
62 mspriteframe_t *pspriteframe;
63 int i, width, height, size, origin[2];
64 char name[256], tempname[256];
65 byte *pixbuf, *pixel, *inpixel;
67 pinframe = (dspriteframe_t *)pin;
69 width = LittleLong (pinframe->width);
70 height = LittleLong (pinframe->height);
71 size = width * height * bytesperpixel;
75 memset (pspriteframe, 0, sizeof (mspriteframe_t));
77 // pspriteframe->width = width;
78 // pspriteframe->height = height;
79 origin[0] = LittleLong (pinframe->origin[0]);
80 origin[1] = LittleLong (pinframe->origin[1]);
82 pspriteframe->up = origin[1];
83 pspriteframe->down = origin[1] - height;
84 pspriteframe->left = origin[0];
85 pspriteframe->right = width + origin[0];
87 Mod_Sprite_StripExtension(loadmodel->name, tempname);
88 sprintf (name, "%s_%i", tempname, framenum);
89 pspriteframe->texture = loadtextureimagewithmask(name, 0, 0, false, r_mipsprites.value, true);
90 pspriteframe->fogtexture = image_masktex;
92 pixbuf = qmalloc(width*height*4);
94 inpixel = (byte *)(pinframe + 1);
96 if (bytesperpixel == 1)
98 for (i = 0;i < width * height;i++)
100 *pixel++ = palette[inpixel[i]*4+0];
101 *pixel++ = palette[inpixel[i]*4+1];
102 *pixel++ = palette[inpixel[i]*4+2];
103 *pixel++ = palette[inpixel[i]*4+3];
107 memcpy(pixel, inpixel, width*height*4);
109 if (!pspriteframe->texture)
111 pspriteframe->texture = R_LoadTexture (name, width, height, pixbuf, TEXF_ALPHA | TEXF_RGBA | (r_mipsprites.value ? TEXF_MIPMAP : 0) | TEXF_PRECACHE);
112 // make fog version (just alpha)
114 for (i = 0;i < width*height;i++)
121 sprintf (name, "%s_%ifog", loadmodel->name, framenum);
122 pspriteframe->fogtexture = R_LoadTexture (name, width, height, pixbuf, TEXF_ALPHA | TEXF_RGBA | (r_mipsprites.value ? TEXF_MIPMAP : 0) | TEXF_PRECACHE);
127 return (void *)((byte *)pinframe + sizeof (dspriteframe_t) + size);
137 void *Mod_LoadSpriteGroup (void * pin, mspriteframe_t *frame, int numframes, int framenum, int bytesperpixel)
142 ptemp = (void *)(sizeof(dspriteinterval_t) * numframes + sizeof(dspritegroup_t) + (int) pin);
144 for (i = 0;i < numframes;i++)
145 ptemp = Mod_LoadSpriteFrame (ptemp, frame++, framenum * 100 + i, bytesperpixel);
151 // this actually handles both quake sprite and darkplaces sprite32
152 void Mod_LoadQuakeSprite (model_t *mod, void *buffer)
154 int i, j, version, numframes, realframes, size, bytesperpixel, start, end, total, maxwidth, maxheight;
157 dspriteframetype_t *pframetype;
158 dspriteframe_t *pframe;
159 animscene_t *animscenes;
160 mspriteframe_t *frames;
161 dspriteframe_t **framedata;
163 start = Hunk_LowMark ();
165 mod->flags = EF_FULLBRIGHT;
166 // LordHavoc: hack to allow sprites to be non-fullbright
167 for (i = 0;i < MAX_QPATH && mod->name[i];i++)
169 if (mod->name[i] == '!')
171 mod->flags &= ~EF_FULLBRIGHT;
176 // build a list of frames while parsing
177 framedata = qmalloc(65536*sizeof(dspriteframe_t));
179 pin = (dsprite_t *)buffer;
181 version = LittleLong (pin->version);
182 // LordHavoc: 32bit textures
184 if (version == SPRITE32_VERSION)
187 numframes = LittleLong (pin->numframes);
189 psprite = Hunk_AllocName (sizeof(msprite_t), va("%s info", loadname));
191 // mod->cache.data = psprite;
193 psprite->type = LittleLong (pin->type);
194 maxwidth = LittleLong (pin->width);
195 maxheight = LittleLong (pin->height);
196 // psprite->beamlength = LittleFloat (pin->beamlength);
197 mod->synctype = LittleLong (pin->synctype);
198 // psprite->numframes = numframes;
200 mod->mins[0] = mod->mins[1] = -maxwidth/2;
201 mod->maxs[0] = mod->maxs[1] = maxwidth/2;
202 mod->mins[2] = -maxheight/2;
203 mod->maxs[2] = maxheight/2;
209 Host_Error ("Mod_LoadQuakeSprite: Invalid # of frames: %d\n", numframes);
211 mod->numframes = numframes;
213 pframetype = (dspriteframetype_t *)(pin + 1);
215 animscenes = Hunk_AllocName(sizeof(animscene_t) * mod->numframes, va("%s sceneinfo", loadname));
219 for (i = 0;i < numframes;i++)
221 spriteframetype_t frametype;
223 frametype = LittleLong (pframetype->type);
225 sprintf(animscenes[i].name, "frame%i", i);
226 animscenes[i].firstframe = realframes;
227 animscenes[i].loop = true;
228 if (frametype == SPR_SINGLE)
230 animscenes[i].framecount = 1;
231 animscenes[i].framerate = 10;
232 pframe = (dspriteframe_t *) (pframetype + 1);
233 framedata[realframes] = pframe;
234 size = LittleLong(pframe->width) * LittleLong(pframe->height) * bytesperpixel;
235 pframetype = (dspriteframetype_t *) (size + sizeof(dspriteframe_t) + (int) pframe);
240 j = LittleLong(((dspritegroup_t *) (sizeof(dspriteframetype_t) + (int) pframetype))->numframes);
241 animscenes[i].framecount = j;
242 // FIXME: support variable framerate?
243 animscenes[i].framerate = 1.0f / LittleFloat(((dspriteinterval_t *) (sizeof(dspritegroup_t) + sizeof(dspriteframetype_t) + (int) pframetype))->interval);
244 pframe = (dspriteframe_t *) (sizeof(dspriteinterval_t) * j + sizeof(dspritegroup_t) + sizeof(dspriteframetype_t) + (int) pframetype);
247 framedata[realframes] = pframe;
248 size = LittleLong(pframe->width) * LittleLong(pframe->height) * bytesperpixel;
249 pframe = (dspriteframe_t *) (size + sizeof(dspriteframe_t) + (int) pframe);
252 pframetype = (dspriteframetype_t *) pframe;
256 mod->ofs_scenes = (int) animscenes - (int) psprite;
258 frames = Hunk_AllocName(sizeof(mspriteframe_t) * realframes, va("%s frames", loadname));
261 for (i = 0;i < numframes;i++)
263 for (j = 0;j < animscenes[i].framecount;j++)
265 Mod_LoadSpriteFrame (framedata[realframes], frames + realframes, i, bytesperpixel, (byte *)&d_8to24table);
270 psprite->ofs_frames = (int) frames - (int) psprite;
274 mod->type = mod_sprite;
276 // move the complete, relocatable sprite model to the cache
277 end = Hunk_LowMark ();
278 mod->cachesize = total = end - start;
280 Cache_Alloc (&mod->cache, total, loadname);
281 if (!mod->cache.data)
283 memcpy (mod->cache.data, psprite, total);
285 Hunk_FreeToLowMark (start);
288 void Mod_LoadHLSprite (model_t *mod, void *buffer)
290 int i, j, numframes, realframes, size, start, end, total, maxwidth, maxheight, rendermode;
291 byte palette[256][4], *in;
294 dspriteframetype_t *pframetype;
295 dspriteframe_t *pframe;
296 animscene_t *animscenes;
297 mspriteframe_t *frames;
298 dspriteframe_t **framedata;
300 start = Hunk_LowMark ();
302 mod->flags = EF_FULLBRIGHT;
304 // build a list of frames while parsing
305 framedata = qmalloc(65536*sizeof(dspriteframe_t));
307 pin = (dspritehl_t *)buffer;
309 numframes = LittleLong (pin->numframes);
311 psprite = Hunk_AllocName (sizeof(msprite_t), va("%s info", loadname));
313 psprite->type = LittleLong (pin->type);
314 maxwidth = LittleLong (pin->width);
315 maxheight = LittleLong (pin->height);
316 mod->synctype = LittleLong (pin->synctype);
317 rendermode = pin->rendermode;
319 mod->mins[0] = mod->mins[1] = -maxwidth/2;
320 mod->maxs[0] = mod->maxs[1] = maxwidth/2;
321 mod->mins[2] = -maxheight/2;
322 mod->maxs[2] = maxheight/2;
328 Host_Error ("Mod_LoadHLSprite: Invalid # of frames: %d\n", numframes);
330 mod->numframes = numframes;
332 in = (byte *)(pin + 1);
333 i = in[0] + in[1] * 256;
335 Host_Error ("Mod_LoadHLSprite: unexpected number of palette colors %i (should be 256)", i);
340 for (i = 0;i < 256;i++)
342 palette[i][0] = *in++;
343 palette[i][1] = *in++;
344 palette[i][2] = *in++;
347 palette[255][0] = palette[255][1] = palette[255][2] = palette[255][3] = 0;
350 for (i = 0;i < 256;i++)
352 palette[i][0] = *in++;
353 palette[i][1] = *in++;
354 palette[i][2] = *in++;
357 // palette[255][0] = palette[255][1] = palette[255][2] = palette[255][3] = 0;
358 mod->flags |= EF_ADDITIVE;
360 case SPRHL_INDEXALPHA:
361 for (i = 0;i < 256;i++)
370 case SPRHL_ALPHATEST:
371 for (i = 0;i < 256;i++)
373 palette[i][0] = *in++;
374 palette[i][1] = *in++;
375 palette[i][2] = *in++;
378 palette[0][0] = palette[0][1] = palette[0][2] = palette[0][3] = 0;
381 Host_Error("Mod_LoadHLSprite: unknown texFormat (%i, should be 0, 1, 2, or 3)\n", i);
385 pframetype = (dspriteframetype_t *)in;
387 animscenes = Hunk_AllocName(sizeof(animscene_t) * mod->numframes, va("%s sceneinfo", loadname));
391 for (i = 0;i < numframes;i++)
393 spriteframetype_t frametype;
395 frametype = LittleLong (pframetype->type);
397 sprintf(animscenes[i].name, "frame%i", i);
398 animscenes[i].firstframe = realframes;
399 animscenes[i].loop = true;
400 if (frametype == SPR_SINGLE)
402 animscenes[i].framecount = 1;
403 animscenes[i].framerate = 10;
404 pframe = (dspriteframe_t *) (pframetype + 1);
405 framedata[realframes] = pframe;
406 size = LittleLong(pframe->width) * LittleLong(pframe->height);
407 pframetype = (dspriteframetype_t *) (size + sizeof(dspriteframe_t) + (int) pframe);
412 j = LittleLong(((dspritegroup_t *) (sizeof(dspriteframetype_t) + (int) pframetype))->numframes);
413 animscenes[i].framecount = j;
414 // FIXME: support variable framerate?
415 animscenes[i].framerate = 1.0f / LittleFloat(((dspriteinterval_t *) (sizeof(dspritegroup_t) + sizeof(dspriteframetype_t) + (int) pframetype))->interval);
416 pframe = (dspriteframe_t *) (sizeof(dspriteinterval_t) * j + sizeof(dspritegroup_t) + sizeof(dspriteframetype_t) + (int) pframetype);
419 framedata[realframes] = pframe;
420 size = LittleLong(pframe->width) * LittleLong(pframe->height);
421 pframe = (dspriteframe_t *) (size + sizeof(dspriteframe_t) + (int) pframe);
424 pframetype = (dspriteframetype_t *) pframe;
428 mod->ofs_scenes = (int) animscenes - (int) psprite;
430 frames = Hunk_AllocName(sizeof(mspriteframe_t) * realframes, va("%s frames", loadname));
433 for (i = 0;i < numframes;i++)
435 for (j = 0;j < animscenes[i].framecount;j++)
437 Mod_LoadSpriteFrame (framedata[realframes], frames + realframes, i, 1, &palette[0][0]);
442 psprite->ofs_frames = (int) frames - (int) psprite;
446 mod->type = mod_sprite;
448 // move the complete, relocatable sprite model to the cache
449 end = Hunk_LowMark ();
450 mod->cachesize = total = end - start;
452 Cache_Alloc (&mod->cache, total, loadname);
453 if (!mod->cache.data)
455 memcpy (mod->cache.data, psprite, total);
457 Hunk_FreeToLowMark (start);
466 void Mod_LoadSpriteModel (model_t *mod, void *buffer)
469 version = ((dsprite_t *)buffer)->version;
472 case SPRITEHL_VERSION:
473 Mod_LoadHLSprite (mod, buffer);
476 case SPRITE32_VERSION:
477 Mod_LoadQuakeSprite(mod, buffer);
480 Host_Error ("Mod_LoadSpriteModel: %s has wrong version number (%i should be 1 (quake) or 32 (sprite32) or 2 (halflife)", mod->name, version);