1 #include "build.h"
2
3 #if USE_POLYMOST && USE_OPENGL
4 //------------------------------------- MD2/MD3 LIBRARY BEGINS -------------------------------------
5
6 #include "glbuild.h"
7 #include "kplib.h"
8 #include "pragmas.h"
9 #include "cache1d.h"
10 #include "baselayer.h"
11 #include "crc32.h"
12 #include "engine_priv.h"
13 #include "polymost_priv.h"
14 #include "hightile_priv.h"
15 #include "polymosttex_priv.h"
16 #include "mdsprite_priv.h"
17
18 #if defined(_M_IX86) || defined(_M_AMD64) || defined(__i386) || defined(__x86_64)
19 #define SHIFTMOD32(a) (a)
20 #else
21 #define SHIFTMOD32(a) ((a)&31)
22 #endif
23
24 #define VOXBORDWIDTH 1 //use 0 to save memory, but has texture artifacts; 1 looks better...
25 voxmodel *voxmodels[MAXVOXELS];
26
27 tile2model_t tile2model[MAXTILES];
28
29 //Move this to appropriate place!
30 hudtyp hudmem[2][MAXTILES]; //~320KB ... ok for now ... could replace with dynamic alloc
31
32 char mdinited=0;
33 int mdtims, omdtims;
34
35 #define MODELALLOCGROUP 256
36 static int nummodelsalloced = 0;
37 int nextmodelid = 0;
38 mdmodel **models = NULL;
39
40 static int maxmodelverts = 0, allocmodelverts = 0;
41 static int maxelementvbo = 0, allocelementvbo = 0;
42 static point3d *vertlist = NULL; //temp array to store interpolated vertices for drawing
43 static struct polymostvboitem *elementvbo = NULL; // 3 per triangle.
44
45 mdmodel *mdload (const char *);
46 void mdfree (mdmodel *);
47
freeallmodels()48 void freeallmodels ()
49 {
50 int i;
51
52 if (models)
53 {
54 for(i=0;i<nextmodelid;i++) mdfree(models[i]);
55 free(models); models = NULL;
56 nummodelsalloced = 0;
57 nextmodelid = 0;
58 }
59
60 memset(tile2model,-1,sizeof(tile2model));
61
62 if (vertlist)
63 {
64 free(vertlist);
65 vertlist = NULL;
66 allocmodelverts = maxmodelverts = 0;
67 }
68 if (elementvbo) {
69 free(elementvbo);
70 elementvbo = NULL;
71 allocelementvbo = maxelementvbo = 0;
72 }
73
74 }
75
clearskins()76 void clearskins ()
77 {
78 mdmodel *m;
79 int i, j;
80
81 for(i=0;i<nextmodelid;i++)
82 {
83 m = models[i];
84 if (m->mdnum == 1) {
85 voxmodel *v = (voxmodel*)m;
86 for(j=0;j<MAXPALOOKUPS;j++) {
87 if (v->texid[j]) glfunc.glDeleteTextures(1, &v->texid[j]);
88 v->texid[j] = 0;
89 }
90 if (v->vertexbuf) glfunc.glDeleteBuffers(1, &v->vertexbuf);
91 if (v->indexbuf) glfunc.glDeleteBuffers(1, &v->indexbuf);
92 v->vertexbuf = 0;
93 v->indexbuf = 0;
94 } else if (m->mdnum == 2 || m->mdnum == 3) {
95 md2model *m2 = (md2model*)m;
96 mdskinmap_t *sk;
97 for(j=0;j<m2->numskins*(HICEFFECTMASK+1);j++)
98 {
99 if (m2->tex[j] && m2->tex[j]->glpic) {
100 glfunc.glDeleteTextures(1, &m2->tex[j]->glpic);
101 m2->tex[j]->glpic = 0;
102 }
103 }
104
105 for(sk=m2->skinmap;sk;sk=sk->next)
106 {
107 if (!sk->tex)
108 continue;
109 for(j=0;j<(HICEFFECTMASK+1);j++)
110 {
111 if (sk->tex[j] && sk->tex[j]->glpic) {
112 glfunc.glDeleteTextures(1, &sk->tex[j]->glpic);
113 sk->tex[j]->glpic = 0;
114 }
115 }
116 }
117 }
118 }
119
120 for(i=0;i<MAXVOXELS;i++)
121 {
122 voxmodel *v = (voxmodel*)voxmodels[i]; if (!v) continue;
123 for(j=0;j<MAXPALOOKUPS;j++) {
124 if (v->texid[j]) glfunc.glDeleteTextures(1,(GLuint*)&v->texid[j]);
125 v->texid[j] = 0;
126 }
127 if (v->vertexbuf) glfunc.glDeleteBuffers(1, &v->vertexbuf);
128 if (v->indexbuf) glfunc.glDeleteBuffers(1, &v->indexbuf);
129 v->vertexbuf = 0;
130 v->indexbuf = 0;
131 }
132 }
133
mdinit()134 void mdinit ()
135 {
136 memset(hudmem,0,sizeof(hudmem));
137 freeallmodels();
138 mdinited = 1;
139 }
140
md_loadmodel(const char * fn)141 int md_loadmodel (const char *fn)
142 {
143 mdmodel *vm, **ml;
144
145 if (!mdinited) mdinit();
146
147 if (nextmodelid >= nummodelsalloced)
148 {
149 ml = (mdmodel **)realloc(models,(nummodelsalloced+MODELALLOCGROUP)*sizeof(mdmodel*)); if (!ml) return(-1);
150 models = ml; nummodelsalloced += MODELALLOCGROUP;
151 }
152
153 vm = mdload(fn); if (!vm) return(-1);
154 models[nextmodelid++] = vm;
155 return(nextmodelid-1);
156 }
157
md_setmisc(int modelid,float scale,int shadeoff,float zadd)158 int md_setmisc (int modelid, float scale, int shadeoff, float zadd)
159 {
160 mdmodel *m;
161
162 if (!mdinited) mdinit();
163
164 if ((unsigned int)modelid >= (unsigned int)nextmodelid) return -1;
165 m = models[modelid];
166 m->bscale = scale;
167 m->shadeoff = shadeoff;
168 m->zadd = zadd;
169
170 return 0;
171 }
172
md_tilehasmodel(int tilenume)173 int md_tilehasmodel (int tilenume)
174 {
175 if (!mdinited) return -1;
176 return tile2model[tilenume].modelid;
177 }
178
framename2index(mdmodel * vm,const char * nam)179 static int framename2index (mdmodel *vm, const char *nam)
180 {
181 int i = 0;
182
183 switch(vm->mdnum)
184 {
185 case 2:
186 {
187 md2model *m = (md2model *)vm;
188 md2frame_t *fr;
189 for(i=0;i<m->numframes;i++)
190 {
191 fr = (md2frame_t *)&m->frames[i*m->framebytes];
192 if (!Bstrcmp(fr->name, nam)) break;
193 }
194 }
195 break;
196 case 3:
197 {
198 md3model *m = (md3model *)vm;
199 for(i=0;i<m->numframes;i++)
200 if (!Bstrcmp(m->head.frames[i].nam,nam)) break;
201 }
202 break;
203 }
204 return(i);
205 }
206
md_defineframe(int modelid,const char * framename,int tilenume,int skinnum)207 int md_defineframe (int modelid, const char *framename, int tilenume, int skinnum)
208 {
209 void *vm;
210 md2model *m;
211 int i;
212
213 if (!mdinited) mdinit();
214
215 if ((unsigned int)modelid >= (unsigned int)nextmodelid) return(-1);
216 if ((unsigned int)tilenume >= (unsigned int)MAXTILES) return(-2);
217 if (!framename) return(-3);
218
219 m = (md2model *)models[modelid];
220 if (m->mdnum == 1) {
221 tile2model[tilenume].modelid = modelid;
222 tile2model[tilenume].framenum = tile2model[tilenume].skinnum = 0;
223 return 0;
224 }
225
226 i = framename2index((mdmodel*)m,framename);
227 if (i == m->numframes) return(-3); // frame name invalid
228
229 tile2model[tilenume].modelid = modelid;
230 tile2model[tilenume].framenum = i;
231 tile2model[tilenume].skinnum = skinnum;
232
233 return 0;
234 }
235
md_defineanimation(int modelid,const char * framestart,const char * frameend,int fpssc,int flags)236 int md_defineanimation (int modelid, const char *framestart, const char *frameend, int fpssc, int flags)
237 {
238 md2model *m;
239 mdanim_t ma, *map;
240 int i;
241
242 if (!mdinited) mdinit();
243
244 if ((unsigned int)modelid >= (unsigned int)nextmodelid) return(-1);
245
246 memset(&ma, 0, sizeof(ma));
247 m = (md2model *)models[modelid];
248 if (m->mdnum < 2) return 0;
249
250 //find index of start frame
251 i = framename2index((mdmodel*)m,framestart);
252 if (i == m->numframes) return -2;
253 ma.startframe = i;
254
255 //find index of finish frame which must trail start frame
256 i = framename2index((mdmodel*)m,frameend);
257 if (i == m->numframes) return -3;
258 ma.endframe = i;
259
260 ma.fpssc = fpssc;
261 ma.flags = flags;
262
263 map = (mdanim_t*)calloc(1,sizeof(mdanim_t));
264 if (!map) return(-4);
265 memcpy(map, &ma, sizeof(ma));
266
267 map->next = m->animations;
268 m->animations = map;
269
270 return(0);
271 }
272
md_defineskin(int modelid,const char * skinfn,int palnum,int skinnum,int surfnum)273 int md_defineskin (int modelid, const char *skinfn, int palnum, int skinnum, int surfnum)
274 {
275 mdskinmap_t *sk, *skl;
276 md2model *m;
277
278 if (!mdinited) mdinit();
279
280 if ((unsigned int)modelid >= (unsigned int)nextmodelid) return -1;
281 if (!skinfn) return -2;
282 if ((unsigned)palnum >= (unsigned)MAXPALOOKUPS) return -3;
283
284 m = (md2model *)models[modelid];
285 if (m->mdnum < 2) return 0;
286 if (m->mdnum == 2) surfnum = 0;
287
288 skl = NULL;
289 for (sk = m->skinmap; sk; skl = sk, sk = sk->next)
290 if (sk->palette == (unsigned char)palnum && skinnum == sk->skinnum && surfnum == sk->surfnum) break;
291 if (!sk) {
292 sk = (mdskinmap_t *)calloc(1,sizeof(mdskinmap_t));
293 if (!sk) return -4;
294
295 if (!skl) m->skinmap = sk;
296 else skl->next = sk;
297 } else if (sk->fn) free(sk->fn);
298
299 sk->palette = (unsigned char)palnum;
300 sk->skinnum = skinnum;
301 sk->surfnum = surfnum;
302 sk->fn = (char *)malloc(strlen(skinfn)+1);
303 if (!sk->fn) return(-4);
304 strcpy(sk->fn, skinfn);
305
306 return 0;
307 }
308
md_definehud(int modelid,int tilex,double xadd,double yadd,double zadd,double angadd,int flags)309 int md_definehud (int modelid, int tilex, double xadd, double yadd, double zadd, double angadd, int flags)
310 {
311 if (!mdinited) mdinit();
312
313 if ((unsigned int)modelid >= (unsigned int)nextmodelid) return -1;
314 if ((unsigned int)tilex >= (unsigned int)MAXTILES) return -2;
315
316 hudmem[(flags>>2)&1][tilex].xadd = xadd;
317 hudmem[(flags>>2)&1][tilex].yadd = yadd;
318 hudmem[(flags>>2)&1][tilex].zadd = zadd;
319 hudmem[(flags>>2)&1][tilex].angadd = ((short)angadd)|2048;
320 hudmem[(flags>>2)&1][tilex].flags = (short)flags;
321
322 return 0;
323 }
324
md_undefinetile(int tile)325 int md_undefinetile(int tile)
326 {
327 if (!mdinited) return 0;
328 if ((unsigned)tile >= (unsigned)MAXTILES) return -1;
329
330 tile2model[tile].modelid = -1;
331 return 0;
332 }
333
md_undefinemodel(int modelid)334 int md_undefinemodel(int modelid)
335 {
336 int i;
337 if (!mdinited) return 0;
338 if ((unsigned int)modelid >= (unsigned int)nextmodelid) return -1;
339
340 for (i=MAXTILES-1; i>=0; i--)
341 if (tile2model[i].modelid == modelid)
342 tile2model[i].modelid = -1;
343
344 if (models) {
345 mdfree(models[modelid]);
346 models[modelid] = NULL;
347 }
348
349 return 0;
350 }
351
md_initident(PTMIdent * id,const char * filename,int effects)352 static void md_initident(PTMIdent *id, const char * filename, int effects)
353 {
354 memset(id, 0, sizeof(PTMIdent));
355 id->effects = effects;
356 strncpy(id->filename, filename, sizeof(id->filename)-1);
357 id->filename[sizeof(id->filename)-1] = 0;
358 }
359
360 //Note: even though it says md2model, it works for both md2model&md3model
mdloadskin(md2model * m,int number,int pal,int surf)361 PTMHead * mdloadskin (md2model *m, int number, int pal, int surf)
362 {
363 int i, err = 0;
364 char *skinfile = 0, fn[BMAX_PATH+65];
365 PTMHead **tex = 0;
366 mdskinmap_t *sk, *skzero = 0;
367 PTMIdent id;
368
369 if (m->mdnum == 2) {
370 surf = 0;
371 }
372
373 if ((unsigned)pal >= (unsigned)MAXPALOOKUPS) {
374 return 0;
375 }
376
377 i = -1;
378 for (sk = m->skinmap; sk; sk = sk->next) {
379 if ((int)sk->palette == pal && sk->skinnum == number && sk->surfnum == surf) {
380 tex = &sk->tex[ hictinting[pal].f ];
381 skinfile = sk->fn;
382 strcpy(fn,skinfile);
383 //buildprintf("Using exact match skin (pal=%d,skinnum=%d,surfnum=%d) %s\n",pal,number,surf,skinfile);
384 break;
385 }
386 //If no match, give highest priority to number, then pal.. (Parkar's request, 02/27/2005)
387 else if (((int)sk->palette == 0) && (sk->skinnum == number) && (sk->surfnum == surf) && (i < 5)) { i = 5; skzero = sk; }
388 else if (((int)sk->palette == pal) && (sk->skinnum == 0) && (sk->surfnum == surf) && (i < 4)) { i = 4; skzero = sk; }
389 else if (((int)sk->palette == 0) && (sk->skinnum == 0) && (sk->surfnum == surf) && (i < 3)) { i = 3; skzero = sk; }
390 else if (((int)sk->palette == 0) && (sk->skinnum == number) && (i < 2)) { i = 2; skzero = sk; }
391 else if (((int)sk->palette == pal) && (sk->skinnum == 0) && (i < 1)) { i = 1; skzero = sk; }
392 else if (((int)sk->palette == 0) && (sk->skinnum == 0) && (i < 0)) { i = 0; skzero = sk; }
393 }
394 if (!sk) {
395 if (skzero) {
396 tex = &skzero->tex[ hictinting[pal].f ];
397 skinfile = skzero->fn;
398 strcpy(fn,skinfile);
399 //buildprintf("Using def skin 0,0 as fallback, pal=%d\n", pal);
400 } else {
401 if ((unsigned)number >= (unsigned)m->numskins) {
402 number = 0;
403 }
404 tex = &m->tex[ number * (HICEFFECTMASK+1) + hictinting[pal].f ];
405 skinfile = m->skinfn + number*64;
406 strcpy(fn,m->basepath);
407 strcat(fn,skinfile);
408 //buildprintf("Using MD2/MD3 skin (%d) %s, pal=%d\n",number,skinfile,pal);
409 }
410 }
411
412 if (!skinfile[0]) {
413 return 0;
414 }
415
416 if (*tex && (*tex)->glpic) {
417 // texture already loaded
418 return *tex;
419 }
420
421 if (!(*tex)) {
422 // no PTMHead referenced yet at *tex
423 md_initident(&id, skinfile, hictinting[pal].f);
424 *tex = PTM_GetHead(&id);
425 if (!(*tex)) {
426 return 0;
427 }
428 }
429
430 if (!(*tex)->glpic) {
431 // no texture loaded in the PTMHead yet
432 if ((err = PTM_LoadTextureFile(skinfile, *tex, PTH_CLAMPED, hictinting[pal].f))) {
433 if (polymosttexverbosity >= 1) {
434 const char * errstr = PTM_GetLoadTextureFileErrorString(err);
435 buildprintf("MDSprite: %s %s\n",
436 skinfile, errstr);
437 }
438 return 0;
439 }
440 m->usesalpha = (((*tex)->flags & PTH_HASALPHA) == PTH_HASALPHA);
441 }
442
443 if (!m->skinloaded)
444 {
445 if ((*tex)->sizx != (*tex)->tsizx || (*tex)->sizy != (*tex)->tsizy)
446 {
447 float fx, fy;
448 fx = ((float)(*tex)->tsizx)/((float)(*tex)->sizx);
449 fy = ((float)(*tex)->tsizy)/((float)(*tex)->sizy);
450 if (m->mdnum == 2)
451 {
452 //FIXME correct uvs for non-2^x textures
453 }
454 else if (m->mdnum == 3)
455 {
456 md3model *m3 = (md3model *)m;
457 md3surf_t *s;
458 int surfi;
459 for (surfi=0;surfi<m3->head.numsurfs;surfi++)
460 {
461 s = &m3->head.surfs[surfi];
462 for(i=s->numverts-1;i>=0;i--)
463 {
464 s->uv[i].u *= fx;
465 s->uv[i].v *= fy;
466 }
467 }
468 }
469 }
470 m->skinloaded = 1+number;
471 }
472
473 glfunc.glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,glfiltermodes[gltexfiltermode].mag);
474 glfunc.glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,glfiltermodes[gltexfiltermode].min);
475 if (glinfo.maxanisotropy > 1.0)
476 glfunc.glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAX_ANISOTROPY_EXT,glanisotropy);
477 glfunc.glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
478 glfunc.glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
479
480 return (*tex);
481 }
482
483 //Note: even though it says md2model, it works for both md2model&md3model
updateanimation(md2model * m,spritetype * tspr)484 static void updateanimation (md2model *m, spritetype *tspr)
485 {
486 mdanim_t *anim;
487 int i, j;
488
489 m->cframe = m->nframe = tile2model[tspr->picnum].framenum;
490
491 for (anim = m->animations;
492 anim && anim->startframe != m->cframe;
493 anim = anim->next) ;
494 if (!anim) { m->interpol = 0; return; }
495
496 if (((int)spriteext[tspr->owner].mdanimcur) != anim->startframe ||
497 (spriteext[tspr->owner].flags & SPREXT_NOMDANIM))
498 {
499 spriteext[tspr->owner].mdanimcur = (short)anim->startframe;
500 spriteext[tspr->owner].mdanimtims = mdtims;
501 m->cframe = m->nframe = anim->startframe;
502 m->interpol = 0;
503 return;
504 }
505
506 i = (mdtims-spriteext[tspr->owner].mdanimtims)*anim->fpssc;
507 j = ((anim->endframe+1-anim->startframe)<<16);
508
509 //Just in case you play the game for a VERY int time...
510 if (i < 0) { i = 0; spriteext[tspr->owner].mdanimtims = mdtims; }
511 //compare with j*2 instead of j to ensure i stays > j-65536 for MDANIM_ONESHOT
512 if ((i >= j+j) && (anim->fpssc)) //Keep mdanimtims close to mdtims to avoid the use of MOD
513 spriteext[tspr->owner].mdanimtims += j/anim->fpssc;
514
515 if (anim->flags&MDANIM_ONESHOT)
516 { if (i > j-65536) i = j-65536; }
517 else { if (i >= j) { i -= j; if (i >= j) i %= j; } }
518
519 m->cframe = (i>>16)+anim->startframe;
520 m->nframe = m->cframe+1; if (m->nframe > anim->endframe) m->nframe = anim->startframe;
521 m->interpol = ((float)(i&65535))/65536.f;
522 }
523
524 //--------------------------------------- MD2 LIBRARY BEGINS ---------------------------------------
525
md2free(md2model * m)526 static void md2free (md2model *m)
527 {
528 mdanim_t *anim, *nanim = NULL;
529 mdskinmap_t *sk, *nsk = NULL;
530
531 if (!m) return;
532
533 for(anim=m->animations; anim; anim=nanim)
534 {
535 nanim = anim->next;
536 free(anim);
537 }
538 for(sk=m->skinmap; sk; sk=nsk)
539 {
540 nsk = sk->next;
541 free(sk->fn);
542 free(sk);
543 }
544
545 if (m->frames) free(m->frames);
546 if (m->uvs) free(m->uvs);
547 if (m->tris) free(m->tris);
548 if (m->basepath) free(m->basepath);
549 if (m->skinfn) free(m->skinfn);
550
551 if (m->tex) free(m->tex);
552
553 free(m);
554 }
555
md2load(int fil,const char * filnam)556 static md2model *md2load (int fil, const char *filnam)
557 {
558 md2model *m;
559 md2head_t head;
560 char *buf, st[BMAX_PATH];
561 int i;
562
563 m = (md2model *)calloc(1,sizeof(md2model)); if (!m) return(0);
564 m->mdnum = 2; m->scale = .01;
565
566 kread(fil,(char *)&head,sizeof(md2head_t));
567 head.id = B_LITTLE32(head.id); head.vers = B_LITTLE32(head.vers);
568 head.skinxsiz = B_LITTLE32(head.skinxsiz); head.skinysiz = B_LITTLE32(head.skinysiz);
569 head.framebytes = B_LITTLE32(head.framebytes); head.numskins = B_LITTLE32(head.numskins);
570 head.numverts = B_LITTLE32(head.numverts); head.numuv = B_LITTLE32(head.numuv);
571 head.numtris = B_LITTLE32(head.numtris); head.numglcmds = B_LITTLE32(head.numglcmds);
572 head.numframes = B_LITTLE32(head.numframes); head.ofsskins = B_LITTLE32(head.ofsskins);
573 head.ofsuv = B_LITTLE32(head.ofsuv); head.ofstris = B_LITTLE32(head.ofstris);
574 head.ofsframes = B_LITTLE32(head.ofsframes); head.ofsglcmds = B_LITTLE32(head.ofsglcmds);
575 head.ofseof = B_LITTLE32(head.ofseof);
576
577 if ((head.id != 0x32504449) || (head.vers != 8)) { md2free(m); return(0); } //"IDP2"
578
579 m->numskins = head.numskins;
580 m->numframes = head.numframes;
581 m->numverts = head.numverts;
582 m->numuv = head.numuv;
583 m->numtris = head.numtris;
584 m->framebytes = head.framebytes;
585 m->skinxsiz = head.skinxsiz;
586 m->skinysiz = head.skinysiz;
587
588 m->uvs = (md2uv_t *)calloc(m->numuv,sizeof(md2uv_t));
589 if (!m->uvs) { md2free(m); return(0); }
590 klseek(fil,head.ofsuv,SEEK_SET);
591 if (kread(fil,(char *)m->uvs,m->numuv*sizeof(md2uv_t)) != m->numuv*sizeof(md2uv_t))
592 { md2free(m); return(0); }
593
594 m->tris = (md2tri_t *)calloc(m->numtris,sizeof(md2tri_t));
595 if (!m->tris) { md2free(m); return(0); }
596 klseek(fil,head.ofstris,SEEK_SET);
597 if (kread(fil,(char *)m->tris,m->numtris*sizeof(md2tri_t)) != m->numtris*sizeof(md2tri_t))
598 { md2free(m); return(0); }
599
600 m->frames = (char *)calloc(m->numframes,m->framebytes);
601 if (!m->frames) { md2free(m); return(0); }
602 klseek(fil,head.ofsframes,SEEK_SET);
603 if (kread(fil,(char *)m->frames,m->numframes*m->framebytes) != m->numframes*m->framebytes)
604 { md2free(m); return(0); }
605
606 #if B_BIG_ENDIAN != 0
607 {
608 char *f = (char *)m->frames;
609 int *l,j;
610 md2frame_t *fr;
611
612 ///FIXME byteswap tris
613
614 for (i = m->numframes-1; i>=0; i--) {
615 fr = (md2frame_t *)f;
616 l = (int *)&fr->mul;
617 for (j=5;j>=0;j--) l[j] = B_LITTLE32(l[j]);
618 f += m->framebytes;
619 }
620 }
621 #endif
622
623 strcpy(st,filnam);
624 for(i=strlen(st)-1;i>0;i--)
625 if ((st[i] == '/') || (st[i] == '\\')) { i++; break; }
626 if (i<0) i=0;
627 st[i] = 0;
628 m->basepath = (char *)malloc(i+1); if (!m->basepath) { md2free(m); return(0); }
629 strcpy(m->basepath, st);
630
631 m->skinfn = (char *)calloc(m->numskins,64); if (!m->skinfn) { md2free(m); return(0); }
632 klseek(fil,head.ofsskins,SEEK_SET);
633 if (kread(fil,m->skinfn,64*m->numskins) != 64*m->numskins)
634 { md2free(m); return(0); }
635
636 m->tex = (PTMHead **)calloc(m->numskins, sizeof(PTMHead *) * (HICEFFECTMASK+1));
637 if (!m->tex) { md2free(m); return(0); }
638
639 maxmodelverts = max(maxmodelverts, m->numverts);
640 maxelementvbo = max(maxelementvbo, m->numtris * 3);
641
642 return(m);
643 }
644
md2draw(md2model * m,spritetype * tspr,int method)645 static int md2draw (md2model *m, spritetype *tspr, int method)
646 {
647 point3d fp, m0, m1, a0, a1;
648 md2frame_t *f0, *f1;
649 md2vert_t *c0, *c1;
650 int i, j, vbi, *lptr;
651 float f, g, k0, k1, k2, k3, k4, k5, k6, k7, mat[16], pc[4];
652 PTMHead *ptmh = 0;
653 struct polymostdrawpolycall draw;
654
655 updateanimation(m,tspr);
656
657 // -------- Unnecessarily clean (lol) code to generate translation/rotation matrix for MD2 ---------
658
659 //create current&next frame's vertex list from whole list
660 f0 = (md2frame_t *)&m->frames[m->cframe*m->framebytes];
661 f1 = (md2frame_t *)&m->frames[m->nframe*m->framebytes];
662 f = m->interpol; g = 1-f;
663 m0.x = f0->mul.x*m->scale*g; m1.x = f1->mul.x*m->scale*f;
664 m0.y = f0->mul.y*m->scale*g; m1.y = f1->mul.y*m->scale*f;
665 m0.z = f0->mul.z*m->scale*g; m1.z = f1->mul.z*m->scale*f;
666 a0.x = f0->add.x*m->scale; a0.x = (f1->add.x*m->scale-a0.x)*f+a0.x;
667 a0.y = f0->add.y*m->scale; a0.y = (f1->add.y*m->scale-a0.y)*f+a0.y;
668 a0.z = f0->add.z*m->scale; a0.z = (f1->add.z*m->scale-a0.z)*f+a0.z + m->zadd*m->scale;
669 c0 = &f0->verts[0]; c1 = &f1->verts[0];
670
671 // Parkar: Moved up to be able to use k0 for the y-flipping code
672 k0 = tspr->z;
673 if ((globalorientation&128) && !((globalorientation&48)==32)) k0 += (float)((tilesizy[tspr->picnum]*tspr->yrepeat)<<1);
674
675 // Parkar: Changed to use the same method as centeroriented sprites
676 if (globalorientation&8) //y-flipping
677 {
678 m0.z = -m0.z; m1.z = -m1.z; a0.z = -a0.z;
679 k0 -= (float)((tilesizy[tspr->picnum]*tspr->yrepeat)<<2);
680 }
681 if (globalorientation&4) { m0.y = -m0.y; m1.y = -m1.y; a0.y = -a0.y; } //x-flipping
682
683 f = ((float)tspr->xrepeat)/64*m->bscale;
684 m0.x *= f; m1.x *= f; a0.x *= f; f = -f; // 20040610: backwards models aren't cool
685 m0.y *= f; m1.y *= f; a0.y *= f;
686 f = ((float)tspr->yrepeat)/64*m->bscale;
687 m0.z *= f; m1.z *= f; a0.z *= f;
688
689 // floor aligned
690 k1 = tspr->y;
691 if((globalorientation&48)==32)
692 {
693 m0.z = -m0.z; m1.z = -m1.z; a0.z = -a0.z;
694 m0.y = -m0.y; m1.y = -m1.y; a0.y = -a0.y;
695 f = a0.x; a0.x = a0.z; a0.z = f;
696 k1 += (float)((tilesizy[tspr->picnum]*tspr->yrepeat)>>3);
697 }
698
699 f = (65536.0*512.0)/((float)xdimen*viewingrange);
700 g = 32.0/((float)xdimen*gxyaspect);
701 m0.y *= f; m1.y *= f; a0.y = (((float)(tspr->x-globalposx))/ 1024.0 + a0.y)*f;
702 m0.x *=-f; m1.x *=-f; a0.x = (((float)(k1 -globalposy))/ -1024.0 + a0.x)*-f;
703 m0.z *= g; m1.z *= g; a0.z = (((float)(k0 -globalposz))/-16384.0 + a0.z)*g;
704
705 k0 = ((float)(tspr->x-globalposx))*f/1024.0;
706 k1 = ((float)(tspr->y-globalposy))*f/1024.0;
707 f = gcosang2*gshang;
708 g = gsinang2*gshang;
709 k4 = (float)sintable[(tspr->ang+spriteext[tspr->owner].angoff+1024)&2047] / 16384.0;
710 k5 = (float)sintable[(tspr->ang+spriteext[tspr->owner].angoff+ 512)&2047] / 16384.0;
711 k2 = k0*(1-k4)+k1*k5;
712 k3 = k1*(1-k4)-k0*k5;
713 k6 = f*gstang - gsinang*gctang; k7 = g*gstang + gcosang*gctang;
714 mat[0] = k4*k6 + k5*k7; mat[4] = gchang*gstang; mat[ 8] = k4*k7 - k5*k6; mat[12] = k2*k6 + k3*k7;
715 k6 = f*gctang + gsinang*gstang; k7 = g*gctang - gcosang*gstang;
716 mat[1] = k4*k6 + k5*k7; mat[5] = gchang*gctang; mat[ 9] = k4*k7 - k5*k6; mat[13] = k2*k6 + k3*k7;
717 k6 = gcosang2*gchang; k7 = gsinang2*gchang;
718 mat[2] = k4*k6 + k5*k7; mat[6] =-gshang; mat[10] = k4*k7 - k5*k6; mat[14] = k2*k6 + k3*k7;
719
720 mat[12] += a0.y*mat[0] + a0.z*mat[4] + a0.x*mat[ 8];
721 mat[13] += a0.y*mat[1] + a0.z*mat[5] + a0.x*mat[ 9];
722 mat[14] += a0.y*mat[2] + a0.z*mat[6] + a0.x*mat[10];
723
724 // floor aligned
725 if((globalorientation&48)==32)
726 {
727 f = mat[4]; mat[4] = mat[8]*16.0; mat[8] = -f*(1.0/16.0);
728 f = mat[5]; mat[5] = mat[9]*16.0; mat[9] = -f*(1.0/16.0);
729 f = mat[6]; mat[6] = mat[10]*16.0; mat[10] = -f*(1.0/16.0);
730 }
731
732 //Mirrors
733 if (grhalfxdown10x < 0) { mat[0] = -mat[0]; mat[4] = -mat[4]; mat[8] = -mat[8]; mat[12] = -mat[12]; }
734
735 mat[3] = mat[7] = mat[11] = 0.f; mat[15] = 1.f;
736
737 // ------ Unnecessarily clean (lol) code to generate translation/rotation matrix for MD2 ends ------
738
739 for(i=m->numverts-1;i>=0;i--) //interpolate (for animation) & transform to Build coords
740 {
741 vertlist[i].z = ((float)c0[i].v[0])*m0.x + ((float)c1[i].v[0])*m1.x;
742 vertlist[i].y = ((float)c0[i].v[2])*m0.z + ((float)c1[i].v[2])*m1.z;
743 vertlist[i].x = ((float)c0[i].v[1])*m0.y + ((float)c1[i].v[1])*m1.y;
744 }
745
746 ptmh = mdloadskin(m,tile2model[tspr->picnum].skinnum,globalpal,0);
747 if (!ptmh || !ptmh->glpic) return 0;
748
749 //bit 10 is an ugly hack in game.c\animatesprites telling MD2SPRITE
750 //to use Z-buffer hacks to hide overdraw problems with the shadows
751 if (tspr->cstat&1024)
752 {
753 glfunc.glDepthFunc(GL_LESS); //NEVER,LESS,(,L)EQUAL,GREATER,(NOT,G)EQUAL,ALWAYS
754 #if (USE_OPENGL == USE_GLES2)
755 glfunc.glDepthRangef(0.f,0.9999f);
756 #else
757 glfunc.glDepthRange(0.0,0.9999);
758 #endif
759 }
760 if ((grhalfxdown10x >= 0) ^ ((globalorientation&8) != 0) ^ ((globalorientation&4) != 0)) glfunc.glFrontFace(GL_CW); else glfunc.glFrontFace(GL_CCW);
761 glfunc.glEnable(GL_CULL_FACE);
762 glfunc.glCullFace(GL_BACK);
763
764 pc[0] = pc[1] = pc[2] = ((float)(numpalookups-min(max(globalshade+m->shadeoff,0),numpalookups)))/((float)numpalookups);
765 pc[0] *= (float)hictinting[globalpal].r / 255.0;
766 pc[1] *= (float)hictinting[globalpal].g / 255.0;
767 pc[2] *= (float)hictinting[globalpal].b / 255.0;
768 if (tspr->cstat&2) { if (!(tspr->cstat&512)) pc[3] = 0.66; else pc[3] = 0.33; } else pc[3] = 1.0;
769 if (m->usesalpha || (tspr->cstat&2)) glfunc.glEnable(GL_BLEND); else glfunc.glDisable(GL_BLEND); //Sprites with alpha in texture
770
771 for (i=0, vbi=0; i<m->numtris; i++, vbi+=3) {
772 md2tri_t *tri = &m->tris[i];
773 for (j=2; j>=0; j--) {
774 elementvbo[vbi+j].v.x = vertlist[ tri->ivert[j] ].x;
775 elementvbo[vbi+j].v.y = vertlist[ tri->ivert[j] ].y;
776 elementvbo[vbi+j].v.z = vertlist[ tri->ivert[j] ].z;
777 elementvbo[vbi+j].t.s = (GLfloat)m->uvs[ tri->iuv[j] ].u / m->skinxsiz;
778 elementvbo[vbi+j].t.t = (GLfloat)m->uvs[ tri->iuv[j] ].v / m->skinysiz;
779 }
780 }
781
782 draw.texture0 = ptmh->glpic;
783 draw.texture1 = 0;
784 draw.alphacut = 0.32;
785 draw.colour.r = pc[0];
786 draw.colour.g = pc[1];
787 draw.colour.b = pc[2];
788 draw.colour.a = pc[3];
789 draw.fogcolour.r = (float)palookupfog[gfogpalnum].r / 63.f;
790 draw.fogcolour.g = (float)palookupfog[gfogpalnum].g / 63.f;
791 draw.fogcolour.b = (float)palookupfog[gfogpalnum].b / 63.f;
792 draw.fogcolour.a = 1.f;
793 draw.fogdensity = gfogdensity;
794
795 if (method & 1) {
796 draw.projection = &grotatespriteprojmat[0][0];
797 } else {
798 draw.projection = &gdrawroomsprojmat[0][0];
799 }
800 draw.modelview = mat;
801
802 draw.indexcount = 3 * m->numtris;
803 draw.indexbuffer = 0;
804 draw.elementbuffer = 0;
805 draw.elementcount = 3 * m->numtris;
806 draw.elementvbo = elementvbo;
807 polymost_drawpoly_glcall(GL_TRIANGLES, &draw);
808
809 glfunc.glDisable(GL_CULL_FACE);
810 glfunc.glFrontFace(GL_CCW);
811 if (tspr->cstat&1024)
812 {
813 glfunc.glDepthFunc(GL_LEQUAL); //NEVER,LESS,(,L)EQUAL,GREATER,(NOT,G)EQUAL,ALWAYS
814 #if (USE_OPENGL == USE_GLES2)
815 glfunc.glDepthRangef(0.f,0.99999f);
816 #else
817 glfunc.glDepthRange(0.0,0.99999);
818 #endif
819 }
820
821 return 1;
822 }
823
824 //---------------------------------------- MD2 LIBRARY ENDS ----------------------------------------
825 //--------------------------------------- MD3 LIBRARY BEGINS ---------------------------------------
826
827 static void md3free (md3model *m);
828
md3load(int fil)829 static md3model *md3load (int fil)
830 {
831 char *buf, st[BMAX_PATH+2], bst[BMAX_PATH+2];
832 int i, j, surfi, ofsurf, bsc, offs[4], leng[4], maxsurftris = 0;
833 md3model *m;
834 md3surf_t *s;
835
836 md3filehead_t filehead;
837 md3filesurf_t filesurf;
838
839 m = (md3model *)calloc(1,sizeof(md3model)); if (!m) return(0);
840 m->mdnum = 3; m->tex = 0; m->scale = .01;
841
842 kread(fil,&filehead,sizeof(md3filehead_t));
843 m->head.id = B_LITTLE32(filehead.id);
844 m->head.vers = B_LITTLE32(filehead.vers);
845 memcpy(m->head.nam, filehead.nam, sizeof(filehead.nam));
846 m->head.flags = B_LITTLE32(filehead.flags);
847 m->head.numframes = B_LITTLE32(filehead.numframes);
848 m->head.numtags = B_LITTLE32(filehead.numtags);
849 m->head.numsurfs = B_LITTLE32(filehead.numsurfs);
850 m->head.numskins = B_LITTLE32(filehead.numskins);
851 filehead.frames = B_LITTLE32(filehead.frames);
852 filehead.tags = B_LITTLE32(filehead.tags);
853 filehead.surfs = B_LITTLE32(filehead.surfs);
854 m->head.eof = B_LITTLE32(filehead.eof);
855
856 if ((m->head.id != 0x33504449) && (m->head.vers != 15)) { md3free(m); return(0); } //"IDP3"
857
858 m->numskins = m->head.numskins; //<- dead code?
859 m->numframes = m->head.numframes;
860
861 klseek(fil,filehead.frames,SEEK_SET);
862 m->head.frames = (md3frame_t *)calloc(m->head.numframes, sizeof(md3frame_t));
863 if (!m->head.frames) { md3free(m); return(0); }
864 kread(fil,m->head.frames,m->head.numframes*sizeof(md3frame_t));
865
866 if (m->head.numtags == 0) m->head.tags = NULL;
867 else {
868 klseek(fil,filehead.tags,SEEK_SET);
869 m->head.tags = (md3tag_t *)calloc(m->head.numtags, sizeof(md3tag_t));
870 if (!m->head.tags) { md3free(m); return(0); }
871 kread(fil,m->head.tags,m->head.numtags*sizeof(md3tag_t));
872 }
873
874 klseek(fil,filehead.surfs,SEEK_SET);
875 m->head.surfs = (md3surf_t *)calloc(m->head.numsurfs, sizeof(md3surf_t));
876 if (!m->head.surfs) { md3free(m); return(0); }
877
878 #if B_BIG_ENDIAN != 0
879 {
880 int *l;
881
882 for (i = m->head.numframes-1; i>=0; i--) {
883 l = (int *)&m->head.frames[i].min;
884 for (j=3+3+3+1-1;j>=0;j--) l[j] = B_LITTLE32(l[j]);
885 }
886
887 for (i = m->head.numtags-1; i>=0; i--) {
888 l = (int *)&m->head.tags[i].p;
889 for (j=3+3+3+3-1;j>=0;j--) l[j] = B_LITTLE32(l[j]);
890 }
891 }
892 #endif
893
894 ofsurf = filehead.surfs;
895
896 for(surfi=0;surfi<m->head.numsurfs;surfi++)
897 {
898 s = &m->head.surfs[surfi];
899 klseek(fil,ofsurf,SEEK_SET); kread(fil,&filesurf,sizeof(md3filesurf_t));
900
901 s->id = B_LITTLE32(filesurf.id);
902 memcpy(s->nam, filesurf.nam, sizeof(filesurf.nam));
903 s->flags = B_LITTLE32(filesurf.flags);
904 s->numframes = B_LITTLE32(filesurf.numframes);
905 s->numshaders = B_LITTLE32(filesurf.numshaders);
906 s->numverts = B_LITTLE32(filesurf.numverts);
907 s->numtris = B_LITTLE32(filesurf.numtris);
908 filesurf.tris = B_LITTLE32(filesurf.tris);
909 filesurf.shaders = B_LITTLE32(filesurf.shaders);
910 filesurf.uv = B_LITTLE32(filesurf.uv);
911 filesurf.xyzn = B_LITTLE32(filesurf.xyzn);
912 s->ofsend = B_LITTLE32(filesurf.ofsend);
913
914 offs[0] = ofsurf+filesurf.tris ; leng[0] = s->numtris*sizeof(md3tri_t);
915 offs[1] = ofsurf+filesurf.shaders; leng[1] = s->numshaders*sizeof(md3shader_t);
916 offs[2] = ofsurf+filesurf.uv ; leng[2] = s->numverts*sizeof(md3uv_t);
917 offs[3] = ofsurf+filesurf.xyzn ; leng[3] = s->numframes*s->numverts*sizeof(md3xyzn_t);
918
919 s->tris = (md3tri_t *)malloc(leng[0]+leng[1]+leng[2]+leng[3]);
920 if (!s->tris)
921 {
922 md3free(m);
923 return(0);
924 }
925 s->shaders = (md3shader_t *)(((intptr_t)s->tris )+leng[0]);
926 s->uv = (md3uv_t *)(((intptr_t)s->shaders)+leng[1]);
927 s->xyzn = (md3xyzn_t *)(((intptr_t)s->uv )+leng[2]);
928
929 klseek(fil,offs[0],SEEK_SET); kread(fil,s->tris ,leng[0]);
930 klseek(fil,offs[1],SEEK_SET); kread(fil,s->shaders,leng[1]);
931 klseek(fil,offs[2],SEEK_SET); kread(fil,s->uv ,leng[2]);
932 klseek(fil,offs[3],SEEK_SET); kread(fil,s->xyzn ,leng[3]);
933
934 #if B_BIG_ENDIAN != 0
935 {
936 int *l;
937
938 for (i=s->numtris-1;i>=0;i--) {
939 for (j=2;j>=0;j--) s->tris[i].i[j] = B_LITTLE32(s->tris[i].i[j]);
940 }
941 for (i=s->numshaders-1;i>=0;i--) {
942 s->shaders[i].i = B_LITTLE32(s->shaders[i].i);
943 }
944 for (i=s->numverts-1;i>=0;i--) {
945 l = (int*)&s->uv[i];
946 l[0] = B_LITTLE32(l[0]);
947 l[1] = B_LITTLE32(l[1]);
948 }
949 for (i=s->numframes*s->numverts-1;i>=0;i--) {
950 s->xyzn[i].x = (signed short)B_LITTLE16((unsigned short)s->xyzn[i].x);
951 s->xyzn[i].y = (signed short)B_LITTLE16((unsigned short)s->xyzn[i].y);
952 s->xyzn[i].z = (signed short)B_LITTLE16((unsigned short)s->xyzn[i].z);
953 }
954 }
955 #endif
956
957 maxmodelverts = max(maxmodelverts, s->numverts);
958 maxelementvbo = max(maxelementvbo, s->numtris * 3);
959 ofsurf += s->ofsend;
960 }
961
962 return(m);
963 }
964
md3draw(md3model * m,spritetype * tspr,int method)965 static int md3draw (md3model *m, spritetype *tspr, int method)
966 {
967 point3d fp, m0, m1, a0, a1;
968 md3xyzn_t *v0, *v1;
969 int i, j, k, vbi, surfi, *lptr;
970 float f, g, k0, k1, k2, k3, k4, k5, k6, k7, mat[16], pc[4];
971 md3surf_t *s;
972 PTMHead * ptmh = 0;
973 struct polymostdrawpolycall draw;
974
975 updateanimation((md2model *)m,tspr);
976
977 //create current&next frame's vertex list from whole list
978
979 f = m->interpol; g = 1-f;
980 m0.x = (1.0/64.0)*m->scale*g; m1.x = (1.0/64.0)*m->scale*f;
981 m0.y = (1.0/64.0)*m->scale*g; m1.y = (1.0/64.0)*m->scale*f;
982 m0.z = (1.0/64.0)*m->scale*g; m1.z = (1.0/64.0)*m->scale*f;
983 a0.x = a0.y = 0; a0.z = m->zadd*m->scale;
984
985 // Parkar: Moved up to be able to use k0 for the y-flipping code
986 k0 = tspr->z;
987 if ((globalorientation&128) && !((globalorientation&48)==32)) k0 += (float)((tilesizy[tspr->picnum]*tspr->yrepeat)<<1);
988
989 // Parkar: Changed to use the same method as centeroriented sprites
990 if (globalorientation&8) //y-flipping
991 {
992 m0.z = -m0.z; m1.z = -m1.z; a0.z = -a0.z;
993 k0 -= (float)((tilesizy[tspr->picnum]*tspr->yrepeat)<<2);
994 }
995 if (globalorientation&4) { m0.y = -m0.y; m1.y = -m1.y; a0.y = -a0.y; } //x-flipping
996
997 f = ((float)tspr->xrepeat)/64*m->bscale;
998 m0.x *= f; m1.x *= f; a0.x *= f; f = -f; // 20040610: backwards models aren't cool
999 m0.y *= f; m1.y *= f; a0.y *= f;
1000 f = ((float)tspr->yrepeat)/64*m->bscale;
1001 m0.z *= f; m1.z *= f; a0.z *= f;
1002
1003 // floor aligned
1004 k1 = tspr->y;
1005 if((globalorientation&48)==32)
1006 {
1007 m0.z = -m0.z; m1.z = -m1.z; a0.z = -a0.z;
1008 m0.y = -m0.y; m1.y = -m1.y; a0.y = -a0.y;
1009 f = a0.x; a0.x = a0.z; a0.z = f;
1010 k1 += (float)((tilesizy[tspr->picnum]*tspr->yrepeat)>>3);
1011 }
1012
1013 f = (65536.0*512.0)/((float)xdimen*viewingrange);
1014 g = 32.0/((float)xdimen*gxyaspect);
1015 m0.y *= f; m1.y *= f; a0.y = (((float)(tspr->x-globalposx))/ 1024.0 + a0.y)*f;
1016 m0.x *=-f; m1.x *=-f; a0.x = (((float)(k1 -globalposy))/ -1024.0 + a0.x)*-f;
1017 m0.z *= g; m1.z *= g; a0.z = (((float)(k0 -globalposz))/-16384.0 + a0.z)*g;
1018
1019 k0 = ((float)(tspr->x-globalposx))*f/1024.0;
1020 k1 = ((float)(tspr->y-globalposy))*f/1024.0;
1021 f = gcosang2*gshang;
1022 g = gsinang2*gshang;
1023 k4 = (float)sintable[(tspr->ang+spriteext[tspr->owner].angoff+1024)&2047] / 16384.0;
1024 k5 = (float)sintable[(tspr->ang+spriteext[tspr->owner].angoff+ 512)&2047] / 16384.0;
1025 k2 = k0*(1-k4)+k1*k5;
1026 k3 = k1*(1-k4)-k0*k5;
1027 k6 = f*gstang - gsinang*gctang; k7 = g*gstang + gcosang*gctang;
1028 mat[0] = k4*k6 + k5*k7; mat[4] = gchang*gstang; mat[ 8] = k4*k7 - k5*k6; mat[12] = k2*k6 + k3*k7;
1029 k6 = f*gctang + gsinang*gstang; k7 = g*gctang - gcosang*gstang;
1030 mat[1] = k4*k6 + k5*k7; mat[5] = gchang*gctang; mat[ 9] = k4*k7 - k5*k6; mat[13] = k2*k6 + k3*k7;
1031 k6 = gcosang2*gchang; k7 = gsinang2*gchang;
1032 mat[2] = k4*k6 + k5*k7; mat[6] =-gshang; mat[10] = k4*k7 - k5*k6; mat[14] = k2*k6 + k3*k7;
1033
1034 mat[12] += a0.y*mat[0] + a0.z*mat[4] + a0.x*mat[ 8];
1035 mat[13] += a0.y*mat[1] + a0.z*mat[5] + a0.x*mat[ 9];
1036 mat[14] += a0.y*mat[2] + a0.z*mat[6] + a0.x*mat[10];
1037
1038 // floor aligned
1039 if((globalorientation&48)==32)
1040 {
1041 f = mat[4]; mat[4] = mat[8]*16.0; mat[8] = -f*(1.0/16.0);
1042 f = mat[5]; mat[5] = mat[9]*16.0; mat[9] = -f*(1.0/16.0);
1043 f = mat[6]; mat[6] = mat[10]*16.0; mat[10] = -f*(1.0/16.0);
1044 }
1045
1046 //Mirrors
1047 if (grhalfxdown10x < 0) { mat[0] = -mat[0]; mat[4] = -mat[4]; mat[8] = -mat[8]; mat[12] = -mat[12]; }
1048
1049 mat[3] = mat[7] = mat[11] = 0.f; mat[15] = 1.f;
1050
1051 //------------
1052 //bit 10 is an ugly hack in game.c\animatesprites telling MD2SPRITE
1053 //to use Z-buffer hacks to hide overdraw problems with the shadows
1054 if (tspr->cstat&1024)
1055 {
1056 glfunc.glDepthFunc(GL_LESS); //NEVER,LESS,(,L)EQUAL,GREATER,(NOT,G)EQUAL,ALWAYS
1057 #if (USE_OPENGL == USE_GLES2)
1058 glfunc.glDepthRangef(0.f,0.9999f);
1059 #else
1060 glfunc.glDepthRange(0.0,0.9999);
1061 #endif
1062 }
1063 if ((grhalfxdown10x >= 0) ^ ((globalorientation&8) != 0) ^ ((globalorientation&4) != 0)) glfunc.glFrontFace(GL_CW); else glfunc.glFrontFace(GL_CCW);
1064 glfunc.glEnable(GL_CULL_FACE);
1065 glfunc.glCullFace(GL_BACK);
1066
1067 pc[0] = pc[1] = pc[2] = ((float)(numpalookups-min(max(globalshade+m->shadeoff,0),numpalookups)))/((float)numpalookups);
1068 pc[0] *= (float)hictinting[globalpal].r / 255.0;
1069 pc[1] *= (float)hictinting[globalpal].g / 255.0;
1070 pc[2] *= (float)hictinting[globalpal].b / 255.0;
1071 if (tspr->cstat&2) { if (!(tspr->cstat&512)) pc[3] = 0.66; else pc[3] = 0.33; } else pc[3] = 1.0;
1072 if (m->usesalpha || (tspr->cstat&2)) glfunc.glEnable(GL_BLEND); else glfunc.glDisable(GL_BLEND); //Sprites with alpha in texture
1073 //------------
1074
1075 draw.texture1 = 0;
1076 draw.alphacut = 0.32;
1077 draw.colour.r = pc[0];
1078 draw.colour.g = pc[1];
1079 draw.colour.b = pc[2];
1080 draw.colour.a = pc[3];
1081 draw.fogcolour.r = (float)palookupfog[gfogpalnum].r / 63.f;
1082 draw.fogcolour.g = (float)palookupfog[gfogpalnum].g / 63.f;
1083 draw.fogcolour.b = (float)palookupfog[gfogpalnum].b / 63.f;
1084 draw.fogcolour.a = 1.f;
1085 draw.fogdensity = gfogdensity;
1086 draw.indexbuffer = 0;
1087 draw.elementbuffer = 0;
1088 draw.elementvbo = elementvbo;
1089
1090 if (method & 1) {
1091 draw.projection = &grotatespriteprojmat[0][0];
1092 } else {
1093 draw.projection = &gdrawroomsprojmat[0][0];
1094 }
1095 draw.modelview = mat;
1096
1097 for(surfi=0;surfi<m->head.numsurfs;surfi++)
1098 {
1099 s = &m->head.surfs[surfi];
1100 v0 = &s->xyzn[m->cframe*s->numverts];
1101 v1 = &s->xyzn[m->nframe*s->numverts];
1102
1103 for(i=s->numverts-1;i>=0;i--) //interpolate (for animation) & transform to Build coords
1104 {
1105 vertlist[i].z = ((float)v0[i].x)*m0.x + ((float)v1[i].x)*m1.x;
1106 vertlist[i].y = ((float)v0[i].z)*m0.z + ((float)v1[i].z)*m1.z;
1107 vertlist[i].x = ((float)v0[i].y)*m0.y + ((float)v1[i].y)*m1.y;
1108 }
1109
1110 #if 0
1111 //precalc:
1112 float sinlut256[256+(256>>2)];
1113 for(i=0;i<sizeof(sinlut256)/sizeof(sinlut256[0]);i++) sinlut256[i] = sin(((float)i)*(PI*2/255.0));
1114
1115 //normal to xyz:
1116 md3vert_t *mv = &md3vert[?];
1117 z = sinlut256[mv->nlng+(256>>2)];
1118 x = sinlut256[mv->nlat]*z;
1119 y = sinlut256[mv->nlat+(256>>2)]*z;
1120 z = sinlut256[mv->nlng];
1121 #endif
1122
1123 ptmh = mdloadskin((md2model *)m,tile2model[tspr->picnum].skinnum,globalpal,surfi);
1124 if (!ptmh || !ptmh->glpic) continue;
1125
1126 draw.texture0 = ptmh->glpic;
1127
1128 for(i=0, vbi=0; i<s->numtris; i++, vbi+=3)
1129 for(j=2;j>=0;j--)
1130 {
1131 k = s->tris[i].i[j];
1132
1133 elementvbo[vbi+j].v.x = vertlist[k].x;
1134 elementvbo[vbi+j].v.y = vertlist[k].y;
1135 elementvbo[vbi+j].v.z = vertlist[k].z;
1136 elementvbo[vbi+j].t.s = s->uv[k].u;
1137 elementvbo[vbi+j].t.t = s->uv[k].v;
1138 }
1139
1140 draw.indexcount = 3 * s->numtris;
1141 draw.elementcount = 3 * s->numtris;
1142 polymost_drawpoly_glcall(GL_TRIANGLES, &draw);
1143 }
1144
1145 //------------
1146 glfunc.glDisable(GL_CULL_FACE);
1147 glfunc.glFrontFace(GL_CCW);
1148 if (tspr->cstat&1024)
1149 {
1150 glfunc.glDepthFunc(GL_LEQUAL); //NEVER,LESS,(,L)EQUAL,GREATER,(NOT,G)EQUAL,ALWAYS
1151 #if (USE_OPENGL == USE_GLES2)
1152 glfunc.glDepthRangef(0.f,0.99999f);
1153 #else
1154 glfunc.glDepthRange(0.0,0.99999);
1155 #endif
1156 }
1157
1158 return 1;
1159 }
1160
md3free(md3model * m)1161 static void md3free (md3model *m)
1162 {
1163 mdanim_t *anim, *nanim = NULL;
1164 mdskinmap_t *sk, *nsk = NULL;
1165 md3surf_t *s;
1166 int surfi;
1167
1168 if (!m) return;
1169
1170 for(anim=m->animations; anim; anim=nanim)
1171 {
1172 nanim = anim->next;
1173 free(anim);
1174 }
1175 for(sk=m->skinmap; sk; sk=nsk)
1176 {
1177 nsk = sk->next;
1178 free(sk->fn);
1179 free(sk);
1180 }
1181
1182 if (m->head.surfs)
1183 {
1184 for(surfi=m->head.numsurfs-1;surfi>=0;surfi--)
1185 {
1186 s = &m->head.surfs[surfi];
1187 if (s->tris) free(s->tris);
1188 }
1189 free(m->head.surfs);
1190 }
1191 if (m->head.tags) free(m->head.tags);
1192 if (m->head.frames) free(m->head.frames);
1193
1194 if (m->tex) free(m->tex);
1195
1196 free(m);
1197 }
1198
1199 //---------------------------------------- MD3 LIBRARY ENDS ----------------------------------------
1200 //--------------------------------------- VOX LIBRARY BEGINS ---------------------------------------
1201
1202 //For loading/conversion only
1203 static int xsiz, ysiz, zsiz, yzsiz, *vbit = 0; //vbit: 1 bit per voxel: 0=air,1=solid
1204 static float xpiv, ypiv, zpiv; //Might want to use more complex/unique names!
1205 static int *vcolhashead = 0, vcolhashsizm1;
1206 typedef struct { int p, c, n; } voxcol_t;
1207 static voxcol_t *vcol = 0; int vnum = 0, vmax = 0;
1208 typedef struct { short x, y; } spoint2d;
1209 static spoint2d *shp;
1210 static int *shcntmal, *shcnt = 0, shcntp;
1211 static int mytexo5, *zbit, gmaxx, gmaxy, garea, pow2m1[33];
1212 static voxmodel *gvox;
1213
1214 //pitch must equal xsiz*4
gloadtex(int * picbuf,int xsiz,int ysiz,int is8bit,int dapal)1215 unsigned gloadtex (int *picbuf, int xsiz, int ysiz, int is8bit, int dapal)
1216 {
1217 unsigned rtexid;
1218 coltype *pic, *pic2;
1219 unsigned char *cptr;
1220 int i;
1221
1222 pic = (coltype *)picbuf; //Correct for GL's RGB order; also apply gamma here..
1223 pic2 = (coltype *)malloc(xsiz*ysiz*sizeof(coltype)); if (!pic2) return((unsigned)-1);
1224 cptr = (unsigned char*)&britable[gammabrightness ? 0 : curbrightness][0];
1225 if (!is8bit)
1226 {
1227 for(i=xsiz*ysiz-1;i>=0;i--)
1228 {
1229 pic2[i].b = cptr[pic[i].r];
1230 pic2[i].g = cptr[pic[i].g];
1231 pic2[i].r = cptr[pic[i].b];
1232 pic2[i].a = 255;
1233 }
1234 }
1235 else
1236 {
1237 if (palookup[dapal] == 0) dapal = 0;
1238 for(i=xsiz*ysiz-1;i>=0;i--)
1239 {
1240 pic2[i].b = cptr[palette[(int)palookup[dapal][pic[i].a]*3+2]*4];
1241 pic2[i].g = cptr[palette[(int)palookup[dapal][pic[i].a]*3+1]*4];
1242 pic2[i].r = cptr[palette[(int)palookup[dapal][pic[i].a]*3+0]*4];
1243 pic2[i].a = 255;
1244 }
1245 }
1246
1247 glfunc.glGenTextures(1,(GLuint*)&rtexid);
1248 glfunc.glBindTexture(GL_TEXTURE_2D,rtexid);
1249 glfunc.glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
1250 glfunc.glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
1251 glfunc.glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,xsiz,ysiz,0,GL_RGBA,GL_UNSIGNED_BYTE,(unsigned char *)pic2);
1252 free(pic2);
1253 return(rtexid);
1254 }
1255
getvox(int x,int y,int z)1256 static int getvox (int x, int y, int z)
1257 {
1258 z += x*yzsiz + y*zsiz;
1259 for(x=vcolhashead[(z*214013)&vcolhashsizm1];x>=0;x=vcol[x].n)
1260 if (vcol[x].p == z) return(vcol[x].c);
1261 return(0x808080);
1262 }
1263
putvox(int x,int y,int z,int col)1264 static void putvox (int x, int y, int z, int col)
1265 {
1266 if (vnum >= vmax) { vmax = max(vmax<<1,4096); vcol = (voxcol_t *)realloc(vcol,vmax*sizeof(voxcol_t)); }
1267
1268 z += x*yzsiz + y*zsiz;
1269 vcol[vnum].p = z; z = ((z*214013)&vcolhashsizm1);
1270 vcol[vnum].c = col;
1271 vcol[vnum].n = vcolhashead[z]; vcolhashead[z] = vnum++;
1272 }
1273
1274 //Set all bits in vbit from (x,y,z0) to (x,y,z1-1) to 0's
setzrange0(int * lptr,int z0,int z1)1275 static void setzrange0 (int *lptr, int z0, int z1)
1276 {
1277 int z, ze;
1278 if (!((z0^z1)&~31)) { lptr[z0>>5] &= (~(-(1<<SHIFTMOD32(z0))))|(-(1<<SHIFTMOD32(z1))); return; }
1279 z = (z0>>5); ze = (z1>>5);
1280 lptr[z] &=~(-(1<<SHIFTMOD32(z0))); for(z++;z<ze;z++) lptr[z] = 0;
1281 lptr[z] &= (-(1<<SHIFTMOD32(z1)));
1282 }
1283
1284 //Set all bits in vbit from (x,y,z0) to (x,y,z1-1) to 1's
setzrange1(int * lptr,int z0,int z1)1285 static void setzrange1 (int *lptr, int z0, int z1)
1286 {
1287 int z, ze;
1288 if (!((z0^z1)&~31)) { lptr[z0>>5] |= (~(-(1<<SHIFTMOD32(z1))))&(-(1<<SHIFTMOD32(z0))); return; }
1289 z = (z0>>5); ze = (z1>>5);
1290 lptr[z] |= (-(1<<SHIFTMOD32(z0))); for(z++;z<ze;z++) lptr[z] = -1;
1291 lptr[z] |=~(-(1<<SHIFTMOD32(z1)));
1292 }
1293
isrectfree(int x0,int y0,int dx,int dy)1294 static int isrectfree (int x0, int y0, int dx, int dy)
1295 {
1296 #if 0
1297 int i, j, x;
1298 i = y0*gvox->mytexx + x0;
1299 for(dy=0;dy;dy--,i+=gvox->mytexx)
1300 for(x=0;x<dx;x++) { j = i+x; if (zbit[j>>5]&(1<<SHIFTMOD32(j))) return(0); }
1301 #else
1302 int i, c, m, m1, x;
1303
1304 i = y0*mytexo5 + (x0>>5); dx += x0-1; c = (dx>>5) - (x0>>5);
1305 m = ~pow2m1[x0&31]; m1 = pow2m1[(dx&31)+1];
1306 if (!c) { for(m&=m1;dy;dy--,i+=mytexo5) if (zbit[i]&m) return(0); }
1307 else
1308 { for(;dy;dy--,i+=mytexo5)
1309 {
1310 if (zbit[i]&m) return(0);
1311 for(x=1;x<c;x++) if (zbit[i+x]) return(0);
1312 if (zbit[i+x]&m1) return(0);
1313 }
1314 }
1315 #endif
1316 return(1);
1317 }
1318
setrect(int x0,int y0,int dx,int dy)1319 static void setrect (int x0, int y0, int dx, int dy)
1320 {
1321 #if 0
1322 int i, j, y;
1323 i = y0*gvox->mytexx + x0;
1324 for(y=0;y<dy;y++,i+=gvox->mytexx)
1325 for(x=0;x<dx;x++) { j = i+x; zbit[j>>5] |= (1<<SHIFTMOD32(j)); }
1326 #else
1327 int i, c, m, m1, x;
1328
1329 i = y0*mytexo5 + (x0>>5); dx += x0-1; c = (dx>>5) - (x0>>5);
1330 m = ~pow2m1[x0&31]; m1 = pow2m1[(dx&31)+1];
1331 if (!c) { for(m&=m1;dy;dy--,i+=mytexo5) zbit[i] |= m; }
1332 else
1333 { for(;dy;dy--,i+=mytexo5)
1334 {
1335 zbit[i] |= m;
1336 for(x=1;x<c;x++) zbit[i+x] = -1;
1337 zbit[i+x] |= m1;
1338 }
1339 }
1340 #endif
1341 }
1342
cntquad(int x0,int y0,int z0,int UNUSED (x1),int UNUSED (y1),int UNUSED (z1),int x2,int y2,int z2,int UNUSED (face))1343 static void cntquad (int x0, int y0, int z0, int UNUSED(x1), int UNUSED(y1), int UNUSED(z1), int x2, int y2, int z2, int UNUSED(face))
1344 {
1345 int x, y, z;
1346
1347 x = labs(x2-x0); y = labs(y2-y0); z = labs(z2-z0);
1348 if (!x) x = z; else if (!y) y = z;
1349 if (x < y) { z = x; x = y; y = z; }
1350 shcnt[y*shcntp+x]++;
1351 if (x > gmaxx) gmaxx = x;
1352 if (y > gmaxy) gmaxy = y;
1353 garea += (x+(VOXBORDWIDTH<<1))*(y+(VOXBORDWIDTH<<1));
1354 gvox->qcnt++;
1355 }
1356
addquad(int x0,int y0,int z0,int x1,int y1,int z1,int x2,int y2,int z2,int face)1357 static void addquad (int x0, int y0, int z0, int x1, int y1, int z1, int x2, int y2, int z2, int face)
1358 {
1359 int i, j, x, y, z, xx, yy, nx = 0, ny = 0, nz = 0, *lptr;
1360 voxrect_t *qptr;
1361
1362 x = labs(x2-x0); y = labs(y2-y0); z = labs(z2-z0);
1363 if (!x) { x = y; y = z; i = 0; } else if (!y) { y = z; i = 1; } else i = 2;
1364 if (x < y) { z = x; x = y; y = z; i += 3; }
1365 z = shcnt[y*shcntp+x]++;
1366 lptr = &gvox->mytex[(shp[z].y+VOXBORDWIDTH)*gvox->mytexx+(shp[z].x+VOXBORDWIDTH)];
1367 switch(face)
1368 {
1369 case 0: ny = y1; x2 = x0; x0 = x1; x1 = x2; break;
1370 case 1: ny = y0; y0++; y1++; y2++; break;
1371 case 2: nz = z1; y0 = y2; y2 = y1; y1 = y0; z0++; z1++; z2++; break;
1372 case 3: nz = z0; break;
1373 case 4: nx = x1; y2 = y0; y0 = y1; y1 = y2; x0++; x1++; x2++; break;
1374 case 5: nx = x0; break;
1375 }
1376 for(yy=0;yy<y;yy++,lptr+=gvox->mytexx)
1377 for(xx=0;xx<x;xx++)
1378 {
1379 switch(face)
1380 {
1381 case 0: if (i < 3) { nx = x1+x-1-xx; nz = z1+yy; } //back
1382 else { nx = x1+y-1-yy; nz = z1+xx; } break;
1383 case 1: if (i < 3) { nx = x0+xx; nz = z0+yy; } //front
1384 else { nx = x0+yy; nz = z0+xx; } break;
1385 case 2: if (i < 3) { nx = x1-x+xx; ny = y1-1-yy; } //bot
1386 else { nx = x1-1-yy; ny = y1-1-xx; } break;
1387 case 3: if (i < 3) { nx = x0+xx; ny = y0+yy; } //top
1388 else { nx = x0+yy; ny = y0+xx; } break;
1389 case 4: if (i < 3) { ny = y1+x-1-xx; nz = z1+yy; } //right
1390 else { ny = y1+y-1-yy; nz = z1+xx; } break;
1391 case 5: if (i < 3) { ny = y0+xx; nz = z0+yy; } //left
1392 else { ny = y0+yy; nz = z0+xx; } break;
1393 }
1394 lptr[xx] = getvox(nx,ny,nz);
1395 }
1396
1397 //Extend borders horizontally
1398 for(yy=VOXBORDWIDTH;yy<y+VOXBORDWIDTH;yy++)
1399 for(xx=0;xx<VOXBORDWIDTH;xx++)
1400 {
1401 lptr = &gvox->mytex[(shp[z].y+yy)*gvox->mytexx+shp[z].x];
1402 lptr[xx] = lptr[VOXBORDWIDTH]; lptr[xx+x+VOXBORDWIDTH] = lptr[x-1+VOXBORDWIDTH];
1403 }
1404 //Extend borders vertically
1405 for(yy=0;yy<VOXBORDWIDTH;yy++)
1406 {
1407 memcpy(&gvox->mytex[(shp[z].y+yy)*gvox->mytexx+shp[z].x],
1408 &gvox->mytex[(shp[z].y+VOXBORDWIDTH)*gvox->mytexx+shp[z].x],
1409 (x+(VOXBORDWIDTH<<1))<<2);
1410 memcpy(&gvox->mytex[(shp[z].y+y+yy+VOXBORDWIDTH)*gvox->mytexx+shp[z].x],
1411 &gvox->mytex[(shp[z].y+y-1+VOXBORDWIDTH)*gvox->mytexx+shp[z].x],
1412 (x+(VOXBORDWIDTH<<1))<<2);
1413 }
1414
1415 qptr = &gvox->quad[gvox->qcnt];
1416 qptr->v[0].x = x0; qptr->v[0].y = y0; qptr->v[0].z = z0;
1417 qptr->v[1].x = x1; qptr->v[1].y = y1; qptr->v[1].z = z1;
1418 qptr->v[2].x = x2; qptr->v[2].y = y2; qptr->v[2].z = z2;
1419 for(j=0;j<3;j++) { qptr->v[j].u = shp[z].x+VOXBORDWIDTH; qptr->v[j].v = shp[z].y+VOXBORDWIDTH; }
1420 if (i < 3) qptr->v[1].u += x; else qptr->v[1].v += y;
1421 qptr->v[2].u += x; qptr->v[2].v += y;
1422
1423 qptr->v[3].u = qptr->v[0].u - qptr->v[1].u + qptr->v[2].u;
1424 qptr->v[3].v = qptr->v[0].v - qptr->v[1].v + qptr->v[2].v;
1425 qptr->v[3].x = qptr->v[0].x - qptr->v[1].x + qptr->v[2].x;
1426 qptr->v[3].y = qptr->v[0].y - qptr->v[1].y + qptr->v[2].y;
1427 qptr->v[3].z = qptr->v[0].z - qptr->v[1].z + qptr->v[2].z;
1428 if (gvox->qfacind[face] < 0) gvox->qfacind[face] = gvox->qcnt;
1429 gvox->qcnt++;
1430
1431 }
1432
isolid(int x,int y,int z)1433 static int isolid (int x, int y, int z)
1434 {
1435 if ((unsigned int)x >= (unsigned int)xsiz) return(0);
1436 if ((unsigned int)y >= (unsigned int)ysiz) return(0);
1437 if ((unsigned int)z >= (unsigned int)zsiz) return(0);
1438 z += x*yzsiz + y*zsiz; return(vbit[z>>5]&(1<<SHIFTMOD32(z)));
1439 }
1440
vox2poly()1441 static voxmodel *vox2poly ()
1442 {
1443 int i, j, x, y, z, v, ov, oz = 0, cnt, sc, x0, y0, dx, dy, i0, i1, *bx0, *by0;
1444 void (*daquad)(int, int, int, int, int, int, int, int, int, int);
1445 coltype *pic;
1446 unsigned char *cptr, ch;
1447
1448 gvox = (voxmodel *)malloc(sizeof(voxmodel)); if (!gvox) return(0);
1449 memset(gvox,0,sizeof(voxmodel));
1450
1451 //x is largest dimension, y is 2nd largest dimension
1452 x = xsiz; y = ysiz; z = zsiz;
1453 if ((x < y) && (x < z)) x = z; else if (y < z) y = z;
1454 if (x < y) { z = x; x = y; y = z; }
1455 shcntp = x; i = x*y*sizeof(int);
1456 shcntmal = (int *)malloc(i); if (!shcntmal) { free(gvox); return(0); }
1457 memset(shcntmal,0,i); shcnt = &shcntmal[-shcntp-1];
1458 gmaxx = gmaxy = garea = 0;
1459
1460 if (pow2m1[32] != -1) { for(i=0;i<32;i++) pow2m1[i] = (1<<i)-1; pow2m1[32] = -1; }
1461 for(i=0;i<7;i++) gvox->qfacind[i] = -1;
1462
1463 i = ((max(ysiz,zsiz)+1)<<2);
1464 bx0 = (int *)malloc(i<<1); if (!bx0) { free(gvox); return(0); }
1465 by0 = (int *)(((intptr_t)bx0)+i);
1466
1467 for(cnt=0;cnt<2;cnt++)
1468 {
1469 if (!cnt) daquad = cntquad;
1470 else daquad = addquad;
1471 gvox->qcnt = 0;
1472
1473 memset(by0,-1,(max(ysiz,zsiz)+1)<<2); v = 0;
1474
1475 for(i=-1;i<=1;i+=2)
1476 for(y=0;y<ysiz;y++)
1477 for(x=0;x<=xsiz;x++)
1478 for(z=0;z<=zsiz;z++)
1479 {
1480 ov = v; v = (isolid(x,y,z) && (!isolid(x,y+i,z)));
1481 if ((by0[z] >= 0) && ((by0[z] != oz) || (v >= ov)))
1482 { daquad(bx0[z],y,by0[z],x,y,by0[z],x,y,z,i>=0); by0[z] = -1; }
1483 if (v > ov) oz = z; else if ((v < ov) && (by0[z] != oz)) { bx0[z] = x; by0[z] = oz; }
1484 }
1485
1486 for(i=-1;i<=1;i+=2)
1487 for(z=0;z<zsiz;z++)
1488 for(x=0;x<=xsiz;x++)
1489 for(y=0;y<=ysiz;y++)
1490 {
1491 ov = v; v = (isolid(x,y,z) && (!isolid(x,y,z-i)));
1492 if ((by0[y] >= 0) && ((by0[y] != oz) || (v >= ov)))
1493 { daquad(bx0[y],by0[y],z,x,by0[y],z,x,y,z,(i>=0)+2); by0[y] = -1; }
1494 if (v > ov) oz = y; else if ((v < ov) && (by0[y] != oz)) { bx0[y] = x; by0[y] = oz; }
1495 }
1496
1497 for(i=-1;i<=1;i+=2)
1498 for(x=0;x<xsiz;x++)
1499 for(y=0;y<=ysiz;y++)
1500 for(z=0;z<=zsiz;z++)
1501 {
1502 ov = v; v = (isolid(x,y,z) && (!isolid(x-i,y,z)));
1503 if ((by0[z] >= 0) && ((by0[z] != oz) || (v >= ov)))
1504 { daquad(x,bx0[z],by0[z],x,y,by0[z],x,y,z,(i>=0)+4); by0[z] = -1; }
1505 if (v > ov) oz = z; else if ((v < ov) && (by0[z] != oz)) { bx0[z] = y; by0[z] = oz; }
1506 }
1507
1508 if (!cnt)
1509 {
1510 shp = (spoint2d *)malloc(gvox->qcnt*sizeof(spoint2d));
1511 if (!shp) { free(bx0); free(gvox); return(0); }
1512
1513 sc = 0;
1514 for(y=gmaxy;y;y--)
1515 for(x=gmaxx;x>=y;x--)
1516 {
1517 i = shcnt[y*shcntp+x]; shcnt[y*shcntp+x] = sc; //shcnt changes from counter to head index
1518 for(;i>0;i--) { shp[sc].x = x; shp[sc].y = y; sc++; }
1519 }
1520
1521 for(gvox->mytexx=32;gvox->mytexx<(gmaxx+(VOXBORDWIDTH<<1));gvox->mytexx<<=1);
1522 for(gvox->mytexy=32;gvox->mytexy<(gmaxy+(VOXBORDWIDTH<<1));gvox->mytexy<<=1);
1523 while (gvox->mytexx*gvox->mytexy*8 < garea*9) //This should be sufficient to fit most skins...
1524 {
1525 skindidntfit:;
1526 if (gvox->mytexx <= gvox->mytexy) gvox->mytexx <<= 1; else gvox->mytexy <<= 1;
1527 }
1528 mytexo5 = (gvox->mytexx>>5);
1529
1530 i = (((gvox->mytexx*gvox->mytexy+31)>>5)<<2);
1531 zbit = (int *)malloc(i); if (!zbit) { free(bx0); free(gvox); free(shp); return(0); }
1532 memset(zbit,0,i);
1533
1534 v = gvox->mytexx*gvox->mytexy;
1535 for(z=0;z<sc;z++)
1536 {
1537 dx = shp[z].x+(VOXBORDWIDTH<<1); dy = shp[z].y+(VOXBORDWIDTH<<1); i = v;
1538 do
1539 {
1540 #if (VOXUSECHAR != 0)
1541 x0 = (((rand()&32767)*(min(gvox->mytexx,255)-dx))>>15);
1542 y0 = (((rand()&32767)*(min(gvox->mytexy,255)-dy))>>15);
1543 #else
1544 x0 = (((rand()&32767)*(gvox->mytexx+1-dx))>>15);
1545 y0 = (((rand()&32767)*(gvox->mytexy+1-dy))>>15);
1546 #endif
1547 i--;
1548 if (i < 0) //Time-out! Very slow if this happens... but at least it still works :P
1549 {
1550 free(zbit);
1551
1552 //Re-generate shp[].x/y (box sizes) from shcnt (now head indices) for next pass :/
1553 j = 0;
1554 for(y=gmaxy;y;y--)
1555 for(x=gmaxx;x>=y;x--)
1556 {
1557 i = shcnt[y*shcntp+x];
1558 for(;j<i;j++) { shp[j].x = x0; shp[j].y = y0; }
1559 x0 = x; y0 = y;
1560 }
1561 for(;j<sc;j++) { shp[j].x = x0; shp[j].y = y0; }
1562
1563 goto skindidntfit;
1564 }
1565 } while (!isrectfree(x0,y0,dx,dy));
1566 while ((y0) && (isrectfree(x0,y0-1,dx,1))) y0--;
1567 while ((x0) && (isrectfree(x0-1,y0,1,dy))) x0--;
1568 setrect(x0,y0,dx,dy);
1569 shp[z].x = x0; shp[z].y = y0; //Overwrite size with top-left location
1570 }
1571
1572 gvox->quad = (voxrect_t *)malloc(gvox->qcnt*sizeof(voxrect_t));
1573 if (!gvox->quad) { free(zbit); free(shp); free(bx0); free(gvox); return(0); }
1574
1575 gvox->mytex = (int *)malloc(gvox->mytexx*gvox->mytexy*sizeof(int));
1576 if (!gvox->mytex) { free(gvox->quad); free(zbit); free(shp); free(bx0); free(gvox); return(0); }
1577 }
1578 }
1579 free(shp); free(zbit); free(bx0);
1580 return(gvox);
1581 }
1582
loadvox(const char * filnam)1583 static int loadvox (const char *filnam)
1584 {
1585 int i, j, k, x, y, z, pal[256], fil;
1586 unsigned char c[3], *tbuf;
1587
1588 fil = kopen4load((char *)filnam,0); if (fil < 0) return(-1);
1589 kread(fil,&xsiz,4); xsiz = B_LITTLE32(xsiz);
1590 kread(fil,&ysiz,4); ysiz = B_LITTLE32(ysiz);
1591 kread(fil,&zsiz,4); zsiz = B_LITTLE32(zsiz);
1592 xpiv = ((float)xsiz)*.5;
1593 ypiv = ((float)ysiz)*.5;
1594 zpiv = ((float)zsiz)*.5;
1595
1596 klseek(fil,-768,SEEK_END);
1597 for(i=0;i<256;i++)
1598 { kread(fil,c,3); pal[i] = (((int)c[0])<<18)+(((int)c[1])<<10)+(((int)c[2])<<2)+(i<<24); }
1599 pal[255] = -1;
1600
1601 vcolhashsizm1 = 8192-1;
1602 vcolhashead = (int *)malloc((vcolhashsizm1+1)*sizeof(int)); if (!vcolhashead) { kclose(fil); return(-1); }
1603 memset(vcolhashead,-1,(vcolhashsizm1+1)*sizeof(int));
1604
1605 yzsiz = ysiz*zsiz; i = ((xsiz*yzsiz+31)>>3);
1606 vbit = (int *)malloc(i); if (!vbit) { kclose(fil); return(-1); }
1607 memset(vbit,0,i);
1608
1609 tbuf = (unsigned char *)malloc(zsiz*sizeof(unsigned char)); if (!tbuf) { kclose(fil); return(-1); }
1610
1611 klseek(fil,12,SEEK_SET);
1612 for(x=0;x<xsiz;x++)
1613 for(y=0,j=x*yzsiz;y<ysiz;y++,j+=zsiz)
1614 {
1615 kread(fil,tbuf,zsiz);
1616 for(z=zsiz-1;z>=0;z--)
1617 { if (tbuf[z] != 255) { i = j+z; vbit[i>>5] |= (1<<SHIFTMOD32(i)); } }
1618 }
1619
1620 klseek(fil,12,SEEK_SET);
1621 for(x=0;x<xsiz;x++)
1622 for(y=0,j=x*yzsiz;y<ysiz;y++,j+=zsiz)
1623 {
1624 kread(fil,tbuf,zsiz);
1625 for(z=0;z<zsiz;z++)
1626 {
1627 if (tbuf[z] == 255) continue;
1628 if ((!x) || (!y) || (!z) || (x == xsiz-1) || (y == ysiz-1) || (z == zsiz-1))
1629 { putvox(x,y,z,pal[tbuf[z]]); continue; }
1630 k = j+z;
1631 if ((!(vbit[(k-yzsiz)>>5]&(1<<SHIFTMOD32(k-yzsiz)))) ||
1632 (!(vbit[(k+yzsiz)>>5]&(1<<SHIFTMOD32(k+yzsiz)))) ||
1633 (!(vbit[(k- zsiz)>>5]&(1<<SHIFTMOD32(k- zsiz)))) ||
1634 (!(vbit[(k+ zsiz)>>5]&(1<<SHIFTMOD32(k+ zsiz)))) ||
1635 (!(vbit[(k- 1)>>5]&(1<<SHIFTMOD32(k- 1)))) ||
1636 (!(vbit[(k+ 1)>>5]&(1<<SHIFTMOD32(k+ 1)))))
1637 { putvox(x,y,z,pal[tbuf[z]]); continue; }
1638 }
1639 }
1640
1641 free(tbuf); kclose(fil); return(0);
1642 }
1643
loadkvx(const char * filnam)1644 static int loadkvx (const char *filnam)
1645 {
1646 int i, j, k, x, y, z, pal[256], z0, z1, mip1leng, ysizp1, fil;
1647 unsigned short *xyoffs;
1648 unsigned char c[3], *tbuf, *cptr;
1649
1650 fil = kopen4load((char *)filnam,0); if (fil < 0) return(-1);
1651 kread(fil,&mip1leng,4); mip1leng = B_LITTLE32(mip1leng);
1652 kread(fil,&xsiz,4); xsiz = B_LITTLE32(xsiz);
1653 kread(fil,&ysiz,4); ysiz = B_LITTLE32(ysiz);
1654 kread(fil,&zsiz,4); zsiz = B_LITTLE32(zsiz);
1655 kread(fil,&i,4); xpiv = ((float)B_LITTLE32(i))/256.0;
1656 kread(fil,&i,4); ypiv = ((float)B_LITTLE32(i))/256.0;
1657 kread(fil,&i,4); zpiv = ((float)B_LITTLE32(i))/256.0;
1658 klseek(fil,(xsiz+1)<<2,SEEK_CUR);
1659 ysizp1 = ysiz+1;
1660 i = xsiz*ysizp1*sizeof(short);
1661 xyoffs = (unsigned short *)malloc(i); if (!xyoffs) { kclose(fil); return(-1); }
1662 kread(fil,xyoffs,i); for (i=i/sizeof(short)-1; i>=0; i--) xyoffs[i] = B_LITTLE16(xyoffs[i]);
1663
1664 klseek(fil,-768,SEEK_END);
1665 for(i=0;i<256;i++)
1666 { kread(fil,c,3); pal[i] = B_LITTLE32((((int)c[0])<<18)+(((int)c[1])<<10)+(((int)c[2])<<2)+(i<<24)); }
1667
1668 yzsiz = ysiz*zsiz; i = ((xsiz*yzsiz+31)>>3);
1669 vbit = (int *)malloc(i); if (!vbit) { free(xyoffs); kclose(fil); return(-1); }
1670 memset(vbit,0,i);
1671
1672 for(vcolhashsizm1=4096;vcolhashsizm1<(mip1leng>>1);vcolhashsizm1<<=1) ;
1673 vcolhashsizm1--; //approx to numvoxs!
1674 vcolhashead = (int *)malloc((vcolhashsizm1+1)*sizeof(int)); if (!vcolhashead) { free(xyoffs); kclose(fil); return(-1); }
1675 memset(vcolhashead,-1,(vcolhashsizm1+1)*sizeof(int));
1676
1677 klseek(fil,28+((xsiz+1)<<2)+((ysizp1*xsiz)<<1),SEEK_SET);
1678
1679 i = kfilelength(fil)-ktell(fil);
1680 tbuf = (unsigned char *)malloc(i); if (!tbuf) { free(xyoffs); kclose(fil); return(-1); }
1681 kread(fil,tbuf,i); kclose(fil);
1682
1683 cptr = tbuf;
1684 for(x=0;x<xsiz;x++) //Set surface voxels to 1 else 0
1685 for(y=0,j=x*yzsiz;y<ysiz;y++,j+=zsiz)
1686 {
1687 i = xyoffs[x*ysizp1+y+1] - xyoffs[x*ysizp1+y]; if (!i) continue;
1688 z1 = 0;
1689 while (i)
1690 {
1691 z0 = (int)cptr[0]; k = (int)cptr[1]; cptr += 3;
1692 if (!(cptr[-1]&16)) setzrange1(vbit,j+z1,j+z0);
1693 i -= k+3; z1 = z0+k;
1694 setzrange1(vbit,j+z0,j+z1);
1695 for(z=z0;z<z1;z++) putvox(x,y,z,pal[*cptr++]);
1696 }
1697 }
1698
1699 free(tbuf); free(xyoffs); return(0);
1700 }
1701
loadkv6(const char * filnam)1702 static int loadkv6 (const char *filnam)
1703 {
1704 int i, j, x, y, z, numvoxs, z0, z1, fil;
1705 float f;
1706 unsigned short *ylen;
1707 unsigned char c[8];
1708
1709 fil = kopen4load((char *)filnam,0); if (fil < 0) return(-1);
1710 kread(fil,&i,4); if (B_LITTLE32(i) != 0x6c78764b) { kclose(fil); return(-1); } //Kvxl
1711 kread(fil,&xsiz,4); xsiz = B_LITTLE32(xsiz);
1712 kread(fil,&ysiz,4); ysiz = B_LITTLE32(ysiz);
1713 kread(fil,&zsiz,4); zsiz = B_LITTLE32(zsiz);
1714 kread(fil,&f,4); xpiv = B_LITTLEFLOAT(f);
1715 kread(fil,&f,4); ypiv = B_LITTLEFLOAT(f);
1716 kread(fil,&f,4); zpiv = B_LITTLEFLOAT(f);
1717 kread(fil,&numvoxs,4); numvoxs = B_LITTLE32(numvoxs);
1718
1719 ylen = (unsigned short *)malloc(xsiz*ysiz*sizeof(unsigned short));
1720 if (!ylen) { kclose(fil); return(-1); }
1721
1722 klseek(fil,32+(numvoxs<<3)+(xsiz<<2),SEEK_SET);
1723 kread(fil,ylen,xsiz*ysiz*sizeof(short)); for (i=xsiz*ysiz-1; i>=0; i--) ylen[i] = B_LITTLE16(ylen[i]);
1724 klseek(fil,32,SEEK_SET);
1725
1726 yzsiz = ysiz*zsiz; i = ((xsiz*yzsiz+31)>>3);
1727 vbit = (int *)malloc(i); if (!vbit) { free(ylen); kclose(fil); return(-1); }
1728 memset(vbit,0,i);
1729
1730 for(vcolhashsizm1=4096;vcolhashsizm1<numvoxs;vcolhashsizm1<<=1) ;
1731 vcolhashsizm1--;
1732 vcolhashead = (int *)malloc((vcolhashsizm1+1)*sizeof(int)); if (!vcolhashead) { free(ylen); kclose(fil); return(-1); }
1733 memset(vcolhashead,-1,(vcolhashsizm1+1)*sizeof(int));
1734
1735 for(x=0;x<xsiz;x++)
1736 for(y=0,j=x*yzsiz;y<ysiz;y++,j+=zsiz)
1737 {
1738 z1 = zsiz;
1739 for(i=ylen[x*ysiz+y];i>0;i--)
1740 {
1741 kread(fil,c,8); //b,g,r,a,z_lo,z_hi,vis,dir
1742 z0 = B_LITTLE16(*(unsigned short *)&c[4]);
1743 if (!(c[6]&16)) setzrange1(vbit,j+z1,j+z0);
1744 vbit[(j+z0)>>5] |= (1<<SHIFTMOD32(j+z0));
1745 putvox(x,y,z0,B_LITTLE32(*(int *)&c[0])&0xffffff);
1746 z1 = z0+1;
1747 }
1748 }
1749 free(ylen); kclose(fil); return(0);
1750 }
1751
1752 #if 0
1753 //While this code works, it's way too slow and can only cause trouble.
1754 static int loadvxl (const char *filnam)
1755 {
1756 int i, j, x, y, z, fil;
1757 unsigned char *v, *vbuf;
1758
1759 fil = kopen4load((char *)filnam,0); if (fil < 0) return(-1);
1760 kread(fil,&i,4);
1761 kread(fil,&xsiz,4);
1762 kread(fil,&ysiz,4);
1763 if ((i != 0x09072000) || (xsiz != 1024) || (ysiz != 1024)) { kclose(fil); return(-1); }
1764 zsiz = 256;
1765 klseek(fil,96,SEEK_CUR); //skip pos&orient
1766 xpiv = ((float)xsiz)*.5;
1767 ypiv = ((float)ysiz)*.5;
1768 zpiv = ((float)zsiz)*.5;
1769
1770 yzsiz = ysiz*zsiz; i = ((xsiz*yzsiz+31)>>3);
1771 vbit = (int *)malloc(i); if (!vbit) { kclose(fil); return(-1); }
1772 memset(vbit,-1,i);
1773
1774 vcolhashsizm1 = 1048576-1;
1775 vcolhashead = (int *)malloc((vcolhashsizm1+1)*sizeof(int)); if (!vcolhashead) { kclose(fil); return(-1); }
1776 memset(vcolhashead,-1,(vcolhashsizm1+1)*sizeof(int));
1777
1778 //Allocate huge buffer and load rest of file into it...
1779 i = kfilelength(fil)-ktell(fil);
1780 vbuf = (unsigned char *)malloc(i); if (!vbuf) { kclose(fil); return(-1); }
1781 kread(fil,vbuf,i);
1782 kclose(fil);
1783
1784 v = vbuf;
1785 for(y=0;y<ysiz;y++)
1786 for(x=0,j=y*zsiz;x<xsiz;x++,j+=yzsiz)
1787 {
1788 z = 0;
1789 while (1)
1790 {
1791 setzrange0(vbit,j+z,j+v[1]);
1792 for(z=v[1];z<=v[2];z++) putvox(x,y,z,(*(int *)&v[(z-v[1]+1)<<2])&0xffffff);
1793 if (!v[0]) break; z = v[2]-v[1]-v[0]+2; v += v[0]*4;
1794 for(z+=v[3];z<v[3];z++) putvox(x,y,z,(*(int *)&v[(z-v[3])<<2])&0xffffff);
1795 }
1796 v += ((((int)v[2])-((int)v[1])+2)<<2);
1797 }
1798 free(vbuf); return(0);
1799 }
1800 #endif
1801
voxfree(voxmodel * m)1802 void voxfree (voxmodel *m)
1803 {
1804 if (!m) return;
1805 if (m->mytex) free(m->mytex);
1806 if (m->quad) free(m->quad);
1807 if (m->texid) free(m->texid);
1808 free(m);
1809 }
1810
voxload(const char * filnam)1811 voxmodel *voxload (const char *filnam)
1812 {
1813 int i, is8bit, ret;
1814 voxmodel *vm;
1815
1816 i = strlen(filnam)-4; if (i < 0) return(0);
1817 if (!Bstrcasecmp(&filnam[i],".vox")) { ret = loadvox(filnam); is8bit = 1; }
1818 else if (!Bstrcasecmp(&filnam[i],".kvx")) { ret = loadkvx(filnam); is8bit = 1; }
1819 else if (!Bstrcasecmp(&filnam[i],".kv6")) { ret = loadkv6(filnam); is8bit = 0; }
1820 //else if (!Bstrcasecmp(&filnam[i],".vxl")) { ret = loadvxl(filnam); is8bit = 0; }
1821 else return(0);
1822 if (ret >= 0) vm = vox2poly(); else vm = 0;
1823 if (vm)
1824 {
1825 vm->mdnum = 1; //VOXel model id
1826 vm->scale = vm->bscale = 1.0;
1827 vm->xsiz = xsiz; vm->ysiz = ysiz; vm->zsiz = zsiz;
1828 vm->xpiv = xpiv; vm->ypiv = ypiv; vm->zpiv = zpiv;
1829 vm->is8bit = is8bit;
1830
1831 vm->texid = (unsigned int *)calloc(MAXPALOOKUPS,sizeof(unsigned int));
1832 if (!vm->texid) { voxfree(vm); vm = 0; }
1833 }
1834 if (shcntmal) { free(shcntmal); shcntmal = 0; }
1835 if (vbit) { free(vbit); vbit = 0; }
1836 if (vcol) { free(vcol); vcol = 0; vnum = 0; vmax = 0; }
1837 if (vcolhashead) { free(vcolhashead); vcolhashead = 0; }
1838 return(vm);
1839 }
1840
1841 static int voxloadbufs(voxmodel *m);
1842
1843 //Draw voxel model as perfect cubes
voxdraw(voxmodel * m,spritetype * tspr,int method)1844 int voxdraw (voxmodel *m, spritetype *tspr, int method)
1845 {
1846 point3d fp, m0, a0;
1847 int i, j, k, *lptr;
1848 float f, g, k0, k1, k2, k3, k4, k5, k6, k7, mat[16], omat[16], pc[4];
1849 struct polymostdrawpolycall draw;
1850
1851 //updateanimation((md2model *)m,tspr);
1852 if ((tspr->cstat&48)==32) return 0;
1853
1854 m0.x = m->scale;
1855 m0.y = m->scale;
1856 m0.z = m->scale;
1857 a0.x = a0.y = 0; a0.z = m->zadd*m->scale;
1858
1859 //if (globalorientation&8) //y-flipping
1860 //{
1861 // m0.z = -m0.z; a0.z = -a0.z;
1862 // //Add height of 1st frame (use same frame to prevent animation bounce)
1863 // a0.z += m->zsiz*m->scale;
1864 //}
1865 //if (globalorientation&4) { m0.y = -m0.y; a0.y = -a0.y; } //x-flipping
1866
1867 f = ((float)tspr->xrepeat)*(256.0/320.0)/64.0*m->bscale;
1868 m0.x *= f; a0.x *= f; f = -f;
1869 m0.y *= f; a0.y *= f;
1870 f = ((float)tspr->yrepeat)/64.0*m->bscale;
1871 m0.z *= f; a0.z *= f;
1872
1873 k0 = tspr->z;
1874 if (globalorientation&128) k0 += (float)((tilesizy[tspr->picnum]*tspr->yrepeat)<<1);
1875
1876 f = (65536.0*512.0)/((float)xdimen*viewingrange);
1877 g = 32.0/((float)xdimen*gxyaspect);
1878 m0.y *= f; a0.y = (((float)(tspr->x-globalposx))/ 1024.0 + a0.y)*f;
1879 m0.x *=-f; a0.x = (((float)(tspr->y-globalposy))/ -1024.0 + a0.x)*-f;
1880 m0.z *= g; a0.z = (((float)(k0 -globalposz))/-16384.0 + a0.z)*g;
1881
1882 k0 = ((float)(tspr->x-globalposx))*f/1024.0;
1883 k1 = ((float)(tspr->y-globalposy))*f/1024.0;
1884 f = gcosang2*gshang;
1885 g = gsinang2*gshang;
1886 k4 = (float)sintable[(tspr->ang+spriteext[tspr->owner].angoff+1024)&2047] / 16384.0;
1887 k5 = (float)sintable[(tspr->ang+spriteext[tspr->owner].angoff+ 512)&2047] / 16384.0;
1888 k2 = k0*(1-k4)+k1*k5;
1889 k3 = k1*(1-k4)-k0*k5;
1890 k6 = f*gstang - gsinang*gctang; k7 = g*gstang + gcosang*gctang;
1891 mat[0] = k4*k6 + k5*k7; mat[4] = gchang*gstang; mat[ 8] = k4*k7 - k5*k6; mat[12] = k2*k6 + k3*k7;
1892 k6 = f*gctang + gsinang*gstang; k7 = g*gctang - gcosang*gstang;
1893 mat[1] = k4*k6 + k5*k7; mat[5] = gchang*gctang; mat[ 9] = k4*k7 - k5*k6; mat[13] = k2*k6 + k3*k7;
1894 k6 = gcosang2*gchang; k7 = gsinang2*gchang;
1895 mat[2] = k4*k6 + k5*k7; mat[6] =-gshang; mat[10] = k4*k7 - k5*k6; mat[14] = k2*k6 + k3*k7;
1896
1897 mat[12] += a0.y*mat[0] + a0.z*mat[4] + a0.x*mat[ 8];
1898 mat[13] += a0.y*mat[1] + a0.z*mat[5] + a0.x*mat[ 9];
1899 mat[14] += a0.y*mat[2] + a0.z*mat[6] + a0.x*mat[10];
1900
1901 //Mirrors
1902 if (grhalfxdown10x < 0) { mat[0] = -mat[0]; mat[4] = -mat[4]; mat[8] = -mat[8]; mat[12] = -mat[12]; }
1903
1904 //------------
1905 //bit 10 is an ugly hack in game.c\animatesprites telling MD2SPRITE
1906 //to use Z-buffer hacks to hide overdraw problems with the shadows
1907 if (tspr->cstat&1024)
1908 {
1909 glfunc.glDepthFunc(GL_LESS); //NEVER,LESS,(,L)EQUAL,GREATER,(NOT,G)EQUAL,ALWAYS
1910 #if (USE_OPENGL == USE_GLES2)
1911 glfunc.glDepthRangef(0.f,0.9999f);
1912 #else
1913 glfunc.glDepthRange(0.0,0.9999);
1914 #endif
1915 }
1916 if ((grhalfxdown10x >= 0) /*^ ((globalorientation&8) != 0) ^ ((globalorientation&4) != 0)*/) glfunc.glFrontFace(GL_CW); else glfunc.glFrontFace(GL_CCW);
1917 glfunc.glEnable(GL_CULL_FACE);
1918 glfunc.glCullFace(GL_BACK);
1919
1920 pc[0] = pc[1] = pc[2] = ((float)(numpalookups-min(max(globalshade+m->shadeoff,0),numpalookups)))/((float)numpalookups);
1921 pc[0] *= (float)hictinting[globalpal].r / 255.0;
1922 pc[1] *= (float)hictinting[globalpal].g / 255.0;
1923 pc[2] *= (float)hictinting[globalpal].b / 255.0;
1924 if (tspr->cstat&2) { if (!(tspr->cstat&512)) pc[3] = 0.66; else pc[3] = 0.33; } else pc[3] = 1.0;
1925 if (tspr->cstat&2) glfunc.glEnable(GL_BLEND); else glfunc.glDisable(GL_BLEND);
1926 //------------
1927
1928 //transform to Build coords
1929 memcpy(omat,mat,sizeof(omat));
1930 f = 1.f/64.f;
1931 g = m0.x*f; mat[0] *= g; mat[1] *= g; mat[2] *= g;
1932 g = m0.y*f; mat[4] = omat[8]*g; mat[5] = omat[9]*g; mat[6] = omat[10]*g;
1933 g =-m0.z*f; mat[8] = omat[4]*g; mat[9] = omat[5]*g; mat[10] = omat[6]*g;
1934 mat[12] -= (m->xpiv*mat[0] + m->ypiv*mat[4] + (m->zpiv+m->zsiz*.5)*mat[ 8]);
1935 mat[13] -= (m->xpiv*mat[1] + m->ypiv*mat[5] + (m->zpiv+m->zsiz*.5)*mat[ 9]);
1936 mat[14] -= (m->xpiv*mat[2] + m->ypiv*mat[6] + (m->zpiv+m->zsiz*.5)*mat[10]);
1937 mat[3] = mat[7] = mat[11] = 0.f; mat[15] = 1.f;
1938
1939 if (!m->texid[globalpal]) {
1940 m->texid[globalpal] = gloadtex(m->mytex,m->mytexx,m->mytexy,m->is8bit,globalpal);
1941 }
1942
1943 draw.texture0 = m->texid[globalpal];
1944 draw.texture1 = 0;
1945 draw.alphacut = 0.32;
1946 draw.colour.r = pc[0];
1947 draw.colour.g = pc[1];
1948 draw.colour.b = pc[2];
1949 draw.colour.a = pc[3];
1950 draw.fogcolour.r = (float)palookupfog[gfogpalnum].r / 63.f;
1951 draw.fogcolour.g = (float)palookupfog[gfogpalnum].g / 63.f;
1952 draw.fogcolour.b = (float)palookupfog[gfogpalnum].b / 63.f;
1953 draw.fogcolour.a = 1.f;
1954 draw.fogdensity = gfogdensity;
1955
1956 if (method & 1) {
1957 draw.projection = &grotatespriteprojmat[0][0];
1958 } else {
1959 draw.projection = &gdrawroomsprojmat[0][0];
1960 }
1961 draw.modelview = mat;
1962
1963 if (!m->vertexbuf || !m->indexbuf) {
1964 voxloadbufs(m);
1965 }
1966 draw.indexcount = m->indexcount;
1967 draw.indexbuffer = m->indexbuf;
1968 draw.elementbuffer = m->vertexbuf;
1969 draw.elementcount = 0;
1970 draw.elementvbo = NULL;
1971 polymost_drawpoly_glcall(GL_TRIANGLES, &draw);
1972
1973 //------------
1974 glfunc.glDisable(GL_CULL_FACE);
1975 glfunc.glFrontFace(GL_CCW);
1976 if (tspr->cstat&1024)
1977 {
1978 glfunc.glDepthFunc(GL_LEQUAL); //NEVER,LESS,(,L)EQUAL,GREATER,(NOT,G)EQUAL,ALWAYS
1979 #if (USE_OPENGL == USE_GLES2)
1980 glfunc.glDepthRangef(0.f,0.99999f);
1981 #else
1982 glfunc.glDepthRange(0.0,0.99999);
1983 #endif
1984 }
1985 return 1;
1986 }
1987
voxloadbufs(voxmodel * m)1988 static int voxloadbufs(voxmodel *m)
1989 {
1990 int i, j, vxi, ixi, xx, yy, zz;
1991 vert_t *vptr;
1992 GLfloat ru, rv, phack[2];
1993 #if (VOXBORDWIDTH == 0)
1994 GLfloat uhack[2], vhack[2];
1995 #endif
1996 int numindexes, numvertexes;
1997 GLushort *indexes;
1998 struct polymostvboitem *vertexes;
1999
2000 ru = 1.f/((GLfloat)m->mytexx);
2001 rv = 1.f/((GLfloat)m->mytexy);
2002 phack[0] = 0; phack[1] = 1.f/256.f;
2003 #if (VOXBORDWIDTH == 0)
2004 uhack[0] = ru*.125; uhack[1] = -uhack[0];
2005 vhack[0] = rv*.125; vhack[1] = -vhack[0];
2006 #endif
2007
2008 numindexes = 6 * m->qcnt;
2009 numvertexes = 4 * m->qcnt;
2010 indexes = (GLushort *)malloc(numindexes * sizeof(GLushort));
2011 vertexes = (struct polymostvboitem *)malloc(numvertexes * sizeof(struct polymostvboitem));
2012
2013 for(i=0,vxi=0,ixi=0;i<m->qcnt;i++)
2014 {
2015 vptr = &m->quad[i].v[0];
2016
2017 xx = vptr[0].x+vptr[2].x;
2018 yy = vptr[0].y+vptr[2].y;
2019 zz = vptr[0].z+vptr[2].z;
2020
2021 indexes[ixi+0] = vxi+0;
2022 indexes[ixi+1] = vxi+1;
2023 indexes[ixi+2] = vxi+2;
2024 indexes[ixi+3] = vxi+0;
2025 indexes[ixi+4] = vxi+2;
2026 indexes[ixi+5] = vxi+3;
2027 ixi += 6;
2028
2029 for(j=0;j<4;j++)
2030 {
2031 #if (VOXBORDWIDTH == 0)
2032 vertexes[vxi+j].t.s = ((GLfloat)vptr[j].u)*ru+uhack[vptr[j].u!=vptr[0].u];
2033 vertexes[vxi+j].t.t = ((GLfloat)vptr[j].v)*rv+vhack[vptr[j].v!=vptr[0].v];
2034 #else
2035 vertexes[vxi+j].t.s = ((GLfloat)vptr[j].u)*ru;
2036 vertexes[vxi+j].t.t = ((GLfloat)vptr[j].v)*rv;
2037 #endif
2038 vertexes[vxi+j].v.x = ((GLfloat)vptr[j].x) - phack[xx>vptr[j].x*2] + phack[xx<vptr[j].x*2];
2039 vertexes[vxi+j].v.y = ((GLfloat)vptr[j].y) - phack[yy>vptr[j].y*2] + phack[yy<vptr[j].y*2];
2040 vertexes[vxi+j].v.z = ((GLfloat)vptr[j].z) - phack[zz>vptr[j].z*2] + phack[zz<vptr[j].z*2];
2041 }
2042 vxi += 4;
2043 }
2044
2045 glfunc.glGenBuffers(1, &m->indexbuf);
2046 glfunc.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->indexbuf);
2047 glfunc.glBufferData(GL_ELEMENT_ARRAY_BUFFER, numindexes * sizeof(GLushort), indexes, GL_STATIC_DRAW);
2048 m->indexcount = numindexes;
2049
2050 glfunc.glGenBuffers(1, &m->vertexbuf);
2051 glfunc.glBindBuffer(GL_ARRAY_BUFFER, m->vertexbuf);
2052 glfunc.glBufferData(GL_ARRAY_BUFFER, numvertexes * sizeof(struct polymostvboitem), vertexes, GL_STATIC_DRAW);
2053
2054 free(indexes);
2055 free(vertexes);
2056
2057 return 0;
2058 }
2059
2060 //---------------------------------------- VOX LIBRARY ENDS ----------------------------------------
2061 //--------------------------------------- MD LIBRARY BEGINS ---------------------------------------
2062
mdload(const char * filnam)2063 mdmodel *mdload (const char *filnam)
2064 {
2065 mdmodel *vm;
2066 int fil;
2067 int i;
2068
2069 vm = (mdmodel*)voxload(filnam); if (vm) return(vm);
2070
2071 fil = kopen4load((char *)filnam,0); if (fil < 0) return(0);
2072 kread(fil,&i,4); klseek(fil,0,SEEK_SET);
2073 switch(B_LITTLE32(i))
2074 {
2075 case 0x32504449: vm = (mdmodel*)md2load(fil,filnam); break; //IDP2
2076 case 0x33504449: vm = (mdmodel*)md3load(fil); break; //IDP3
2077 default: vm = (mdmodel*)0; break;
2078 }
2079 kclose(fil);
2080 return(vm);
2081 }
2082
2083 // method: 0 = drawrooms projection, 1 = rotatesprite projection
mddraw(spritetype * tspr,int method)2084 int mddraw (spritetype *tspr, int method)
2085 {
2086 mdanim_t *anim;
2087 mdmodel *vm;
2088
2089 if (maxmodelverts > allocmodelverts)
2090 {
2091 point3d *vl = (point3d *)realloc(vertlist,sizeof(point3d)*maxmodelverts);
2092 if (!vl) { buildprintf("ERROR: Not enough memory to allocate %d vertices!\n",maxmodelverts); return 0; }
2093 vertlist = vl; allocmodelverts = maxmodelverts;
2094 }
2095 if (maxelementvbo > allocelementvbo)
2096 {
2097 struct polymostvboitem *vbo = (struct polymostvboitem *)realloc(elementvbo, maxelementvbo * sizeof(struct polymostvboitem));
2098 if (!vbo) { buildprintf("ERROR: Not enough memory to allocate %d vertex buffer items!\n",maxelementvbo); return 0; }
2099 elementvbo = vbo; allocelementvbo = maxelementvbo;
2100 }
2101
2102 vm = models[tile2model[tspr->picnum].modelid];
2103 if (vm->mdnum == 1) { return voxdraw((voxmodel *)vm,tspr,method); }
2104 if (vm->mdnum == 2) { return md2draw((md2model *)vm,tspr,method); }
2105 if (vm->mdnum == 3) { return md3draw((md3model *)vm,tspr,method); }
2106 return 0;
2107 }
2108
mdfree(mdmodel * vm)2109 void mdfree (mdmodel *vm)
2110 {
2111 if (vm->mdnum == 1) { voxfree((voxmodel *)vm); return; }
2112 if (vm->mdnum == 2) { md2free((md2model *)vm); return; }
2113 if (vm->mdnum == 3) { md3free((md3model *)vm); return; }
2114 }
2115
2116 //---------------------------------------- MD LIBRARY ENDS ----------------------------------------
2117 #endif //USE_POLYMOST && USE_OPENGL
2118