1 /*
2 Copyright (C) 1997-2001 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 #include "gl_local.h"
23
24 model_t *loadmodel;
25 int modfilelen;
26
27 void Mod_LoadSpriteModel (model_t *mod, void *buffer);
28 void Mod_LoadBrushModel (model_t *mod, void *buffer);
29 void Mod_LoadAliasModel (model_t *mod, void *buffer);
30 model_t *Mod_LoadModel (model_t *mod, qboolean crash);
31
32 byte mod_novis[MAX_MAP_LEAFS/8];
33
34 #define MAX_MOD_KNOWN 512
35 model_t mod_known[MAX_MOD_KNOWN];
36 int mod_numknown;
37
38 // the inline * models from the current map are kept seperate
39 model_t mod_inline[MAX_MOD_KNOWN];
40
41 int registration_sequence;
42
43 typedef struct {
44 char name[MAX_OSPATH];
45 int width;
46 int height;
47 } texSize_t;
48
49 static texSize_t r_texSizes[MAX_IMAGES];
50 static int r_numTexSizes;
51
52 int numentitychars;
53 char map_entitystring[MAX_MAP_ENTSTRING];
54
55 byte *mod_base;
56
57 /*
58 =================
59 Mod_LoadEntityString
60 =================
61 */
Mod_LoadEntityString(lump_t * l)62 void Mod_LoadEntityString (lump_t *l)
63 {
64 numentitychars = l->filelen;
65 if (l->filelen > MAX_MAP_ENTSTRING)
66 Sys_Error ("Map has too large entity lump");
67
68 memcpy (map_entitystring, mod_base + l->fileofs, l->filelen);
69 }
70
CM_EntityString(void)71 char *CM_EntityString (void)
72 {
73 return map_entitystring;
74 }
75
76 /*
77 ================
78 R_ParseLightEntities - BERSERK
79
80 parses light entity string
81 ================
82 */
83
R_ParseLightEntities(void)84 static void R_ParseLightEntities (void)
85 {
86
87 int i;
88 char *entString;
89 char *buf, *tok;
90 char block[2048], *bl;
91 vec3_t origin, color;
92 float intensity;
93
94 //DONT LOAD MAP ETS
95 // return;
96
97 entString = map_entitystring;
98
99 buf = CM_EntityString();
100 while (1){
101 tok = Com_ParseExt(&buf, true);
102 if (!tok[0])
103 break; // End of data
104
105 if (Q_stricmp(tok, "{"))
106 continue; // Should never happen!
107
108 // Parse the text inside brackets
109 block[0] = 0;
110 do {
111 tok = Com_ParseExt(&buf, false);
112 if (!Q_stricmp(tok, "}"))
113 break; // Done
114
115 if (!tok[0]) // Newline
116 Q_strcat(block, "\n", sizeof(block));
117 else { // Token
118 Q_strcat(block, " ", sizeof(block));
119 Q_strcat(block, tok, sizeof(block));
120 }
121 } while (buf);
122
123 // Now look for "classname"
124 tok = strstr(block, "classname");
125 if (!tok)
126 continue; // Not found
127
128 // Skip over "classname" and whitespace
129 tok += strlen("classname");
130 while (*tok && *tok == ' ')
131 tok++;
132
133 // Next token must be "light"
134 if (Q_strnicmp(tok, "light", 5))
135 continue; // Not "light"
136
137 // Finally parse the light entity
138 VectorClear(origin);
139 intensity = 0;
140
141 bl = block;
142 while (1){
143 tok = Com_ParseExt(&bl, true);
144 if (!tok[0])
145 break; // End of data
146
147 if (!Q_stricmp("origin", tok)){
148 for (i = 0; i < 3; i++){
149 tok = Com_ParseExt(&bl, false);
150 origin[i] = atof(tok);
151 }
152 }
153 else if (!Q_stricmp("light", tok) || !Q_stricmp("_light", tok)){
154 tok = Com_ParseExt(&bl, false);
155 intensity = atof(tok);
156 }
157 else
158 Com_SkipRestOfLine(&bl);
159 }
160
161 if (!intensity)
162 intensity = 150;
163
164 // Add it to the list
165 if (r_numWorldLights == MAX_LIGHTS)
166 break;
167
168 VectorCopy(origin, r_worldLights[r_numWorldLights].origin);
169 r_worldLights[r_numWorldLights].intensity = intensity/2;
170 r_worldLights[r_numWorldLights].surf = NULL;
171 r_numWorldLights++;
172 }
173 }
174 void GL_LightmapColor (msurface_t *surf, vec3_t color);
175 //only add one light per light surface
GL_AddSurfaceWorldLight(msurface_t * surf)176 void GL_AddSurfaceWorldLight (msurface_t *surf)
177 {
178 int i, intensity;
179 glpoly_t *poly;
180 vec3_t origin = {0,0,0}, color = {0,0,0};
181
182 if (!(surf->texinfo->flags & SURF_LIGHT))
183 return;
184 if (r_numWorldLights == MAX_LIGHTS)
185 return;
186
187 for (poly=surf->polys, i=0 ; poly ; poly=poly->next, i++)
188 VectorAdd(origin, poly->center, origin);
189
190 VectorScale(origin, 1.0/(float)i, origin);
191 VectorCopy(origin, r_worldLights[r_numWorldLights].origin);
192
193 intensity = surf->texinfo->value/2;
194 if (intensity>200) intensity = 200;
195 r_worldLights[r_numWorldLights].intensity = intensity;
196
197 r_worldLights[r_numWorldLights].surf = surf;
198
199 r_numWorldLights++;
200 }
201
202 /*
203 =================
204 R_GetTexSize
205 =================
206 */
R_GetTexSize(char * name,mtexinfo_t * out)207 static void R_GetTexSize (char *name, mtexinfo_t *out)
208 {
209 int i;
210 char fullname[MAX_QPATH];
211 miptex_t *mt;
212 rscript_t *rs;
213 int *width, *height;
214
215 width = &out->texWidth;
216 height = &out->texHeight;
217
218 // Look in the script file
219 for (i = 0; i < r_numTexSizes; i++)
220 {
221 if (!Q_stricmp(r_texSizes[i].name, name))
222 {
223 *width = r_texSizes[i].width;
224 *height = r_texSizes[i].height;
225 return;
226 }
227 }
228
229
230 out->script = rs = out->script = RS_FindScript(va("textures/%s",name) );
231 if (rs && rs->picsize.enable)
232 {
233 if (r_numTexSizes < MAX_IMAGES)
234 {
235 strcpy(r_texSizes[r_numTexSizes].name, name);
236 r_texSizes[r_numTexSizes].width = LittleLong(rs->picsize.width);
237 r_texSizes[r_numTexSizes].height = LittleLong(rs->picsize.height);
238 r_numTexSizes++;
239 }
240
241 out->texWidth = rs->picsize.width;
242 out->texHeight= rs->picsize.height;
243 }
244
245 // Load it from disk, but also cache the width and height to avoid
246 // reloading it during the map loading process if it's referenced
247 // again later
248 Com_sprintf(fullname, sizeof(fullname), "textures/%s.wal", name);
249 ri.FS_LoadFile(fullname, (void **)&mt);
250 if (mt)
251 {
252 if (r_numTexSizes < MAX_IMAGES)
253 {
254 strcpy(r_texSizes[r_numTexSizes].name, name);
255 r_texSizes[r_numTexSizes].width = LittleLong(mt->width);
256 r_texSizes[r_numTexSizes].height = LittleLong(mt->height);
257 r_numTexSizes++;
258 }
259
260 *width = LittleLong(mt->width);
261 *height = LittleLong(mt->height);
262
263 ri.FS_FreeFile(mt);
264 return;
265 }
266 else
267 {
268 image_t *img = GL_FindImage (va("textures/%s.wal", name), it_wall);
269 if (img)
270 {
271 *width = LittleLong(img->width);
272 *height = LittleLong(img->height);
273 return;
274 }
275 }
276 // This is not the best solution, but what could we do?
277 *width = 64;
278 *height = 64;
279 }
280
281 /*
282 ===============
283 Mod_PointInLeaf
284 ===============
285 */
Mod_PointInLeaf(vec3_t p,model_t * model)286 mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
287 {
288 mnode_t *node;
289 float d;
290 cplane_t *plane;
291
292 if (!model || !model->nodes)
293 ri.Sys_Error (ERR_DROP, "Mod_PointInLeaf: bad model");
294
295 node = model->nodes;
296 while (1)
297 {
298 if (node->contents != -1)
299 return (mleaf_t *)node;
300
301 plane = node->plane;
302
303 d = DotProduct (p,plane->normal) - plane->dist;
304
305 if (d > 0)
306 node = node->children[0];
307 else
308 node = node->children[1];
309 }
310
311 return NULL; // never reached
312 }
313
314
315 /*
316 ===================
317 Mod_DecompressVis
318 ===================
319 */
Mod_DecompressVis(byte * in,model_t * model)320 byte *Mod_DecompressVis (byte *in, model_t *model)
321 {
322 static byte decompressed[MAX_MAP_LEAFS/8];
323 int c;
324 byte *out;
325 int row;
326
327 row = (model->vis->numclusters+7)>>3;
328 out = decompressed;
329
330 if (!in)
331 { // no vis info, so make all visible
332 while (row)
333 {
334 *out++ = 0xff;
335 row--;
336 }
337 return decompressed;
338 }
339
340 do
341 {
342 if (*in)
343 {
344 *out++ = *in++;
345 continue;
346 }
347
348 c = in[1];
349 in += 2;
350 while (c)
351 {
352 *out++ = 0;
353 c--;
354 }
355 } while (out - decompressed < row);
356
357 return decompressed;
358 }
359
360 /*
361 ==============
362 Mod_ClusterPVS
363 ==============
364 */
Mod_ClusterPVS(int cluster,model_t * model)365 byte *Mod_ClusterPVS (int cluster, model_t *model)
366 {
367 if (cluster == -1 || !model->vis)
368 return mod_novis;
369 return Mod_DecompressVis ( (byte *)model->vis + model->vis->bitofs[cluster][DVIS_PVS],
370 model);
371 }
372
373
374 //===============================================================================
375
376 /*
377 ================
378 Mod_Modellist_f
379 ================
380 */
Mod_Modellist_f(void)381 void Mod_Modellist_f (void)
382 {
383 int i;
384 model_t *mod;
385 int total;
386
387 total = 0;
388 ri.Con_Printf (PRINT_ALL,"Loaded models:\n");
389 for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++)
390 {
391 if (!mod->name[0])
392 continue;
393 ri.Con_Printf (PRINT_ALL, "%8i : %s\n",mod->extradatasize, mod->name);
394 total += mod->extradatasize;
395 }
396 ri.Con_Printf (PRINT_ALL, "Total resident: %i\n", total);
397 }
398
399 /*
400 ===============
401 Mod_Init
402 ===============
403 */
Mod_Init(void)404 void Mod_Init (void)
405 {
406 memset (mod_novis, 0xff, sizeof(mod_novis));
407 }
408
409
410
411 /*
412 ==================
413 Mod_ForName
414
415 Loads in a model for the given name
416 ==================
417 */
418
Get_ModelName(struct model_s * mod)419 char *Get_ModelName (struct model_s *mod)
420 {
421 return mod->name;
422 }
423
Mod_ForName(const char * name,qboolean crash)424 model_t *Mod_ForName (const char *name, qboolean crash)
425 {
426 model_t *mod;
427 unsigned *buf;
428 int i;
429
430 if (!name[0])
431 ri.Sys_Error (ERR_DROP, "Mod_ForName: NULL name");
432
433 //
434 // inline models are grabbed only from worldmodel
435 //
436 if (name[0] == '*')
437 {
438 i = atoi(name+1);
439 if (i < 1 || !r_worldmodel || i >= r_worldmodel->numsubmodels)
440 ri.Sys_Error (ERR_DROP, "bad inline model number");
441 return &mod_inline[i];
442 }
443
444 //
445 // search the currently loaded models
446 //
447 for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
448 {
449 if (!mod->name[0])
450 continue;
451 if (!strcmp (mod->name, name) ) {
452 if (mod->type == mod_alias) {
453 // Make sure models scripts are definately reloaded between maps - MrG
454 char rs[MAX_OSPATH];
455 int i = 0;
456 image_t *img;
457
458 img=mod->skins[i];
459 while (img != NULL) {
460 strcpy(rs,mod->skins[i]->name);
461 rs[strlen(rs)-4]=0;
462 mod->script[i] = RS_FindScript(rs);
463 if (mod->script[i])
464 RS_ReadyScript((rscript_t *)mod->script[i]);
465 i++;
466 img=mod->skins[i];
467 }
468 }
469
470 return mod;
471 }
472 }
473
474 //
475 // find a free model slot spot
476 //
477 for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
478 {
479 if (!mod->name[0])
480 break; // free spot
481 }
482 if (i == mod_numknown)
483 {
484 if (mod_numknown == MAX_MOD_KNOWN)
485 ri.Sys_Error (ERR_DROP, "mod_numknown == MAX_MOD_KNOWN");
486 mod_numknown++;
487 }
488 strcpy (mod->name, name);
489
490 //
491 // load the file
492 //
493 modfilelen = ri.FS_LoadFile (mod->name, (void **)&buf);
494 if (!buf)
495 {
496 if (crash)
497 ri.Sys_Error (ERR_DROP, "Mod_NumForName: %s not found", mod->name);
498 memset (mod->name, 0, sizeof(mod->name));
499 return NULL;
500 }
501
502 loadmodel = mod;
503
504 //
505 // fill it in
506 //
507
508
509 // call the apropriate loader
510
511 switch (LittleLong(*(unsigned *)buf))
512 {
513 case IDALIASHEADER:
514 loadmodel->extradata = Hunk_Begin (0x200000);
515 Mod_LoadAliasModel (mod, buf);
516 break;
517
518 case IDSPRITEHEADER:
519 loadmodel->extradata = Hunk_Begin (0x10000);
520 Mod_LoadSpriteModel (mod, buf);
521 break;
522
523 case IDBSPHEADER:
524 loadmodel->extradata = Hunk_Begin (0x1000000);
525 Mod_LoadBrushModel (mod, buf);
526 break;
527
528 default:
529 ri.Sys_Error (ERR_DROP,"Mod_NumForName: unknown fileid for %s", mod->name);
530 break;
531 }
532
533 loadmodel->extradatasize = Hunk_End ();
534
535 ri.FS_FreeFile (buf);
536
537 return mod;
538 }
539
540 /*
541 ===============================================================================
542
543 BRUSHMODEL LOADING
544
545 ===============================================================================
546 */
547
548
549 /*
550 =================
551 Mod_LoadLighting
552 =================
553 */
Mod_LoadLighting(lump_t * l)554 void Mod_LoadLighting (lump_t *l)
555 {
556 if (!l->filelen)
557 {
558 loadmodel->lightdata = NULL;
559 return;
560 }
561 loadmodel->lightdata = Hunk_Alloc ( l->filelen);
562 memcpy (loadmodel->lightdata, mod_base + l->fileofs, l->filelen);
563 }
564
565
566 /*
567 =================
568 Mod_LoadVisibility
569 =================
570 */
Mod_LoadVisibility(lump_t * l)571 void Mod_LoadVisibility (lump_t *l)
572 {
573 int i;
574
575 if (!l->filelen)
576 {
577 loadmodel->vis = NULL;
578 return;
579 }
580 loadmodel->vis = Hunk_Alloc ( l->filelen);
581 memcpy (loadmodel->vis, mod_base + l->fileofs, l->filelen);
582
583 loadmodel->vis->numclusters = LittleLong (loadmodel->vis->numclusters);
584 for (i=0 ; i<loadmodel->vis->numclusters ; i++)
585 {
586 loadmodel->vis->bitofs[i][0] = LittleLong (loadmodel->vis->bitofs[i][0]);
587 loadmodel->vis->bitofs[i][1] = LittleLong (loadmodel->vis->bitofs[i][1]);
588 }
589 }
590
591
592 /*
593 =================
594 Mod_LoadVertexes
595 =================
596 */
Mod_LoadVertexes(lump_t * l)597 void Mod_LoadVertexes (lump_t *l)
598 {
599 dvertex_t *in;
600 mvertex_t *out;
601 int i, count;
602
603 in = (void *)(mod_base + l->fileofs);
604 if (l->filelen % sizeof(*in))
605 ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
606 count = l->filelen / sizeof(*in);
607 out = Hunk_Alloc ( count*sizeof(*out));
608
609 loadmodel->vertexes = out;
610 loadmodel->numvertexes = count;
611
612 for ( i=0 ; i<count ; i++, in++, out++)
613 {
614 out->position[0] = LittleFloat (in->point[0]);
615 out->position[1] = LittleFloat (in->point[1]);
616 out->position[2] = LittleFloat (in->point[2]);
617 }
618 }
619
620 /*
621 =================
622 RadiusFromBounds
623 =================
624 */
RadiusFromBounds(vec3_t mins,vec3_t maxs)625 float RadiusFromBounds (vec3_t mins, vec3_t maxs)
626 {
627 int i;
628 vec3_t corner;
629
630 for (i=0 ; i<3 ; i++)
631 {
632 corner[i] = fabs(mins[i]) > fabs(maxs[i]) ? fabs(mins[i]) : fabs(maxs[i]);
633 }
634
635 return VectorLength (corner);
636 }
637
638
639 /*
640 =================
641 Mod_LoadSubmodels
642 =================
643 */
Mod_LoadSubmodels(lump_t * l)644 void Mod_LoadSubmodels (lump_t *l)
645 {
646 dmodel_t *in;
647 mmodel_t *out;
648 int i, j, count;
649
650 in = (void *)(mod_base + l->fileofs);
651 if (l->filelen % sizeof(*in))
652 ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
653 count = l->filelen / sizeof(*in);
654 out = Hunk_Alloc ( count*sizeof(*out));
655
656 loadmodel->submodels = out;
657 loadmodel->numsubmodels = count;
658
659 for ( i=0 ; i<count ; i++, in++, out++)
660 {
661 for (j=0 ; j<3 ; j++)
662 { // spread the mins / maxs by a pixel
663 out->mins[j] = LittleFloat (in->mins[j]) - 1;
664 out->maxs[j] = LittleFloat (in->maxs[j]) + 1;
665 out->origin[j] = LittleFloat (in->origin[j]);
666 }
667 out->radius = RadiusFromBounds (out->mins, out->maxs);
668 out->headnode = LittleLong (in->headnode);
669 out->firstface = LittleLong (in->firstface);
670 out->numfaces = LittleLong (in->numfaces);
671 }
672 }
673
674 /*
675 =================
676 Mod_LoadEdges
677 =================
678 */
Mod_LoadEdges(lump_t * l)679 void Mod_LoadEdges (lump_t *l)
680 {
681 dedge_t *in;
682 medge_t *out;
683 int i, count;
684
685 in = (void *)(mod_base + l->fileofs);
686 if (l->filelen % sizeof(*in))
687 ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
688 count = l->filelen / sizeof(*in);
689 out = Hunk_Alloc ( (count + 1) * sizeof(*out));
690
691 loadmodel->edges = out;
692 loadmodel->numedges = count;
693
694 for ( i=0 ; i<count ; i++, in++, out++)
695 {
696 out->v[0] = (unsigned short)LittleShort(in->v[0]);
697 out->v[1] = (unsigned short)LittleShort(in->v[1]);
698 }
699 }
700
701 /*
702 =================
703 Mod_LoadTexinfo
704 =================
705 */
Mod_LoadTexinfo(lump_t * l)706 void Mod_LoadTexinfo (lump_t *l)
707 {
708 texinfo_t *in;
709 mtexinfo_t *out, *step;
710 int i, j, count;
711 char name[MAX_QPATH];
712 int next;
713
714 in = (void *)(mod_base + l->fileofs);
715 if (l->filelen % sizeof(*in))
716 ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
717 count = l->filelen / sizeof(*in);
718 out = Hunk_Alloc ( count*sizeof(*out));
719
720 loadmodel->texinfo = out;
721 loadmodel->numtexinfo = count;
722
723 for ( i=0 ; i<count ; i++, in++, out++)
724 {
725 for (j=0 ; j<8 ; j++)
726 out->vecs[0][j] = LittleFloat (in->vecs[0][j]);
727
728 out->flags = LittleLong (in->flags);
729 next = LittleLong (in->nexttexinfo);
730 if (next > 0)
731 out->next = loadmodel->texinfo + next;
732 else
733 out->next = NULL;
734
735 //get light level
736 out->value = in->value;
737 R_GetTexSize(in->texture, out);
738
739 Com_sprintf (name, sizeof(name), "textures/%s.wal", in->texture);
740 if (!(out->image = GL_FindImage (name, it_wall)))
741 {
742 ri.Con_Printf (PRINT_ALL, "Couldn't load %s\n", name);
743 out->image = r_notexture;
744 }
745 }
746
747 // count animation frames
748 for (i=0 ; i<count ; i++)
749 {
750 out = &loadmodel->texinfo[i];
751 out->numframes = 1;
752 for (step = out->next ; step && step != out ; step=step->next)
753 out->numframes++;
754 }
755 }
756
757 /*
758 ================
759 CalcSurfaceExtents
760
761 Fills in s->texturemins[] and s->extents[]
762 ================
763 */
CalcSurfaceExtents(msurface_t * s)764 void CalcSurfaceExtents (msurface_t *s)
765 {
766 float mins[2], maxs[2], val;
767 int i,j, e;
768 mvertex_t *v;
769 mtexinfo_t *tex;
770 int bmins[2], bmaxs[2];
771
772 mins[0] = mins[1] = 999999;
773 maxs[0] = maxs[1] = -99999;
774
775 tex = s->texinfo;
776
777 for (i=0 ; i<s->numedges ; i++)
778 {
779 e = loadmodel->surfedges[s->firstedge+i];
780 if (e >= 0)
781 v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
782 else
783 v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
784
785 for (j=0 ; j<2 ; j++)
786 {
787 val = v->position[0] * tex->vecs[j][0] +
788 v->position[1] * tex->vecs[j][1] +
789 v->position[2] * tex->vecs[j][2] +
790 tex->vecs[j][3];
791 if (val < mins[j])
792 mins[j] = val;
793 if (val > maxs[j])
794 maxs[j] = val;
795 }
796 }
797
798 for (i=0 ; i<2 ; i++)
799 {
800 bmins[i] = floor(mins[i]/16);
801 bmaxs[i] = ceil(maxs[i]/16);
802
803 s->texturemins[i] = bmins[i] * 16;
804 s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
805
806 // if ( !(tex->flags & TEX_SPECIAL) && s->extents[i] > 512 /* 256 */ )
807 // ri.Sys_Error (ERR_DROP, "Bad surface extents");
808 }
809 }
810
811
812 void GL_AddSurfaceWorldLight (msurface_t *surf);
813 void GL_FindPolyCenters (msurface_t *surf);
814 void GL_BuildPolygonFromSurface(msurface_t *fa);
815 void GL_CreateVertexLightmap (msurface_t *surf);
816 void GL_CreateSurfaceLightmap (msurface_t *surf);
817 void GL_EndBuildingLightmaps (void);
818 void GL_BeginBuildingLightmaps (model_t *m);
819
820 /*
821 =================
822 Mod_LoadFaces
823 =================
824 */
825
Mod_LoadFaces(lump_t * l)826 void Mod_LoadFaces (lump_t *l)
827 {
828 dface_t *in;
829 msurface_t *out;
830 int i, j, count, surfnum;
831 int planenum, side;
832 int ti;
833 qboolean lit;
834
835 in = (void *)(mod_base + l->fileofs);
836 if (l->filelen % sizeof(*in))
837 ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
838 count = l->filelen / sizeof(*in);
839 out = Hunk_Alloc ( count*sizeof(*out));
840
841 loadmodel->surfaces = out;
842 loadmodel->numsurfaces = count;
843
844 currentmodel = loadmodel;
845
846 GL_BeginBuildingLightmaps (loadmodel);
847
848 for ( surfnum=0 ; surfnum<count ; surfnum++, in++, out++)
849 {
850 //refresh ent link...
851 out->firstedge = LittleLong(in->firstedge);
852 out->numedges = LittleShort(in->numedges);
853 out->flags = 0;
854 out->polys = NULL;
855
856 planenum = LittleShort(in->planenum);
857 side = LittleShort(in->side);
858 if (side)
859 out->flags |= SURF_PLANEBACK;
860
861 out->plane = loadmodel->planes + planenum;
862
863 ti = LittleShort (in->texinfo);
864 if (ti < 0 || ti >= loadmodel->numtexinfo)
865 ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: bad texinfo number");
866 out->texinfo = loadmodel->texinfo + ti;
867
868 CalcSurfaceExtents (out);
869
870 // lighting info
871
872 for (i=0 ; i<MAXLIGHTMAPS ; i++)
873 out->styles[i] = in->styles[i];
874 i = LittleLong(in->lightofs);
875 if (i == -1)
876 {
877 out->samples = NULL;
878 }
879 else
880 {
881 out->samples = loadmodel->lightdata + i;
882 }
883
884 // set the drawing flags
885
886 if (out->texinfo->flags & SURF_WARP)
887 {
888
889 out->flags |= SURF_DRAWTURB;
890 for (i=0 ; i<2 ; i++)
891 {
892 out->extents[i] = 16384;
893 out->texturemins[i] = -8192;
894 }
895 GL_SubdivideSurface (out); // cut up polygon for warps
896 }
897
898 // create lightmaps and polygons
899 if ( !(out->texinfo->flags & (SURF_SKY|SURF_TRANS33|SURF_TRANS66|SURF_WARP) ) )
900 {
901 GL_CreateSurfaceLightmap (out);
902
903 }
904
905 if (! (out->texinfo->flags & SURF_WARP) )
906 {
907 if(!out->texinfo->script)
908 {
909 GL_BuildPolygonFromSurface(out);
910 }
911 else
912 {
913 rscript_t *rs = (rscript_t *)out->texinfo->script;
914
915 if(rs->subdivide)
916 GL_SubdivideLightmappedSurface(out, rs->subdivide);
917 else
918 {
919 rscript_t *rs = (rscript_t *)out->texinfo->script;
920
921 if (rs->stage->texture != NULL)
922 out->texinfo->image = rs->stage->texture;
923 else if (rs->stage->anim_stage != NULL)
924 out->texinfo->image = rs->stage->anim_stage->texture;
925
926 GL_BuildPolygonFromSurface(out);
927 }
928 }
929 }
930
931 if (out->polys)
932 {
933 GL_CreateVertexLightmap(out);
934 GL_FindPolyCenters(out);
935 }
936
937 GL_AddSurfaceWorldLight(out);
938 }
939
940 GL_EndBuildingLightmaps ();
941 }
942
943
944 /*
945 =================
946 Mod_SetParent
947 =================
948 */
Mod_SetParent(mnode_t * node,mnode_t * parent)949 void Mod_SetParent (mnode_t *node, mnode_t *parent)
950 {
951 node->parent = parent;
952 if (node->contents != -1)
953 return;
954 Mod_SetParent (node->children[0], node);
955 Mod_SetParent (node->children[1], node);
956 }
957
958 /*
959 =================
960 Mod_LoadNodes
961 =================
962 */
Mod_LoadNodes(lump_t * l)963 void Mod_LoadNodes (lump_t *l)
964 {
965 int i, j, count, p;
966 dnode_t *in;
967 mnode_t *out;
968
969 in = (void *)(mod_base + l->fileofs);
970 if (l->filelen % sizeof(*in))
971 ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
972 count = l->filelen / sizeof(*in);
973 out = Hunk_Alloc ( count*sizeof(*out));
974
975 loadmodel->nodes = out;
976 loadmodel->numnodes = count;
977
978 for ( i=0 ; i<count ; i++, in++, out++)
979 {
980 for (j=0 ; j<3 ; j++)
981 {
982 out->minmaxs[j] = LittleShort (in->mins[j]);
983 out->minmaxs[3+j] = LittleShort (in->maxs[j]);
984 }
985
986 p = LittleLong(in->planenum);
987 out->plane = loadmodel->planes + p;
988
989 out->firstsurface = LittleShort (in->firstface);
990 out->numsurfaces = LittleShort (in->numfaces);
991 out->contents = -1; // differentiate from leafs
992
993 for (j=0 ; j<2 ; j++)
994 {
995 p = LittleLong (in->children[j]);
996 if (p >= 0)
997 out->children[j] = loadmodel->nodes + p;
998 else
999 out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p));
1000 }
1001 }
1002
1003 Mod_SetParent (loadmodel->nodes, NULL); // sets nodes and leafs
1004 }
1005
1006 /*
1007 =================
1008 Mod_LoadLeafs
1009 =================
1010 */
Mod_LoadLeafs(lump_t * l)1011 void Mod_LoadLeafs (lump_t *l)
1012 {
1013 dleaf_t *in;
1014 mleaf_t *out;
1015 int i, j, count, p;
1016 glpoly_t *poly;
1017
1018 in = (void *)(mod_base + l->fileofs);
1019 if (l->filelen % sizeof(*in))
1020 ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
1021 count = l->filelen / sizeof(*in);
1022 out = Hunk_Alloc ( count*sizeof(*out));
1023
1024 loadmodel->leafs = out;
1025 loadmodel->numleafs = count;
1026
1027 for ( i=0 ; i<count ; i++, in++, out++)
1028 {
1029 for (j=0 ; j<3 ; j++)
1030 {
1031 out->minmaxs[j] = LittleShort (in->mins[j]);
1032 out->minmaxs[3+j] = LittleShort (in->maxs[j]);
1033 }
1034
1035 p = LittleLong(in->contents);
1036 out->contents = p;
1037
1038 out->cluster = LittleShort(in->cluster);
1039 out->area = LittleShort(in->area);
1040
1041 out->firstmarksurface = loadmodel->marksurfaces +
1042 LittleShort(in->firstleafface);
1043 out->nummarksurfaces = LittleShort(in->numleaffaces);
1044
1045 // gl underwater warp
1046 if (out->contents & MASK_WATER )
1047 {
1048 for (j=0 ; j<out->nummarksurfaces ; j++)
1049 {
1050 out->firstmarksurface[j]->flags |= SURF_UNDERWATER;
1051 for (poly = out->firstmarksurface[j]->polys ; poly ; poly=poly->next)
1052 poly->flags |= SURF_UNDERWATER;
1053 }
1054 }
1055 }
1056 }
1057
1058 /*
1059 =================
1060 Mod_LoadMarksurfaces
1061 =================
1062 */
Mod_LoadMarksurfaces(lump_t * l)1063 void Mod_LoadMarksurfaces (lump_t *l)
1064 {
1065 int i, j, count;
1066 short *in;
1067 msurface_t **out;
1068
1069 in = (void *)(mod_base + l->fileofs);
1070 if (l->filelen % sizeof(*in))
1071 ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
1072 count = l->filelen / sizeof(*in);
1073 out = Hunk_Alloc ( count*sizeof(*out));
1074
1075 loadmodel->marksurfaces = out;
1076 loadmodel->nummarksurfaces = count;
1077
1078 for ( i=0 ; i<count ; i++)
1079 {
1080 j = LittleShort(in[i]);
1081 if (j < 0 || j >= loadmodel->numsurfaces)
1082 ri.Sys_Error (ERR_DROP, "Mod_ParseMarksurfaces: bad surface number");
1083 out[i] = loadmodel->surfaces + j;
1084 }
1085 }
1086
1087 /*
1088 =================
1089 Mod_LoadSurfedges
1090 =================
1091 */
Mod_LoadSurfedges(lump_t * l)1092 void Mod_LoadSurfedges (lump_t *l)
1093 {
1094 int i, count;
1095 int *in, *out;
1096
1097 in = (void *)(mod_base + l->fileofs);
1098 if (l->filelen % sizeof(*in))
1099 ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
1100 count = l->filelen / sizeof(*in);
1101 if (count < 1 || count >= MAX_MAP_SURFEDGES)
1102 ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: bad surfedges count in %s: %i",
1103 loadmodel->name, count);
1104
1105 out = Hunk_Alloc ( count*sizeof(*out));
1106
1107 loadmodel->surfedges = out;
1108 loadmodel->numsurfedges = count;
1109
1110 for ( i=0 ; i<count ; i++)
1111 out[i] = LittleLong (in[i]);
1112 }
1113
1114
1115 /*
1116 =================
1117 Mod_LoadPlanes
1118 =================
1119 */
Mod_LoadPlanes(lump_t * l)1120 void Mod_LoadPlanes (lump_t *l)
1121 {
1122 int i, j;
1123 cplane_t *out;
1124 dplane_t *in;
1125 int count;
1126 int bits;
1127
1128 in = (void *)(mod_base + l->fileofs);
1129 if (l->filelen % sizeof(*in))
1130 ri.Sys_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
1131
1132 count = l->filelen / sizeof(*in);
1133
1134 //original bug
1135 // out = Hunk_Alloc ( count*2*sizeof(*out));
1136 out = Hunk_Alloc ( count*sizeof(*out));
1137
1138 loadmodel->planes = out;
1139 loadmodel->numplanes = count;
1140
1141 for ( i=0 ; i<count ; i++, in++, out++)
1142 {
1143 bits = 0;
1144 for (j=0 ; j<3 ; j++)
1145 {
1146 out->normal[j] = LittleFloat (in->normal[j]);
1147 if (out->normal[j] < 0)
1148 bits |= 1<<j;
1149 }
1150
1151 out->dist = LittleFloat (in->dist);
1152 //out->type = LittleLong (in->type);
1153 out->type = PlaneTypeForNormal(out->normal);
1154 out->signbits = bits;
1155 }
1156 }
1157
1158 /*
1159 =================
1160 Mod_LoadBrushModel
1161 =================
1162 */
1163
Mod_LoadBrushModel(model_t * mod,void * buffer)1164 void Mod_LoadBrushModel (model_t *mod, void *buffer)
1165 {
1166 int i;
1167 dheader_t *header;
1168 mmodel_t *bm;
1169 char rs_name[MAX_OSPATH], tmp[16]; // rscript - MrG
1170
1171 // end
1172 r_numWorldLights = 0;
1173
1174 loadmodel->type = mod_brush;
1175 if (loadmodel != mod_known)
1176 ri.Sys_Error (ERR_DROP, "Loaded a brush model after the world");
1177
1178 header = (dheader_t *)buffer;
1179
1180 i = LittleLong (header->version);
1181 if (i != BSPVERSION)
1182 ri.Sys_Error (ERR_DROP, "Mod_LoadBrushModel: %s has wrong version number (%i should be %i)", mod->name, i, BSPVERSION);
1183
1184 // swap all the lumps
1185 mod_base = (byte *)header;
1186
1187 for (i=0 ; i<sizeof(dheader_t)/4 ; i++)
1188 ((int *)header)[i] = LittleLong ( ((int *)header)[i]);
1189
1190
1191 // rscript - MrG
1192 RS_FreeUnmarked();
1193 strcpy(tmp,loadmodel->name+5);
1194 tmp[strlen(tmp)-4]=0;
1195 Com_sprintf(rs_name,MAX_OSPATH,"scripts/maps/%s.rscript",tmp);
1196 RS_ScanPathForScripts(); // load all found scripts
1197 RS_LoadScript(rs_name);
1198
1199 // load into heap
1200 Mod_LoadEntityString (&header->lumps[LUMP_ENTITIES]);
1201 Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]);
1202 Mod_LoadEdges (&header->lumps[LUMP_EDGES]);
1203 Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]);
1204 Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]);
1205 Mod_LoadPlanes (&header->lumps[LUMP_PLANES]);
1206 Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]);
1207 Mod_LoadFaces (&header->lumps[LUMP_FACES]);
1208 Mod_LoadMarksurfaces (&header->lumps[LUMP_LEAFFACES]);
1209 Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]);
1210 Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]);
1211 Mod_LoadNodes (&header->lumps[LUMP_NODES]);
1212 Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]);
1213 mod->numframes = 2; // regular and alternate animation
1214
1215 RS_ReloadImageScriptLinks();
1216 RS_LoadSpecialScripts();
1217
1218 //
1219 // set up the submodels
1220 //
1221 for (i=0 ; i<mod->numsubmodels ; i++)
1222 {
1223 model_t *starmod;
1224
1225 bm = &mod->submodels[i];
1226 starmod = &mod_inline[i];
1227
1228 *starmod = *loadmodel;
1229
1230 starmod->firstmodelsurface = bm->firstface;
1231 starmod->nummodelsurfaces = bm->numfaces;
1232 starmod->firstnode = bm->headnode;
1233 if (starmod->firstnode >= loadmodel->numnodes)
1234 ri.Sys_Error (ERR_DROP, "Inline model %i has bad firstnode", i);
1235
1236 VectorCopy (bm->maxs, starmod->maxs);
1237 VectorCopy (bm->mins, starmod->mins);
1238 starmod->radius = bm->radius;
1239
1240 if (i == 0)
1241 *loadmodel = *starmod;
1242
1243 starmod->numleafs = bm->visleafs;
1244 }
1245
1246 R_ParseLightEntities();
1247 }
1248
1249 /*
1250 ==============================================================================
1251
1252 ALIAS MODELS
1253
1254 ==============================================================================
1255 */
1256
1257 /*
1258 =================
1259 Mod_LoadAliasModel
1260 =================
1261 */
Mod_LoadAliasModel(model_t * mod,void * buffer)1262 void Mod_LoadAliasModel (model_t *mod, void *buffer)
1263 {
1264 int i, j;
1265 dmdl_t *pinmodel, *pheader;
1266 dstvert_t *pinst, *poutst;
1267 dtriangle_t *pintri, *pouttri;
1268 daliasframe_t *pinframe, *poutframe;
1269 int *pincmd, *poutcmd;
1270 int version;
1271
1272 pinmodel = (dmdl_t *)buffer;
1273
1274 version = LittleLong (pinmodel->version);
1275 if (version != ALIAS_VERSION)
1276 ri.Sys_Error (ERR_DROP, "%s has wrong version number (%i should be %i)",
1277 mod->name, version, ALIAS_VERSION);
1278
1279 pheader = Hunk_Alloc (LittleLong(pinmodel->ofs_end));
1280
1281 // byte swap the header fields and sanity check
1282 for (i=0 ; i<sizeof(dmdl_t)/4 ; i++)
1283 ((int *)pheader)[i] = LittleLong (((int *)buffer)[i]);
1284
1285 if (pheader->skinheight > MAX_LBM_HEIGHT)
1286 ri.Sys_Error (ERR_DROP, "model %s has a skin taller than %d", mod->name,
1287 MAX_LBM_HEIGHT);
1288
1289 if (pheader->num_xyz <= 0)
1290 ri.Sys_Error (ERR_DROP, "model %s has no vertices", mod->name);
1291
1292 if (pheader->num_xyz > MAX_VERTS)
1293 ri.Sys_Error (ERR_DROP, "model %s has too many vertices", mod->name);
1294
1295 if (pheader->num_st <= 0)
1296 ri.Sys_Error (ERR_DROP, "model %s has no st vertices", mod->name);
1297
1298 if (pheader->num_tris <= 0)
1299 ri.Sys_Error (ERR_DROP, "model %s has no triangles", mod->name);
1300
1301 if (pheader->num_frames <= 0)
1302 ri.Sys_Error (ERR_DROP, "model %s has no frames", mod->name);
1303
1304 //
1305 // load base s and t vertices (not used in gl version)
1306 //
1307 pinst = (dstvert_t *) ((byte *)pinmodel + pheader->ofs_st);
1308 poutst = (dstvert_t *) ((byte *)pheader + pheader->ofs_st);
1309
1310 for (i=0 ; i<pheader->num_st ; i++)
1311 {
1312 poutst[i].s = LittleShort (pinst[i].s);
1313 poutst[i].t = LittleShort (pinst[i].t);
1314 }
1315
1316 //
1317 // load triangle lists
1318 //
1319 pintri = (dtriangle_t *) ((byte *)pinmodel + pheader->ofs_tris);
1320 pouttri = (dtriangle_t *) ((byte *)pheader + pheader->ofs_tris);
1321
1322 for (i=0 ; i<pheader->num_tris ; i++)
1323 {
1324 for (j=0 ; j<3 ; j++)
1325 {
1326 pouttri[i].index_xyz[j] = LittleShort (pintri[i].index_xyz[j]);
1327 pouttri[i].index_st[j] = LittleShort (pintri[i].index_st[j]);
1328 }
1329 }
1330
1331 //
1332 // load the frames
1333 //
1334 for (i=0 ; i<pheader->num_frames ; i++)
1335 {
1336 pinframe = (daliasframe_t *) ((byte *)pinmodel
1337 + pheader->ofs_frames + i * pheader->framesize);
1338 poutframe = (daliasframe_t *) ((byte *)pheader
1339 + pheader->ofs_frames + i * pheader->framesize);
1340
1341 memcpy (poutframe->name, pinframe->name, sizeof(poutframe->name));
1342 for (j=0 ; j<3 ; j++)
1343 {
1344 poutframe->scale[j] = LittleFloat (pinframe->scale[j]);
1345 poutframe->translate[j] = LittleFloat (pinframe->translate[j]);
1346 }
1347 // verts are all 8 bit, so no swapping needed
1348 memcpy (poutframe->verts, pinframe->verts,
1349 pheader->num_xyz*sizeof(dtrivertx_t));
1350
1351 }
1352
1353 mod->type = mod_alias;
1354
1355 //
1356 // load the glcmds
1357 //
1358 pincmd = (int *) ((byte *)pinmodel + pheader->ofs_glcmds);
1359 poutcmd = (int *) ((byte *)pheader + pheader->ofs_glcmds);
1360 for (i=0 ; i<pheader->num_glcmds ; i++)
1361 poutcmd[i] = LittleLong (pincmd[i]);
1362
1363
1364 // register all skins
1365 memcpy ((char *)pheader + pheader->ofs_skins, (char *)pinmodel + pheader->ofs_skins,
1366 pheader->num_skins*MAX_SKINNAME);
1367
1368 for (i=0 ; i<pheader->num_skins ; i++)
1369 {
1370 char rs[MAX_OSPATH];
1371 mod->skins[i] = GL_FindImage ((char *)pheader + pheader->ofs_skins + i*MAX_SKINNAME
1372 , it_skin);
1373
1374 strcpy(rs,(char *)pheader + pheader->ofs_skins + i*MAX_SKINNAME);
1375
1376 rs[strlen(rs)-4]=0;
1377 mod->script[i] = RS_FindScript(rs);
1378 if (mod->script[i])
1379 RS_ReadyScript((rscript_t *)mod->script[i]);
1380 }
1381
1382 mod->mins[0] = -32;
1383 mod->mins[1] = -32;
1384 mod->mins[2] = -32;
1385 mod->maxs[0] = 32;
1386 mod->maxs[1] = 32;
1387 mod->maxs[2] = 32;
1388 }
1389
1390 /*
1391 ==============================================================================
1392
1393 SPRITE MODELS
1394
1395 ==============================================================================
1396 */
1397
1398 /*
1399 =================
1400 Mod_LoadSpriteModel
1401 =================
1402 */
Mod_LoadSpriteModel(model_t * mod,void * buffer)1403 void Mod_LoadSpriteModel (model_t *mod, void *buffer)
1404 {
1405 dsprite_t *sprin, *sprout;
1406 int i;
1407
1408 sprin = (dsprite_t *)buffer;
1409 sprout = Hunk_Alloc (modfilelen);
1410
1411 sprout->ident = LittleLong (sprin->ident);
1412 sprout->version = LittleLong (sprin->version);
1413 sprout->numframes = LittleLong (sprin->numframes);
1414
1415 if (sprout->version != SPRITE_VERSION)
1416 ri.Sys_Error (ERR_DROP, "%s has wrong version number (%i should be %i)",
1417 mod->name, sprout->version, SPRITE_VERSION);
1418
1419 if (sprout->numframes > MAX_MD2SKINS)
1420 ri.Sys_Error (ERR_DROP, "%s has too many frames (%i > %i)",
1421 mod->name, sprout->numframes, MAX_MD2SKINS);
1422
1423 // byte swap everything
1424 for (i=0 ; i<sprout->numframes ; i++)
1425 {
1426 sprout->frames[i].width = LittleLong (sprin->frames[i].width);
1427 sprout->frames[i].height = LittleLong (sprin->frames[i].height);
1428 sprout->frames[i].origin_x = LittleLong (sprin->frames[i].origin_x);
1429 sprout->frames[i].origin_y = LittleLong (sprin->frames[i].origin_y);
1430 memcpy (sprout->frames[i].name, sprin->frames[i].name, MAX_SKINNAME);
1431 mod->skins[i] = GL_FindImage (sprout->frames[i].name,
1432 it_sprite);
1433 }
1434
1435 mod->type = mod_sprite;
1436 }
1437
1438 //=============================================================================
1439
1440 /*
1441 @@@@@@@@@@@@@@@@@@@@@
1442 R_BeginRegistration
1443
1444 Specifies the model that will be used as the world
1445 @@@@@@@@@@@@@@@@@@@@@
1446 */
R_BeginRegistration(char * model)1447 void R_BeginRegistration (char *model)
1448 {
1449 char fullname[MAX_QPATH];
1450 cvar_t *flushmap;
1451
1452 registration_sequence++;
1453 r_oldviewcluster = -1; // force markleafs
1454
1455 Com_sprintf (fullname, sizeof(fullname), "maps/%s.bsp", model);
1456
1457 // explicitly free the old map if different
1458 // this guarantees that mod_known[0] is the world map
1459 flushmap = ri.Cvar_Get ("flushmap", "0", 0);
1460 if ( strcmp(mod_known[0].name, fullname) || flushmap->value)
1461 Mod_Free (&mod_known[0]);
1462 r_worldmodel = Mod_ForName(fullname, true);
1463
1464 r_viewcluster = -1;
1465 }
1466
1467
Mod_GetTris(short p1,short p2,dtriangle_t * side1,dmdl_t * hdr)1468 signed int *Mod_GetTris(short p1, short p2, dtriangle_t *side1, dmdl_t *hdr)
1469 {
1470 dtriangle_t *tris = (dtriangle_t *)((unsigned char*)hdr + hdr->ofs_tris);
1471 int i;
1472
1473 for (i=0; i<hdr->num_tris; i++, tris++)
1474 {
1475 if (tris == side1)
1476 continue;
1477
1478 if (tris->index_xyz[0] == p2 && tris->index_xyz[1] == p1)
1479 return i;
1480 if (tris->index_xyz[1] == p2 && tris->index_xyz[2] == p1)
1481 return i;
1482 if (tris->index_xyz[2] == p2 && tris->index_xyz[0] == p1)
1483 return i;
1484 }
1485 tris--;
1486 return -1;
1487 }
1488
Mod_FindSharedEdges(model_t * mod)1489 void Mod_FindSharedEdges(model_t *mod)
1490 {
1491 dmdl_t *hdr = (dmdl_t *)mod->extradata;
1492 dtriangle_t *tris = (dtriangle_t *)((unsigned char*)hdr + hdr->ofs_tris);
1493 int i,o;
1494
1495 mod->noshadow = false;
1496
1497 for (i=0; i<hdr->num_tris; i++)
1498 {
1499 mod->edge_tri[i][0] = Mod_GetTris(tris->index_xyz[0], tris->index_xyz[1], tris, hdr);
1500 mod->edge_tri[i][1] = Mod_GetTris(tris->index_xyz[1], tris->index_xyz[2], tris, hdr);
1501 mod->edge_tri[i][2] = Mod_GetTris(tris->index_xyz[2], tris->index_xyz[0], tris, hdr);
1502
1503 for (o=0; o<3; o++)
1504 if (mod->edge_tri[i][o] == -1)
1505 mod->noshadow = true;
1506
1507 tris++;
1508 }
1509 }
1510
1511 /*
1512 @@@@@@@@@@@@@@@@@@@@@
1513 R_RegisterModel
1514
1515 @@@@@@@@@@@@@@@@@@@@@
1516 */
R_RegisterModel(char * name)1517 struct model_s *R_RegisterModel (char *name)
1518 {
1519 model_t *mod;
1520 int i;
1521 dsprite_t *sprout;
1522 dmdl_t *pheader;
1523
1524 mod = Mod_ForName (name, false);
1525 if (mod)
1526 {
1527 mod->registration_sequence = registration_sequence;
1528
1529 // register any images used by the models
1530 if (mod->type == mod_sprite)
1531 {
1532 sprout = (dsprite_t *)mod->extradata;
1533 for (i=0 ; i<sprout->numframes ; i++)
1534 mod->skins[i] = GL_FindImage (sprout->frames[i].name, it_sprite);
1535 }
1536 else if (mod->type == mod_alias)
1537 {
1538 pheader = (dmdl_t *)mod->extradata;
1539 for (i=0 ; i<pheader->num_skins ; i++)
1540 mod->skins[i] = GL_FindImage ((char *)pheader + pheader->ofs_skins + i*MAX_SKINNAME, it_skin);
1541 //PGM
1542 mod->numframes = pheader->num_frames;
1543 //PGM
1544 Mod_FindSharedEdges(mod);
1545 }
1546 else if (mod->type == mod_brush)
1547 {
1548 for (i=0 ; i<mod->numtexinfo ; i++)
1549 mod->texinfo[i].image->registration_sequence = registration_sequence;
1550 }
1551 }
1552 return mod;
1553 }
1554
1555
1556 /*
1557 @@@@@@@@@@@@@@@@@@@@@
1558 R_EndRegistration
1559
1560 @@@@@@@@@@@@@@@@@@@@@
1561 */
R_EndRegistration(void)1562 void R_EndRegistration (void)
1563 {
1564 int i;
1565 model_t *mod;
1566
1567 for (i=0, mod=mod_known ; i<mod_numknown ; i++, mod++)
1568 {
1569 if (!mod->name[0])
1570 continue;
1571 if (mod->registration_sequence != registration_sequence)
1572 { // don't need this model
1573 Mod_Free (mod);
1574 }
1575 }
1576
1577 RS_UpdateRegistration();
1578 GL_FreeUnusedImages ();
1579 }
1580
1581
1582 //=============================================================================
1583
1584
1585 /*
1586 ================
1587 Mod_Free
1588 ================
1589 */
Mod_Free(model_t * mod)1590 void Mod_Free (model_t *mod)
1591 {
1592 Hunk_Free (mod->extradata);
1593 memset (mod, 0, sizeof(*mod));
1594 }
1595
1596 /*
1597 ================
1598 Mod_FreeAll
1599 ================
1600 */
Mod_FreeAll(void)1601 void Mod_FreeAll (void)
1602 {
1603 int i;
1604
1605 for (i=0 ; i<mod_numknown ; i++)
1606 {
1607 if (mod_known[i].extradatasize)
1608 Mod_Free (&mod_known[i]);
1609 }
1610 }
1611
1612
1613 /*
1614 =======================================================================
1615
1616 FRAGMENT CLIPPING
1617
1618 =======================================================================
1619 */
1620
1621 #define SIDE_FRONT 0
1622 #define SIDE_BACK 1
1623 #define SIDE_ON 2
1624
1625 #define ON_EPSILON 0.1
1626
1627 #define MAX_FRAGMENT_POINTS 128
1628 #define MAX_FRAGMENT_PLANES 6
1629
1630 static qboolean cm_markSplash;
1631
1632 static int cm_numMarkPoints;
1633 static int cm_maxMarkPoints;
1634 static vec3_t *cm_markPoints;
1635 static vec2_t *cm_markTCoords;
1636
1637 msurface_t *cm_markSurface;
1638
1639 static int cm_numMarkFragments;
1640 static int cm_maxMarkFragments;
1641 static markFragment_t *cm_markFragments;
1642
1643 static cplane_t cm_markPlanes[MAX_FRAGMENT_PLANES];
1644
1645 static int cm_markCheckCount;
1646
PlaneTypeForNormal(const vec3_t normal)1647 int PlaneTypeForNormal (const vec3_t normal)
1648 {
1649 if (normal[0] == 1.0)
1650 return 0;//PLANE_X;
1651 if (normal[1] == 1.0)
1652 return 1;//PLANE_Y;
1653 if (normal[2] == 1.0)
1654 return 2;//PLANE_Z;
1655 return 3;//PLANE_NON_AXIAL;
1656 }
1657
1658 /*
1659 =================
1660 Mod_ClipFragment
1661 =================
1662 */
1663
worldVert(int i,msurface_t * surf)1664 float *worldVert (int i, msurface_t *surf)
1665 {
1666 int e = r_worldmodel->surfedges[surf->firstedge + i];
1667 if (e >= 0)
1668 return &r_worldmodel->vertexes[r_worldmodel->edges[e].v[0]].position[0];
1669 else
1670 return &r_worldmodel->vertexes[r_worldmodel->edges[-e].v[1]].position[0];
1671
1672 }
1673
Mod_ClipFragment(int numPoints,vec3_t points,int stage,markFragment_t * mf)1674 static void Mod_ClipFragment (int numPoints, vec3_t points, int stage, markFragment_t *mf)
1675 {
1676 int i;
1677 float *p;
1678 qboolean frontSide;
1679 vec3_t front[MAX_FRAGMENT_POINTS];
1680 int f;
1681 float dist;
1682 float dists[MAX_FRAGMENT_POINTS];
1683 int sides[MAX_FRAGMENT_POINTS];
1684 cplane_t *plane;
1685
1686 if (numPoints > MAX_FRAGMENT_POINTS-2)
1687 ri.Sys_Error(ERR_DROP, "Mod_ClipFragment: MAX_FRAGMENT_POINTS hit");
1688
1689 if (stage == MAX_FRAGMENT_PLANES)
1690 {
1691 // Fully clipped
1692 if (numPoints > 2)
1693 {
1694 mf->numPoints = numPoints;
1695 mf->firstPoint = cm_numMarkPoints;
1696
1697 if (cm_numMarkPoints + numPoints > cm_maxMarkPoints)
1698 numPoints = cm_maxMarkPoints - cm_numMarkPoints;
1699
1700 for (i = 0, p = points; i < numPoints; i++, p += 3)
1701 VectorCopy(p, cm_markPoints[cm_numMarkPoints+i]);
1702
1703 cm_numMarkPoints += numPoints;
1704 }
1705
1706 return;
1707 }
1708
1709 frontSide = false;
1710
1711 plane = &cm_markPlanes[stage];
1712 for (i = 0, p = points; i < numPoints; i++, p += 3)
1713 {
1714 if (plane->type < 3)
1715 dists[i] = dist = p[plane->type] - plane->dist;
1716 else
1717 dists[i] = dist = DotProduct(p, plane->normal) - plane->dist;
1718
1719 if (dist > ON_EPSILON)
1720 {
1721 frontSide = true;
1722 sides[i] = SIDE_FRONT;
1723 }
1724 else if (dist < -ON_EPSILON)
1725 sides[i] = SIDE_BACK;
1726 else
1727 sides[i] = SIDE_ON;
1728 }
1729
1730 if (!frontSide)
1731 return; // Not clipped
1732
1733 // Clip it
1734 dists[i] = dists[0];
1735 sides[i] = sides[0];
1736 VectorCopy(points, (points + (i*3)));
1737
1738 f = 0;
1739
1740 for (i = 0, p = points; i < numPoints; i++, p += 3)
1741 {
1742 switch (sides[i])
1743 {
1744 case SIDE_FRONT:
1745 VectorCopy(p, front[f]);
1746 f++;
1747 break;
1748 case SIDE_BACK:
1749 break;
1750 case SIDE_ON:
1751 VectorCopy(p, front[f]);
1752 f++;
1753 break;
1754 }
1755
1756 if (sides[i] == SIDE_ON || sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
1757 continue;
1758
1759 dist = dists[i] / (dists[i] - dists[i+1]);
1760
1761 front[f][0] = p[0] + (p[3] - p[0]) * dist;
1762 front[f][1] = p[1] + (p[4] - p[1]) * dist;
1763 front[f][2] = p[2] + (p[5] - p[2]) * dist;
1764
1765 f++;
1766 }
1767
1768 // Continue with planes
1769 Mod_ClipFragment(f, front[0], stage+1, mf);
1770 }
1771
1772 /*
1773 =================
1774 Mod_SplashFragTexCoords
1775 =================
1776 */
1777
Mod_SplashFragTexCoords(vec3_t axis[3],const vec3_t origin,float radius,markFragment_t * fr)1778 void Mod_SplashFragTexCoords (vec3_t axis[3], const vec3_t origin, float radius, markFragment_t *fr)
1779 {
1780 int j;
1781 vec3_t v;
1782
1783 if (!cm_markSplash)
1784 return;
1785
1786 for ( j = 0; j < fr->numPoints; j++ )
1787 {
1788 VectorSubtract (cm_markPoints[fr->firstPoint+j], origin, v );
1789 cm_markTCoords[fr->firstPoint+j][0] = DotProduct ( v, axis[0] ) + 0.5f;
1790 cm_markTCoords[fr->firstPoint+j][1] = DotProduct ( v, axis[1] ) + 0.5f;
1791 }
1792 }
1793
1794 /*
1795 =================
1796 Mod_ClipFragmentToSurface
1797 =================
1798 */
Mod_ClipFragmentToSurface(const vec3_t origin,const float radius,msurface_t * surf,const vec3_t normal)1799 static void Mod_ClipFragmentToSurface (const vec3_t origin, const float radius, msurface_t *surf, const vec3_t normal)
1800 {
1801 qboolean planeback = surf->flags & SURF_PLANEBACK;
1802 int i;
1803 float d;
1804 vec3_t points[MAX_FRAGMENT_POINTS];
1805 markFragment_t *mf;
1806 glpoly_t *bp, *p;
1807 vec3_t axis[3];
1808
1809 if (cm_numMarkPoints >= cm_maxMarkPoints || cm_numMarkFragments >= cm_maxMarkFragments)
1810 return; // Already reached the limit somewhere else
1811
1812 if (cm_markSplash)
1813 {
1814 float dot, dist;
1815 int sidebit;
1816
1817 cm_markSurface = surf;
1818
1819 //First check for facing planes
1820 if ( surf->plane->type < 3 )
1821 dist = origin[surf->plane->type] - surf->plane->dist;
1822 else
1823 dist = DotProduct (origin, surf->plane->normal) - surf->plane->dist;
1824 // cull the polygon
1825 if (dist > ON_EPSILON && (surf->flags & SURF_PLANEBACK) )
1826 return;
1827 else if (dist < -ON_EPSILON && !(surf->flags & SURF_PLANEBACK) )
1828 return;
1829
1830 VectorNormalize2 ( cm_markSurface->plane->normal, axis[0] );
1831 PerpendicularVector ( axis[1], axis[0] );
1832 RotatePointAroundVector ( axis[2], axis[0], axis[1], 0 );
1833 CrossProduct ( axis[0], axis[2], axis[1] );
1834
1835 for (i = 0; i < 3; i++)
1836 {
1837 dot = DotProduct(origin, axis[i]);
1838
1839 VectorCopy(axis[i], cm_markPlanes[i*2+0].normal);
1840 cm_markPlanes[i*2+0].dist = dot - radius;
1841 cm_markPlanes[i*2+0].type = PlaneTypeForNormal(cm_markPlanes[i*2+0].normal);
1842
1843 VectorNegate(axis[i], cm_markPlanes[i*2+1].normal);
1844 cm_markPlanes[i*2+1].dist = -dot - radius;
1845 cm_markPlanes[i*2+1].type = PlaneTypeForNormal(cm_markPlanes[i*2+1].normal);
1846 }
1847
1848 VectorScale ( axis[1], 0.5f / radius, axis[0] );
1849 VectorScale ( axis[2], 0.5f / radius, axis[1] );
1850 }
1851 else
1852 {
1853 float d = DotProduct(normal, surf->plane->normal);
1854 if ((planeback && d > -0.75) || (!planeback && d < 0.75))
1855 return; // Greater than X degrees
1856 }
1857
1858 for (i = 2; i < surf->numedges; i++)
1859 {
1860 mf = &cm_markFragments[cm_numMarkFragments];
1861 mf->firstPoint = mf->numPoints = 0;
1862
1863 VectorCopy(worldVert(0, surf), points[0]);
1864 VectorCopy(worldVert(i-1, surf), points[1]);
1865 VectorCopy(worldVert(i, surf), points[2]);
1866
1867 Mod_ClipFragment(3, points[0], 0, mf);
1868
1869 if (mf->numPoints)
1870 {
1871 Mod_SplashFragTexCoords (axis, origin, radius, mf);
1872 cm_numMarkFragments++;
1873
1874 if (cm_numMarkPoints >= cm_maxMarkPoints || cm_numMarkFragments >= cm_maxMarkFragments)
1875 return;
1876 }
1877 }
1878 }
1879
1880 /*
1881 =================
1882 Mod_RecursiveMarkFragments
1883 =================
1884 */
Mod_RecursiveMarkFragments(const vec3_t origin,const vec3_t normal,float radius,mnode_t * node)1885 static void Mod_RecursiveMarkFragments (const vec3_t origin, const vec3_t normal, float radius, mnode_t *node)
1886 {
1887
1888 int i;
1889 float dist;
1890 cplane_t *plane;
1891 msurface_t *surf;
1892
1893 if (cm_numMarkPoints >= cm_maxMarkPoints || cm_numMarkFragments >= cm_maxMarkFragments)
1894 return; // Already reached the limit somewhere else
1895
1896 if (node->contents != -1)
1897 return;
1898
1899 // Find which side of the node we are on
1900 plane = node->plane;
1901 if (plane->type < 3)
1902 dist = origin[plane->type] - plane->dist;
1903 else
1904 dist = DotProduct(origin, plane->normal) - plane->dist;
1905
1906 // Go down the appropriate sides
1907 if (dist > radius)
1908 {
1909 Mod_RecursiveMarkFragments(origin, normal, radius, node->children[0]);
1910 return;
1911 }
1912 if (dist < -radius)
1913 {
1914 Mod_RecursiveMarkFragments(origin, normal, radius, node->children[1]);
1915 return;
1916 }
1917 // Clip against each surface
1918
1919 surf = r_worldmodel->surfaces + node->firstsurface;
1920 for (i=0 ; i<node->numsurfaces ; i++, surf++)
1921 {
1922 if (surf->checkCount == cm_markCheckCount)
1923 continue; // Already checked this surface in another node
1924
1925 if (surf->texinfo->flags & (SURF_SKY|SURF_WARP))//|SURF_TRANS33|SURF_TRANS66|(0x1000000)))
1926 continue;
1927
1928 surf->checkCount = cm_markCheckCount;
1929
1930 Mod_ClipFragmentToSurface(origin, radius, surf, normal);
1931 }
1932 // Recurse down the children
1933 Mod_RecursiveMarkFragments(origin, normal, radius, node->children[0]);
1934 Mod_RecursiveMarkFragments(origin, normal, radius, node->children[1]);
1935 }
1936
1937 /*
1938 =================
1939 Mod_SetTexCoords
1940 =================
1941 */
1942
Mod_SetTexCoords(const vec3_t origin,vec3_t axis[3],float radius)1943 void Mod_SetTexCoords (const vec3_t origin, vec3_t axis[3], float radius)
1944 {
1945 int i, j;
1946 vec3_t newaxis[2], v;
1947 markFragment_t *fr;
1948
1949 VectorScale ( axis[1], 0.5f / radius, newaxis[0] );
1950 VectorScale ( axis[2], 0.5f / radius, newaxis[1] );
1951
1952 for ( i = 0, fr = cm_markFragments; i < cm_numMarkFragments; i++, fr++ )
1953 for ( j = 0; j < fr->numPoints; j++ )
1954 {
1955 VectorSubtract (cm_markPoints[fr->firstPoint+j], origin, v );
1956 cm_markTCoords[fr->firstPoint+j][0] = DotProduct ( v, newaxis[0] ) + 0.5f;
1957 cm_markTCoords[fr->firstPoint+j][1] = DotProduct ( v, newaxis[1] ) + 0.5f;
1958 }
1959 }
1960
1961 /*
1962 =================
1963 Mod_MarkFragments
1964 =================
1965 */
1966
Mod_MarkFragments(const vec3_t origin,vec3_t axis[3],float radius,int maxPoints,vec3_t * points,vec2_t * tcoords,int maxFragments,markFragment_t * fragments)1967 int Mod_MarkFragments (const vec3_t origin, vec3_t axis[3], float radius, int maxPoints, vec3_t *points, vec2_t *tcoords, int maxFragments, markFragment_t *fragments)
1968 {
1969
1970 int i;
1971 float dot;
1972
1973 if (!r_worldmodel || !r_worldmodel->nodes)
1974 return 0; // Map not loaded
1975
1976 cm_markCheckCount++; // For multi-check avoidance
1977
1978 // Initialize fragments
1979 cm_numMarkPoints = 0;
1980 cm_maxMarkPoints = maxPoints;
1981 cm_markPoints = points;
1982
1983 cm_markTCoords = tcoords;
1984
1985 cm_numMarkFragments = 0;
1986 cm_maxMarkFragments = maxFragments;
1987 cm_markFragments = fragments;
1988
1989 if (VectorCompare(axis[0], vec3_origin))
1990 cm_markSplash = true;
1991 else
1992 cm_markSplash = false;
1993
1994 // Calculate clipping planes
1995 if (!cm_markSplash)
1996 for (i = 0; i < 3; i++)
1997 {
1998 dot = DotProduct(origin, axis[i]);
1999
2000 VectorCopy(axis[i], cm_markPlanes[i*2+0].normal);
2001 cm_markPlanes[i*2+0].dist = dot - radius;
2002 cm_markPlanes[i*2+0].type = PlaneTypeForNormal(cm_markPlanes[i*2+0].normal);
2003
2004 VectorNegate(axis[i], cm_markPlanes[i*2+1].normal);
2005 cm_markPlanes[i*2+1].dist = -dot - radius;
2006 cm_markPlanes[i*2+1].type = PlaneTypeForNormal(cm_markPlanes[i*2+1].normal);
2007 }
2008
2009 // Clip against world geometry
2010 Mod_RecursiveMarkFragments(origin, axis[0], radius, r_worldmodel->nodes);
2011
2012 if (!cm_markSplash)
2013 Mod_SetTexCoords(origin, axis, radius);
2014
2015 return cm_numMarkFragments;
2016 }
2017