]> icculus.org git repositories - divverent/darkplaces.git/blob - model_shared.c
models don't allocate a texture pool when running dedicated
[divverent/darkplaces.git] / model_shared.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 model_t *loadmodel;
28
29 // LordHavoc: increased from 512 to 2048
30 #define MAX_MOD_KNOWN   2048
31 static model_t mod_known[MAX_MOD_KNOWN];
32
33 static void mod_start(void)
34 {
35         int i;
36         for (i = 0;i < MAX_MOD_KNOWN;i++)
37                 if (mod_known[i].name[0])
38                         Mod_UnloadModel(&mod_known[i]);
39 }
40
41 static void mod_shutdown(void)
42 {
43         int i;
44         for (i = 0;i < MAX_MOD_KNOWN;i++)
45                 if (mod_known[i].name[0])
46                         Mod_UnloadModel(&mod_known[i]);
47 }
48
49 static void mod_newmap(void)
50 {
51 }
52
53 /*
54 ===============
55 Mod_Init
56 ===============
57 */
58 static void Mod_Print (void);
59 static void Mod_Flush (void);
60 void Mod_Init (void)
61 {
62         Mod_BrushInit();
63         Mod_AliasInit();
64         Mod_SpriteInit();
65
66         Cmd_AddCommand ("modellist", Mod_Print);
67         Cmd_AddCommand ("modelflush", Mod_Flush);
68 }
69
70 void Mod_RenderInit(void)
71 {
72         R_RegisterModule("Models", mod_start, mod_shutdown, mod_newmap);
73 }
74
75 void Mod_FreeModel (model_t *mod)
76 {
77         R_FreeTexturePool(&mod->texturepool);
78         Mem_FreePool(&mod->mempool);
79
80         // clear the struct to make it available
81         memset(mod, 0, sizeof(model_t));
82 }
83
84 void Mod_UnloadModel (model_t *mod)
85 {
86         char name[MAX_QPATH];
87         qboolean isworldmodel;
88         strcpy(name, mod->name);
89         isworldmodel = mod->isworldmodel;
90         Mod_FreeModel(mod);
91         strcpy(mod->name, name);
92         mod->isworldmodel = isworldmodel;
93         mod->needload = true;
94 }
95
96 /*
97 ==================
98 Mod_LoadModel
99
100 Loads a model
101 ==================
102 */
103 static model_t *Mod_LoadModel (model_t *mod, qboolean crash, qboolean checkdisk, qboolean isworldmodel)
104 {
105         int crc;
106         void *buf;
107         char tempname[MAX_QPATH];
108
109         mod->used = true;
110
111         if (mod->name[0] == '*') // submodel
112                 return mod;
113
114         if (checkdisk)
115         {
116                 // load the file
117                 buf = COM_LoadFile (mod->name, false);
118                 if (!buf)
119                 {
120                         if (crash)
121                                 Host_Error ("Mod_LoadModel: %s not found", mod->name); // LordHavoc: Sys_Error was *ANNOYING*
122                         return NULL;
123                 }
124
125                 crc = CRC_Block(buf, com_filesize);
126
127                 if (!mod->needload && mod->crc == crc && mod->isworldmodel == isworldmodel)
128                 {
129                         Mem_Free(buf);
130                         return mod; // already loaded
131                 }
132
133                 Con_DPrintf("loading model %s\n", mod->name);
134         }
135         else
136         {
137                 if (!mod->needload && mod->isworldmodel == isworldmodel)
138                         return mod; // already loaded
139
140                 Con_DPrintf("loading model %s\n", mod->name);
141
142                 buf = COM_LoadFile (mod->name, false);
143                 if (!buf)
144                 {
145                         if (crash)
146                                 Host_Error ("Mod_LoadModel: %s not found", mod->name); // LordHavoc: Sys_Error was *ANNOYING*
147                         return NULL;
148                 }
149                 crc = CRC_Block(buf, com_filesize);
150         }
151
152         // make sure nothing got trashed
153         Mem_CheckSentinelsGlobal();
154
155         // allocate a new model
156         loadmodel = mod;
157
158         // LordHavoc: clear the model struct
159         strcpy(tempname, mod->name);
160         Mod_FreeModel(mod);
161
162         strcpy(mod->name, tempname);
163         mod->isworldmodel = isworldmodel;
164         mod->needload = false;
165         mod->used = true;
166         mod->crc = crc;
167
168         // all models use memory, so allocate a memory pool
169         mod->mempool = Mem_AllocPool(mod->name);
170         // all models load textures, so allocate a texture pool
171         if (cls.state != ca_dedicated)
172                 mod->texturepool = R_AllocTexturePool();
173
174         // call the apropriate loader
175              if (!memcmp(buf, "IDPO"    , 4)) Mod_LoadAliasModel  (mod, buf);
176         else if (!memcmp(buf, "IDP2"    , 4)) Mod_LoadQ2AliasModel(mod, buf);
177         else if (!memcmp(buf, "ZYMOTIC" , 7)) Mod_LoadZymoticModel(mod, buf);
178         else if (!memcmp(buf, "IDSP"    , 4)) Mod_LoadSpriteModel (mod, buf);
179         else                                  Mod_LoadBrushModel  (mod, buf);
180
181         Mem_Free(buf);
182
183         // make sure nothing got trashed
184         Mem_CheckSentinelsGlobal();
185
186         return mod;
187 }
188
189 void Mod_CheckLoaded (model_t *mod)
190 {
191         if (mod)
192         {
193                 if (!mod->needload)
194                 {
195                         if (mod->type == mod_invalid)
196                                 Host_Error("Mod_CheckLoaded: invalid model\n");
197                         mod->used = true;
198                         return;
199                 }
200
201                 Mod_LoadModel(mod, true, true, mod->isworldmodel);
202         }
203 }
204
205 /*
206 ===================
207 Mod_ClearAll
208 ===================
209 */
210 void Mod_ClearAll (void)
211 {
212         /*
213         int             i;
214         model_t *mod;
215
216         for (i = 0, mod = mod_known;i < MAX_MOD_KNOWN;i++, mod++)
217                 if (mod->name[0])
218                         if (mod->usesheap)
219                                 Mod_FreeModel(mod);
220         */
221 }
222
223 void Mod_ClearUsed(void)
224 {
225         int             i;
226         model_t *mod;
227
228         for (i = 0, mod = mod_known;i < MAX_MOD_KNOWN;i++, mod++)
229                 if (mod->name[0])
230                         mod->used = false;
231 }
232
233 void Mod_PurgeUnused(void)
234 {
235         int             i;
236         model_t *mod;
237
238         for (i = 0, mod = mod_known;i < MAX_MOD_KNOWN;i++, mod++)
239                 if (mod->name[0])
240                         if (!mod->used)
241                                 Mod_FreeModel(mod);
242 }
243
244 /*
245 ==================
246 Mod_FindName
247
248 ==================
249 */
250 model_t *Mod_FindName (char *name)
251 {
252         int             i;
253         model_t *mod, *freemod;
254
255         if (!name[0])
256                 Host_Error ("Mod_ForName: NULL name");
257
258 // search the currently loaded models
259         freemod = NULL;
260         for (i = 0, mod = mod_known;i < MAX_MOD_KNOWN;i++, mod++)
261         {
262                 if (mod->name[0])
263                 {
264                         if (!strcmp (mod->name, name))
265                         {
266                                 mod->used = true;
267                                 return mod;
268                         }
269                 }
270                 else if (freemod == NULL)
271                         freemod = mod;
272         }
273
274         if (freemod)
275         {
276                 mod = freemod;
277                 strcpy (mod->name, name);
278                 mod->needload = true;
279                 mod->used = true;
280                 return mod;
281         }
282
283         Host_Error ("Mod_FindName: ran out of models\n");
284         return NULL;
285 }
286
287 /*
288 ==================
289 Mod_TouchModel
290
291 ==================
292 */
293 void Mod_TouchModel (char *name)
294 {
295         model_t *mod;
296
297         mod = Mod_FindName (name);
298         mod->used = true;
299 }
300
301 /*
302 ==================
303 Mod_ForName
304
305 Loads in a model for the given name
306 ==================
307 */
308 model_t *Mod_ForName (char *name, qboolean crash, qboolean checkdisk, qboolean isworldmodel)
309 {
310         model_t *mod;
311
312         mod = Mod_FindName (name);
313         mod->used = true;
314
315         return Mod_LoadModel (mod, crash, checkdisk, isworldmodel);
316 }
317
318 byte    *mod_base;
319
320 /*
321 =================
322 RadiusFromBounds
323 =================
324 */
325 /*
326 float RadiusFromBounds (vec3_t mins, vec3_t maxs)
327 {
328         int             i;
329         vec3_t  corner;
330
331         for (i=0 ; i<3 ; i++)
332                 corner[i] = fabs(mins[i]) > fabs(maxs[i]) ? fabs(mins[i]) : fabs(maxs[i]);
333
334         return Length (corner);
335 }
336 */
337
338 //=============================================================================
339
340 /*
341 ================
342 Mod_Print
343 ================
344 */
345 static void Mod_Print (void)
346 {
347         int             i;
348         model_t *mod;
349
350         Con_Printf ("Loaded models:\n");
351         for (i = 0, mod = mod_known;i < MAX_MOD_KNOWN;i++, mod++)
352                 if (mod->name[0])
353                         Con_Printf ("%4iK %s\n", mod->mempool ? (mod->mempool->totalsize + 1023) / 1024 : 0, mod->name);
354 }
355
356 static void Mod_Flush (void)
357 {
358         int             i;
359
360         Con_Printf ("Unloading models\n");
361         for (i = 0;i < MAX_MOD_KNOWN;i++)
362                 if (mod_known[i].name[0])
363                         Mod_UnloadModel(&mod_known[i]);
364 }
365