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