Rev 5053 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5053 | Rev 5075 | ||
---|---|---|---|
1 | //------------------------------------- MD2/MD3 LIBRARY BEGINS -------------------------------------
|
1 | //------------------------------------- MD2/MD3 LIBRARY BEGINS -------------------------------------
|
2 | 2 | ||
3 | #ifdef USE_OPENGL
|
3 | #ifdef USE_OPENGL
|
4 | 4 | ||
5 | #include "compat.h"
|
5 | #include "compat.h"
|
6 | #include "build.h"
|
6 | #include "build.h"
|
7 | #include "glbuild.h"
|
7 | #include "glbuild.h"
|
8 | #include "pragmas.h"
|
8 | #include "pragmas.h"
|
9 | #include "baselayer.h"
|
9 | #include "baselayer.h"
|
10 | #include "engine_priv.h"
|
10 | #include "engine_priv.h"
|
11 | #include "hightile.h"
|
11 | #include "hightile.h"
|
12 | #include "polymost.h"
|
12 | #include "polymost.h"
|
13 | #include "texcache.h"
|
13 | #include "texcache.h"
|
14 | #include "mdsprite.h"
|
14 | #include "mdsprite.h"
|
15 | #include "cache1d.h"
|
15 | #include "cache1d.h"
|
16 | #include "kplib.h"
|
16 | #include "kplib.h"
|
17 | #include "common.h"
|
17 | #include "common.h"
|
18 | 18 | ||
19 | #include <math.h>
|
19 | #include <math.h>
|
20 | #include <float.h>
|
20 | #include <float.h>
|
21 | 21 | ||
22 | static int32_t curextra=MAXTILES; |
22 | static int32_t curextra=MAXTILES; |
23 | 23 | ||
24 | #define MIN_CACHETIME_PRINT 10
|
24 | #define MIN_CACHETIME_PRINT 10
|
25 | 25 | ||
26 | static void QuitOnFatalError(const char *msg) |
26 | static void QuitOnFatalError(const char *msg) |
27 | {
|
27 | {
|
28 | if (msg) |
28 | if (msg) |
29 | initprintf("%s\n", msg); |
29 | initprintf("%s\n", msg); |
30 | uninitengine(); |
30 | uninitengine(); |
31 | Bexit(1); |
31 | Bexit(1); |
32 | }
|
32 | }
|
33 | 33 | ||
34 | 34 | ||
35 | static int32_t addtileP(int32_t model,int32_t tile,int32_t pallet) |
35 | static int32_t addtileP(int32_t model,int32_t tile,int32_t pallet) |
36 | {
|
36 | {
|
37 | // tile >= 0 && tile < MAXTILES
|
37 | // tile >= 0 && tile < MAXTILES
|
38 | 38 | ||
39 | UNREFERENCED_PARAMETER(model); |
39 | UNREFERENCED_PARAMETER(model); |
40 | if (curextra==MAXTILES+EXTRATILES-1) |
40 | if (curextra==MAXTILES+EXTRATILES-1) |
41 | {
|
41 | {
|
42 | initprintf("warning: max EXTRATILES reached\n"); |
42 | initprintf("warning: max EXTRATILES reached\n"); |
43 | return curextra; |
43 | return curextra; |
44 | }
|
44 | }
|
45 | 45 | ||
46 | if (tile2model[tile].modelid==-1) |
46 | if (tile2model[tile].modelid==-1) |
47 | {
|
47 | {
|
48 | tile2model[tile].pal=pallet; |
48 | tile2model[tile].pal=pallet; |
49 | return tile; |
49 | return tile; |
50 | }
|
50 | }
|
51 | 51 | ||
52 | if (tile2model[tile].pal==pallet) |
52 | if (tile2model[tile].pal==pallet) |
53 | return tile; |
53 | return tile; |
54 | 54 | ||
55 | while (tile2model[tile].next!=-1) |
55 | while (tile2model[tile].next!=-1) |
56 | {
|
56 | {
|
57 | tile=tile2model[tile].next; |
57 | tile=tile2model[tile].next; |
58 | if (tile2model[tile].pal==pallet) |
58 | if (tile2model[tile].pal==pallet) |
59 | return tile; |
59 | return tile; |
60 | }
|
60 | }
|
61 | 61 | ||
62 | tile2model[tile].next=curextra; |
62 | tile2model[tile].next=curextra; |
63 | tile2model[curextra].pal=pallet; |
63 | tile2model[curextra].pal=pallet; |
64 | 64 | ||
65 | return curextra++; |
65 | return curextra++; |
66 | }
|
66 | }
|
67 | int32_t Ptile2tile(int32_t tile,int32_t pallet) |
67 | int32_t Ptile2tile(int32_t tile,int32_t pallet) |
68 | {
|
68 | {
|
69 | int32_t t=tile; |
69 | int32_t t=tile; |
70 | // if(tile>=1550&&tile<=1589){initprintf("(%d, %d)\n",tile,pallet);pallet=0;}
|
70 | // if(tile>=1550&&tile<=1589){initprintf("(%d, %d)\n",tile,pallet);pallet=0;}
|
71 | while ((tile=tile2model[tile].next)!=-1) |
71 | while ((tile=tile2model[tile].next)!=-1) |
72 | if (tile2model[tile].pal==pallet) |
72 | if (tile2model[tile].pal==pallet) |
73 | return tile; |
73 | return tile; |
74 | return t; |
74 | return t; |
75 | }
|
75 | }
|
76 | 76 | ||
77 | #define MODELALLOCGROUP 256
|
77 | #define MODELALLOCGROUP 256
|
78 | static int32_t nummodelsalloced = 0; |
78 | static int32_t nummodelsalloced = 0; |
79 | 79 | ||
80 | static int32_t maxmodelverts = 0, allocmodelverts = 0; |
80 | static int32_t maxmodelverts = 0, allocmodelverts = 0; |
81 | static int32_t maxmodeltris = 0, allocmodeltris = 0; |
81 | static int32_t maxmodeltris = 0, allocmodeltris = 0; |
82 | static vec3f_t *vertlist = NULL; //temp array to store interpolated vertices for drawing |
82 | static vec3f_t *vertlist = NULL; //temp array to store interpolated vertices for drawing |
83 | 83 | ||
84 | static int32_t allocvbos = 0, curvbo = 0; |
84 | static int32_t allocvbos = 0, curvbo = 0; |
85 | static GLuint *vertvbos = NULL; |
85 | static GLuint *vertvbos = NULL; |
86 | static GLuint *indexvbos = NULL; |
86 | static GLuint *indexvbos = NULL; |
87 | 87 | ||
88 | #ifdef POLYMER
|
88 | #ifdef POLYMER
|
89 | static int32_t *tribuf = NULL; |
89 | static int32_t *tribuf = NULL; |
90 | static int32_t tribufverts = 0; |
90 | static int32_t tribufverts = 0; |
91 | #endif
|
91 | #endif
|
92 | 92 | ||
93 | static mdmodel_t *mdload(const char *); |
93 | static mdmodel_t *mdload(const char *); |
94 | static void mdfree(mdmodel_t *); |
94 | static void mdfree(mdmodel_t *); |
95 | int32_t globalnoeffect=0; |
95 | int32_t globalnoeffect=0; |
96 | 96 | ||
97 | extern int32_t timerticspersec; |
97 | extern int32_t timerticspersec; |
98 | 98 | ||
99 | void md_freevbos() |
99 | void md_freevbos() |
100 | {
|
100 | {
|
101 | int32_t i; |
101 | int32_t i; |
102 | 102 | ||
103 | for (i=0; i<nextmodelid; i++) |
103 | for (i=0; i<nextmodelid; i++) |
104 | if (models[i]->mdnum == 3) |
104 | if (models[i]->mdnum == 3) |
105 | {
|
105 | {
|
106 | md3model_t *m = (md3model_t *)models[i]; |
106 | md3model_t *m = (md3model_t *)models[i]; |
107 | if (m->vbos) |
107 | if (m->vbos) |
108 | {
|
108 | {
|
109 | // OSD_Printf("freeing model %d vbo\n",i);
|
109 | // OSD_Printf("freeing model %d vbo\n",i);
|
110 | bglDeleteBuffersARB(m->head.numsurfs, m->vbos); |
110 | bglDeleteBuffersARB(m->head.numsurfs, m->vbos); |
111 | Bfree(m->vbos); |
111 | Bfree(m->vbos); |
112 | m->vbos = NULL; |
112 | m->vbos = NULL; |
113 | }
|
113 | }
|
114 | }
|
114 | }
|
115 | 115 | ||
116 | if (allocvbos) |
116 | if (allocvbos) |
117 | {
|
117 | {
|
118 | bglDeleteBuffersARB(allocvbos, indexvbos); |
118 | bglDeleteBuffersARB(allocvbos, indexvbos); |
119 | bglDeleteBuffersARB(allocvbos, vertvbos); |
119 | bglDeleteBuffersARB(allocvbos, vertvbos); |
120 | allocvbos = 0; |
120 | allocvbos = 0; |
121 | }
|
121 | }
|
122 | }
|
122 | }
|
123 | 123 | ||
124 | void freeallmodels() |
124 | void freeallmodels() |
125 | {
|
125 | {
|
126 | int32_t i; |
126 | int32_t i; |
127 | 127 | ||
128 | if (models) |
128 | if (models) |
129 | {
|
129 | {
|
130 | for (i=0; i<nextmodelid; i++) mdfree(models[i]); |
130 | for (i=0; i<nextmodelid; i++) mdfree(models[i]); |
131 | Bfree(models); models = NULL; |
131 | Bfree(models); models = NULL; |
132 | nummodelsalloced = 0; |
132 | nummodelsalloced = 0; |
133 | nextmodelid = 0; |
133 | nextmodelid = 0; |
134 | }
|
134 | }
|
135 | 135 | ||
136 | memset(tile2model,-1,sizeof(tile2model)); |
136 | memset(tile2model,-1,sizeof(tile2model)); |
137 | curextra=MAXTILES; |
137 | curextra=MAXTILES; |
138 | 138 | ||
139 | if (vertlist) |
139 | if (vertlist) |
140 | {
|
140 | {
|
141 | Bfree(vertlist); |
141 | Bfree(vertlist); |
142 | vertlist = NULL; |
142 | vertlist = NULL; |
143 | allocmodelverts = maxmodelverts = 0; |
143 | allocmodelverts = maxmodelverts = 0; |
144 | allocmodeltris = maxmodeltris = 0; |
144 | allocmodeltris = maxmodeltris = 0; |
145 | }
|
145 | }
|
146 | 146 | ||
147 | md_freevbos(); |
147 | md_freevbos(); |
148 | #ifdef POLYMER
|
148 | #ifdef POLYMER
|
149 | DO_FREE_AND_NULL(tribuf); |
149 | DO_FREE_AND_NULL(tribuf); |
150 | #endif
|
150 | #endif
|
151 | }
|
151 | }
|
152 | 152 | ||
153 | 153 | ||
154 | // Skin texture names can be aliased! This is ugly, but at least correct.
|
154 | // Skin texture names can be aliased! This is ugly, but at least correct.
|
155 | static void nullskintexids(GLuint texid) |
155 | static void nullskintexids(GLuint texid) |
156 | {
|
156 | {
|
157 | int32_t i, j; |
157 | int32_t i, j; |
158 | 158 | ||
159 | for (i=0; i<nextmodelid; i++) |
159 | for (i=0; i<nextmodelid; i++) |
160 | {
|
160 | {
|
161 | mdmodel_t *m = models[i]; |
161 | mdmodel_t *m = models[i]; |
162 | 162 | ||
163 | if (m->mdnum == 2 || m->mdnum == 3) |
163 | if (m->mdnum == 2 || m->mdnum == 3) |
164 | {
|
164 | {
|
165 | mdskinmap_t *sk; |
165 | mdskinmap_t *sk; |
166 | md2model_t *m2 = (md2model_t *)m; |
166 | md2model_t *m2 = (md2model_t *)m; |
167 | 167 | ||
168 | for (j=0; j<m2->numskins*(HICEFFECTMASK+1); j++) |
168 | for (j=0; j<m2->numskins*(HICEFFECTMASK+1); j++) |
169 | if (m2->texid[j] == texid) |
169 | if (m2->texid[j] == texid) |
170 | m2->texid[j] = 0; |
170 | m2->texid[j] = 0; |
171 | 171 | ||
172 | for (sk=m2->skinmap; sk; sk=sk->next) |
172 | for (sk=m2->skinmap; sk; sk=sk->next) |
173 | for (j=0; j<(HICEFFECTMASK+1); j++) |
173 | for (j=0; j<(HICEFFECTMASK+1); j++) |
174 | if (sk->texid[j] == texid) |
174 | if (sk->texid[j] == texid) |
175 | sk->texid[j] = 0; |
175 | sk->texid[j] = 0; |
176 | }
|
176 | }
|
177 | }
|
177 | }
|
178 | }
|
178 | }
|
179 | 179 | ||
180 | void clearskins() |
180 | void clearskins() |
181 | {
|
181 | {
|
182 | int32_t i, j; |
182 | int32_t i, j; |
183 | 183 | ||
184 | for (i=0; i<nextmodelid; i++) |
184 | for (i=0; i<nextmodelid; i++) |
185 | {
|
185 | {
|
186 | mdmodel_t *m = models[i]; |
186 | mdmodel_t *m = models[i]; |
187 | 187 | ||
188 | if (m->mdnum == 1) |
188 | if (m->mdnum == 1) |
189 | {
|
189 | {
|
190 | voxmodel_t *v = (voxmodel_t *)m; |
190 | voxmodel_t *v = (voxmodel_t *)m; |
191 | 191 | ||
192 | for (j=0; j<MAXPALOOKUPS; j++) |
192 | for (j=0; j<MAXPALOOKUPS; j++) |
193 | if (v->texid[j]) |
193 | if (v->texid[j]) |
194 | {
|
194 | {
|
195 | bglDeleteTextures(1, &v->texid[j]); |
195 | bglDeleteTextures(1, &v->texid[j]); |
196 | v->texid[j] = 0; |
196 | v->texid[j] = 0; |
197 | }
|
197 | }
|
198 | }
|
198 | }
|
199 | else if (m->mdnum == 2 || m->mdnum == 3) |
199 | else if (m->mdnum == 2 || m->mdnum == 3) |
200 | {
|
200 | {
|
201 | mdskinmap_t *sk; |
201 | mdskinmap_t *sk; |
202 | md2model_t *m2 = (md2model_t *)m; |
202 | md2model_t *m2 = (md2model_t *)m; |
203 | 203 | ||
204 | for (j=0; j<m2->numskins*(HICEFFECTMASK+1); j++) |
204 | for (j=0; j<m2->numskins*(HICEFFECTMASK+1); j++) |
205 | if (m2->texid[j]) |
205 | if (m2->texid[j]) |
206 | {
|
206 | {
|
207 | GLuint otexid = m2->texid[j]; |
207 | GLuint otexid = m2->texid[j]; |
208 | 208 | ||
209 | bglDeleteTextures(1, &m2->texid[j]); |
209 | bglDeleteTextures(1, &m2->texid[j]); |
210 | m2->texid[j] = 0; |
210 | m2->texid[j] = 0; |
211 | 211 | ||
212 | nullskintexids(otexid); |
212 | nullskintexids(otexid); |
213 | }
|
213 | }
|
214 | 214 | ||
215 | for (sk=m2->skinmap; sk; sk=sk->next) |
215 | for (sk=m2->skinmap; sk; sk=sk->next) |
216 | for (j=0; j<(HICEFFECTMASK+1); j++) |
216 | for (j=0; j<(HICEFFECTMASK+1); j++) |
217 | if (sk->texid[j]) |
217 | if (sk->texid[j]) |
218 | {
|
218 | {
|
219 | GLuint otexid = sk->texid[j]; |
219 | GLuint otexid = sk->texid[j]; |
220 | 220 | ||
221 | bglDeleteTextures(1, &sk->texid[j]); |
221 | bglDeleteTextures(1, &sk->texid[j]); |
222 | sk->texid[j] = 0; |
222 | sk->texid[j] = 0; |
223 | 223 | ||
224 | nullskintexids(otexid); |
224 | nullskintexids(otexid); |
225 | }
|
225 | }
|
226 | }
|
226 | }
|
227 | }
|
227 | }
|
228 | 228 | ||
229 | for (i=0; i<MAXVOXELS; i++) |
229 | for (i=0; i<MAXVOXELS; i++) |
230 | {
|
230 | {
|
231 | voxmodel_t *v = voxmodels[i]; |
231 | voxmodel_t *v = voxmodels[i]; |
232 | if (!v) continue; |
232 | if (!v) continue; |
233 | 233 | ||
234 | for (j=0; j<MAXPALOOKUPS; j++) |
234 | for (j=0; j<MAXPALOOKUPS; j++) |
235 | if (v->texid[j]) |
235 | if (v->texid[j]) |
236 | {
|
236 | {
|
237 | bglDeleteTextures(1, &v->texid[j]); |
237 | bglDeleteTextures(1, &v->texid[j]); |
238 | v->texid[j] = 0; |
238 | v->texid[j] = 0; |
239 | }
|
239 | }
|
240 | }
|
240 | }
|
241 | }
|
241 | }
|
242 | 242 | ||
243 | void mdinit() |
243 | void mdinit() |
244 | {
|
244 | {
|
245 | memset(hudmem,0,sizeof(hudmem)); |
245 | memset(hudmem,0,sizeof(hudmem)); |
246 | freeallmodels(); |
246 | freeallmodels(); |
247 | mdinited = 1; |
247 | mdinited = 1; |
248 | }
|
248 | }
|
249 | 249 | ||
250 | int32_t md_loadmodel(const char *fn) |
250 | int32_t md_loadmodel(const char *fn) |
251 | {
|
251 | {
|
252 | mdmodel_t *vm, **ml; |
252 | mdmodel_t *vm, **ml; |
253 | 253 | ||
254 | if (!mdinited) mdinit(); |
254 | if (!mdinited) mdinit(); |
255 | 255 | ||
256 | if (nextmodelid >= nummodelsalloced) |
256 | if (nextmodelid >= nummodelsalloced) |
257 | {
|
257 | {
|
258 | ml = (mdmodel_t **)Xrealloc(models,(nummodelsalloced+MODELALLOCGROUP)*sizeof(void *)); |
258 | ml = (mdmodel_t **)Xrealloc(models,(nummodelsalloced+MODELALLOCGROUP)*sizeof(void *)); |
259 | models = ml; nummodelsalloced += MODELALLOCGROUP; |
259 | models = ml; nummodelsalloced += MODELALLOCGROUP; |
260 | }
|
260 | }
|
261 | 261 | ||
262 | vm = mdload(fn); if (!vm) return(-1); |
262 | vm = mdload(fn); if (!vm) return(-1); |
263 | models[nextmodelid++] = vm; |
263 | models[nextmodelid++] = vm; |
264 | return(nextmodelid-1); |
264 | return(nextmodelid-1); |
265 | }
|
265 | }
|
266 | 266 | ||
267 | int32_t md_setmisc(int32_t modelid, float scale, int32_t shadeoff, float zadd, float yoffset, int32_t flags) |
267 | int32_t md_setmisc(int32_t modelid, float scale, int32_t shadeoff, float zadd, float yoffset, int32_t flags) |
268 | {
|
268 | {
|
269 | mdmodel_t *m; |
269 | mdmodel_t *m; |
270 | 270 | ||
271 | if (!mdinited) mdinit(); |
271 | if (!mdinited) mdinit(); |
272 | 272 | ||
273 | if ((uint32_t)modelid >= (uint32_t)nextmodelid) return -1; |
273 | if ((uint32_t)modelid >= (uint32_t)nextmodelid) return -1; |
274 | m = models[modelid]; |
274 | m = models[modelid]; |
275 | m->bscale = scale; |
275 | m->bscale = scale; |
276 | m->shadeoff = shadeoff; |
276 | m->shadeoff = shadeoff; |
277 | m->zadd = zadd; |
277 | m->zadd = zadd; |
278 | m->yoffset = yoffset; |
278 | m->yoffset = yoffset; |
279 | m->flags = flags; |
279 | m->flags = flags; |
280 | 280 | ||
281 | return 0; |
281 | return 0; |
282 | }
|
282 | }
|
283 | 283 | ||
284 | static int32_t framename2index(mdmodel_t *vm, const char *nam) |
284 | static int32_t framename2index(mdmodel_t *vm, const char *nam) |
285 | {
|
285 | {
|
286 | int32_t i = 0; |
286 | int32_t i = 0; |
287 | 287 | ||
288 | switch (vm->mdnum) |
288 | switch (vm->mdnum) |
289 | {
|
289 | {
|
290 | case 2: |
290 | case 2: |
291 | {
|
291 | {
|
292 | md2model_t *m = (md2model_t *)vm; |
292 | md2model_t *m = (md2model_t *)vm; |
293 | md2frame_t *fr; |
293 | md2frame_t *fr; |
294 | for (i=0; i<m->numframes; i++) |
294 | for (i=0; i<m->numframes; i++) |
295 | {
|
295 | {
|
296 | fr = (md2frame_t *)&m->frames[i*m->framebytes]; |
296 | fr = (md2frame_t *)&m->frames[i*m->framebytes]; |
297 | if (!Bstrcmp(fr->name, nam)) break; |
297 | if (!Bstrcmp(fr->name, nam)) break; |
298 | }
|
298 | }
|
299 | }
|
299 | }
|
300 | break; |
300 | break; |
301 | case 3: |
301 | case 3: |
302 | {
|
302 | {
|
303 | md3model_t *m = (md3model_t *)vm; |
303 | md3model_t *m = (md3model_t *)vm; |
304 | for (i=0; i<m->numframes; i++) |
304 | for (i=0; i<m->numframes; i++) |
305 | if (!Bstrcmp(m->head.frames[i].nam,nam)) break; |
305 | if (!Bstrcmp(m->head.frames[i].nam,nam)) break; |
306 | }
|
306 | }
|
307 | break; |
307 | break; |
308 | }
|
308 | }
|
309 | return(i); |
309 | return(i); |
310 | }
|
310 | }
|
311 | 311 | ||
312 | int32_t md_defineframe(int32_t modelid, const char *framename, int32_t tilenume, int32_t skinnum, float smoothduration, int32_t pal) |
312 | int32_t md_defineframe(int32_t modelid, const char *framename, int32_t tilenume, int32_t skinnum, float smoothduration, int32_t pal) |
313 | {
|
313 | {
|
314 | md2model_t *m; |
314 | md2model_t *m; |
315 | int32_t i; |
315 | int32_t i; |
316 | 316 | ||
317 | if (!mdinited) mdinit(); |
317 | if (!mdinited) mdinit(); |
318 | 318 | ||
319 | if ((uint32_t)modelid >= (uint32_t)nextmodelid) return(-1); |
319 | if ((uint32_t)modelid >= (uint32_t)nextmodelid) return(-1); |
320 | if ((uint32_t)tilenume >= (uint32_t)MAXTILES) return(-2); |
320 | if ((uint32_t)tilenume >= (uint32_t)MAXTILES) return(-2); |
321 | if (!framename) return(-3); |
321 | if (!framename) return(-3); |
322 | 322 | ||
323 | tilenume=addtileP(modelid,tilenume,pal); |
323 | tilenume=addtileP(modelid,tilenume,pal); |
324 | m = (md2model_t *)models[modelid]; |
324 | m = (md2model_t *)models[modelid]; |
325 | if (m->mdnum == 1) |
325 | if (m->mdnum == 1) |
326 | {
|
326 | {
|
327 | tile2model[tilenume].modelid = modelid; |
327 | tile2model[tilenume].modelid = modelid; |
328 | tile2model[tilenume].framenum = tile2model[tilenume].skinnum = 0; |
328 | tile2model[tilenume].framenum = tile2model[tilenume].skinnum = 0; |
329 | return 0; |
329 | return 0; |
330 | }
|
330 | }
|
331 | 331 | ||
332 | i = framename2index((mdmodel_t *)m,framename); |
332 | i = framename2index((mdmodel_t *)m,framename); |
333 | if (i == m->numframes) return(-3); // frame name invalid |
333 | if (i == m->numframes) return(-3); // frame name invalid |
334 | 334 | ||
335 | tile2model[tilenume].modelid = modelid; |
335 | tile2model[tilenume].modelid = modelid; |
336 | tile2model[tilenume].framenum = i; |
336 | tile2model[tilenume].framenum = i; |
337 | tile2model[tilenume].skinnum = skinnum; |
337 | tile2model[tilenume].skinnum = skinnum; |
338 | tile2model[tilenume].smoothduration = smoothduration; |
338 | tile2model[tilenume].smoothduration = smoothduration; |
339 | 339 | ||
340 | return i; |
340 | return i; |
341 | }
|
341 | }
|
342 | 342 | ||
343 | int32_t md_defineanimation(int32_t modelid, const char *framestart, const char *frameend, int32_t fpssc, int32_t flags) |
343 | int32_t md_defineanimation(int32_t modelid, const char *framestart, const char *frameend, int32_t fpssc, int32_t flags) |
344 | {
|
344 | {
|
345 | md2model_t *m; |
345 | md2model_t *m; |
346 | mdanim_t ma, *map; |
346 | mdanim_t ma, *map; |
347 | int32_t i; |
347 | int32_t i; |
348 | 348 | ||
349 | if (!mdinited) mdinit(); |
349 | if (!mdinited) mdinit(); |
350 | 350 | ||
351 | if ((uint32_t)modelid >= (uint32_t)nextmodelid) return(-1); |
351 | if ((uint32_t)modelid >= (uint32_t)nextmodelid) return(-1); |
352 | 352 | ||
353 | Bmemset(&ma, 0, sizeof(ma)); |
353 | Bmemset(&ma, 0, sizeof(ma)); |
354 | m = (md2model_t *)models[modelid]; |
354 | m = (md2model_t *)models[modelid]; |
355 | if (m->mdnum < 2) return 0; |
355 | if (m->mdnum < 2) return 0; |
356 | 356 | ||
357 | //find index of start frame
|
357 | //find index of start frame
|
358 | i = framename2index((mdmodel_t *)m,framestart); |
358 | i = framename2index((mdmodel_t *)m,framestart); |
359 | if (i == m->numframes) return -2; |
359 | if (i == m->numframes) return -2; |
360 | ma.startframe = i; |
360 | ma.startframe = i; |
361 | 361 | ||
362 | //find index of finish frame which must trail start frame
|
362 | //find index of finish frame which must trail start frame
|
363 | i = framename2index((mdmodel_t *)m,frameend); |
363 | i = framename2index((mdmodel_t *)m,frameend); |
364 | if (i == m->numframes) return -3; |
364 | if (i == m->numframes) return -3; |
365 | ma.endframe = i; |
365 | ma.endframe = i; |
366 | 366 | ||
367 | ma.fpssc = fpssc; |
367 | ma.fpssc = fpssc; |
368 | ma.flags = flags; |
368 | ma.flags = flags; |
369 | 369 | ||
370 | map = (mdanim_t *)Xmalloc(sizeof(mdanim_t)); |
370 | map = (mdanim_t *)Xmalloc(sizeof(mdanim_t)); |
371 | 371 | ||
372 | Bmemcpy(map, &ma, sizeof(ma)); |
372 | Bmemcpy(map, &ma, sizeof(ma)); |
373 | 373 | ||
374 | map->next = m->animations; |
374 | map->next = m->animations; |
375 | m->animations = map; |
375 | m->animations = map; |
376 | 376 | ||
377 | return(0); |
377 | return(0); |
378 | }
|
378 | }
|
379 | 379 | ||
380 | #if 0
|
380 | #if 0
|
381 | // FIXME: CURRENTLY DISABLED: interpolation may access frames we consider 'unused'?
|
381 | // FIXME: CURRENTLY DISABLED: interpolation may access frames we consider 'unused'?
|
382 | int32_t md_thinoutmodel(int32_t modelid, uint8_t *usedframebitmap) |
382 | int32_t md_thinoutmodel(int32_t modelid, uint8_t *usedframebitmap) |
383 | {
|
383 | {
|
384 | md3model_t *m; |
384 | md3model_t *m; |
385 | md3surf_t *s; |
385 | md3surf_t *s; |
386 | mdanim_t *anm; |
386 | mdanim_t *anm; |
387 | int32_t i, surfi, sub, usedframes; |
387 | int32_t i, surfi, sub, usedframes; |
388 | static int16_t otonframe[1024]; |
388 | static int16_t otonframe[1024]; |
389 | 389 | ||
390 | if ((uint32_t)modelid >= (uint32_t)nextmodelid) return -1; |
390 | if ((uint32_t)modelid >= (uint32_t)nextmodelid) return -1; |
391 | m = (md3model_t *)models[modelid]; |
391 | m = (md3model_t *)models[modelid]; |
392 | if (m->mdnum != 3) return -2; |
392 | if (m->mdnum != 3) return -2; |
393 | 393 | ||
394 | for (anm=m->animations; anm; anm=anm->next) |
394 | for (anm=m->animations; anm; anm=anm->next) |
395 | {
|
395 | {
|
396 | if (anm->endframe <= anm->startframe) |
396 | if (anm->endframe <= anm->startframe) |
397 | {
|
397 | {
|
398 | // initprintf("backward anim %d-%d\n", anm->startframe, anm->endframe);
|
398 | // initprintf("backward anim %d-%d\n", anm->startframe, anm->endframe);
|
399 | return -3; |
399 | return -3; |
400 | }
|
400 | }
|
401 | 401 | ||
402 | for (i=anm->startframe; i<anm->endframe; i++) |
402 | for (i=anm->startframe; i<anm->endframe; i++) |
403 | usedframebitmap[i>>3] |= (1<<(i&7)); |
403 | usedframebitmap[i>>3] |= (1<<(i&7)); |
404 | }
|
404 | }
|
405 | 405 | ||
406 | sub = 0; |
406 | sub = 0; |
407 | for (i=0; i<m->numframes; i++) |
407 | for (i=0; i<m->numframes; i++) |
408 | {
|
408 | {
|
409 | if (!(usedframebitmap[i>>3]&(1<<(i&7)))) |
409 | if (!(usedframebitmap[i>>3]&(1<<(i&7)))) |
410 | {
|
410 | {
|
411 | sub++;
|
411 | sub++;
|
412 | otonframe[i] = -1; |
412 | otonframe[i] = -1; |
413 | continue; |
413 | continue; |
414 | }
|
414 | }
|
415 | 415 | ||
416 | otonframe[i] = i-sub; |
416 | otonframe[i] = i-sub; |
417 | }
|
417 | }
|
418 | 418 | ||
419 | usedframes = m->numframes - sub; |
419 | usedframes = m->numframes - sub; |
420 | if (usedframes==0 || usedframes==m->numframes) |
420 | if (usedframes==0 || usedframes==m->numframes) |
421 | return usedframes; |
421 | return usedframes; |
422 | 422 | ||
423 | //// THIN OUT! ////
|
423 | //// THIN OUT! ////
|
424 | 424 | ||
425 | for (i=0; i<m->numframes; i++) |
425 | for (i=0; i<m->numframes; i++) |
426 | {
|
426 | {
|
427 | if (otonframe[i]>=0 && otonframe[i] != i) |
427 | if (otonframe[i]>=0 && otonframe[i] != i) |
428 | {
|
428 | {
|
429 | if (m->muladdframes) |
429 | if (m->muladdframes) |
430 | Bmemcpy(&m->muladdframes[2*otonframe[i]], &m->muladdframes[2*i], 2*sizeof(vec3f_t)); |
430 | Bmemcpy(&m->muladdframes[2*otonframe[i]], &m->muladdframes[2*i], 2*sizeof(vec3f_t)); |
431 | Bmemcpy(&m->head.frames[otonframe[i]], &m->head.frames[i], sizeof(md3frame_t)); |
431 | Bmemcpy(&m->head.frames[otonframe[i]], &m->head.frames[i], sizeof(md3frame_t)); |
432 | }
|
432 | }
|
433 | }
|
433 | }
|
434 | 434 | ||
435 | for (surfi=0; surfi < m->head.numsurfs; surfi++) |
435 | for (surfi=0; surfi < m->head.numsurfs; surfi++) |
436 | {
|
436 | {
|
437 | s = &m->head.surfs[surfi]; |
437 | s = &m->head.surfs[surfi]; |
438 | 438 | ||
439 | for (i=0; i<m->numframes; i++) |
439 | for (i=0; i<m->numframes; i++) |
440 | if (otonframe[i]>=0 && otonframe[i] != i) |
440 | if (otonframe[i]>=0 && otonframe[i] != i) |
441 | Bmemcpy(&s->xyzn[otonframe[i]*s->numverts], &s->xyzn[i*s->numverts], s->numverts*sizeof(md3xyzn_t)); |
441 | Bmemcpy(&s->xyzn[otonframe[i]*s->numverts], &s->xyzn[i*s->numverts], s->numverts*sizeof(md3xyzn_t)); |
442 | }
|
442 | }
|
443 | 443 | ||
444 | ////// tweak frame indices in various places
|
444 | ////// tweak frame indices in various places
|
445 | 445 | ||
446 | for (anm=m->animations; anm; anm=anm->next) |
446 | for (anm=m->animations; anm; anm=anm->next) |
447 | {
|
447 | {
|
448 | if (otonframe[anm->startframe]==-1 || otonframe[anm->endframe-1]==-1) |
448 | if (otonframe[anm->startframe]==-1 || otonframe[anm->endframe-1]==-1) |
449 | initprintf("md %d WTF: anm %d %d\n", modelid, anm->startframe, anm->endframe); |
449 | initprintf("md %d WTF: anm %d %d\n", modelid, anm->startframe, anm->endframe); |
450 | 450 | ||
451 | anm->startframe = otonframe[anm->startframe]; |
451 | anm->startframe = otonframe[anm->startframe]; |
452 | anm->endframe = otonframe[anm->endframe-1]; |
452 | anm->endframe = otonframe[anm->endframe-1]; |
453 | }
|
453 | }
|
454 | 454 | ||
455 | for (i=0; i<MAXTILES+EXTRATILES; i++) |
455 | for (i=0; i<MAXTILES+EXTRATILES; i++) |
456 | if (tile2model[i].modelid == modelid) |
456 | if (tile2model[i].modelid == modelid) |
457 | {
|
457 | {
|
458 | if (otonframe[tile2model[i].framenum]==-1) |
458 | if (otonframe[tile2model[i].framenum]==-1) |
459 | initprintf("md %d WTF: tile %d, fr %d\n", modelid, i, tile2model[i].framenum); |
459 | initprintf("md %d WTF: tile %d, fr %d\n", modelid, i, tile2model[i].framenum); |
460 | tile2model[i].framenum = otonframe[tile2model[i].framenum]; |
460 | tile2model[i].framenum = otonframe[tile2model[i].framenum]; |
461 | }
|
461 | }
|
462 | 462 | ||
463 | ////// realloc & change "numframes" everywhere
|
463 | ////// realloc & change "numframes" everywhere
|
464 | 464 | ||
465 | if (m->muladdframes) |
465 | if (m->muladdframes) |
466 | m->muladdframes = Xrealloc(m->muladdframes, 2*sizeof(vec3f_t)*usedframes); |
466 | m->muladdframes = Xrealloc(m->muladdframes, 2*sizeof(vec3f_t)*usedframes); |
467 | m->head.frames = Xrealloc(m->head.frames, sizeof(md3frame_t)*usedframes); |
467 | m->head.frames = Xrealloc(m->head.frames, sizeof(md3frame_t)*usedframes); |
468 | 468 | ||
469 | for (surfi=0; surfi < m->head.numsurfs; surfi++) |
469 | for (surfi=0; surfi < m->head.numsurfs; surfi++) |
470 | {
|
470 | {
|
471 | m->head.surfs[surfi].numframes = usedframes; |
471 | m->head.surfs[surfi].numframes = usedframes; |
472 | // CAN'T do that because xyzn is offset from a larger block when loaded from md3:
|
472 | // CAN'T do that because xyzn is offset from a larger block when loaded from md3:
|
473 | // m->head.surfs[surfi].xyzn = Xrealloc(m->head.surfs[surfi].xyzn, s->numverts*usedframes*sizeof(md3xyzn_t));
|
473 | // m->head.surfs[surfi].xyzn = Xrealloc(m->head.surfs[surfi].xyzn, s->numverts*usedframes*sizeof(md3xyzn_t));
|
474 | }
|
474 | }
|
475 | 475 | ||
476 | m->head.numframes = usedframes; |
476 | m->head.numframes = usedframes; |
477 | m->numframes = usedframes; |
477 | m->numframes = usedframes; |
478 | 478 | ||
479 | ////////////
|
479 | ////////////
|
480 | return usedframes; |
480 | return usedframes; |
481 | }
|
481 | }
|
482 | #endif
|
482 | #endif
|
483 | 483 | ||
484 | int32_t md_defineskin(int32_t modelid, const char *skinfn, int32_t palnum, int32_t skinnum, int32_t surfnum, float param, float specpower, float specfactor) |
484 | int32_t md_defineskin(int32_t modelid, const char *skinfn, int32_t palnum, int32_t skinnum, int32_t surfnum, float param, float specpower, float specfactor) |
485 | {
|
485 | {
|
486 | mdskinmap_t *sk, *skl; |
486 | mdskinmap_t *sk, *skl; |
487 | md2model_t *m; |
487 | md2model_t *m; |
488 | 488 | ||
489 | if (!mdinited) mdinit(); |
489 | if (!mdinited) mdinit(); |
490 | 490 | ||
491 | if ((uint32_t)modelid >= (uint32_t)nextmodelid) return -1; |
491 | if ((uint32_t)modelid >= (uint32_t)nextmodelid) return -1; |
492 | if (!skinfn) return -2; |
492 | if (!skinfn) return -2; |
493 | if ((unsigned)palnum >= (unsigned)MAXPALOOKUPS) return -3; |
493 | if ((unsigned)palnum >= (unsigned)MAXPALOOKUPS) return -3; |
494 | 494 | ||
495 | m = (md2model_t *)models[modelid]; |
495 | m = (md2model_t *)models[modelid]; |
496 | if (m->mdnum < 2) return 0; |
496 | if (m->mdnum < 2) return 0; |
497 | if (m->mdnum == 2) surfnum = 0; |
497 | if (m->mdnum == 2) surfnum = 0; |
498 | 498 | ||
499 | skl = NULL; |
499 | skl = NULL; |
500 | for (sk = m->skinmap; sk; skl = sk, sk = sk->next) |
500 | for (sk = m->skinmap; sk; skl = sk, sk = sk->next) |
501 | if (sk->palette == (uint8_t)palnum && skinnum == sk->skinnum && surfnum == sk->surfnum) |
501 | if (sk->palette == (uint8_t)palnum && skinnum == sk->skinnum && surfnum == sk->surfnum) |
502 | break; |
502 | break; |
503 | if (!sk) |
503 | if (!sk) |
504 | {
|
504 | {
|
505 | sk = (mdskinmap_t *)Xcalloc(1,sizeof(mdskinmap_t)); |
505 | sk = (mdskinmap_t *)Xcalloc(1,sizeof(mdskinmap_t)); |
506 | 506 | ||
507 | if (!skl) m->skinmap = sk; |
507 | if (!skl) m->skinmap = sk; |
508 | else skl->next = sk; |
508 | else skl->next = sk; |
509 | }
|
509 | }
|
510 | else if (sk->fn) Bfree(sk->fn); |
510 | else if (sk->fn) Bfree(sk->fn); |
511 | 511 | ||
512 | sk->palette = (uint8_t)palnum; |
512 | sk->palette = (uint8_t)palnum; |
513 | sk->skinnum = skinnum; |
513 | sk->skinnum = skinnum; |
514 | sk->surfnum = surfnum; |
514 | sk->surfnum = surfnum; |
515 | sk->param = param; |
515 | sk->param = param; |
516 | sk->specpower = specpower; |
516 | sk->specpower = specpower; |
517 | sk->specfactor = specfactor; |
517 | sk->specfactor = specfactor; |
518 | sk->fn = Xstrdup(skinfn); |
518 | sk->fn = Xstrdup(skinfn); |
519 | 519 | ||
520 | return 0; |
520 | return 0; |
521 | }
|
521 | }
|
522 | 522 | ||
523 | int32_t md_definehud(int32_t modelid, int32_t tilex, float xadd, float yadd, float zadd, int32_t angadd, int32_t flags, int32_t fov) |
523 | int32_t md_definehud(int32_t modelid, int32_t tilex, float xadd, float yadd, float zadd, int32_t angadd, int32_t flags, int32_t fov) |
524 | {
|
524 | {
|
525 | if (!mdinited) mdinit(); |
525 | if (!mdinited) mdinit(); |
526 | 526 | ||
527 | if ((uint32_t)modelid >= (uint32_t)nextmodelid) return -1; |
527 | if ((uint32_t)modelid >= (uint32_t)nextmodelid) return -1; |
528 | if ((uint32_t)tilex >= (uint32_t)MAXTILES) return -2; |
528 | if ((uint32_t)tilex >= (uint32_t)MAXTILES) return -2; |
529 | 529 | ||
530 | hudmem[(flags>>2)&1][tilex].add.x = xadd; |
530 | hudmem[(flags>>2)&1][tilex].add.x = xadd; |
531 | hudmem[(flags>>2)&1][tilex].add.y = yadd; |
531 | hudmem[(flags>>2)&1][tilex].add.y = yadd; |
532 | hudmem[(flags>>2)&1][tilex].add.z = zadd; |
532 | hudmem[(flags>>2)&1][tilex].add.z = zadd; |
533 | hudmem[(flags>>2)&1][tilex].angadd = ((int16_t)angadd)|2048; |
533 | hudmem[(flags>>2)&1][tilex].angadd = ((int16_t)angadd)|2048; |
534 | hudmem[(flags>>2)&1][tilex].flags = (int16_t)flags; |
534 | hudmem[(flags>>2)&1][tilex].flags = (int16_t)flags; |
535 | hudmem[(flags>>2)&1][tilex].fov = (int16_t)fov; |
535 | hudmem[(flags>>2)&1][tilex].fov = (int16_t)fov; |
536 | 536 | ||
537 | return 0; |
537 | return 0; |
538 | }
|
538 | }
|
539 | 539 | ||
540 | int32_t md_undefinetile(int32_t tile) |
540 | int32_t md_undefinetile(int32_t tile) |
541 | {
|
541 | {
|
542 | if (!mdinited) return 0; |
542 | if (!mdinited) return 0; |
543 | if ((unsigned)tile >= (unsigned)MAXTILES) return -1; |
543 | if ((unsigned)tile >= (unsigned)MAXTILES) return -1; |
544 | 544 | ||
545 | tile2model[tile].modelid = -1; |
545 | tile2model[tile].modelid = -1; |
546 | tile2model[tile].next=-1; |
546 | tile2model[tile].next=-1; |
547 | hudmem[0][tile].angadd = 0; |
547 | hudmem[0][tile].angadd = 0; |
548 | hudmem[1][tile].angadd = 0; |
548 | hudmem[1][tile].angadd = 0; |
549 | 549 | ||
550 | return 0; |
550 | return 0; |
551 | }
|
551 | }
|
552 | 552 | ||
553 | /* this function is problematic, it leaves NULL holes in model[]
|
553 | /* this function is problematic, it leaves NULL holes in model[]
|
554 | * (which runs from 0 to nextmodelid-1) */
|
554 | * (which runs from 0 to nextmodelid-1) */
|
555 | int32_t md_undefinemodel(int32_t modelid) |
555 | int32_t md_undefinemodel(int32_t modelid) |
556 | {
|
556 | {
|
557 | int32_t i; |
557 | int32_t i; |
558 | if (!mdinited) return 0; |
558 | if (!mdinited) return 0; |
559 | if ((uint32_t)modelid >= (uint32_t)nextmodelid) return -1; |
559 | if ((uint32_t)modelid >= (uint32_t)nextmodelid) return -1; |
560 | 560 | ||
561 | for (i=MAXTILES+EXTRATILES-1; i>=0; i--) |
561 | for (i=MAXTILES+EXTRATILES-1; i>=0; i--) |
562 | if (tile2model[i].modelid == modelid) |
562 | if (tile2model[i].modelid == modelid) |
563 | tile2model[i].modelid = -1; |
563 | tile2model[i].modelid = -1; |
564 | 564 | ||
565 | if (models) |
565 | if (models) |
566 | {
|
566 | {
|
567 | mdfree(models[modelid]); |
567 | mdfree(models[modelid]); |
568 | models[modelid] = NULL; |
568 | models[modelid] = NULL; |
569 | }
|
569 | }
|
570 | 570 | ||
571 | return 0; |
571 | return 0; |
572 | }
|
572 | }
|
573 | 573 | ||
574 | static int32_t daskinloader(int32_t filh, intptr_t *fptr, int32_t *bpl, int32_t *sizx, int32_t *sizy, |
574 | static int32_t daskinloader(int32_t filh, intptr_t *fptr, int32_t *bpl, int32_t *sizx, int32_t *sizy, |
575 | int32_t *osizx, int32_t *osizy, char *hasalpha, int32_t pal, char effect) |
575 | int32_t *osizx, int32_t *osizy, char *hasalpha, int32_t pal, char effect) |
576 | {
|
576 | {
|
577 | int32_t picfillen, j,y,x; |
577 | int32_t picfillen, j,y,x; |
578 | char *picfil,*cptr,al=255; |
578 | char *picfil,*cptr,al=255; |
579 | coltype *pic; |
579 | coltype *pic; |
580 | int32_t xsiz, ysiz, tsizx, tsizy; |
580 | int32_t xsiz, ysiz, tsizx, tsizy; |
581 | int32_t r, g, b; |
581 | int32_t r, g, b; |
582 | 582 | ||
583 | picfillen = kfilelength(filh); |
583 | picfillen = kfilelength(filh); |
584 | picfil = (char *)Xmalloc(picfillen+1); |
584 | picfil = (char *)Xmalloc(picfillen+1); |
585 | kread(filh, picfil, picfillen); |
585 | kread(filh, picfil, picfillen); |
586 | 586 | ||
587 | // tsizx/y = replacement texture's natural size
|
587 | // tsizx/y = replacement texture's natural size
|
588 | // xsiz/y = 2^x size of replacement
|
588 | // xsiz/y = 2^x size of replacement
|
589 | 589 | ||
590 | kpgetdim(picfil,picfillen,&tsizx,&tsizy); |
590 | kpgetdim(picfil,picfillen,&tsizx,&tsizy); |
591 | if (tsizx == 0 || tsizy == 0) { Bfree(picfil); return -2; } |
591 | if (tsizx == 0 || tsizy == 0) { Bfree(picfil); return -2; } |
592 | 592 | ||
593 | if (!glinfo.texnpot) |
593 | if (!glinfo.texnpot) |
594 | {
|
594 | {
|
595 | for (xsiz=1; xsiz<tsizx; xsiz+=xsiz); |
595 | for (xsiz=1; xsiz<tsizx; xsiz+=xsiz); |
596 | for (ysiz=1; ysiz<tsizy; ysiz+=ysiz); |
596 | for (ysiz=1; ysiz<tsizy; ysiz+=ysiz); |
597 | }
|
597 | }
|
598 | else
|
598 | else
|
599 | {
|
599 | {
|
600 | xsiz = tsizx; |
600 | xsiz = tsizx; |
601 | ysiz = tsizy; |
601 | ysiz = tsizy; |
602 | }
|
602 | }
|
603 | *osizx = tsizx; *osizy = tsizy; |
603 | *osizx = tsizx; *osizy = tsizy; |
604 | pic = (coltype *)Xmalloc(xsiz*ysiz*sizeof(coltype)); |
604 | pic = (coltype *)Xmalloc(xsiz*ysiz*sizeof(coltype)); |
605 | 605 | ||
606 | memset(pic,0,xsiz*ysiz*sizeof(coltype)); |
606 | memset(pic,0,xsiz*ysiz*sizeof(coltype)); |
607 | 607 | ||
608 | if (kprender(picfil,picfillen,(intptr_t)pic,xsiz*sizeof(coltype),xsiz,ysiz)) |
608 | if (kprender(picfil,picfillen,(intptr_t)pic,xsiz*sizeof(coltype),xsiz,ysiz)) |
609 | { Bfree(picfil); Bfree(pic); return -2; } |
609 | { Bfree(picfil); Bfree(pic); return -2; } |
610 | Bfree(picfil); |
610 | Bfree(picfil); |
611 | 611 | ||
612 | cptr = &britable[gammabrightness ? 0 : curbrightness][0]; |
612 | cptr = &britable[gammabrightness ? 0 : curbrightness][0]; |
613 | r=(glinfo.bgra)?hictinting[pal].b:hictinting[pal].r; |
613 | r=(glinfo.bgra)?hictinting[pal].b:hictinting[pal].r; |
614 | g=hictinting[pal].g; |
614 | g=hictinting[pal].g; |
615 | b=(glinfo.bgra)?hictinting[pal].r:hictinting[pal].b; |
615 | b=(glinfo.bgra)?hictinting[pal].r:hictinting[pal].b; |
616 | for (y=0,j=0; y<tsizy; y++,j+=xsiz) |
616 | for (y=0,j=0; y<tsizy; y++,j+=xsiz) |
617 | {
|
617 | {
|
618 | coltype *rpptr = &pic[j], tcol; |
618 | coltype *rpptr = &pic[j], tcol; |
619 | 619 | ||
620 | for (x=0; x<tsizx; x++) |
620 | for (x=0; x<tsizx; x++) |
621 | {
|
621 | {
|
622 | tcol.b = cptr[rpptr[x].b]; |
622 | tcol.b = cptr[rpptr[x].b]; |
623 | tcol.g = cptr[rpptr[x].g]; |
623 | tcol.g = cptr[rpptr[x].g]; |
624 | tcol.r = cptr[rpptr[x].r]; |
624 | tcol.r = cptr[rpptr[x].r]; |
625 | 625 | ||
626 | if (effect & HICTINT_GRAYSCALE) |
626 | if (effect & HICTINT_GRAYSCALE) |
627 | {
|
627 | {
|
628 | tcol.g = tcol.r = tcol.b = (uint8_t)((tcol.r * GRAYSCALE_COEFF_RED) + (tcol.g * GRAYSCALE_COEFF_GREEN) + |
628 | tcol.g = tcol.r = tcol.b = (uint8_t)((tcol.r * GRAYSCALE_COEFF_RED) + (tcol.g * GRAYSCALE_COEFF_GREEN) + |
629 | (tcol.b * GRAYSCALE_COEFF_BLUE)); |
629 | (tcol.b * GRAYSCALE_COEFF_BLUE)); |
630 | }
|
630 | }
|
631 | 631 | ||
632 | if (effect & HICTINT_INVERT) |
632 | if (effect & HICTINT_INVERT) |
633 | {
|
633 | {
|
634 | tcol.b = 255-tcol.b; |
634 | tcol.b = 255-tcol.b; |
635 | tcol.g = 255-tcol.g; |
635 | tcol.g = 255-tcol.g; |
636 | tcol.r = 255-tcol.r; |
636 | tcol.r = 255-tcol.r; |
637 | }
|
637 | }
|
638 | 638 | ||
639 | if (effect & HICTINT_COLORIZE) |
639 | if (effect & HICTINT_COLORIZE) |
640 | {
|
640 | {
|
641 | tcol.b = min((int32_t)(tcol.b)*b/64,255); |
641 | tcol.b = min((int32_t)(tcol.b)*b/64,255); |
642 | tcol.g = min((int32_t)(tcol.g)*g/64,255); |
642 | tcol.g = min((int32_t)(tcol.g)*g/64,255); |
643 | tcol.r = min((int32_t)(tcol.r)*r/64,255); |
643 | tcol.r = min((int32_t)(tcol.r)*r/64,255); |
644 | }
|
644 | }
|
645 | 645 | ||
646 | rpptr[x].b = tcol.b; |
646 | rpptr[x].b = tcol.b; |
647 | rpptr[x].g = tcol.g; |
647 | rpptr[x].g = tcol.g; |
648 | rpptr[x].r = tcol.r; |
648 | rpptr[x].r = tcol.r; |
649 | al &= rpptr[x].a; |
649 | al &= rpptr[x].a; |
650 | }
|
650 | }
|
651 | }
|
651 | }
|
652 | if (!glinfo.bgra) |
652 | if (!glinfo.bgra) |
653 | {
|
653 | {
|
654 | for (j=xsiz*ysiz-1; j>=0; j--) |
654 | for (j=xsiz*ysiz-1; j>=0; j--) |
655 | {
|
655 | {
|
656 | swapchar(&pic[j].r, &pic[j].b); |
656 | swapchar(&pic[j].r, &pic[j].b); |
657 | }
|
657 | }
|
658 | }
|
658 | }
|
659 | 659 | ||
660 | *sizx = xsiz; |
660 | *sizx = xsiz; |
661 | *sizy = ysiz; |
661 | *sizy = ysiz; |
662 | *bpl = xsiz; |
662 | *bpl = xsiz; |
663 | *fptr = (intptr_t)pic; |
663 | *fptr = (intptr_t)pic; |
664 | *hasalpha = (al != 255); |
664 | *hasalpha = (al != 255); |
665 | 665 | ||
666 | return 0; |
666 | return 0; |
667 | }
|
667 | }
|
668 | 668 | ||
669 | static inline int32_t hicfxmask(int32_t pal) |
669 | static inline int32_t hicfxmask(int32_t pal) |
670 | {
|
670 | {
|
671 | return globalnoeffect ? 0 : (hictinting[pal].f & HICEFFECTMASK); |
671 | return globalnoeffect ? 0 : (hictinting[pal].f & HICEFFECTMASK); |
672 | }
|
672 | }
|
673 | 673 | ||
674 | //Note: even though it says md2model, it works for both md2model&md3model
|
674 | //Note: even though it says md2model, it works for both md2model&md3model
|
675 | int32_t mdloadskin(md2model_t *m, int32_t number, int32_t pal, int32_t surf) |
675 | int32_t mdloadskin(md2model_t *m, int32_t number, int32_t pal, int32_t surf) |
676 | {
|
676 | {
|
677 | int32_t i, bpl, xsiz=0, ysiz=0, osizx, osizy, texfmt = GL_RGBA, intexfmt = GL_RGBA; |
677 | int32_t i, bpl, osizx, osizy, texfmt = GL_RGBA, intexfmt = GL_RGBA; |
678 | char *skinfile, hasalpha, fn[BMAX_PATH]; |
678 | char *skinfile, hasalpha, fn[BMAX_PATH]; |
679 | GLuint *texidx = NULL; |
679 | GLuint *texidx = NULL; |
680 | mdskinmap_t *sk, *skzero = NULL; |
680 | mdskinmap_t *sk, *skzero = NULL; |
681 | int32_t doalloc = 1, filh; |
681 | int32_t doalloc = 1, filh; |
682 | int32_t gotcache, picfillen; |
682 | int32_t gotcache, picfillen; |
683 | texcacheheader cachead;
|
683 | texcacheheader cachead;
|
684 | 684 | ||
685 | int32_t startticks, willprint=0; |
685 | int32_t startticks, willprint=0; |
- | 686 | vec2_t siz = { 0, 0 }; |
|
686 | 687 | ||
687 | if (m->mdnum == 2) |
688 | if (m->mdnum == 2) |
688 | surf = 0; |
689 | surf = 0; |
689 | 690 | ||
690 | if ((unsigned)pal >= (unsigned)MAXPALOOKUPS) |
691 | if ((unsigned)pal >= (unsigned)MAXPALOOKUPS) |
691 | return 0; |
692 | return 0; |
692 | 693 | ||
693 | i = -1; |
694 | i = -1; |
694 | for (sk = m->skinmap; sk; sk = sk->next) |
695 | for (sk = m->skinmap; sk; sk = sk->next) |
695 | {
|
696 | {
|
696 | if (sk->palette == pal && sk->skinnum == number && sk->surfnum == surf) |
697 | if (sk->palette == pal && sk->skinnum == number && sk->surfnum == surf) |
697 | {
|
698 | {
|
698 | skinfile = sk->fn; |
699 | skinfile = sk->fn; |
699 | texidx = &sk->texid[hicfxmask(pal)]; |
700 | texidx = &sk->texid[hicfxmask(pal)]; |
700 | Bstrncpyz(fn, skinfile, BMAX_PATH); |
701 | Bstrncpyz(fn, skinfile, BMAX_PATH); |
701 | //OSD_Printf("Using exact match skin (pal=%d,skinnum=%d,surfnum=%d) %s\n",pal,number,surf,skinfile);
|
702 | //OSD_Printf("Using exact match skin (pal=%d,skinnum=%d,surfnum=%d) %s\n",pal,number,surf,skinfile);
|
702 | break; |
703 | break; |
703 | }
|
704 | }
|
704 | //If no match, give highest priority to number, then pal.. (Parkar's request, 02/27/2005)
|
705 | //If no match, give highest priority to number, then pal.. (Parkar's request, 02/27/2005)
|
705 | else if ((sk->palette == 0) && (sk->skinnum == number) && (sk->surfnum == surf) && (i < 5)) { i = 5; skzero = sk; } |
706 | else if ((sk->palette == 0) && (sk->skinnum == number) && (sk->surfnum == surf) && (i < 5)) { i = 5; skzero = sk; } |
706 | else if ((sk->palette == pal) && (sk->skinnum == 0) && (sk->surfnum == surf) && (i < 4)) { i = 4; skzero = sk; } |
707 | else if ((sk->palette == pal) && (sk->skinnum == 0) && (sk->surfnum == surf) && (i < 4)) { i = 4; skzero = sk; } |
707 | else if ((sk->palette == 0) && (sk->skinnum == 0) && (sk->surfnum == surf) && (i < 3)) { i = 3; skzero = sk; } |
708 | else if ((sk->palette == 0) && (sk->skinnum == 0) && (sk->surfnum == surf) && (i < 3)) { i = 3; skzero = sk; } |
708 | else if ((sk->palette == 0) && (sk->skinnum == number) && (i < 2)) { i = 2; skzero = sk; } |
709 | else if ((sk->palette == 0) && (sk->skinnum == number) && (i < 2)) { i = 2; skzero = sk; } |
709 | else if ((sk->palette == pal) && (sk->skinnum == 0) && (i < 1)) { i = 1; skzero = sk; } |
710 | else if ((sk->palette == pal) && (sk->skinnum == 0) && (i < 1)) { i = 1; skzero = sk; } |
710 | else if ((sk->palette == 0) && (sk->skinnum == 0) && (i < 0)) { i = 0; skzero = sk; } |
711 | else if ((sk->palette == 0) && (sk->skinnum == 0) && (i < 0)) { i = 0; skzero = sk; } |
711 | }
|
712 | }
|
712 | 713 | ||
713 | if (!sk) |
714 | if (!sk) |
714 | {
|
715 | {
|
715 | if (pal >= (MAXPALOOKUPS - RESERVEDPALS)) |
716 | if (pal >= (MAXPALOOKUPS - RESERVEDPALS)) |
716 | return (0); |
717 | return (0); |
717 | 718 | ||
718 | if (skzero) |
719 | if (skzero) |
719 | {
|
720 | {
|
720 | skinfile = skzero->fn; |
721 | skinfile = skzero->fn; |
721 | texidx = &skzero->texid[hicfxmask(pal)]; |
722 | texidx = &skzero->texid[hicfxmask(pal)]; |
722 | Bstrncpyz(fn, skinfile, BMAX_PATH); |
723 | Bstrncpyz(fn, skinfile, BMAX_PATH); |
723 | //OSD_Printf("Using def skin 0,0 as fallback, pal=%d\n", pal);
|
724 | //OSD_Printf("Using def skin 0,0 as fallback, pal=%d\n", pal);
|
724 | }
|
725 | }
|
725 | else
|
726 | else
|
726 | return 0; |
727 | return 0; |
727 | #if 0
|
728 | #if 0
|
728 | {
|
729 | {
|
729 | // fall back to the model-defined texture
|
730 | // fall back to the model-defined texture
|
730 | if ((unsigned)number >= (unsigned)m->numskins) |
731 | if ((unsigned)number >= (unsigned)m->numskins) |
731 | number = 0; |
732 | number = 0; |
732 | 733 | ||
733 | // m->skinfn is undefined when md3model_t is cast to md2model_t --> crash
|
734 | // m->skinfn is undefined when md3model_t is cast to md2model_t --> crash
|
734 | skinfile = m->skinfn + number*64; |
735 | skinfile = m->skinfn + number*64; |
735 | texidx = &m->texid[number*(HICEFFECTMASK+1) + hicfxmask(pal)]; |
736 | texidx = &m->texid[number*(HICEFFECTMASK+1) + hicfxmask(pal)]; |
736 | Bstrncpyz(fn, m->basepath, BMAX_PATH); |
737 | Bstrncpyz(fn, m->basepath, BMAX_PATH); |
737 | if ((Bstrlen(fn) + Bstrlen(skinfile)) < BMAX_PATH) |
738 | if ((Bstrlen(fn) + Bstrlen(skinfile)) < BMAX_PATH) |
738 | Bstrcat(fn,skinfile); |
739 | Bstrcat(fn,skinfile); |
739 | //OSD_Printf("Using MD2/MD3 skin (%d) %s, pal=%d\n",number,skinfile,pal);
|
740 | //OSD_Printf("Using MD2/MD3 skin (%d) %s, pal=%d\n",number,skinfile,pal);
|
740 | }
|
741 | }
|
741 | #endif
|
742 | #endif
|
742 | }
|
743 | }
|
743 | 744 | ||
744 | if (!skinfile[0]) |
745 | if (!skinfile[0]) |
745 | return 0; |
746 | return 0; |
746 | 747 | ||
747 | if (*texidx) |
748 | if (*texidx) |
748 | return *texidx; |
749 | return *texidx; |
749 | 750 | ||
750 | // possibly fetch an already loaded multitexture :_)
|
751 | // possibly fetch an already loaded multitexture :_)
|
751 | if (pal >= (MAXPALOOKUPS - RESERVEDPALS)) |
752 | if (pal >= (MAXPALOOKUPS - RESERVEDPALS)) |
752 | for (i=0; i<nextmodelid; i++) |
753 | for (i=0; i<nextmodelid; i++) |
753 | for (skzero = ((md2model_t *)models[i])->skinmap; skzero; skzero = skzero->next) |
754 | for (skzero = ((md2model_t *)models[i])->skinmap; skzero; skzero = skzero->next) |
754 | if (!Bstrcasecmp(skzero->fn, sk->fn) && skzero->texid[hicfxmask(pal)]) |
755 | if (!Bstrcasecmp(skzero->fn, sk->fn) && skzero->texid[hicfxmask(pal)]) |
755 | {
|
756 | {
|
756 | int32_t f = hicfxmask(pal); |
757 | int32_t f = hicfxmask(pal); |
757 | 758 | ||
758 | sk->texid[f] = skzero->texid[f]; |
759 | sk->texid[f] = skzero->texid[f]; |
759 | return sk->texid[f]; |
760 | return sk->texid[f]; |
760 | }
|
761 | }
|
761 | 762 | ||
762 | *texidx = 0; |
763 | *texidx = 0; |
763 | 764 | ||
764 | if ((filh = kopen4load(fn, 0)) < 0) |
765 | if ((filh = kopen4load(fn, 0)) < 0) |
765 | {
|
766 | {
|
766 | OSD_Printf("Skin \"%s\" not found.\n",fn); |
767 | OSD_Printf("Skin \"%s\" not found.\n",fn); |
767 | skinfile[0] = 0; |
768 | skinfile[0] = 0; |
768 | return 0; |
769 | return 0; |
769 | }
|
770 | }
|
770 | 771 | ||
771 | 772 | ||
772 | picfillen = kfilelength(filh); |
773 | picfillen = kfilelength(filh); |
773 | kclose(filh); // FIXME: shouldn't have to do this. bug in cache1d.c |
774 | kclose(filh); // FIXME: shouldn't have to do this. bug in cache1d.c |
774 | 775 | ||
775 | startticks = getticks(); |
776 | startticks = getticks(); |
776 | 777 | ||
777 | gotcache = texcache_readtexheader(fn, picfillen, pal<<8, hicfxmask(pal), &cachead, 1); |
778 | gotcache = texcache_readtexheader(fn, picfillen, pal<<8, hicfxmask(pal), &cachead, 1); |
778 | 779 | ||
779 | if (gotcache && !texcache_loadskin(&cachead, &doalloc, texidx, &xsiz, &ysiz)) |
780 | if (gotcache && !texcache_loadskin(&cachead, &doalloc, texidx, &siz.x, &siz.y)) |
780 | {
|
781 | {
|
781 | osizx = cachead.xdim; |
782 | osizx = cachead.xdim; |
782 | osizy = cachead.ydim; |
783 | osizy = cachead.ydim; |
783 | hasalpha = (cachead.flags & CACHEAD_HASALPHA) ? 1 : 0; |
784 | hasalpha = (cachead.flags & CACHEAD_HASALPHA) ? 1 : 0; |
784 | if (pal < (MAXPALOOKUPS - RESERVEDPALS)) |
785 | if (pal < (MAXPALOOKUPS - RESERVEDPALS)) |
785 | m->usesalpha = hasalpha; |
786 | m->usesalpha = hasalpha; |
786 | //kclose(filh); // FIXME: uncomment when cache1d.c is fixed
|
787 | //kclose(filh); // FIXME: uncomment when cache1d.c is fixed
|
787 | }
|
788 | }
|
788 | else
|
789 | else
|
789 | {
|
790 | {
|
790 | int32_t ret; |
791 | int32_t ret; |
791 | intptr_t fptr=0; |
792 | intptr_t fptr=0; |
792 | 793 | ||
793 | gotcache = 0; // the compressed version will be saved to disk |
794 | gotcache = 0; // the compressed version will be saved to disk |
794 | 795 | ||
795 | if ((filh = kopen4load(fn, 0)) < 0) |
796 | if ((filh = kopen4load(fn, 0)) < 0) |
796 | return -1; |
797 | return -1; |
797 | 798 | ||
798 | ret = daskinloader(filh,&fptr,&bpl,&xsiz,&ysiz,&osizx,&osizy,&hasalpha,pal,hicfxmask(pal)); |
799 | ret = daskinloader(filh,&fptr,&bpl,&siz.x,&siz.y,&osizx,&osizy,&hasalpha,pal,hicfxmask(pal)); |
799 | 800 | ||
800 | if (ret) |
801 | if (ret) |
801 | {
|
802 | {
|
802 | kclose(filh); |
803 | kclose(filh); |
803 | OSD_Printf("Failed loading skin file \"%s\": error %d\n", fn, ret); |
804 | OSD_Printf("Failed loading skin file \"%s\": error %d\n", fn, ret); |
804 | if (ret==-1) |
805 | if (ret==-1) |
805 | QuitOnFatalError("OUT OF MEMORY in daskinloader!"); |
806 | QuitOnFatalError("OUT OF MEMORY in daskinloader!"); |
806 | 807 | ||
807 | skinfile[0] = 0; |
808 | skinfile[0] = 0; |
808 | return(0); |
809 | return(0); |
809 | }
|
810 | }
|
810 | else kclose(filh); |
811 | else kclose(filh); |
811 | 812 | ||
812 | willprint = 1; |
813 | willprint = 1; |
813 | 814 | ||
814 | if (pal < (MAXPALOOKUPS - RESERVEDPALS)) |
815 | if (pal < (MAXPALOOKUPS - RESERVEDPALS)) |
815 | m->usesalpha = hasalpha; |
816 | m->usesalpha = hasalpha; |
816 | if ((doalloc&3)==1) |
817 | if ((doalloc&3)==1) |
817 | bglGenTextures(1, texidx); |
818 | bglGenTextures(1, texidx); |
818 | 819 | ||
819 | bglBindTexture(GL_TEXTURE_2D, *texidx); |
820 | bglBindTexture(GL_TEXTURE_2D, *texidx); |
820 | 821 | ||
821 | //gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA,xsiz,ysiz,GL_BGRA_EXT,GL_UNSIGNED_BYTE,(char *)fptr);
|
822 | //gluBuild2DMipmaps(GL_TEXTURE_2D,GL_RGBA,xsiz,ysiz,GL_BGRA_EXT,GL_UNSIGNED_BYTE,(char *)fptr);
|
822 | if (glinfo.texcompr && glusetexcompr) |
823 | if (glinfo.texcompr && glusetexcompr) |
823 | intexfmt = hasalpha ? GL_COMPRESSED_RGBA_ARB : GL_COMPRESSED_RGB_ARB; |
824 | intexfmt = hasalpha ? GL_COMPRESSED_RGBA_ARB : GL_COMPRESSED_RGB_ARB; |
824 | else if (!hasalpha) |
825 | else if (!hasalpha) |
825 | intexfmt = GL_RGB; |
826 | intexfmt = GL_RGB; |
826 | 827 | ||
827 | if (glinfo.bgra) |
828 | if (glinfo.bgra) |
828 | texfmt = GL_BGRA; |
829 | texfmt = GL_BGRA; |
829 | 830 | ||
830 | uploadtexture((doalloc&1), xsiz, ysiz, intexfmt, texfmt, (coltype *)fptr, xsiz, ysiz, DAMETH_HI); |
831 | uploadtexture((doalloc&1), siz, intexfmt, texfmt, (coltype *)fptr, siz, DAMETH_HI); |
831 | Bfree((void *)fptr); |
832 | Bfree((void *)fptr); |
832 | }
|
833 | }
|
833 | 834 | ||
834 | if (!m->skinloaded) |
835 | if (!m->skinloaded) |
835 | {
|
836 | {
|
836 | if (xsiz != osizx || ysiz != osizy) |
837 | if (siz.x != osizx || siz.y != osizy) |
837 | {
|
838 | {
|
838 | float fx, fy; |
839 | float fx, fy; |
839 | fx = ((float)osizx)/((float)xsiz); |
840 | fx = ((float)osizx)/((float)siz.x); |
840 | fy = ((float)osizy)/((float)ysiz); |
841 | fy = ((float)osizy)/((float)siz.y); |
841 | if (m->mdnum == 2) |
842 | if (m->mdnum == 2) |
842 | {
|
843 | {
|
843 | int32_t *lptr; |
844 | int32_t *lptr; |
844 | for (lptr=m->glcmds; (i=*lptr++);) |
845 | for (lptr=m->glcmds; (i=*lptr++);) |
845 | for (i=labs(i); i>0; i--,lptr+=3) |
846 | for (i=labs(i); i>0; i--,lptr+=3) |
846 | {
|
847 | {
|
847 | ((float *)lptr)[0] *= fx; |
848 | ((float *)lptr)[0] *= fx; |
848 | ((float *)lptr)[1] *= fy; |
849 | ((float *)lptr)[1] *= fy; |
849 | }
|
850 | }
|
850 | }
|
851 | }
|
851 | else if (m->mdnum == 3) |
852 | else if (m->mdnum == 3) |
852 | {
|
853 | {
|
853 | md3model_t *m3 = (md3model_t *)m; |
854 | md3model_t *m3 = (md3model_t *)m; |
854 | md3surf_t *s; |
855 | md3surf_t *s; |
855 | int32_t surfi; |
856 | int32_t surfi; |
856 | for (surfi=0; surfi<m3->head.numsurfs; surfi++) |
857 | for (surfi=0; surfi<m3->head.numsurfs; surfi++) |
857 | {
|
858 | {
|
858 | s = &m3->head.surfs[surfi]; |
859 | s = &m3->head.surfs[surfi]; |
859 | for (i=s->numverts-1; i>=0; i--) |
860 | for (i=s->numverts-1; i>=0; i--) |
860 | {
|
861 | {
|
861 | s->uv[i].u *= fx; |
862 | s->uv[i].u *= fx; |
862 | s->uv[i].v *= fy; |
863 | s->uv[i].v *= fy; |
863 | }
|
864 | }
|
864 | }
|
865 | }
|
865 | }
|
866 | }
|
866 | }
|
867 | }
|
867 | m->skinloaded = 1+number; |
868 | m->skinloaded = 1+number; |
868 | }
|
869 | }
|
869 | 870 | ||
870 | bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,glfiltermodes[gltexfiltermode].mag); |
871 | bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,glfiltermodes[gltexfiltermode].mag); |
871 | bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,glfiltermodes[gltexfiltermode].min); |
872 | bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,glfiltermodes[gltexfiltermode].min); |
872 | #ifndef EDUKE32_GLES
|
873 | #ifndef EDUKE32_GLES
|
873 | if (glinfo.maxanisotropy > 1.0) |
874 | if (glinfo.maxanisotropy > 1.0) |
874 | bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAX_ANISOTROPY_EXT,glanisotropy); |
875 | bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAX_ANISOTROPY_EXT,glanisotropy); |
875 | #endif
|
876 | #endif
|
876 | bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); |
877 | bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); |
877 | bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); |
878 | bglTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); |
878 | 879 | ||
879 | if (glinfo.texcompr && glusetexcompr && glusetexcache) |
880 | if (glinfo.texcompr && glusetexcompr && glusetexcache) |
880 | if (!gotcache) |
881 | if (!gotcache) |
881 | {
|
882 | {
|
882 | const int32_t nonpow2 = check_nonpow2(xsiz) || check_nonpow2(ysiz); |
883 | const int32_t nonpow2 = check_nonpow2(siz.x) || check_nonpow2(siz.y); |
883 | 884 | ||
884 | // save off the compressed version
|
885 | // save off the compressed version
|
885 | cachead.quality = r_downsize; |
886 | cachead.quality = r_downsize; |
886 | cachead.xdim = osizx>>cachead.quality; |
887 | cachead.xdim = osizx>>cachead.quality; |
887 | cachead.ydim = osizy>>cachead.quality; |
888 | cachead.ydim = osizy>>cachead.quality; |
888 | 889 | ||
889 | cachead.flags = nonpow2*CACHEAD_NONPOW2 | (hasalpha ? CACHEAD_HASALPHA : 0); |
890 | cachead.flags = nonpow2*CACHEAD_NONPOW2 | (hasalpha ? CACHEAD_HASALPHA : 0); |
890 | 891 | ||
891 | /// OSD_Printf("Caching \"%s\"\n",fn);
|
892 | /// OSD_Printf("Caching \"%s\"\n",fn);
|
892 | texcache_writetex(fn, picfillen, pal<<8, hicfxmask(pal), &cachead); |
893 | texcache_writetex(fn, picfillen, pal<<8, hicfxmask(pal), &cachead); |
893 | 894 | ||
894 | if (willprint) |
895 | if (willprint) |
895 | {
|
896 | {
|
896 | int32_t etime = getticks()-startticks; |
897 | int32_t etime = getticks()-startticks; |
897 | if (etime>=MIN_CACHETIME_PRINT) |
898 | if (etime>=MIN_CACHETIME_PRINT) |
898 | OSD_Printf("Load skin: p%d-e%d \"%s\"... cached... %d ms\n", pal, hicfxmask(pal), fn, etime); |
899 | OSD_Printf("Load skin: p%d-e%d \"%s\"... cached... %d ms\n", pal, hicfxmask(pal), fn, etime); |
899 | willprint = 0; |
900 | willprint = 0; |
900 | }
|
901 | }
|
901 | else
|
902 | else
|
902 | OSD_Printf("Cached skin \"%s\"\n", fn); |
903 | OSD_Printf("Cached skin \"%s\"\n", fn); |
903 | }
|
904 | }
|
904 | 905 | ||
905 | if (willprint) |
906 | if (willprint) |
906 | {
|
907 | {
|
907 | int32_t etime = getticks()-startticks; |
908 | int32_t etime = getticks()-startticks; |
908 | if (etime>=MIN_CACHETIME_PRINT) |
909 | if (etime>=MIN_CACHETIME_PRINT) |
909 | OSD_Printf("Load skin: p%d-e%d \"%s\"... %d ms\n", pal, hicfxmask(pal), fn, etime); |
910 | OSD_Printf("Load skin: p%d-e%d \"%s\"... %d ms\n", pal, hicfxmask(pal), fn, etime); |
910 | }
|
911 | }
|
911 | 912 | ||
912 | return(*texidx); |
913 | return(*texidx); |
913 | }
|
914 | }
|
914 | 915 | ||
915 | //Note: even though it says md2model, it works for both md2model&md3model
|
916 | //Note: even though it says md2model, it works for both md2model&md3model
|
916 | void updateanimation(md2model_t *m, const tspritetype *tspr, uint8_t lpal) |
917 | void updateanimation(md2model_t *m, const tspritetype *tspr, uint8_t lpal) |
917 | {
|
918 | {
|
918 | const mdanim_t *anim; |
919 | const mdanim_t *anim; |
919 | int32_t i, j, k; |
920 | int32_t i, j, k; |
920 | int32_t fps; |
921 | int32_t fps; |
921 | 922 | ||
922 | int32_t tile, smoothdurationp; |
923 | int32_t tile, smoothdurationp; |
923 | spritesmooth_t *smooth; |
924 | spritesmooth_t *smooth; |
924 | spriteext_t *sprext; |
925 | spriteext_t *sprext; |
925 | 926 | ||
926 | if (m->numframes < 2) |
927 | if (m->numframes < 2) |
927 | {
|
928 | {
|
928 | m->interpol = 0; |
929 | m->interpol = 0; |
929 | return; |
930 | return; |
930 | }
|
931 | }
|
931 | 932 | ||
932 | tile = Ptile2tile(tspr->picnum,lpal); |
933 | tile = Ptile2tile(tspr->picnum,lpal); |
933 | m->cframe = m->nframe = tile2model[tile].framenum; |
934 | m->cframe = m->nframe = tile2model[tile].framenum; |
934 | #ifdef DEBUGGINGAIDS
|
935 | #ifdef DEBUGGINGAIDS
|
935 | if (m->cframe >= m->numframes) |
936 | if (m->cframe >= m->numframes) |
936 | OSD_Printf("1: c > n\n"); |
937 | OSD_Printf("1: c > n\n"); |
937 | #endif
|
938 | #endif
|
938 | 939 | ||
939 | smoothdurationp = (r_animsmoothing && (tile2model[tile].smoothduration != 0)); |
940 | smoothdurationp = (r_animsmoothing && (tile2model[tile].smoothduration != 0)); |
940 | 941 | ||
941 | smooth = ((unsigned)tspr->owner < MAXSPRITES+MAXUNIQHUDID) ? &spritesmooth[tspr->owner] : NULL; |
942 | smooth = ((unsigned)tspr->owner < MAXSPRITES+MAXUNIQHUDID) ? &spritesmooth[tspr->owner] : NULL; |
942 | sprext = ((unsigned)tspr->owner < MAXSPRITES+MAXUNIQHUDID) ? &spriteext[tspr->owner] : NULL; |
943 | sprext = ((unsigned)tspr->owner < MAXSPRITES+MAXUNIQHUDID) ? &spriteext[tspr->owner] : NULL; |
943 | 944 | ||
944 | for (anim = m->animations; anim && anim->startframe != m->cframe; anim = anim->next) |
945 | for (anim = m->animations; anim && anim->startframe != m->cframe; anim = anim->next) |
945 | {
|
946 | {
|
946 | /* do nothing */; |
947 | /* do nothing */; |
947 | }
|
948 | }
|
948 | 949 | ||
949 | if (!anim) |
950 | if (!anim) |
950 | {
|
951 | {
|
951 | if (!smoothdurationp || ((smooth->mdoldframe == m->cframe) && (smooth->mdcurframe == m->cframe))) |
952 | if (!smoothdurationp || ((smooth->mdoldframe == m->cframe) && (smooth->mdcurframe == m->cframe))) |
952 | {
|
953 | {
|
953 | m->interpol = 0; |
954 | m->interpol = 0; |
954 | return; |
955 | return; |
955 | }
|
956 | }
|
956 | 957 | ||
957 | // assert(smoothdurationp && ((smooth->mdoldframe != m->cframe) || (smooth->mdcurframe != m->cframe)))
|
958 | // assert(smoothdurationp && ((smooth->mdoldframe != m->cframe) || (smooth->mdcurframe != m->cframe)))
|
958 | 959 | ||
959 | if (smooth->mdoldframe != m->cframe) |
960 | if (smooth->mdoldframe != m->cframe) |
960 | {
|
961 | {
|
961 | if (smooth->mdsmooth == 0) |
962 | if (smooth->mdsmooth == 0) |
962 | {
|
963 | {
|
963 | sprext->mdanimtims = mdtims; |
964 | sprext->mdanimtims = mdtims; |
964 | m->interpol = 0; |
965 | m->interpol = 0; |
965 | smooth->mdsmooth = 1; |
966 | smooth->mdsmooth = 1; |
966 | smooth->mdcurframe = m->cframe; |
967 | smooth->mdcurframe = m->cframe; |
967 | }
|
968 | }
|
968 | 969 | ||
969 | if (smooth->mdcurframe != m->cframe) |
970 | if (smooth->mdcurframe != m->cframe) |
970 | {
|
971 | {
|
971 | sprext->mdanimtims = mdtims; |
972 | sprext->mdanimtims = mdtims; |
972 | m->interpol = 0; |
973 | m->interpol = 0; |
973 | smooth->mdsmooth = 1; |
974 | smooth->mdsmooth = 1; |
974 | smooth->mdoldframe = smooth->mdcurframe; |
975 | smooth->mdoldframe = smooth->mdcurframe; |
975 | smooth->mdcurframe = m->cframe; |
976 | smooth->mdcurframe = m->cframe; |
976 | }
|
977 | }
|
977 | }
|
978 | }
|
978 | else // if (smooth->mdcurframe != m->cframe) |
979 | else // if (smooth->mdcurframe != m->cframe) |
979 | {
|
980 | {
|
980 | sprext->mdanimtims = mdtims; |
981 | sprext->mdanimtims = mdtims; |
981 | m->interpol = 0; |
982 | m->interpol = 0; |
982 | smooth->mdsmooth = 1; |
983 | smooth->mdsmooth = 1; |
983 | smooth->mdoldframe = smooth->mdcurframe; |
984 | smooth->mdoldframe = smooth->mdcurframe; |
984 | smooth->mdcurframe = m->cframe; |
985 | smooth->mdcurframe = m->cframe; |
985 | }
|
986 | }
|
986 | }
|
987 | }
|
987 | else if (/* anim && */ sprext->mdanimcur != anim->startframe) |
988 | else if (/* anim && */ sprext->mdanimcur != anim->startframe) |
988 | {
|
989 | {
|
989 | //if (sprext->flags & SPREXT_NOMDANIM) OSD_Printf("SPREXT_NOMDANIM\n");
|
990 | //if (sprext->flags & SPREXT_NOMDANIM) OSD_Printf("SPREXT_NOMDANIM\n");
|
990 | //OSD_Printf("smooth launched ! oldanim %i new anim %i\n", sprext->mdanimcur, anim->startframe);
|
991 | //OSD_Printf("smooth launched ! oldanim %i new anim %i\n", sprext->mdanimcur, anim->startframe);
|
991 | sprext->mdanimcur = (int16_t)anim->startframe; |
992 | sprext->mdanimcur = (int16_t)anim->startframe; |
992 | sprext->mdanimtims = mdtims; |
993 | sprext->mdanimtims = mdtims; |
993 | m->interpol = 0; |
994 | m->interpol = 0; |
994 | 995 | ||
995 | if (!smoothdurationp) |
996 | if (!smoothdurationp) |
996 | {
|
997 | {
|
997 | m->cframe = m->nframe = anim->startframe; |
998 | m->cframe = m->nframe = anim->startframe; |
998 | #ifdef DEBUGGINGAIDS
|
999 | #ifdef DEBUGGINGAIDS
|
999 | if (m->cframe >= m->numframes) |
1000 | if (m->cframe >= m->numframes) |
1000 | OSD_Printf("2: c > n\n"); |
1001 | OSD_Printf("2: c > n\n"); |
1001 | #endif
|
1002 | #endif
|
1002 | return; |
1003 | return; |
1003 | }
|
1004 | }
|
1004 | 1005 | ||
1005 | m->nframe = anim->startframe; |
1006 | m->nframe = anim->startframe; |
1006 | m->cframe = smooth->mdoldframe; |
1007 | m->cframe = smooth->mdoldframe; |
1007 | #ifdef DEBUGGINGAIDS
|
1008 | #ifdef DEBUGGINGAIDS
|
1008 | if (m->cframe >= m->numframes) |
1009 | if (m->cframe >= m->numframes) |
1009 | OSD_Printf("3: c > n\n"); |
1010 | OSD_Printf("3: c > n\n"); |
1010 | #endif
|
1011 | #endif
|
1011 | smooth->mdsmooth = 1; |
1012 | smooth->mdsmooth = 1; |
1012 | return; |
1013 | return; |
1013 | }
|
1014 | }
|
1014 | 1015 | ||
1015 | fps = smooth->mdsmooth ? Blrintf((1.0f / (float) (tile2model[tile].smoothduration)) * 66.f) : anim->fpssc; |
1016 | fps = smooth->mdsmooth ? Blrintf((1.0f / (float) (tile2model[tile].smoothduration)) * 66.f) : anim->fpssc; |
1016 | 1017 | ||
1017 | i = (mdtims - sprext->mdanimtims)*((fps*timerticspersec)/120); |
1018 | i = (mdtims - sprext->mdanimtims)*((fps*timerticspersec)/120); |
1018 | 1019 | ||
1019 | if (smooth->mdsmooth) |
1020 | if (smooth->mdsmooth) |
1020 | j = 65536; |
1021 | j = 65536; |
1021 | else
|
1022 | else
|
1022 | j = ((anim->endframe+1-anim->startframe)<<16); |
1023 | j = ((anim->endframe+1-anim->startframe)<<16); |
1023 | // XXX: Just in case you play the game for a VERY long time...
|
1024 | // XXX: Just in case you play the game for a VERY long time...
|
1024 | if (i < 0) { i = 0; sprext->mdanimtims = mdtims; } |
1025 | if (i < 0) { i = 0; sprext->mdanimtims = mdtims; } |
1025 | //compare with j*2 instead of j to ensure i stays > j-65536 for MDANIM_ONESHOT
|
1026 | //compare with j*2 instead of j to ensure i stays > j-65536 for MDANIM_ONESHOT
|
1026 | if (anim && (i >= j+j) && (fps) && !mdpause) //Keep mdanimtims close to mdtims to avoid the use of MOD |
1027 | if (anim && (i >= j+j) && (fps) && !mdpause) //Keep mdanimtims close to mdtims to avoid the use of MOD |
1027 | sprext->mdanimtims += j/((fps*timerticspersec)/120); |
1028 | sprext->mdanimtims += j/((fps*timerticspersec)/120); |
1028 | 1029 | ||
1029 | k = i; |
1030 | k = i; |
1030 | 1031 | ||
1031 | if (anim && (anim->flags&MDANIM_ONESHOT)) |
1032 | if (anim && (anim->flags&MDANIM_ONESHOT)) |
1032 | { if (i > j-65536) i = j-65536; } |
1033 | { if (i > j-65536) i = j-65536; } |
1033 | else { if (i >= j) { i -= j; if (i >= j) i %= j; } } |
1034 | else { if (i >= j) { i -= j; if (i >= j) i %= j; } } |
1034 | 1035 | ||
1035 | if (r_animsmoothing && smooth->mdsmooth) |
1036 | if (r_animsmoothing && smooth->mdsmooth) |
1036 | {
|
1037 | {
|
1037 | m->nframe = anim ? anim->startframe : smooth->mdcurframe; |
1038 | m->nframe = anim ? anim->startframe : smooth->mdcurframe; |
1038 | m->cframe = smooth->mdoldframe; |
1039 | m->cframe = smooth->mdoldframe; |
1039 | #ifdef DEBUGGINGAIDS
|
1040 | #ifdef DEBUGGINGAIDS
|
1040 | if (m->cframe >= m->numframes) |
1041 | if (m->cframe >= m->numframes) |
1041 | OSD_Printf("4: c > n\n"); |
1042 | OSD_Printf("4: c > n\n"); |
1042 | #endif
|
1043 | #endif
|
1043 | //OSD_Printf("smoothing... cframe %i nframe %i\n", m->cframe, m->nframe);
|
1044 | //OSD_Printf("smoothing... cframe %i nframe %i\n", m->cframe, m->nframe);
|
1044 | if (k > 65535) |
1045 | if (k > 65535) |
1045 | {
|
1046 | {
|
1046 | sprext->mdanimtims = mdtims; |
1047 | sprext->mdanimtims = mdtims; |
1047 | m->interpol = 0; |
1048 | m->interpol = 0; |
1048 | smooth->mdsmooth = 0; |
1049 | smooth->mdsmooth = 0; |
1049 | m->cframe = m->nframe; // = anim ? anim->startframe : smooth->mdcurframe; |
1050 | m->cframe = m->nframe; // = anim ? anim->startframe : smooth->mdcurframe; |
1050 | #ifdef DEBUGGINGAIDS
|
1051 | #ifdef DEBUGGINGAIDS
|
1051 | if (m->cframe >= m->numframes) |
1052 | if (m->cframe >= m->numframes) |
1052 | OSD_Printf("5: c > n\n"); |
1053 | OSD_Printf("5: c > n\n"); |
1053 | #endif
|
1054 | #endif
|
1054 | smooth->mdoldframe = m->cframe; |
1055 | smooth->mdoldframe = m->cframe; |
1055 | //OSD_Printf("smooth stopped !\n");
|
1056 | //OSD_Printf("smooth stopped !\n");
|
1056 | return; |
1057 | return; |
1057 | }
|
1058 | }
|
1058 | }
|
1059 | }
|
1059 | else
|
1060 | else
|
1060 | {
|
1061 | {
|
1061 | m->cframe = (i>>16)+anim->startframe; |
1062 | m->cframe = (i>>16)+anim->startframe; |
1062 | #ifdef DEBUGGINGAIDS
|
1063 | #ifdef DEBUGGINGAIDS
|
1063 | if (m->cframe >= m->numframes) |
1064 | if (m->cframe >= m->numframes) |
1064 | OSD_Printf("6: c > n\n"); |
1065 | OSD_Printf("6: c > n\n"); |
1065 | #endif
|
1066 | #endif
|
1066 | m->nframe = m->cframe+1; |
1067 | m->nframe = m->cframe+1; |
1067 | if (m->nframe > anim->endframe) // VERIFY: (!(r_animsmoothing && smooth->mdsmooth)) implies (anim!=NULL) ? |
1068 | if (m->nframe > anim->endframe) // VERIFY: (!(r_animsmoothing && smooth->mdsmooth)) implies (anim!=NULL) ? |
1068 | m->nframe = anim->startframe; |
1069 | m->nframe = anim->startframe; |
1069 | 1070 | ||
1070 | smooth->mdoldframe = m->cframe; |
1071 | smooth->mdoldframe = m->cframe; |
1071 | //OSD_Printf("not smoothing... cframe %i nframe %i\n", m->cframe, m->nframe);
|
1072 | //OSD_Printf("not smoothing... cframe %i nframe %i\n", m->cframe, m->nframe);
|
1072 | }
|
1073 | }
|
1073 | 1074 | ||
1074 | m->interpol = ((float)(i&65535))/65536.f; |
1075 | m->interpol = ((float)(i&65535))/65536.f; |
1075 | //OSD_Printf("interpol %f\n", m->interpol);
|
1076 | //OSD_Printf("interpol %f\n", m->interpol);
|
1076 | }
|
1077 | }
|
1077 | 1078 | ||
1078 | // VBO generation and allocation
|
1079 | // VBO generation and allocation
|
1079 | static void mdloadvbos(md3model_t *m) |
1080 | static void mdloadvbos(md3model_t *m) |
1080 | {
|
1081 | {
|
1081 | int32_t i; |
1082 | int32_t i; |
1082 | 1083 | ||
1083 | m->vbos = (GLuint *)Xmalloc(m->head.numsurfs * sizeof(GLuint)); |
1084 | m->vbos = (GLuint *)Xmalloc(m->head.numsurfs * sizeof(GLuint)); |
1084 | bglGenBuffersARB(m->head.numsurfs, m->vbos); |
1085 | bglGenBuffersARB(m->head.numsurfs, m->vbos); |
1085 | 1086 | ||
1086 | i = 0; |
1087 | i = 0; |
1087 | while (i < m->head.numsurfs) |
1088 | while (i < m->head.numsurfs) |
1088 | {
|
1089 | {
|
1089 | bglBindBufferARB(GL_ARRAY_BUFFER_ARB, m->vbos[i]); |
1090 | bglBindBufferARB(GL_ARRAY_BUFFER_ARB, m->vbos[i]); |
1090 | bglBufferDataARB(GL_ARRAY_BUFFER_ARB, m->head.surfs[i].numverts * sizeof(md3uv_t), m->head.surfs[i].uv, GL_STATIC_DRAW_ARB); |
1091 | bglBufferDataARB(GL_ARRAY_BUFFER_ARB, m->head.surfs[i].numverts * sizeof(md3uv_t), m->head.surfs[i].uv, GL_STATIC_DRAW_ARB); |
1091 | i++;
|
1092 | i++;
|
1092 | }
|
1093 | }
|
1093 | bglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); |
1094 | bglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); |
1094 | }
|
1095 | }
|
1095 | 1096 | ||
1096 | //--------------------------------------- MD2 LIBRARY BEGINS ---------------------------------------
|
1097 | //--------------------------------------- MD2 LIBRARY BEGINS ---------------------------------------
|
1097 | static md2model_t *md2load(int32_t fil, const char *filnam) |
1098 | static md2model_t *md2load(int32_t fil, const char *filnam) |
1098 | {
|
1099 | {
|
1099 | md2model_t *m; |
1100 | md2model_t *m; |
1100 | md3model_t *m3; |
1101 | md3model_t *m3; |
1101 | md3surf_t *s; |
1102 | md3surf_t *s; |
1102 | md2frame_t *f; |
1103 | md2frame_t *f; |
1103 | md2head_t head;
|
1104 | md2head_t head;
|
1104 | char st[BMAX_PATH]; |
1105 | char st[BMAX_PATH]; |
1105 | int32_t i, j, k; |
1106 | int32_t i, j, k; |
1106 | 1107 | ||
1107 | int32_t ournumskins, ournumglcmds; |
1108 | int32_t ournumskins, ournumglcmds; |
1108 | 1109 | ||
1109 | m = (md2model_t *)Xcalloc(1,sizeof(md2model_t)); |
1110 | m = (md2model_t *)Xcalloc(1,sizeof(md2model_t)); |
1110 | m->mdnum = 2; m->scale = .01f; |
1111 | m->mdnum = 2; m->scale = .01f; |
1111 | 1112 | ||
1112 | kread(fil,(char *)&head,sizeof(md2head_t)); |
1113 | kread(fil,(char *)&head,sizeof(md2head_t)); |
1113 | #if B_BIG_ENDIAN != 0
|
1114 | #if B_BIG_ENDIAN != 0
|
1114 | head.id = B_LITTLE32(head.id); head.vers = B_LITTLE32(head.vers); |
1115 | head.id = B_LITTLE32(head.id); head.vers = B_LITTLE32(head.vers); |
1115 | head.skinxsiz = B_LITTLE32(head.skinxsiz); head.skinysiz = B_LITTLE32(head.skinysiz); |
1116 | head.skinxsiz = B_LITTLE32(head.skinxsiz); head.skinysiz = B_LITTLE32(head.skinysiz); |
1116 | head.framebytes = B_LITTLE32(head.framebytes); head.numskins = B_LITTLE32(head.numskins); |
1117 | head.framebytes = B_LITTLE32(head.framebytes); head.numskins = B_LITTLE32(head.numskins); |
1117 | head.numverts = B_LITTLE32(head.numverts); head.numuv = B_LITTLE32(head.numuv); |
1118 | head.numverts = B_LITTLE32(head.numverts); head.numuv = B_LITTLE32(head.numuv); |
1118 | head.numtris = B_LITTLE32(head.numtris); head.numglcmds = B_LITTLE32(head.numglcmds); |
1119 | head.numtris = B_LITTLE32(head.numtris); head.numglcmds = B_LITTLE32(head.numglcmds); |
1119 | head.numframes = B_LITTLE32(head.numframes); head.ofsskins = B_LITTLE32(head.ofsskins); |
1120 | head.numframes = B_LITTLE32(head.numframes); head.ofsskins = B_LITTLE32(head.ofsskins); |
1120 | head.ofsuv = B_LITTLE32(head.ofsuv); head.ofstris = B_LITTLE32(head.ofstris); |
1121 | head.ofsuv = B_LITTLE32(head.ofsuv); head.ofstris = B_LITTLE32(head.ofstris); |
1121 | head.ofsframes = B_LITTLE32(head.ofsframes); head.ofsglcmds = B_LITTLE32(head.ofsglcmds); |
1122 | head.ofsframes = B_LITTLE32(head.ofsframes); head.ofsglcmds = B_LITTLE32(head.ofsglcmds); |
1122 | head.ofseof = B_LITTLE32(head.ofseof); |
1123 | head.ofseof = B_LITTLE32(head.ofseof); |
1123 | #endif
|
1124 | #endif
|
1124 | 1125 | ||
1125 | if ((head.id != IDP2_MAGIC) || (head.vers != 8)) { Bfree(m); return(0); } //"IDP2" |
1126 | if ((head.id != IDP2_MAGIC) || (head.vers != 8)) { Bfree(m); return(0); } //"IDP2" |
1126 | 1127 | ||
1127 | ournumskins = head.numskins ? head.numskins : 1; |
1128 | ournumskins = head.numskins ? head.numskins : 1; |
1128 | ournumglcmds = head.numglcmds ? head.numglcmds : 1; |
1129 | ournumglcmds = head.numglcmds ? head.numglcmds : 1; |
1129 | 1130 | ||
1130 | m->numskins = head.numskins; |
1131 | m->numskins = head.numskins; |
1131 | m->numframes = head.numframes; |
1132 | m->numframes = head.numframes; |
1132 | m->numverts = head.numverts; |
1133 | m->numverts = head.numverts; |
1133 | m->numglcmds = head.numglcmds; |
1134 | m->numglcmds = head.numglcmds; |
1134 | m->framebytes = head.framebytes; |
1135 | m->framebytes = head.framebytes; |
1135 | 1136 | ||
1136 | m->frames = (char *)Xmalloc(m->numframes*m->framebytes); |
1137 | m->frames = (char *)Xmalloc(m->numframes*m->framebytes); |
1137 | m->glcmds = (int32_t *)Xmalloc(ournumglcmds*sizeof(int32_t)); |
1138 | m->glcmds = (int32_t *)Xmalloc(ournumglcmds*sizeof(int32_t)); |
1138 | m->tris = (md2tri_t *)Xmalloc(head.numtris*sizeof(md2tri_t)); |
1139 | m->tris = (md2tri_t *)Xmalloc(head.numtris*sizeof(md2tri_t)); |
1139 | m->uv = (md2uv_t *)Xmalloc(head.numuv*sizeof(md2uv_t)); |
1140 | m->uv = (md2uv_t *)Xmalloc(head.numuv*sizeof(md2uv_t)); |
1140 | 1141 | ||
1141 | klseek(fil,head.ofsframes,SEEK_SET); |
1142 | klseek(fil,head.ofsframes,SEEK_SET); |
1142 | if (kread(fil,(char *)m->frames,m->numframes*m->framebytes) != m->numframes*m->framebytes) |
1143 | if (kread(fil,(char *)m->frames,m->numframes*m->framebytes) != m->numframes*m->framebytes) |
1143 | { Bfree(m->uv); Bfree(m->tris); Bfree(m->glcmds); Bfree(m->frames); Bfree(m); return(0); } |
1144 | { Bfree(m->uv); Bfree(m->tris); Bfree(m->glcmds); Bfree(m->frames); Bfree(m); return(0); } |
1144 | 1145 | ||
1145 | if (m->numglcmds > 0) |
1146 | if (m->numglcmds > 0) |
1146 | {
|
1147 | {
|
1147 | klseek(fil,head.ofsglcmds,SEEK_SET); |
1148 | klseek(fil,head.ofsglcmds,SEEK_SET); |
1148 | if (kread(fil,(char *)m->glcmds,m->numglcmds*sizeof(int32_t)) != (int32_t)(m->numglcmds*sizeof(int32_t))) |
1149 | if (kread(fil,(char *)m->glcmds,m->numglcmds*sizeof(int32_t)) != (int32_t)(m->numglcmds*sizeof(int32_t))) |
1149 | { Bfree(m->uv); Bfree(m->tris); Bfree(m->glcmds); Bfree(m->frames); Bfree(m); return(0); } |
1150 | { Bfree(m->uv); Bfree(m->tris); Bfree(m->glcmds); Bfree(m->frames); Bfree(m); return(0); } |
1150 | }
|
1151 | }
|
1151 | 1152 | ||
1152 | klseek(fil,head.ofstris,SEEK_SET); |
1153 | klseek(fil,head.ofstris,SEEK_SET); |
1153 | if (kread(fil,(char *)m->tris,head.numtris*sizeof(md2tri_t)) != (int32_t)(head.numtris*sizeof(md2tri_t))) |
1154 | if (kread(fil,(char *)m->tris,head.numtris*sizeof(md2tri_t)) != (int32_t)(head.numtris*sizeof(md2tri_t))) |
1154 | { Bfree(m->uv); Bfree(m->tris); Bfree(m->glcmds); Bfree(m->frames); Bfree(m); return(0); } |
1155 | { Bfree(m->uv); Bfree(m->tris); Bfree(m->glcmds); Bfree(m->frames); Bfree(m); return(0); } |
1155 | 1156 | ||
1156 | klseek(fil,head.ofsuv,SEEK_SET); |
1157 | klseek(fil,head.ofsuv,SEEK_SET); |
1157 | if (kread(fil,(char *)m->uv,head.numuv*sizeof(md2uv_t)) != (int32_t)(head.numuv*sizeof(md2uv_t))) |
1158 | if (kread(fil,(char *)m->uv,head.numuv*sizeof(md2uv_t)) != (int32_t)(head.numuv*sizeof(md2uv_t))) |
1158 | { Bfree(m->uv); Bfree(m->tris); Bfree(m->glcmds); Bfree(m->frames); Bfree(m); return(0); } |
1159 | { Bfree(m->uv); Bfree(m->tris); Bfree(m->glcmds); Bfree(m->frames); Bfree(m); return(0); } |
1159 | 1160 | ||
1160 | #if B_BIG_ENDIAN != 0
|
1161 | #if B_BIG_ENDIAN != 0
|
1161 | {
|
1162 | {
|
1162 | char *f = (char *)m->frames; |
1163 | char *f = (char *)m->frames; |
1163 | int32_t *l,j; |
1164 | int32_t *l,j; |
1164 | md2frame_t *fr; |
1165 | md2frame_t *fr; |
1165 | 1166 | ||
1166 | for (i = m->numframes-1; i>=0; i--) |
1167 | for (i = m->numframes-1; i>=0; i--) |
1167 | {
|
1168 | {
|
1168 | fr = (md2frame_t *)f; |
1169 | fr = (md2frame_t *)f; |
1169 | l = (int32_t *)&fr->mul; |
1170 | l = (int32_t *)&fr->mul; |
1170 | for (j=5; j>=0; j--) l[j] = B_LITTLE32(l[j]); |
1171 | for (j=5; j>=0; j--) l[j] = B_LITTLE32(l[j]); |
1171 | f += m->framebytes; |
1172 | f += m->framebytes; |
1172 | }
|
1173 | }
|
1173 | 1174 | ||
1174 | for (i = m->numglcmds-1; i>=0; i--) |
1175 | for (i = m->numglcmds-1; i>=0; i--) |
1175 | {
|
1176 | {
|
1176 | m->glcmds[i] = B_LITTLE32(m->glcmds[i]); |
1177 | m->glcmds[i] = B_LITTLE32(m->glcmds[i]); |
1177 | }
|
1178 | }
|
1178 | for (i = head.numtris-1; i>=0; i--) |
1179 | for (i = head.numtris-1; i>=0; i--) |
1179 | {
|
1180 | {
|
1180 | m->tris[i].v[0] = B_LITTLE16(m->tris[i].v[0]); |
1181 | m->tris[i].v[0] = B_LITTLE16(m->tris[i].v[0]); |
1181 | m->tris[i].v[1] = B_LITTLE16(m->tris[i].v[1]); |
1182 | m->tris[i].v[1] = B_LITTLE16(m->tris[i].v[1]); |
1182 | m->tris[i].v[2] = B_LITTLE16(m->tris[i].v[2]); |
1183 | m->tris[i].v[2] = B_LITTLE16(m->tris[i].v[2]); |
1183 | m->tris[i].u[0] = B_LITTLE16(m->tris[i].u[0]); |
1184 | m->tris[i].u[0] = B_LITTLE16(m->tris[i].u[0]); |
1184 | m->tris[i].u[1] = B_LITTLE16(m->tris[i].u[1]); |
1185 | m->tris[i].u[1] = B_LITTLE16(m->tris[i].u[1]); |
1185 | m->tris[i].u[2] = B_LITTLE16(m->tris[i].u[2]); |
1186 | m->tris[i].u[2] = B_LITTLE16(m->tris[i].u[2]); |
1186 | }
|
1187 | }
|
1187 | for (i = head.numuv-1; i>=0; i--) |
1188 | for (i = head.numuv-1; i>=0; i--) |
1188 | {
|
1189 | {
|
1189 | m->uv[i].u = B_LITTLE16(m->uv[i].u); |
1190 | m->uv[i].u = B_LITTLE16(m->uv[i].u); |
1190 | m->uv[i].v = B_LITTLE16(m->uv[i].v); |
1191 | m->uv[i].v = B_LITTLE16(m->uv[i].v); |
1191 | }
|
1192 | }
|
1192 | }
|
1193 | }
|
1193 | #endif
|
1194 | #endif
|
1194 | 1195 | ||
1195 | Bstrcpy(st,filnam); |
1196 | Bstrcpy(st,filnam); |
1196 | for (i=strlen(st)-1; i>0; i--) |
1197 | for (i=strlen(st)-1; i>0; i--) |
1197 | if ((st[i] == '/') || (st[i] == '\\')) { i++; break; } |
1198 | if ((st[i] == '/') || (st[i] == '\\')) { i++; break; } |
1198 | if (i<0) i=0; |
1199 | if (i<0) i=0; |
1199 | st[i] = 0; |
1200 | st[i] = 0; |
1200 | m->basepath = (char *)Xmalloc(i+1); |
1201 | m->basepath = (char *)Xmalloc(i+1); |
1201 | Bstrcpy(m->basepath, st); |
1202 | Bstrcpy(m->basepath, st); |
1202 | 1203 | ||
1203 | m->skinfn = (char *)Xmalloc(ournumskins*64); |
1204 | m->skinfn = (char *)Xmalloc(ournumskins*64); |
1204 | if (m->numskins > 0) |
1205 | if (m->numskins > 0) |
1205 | {
|
1206 | {
|
1206 | klseek(fil,head.ofsskins,SEEK_SET); |
1207 | klseek(fil,head.ofsskins,SEEK_SET); |
1207 | if (kread(fil,m->skinfn,64*m->numskins) != 64*m->numskins) |
1208 | if (kread(fil,m->skinfn,64*m->numskins) != 64*m->numskins) |
1208 | { Bfree(m->glcmds); Bfree(m->frames); Bfree(m); return(0); } |
1209 | { Bfree(m->glcmds); Bfree(m->frames); Bfree(m); return(0); } |
1209 | }
|
1210 | }
|
1210 | 1211 | ||
1211 | m->texid = (GLuint *)Xcalloc(ournumskins, sizeof(GLuint) * (HICEFFECTMASK+1)); |
1212 | m->texid = (GLuint *)Xcalloc(ournumskins, sizeof(GLuint) * (HICEFFECTMASK+1)); |
1212 | 1213 | ||
1213 | maxmodelverts = max(maxmodelverts, m->numverts); |
1214 | maxmodelverts = max(maxmodelverts, m->numverts); |
1214 | maxmodeltris = max(maxmodeltris, head.numtris); |
1215 | maxmodeltris = max(maxmodeltris, head.numtris); |
1215 | 1216 | ||
1216 | //return(m);
|
1217 | //return(m);
|
1217 | 1218 | ||
1218 | // the MD2 is now loaded internally - let's begin the MD3 conversion process
|
1219 | // the MD2 is now loaded internally - let's begin the MD3 conversion process
|
1219 | //OSD_Printf("Beginning md3 conversion.\n");
|
1220 | //OSD_Printf("Beginning md3 conversion.\n");
|
1220 | m3 = (md3model_t *)Xcalloc(1, sizeof(md3model_t)); |
1221 | m3 = (md3model_t *)Xcalloc(1, sizeof(md3model_t)); |
1221 | m3->mdnum = 3; m3->texid = 0; m3->scale = m->scale; |
1222 | m3->mdnum = 3; m3->texid = 0; m3->scale = m->scale; |
1222 | m3->head.id = IDP3_MAGIC; m3->head.vers = 15; |
1223 | m3->head.id = IDP3_MAGIC; m3->head.vers = 15; |
1223 | 1224 | ||
1224 | m3->head.flags = 0; |
1225 | m3->head.flags = 0; |
1225 | 1226 | ||
1226 | m3->head.numframes = m->numframes; |
1227 | m3->head.numframes = m->numframes; |
1227 | m3->head.numtags = 0; m3->head.numsurfs = 1; |
1228 | m3->head.numtags = 0; m3->head.numsurfs = 1; |
1228 | m3->head.numskins = 0; |
1229 | m3->head.numskins = 0; |
1229 | 1230 | ||
1230 | m3->numskins = m3->head.numskins; |
1231 | m3->numskins = m3->head.numskins; |
1231 | m3->numframes = m3->head.numframes; |
1232 | m3->numframes = m3->head.numframes; |
1232 | 1233 | ||
1233 | m3->head.frames = (md3frame_t *)Xcalloc(m3->head.numframes, sizeof(md3frame_t)); |
1234 | m3->head.frames = (md3frame_t *)Xcalloc(m3->head.numframes, sizeof(md3frame_t)); |
1234 | m3->muladdframes = (vec3f_t *)Xcalloc(m->numframes * 2, sizeof(vec3f_t)); |
1235 | m3->muladdframes = (vec3f_t *)Xcalloc(m->numframes * 2, sizeof(vec3f_t)); |
1235 | 1236 | ||
1236 | f = (md2frame_t *)(m->frames); |
1237 | f = (md2frame_t *)(m->frames); |
1237 | 1238 | ||
1238 | // frames converting
|
1239 | // frames converting
|
1239 | i = 0; |
1240 | i = 0; |
1240 | while (i < m->numframes) |
1241 | while (i < m->numframes) |
1241 | {
|
1242 | {
|
1242 | f = (md2frame_t *)&m->frames[i*m->framebytes]; |
1243 | f = (md2frame_t *)&m->frames[i*m->framebytes]; |
1243 | Bstrcpy(m3->head.frames[i].nam, f->name); |
1244 | Bstrcpy(m3->head.frames[i].nam, f->name); |
1244 | //OSD_Printf("Copied frame %s.\n", m3->head.frames[i].nam);
|
1245 | //OSD_Printf("Copied frame %s.\n", m3->head.frames[i].nam);
|
1245 | m3->muladdframes[i*2] = f->mul; |
1246 | m3->muladdframes[i*2] = f->mul; |
1246 | m3->muladdframes[i*2+1] = f->add; |
1247 | m3->muladdframes[i*2+1] = f->add; |
1247 | i++;
|
1248 | i++;
|
1248 | }
|
1249 | }
|
1249 | 1250 | ||
1250 | m3->head.tags = NULL; |
1251 | m3->head.tags = NULL; |
1251 | 1252 | ||
1252 | m3->head.surfs = (md3surf_t *)Xcalloc(1, sizeof(md3surf_t)); |
1253 | m3->head.surfs = (md3surf_t *)Xcalloc(1, sizeof(md3surf_t)); |
1253 | s = m3->head.surfs; |
1254 | s = m3->head.surfs; |
1254 | 1255 | ||
1255 | // model converting
|
1256 | // model converting
|
1256 | s->id = IDP3_MAGIC; s->flags = 0; |
1257 | s->id = IDP3_MAGIC; s->flags = 0; |
1257 | s->numframes = m->numframes; s->numshaders = 0; |
1258 | s->numframes = m->numframes; s->numshaders = 0; |
1258 | s->numtris = head.numtris; |
1259 | s->numtris = head.numtris; |
1259 | s->numverts = head.numtris * 3; // oh man talk about memory effectiveness :(((( |
1260 | s->numverts = head.numtris * 3; // oh man talk about memory effectiveness :(((( |
1260 | // MD2 is actually more accurate than MD3 in term of uv-mapping, because each triangle has a triangle counterpart on the UV-map.
|
1261 | // MD2 is actually more accurate than MD3 in term of uv-mapping, because each triangle has a triangle counterpart on the UV-map.
|
1261 | // In MD3, each vertex unique UV coordinates, meaning that you have to duplicate vertices if you need non-seamless UV-mapping.
|
1262 | // In MD3, each vertex unique UV coordinates, meaning that you have to duplicate vertices if you need non-seamless UV-mapping.
|
1262 | 1263 | ||
1263 | maxmodelverts = max(maxmodelverts, s->numverts); |
1264 | maxmodelverts = max(maxmodelverts, s->numverts); |
1264 | 1265 | ||
1265 | Bstrcpy(s->nam, "Dummy surface from MD2"); |
1266 | Bstrcpy(s->nam, "Dummy surface from MD2"); |
1266 | 1267 | ||
1267 | s->shaders = NULL; |
1268 | s->shaders = NULL; |
1268 | 1269 | ||
1269 | s->tris = (md3tri_t *)Xcalloc(head.numtris, sizeof(md3tri_t)); |
1270 | s->tris = (md3tri_t *)Xcalloc(head.numtris, sizeof(md3tri_t)); |
1270 | s->uv = (md3uv_t *)Xcalloc(s->numverts, sizeof(md3uv_t)); |
1271 | s->uv = (md3uv_t *)Xcalloc(s->numverts, sizeof(md3uv_t)); |
1271 | s->xyzn = (md3xyzn_t *)Xcalloc(s->numverts * m->numframes, sizeof(md3xyzn_t)); |
1272 | s->xyzn = (md3xyzn_t *)Xcalloc(s->numverts * m->numframes, sizeof(md3xyzn_t)); |
1272 | 1273 | ||
1273 | //memoryusage += (s->numverts * m->numframes * sizeof(md3xyzn_t));
|
1274 | //memoryusage += (s->numverts * m->numframes * sizeof(md3xyzn_t));
|
1274 | //OSD_Printf("Current model geometry memory usage : %i.\n", memoryusage);
|
1275 | //OSD_Printf("Current model geometry memory usage : %i.\n", memoryusage);
|
1275 | 1276 | ||
1276 | //OSD_Printf("Number of frames : %i\n", m->numframes);
|
1277 | //OSD_Printf("Number of frames : %i\n", m->numframes);
|
1277 | //OSD_Printf("Number of triangles : %i\n", head.numtris);
|
1278 | //OSD_Printf("Number of triangles : %i\n", head.numtris);
|
1278 | //OSD_Printf("Number of vertices : %i\n", s->numverts);
|
1279 | //OSD_Printf("Number of vertices : %i\n", s->numverts);
|
1279 | 1280 | ||
1280 | // triangle converting
|
1281 | // triangle converting
|
1281 | i = 0; |
1282 | i = 0; |
1282 | while (i < head.numtris) |
1283 | while (i < head.numtris) |
1283 | {
|
1284 | {
|
1284 | j = 0; |
1285 | j = 0; |
1285 | //OSD_Printf("Triangle : %i\n", i);
|
1286 | //OSD_Printf("Triangle : %i\n", i);
|
1286 | while (j < 3) |
1287 | while (j < 3) |
1287 | {
|
1288 | {
|
1288 | // triangle vertex indexes
|
1289 | // triangle vertex indexes
|
1289 | s->tris[i].i[j] = i*3 + j; |
1290 | s->tris[i].i[j] = i*3 + j; |
1290 | 1291 | ||
1291 | // uv coords
|
1292 | // uv coords
|
1292 | s->uv[i*3+j].u = (float)(m->uv[m->tris[i].u[j]].u) / (float)(head.skinxsiz); |
1293 | s->uv[i*3+j].u = (float)(m->uv[m->tris[i].u[j]].u) / (float)(head.skinxsiz); |
1293 | s->uv[i*3+j].v = (float)(m->uv[m->tris[i].u[j]].v) / (float)(head.skinysiz); |
1294 | s->uv[i*3+j].v = (float)(m->uv[m->tris[i].u[j]].v) / (float)(head.skinysiz); |
1294 | 1295 | ||
1295 | // vertices for each frame
|
1296 | // vertices for each frame
|
1296 | k = 0; |
1297 | k = 0; |
1297 | while (k < m->numframes) |
1298 | while (k < m->numframes) |
1298 | {
|
1299 | {
|
1299 | f = (md2frame_t *)&m->frames[k*m->framebytes]; |
1300 | f = (md2frame_t *)&m->frames[k*m->framebytes]; |
1300 | s->xyzn[(k*s->numverts) + (i*3) + j].x = (int16_t) (((f->verts[m->tris[i].v[j]].v[0] * f->mul.x) + f->add.x) * 64.f); |
1301 | s->xyzn[(k*s->numverts) + (i*3) + j].x = (int16_t) (((f->verts[m->tris[i].v[j]].v[0] * f->mul.x) + f->add.x) * 64.f); |
1301 | s->xyzn[(k*s->numverts) + (i*3) + j].y = (int16_t) (((f->verts[m->tris[i].v[j]].v[1] * f->mul.y) + f->add.y) * 64.f); |
1302 | s->xyzn[(k*s->numverts) + (i*3) + j].y = (int16_t) (((f->verts[m->tris[i].v[j]].v[1] * f->mul.y) + f->add.y) * 64.f); |
1302 | s->xyzn[(k*s->numverts) + (i*3) + j].z = (int16_t) (((f->verts[m->tris[i].v[j]].v[2] * f->mul.z) + f->add.z) * 64.f); |
1303 | s->xyzn[(k*s->numverts) + (i*3) + j].z = (int16_t) (((f->verts[m->tris[i].v[j]].v[2] * f->mul.z) + f->add.z) * 64.f); |
1303 | 1304 | ||
1304 | k++;
|
1305 | k++;
|
1305 | }
|
1306 | }
|
1306 | j++;
|
1307 | j++;
|
1307 | }
|
1308 | }
|
1308 | //OSD_Printf("End triangle.\n");
|
1309 | //OSD_Printf("End triangle.\n");
|
1309 | i++;
|
1310 | i++;
|
1310 | }
|
1311 | }
|
1311 | //OSD_Printf("Finished md3 conversion.\n");
|
1312 | //OSD_Printf("Finished md3 conversion.\n");
|
1312 | 1313 | ||
1313 | {
|
1314 | {
|
1314 | mdskinmap_t *sk; |
1315 | mdskinmap_t *sk; |
1315 | 1316 | ||
1316 | sk = (mdskinmap_t *)Xcalloc(1,sizeof(mdskinmap_t)); |
1317 | sk = (mdskinmap_t *)Xcalloc(1,sizeof(mdskinmap_t)); |
1317 | sk->palette = 0; |
1318 | sk->palette = 0; |
1318 | sk->skinnum = 0; |
1319 | sk->skinnum = 0; |
1319 | sk->surfnum = 0; |
1320 | sk->surfnum = 0; |
1320 | 1321 | ||
1321 | if (m->numskins > 0) |
1322 | if (m->numskins > 0) |
1322 | {
|
1323 | {
|
1323 | sk->fn = (char *)Xmalloc(strlen(m->basepath)+strlen(m->skinfn)+1); |
1324 | sk->fn = (char *)Xmalloc(strlen(m->basepath)+strlen(m->skinfn)+1); |
1324 | Bstrcpy(sk->fn, m->basepath); |
1325 | Bstrcpy(sk->fn, m->basepath); |
1325 | Bstrcat(sk->fn, m->skinfn); |
1326 | Bstrcat(sk->fn, m->skinfn); |
1326 | }
|
1327 | }
|
1327 | m3->skinmap = sk; |
1328 | m3->skinmap = sk; |
1328 | }
|
1329 | }
|
1329 | 1330 | ||
1330 | m3->indexes = (uint16_t *)Xmalloc(sizeof(uint16_t) * s->numtris); |
1331 | m3->indexes = (uint16_t *)Xmalloc(sizeof(uint16_t) * s->numtris); |
1331 | m3->vindexes = (uint16_t *)Xmalloc(sizeof(uint16_t) * s->numtris * 3); |
1332 | m3->vindexes = (uint16_t *)Xmalloc(sizeof(uint16_t) * s->numtris * 3); |
1332 | m3->maxdepths = (float *)Xmalloc(sizeof(float) * s->numtris); |
1333 | m3->maxdepths = (float *)Xmalloc(sizeof(float) * s->numtris); |
1333 | 1334 | ||
1334 | m3->vbos = NULL; |
1335 | m3->vbos = NULL; |
1335 | 1336 | ||
1336 | // die MD2 ! DIE !
|
1337 | // die MD2 ! DIE !
|
1337 | Bfree(m->texid); Bfree(m->skinfn); Bfree(m->basepath); Bfree(m->uv); Bfree(m->tris); Bfree(m->glcmds); Bfree(m->frames); Bfree(m); |
1338 | Bfree(m->texid); Bfree(m->skinfn); Bfree(m->basepath); Bfree(m->uv); Bfree(m->tris); Bfree(m->glcmds); Bfree(m->frames); Bfree(m); |
1338 | 1339 | ||
1339 | return((md2model_t *)m3); |
1340 | return((md2model_t *)m3); |
1340 | }
|
1341 | }
|
1341 | //---------------------------------------- MD2 LIBRARY ENDS ----------------------------------------
|
1342 | //---------------------------------------- MD2 LIBRARY ENDS ----------------------------------------
|
1342 | 1343 | ||
1343 | // DICHOTOMIC RECURSIVE SORTING - USED BY MD3DRAW
|
1344 | // DICHOTOMIC RECURSIVE SORTING - USED BY MD3DRAW
|
1344 | int32_t partition(uint16_t *indexes, float *depths, int32_t f, int32_t l) |
1345 | int32_t partition(uint16_t *indexes, float *depths, int32_t f, int32_t l) |
1345 | {
|
1346 | {
|
1346 | int32_t up = f, down = l; |
1347 | int32_t up = f, down = l; |
1347 | float piv = depths[f]; |
1348 | float piv = depths[f]; |
1348 | uint16_t piv2 = indexes[f]; |
1349 | uint16_t piv2 = indexes[f]; |
1349 | do
|
1350 | do
|
1350 | {
|
1351 | {
|
1351 | while ((depths[up] <= piv) && (up < l)) |
1352 | while ((depths[up] <= piv) && (up < l)) |
1352 | up++;
|
1353 | up++;
|
1353 | while ((depths[down] > piv) && (down > f)) |
1354 | while ((depths[down] > piv) && (down > f)) |
1354 | down--;
|
1355 | down--;
|
1355 | if (up < down) |
1356 | if (up < down) |
1356 | {
|
1357 | {
|
1357 | swapfloat(&depths[up], &depths[down]); |
1358 | swapfloat(&depths[up], &depths[down]); |
1358 | swapshort(&indexes[up], &indexes[down]); |
1359 | swapshort(&indexes[up], &indexes[down]); |
1359 | }
|
1360 | }
|
1360 | }
|
1361 | }
|
1361 | while (down > up); |
1362 | while (down > up); |
1362 | depths[f] = depths[down], depths[down] = piv; |
1363 | depths[f] = depths[down], depths[down] = piv; |
1363 | indexes[f] = indexes[down], indexes[down] = piv2; |
1364 | indexes[f] = indexes[down], indexes[down] = piv2; |
1364 | return down; |
1365 | return down; |
1365 | }
|
1366 | }
|
1366 | 1367 | ||
1367 | static inline void quicksort(uint16_t *indexes, float *depths, int32_t first, int32_t last) |
1368 | static inline void quicksort(uint16_t *indexes, float *depths, int32_t first, int32_t last) |
1368 | {
|
1369 | {
|
1369 | int32_t pivIndex; |
1370 | int32_t pivIndex; |
1370 | if (first >= last) return; |
1371 | if (first >= last) return; |
1371 | pivIndex = partition(indexes, depths, first, last); |
1372 | pivIndex = partition(indexes, depths, first, last); |
1372 | if (first < (pivIndex-1)) quicksort(indexes, depths, first, (pivIndex-1)); |
1373 | if (first < (pivIndex-1)) quicksort(indexes, depths, first, (pivIndex-1)); |
1373 | if ((pivIndex+1) >= last) return; |
1374 | if ((pivIndex+1) >= last) return; |
1374 | quicksort(indexes, depths, (pivIndex+1), last); |
1375 | quicksort(indexes, depths, (pivIndex+1), last); |
1375 | }
|
1376 | }
|
1376 | // END OF QUICKSORT LIB
|
1377 | // END OF QUICKSORT LIB
|
1377 | 1378 | ||
1378 | //--------------------------------------- MD3 LIBRARY BEGINS ---------------------------------------
|
1379 | //--------------------------------------- MD3 LIBRARY BEGINS ---------------------------------------
|
1379 | 1380 | ||
1380 | static md3model_t *md3load(int32_t fil) |
1381 | static md3model_t *md3load(int32_t fil) |
1381 | {
|
1382 | {
|
1382 | int32_t i, surfi, ofsurf, offs[4], leng[4]; |
1383 | int32_t i, surfi, ofsurf, offs[4], leng[4]; |
1383 | int32_t maxtrispersurf; |
1384 | int32_t maxtrispersurf; |
1384 | md3model_t *m; |
1385 | md3model_t *m; |
1385 | md3surf_t *s; |
1386 | md3surf_t *s; |
1386 | 1387 | ||
1387 | m = (md3model_t *)Xcalloc(1,sizeof(md3model_t)); |
1388 | m = (md3model_t *)Xcalloc(1,sizeof(md3model_t)); |
1388 | m->mdnum = 3; m->texid = 0; m->scale = .01f; |
1389 | m->mdnum = 3; m->texid = 0; m->scale = .01f; |
1389 | 1390 | ||
1390 | m->muladdframes = NULL; |
1391 | m->muladdframes = NULL; |
1391 | 1392 | ||
1392 | kread(fil,&m->head,SIZEOF_MD3HEAD_T); |
1393 | kread(fil,&m->head,SIZEOF_MD3HEAD_T); |
1393 | 1394 | ||
1394 | #if B_BIG_ENDIAN != 0
|
1395 | #if B_BIG_ENDIAN != 0
|
1395 | m->head.id = B_LITTLE32(m->head.id); m->head.vers = B_LITTLE32(m->head.vers); |
1396 | m->head.id = B_LITTLE32(m->head.id); m->head.vers = B_LITTLE32(m->head.vers); |
1396 | m->head.flags = B_LITTLE32(m->head.flags); m->head.numframes = B_LITTLE32(m->head.numframes); |
1397 | m->head.flags = B_LITTLE32(m->head.flags); m->head.numframes = B_LITTLE32(m->head.numframes); |
1397 | m->head.numtags = B_LITTLE32(m->head.numtags); m->head.numsurfs = B_LITTLE32(m->head.numsurfs); |
1398 | m->head.numtags = B_LITTLE32(m->head.numtags); m->head.numsurfs = B_LITTLE32(m->head.numsurfs); |
1398 | m->head.numskins = B_LITTLE32(m->head.numskins); m->head.ofsframes = B_LITTLE32(m->head.ofsframes); |
1399 | m->head.numskins = B_LITTLE32(m->head.numskins); m->head.ofsframes = B_LITTLE32(m->head.ofsframes); |
1399 | m->head.ofstags = B_LITTLE32(m->head.ofstags); m->head.ofssurfs = B_LITTLE32(m->head.ofssurfs); |
1400 | m->head.ofstags = B_LITTLE32(m->head.ofstags); m->head.ofssurfs = B_LITTLE32(m->head.ofssurfs); |
1400 | m->head.eof = B_LITTLE32(m->head.eof); |
1401 | m->head.eof = B_LITTLE32(m->head.eof); |
1401 | #endif
|
1402 | #endif
|
1402 | 1403 | ||
1403 | if ((m->head.id != IDP3_MAGIC) && (m->head.vers != 15)) { Bfree(m); return(0); } //"IDP3" |
1404 | if ((m->head.id != IDP3_MAGIC) && (m->head.vers != 15)) { Bfree(m); return(0); } //"IDP3" |
1404 | 1405 | ||
1405 | m->numskins = m->head.numskins; //<- dead code? |
1406 | m->numskins = m->head.numskins; //<- dead code? |
1406 | m->numframes = m->head.numframes; |
1407 | m->numframes = m->head.numframes; |
1407 | 1408 | ||
1408 | ofsurf = m->head.ofssurfs; |
1409 | ofsurf = m->head.ofssurfs; |
1409 | 1410 | ||
1410 | klseek(fil,m->head.ofsframes,SEEK_SET); i = m->head.numframes*sizeof(md3frame_t); |
1411 | klseek(fil,m->head.ofsframes,SEEK_SET); i = m->head.numframes*sizeof(md3frame_t); |
1411 | m->head.frames = (md3frame_t *)Xmalloc(i); |
1412 | m->head.frames = (md3frame_t *)Xmalloc(i); |
1412 | kread(fil,m->head.frames,i); |
1413 | kread(fil,m->head.frames,i); |
1413 | 1414 | ||
1414 | if (m->head.numtags == 0) m->head.tags = NULL; |
1415 | if (m->head.numtags == 0) m->head.tags = NULL; |
1415 | else
|
1416 | else
|
1416 | {
|
1417 | {
|
1417 | klseek(fil,m->head.ofstags,SEEK_SET); i = m->head.numtags*sizeof(md3tag_t); |
1418 | klseek(fil,m->head.ofstags,SEEK_SET); i = m->head.numtags*sizeof(md3tag_t); |
1418 | m->head.tags = (md3tag_t *)Xmalloc(i); |
1419 | m->head.tags = (md3tag_t *)Xmalloc(i); |
1419 | kread(fil,m->head.tags,i); |
1420 | kread(fil,m->head.tags,i); |
1420 | }
|
1421 | }
|
1421 | 1422 | ||
1422 | klseek(fil,m->head.ofssurfs,SEEK_SET); |
1423 | klseek(fil,m->head.ofssurfs,SEEK_SET); |
1423 | m->head.surfs = (md3surf_t *)Xcalloc(m->head.numsurfs, sizeof(md3surf_t)); |
1424 | m->head.surfs = (md3surf_t *)Xcalloc(m->head.numsurfs, sizeof(md3surf_t)); |
1424 | // NOTE: We assume that NULL is represented by all-zeros.
|
1425 | // NOTE: We assume that NULL is represented by all-zeros.
|
1425 | // surfs[0].geometry is for POLYMER_MD_PROCESS_CHECK (else: crashes).
|
1426 | // surfs[0].geometry is for POLYMER_MD_PROCESS_CHECK (else: crashes).
|
1426 | // surfs[i].geometry is for FREE_SURFS_GEOMETRY.
|
1427 | // surfs[i].geometry is for FREE_SURFS_GEOMETRY.
|
1427 | Bassert(m->head.surfs[0].geometry == NULL); |
1428 | Bassert(m->head.surfs[0].geometry == NULL); |
1428 | 1429 | ||
1429 | #if B_BIG_ENDIAN != 0
|
1430 | #if B_BIG_ENDIAN != 0
|
1430 | {
|
1431 | {
|
1431 | int32_t j, *l; |
1432 | int32_t j, *l; |
1432 | 1433 | ||
1433 | for (i = m->head.numframes-1; i>=0; i--) |
1434 | for (i = m->head.numframes-1; i>=0; i--) |
1434 | {
|
1435 | {
|
1435 | l = (int32_t *)&m->head.frames[i].min; |
1436 | l = (int32_t *)&m->head.frames[i].min; |
1436 | for (j=3+3+3+1-1; j>=0; j--) l[j] = B_LITTLE32(l[j]); |
1437 | for (j=3+3+3+1-1; j>=0; j--) l[j] = B_LITTLE32(l[j]); |
1437 | }
|
1438 | }
|
1438 | 1439 | ||
1439 | for (i = m->head.numtags-1; i>=0; i--) |
1440 | for (i = m->head.numtags-1; i>=0; i--) |
1440 | {
|
1441 | {
|
1441 | l = (int32_t *)&m->head.tags[i].p; |
1442 | l = (int32_t *)&m->head.tags[i].p; |
1442 | for (j=3+3+3+3-1; j>=0; j--) l[j] = B_LITTLE32(l[j]); |
1443 | for (j=3+3+3+3-1; j>=0; j--) l[j] = B_LITTLE32(l[j]); |
1443 | }
|
1444 | }
|
1444 | }
|
1445 | }
|
1445 | #endif
|
1446 | #endif
|
1446 | 1447 | ||
1447 | maxtrispersurf = 0; |
1448 | maxtrispersurf = 0; |
1448 | 1449 | ||
1449 | for (surfi=0; surfi<m->head.numsurfs; surfi++) |
1450 | for (surfi=0; surfi<m->head.numsurfs; surfi++) |
1450 | {
|
1451 | {
|
1451 | s = &m->head.surfs[surfi]; |
1452 | s = &m->head.surfs[surfi]; |
1452 | klseek(fil,ofsurf,SEEK_SET); kread(fil,s,SIZEOF_MD3SURF_T); |
1453 | klseek(fil,ofsurf,SEEK_SET); kread(fil,s,SIZEOF_MD3SURF_T); |
1453 | 1454 | ||
1454 | #if B_BIG_ENDIAN != 0
|
1455 | #if B_BIG_ENDIAN != 0
|
1455 | {
|
1456 | {
|
1456 | int32_t j, *l; |
1457 | int32_t j, *l; |
1457 | s->id = B_LITTLE32(s->id); |
1458 | s->id = B_LITTLE32(s->id); |
1458 | l = (int32_t *)&s->flags; |
1459 | l = (int32_t *)&s->flags; |
1459 | for (j=1+1+1+1+1+1+1+1+1+1-1; j>=0; j--) l[j] = B_LITTLE32(l[j]); |
1460 | for (j=1+1+1+1+1+1+1+1+1+1-1; j>=0; j--) l[j] = B_LITTLE32(l[j]); |
1460 | }
|
1461 | }
|
1461 | #endif
|
1462 | #endif
|
1462 | 1463 | ||
1463 | offs[0] = ofsurf+s->ofstris; |
1464 | offs[0] = ofsurf+s->ofstris; |
1464 | offs[1] = ofsurf+s->ofsshaders; |
1465 | offs[1] = ofsurf+s->ofsshaders; |
1465 | offs[2] = ofsurf+s->ofsuv; |
1466 | offs[2] = ofsurf+s->ofsuv; |
1466 | offs[3] = ofsurf+s->ofsxyzn; |
1467 | offs[3] = ofsurf+s->ofsxyzn; |
1467 | 1468 | ||
1468 | leng[0] = s->numtris*sizeof(md3tri_t); |
1469 | leng[0] = s->numtris*sizeof(md3tri_t); |
1469 | leng[1] = s->numshaders*sizeof(md3shader_t); |
1470 | leng[1] = s->numshaders*sizeof(md3shader_t); |
1470 | leng[2] = s->numverts*sizeof(md3uv_t); |
1471 | leng[2] = s->numverts*sizeof(md3uv_t); |
1471 | leng[3] = s->numframes*s->numverts*sizeof(md3xyzn_t); |
1472 | leng[3] = s->numframes*s->numverts*sizeof(md3xyzn_t); |
1472 | 1473 | ||
1473 | //memoryusage += (s->numverts * s->numframes * sizeof(md3xyzn_t));
|
1474 | //memoryusage += (s->numverts * s->numframes * sizeof(md3xyzn_t));
|
1474 | //OSD_Printf("Current model geometry memory usage : %i.\n", memoryusage);
|
1475 | //OSD_Printf("Current model geometry memory usage : %i.\n", memoryusage);
|
1475 | 1476 | ||
1476 | s->tris = (md3tri_t *)Xmalloc((leng[0] + leng[1]) + (leng[2] + leng[3])); |
1477 | s->tris = (md3tri_t *)Xmalloc((leng[0] + leng[1]) + (leng[2] + leng[3])); |
1477 | 1478 | ||
1478 | s->shaders = (md3shader_t *)(((intptr_t)s->tris)+leng[0]); |
1479 | s->shaders = (md3shader_t *)(((intptr_t)s->tris)+leng[0]); |
1479 | s->uv = (md3uv_t *)(((intptr_t)s->shaders)+leng[1]); |
1480 | s->uv = (md3uv_t *)(((intptr_t)s->shaders)+leng[1]); |
1480 | s->xyzn = (md3xyzn_t *)(((intptr_t)s->uv)+leng[2]); |
1481 | s->xyzn = (md3xyzn_t *)(((intptr_t)s->uv)+leng[2]); |
1481 | 1482 | ||
1482 | klseek(fil,offs[0],SEEK_SET); kread(fil,s->tris ,leng[0]); |
1483 | klseek(fil,offs[0],SEEK_SET); kread(fil,s->tris ,leng[0]); |
1483 | klseek(fil,offs[1],SEEK_SET); kread(fil,s->shaders,leng[1]); |
1484 | klseek(fil,offs[1],SEEK_SET); kread(fil,s->shaders,leng[1]); |
1484 | klseek(fil,offs[2],SEEK_SET); kread(fil,s->uv ,leng[2]); |
1485 | klseek(fil,offs[2],SEEK_SET); kread(fil,s->uv ,leng[2]); |
1485 | klseek(fil,offs[3],SEEK_SET); kread(fil,s->xyzn ,leng[3]); |
1486 | klseek(fil,offs[3],SEEK_SET); kread(fil,s->xyzn ,leng[3]); |
1486 | 1487 | ||
1487 | #if B_BIG_ENDIAN != 0
|
1488 | #if B_BIG_ENDIAN != 0
|
1488 | {
|
1489 | {
|
1489 | int32_t j, *l; |
1490 | int32_t j, *l; |
1490 | 1491 | ||
1491 | for (i=s->numtris-1; i>=0; i--) |
1492 | for (i=s->numtris-1; i>=0; i--) |
1492 | {
|
1493 | {
|
1493 | for (j=2; j>=0; j--) s->tris[i].i[j] = B_LITTLE32(s->tris[i].i[j]); |
1494 | for (j=2; j>=0; j--) s->tris[i].i[j] = B_LITTLE32(s->tris[i].i[j]); |
1494 | }
|
1495 | }
|
1495 | for (i=s->numshaders-1; i>=0; i--) |
1496 | for (i=s->numshaders-1; i>=0; i--) |
1496 | {
|
1497 | {
|
1497 | s->shaders[i].i = B_LITTLE32(s->shaders[i].i); |
1498 | s->shaders[i].i = B_LITTLE32(s->shaders[i].i); |
1498 | }
|
1499 | }
|
1499 | for (i=s->numverts-1; i>=0; i--) |
1500 | for (i=s->numverts-1; i>=0; i--) |
1500 | {
|
1501 | {
|
1501 | l = (int32_t *)&s->uv[i].u; |
1502 | l = (int32_t *)&s->uv[i].u; |
1502 | l[0] = B_LITTLE32(l[0]); |
1503 | l[0] = B_LITTLE32(l[0]); |
1503 | l[1] = B_LITTLE32(l[1]); |
1504 | l[1] = B_LITTLE32(l[1]); |
1504 | }
|
1505 | }
|
1505 | for (i=s->numframes*s->numverts-1; i>=0; i--) |
1506 | for (i=s->numframes*s->numverts-1; i>=0; i--) |
1506 | {
|
1507 | {
|
1507 | s->xyzn[i].x = (int16_t)B_LITTLE16((uint16_t)s->xyzn[i].x); |
1508 | s->xyzn[i].x = (int16_t)B_LITTLE16((uint16_t)s->xyzn[i].x); |
1508 | s->xyzn[i].y = (int16_t)B_LITTLE16((uint16_t)s->xyzn[i].y); |
1509 | s->xyzn[i].y = (int16_t)B_LITTLE16((uint16_t)s->xyzn[i].y); |
1509 | s->xyzn[i].z = (int16_t)B_LITTLE16((uint16_t)s->xyzn[i].z); |
1510 | s->xyzn[i].z = (int16_t)B_LITTLE16((uint16_t)s->xyzn[i].z); |
1510 | }
|
1511 | }
|
1511 | }
|
1512 | }
|
1512 | #endif
|
1513 | #endif
|
1513 | maxmodelverts = max(maxmodelverts, s->numverts); |
1514 | maxmodelverts = max(maxmodelverts, s->numverts); |
1514 | maxmodeltris = max(maxmodeltris, s->numtris); |
1515 | maxmodeltris = max(maxmodeltris, s->numtris); |
1515 | maxtrispersurf = max(maxtrispersurf, s->numtris); |
1516 | maxtrispersurf = max(maxtrispersurf, s->numtris); |
1516 | ofsurf += s->ofsend; |
1517 | ofsurf += s->ofsend; |
1517 | }
|
1518 | }
|
1518 | 1519 | ||
1519 | m->indexes = (uint16_t *)Xmalloc(sizeof(uint16_t) * maxtrispersurf); |
1520 | m->indexes = (uint16_t *)Xmalloc(sizeof(uint16_t) * maxtrispersurf); |
1520 | m->vindexes = (uint16_t *)Xmalloc(sizeof(uint16_t) * maxtrispersurf * 3); |
1521 | m->vindexes = (uint16_t *)Xmalloc(sizeof(uint16_t) * maxtrispersurf * 3); |
1521 | m->maxdepths = (float *)Xmalloc(sizeof(float) * maxtrispersurf); |
1522 | m->maxdepths = (float *)Xmalloc(sizeof(float) * maxtrispersurf); |
1522 | 1523 | ||
1523 | m->vbos = NULL; |
1524 | m->vbos = NULL; |
1524 | 1525 | ||
1525 | return(m); |
1526 | return(m); |
1526 | }
|
1527 | }
|
1527 | 1528 | ||
1528 | static inline void invertmatrix(float *m, float *out) |
1529 | static inline void invertmatrix(float *m, float *out) |
1529 | {
|
1530 | {
|
1530 | float det; |
1531 | float det; |
1531 | 1532 | ||
1532 | det = (m[0] * (m[4]*m[8] - m[5] * m[7])) |
1533 | det = (m[0] * (m[4]*m[8] - m[5] * m[7])) |
1533 | - (m[1] * (m[3]*m[8] - m[5] * m[6])) |
1534 | - (m[1] * (m[3]*m[8] - m[5] * m[6])) |
1534 | + (m[2] * (m[3]*m[7] - m[4] * m[6])); |
1535 | + (m[2] * (m[3]*m[7] - m[4] * m[6])); |
1535 | 1536 | ||
1536 | if (det == 0.0f) |
1537 | if (det == 0.0f) |
1537 | {
|
1538 | {
|
1538 | Bmemset(out, 0, sizeof(float) * 9); |
1539 | Bmemset(out, 0, sizeof(float) * 9); |
1539 | out[8] = out[4] = out[0] = 1.f; |
1540 | out[8] = out[4] = out[0] = 1.f; |
1540 | return; |
1541 | return; |
1541 | }
|
1542 | }
|
1542 | 1543 | ||
1543 | det = 1.0f / det; |
1544 | det = 1.0f / det; |
1544 |