2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
\r
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
\r
5 This file is part of GtkRadiant.
\r
7 GtkRadiant is free software; you can redistribute it and/or modify
\r
8 it under the terms of the GNU General Public License as published by
\r
9 the Free Software Foundation; either version 2 of the License, or
\r
10 (at your option) any later version.
\r
12 GtkRadiant is distributed in the hope that it will be useful,
\r
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
15 GNU General Public License for more details.
\r
17 You should have received a copy of the GNU General Public License
\r
18 along with GtkRadiant; if not, write to the Free Software
\r
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
\r
24 vec3_t texture_reflectivity[MAX_MAP_TEXINFO];
\r
27 ===================================================================
\r
29 TEXTURE LIGHT VALUES
\r
31 ===================================================================
\r
35 ======================
\r
36 CalcTextureReflectivity_Quake2
\r
37 ======================
\r
39 void CalcTextureReflectivity_Quake2 (void)
\r
50 sprintf (path, "%spics/colormap.pcx", gamedir);
\r
52 // get the game palette
\r
53 Load256Image (path, NULL, &palette, NULL, NULL);
\r
55 // allways set index 0 even if no textures
\r
56 texture_reflectivity[0][0] = 0.5;
\r
57 texture_reflectivity[0][1] = 0.5;
\r
58 texture_reflectivity[0][2] = 0.5;
\r
60 for (i=0 ; i<numtexinfo ; i++)
\r
62 // see if an earlier texinfo allready got the value
\r
63 for (j=0 ; j<i ; j++)
\r
65 if (!strcmp (texinfo[i].texture, texinfo[j].texture))
\r
67 VectorCopy (texture_reflectivity[j], texture_reflectivity[i]);
\r
74 // load the wal file
\r
75 sprintf (path, "%stextures/%s.wal", gamedir, texinfo[i].texture);
\r
76 if (TryLoadFile (path, (void **)&mt) == -1)
\r
78 Sys_Printf ("Couldn't load %s\n", path);
\r
79 texture_reflectivity[i][0] = 0.5;
\r
80 texture_reflectivity[i][1] = 0.5;
\r
81 texture_reflectivity[i][2] = 0.5;
\r
84 texels = LittleLong(mt->width)*LittleLong(mt->height);
\r
85 color[0] = color[1] = color[2] = 0;
\r
87 for (j=0 ; j<texels ; j++)
\r
89 texel = ((byte *)mt)[LittleLong(mt->offsets[0]) + j];
\r
90 for (k=0 ; k<3 ; k++)
\r
91 color[k] += palette[texel*3+k];
\r
94 for (j=0 ; j<3 ; j++)
\r
96 r = color[j]/texels/255.0;
\r
97 texture_reflectivity[i][j] = r;
\r
99 // scale the reflectivity up, because the textures are
\r
101 scale = ColorNormalize (texture_reflectivity[i],
\r
102 texture_reflectivity[i]);
\r
106 VectorScale (texture_reflectivity[i], scale, texture_reflectivity[i]);
\r
109 texture_reflectivity[i][0] = 0.5;
\r
110 texture_reflectivity[i][1] = 0.5;
\r
111 texture_reflectivity[i][2] = 0.5;
\r
117 ======================
\r
118 CalcTextureReflectivity_Heretic2
\r
119 ======================
\r
121 void CalcTextureReflectivity_Heretic2 (void)
\r
130 miptex_m32_t *mt32;
\r
134 // allways set index 0 even if no textures
\r
135 texture_reflectivity[0][0] = 0.5;
\r
136 texture_reflectivity[0][1] = 0.5;
\r
137 texture_reflectivity[0][2] = 0.5;
\r
139 for (i=0 ; i<numtexinfo ; i++)
\r
141 // see if an earlier texinfo allready got the value
\r
142 for (j=0 ; j<i ; j++)
\r
144 if (!strcmp (texinfo[i].texture, texinfo[j].texture))
\r
146 VectorCopy (texture_reflectivity[j], texture_reflectivity[i]);
\r
153 // load the wal file
\r
155 sprintf (path, "%stextures/%s.m32", gamedir, texinfo[i].texture);
\r
156 if (TryLoadFile (path, (void **)&mt32) == -1)
\r
158 sprintf (path, "%stextures/%s.m8", gamedir, texinfo[i].texture);
\r
159 if (TryLoadFile (path, (void **)&mt) == -1)
\r
161 Sys_Printf ("Couldn't load %s\n", path);
\r
162 texture_reflectivity[i][0] = 0.5;
\r
163 texture_reflectivity[i][1] = 0.5;
\r
164 texture_reflectivity[i][2] = 0.5;
\r
167 texels = LittleLong(mt->width[0])*LittleLong(mt->height[0]);
\r
168 color[0] = color[1] = color[2] = 0;
\r
170 for (j=0 ; j<texels ; j++)
\r
172 texel = ((byte *)mt)[LittleLong(mt->offsets[0]) + j];
\r
173 color[0] += mt->palette[texel].r;
\r
174 color[1] += mt->palette[texel].g;
\r
175 color[2] += mt->palette[texel].b;
\r
182 texels = LittleLong(mt32->width[0])*LittleLong(mt32->height[0]);
\r
183 color[0] = color[1] = color[2] = 0;
\r
185 for (j=0 ; j<texels ; j++)
\r
187 pos = (byte *)mt32 + mt32->offsets[0] + (j<<2);
\r
188 color[0] += *pos++; // r
\r
189 color[1] += *pos++; // g
\r
190 color[2] += *pos++; // b
\r
197 for (j=0 ; j<3 ; j++)
\r
199 r = color[j]/((float) texels*255.0);
\r
200 texture_reflectivity[i][j] = r;
\r
206 =======================================================================
\r
210 =======================================================================
\r
218 winding_t *WindingFromFace (dface_t *f)
\r
226 w = AllocWinding (f->numedges);
\r
227 w->numpoints = f->numedges;
\r
229 for (i=0 ; i<f->numedges ; i++)
\r
231 se = dsurfedges[f->firstedge + i];
\r
233 v = dedges[-se].v[1];
\r
235 v = dedges[se].v[0];
\r
237 dv = &dvertexes[v];
\r
238 VectorCopy (dv->point, w->p[i]);
\r
241 RemoveColinearPoints (w);
\r
251 void BaseLightForFace (dface_t *f, vec3_t color)
\r
256 // check for light emited by texture
\r
258 tx = &texinfo[f->texinfo];
\r
259 if (!(tx->flags & SURF_LIGHT) || tx->value == 0)
\r
261 VectorClear (color);
\r
265 VectorScale (texture_reflectivity[f->texinfo], tx->value, color);
\r
268 qboolean IsSky (dface_t *f)
\r
272 tx = &texinfo[f->texinfo];
\r
273 if (tx->flags & SURF_SKY)
\r
284 void MakePatchForFace (int fn, winding_t *w)
\r
296 area = WindingArea (w);
\r
299 patch = &patches[num_patches];
\r
300 if (num_patches == MAX_PATCHES)
\r
301 Error ("num_patches == MAX_PATCHES");
\r
302 patch->next = face_patches[fn];
\r
303 face_patches[fn] = patch;
\r
305 patch->winding = w;
\r
308 patch->plane = &backplanes[f->planenum];
\r
310 patch->plane = &dplanes[f->planenum];
\r
311 if (face_offset[fn][0] || face_offset[fn][1] || face_offset[fn][2] )
\r
312 { // origin offset faces must create new planes
\r
313 if (numplanes + fakeplanes >= MAX_MAP_PLANES)
\r
314 Error ("numplanes + fakeplanes >= MAX_MAP_PLANES");
\r
315 pl = &dplanes[numplanes + fakeplanes];
\r
318 *pl = *(patch->plane);
\r
319 pl->dist += DotProduct (face_offset[fn], pl->normal);
\r
323 WindingCenter (w, patch->origin);
\r
324 VectorAdd (patch->origin, patch->plane->normal, patch->origin);
\r
325 leaf = Rad_PointInLeaf(patch->origin);
\r
326 patch->cluster = leaf->cluster;
\r
327 if (patch->cluster == -1)
\r
328 Sys_FPrintf( SYS_VRB, "patch->cluster == -1\n");
\r
330 patch->area = area;
\r
331 if (patch->area <= 1)
\r
333 patch->sky = IsSky (f);
\r
335 VectorCopy (texture_reflectivity[f->texinfo], patch->reflectivity);
\r
337 // non-bmodel patches can emit light
\r
338 if (fn < dmodels[0].numfaces)
\r
340 BaseLightForFace (f, patch->baselight);
\r
342 ColorNormalize (patch->reflectivity, color);
\r
344 for (i=0 ; i<3 ; i++)
\r
345 patch->baselight[i] *= color[i];
\r
347 VectorCopy (patch->baselight, patch->totallight);
\r
353 entity_t *EntityForModel (int modnum)
\r
359 sprintf (name, "*%i", modnum);
\r
360 // search the entities for one using modnum
\r
361 for (i=0 ; i<num_entities ; i++)
\r
363 s = ValueForKey (&entities[i], "model");
\r
364 if (!strcmp (s, name))
\r
365 return &entities[i];
\r
368 return &entities[0];
\r
376 void MakePatches (void)
\r
386 Sys_FPrintf( SYS_VRB, "%i faces\n", numfaces);
\r
388 for (i=0 ; i<nummodels ; i++)
\r
391 ent = EntityForModel (i);
\r
392 // bmodels with origin brushes need to be offset into their
\r
394 GetVectorForKey (ent, "origin", origin);
\r
395 //VectorCopy (vec3_origin, origin);
\r
397 for (j=0 ; j<mod->numfaces ; j++)
\r
399 fn = mod->firstface + j;
\r
400 face_entity[fn] = ent;
\r
401 VectorCopy (origin, face_offset[fn]);
\r
403 w = WindingFromFace (f);
\r
404 for (k=0 ; k<w->numpoints ; k++)
\r
406 VectorAdd (w->p[k], origin, w->p[k]);
\r
408 MakePatchForFace (fn, w);
\r
412 Sys_FPrintf( SYS_VRB, "%i sqaure feet\n", (int)(totalarea/64));
\r
416 =======================================================================
\r
420 =======================================================================
\r
423 void FinishSplit (patch_t *patch, patch_t *newp)
\r
427 VectorCopy (patch->baselight, newp->baselight);
\r
428 VectorCopy (patch->totallight, newp->totallight);
\r
429 VectorCopy (patch->reflectivity, newp->reflectivity);
\r
430 newp->plane = patch->plane;
\r
431 newp->sky = patch->sky;
\r
433 patch->area = WindingArea (patch->winding);
\r
434 newp->area = WindingArea (newp->winding);
\r
436 if (patch->area <= 1)
\r
438 if (newp->area <= 1)
\r
441 WindingCenter (patch->winding, patch->origin);
\r
442 VectorAdd (patch->origin, patch->plane->normal, patch->origin);
\r
443 leaf = Rad_PointInLeaf(patch->origin);
\r
444 patch->cluster = leaf->cluster;
\r
445 if (patch->cluster == -1)
\r
446 Sys_FPrintf( SYS_VRB, "patch->cluster == -1\n");
\r
448 WindingCenter (newp->winding, newp->origin);
\r
449 VectorAdd (newp->origin, newp->plane->normal, newp->origin);
\r
450 leaf = Rad_PointInLeaf(newp->origin);
\r
451 newp->cluster = leaf->cluster;
\r
452 if (newp->cluster == -1)
\r
453 Sys_FPrintf( SYS_VRB, "patch->cluster == -1\n");
\r
460 Chops the patch only if its local bounds exceed the max size
\r
463 void SubdividePatch (patch_t *patch)
\r
465 winding_t *w, *o1, *o2;
\r
466 vec3_t mins, maxs, total;
\r
473 w = patch->winding;
\r
474 mins[0] = mins[1] = mins[2] = 99999;
\r
475 maxs[0] = maxs[1] = maxs[2] = -99999;
\r
476 for (i=0 ; i<w->numpoints ; i++)
\r
478 for (j=0 ; j<3 ; j++)
\r
487 VectorSubtract (maxs, mins, total);
\r
488 for (i=0 ; i<3 ; i++)
\r
489 if (total[i] > (subdiv+1) )
\r
493 // no splitting needed
\r
498 // split the winding
\r
500 VectorCopy (vec3_origin, split);
\r
502 dist = (mins[i] + maxs[i])*0.5;
\r
503 ClipWindingEpsilon (w, split, dist, ON_EPSILON, &o1, &o2);
\r
506 // create a new patch
\r
508 if (num_patches == MAX_PATCHES)
\r
509 Error ("MAX_PATCHES");
\r
510 newp = &patches[num_patches];
\r
513 newp->next = patch->next;
\r
514 patch->next = newp;
\r
516 patch->winding = o1;
\r
517 newp->winding = o2;
\r
519 FinishSplit (patch, newp);
\r
521 SubdividePatch (patch);
\r
522 SubdividePatch (newp);
\r
530 Chops the patch by a global grid
\r
533 void DicePatch (patch_t *patch)
\r
535 winding_t *w, *o1, *o2;
\r
542 w = patch->winding;
\r
543 WindingBounds (w, mins, maxs);
\r
544 for (i=0 ; i<3 ; i++)
\r
545 if (floor((mins[i]+1)/subdiv) < floor((maxs[i]-1)/subdiv))
\r
549 // no splitting needed
\r
554 // split the winding
\r
556 VectorCopy (vec3_origin, split);
\r
558 dist = subdiv*(1+floor((mins[i]+1)/subdiv));
\r
559 ClipWindingEpsilon (w, split, dist, ON_EPSILON, &o1, &o2);
\r
562 // create a new patch
\r
564 if (num_patches == MAX_PATCHES)
\r
565 Error ("MAX_PATCHES");
\r
566 newp = &patches[num_patches];
\r
569 newp->next = patch->next;
\r
570 patch->next = newp;
\r
572 patch->winding = o1;
\r
573 newp->winding = o2;
\r
575 FinishSplit (patch, newp);
\r
587 void SubdividePatches (void)
\r
594 num = num_patches; // because the list will grow
\r
595 for (i=0 ; i<num ; i++)
\r
597 // SubdividePatch (&patches[i]);
\r
598 DicePatch (&patches[i]);
\r
600 Sys_FPrintf( SYS_VRB, "%i patches after subdivision\n", num_patches);
\r
603 //=====================================================================
\r