]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - tools/quake2/q2map/patches.c
my own uncrustify run
[xonotic/netradiant.git] / tools / quake2 / q2map / patches.c
1 /*
2    Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3    For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5    This file is part of GtkRadiant.
6
7    GtkRadiant is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    GtkRadiant is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with GtkRadiant; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 #include "qrad.h"
23
24 vec3_t texture_reflectivity[MAX_MAP_TEXINFO];
25
26 /*
27    ===================================================================
28
29    TEXTURE LIGHT VALUES
30
31    ===================================================================
32  */
33
34 /*
35    ======================
36    CalcTextureReflectivity_Quake2
37    ======================
38  */
39 void CalcTextureReflectivity_Quake2( void ){
40         int i;
41         int j, k, texels;
42         int color[3];
43         int texel;
44         byte            *palette;
45         char path[1024];
46         float r, scale;
47         miptex_t        *mt;
48
49         sprintf( path, "%spics/colormap.pcx", gamedir );
50
51         // get the game palette
52         Load256Image( path, NULL, &palette, NULL, NULL );
53
54         // allways set index 0 even if no textures
55         texture_reflectivity[0][0] = 0.5;
56         texture_reflectivity[0][1] = 0.5;
57         texture_reflectivity[0][2] = 0.5;
58
59         for ( i = 0 ; i < numtexinfo ; i++ )
60         {
61                 // see if an earlier texinfo allready got the value
62                 for ( j = 0 ; j < i ; j++ )
63                 {
64                         if ( !strcmp( texinfo[i].texture, texinfo[j].texture ) ) {
65                                 VectorCopy( texture_reflectivity[j], texture_reflectivity[i] );
66                                 break;
67                         }
68                 }
69                 if ( j != i ) {
70                         continue;
71                 }
72
73                 // load the wal file
74                 sprintf( path, "%stextures/%s.wal", gamedir, texinfo[i].texture );
75                 if ( TryLoadFile( path, (void **)&mt ) == -1 ) {
76                         Sys_Printf( "Couldn't load %s\n", path );
77                         texture_reflectivity[i][0] = 0.5;
78                         texture_reflectivity[i][1] = 0.5;
79                         texture_reflectivity[i][2] = 0.5;
80                         continue;
81                 }
82                 texels = LittleLong( mt->width ) * LittleLong( mt->height );
83                 color[0] = color[1] = color[2] = 0;
84
85                 for ( j = 0 ; j < texels ; j++ )
86                 {
87                         texel = ( (byte *)mt )[LittleLong( mt->offsets[0] ) + j];
88                         for ( k = 0 ; k < 3 ; k++ )
89                                 color[k] += palette[texel * 3 + k];
90                 }
91
92                 for ( j = 0 ; j < 3 ; j++ )
93                 {
94                         r = color[j] / texels / 255.0;
95                         texture_reflectivity[i][j] = r;
96                 }
97                 // scale the reflectivity up, because the textures are
98                 // so dim
99                 scale = ColorNormalize( texture_reflectivity[i],
100                                                                 texture_reflectivity[i] );
101                 if ( scale < 0.5 ) {
102                         scale *= 2;
103                         VectorScale( texture_reflectivity[i], scale, texture_reflectivity[i] );
104                 }
105 #if 0
106                 texture_reflectivity[i][0] = 0.5;
107                 texture_reflectivity[i][1] = 0.5;
108                 texture_reflectivity[i][2] = 0.5;
109 #endif
110         }
111 }
112
113 /*
114    ======================
115    CalcTextureReflectivity_Heretic2
116    ======================
117  */
118 void CalcTextureReflectivity_Heretic2( void ){
119         int i;
120         int j, texels;
121         int color[3];
122         int texel;
123         char path[1024];
124         float r;
125         miptex_m8_t     *mt;
126         miptex_m32_t        *mt32;
127         byte            *pos;
128
129
130         // allways set index 0 even if no textures
131         texture_reflectivity[0][0] = 0.5;
132         texture_reflectivity[0][1] = 0.5;
133         texture_reflectivity[0][2] = 0.5;
134
135         for ( i = 0 ; i < numtexinfo ; i++ )
136         {
137                 // see if an earlier texinfo allready got the value
138                 for ( j = 0 ; j < i ; j++ )
139                 {
140                         if ( !strcmp( texinfo[i].texture, texinfo[j].texture ) ) {
141                                 VectorCopy( texture_reflectivity[j], texture_reflectivity[i] );
142                                 break;
143                         }
144                 }
145                 if ( j != i ) {
146                         continue;
147                 }
148
149                 // load the wal file
150
151                 sprintf( path, "%stextures/%s.m32", gamedir, texinfo[i].texture );
152                 if ( TryLoadFile( path, (void **)&mt32 ) == -1 ) {
153                         sprintf( path, "%stextures/%s.m8", gamedir, texinfo[i].texture );
154                         if ( TryLoadFile( path, (void **)&mt ) == -1 ) {
155                                 Sys_Printf( "Couldn't load %s\n", path );
156                                 texture_reflectivity[i][0] = 0.5;
157                                 texture_reflectivity[i][1] = 0.5;
158                                 texture_reflectivity[i][2] = 0.5;
159                                 continue;
160                         }
161                         texels = LittleLong( mt->width[0] ) * LittleLong( mt->height[0] );
162                         color[0] = color[1] = color[2] = 0;
163
164                         for ( j = 0 ; j < texels ; j++ )
165                         {
166                                 texel = ( (byte *)mt )[LittleLong( mt->offsets[0] ) + j];
167                                 color[0] += mt->palette[texel].r;
168                                 color[1] += mt->palette[texel].g;
169                                 color[2] += mt->palette[texel].b;
170                         }
171
172                         free( mt );
173                 }
174                 else
175                 {
176                         texels = LittleLong( mt32->width[0] ) * LittleLong( mt32->height[0] );
177                         color[0] = color[1] = color[2] = 0;
178
179                         for ( j = 0 ; j < texels ; j++ )
180                         {
181                                 pos = (byte *)mt32 + mt32->offsets[0] + ( j << 2 );
182                                 color[0] += *pos++; // r
183                                 color[1] += *pos++; // g
184                                 color[2] += *pos++; // b
185                         }
186
187                         free( mt32 );
188                 }
189
190
191                 for ( j = 0 ; j < 3 ; j++ )
192                 {
193                         r = color[j] / ( (float) texels * 255.0 );
194                         texture_reflectivity[i][j] = r;
195                 }
196         }
197 }
198
199 /*
200    =======================================================================
201
202    MAKE FACES
203
204    =======================================================================
205  */
206
207 /*
208    =============
209    WindingFromFace
210    =============
211  */
212 winding_t   *WindingFromFace( dface_t *f ){
213         int i;
214         int se;
215         dvertex_t   *dv;
216         int v;
217         winding_t   *w;
218
219         w = AllocWinding( f->numedges );
220         w->numpoints = f->numedges;
221
222         for ( i = 0 ; i < f->numedges ; i++ )
223         {
224                 se = dsurfedges[f->firstedge + i];
225                 if ( se < 0 ) {
226                         v = dedges[-se].v[1];
227                 }
228                 else{
229                         v = dedges[se].v[0];
230                 }
231
232                 dv = &dvertexes[v];
233                 VectorCopy( dv->point, w->p[i] );
234         }
235
236         RemoveColinearPoints( w );
237
238         return w;
239 }
240
241 /*
242    =============
243    BaseLightForFace
244    =============
245  */
246 void BaseLightForFace( dface_t *f, vec3_t color ){
247         texinfo_t   *tx;
248
249         //
250         // check for light emited by texture
251         //
252         tx = &texinfo[f->texinfo];
253         if ( !( tx->flags & SURF_LIGHT ) || tx->value == 0 ) {
254                 VectorClear( color );
255                 return;
256         }
257
258         VectorScale( texture_reflectivity[f->texinfo], tx->value, color );
259 }
260
261 qboolean IsSky( dface_t *f ){
262         texinfo_t   *tx;
263
264         tx = &texinfo[f->texinfo];
265         if ( tx->flags & SURF_SKY ) {
266                 return true;
267         }
268         return false;
269 }
270
271 /*
272    =============
273    MakePatchForFace
274    =============
275  */
276 float totalarea;
277 void MakePatchForFace( int fn, winding_t *w ){
278         dface_t *f;
279         float area;
280         patch_t     *patch;
281         dplane_t    *pl;
282         int i;
283         vec3_t color;
284         dleaf_t     *leaf;
285
286         f = &dfaces[fn];
287
288         area = WindingArea( w );
289         totalarea += area;
290
291         patch = &patches[num_patches];
292         if ( num_patches == MAX_PATCHES ) {
293                 Error( "num_patches == MAX_PATCHES" );
294         }
295         patch->next = face_patches[fn];
296         face_patches[fn] = patch;
297
298         patch->winding = w;
299
300         if ( f->side ) {
301                 patch->plane = &backplanes[f->planenum];
302         }
303         else{
304                 patch->plane = &dplanes[f->planenum];
305         }
306         if ( face_offset[fn][0] || face_offset[fn][1] || face_offset[fn][2] ) { // origin offset faces must create new planes
307                 if ( numplanes + fakeplanes >= MAX_MAP_PLANES ) {
308                         Error( "numplanes + fakeplanes >= MAX_MAP_PLANES" );
309                 }
310                 pl = &dplanes[numplanes + fakeplanes];
311                 fakeplanes++;
312
313                 *pl = *( patch->plane );
314                 pl->dist += DotProduct( face_offset[fn], pl->normal );
315                 patch->plane = pl;
316         }
317
318         WindingCenter( w, patch->origin );
319         VectorAdd( patch->origin, patch->plane->normal, patch->origin );
320         leaf = Rad_PointInLeaf( patch->origin );
321         patch->cluster = leaf->cluster;
322         if ( patch->cluster == -1 ) {
323                 Sys_FPrintf( SYS_VRB, "patch->cluster == -1\n" );
324         }
325
326         patch->area = area;
327         if ( patch->area <= 1 ) {
328                 patch->area = 1;
329         }
330         patch->sky = IsSky( f );
331
332         VectorCopy( texture_reflectivity[f->texinfo], patch->reflectivity );
333
334         // non-bmodel patches can emit light
335         if ( fn < dmodels[0].numfaces ) {
336                 BaseLightForFace( f, patch->baselight );
337
338                 ColorNormalize( patch->reflectivity, color );
339
340                 for ( i = 0 ; i < 3 ; i++ )
341                         patch->baselight[i] *= color[i];
342
343                 VectorCopy( patch->baselight, patch->totallight );
344         }
345         num_patches++;
346 }
347
348
349 entity_t *EntityForModel( int modnum ){
350         int i;
351         char    *s;
352         char name[16];
353
354         sprintf( name, "*%i", modnum );
355         // search the entities for one using modnum
356         for ( i = 0 ; i < num_entities ; i++ )
357         {
358                 s = ValueForKey( &entities[i], "model" );
359                 if ( !strcmp( s, name ) ) {
360                         return &entities[i];
361                 }
362         }
363
364         return &entities[0];
365 }
366
367 /*
368    =============
369    MakePatches
370    =============
371  */
372 void MakePatches( void ){
373         int i, j, k;
374         dface_t *f;
375         int fn;
376         winding_t   *w;
377         dmodel_t    *mod;
378         vec3_t origin;
379         entity_t    *ent;
380
381         Sys_FPrintf( SYS_VRB, "%i faces\n", numfaces );
382
383         for ( i = 0 ; i < nummodels ; i++ )
384         {
385                 mod = &dmodels[i];
386                 ent = EntityForModel( i );
387                 // bmodels with origin brushes need to be offset into their
388                 // in-use position
389                 GetVectorForKey( ent, "origin", origin );
390 //VectorCopy (vec3_origin, origin);
391
392                 for ( j = 0 ; j < mod->numfaces ; j++ )
393                 {
394                         fn = mod->firstface + j;
395                         face_entity[fn] = ent;
396                         VectorCopy( origin, face_offset[fn] );
397                         f = &dfaces[fn];
398                         w = WindingFromFace( f );
399                         for ( k = 0 ; k < w->numpoints ; k++ )
400                         {
401                                 VectorAdd( w->p[k], origin, w->p[k] );
402                         }
403                         MakePatchForFace( fn, w );
404                 }
405         }
406
407         Sys_FPrintf( SYS_VRB, "%i sqaure feet\n", (int)( totalarea / 64 ) );
408 }
409
410 /*
411    =======================================================================
412
413    SUBDIVIDE
414
415    =======================================================================
416  */
417
418 void FinishSplit( patch_t *patch, patch_t *newp ){
419         dleaf_t     *leaf;
420
421         VectorCopy( patch->baselight, newp->baselight );
422         VectorCopy( patch->totallight, newp->totallight );
423         VectorCopy( patch->reflectivity, newp->reflectivity );
424         newp->plane = patch->plane;
425         newp->sky = patch->sky;
426
427         patch->area = WindingArea( patch->winding );
428         newp->area = WindingArea( newp->winding );
429
430         if ( patch->area <= 1 ) {
431                 patch->area = 1;
432         }
433         if ( newp->area <= 1 ) {
434                 newp->area = 1;
435         }
436
437         WindingCenter( patch->winding, patch->origin );
438         VectorAdd( patch->origin, patch->plane->normal, patch->origin );
439         leaf = Rad_PointInLeaf( patch->origin );
440         patch->cluster = leaf->cluster;
441         if ( patch->cluster == -1 ) {
442                 Sys_FPrintf( SYS_VRB, "patch->cluster == -1\n" );
443         }
444
445         WindingCenter( newp->winding, newp->origin );
446         VectorAdd( newp->origin, newp->plane->normal, newp->origin );
447         leaf = Rad_PointInLeaf( newp->origin );
448         newp->cluster = leaf->cluster;
449         if ( newp->cluster == -1 ) {
450                 Sys_FPrintf( SYS_VRB, "patch->cluster == -1\n" );
451         }
452 }
453
454 /*
455    =============
456    SubdividePatch
457
458    Chops the patch only if its local bounds exceed the max size
459    =============
460  */
461 void    SubdividePatch( patch_t *patch ){
462         winding_t *w, *o1, *o2;
463         vec3_t mins, maxs, total;
464         vec3_t split;
465         vec_t dist;
466         int i, j;
467         vec_t v;
468         patch_t *newp;
469
470         w = patch->winding;
471         mins[0] = mins[1] = mins[2] = 99999;
472         maxs[0] = maxs[1] = maxs[2] = -99999;
473         for ( i = 0 ; i < w->numpoints ; i++ )
474         {
475                 for ( j = 0 ; j < 3 ; j++ )
476                 {
477                         v = w->p[i][j];
478                         if ( v < mins[j] ) {
479                                 mins[j] = v;
480                         }
481                         if ( v > maxs[j] ) {
482                                 maxs[j] = v;
483                         }
484                 }
485         }
486         VectorSubtract( maxs, mins, total );
487         for ( i = 0 ; i < 3 ; i++ )
488                 if ( total[i] > ( subdiv + 1 ) ) {
489                         break;
490                 }
491         if ( i == 3 ) {
492                 // no splitting needed
493                 return;
494         }
495
496         //
497         // split the winding
498         //
499         VectorCopy( vec3_origin, split );
500         split[i] = 1;
501         dist = ( mins[i] + maxs[i] ) * 0.5;
502         ClipWindingEpsilon( w, split, dist, ON_EPSILON, &o1, &o2 );
503
504         //
505         // create a new patch
506         //
507         if ( num_patches == MAX_PATCHES ) {
508                 Error( "MAX_PATCHES" );
509         }
510         newp = &patches[num_patches];
511         num_patches++;
512
513         newp->next = patch->next;
514         patch->next = newp;
515
516         patch->winding = o1;
517         newp->winding = o2;
518
519         FinishSplit( patch, newp );
520
521         SubdividePatch( patch );
522         SubdividePatch( newp );
523 }
524
525
526 /*
527    =============
528    DicePatch
529
530    Chops the patch by a global grid
531    =============
532  */
533 void    DicePatch( patch_t *patch ){
534         winding_t *w, *o1, *o2;
535         vec3_t mins, maxs;
536         vec3_t split;
537         vec_t dist;
538         int i;
539         patch_t *newp;
540
541         w = patch->winding;
542         WindingBounds( w, mins, maxs );
543         for ( i = 0 ; i < 3 ; i++ )
544                 if ( floor( ( mins[i] + 1 ) / subdiv ) < floor( ( maxs[i] - 1 ) / subdiv ) ) {
545                         break;
546                 }
547         if ( i == 3 ) {
548                 // no splitting needed
549                 return;
550         }
551
552         //
553         // split the winding
554         //
555         VectorCopy( vec3_origin, split );
556         split[i] = 1;
557         dist = subdiv * ( 1 + floor( ( mins[i] + 1 ) / subdiv ) );
558         ClipWindingEpsilon( w, split, dist, ON_EPSILON, &o1, &o2 );
559
560         //
561         // create a new patch
562         //
563         if ( num_patches == MAX_PATCHES ) {
564                 Error( "MAX_PATCHES" );
565         }
566         newp = &patches[num_patches];
567         num_patches++;
568
569         newp->next = patch->next;
570         patch->next = newp;
571
572         patch->winding = o1;
573         newp->winding = o2;
574
575         FinishSplit( patch, newp );
576
577         DicePatch( patch );
578         DicePatch( newp );
579 }
580
581
582 /*
583    =============
584    SubdividePatches
585    =============
586  */
587 void SubdividePatches( void ){
588         int i, num;
589
590         if ( subdiv < 1 ) {
591                 return;
592         }
593
594         num = num_patches;  // because the list will grow
595         for ( i = 0 ; i < num ; i++ )
596         {
597 //              SubdividePatch (&patches[i]);
598                 DicePatch( &patches[i] );
599         }
600         Sys_FPrintf( SYS_VRB, "%i patches after subdivision\n", num_patches );
601 }
602
603 //=====================================================================