got rid of Hunk_Alloc, all allocations now have a proper name (perhaps a bit too...
[divverent/darkplaces.git] / model_sprite.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
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.
8
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.  
12
13 See the GNU General Public License for more details.
14
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.
18
19 */
20 // models.c -- model loading and caching
21
22 // models are the only shared resource between a client and server running
23 // on the same machine.
24
25 #include "quakedef.h"
26
27 /*
28 ===============
29 Mod_SpriteInit
30 ===============
31 */
32 void Mod_SpriteInit (void)
33 {
34 }
35
36 void Mod_Sprite_StripExtension(char *in, char *out)
37 {
38         char *end;
39         end = in + strlen(in);
40         if ((end - in) >= 6)
41                 if (strcmp(end - 6, ".spr32") == 0)
42                         end -= 6;
43         if ((end - in) >= 4)
44                 if (strcmp(end - 4, ".spr") == 0)
45                         end -= 4;
46         while (in < end)
47                 *out++ = *in++;
48         *out++ = 0;
49 }
50
51 /*
52 =================
53 Mod_LoadSpriteFrame
54 =================
55 */
56 void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum, int bytesperpixel)
57 {
58         dspriteframe_t          *pinframe;
59         mspriteframe_t          *pspriteframe;
60         int                                     i, width, height, size, origin[2];
61         char                            name[256], tempname[256];
62         byte                            *pixbuf, *pixel, *inpixel;
63
64         pinframe = (dspriteframe_t *)pin;
65
66         width = LittleLong (pinframe->width);
67         height = LittleLong (pinframe->height);
68         size = width * height * bytesperpixel;
69
70         pspriteframe = Hunk_AllocName (sizeof (mspriteframe_t), va("%s frames", loadname));
71
72         memset (pspriteframe, 0, sizeof (mspriteframe_t));
73
74         *ppframe = pspriteframe;
75
76         pspriteframe->width = width;
77         pspriteframe->height = height;
78         origin[0] = LittleLong (pinframe->origin[0]);
79         origin[1] = LittleLong (pinframe->origin[1]);
80
81         pspriteframe->up = origin[1];
82         pspriteframe->down = origin[1] - height;
83         pspriteframe->left = origin[0];
84         pspriteframe->right = width + origin[0];
85
86         Mod_Sprite_StripExtension(loadmodel->name, tempname);
87         sprintf (name, "%s_%i", tempname, framenum);
88         pspriteframe->gl_texturenum = loadtextureimagewithmask(name, 0, 0, false, true);
89         pspriteframe->gl_fogtexturenum = image_masktexnum;
90         if (pspriteframe->gl_texturenum == 0)
91         {
92                 pspriteframe->gl_texturenum = GL_LoadTexture (name, width, height, (byte *)(pinframe + 1), true, true, bytesperpixel);
93                 // make fog version (just alpha)
94                 pixbuf = pixel = qmalloc(width*height*4);
95                 inpixel = (byte *)(pinframe + 1);
96                 if (bytesperpixel == 1)
97                 {
98                         for (i = 0;i < width*height;i++)
99                         {
100                                 *pixel++ = 255;
101                                 *pixel++ = 255;
102                                 *pixel++ = 255;
103                                 if (*inpixel++ != 255)
104                                         *pixel++ = 255;
105                                 else
106                                         *pixel++ = 0;
107                         }
108                 }
109                 else
110                 {
111                         inpixel+=3;
112                         for (i = 0;i < width*height;i++)
113                         {
114                                 *pixel++ = 255;
115                                 *pixel++ = 255;
116                                 *pixel++ = 255;
117                                 *pixel++ = *inpixel;
118                                 inpixel+=4;
119                         }
120                 }
121                 sprintf (name, "%s_%ifog", loadmodel->name, framenum);
122                 pspriteframe->gl_fogtexturenum = GL_LoadTexture (name, width, height, pixbuf, true, true, 4);
123                 qfree(pixbuf);
124         }
125
126         return (void *)((byte *)pinframe + sizeof (dspriteframe_t) + size);
127 }
128
129
130 /*
131 =================
132 Mod_LoadSpriteGroup
133 =================
134 */
135 void * Mod_LoadSpriteGroup (void * pin, mspriteframe_t **ppframe, int framenum, int bytesperpixel)
136 {
137         dspritegroup_t          *pingroup;
138         mspritegroup_t          *pspritegroup;
139         int                                     i, numframes;
140         dspriteinterval_t       *pin_intervals;
141         float                           *poutintervals;
142         void                            *ptemp;
143
144         pingroup = (dspritegroup_t *)pin;
145
146         numframes = LittleLong (pingroup->numframes);
147
148         pspritegroup = Hunk_AllocName (sizeof (mspritegroup_t) + (numframes - 1) * sizeof (pspritegroup->frames[0]), va("%s frames", loadname));
149
150         pspritegroup->numframes = numframes;
151
152         *ppframe = (mspriteframe_t *)pspritegroup;
153
154         pin_intervals = (dspriteinterval_t *)(pingroup + 1);
155
156         poutintervals = Hunk_AllocName (numframes * sizeof (float), va("%s frames", loadname));
157
158         pspritegroup->intervals = poutintervals;
159
160         for (i=0 ; i<numframes ; i++)
161         {
162                 *poutintervals = LittleFloat (pin_intervals->interval);
163                 if (*poutintervals <= 0.0)
164                         Host_Error ("Mod_LoadSpriteGroup: interval<=0");
165
166                 poutintervals++;
167                 pin_intervals++;
168         }
169
170         ptemp = (void *)pin_intervals;
171
172         for (i=0 ; i<numframes ; i++)
173                 ptemp = Mod_LoadSpriteFrame (ptemp, &pspritegroup->frames[i], framenum * 100 + i, bytesperpixel);
174
175         return ptemp;
176 }
177
178
179 /*
180 =================
181 Mod_LoadSpriteModel
182 =================
183 */
184 void Mod_LoadSpriteModel (model_t *mod, void *buffer)
185 {
186         int                                     i;
187         int                                     version;
188         dsprite_t                       *pin;
189         msprite_t                       *psprite;
190         int                                     numframes;
191         int                                     size;
192         dspriteframetype_t      *pframetype;
193         // LordHavoc: 32bit textures
194         int             bytesperpixel;
195
196         mod->flags = EF_FULLBRIGHT;
197         // LordHavoc: hack to allow sprites to be non-fullbright
198         for (i = 0;i < MAX_QPATH && mod->name[i];i++)
199         {
200                 if (mod->name[i] == '!')
201                 {
202                         mod->flags &= ~EF_FULLBRIGHT;
203                         break;
204                 }
205         }
206
207         pin = (dsprite_t *)buffer;
208
209         version = LittleLong (pin->version);
210         if (version == 2)
211         {
212                 version = 32;
213                 Con_Printf("warning: %s is a version 2 sprite (RGBA), supported for now, please hex edit to version 32 incase HalfLife sprites might be supported at some point.\n", mod->name);
214         }
215         // LordHavoc: 32bit textures
216         if (version != SPRITE_VERSION && version != SPRITE32_VERSION)
217                 Host_Error ("%s has wrong version number "
218                                  "(%i should be %i or %i)", mod->name, version, SPRITE_VERSION, SPRITE32_VERSION);
219         bytesperpixel = 1;
220         if (version == SPRITE32_VERSION)
221                 bytesperpixel = 4;
222
223         numframes = LittleLong (pin->numframes);
224
225         size = sizeof (msprite_t) +     (numframes - 1) * sizeof (psprite->frames);
226
227         psprite = Hunk_AllocName (size, va("%s info", loadname));
228
229         mod->cache.data = psprite;
230
231         psprite->type = LittleLong (pin->type);
232         psprite->maxwidth = LittleLong (pin->width);
233         psprite->maxheight = LittleLong (pin->height);
234         psprite->beamlength = LittleFloat (pin->beamlength);
235         mod->synctype = LittleLong (pin->synctype);
236         psprite->numframes = numframes;
237
238         mod->mins[0] = mod->mins[1] = -psprite->maxwidth/2;
239         mod->maxs[0] = mod->maxs[1] = psprite->maxwidth/2;
240         mod->mins[2] = -psprite->maxheight/2;
241         mod->maxs[2] = psprite->maxheight/2;
242         
243 //
244 // load the frames
245 //
246         if (numframes < 1)
247                 Host_Error ("Mod_LoadSpriteModel: Invalid # of frames: %d\n", numframes);
248
249         mod->numframes = numframes;
250
251         pframetype = (dspriteframetype_t *)(pin + 1);
252
253         for (i=0 ; i<numframes ; i++)
254         {
255                 spriteframetype_t       frametype;
256
257                 frametype = LittleLong (pframetype->type);
258                 psprite->frames[i].type = frametype;
259
260                 if (frametype == SPR_SINGLE)
261                         pframetype = (dspriteframetype_t *) Mod_LoadSpriteFrame (pframetype + 1, &psprite->frames[i].frameptr, i, bytesperpixel);
262                 else
263                         pframetype = (dspriteframetype_t *) Mod_LoadSpriteGroup (pframetype + 1, &psprite->frames[i].frameptr, i, bytesperpixel);
264         }
265
266         mod->type = mod_sprite;
267 }