bmodel rotation physics now work
[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 /*
37 =================
38 Mod_LoadSpriteFrame
39 =================
40 */
41 void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum, int bytesperpixel)
42 {
43         dspriteframe_t          *pinframe;
44         mspriteframe_t          *pspriteframe;
45         int                                     i, width, height, size, origin[2];
46         char                            name[64];
47         byte                            *pixbuf, *pixel, *inpixel;
48
49         pinframe = (dspriteframe_t *)pin;
50
51         width = LittleLong (pinframe->width);
52         height = LittleLong (pinframe->height);
53         size = width * height * bytesperpixel;
54
55         pspriteframe = Hunk_AllocName (sizeof (mspriteframe_t),loadname);
56
57         memset (pspriteframe, 0, sizeof (mspriteframe_t));
58
59         *ppframe = pspriteframe;
60
61         pspriteframe->width = width;
62         pspriteframe->height = height;
63         origin[0] = LittleLong (pinframe->origin[0]);
64         origin[1] = LittleLong (pinframe->origin[1]);
65
66         pspriteframe->up = origin[1];
67         pspriteframe->down = origin[1] - height;
68         pspriteframe->left = origin[0];
69         pspriteframe->right = width + origin[0];
70
71         sprintf (name, "%s_%i", loadmodel->name, framenum);
72         pspriteframe->gl_texturenum = loadtextureimagewithmask(name, 0, 0, false, true);
73         pspriteframe->gl_fogtexturenum = image_masktexnum;
74         if (pspriteframe->gl_texturenum == 0)
75         {
76                 pspriteframe->gl_texturenum = GL_LoadTexture (name, width, height, (byte *)(pinframe + 1), true, true, bytesperpixel);
77                 // make fog version (just alpha)
78                 pixbuf = pixel = malloc(width*height*4);
79                 inpixel = (byte *)(pinframe + 1);
80                 if (bytesperpixel == 1)
81                 {
82                         for (i = 0;i < width*height;i++)
83                         {
84                                 *pixel++ = 255;
85                                 *pixel++ = 255;
86                                 *pixel++ = 255;
87                                 if (*inpixel++ != 255)
88                                         *pixel++ = 255;
89                                 else
90                                         *pixel++ = 0;
91                         }
92                 }
93                 else
94                 {
95                         inpixel+=3;
96                         for (i = 0;i < width*height;i++)
97                         {
98                                 *pixel++ = 255;
99                                 *pixel++ = 255;
100                                 *pixel++ = 255;
101                                 *pixel++ = *inpixel;
102                                 inpixel+=4;
103                         }
104                 }
105                 sprintf (name, "%s_%ifog", loadmodel->name, framenum);
106                 pspriteframe->gl_fogtexturenum = GL_LoadTexture (name, width, height, pixbuf, true, true, 4);
107                 free(pixbuf);
108         }
109
110         return (void *)((byte *)pinframe + sizeof (dspriteframe_t) + size);
111 }
112
113
114 /*
115 =================
116 Mod_LoadSpriteGroup
117 =================
118 */
119 void * Mod_LoadSpriteGroup (void * pin, mspriteframe_t **ppframe, int framenum, int bytesperpixel)
120 {
121         dspritegroup_t          *pingroup;
122         mspritegroup_t          *pspritegroup;
123         int                                     i, numframes;
124         dspriteinterval_t       *pin_intervals;
125         float                           *poutintervals;
126         void                            *ptemp;
127
128         pingroup = (dspritegroup_t *)pin;
129
130         numframes = LittleLong (pingroup->numframes);
131
132         pspritegroup = Hunk_AllocName (sizeof (mspritegroup_t) +
133                                 (numframes - 1) * sizeof (pspritegroup->frames[0]), loadname);
134
135         pspritegroup->numframes = numframes;
136
137         *ppframe = (mspriteframe_t *)pspritegroup;
138
139         pin_intervals = (dspriteinterval_t *)(pingroup + 1);
140
141         poutintervals = Hunk_AllocName (numframes * sizeof (float), loadname);
142
143         pspritegroup->intervals = poutintervals;
144
145         for (i=0 ; i<numframes ; i++)
146         {
147                 *poutintervals = LittleFloat (pin_intervals->interval);
148                 if (*poutintervals <= 0.0)
149                         Host_Error ("Mod_LoadSpriteGroup: interval<=0");
150
151                 poutintervals++;
152                 pin_intervals++;
153         }
154
155         ptemp = (void *)pin_intervals;
156
157         for (i=0 ; i<numframes ; i++)
158         {
159                 ptemp = Mod_LoadSpriteFrame (ptemp, &pspritegroup->frames[i], framenum * 100 + i, bytesperpixel);
160         }
161
162         return ptemp;
163 }
164
165
166 /*
167 =================
168 Mod_LoadSpriteModel
169 =================
170 */
171 void Mod_LoadSpriteModel (model_t *mod, void *buffer)
172 {
173         int                                     i;
174         int                                     version;
175         dsprite_t                       *pin;
176         msprite_t                       *psprite;
177         int                                     numframes;
178         int                                     size;
179         dspriteframetype_t      *pframetype;
180         // LordHavoc: 32bit textures
181         int             bytesperpixel;
182
183         mod->flags = EF_FULLBRIGHT;
184         // LordHavoc: hack to allow sprites to be non-fullbright
185         for (i = 0;i < MAX_QPATH && mod->name[i];i++)
186         {
187                 if (mod->name[i] == '!')
188                 {
189                         mod->flags &= ~EF_FULLBRIGHT;
190                         break;
191                 }
192         }
193
194         pin = (dsprite_t *)buffer;
195
196         version = LittleLong (pin->version);
197         if (version == 2)
198         {
199                 version = 32;
200                 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);
201         }
202         // LordHavoc: 32bit textures
203         if (version != SPRITE_VERSION && version != SPRITE32_VERSION)
204                 Host_Error ("%s has wrong version number "
205                                  "(%i should be %i or %i)", mod->name, version, SPRITE_VERSION, SPRITE32_VERSION);
206         bytesperpixel = 1;
207         if (version == SPRITE32_VERSION)
208                 bytesperpixel = 4;
209
210         numframes = LittleLong (pin->numframes);
211
212         size = sizeof (msprite_t) +     (numframes - 1) * sizeof (psprite->frames);
213
214         psprite = Hunk_AllocName (size, loadname);
215
216         mod->cache.data = psprite;
217
218         psprite->type = LittleLong (pin->type);
219         psprite->maxwidth = LittleLong (pin->width);
220         psprite->maxheight = LittleLong (pin->height);
221         psprite->beamlength = LittleFloat (pin->beamlength);
222         mod->synctype = LittleLong (pin->synctype);
223         psprite->numframes = numframes;
224
225         mod->mins[0] = mod->mins[1] = -psprite->maxwidth/2;
226         mod->maxs[0] = mod->maxs[1] = psprite->maxwidth/2;
227         mod->mins[2] = -psprite->maxheight/2;
228         mod->maxs[2] = psprite->maxheight/2;
229         
230 //
231 // load the frames
232 //
233         if (numframes < 1)
234                 Host_Error ("Mod_LoadSpriteModel: Invalid # of frames: %d\n", numframes);
235
236         mod->numframes = numframes;
237
238         pframetype = (dspriteframetype_t *)(pin + 1);
239
240         for (i=0 ; i<numframes ; i++)
241         {
242                 spriteframetype_t       frametype;
243
244                 frametype = LittleLong (pframetype->type);
245                 psprite->frames[i].type = frametype;
246
247                 if (frametype == SPR_SINGLE)
248                         pframetype = (dspriteframetype_t *) Mod_LoadSpriteFrame (pframetype + 1, &psprite->frames[i].frameptr, i, bytesperpixel);
249                 else
250                         pframetype = (dspriteframetype_t *) Mod_LoadSpriteGroup (pframetype + 1, &psprite->frames[i].frameptr, i, bytesperpixel);
251         }
252
253         mod->type = mod_sprite;
254 }