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