diff options
Diffstat (limited to 'q3map/fog.c')
-rw-r--r-- | q3map/fog.c | 554 |
1 files changed, 0 insertions, 554 deletions
diff --git a/q3map/fog.c b/q3map/fog.c deleted file mode 100644 index fa938dd..0000000 --- a/q3map/fog.c +++ /dev/null @@ -1,554 +0,0 @@ -/* -=========================================================================== -Copyright (C) 1999-2005 Id Software, Inc. - -This file is part of Quake III Arena source code. - -Quake III Arena source code is free software; you can redistribute it -and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, -or (at your option) any later version. - -Quake III Arena source code is distributed in the hope that it will be -useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Foobar; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -=========================================================================== -*/ -#include "qbsp.h" - - -int c_fogFragment; -int c_fogPatchFragments; - -/* -==================== -DrawSurfToMesh -==================== -*/ -mesh_t *DrawSurfToMesh( mapDrawSurface_t *ds ) { - mesh_t *m; - - m = malloc( sizeof( *m ) ); - m->width = ds->patchWidth; - m->height = ds->patchHeight; - m->verts = malloc( sizeof(m->verts[0]) * m->width * m->height ); - memcpy( m->verts, ds->verts, sizeof(m->verts[0]) * m->width * m->height ); - - return m; -} - - -/* -==================== -SplitMeshByPlane -==================== -*/ -void SplitMeshByPlane( mesh_t *in, vec3_t normal, float dist, mesh_t **front, mesh_t **back ) { - int w, h, split; - float d[MAX_PATCH_SIZE][MAX_PATCH_SIZE]; - drawVert_t *dv, *v1, *v2; - int c_front, c_back, c_on; - mesh_t *f, *b; - int i; - float frac; - int frontAprox, backAprox; - - for ( i = 0 ; i < 2 ; i++ ) { - dv = in->verts; - c_front = 0; - c_back = 0; - c_on = 0; - for ( h = 0 ; h < in->height ; h++ ) { - for ( w = 0 ; w < in->width ; w++, dv++ ) { - d[h][w] = DotProduct( dv->xyz, normal ) - dist; - if ( d[h][w] > ON_EPSILON ) { - c_front++; - } else if ( d[h][w] < -ON_EPSILON ) { - c_back++; - } else { - c_on++; - } - } - } - - *front = NULL; - *back = NULL; - - if ( !c_front ) { - *back = in; - return; - } - if ( !c_back ) { - *front = in; - return; - } - - // find a split point - split = -1; - for ( w = 0 ; w < in->width -1 ; w++ ) { - if ( ( d[0][w] < 0 ) != ( d[0][w+1] < 0 ) ) { - if ( split == -1 ) { - split = w; - break; - } - } - } - - if ( split == -1 ) { - if ( i == 1 ) { - qprintf( "No crossing points in patch\n"); - *front = in; - return; - } - - in = TransposeMesh( in ); - InvertMesh( in ); - continue; - } - - // make sure the split point stays the same for all other rows - for ( h = 1 ; h < in->height ; h++ ) { - for ( w = 0 ; w < in->width -1 ; w++ ) { - if ( ( d[h][w] < 0 ) != ( d[h][w+1] < 0 ) ) { - if ( w != split ) { - _printf( "multiple crossing points for patch -- can't clip\n"); - *front = in; - return; - } - } - } - if ( ( d[h][split] < 0 ) == ( d[h][split+1] < 0 ) ) { - _printf( "differing crossing points for patch -- can't clip\n"); - *front = in; - return; - } - } - - break; - } - - - // create two new meshes - f = malloc( sizeof( *f ) ); - f->width = split + 2; - if ( ! (f->width & 1) ) { - f->width++; - frontAprox = 1; - } else { - frontAprox = 0; - } - if ( f->width > MAX_PATCH_SIZE ) { - Error( "MAX_PATCH_SIZE after split"); - } - f->height = in->height; - f->verts = malloc( sizeof(f->verts[0]) * f->width * f->height ); - - b = malloc( sizeof( *b ) ); - b->width = in->width - split; - if ( ! (b->width & 1) ) { - b->width++; - backAprox = 1; - } else { - backAprox = 0; - } - if ( b->width > MAX_PATCH_SIZE ) { - Error( "MAX_PATCH_SIZE after split"); - } - b->height = in->height; - b->verts = malloc( sizeof(b->verts[0]) * b->width * b->height ); - - if ( d[0][0] > 0 ) { - *front = f; - *back = b; - } else { - *front = b; - *back = f; - } - - // distribute the points - for ( w = 0 ; w < in->width ; w++ ) { - for ( h = 0 ; h < in->height ; h++ ) { - if ( w <= split ) { - f->verts[ h * f->width + w ] = in->verts[ h * in->width + w ]; - } else { - b->verts[ h * b->width + w - split + backAprox ] = in->verts[ h * in->width + w ]; - } - } - } - - // clip the crossing line - for ( h = 0 ; h < in->height ; h++ ) { - dv = &f->verts[ h * f->width + split + 1 ]; - v1 = &in->verts[ h * in->width + split ]; - v2 = &in->verts[ h * in->width + split + 1 ]; - frac = d[h][split] / ( d[h][split] - d[h][split+1] ); - for ( i = 0 ; i < 10 ; i++ ) { - dv->xyz[i] = v1->xyz[i] + frac * ( v2->xyz[i] - v1->xyz[i] ); - } - dv->xyz[10] = 0;//set all 4 colors to 0 - if ( frontAprox ) { - f->verts[ h * f->width + split + 2 ] = *dv; - } - b->verts[ h * b->width ] = *dv; - if ( backAprox ) { - b->verts[ h * b->width + 1 ] = *dv; - } - } - - /* -PrintMesh( in ); -_printf("\n"); -PrintMesh( f ); -_printf("\n"); -PrintMesh( b ); -_printf("\n"); - */ - - FreeMesh( in ); -} - - -/* -==================== -ChopPatchByBrush -==================== -*/ -qboolean ChopPatchByBrush( mapDrawSurface_t *ds, bspbrush_t *b ) { - int i, j; - side_t *s; - plane_t *plane; - mesh_t *outside[MAX_BRUSH_SIDES]; - int numOutside; - mesh_t *m, *front, *back; - mapDrawSurface_t *newds; - - m = DrawSurfToMesh( ds ); - numOutside = 0; - - // only split by the top and bottom planes to avoid - // some messy patch clipping issues - - for ( i = 4 ; i <= 5 ; i++ ) { - s = &b->sides[ i ]; - plane = &mapplanes[ s->planenum ]; - - SplitMeshByPlane( m, plane->normal, plane->dist, &front, &back ); - - if ( !back ) { - // nothing actually contained inside - for ( j = 0 ; j < numOutside ; j++ ) { - FreeMesh( outside[j] ); - } - return qfalse; - } - m = back; - - if ( front ) { - if ( numOutside == MAX_BRUSH_SIDES ) { - Error( "MAX_BRUSH_SIDES" ); - } - outside[ numOutside ] = front; - numOutside++; - } - } - - // all of outside fragments become seperate drawsurfs - c_fogPatchFragments += numOutside; - for ( i = 0 ; i < numOutside ; i++ ) { - newds = DrawSurfaceForMesh( outside[ i ] ); - newds->shaderInfo = ds->shaderInfo; - FreeMesh( outside[ i ] ); - } - - // replace ds with m - ds->patchWidth = m->width; - ds->patchHeight = m->height; - ds->numVerts = m->width * m->height; - free( ds->verts ); - ds->verts = malloc( ds->numVerts * sizeof( *ds->verts ) ); - memcpy( ds->verts, m->verts, ds->numVerts * sizeof( *ds->verts ) ); - - FreeMesh( m ); - - return qtrue; -} - -//=============================================================================== - -/* -==================== -WindingFromDrawSurf -==================== -*/ -winding_t *WindingFromDrawSurf( mapDrawSurface_t *ds ) { - winding_t *w; - int i; - - w = AllocWinding( ds->numVerts ); - w->numpoints = ds->numVerts; - for ( i = 0 ; i < ds->numVerts ; i++ ) { - VectorCopy( ds->verts[i].xyz, w->p[i] ); - } - return w; -} - -/* -==================== -ChopFaceByBrush - -There may be a fragment contained in the brush -==================== -*/ -qboolean ChopFaceByBrush( mapDrawSurface_t *ds, bspbrush_t *b ) { - int i, j; - side_t *s; - plane_t *plane; - winding_t *w; - winding_t *front, *back; - winding_t *outside[MAX_BRUSH_SIDES]; - int numOutside; - mapDrawSurface_t *newds; - drawVert_t *dv; - shaderInfo_t *si; - float mins[2]; - - // brush primitive : - // axis base - vec3_t texX,texY; - vec_t x,y; - - w = WindingFromDrawSurf( ds ); - numOutside = 0; - - for ( i = 0 ; i < b->numsides ; i++ ) { - s = &b->sides[ i ]; - if ( s->backSide ) { - continue; - } - plane = &mapplanes[ s->planenum ]; - - // handle coplanar outfacing (don't fog) - if ( ds->side->planenum == s->planenum ) { - return qfalse; - } - - // handle coplanar infacing (keep inside) - if ( ( ds->side->planenum ^ 1 ) == s->planenum ) { - continue; - } - - // general case - ClipWindingEpsilon( w, plane->normal, plane->dist, ON_EPSILON, - &front, &back ); - FreeWinding( w ); - if ( !back ) { - // nothing actually contained inside - for ( j = 0 ; j < numOutside ; j++ ) { - FreeWinding( outside[j] ); - } - return qfalse; - } - if ( front ) { - if ( numOutside == MAX_BRUSH_SIDES ) { - Error( "MAX_BRUSH_SIDES" ); - } - outside[ numOutside ] = front; - numOutside++; - } - w = back; - } - - // all of outside fragments become seperate drawsurfs - // linked to the same side - c_fogFragment += numOutside; - s = ds->side; - - for ( i = 0 ; i < numOutside ; i++ ) { - newds = DrawSurfaceForSide( ds->mapBrush, s, outside[i] ); - FreeWinding( outside[i] ); - } - - - // replace ds->verts with the verts for w - ds->numVerts = w->numpoints; - free( ds->verts ); - - ds->verts = malloc( ds->numVerts * sizeof( *ds->verts ) ); - memset( ds->verts, 0, ds->numVerts * sizeof( *ds->verts ) ); - - si = s->shaderInfo; - - mins[0] = 9999; - mins[1] = 9999; - - // compute s/t coordinates from brush primitive texture matrix - // compute axis base - ComputeAxisBase( mapplanes[s->planenum].normal, texX, texY ); - - for ( j = 0 ; j < w->numpoints ; j++ ) { - dv = ds->verts + j; - VectorCopy( w->p[j], dv->xyz ); - - if (g_bBrushPrimit==BPRIMIT_OLDBRUSHES) - { - // calculate texture s/t - dv->st[0] = s->vecs[0][3] + DotProduct( s->vecs[0], dv->xyz ); - dv->st[1] = s->vecs[1][3] + DotProduct( s->vecs[1], dv->xyz ); - dv->st[0] /= si->width; - dv->st[1] /= si->height; - } - else - { - // calculate texture s/t from brush primitive texture matrix - x = DotProduct( dv->xyz, texX ); - y = DotProduct( dv->xyz, texY ); - dv->st[0]=s->texMat[0][0]*x+s->texMat[0][1]*y+s->texMat[0][2]; - dv->st[1]=s->texMat[1][0]*x+s->texMat[1][1]*y+s->texMat[1][2]; - } - - if ( dv->st[0] < mins[0] ) { - mins[0] = dv->st[0]; - } - if ( dv->st[1] < mins[1] ) { - mins[1] = dv->st[1]; - } - - // copy normal - VectorCopy ( mapplanes[s->planenum].normal, dv->normal ); - } - - // adjust the texture coordinates to be as close to 0 as possible - if ( !si->globalTexture ) { - mins[0] = floor( mins[0] ); - mins[1] = floor( mins[1] ); - for ( i = 0 ; i < w->numpoints ; i++ ) { - dv = ds->verts + i; - dv->st[0] -= mins[0]; - dv->st[1] -= mins[1]; - } - } - - return qtrue; -} - -//=============================================================================== - - -/* -===================== -FogDrawSurfs - -Call after the surface list has been pruned, -before tjunction fixing -before lightmap allocation -===================== -*/ -void FogDrawSurfs( void ) { - int i, j, k; - mapDrawSurface_t *ds; - bspbrush_t *b; - vec3_t mins, maxs; - int c_fogged; - int numBaseDrawSurfs; - dfog_t *fog; - - qprintf("----- FogDrawsurfs -----\n"); - - c_fogged = 0; - c_fogFragment = 0; - - // find all fog brushes - for ( b = entities[0].brushes ; b ; b = b->next ) { - if ( !(b->contents & CONTENTS_FOG) ) { - continue; - } - - if ( numFogs == MAX_MAP_FOGS ) { - Error( "MAX_MAP_FOGS" ); - } - fog = &dfogs[numFogs]; - numFogs++; - fog->brushNum = b->outputNumber; - - // find a side with a valid shaderInfo - // non-axial fog columns may have bevel planes that need to be skipped - for ( i = 0 ; i < b->numsides ; i++ ) { - if ( b->sides[i].shaderInfo && (b->sides[i].shaderInfo->contents & CONTENTS_FOG) ) { - strcpy( fog->shader, b->sides[i].shaderInfo->shader ); - break; - } - } - if ( i == b->numsides ) { - continue; // shouldn't happen - } - - fog->visibleSide = -1; - - // clip each surface into this, but don't clip any of - // the resulting fragments to the same brush - numBaseDrawSurfs = numMapDrawSurfs; - for ( i = 0 ; i < numBaseDrawSurfs ; i++ ) { - ds = &mapDrawSurfs[i]; - - // bound the drawsurf - ClearBounds( mins, maxs ); - for ( j = 0 ; j < ds->numVerts ; j++ ) { - AddPointToBounds( ds->verts[j].xyz, mins, maxs ); - } - - // check against the fog brush - for ( k = 0 ; k < 3 ; k++ ) { - if ( mins[k] > b->maxs[k] ) { - break; - } - if ( maxs[k] < b->mins[k] ) { - break; - } - } - if ( k < 3 ) { - continue; // bboxes don't intersect - } - - if ( ds->mapBrush == b ) { - int s; - - s = ds->side - b->sides; - if ( s <= 6 ) { // not one of the reversed inside faces - // this is a visible fog plane - if ( fog->visibleSide != -1 ) { - _printf( "WARNING: fog brush %i has multiple visible sides\n", b->brushnum ); - } - fog->visibleSide = s; - } - } - - if ( ds->miscModel ) { - // we could write splitting code for trimodels if we wanted to... - c_fogged++; - ds->fogNum = numFogs - 1; - } else if ( ds->patch ) { - if ( ChopPatchByBrush( ds, b ) ) { - c_fogged++; - ds->fogNum = numFogs - 1; - } - } else { - if ( ChopFaceByBrush( ds, b ) ) { - c_fogged++; - ds->fogNum = numFogs - 1; - } - } - } - } - - // split the drawsurfs by the fog brushes - - qprintf( "%5i fogs\n", numFogs ); - qprintf( "%5i fog polygon fragments\n", c_fogFragment ); - qprintf( "%5i fog patch fragments\n", c_fogPatchFragments ); - qprintf( "%5i fogged drawsurfs\n", c_fogged ); -} |