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