2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
5 This file is part of GtkRadiant.
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.
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.
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
24 vec3_t texture_reflectivity[MAX_MAP_TEXINFO];
27 ===================================================================
31 ===================================================================
35 ======================
36 CalcTextureReflectivity_Quake2
37 ======================
39 void CalcTextureReflectivity_Quake2( void ){
49 sprintf( path, "%spics/colormap.pcx", gamedir );
51 // get the game palette
52 Load256Image( path, NULL, &palette, NULL, NULL );
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;
59 for ( i = 0 ; i < numtexinfo ; i++ )
61 // see if an earlier texinfo allready got the value
62 for ( j = 0 ; j < i ; j++ )
64 if ( !strcmp( texinfo[i].texture, texinfo[j].texture ) ) {
65 VectorCopy( texture_reflectivity[j], texture_reflectivity[i] );
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;
82 texels = LittleLong( mt->width ) * LittleLong( mt->height );
83 color[0] = color[1] = color[2] = 0;
85 for ( j = 0 ; j < texels ; j++ )
87 texel = ( (byte *)mt )[LittleLong( mt->offsets[0] ) + j];
88 for ( k = 0 ; k < 3 ; k++ )
89 color[k] += palette[texel * 3 + k];
92 for ( j = 0 ; j < 3 ; j++ )
94 r = color[j] / texels / 255.0;
95 texture_reflectivity[i][j] = r;
97 // scale the reflectivity up, because the textures are
99 scale = ColorNormalize( texture_reflectivity[i],
100 texture_reflectivity[i] );
103 VectorScale( texture_reflectivity[i], scale, texture_reflectivity[i] );
106 texture_reflectivity[i][0] = 0.5;
107 texture_reflectivity[i][1] = 0.5;
108 texture_reflectivity[i][2] = 0.5;
114 ======================
115 CalcTextureReflectivity_Heretic2
116 ======================
118 void CalcTextureReflectivity_Heretic2( void ){
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;
135 for ( i = 0 ; i < numtexinfo ; i++ )
137 // see if an earlier texinfo allready got the value
138 for ( j = 0 ; j < i ; j++ )
140 if ( !strcmp( texinfo[i].texture, texinfo[j].texture ) ) {
141 VectorCopy( texture_reflectivity[j], texture_reflectivity[i] );
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;
161 texels = LittleLong( mt->width[0] ) * LittleLong( mt->height[0] );
162 color[0] = color[1] = color[2] = 0;
164 for ( j = 0 ; j < texels ; j++ )
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;
176 texels = LittleLong( mt32->width[0] ) * LittleLong( mt32->height[0] );
177 color[0] = color[1] = color[2] = 0;
179 for ( j = 0 ; j < texels ; j++ )
181 pos = (byte *)mt32 + mt32->offsets[0] + ( j << 2 );
182 color[0] += *pos++; // r
183 color[1] += *pos++; // g
184 color[2] += *pos++; // b
191 for ( j = 0 ; j < 3 ; j++ )
193 r = color[j] / ( (float) texels * 255.0 );
194 texture_reflectivity[i][j] = r;
200 =======================================================================
204 =======================================================================
212 winding_t *WindingFromFace( dface_t *f ){
219 w = AllocWinding( f->numedges );
220 w->numpoints = f->numedges;
222 for ( i = 0 ; i < f->numedges ; i++ )
224 se = dsurfedges[f->firstedge + i];
226 v = dedges[-se].v[1];
233 VectorCopy( dv->point, w->p[i] );
236 RemoveColinearPoints( w );
246 void BaseLightForFace( dface_t *f, vec3_t color ){
250 // check for light emited by texture
252 tx = &texinfo[f->texinfo];
253 if ( !( tx->flags & SURF_LIGHT ) || tx->value == 0 ) {
254 VectorClear( color );
258 VectorScale( texture_reflectivity[f->texinfo], tx->value, color );
261 qboolean IsSky( dface_t *f ){
264 tx = &texinfo[f->texinfo];
265 if ( tx->flags & SURF_SKY ) {
277 void MakePatchForFace( int fn, winding_t *w ){
288 area = WindingArea( w );
291 patch = &patches[num_patches];
292 if ( num_patches == MAX_PATCHES ) {
293 Error( "num_patches == MAX_PATCHES" );
295 patch->next = face_patches[fn];
296 face_patches[fn] = patch;
301 patch->plane = &backplanes[f->planenum];
304 patch->plane = &dplanes[f->planenum];
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" );
310 pl = &dplanes[numplanes + fakeplanes];
313 *pl = *( patch->plane );
314 pl->dist += DotProduct( face_offset[fn], pl->normal );
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" );
327 if ( patch->area <= 1 ) {
330 patch->sky = IsSky( f );
332 VectorCopy( texture_reflectivity[f->texinfo], patch->reflectivity );
334 // non-bmodel patches can emit light
335 if ( fn < dmodels[0].numfaces ) {
336 BaseLightForFace( f, patch->baselight );
338 ColorNormalize( patch->reflectivity, color );
340 for ( i = 0 ; i < 3 ; i++ )
341 patch->baselight[i] *= color[i];
343 VectorCopy( patch->baselight, patch->totallight );
349 entity_t *EntityForModel( int modnum ){
354 sprintf( name, "*%i", modnum );
355 // search the entities for one using modnum
356 for ( i = 0 ; i < num_entities ; i++ )
358 s = ValueForKey( &entities[i], "model" );
359 if ( !strcmp( s, name ) ) {
372 void MakePatches( void ){
381 Sys_FPrintf( SYS_VRB, "%i faces\n", numfaces );
383 for ( i = 0 ; i < nummodels ; i++ )
386 ent = EntityForModel( i );
387 // bmodels with origin brushes need to be offset into their
389 GetVectorForKey( ent, "origin", origin );
390 //VectorCopy (vec3_origin, origin);
392 for ( j = 0 ; j < mod->numfaces ; j++ )
394 fn = mod->firstface + j;
395 face_entity[fn] = ent;
396 VectorCopy( origin, face_offset[fn] );
398 w = WindingFromFace( f );
399 for ( k = 0 ; k < w->numpoints ; k++ )
401 VectorAdd( w->p[k], origin, w->p[k] );
403 MakePatchForFace( fn, w );
407 Sys_FPrintf( SYS_VRB, "%i sqaure feet\n", (int)( totalarea / 64 ) );
411 =======================================================================
415 =======================================================================
418 void FinishSplit( patch_t *patch, patch_t *newp ){
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;
427 patch->area = WindingArea( patch->winding );
428 newp->area = WindingArea( newp->winding );
430 if ( patch->area <= 1 ) {
433 if ( newp->area <= 1 ) {
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" );
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" );
458 Chops the patch only if its local bounds exceed the max size
461 void SubdividePatch( patch_t *patch ){
462 winding_t *w, *o1, *o2;
463 vec3_t mins, maxs, total;
471 mins[0] = mins[1] = mins[2] = 99999;
472 maxs[0] = maxs[1] = maxs[2] = -99999;
473 for ( i = 0 ; i < w->numpoints ; i++ )
475 for ( j = 0 ; j < 3 ; j++ )
486 VectorSubtract( maxs, mins, total );
487 for ( i = 0 ; i < 3 ; i++ )
488 if ( total[i] > ( subdiv + 1 ) ) {
492 // no splitting needed
499 VectorCopy( vec3_origin, split );
501 dist = ( mins[i] + maxs[i] ) * 0.5;
502 ClipWindingEpsilon( w, split, dist, ON_EPSILON, &o1, &o2 );
505 // create a new patch
507 if ( num_patches == MAX_PATCHES ) {
508 Error( "MAX_PATCHES" );
510 newp = &patches[num_patches];
513 newp->next = patch->next;
519 FinishSplit( patch, newp );
521 SubdividePatch( patch );
522 SubdividePatch( newp );
530 Chops the patch by a global grid
533 void DicePatch( patch_t *patch ){
534 winding_t *w, *o1, *o2;
542 WindingBounds( w, mins, maxs );
543 for ( i = 0 ; i < 3 ; i++ )
544 if ( floor( ( mins[i] + 1 ) / subdiv ) < floor( ( maxs[i] - 1 ) / subdiv ) ) {
548 // no splitting needed
555 VectorCopy( vec3_origin, split );
557 dist = subdiv * ( 1 + floor( ( mins[i] + 1 ) / subdiv ) );
558 ClipWindingEpsilon( w, split, dist, ON_EPSILON, &o1, &o2 );
561 // create a new patch
563 if ( num_patches == MAX_PATCHES ) {
564 Error( "MAX_PATCHES" );
566 newp = &patches[num_patches];
569 newp->next = patch->next;
575 FinishSplit( patch, newp );
587 void SubdividePatches( void ){
594 num = num_patches; // because the list will grow
595 for ( i = 0 ; i < num ; i++ )
597 // SubdividePatch (&patches[i]);
598 DicePatch( &patches[i] );
600 Sys_FPrintf( SYS_VRB, "%i patches after subdivision\n", num_patches );
603 //=====================================================================