Coordinates are now floats in network protocol (bloats it yes, but the accuracy allow...
[xonotic/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 char    loadname[32];   // for hunk tags
29
30 extern void Mod_LoadSpriteModel (model_t *mod, void *buffer);
31 extern void Mod_LoadBrushModel (model_t *mod, void *buffer);
32 extern void Mod_LoadAliasModel (model_t *mod, void *buffer);
33 extern void Mod_LoadQ2AliasModel (model_t *mod, void *buffer);
34 extern void Mod_LoadZymoticModel (model_t *mod, void *buffer);
35 model_t *Mod_LoadModel (model_t *mod, qboolean crash);
36
37 #define MAX_MOD_KNOWN   512
38 model_t mod_known[MAX_MOD_KNOWN];
39 int             mod_numknown;
40
41 extern void Mod_BrushInit();
42 extern void Mod_AliasInit();
43 extern void Mod_SpriteInit();
44
45 /*
46 ===============
47 Mod_Init
48 ===============
49 */
50 void Mod_Init (void)
51 {
52         Mod_BrushInit();
53         Mod_AliasInit();
54         Mod_SpriteInit();
55 }
56
57 /*
58 ===============
59 Mod_Init
60
61 Caches the data if needed
62 ===============
63 */
64 void *Mod_Extradata (model_t *mod)
65 {
66         void    *r;
67         
68         r = Cache_Check (&mod->cache);
69         if (r)
70                 return r;
71
72         Mod_LoadModel (mod, true);
73         
74         if (!mod->cache.data)
75                 Host_Error ("Mod_Extradata: caching failed");
76         return mod->cache.data;
77 }
78
79 /*
80 ===================
81 Mod_ClearAll
82 ===================
83 */
84 void Mod_ClearAll (void)
85 {
86         int             i;
87         model_t *mod;
88         
89         for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
90                 if (mod->type != mod_alias)
91                         mod->needload = true;
92 }
93
94 /*
95 ==================
96 Mod_FindName
97
98 ==================
99 */
100 model_t *Mod_FindName (char *name)
101 {
102         int             i;
103         model_t *mod;
104         
105         if (!name[0])
106                 Host_Error ("Mod_ForName: NULL name");
107                 
108 //
109 // search the currently loaded models
110 //
111         for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
112                 if (!strcmp (mod->name, name) )
113                         break;
114                         
115         if (i == mod_numknown)
116         {
117                 if (mod_numknown == MAX_MOD_KNOWN)
118                         Host_Error ("mod_numknown == MAX_MOD_KNOWN");
119                 strcpy (mod->name, name);
120                 mod->needload = true;
121                 mod_numknown++;
122         }
123
124         return mod;
125 }
126
127 /*
128 ==================
129 Mod_TouchModel
130
131 ==================
132 */
133 void Mod_TouchModel (char *name)
134 {
135         model_t *mod;
136         
137         mod = Mod_FindName (name);
138         
139         if (!mod->needload)
140         {
141                 if (mod->type == mod_alias)
142                         Cache_Check (&mod->cache);
143         }
144 }
145
146 /*
147 ==================
148 Mod_LoadModel
149
150 Loads a model into the cache
151 ==================
152 */
153 model_t *Mod_LoadModel (model_t *mod, qboolean crash)
154 {
155         void    *d;
156         unsigned *buf;
157
158         if (!mod->needload)
159         {
160                 if (mod->type == mod_alias)
161                 {
162                         d = Cache_Check (&mod->cache);
163                         if (d)
164                                 return mod;
165                 }
166                 else
167                         return mod;             // not cached at all
168         }
169
170         Con_DPrintf("loading model %s\n", mod->name);
171
172 // load the file
173         buf = (unsigned *)COM_LoadMallocFile (mod->name, false);
174         if (!buf)
175         {
176                 if (crash)
177                         Host_Error ("Mod_NumForName: %s not found", mod->name); // LordHavoc: Sys_Error was *ANNOYING*
178                 return NULL;
179         }
180         
181 // allocate a new model
182 //      COM_FileBase (mod->name, loadname);
183         strcpy(loadname, mod->name);
184         
185         loadmodel = mod;
186
187 // call the apropriate loader
188         mod->needload = false;
189         
190         switch (LittleLong(*(unsigned *)buf))
191         {
192         case IDPOLYHEADER:
193                 Mod_LoadAliasModel (mod, buf);
194                 break;
195
196         case MD2IDALIASHEADER: // LordHavoc: added Quake2 model support
197                 Mod_LoadQ2AliasModel (mod, buf);
198                 break;
199
200         case (('O'<<24)+('M'<<16)+('Y'<<8)+'Z'):
201                 Mod_LoadZymoticModel(mod, buf);
202                 break;
203                 
204         case IDSPRITEHEADER:
205                 Mod_LoadSpriteModel (mod, buf);
206                 break;
207         
208         default:
209                 Mod_LoadBrushModel (mod, buf);
210                 break;
211         }
212         qfree(buf);
213
214         return mod;
215 }
216
217 /*
218 ==================
219 Mod_ForName
220
221 Loads in a model for the given name
222 ==================
223 */
224 model_t *Mod_ForName (char *name, qboolean crash)
225 {
226         model_t *mod;
227         
228         mod = Mod_FindName (name);
229         
230         return Mod_LoadModel (mod, crash);
231 }
232
233 byte    *mod_base;
234
235 /*
236 =================
237 RadiusFromBounds
238 =================
239 */
240 float RadiusFromBounds (vec3_t mins, vec3_t maxs)
241 {
242         int             i;
243         vec3_t  corner;
244
245         for (i=0 ; i<3 ; i++)
246                 corner[i] = fabs(mins[i]) > fabs(maxs[i]) ? fabs(mins[i]) : fabs(maxs[i]);
247
248         return Length (corner);
249 }
250
251 //=============================================================================
252
253 /*
254 ================
255 Mod_Print
256 ================
257 */
258 void Mod_Print (void)
259 {
260         int             i;
261         model_t *mod;
262
263         Con_Printf ("Cached models:\n");
264         for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++)
265         {
266                 Con_Printf ("%8p : %s\n",mod->cache.data, mod->name);
267         }
268 }
269
270