Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5131 clevermous 1
/*
2
Copyright (C) 1996-1997 Id Software, Inc.
3
 
4
This program is free software; you can redistribute it and/or
5
modify it under the terms of the GNU General Public License
6
as published by the Free Software Foundation; either version 2
7
of the License, or (at your option) any later version.
8
 
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
 
13
See the GNU General Public License for more details.
14
 
15
You should have received a copy of the GNU General Public License
16
along with this program; if not, write to the Free Software
17
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
 
19
*/
20
// models.c -- model loading and caching
21
 
22
// models are the only shared resource between a client and server running
23
// on the same machine.
24
 
25
#include "quakedef.h"
26
 
27
model_t	*loadmodel;
28
char	loadname[32];	// for hunk tags
29
 
30
void Mod_LoadSpriteModel (model_t *mod, void *buffer);
31
void Mod_LoadBrushModel (model_t *mod, void *buffer);
32
void Mod_LoadAliasModel (model_t *mod, void *buffer);
33
model_t *Mod_LoadModel (model_t *mod, qboolean crash);
34
 
35
byte	mod_novis[MAX_MAP_LEAFS/8];
36
 
37
#define	MAX_MOD_KNOWN	512
38
model_t	mod_known[MAX_MOD_KNOWN];
39
int		mod_numknown;
40
 
41
cvar_t gl_subdivide_size = {"gl_subdivide_size", "128", true};
42
 
43
/*
44
===============
45
Mod_Init
46
===============
47
*/
48
void Mod_Init (void)
49
{
50
	Cvar_RegisterVariable (&gl_subdivide_size);
51
	memset (mod_novis, 0xff, sizeof(mod_novis));
52
}
53
 
54
/*
55
===============
56
Mod_Init
57
 
58
Caches the data if needed
59
===============
60
*/
61
void *Mod_Extradata (model_t *mod)
62
{
63
	void	*r;
64
 
65
	r = Cache_Check (&mod->cache);
66
	if (r)
67
		return r;
68
 
69
	Mod_LoadModel (mod, true);
70
 
71
	if (!mod->cache.data)
72
		Sys_Error ("Mod_Extradata: caching failed");
73
	return mod->cache.data;
74
}
75
 
76
/*
77
===============
78
Mod_PointInLeaf
79
===============
80
*/
81
mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
82
{
83
	mnode_t		*node;
84
	float		d;
85
	mplane_t	*plane;
86
 
87
	if (!model || !model->nodes)
88
		Sys_Error ("Mod_PointInLeaf: bad model");
89
 
90
	node = model->nodes;
91
	while (1)
92
	{
93
		if (node->contents < 0)
94
			return (mleaf_t *)node;
95
		plane = node->plane;
96
		d = DotProduct (p,plane->normal) - plane->dist;
97
		if (d > 0)
98
			node = node->children[0];
99
		else
100
			node = node->children[1];
101
	}
102
 
103
	return NULL;	// never reached
104
}
105
 
106
 
107
/*
108
===================
109
Mod_DecompressVis
110
===================
111
*/
112
byte *Mod_DecompressVis (byte *in, model_t *model)
113
{
114
	static byte	decompressed[MAX_MAP_LEAFS/8];
115
	int		c;
116
	byte	*out;
117
	int		row;
118
 
119
	row = (model->numleafs+7)>>3;
120
	out = decompressed;
121
 
122
#if 0
123
	memcpy (out, in, row);
124
#else
125
	if (!in)
126
	{	// no vis info, so make all visible
127
		while (row)
128
		{
129
			*out++ = 0xff;
130
			row--;
131
		}
132
		return decompressed;
133
	}
134
 
135
	do
136
	{
137
		if (*in)
138
		{
139
			*out++ = *in++;
140
			continue;
141
		}
142
 
143
		c = in[1];
144
		in += 2;
145
		while (c)
146
		{
147
			*out++ = 0;
148
			c--;
149
		}
150
	} while (out - decompressed < row);
151
#endif
152
 
153
	return decompressed;
154
}
155
 
156
byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model)
157
{
158
	if (leaf == model->leafs)
159
		return mod_novis;
160
	return Mod_DecompressVis (leaf->compressed_vis, model);
161
}
162
 
163
/*
164
===================
165
Mod_ClearAll
166
===================
167
*/
168
void Mod_ClearAll (void)
169
{
170
	int		i;
171
	model_t	*mod;
172
 
173
	for (i=0 , mod=mod_known ; i
174
		if (mod->type != mod_alias)
175
			mod->needload = true;
176
}
177
 
178
/*
179
==================
180
Mod_FindName
181
 
182
==================
183
*/
184
model_t *Mod_FindName (char *name)
185
{
186
	int		i;
187
	model_t	*mod;
188
 
189
	if (!name[0])
190
		Sys_Error ("Mod_ForName: NULL name");
191
 
192
//
193
// search the currently loaded models
194
//
195
	for (i=0 , mod=mod_known ; i
196
		if (!strcmp (mod->name, name) )
197
			break;
198
 
199
	if (i == mod_numknown)
200
	{
201
		if (mod_numknown == MAX_MOD_KNOWN)
202
			Sys_Error ("mod_numknown == MAX_MOD_KNOWN");
203
		strcpy (mod->name, name);
204
		mod->needload = true;
205
		mod_numknown++;
206
	}
207
 
208
	return mod;
209
}
210
 
211
/*
212
==================
213
Mod_TouchModel
214
 
215
==================
216
*/
217
void Mod_TouchModel (char *name)
218
{
219
	model_t	*mod;
220
 
221
	mod = Mod_FindName (name);
222
 
223
	if (!mod->needload)
224
	{
225
		if (mod->type == mod_alias)
226
			Cache_Check (&mod->cache);
227
	}
228
}
229
 
230
/*
231
==================
232
Mod_LoadModel
233
 
234
Loads a model into the cache
235
==================
236
*/
237
model_t *Mod_LoadModel (model_t *mod, qboolean crash)
238
{
239
	void	*d;
240
	unsigned *buf;
241
	byte	stackbuf[1024];		// avoid dirtying the cache heap
242
 
243
	if (!mod->needload)
244
	{
245
		if (mod->type == mod_alias)
246
		{
247
			d = Cache_Check (&mod->cache);
248
			if (d)
249
				return mod;
250
		}
251
		else
252
			return mod;		// not cached at all
253
	}
254
 
255
//
256
// because the world is so huge, load it one piece at a time
257
//
258
	if (!crash)
259
	{
260
 
261
	}
262
 
263
//
264
// load the file
265
//
266
	buf = (unsigned *)COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf));
267
	if (!buf)
268
	{
269
		if (crash)
270
			Sys_Error ("Mod_NumForName: %s not found", mod->name);
271
		return NULL;
272
	}
273
 
274
//
275
// allocate a new model
276
//
277
	COM_FileBase (mod->name, loadname);
278
 
279
	loadmodel = mod;
280
 
281
//
282
// fill it in
283
//
284
 
285
// call the apropriate loader
286
	mod->needload = false;
287
 
288
	switch (LittleLong(*(unsigned *)buf))
289
	{
290
	case IDPOLYHEADER:
291
		Mod_LoadAliasModel (mod, buf);
292
		break;
293
 
294
	case IDSPRITEHEADER:
295
		Mod_LoadSpriteModel (mod, buf);
296
		break;
297
 
298
	default:
299
		Mod_LoadBrushModel (mod, buf);
300
		break;
301
	}
302
 
303
	return mod;
304
}
305
 
306
/*
307
==================
308
Mod_ForName
309
 
310
Loads in a model for the given name
311
==================
312
*/
313
model_t *Mod_ForName (char *name, qboolean crash)
314
{
315
	model_t	*mod;
316
 
317
	mod = Mod_FindName (name);
318
 
319
	return Mod_LoadModel (mod, crash);
320
}
321
 
322
 
323
/*
324
===============================================================================
325
 
326
					BRUSHMODEL LOADING
327
 
328
===============================================================================
329
*/
330
 
331
byte	*mod_base;
332
 
333
 
334
/*
335
=================
336
Mod_LoadTextures
337
=================
338
*/
339
void Mod_LoadTextures (lump_t *l)
340
{
341
	int		i, j, pixels, num, max, altmax;
342
	miptex_t	*mt;
343
	texture_t	*tx, *tx2;
344
	texture_t	*anims[10];
345
	texture_t	*altanims[10];
346
	dmiptexlump_t *m;
347
 
348
	if (!l->filelen)
349
	{
350
		loadmodel->textures = NULL;
351
		return;
352
	}
353
	m = (dmiptexlump_t *)(mod_base + l->fileofs);
354
 
355
	m->nummiptex = LittleLong (m->nummiptex);
356
 
357
	loadmodel->numtextures = m->nummiptex;
358
	loadmodel->textures = Hunk_AllocName (m->nummiptex * sizeof(*loadmodel->textures) , loadname);
359
 
360
	for (i=0 ; inummiptex ; i++)
361
	{
362
		m->dataofs[i] = LittleLong(m->dataofs[i]);
363
		if (m->dataofs[i] == -1)
364
			continue;
365
		mt = (miptex_t *)((byte *)m + m->dataofs[i]);
366
		mt->width = LittleLong (mt->width);
367
		mt->height = LittleLong (mt->height);
368
		for (j=0 ; j
369
			mt->offsets[j] = LittleLong (mt->offsets[j]);
370
 
371
		if ( (mt->width & 15) || (mt->height & 15) )
372
			Sys_Error ("Texture %s is not 16 aligned", mt->name);
373
		pixels = mt->width*mt->height/64*85;
374
		tx = Hunk_AllocName (sizeof(texture_t) +pixels, loadname );
375
		loadmodel->textures[i] = tx;
376
 
377
		memcpy (tx->name, mt->name, sizeof(tx->name));
378
		tx->width = mt->width;
379
		tx->height = mt->height;
380
		for (j=0 ; j
381
			tx->offsets[j] = mt->offsets[j] + sizeof(texture_t) - sizeof(miptex_t);
382
		// the pixels immediately follow the structures
383
		memcpy ( tx+1, mt+1, pixels);
384
 
385
 
386
		if (!Q_strncmp(mt->name,"sky",3))
387
			R_InitSky (tx);
388
		else
389
		{
390
			texture_mode = GL_LINEAR_MIPMAP_NEAREST; //_LINEAR;
391
			tx->gl_texturenum = GL_LoadTexture (mt->name, tx->width, tx->height, (byte *)(tx+1), true, false);
392
			texture_mode = GL_LINEAR;
393
		}
394
	}
395
 
396
//
397
// sequence the animations
398
//
399
	for (i=0 ; inummiptex ; i++)
400
	{
401
		tx = loadmodel->textures[i];
402
		if (!tx || tx->name[0] != '+')
403
			continue;
404
		if (tx->anim_next)
405
			continue;	// allready sequenced
406
 
407
	// find the number of frames in the animation
408
		memset (anims, 0, sizeof(anims));
409
		memset (altanims, 0, sizeof(altanims));
410
 
411
		max = tx->name[1];
412
		altmax = 0;
413
		if (max >= 'a' && max <= 'z')
414
			max -= 'a' - 'A';
415
		if (max >= '0' && max <= '9')
416
		{
417
			max -= '0';
418
			altmax = 0;
419
			anims[max] = tx;
420
			max++;
421
		}
422
		else if (max >= 'A' && max <= 'J')
423
		{
424
			altmax = max - 'A';
425
			max = 0;
426
			altanims[altmax] = tx;
427
			altmax++;
428
		}
429
		else
430
			Sys_Error ("Bad animating texture %s", tx->name);
431
 
432
		for (j=i+1 ; jnummiptex ; j++)
433
		{
434
			tx2 = loadmodel->textures[j];
435
			if (!tx2 || tx2->name[0] != '+')
436
				continue;
437
			if (strcmp (tx2->name+2, tx->name+2))
438
				continue;
439
 
440
			num = tx2->name[1];
441
			if (num >= 'a' && num <= 'z')
442
				num -= 'a' - 'A';
443
			if (num >= '0' && num <= '9')
444
			{
445
				num -= '0';
446
				anims[num] = tx2;
447
				if (num+1 > max)
448
					max = num + 1;
449
			}
450
			else if (num >= 'A' && num <= 'J')
451
			{
452
				num = num - 'A';
453
				altanims[num] = tx2;
454
				if (num+1 > altmax)
455
					altmax = num+1;
456
			}
457
			else
458
				Sys_Error ("Bad animating texture %s", tx->name);
459
		}
460
 
461
#define	ANIM_CYCLE	2
462
	// link them all together
463
		for (j=0 ; j
464
		{
465
			tx2 = anims[j];
466
			if (!tx2)
467
				Sys_Error ("Missing frame %i of %s",j, tx->name);
468
			tx2->anim_total = max * ANIM_CYCLE;
469
			tx2->anim_min = j * ANIM_CYCLE;
470
			tx2->anim_max = (j+1) * ANIM_CYCLE;
471
			tx2->anim_next = anims[ (j+1)%max ];
472
			if (altmax)
473
				tx2->alternate_anims = altanims[0];
474
		}
475
		for (j=0 ; j
476
		{
477
			tx2 = altanims[j];
478
			if (!tx2)
479
				Sys_Error ("Missing frame %i of %s",j, tx->name);
480
			tx2->anim_total = altmax * ANIM_CYCLE;
481
			tx2->anim_min = j * ANIM_CYCLE;
482
			tx2->anim_max = (j+1) * ANIM_CYCLE;
483
			tx2->anim_next = altanims[ (j+1)%altmax ];
484
			if (max)
485
				tx2->alternate_anims = anims[0];
486
		}
487
	}
488
}
489
 
490
/*
491
=================
492
Mod_LoadLighting
493
=================
494
*/
495
void Mod_LoadLighting (lump_t *l)
496
{
497
	if (!l->filelen)
498
	{
499
		loadmodel->lightdata = NULL;
500
		return;
501
	}
502
	loadmodel->lightdata = Hunk_AllocName ( l->filelen, loadname);
503
	memcpy (loadmodel->lightdata, mod_base + l->fileofs, l->filelen);
504
}
505
 
506
 
507
/*
508
=================
509
Mod_LoadVisibility
510
=================
511
*/
512
void Mod_LoadVisibility (lump_t *l)
513
{
514
	if (!l->filelen)
515
	{
516
		loadmodel->visdata = NULL;
517
		return;
518
	}
519
	loadmodel->visdata = Hunk_AllocName ( l->filelen, loadname);
520
	memcpy (loadmodel->visdata, mod_base + l->fileofs, l->filelen);
521
}
522
 
523
 
524
/*
525
=================
526
Mod_LoadEntities
527
=================
528
*/
529
void Mod_LoadEntities (lump_t *l)
530
{
531
	if (!l->filelen)
532
	{
533
		loadmodel->entities = NULL;
534
		return;
535
	}
536
	loadmodel->entities = Hunk_AllocName ( l->filelen, loadname);
537
	memcpy (loadmodel->entities, mod_base + l->fileofs, l->filelen);
538
}
539
 
540
 
541
/*
542
=================
543
Mod_LoadVertexes
544
=================
545
*/
546
void Mod_LoadVertexes (lump_t *l)
547
{
548
	dvertex_t	*in;
549
	mvertex_t	*out;
550
	int			i, count;
551
 
552
	in = (void *)(mod_base + l->fileofs);
553
	if (l->filelen % sizeof(*in))
554
		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
555
	count = l->filelen / sizeof(*in);
556
	out = Hunk_AllocName ( count*sizeof(*out), loadname);
557
 
558
	loadmodel->vertexes = out;
559
	loadmodel->numvertexes = count;
560
 
561
	for ( i=0 ; i
562
	{
563
		out->position[0] = LittleFloat (in->point[0]);
564
		out->position[1] = LittleFloat (in->point[1]);
565
		out->position[2] = LittleFloat (in->point[2]);
566
	}
567
}
568
 
569
/*
570
=================
571
Mod_LoadSubmodels
572
=================
573
*/
574
void Mod_LoadSubmodels (lump_t *l)
575
{
576
	dmodel_t	*in;
577
	dmodel_t	*out;
578
	int			i, j, count;
579
 
580
	in = (void *)(mod_base + l->fileofs);
581
	if (l->filelen % sizeof(*in))
582
		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
583
	count = l->filelen / sizeof(*in);
584
	out = Hunk_AllocName ( count*sizeof(*out), loadname);
585
 
586
	loadmodel->submodels = out;
587
	loadmodel->numsubmodels = count;
588
 
589
	for ( i=0 ; i
590
	{
591
		for (j=0 ; j<3 ; j++)
592
		{	// spread the mins / maxs by a pixel
593
			out->mins[j] = LittleFloat (in->mins[j]) - 1;
594
			out->maxs[j] = LittleFloat (in->maxs[j]) + 1;
595
			out->origin[j] = LittleFloat (in->origin[j]);
596
		}
597
		for (j=0 ; j
598
			out->headnode[j] = LittleLong (in->headnode[j]);
599
		out->visleafs = LittleLong (in->visleafs);
600
		out->firstface = LittleLong (in->firstface);
601
		out->numfaces = LittleLong (in->numfaces);
602
	}
603
}
604
 
605
/*
606
=================
607
Mod_LoadEdges
608
=================
609
*/
610
void Mod_LoadEdges (lump_t *l)
611
{
612
	dedge_t *in;
613
	medge_t *out;
614
	int 	i, count;
615
 
616
	in = (void *)(mod_base + l->fileofs);
617
	if (l->filelen % sizeof(*in))
618
		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
619
	count = l->filelen / sizeof(*in);
620
	out = Hunk_AllocName ( (count + 1) * sizeof(*out), loadname);
621
 
622
	loadmodel->edges = out;
623
	loadmodel->numedges = count;
624
 
625
	for ( i=0 ; i
626
	{
627
		out->v[0] = (unsigned short)LittleShort(in->v[0]);
628
		out->v[1] = (unsigned short)LittleShort(in->v[1]);
629
	}
630
}
631
 
632
/*
633
=================
634
Mod_LoadTexinfo
635
=================
636
*/
637
void Mod_LoadTexinfo (lump_t *l)
638
{
639
	texinfo_t *in;
640
	mtexinfo_t *out;
641
	int 	i, j, count;
642
	int		miptex;
643
	float	len1, len2;
644
 
645
	in = (void *)(mod_base + l->fileofs);
646
	if (l->filelen % sizeof(*in))
647
		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
648
	count = l->filelen / sizeof(*in);
649
	out = Hunk_AllocName ( count*sizeof(*out), loadname);
650
 
651
	loadmodel->texinfo = out;
652
	loadmodel->numtexinfo = count;
653
 
654
	for ( i=0 ; i
655
	{
656
		for (j=0 ; j<8 ; j++)
657
			out->vecs[0][j] = LittleFloat (in->vecs[0][j]);
658
		len1 = Length (out->vecs[0]);
659
		len2 = Length (out->vecs[1]);
660
		len1 = (len1 + len2)/2;
661
		if (len1 < 0.32)
662
			out->mipadjust = 4;
663
		else if (len1 < 0.49)
664
			out->mipadjust = 3;
665
		else if (len1 < 0.99)
666
			out->mipadjust = 2;
667
		else
668
			out->mipadjust = 1;
669
#if 0
670
		if (len1 + len2 < 0.001)
671
			out->mipadjust = 1;		// don't crash
672
		else
673
			out->mipadjust = 1 / floor( (len1+len2)/2 + 0.1 );
674
#endif
675
 
676
		miptex = LittleLong (in->miptex);
677
		out->flags = LittleLong (in->flags);
678
 
679
		if (!loadmodel->textures)
680
		{
681
			out->texture = r_notexture_mip;	// checkerboard texture
682
			out->flags = 0;
683
		}
684
		else
685
		{
686
			if (miptex >= loadmodel->numtextures)
687
				Sys_Error ("miptex >= loadmodel->numtextures");
688
			out->texture = loadmodel->textures[miptex];
689
			if (!out->texture)
690
			{
691
				out->texture = r_notexture_mip; // texture not found
692
				out->flags = 0;
693
			}
694
		}
695
	}
696
}
697
 
698
/*
699
================
700
CalcSurfaceExtents
701
 
702
Fills in s->texturemins[] and s->extents[]
703
================
704
*/
705
void CalcSurfaceExtents (msurface_t *s)
706
{
707
	float	mins[2], maxs[2], val;
708
	int		i,j, e;
709
	mvertex_t	*v;
710
	mtexinfo_t	*tex;
711
	int		bmins[2], bmaxs[2];
712
 
713
	mins[0] = mins[1] = 999999;
714
	maxs[0] = maxs[1] = -99999;
715
 
716
	tex = s->texinfo;
717
 
718
	for (i=0 ; inumedges ; i++)
719
	{
720
		e = loadmodel->surfedges[s->firstedge+i];
721
		if (e >= 0)
722
			v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
723
		else
724
			v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
725
 
726
		for (j=0 ; j<2 ; j++)
727
		{
728
			val = v->position[0] * tex->vecs[j][0] +
729
				v->position[1] * tex->vecs[j][1] +
730
				v->position[2] * tex->vecs[j][2] +
731
				tex->vecs[j][3];
732
			if (val < mins[j])
733
				mins[j] = val;
734
			if (val > maxs[j])
735
				maxs[j] = val;
736
		}
737
	}
738
 
739
	for (i=0 ; i<2 ; i++)
740
	{
741
		bmins[i] = floor(mins[i]/16);
742
		bmaxs[i] = ceil(maxs[i]/16);
743
 
744
		s->texturemins[i] = bmins[i] * 16;
745
		s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
746
		if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 512 /* 256 */ )
747
			Sys_Error ("Bad surface extents");
748
	}
749
}
750
 
751
 
752
/*
753
=================
754
Mod_LoadFaces
755
=================
756
*/
757
void Mod_LoadFaces (lump_t *l)
758
{
759
	dface_t		*in;
760
	msurface_t 	*out;
761
	int			i, count, surfnum;
762
	int			planenum, side;
763
 
764
	in = (void *)(mod_base + l->fileofs);
765
	if (l->filelen % sizeof(*in))
766
		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
767
	count = l->filelen / sizeof(*in);
768
	out = Hunk_AllocName ( count*sizeof(*out), loadname);
769
 
770
	loadmodel->surfaces = out;
771
	loadmodel->numsurfaces = count;
772
 
773
	for ( surfnum=0 ; surfnum
774
	{
775
		out->firstedge = LittleLong(in->firstedge);
776
		out->numedges = LittleShort(in->numedges);
777
		out->flags = 0;
778
 
779
		planenum = LittleShort(in->planenum);
780
		side = LittleShort(in->side);
781
		if (side)
782
			out->flags |= SURF_PLANEBACK;
783
 
784
		out->plane = loadmodel->planes + planenum;
785
 
786
		out->texinfo = loadmodel->texinfo + LittleShort (in->texinfo);
787
 
788
		CalcSurfaceExtents (out);
789
 
790
	// lighting info
791
 
792
		for (i=0 ; i
793
			out->styles[i] = in->styles[i];
794
		i = LittleLong(in->lightofs);
795
		if (i == -1)
796
			out->samples = NULL;
797
		else
798
			out->samples = loadmodel->lightdata + i;
799
 
800
	// set the drawing flags flag
801
 
802
		if (!Q_strncmp(out->texinfo->texture->name,"sky",3))	// sky
803
		{
804
			out->flags |= (SURF_DRAWSKY | SURF_DRAWTILED);
805
#ifndef QUAKE2
806
			GL_SubdivideSurface (out);	// cut up polygon for warps
807
#endif
808
			continue;
809
		}
810
 
811
		if (!Q_strncmp(out->texinfo->texture->name,"*",1))		// turbulent
812
		{
813
			out->flags |= (SURF_DRAWTURB | SURF_DRAWTILED);
814
			for (i=0 ; i<2 ; i++)
815
			{
816
				out->extents[i] = 16384;
817
				out->texturemins[i] = -8192;
818
			}
819
			GL_SubdivideSurface (out);	// cut up polygon for warps
820
			continue;
821
		}
822
 
823
	}
824
}
825
 
826
 
827
/*
828
=================
829
Mod_SetParent
830
=================
831
*/
832
void Mod_SetParent (mnode_t *node, mnode_t *parent)
833
{
834
	node->parent = parent;
835
	if (node->contents < 0)
836
		return;
837
	Mod_SetParent (node->children[0], node);
838
	Mod_SetParent (node->children[1], node);
839
}
840
 
841
/*
842
=================
843
Mod_LoadNodes
844
=================
845
*/
846
void Mod_LoadNodes (lump_t *l)
847
{
848
	int			i, j, count, p;
849
	dnode_t		*in;
850
	mnode_t 	*out;
851
 
852
	in = (void *)(mod_base + l->fileofs);
853
	if (l->filelen % sizeof(*in))
854
		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
855
	count = l->filelen / sizeof(*in);
856
	out = Hunk_AllocName ( count*sizeof(*out), loadname);
857
 
858
	loadmodel->nodes = out;
859
	loadmodel->numnodes = count;
860
 
861
	for ( i=0 ; i
862
	{
863
		for (j=0 ; j<3 ; j++)
864
		{
865
			out->minmaxs[j] = LittleShort (in->mins[j]);
866
			out->minmaxs[3+j] = LittleShort (in->maxs[j]);
867
		}
868
 
869
		p = LittleLong(in->planenum);
870
		out->plane = loadmodel->planes + p;
871
 
872
		out->firstsurface = LittleShort (in->firstface);
873
		out->numsurfaces = LittleShort (in->numfaces);
874
 
875
		for (j=0 ; j<2 ; j++)
876
		{
877
			p = LittleShort (in->children[j]);
878
			if (p >= 0)
879
				out->children[j] = loadmodel->nodes + p;
880
			else
881
				out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p));
882
		}
883
	}
884
 
885
	Mod_SetParent (loadmodel->nodes, NULL);	// sets nodes and leafs
886
}
887
 
888
/*
889
=================
890
Mod_LoadLeafs
891
=================
892
*/
893
void Mod_LoadLeafs (lump_t *l)
894
{
895
	dleaf_t 	*in;
896
	mleaf_t 	*out;
897
	int			i, j, count, p;
898
 
899
	in = (void *)(mod_base + l->fileofs);
900
	if (l->filelen % sizeof(*in))
901
		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
902
	count = l->filelen / sizeof(*in);
903
	out = Hunk_AllocName ( count*sizeof(*out), loadname);
904
 
905
	loadmodel->leafs = out;
906
	loadmodel->numleafs = count;
907
 
908
	for ( i=0 ; i
909
	{
910
		for (j=0 ; j<3 ; j++)
911
		{
912
			out->minmaxs[j] = LittleShort (in->mins[j]);
913
			out->minmaxs[3+j] = LittleShort (in->maxs[j]);
914
		}
915
 
916
		p = LittleLong(in->contents);
917
		out->contents = p;
918
 
919
		out->firstmarksurface = loadmodel->marksurfaces +
920
			LittleShort(in->firstmarksurface);
921
		out->nummarksurfaces = LittleShort(in->nummarksurfaces);
922
 
923
		p = LittleLong(in->visofs);
924
		if (p == -1)
925
			out->compressed_vis = NULL;
926
		else
927
			out->compressed_vis = loadmodel->visdata + p;
928
		out->efrags = NULL;
929
 
930
		for (j=0 ; j<4 ; j++)
931
			out->ambient_sound_level[j] = in->ambient_level[j];
932
 
933
		// gl underwater warp
934
		if (out->contents != CONTENTS_EMPTY)
935
		{
936
			for (j=0 ; jnummarksurfaces ; j++)
937
				out->firstmarksurface[j]->flags |= SURF_UNDERWATER;
938
		}
939
	}
940
}
941
 
942
/*
943
=================
944
Mod_LoadClipnodes
945
=================
946
*/
947
void Mod_LoadClipnodes (lump_t *l)
948
{
949
	dclipnode_t *in, *out;
950
	int			i, count;
951
	hull_t		*hull;
952
 
953
	in = (void *)(mod_base + l->fileofs);
954
	if (l->filelen % sizeof(*in))
955
		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
956
	count = l->filelen / sizeof(*in);
957
	out = Hunk_AllocName ( count*sizeof(*out), loadname);
958
 
959
	loadmodel->clipnodes = out;
960
	loadmodel->numclipnodes = count;
961
 
962
	hull = &loadmodel->hulls[1];
963
	hull->clipnodes = out;
964
	hull->firstclipnode = 0;
965
	hull->lastclipnode = count-1;
966
	hull->planes = loadmodel->planes;
967
	hull->clip_mins[0] = -16;
968
	hull->clip_mins[1] = -16;
969
	hull->clip_mins[2] = -24;
970
	hull->clip_maxs[0] = 16;
971
	hull->clip_maxs[1] = 16;
972
	hull->clip_maxs[2] = 32;
973
 
974
	hull = &loadmodel->hulls[2];
975
	hull->clipnodes = out;
976
	hull->firstclipnode = 0;
977
	hull->lastclipnode = count-1;
978
	hull->planes = loadmodel->planes;
979
	hull->clip_mins[0] = -32;
980
	hull->clip_mins[1] = -32;
981
	hull->clip_mins[2] = -24;
982
	hull->clip_maxs[0] = 32;
983
	hull->clip_maxs[1] = 32;
984
	hull->clip_maxs[2] = 64;
985
 
986
	for (i=0 ; i
987
	{
988
		out->planenum = LittleLong(in->planenum);
989
		out->children[0] = LittleShort(in->children[0]);
990
		out->children[1] = LittleShort(in->children[1]);
991
	}
992
}
993
 
994
/*
995
=================
996
Mod_MakeHull0
997
 
998
Deplicate the drawing hull structure as a clipping hull
999
=================
1000
*/
1001
void Mod_MakeHull0 (void)
1002
{
1003
	mnode_t		*in, *child;
1004
	dclipnode_t *out;
1005
	int			i, j, count;
1006
	hull_t		*hull;
1007
 
1008
	hull = &loadmodel->hulls[0];
1009
 
1010
	in = loadmodel->nodes;
1011
	count = loadmodel->numnodes;
1012
	out = Hunk_AllocName ( count*sizeof(*out), loadname);
1013
 
1014
	hull->clipnodes = out;
1015
	hull->firstclipnode = 0;
1016
	hull->lastclipnode = count-1;
1017
	hull->planes = loadmodel->planes;
1018
 
1019
	for (i=0 ; i
1020
	{
1021
		out->planenum = in->plane - loadmodel->planes;
1022
		for (j=0 ; j<2 ; j++)
1023
		{
1024
			child = in->children[j];
1025
			if (child->contents < 0)
1026
				out->children[j] = child->contents;
1027
			else
1028
				out->children[j] = child - loadmodel->nodes;
1029
		}
1030
	}
1031
}
1032
 
1033
/*
1034
=================
1035
Mod_LoadMarksurfaces
1036
=================
1037
*/
1038
void Mod_LoadMarksurfaces (lump_t *l)
1039
{
1040
	int		i, j, count;
1041
	short		*in;
1042
	msurface_t **out;
1043
 
1044
	in = (void *)(mod_base + l->fileofs);
1045
	if (l->filelen % sizeof(*in))
1046
		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
1047
	count = l->filelen / sizeof(*in);
1048
	out = Hunk_AllocName ( count*sizeof(*out), loadname);
1049
 
1050
	loadmodel->marksurfaces = out;
1051
	loadmodel->nummarksurfaces = count;
1052
 
1053
	for ( i=0 ; i
1054
	{
1055
		j = LittleShort(in[i]);
1056
		if (j >= loadmodel->numsurfaces)
1057
			Sys_Error ("Mod_ParseMarksurfaces: bad surface number");
1058
		out[i] = loadmodel->surfaces + j;
1059
	}
1060
}
1061
 
1062
/*
1063
=================
1064
Mod_LoadSurfedges
1065
=================
1066
*/
1067
void Mod_LoadSurfedges (lump_t *l)
1068
{
1069
	int		i, count;
1070
	int		*in, *out;
1071
 
1072
	in = (void *)(mod_base + l->fileofs);
1073
	if (l->filelen % sizeof(*in))
1074
		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
1075
	count = l->filelen / sizeof(*in);
1076
	out = Hunk_AllocName ( count*sizeof(*out), loadname);
1077
 
1078
	loadmodel->surfedges = out;
1079
	loadmodel->numsurfedges = count;
1080
 
1081
	for ( i=0 ; i
1082
		out[i] = LittleLong (in[i]);
1083
}
1084
 
1085
 
1086
/*
1087
=================
1088
Mod_LoadPlanes
1089
=================
1090
*/
1091
void Mod_LoadPlanes (lump_t *l)
1092
{
1093
	int			i, j;
1094
	mplane_t	*out;
1095
	dplane_t 	*in;
1096
	int			count;
1097
	int			bits;
1098
 
1099
	in = (void *)(mod_base + l->fileofs);
1100
	if (l->filelen % sizeof(*in))
1101
		Sys_Error ("MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
1102
	count = l->filelen / sizeof(*in);
1103
	out = Hunk_AllocName ( count*2*sizeof(*out), loadname);
1104
 
1105
	loadmodel->planes = out;
1106
	loadmodel->numplanes = count;
1107
 
1108
	for ( i=0 ; i
1109
	{
1110
		bits = 0;
1111
		for (j=0 ; j<3 ; j++)
1112
		{
1113
			out->normal[j] = LittleFloat (in->normal[j]);
1114
			if (out->normal[j] < 0)
1115
				bits |= 1<
1116
		}
1117
 
1118
		out->dist = LittleFloat (in->dist);
1119
		out->type = LittleLong (in->type);
1120
		out->signbits = bits;
1121
	}
1122
}
1123
 
1124
/*
1125
=================
1126
RadiusFromBounds
1127
=================
1128
*/
1129
float RadiusFromBounds (vec3_t mins, vec3_t maxs)
1130
{
1131
	int		i;
1132
	vec3_t	corner;
1133
 
1134
	for (i=0 ; i<3 ; i++)
1135
	{
1136
		corner[i] = fabs(mins[i]) > fabs(maxs[i]) ? fabs(mins[i]) : fabs(maxs[i]);
1137
	}
1138
 
1139
	return Length (corner);
1140
}
1141
 
1142
/*
1143
=================
1144
Mod_LoadBrushModel
1145
=================
1146
*/
1147
void Mod_LoadBrushModel (model_t *mod, void *buffer)
1148
{
1149
	int			i, j;
1150
	dheader_t	*header;
1151
	dmodel_t 	*bm;
1152
 
1153
	loadmodel->type = mod_brush;
1154
 
1155
	header = (dheader_t *)buffer;
1156
 
1157
	i = LittleLong (header->version);
1158
	if (i != BSPVERSION)
1159
		Sys_Error ("Mod_LoadBrushModel: %s has wrong version number (%i should be %i)", mod->name, i, BSPVERSION);
1160
 
1161
// swap all the lumps
1162
	mod_base = (byte *)header;
1163
 
1164
	for (i=0 ; i
1165
		((int *)header)[i] = LittleLong ( ((int *)header)[i]);
1166
 
1167
// load into heap
1168
 
1169
	Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]);
1170
	Mod_LoadEdges (&header->lumps[LUMP_EDGES]);
1171
	Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]);
1172
	Mod_LoadTextures (&header->lumps[LUMP_TEXTURES]);
1173
	Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]);
1174
	Mod_LoadPlanes (&header->lumps[LUMP_PLANES]);
1175
	Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]);
1176
	Mod_LoadFaces (&header->lumps[LUMP_FACES]);
1177
	Mod_LoadMarksurfaces (&header->lumps[LUMP_MARKSURFACES]);
1178
	Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]);
1179
	Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]);
1180
	Mod_LoadNodes (&header->lumps[LUMP_NODES]);
1181
	Mod_LoadClipnodes (&header->lumps[LUMP_CLIPNODES]);
1182
	Mod_LoadEntities (&header->lumps[LUMP_ENTITIES]);
1183
	Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]);
1184
 
1185
	Mod_MakeHull0 ();
1186
 
1187
	mod->numframes = 2;		// regular and alternate animation
1188
 
1189
//
1190
// set up the submodels (FIXME: this is confusing)
1191
//
1192
	for (i=0 ; inumsubmodels ; i++)
1193
	{
1194
		bm = &mod->submodels[i];
1195
 
1196
		mod->hulls[0].firstclipnode = bm->headnode[0];
1197
		for (j=1 ; j
1198
		{
1199
			mod->hulls[j].firstclipnode = bm->headnode[j];
1200
			mod->hulls[j].lastclipnode = mod->numclipnodes-1;
1201
		}
1202
 
1203
		mod->firstmodelsurface = bm->firstface;
1204
		mod->nummodelsurfaces = bm->numfaces;
1205
 
1206
		VectorCopy (bm->maxs, mod->maxs);
1207
		VectorCopy (bm->mins, mod->mins);
1208
 
1209
		mod->radius = RadiusFromBounds (mod->mins, mod->maxs);
1210
 
1211
		mod->numleafs = bm->visleafs;
1212
 
1213
		if (i < mod->numsubmodels-1)
1214
		{	// duplicate the basic information
1215
			char	name[10];
1216
 
1217
			sprintf (name, "*%i", i+1);
1218
			loadmodel = Mod_FindName (name);
1219
			*loadmodel = *mod;
1220
			strcpy (loadmodel->name, name);
1221
			mod = loadmodel;
1222
		}
1223
	}
1224
}
1225
 
1226
/*
1227
==============================================================================
1228
 
1229
ALIAS MODELS
1230
 
1231
==============================================================================
1232
*/
1233
 
1234
aliashdr_t	*pheader;
1235
 
1236
stvert_t	stverts[MAXALIASVERTS];
1237
mtriangle_t	triangles[MAXALIASTRIS];
1238
 
1239
// a pose is a single set of vertexes.  a frame may be
1240
// an animating sequence of poses
1241
trivertx_t	*poseverts[MAXALIASFRAMES];
1242
int			posenum;
1243
 
1244
byte		**player_8bit_texels_tbl;
1245
byte		*player_8bit_texels;
1246
 
1247
/*
1248
=================
1249
Mod_LoadAliasFrame
1250
=================
1251
*/
1252
void * Mod_LoadAliasFrame (void * pin, maliasframedesc_t *frame)
1253
{
1254
	trivertx_t		*pframe, *pinframe;
1255
	int				i, j;
1256
	daliasframe_t	*pdaliasframe;
1257
 
1258
	pdaliasframe = (daliasframe_t *)pin;
1259
 
1260
	strcpy (frame->name, pdaliasframe->name);
1261
	frame->firstpose = posenum;
1262
	frame->numposes = 1;
1263
 
1264
	for (i=0 ; i<3 ; i++)
1265
	{
1266
	// these are byte values, so we don't have to worry about
1267
	// endianness
1268
		frame->bboxmin.v[i] = pdaliasframe->bboxmin.v[i];
1269
		frame->bboxmin.v[i] = pdaliasframe->bboxmax.v[i];
1270
	}
1271
 
1272
	pinframe = (trivertx_t *)(pdaliasframe + 1);
1273
 
1274
	poseverts[posenum] = pinframe;
1275
	posenum++;
1276
 
1277
	pinframe += pheader->numverts;
1278
 
1279
	return (void *)pinframe;
1280
}
1281
 
1282
 
1283
/*
1284
=================
1285
Mod_LoadAliasGroup
1286
=================
1287
*/
1288
void *Mod_LoadAliasGroup (void * pin,  maliasframedesc_t *frame)
1289
{
1290
	daliasgroup_t		*pingroup;
1291
	int					i, numframes;
1292
	daliasinterval_t	*pin_intervals;
1293
	void				*ptemp;
1294
 
1295
	pingroup = (daliasgroup_t *)pin;
1296
 
1297
	numframes = LittleLong (pingroup->numframes);
1298
 
1299
	frame->firstpose = posenum;
1300
	frame->numposes = numframes;
1301
 
1302
	for (i=0 ; i<3 ; i++)
1303
	{
1304
	// these are byte values, so we don't have to worry about endianness
1305
		frame->bboxmin.v[i] = pingroup->bboxmin.v[i];
1306
		frame->bboxmin.v[i] = pingroup->bboxmax.v[i];
1307
	}
1308
 
1309
	pin_intervals = (daliasinterval_t *)(pingroup + 1);
1310
 
1311
	frame->interval = LittleFloat (pin_intervals->interval);
1312
 
1313
	pin_intervals += numframes;
1314
 
1315
	ptemp = (void *)pin_intervals;
1316
 
1317
	for (i=0 ; i
1318
	{
1319
		poseverts[posenum] = (trivertx_t *)((daliasframe_t *)ptemp + 1);
1320
		posenum++;
1321
 
1322
		ptemp = (trivertx_t *)((daliasframe_t *)ptemp + 1) + pheader->numverts;
1323
	}
1324
 
1325
	return ptemp;
1326
}
1327
 
1328
//=========================================================
1329
 
1330
/*
1331
=================
1332
Mod_FloodFillSkin
1333
 
1334
Fill background pixels so mipmapping doesn't have haloes - Ed
1335
=================
1336
*/
1337
 
1338
typedef struct
1339
{
1340
	short		x, y;
1341
} floodfill_t;
1342
 
1343
extern unsigned d_8to24table[];
1344
 
1345
// must be a power of 2
1346
#define FLOODFILL_FIFO_SIZE 0x1000
1347
#define FLOODFILL_FIFO_MASK (FLOODFILL_FIFO_SIZE - 1)
1348
 
1349
#define FLOODFILL_STEP( off, dx, dy ) \
1350
{ \
1351
	if (pos[off] == fillcolor) \
1352
	{ \
1353
		pos[off] = 255; \
1354
		fifo[inpt].x = x + (dx), fifo[inpt].y = y + (dy); \
1355
		inpt = (inpt + 1) & FLOODFILL_FIFO_MASK; \
1356
	} \
1357
	else if (pos[off] != 255) fdc = pos[off]; \
1358
}
1359
 
1360
void Mod_FloodFillSkin( byte *skin, int skinwidth, int skinheight )
1361
{
1362
	byte				fillcolor = *skin; // assume this is the pixel to fill
1363
	floodfill_t			fifo[FLOODFILL_FIFO_SIZE];
1364
	int					inpt = 0, outpt = 0;
1365
	int					filledcolor = -1;
1366
	int					i;
1367
 
1368
	if (filledcolor == -1)
1369
	{
1370
		filledcolor = 0;
1371
		// attempt to find opaque black
1372
		for (i = 0; i < 256; ++i)
1373
			if (d_8to24table[i] == (255 << 0)) // alpha 1.0
1374
			{
1375
				filledcolor = i;
1376
				break;
1377
			}
1378
	}
1379
 
1380
	// can't fill to filled color or to transparent color (used as visited marker)
1381
	if ((fillcolor == filledcolor) || (fillcolor == 255))
1382
	{
1383
		//printf( "not filling skin from %d to %d\n", fillcolor, filledcolor );
1384
		return;
1385
	}
1386
 
1387
	fifo[inpt].x = 0, fifo[inpt].y = 0;
1388
	inpt = (inpt + 1) & FLOODFILL_FIFO_MASK;
1389
 
1390
	while (outpt != inpt)
1391
	{
1392
		int			x = fifo[outpt].x, y = fifo[outpt].y;
1393
		int			fdc = filledcolor;
1394
		byte		*pos = &skin[x + skinwidth * y];
1395
 
1396
		outpt = (outpt + 1) & FLOODFILL_FIFO_MASK;
1397
 
1398
		if (x > 0)				FLOODFILL_STEP( -1, -1, 0 );
1399
		if (x < skinwidth - 1)	FLOODFILL_STEP( 1, 1, 0 );
1400
		if (y > 0)				FLOODFILL_STEP( -skinwidth, 0, -1 );
1401
		if (y < skinheight - 1)	FLOODFILL_STEP( skinwidth, 0, 1 );
1402
		skin[x + skinwidth * y] = fdc;
1403
	}
1404
}
1405
 
1406
/*
1407
===============
1408
Mod_LoadAllSkins
1409
===============
1410
*/
1411
void *Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype)
1412
{
1413
	int		i, j, k;
1414
	char	name[32];
1415
	int		s;
1416
	byte	*copy;
1417
	byte	*skin;
1418
	byte	*texels;
1419
	daliasskingroup_t		*pinskingroup;
1420
	int		groupskins;
1421
	daliasskininterval_t	*pinskinintervals;
1422
 
1423
	skin = (byte *)(pskintype + 1);
1424
 
1425
	if (numskins < 1 || numskins > MAX_SKINS)
1426
		Sys_Error ("Mod_LoadAliasModel: Invalid # of skins: %d\n", numskins);
1427
 
1428
	s = pheader->skinwidth * pheader->skinheight;
1429
 
1430
	for (i=0 ; i
1431
	{
1432
		if (pskintype->type == ALIAS_SKIN_SINGLE) {
1433
			Mod_FloodFillSkin( skin, pheader->skinwidth, pheader->skinheight );
1434
 
1435
			// save 8 bit texels for the player model to remap
1436
	//		if (!strcmp(loadmodel->name,"progs/player.mdl")) {
1437
				texels = Hunk_AllocName(s, loadname);
1438
				pheader->texels[i] = texels - (byte *)pheader;
1439
				memcpy (texels, (byte *)(pskintype + 1), s);
1440
	//		}
1441
			sprintf (name, "%s_%i", loadmodel->name, i);
1442
			pheader->gl_texturenum[i][0] =
1443
			pheader->gl_texturenum[i][1] =
1444
			pheader->gl_texturenum[i][2] =
1445
			pheader->gl_texturenum[i][3] =
1446
				GL_LoadTexture (name, pheader->skinwidth,
1447
				pheader->skinheight, (byte *)(pskintype + 1), true, false);
1448
			pskintype = (daliasskintype_t *)((byte *)(pskintype+1) + s);
1449
		} else {
1450
			// animating skin group.  yuck.
1451
			pskintype++;
1452
			pinskingroup = (daliasskingroup_t *)pskintype;
1453
			groupskins = LittleLong (pinskingroup->numskins);
1454
			pinskinintervals = (daliasskininterval_t *)(pinskingroup + 1);
1455
 
1456
			pskintype = (void *)(pinskinintervals + groupskins);
1457
 
1458
			for (j=0 ; j
1459
			{
1460
					Mod_FloodFillSkin( skin, pheader->skinwidth, pheader->skinheight );
1461
					if (j == 0) {
1462
						texels = Hunk_AllocName(s, loadname);
1463
						pheader->texels[i] = texels - (byte *)pheader;
1464
						memcpy (texels, (byte *)(pskintype), s);
1465
					}
1466
					sprintf (name, "%s_%i_%i", loadmodel->name, i,j);
1467
					pheader->gl_texturenum[i][j&3] =
1468
						GL_LoadTexture (name, pheader->skinwidth,
1469
						pheader->skinheight, (byte *)(pskintype), true, false);
1470
					pskintype = (daliasskintype_t *)((byte *)(pskintype) + s);
1471
			}
1472
			k = j;
1473
			for (/* */; j < 4; j++)
1474
				pheader->gl_texturenum[i][j&3] =
1475
				pheader->gl_texturenum[i][j - k];
1476
		}
1477
	}
1478
 
1479
	return (void *)pskintype;
1480
}
1481
 
1482
//=========================================================================
1483
 
1484
/*
1485
=================
1486
Mod_LoadAliasModel
1487
=================
1488
*/
1489
void Mod_LoadAliasModel (model_t *mod, void *buffer)
1490
{
1491
	int					i, j;
1492
	mdl_t				*pinmodel;
1493
	stvert_t			*pinstverts;
1494
	dtriangle_t			*pintriangles;
1495
	int					version, numframes, numskins;
1496
	int					size;
1497
	daliasframetype_t	*pframetype;
1498
	daliasskintype_t	*pskintype;
1499
	int					start, end, total;
1500
 
1501
	start = Hunk_LowMark ();
1502
 
1503
	pinmodel = (mdl_t *)buffer;
1504
 
1505
	version = LittleLong (pinmodel->version);
1506
	if (version != ALIAS_VERSION)
1507
		Sys_Error ("%s has wrong version number (%i should be %i)",
1508
				 mod->name, version, ALIAS_VERSION);
1509
 
1510
//
1511
// allocate space for a working header, plus all the data except the frames,
1512
// skin and group info
1513
//
1514
	size = 	sizeof (aliashdr_t)
1515
			+ (LittleLong (pinmodel->numframes) - 1) *
1516
			sizeof (pheader->frames[0]);
1517
	pheader = Hunk_AllocName (size, loadname);
1518
 
1519
	mod->flags = LittleLong (pinmodel->flags);
1520
 
1521
//
1522
// endian-adjust and copy the data, starting with the alias model header
1523
//
1524
	pheader->boundingradius = LittleFloat (pinmodel->boundingradius);
1525
	pheader->numskins = LittleLong (pinmodel->numskins);
1526
	pheader->skinwidth = LittleLong (pinmodel->skinwidth);
1527
	pheader->skinheight = LittleLong (pinmodel->skinheight);
1528
 
1529
	if (pheader->skinheight > MAX_LBM_HEIGHT)
1530
		Sys_Error ("model %s has a skin taller than %d", mod->name,
1531
				   MAX_LBM_HEIGHT);
1532
 
1533
	pheader->numverts = LittleLong (pinmodel->numverts);
1534
 
1535
	if (pheader->numverts <= 0)
1536
		Sys_Error ("model %s has no vertices", mod->name);
1537
 
1538
	if (pheader->numverts > MAXALIASVERTS)
1539
		Sys_Error ("model %s has too many vertices", mod->name);
1540
 
1541
	pheader->numtris = LittleLong (pinmodel->numtris);
1542
 
1543
	if (pheader->numtris <= 0)
1544
		Sys_Error ("model %s has no triangles", mod->name);
1545
 
1546
	pheader->numframes = LittleLong (pinmodel->numframes);
1547
	numframes = pheader->numframes;
1548
	if (numframes < 1)
1549
		Sys_Error ("Mod_LoadAliasModel: Invalid # of frames: %d\n", numframes);
1550
 
1551
	pheader->size = LittleFloat (pinmodel->size) * ALIAS_BASE_SIZE_RATIO;
1552
	mod->synctype = LittleLong (pinmodel->synctype);
1553
	mod->numframes = pheader->numframes;
1554
 
1555
	for (i=0 ; i<3 ; i++)
1556
	{
1557
		pheader->scale[i] = LittleFloat (pinmodel->scale[i]);
1558
		pheader->scale_origin[i] = LittleFloat (pinmodel->scale_origin[i]);
1559
		pheader->eyeposition[i] = LittleFloat (pinmodel->eyeposition[i]);
1560
	}
1561
 
1562
 
1563
//
1564
// load the skins
1565
//
1566
	pskintype = (daliasskintype_t *)&pinmodel[1];
1567
	pskintype = Mod_LoadAllSkins (pheader->numskins, pskintype);
1568
 
1569
//
1570
// load base s and t vertices
1571
//
1572
	pinstverts = (stvert_t *)pskintype;
1573
 
1574
	for (i=0 ; inumverts ; i++)
1575
	{
1576
		stverts[i].onseam = LittleLong (pinstverts[i].onseam);
1577
		stverts[i].s = LittleLong (pinstverts[i].s);
1578
		stverts[i].t = LittleLong (pinstverts[i].t);
1579
	}
1580
 
1581
//
1582
// load triangle lists
1583
//
1584
	pintriangles = (dtriangle_t *)&pinstverts[pheader->numverts];
1585
 
1586
	for (i=0 ; inumtris ; i++)
1587
	{
1588
		triangles[i].facesfront = LittleLong (pintriangles[i].facesfront);
1589
 
1590
		for (j=0 ; j<3 ; j++)
1591
		{
1592
			triangles[i].vertindex[j] =
1593
					LittleLong (pintriangles[i].vertindex[j]);
1594
		}
1595
	}
1596
 
1597
//
1598
// load the frames
1599
//
1600
	posenum = 0;
1601
	pframetype = (daliasframetype_t *)&pintriangles[pheader->numtris];
1602
 
1603
	for (i=0 ; i
1604
	{
1605
		aliasframetype_t	frametype;
1606
 
1607
		frametype = LittleLong (pframetype->type);
1608
 
1609
		if (frametype == ALIAS_SINGLE)
1610
		{
1611
			pframetype = (daliasframetype_t *)
1612
					Mod_LoadAliasFrame (pframetype + 1, &pheader->frames[i]);
1613
		}
1614
		else
1615
		{
1616
			pframetype = (daliasframetype_t *)
1617
					Mod_LoadAliasGroup (pframetype + 1, &pheader->frames[i]);
1618
		}
1619
	}
1620
 
1621
	pheader->numposes = posenum;
1622
 
1623
	mod->type = mod_alias;
1624
 
1625
// FIXME: do this right
1626
	mod->mins[0] = mod->mins[1] = mod->mins[2] = -16;
1627
	mod->maxs[0] = mod->maxs[1] = mod->maxs[2] = 16;
1628
 
1629
	//
1630
	// build the draw lists
1631
	//
1632
	GL_MakeAliasModelDisplayLists (mod, pheader);
1633
 
1634
//
1635
// move the complete, relocatable alias model to the cache
1636
//
1637
	end = Hunk_LowMark ();
1638
	total = end - start;
1639
 
1640
	Cache_Alloc (&mod->cache, total, loadname);
1641
	if (!mod->cache.data)
1642
		return;
1643
	memcpy (mod->cache.data, pheader, total);
1644
 
1645
	Hunk_FreeToLowMark (start);
1646
}
1647
 
1648
//=============================================================================
1649
 
1650
/*
1651
=================
1652
Mod_LoadSpriteFrame
1653
=================
1654
*/
1655
void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum)
1656
{
1657
	dspriteframe_t		*pinframe;
1658
	mspriteframe_t		*pspriteframe;
1659
	int					i, width, height, size, origin[2];
1660
	unsigned short		*ppixout;
1661
	byte				*ppixin;
1662
	char				name[64];
1663
 
1664
	pinframe = (dspriteframe_t *)pin;
1665
 
1666
	width = LittleLong (pinframe->width);
1667
	height = LittleLong (pinframe->height);
1668
	size = width * height;
1669
 
1670
	pspriteframe = Hunk_AllocName (sizeof (mspriteframe_t),loadname);
1671
 
1672
	Q_memset (pspriteframe, 0, sizeof (mspriteframe_t));
1673
 
1674
	*ppframe = pspriteframe;
1675
 
1676
	pspriteframe->width = width;
1677
	pspriteframe->height = height;
1678
	origin[0] = LittleLong (pinframe->origin[0]);
1679
	origin[1] = LittleLong (pinframe->origin[1]);
1680
 
1681
	pspriteframe->up = origin[1];
1682
	pspriteframe->down = origin[1] - height;
1683
	pspriteframe->left = origin[0];
1684
	pspriteframe->right = width + origin[0];
1685
 
1686
	sprintf (name, "%s_%i", loadmodel->name, framenum);
1687
	pspriteframe->gl_texturenum = GL_LoadTexture (name, width, height, (byte *)(pinframe + 1), true, true);
1688
 
1689
	return (void *)((byte *)pinframe + sizeof (dspriteframe_t) + size);
1690
}
1691
 
1692
 
1693
/*
1694
=================
1695
Mod_LoadSpriteGroup
1696
=================
1697
*/
1698
void * Mod_LoadSpriteGroup (void * pin, mspriteframe_t **ppframe, int framenum)
1699
{
1700
	dspritegroup_t		*pingroup;
1701
	mspritegroup_t		*pspritegroup;
1702
	int					i, numframes;
1703
	dspriteinterval_t	*pin_intervals;
1704
	float				*poutintervals;
1705
	void				*ptemp;
1706
 
1707
	pingroup = (dspritegroup_t *)pin;
1708
 
1709
	numframes = LittleLong (pingroup->numframes);
1710
 
1711
	pspritegroup = Hunk_AllocName (sizeof (mspritegroup_t) +
1712
				(numframes - 1) * sizeof (pspritegroup->frames[0]), loadname);
1713
 
1714
	pspritegroup->numframes = numframes;
1715
 
1716
	*ppframe = (mspriteframe_t *)pspritegroup;
1717
 
1718
	pin_intervals = (dspriteinterval_t *)(pingroup + 1);
1719
 
1720
	poutintervals = Hunk_AllocName (numframes * sizeof (float), loadname);
1721
 
1722
	pspritegroup->intervals = poutintervals;
1723
 
1724
	for (i=0 ; i
1725
	{
1726
		*poutintervals = LittleFloat (pin_intervals->interval);
1727
		if (*poutintervals <= 0.0)
1728
			Sys_Error ("Mod_LoadSpriteGroup: interval<=0");
1729
 
1730
		poutintervals++;
1731
		pin_intervals++;
1732
	}
1733
 
1734
	ptemp = (void *)pin_intervals;
1735
 
1736
	for (i=0 ; i
1737
	{
1738
		ptemp = Mod_LoadSpriteFrame (ptemp, &pspritegroup->frames[i], framenum * 100 + i);
1739
	}
1740
 
1741
	return ptemp;
1742
}
1743
 
1744
 
1745
/*
1746
=================
1747
Mod_LoadSpriteModel
1748
=================
1749
*/
1750
void Mod_LoadSpriteModel (model_t *mod, void *buffer)
1751
{
1752
	int					i;
1753
	int					version;
1754
	dsprite_t			*pin;
1755
	msprite_t			*psprite;
1756
	int					numframes;
1757
	int					size;
1758
	dspriteframetype_t	*pframetype;
1759
 
1760
	pin = (dsprite_t *)buffer;
1761
 
1762
	version = LittleLong (pin->version);
1763
	if (version != SPRITE_VERSION)
1764
		Sys_Error ("%s has wrong version number "
1765
				 "(%i should be %i)", mod->name, version, SPRITE_VERSION);
1766
 
1767
	numframes = LittleLong (pin->numframes);
1768
 
1769
	size = sizeof (msprite_t) +	(numframes - 1) * sizeof (psprite->frames);
1770
 
1771
	psprite = Hunk_AllocName (size, loadname);
1772
 
1773
	mod->cache.data = psprite;
1774
 
1775
	psprite->type = LittleLong (pin->type);
1776
	psprite->maxwidth = LittleLong (pin->width);
1777
	psprite->maxheight = LittleLong (pin->height);
1778
	psprite->beamlength = LittleFloat (pin->beamlength);
1779
	mod->synctype = LittleLong (pin->synctype);
1780
	psprite->numframes = numframes;
1781
 
1782
	mod->mins[0] = mod->mins[1] = -psprite->maxwidth/2;
1783
	mod->maxs[0] = mod->maxs[1] = psprite->maxwidth/2;
1784
	mod->mins[2] = -psprite->maxheight/2;
1785
	mod->maxs[2] = psprite->maxheight/2;
1786
 
1787
//
1788
// load the frames
1789
//
1790
	if (numframes < 1)
1791
		Sys_Error ("Mod_LoadSpriteModel: Invalid # of frames: %d\n", numframes);
1792
 
1793
	mod->numframes = numframes;
1794
 
1795
	pframetype = (dspriteframetype_t *)(pin + 1);
1796
 
1797
	for (i=0 ; i
1798
	{
1799
		spriteframetype_t	frametype;
1800
 
1801
		frametype = LittleLong (pframetype->type);
1802
		psprite->frames[i].type = frametype;
1803
 
1804
		if (frametype == SPR_SINGLE)
1805
		{
1806
			pframetype = (dspriteframetype_t *)
1807
					Mod_LoadSpriteFrame (pframetype + 1,
1808
										 &psprite->frames[i].frameptr, i);
1809
		}
1810
		else
1811
		{
1812
			pframetype = (dspriteframetype_t *)
1813
					Mod_LoadSpriteGroup (pframetype + 1,
1814
										 &psprite->frames[i].frameptr, i);
1815
		}
1816
	}
1817
 
1818
	mod->type = mod_sprite;
1819
}
1820
 
1821
//=============================================================================
1822
 
1823
/*
1824
================
1825
Mod_Print
1826
================
1827
*/
1828
void Mod_Print (void)
1829
{
1830
	int		i;
1831
	model_t	*mod;
1832
 
1833
	Con_Printf ("Cached models:\n");
1834
	for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++)
1835
	{
1836
		Con_Printf ("%8p : %s\n",mod->cache.data, mod->name);
1837
	}
1838
}
1839
 
1840