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