diff options
author | tma <tma@edf5b092-35ff-0310-97b2-ce42778d08ea> | 2005-09-28 18:55:31 +0000 |
---|---|---|
committer | tma <tma@edf5b092-35ff-0310-97b2-ce42778d08ea> | 2005-09-28 18:55:31 +0000 |
commit | ec912002d3f75729c627cf467903c4607a529495 (patch) | |
tree | b944aa3ec6a159d4607b3bb25cb09640bca02ddb /q3map | |
parent | ea1ca0473a510a02fff82788a2a6c8d95a6bf2d3 (diff) | |
download | ioquake3-aero-ec912002d3f75729c627cf467903c4607a529495.tar.gz ioquake3-aero-ec912002d3f75729c627cf467903c4607a529495.zip |
* Removed q3map and associated common and libs directories
git-svn-id: svn://svn.icculus.org/quake3/trunk@123 edf5b092-35ff-0310-97b2-ce42778d08ea
Diffstat (limited to 'q3map')
36 files changed, 0 insertions, 31449 deletions
diff --git a/q3map/brush.c b/q3map/brush.c deleted file mode 100644 index 506bd1d..0000000 --- a/q3map/brush.c +++ /dev/null @@ -1,861 +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_active_brushes; - -int c_nodes; - -// if a brush just barely pokes onto the other side, -// let it slide by without chopping -#define PLANESIDE_EPSILON 0.001 -//0.1 - - - - -/* -================ -CountBrushList -================ -*/ -int CountBrushList (bspbrush_t *brushes) -{ - int c; - - c = 0; - for ( ; brushes ; brushes = brushes->next) - c++; - return c; -} - - -/* -================ -AllocBrush -================ -*/ -bspbrush_t *AllocBrush (int numsides) -{ - bspbrush_t *bb; - int c; - - c = (int)&(((bspbrush_t *)0)->sides[numsides]); - bb = malloc(c); - memset (bb, 0, c); - if (numthreads == 1) - c_active_brushes++; - return bb; -} - -/* -================ -FreeBrush -================ -*/ -void FreeBrush (bspbrush_t *brushes) -{ - int i; - - for (i=0 ; i<brushes->numsides ; i++) - if (brushes->sides[i].winding) - FreeWinding(brushes->sides[i].winding); - free (brushes); - if (numthreads == 1) - c_active_brushes--; -} - - -/* -================ -FreeBrushList -================ -*/ -void FreeBrushList (bspbrush_t *brushes) -{ - bspbrush_t *next; - - for ( ; brushes ; brushes = next) - { - next = brushes->next; - - FreeBrush (brushes); - } -} - -/* -================== -CopyBrush - -Duplicates the brush, the sides, and the windings -================== -*/ -bspbrush_t *CopyBrush (bspbrush_t *brush) -{ - bspbrush_t *newbrush; - int size; - int i; - - size = (int)&(((bspbrush_t *)0)->sides[brush->numsides]); - - newbrush = AllocBrush (brush->numsides); - memcpy (newbrush, brush, size); - - for (i=0 ; i<brush->numsides ; i++) - { - if (brush->sides[i].winding) - newbrush->sides[i].winding = CopyWinding (brush->sides[i].winding); - } - - return newbrush; -} - - -/* -================ -DrawBrushList -================ -*/ -void DrawBrushList (bspbrush_t *brush) -{ - int i; - side_t *s; - - GLS_BeginScene (); - for ( ; brush ; brush=brush->next) - { - for (i=0 ; i<brush->numsides ; i++) - { - s = &brush->sides[i]; - if (!s->winding) - continue; - GLS_Winding (s->winding, 0); - } - } - GLS_EndScene (); -} - - - -/* -================ -WriteBrushList -================ -*/ -void WriteBrushList (char *name, bspbrush_t *brush, qboolean onlyvis) -{ - int i; - side_t *s; - FILE *f; - - qprintf ("writing %s\n", name); - f = SafeOpenWrite (name); - - for ( ; brush ; brush=brush->next) - { - for (i=0 ; i<brush->numsides ; i++) - { - s = &brush->sides[i]; - if (!s->winding) - continue; - if (onlyvis && !s->visible) - continue; - OutputWinding (brush->sides[i].winding, f); - } - } - - fclose (f); -} - - -/* -============= -PrintBrush -============= -*/ -void PrintBrush (bspbrush_t *brush) -{ - int i; - - _printf ("brush: %p\n", brush); - for (i=0;i<brush->numsides ; i++) - { - pw(brush->sides[i].winding); - _printf ("\n"); - } -} - -/* -================== -BoundBrush - -Sets the mins/maxs based on the windings -returns false if the brush doesn't enclose a valid volume -================== -*/ -qboolean BoundBrush (bspbrush_t *brush) -{ - int i, j; - winding_t *w; - - ClearBounds (brush->mins, brush->maxs); - for (i=0 ; i<brush->numsides ; i++) - { - w = brush->sides[i].winding; - if (!w) - continue; - for (j=0 ; j<w->numpoints ; j++) - AddPointToBounds (w->p[j], brush->mins, brush->maxs); - } - - for (i=0 ; i<3 ; i++) { - if (brush->mins[i] < MIN_WORLD_COORD || brush->maxs[i] > MAX_WORLD_COORD - || brush->mins[i] >= brush->maxs[i] ) { - return qfalse; - } - } - - return qtrue; -} - -/* -================== -CreateBrushWindings - -makes basewindigs for sides and mins / maxs for the brush -returns false if the brush doesn't enclose a valid volume -================== -*/ -qboolean CreateBrushWindings (bspbrush_t *brush) -{ - int i, j; - winding_t *w; - side_t *side; - plane_t *plane; - - for ( i = 0; i < brush->numsides; i++ ) - { - side = &brush->sides[i]; - // don't create a winding for a bevel - if ( side->bevel ) { - continue; - } - plane = &mapplanes[side->planenum]; - w = BaseWindingForPlane (plane->normal, plane->dist); - for ( j = 0; j < brush->numsides && w; j++ ) - { - if (i == j) - continue; - if ( brush->sides[j].planenum == ( brush->sides[i].planenum ^ 1 ) ) - continue; // back side clipaway - if (brush->sides[j].bevel) - continue; - if (brush->sides[j].backSide) - continue; - plane = &mapplanes[brush->sides[j].planenum^1]; - ChopWindingInPlace (&w, plane->normal, plane->dist, 0); //CLIP_EPSILON); - } - // free any existing winding - if ( side->winding ) { - FreeWinding( side->winding ); - } - side->winding = w; - } - - return BoundBrush (brush); -} - -/* -================== -BrushFromBounds - -Creates a new axial brush -================== -*/ -bspbrush_t *BrushFromBounds (vec3_t mins, vec3_t maxs) -{ - bspbrush_t *b; - int i; - vec3_t normal; - vec_t dist; - - b = AllocBrush (6); - b->numsides = 6; - for (i=0 ; i<3 ; i++) - { - VectorClear (normal); - normal[i] = 1; - dist = maxs[i]; - b->sides[i].planenum = FindFloatPlane (normal, dist); - - normal[i] = -1; - dist = -mins[i]; - b->sides[3+i].planenum = FindFloatPlane (normal, dist); - } - - CreateBrushWindings (b); - - return b; -} - -/* -================== -BrushVolume - -================== -*/ -vec_t BrushVolume (bspbrush_t *brush) -{ - int i; - winding_t *w; - vec3_t corner; - vec_t d, area, volume; - plane_t *plane; - - if (!brush) - return 0; - - // grab the first valid point as the corner - - w = NULL; - for (i=0 ; i<brush->numsides ; i++) - { - w = brush->sides[i].winding; - if (w) - break; - } - if (!w) - return 0; - VectorCopy (w->p[0], corner); - - // make tetrahedrons to all other faces - - volume = 0; - for ( ; i<brush->numsides ; i++) - { - w = brush->sides[i].winding; - if (!w) - continue; - plane = &mapplanes[brush->sides[i].planenum]; - d = -(DotProduct (corner, plane->normal) - plane->dist); - area = WindingArea (w); - volume += d*area; - } - - volume /= 3; - return volume; -} - - -/* -================== -WriteBspBrushMap -================== -*/ -void WriteBspBrushMap (char *name, bspbrush_t *list) -{ - FILE *f; - side_t *s; - int i; - winding_t *w; - - _printf ("writing %s\n", name); - f = fopen (name, "wb"); - if (!f) - Error ("Can't write %s\b", name); - - fprintf (f, "{\n\"classname\" \"worldspawn\"\n"); - - for ( ; list ; list=list->next ) - { - fprintf (f, "{\n"); - for (i=0,s=list->sides ; i<list->numsides ; i++,s++) - { - w = BaseWindingForPlane (mapplanes[s->planenum].normal, mapplanes[s->planenum].dist); - - fprintf (f,"( %i %i %i ) ", (int)w->p[0][0], (int)w->p[0][1], (int)w->p[0][2]); - fprintf (f,"( %i %i %i ) ", (int)w->p[1][0], (int)w->p[1][1], (int)w->p[1][2]); - fprintf (f,"( %i %i %i ) ", (int)w->p[2][0], (int)w->p[2][1], (int)w->p[2][2]); - - fprintf (f, "notexture 0 0 0 1 1\n" ); - FreeWinding (w); - } - fprintf (f, "}\n"); - } - fprintf (f, "}\n"); - - fclose (f); - -} - - -//===================================================================================== - -/* -==================== -FilterBrushIntoTree_r - -==================== -*/ -int FilterBrushIntoTree_r( bspbrush_t *b, node_t *node ) { - bspbrush_t *front, *back; - int c; - - if ( !b ) { - return 0; - } - - // add it to the leaf list - if ( node->planenum == PLANENUM_LEAF ) { - b->next = node->brushlist; - node->brushlist = b; - - // classify the leaf by the structural brush - if ( !b->detail ) { - if ( b->opaque ) { - node->opaque = qtrue; - node->areaportal = qfalse; - } else if ( b->contents & CONTENTS_AREAPORTAL ) { - if ( !node->opaque ) { - node->areaportal = qtrue; - } - } - } - - return 1; - } - - // split it by the node plane - SplitBrush ( b, node->planenum, &front, &back ); - FreeBrush( b ); - - c = 0; - c += FilterBrushIntoTree_r( front, node->children[0] ); - c += FilterBrushIntoTree_r( back, node->children[1] ); - - return c; -} - -/* -===================== -FilterDetailBrushesIntoTree - -Fragment all the detail brushes into the structural leafs -===================== -*/ -void FilterDetailBrushesIntoTree( entity_t *e, tree_t *tree ) { - bspbrush_t *b, *newb; - int r; - int c_unique, c_clusters; - int i; - - qprintf( "----- FilterDetailBrushesIntoTree -----\n"); - - c_unique = 0; - c_clusters = 0; - for ( b = e->brushes ; b ; b = b->next ) { - if ( !b->detail ) { - continue; - } - c_unique++; - newb = CopyBrush( b ); - r = FilterBrushIntoTree_r( newb, tree->headnode ); - c_clusters += r; - - // mark all sides as visible so drawsurfs are created - if ( r ) { - for ( i = 0 ; i < b->numsides ; i++ ) { - if ( b->sides[i].winding ) { - b->sides[i].visible = qtrue; - } - } - } - } - - qprintf( "%5i detail brushes\n", c_unique ); - qprintf( "%5i cluster references\n", c_clusters ); -} - -/* -===================== -FilterStructuralBrushesIntoTree - -Mark the leafs as opaque and areaportals -===================== -*/ -void FilterStructuralBrushesIntoTree( entity_t *e, tree_t *tree ) { - bspbrush_t *b, *newb; - int r; - int c_unique, c_clusters; - int i; - - qprintf( "----- FilterStructuralBrushesIntoTree -----\n"); - - c_unique = 0; - c_clusters = 0; - for ( b = e->brushes ; b ; b = b->next ) { - if ( b->detail ) { - continue; - } - c_unique++; - newb = CopyBrush( b ); - r = FilterBrushIntoTree_r( newb, tree->headnode ); - c_clusters += r; - - // mark all sides as visible so drawsurfs are created - if ( r ) { - for ( i = 0 ; i < b->numsides ; i++ ) { - if ( b->sides[i].winding ) { - b->sides[i].visible = qtrue; - } - } - } - } - - qprintf( "%5i structural brushes\n", c_unique ); - qprintf( "%5i cluster references\n", c_clusters ); -} - - - -/* -================ -AllocTree -================ -*/ -tree_t *AllocTree (void) -{ - tree_t *tree; - - tree = malloc(sizeof(*tree)); - memset (tree, 0, sizeof(*tree)); - ClearBounds (tree->mins, tree->maxs); - - return tree; -} - -/* -================ -AllocNode -================ -*/ -node_t *AllocNode (void) -{ - node_t *node; - - node = malloc(sizeof(*node)); - memset (node, 0, sizeof(*node)); - - return node; -} - - -/* -================ -WindingIsTiny - -Returns true if the winding would be crunched out of -existance by the vertex snapping. -================ -*/ -#define EDGE_LENGTH 0.2 -qboolean WindingIsTiny (winding_t *w) -{ -/* - if (WindingArea (w) < 1) - return qtrue; - return qfalse; -*/ - int i, j; - vec_t len; - vec3_t delta; - int edges; - - edges = 0; - for (i=0 ; i<w->numpoints ; i++) - { - j = i == w->numpoints - 1 ? 0 : i+1; - VectorSubtract (w->p[j], w->p[i], delta); - len = VectorLength (delta); - if (len > EDGE_LENGTH) - { - if (++edges == 3) - return qfalse; - } - } - return qtrue; -} - -/* -================ -WindingIsHuge - -Returns true if the winding still has one of the points -from basewinding for plane -================ -*/ -qboolean WindingIsHuge (winding_t *w) -{ - int i, j; - - for (i=0 ; i<w->numpoints ; i++) - { - for (j=0 ; j<3 ; j++) - if (w->p[i][j] <= MIN_WORLD_COORD || w->p[i][j] >= MAX_WORLD_COORD) - return qtrue; - } - return qfalse; -} - -//============================================================ - -/* -================== -BrushMostlyOnSide - -================== -*/ -int BrushMostlyOnSide (bspbrush_t *brush, plane_t *plane) -{ - int i, j; - winding_t *w; - vec_t d, max; - int side; - - max = 0; - side = PSIDE_FRONT; - for (i=0 ; i<brush->numsides ; i++) - { - w = brush->sides[i].winding; - if (!w) - continue; - for (j=0 ; j<w->numpoints ; j++) - { - d = DotProduct (w->p[j], plane->normal) - plane->dist; - if (d > max) - { - max = d; - side = PSIDE_FRONT; - } - if (-d > max) - { - max = -d; - side = PSIDE_BACK; - } - } - } - return side; -} - -/* -================ -SplitBrush - -Generates two new brushes, leaving the original -unchanged -================ -*/ -void SplitBrush (bspbrush_t *brush, int planenum, - bspbrush_t **front, bspbrush_t **back) -{ - bspbrush_t *b[2]; - int i, j; - winding_t *w, *cw[2], *midwinding; - plane_t *plane, *plane2; - side_t *s, *cs; - float d, d_front, d_back; - - *front = *back = NULL; - plane = &mapplanes[planenum]; - - // check all points - d_front = d_back = 0; - for (i=0 ; i<brush->numsides ; i++) - { - w = brush->sides[i].winding; - if (!w) - continue; - for (j=0 ; j<w->numpoints ; j++) - { - d = DotProduct (w->p[j], plane->normal) - plane->dist; - if (d > 0 && d > d_front) - d_front = d; - if (d < 0 && d < d_back) - d_back = d; - } - } - if (d_front < 0.1) // PLANESIDE_EPSILON) - { // only on back - *back = CopyBrush (brush); - return; - } - if (d_back > -0.1) // PLANESIDE_EPSILON) - { // only on front - *front = CopyBrush (brush); - return; - } - - // create a new winding from the split plane - - w = BaseWindingForPlane (plane->normal, plane->dist); - for (i=0 ; i<brush->numsides && w ; i++) - { - if ( brush->sides[i].backSide ) { - continue; // fake back-sided polygons never split - } - plane2 = &mapplanes[brush->sides[i].planenum ^ 1]; - ChopWindingInPlace (&w, plane2->normal, plane2->dist, 0); // PLANESIDE_EPSILON); - } - - if (!w || WindingIsTiny (w) ) - { // the brush isn't really split - int side; - - side = BrushMostlyOnSide (brush, plane); - if (side == PSIDE_FRONT) - *front = CopyBrush (brush); - if (side == PSIDE_BACK) - *back = CopyBrush (brush); - return; - } - - if (WindingIsHuge (w)) - { - qprintf ("WARNING: huge winding\n"); - } - - midwinding = w; - - // split it for real - - for (i=0 ; i<2 ; i++) - { - b[i] = AllocBrush (brush->numsides+1); - memcpy( b[i], brush, sizeof( bspbrush_t ) - sizeof( brush->sides ) ); - b[i]->numsides = 0; - b[i]->next = NULL; - b[i]->original = brush->original; - } - - // split all the current windings - - for (i=0 ; i<brush->numsides ; i++) - { - s = &brush->sides[i]; - w = s->winding; - if (!w) - continue; - ClipWindingEpsilon (w, plane->normal, plane->dist, - 0 /*PLANESIDE_EPSILON*/, &cw[0], &cw[1]); - for (j=0 ; j<2 ; j++) - { - if (!cw[j]) - continue; -/* - if (WindingIsTiny (cw[j])) - { - FreeWinding (cw[j]); - continue; - } -*/ - cs = &b[j]->sides[b[j]->numsides]; - b[j]->numsides++; - *cs = *s; - cs->winding = cw[j]; - } - } - - - // see if we have valid polygons on both sides - - for (i=0 ; i<2 ; i++) - { - BoundBrush (b[i]); - for (j=0 ; j<3 ; j++) - { - if (b[i]->mins[j] < MIN_WORLD_COORD || b[i]->maxs[j] > MAX_WORLD_COORD) - { - qprintf ("bogus brush after clip\n"); - break; - } - } - - if (b[i]->numsides < 3 || j < 3) - { - FreeBrush (b[i]); - b[i] = NULL; - } - } - - if ( !(b[0] && b[1]) ) - { - if (!b[0] && !b[1]) - qprintf ("split removed brush\n"); - else - qprintf ("split not on both sides\n"); - if (b[0]) - { - FreeBrush (b[0]); - *front = CopyBrush (brush); - } - if (b[1]) - { - FreeBrush (b[1]); - *back = CopyBrush (brush); - } - return; - } - - // add the midwinding to both sides - for (i=0 ; i<2 ; i++) - { - cs = &b[i]->sides[b[i]->numsides]; - b[i]->numsides++; - - cs->planenum = planenum^i^1; - cs->shaderInfo = NULL; - if (i==0) - cs->winding = CopyWinding (midwinding); - else - cs->winding = midwinding; - } - -{ - vec_t v1; - int i; - - for (i=0 ; i<2 ; i++) - { - v1 = BrushVolume (b[i]); - if (v1 < 1.0) - { - FreeBrush (b[i]); - b[i] = NULL; -// qprintf ("tiny volume after clip\n"); - } - } -} - - *front = b[0]; - *back = b[1]; -} diff --git a/q3map/brush_primit.c b/q3map/brush_primit.c deleted file mode 100644 index 198e90e..0000000 --- a/q3map/brush_primit.c +++ /dev/null @@ -1,52 +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" - - -// global flag -int g_bBrushPrimit; - -// NOTE : ComputeAxisBase here and in editor code must always BE THE SAME ! -// WARNING : special case behaviour of atan2(y,x) <-> atan(y/x) might not be the same everywhere when x == 0 -// rotation by (0,RotY,RotZ) assigns X to normal -void ComputeAxisBase(vec3_t normal,vec3_t texX,vec3_t texY) -{ - vec_t RotY,RotZ; - // do some cleaning - if (fabs(normal[0])<1e-6) - normal[0]=0.0f; - if (fabs(normal[1])<1e-6) - normal[1]=0.0f; - if (fabs(normal[2])<1e-6) - normal[2]=0.0f; - // compute the two rotations around Y and Z to rotate X to normal - RotY=-atan2(normal[2],sqrt(normal[1]*normal[1]+normal[0]*normal[0])); - RotZ=atan2(normal[1],normal[0]); - // rotate (0,1,0) and (0,0,1) to compute texX and texY - texX[0]=-sin(RotZ); - texX[1]=cos(RotZ); - texX[2]=0; - // the texY vector is along -Z ( T texture coorinates axis ) - texY[0]=-sin(RotY)*cos(RotZ); - texY[1]=-sin(RotY)*sin(RotZ); - texY[2]=-cos(RotY); -} diff --git a/q3map/bsp.c b/q3map/bsp.c deleted file mode 100644 index 2cf15bd..0000000 --- a/q3map/bsp.c +++ /dev/null @@ -1,605 +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" - -#ifdef _WIN32 -#ifdef _TTIMOBUILD -#include "pakstuff.h" -#else -#include "../libs/pakstuff.h" -#endif -extern HWND hwndOut; -#endif - -char source[1024]; -char tempsource[1024]; -char name[1024]; - -vec_t microvolume = 1.0; -qboolean glview; -qboolean nodetail; -qboolean fulldetail; -qboolean onlyents; -qboolean onlytextures; -qboolean nowater; -qboolean nofill; -qboolean noopt; -qboolean leaktest; -qboolean verboseentities; -qboolean noCurveBrushes; -qboolean fakemap; -qboolean notjunc; -qboolean nomerge; -qboolean nofog; -qboolean nosubdivide; -qboolean testExpand; -qboolean showseams; - -char outbase[32]; - -int entity_num; - -/* -============ -ProcessWorldModel - -============ -*/ -void ProcessWorldModel( void ) { - entity_t *e; - tree_t *tree; - bspface_t *faces; - qboolean leaked; - - BeginModel(); - - e = &entities[0]; - e->firstDrawSurf = 0;//numMapDrawSurfs; - - // check for patches with adjacent edges that need to LOD together - PatchMapDrawSurfs( e ); - - // build an initial bsp tree using all of the sides - // of all of the structural brushes - faces = MakeStructuralBspFaceList ( entities[0].brushes ); - tree = FaceBSP( faces ); - MakeTreePortals (tree); - FilterStructuralBrushesIntoTree( e, tree ); - - // see if the bsp is completely enclosed - if ( FloodEntities (tree) ) { - // rebuild a better bsp tree using only the - // sides that are visible from the inside - FillOutside (tree->headnode); - - // chop the sides to the convex hull of - // their visible fragments, giving us the smallest - // polygons - ClipSidesIntoTree( e, tree ); - - faces = MakeVisibleBspFaceList( entities[0].brushes ); - FreeTree (tree); - tree = FaceBSP( faces ); - MakeTreePortals( tree ); - FilterStructuralBrushesIntoTree( e, tree ); - leaked = qfalse; - } else { - _printf ("**********************\n"); - _printf ("******* leaked *******\n"); - _printf ("**********************\n"); - LeakFile (tree); - if ( leaktest ) { - _printf ("--- MAP LEAKED, ABORTING LEAKTEST ---\n"); - exit (0); - } - leaked = qtrue; - - // chop the sides to the convex hull of - // their visible fragments, giving us the smallest - // polygons - ClipSidesIntoTree( e, tree ); - } - - // save out information for visibility processing - NumberClusters( tree ); - if ( !leaked ) { - WritePortalFile( tree ); - } - if ( glview ) { - // dump the portals for debugging - WriteGLView( tree, source ); - } - FloodAreas (tree); - - // add references to the detail brushes - FilterDetailBrushesIntoTree( e, tree ); - - // create drawsurfs for triangle models - AddTriangleModels( tree ); - - // drawsurfs that cross fog boundaries will need to - // be split along the bound - if ( !nofog ) { - FogDrawSurfs(); // may fragment drawsurfs - } - - // subdivide each drawsurf as required by shader tesselation - if ( !nosubdivide ) { - SubdivideDrawSurfs( e, tree ); - } - - // merge together all common shaders on the same plane and remove - // all colinear points, so extra tjunctions won't be generated - if ( !nomerge ) { - MergeSides( e, tree ); // !@# testing - } - - // add in any vertexes required to fix tjunctions - if ( !notjunc ) { - FixTJunctions( e ); - } - - // allocate lightmaps for faces and patches - AllocateLightmaps( e ); - - // add references to the final drawsurfs in the apropriate clusters - FilterDrawsurfsIntoTree( e, tree ); - - EndModel( tree->headnode ); - - FreeTree (tree); -} - -/* -============ -ProcessSubModel - -============ -*/ -void ProcessSubModel( void ) { - entity_t *e; - tree_t *tree; - bspbrush_t *b, *bc; - node_t *node; - - BeginModel (); - - e = &entities[entity_num]; - e->firstDrawSurf = numMapDrawSurfs; - - PatchMapDrawSurfs( e ); - - // just put all the brushes in an empty leaf - // FIXME: patches? - node = AllocNode(); - node->planenum = PLANENUM_LEAF; - for ( b = e->brushes ; b ; b = b->next ) { - bc = CopyBrush( b ); - bc->next = node->brushlist; - node->brushlist = bc; - } - - tree = AllocTree(); - tree->headnode = node; - - ClipSidesIntoTree( e, tree ); - - // subdivide each drawsurf as required by shader tesselation or fog - if ( !nosubdivide ) { - SubdivideDrawSurfs( e, tree ); - } - - // merge together all common shaders on the same plane and remove - // all colinear points, so extra tjunctions won't be generated - if ( !nomerge ) { - MergeSides( e, tree ); // !@# testing - } - - // add in any vertexes required to fix tjunctions - if ( !notjunc ) { - FixTJunctions( e ); - } - - // allocate lightmaps for faces and patches - AllocateLightmaps( e ); - - // add references to the final drawsurfs in the apropriate clusters - FilterDrawsurfsIntoTree( e, tree ); - - EndModel ( node ); - - FreeTree( tree ); -} - - -/* -============ -ProcessModels -============ -*/ -void ProcessModels (void) -{ - qboolean oldVerbose; - entity_t *entity; - - oldVerbose = verbose; - - BeginBSPFile (); - - for ( entity_num=0 ; entity_num< num_entities ; entity_num++ ) { - entity = &entities[entity_num]; - - if ( !entity->brushes && !entity->patches ) { - continue; - } - - qprintf ("############### model %i ###############\n", nummodels); - if (entity_num == 0) - ProcessWorldModel (); - else - ProcessSubModel (); - - if (!verboseentities) - verbose = qfalse; // don't bother printing submodels - } - - verbose = oldVerbose; -} - -/* -============ -Bspinfo -============ -*/ -void Bspinfo( int count, char **fileNames ) { - int i; - char source[1024]; - int size; - FILE *f; - - if ( count < 1 ) { - _printf( "No files to dump info for.\n"); - return; - } - - for ( i = 0 ; i < count ; i++ ) { - _printf ("---------------------\n"); - strcpy (source, fileNames[ i ] ); - DefaultExtension (source, ".bsp"); - f = fopen (source, "rb"); - if (f) - { - size = Q_filelength (f); - fclose (f); - } - else - size = 0; - _printf ("%s: %i\n", source, size); - - LoadBSPFile (source); - PrintBSPFileSizes (); - _printf ("---------------------\n"); - } -} - - -/* -============ -OnlyEnts -============ -*/ -void OnlyEnts( void ) { - char out[1024]; - - sprintf (out, "%s.bsp", source); - LoadBSPFile (out); - num_entities = 0; - - LoadMapFile (name); - SetModelNumbers (); - SetLightStyles (); - - UnparseEntities (); - - WriteBSPFile (out); -} - - -/* -============ -OnlyTextures -============ -*/ -void OnlyTextures( void ) { // FIXME!!! - char out[1024]; - int i; - - Error( "-onlytextures isn't working now..." ); - - sprintf (out, "%s.bsp", source); - - LoadMapFile (name); - - LoadBSPFile (out); - - // replace all the drawsurface shader names - for ( i = 0 ; i < numDrawSurfaces ; i++ ) { - } - - WriteBSPFile (out); -} - - -/* -============ -main -============ -*/ -int LightMain( int argc, char **argv ); -int VLightMain (int argc, char **argv); -int VSoundMain (int argc, char **argv); -int VisMain( int argc, char **argv ); - -int main (int argc, char **argv) { - int i; - double start, end; - char path[1024]; - - _printf ("Q3Map v1.0s (c) 1999 Id Software Inc.\n"); - - if ( argc < 2 ) { - Error ("usage: q3map [options] mapfile"); - } - - // check for general program options - if (!strcmp(argv[1], "-info")) { - Bspinfo( argc - 2, argv + 2 ); - return 0; - } - if (!strcmp(argv[1], "-light")) { - LightMain( argc - 1, argv + 1 ); - return 0; - } - if (!strcmp(argv[1], "-vlight")) { - VLightMain( argc - 1, argv + 1 ); - return 0; - } - if (!strcmp(argv[1], "-vsound")) { - VSoundMain( argc - 1, argv + 1 ); - return 0; - } - if (!strcmp(argv[1], "-vis")) { - VisMain( argc - 1, argv + 1 ); - return 0; - } - - // do a bsp if nothing else was specified - - _printf ("---- q3map ----\n"); - - tempsource[0] = '\0'; - - for (i=1 ; i<argc ; i++) - { - if (!strcmp(argv[i],"-tempname")) - { - strcpy(tempsource, argv[++i]); - } - else if (!strcmp(argv[i],"-threads")) - { - numthreads = atoi (argv[i+1]); - i++; - } - else if (!strcmp(argv[i],"-glview")) - { - glview = qtrue; - } - else if (!strcmp(argv[i], "-v")) - { - _printf ("verbose = true\n"); - verbose = qtrue; - } - else if (!strcmp(argv[i], "-draw")) - { - _printf ("drawflag = true\n"); - drawflag = qtrue; - } - else if (!strcmp(argv[i], "-nowater")) - { - _printf ("nowater = true\n"); - nowater = qtrue; - } - else if (!strcmp(argv[i], "-noopt")) - { - _printf ("noopt = true\n"); - noopt = qtrue; - } - else if (!strcmp(argv[i], "-nofill")) - { - _printf ("nofill = true\n"); - nofill = qtrue; - } - else if (!strcmp(argv[i], "-nodetail")) - { - _printf ("nodetail = true\n"); - nodetail = qtrue; - } - else if (!strcmp(argv[i], "-fulldetail")) - { - _printf ("fulldetail = true\n"); - fulldetail = qtrue; - } - else if (!strcmp(argv[i], "-onlyents")) - { - _printf ("onlyents = true\n"); - onlyents = qtrue; - } - else if (!strcmp(argv[i], "-onlytextures")) - { - _printf ("onlytextures = true\n"); // FIXME: make work again! - onlytextures = qtrue; - } - else if (!strcmp(argv[i], "-micro")) - { - microvolume = atof(argv[i+1]); - _printf ("microvolume = %f\n", microvolume); - i++; - } - else if (!strcmp(argv[i], "-nofog")) - { - _printf ("nofog = true\n"); - nofog = qtrue; - } - else if (!strcmp(argv[i], "-nosubdivide")) - { - _printf ("nosubdivide = true\n"); - nosubdivide = qtrue; - } - else if (!strcmp(argv[i], "-leaktest")) - { - _printf ("leaktest = true\n"); - leaktest = qtrue; - } - else if (!strcmp(argv[i], "-verboseentities")) - { - _printf ("verboseentities = true\n"); - verboseentities = qtrue; - } - else if (!strcmp(argv[i], "-nocurves")) - { - noCurveBrushes = qtrue; - _printf ("no curve brushes\n"); - } - else if (!strcmp(argv[i], "-notjunc")) - { - notjunc = qtrue; - _printf ("no tjunction fixing\n"); - } - else if (!strcmp(argv[i], "-expand")) - { - testExpand = qtrue; - _printf ("Writing expanded.map.\n"); - } - else if (!strcmp(argv[i], "-showseams")) - { - showseams = qtrue; - _printf ("Showing seams on terrain.\n"); - } - else if (!strcmp (argv[i],"-tmpout")) - { - strcpy (outbase, "/tmp"); - } - else if (!strcmp (argv[i],"-fakemap")) - { - fakemap = qtrue; - _printf( "will generate fakemap.map\n"); - } - else if (!strcmp(argv[i], "-samplesize")) - { - samplesize = atoi(argv[i+1]); - if (samplesize < 1) samplesize = 1; - i++; - _printf("lightmap sample size is %dx%d units\n", samplesize, samplesize); - } - else if (argv[i][0] == '-') - Error ("Unknown option \"%s\"", argv[i]); - else - break; - } - - if (i != argc - 1) - Error ("usage: q3map [options] mapfile"); - - start = I_FloatTime (); - - ThreadSetDefault (); - //numthreads = 1; // multiple threads aren't helping because of heavy malloc use - SetQdirFromPath (argv[i]); - -#ifdef _WIN32 - InitPakFile(gamedir, NULL); -#endif - - strcpy (source, ExpandArg (argv[i])); - StripExtension (source); - - // delete portal and line files - sprintf (path, "%s.prt", source); - remove (path); - sprintf (path, "%s.lin", source); - remove (path); - - strcpy (name, ExpandArg (argv[i])); - if ( strcmp(name + strlen(name) - 4, ".reg" ) ) { - // if we are doing a full map, delete the last saved region map - sprintf (path, "%s.reg", source); - remove (path); - - DefaultExtension (name, ".map"); // might be .reg - } - - // - // if onlyents, just grab the entites and resave - // - if ( onlyents ) { - OnlyEnts(); - return 0; - } - - // - // if onlytextures, just grab the textures and resave - // - if ( onlytextures ) { - OnlyTextures(); - return 0; - } - - // - // start from scratch - // - LoadShaderInfo(); - - // load original file from temp spot in case it was renamed by the editor on the way in - if (strlen(tempsource) > 0) { - LoadMapFile (tempsource); - } else { - LoadMapFile (name); - } - - SetModelNumbers (); - SetLightStyles (); - - ProcessModels (); - - EndBSPFile(); - - end = I_FloatTime (); - _printf ("%5.0f seconds elapsed\n", end-start); - - // remove temp name if appropriate - if (strlen(tempsource) > 0) { - remove(tempsource); - } - - return 0; -} - diff --git a/q3map/facebsp.c b/q3map/facebsp.c deleted file mode 100644 index a146a21..0000000 --- a/q3map/facebsp.c +++ /dev/null @@ -1,379 +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_faceLeafs; - - -/* -================ -AllocBspFace -================ -*/ -bspface_t *AllocBspFace( void ) { - bspface_t *f; - - f = malloc(sizeof(*f)); - memset( f, 0, sizeof(*f) ); - - return f; -} - -/* -================ -FreeBspFace -================ -*/ -void FreeBspFace( bspface_t *f ) { - if ( f->w ) { - FreeWinding( f->w ); - } - free( f ); -} - - -/* -================ -SelectSplitPlaneNum -================ -*/ -int hintsplit; - -#define BLOCK_SIZE 1024 -int SelectSplitPlaneNum( node_t *node, bspface_t *list ) { - bspface_t *split; - bspface_t *check; - bspface_t *bestSplit; - int splits, facing, front, back; - int side; - plane_t *plane; - int value, bestValue; - int i; - vec3_t normal; - float dist; - int planenum; - - hintsplit = qfalse; - // if it is crossing a 1k block boundary, force a split - for ( i = 0 ; i < 2 ; i++ ) { - dist = BLOCK_SIZE * ( floor( node->mins[i] / BLOCK_SIZE ) + 1 ); - if ( node->maxs[i] > dist ) { - VectorClear( normal ); - normal[i] = 1; - planenum = FindFloatPlane( normal, dist ); - return planenum; - } - } - - // pick one of the face planes - bestValue = -99999; - bestSplit = list; - - for ( split = list ; split ; split = split->next ) { - split->checked = qfalse; - } - - for ( split = list ; split ; split = split->next ) { - if ( split->checked ) { - continue; - } - plane = &mapplanes[ split->planenum ]; - splits = 0; - facing = 0; - front = 0; - back = 0; - for ( check = list ; check ; check = check->next ) { - if ( check->planenum == split->planenum ) { - facing++; - check->checked = qtrue; // won't need to test this plane again - continue; - } - side = WindingOnPlaneSide( check->w, plane->normal, plane->dist ); - if ( side == SIDE_CROSS ) { - splits++; - } else if ( side == SIDE_FRONT ) { - front++; - } else if ( side == SIDE_BACK ) { - back++; - } - } - value = 5*facing - 5*splits; // - abs(front-back); - if ( plane->type < 3 ) { - value+=5; // axial is better - } - value += split->priority; // prioritize hints higher - - if ( value > bestValue ) { - bestValue = value; - bestSplit = split; - } - } - - if ( bestValue == -99999 ) { - return -1; - } - - if (bestSplit->hint) - hintsplit = qtrue; - - return bestSplit->planenum; -} - -int CountFaceList( bspface_t *list ) { - int c; - c = 0; - for ( ; list ; list = list->next ) { - c++; - } - return c; -} - -/* -================ -BuildFaceTree_r -================ -*/ -void BuildFaceTree_r( node_t *node, bspface_t *list ) { - bspface_t *split; - bspface_t *next; - int side; - plane_t *plane; - bspface_t *newFace; - bspface_t *childLists[2]; - winding_t *frontWinding, *backWinding; - int i; - int splitPlaneNum; - - i = CountFaceList( list ); - - splitPlaneNum = SelectSplitPlaneNum( node, list ); - // if we don't have any more faces, this is a node - if ( splitPlaneNum == -1 ) { - node->planenum = PLANENUM_LEAF; - c_faceLeafs++; - return; - } - - // partition the list - node->planenum = splitPlaneNum; - node->hint = hintsplit; - plane = &mapplanes[ splitPlaneNum ]; - childLists[0] = NULL; - childLists[1] = NULL; - for ( split = list ; split ; split = next ) { - next = split->next; - - if ( split->planenum == node->planenum ) { - FreeBspFace( split ); - continue; - } - - side = WindingOnPlaneSide( split->w, plane->normal, plane->dist ); - - if ( side == SIDE_CROSS ) { - ClipWindingEpsilon( split->w, plane->normal, plane->dist, CLIP_EPSILON * 2, - &frontWinding, &backWinding ); - if ( frontWinding ) { - newFace = AllocBspFace(); - newFace->w = frontWinding; - newFace->next = childLists[0]; - newFace->planenum = split->planenum; - newFace->priority = split->priority; - newFace->hint = split->hint; - childLists[0] = newFace; - } - if ( backWinding ) { - newFace = AllocBspFace(); - newFace->w = backWinding; - newFace->next = childLists[1]; - newFace->planenum = split->planenum; - newFace->priority = split->priority; - newFace->hint = split->hint; - childLists[1] = newFace; - } - FreeBspFace( split ); - } else if ( side == SIDE_FRONT ) { - split->next = childLists[0]; - childLists[0] = split; - } else if ( side == SIDE_BACK ) { - split->next = childLists[1]; - childLists[1] = split; - } - } - - - // recursively process children - for ( i = 0 ; i < 2 ; i++ ) { - node->children[i] = AllocNode(); - node->children[i]->parent = node; - VectorCopy( node->mins, node->children[i]->mins ); - VectorCopy( node->maxs, node->children[i]->maxs ); - } - - for ( i = 0 ; i < 3 ; i++ ) { - if ( plane->normal[i] == 1 ) { - node->children[0]->mins[i] = plane->dist; - node->children[1]->maxs[i] = plane->dist; - break; - } - } - - for ( i = 0 ; i < 2 ; i++ ) { - BuildFaceTree_r ( node->children[i], childLists[i]); - } -} - - -/* -================ -FaceBSP - -List will be freed before returning -================ -*/ -tree_t *FaceBSP( bspface_t *list ) { - tree_t *tree; - bspface_t *face; - int i; - int count; - - qprintf( "--- FaceBSP ---\n" ); - - tree = AllocTree (); - - count = 0; - for ( face = list ; face ; face = face->next ) { - count++; - for ( i = 0 ; i < face->w->numpoints ; i++ ) { - AddPointToBounds( face->w->p[i], tree->mins, tree->maxs); - } - } - qprintf( "%5i faces\n", count ); - - tree->headnode = AllocNode(); - VectorCopy( tree->mins, tree->headnode->mins ); - VectorCopy( tree->maxs, tree->headnode->maxs ); - c_faceLeafs = 0; - - BuildFaceTree_r ( tree->headnode, list ); - - qprintf( "%5i leafs\n", c_faceLeafs ); - - return tree; -} - - -/* -================= -BspFaceForPortal -================= -*/ -bspface_t *BspFaceForPortal( portal_t *p ) { - bspface_t *f; - - f = AllocBspFace(); - f->w = CopyWinding( p->winding ); - f->planenum = p->onnode->planenum & ~1; - - return f; -} - - - -/* -================= -MakeStructuralBspFaceList -================= -*/ -bspface_t *MakeStructuralBspFaceList( bspbrush_t *list ) { - bspbrush_t *b; - int i; - side_t *s; - winding_t *w; - bspface_t *f, *flist; - - flist = NULL; - for ( b = list ; b ; b = b->next ) { - if ( b->detail ) { - continue; - } - for ( i = 0 ; i < b->numsides ; i++ ) { - s = &b->sides[i]; - w = s->winding; - if ( !w ) { - continue; - } - f = AllocBspFace(); - f->w = CopyWinding( w ); - f->planenum = s->planenum & ~1; - f->next = flist; - if (s->surfaceFlags & SURF_HINT) { - //f->priority = HINT_PRIORITY; - f->hint = qtrue; - } - flist = f; - } - } - - return flist; -} - -/* -================= -MakeVisibleBspFaceList -================= -*/ -bspface_t *MakeVisibleBspFaceList( bspbrush_t *list ) { - bspbrush_t *b; - int i; - side_t *s; - winding_t *w; - bspface_t *f, *flist; - - flist = NULL; - for ( b = list ; b ; b = b->next ) { - if ( b->detail ) { - continue; - } - for ( i = 0 ; i < b->numsides ; i++ ) { - s = &b->sides[i]; - w = s->visibleHull; - if ( !w ) { - continue; - } - f = AllocBspFace(); - f->w = CopyWinding( w ); - f->planenum = s->planenum & ~1; - f->next = flist; - if (s->surfaceFlags & SURF_HINT) { - //f->priority = HINT_PRIORITY; - f->hint = qtrue; - } - flist = f; - } - } - - return flist; -} - 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 ); -} diff --git a/q3map/gldraw.c b/q3map/gldraw.c deleted file mode 100644 index 80620a4..0000000 --- a/q3map/gldraw.c +++ /dev/null @@ -1,232 +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 <windows.h> -#include <GL/gl.h> -#include <GL/glu.h> -#include <GL/glaux.h> - -#include "qbsp.h" - -// can't use the glvertex3fv functions, because the vec3_t fields -// could be either floats or doubles, depending on DOUBLEVEC_T - -qboolean drawflag; -vec3_t draw_mins, draw_maxs; - - -#define WIN_SIZE 512 - -void InitWindow (void) -{ - auxInitDisplayMode (AUX_SINGLE | AUX_RGB); - auxInitPosition (0, 0, WIN_SIZE, WIN_SIZE); - auxInitWindow ("qcsg"); -} - -void Draw_ClearWindow (void) -{ - static int init; - int w, h, g; - vec_t mx, my; - - if (!drawflag) - return; - - if (!init) - { - init = qtrue; - InitWindow (); - } - - glClearColor (1,0.8,0.8,0); - glClear (GL_COLOR_BUFFER_BIT); - - w = (draw_maxs[0] - draw_mins[0]); - h = (draw_maxs[1] - draw_mins[1]); - - mx = draw_mins[0] + w/2; - my = draw_mins[1] + h/2; - - g = w > h ? w : h; - - glLoadIdentity (); - gluPerspective (90, 1, 2, 16384); - gluLookAt (mx, my, draw_maxs[2] + g/2, mx , my, draw_maxs[2], 0, 1, 0); - - glColor3f (0,0,0); -// glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); - glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); - glDisable (GL_DEPTH_TEST); - glEnable (GL_BLEND); - glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - -#if 0 - glColor4f (1,0,0,0.5); - glBegin (GL_POLYGON); - - glVertex3f (0, 500, 0); - glVertex3f (0, 900, 0); - glVertex3f (0, 900, 100); - glVertex3f (0, 500, 100); - - glEnd (); -#endif - - glFlush (); - -} - -void Draw_SetRed (void) -{ - if (!drawflag) - return; - - glColor3f (1,0,0); -} - -void Draw_SetGrey (void) -{ - if (!drawflag) - return; - - glColor3f (0.5,0.5,0.5); -} - -void Draw_SetBlack (void) -{ - if (!drawflag) - return; - - glColor3f (0,0,0); -} - -void DrawWinding (winding_t *w) -{ - int i; - - if (!drawflag) - return; - - glColor4f (0,0,0,0.5); - glBegin (GL_LINE_LOOP); - for (i=0 ; i<w->numpoints ; i++) - glVertex3f (w->p[i][0],w->p[i][1],w->p[i][2] ); - glEnd (); - - glColor4f (0,1,0,0.3); - glBegin (GL_POLYGON); - for (i=0 ; i<w->numpoints ; i++) - glVertex3f (w->p[i][0],w->p[i][1],w->p[i][2] ); - glEnd (); - - glFlush (); -} - -void DrawAuxWinding (winding_t *w) -{ - int i; - - if (!drawflag) - return; - - glColor4f (0,0,0,0.5); - glBegin (GL_LINE_LOOP); - for (i=0 ; i<w->numpoints ; i++) - glVertex3f (w->p[i][0],w->p[i][1],w->p[i][2] ); - glEnd (); - - glColor4f (1,0,0,0.3); - glBegin (GL_POLYGON); - for (i=0 ; i<w->numpoints ; i++) - glVertex3f (w->p[i][0],w->p[i][1],w->p[i][2] ); - glEnd (); - - glFlush (); -} - -//============================================================ - -#define GLSERV_PORT 25001 - -qboolean wins_init; -int draw_socket; - -void GLS_BeginScene (void) -{ - WSADATA winsockdata; - WORD wVersionRequested; - struct sockaddr_in address; - int r; - - if (!wins_init) - { - wins_init = qtrue; - - wVersionRequested = MAKEWORD(1, 1); - - r = WSAStartup (MAKEWORD(1, 1), &winsockdata); - - if (r) - Error ("Winsock initialization failed."); - - } - - // connect a socket to the server - - draw_socket = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP); - if (draw_socket == -1) - Error ("draw_socket failed"); - - address.sin_family = AF_INET; - address.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - address.sin_port = GLSERV_PORT; - r = connect (draw_socket, (struct sockaddr *)&address, sizeof(address)); - if (r == -1) - { - closesocket (draw_socket); - draw_socket = 0; - } -} - -void GLS_Winding (winding_t *w, int code) -{ - byte buf[1024]; - int i, j; - - if (!draw_socket) - return; - - ((int *)buf)[0] = w->numpoints; - ((int *)buf)[1] = code; - for (i=0 ; i<w->numpoints ; i++) - for (j=0 ; j<3 ; j++) - ((float *)buf)[2+i*3+j] = w->p[i][j]; - - send (draw_socket, buf, w->numpoints*12+8, 0); -} - -void GLS_EndScene (void) -{ - closesocket (draw_socket); - draw_socket = 0; -} diff --git a/q3map/glfile.c b/q3map/glfile.c deleted file mode 100644 index b00df75..0000000 --- a/q3map/glfile.c +++ /dev/null @@ -1,148 +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_glfaces; - -int PortalVisibleSides (portal_t *p) -{ - int fcon, bcon; - - if (!p->onnode) - return 0; // outside - - fcon = p->nodes[0]->opaque; - bcon = p->nodes[1]->opaque; - - // same contents never create a face - if (fcon == bcon) - return 0; - - if (!fcon) - return 1; - if (!bcon) - return 2; - return 0; -} - -void OutputWinding (winding_t *w, FILE *glview) -{ - static int level = 128; - vec_t light; - int i; - - fprintf (glview, "%i\n", w->numpoints); - level+=28; - light = (level&255)/255.0; - for (i=0 ; i<w->numpoints ; i++) - { - fprintf (glview, "%6.3f %6.3f %6.3f %6.3f %6.3f %6.3f\n", - w->p[i][0], - w->p[i][1], - w->p[i][2], - light, - light, - light); - } - fprintf (glview, "\n"); -} - -/* -============= -OutputPortal -============= -*/ -void OutputPortal (portal_t *p, FILE *glview) -{ - winding_t *w; - int sides; - - sides = PortalVisibleSides (p); - if (!sides) - return; - - c_glfaces++; - - w = p->winding; - - if (sides == 2) // back side - w = ReverseWinding (w); - - OutputWinding (w, glview); - - if (sides == 2) - FreeWinding(w); -} - -/* -============= -WriteGLView_r -============= -*/ -void WriteGLView_r (node_t *node, FILE *glview) -{ - portal_t *p, *nextp; - - if (node->planenum != PLANENUM_LEAF) - { - WriteGLView_r (node->children[0], glview); - WriteGLView_r (node->children[1], glview); - return; - } - - // write all the portals - for (p=node->portals ; p ; p=nextp) - { - if (p->nodes[0] == node) - { - OutputPortal (p, glview); - nextp = p->next[0]; - } - else - nextp = p->next[1]; - } -} - -/* -============= -WriteGLView -============= -*/ -void WriteGLView (tree_t *tree, char *source) -{ - char name[1024]; - FILE *glview; - - c_glfaces = 0; - sprintf (name, "%s%s.gl",outbase, source); - _printf ("Writing %s\n", name); - - glview = fopen (name, "w"); - if (!glview) - Error ("Couldn't open %s", name); - WriteGLView_r (tree->headnode, glview); - fclose (glview); - - _printf ("%5i c_glfaces\n", c_glfaces); -} - diff --git a/q3map/leakfile.c b/q3map/leakfile.c deleted file mode 100644 index 683c22a..0000000 --- a/q3map/leakfile.c +++ /dev/null @@ -1,100 +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" - -/* -============================================================================== - -LEAF FILE GENERATION - -Save out name.line for qe3 to read -============================================================================== -*/ - - -/* -============= -LeakFile - -Finds the shortest possible chain of portals -that leads from the outside leaf to a specifically -occupied leaf -============= -*/ -void LeakFile (tree_t *tree) -{ - vec3_t mid; - FILE *linefile; - char filename[1024]; - node_t *node; - int count; - - if (!tree->outside_node.occupied) - return; - - qprintf ("--- LeakFile ---\n"); - - // - // write the points to the file - // - sprintf (filename, "%s.lin", source); - linefile = fopen (filename, "w"); - if (!linefile) - Error ("Couldn't open %s\n", filename); - - count = 0; - node = &tree->outside_node; - while (node->occupied > 1) - { - int next; - portal_t *p, *nextportal; - node_t *nextnode; - int s; - - // find the best portal exit - next = node->occupied; - for (p=node->portals ; p ; p = p->next[!s]) - { - s = (p->nodes[0] == node); - if (p->nodes[s]->occupied - && p->nodes[s]->occupied < next) - { - nextportal = p; - nextnode = p->nodes[s]; - next = nextnode->occupied; - } - } - node = nextnode; - WindingCenter (nextportal->winding, mid); - fprintf (linefile, "%f %f %f\n", mid[0], mid[1], mid[2]); - count++; - } - // add the occupant center - GetVectorForKey (node->occupant, "origin", mid); - - fprintf (linefile, "%f %f %f\n", mid[0], mid[1], mid[2]); - qprintf ("%5i point linefile\n", count+1); - - fclose (linefile); -} - diff --git a/q3map/light.c b/q3map/light.c deleted file mode 100644 index 1563d58..0000000 --- a/q3map/light.c +++ /dev/null @@ -1,2149 +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 -=========================================================================== -*/ -// light.c - -#include "light.h" -#ifdef _WIN32 -#ifdef _TTIMOBUILD -#include "pakstuff.h" -#else -#include "../libs/pakstuff.h" -#endif -#endif - - -#define EXTRASCALE 2 - -typedef struct { - float plane[4]; - vec3_t origin; - vec3_t vectors[2]; - shaderInfo_t *si; -} filter_t; - -#define MAX_FILTERS 1024 -filter_t filters[MAX_FILTERS]; -int numFilters; - -extern char source[1024]; - -qboolean notrace; -qboolean patchshadows; -qboolean dump; -qboolean extra; -qboolean extraWide; -qboolean lightmapBorder; - -qboolean noSurfaces; - -int samplesize = 16; //sample size in units -int novertexlighting = 0; -int nogridlighting = 0; - -// for run time tweaking of all area sources in the level -float areaScale = 0.25; - -// for run time tweaking of all point sources in the level -float pointScale = 7500; - -qboolean exactPointToPolygon = qtrue; - -float formFactorValueScale = 3; - -float linearScale = 1.0 / 8000; - -light_t *lights; -int numPointLights; -int numAreaLights; - -FILE *dumpFile; - -int c_visible, c_occluded; - -//int defaultLightSubdivide = 128; // vary by surface size? -int defaultLightSubdivide = 999; // vary by surface size? - -vec3_t ambientColor; - -vec3_t surfaceOrigin[ MAX_MAP_DRAW_SURFS ]; -int entitySurface[ MAX_MAP_DRAW_SURFS ]; - -// 7,9,11 normalized to avoid being nearly coplanar with common faces -//vec3_t sunDirection = { 0.441835, 0.56807, 0.694313 }; -//vec3_t sunDirection = { 0.45, 0, 0.9 }; -//vec3_t sunDirection = { 0, 0, 1 }; - -// these are usually overrided by shader values -vec3_t sunDirection = { 0.45, 0.3, 0.9 }; -vec3_t sunLight = { 100, 100, 50 }; - - - -typedef struct { - dbrush_t *b; - vec3_t bounds[2]; -} skyBrush_t; - -int numSkyBrushes; -skyBrush_t skyBrushes[MAX_MAP_BRUSHES]; - - -/* - -the corners of a patch mesh will always be exactly at lightmap samples. -The dimensions of the lightmap will be equal to the average length of the control -mesh in each dimension divided by 2. -The lightmap sample points should correspond to the chosen subdivision points. - -*/ - -/* -=============================================================== - -SURFACE LOADING - -=============================================================== -*/ - -#define MAX_FACE_POINTS 128 - -/* -=============== -SubdivideAreaLight - -Subdivide area lights that are very large -A light that is subdivided will never backsplash, avoiding weird pools of light near edges -=============== -*/ -void SubdivideAreaLight( shaderInfo_t *ls, winding_t *w, vec3_t normal, - float areaSubdivide, qboolean backsplash ) { - float area, value, intensity; - light_t *dl, *dl2; - vec3_t mins, maxs; - int axis; - winding_t *front, *back; - vec3_t planeNormal; - float planeDist; - - if ( !w ) { - return; - } - - WindingBounds( w, mins, maxs ); - - // check for subdivision - for ( axis = 0 ; axis < 3 ; axis++ ) { - if ( maxs[axis] - mins[axis] > areaSubdivide ) { - VectorClear( planeNormal ); - planeNormal[axis] = 1; - planeDist = ( maxs[axis] + mins[axis] ) * 0.5; - ClipWindingEpsilon ( w, planeNormal, planeDist, ON_EPSILON, &front, &back ); - SubdivideAreaLight( ls, front, normal, areaSubdivide, qfalse ); - SubdivideAreaLight( ls, back, normal, areaSubdivide, qfalse ); - FreeWinding( w ); - return; - } - } - - // create a light from this - area = WindingArea (w); - if ( area <= 0 || area > 20000000 ) { - return; - } - - numAreaLights++; - dl = malloc(sizeof(*dl)); - memset (dl, 0, sizeof(*dl)); - dl->next = lights; - lights = dl; - dl->type = emit_area; - - WindingCenter( w, dl->origin ); - dl->w = w; - VectorCopy ( normal, dl->normal); - dl->dist = DotProduct( dl->origin, normal ); - - value = ls->value; - intensity = value * area * areaScale; - VectorAdd( dl->origin, dl->normal, dl->origin ); - - VectorCopy( ls->color, dl->color ); - - dl->photons = intensity; - - // emitColor is irrespective of the area - VectorScale( ls->color, value*formFactorValueScale*areaScale, dl->emitColor ); - - dl->si = ls; - - if ( ls->contents & CONTENTS_FOG ) { - dl->twosided = qtrue; - } - - // optionally create a point backsplash light - if ( backsplash && ls->backsplashFraction > 0 ) { - dl2 = malloc(sizeof(*dl)); - memset (dl2, 0, sizeof(*dl2)); - dl2->next = lights; - lights = dl2; - dl2->type = emit_point; - - VectorMA( dl->origin, ls->backsplashDistance, normal, dl2->origin ); - - VectorCopy( ls->color, dl2->color ); - - dl2->photons = dl->photons * ls->backsplashFraction; - dl2->si = ls; - } -} - - -/* -=============== -CountLightmaps -=============== -*/ -void CountLightmaps( void ) { - int count; - int i; - dsurface_t *ds; - - qprintf ("--- CountLightmaps ---\n"); - count = 0; - for ( i = 0 ; i < numDrawSurfaces ; i++ ) { - // see if this surface is light emiting - ds = &drawSurfaces[i]; - if ( ds->lightmapNum > count ) { - count = ds->lightmapNum; - } - } - - count++; - numLightBytes = count * LIGHTMAP_WIDTH * LIGHTMAP_HEIGHT * 3; - if ( numLightBytes > MAX_MAP_LIGHTING ) { - Error("MAX_MAP_LIGHTING exceeded"); - } - - qprintf( "%5i drawSurfaces\n", numDrawSurfaces ); - qprintf( "%5i lightmaps\n", count ); -} - -/* -=============== -CreateSurfaceLights - -This creates area lights -=============== -*/ -void CreateSurfaceLights( void ) { - int i, j, side; - dsurface_t *ds; - shaderInfo_t *ls; - winding_t *w; - cFacet_t *f; - light_t *dl; - vec3_t origin; - drawVert_t *dv; - int c_lightSurfaces; - float lightSubdivide; - vec3_t normal; - - qprintf ("--- CreateSurfaceLights ---\n"); - c_lightSurfaces = 0; - - for ( i = 0 ; i < numDrawSurfaces ; i++ ) { - // see if this surface is light emiting - ds = &drawSurfaces[i]; - - ls = ShaderInfoForShader( dshaders[ ds->shaderNum].shader ); - if ( ls->value == 0 ) { - continue; - } - - // determine how much we need to chop up the surface - if ( ls->lightSubdivide ) { - lightSubdivide = ls->lightSubdivide; - } else { - lightSubdivide = defaultLightSubdivide; - } - - c_lightSurfaces++; - - // an autosprite shader will become - // a point light instead of an area light - if ( ls->autosprite ) { - // autosprite geometry should only have four vertexes - if ( surfaceTest[i] ) { - // curve or misc_model - f = surfaceTest[i]->facets; - if ( surfaceTest[i]->numFacets != 1 || f->numBoundaries != 4 ) { - _printf( "WARNING: surface at (%i %i %i) has autosprite shader but isn't a quad\n", - (int)f->points[0], (int)f->points[1], (int)f->points[2] ); - } - VectorAdd( f->points[0], f->points[1], origin ); - VectorAdd( f->points[2], origin, origin ); - VectorAdd( f->points[3], origin, origin ); - VectorScale( origin, 0.25, origin ); - } else { - // normal polygon - dv = &drawVerts[ ds->firstVert ]; - if ( ds->numVerts != 4 ) { - _printf( "WARNING: surface at (%i %i %i) has autosprite shader but %i verts\n", - (int)dv->xyz[0], (int)dv->xyz[1], (int)dv->xyz[2] ); - continue; - } - - VectorAdd( dv[0].xyz, dv[1].xyz, origin ); - VectorAdd( dv[2].xyz, origin, origin ); - VectorAdd( dv[3].xyz, origin, origin ); - VectorScale( origin, 0.25, origin ); - } - - - numPointLights++; - dl = malloc(sizeof(*dl)); - memset (dl, 0, sizeof(*dl)); - dl->next = lights; - lights = dl; - - VectorCopy( origin, dl->origin ); - VectorCopy( ls->color, dl->color ); - dl->photons = ls->value * pointScale; - dl->type = emit_point; - continue; - } - - // possibly create for both sides of the polygon - for ( side = 0 ; side <= ls->twoSided ; side++ ) { - // create area lights - if ( surfaceTest[i] ) { - // curve or misc_model - for ( j = 0 ; j < surfaceTest[i]->numFacets ; j++ ) { - f = surfaceTest[i]->facets + j; - w = AllocWinding( f->numBoundaries ); - w->numpoints = f->numBoundaries; - memcpy( w->p, f->points, f->numBoundaries * 12 ); - - VectorCopy( f->surface, normal ); - if ( side ) { - winding_t *t; - - t = w; - w = ReverseWinding( t ); - FreeWinding( t ); - VectorSubtract( vec3_origin, normal, normal ); - } - SubdivideAreaLight( ls, w, normal, lightSubdivide, qtrue ); - } - } else { - // normal polygon - - w = AllocWinding( ds->numVerts ); - w->numpoints = ds->numVerts; - for ( j = 0 ; j < ds->numVerts ; j++ ) { - VectorCopy( drawVerts[ds->firstVert+j].xyz, w->p[j] ); - } - VectorCopy( ds->lightmapVecs[2], normal ); - if ( side ) { - winding_t *t; - - t = w; - w = ReverseWinding( t ); - FreeWinding( t ); - VectorSubtract( vec3_origin, normal, normal ); - } - SubdivideAreaLight( ls, w, normal, lightSubdivide, qtrue ); - } - } - } - - _printf( "%5i light emitting surfaces\n", c_lightSurfaces ); -} - - - -/* -================ -FindSkyBrushes -================ -*/ -void FindSkyBrushes( void ) { - int i, j; - dbrush_t *b; - skyBrush_t *sb; - shaderInfo_t *si; - dbrushside_t *s; - - // find the brushes - for ( i = 0 ; i < numbrushes ; i++ ) { - b = &dbrushes[i]; - for ( j = 0 ; j < b->numSides ; j++ ) { - s = &dbrushsides[ b->firstSide + j ]; - if ( dshaders[ s->shaderNum ].surfaceFlags & SURF_SKY ) { - sb = &skyBrushes[ numSkyBrushes ]; - sb->b = b; - sb->bounds[0][0] = -dplanes[ dbrushsides[ b->firstSide + 0 ].planeNum ].dist - 1; - sb->bounds[1][0] = dplanes[ dbrushsides[ b->firstSide + 1 ].planeNum ].dist + 1; - sb->bounds[0][1] = -dplanes[ dbrushsides[ b->firstSide + 2 ].planeNum ].dist - 1; - sb->bounds[1][1] = dplanes[ dbrushsides[ b->firstSide + 3 ].planeNum ].dist + 1; - sb->bounds[0][2] = -dplanes[ dbrushsides[ b->firstSide + 4 ].planeNum ].dist - 1; - sb->bounds[1][2] = dplanes[ dbrushsides[ b->firstSide + 5 ].planeNum ].dist + 1; - numSkyBrushes++; - break; - } - } - } - - // default - VectorNormalize( sunDirection, sunDirection ); - - // find the sky shader - for ( i = 0 ; i < numDrawSurfaces ; i++ ) { - si = ShaderInfoForShader( dshaders[ drawSurfaces[i].shaderNum ].shader ); - if ( si->surfaceFlags & SURF_SKY ) { - VectorCopy( si->sunLight, sunLight ); - VectorCopy( si->sunDirection, sunDirection ); - break; - } - } -} - -/* -================================================================= - - LIGHT SETUP - -================================================================= -*/ - -/* -================== -FindTargetEntity -================== -*/ -entity_t *FindTargetEntity( const char *target ) { - int i; - const char *n; - - for ( i = 0 ; i < num_entities ; i++ ) { - n = ValueForKey (&entities[i], "targetname"); - if ( !strcmp (n, target) ) { - return &entities[i]; - } - } - - return NULL; -} - - - -/* -============= -CreateEntityLights -============= -*/ -void CreateEntityLights (void) -{ - int i; - light_t *dl; - entity_t *e, *e2; - const char *name; - const char *target; - vec3_t dest; - const char *_color; - float intensity; - int spawnflags; - - // - // entities - // - for ( i = 0 ; i < num_entities ; i++ ) { - e = &entities[i]; - name = ValueForKey (e, "classname"); - if (strncmp (name, "light", 5)) - continue; - - numPointLights++; - dl = malloc(sizeof(*dl)); - memset (dl, 0, sizeof(*dl)); - dl->next = lights; - lights = dl; - - spawnflags = FloatForKey (e, "spawnflags"); - if ( spawnflags & 1 ) { - dl->linearLight = qtrue; - } - - GetVectorForKey (e, "origin", dl->origin); - dl->style = FloatForKey (e, "_style"); - if (!dl->style) - dl->style = FloatForKey (e, "style"); - if (dl->style < 0) - dl->style = 0; - - intensity = FloatForKey (e, "light"); - if (!intensity) - intensity = FloatForKey (e, "_light"); - if (!intensity) - intensity = 300; - _color = ValueForKey (e, "_color"); - if (_color && _color[0]) - { - sscanf (_color, "%f %f %f", &dl->color[0],&dl->color[1],&dl->color[2]); - ColorNormalize (dl->color, dl->color); - } - else - dl->color[0] = dl->color[1] = dl->color[2] = 1.0; - - intensity = intensity * pointScale; - dl->photons = intensity; - - dl->type = emit_point; - - // lights with a target will be spotlights - target = ValueForKey (e, "target"); - - if ( target[0] ) { - float radius; - float dist; - - e2 = FindTargetEntity (target); - if (!e2) { - _printf ("WARNING: light at (%i %i %i) has missing target\n", - (int)dl->origin[0], (int)dl->origin[1], (int)dl->origin[2]); - } else { - GetVectorForKey (e2, "origin", dest); - VectorSubtract (dest, dl->origin, dl->normal); - dist = VectorNormalize (dl->normal, dl->normal); - radius = FloatForKey (e, "radius"); - if ( !radius ) { - radius = 64; - } - if ( !dist ) { - dist = 64; - } - dl->radiusByDist = (radius + 16) / dist; - dl->type = emit_spotlight; - } - } - } -} - -//================================================================= - -/* -================ -SetEntityOrigins - -Find the offset values for inline models -================ -*/ -void SetEntityOrigins( void ) { - int i, j; - entity_t *e; - vec3_t origin; - const char *key; - int modelnum; - dmodel_t *dm; - - for ( i=0 ; i < num_entities ; i++ ) { - e = &entities[i]; - key = ValueForKey (e, "model"); - if ( key[0] != '*' ) { - continue; - } - modelnum = atoi( key + 1 ); - dm = &dmodels[ modelnum ]; - - // set entity surface to true for all surfaces for this model - for ( j = 0 ; j < dm->numSurfaces ; j++ ) { - entitySurface[ dm->firstSurface + j ] = qtrue; - } - - key = ValueForKey (e, "origin"); - if ( !key[0] ) { - continue; - } - GetVectorForKey ( e, "origin", origin ); - - // set origin for all surfaces for this model - for ( j = 0 ; j < dm->numSurfaces ; j++ ) { - VectorCopy( origin, surfaceOrigin[ dm->firstSurface + j ] ); - } - } -} - - -/* -================================================================= - - -================================================================= -*/ - -#define MAX_POINTS_ON_WINDINGS 64 - -/* -================ -PointToPolygonFormFactor -================ -*/ -float PointToPolygonFormFactor( const vec3_t point, const vec3_t normal, const winding_t *w ) { - vec3_t triVector, triNormal; - int i, j; - vec3_t dirs[MAX_POINTS_ON_WINDING]; - float total; - float dot, angle, facing; - - for ( i = 0 ; i < w->numpoints ; i++ ) { - VectorSubtract( w->p[i], point, dirs[i] ); - VectorNormalize( dirs[i], dirs[i] ); - } - - // duplicate first vertex to avoid mod operation - VectorCopy( dirs[0], dirs[i] ); - - total = 0; - for ( i = 0 ; i < w->numpoints ; i++ ) { - j = i+1; - dot = DotProduct( dirs[i], dirs[j] ); - - // roundoff can cause slight creep, which gives an IND from acos - if ( dot > 1.0 ) { - dot = 1.0; - } else if ( dot < -1.0 ) { - dot = -1.0; - } - - angle = acos( dot ); - CrossProduct( dirs[i], dirs[j], triVector ); - if ( VectorNormalize( triVector, triNormal ) < 0.0001 ) { - continue; - } - facing = DotProduct( normal, triNormal ); - total += facing * angle; - - if ( total > 6.3 || total < -6.3 ) { - static qboolean printed; - - if ( !printed ) { - printed = qtrue; - _printf( "WARNING: bad PointToPolygonFormFactor: %f at %1.1f %1.1f %1.1f from %1.1f %1.1f %1.1f\n", total, - w->p[i][0], w->p[i][1], w->p[i][2], point[0], point[1], point[2]); - } - return 0; - } - - } - - total /= 2*3.141592657; // now in the range of 0 to 1 over the entire incoming hemisphere - - return total; -} - - -/* -================ -FilterTrace - -Returns 0 to 1.0 filter fractions for the given trace -================ -*/ -void FilterTrace( const vec3_t start, const vec3_t end, vec3_t filter ) { - float d1, d2; - filter_t *f; - int filterNum; - vec3_t point; - float frac; - int i; - float s, t; - int u, v; - int x, y; - byte *pixel; - float radius; - float len; - vec3_t total; - - filter[0] = 1.0; - filter[1] = 1.0; - filter[2] = 1.0; - - for ( filterNum = 0 ; filterNum < numFilters ; filterNum++ ) { - f = &filters[ filterNum ]; - - // see if the plane is crossed - d1 = DotProduct( start, f->plane ) - f->plane[3]; - d2 = DotProduct( end, f->plane ) - f->plane[3]; - - if ( ( d1 < 0 ) == ( d2 < 0 ) ) { - continue; - } - - // calculate the crossing point - frac = d1 / ( d1 - d2 ); - - for ( i = 0 ; i < 3 ; i++ ) { - point[i] = start[i] + frac * ( end[i] - start[i] ); - } - - VectorSubtract( point, f->origin, point ); - - s = DotProduct( point, f->vectors[0] ); - t = 1.0 - DotProduct( point, f->vectors[1] ); - if ( s < 0 || s >= 1.0 || t < 0 || t >= 1.0 ) { - continue; - } - - // decide the filter size - radius = 10 * frac; - len = VectorLength( f->vectors[0] ); - if ( !len ) { - continue; - } - radius = radius * len * f->si->width; - - // look up the filter, taking multiple samples - VectorClear( total ); - for ( u = -1 ; u <= 1 ; u++ ) { - for ( v = -1 ; v <=1 ; v++ ) { - x = s * f->si->width + u * radius; - if ( x < 0 ) { - x = 0; - } - if ( x >= f->si->width ) { - x = f->si->width - 1; - } - y = t * f->si->height + v * radius; - if ( y < 0 ) { - y = 0; - } - if ( y >= f->si->height ) { - y = f->si->height - 1; - } - - pixel = f->si->pixels + ( y * f->si->width + x ) * 4; - total[0] += pixel[0]; - total[1] += pixel[1]; - total[2] += pixel[2]; - } - } - - filter[0] *= total[0]/(255.0*9); - filter[1] *= total[1]/(255.0*9); - filter[2] *= total[2]/(255.0*9); - } - -} - -/* -================ -SunToPoint - -Returns an amount of light to add at the point -================ -*/ -int c_sunHit, c_sunMiss; -void SunToPoint( const vec3_t origin, traceWork_t *tw, vec3_t addLight ) { - int i; - trace_t trace; - skyBrush_t *b; - vec3_t end; - - if ( !numSkyBrushes ) { - VectorClear( addLight ); - return; - } - - VectorMA( origin, MAX_WORLD_COORD * 2, sunDirection, end ); - - TraceLine( origin, end, &trace, qtrue, tw ); - - // see if trace.hit is inside a sky brush - for ( i = 0 ; i < numSkyBrushes ; i++) { - b = &skyBrushes[ i ]; - - // this assumes that sky brushes are axial... - if ( trace.hit[0] < b->bounds[0][0] - || trace.hit[0] > b->bounds[1][0] - || trace.hit[1] < b->bounds[0][1] - || trace.hit[1] > b->bounds[1][1] - || trace.hit[2] < b->bounds[0][2] - || trace.hit[2] > b->bounds[1][2] ) { - continue; - } - - - // trace again to get intermediate filters - TraceLine( origin, trace.hit, &trace, qtrue, tw ); - - // we hit the sky, so add sunlight - if ( numthreads == 1 ) { - c_sunHit++; - } - addLight[0] = trace.filter[0] * sunLight[0]; - addLight[1] = trace.filter[1] * sunLight[1]; - addLight[2] = trace.filter[2] * sunLight[2]; - - return; - } - - if ( numthreads == 1 ) { - c_sunMiss++; - } - - VectorClear( addLight ); -} - -/* -================ -SunToPlane -================ -*/ -void SunToPlane( const vec3_t origin, const vec3_t normal, vec3_t color, traceWork_t *tw ) { - float angle; - vec3_t sunColor; - - if ( !numSkyBrushes ) { - return; - } - - angle = DotProduct( normal, sunDirection ); - if ( angle <= 0 ) { - return; // facing away - } - - SunToPoint( origin, tw, sunColor ); - VectorMA( color, angle, sunColor, color ); -} - -/* -================ -LightingAtSample -================ -*/ -void LightingAtSample( vec3_t origin, vec3_t normal, vec3_t color, - qboolean testOcclusion, qboolean forceSunLight, traceWork_t *tw ) { - light_t *light; - trace_t trace; - float angle; - float add; - float dist; - vec3_t dir; - - VectorCopy( ambientColor, color ); - - // trace to all the lights - for ( light = lights ; light ; light = light->next ) { - - //MrE: if the light is behind the surface - if ( DotProduct(light->origin, normal) - DotProduct(normal, origin) < 0 ) - continue; - // testing exact PTPFF - if ( exactPointToPolygon && light->type == emit_area ) { - float factor; - float d; - vec3_t pushedOrigin; - - // see if the point is behind the light - d = DotProduct( origin, light->normal ) - light->dist; - if ( !light->twosided ) { - if ( d < -1 ) { - continue; // point is behind light - } - } - - // test occlusion and find light filters - // clip the line, tracing from the surface towards the light - if ( !notrace && testOcclusion ) { - TraceLine( origin, light->origin, &trace, qfalse, tw ); - - // other light rays must not hit anything - if ( trace.passSolid ) { - continue; - } - } else { - trace.filter[0] = 1.0; - trace.filter[1] = 1.0; - trace.filter[2] = 1.0; - } - - // nudge the point so that it is clearly forward of the light - // so that surfaces meeting a light emiter don't get black edges - if ( d > -8 && d < 8 ) { - VectorMA( origin, (8-d), light->normal, pushedOrigin ); - } else { - VectorCopy( origin, pushedOrigin ); - } - - // calculate the contribution - factor = PointToPolygonFormFactor( pushedOrigin, normal, light->w ); - if ( factor <= 0 ) { - if ( light->twosided ) { - factor = -factor; - } else { - continue; - } - } - color[0] += factor * light->emitColor[0] * trace.filter[0]; - color[1] += factor * light->emitColor[1] * trace.filter[1]; - color[2] += factor * light->emitColor[2] * trace.filter[2]; - - continue; - } - - // calculate the amount of light at this sample - if ( light->type == emit_point ) { - VectorSubtract( light->origin, origin, dir ); - dist = VectorNormalize( dir, dir ); - // clamp the distance to prevent super hot spots - if ( dist < 16 ) { - dist = 16; - } - angle = DotProduct( normal, dir ); - if ( light->linearLight ) { - add = angle * light->photons * linearScale - dist; - if ( add < 0 ) { - add = 0; - } - } else { - add = light->photons / ( dist * dist ) * angle; - } - } else if ( light->type == emit_spotlight ) { - float distByNormal; - vec3_t pointAtDist; - float radiusAtDist; - float sampleRadius; - vec3_t distToSample; - float coneScale; - - VectorSubtract( light->origin, origin, dir ); - - distByNormal = -DotProduct( dir, light->normal ); - if ( distByNormal < 0 ) { - continue; - } - VectorMA( light->origin, distByNormal, light->normal, pointAtDist ); - radiusAtDist = light->radiusByDist * distByNormal; - - VectorSubtract( origin, pointAtDist, distToSample ); - sampleRadius = VectorLength( distToSample ); - - if ( sampleRadius >= radiusAtDist ) { - continue; // outside the cone - } - if ( sampleRadius <= radiusAtDist - 32 ) { - coneScale = 1.0; // fully inside - } else { - coneScale = ( radiusAtDist - sampleRadius ) / 32.0; - } - - dist = VectorNormalize( dir, dir ); - // clamp the distance to prevent super hot spots - if ( dist < 16 ) { - dist = 16; - } - angle = DotProduct( normal, dir ); - add = light->photons / ( dist * dist ) * angle * coneScale; - - } else if ( light->type == emit_area ) { - VectorSubtract( light->origin, origin, dir ); - dist = VectorNormalize( dir, dir ); - // clamp the distance to prevent super hot spots - if ( dist < 16 ) { - dist = 16; - } - angle = DotProduct( normal, dir ); - if ( angle <= 0 ) { - continue; - } - angle *= -DotProduct( light->normal, dir ); - if ( angle <= 0 ) { - continue; - } - - if ( light->linearLight ) { - add = angle * light->photons * linearScale - dist; - if ( add < 0 ) { - add = 0; - } - } else { - add = light->photons / ( dist * dist ) * angle; - } - } - - if ( add <= 1.0 ) { - continue; - } - - // clip the line, tracing from the surface towards the light - if ( !notrace && testOcclusion ) { - TraceLine( origin, light->origin, &trace, qfalse, tw ); - - // other light rays must not hit anything - if ( trace.passSolid ) { - continue; - } - } else { - trace.filter[0] = 1; - trace.filter[1] = 1; - trace.filter[2] = 1; - } - - // add the result - color[0] += add * light->color[0] * trace.filter[0]; - color[1] += add * light->color[1] * trace.filter[1]; - color[2] += add * light->color[2] * trace.filter[2]; - } - - // - // trace directly to the sun - // - if ( testOcclusion || forceSunLight ) { - SunToPlane( origin, normal, color, tw ); - } -} - -/* -============= -PrintOccluded - -For debugging -============= -*/ -void PrintOccluded( byte occluded[LIGHTMAP_WIDTH*EXTRASCALE][LIGHTMAP_HEIGHT*EXTRASCALE], - int width, int height ) { - int i, j; - - _printf( "\n" ); - - for ( i = 0 ; i < height ; i++ ) { - for ( j = 0 ; j < width ; j++ ) { - _printf("%i", (int)occluded[j][i] ); - } - _printf( "\n" ); - } -} - - -/* -============= -VertexLighting - -Vertex lighting will completely ignore occlusion, because -shadows would not be resolvable anyway. -============= -*/ -void VertexLighting( dsurface_t *ds, qboolean testOcclusion, qboolean forceSunLight, float scale, traceWork_t *tw ) { - int i, j; - drawVert_t *dv; - vec3_t sample, normal; - float max; - - VectorCopy( ds->lightmapVecs[2], normal ); - - // generate vertex lighting - for ( i = 0 ; i < ds->numVerts ; i++ ) { - dv = &drawVerts[ ds->firstVert + i ]; - - if ( ds->patchWidth ) { - LightingAtSample( dv->xyz, dv->normal, sample, testOcclusion, forceSunLight, tw ); - } - else if (ds->surfaceType == MST_TRIANGLE_SOUP) { - LightingAtSample( dv->xyz, dv->normal, sample, testOcclusion, forceSunLight, tw ); - } - else { - LightingAtSample( dv->xyz, normal, sample, testOcclusion, forceSunLight, tw ); - } - - if (scale >= 0) - VectorScale(sample, scale, sample); - // clamp with color normalization - max = sample[0]; - if ( sample[1] > max ) { - max = sample[1]; - } - if ( sample[2] > max ) { - max = sample[2]; - } - if ( max > 255 ) { - VectorScale( sample, 255/max, sample ); - } - - // save the sample - for ( j = 0 ; j < 3 ; j++ ) { - if ( sample[j] > 255 ) { - sample[j] = 255; - } - dv->color[j] = sample[j]; - } - - // Don't bother writing alpha since it will already be set to 255, - // plus we don't want to write over alpha generated by SetTerrainTextures - //dv->color[3] = 255; - } -} - - -/* -================= -LinearSubdivideMesh - -For extra lighting, just midpoint one of the axis. -The edges are clamped at the original edges. -================= -*/ -mesh_t *LinearSubdivideMesh( mesh_t *in ) { - int i, j; - mesh_t *out; - drawVert_t *v1, *v2, *vout; - - out = malloc( sizeof( *out ) ); - - out->width = in->width * 2; - out->height = in->height; - out->verts = malloc( out->width * out->height * sizeof(*out->verts) ); - for ( j = 0 ; j < in->height ; j++ ) { - out->verts[ j * out->width + 0 ] = in->verts[ j * in->width + 0 ]; - out->verts[ j * out->width + out->width - 1 ] = in->verts[ j * in->width + in->width - 1 ]; - for ( i = 1 ; i < out->width - 1 ; i+= 2 ) { - v1 = in->verts + j * in->width + (i >> 1); - v2 = v1 + 1; - vout = out->verts + j * out->width + i; - - vout->xyz[0] = 0.75 * v1->xyz[0] + 0.25 * v2->xyz[0]; - vout->xyz[1] = 0.75 * v1->xyz[1] + 0.25 * v2->xyz[1]; - vout->xyz[2] = 0.75 * v1->xyz[2] + 0.25 * v2->xyz[2]; - - vout->normal[0] = 0.75 * v1->normal[0] + 0.25 * v2->normal[0]; - vout->normal[1] = 0.75 * v1->normal[1] + 0.25 * v2->normal[1]; - vout->normal[2] = 0.75 * v1->normal[2] + 0.25 * v2->normal[2]; - - VectorNormalize( vout->normal, vout->normal ); - - vout++; - - vout->xyz[0] = 0.25 * v1->xyz[0] + 0.75 * v2->xyz[0]; - vout->xyz[1] = 0.25 * v1->xyz[1] + 0.75 * v2->xyz[1]; - vout->xyz[2] = 0.25 * v1->xyz[2] + 0.75 * v2->xyz[2]; - - vout->normal[0] = 0.25 * v1->normal[0] + 0.75 * v2->normal[0]; - vout->normal[1] = 0.25 * v1->normal[1] + 0.75 * v2->normal[1]; - vout->normal[2] = 0.25 * v1->normal[2] + 0.75 * v2->normal[2]; - - VectorNormalize( vout->normal, vout->normal ); - - } - } - - FreeMesh( in ); - - return out; -} - -/* -============== -ColorToBytes -============== -*/ -void ColorToBytes( const float *color, byte *colorBytes ) { - float max; - vec3_t sample; - - VectorCopy( color, sample ); - - // clamp with color normalization - max = sample[0]; - if ( sample[1] > max ) { - max = sample[1]; - } - if ( sample[2] > max ) { - max = sample[2]; - } - if ( max > 255 ) { - VectorScale( sample, 255/max, sample ); - } - colorBytes[ 0 ] = sample[0]; - colorBytes[ 1 ] = sample[1]; - colorBytes[ 2 ] = sample[2]; -} - - - -/* -============= -TraceLtm -============= -*/ -void TraceLtm( int num ) { - dsurface_t *ds; - int i, j, k; - int x, y; - int position, numPositions; - vec3_t base, origin, normal; - byte occluded[LIGHTMAP_WIDTH*EXTRASCALE][LIGHTMAP_HEIGHT*EXTRASCALE]; - vec3_t color[LIGHTMAP_WIDTH*EXTRASCALE][LIGHTMAP_HEIGHT*EXTRASCALE]; - traceWork_t tw; - vec3_t average; - int count; - mesh_t srcMesh, *mesh, *subdivided; - shaderInfo_t *si; - static float nudge[2][9] = { - { 0, -1, 0, 1, -1, 1, -1, 0, 1 }, - { 0, -1, -1, -1, 0, 0, 1, 1, 1 } - }; - int sampleWidth, sampleHeight, ssize; - vec3_t lightmapOrigin, lightmapVecs[2]; - int widthtable[LIGHTMAP_WIDTH], heighttable[LIGHTMAP_WIDTH]; - - ds = &drawSurfaces[num]; - si = ShaderInfoForShader( dshaders[ ds->shaderNum].shader ); - - // vertex-lit triangle model - if ( ds->surfaceType == MST_TRIANGLE_SOUP ) { - VertexLighting( ds, !si->noVertexShadows, si->forceSunLight, 1.0, &tw ); - return; - } - - if ( ds->lightmapNum == -1 ) { - return; // doesn't need lighting at all - } - - if (!novertexlighting) { - // calculate the vertex lighting for gouraud shade mode - VertexLighting( ds, si->vertexShadows, si->forceSunLight, si->vertexScale, &tw ); - } - - if ( ds->lightmapNum < 0 ) { - return; // doesn't need lightmap lighting - } - - si = ShaderInfoForShader( dshaders[ ds->shaderNum].shader ); - ssize = samplesize; - if (si->lightmapSampleSize) - ssize = si->lightmapSampleSize; - - if (si->patchShadows) - tw.patchshadows = qtrue; - else - tw.patchshadows = patchshadows; - - if ( ds->surfaceType == MST_PATCH ) { - srcMesh.width = ds->patchWidth; - srcMesh.height = ds->patchHeight; - srcMesh.verts = drawVerts + ds->firstVert; - mesh = SubdivideMesh( srcMesh, 8, 999 ); - PutMeshOnCurve( *mesh ); - MakeMeshNormals( *mesh ); - - subdivided = RemoveLinearMeshColumnsRows( mesh ); - FreeMesh(mesh); - - mesh = SubdivideMeshQuads( subdivided, ssize, LIGHTMAP_WIDTH, widthtable, heighttable); - if ( mesh->width != ds->lightmapWidth || mesh->height != ds->lightmapHeight ) { - Error( "Mesh lightmap miscount"); - } - - if ( extra ) { - mesh_t *mp; - - // chop it up for more light samples (leaking memory...) - mp = mesh;//CopyMesh( mesh ); - mp = LinearSubdivideMesh( mp ); - mp = TransposeMesh( mp ); - mp = LinearSubdivideMesh( mp ); - mp = TransposeMesh( mp ); - - mesh = mp; - } - } else { - VectorCopy( ds->lightmapVecs[2], normal ); - - if ( !extra ) { - VectorCopy( ds->lightmapOrigin, lightmapOrigin ); - VectorCopy( ds->lightmapVecs[0], lightmapVecs[0] ); - VectorCopy( ds->lightmapVecs[1], lightmapVecs[1] ); - } else { - // sample at a closer spacing for antialiasing - VectorCopy( ds->lightmapOrigin, lightmapOrigin ); - VectorScale( ds->lightmapVecs[0], 0.5, lightmapVecs[0] ); - VectorScale( ds->lightmapVecs[1], 0.5, lightmapVecs[1] ); - VectorMA( lightmapOrigin, -0.5, lightmapVecs[0], lightmapOrigin ); - VectorMA( lightmapOrigin, -0.5, lightmapVecs[1], lightmapOrigin ); - } - } - - if ( extra ) { - sampleWidth = ds->lightmapWidth * 2; - sampleHeight = ds->lightmapHeight * 2; - } else { - sampleWidth = ds->lightmapWidth; - sampleHeight = ds->lightmapHeight; - } - - memset ( color, 0, sizeof( color ) ); - - // determine which samples are occluded - memset ( occluded, 0, sizeof( occluded ) ); - for ( i = 0 ; i < sampleWidth ; i++ ) { - for ( j = 0 ; j < sampleHeight ; j++ ) { - - if ( ds->patchWidth ) { - numPositions = 9; - VectorCopy( mesh->verts[j*mesh->width+i].normal, normal ); - // VectorNormalize( normal, normal ); - // push off of the curve a bit - VectorMA( mesh->verts[j*mesh->width+i].xyz, 1, normal, base ); - - MakeNormalVectors( normal, lightmapVecs[0], lightmapVecs[1] ); - } else { - numPositions = 9; - for ( k = 0 ; k < 3 ; k++ ) { - base[k] = lightmapOrigin[k] + normal[k] - + i * lightmapVecs[0][k] - + j * lightmapVecs[1][k]; - } - } - VectorAdd( base, surfaceOrigin[ num ], base ); - - // we may need to slightly nudge the sample point - // if directly on a wall - for ( position = 0 ; position < numPositions ; position++ ) { - // calculate lightmap sample position - for ( k = 0 ; k < 3 ; k++ ) { - origin[k] = base[k] + - + ( nudge[0][position]/16 ) * lightmapVecs[0][k] - + ( nudge[1][position]/16 ) * lightmapVecs[1][k]; - } - - if ( notrace ) { - break; - } - if ( !PointInSolid( origin ) ) { - break; - } - } - - // if none of the nudges worked, this sample is occluded - if ( position == numPositions ) { - occluded[i][j] = qtrue; - if ( numthreads == 1 ) { - c_occluded++; - } - continue; - } - - if ( numthreads == 1 ) { - c_visible++; - } - occluded[i][j] = qfalse; - LightingAtSample( origin, normal, color[i][j], qtrue, qfalse, &tw ); - } - } - - if ( dump ) { - PrintOccluded( occluded, sampleWidth, sampleHeight ); - } - - // calculate average values for occluded samples - for ( i = 0 ; i < sampleWidth ; i++ ) { - for ( j = 0 ; j < sampleHeight ; j++ ) { - if ( !occluded[i][j] ) { - continue; - } - // scan all surrounding samples - count = 0; - VectorClear( average ); - for ( x = -1 ; x <= 1; x++ ) { - for ( y = -1 ; y <= 1 ; y++ ) { - if ( i + x < 0 || i + x >= sampleWidth ) { - continue; - } - if ( j + y < 0 || j + y >= sampleHeight ) { - continue; - } - if ( occluded[i+x][j+y] ) { - continue; - } - count++; - VectorAdd( color[i+x][j+y], average, average ); - } - } - if ( count ) { - VectorScale( average, 1.0/count, color[i][j] ); - } - } - } - - // average together the values if we are extra sampling - if ( ds->lightmapWidth != sampleWidth ) { - for ( i = 0 ; i < ds->lightmapWidth ; i++ ) { - for ( j = 0 ; j < ds->lightmapHeight ; j++ ) { - for ( k = 0 ; k < 3 ; k++ ) { - float value, coverage; - - value = color[i*2][j*2][k] + color[i*2][j*2+1][k] + - color[i*2+1][j*2][k] + color[i*2+1][j*2+1][k]; - coverage = 4; - if ( extraWide ) { - // wider than box filter - if ( i > 0 ) { - value += color[i*2-1][j*2][k] + color[i*2-1][j*2+1][k]; - value += color[i*2-2][j*2][k] + color[i*2-2][j*2+1][k]; - coverage += 4; - } - if ( i < ds->lightmapWidth - 1 ) { - value += color[i*2+2][j*2][k] + color[i*2+2][j*2+1][k]; - value += color[i*2+3][j*2][k] + color[i*2+3][j*2+1][k]; - coverage += 4; - } - if ( j > 0 ) { - value += color[i*2][j*2-1][k] + color[i*2+1][j*2-1][k]; - value += color[i*2][j*2-2][k] + color[i*2+1][j*2-2][k]; - coverage += 4; - } - if ( j < ds->lightmapHeight - 1 ) { - value += color[i*2][j*2+2][k] + color[i*2+1][j*2+2][k]; - value += color[i*2][j*2+3][k] + color[i*2+1][j*2+3][k]; - coverage += 2; - } - } - - color[i][j][k] = value / coverage; - } - } - } - } - - // optionally create a debugging border around the lightmap - if ( lightmapBorder ) { - for ( i = 0 ; i < ds->lightmapWidth ; i++ ) { - color[i][0][0] = 255; - color[i][0][1] = 0; - color[i][0][2] = 0; - - color[i][ds->lightmapHeight-1][0] = 255; - color[i][ds->lightmapHeight-1][1] = 0; - color[i][ds->lightmapHeight-1][2] = 0; - } - for ( i = 0 ; i < ds->lightmapHeight ; i++ ) { - color[0][i][0] = 255; - color[0][i][1] = 0; - color[0][i][2] = 0; - - color[ds->lightmapWidth-1][i][0] = 255; - color[ds->lightmapWidth-1][i][1] = 0; - color[ds->lightmapWidth-1][i][2] = 0; - } - } - - // clamp the colors to bytes and store off - for ( i = 0 ; i < ds->lightmapWidth ; i++ ) { - for ( j = 0 ; j < ds->lightmapHeight ; j++ ) { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + j) - * LIGHTMAP_WIDTH + ds->lightmapX + i; - - ColorToBytes( color[i][j], lightBytes + k*3 ); - } - } - - if (ds->surfaceType == MST_PATCH) - { - FreeMesh(mesh); - } -} - - -//============================================================================= - -vec3_t gridMins; -vec3_t gridSize = { 64, 64, 128 }; -int gridBounds[3]; - - -/* -======================== -LightContributionToPoint -======================== -*/ -qboolean LightContributionToPoint( const light_t *light, const vec3_t origin, - vec3_t color, traceWork_t *tw ) { - trace_t trace; - float add; - - add = 0; - - VectorClear( color ); - - // testing exact PTPFF - if ( exactPointToPolygon && light->type == emit_area ) { - float factor; - float d; - vec3_t normal; - - // see if the point is behind the light - d = DotProduct( origin, light->normal ) - light->dist; - if ( !light->twosided ) { - if ( d < 1 ) { - return qfalse; // point is behind light - } - } - - // test occlusion - // clip the line, tracing from the surface towards the light - TraceLine( origin, light->origin, &trace, qfalse, tw ); - if ( trace.passSolid ) { - return qfalse; - } - - // calculate the contribution - VectorSubtract( light->origin, origin, normal ); - if ( VectorNormalize( normal, normal ) == 0 ) { - return qfalse; - } - factor = PointToPolygonFormFactor( origin, normal, light->w ); - if ( factor <= 0 ) { - if ( light->twosided ) { - factor = -factor; - } else { - return qfalse; - } - } - VectorScale( light->emitColor, factor, color ); - return qtrue; - } - - // calculate the amount of light at this sample - if ( light->type == emit_point || light->type == emit_spotlight ) { - vec3_t dir; - float dist; - - VectorSubtract( light->origin, origin, dir ); - dist = VectorLength( dir ); - // clamp the distance to prevent super hot spots - if ( dist < 16 ) { - dist = 16; - } - if ( light->linearLight ) { - add = light->photons * linearScale - dist; - if ( add < 0 ) { - add = 0; - } - } else { - add = light->photons / ( dist * dist ); - } - } else { - return qfalse; - } - - if ( add <= 1.0 ) { - return qfalse; - } - - // clip the line, tracing from the surface towards the light - TraceLine( origin, light->origin, &trace, qfalse, tw ); - - // other light rays must not hit anything - if ( trace.passSolid ) { - return qfalse; - } - - // add the result - color[0] = add * light->color[0]; - color[1] = add * light->color[1]; - color[2] = add * light->color[2]; - - return qtrue; -} - -typedef struct { - vec3_t dir; - vec3_t color; -} contribution_t; - -/* -============= -TraceGrid - -Grid samples are foe quickly determining the lighting -of dynamically placed entities in the world -============= -*/ -#define MAX_CONTRIBUTIONS 1024 -void TraceGrid( int num ) { - int x, y, z; - vec3_t origin; - light_t *light; - vec3_t color; - int mod; - vec3_t directedColor; - vec3_t summedDir; - contribution_t contributions[MAX_CONTRIBUTIONS]; - int numCon; - int i; - traceWork_t tw; - float addSize; - - mod = num; - z = mod / ( gridBounds[0] * gridBounds[1] ); - mod -= z * ( gridBounds[0] * gridBounds[1] ); - - y = mod / gridBounds[0]; - mod -= y * gridBounds[0]; - - x = mod; - - origin[0] = gridMins[0] + x * gridSize[0]; - origin[1] = gridMins[1] + y * gridSize[1]; - origin[2] = gridMins[2] + z * gridSize[2]; - - if ( PointInSolid( origin ) ) { - vec3_t baseOrigin; - int step; - - VectorCopy( origin, baseOrigin ); - - // try to nudge the origin around to find a valid point - for ( step = 9 ; step <= 18 ; step += 9 ) { - for ( i = 0 ; i < 8 ; i++ ) { - VectorCopy( baseOrigin, origin ); - if ( i & 1 ) { - origin[0] += step; - } else { - origin[0] -= step; - } - if ( i & 2 ) { - origin[1] += step; - } else { - origin[1] -= step; - } - if ( i & 4 ) { - origin[2] += step; - } else { - origin[2] -= step; - } - - if ( !PointInSolid( origin ) ) { - break; - } - } - if ( i != 8 ) { - break; - } - } - if ( step > 18 ) { - // can't find a valid point at all - for ( i = 0 ; i < 8 ; i++ ) { - gridData[ num*8 + i ] = 0; - } - return; - } - } - - VectorClear( summedDir ); - - // trace to all the lights - - // find the major light direction, and divide the - // total light between that along the direction and - // the remaining in the ambient - numCon = 0; - for ( light = lights ; light ; light = light->next ) { - vec3_t add; - vec3_t dir; - float addSize; - - if ( !LightContributionToPoint( light, origin, add, &tw ) ) { - continue; - } - - VectorSubtract( light->origin, origin, dir ); - VectorNormalize( dir, dir ); - - VectorCopy( add, contributions[numCon].color ); - VectorCopy( dir, contributions[numCon].dir ); - numCon++; - - addSize = VectorLength( add ); - VectorMA( summedDir, addSize, dir, summedDir ); - - if ( numCon == MAX_CONTRIBUTIONS-1 ) { - break; - } - } - - // - // trace directly to the sun - // - SunToPoint( origin, &tw, color ); - addSize = VectorLength( color ); - if ( addSize > 0 ) { - VectorCopy( color, contributions[numCon].color ); - VectorCopy( sunDirection, contributions[numCon].dir ); - VectorMA( summedDir, addSize, sunDirection, summedDir ); - numCon++; - } - - - // now that we have identified the primary light direction, - // go back and seperate all the light into directed and ambient - VectorNormalize( summedDir, summedDir ); - VectorCopy( ambientColor, color ); - VectorClear( directedColor ); - - for ( i = 0 ; i < numCon ; i++ ) { - float d; - - d = DotProduct( contributions[i].dir, summedDir ); - if ( d < 0 ) { - d = 0; - } - - VectorMA( directedColor, d, contributions[i].color, directedColor ); - - // the ambient light will be at 1/4 the value of directed light - d = 0.25 * ( 1.0 - d ); - VectorMA( color, d, contributions[i].color, color ); - } - - // now do some fudging to keep the ambient from being too low - VectorMA( color, 0.25, directedColor, color ); - - // - // save the resulting value out - // - ColorToBytes( color, gridData + num*8 ); - ColorToBytes( directedColor, gridData + num*8 + 3 ); - - VectorNormalize( summedDir, summedDir ); - NormalToLatLong( summedDir, gridData + num*8 + 6); -} - - -/* -============= -SetupGrid -============= -*/ -void SetupGrid( void ) { - int i; - vec3_t maxs; - - for ( i = 0 ; i < 3 ; i++ ) { - gridMins[i] = gridSize[i] * ceil( dmodels[0].mins[i] / gridSize[i] ); - maxs[i] = gridSize[i] * floor( dmodels[0].maxs[i] / gridSize[i] ); - gridBounds[i] = (maxs[i] - gridMins[i])/gridSize[i] + 1; - } - - numGridPoints = gridBounds[0] * gridBounds[1] * gridBounds[2]; - if (numGridPoints * 8 >= MAX_MAP_LIGHTGRID) - Error("MAX_MAP_LIGHTGRID"); - qprintf( "%5i gridPoints\n", numGridPoints ); -} - -//============================================================================= - -/* -============= -RemoveLightsInSolid -============= -*/ -void RemoveLightsInSolid(void) -{ - light_t *light, *prev; - int numsolid = 0; - - prev = NULL; - for ( light = lights ; light ; ) { - if (PointInSolid(light->origin)) - { - if (prev) prev->next = light->next; - else lights = light->next; - if (light->w) - FreeWinding(light->w); - free(light); - numsolid++; - if (prev) - light = prev->next; - else - light = lights; - } - else - { - prev = light; - light = light->next; - } - } - _printf (" %7i lights in solid\n", numsolid); -} - -/* -============= -LightWorld -============= -*/ -void LightWorld (void) { - float f; - - // determine the number of grid points - SetupGrid(); - - // find the optional world ambient - GetVectorForKey( &entities[0], "_color", ambientColor ); - f = FloatForKey( &entities[0], "ambient" ); - VectorScale( ambientColor, f, ambientColor ); - - // create lights out of patches and lights - qprintf ("--- CreateLights ---\n"); - CreateEntityLights (); - qprintf ("%i point lights\n", numPointLights); - qprintf ("%i area lights\n", numAreaLights); - - if (!nogridlighting) { - qprintf ("--- TraceGrid ---\n"); - RunThreadsOnIndividual( numGridPoints, qtrue, TraceGrid ); - qprintf( "%i x %i x %i = %i grid\n", gridBounds[0], gridBounds[1], - gridBounds[2], numGridPoints); - } - - qprintf ("--- TraceLtm ---\n"); - RunThreadsOnIndividual( numDrawSurfaces, qtrue, TraceLtm ); - qprintf( "%5i visible samples\n", c_visible ); - qprintf( "%5i occluded samples\n", c_occluded ); -} - -/* -======== -CreateFilters - -EXPERIMENTAL, UNUSED - -Look for transparent light filter surfaces. - -This will only work for flat 3*3 patches that exactly hold one copy of the texture. -======== -*/ -#define PLANAR_PATCH_EPSILON 0.1 -void CreateFilters( void ) { - int i; - filter_t *f; - dsurface_t *ds; - shaderInfo_t *si; - drawVert_t *v1, *v2, *v3; - vec3_t d1, d2; - int vertNum; - - numFilters = 0; - - return; - - for ( i = 0 ; i < numDrawSurfaces ; i++ ) { - ds = &drawSurfaces[i]; - if ( !ds->patchWidth ) { - continue; - } - si = ShaderInfoForShader( dshaders[ ds->shaderNum ].shader ); -/* - if ( !(si->surfaceFlags & SURF_LIGHTFILTER) ) { - continue; - } -*/ - - // we have a filter patch - v1 = &drawVerts[ ds->firstVert ]; - - if ( ds->patchWidth != 3 || ds->patchHeight != 3 ) { - _printf("WARNING: patch at %i %i %i has SURF_LIGHTFILTER but isn't a 3 by 3\n", - v1->xyz[0], v1->xyz[1], v1->xyz[2] ); - continue; - } - - if ( numFilters == MAX_FILTERS ) { - Error( "MAX_FILTERS" ); - } - f = &filters[ numFilters ]; - numFilters++; - - v2 = &drawVerts[ ds->firstVert + 2 ]; - v3 = &drawVerts[ ds->firstVert + 6 ]; - - VectorSubtract( v2->xyz, v1->xyz, d1 ); - VectorSubtract( v3->xyz, v1->xyz, d2 ); - VectorNormalize( d1, d1 ); - VectorNormalize( d2, d2 ); - CrossProduct( d1, d2, f->plane ); - f->plane[3] = DotProduct( v1->xyz, f->plane ); - - // make sure all the control points are on the plane - for ( vertNum = 0 ; vertNum < ds->numVerts ; vertNum++ ) { - float d; - - d = DotProduct( drawVerts[ ds->firstVert + vertNum ].xyz, f->plane ) - f->plane[3]; - if ( fabs( d ) > PLANAR_PATCH_EPSILON ) { - break; - } - } - if ( vertNum != ds->numVerts ) { - numFilters--; - _printf("WARNING: patch at %i %i %i has SURF_LIGHTFILTER but isn't flat\n", - v1->xyz[0], v1->xyz[1], v1->xyz[2] ); - continue; - } - } - - f = &filters[0]; - numFilters = 1; - - f->plane[0] = 1; - f->plane[1] = 0; - f->plane[2] = 0; - f->plane[3] = 448; - - f->origin[0] = 448; - f->origin[1] = 192; - f->origin[2] = 0; - - f->vectors[0][0] = 0; - f->vectors[0][1] = -1.0 / 128; - f->vectors[0][2] = 0; - - f->vectors[1][0] = 0; - f->vectors[1][1] = 0; - f->vectors[1][2] = 1.0 / 128; - - f->si = ShaderInfoForShader( "textures/hell/blocks11ct" ); -} - -/* -============= -VertexLightingThread -============= -*/ -void VertexLightingThread(int num) { - dsurface_t *ds; - traceWork_t tw; - shaderInfo_t *si; - - ds = &drawSurfaces[num]; - - // vertex-lit triangle model - if ( ds->surfaceType == MST_TRIANGLE_SOUP ) { - return; - } - - if (novertexlighting) - return; - - if ( ds->lightmapNum == -1 ) { - return; // doesn't need lighting at all - } - - si = ShaderInfoForShader( dshaders[ ds->shaderNum].shader ); - - // calculate the vertex lighting for gouraud shade mode - VertexLighting( ds, si->vertexShadows, si->forceSunLight, si->vertexScale, &tw ); -} - -/* -============= -TriSoupLightingThread -============= -*/ -void TriSoupLightingThread(int num) { - dsurface_t *ds; - traceWork_t tw; - shaderInfo_t *si; - - ds = &drawSurfaces[num]; - si = ShaderInfoForShader( dshaders[ ds->shaderNum].shader ); - - // vertex-lit triangle model - if ( ds->surfaceType == MST_TRIANGLE_SOUP ) { - VertexLighting( ds, !si->noVertexShadows, si->forceSunLight, 1.0, &tw ); - } -} - -/* -============= -GridAndVertexLighting -============= -*/ -void GridAndVertexLighting(void) { - SetupGrid(); - - FindSkyBrushes(); - CreateFilters(); - InitTrace(); - CreateEntityLights (); - CreateSurfaceLights(); - - if (!nogridlighting) { - _printf ("--- TraceGrid ---\n"); - RunThreadsOnIndividual( numGridPoints, qtrue, TraceGrid ); - } - - if (!novertexlighting) { - _printf ("--- Vertex Lighting ---\n"); - RunThreadsOnIndividual( numDrawSurfaces, qtrue, VertexLightingThread ); - } - - _printf("--- Model Lighting ---\n"); - RunThreadsOnIndividual( numDrawSurfaces, qtrue, TriSoupLightingThread ); -} - -/* -======== -LightMain - -======== -*/ -int LightMain (int argc, char **argv) { - int i; - double start, end; - const char *value; - - _printf ("----- Lighting ----\n"); - - verbose = qfalse; - - for (i=1 ; i<argc ; i++) { - if (!strcmp(argv[i],"-tempname")) - { - i++; - } else if (!strcmp(argv[i],"-v")) { - verbose = qtrue; - } else if (!strcmp(argv[i],"-threads")) { - numthreads = atoi (argv[i+1]); - i++; - } else if (!strcmp(argv[i],"-area")) { - areaScale *= atof(argv[i+1]); - _printf ("area light scaling at %f\n", areaScale); - i++; - } else if (!strcmp(argv[i],"-point")) { - pointScale *= atof(argv[i+1]); - _printf ("point light scaling at %f\n", pointScale); - i++; - } else if (!strcmp(argv[i],"-notrace")) { - notrace = qtrue; - _printf ("No occlusion tracing\n"); - } else if (!strcmp(argv[i],"-patchshadows")) { - patchshadows = qtrue; - _printf ("Patch shadow casting enabled\n"); - } else if (!strcmp(argv[i],"-extra")) { - extra = qtrue; - _printf ("Extra detail tracing\n"); - } else if (!strcmp(argv[i],"-extrawide")) { - extra = qtrue; - extraWide = qtrue; - _printf ("Extra wide detail tracing\n"); - } else if (!strcmp(argv[i], "-samplesize")) { - samplesize = atoi(argv[i+1]); - if (samplesize < 1) samplesize = 1; - i++; - _printf("lightmap sample size is %dx%d units\n", samplesize, samplesize); - } else if (!strcmp(argv[i], "-novertex")) { - novertexlighting = qtrue; - _printf("no vertex lighting = true\n"); - } else if (!strcmp(argv[i], "-nogrid")) { - nogridlighting = qtrue; - _printf("no grid lighting = true\n"); - } else if (!strcmp(argv[i],"-border")) { - lightmapBorder = qtrue; - _printf ("Adding debug border to lightmaps\n"); - } else if (!strcmp(argv[i],"-nosurf")) { - noSurfaces = qtrue; - _printf ("Not tracing against surfaces\n" ); - } else if (!strcmp(argv[i],"-dump")) { - dump = qtrue; - _printf ("Dumping occlusion maps\n"); - } else { - break; - } - } - - ThreadSetDefault (); - - if (i != argc - 1) { - _printf("usage: q3map -light [-<switch> [-<switch> ...]] <mapname>\n" - "\n" - "Switches:\n" - " v = verbose output\n" - " threads <X> = set number of threads to X\n" - " area <V> = set the area light scale to V\n" - " point <W> = set the point light scale to W\n" - " notrace = don't cast any shadows\n" - " extra = enable super sampling for anti-aliasing\n" - " extrawide = same as extra but smoothen more\n" - " nogrid = don't calculate light grid for dynamic model lighting\n" - " novertex = don't calculate vertex lighting\n" - " samplesize <N> = set the lightmap pixel size to NxN units\n"); - exit(0); - } - - start = I_FloatTime (); - - SetQdirFromPath (argv[i]); - -#ifdef _WIN32 - InitPakFile(gamedir, NULL); -#endif - - strcpy (source, ExpandArg(argv[i])); - StripExtension (source); - DefaultExtension (source, ".bsp"); - - LoadShaderInfo(); - - _printf ("reading %s\n", source); - - LoadBSPFile (source); - - FindSkyBrushes(); - - ParseEntities(); - - value = ValueForKey( &entities[0], "gridsize" ); - if (strlen(value)) { - sscanf( value, "%f %f %f", &gridSize[0], &gridSize[1], &gridSize[2] ); - _printf("grid size = {%1.1f, %1.1f, %1.1f}\n", gridSize[0], gridSize[1], gridSize[2]); - } - - CreateFilters(); - - InitTrace(); - - SetEntityOrigins(); - - CountLightmaps(); - - CreateSurfaceLights(); - - LightWorld(); - - _printf ("writing %s\n", source); - WriteBSPFile (source); - - end = I_FloatTime (); - _printf ("%5.0f seconds elapsed\n", end-start); - - return 0; -} - diff --git a/q3map/light.h b/q3map/light.h deleted file mode 100644 index ada2763..0000000 --- a/q3map/light.h +++ /dev/null @@ -1,151 +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 "cmdlib.h" -#include "mathlib.h" -#include "bspfile.h" -#include "polylib.h" -#include "imagelib.h" -#include "threads.h" -#include "scriplib.h" - -#include "shaders.h" -#include "mesh.h" - - - -typedef enum -{ - emit_point, - emit_area, - emit_spotlight, - emit_sun -} emittype_t; - -#define MAX_LIGHT_EDGES 8 -typedef struct light_s -{ - struct light_s *next; - emittype_t type; - struct shaderInfo_s *si; - - vec3_t origin; - vec3_t normal; // for surfaces, spotlights, and suns - float dist; // plane location along normal - - qboolean linearLight; - int photons; - int style; - vec3_t color; - float radiusByDist; // for spotlights - - qboolean twosided; // fog lights both sides - - winding_t *w; - vec3_t emitColor; // full out-of-gamut value -} light_t; - - -extern float lightscale; -extern float ambient; -extern float maxlight; -extern float direct_scale; -extern float entity_scale; - -extern qboolean noSurfaces; - -//=============================================================== - -// light_trace.c - -// a facet is a subdivided element of a patch aproximation or model -typedef struct cFacet_s { - float surface[4]; - int numBoundaries; // either 3 or 4, anything less is degenerate - float boundaries[4][4]; // positive is outside the bounds - - vec3_t points[4]; // needed for area light subdivision - - float textureMatrix[2][4]; // compute texture coordinates at point of impact for translucency -} cFacet_t; - -typedef struct { - vec3_t mins, maxs; - vec3_t origin; - float radius; - - qboolean patch; - - int numFacets; - cFacet_t *facets; - - shaderInfo_t *shader; // for translucency -} surfaceTest_t; - - -typedef struct { - vec3_t filter; // starts out 1.0, 1.0, 1.0, may be reduced if - // transparent surfaces are crossed - - vec3_t hit; // the impact point of a completely opaque surface - float hitFraction; // 0 = at start, 1.0 = at end - qboolean passSolid; -} trace_t; - -extern surfaceTest_t *surfaceTest[MAX_MAP_DRAW_SURFS]; - -void InitTrace( void ); - -// traceWork_t is only a parameter to crutch up poor large local allocations on -// winNT and macOS. It should be allocated in the worker function, but never -// looked at. -typedef struct { - vec3_t start, end; - int numOpenLeafs; - int openLeafNumbers[MAX_MAP_LEAFS]; - trace_t *trace; - int patchshadows; -} traceWork_t; - -void TraceLine( const vec3_t start, const vec3_t stop, trace_t *trace, - qboolean testAll, traceWork_t *tw ); -qboolean PointInSolid( vec3_t start ); - -//=============================================================== - -//=============================================================== - - -typedef struct { - int textureNum; - int x, y, width, height; - - // for patches - qboolean patch; - mesh_t mesh; - - // for faces - vec3_t origin; - vec3_t vecs[3]; -} lightmap_t; - - diff --git a/q3map/light_trace.c b/q3map/light_trace.c deleted file mode 100644 index 2c78575..0000000 --- a/q3map/light_trace.c +++ /dev/null @@ -1,944 +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 "light.h" - - - -#define CURVE_FACET_ERROR 8 - -int c_totalTrace; -int c_cullTrace, c_testTrace; -int c_testFacets; - -surfaceTest_t *surfaceTest[MAX_MAP_DRAW_SURFS]; - -/* -===================== -CM_GenerateBoundaryForPoints -===================== -*/ -void CM_GenerateBoundaryForPoints( float boundary[4], float plane[4], vec3_t a, vec3_t b ) { - vec3_t d1; - - // amke a perpendicular vector to the edge and the surface - VectorSubtract( b, a, d1 ); - CrossProduct( plane, d1, boundary ); - VectorNormalize( boundary, boundary ); - boundary[3] = DotProduct( a, boundary ); -} - -/* -===================== -TextureMatrixFromPoints -===================== -*/ -void TextureMatrixFromPoints( cFacet_t *f, drawVert_t *a, drawVert_t *b, drawVert_t *c ) { - int i, j; - float t; - float m[3][4]; - float s; - - // This is an incredibly stupid way of solving a three variable equation - for ( i = 0 ; i < 2 ; i++ ) { - - m[0][0] = a->xyz[0]; - m[0][1] = a->xyz[1]; - m[0][2] = a->xyz[2]; - m[0][3] = a->st[i]; - - m[1][0] = b->xyz[0]; - m[1][1] = b->xyz[1]; - m[1][2] = b->xyz[2]; - m[1][3] = b->st[i]; - - m[2][0] = c->xyz[0]; - m[2][1] = c->xyz[1]; - m[2][2] = c->xyz[2]; - m[2][3] = c->st[i]; - - if ( fabs(m[1][0]) > fabs(m[0][0]) && fabs(m[1][0]) > fabs(m[2][0]) ) { - for ( j = 0 ; j < 4 ; j ++ ) { - t = m[0][j]; - m[0][j] = m[1][j]; - m[1][j] = t; - } - } else if ( fabs(m[2][0]) > fabs(m[0][0]) && fabs(m[2][0]) > fabs(m[1][0]) ) { - for ( j = 0 ; j < 4 ; j ++ ) { - t = m[0][j]; - m[0][j] = m[2][j]; - m[2][j] = t; - } - } - - s = 1.0 / m[0][0]; - m[0][0] *= s; - m[0][1] *= s; - m[0][2] *= s; - m[0][3] *= s; - - s = m[1][0]; - m[1][0] -= m[0][0] * s; - m[1][1] -= m[0][1] * s; - m[1][2] -= m[0][2] * s; - m[1][3] -= m[0][3] * s; - - s = m[2][0]; - m[2][0] -= m[0][0] * s; - m[2][1] -= m[0][1] * s; - m[2][2] -= m[0][2] * s; - m[2][3] -= m[0][3] * s; - - if ( fabs(m[2][1]) > fabs(m[1][1]) ) { - for ( j = 0 ; j < 4 ; j ++ ) { - t = m[1][j]; - m[1][j] = m[2][j]; - m[2][j] = t; - } - } - - s = 1.0 / m[1][1]; - m[1][0] *= s; - m[1][1] *= s; - m[1][2] *= s; - m[1][3] *= s; - - s = m[2][1]; - m[2][0] -= m[1][0] * s; - m[2][1] -= m[1][1] * s; - m[2][2] -= m[1][2] * s; - m[2][3] -= m[1][3] * s; - - s = 1.0 / m[2][2]; - m[2][0] *= s; - m[2][1] *= s; - m[2][2] *= s; - m[2][3] *= s; - - f->textureMatrix[i][2] = m[2][3]; - f->textureMatrix[i][1] = m[1][3] - f->textureMatrix[i][2] * m[1][2]; - f->textureMatrix[i][0] = m[0][3] - f->textureMatrix[i][2] * m[0][2] - f->textureMatrix[i][1] * m[0][1]; - - f->textureMatrix[i][3] = 0; -/* - s = fabs( DotProduct( a->xyz, f->textureMatrix[i] ) - a->st[i] ); - if ( s > 0.01 ) { - Error( "Bad textureMatrix" ); - } - s = fabs( DotProduct( b->xyz, f->textureMatrix[i] ) - b->st[i] ); - if ( s > 0.01 ) { - Error( "Bad textureMatrix" ); - } - s = fabs( DotProduct( c->xyz, f->textureMatrix[i] ) - c->st[i] ); - if ( s > 0.01 ) { - Error( "Bad textureMatrix" ); - } -*/ - } -} - -/* -===================== -CM_GenerateFacetFor3Points -===================== -*/ -qboolean CM_GenerateFacetFor3Points( cFacet_t *f, drawVert_t *a, drawVert_t *b, drawVert_t *c ) { - // if we can't generate a valid plane for the points, ignore the facet - if ( !PlaneFromPoints( f->surface, a->xyz, b->xyz, c->xyz ) ) { - f->numBoundaries = 0; - return qfalse; - } - - // make boundaries - f->numBoundaries = 3; - - CM_GenerateBoundaryForPoints( f->boundaries[0], f->surface, a->xyz, b->xyz ); - CM_GenerateBoundaryForPoints( f->boundaries[1], f->surface, b->xyz, c->xyz ); - CM_GenerateBoundaryForPoints( f->boundaries[2], f->surface, c->xyz, a->xyz ); - - VectorCopy( a->xyz, f->points[0] ); - VectorCopy( b->xyz, f->points[1] ); - VectorCopy( c->xyz, f->points[2] ); - - TextureMatrixFromPoints( f, a, b, c ); - - return qtrue; -} - -/* -===================== -CM_GenerateFacetFor4Points - -Attempts to use four points as a planar quad -===================== -*/ -#define PLANAR_EPSILON 0.1 -qboolean CM_GenerateFacetFor4Points( cFacet_t *f, drawVert_t *a, drawVert_t *b, drawVert_t *c, drawVert_t *d ) { - float dist; - int i; - vec4_t plane; - - // if we can't generate a valid plane for the points, ignore the facet - if ( !PlaneFromPoints( f->surface, a->xyz, b->xyz, c->xyz ) ) { - f->numBoundaries = 0; - return qfalse; - } - - // if the fourth point is also on the plane, we can make a quad facet - dist = DotProduct( d->xyz, f->surface ) - f->surface[3]; - if ( fabs( dist ) > PLANAR_EPSILON ) { - f->numBoundaries = 0; - return qfalse; - } - - // make boundaries - f->numBoundaries = 4; - - CM_GenerateBoundaryForPoints( f->boundaries[0], f->surface, a->xyz, b->xyz ); - CM_GenerateBoundaryForPoints( f->boundaries[1], f->surface, b->xyz, c->xyz ); - CM_GenerateBoundaryForPoints( f->boundaries[2], f->surface, c->xyz, d->xyz ); - CM_GenerateBoundaryForPoints( f->boundaries[3], f->surface, d->xyz, a->xyz ); - - VectorCopy( a->xyz, f->points[0] ); - VectorCopy( b->xyz, f->points[1] ); - VectorCopy( c->xyz, f->points[2] ); - VectorCopy( d->xyz, f->points[3] ); - - for (i = 1; i < 4; i++) - { - if ( !PlaneFromPoints( plane, f->points[i], f->points[(i+1) % 4], f->points[(i+2) % 4]) ) { - f->numBoundaries = 0; - return qfalse; - } - - if (DotProduct(f->surface, plane) < 0.9) { - f->numBoundaries = 0; - return qfalse; - } - } - - TextureMatrixFromPoints( f, a, b, c ); - - return qtrue; -} - - - - -/* -=============== -SphereFromBounds -=============== -*/ -void SphereFromBounds( vec3_t mins, vec3_t maxs, vec3_t origin, float *radius ) { - vec3_t temp; - - VectorAdd( mins, maxs, origin ); - VectorScale( origin, 0.5, origin ); - VectorSubtract( maxs, origin, temp ); - *radius = VectorLength( temp ); -} - - -/* -==================== -FacetsForTriangleSurface -==================== -*/ -void FacetsForTriangleSurface( dsurface_t *dsurf, shaderInfo_t *si, surfaceTest_t *test ) { - int i; - drawVert_t *v1, *v2, *v3, *v4; - int count; - int i1, i2, i3, i4, i5, i6; - - test->patch = qfalse; - test->numFacets = dsurf->numIndexes / 3; - test->facets = malloc( sizeof( test->facets[0] ) * test->numFacets ); - test->shader = si; - - count = 0; - for ( i = 0 ; i < test->numFacets ; i++ ) { - i1 = drawIndexes[ dsurf->firstIndex + i*3 ]; - i2 = drawIndexes[ dsurf->firstIndex + i*3 + 1 ]; - i3 = drawIndexes[ dsurf->firstIndex + i*3 + 2 ]; - - v1 = &drawVerts[ dsurf->firstVert + i1 ]; - v2 = &drawVerts[ dsurf->firstVert + i2 ]; - v3 = &drawVerts[ dsurf->firstVert + i3 ]; - - // try and make a quad out of two triangles - if ( i != test->numFacets - 1 ) { - i4 = drawIndexes[ dsurf->firstIndex + i*3 + 3 ]; - i5 = drawIndexes[ dsurf->firstIndex + i*3 + 4 ]; - i6 = drawIndexes[ dsurf->firstIndex + i*3 + 5 ]; - if ( i4 == i3 && i5 == i2 ) { - v4 = &drawVerts[ dsurf->firstVert + i6 ]; - if ( CM_GenerateFacetFor4Points( &test->facets[count], v1, v2, v4, v3 ) ) { - count++; - i++; // skip next tri - continue; - } - } - } - - if (CM_GenerateFacetFor3Points( &test->facets[count], v1, v2, v3 )) - count++; - } - - // we may have turned some pairs into quads - test->numFacets = count; -} - -/* -==================== -FacetsForPatch -==================== -*/ -void FacetsForPatch( dsurface_t *dsurf, shaderInfo_t *si, surfaceTest_t *test ) { - int i, j; - drawVert_t *v1, *v2, *v3, *v4; - int count; - mesh_t srcMesh, *subdivided, *mesh; - - srcMesh.width = dsurf->patchWidth; - srcMesh.height = dsurf->patchHeight; - srcMesh.verts = &drawVerts[ dsurf->firstVert ]; - - //subdivided = SubdivideMesh( mesh, CURVE_FACET_ERROR, 9999 ); - mesh = SubdivideMesh( srcMesh, 8, 999 ); - PutMeshOnCurve( *mesh ); - MakeMeshNormals( *mesh ); - - subdivided = RemoveLinearMeshColumnsRows( mesh ); - FreeMesh(mesh); - - test->patch = qtrue; - test->numFacets = ( subdivided->width - 1 ) * ( subdivided->height - 1 ) * 2; - test->facets = malloc( sizeof( test->facets[0] ) * test->numFacets ); - test->shader = si; - - count = 0; - for ( i = 0 ; i < subdivided->width - 1 ; i++ ) { - for ( j = 0 ; j < subdivided->height - 1 ; j++ ) { - - v1 = subdivided->verts + j * subdivided->width + i; - v2 = v1 + 1; - v3 = v1 + subdivided->width + 1; - v4 = v1 + subdivided->width; - - if ( CM_GenerateFacetFor4Points( &test->facets[count], v1, v4, v3, v2 ) ) { - count++; - } else { - if (CM_GenerateFacetFor3Points( &test->facets[count], v1, v4, v3 )) - count++; - if (CM_GenerateFacetFor3Points( &test->facets[count], v1, v3, v2 )) - count++; - } - } - } - test->numFacets = count; - FreeMesh(subdivided); -} - - -/* -===================== -InitSurfacesForTesting - -Builds structures to speed the ray tracing against surfaces -===================== -*/ -void InitSurfacesForTesting( void ) { - - int i, j; - dsurface_t *dsurf; - surfaceTest_t *test; - drawVert_t *dvert; - shaderInfo_t *si; - - for ( i = 0 ; i < numDrawSurfaces ; i++ ) { - dsurf = &drawSurfaces[ i ]; - if ( !dsurf->numIndexes && !dsurf->patchWidth ) { - continue; - } - - // don't make surfaces for transparent objects - // because we want light to pass through them - si = ShaderInfoForShader( dshaders[ dsurf->shaderNum].shader ); - if ( (si->contents & CONTENTS_TRANSLUCENT) && !(si->surfaceFlags & SURF_ALPHASHADOW) ) { - continue; - } - - test = malloc( sizeof( *test ) ); - surfaceTest[i] = test; - ClearBounds( test->mins, test->maxs ); - - dvert = &drawVerts[ dsurf->firstVert ]; - for ( j = 0 ; j < dsurf->numVerts ; j++, dvert++ ) { - AddPointToBounds( dvert->xyz, test->mins, test->maxs ); - } - - SphereFromBounds( test->mins, test->maxs, test->origin, &test->radius ); - - if ( dsurf->surfaceType == MST_TRIANGLE_SOUP || dsurf->surfaceType == MST_PLANAR ) { - FacetsForTriangleSurface( dsurf, si, test ); - } else if ( dsurf->surfaceType == MST_PATCH ) { - FacetsForPatch( dsurf, si, test ); - } - } -} - - -/* -===================== -GenerateBoundaryForPoints -===================== -*/ -void GenerateBoundaryForPoints( float boundary[4], float plane[4], vec3_t a, vec3_t b ) { - vec3_t d1; - - // amke a perpendicular vector to the edge and the surface - VectorSubtract( b, a, d1 ); - CrossProduct( plane, d1, boundary ); - VectorNormalize( boundary, boundary ); - boundary[3] = DotProduct( a, boundary ); -} - - -/* -================= -SetFacetFilter - -Given a point on a facet, determine the color filter -for light passing through -================= -*/ -void SetFacetFilter( traceWork_t *tr, shaderInfo_t *shader, cFacet_t *facet, vec3_t point ) { - float s, t; - int is, it; - byte *image; - int b; - - // most surfaces are completely opaque - if ( !(shader->surfaceFlags & SURF_ALPHASHADOW) ) { - VectorClear( tr->trace->filter ); - return; - } - - s = DotProduct( point, facet->textureMatrix[0] ) + facet->textureMatrix[0][3]; - t = DotProduct( point, facet->textureMatrix[1] ) + facet->textureMatrix[1][3]; - - if ( !shader->pixels ) { - // assume completely solid - VectorClear( point ); - return; - } - - s = s - floor( s ); - t = t - floor( t ); - - is = s * shader->width; - it = t * shader->height; - - image = shader->pixels + 4 * ( it * shader->width + is ); - - // alpha filter - b = image[3]; - - // alpha test makes this a binary option - b = b < 128 ? 0 : 255; - - tr->trace->filter[0] = tr->trace->filter[0] * (255-b) / 255; - tr->trace->filter[1] = tr->trace->filter[1] * (255-b) / 255; - tr->trace->filter[2] = tr->trace->filter[2] * (255-b) / 255; -} - - -/* -==================== -TraceAgainstFacet - -Shader is needed for translucent surfaces -==================== -*/ -void TraceAgainstFacet( traceWork_t *tr, shaderInfo_t *shader, cFacet_t *facet ) { - int j; - float d1, d2, d, f; - vec3_t point; - float dist; - - // ignore degenerate facets - if ( facet->numBoundaries < 3 ) { - return; - } - - dist = facet->surface[3]; - - // compare the trace endpoints against the facet plane - d1 = DotProduct( tr->start, facet->surface ) - dist; - if ( d1 > -1 && d1 < 1 ) { - return; // don't self intersect - } - d2 = DotProduct( tr->end, facet->surface ) - dist; - if ( d2 > -1 && d2 < 1 ) { - return; // don't self intersect - } - - // calculate the intersection fraction - f = ( d1 - ON_EPSILON ) / ( d1 - d2 ); - if ( f <= 0 ) { - return; - } - if ( f >= tr->trace->hitFraction ) { - return; // we have hit something earlier - } - - // calculate the intersection point - for ( j = 0 ; j < 3 ; j++ ) { - point[j] = tr->start[j] + f * ( tr->end[j] - tr->start[j] ); - } - - // check the point against the facet boundaries - for ( j = 0 ; j < facet->numBoundaries ; j++ ) { - // adjust the plane distance apropriately for mins/maxs - dist = facet->boundaries[j][3]; - - d = DotProduct( point, facet->boundaries[j] ); - if ( d > dist + ON_EPSILON ) { - break; // outside the bounds - } - } - - if ( j != facet->numBoundaries ) { - return; // we are outside the bounds of the facet - } - - // we hit this facet - - // if this is a transparent surface, calculate filter value - if ( shader->surfaceFlags & SURF_ALPHASHADOW ) { - SetFacetFilter( tr, shader, facet, point ); - } else { - // completely opaque - VectorClear( tr->trace->filter ); - tr->trace->hitFraction = f; - } - -// VectorCopy( facet->surface, tr->trace->plane.normal ); -// tr->trace->plane.dist = facet->surface[3]; -} - - -/* -=============================================================== - - LINE TRACING - -=============================================================== -*/ - - -#define TRACE_ON_EPSILON 0.1 - -typedef struct tnode_s -{ - int type; - vec3_t normal; - float dist; - int children[2]; - int planeNum; -} tnode_t; - -#define MAX_TNODES (MAX_MAP_NODES*4) -tnode_t *tnodes, *tnode_p; - -/* -============== -MakeTnode - -Converts the disk node structure into the efficient tracing structure -============== -*/ -void MakeTnode (int nodenum) -{ - tnode_t *t; - dplane_t *plane; - int i; - dnode_t *node; - int leafNum; - - t = tnode_p++; - - node = dnodes + nodenum; - plane = dplanes + node->planeNum; - - t->planeNum = node->planeNum; - t->type = PlaneTypeForNormal( plane->normal ); - VectorCopy (plane->normal, t->normal); - t->dist = plane->dist; - - for (i=0 ; i<2 ; i++) - { - if (node->children[i] < 0) { - leafNum = -node->children[i] - 1; - if ( dleafs[leafNum].cluster == -1 ) { - // solid - t->children[i] = leafNum | ( 1 << 31 ) | ( 1 << 30 ); - } else { - t->children[i] = leafNum | ( 1 << 31 ); - } - } else { - t->children[i] = tnode_p - tnodes; - MakeTnode (node->children[i]); - } - } - -} - -/* -============= -InitTrace - -Loads the node structure out of a .bsp file to be used for light occlusion -============= -*/ -void InitTrace( void ) { - // 32 byte align the structs - tnodes = malloc( (MAX_TNODES+1) * sizeof(tnode_t)); - tnodes = (tnode_t *)(((int)tnodes + 31)&~31); - tnode_p = tnodes; - - MakeTnode (0); - - InitSurfacesForTesting(); -} - - -/* -=================== -PointInSolid -=================== -*/ -qboolean PointInSolid_r( vec3_t start, int node ) { - tnode_t *tnode; - float front; - - while ( !(node & (1<<31) ) ) { - tnode = &tnodes[node]; - switch (tnode->type) { - case PLANE_X: - front = start[0] - tnode->dist; - break; - case PLANE_Y: - front = start[1] - tnode->dist; - break; - case PLANE_Z: - front = start[2] - tnode->dist; - break; - default: - front = (start[0]*tnode->normal[0] + start[1]*tnode->normal[1] + start[2]*tnode->normal[2]) - tnode->dist; - break; - } - - if ( front == 0 ) { - // exactly on node, must check both sides - return (qboolean) ( PointInSolid_r( start, tnode->children[0] ) - | PointInSolid_r( start, tnode->children[1] ) ); - } - - if ( front > 0 ) { - node = tnode->children[0]; - } else { - node = tnode->children[1]; - } - } - - if ( node & ( 1 << 30 ) ) { - return qtrue; - } - return qfalse; -} - -/* -============= -PointInSolid - -============= -*/ -qboolean PointInSolid( vec3_t start ) { - return PointInSolid_r( start, 0 ); -} - - -/* -============= -TraceLine_r - -Returns qtrue if something is hit and tracing can stop -============= -*/ -int TraceLine_r( int node, const vec3_t start, const vec3_t stop, traceWork_t *tw ) { - tnode_t *tnode; - float front, back; - vec3_t mid; - float frac; - int side; - int r; - - if (node & (1<<31)) { - if (node & ( 1 << 30 ) ) { - VectorCopy (start, tw->trace->hit); - tw->trace->passSolid = qtrue; - return qtrue; - } else { - // save the node off for more exact testing - if ( tw->numOpenLeafs == MAX_MAP_LEAFS ) { - return qfalse; - } - tw->openLeafNumbers[ tw->numOpenLeafs ] = node & ~(3 << 30); - tw->numOpenLeafs++; - return qfalse; - } - } - - tnode = &tnodes[node]; - switch (tnode->type) { - case PLANE_X: - front = start[0] - tnode->dist; - back = stop[0] - tnode->dist; - break; - case PLANE_Y: - front = start[1] - tnode->dist; - back = stop[1] - tnode->dist; - break; - case PLANE_Z: - front = start[2] - tnode->dist; - back = stop[2] - tnode->dist; - break; - default: - front = (start[0]*tnode->normal[0] + start[1]*tnode->normal[1] + start[2]*tnode->normal[2]) - tnode->dist; - back = (stop[0]*tnode->normal[0] + stop[1]*tnode->normal[1] + stop[2]*tnode->normal[2]) - tnode->dist; - break; - } - - if (front >= -TRACE_ON_EPSILON && back >= -TRACE_ON_EPSILON) { - return TraceLine_r (tnode->children[0], start, stop, tw); - } - - if (front < TRACE_ON_EPSILON && back < TRACE_ON_EPSILON) { - return TraceLine_r (tnode->children[1], start, stop, tw); - } - - side = front < 0; - - frac = front / (front-back); - - mid[0] = start[0] + (stop[0] - start[0])*frac; - mid[1] = start[1] + (stop[1] - start[1])*frac; - mid[2] = start[2] + (stop[2] - start[2])*frac; - - r = TraceLine_r (tnode->children[side], start, mid, tw); - - if (r) { - return r; - } - -// trace->planeNum = tnode->planeNum; - return TraceLine_r (tnode->children[!side], mid, stop, tw); -} - -//========================================================================================== - - -/* -================ -SphereCull -================ -*/ -qboolean SphereCull( vec3_t start, vec3_t stop, vec3_t origin, float radius ) { - vec3_t v; - float d; - vec3_t dir; - float len; - vec3_t on; - - VectorSubtract( stop, start, dir ); - len = VectorNormalize( dir, dir ); - - VectorSubtract( origin, start, v ); - d = DotProduct( v, dir ); - if ( d > len + radius ) { - return qtrue; // too far ahead - } - if ( d < -radius ) { - return qtrue; // too far behind - } - VectorMA( start, d, dir, on ); - - VectorSubtract( on, origin, v ); - - len = VectorLength( v ); - - if ( len > radius ) { - return qtrue; // too far to the side - } - - return qfalse; // must be traced against -} - -/* -================ -TraceAgainstSurface -================ -*/ -void TraceAgainstSurface( traceWork_t *tw, surfaceTest_t *surf ) { - int i; - - // if surfaces are trans - if ( SphereCull( tw->start, tw->end, surf->origin, surf->radius ) ) { - if ( numthreads == 1 ) { - c_cullTrace++; - } - return; - } - - if ( numthreads == 1 ) { - c_testTrace++; - c_testFacets += surf->numFacets; - } - - /* - // MrE: backface culling - if (!surf->patch && surf->numFacets) { - // if the surface does not cast an alpha shadow - if ( !(surf->shader->surfaceFlags & SURF_ALPHASHADOW) ) { - vec3_t vec; - VectorSubtract(tw->end, tw->start, vec); - if (DotProduct(vec, surf->facets->surface) > 0) - return; - } - } - */ - - // test against each facet - for ( i = 0 ; i < surf->numFacets ; i++ ) { - TraceAgainstFacet( tw, surf->shader, surf->facets + i ); - } -} - -/* -============= -TraceLine - -Follow the trace just through the solid leafs first, and only -if it passes that, trace against the objects inside the empty leafs -Returns qtrue if the trace hit any - -traceWork_t is only a parameter to crutch up poor large local allocations on -winNT and macOS. It should be allocated in the worker function, but never -looked at. - -leave testAll false if all you care about is if it hit anything at all. -if you need to know the exact first point of impact (for a sun trace), set -testAll to true -============= -*/ -extern qboolean patchshadows; - -void TraceLine( const vec3_t start, const vec3_t stop, trace_t *trace, qboolean testAll, traceWork_t *tw ) { - int r; - int i, j; - dleaf_t *leaf; - float oldHitFrac; - surfaceTest_t *test; - int surfaceNum; - byte surfaceTested[MAX_MAP_DRAW_SURFS/8]; - ; - - if ( numthreads == 1 ) { - c_totalTrace++; - } - - // assume all light gets through, unless the ray crosses - // a translucent surface - trace->filter[0] = 1.0; - trace->filter[1] = 1.0; - trace->filter[2] = 1.0; - - VectorCopy( start, tw->start ); - VectorCopy( stop, tw->end ); - tw->trace = trace; - - tw->numOpenLeafs = 0; - - trace->passSolid = qfalse; - trace->hitFraction = 1.0; - - r = TraceLine_r( 0, start, stop, tw ); - - // if we hit a solid leaf, stop without testing the leaf - // surfaces. Note that the plane and endpoint might not - // be the first solid intersection along the ray. - if ( r && !testAll ) { - return; - } - - if ( noSurfaces ) { - return; - } - - memset( surfaceTested, 0, (numDrawSurfaces+7)/8 ); - oldHitFrac = trace->hitFraction; - - for ( i = 0 ; i < tw->numOpenLeafs ; i++ ) { - leaf = &dleafs[ tw->openLeafNumbers[ i ] ]; - for ( j = 0 ; j < leaf->numLeafSurfaces ; j++ ) { - surfaceNum = dleafsurfaces[ leaf->firstLeafSurface + j ]; - - // make sure we don't test the same ray against a surface more than once - if ( surfaceTested[ surfaceNum>>3 ] & ( 1 << ( surfaceNum & 7) ) ) { - continue; - } - surfaceTested[ surfaceNum>>3 ] |= ( 1 << ( surfaceNum & 7 ) ); - - test = surfaceTest[ surfaceNum ]; - if ( !test ) { - continue; - } - // - if ( !tw->patchshadows && test->patch ) { - continue; - } - TraceAgainstSurface( tw, test ); - } - - // if the trace is now solid, we can't possibly hit anything closer - if ( trace->hitFraction < oldHitFrac ) { - trace->passSolid = qtrue; - break; - } - } - - for ( i = 0 ; i < 3 ; i++ ) { - trace->hit[i] = start[i] + ( stop[i] - start[i] ) * trace->hitFraction; - } -} - diff --git a/q3map/lightmaps.c b/q3map/lightmaps.c deleted file mode 100644 index ce1fc12..0000000 --- a/q3map/lightmaps.c +++ /dev/null @@ -1,395 +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" - - -/* - - Lightmap allocation has to be done after all flood filling and - visible surface determination. - -*/ - -int numSortShaders; -mapDrawSurface_t *surfsOnShader[MAX_MAP_SHADERS]; - - -int allocated[LIGHTMAP_WIDTH]; - -int numLightmaps = 1; -int c_exactLightmap; - - -void PrepareNewLightmap( void ) { - memset( allocated, 0, sizeof( allocated ) ); - numLightmaps++; -} - -/* -=============== -AllocLMBlock - -returns a texture number and the position inside it -=============== -*/ -qboolean AllocLMBlock (int w, int h, int *x, int *y) -{ - int i, j; - int best, best2; - - best = LIGHTMAP_HEIGHT; - - for ( i=0 ; i <= LIGHTMAP_WIDTH-w ; i++ ) { - best2 = 0; - - for (j=0 ; j<w ; j++) { - if (allocated[i+j] >= best) { - break; - } - if (allocated[i+j] > best2) { - best2 = allocated[i+j]; - } - } - if (j == w) { // this is a valid spot - *x = i; - *y = best = best2; - } - } - - if (best + h > LIGHTMAP_HEIGHT) { - return qfalse; - } - - for (i=0 ; i<w ; i++) { - allocated[*x + i] = best + h; - } - - return qtrue; -} - - -/* -=================== -AllocateLightmapForPatch -=================== -*/ -//#define LIGHTMAP_PATCHSHIFT - -void AllocateLightmapForPatch( mapDrawSurface_t *ds ) { - int i, j, k; - drawVert_t *verts; - int w, h; - int x, y; - float s, t; - mesh_t mesh, *subdividedMesh, *tempMesh, *newmesh; - int widthtable[LIGHTMAP_WIDTH], heighttable[LIGHTMAP_HEIGHT], ssize; - - verts = ds->verts; - - mesh.width = ds->patchWidth; - mesh.height = ds->patchHeight; - mesh.verts = verts; - newmesh = SubdivideMesh( mesh, 8, 999 ); - - PutMeshOnCurve( *newmesh ); - tempMesh = RemoveLinearMeshColumnsRows( newmesh ); - FreeMesh(newmesh); - - ssize = samplesize; - if (ds->shaderInfo->lightmapSampleSize) - ssize = ds->shaderInfo->lightmapSampleSize; - -#ifdef LIGHTMAP_PATCHSHIFT - subdividedMesh = SubdivideMeshQuads( tempMesh, ssize, LIGHTMAP_WIDTH-1, widthtable, heighttable); -#else - subdividedMesh = SubdivideMeshQuads( tempMesh, ssize, LIGHTMAP_WIDTH, widthtable, heighttable); -#endif - - w = subdividedMesh->width; - h = subdividedMesh->height; - -#ifdef LIGHTMAP_PATCHSHIFT - w++; - h++; -#endif - - FreeMesh(subdividedMesh); - - // allocate the lightmap - c_exactLightmap += w * h; - - if ( !AllocLMBlock( w, h, &x, &y ) ) { - PrepareNewLightmap(); - if ( !AllocLMBlock( w, h, &x, &y ) ) { - Error("Entity %i, brush %i: Lightmap allocation failed", - ds->mapBrush->entitynum, ds->mapBrush->brushnum ); - } - } - -#ifdef LIGHTMAP_PATCHSHIFT - w--; - h--; -#endif - - // set the lightmap texture coordinates in the drawVerts - ds->lightmapNum = numLightmaps - 1; - ds->lightmapWidth = w; - ds->lightmapHeight = h; - ds->lightmapX = x; - ds->lightmapY = y; - - for ( i = 0 ; i < ds->patchWidth ; i++ ) { - for ( k = 0 ; k < w ; k++ ) { - if ( originalWidths[k] >= i ) { - break; - } - } - if (k >= w) - k = w-1; - s = x + k; - for ( j = 0 ; j < ds->patchHeight ; j++ ) { - for ( k = 0 ; k < h ; k++ ) { - if ( originalHeights[k] >= j ) { - break; - } - } - if (k >= h) - k = h-1; - t = y + k; - verts[i + j * ds->patchWidth].lightmap[0] = ( s + 0.5 ) / LIGHTMAP_WIDTH; - verts[i + j * ds->patchWidth].lightmap[1] = ( t + 0.5 ) / LIGHTMAP_HEIGHT; - } - } -} - - -/* -=================== -AllocateLightmapForSurface -=================== -*/ -//#define LIGHTMAP_BLOCK 16 -void AllocateLightmapForSurface( mapDrawSurface_t *ds ) { - vec3_t mins, maxs, size, exactSize, delta; - int i; - drawVert_t *verts; - int w, h; - int x, y, ssize; - int axis; - vec3_t vecs[2]; - float s, t; - vec3_t origin; - plane_t *plane; - float d; - vec3_t planeNormal; - - if ( ds->patch ) { - AllocateLightmapForPatch( ds ); - return; - } - - ssize = samplesize; - if (ds->shaderInfo->lightmapSampleSize) - ssize = ds->shaderInfo->lightmapSampleSize; - - plane = &mapplanes[ ds->side->planenum ]; - - // bound the surface - ClearBounds( mins, maxs ); - verts = ds->verts; - for ( i = 0 ; i < ds->numVerts ; i++ ) { - AddPointToBounds( verts[i].xyz, mins, maxs ); - } - - // round to the lightmap resolution - for ( i = 0 ; i < 3 ; i++ ) { - exactSize[i] = maxs[i] - mins[i]; - mins[i] = ssize * floor( mins[i] / ssize ); - maxs[i] = ssize * ceil( maxs[i] / ssize ); - size[i] = (maxs[i] - mins[i]) / ssize + 1; - } - - // the two largest axis will be the lightmap size - memset( vecs, 0, sizeof( vecs ) ); - - planeNormal[0] = fabs( plane->normal[0] ); - planeNormal[1] = fabs( plane->normal[1] ); - planeNormal[2] = fabs( plane->normal[2] ); - - if ( planeNormal[0] >= planeNormal[1] && planeNormal[0] >= planeNormal[2] ) { - w = size[1]; - h = size[2]; - axis = 0; - vecs[0][1] = 1.0 / ssize; - vecs[1][2] = 1.0 / ssize; - } else if ( planeNormal[1] >= planeNormal[0] && planeNormal[1] >= planeNormal[2] ) { - w = size[0]; - h = size[2]; - axis = 1; - vecs[0][0] = 1.0 / ssize; - vecs[1][2] = 1.0 / ssize; - } else { - w = size[0]; - h = size[1]; - axis = 2; - vecs[0][0] = 1.0 / ssize; - vecs[1][1] = 1.0 / ssize; - } - - if ( !plane->normal[axis] ) { - Error( "Chose a 0 valued axis" ); - } - - if ( w > LIGHTMAP_WIDTH ) { - VectorScale ( vecs[0], (float)LIGHTMAP_WIDTH/w, vecs[0] ); - w = LIGHTMAP_WIDTH; - } - - if ( h > LIGHTMAP_HEIGHT ) { - VectorScale ( vecs[1], (float)LIGHTMAP_HEIGHT/h, vecs[1] ); - h = LIGHTMAP_HEIGHT; - } - - c_exactLightmap += w * h; - - if ( !AllocLMBlock( w, h, &x, &y ) ) { - PrepareNewLightmap(); - if ( !AllocLMBlock( w, h, &x, &y ) ) { - Error("Entity %i, brush %i: Lightmap allocation failed", - ds->mapBrush->entitynum, ds->mapBrush->brushnum ); - } - } - - // set the lightmap texture coordinates in the drawVerts - ds->lightmapNum = numLightmaps - 1; - ds->lightmapWidth = w; - ds->lightmapHeight = h; - ds->lightmapX = x; - ds->lightmapY = y; - - for ( i = 0 ; i < ds->numVerts ; i++ ) { - VectorSubtract( verts[i].xyz, mins, delta ); - s = DotProduct( delta, vecs[0] ) + x + 0.5; - t = DotProduct( delta, vecs[1] ) + y + 0.5; - verts[i].lightmap[0] = s / LIGHTMAP_WIDTH; - verts[i].lightmap[1] = t / LIGHTMAP_HEIGHT; - } - - // calculate the world coordinates of the lightmap samples - - // project mins onto plane to get origin - d = DotProduct( mins, plane->normal ) - plane->dist; - d /= plane->normal[ axis ]; - VectorCopy( mins, origin ); - origin[axis] -= d; - - // project stepped lightmap blocks and subtract to get planevecs - for ( i = 0 ; i < 2 ; i++ ) { - vec3_t normalized; - float len; - - len = VectorNormalize( vecs[i], normalized ); - VectorScale( normalized, (1.0/len), vecs[i] ); - d = DotProduct( vecs[i], plane->normal ); - d /= plane->normal[ axis ]; - vecs[i][axis] -= d; - } - - VectorCopy( origin, ds->lightmapOrigin ); - VectorCopy( vecs[0], ds->lightmapVecs[0] ); - VectorCopy( vecs[1], ds->lightmapVecs[1] ); - VectorCopy( plane->normal, ds->lightmapVecs[2] ); -} - -/* -=================== -AllocateLightmaps -=================== -*/ -void AllocateLightmaps( entity_t *e ) { - int i, j; - mapDrawSurface_t *ds; - shaderInfo_t *si; - - qprintf ("--- AllocateLightmaps ---\n"); - - - // sort all surfaces by shader so common shaders will usually - // be in the same lightmap - numSortShaders = 0; - - for ( i = e->firstDrawSurf ; i < numMapDrawSurfs ; i++ ) { - ds = &mapDrawSurfs[i]; - if ( !ds->numVerts ) { - continue; // leftover from a surface subdivision - } - if ( ds->miscModel ) { - continue; - } - if ( !ds->patch ) { - VectorCopy( mapplanes[ds->side->planenum].normal, ds->lightmapVecs[2] ); - } - - // search for this shader - for ( j = 0 ; j < numSortShaders ; j++ ) { - if ( ds->shaderInfo == surfsOnShader[j]->shaderInfo ) { - ds->nextOnShader = surfsOnShader[j]; - surfsOnShader[j] = ds; - break; - } - } - if ( j == numSortShaders ) { - if ( numSortShaders >= MAX_MAP_SHADERS ) { - Error( "MAX_MAP_SHADERS" ); - } - surfsOnShader[j] = ds; - numSortShaders++; - } - } - qprintf( "%5i unique shaders\n", numSortShaders ); - - // for each shader, allocate lightmaps for each surface - -// numLightmaps = 0; -// PrepareNewLightmap(); - - for ( i = 0 ; i < numSortShaders ; i++ ) { - si = surfsOnShader[i]->shaderInfo; - - for ( ds = surfsOnShader[i] ; ds ; ds = ds->nextOnShader ) { - // some surfaces don't need lightmaps allocated for them - if ( si->surfaceFlags & SURF_NOLIGHTMAP ) { - ds->lightmapNum = -1; - } else if ( si->surfaceFlags & SURF_POINTLIGHT ) { - ds->lightmapNum = -3; - } else { - AllocateLightmapForSurface( ds ); - } - } - } - - qprintf( "%7i exact lightmap texels\n", c_exactLightmap ); - qprintf( "%7i block lightmap texels\n", numLightmaps * LIGHTMAP_WIDTH*LIGHTMAP_HEIGHT ); -} - - - diff --git a/q3map/lightv.c b/q3map/lightv.c deleted file mode 100644 index 3e9617b..0000000 --- a/q3map/lightv.c +++ /dev/null @@ -1,5748 +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 "cmdlib.h" -#include "mathlib.h" -#include "bspfile.h" -#include "imagelib.h" -#include "threads.h" -#include "mutex.h" -#include "scriplib.h" - -#include "shaders.h" -#include "mesh.h" - -#ifdef _WIN32 -//Improve floating-point consistency. -#pragma optimize( "p", on ) -#endif - -#ifdef _WIN32 -#include "../libs/pakstuff.h" -#endif - -#define MAX_CLUSTERS 16384 -#define MAX_PORTALS 32768 -#define MAX_FACETS 65536 -#define MAX_LIGHTS 16384 - -#define LIGHTMAP_SIZE 128 - -#define LIGHTMAP_PIXELSHIFT 0.5 - -//#define LIGHTMAP_PATCHSHIFT - -#define PORTALFILE "PRT1" - -#define ON_EPSILON 0.1 - -#define VectorSet(v, x, y, z) v[0] = x;v[1] = y;v[2] = z; - -typedef struct -{ - vec3_t normal; - float dist; -} plane_t; - -#define MAX_POINTS_ON_WINDING 64 -//NOTE: whenever this is overflowed parts of lightmaps might end up not being lit -#define MAX_POINTS_ON_FIXED_WINDING 48 - -typedef struct -{ - int numpoints; - vec3_t points[MAX_POINTS_ON_FIXED_WINDING]; // variable sized -} winding_t; - -typedef struct -{ - plane_t plane; // normal pointing into neighbor - int leaf; // neighbor - winding_t *winding; - vec3_t origin; // for fast clip testing - float radius; -} lportal_t; - -#define MAX_PORTALS_ON_LEAF 128 -typedef struct lleaf_s -{ - int numportals; - lportal_t *portals[MAX_PORTALS_ON_LEAF]; - // - int numSurfaces; - int firstSurface; -} lleaf_t; - -typedef struct lFacet_s -{ - int num; - plane_t plane; - vec3_t points[4]; // - int numpoints; - float lightmapCoords[4][2]; - plane_t boundaries[4]; // negative is outside the bounds - float textureMatrix[2][4]; // texture coordinates for translucency - float lightmapMatrix[2][4]; // lightmap texture coordinates - vec3_t mins; - int x, y, width, height; -} lFacet_t; - -typedef struct lsurfaceTest_s -{ - vec3_t mins, maxs; - vec3_t origin; - float radius; - qboolean patch; // true if this is a patch - qboolean trisoup; // true if this is a triangle soup - int numFacets; - lFacet_t *facets; - mesh_t *detailMesh; // detailed mesh with points for each lmp - shaderInfo_t *shader; // for translucency - mutex_t *mutex; - int numvolumes; // number of volumes casted at this surface - // - int always_tracelight; - int always_vlight; -} lsurfaceTest_t; - -//volume types -#define VOLUME_NORMAL 0 -#define VOLUME_DIRECTED 1 - -#define MAX_TRANSLUCENTFACETS 32 - -typedef struct lightvolume_s -{ - int num; - int cluster; //cluster this light volume started in - plane_t endplane; //end plane - plane_t farplane; //original end plane - vec3_t points[MAX_POINTS_ON_WINDING]; //end winding points - plane_t planes[MAX_POINTS_ON_WINDING]; //volume bounding planes - int numplanes; //number of volume bounding planes - int type; //light volume type - //list with translucent surfaces the volume went through - int transFacets[MAX_TRANSLUCENTFACETS]; - int transSurfaces[MAX_TRANSLUCENTFACETS]; - int numtransFacets; - //clusters already tested - byte clusterTested[MAX_CLUSTERS/8]; - //facets already tested - byte facetTested[MAX_FACETS/8]; - int facetNum; //number of the facet blocking the light in this volume - int surfaceNum; //number of the surface blocking the light in this volume -} lightvolume_t; - -//light types -#define LIGHT_POINTRADIAL 1 -#define LIGHT_POINTSPOT 2 -#define LIGHT_POINTFAKESURFACE 3 -#define LIGHT_SURFACEDIRECTED 4 -#define LIGHT_SURFACERADIAL 5 -#define LIGHT_SURFACESPOT 6 - -//light distance attenuation types -#define LDAT_QUADRATIC 0 -#define LDAT_LINEAR 1 -#define LDAT_NOSCALE 2 - -//light angle attenuation types -#define LAAT_NORMAL 0 -#define LAAT_QUADRATIC 1 -#define LAAT_DOUBLEQUADRATIC 2 - -typedef struct vlight_s -{ - vec3_t origin; //light origin, for point lights - winding_t w; //light winding, for area lights - vec4_t plane; //light winding plane - vec3_t normal; //direction of the light - int type; //light type - vec3_t color; //light color - qboolean twosided; //radiates light at both sides of the winding - int style; //light style (not used) - int atten_disttype; //light distance attenuation type - int atten_angletype; //light angle attenuation type - float atten_distscale; //distance attenuation scale - float atten_anglescale; //angle attenuation scale - float radiusByDist; //radius by distance for spot lights - float photons; //emitted photons - float intensity; //intensity - vec3_t emitColor; //full out-of-gamut value (not used) - struct shaderInfo_s *si; //shader info - int insolid; //set when light is in solid -} vlight_t; - -float lightLinearScale = 1.0 / 8000; -float lightPointScale = 7500; -float lightAreaScale = 0.25; -float lightFormFactorValueScale = 3; -int lightDefaultSubdivide = 999; // vary by surface size? -vec3_t lightAmbientColor; - -int portalclusters, numportals, numfaces; -lleaf_t *leafs; -lportal_t *portals; -int numvlights = 0; -vlight_t *vlights[MAX_LIGHTS]; -int nostitching = 0; -int noalphashading = 0; -int nocolorshading = 0; -int nobackfaceculling = 0; -int defaulttracelight = 0; -int radiosity = 0; -int radiosity_scale; - -int clustersurfaces[MAX_MAP_LEAFFACES]; -int numclustersurfaces = 0; -lsurfaceTest_t *lsurfaceTest[MAX_MAP_DRAW_SURFS]; -int numfacets; -float lightmappixelarea[MAX_MAP_LIGHTING/3]; -float *lightFloats;//[MAX_MAP_LIGHTING]; - -// from polylib.c -winding_t *AllocWinding (int points); -void FreeWinding (winding_t *w); -void WindingCenter (winding_t *w, vec3_t center); -void WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs); -vec_t WindingArea (winding_t *w); -winding_t *BaseWindingForPlane (vec3_t normal, vec_t dist); -void ClipWindingEpsilon (winding_t *in, vec3_t normal, vec_t dist, - vec_t epsilon, winding_t **front, winding_t **back); -winding_t *ReverseWinding (winding_t *w); - -// from light.c -extern char source[1024]; -extern vec3_t surfaceOrigin[ MAX_MAP_DRAW_SURFS ]; -extern int entitySurface[ MAX_MAP_DRAW_SURFS ]; -extern int samplesize; -extern int novertexlighting; -extern int nogridlighting; -extern qboolean patchshadows; -extern vec3_t gridSize; - -float PointToPolygonFormFactor( const vec3_t point, const vec3_t normal, const winding_t *w ); -void ColorToBytes( const float *color, byte *colorBytes ); -void CountLightmaps( void ); -void GridAndVertexLighting( void ); -void SetEntityOrigins( void ); - - -//#define DEBUGNET - -#ifdef DEBUGNET - -#include "l_net.h" - -socket_t *debug_socket; - -/* -===================== -DebugNet_Setup -===================== -*/ -void DebugNet_Setup(void) -{ - address_t address; - int i; - - Net_Setup(); - Net_StringToAddress("127.0.0.1:28000", &address); - for (i = 0; i < 10; i++) - { - debug_socket = Net_Connect(&address, 28005 + i); - if (debug_socket) - break; - } -} - -/* -===================== -DebugNet_Shutdown -===================== -*/ -void DebugNet_Shutdown(void) -{ - netmessage_t msg; - - if (debug_socket) - { - NMSG_Clear(&msg); - NMSG_WriteByte(&msg, 1); - Net_Send(debug_socket, &msg); - Net_Disconnect(debug_socket); - } - debug_socket = NULL; - Net_Shutdown(); -} - -/* -===================== -DebugNet_RemoveAllPolys -===================== -*/ -void DebugNet_RemoveAllPolys(void) -{ - netmessage_t msg; - - if (!debug_socket) - return; - NMSG_Clear(&msg); - NMSG_WriteByte(&msg, 2); //remove all debug polys - Net_Send(debug_socket, &msg); -} - -/* -==================== -DebugNet_DrawWinding -===================== -*/ -void DebugNet_DrawWinding(winding_t *w, int color) -{ - netmessage_t msg; - int i; - - if (!debug_socket) - return; - NMSG_Clear(&msg); - NMSG_WriteByte(&msg, 0); //draw a winding - NMSG_WriteByte(&msg, w->numpoints); //number of points - NMSG_WriteLong(&msg, color); //color - for (i = 0; i < w->numpoints; i++) - { - NMSG_WriteFloat(&msg, w->points[i][0]); - NMSG_WriteFloat(&msg, w->points[i][1]); - NMSG_WriteFloat(&msg, w->points[i][2]); - } - Net_Send(debug_socket, &msg); -} - -/* -===================== -DebugNet_DrawLine -===================== -*/ -void DebugNet_DrawLine(vec3_t p1, vec3_t p2, int color) -{ - netmessage_t msg; - - if (!debug_socket) - return; - NMSG_Clear(&msg); - NMSG_WriteByte(&msg, 1); //draw a line - NMSG_WriteLong(&msg, color); //color - NMSG_WriteFloat(&msg, p1[0]); - NMSG_WriteFloat(&msg, p1[1]); - NMSG_WriteFloat(&msg, p1[2]); - NMSG_WriteFloat(&msg, p2[0]); - NMSG_WriteFloat(&msg, p2[1]); - NMSG_WriteFloat(&msg, p2[2]); - Net_Send(debug_socket, &msg); -} - -/* -===================== -DebugNet_DrawMesh -===================== -*/ -void DebugNet_DrawMesh(mesh_t *mesh) -{ - int i, j; - float dot; - drawVert_t *v1, *v2, *v3, *v4; - winding_t winding; - plane_t plane; - vec3_t d1, d2; - - for ( i = 0 ; i < mesh->width - 1 ; i++ ) { - for ( j = 0 ; j < mesh->height - 1 ; j++ ) { - - v1 = mesh->verts + j * mesh->width + i; - v2 = v1 + 1; - v3 = v1 + mesh->width + 1; - v4 = v1 + mesh->width; - - VectorSubtract( v4->xyz, v1->xyz, d1 ); - VectorSubtract( v3->xyz, v1->xyz, d2 ); - CrossProduct( d2, d1, plane.normal ); - if ( VectorNormalize( plane.normal, plane.normal ) != 0 ) - { - plane.dist = DotProduct( v1->xyz, plane.normal ); - dot = DotProduct(plane.normal, v2->xyz) - plane.dist; - if (fabs(dot) < 0.1) - { - VectorCopy(v1->xyz, winding.points[0]); - VectorCopy(v4->xyz, winding.points[1]); - VectorCopy(v3->xyz, winding.points[2]); - VectorCopy(v2->xyz, winding.points[3]); - winding.numpoints = 4; - DebugNet_DrawWinding(&winding, 2); - continue; - } - } - - winding.numpoints = 3; - VectorCopy(v1->xyz, winding.points[0]); - VectorCopy(v4->xyz, winding.points[1]); - VectorCopy(v3->xyz, winding.points[2]); - DebugNet_DrawWinding(&winding, 2); - - VectorCopy(v1->xyz, winding.points[0]); - VectorCopy(v3->xyz, winding.points[1]); - VectorCopy(v2->xyz, winding.points[2]); - DebugNet_DrawWinding(&winding, 2); - } - } -} - -/* -===================== -VL_DrawLightVolume -===================== -*/ -int VL_ChopWinding (winding_t *in, plane_t *split, float epsilon); - -void VL_DrawLightVolume(vlight_t *light, lightvolume_t *volume) -{ - winding_t w; - int i; - vec3_t p2, invlight; - - memcpy(w.points, volume->points, volume->numplanes * sizeof(vec3_t)); - w.numpoints = volume->numplanes; - DebugNet_DrawWinding(&w, 2); - - if (volume->type == VOLUME_DIRECTED) - { - VectorCopy(light->normal, invlight); - VectorInverse(invlight); - for (i = 0; i < volume->numplanes; i++) - { - VectorCopy(volume->points[i], w.points[0]); - VectorCopy(volume->points[(i+1) % volume->numplanes], w.points[1]); - VectorMA(w.points[1], MAX_WORLD_COORD, invlight, w.points[2]); - VectorMA(w.points[0], MAX_WORLD_COORD, invlight, w.points[3]); - w.numpoints = 4; - DebugNet_DrawWinding(&w, 2); - VectorMA(volume->points[i], 8, volume->planes[i].normal, p2); - DebugNet_DrawLine(volume->points[i], p2, 3); - } - } - else - { - // - VectorCopy(light->origin, w.points[0]); - w.numpoints = 3; - for (i = 0; i < volume->numplanes; i++) - { - VectorCopy(volume->points[i], w.points[1]); - VectorCopy(volume->points[(i+1) % volume->numplanes], w.points[2]); - VL_ChopWinding(&w, &volume->endplane, 0); - DebugNet_DrawWinding(&w, 2); - VectorMA(volume->points[i], 8, volume->planes[i].normal, p2); - DebugNet_DrawLine(volume->points[i], p2, 3); - } - } -} - -/* -============= -VL_DrawLightmapPixel -============= -*/ -void VL_DrawLightmapPixel(int surfaceNum, int x, int y, int color) -{ - winding_t w; - dsurface_t *ds; - mesh_t *mesh; - - ds = &drawSurfaces[surfaceNum]; - - if (ds->surfaceType == MST_PATCH) - { - mesh = lsurfaceTest[surfaceNum]->detailMesh; - VectorCopy( mesh->verts[(y-ds->lightmapY)*mesh->width+x-ds->lightmapX].xyz, w.points[0]); - VectorCopy( mesh->verts[(y+1-ds->lightmapY)*mesh->width+x-ds->lightmapX].xyz, w.points[1]); - VectorCopy( mesh->verts[(y+1-ds->lightmapY)*mesh->width+x+1-ds->lightmapX].xyz, w.points[2]); - VectorCopy( mesh->verts[(y-ds->lightmapY)*mesh->width+x+1-ds->lightmapX].xyz, w.points[3]); - w.numpoints = 4; - } - else - { - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT - ds->lightmapX, ds->lightmapVecs[0], w.points[0]); - VectorMA(w.points[0], (float) y - LIGHTMAP_PIXELSHIFT - ds->lightmapY, ds->lightmapVecs[1], w.points[0]); - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT - ds->lightmapX, ds->lightmapVecs[0], w.points[1]); - VectorMA(w.points[1], (float) y - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapY, ds->lightmapVecs[1], w.points[1]); - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapX, ds->lightmapVecs[0], w.points[2]); - VectorMA(w.points[2], (float) y - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapY, ds->lightmapVecs[1], w.points[2]); - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapX, ds->lightmapVecs[0], w.points[3]); - VectorMA(w.points[3], (float) y - LIGHTMAP_PIXELSHIFT - ds->lightmapY, ds->lightmapVecs[1], w.points[3]); - w.numpoints = 4; - } - DebugNet_DrawWinding(&w, color); -} - -/* -============ -VL_DrawPortals -============ -*/ -void VL_DrawPortals(void) -{ - int j; - lportal_t *p; - - for (j = 0; j < numportals * 2; j++) - { - p = portals + j; - DebugNet_DrawWinding(p->winding, 1); - } -} - -/* -============ -VL_DrawLeaf -============ -*/ -void VL_DrawLeaf(int cluster) -{ - int i; - lleaf_t *leaf; - lportal_t *p; - - leaf = &leafs[cluster]; - for (i = 0; i < leaf->numportals; i++) - { - p = leaf->portals[i]; - DebugNet_DrawWinding(p->winding, 1); - } -} - -#endif //DEBUGNET - -/* -============= -VL_SplitWinding -============= -*/ -int VL_SplitWinding (winding_t *in, winding_t *back, plane_t *split, float epsilon) -{ - vec_t dists[128]; - int sides[128]; - int counts[3]; - vec_t dot; - int i, j; - vec_t *p1, *p2; - vec3_t mid; - winding_t out; - winding_t *neww; - - counts[0] = counts[1] = counts[2] = 0; - - // determine sides for each point - for (i=0 ; i<in->numpoints ; i++) - { - dot = DotProduct (in->points[i], split->normal); - dot -= split->dist; - dists[i] = dot; - if (dot > epsilon) - sides[i] = SIDE_FRONT; - else if (dot < -epsilon) - sides[i] = SIDE_BACK; - else - { - sides[i] = SIDE_ON; - } - counts[sides[i]]++; - } - - if (!counts[SIDE_BACK]) - { - if (!counts[SIDE_FRONT]) - return SIDE_ON; - else - return SIDE_FRONT; - } - - if (!counts[SIDE_FRONT]) - { - return SIDE_BACK; - } - - sides[i] = sides[0]; - dists[i] = dists[0]; - - neww = &out; - - neww->numpoints = 0; - back->numpoints = 0; - - for (i=0 ; i<in->numpoints ; i++) - { - p1 = in->points[i]; - - if (neww->numpoints >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VL_SplitWinding -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return SIDE_FRONT; // can't chop -- fall back to original - } - if (back->numpoints >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VL_SplitWinding -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return SIDE_FRONT; - } - - if (sides[i] == SIDE_ON) - { - VectorCopy (p1, neww->points[neww->numpoints]); - neww->numpoints++; - VectorCopy (p1, back->points[back->numpoints]); - back->numpoints++; - continue; - } - - if (sides[i] == SIDE_FRONT) - { - VectorCopy (p1, neww->points[neww->numpoints]); - neww->numpoints++; - } - if (sides[i] == SIDE_BACK) - { - VectorCopy (p1, back->points[back->numpoints]); - back->numpoints++; - } - - if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) - continue; - - if (neww->numpoints >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VL_SplitWinding -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return SIDE_FRONT; // can't chop -- fall back to original - } - - if (back->numpoints >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VL_SplitWinding -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return SIDE_FRONT; // can't chop -- fall back to original - } - - // generate a split point - p2 = in->points[(i+1)%in->numpoints]; - - dot = dists[i] / (dists[i]-dists[i+1]); - for (j=0 ; j<3 ; j++) - { // avoid round off error when possible - if (split->normal[j] == 1) - mid[j] = split->dist; - else if (split->normal[j] == -1) - mid[j] = -split->dist; - else - mid[j] = p1[j] + dot*(p2[j]-p1[j]); - } - - VectorCopy (mid, neww->points[neww->numpoints]); - neww->numpoints++; - VectorCopy (mid, back->points[back->numpoints]); - back->numpoints++; - } - memcpy(in, &out, sizeof(winding_t)); - - return SIDE_CROSS; -} - -/* -===================== -VL_LinkSurfaceIntoCluster -===================== -*/ -void VL_LinkSurfaceIntoCluster(int cluster, int surfaceNum) -{ - lleaf_t *leaf; - int i; - - leaf = &leafs[cluster]; - - for (i = 0; i < leaf->numSurfaces; i++) - { - if (clustersurfaces[leaf->firstSurface + i] == surfaceNum) - return; - } - for (i = numclustersurfaces; i > leaf->firstSurface + leaf->numSurfaces; i--) - clustersurfaces[i] = clustersurfaces[i-1]; - for (i = 0; i < portalclusters; i++) - { - if (i == cluster) - continue; - if (leafs[i].firstSurface >= leaf->firstSurface + leaf->numSurfaces) - leafs[i].firstSurface++; - } - clustersurfaces[leaf->firstSurface + leaf->numSurfaces] = surfaceNum; - leaf->numSurfaces++; - numclustersurfaces++; - if (numclustersurfaces >= MAX_MAP_LEAFFACES) - Error("MAX_MAP_LEAFFACES"); -} - -/* -===================== -VL_R_LinkSurface -===================== -*/ -void VL_R_LinkSurface(int nodenum, int surfaceNum, winding_t *w) -{ - int leafnum, cluster, res; - dnode_t *node; - dplane_t *plane; - winding_t back; - plane_t split; - - while(nodenum >= 0) - { - node = &dnodes[nodenum]; - plane = &dplanes[node->planeNum]; - - VectorCopy(plane->normal, split.normal); - split.dist = plane->dist; - res = VL_SplitWinding (w, &back, &split, 0.1); - - if (res == SIDE_FRONT) - { - nodenum = node->children[0]; - } - else if (res == SIDE_BACK) - { - nodenum = node->children[1]; - } - else if (res == SIDE_ON) - { - memcpy(&back, w, sizeof(winding_t)); - VL_R_LinkSurface(node->children[1], surfaceNum, &back); - nodenum = node->children[0]; - } - else - { - VL_R_LinkSurface(node->children[1], surfaceNum, &back); - nodenum = node->children[0]; - } - } - leafnum = -nodenum - 1; - cluster = dleafs[leafnum].cluster; - if (cluster != -1) - { - VL_LinkSurfaceIntoCluster(cluster, surfaceNum); - } -} - -/* -===================== -VL_LinkSurfaces - -maybe link each facet seperately instead of the test surfaces? -===================== -*/ -void VL_LinkSurfaces(void) -{ - int i, j; - lsurfaceTest_t *test; - lFacet_t *facet; - winding_t winding; - - for ( i = 0 ; i < numDrawSurfaces ; i++ ) - { - test = lsurfaceTest[ i ]; - if (!test) - continue; - for (j = 0; j < test->numFacets; j++) - { - facet = &test->facets[j]; - memcpy(winding.points, facet->points, facet->numpoints * sizeof(vec3_t)); - winding.numpoints = facet->numpoints; - VL_R_LinkSurface(0, i, &winding); - } - } -} - -/* -===================== -VL_TextureMatrixFromPoints -===================== -*/ -void VL_TextureMatrixFromPoints( lFacet_t *f, drawVert_t *a, drawVert_t *b, drawVert_t *c ) { - int i, j; - float t; - float m[3][4]; - float s; - - // This is an incredibly stupid way of solving a three variable equation - for ( i = 0 ; i < 2 ; i++ ) { - - m[0][0] = a->xyz[0]; - m[0][1] = a->xyz[1]; - m[0][2] = a->xyz[2]; - m[0][3] = a->st[i]; - - m[1][0] = b->xyz[0]; - m[1][1] = b->xyz[1]; - m[1][2] = b->xyz[2]; - m[1][3] = b->st[i]; - - m[2][0] = c->xyz[0]; - m[2][1] = c->xyz[1]; - m[2][2] = c->xyz[2]; - m[2][3] = c->st[i]; - - if ( fabs(m[1][0]) > fabs(m[0][0]) && fabs(m[1][0]) > fabs(m[2][0]) ) { - for ( j = 0 ; j < 4 ; j ++ ) { - t = m[0][j]; - m[0][j] = m[1][j]; - m[1][j] = t; - } - } else if ( fabs(m[2][0]) > fabs(m[0][0]) && fabs(m[2][0]) > fabs(m[1][0]) ) { - for ( j = 0 ; j < 4 ; j ++ ) { - t = m[0][j]; - m[0][j] = m[2][j]; - m[2][j] = t; - } - } - - s = 1.0 / m[0][0]; - m[0][0] *= s; - m[0][1] *= s; - m[0][2] *= s; - m[0][3] *= s; - - s = m[1][0]; - m[1][0] -= m[0][0] * s; - m[1][1] -= m[0][1] * s; - m[1][2] -= m[0][2] * s; - m[1][3] -= m[0][3] * s; - - s = m[2][0]; - m[2][0] -= m[0][0] * s; - m[2][1] -= m[0][1] * s; - m[2][2] -= m[0][2] * s; - m[2][3] -= m[0][3] * s; - - if ( fabs(m[2][1]) > fabs(m[1][1]) ) { - for ( j = 0 ; j < 4 ; j ++ ) { - t = m[1][j]; - m[1][j] = m[2][j]; - m[2][j] = t; - } - } - - s = 1.0 / m[1][1]; - m[1][0] *= s; - m[1][1] *= s; - m[1][2] *= s; - m[1][3] *= s; - - s = m[2][1];// / m[1][1]; - m[2][0] -= m[1][0] * s; - m[2][1] -= m[1][1] * s; - m[2][2] -= m[1][2] * s; - m[2][3] -= m[1][3] * s; - - s = 1.0 / m[2][2]; - m[2][0] *= s; - m[2][1] *= s; - m[2][2] *= s; - m[2][3] *= s; - - f->textureMatrix[i][2] = m[2][3]; - f->textureMatrix[i][1] = m[1][3] - f->textureMatrix[i][2] * m[1][2]; - f->textureMatrix[i][0] = m[0][3] - f->textureMatrix[i][2] * m[0][2] - f->textureMatrix[i][1] * m[0][1]; - - f->textureMatrix[i][3] = 0; -/* - s = fabs( DotProduct( a->xyz, f->textureMatrix[i] ) - a->st[i] ); - if ( s > 0.01 ) { - Error( "Bad textureMatrix" ); - } - s = fabs( DotProduct( b->xyz, f->textureMatrix[i] ) - b->st[i] ); - if ( s > 0.01 ) { - Error( "Bad textureMatrix" ); - } - s = fabs( DotProduct( c->xyz, f->textureMatrix[i] ) - c->st[i] ); - if ( s > 0.01 ) { - Error( "Bad textureMatrix" ); - } -*/ - } -} - -/* -===================== -VL_LightmapMatrixFromPoints -===================== -*/ -void VL_LightmapMatrixFromPoints( dsurface_t *dsurf, shaderInfo_t *si, lFacet_t *f, drawVert_t *a, drawVert_t *b, drawVert_t *c ) { - int i, j; - float t; - float m[3][4], al, bl, cl; - float s; - int h, w, ssize; - vec3_t mins, maxs, delta, size, planeNormal; - drawVert_t *verts; - static int message; - - // vertex-lit triangle model - if ( dsurf->surfaceType == MST_TRIANGLE_SOUP ) { - return; - } - - if ( dsurf->lightmapNum < 0 ) { - return; // doesn't need lighting - } - - VectorClear(f->mins); - if (dsurf->surfaceType != MST_PATCH) - { - ssize = samplesize; - if (si->lightmapSampleSize) - ssize = si->lightmapSampleSize; - ClearBounds( mins, maxs ); - verts = &drawVerts[dsurf->firstVert]; - for ( i = 0 ; i < dsurf->numVerts ; i++ ) { - AddPointToBounds( verts[i].xyz, mins, maxs ); - } - // round to the lightmap resolution - for ( i = 0 ; i < 3 ; i++ ) { - mins[i] = ssize * floor( mins[i] / ssize ); - maxs[i] = ssize * ceil( maxs[i] / ssize ); - f->mins[i] = mins[i]; - size[i] = (maxs[i] - mins[i]) / ssize + 1; - } - // the two largest axis will be the lightmap size - VectorClear(f->lightmapMatrix[0]); - f->lightmapMatrix[0][3] = 0; - VectorClear(f->lightmapMatrix[1]); - f->lightmapMatrix[1][3] = 0; - - planeNormal[0] = fabs( dsurf->lightmapVecs[2][0] ); - planeNormal[1] = fabs( dsurf->lightmapVecs[2][1] ); - planeNormal[2] = fabs( dsurf->lightmapVecs[2][2] ); - - if ( planeNormal[0] >= planeNormal[1] && planeNormal[0] >= planeNormal[2] ) { - w = size[1]; - h = size[2]; - f->lightmapMatrix[0][1] = 1.0 / ssize; - f->lightmapMatrix[1][2] = 1.0 / ssize; - } else if ( planeNormal[1] >= planeNormal[0] && planeNormal[1] >= planeNormal[2] ) { - w = size[0]; - h = size[2]; - f->lightmapMatrix[0][0] = 1.0 / ssize; - f->lightmapMatrix[1][2] = 1.0 / ssize; - } else { - w = size[0]; - h = size[1]; - f->lightmapMatrix[0][0] = 1.0 / ssize; - f->lightmapMatrix[1][1] = 1.0 / ssize; - } - if ( w > LIGHTMAP_WIDTH ) { - VectorScale ( f->lightmapMatrix[0], (float)LIGHTMAP_SIZE/w, f->lightmapMatrix[0] ); - } - - if ( h > LIGHTMAP_HEIGHT ) { - VectorScale ( f->lightmapMatrix[1], (float)LIGHTMAP_SIZE/h, f->lightmapMatrix[1] ); - } - VectorSubtract(a->xyz, f->mins, delta); - s = (DotProduct( delta, f->lightmapMatrix[0] ) + dsurf->lightmapX + 0.5) / LIGHTMAP_SIZE; - if ( fabs(s - a->lightmap[0]) > 0.01 ) { - _printf( "Bad lightmapMatrix" ); - } - t = (DotProduct( delta, f->lightmapMatrix[1] ) + dsurf->lightmapY + 0.5) / LIGHTMAP_SIZE; - if ( fabs(t - a->lightmap[1]) > 0.01 ) { - _printf( "Bad lightmapMatrix" ); - } - VectorSubtract(b->xyz, f->mins, delta); - s = (DotProduct( delta, f->lightmapMatrix[0] ) + dsurf->lightmapX + 0.5) / LIGHTMAP_SIZE; - if ( fabs(s - b->lightmap[0]) > 0.01 ) { - _printf( "Bad lightmapMatrix" ); - } - t = (DotProduct( delta, f->lightmapMatrix[1] ) + dsurf->lightmapY + 0.5) / LIGHTMAP_SIZE; - if ( fabs(t - b->lightmap[1]) > 0.01 ) { - _printf( "Bad lightmapMatrix" ); - } - VectorSubtract(c->xyz, f->mins, delta); - s = (DotProduct( delta, f->lightmapMatrix[0] ) + dsurf->lightmapX + 0.5) / LIGHTMAP_SIZE; - if ( fabs(s - c->lightmap[0]) > 0.01 ) { - _printf( "Bad lightmapMatrix" ); - } - t = (DotProduct( delta, f->lightmapMatrix[1] ) + dsurf->lightmapY + 0.5) / LIGHTMAP_SIZE; - if ( fabs(t - c->lightmap[1]) > 0.01 ) { - _printf( "Bad lightmapMatrix" ); - } - VectorAdd(f->mins, surfaceOrigin[dsurf - drawSurfaces], f->mins); - return; - } - // This is an incredibly stupid way of solving a three variable equation - for ( i = 0 ; i < 2 ; i++ ) { - - if (i) - al = a->lightmap[i] - ((float) dsurf->lightmapY + 0.5) / LIGHTMAP_SIZE; - else - al = a->lightmap[i] - ((float) dsurf->lightmapX + 0.5) / LIGHTMAP_SIZE; - - m[0][0] = a->xyz[0] - f->mins[0]; - m[0][1] = a->xyz[1] - f->mins[1]; - m[0][2] = a->xyz[2] - f->mins[2]; - m[0][3] = al; - - if (i) - bl = b->lightmap[i] - ((float) dsurf->lightmapY + 0.5) / LIGHTMAP_SIZE; - else - bl = b->lightmap[i] - ((float) dsurf->lightmapX + 0.5) / LIGHTMAP_SIZE; - - m[1][0] = b->xyz[0] - f->mins[0]; - m[1][1] = b->xyz[1] - f->mins[1]; - m[1][2] = b->xyz[2] - f->mins[2]; - m[1][3] = bl; - - if (i) - cl = c->lightmap[i] - ((float) dsurf->lightmapY + 0.5) / LIGHTMAP_SIZE; - else - cl = c->lightmap[i] - ((float) dsurf->lightmapX + 0.5) / LIGHTMAP_SIZE; - - m[2][0] = c->xyz[0] - f->mins[0]; - m[2][1] = c->xyz[1] - f->mins[1]; - m[2][2] = c->xyz[2] - f->mins[2]; - m[2][3] = cl; - - if ( fabs(m[1][0]) > fabs(m[0][0]) && fabs(m[1][0]) >= fabs(m[2][0]) ) { - for ( j = 0 ; j < 4 ; j ++ ) { - t = m[0][j]; - m[0][j] = m[1][j]; - m[1][j] = t; - } - } else if ( fabs(m[2][0]) > fabs(m[0][0]) && fabs(m[2][0]) >= fabs(m[1][0]) ) { - for ( j = 0 ; j < 4 ; j ++ ) { - t = m[0][j]; - m[0][j] = m[2][j]; - m[2][j] = t; - } - } - - if (m[0][0]) - { - s = 1.0 / m[0][0]; - m[0][0] *= s; - m[0][1] *= s; - m[0][2] *= s; - m[0][3] *= s; - - s = m[1][0]; - m[1][0] -= m[0][0] * s; - m[1][1] -= m[0][1] * s; - m[1][2] -= m[0][2] * s; - m[1][3] -= m[0][3] * s; - - s = m[2][0]; - m[2][0] -= m[0][0] * s; - m[2][1] -= m[0][1] * s; - m[2][2] -= m[0][2] * s; - m[2][3] -= m[0][3] * s; - } - - if ( fabs(m[2][1]) > fabs(m[1][1]) ) { - for ( j = 0 ; j < 4 ; j ++ ) { - t = m[1][j]; - m[1][j] = m[2][j]; - m[2][j] = t; - } - } - - if (m[1][1]) - { - s = 1.0 / m[1][1]; - m[1][0] *= s; - m[1][1] *= s; - m[1][2] *= s; - m[1][3] *= s; - - s = m[2][1]; - m[2][0] -= m[1][0] * s; - m[2][1] -= m[1][1] * s; - m[2][2] -= m[1][2] * s; - m[2][3] -= m[1][3] * s; - } - - if (m[2][2]) - { - s = 1.0 / m[2][2]; - m[2][0] *= s; - m[2][1] *= s; - m[2][2] *= s; - m[2][3] *= s; - } - - f->lightmapMatrix[i][2] = m[2][3]; - f->lightmapMatrix[i][1] = m[1][3] - f->lightmapMatrix[i][2] * m[1][2]; - f->lightmapMatrix[i][0] = m[0][3] - f->lightmapMatrix[i][2] * m[0][2] - f->lightmapMatrix[i][1] * m[0][1]; - - f->lightmapMatrix[i][3] = 0; - - VectorSubtract(a->xyz, f->mins, delta); - s = fabs( DotProduct( delta, f->lightmapMatrix[i] ) - al ); - if ( s > 0.01 ) { - if (!message) - _printf( "Bad lightmapMatrix\n" ); - message = qtrue; - } - VectorSubtract(b->xyz, f->mins, delta); - s = fabs( DotProduct( delta, f->lightmapMatrix[i] ) - bl ); - if ( s > 0.01 ) { - if (!message) - _printf( "Bad lightmapMatrix\n" ); - message = qtrue; - } - VectorSubtract(c->xyz, f->mins, delta); - s = fabs( DotProduct( delta, f->lightmapMatrix[i] ) - cl ); - if ( s > 0.01 ) { - if (!message) - _printf( "Bad lightmapMatrix\n" ); - message = qtrue; - } - VectorAdd(f->mins, surfaceOrigin[dsurf - drawSurfaces], f->mins); - } -} - -/* -============= -Plane_Equal -============= -*/ -#define NORMAL_EPSILON 0.0001 -#define DIST_EPSILON 0.02 - -int Plane_Equal(plane_t *a, plane_t *b, int flip) -{ - vec3_t normal; - float dist; - - if (flip) { - normal[0] = - b->normal[0]; - normal[1] = - b->normal[1]; - normal[2] = - b->normal[2]; - dist = - b->dist; - } - else { - normal[0] = b->normal[0]; - normal[1] = b->normal[1]; - normal[2] = b->normal[2]; - dist = b->dist; - } - if ( - fabs(a->normal[0] - normal[0]) < NORMAL_EPSILON - && fabs(a->normal[1] - normal[1]) < NORMAL_EPSILON - && fabs(a->normal[2] - normal[2]) < NORMAL_EPSILON - && fabs(a->dist - dist) < DIST_EPSILON ) - return qtrue; - return qfalse; -} - -/* -============= -VL_PlaneFromPoints -============= -*/ -qboolean VL_PlaneFromPoints( plane_t *plane, const vec3_t a, const vec3_t b, const vec3_t c ) { - vec3_t d1, d2; - - VectorSubtract( b, a, d1 ); - VectorSubtract( c, a, d2 ); - CrossProduct( d2, d1, plane->normal ); - if ( VectorNormalize( plane->normal, plane->normal ) == 0 ) { - return qfalse; - } - - plane->dist = DotProduct( a, plane->normal ); - return qtrue; -} - -/* -===================== -VL_GenerateBoundaryForPoints -===================== -*/ -void VL_GenerateBoundaryForPoints( plane_t *boundary, plane_t *plane, vec3_t a, vec3_t b ) { - vec3_t d1; - - // make a perpendicular vector to the edge and the surface - VectorSubtract( a, b, d1 ); - CrossProduct( plane->normal, d1, boundary->normal ); - VectorNormalize( boundary->normal, boundary->normal ); - boundary->dist = DotProduct( a, boundary->normal ); -} - -/* -===================== -VL_GenerateFacetFor3Points -===================== -*/ -qboolean VL_GenerateFacetFor3Points( dsurface_t *dsurf, shaderInfo_t *si, lFacet_t *f, drawVert_t *a, drawVert_t *b, drawVert_t *c ) { - // - vec3_t dir; - int i; - - // if we can't generate a valid plane for the points, ignore the facet - if ( !VL_PlaneFromPoints( &f->plane, a->xyz, b->xyz, c->xyz ) ) { - f->numpoints = 0; - return qfalse; - } - - f->num = numfacets++; - - VectorAdd( a->xyz, surfaceOrigin[dsurf - drawSurfaces], f->points[0] ); - VectorAdd( b->xyz, surfaceOrigin[dsurf - drawSurfaces], f->points[1] ); - VectorAdd( c->xyz, surfaceOrigin[dsurf - drawSurfaces], f->points[2] ); - - f->lightmapCoords[0][0] = a->lightmap[0]; - f->lightmapCoords[0][1] = a->lightmap[1]; - f->lightmapCoords[1][0] = b->lightmap[0]; - f->lightmapCoords[1][1] = b->lightmap[1]; - f->lightmapCoords[2][0] = c->lightmap[0]; - f->lightmapCoords[2][1] = c->lightmap[1]; - - VL_GenerateBoundaryForPoints( &f->boundaries[0], &f->plane, f->points[0], f->points[1] ); - VL_GenerateBoundaryForPoints( &f->boundaries[1], &f->plane, f->points[1], f->points[2] ); - VL_GenerateBoundaryForPoints( &f->boundaries[2], &f->plane, f->points[2], f->points[0] ); - - for (i = 0; i < 3; i++) - { - VectorSubtract(f->points[(i+1)%3], f->points[i], dir); - if (VectorLength(dir) < 0.1) - return qfalse; - } - - VL_TextureMatrixFromPoints( f, a, b, c ); - VL_LightmapMatrixFromPoints( dsurf, si, f, a, b, c ); - - f->numpoints = 3; - - return qtrue; -} - -/* -===================== -VL_GenerateFacetFor4Points - -Attempts to use four points as a planar quad -===================== -*/ -#define PLANAR_EPSILON 0.1 -qboolean VL_GenerateFacetFor4Points( dsurface_t *dsurf, shaderInfo_t *si, lFacet_t *f, drawVert_t *a, drawVert_t *b, drawVert_t *c, drawVert_t *d ) { - float dist; - vec3_t dir; - int i; - plane_t plane; - - // if we can't generate a valid plane for the points, ignore the facet - if ( !VL_PlaneFromPoints( &f->plane, a->xyz, b->xyz, c->xyz ) ) { - f->numpoints = 0; - return qfalse; - } - - // if the fourth point is also on the plane, we can make a quad facet - dist = DotProduct( d->xyz, f->plane.normal ) - f->plane.dist; - if ( fabs( dist ) > PLANAR_EPSILON ) { - f->numpoints = 0; - return qfalse; - } - - VectorAdd( a->xyz, surfaceOrigin[dsurf - drawSurfaces], f->points[0] ); - VectorAdd( b->xyz, surfaceOrigin[dsurf - drawSurfaces], f->points[1] ); - VectorAdd( c->xyz, surfaceOrigin[dsurf - drawSurfaces], f->points[2] ); - VectorAdd( d->xyz, surfaceOrigin[dsurf - drawSurfaces], f->points[3] ); - - for (i = 1; i < 4; i++) - { - if ( !VL_PlaneFromPoints( &plane, f->points[i], f->points[(i+1) % 4], f->points[(i+2) % 4]) ) { - f->numpoints = 0; - return qfalse; - } - - if (!Plane_Equal(&f->plane, &plane, qfalse)) { - f->numpoints = 0; - return qfalse; - } - } - - f->lightmapCoords[0][0] = a->lightmap[0]; - f->lightmapCoords[0][1] = a->lightmap[1]; - f->lightmapCoords[1][0] = b->lightmap[0]; - f->lightmapCoords[1][1] = b->lightmap[1]; - f->lightmapCoords[2][0] = c->lightmap[0]; - f->lightmapCoords[2][1] = c->lightmap[1]; - f->lightmapCoords[3][0] = d->lightmap[0]; - f->lightmapCoords[3][1] = d->lightmap[1]; - - VL_GenerateBoundaryForPoints( &f->boundaries[0], &f->plane, f->points[0], f->points[1] ); - VL_GenerateBoundaryForPoints( &f->boundaries[1], &f->plane, f->points[1], f->points[2] ); - VL_GenerateBoundaryForPoints( &f->boundaries[2], &f->plane, f->points[2], f->points[3] ); - VL_GenerateBoundaryForPoints( &f->boundaries[3], &f->plane, f->points[3], f->points[0] ); - - for (i = 0; i < 4; i++) - { - VectorSubtract(f->points[(i+1)%4], f->points[i], dir); - if (VectorLength(dir) < 0.1) - return qfalse; - } - - VL_TextureMatrixFromPoints( f, a, b, c ); - VL_LightmapMatrixFromPoints( dsurf, si, f, a, b, c ); - - f->num = numfacets++; - f->numpoints = 4; - - return qtrue; -} - -/* -=============== -VL_SphereFromBounds -=============== -*/ -void VL_SphereFromBounds( vec3_t mins, vec3_t maxs, vec3_t origin, float *radius ) { - vec3_t temp; - - VectorAdd( mins, maxs, origin ); - VectorScale( origin, 0.5, origin ); - VectorSubtract( maxs, origin, temp ); - *radius = VectorLength( temp ); -} - -/* -==================== -VL_FacetsForTriangleSurface -==================== -*/ -void VL_FacetsForTriangleSurface( dsurface_t *dsurf, shaderInfo_t *si, lsurfaceTest_t *test ) { - int i; - drawVert_t *v1, *v2, *v3, *v4; - int count; - int i1, i2, i3, i4, i5, i6; - - test->patch = qfalse; - if (dsurf->surfaceType == MST_TRIANGLE_SOUP) - test->trisoup = qtrue; - else - test->trisoup = qfalse; - test->numFacets = dsurf->numIndexes / 3; - test->facets = malloc( sizeof( test->facets[0] ) * test->numFacets ); - test->shader = si; - - count = 0; - for ( i = 0 ; i < test->numFacets ; i++ ) { - i1 = drawIndexes[ dsurf->firstIndex + i*3 ]; - i2 = drawIndexes[ dsurf->firstIndex + i*3 + 1 ]; - i3 = drawIndexes[ dsurf->firstIndex + i*3 + 2 ]; - - v1 = &drawVerts[ dsurf->firstVert + i1 ]; - v2 = &drawVerts[ dsurf->firstVert + i2 ]; - v3 = &drawVerts[ dsurf->firstVert + i3 ]; - - // try and make a quad out of two triangles - if ( i != test->numFacets - 1 ) { - i4 = drawIndexes[ dsurf->firstIndex + i*3 + 3 ]; - i5 = drawIndexes[ dsurf->firstIndex + i*3 + 4 ]; - i6 = drawIndexes[ dsurf->firstIndex + i*3 + 5 ]; - if ( i4 == i3 && i5 == i2 ) { - v4 = &drawVerts[ dsurf->firstVert + i6 ]; - if ( VL_GenerateFacetFor4Points( dsurf, si, &test->facets[count], v1, v2, v4, v3 ) ) { - count++; - i++; // skip next tri - continue; - } - } - } - - if (VL_GenerateFacetFor3Points( dsurf, si, &test->facets[count], v1, v2, v3 )) { - count++; - } - } - - // we may have turned some pairs into quads - test->numFacets = count; -} - -/* -==================== -VL_FacetsForPatch -==================== -*/ -void VL_FacetsForPatch( dsurface_t *dsurf, int surfaceNum, shaderInfo_t *si, lsurfaceTest_t *test ) { - int i, j, x, y; - drawVert_t *v1, *v2, *v3, *v4; - int count, ssize; - mesh_t mesh; - mesh_t *subdivided, *detailmesh, *newmesh; - int widthtable[LIGHTMAP_SIZE], heighttable[LIGHTMAP_SIZE]; - - mesh.width = dsurf->patchWidth; - mesh.height = dsurf->patchHeight; - mesh.verts = &drawVerts[ dsurf->firstVert ]; - - newmesh = SubdivideMesh( mesh, 8, 999 ); - PutMeshOnCurve( *newmesh ); - MakeMeshNormals( *newmesh ); - - subdivided = RemoveLinearMeshColumnsRows( newmesh ); - FreeMesh(newmesh); - - // DebugNet_RemoveAllPolys(); - // DebugNet_DrawMesh(subdivided); - - ssize = samplesize; - if (si->lightmapSampleSize) - ssize = si->lightmapSampleSize; - - if ( dsurf->lightmapNum >= 0 ) { - - detailmesh = SubdivideMeshQuads( subdivided, ssize, LIGHTMAP_SIZE, widthtable, heighttable); - test->detailMesh = detailmesh; - - // DebugNet_RemoveAllPolys(); - // DebugNet_DrawMesh(detailmesh); - - if ( detailmesh->width != dsurf->lightmapWidth || detailmesh->height != dsurf->lightmapHeight ) { - Error( "Mesh lightmap miscount"); - } - } - else { - test->detailMesh = NULL; - memset(widthtable, 0, sizeof(widthtable)); - memset(heighttable, 0, sizeof(heighttable)); - } - - test->patch = qtrue; - test->trisoup = qfalse; - test->numFacets = ( subdivided->width - 1 ) * ( subdivided->height - 1 ) * 2; - test->facets = malloc( sizeof( test->facets[0] ) * test->numFacets ); - test->shader = si; - - count = 0; - x = 0; - for ( i = 0 ; i < subdivided->width - 1 ; i++ ) { - y = 0; - for ( j = 0 ; j < subdivided->height - 1 ; j++ ) { - - v1 = subdivided->verts + j * subdivided->width + i; - v2 = v1 + 1; - v3 = v1 + subdivided->width + 1; - v4 = v1 + subdivided->width; - - if ( VL_GenerateFacetFor4Points( dsurf, si, &test->facets[count], v1, v4, v3, v2 ) ) { - test->facets[count].x = x; - test->facets[count].y = y; - test->facets[count].width = widthtable[i]; - test->facets[count].height = heighttable[j]; - count++; - } else { - if (VL_GenerateFacetFor3Points( dsurf, si, &test->facets[count], v1, v4, v3 )) { - test->facets[count].x = x; - test->facets[count].y = y; - test->facets[count].width = widthtable[i]; - test->facets[count].height = heighttable[j]; - count++; - } - if (VL_GenerateFacetFor3Points( dsurf, si, &test->facets[count], v1, v3, v2 )) { - test->facets[count].x = x; - test->facets[count].y = y; - test->facets[count].width = widthtable[i]; - test->facets[count].height = heighttable[j]; - count++; - } - } - y += heighttable[j]; - } - x += widthtable[i]; - } - test->numFacets = count; - - FreeMesh(subdivided); -} - -/* -===================== -VL_InitSurfacesForTesting -===================== -*/ -void VL_InitSurfacesForTesting( void ) { - - int i, j, k; - dsurface_t *dsurf; - lsurfaceTest_t *test; - shaderInfo_t *si; - lFacet_t *facet; - - for ( i = 0 ; i < numDrawSurfaces ; i++ ) { - // don't light the entity surfaces with vlight - if ( entitySurface[i] ) - continue; - // - dsurf = &drawSurfaces[ i ]; - if ( !dsurf->numIndexes && !dsurf->patchWidth ) { - continue; - } - - si = ShaderInfoForShader( dshaders[ dsurf->shaderNum].shader ); - // if the surface is translucent and does not cast an alpha shadow - if ( (si->contents & CONTENTS_TRANSLUCENT) && !(si->surfaceFlags & SURF_ALPHASHADOW) ) { - // if the surface has no lightmap - if ( dsurf->lightmapNum < 0 ) - continue; - } - - test = malloc( sizeof( *test ) ); - memset(test, 0, sizeof( *test )); - test->mutex = MutexAlloc(); - test->numvolumes = 0; - if (si->forceTraceLight) - test->always_tracelight = qtrue; - else if (si->forceVLight) - test->always_vlight = qtrue; - lsurfaceTest[i] = test; - - if ( dsurf->surfaceType == MST_TRIANGLE_SOUP || dsurf->surfaceType == MST_PLANAR ) { - VL_FacetsForTriangleSurface( dsurf, si, test ); - } else if ( dsurf->surfaceType == MST_PATCH ) { - VL_FacetsForPatch( dsurf, i, si, test ); - } - if (numfacets >= MAX_FACETS) - Error("numfacets >= MAX_FACETS (%d)", MAX_FACETS); - - ClearBounds( test->mins, test->maxs ); - for (j = 0; j < test->numFacets; j++) - { - facet = &test->facets[j]; - for ( k = 0 ; k < facet->numpoints; k++) { - AddPointToBounds( facet->points[k], test->mins, test->maxs ); - } - } - VL_SphereFromBounds( test->mins, test->maxs, test->origin, &test->radius ); - } - _printf("%6d facets\n", numfacets); - _printf("linking surfaces...\n"); - VL_LinkSurfaces(); -} - -/* -============= -VL_ChopWinding -============= -*/ -int VL_ChopWinding (winding_t *in, plane_t *split, float epsilon) -{ - vec_t dists[128]; - int sides[128]; - int counts[3]; - vec_t dot; - int i, j; - vec_t *p1, *p2; - vec3_t mid; - winding_t out; - winding_t *neww; - - counts[0] = counts[1] = counts[2] = 0; - - // determine sides for each point - for (i=0 ; i<in->numpoints ; i++) - { - dot = DotProduct (in->points[i], split->normal); - dot -= split->dist; - dists[i] = dot; - if (dot > epsilon) - sides[i] = SIDE_FRONT; - else if (dot < -epsilon) - sides[i] = SIDE_BACK; - else - { - sides[i] = SIDE_ON; - } - counts[sides[i]]++; - } - - if (!counts[SIDE_BACK]) - { - if (!counts[SIDE_FRONT]) - return SIDE_ON; - else - return SIDE_FRONT; - } - - if (!counts[SIDE_FRONT]) - { - return SIDE_BACK; - } - - sides[i] = sides[0]; - dists[i] = dists[0]; - - neww = &out; - - neww->numpoints = 0; - - for (i=0 ; i<in->numpoints ; i++) - { - p1 = in->points[i]; - - if (neww->numpoints >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VL_ChopWinding -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return SIDE_FRONT; // can't chop -- fall back to original - } - - if (sides[i] == SIDE_ON) - { - VectorCopy (p1, neww->points[neww->numpoints]); - neww->numpoints++; - continue; - } - - if (sides[i] == SIDE_FRONT) - { - VectorCopy (p1, neww->points[neww->numpoints]); - neww->numpoints++; - } - - if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) - continue; - - if (neww->numpoints >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VL_ChopWinding -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return SIDE_FRONT; // can't chop -- fall back to original - } - - // generate a split point - p2 = in->points[(i+1)%in->numpoints]; - - dot = dists[i] / (dists[i]-dists[i+1]); - for (j=0 ; j<3 ; j++) - { // avoid round off error when possible - if (split->normal[j] == 1) - mid[j] = split->dist; - else if (split->normal[j] == -1) - mid[j] = -split->dist; - else - mid[j] = p1[j] + dot*(p2[j]-p1[j]); - } - - VectorCopy (mid, neww->points[neww->numpoints]); - neww->numpoints++; - } - memcpy(in, &out, sizeof(winding_t)); - - return SIDE_CROSS; -} - -/* -============= -VL_ChopWindingWithBrush - - returns all winding fragments outside the brush -============= -*/ -int VL_ChopWindingWithBrush(winding_t *w, dbrush_t *brush, winding_t *outwindings, int maxout) -{ - int i, res, numout; - winding_t front, back; - plane_t plane; - - numout = 0; - memcpy(front.points, w->points, w->numpoints * sizeof(vec3_t)); - front.numpoints = w->numpoints; - for (i = 0; i < brush->numSides; i++) - { - VectorCopy(dplanes[ dbrushsides[ brush->firstSide + i ].planeNum ].normal, plane.normal); - VectorInverse(plane.normal); - plane.dist = -dplanes[ dbrushsides[ brush->firstSide + i ].planeNum ].dist; - res = VL_SplitWinding(&front, &back, &plane, 0.1); - if (res == SIDE_BACK || res == SIDE_ON) - { - memcpy(outwindings[0].points, w->points, w->numpoints * sizeof(vec3_t)); - outwindings[0].numpoints = w->numpoints; - return 1; //did not intersect - } - if (res != SIDE_FRONT) - { - if (numout >= maxout) - { - _printf("WARNING: VL_ChopWindingWithBrush: more than %d windings\n", maxout); - return 0; - } - memcpy(outwindings[numout].points, back.points, back.numpoints * sizeof(vec3_t)); - outwindings[numout].numpoints = back.numpoints; - numout++; - } - } - return numout; -} - -/* -============= -VL_WindingAreaOutsideBrushes -============= -*/ -float VL_WindingAreaOutsideBrushes(winding_t *w, int *brushnums, int numbrushes) -{ - int i, j, numwindings[2], n; - winding_t windingsbuf[2][64]; - dbrush_t *brush; - float area; - - memcpy(windingsbuf[0][0].points, w->points, w->numpoints * sizeof(vec3_t)); - windingsbuf[0][0].numpoints = w->numpoints; - numwindings[0] = 1; - for (i = 0; i < numbrushes; i++) - { - brush = &dbrushes[brushnums[i]]; - if (!(dshaders[brush->shaderNum].contentFlags & ( - CONTENTS_LAVA - | CONTENTS_SLIME - | CONTENTS_WATER - | CONTENTS_FOG - | CONTENTS_AREAPORTAL - | CONTENTS_PLAYERCLIP - | CONTENTS_MONSTERCLIP - | CONTENTS_CLUSTERPORTAL - | CONTENTS_DONOTENTER - | CONTENTS_BODY - | CONTENTS_CORPSE - | CONTENTS_TRANSLUCENT - | CONTENTS_TRIGGER - | CONTENTS_NODROP) ) && - (dshaders[brush->shaderNum].contentFlags & CONTENTS_SOLID) ) - { - numwindings[!(i & 1)] = 0; - for (j = 0; j < numwindings[i&1]; j++) - { - n = VL_ChopWindingWithBrush(&windingsbuf[i&1][j], brush, - &windingsbuf[!(i&1)][numwindings[!(i&1)]], - 64 - numwindings[!(i&1)]); - numwindings[!(i&1)] += n; - } - if (!numwindings[!(i&1)]) - return 0; - } - else - { - for (j = 0; j < numwindings[i&1]; j++) - { - windingsbuf[!(i&1)][j] = windingsbuf[i&1][j]; - } - numwindings[!(i&1)] = numwindings[i&1]; - } - } - area = 0; - for (j = 0; j < numwindings[i&1]; j++) - { - area += WindingArea(&windingsbuf[i&1][j]); - } - return area; -} - -/* -============= -VL_R_WindingAreaOutsideSolid -============= -*/ -float VL_R_WindingAreaOutsideSolid(winding_t *w, vec3_t normal, int nodenum) -{ - int leafnum, res; - float area; - dnode_t *node; - dleaf_t *leaf; - dplane_t *plane; - winding_t back; - plane_t split; - - area = 0; - while(nodenum >= 0) - { - node = &dnodes[nodenum]; - plane = &dplanes[node->planeNum]; - - VectorCopy(plane->normal, split.normal); - split.dist = plane->dist; - res = VL_SplitWinding (w, &back, &split, 0.1); - - if (res == SIDE_FRONT) - { - nodenum = node->children[0]; - } - else if (res == SIDE_BACK) - { - nodenum = node->children[1]; - } - else if (res == SIDE_ON) - { - if (DotProduct(normal, plane->normal) > 0) - nodenum = node->children[0]; - else - nodenum = node->children[1]; - } - else - { - area += VL_R_WindingAreaOutsideSolid(&back, normal, node->children[1]); - nodenum = node->children[0]; - } - } - leafnum = -nodenum - 1; - leaf = &dleafs[leafnum]; - if (leaf->cluster != -1) - { - area += VL_WindingAreaOutsideBrushes(w, &dleafbrushes[leaf->firstLeafBrush], leaf->numLeafBrushes); - } - return area; -} - -/* -============= -VL_WindingAreaOutsideSolid -============= -*/ -float VL_WindingAreaOutsideSolid(winding_t *w, vec3_t normal) -{ - return VL_R_WindingAreaOutsideSolid(w, normal, 0); -} - -/* -============= -VL_ChopWindingWithFacet -============= -*/ -float VL_ChopWindingWithFacet(winding_t *w, lFacet_t *facet) -{ - int i; - - for (i = 0; i < facet->numpoints; i++) - { - if (VL_ChopWinding(w, &facet->boundaries[i], 0) == SIDE_BACK) - return 0; - } - if (nostitching) - return WindingArea(w); - else - return VL_WindingAreaOutsideSolid(w, facet->plane.normal); -} - -/* -============= -VL_CalcVisibleLightmapPixelArea - -nice brute force ;) -============= -*/ -void VL_CalcVisibleLightmapPixelArea(void) -{ - int i, j, x, y, k; - dsurface_t *ds; - lsurfaceTest_t *test; - mesh_t *mesh; - winding_t w, tmpw; - float area; - - _printf("calculating visible lightmap pixel area...\n"); - for ( i = 0 ; i < numDrawSurfaces ; i++ ) - { - test = lsurfaceTest[ i ]; - if (!test) - continue; - ds = &drawSurfaces[ i ]; - - if ( ds->lightmapNum < 0 ) - continue; - - for (y = 0; y < ds->lightmapHeight; y++) - { - for (x = 0; x < ds->lightmapWidth; x++) - { - if (ds->surfaceType == MST_PATCH) - { - if (y == ds->lightmapHeight-1) - continue; - if (x == ds->lightmapWidth-1) - continue; - mesh = lsurfaceTest[i]->detailMesh; - VectorCopy( mesh->verts[y*mesh->width+x].xyz, w.points[0]); - VectorCopy( mesh->verts[(y+1)*mesh->width+x].xyz, w.points[1]); - VectorCopy( mesh->verts[(y+1)*mesh->width+x+1].xyz, w.points[2]); - VectorCopy( mesh->verts[y*mesh->width+x+1].xyz, w.points[3]); - w.numpoints = 4; - if (nostitching) - area = WindingArea(&w); - else - area = VL_WindingAreaOutsideSolid(&w, mesh->verts[y*mesh->width+x].normal); - } - else - { - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT, ds->lightmapVecs[0], w.points[0]); - VectorMA(w.points[0], (float) y - LIGHTMAP_PIXELSHIFT, ds->lightmapVecs[1], w.points[0]); - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT, ds->lightmapVecs[0], w.points[3]); - VectorMA(w.points[3], (float) y - LIGHTMAP_PIXELSHIFT + 1, ds->lightmapVecs[1], w.points[3]); - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT + 1, ds->lightmapVecs[0], w.points[2]); - VectorMA(w.points[2], (float) y - LIGHTMAP_PIXELSHIFT + 1, ds->lightmapVecs[1], w.points[2]); - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT + 1, ds->lightmapVecs[0], w.points[1]); - VectorMA(w.points[1], (float) y - LIGHTMAP_PIXELSHIFT, ds->lightmapVecs[1], w.points[1]); - w.numpoints = 4; - area = 0; - for (j = 0; j < test->numFacets; j++) - { - memcpy(&tmpw, &w, sizeof(winding_t)); - area += VL_ChopWindingWithFacet(&tmpw, &test->facets[j]); - } - } - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - lightmappixelarea[k] = area; - } - } - } -} - -/* -============= -VL_FindAdjacentSurface -============= -*/ -int VL_FindAdjacentSurface(int surfaceNum, int facetNum, vec3_t p1, vec3_t p2, int *sNum, int *fNum, int *point) -{ - int i, j, k; - lsurfaceTest_t *test; - lFacet_t *facet; - dsurface_t *ds; - float *fp1, *fp2; - vec3_t dir; - plane_t *facetplane; - // winding_t w; - - facetplane = &lsurfaceTest[surfaceNum]->facets[facetNum].plane; - // DebugNet_RemoveAllPolys(); - // memcpy(w.points, lsurfaceTest[surfaceNum]->facets[facetNum].points, - // lsurfaceTest[surfaceNum]->facets[facetNum].numpoints * sizeof(vec3_t)); - // w.numpoints = lsurfaceTest[surfaceNum]->facets[facetNum].numpoints; - // DebugNet_DrawWinding(&w, 2); - for ( i = 0 ; i < numDrawSurfaces ; i++ ) - { - if (i == surfaceNum) - continue; - test = lsurfaceTest[ i ]; - if (!test) - continue; - if (test->trisoup)// || test->patch) - continue; - ds = &drawSurfaces[i]; - if ( ds->lightmapNum < 0 ) - continue; - //if this surface is not even near the edge - VectorSubtract(p1, test->origin, dir); - if (fabs(dir[0]) > test->radius || - fabs(dir[1]) > test->radius || - fabs(dir[1]) > test->radius) - { - VectorSubtract(p2, test->origin, dir); - if (fabs(dir[0]) > test->radius || - fabs(dir[1]) > test->radius || - fabs(dir[1]) > test->radius) - { - continue; - } - } - // - for (j = 0; j < test->numFacets; j++) - { - facet = &test->facets[j]; - // - //if (!Plane_Equal(&facet->plane, facetplane, qfalse)) - if (DotProduct(facet->plane.normal, facetplane->normal) < 0.9) - { - if (!test->trisoup && !test->patch) - break; - continue; - } - // - for (k = 0; k < facet->numpoints; k++) - { - fp1 = facet->points[k]; - if (fabs(p2[0] - fp1[0]) < 0.1 && - fabs(p2[1] - fp1[1]) < 0.1 && - fabs(p2[2] - fp1[2]) < 0.1) - { - fp2 = facet->points[(k+1) % facet->numpoints]; - if (fabs(p1[0] - fp2[0]) < 0.1 && - fabs(p1[1] - fp2[1]) < 0.1 && - fabs(p1[2] - fp2[2]) < 0.1) - { - // memcpy(w.points, facet->points, facet->numpoints * sizeof(vec3_t)); - // w.numpoints = facet->numpoints; - // DebugNet_DrawWinding(&w, 1); - *sNum = i; - *fNum = j; - *point = k; - return qtrue; - } - } - /* - else if (fabs(p1[0] - fp1[0]) < 0.1 && - fabs(p1[1] - fp1[1]) < 0.1 && - fabs(p1[2] - fp1[2]) < 0.1) - { - fp2 = facet->points[(k+1) % facet->numpoints]; - if (fabs(p2[0] - fp2[0]) < 0.1 && - fabs(p2[1] - fp2[1]) < 0.1 && - fabs(p2[2] - fp2[2]) < 0.1) - { - // memcpy(w.points, facet->points, facet->numpoints * sizeof(vec3_t)); - // w.numpoints = facet->numpoints; - // DebugNet_DrawWinding(&w, 1); - *sNum = i; - *fNum = j; - *point = k; - return qtrue; - } - } - //*/ - } - } - } - return qfalse; -} - -/* -============= -VL_SmoothenLightmapEdges - -this code is used to smoothen lightmaps across surface edges -============= -*/ -void VL_SmoothenLightmapEdges(void) -{ - int i, j, k, coords1[2][2]; - float coords2[2][2]; - int x1, y1, xinc1, yinc1, k1, k2; - float x2, y2, xinc2, yinc2, length; - int surfaceNum, facetNum, point; - lsurfaceTest_t *test; - lFacet_t *facet1, *facet2; - dsurface_t *ds1, *ds2; - float *p[2], s, t, *color1, *color2; - vec3_t dir, cross; - - for ( i = 0 ; i < numDrawSurfaces ; i++ ) - { - test = lsurfaceTest[ i ]; - if (!test) - continue; - if (test->trisoup)// || test->patch) - continue; - ds1 = &drawSurfaces[i]; - if ( ds1->lightmapNum < 0 ) - continue; - for (j = 0; j < test->numFacets; j++) - { - facet1 = &test->facets[j]; - // - for (k = 0; k < facet1->numpoints; k++) - { - p[0] = facet1->points[k]; - p[1] = facet1->points[(k+1)%facet1->numpoints]; - // - coords1[0][0] = facet1->lightmapCoords[k][0] * LIGHTMAP_SIZE; - coords1[0][1] = facet1->lightmapCoords[k][1] * LIGHTMAP_SIZE; - coords1[1][0] = facet1->lightmapCoords[(k+1)%facet1->numpoints][0] * LIGHTMAP_SIZE; - coords1[1][1] = facet1->lightmapCoords[(k+1)%facet1->numpoints][1] * LIGHTMAP_SIZE; - if (coords1[0][0] >= LIGHTMAP_SIZE) - coords1[0][0] = LIGHTMAP_SIZE-1; - if (coords1[0][1] >= LIGHTMAP_SIZE) - coords1[0][1] = LIGHTMAP_SIZE-1; - if (coords1[1][0] >= LIGHTMAP_SIZE) - coords1[1][0] = LIGHTMAP_SIZE-1; - if (coords1[1][1] >= LIGHTMAP_SIZE) - coords1[1][1] = LIGHTMAP_SIZE-1; - // try one row or column further because on flat faces the lightmap can - // extend beyond the edge - VectorSubtract(p[1], p[0], dir); - VectorNormalize(dir, dir); - CrossProduct(dir, facet1->plane.normal, cross); - // - if (coords1[0][0] - coords1[1][0] == 0) - { - s = DotProduct( cross, facet1->lightmapMatrix[0] ); - coords1[0][0] += s < 0 ? 1 : -1; - coords1[1][0] += s < 0 ? 1 : -1; - if (coords1[0][0] < ds1->lightmapX || coords1[0][0] >= ds1->lightmapX + ds1->lightmapWidth) - { - coords1[0][0] += s < 0 ? -1 : 1; - coords1[1][0] += s < 0 ? -1 : 1; - } - length = fabs(coords1[1][1] - coords1[0][1]); - } - else if (coords1[0][1] - coords1[1][1] == 0) - { - t = DotProduct( cross, facet1->lightmapMatrix[1] ); - coords1[0][1] += t < 0 ? 1 : -1; - coords1[1][1] += t < 0 ? 1 : -1; - if (coords1[0][1] < ds1->lightmapY || coords1[0][1] >= ds1->lightmapY + ds1->lightmapHeight) - { - coords1[0][1] += t < 0 ? -1 : 1; - coords1[1][1] += t < 0 ? -1 : 1; - } - length = fabs(coords1[1][0] - coords1[0][0]); - } - else - { - //the edge is not parallell to one of the lightmap axis - continue; - } - // - x1 = coords1[0][0]; - y1 = coords1[0][1]; - xinc1 = coords1[1][0] - coords1[0][0]; - if (xinc1 < 0) xinc1 = -1; - if (xinc1 > 0) xinc1 = 1; - yinc1 = coords1[1][1] - coords1[0][1]; - if (yinc1 < 0) yinc1 = -1; - if (yinc1 > 0) yinc1 = 1; - // the edge should be parallell to one of the lightmap axis - if (xinc1 != 0 && yinc1 != 0) - continue; - // - if (!VL_FindAdjacentSurface(i, j, p[0], p[1], &surfaceNum, &facetNum, &point)) - continue; - // - ds2 = &drawSurfaces[surfaceNum]; - facet2 = &lsurfaceTest[surfaceNum]->facets[facetNum]; - coords2[0][0] = facet2->lightmapCoords[(point+1)%facet2->numpoints][0] * LIGHTMAP_SIZE; - coords2[0][1] = facet2->lightmapCoords[(point+1)%facet2->numpoints][1] * LIGHTMAP_SIZE; - coords2[1][0] = facet2->lightmapCoords[point][0] * LIGHTMAP_SIZE; - coords2[1][1] = facet2->lightmapCoords[point][1] * LIGHTMAP_SIZE; - if (coords2[0][0] >= LIGHTMAP_SIZE) - coords2[0][0] = LIGHTMAP_SIZE-1; - if (coords2[0][1] >= LIGHTMAP_SIZE) - coords2[0][1] = LIGHTMAP_SIZE-1; - if (coords2[1][0] >= LIGHTMAP_SIZE) - coords2[1][0] = LIGHTMAP_SIZE-1; - if (coords2[1][1] >= LIGHTMAP_SIZE) - coords2[1][1] = LIGHTMAP_SIZE-1; - // - x2 = coords2[0][0]; - y2 = coords2[0][1]; - xinc2 = coords2[1][0] - coords2[0][0]; - if (length) - xinc2 = xinc2 / length; - yinc2 = coords2[1][1] - coords2[0][1]; - if (length) - yinc2 = yinc2 / length; - // the edge should be parallell to one of the lightmap axis - if ((int) xinc2 != 0 && (int) yinc2 != 0) - continue; - // - while(1) - { - k1 = ( ds1->lightmapNum * LIGHTMAP_HEIGHT + y1) * LIGHTMAP_WIDTH + x1; - k2 = ( ds2->lightmapNum * LIGHTMAP_HEIGHT + ((int) y2)) * LIGHTMAP_WIDTH + ((int) x2); - color1 = lightFloats + k1*3; - color2 = lightFloats + k2*3; - if (lightmappixelarea[k1] < 0.01) - { - color1[0] = color2[0]; - color1[1] = color2[1]; - color1[2] = color2[2]; - } - else - { - color1[0] = (float) color2[0] * 0.7 + (float) color1[0] * 0.3; - color1[1] = (float) color2[1] * 0.7 + (float) color1[1] * 0.3; - color1[2] = (float) color2[2] * 0.7 + (float) color1[2] * 0.3; - } - // - if (x1 == coords1[1][0] && - y1 == coords1[1][1]) - break; - x1 += xinc1; - y1 += yinc1; - x2 += xinc2; - y2 += yinc2; - if (x2 < ds2->lightmapX) - x2 = ds2->lightmapX; - if (x2 >= ds2->lightmapX + ds2->lightmapWidth) - x2 = ds2->lightmapX + ds2->lightmapWidth-1; - if (y2 < ds2->lightmapY) - y2 = ds2->lightmapY; - if (y2 >= ds2->lightmapY + ds2->lightmapHeight) - y2 = ds2->lightmapY + ds2->lightmapHeight-1; - } - } - } - } -} - -/* -============= -VL_FixLightmapEdges -============= -*/ -void VL_FixLightmapEdges(void) -{ - int i, j, x, y, k, foundvalue, height, width, index; - int pos, top, bottom; - dsurface_t *ds; - lsurfaceTest_t *test; - float color[3]; - float *ptr; - byte filled[(LIGHTMAP_SIZE+1) * (LIGHTMAP_SIZE+1) / 8]; - float lightmap_edge_epsilon; - - lightmap_edge_epsilon = 0.1 * samplesize; - for ( i = 0 ; i < numDrawSurfaces ; i++ ) - { - test = lsurfaceTest[ i ]; - if (!test) - continue; - ds = &drawSurfaces[ i ]; - - if ( ds->lightmapNum < 0 ) - continue; - if (ds->surfaceType == MST_PATCH) - { - height = ds->lightmapHeight - 1; - width = ds->lightmapWidth - 1; - } - else - { - height = ds->lightmapHeight; - width = ds->lightmapWidth; - } - memset(filled, 0, sizeof(filled)); -// printf("\n"); - for (x = 0; x < width; x++) - { - for (y = 0; y < height; y++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - if (lightmappixelarea[k] > lightmap_edge_epsilon) - { - index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x; - filled[index >> 3] |= 1 << (index & 7); -// printf("*"); - } -// else -// printf("_"); - } -// printf("\n"); - } - for (y = 0; y < height; y++) - { - pos = -2; - for (x = 0; x < width; x++) - { - index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x; - if (pos == -2) - { - if (filled[index >> 3] & (1 << (index & 7))) - pos = -1; - } - else if (pos == -1) - { - if (!(filled[index >> 3] & (1 << (index & 7)))) - pos = x - 1; - } - else - { - if (filled[index >> 3] & (1 << (index & 7))) - { - bottom = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + pos; - top = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - for (j = 0; j < (x - pos + 1) / 2; j++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + pos + j + 1; - index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + pos + j + 1; - filled[index >> 3] |= 1 << (index & 7); - (lightFloats + k*3)[0] = (lightFloats + top*3)[0]; - (lightFloats + k*3)[1] = (lightFloats + top*3)[1]; - (lightFloats + k*3)[2] = (lightFloats + top*3)[2]; - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x - j - 1; - index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x - j - 1; - filled[index >> 3] |= 1 << (index & 7); - (lightFloats + k*3)[0] = (lightFloats + bottom*3)[0]; - (lightFloats + k*3)[1] = (lightFloats + bottom*3)[1]; - (lightFloats + k*3)[2] = (lightFloats + bottom*3)[2]; - } - pos = -1; - } - } - } - } - for (x = 0; x < width; x++) - { - pos = -2; - for (y = 0; y < height; y++) - { - index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x; - if (pos == -2) - { - if (filled[index >> 3] & (1 << (index & 7))) - pos = -1; - } - else if (pos == -1) - { - if (!(filled[index >> 3] & (1 << (index & 7)))) - pos = y - 1; - } - else - { - if (filled[index >> 3] & (1 << (index & 7))) - { - bottom = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + pos) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - top = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - for (j = 0; j < (y - pos + 1) / 2; j++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + pos + j + 1) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - index = (ds->lightmapY + pos + j + 1) * LIGHTMAP_WIDTH + ds->lightmapX + x; - filled[index >> 3] |= 1 << (index & 7); - (lightFloats + k*3)[0] = (lightFloats + top*3)[0]; - (lightFloats + k*3)[1] = (lightFloats + top*3)[1]; - (lightFloats + k*3)[2] = (lightFloats + top*3)[2]; - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y - j - 1) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - index = (ds->lightmapY + y - j - 1) * LIGHTMAP_WIDTH + ds->lightmapX + x; - filled[index >> 3] |= 1 << (index & 7); - (lightFloats + k*3)[0] = (lightFloats + bottom*3)[0]; - (lightFloats + k*3)[1] = (lightFloats + bottom*3)[1]; - (lightFloats + k*3)[2] = (lightFloats + bottom*3)[2]; - } - pos = -1; - } - } - } - } - for (y = 0; y < height; y++) - { - foundvalue = qfalse; - for (x = 0; x < width; x++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x; - if (foundvalue) - { - if (filled[index >> 3] & (1 << (index & 7))) - { - ptr = lightFloats + k*3; - color[0] = ptr[0]; - color[1] = ptr[1]; - color[2] = ptr[2]; - } - else - { - ptr = lightFloats + k*3; - ptr[0] = color[0]; - ptr[1] = color[1]; - ptr[2] = color[2]; - filled[index >> 3] |= 1 << (index & 7); - } - } - else - { - if (filled[index >> 3] & (1 << (index & 7))) - { - ptr = lightFloats + k*3; - color[0] = ptr[0]; - color[1] = ptr[1]; - color[2] = ptr[2]; - foundvalue = qtrue; - } - } - } - foundvalue = qfalse; - for (x = width-1; x >= 0; x--) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x; - if (foundvalue) - { - if (filled[index >> 3] & (1 << (index & 7))) - { - ptr = lightFloats + k*3; - color[0] = ptr[0]; - color[1] = ptr[1]; - color[2] = ptr[2]; - } - else - { - ptr = lightFloats + k*3; - ptr[0] = color[0]; - ptr[1] = color[1]; - ptr[2] = color[2]; - filled[index >> 3] |= 1 << (index & 7); - } - } - else - { - if (filled[index >> 3] & (1 << (index & 7))) - { - ptr = lightFloats + k*3; - color[0] = ptr[0]; - color[1] = ptr[1]; - color[2] = ptr[2]; - foundvalue = qtrue; - } - } - } - } - for (x = 0; x < width; x++) - { - foundvalue = qfalse; - for (y = 0; y < height; y++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x; - if (foundvalue) - { - if (filled[index >> 3] & (1 << (index & 7))) - { - ptr = lightFloats + k*3; - color[0] = ptr[0]; - color[1] = ptr[1]; - color[2] = ptr[2]; - } - else - { - ptr = lightFloats + k*3; - ptr[0] = color[0]; - ptr[1] = color[1]; - ptr[2] = color[2]; - filled[index >> 3] |= 1 << (index & 7); - } - } - else - { - if (filled[index >> 3] & (1 << (index & 7))) - { - ptr = lightFloats + k*3; - color[0] = ptr[0]; - color[1] = ptr[1]; - color[2] = ptr[2]; - foundvalue = qtrue; - } - } - } - foundvalue = qfalse; - for (y = height-1; y >= 0; y--) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x; - if (foundvalue) - { - if (filled[index >> 3] & (1 << (index & 7))) - { - ptr = lightFloats + k*3; - color[0] = ptr[0]; - color[1] = ptr[1]; - color[2] = ptr[2]; - } - else - { - ptr = lightFloats + k*3; - ptr[0] = color[0]; - ptr[1] = color[1]; - ptr[2] = color[2]; - filled[index >> 3] |= 1 << (index & 7); - } - } - else - { - if (filled[index >> 3] & (1 << (index & 7))) - { - ptr = lightFloats + k*3; - color[0] = ptr[0]; - color[1] = ptr[1]; - color[2] = ptr[2]; - foundvalue = qtrue; - } - } - } - } - if (ds->surfaceType == MST_PATCH) - { - x = ds->lightmapWidth-1; - for (y = 0; y < ds->lightmapHeight; y++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - ptr = lightFloats + k*3; - ptr[0] = (lightFloats + (k-1)*3)[0]; - ptr[1] = (lightFloats + (k-1)*3)[1]; - ptr[2] = (lightFloats + (k-1)*3)[2]; - } - y = ds->lightmapHeight-1; - for (x = 0; x < ds->lightmapWidth; x++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - ptr = lightFloats + k*3; - ptr[0] = (lightFloats + (k-LIGHTMAP_WIDTH)*3)[0]; - ptr[1] = (lightFloats + (k-LIGHTMAP_WIDTH)*3)[1]; - ptr[2] = (lightFloats + (k-LIGHTMAP_WIDTH)*3)[2]; - } - } - /* - //colored debug edges - if (ds->surfaceType == MST_PATCH) - { - x = ds->lightmapWidth-1; - for (y = 0; y < ds->lightmapHeight; y++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - ptr = lightFloats + k*3; - ptr[0] = 255; - ptr[1] = 0; - ptr[2] = 0; - } - y = ds->lightmapHeight-1; - for (x = 0; x < ds->lightmapWidth; x++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - ptr = lightFloats + k*3; - ptr[0] = 0; - ptr[1] = 255; - ptr[2] = 0; - } - } - //*/ - } - // - VL_SmoothenLightmapEdges(); -} - -/* -============= -VL_ShiftPatchLightmaps -============= -*/ -void VL_ShiftPatchLightmaps(void) -{ - int i, j, x, y, k; - drawVert_t *verts; - dsurface_t *ds; - lsurfaceTest_t *test; - float *ptr; - - for ( i = 0 ; i < numDrawSurfaces ; i++ ) - { - test = lsurfaceTest[ i ]; - if (!test) - continue; - ds = &drawSurfaces[ i ]; - - if ( ds->lightmapNum < 0 ) - continue; - if (ds->surfaceType != MST_PATCH) - continue; - for (x = ds->lightmapWidth; x > 0; x--) - { - for (y = 0; y <= ds->lightmapHeight; y++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - ptr = lightFloats + k*3; - ptr[0] = (lightFloats + (k-1)*3)[0]; - ptr[1] = (lightFloats + (k-1)*3)[1]; - ptr[2] = (lightFloats + (k-1)*3)[2]; - } - } - for (y = ds->lightmapHeight; y > 0; y--) - { - for (x = 0; x <= ds->lightmapWidth; x++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - ptr = lightFloats + k*3; - ptr[0] = (lightFloats + (k-LIGHTMAP_WIDTH)*3)[0]; - ptr[1] = (lightFloats + (k-LIGHTMAP_WIDTH)*3)[1]; - ptr[2] = (lightFloats + (k-LIGHTMAP_WIDTH)*3)[2]; - } - } - verts = &drawVerts[ ds->firstVert ]; - for ( j = 0 ; j < ds->patchHeight * ds->patchWidth; j++ ) - { - verts[j].lightmap[0] += 0.5 / LIGHTMAP_WIDTH; - verts[j].lightmap[1] += 0.5 / LIGHTMAP_HEIGHT; - } - ds->lightmapHeight++; - ds->lightmapWidth++; - } -} - -/* -============= -VL_StoreLightmap -============= -*/ -void VL_StoreLightmap(void) -{ - int i, x, y, k; - dsurface_t *ds; - lsurfaceTest_t *test; - float *src; - byte *dst; - - _printf("storing lightmaps...\n"); - //fix lightmap edges before storing them - VL_FixLightmapEdges(); - // -#ifdef LIGHTMAP_PATCHSHIFT - VL_ShiftPatchLightmaps(); -#endif - // - for ( i = 0 ; i < numDrawSurfaces ; i++ ) - { - test = lsurfaceTest[ i ]; - if (!test) - continue; - ds = &drawSurfaces[ i ]; - - if ( ds->lightmapNum < 0 ) - continue; - - for (y = 0; y < ds->lightmapHeight; y++) - { - for (x = 0; x < ds->lightmapWidth; x++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - VectorAdd((lightFloats + k*3), lightAmbientColor, (lightFloats + k*3)); - src = &lightFloats[k*3]; - dst = lightBytes + k*3; - ColorToBytes(src, dst); - } - } - } -} - -/* -============= -PointInLeafnum -============= -*/ -int PointInLeafnum(vec3_t point) -{ - int nodenum; - vec_t dist; - dnode_t *node; - dplane_t *plane; - - nodenum = 0; - while (nodenum >= 0) - { - node = &dnodes[nodenum]; - plane = &dplanes[node->planeNum]; - dist = DotProduct (point, plane->normal) - plane->dist; - if (dist > 0) - nodenum = node->children[0]; - else - nodenum = node->children[1]; - } - - return -nodenum - 1; -} - -/* -============= -VL_PointInLeafnum_r -============= -*/ -int VL_PointInLeafnum_r(vec3_t point, int nodenum) -{ - int leafnum; - vec_t dist; - dnode_t *node; - dplane_t *plane; - - while (nodenum >= 0) - { - node = &dnodes[nodenum]; - plane = &dplanes[node->planeNum]; - dist = DotProduct (point, plane->normal) - plane->dist; - if (dist > 0.1) - { - nodenum = node->children[0]; - } - else if (dist < -0.1) - { - nodenum = node->children[1]; - } - else - { - leafnum = VL_PointInLeafnum_r(point, node->children[0]); - if (dleafs[leafnum].cluster != -1) - return leafnum; - nodenum = node->children[1]; - } - } - - leafnum = -nodenum - 1; - return leafnum; -} - -/* -============= -VL_PointInLeafnum -============= -*/ -int VL_PointInLeafnum(vec3_t point) -{ - return VL_PointInLeafnum_r(point, 0); -} - -/* -============= -VL_LightLeafnum -============= -*/ -int VL_LightLeafnum(vec3_t point) -{ - /* - int leafnum; - dleaf_t *leaf; - float x, y, z; - vec3_t test; - - leafnum = VL_PointInLeafnum(point); - leaf = &dleafs[leafnum]; - if (leaf->cluster != -1) - return leafnum; - for (z = 1; z >= -1; z -= 1) - { - for (x = 1; x >= -1; x -= 1) - { - for (y = 1; y >= -1; y -= 1) - { - VectorCopy(point, test); - test[0] += x; - test[1] += y; - test[2] += z; - leafnum = VL_PointInLeafnum(test); - leaf = &dleafs[leafnum]; - if (leaf->cluster != -1) - { - VectorCopy(test, point); - return leafnum; - } - } - } - } - return leafnum; - */ - return VL_PointInLeafnum(point); -} - -//#define LIGHTPOLYS - -#ifdef LIGHTPOLYS - -winding_t *lightwindings[MAX_MAP_DRAW_SURFS]; -int numlightwindings; - -/* -============= -VL_DrawLightWindings -============= -*/ -void VL_DrawLightWindings(void) -{ - int i; - for (i = 0; i < numlightwindings; i++) - { -#ifdef DEBUGNET - DebugNet_DrawWinding(lightwindings[i], 1); -#endif - } -} - -/* -============= -VL_LightSurfaceWithVolume -============= -*/ -void VL_LightSurfaceWithVolume(int surfaceNum, int facetNum, vlight_t *light, lightvolume_t *volume) -{ - winding_t *w; - lsurfaceTest_t *test; - lFacet_t *facet; - int i; - - test = lsurfaceTest[ surfaceNum ]; - facet = &test->facets[ facetNum ]; - - // - w = (winding_t *) malloc(sizeof(winding_t)); - memcpy(w->points, facet->points, sizeof(vec3_t) * facet->numpoints); - w->numpoints = facet->numpoints; - - for (i = 0; i < volume->numplanes; i++) - { - //if totally on the back - if (VL_ChopWinding(w, &volume->planes[i], 0.01) == SIDE_BACK) - return; - } - lightwindings[numlightwindings] = w; - numlightwindings++; - if (numlightwindings >= MAX_MAP_DRAW_SURFS) - Error("MAX_LIGHTWINDINGS"); -} - -#else - -/* -============= -VL_LightSurfaceWithVolume -============= -*/ -/* -int VL_PointInsideLightVolume(vec3_t point, lightvolume_t *volume) -{ - int i; - float d; - - for (i = 0; i < volume->numplanes; i++) - { - d = DotProduct(volume->planes[i].normal, point) - volume->planes[i].dist; - if (d < 0) return qfalse; - } - return qtrue; -} - -void VL_LightSurfaceWithVolume( int surfaceNum, int facetNum, vlight_t *light, lightvolume_t *volume ) -{ - dsurface_t *ds; - int i, j, k; - int numPositions; - vec3_t base, normal, color; - int sampleWidth, sampleHeight; - vec3_t lightmapOrigin, lightmapVecs[2], dir; - unsigned char *ptr; - float add, dist, angle; - mesh_t * mesh; - - ds = &drawSurfaces[surfaceNum]; - - // vertex-lit triangle model - if ( ds->surfaceType == MST_TRIANGLE_SOUP ) { - return; - } - - if ( ds->lightmapNum < 0 ) { - return; // doesn't need lighting - } - - if ( ds->surfaceType == MST_PATCH ) { - mesh = lsurfaceTest[surfaceNum]->detailMesh; - } else { - VectorCopy( ds->lightmapVecs[2], normal ); - - VectorCopy( ds->lightmapOrigin, lightmapOrigin ); - VectorCopy( ds->lightmapVecs[0], lightmapVecs[0] ); - VectorCopy( ds->lightmapVecs[1], lightmapVecs[1] ); - } - - sampleWidth = ds->lightmapWidth; - sampleHeight = ds->lightmapHeight; - - //calculate lightmap - for ( i = 0 ; i < sampleWidth; i++ ) { - for ( j = 0 ; j < sampleHeight; j++ ) { - - if ( ds->patchWidth ) { - numPositions = 9; - VectorCopy( mesh->verts[j*mesh->width+i].normal, normal ); - // VectorNormalize( normal, normal ); - // push off of the curve a bit - VectorMA( mesh->verts[j*mesh->width+i].xyz, 1, normal, base ); - -// MakeNormalVectors( normal, lightmapVecs[0], lightmapVecs[1] ); - } else { - numPositions = 9; - for ( k = 0 ; k < 3 ; k++ ) { - base[k] = lightmapOrigin[k] + normal[k] - + ((float) i) * lightmapVecs[0][k] - + ((float) j) * lightmapVecs[1][k]; - } - } - VectorAdd( base, surfaceOrigin[ surfaceNum ], base ); - - VectorSubtract(base, light->origin, dir); - dist = VectorNormalize(dir, dir); - if ( dist < 16 ) { - dist = 16; - } - angle = 1;//DotProduct( normal, dir ); //1; - if (angle > 1) - angle = 1; - if ( light->atten_disttype == LDAT_LINEAR ) { - add = angle * light->photons * lightLinearScale - dist; - if ( add < 0 ) { - add = 0; - } - } else { - add = light->photons / ( dist * dist ) * angle; - } - if (add <= 1.0) - continue; - - if (VL_PointInsideLightVolume(base, volume)) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + j) - * LIGHTMAP_WIDTH + ds->lightmapX + i; - ptr = lightBytes + k*3; - color[0] = (float) ptr[0] + add * light->color[0]; - color[1] = (float) ptr[1] + add * light->color[1]; - color[2] = (float) ptr[2] + add * light->color[2]; - ColorToBytes(color, ptr); - } - } - } -} -*/ - -/* -============= -VL_GetFilter - -FIXME: don't use a lightmap pixel origin but use the four corner points - to map part of a translucent surface onto the lightmap pixel -============= -*/ -void VL_GetFilter(vlight_t *light, lightvolume_t *volume, vec3_t lmp, vec3_t filter) -{ - lFacet_t *facet; - lsurfaceTest_t *test; - float d, d1, d2, frac, s, t, ns; - int i, j, is, it, b; - int x, y, u, v, numsamples, radius, color[4], largest; - byte *image; - vec3_t point, origin, total; - - VectorSet(filter, 1, 1, 1); - - if (noalphashading) - return; - - if (volume->numtransFacets <= 0) - return; - - if (light->type == LIGHT_SURFACEDIRECTED) - { - // project the light map pixel origin onto the area light source plane - d = DotProduct(lmp, light->normal) - DotProduct(light->normal, light->w.points[0]); - VectorMA(lmp, -d, light->normal, origin); - } - else - { - VectorCopy(light->origin, origin); - } - for (i = 0; i < volume->numtransFacets; i++) - { - test = lsurfaceTest[ volume->transSurfaces[i] ]; - facet = &test->facets[ volume->transFacets[i] ]; - // if this surface does not cast an alpha shadow - if ( !(test->shader->surfaceFlags & SURF_ALPHASHADOW) ) - continue; - // if there are no texture pixel available - if ( !test->shader->pixels ) { - continue; - } - // - d1 = DotProduct( origin, facet->plane.normal) - facet->plane.dist; - d2 = DotProduct( lmp, facet->plane.normal ) - facet->plane.dist; - // this should never happen because the light volume went through the facet - if ( ( d1 < 0 ) == ( d2 < 0 ) ) { - continue; - } - // calculate the crossing point - frac = d1 / ( d1 - d2 ); - - for ( j = 0 ; j < 3 ; j++ ) { - point[j] = origin[j] + frac * ( lmp[j] - origin[j] ); - } - - s = DotProduct( point, facet->textureMatrix[0] ) + facet->textureMatrix[0][3]; - t = DotProduct( point, facet->textureMatrix[1] ) + facet->textureMatrix[1][3]; - if (s < 0) - s = 0; - if (t < 0) - t = 0; - - s = s - floor( s ); - t = t - floor( t ); - - is = s * test->shader->width; - it = t * test->shader->height; - - //if old style alpha shading - if (nocolorshading) { - image = test->shader->pixels + 4 * ( it * test->shader->width + is ); - - // alpha filter - b = image[3]; - - // alpha test makes this a binary option - b = b < 128 ? 0 : 255; - - filter[0] = filter[0] * (255-b) / 255; - filter[1] = filter[1] * (255-b) / 255; - filter[2] = filter[2] * (255-b) / 255; - } - else { - VectorClear(total); - numsamples = 0; - radius = 2; - for ( u = -radius; u <= radius; u++ ) - { - x = is + u; - if ( x < 0 || x >= test->shader->width) - continue; - for ( v = -radius; v <= radius; v++ ) - { - y = it + v; - if ( y < 0 || y >= test->shader->height) - continue; - - image = test->shader->pixels + 4 * ( y * test->shader->width + x ); - color[0] = image[0]; - color[1] = image[1]; - color[2] = image[2]; - largest = 0; - for (j = 0; j < 3; j++) - if (image[j] > largest) - largest = image[j]; - if (largest <= 0 || image[3] == 0) { - color[0] = 255; - color[1] = 255; - color[2] = 255; - largest = 255; - } - total[0] += ((float) color[0]/largest) * (255-image[3]) / 255.0; - total[1] += ((float) color[1]/largest) * (255-image[3]) / 255.0; - total[2] += ((float) color[2]/largest) * (255-image[3]) / 255.0; - numsamples++; - } - } - ns = numsamples; - // - filter[0] *= total[0] / ns; - filter[1] *= total[1] / ns; - filter[2] *= total[2] / ns; - } - } -} - -/* -============= -VL_LightSurfaceWithVolume -============= -*/ -void VL_LightSurfaceWithVolume( int surfaceNum, int facetNum, vlight_t *light, lightvolume_t *volume ) -{ - int i; - dsurface_t *ds; - lFacet_t *facet; - lsurfaceTest_t *test; - winding_t w; - vec3_t base, dir, delta, normal, filter, origin; - int min_x[LIGHTMAP_SIZE+2], max_x[LIGHTMAP_SIZE+2]; - int min_y, max_y, k, x, y, n; - float *color, distscale; - float d, add, angle, dist, area, insidearea, coords[MAX_POINTS_ON_WINDING+1][2]; - mesh_t *mesh; - byte polygonedges[(LIGHTMAP_SIZE+1) * (LIGHTMAP_SIZE+1) / 8]; - - - ds = &drawSurfaces[surfaceNum]; - - // vertex-lit triangle model - if ( ds->surfaceType == MST_TRIANGLE_SOUP ) { - return; - } - - if ( ds->lightmapNum < 0 ) { - return; // doesn't need lighting - } - - test = lsurfaceTest[ surfaceNum ]; - facet = &test->facets[ facetNum ]; - - if (defaulttracelight && !test->always_vlight) - return; - if (test->always_tracelight) - return; - - memcpy(w.points, facet->points, sizeof(vec3_t) * facet->numpoints); - w.numpoints = facet->numpoints; - - for (i = 0; i < volume->numplanes; i++) - { - //if totally on the back - if (VL_ChopWinding(&w, &volume->planes[i], 0.01) == SIDE_BACK) - return; - } - - // only one thread at a time may write to the lightmap of this surface - MutexLock(test->mutex); - - test->numvolumes++; - - if (ds->surfaceType == MST_PATCH) - { - // FIXME: reduce size and don't mark all as edge - min_y = ds->lightmapY + facet->y; - max_y = ds->lightmapY + facet->y + facet->height - 1; - for (y = min_y; y <= max_y; y++) - { - min_x[y] = ds->lightmapX + facet->x; - max_x[y] = ds->lightmapX + facet->x + facet->width - 1; - for (x = min_x[y]; x <= max_x[y]; x++) - { - n = y * LIGHTMAP_SIZE + x; - polygonedges[n >> 3] |= 1 << (n & 7); - } - } - } - else - { - for (i = 0; i < w.numpoints; i++) - { - float s, t; - - if (i >= MAX_POINTS_ON_WINDING) - _printf("coords overflow\n"); - if (ds->surfaceType != MST_PATCH) - { - VectorSubtract(w.points[i], facet->mins, delta); - s = DotProduct( delta, facet->lightmapMatrix[0] ) + ds->lightmapX + 0.5; - t = DotProduct( delta, facet->lightmapMatrix[1] ) + ds->lightmapY + 0.5; - if (s >= LIGHTMAP_SIZE) - s = LIGHTMAP_SIZE - 0.5; - if (s < 0) - s = 0; - if (t >= LIGHTMAP_SIZE) - t = LIGHTMAP_SIZE - 0.5; - if (t < 0) - t = 0; - coords[i][0] = s; - coords[i][1] = t; - } - else - { - s = DotProduct( w.points[i], facet->lightmapMatrix[0] ) + facet->lightmapMatrix[0][3]; - t = DotProduct( w.points[i], facet->lightmapMatrix[1] ) + facet->lightmapMatrix[1][3]; - - s = s - floor( s ); - t = t - floor( t ); - - coords[i][0] = ds->lightmapX + s * LIGHTMAP_SIZE;// + 0.5; - coords[i][1] = ds->lightmapY + t * LIGHTMAP_SIZE;// + 0.5; - - if (coords[i][0] >= LIGHTMAP_SIZE) - coords[i][0] -= LIGHTMAP_SIZE; - if (coords[i][1] >= LIGHTMAP_SIZE) - coords[i][1] -= LIGHTMAP_SIZE; - if (coords[i][0] < ds->lightmapX) - coords[i][0] = ds->lightmapX; - if (coords[i][1] < ds->lightmapY) - coords[i][1] = ds->lightmapY; - } - x = coords[i][0]; - y = coords[i][1]; - if (x < ds->lightmapX || x >= LIGHTMAP_SIZE) - _printf("VL_LightSurfaceWithVolume: x outside lightmap\n"); - if (y < ds->lightmapY || y >= LIGHTMAP_SIZE) - _printf("VL_LightSurfaceWithVolume: y outside lightmap\n"); - } - coords[i][0] = coords[0][0]; - coords[i][1] = coords[0][1]; - - // - min_y = LIGHTMAP_SIZE; - max_y = 0; - for (i = 0; i < LIGHTMAP_SIZE; i++) - { - min_x[i] = LIGHTMAP_SIZE; - max_x[i] = 0; - } - memset(polygonedges, 0, sizeof(polygonedges)); - // scan convert the polygon onto the lightmap - // for each edge it marks *every* lightmap pixel the edge goes through - // so no brasenham and no scan conversion used for texture mapping but - // more something like ray casting - // this is necesary because we need all lightmap pixels totally or partly - // inside the light volume. these lightmap pixels are only lit for the part - // that they are inside the light volume. - for (i = 0; i < w.numpoints; i++) - { - float xf, yf, dx, dy, xstep, ystep, xfrac, yfrac; - int xinc, yinc; - - xf = coords[i][0]; - yf = coords[i][1]; - dx = coords[i+1][0] - xf; - dy = coords[i+1][1] - yf; - // - x = (int) xf; - y = (int) yf; - // - if (y < min_y) - min_y = y; - if (y > max_y) - max_y = y; - // - if (fabs(dx) > fabs(dy)) - { - if (dx > 0) - { - // y fraction at integer x below fractional x - yfrac = yf + (floor(xf) - xf) * dy / dx; - xinc = 1; - } - else if (dx < 0) - { - // y fraction at integer x above fractional x - yfrac = yf + (floor(xf) + 1 - xf) * dy / dx; - xinc = -1; - } - else - { - yfrac = yf; - xinc = 0; - } - // step in y direction per 1 unit in x direction - if (dx) - ystep = dy / fabs(dx); - else - ystep = 0; - while(1) - { - if (x < ds->lightmapX || x >= LIGHTMAP_SIZE) - _printf("VL_LightSurfaceWithVolume: x outside lightmap\n"); - if (y < ds->lightmapY || y >= LIGHTMAP_SIZE) - _printf("VL_LightSurfaceWithVolume: y outside lightmap\n"); - // - n = y * LIGHTMAP_SIZE + x; - polygonedges[n >> 3] |= 1 << (n & 7); - if (x < min_x[y]) - min_x[y] = x; - if (x > max_x[y]) - max_x[y] = x; - if (x == (int) coords[i+1][0]) - break; - yfrac += ystep; - if (dy > 0) - { - if (yfrac > (float) y + 1) - { - y += 1; - // - n = y * LIGHTMAP_SIZE + x; - polygonedges[n >> 3] |= 1 << (n & 7); - if (x < min_x[y]) - min_x[y] = x; - if (x > max_x[y]) - max_x[y] = x; - } - } - else - { - if (yfrac < (float) y) - { - y -= 1; - // - n = y * LIGHTMAP_SIZE + x; - polygonedges[n >> 3] |= 1 << (n & 7); - if (x < min_x[y]) - min_x[y] = x; - if (x > max_x[y]) - max_x[y] = x; - } - } - x += xinc; - } - } - else - { - if (dy > 0) - { - //x fraction at integer y below fractional y - xfrac = xf + (floor(yf) - yf) * dx / dy; - yinc = 1; - } - else if (dy < 0) - { - //x fraction at integer y above fractional y - xfrac = xf + (floor(yf) + 1 - yf) * dx / dy; - yinc = -1; - } - else - { - xfrac = xf; - yinc = 0; - } - // step in x direction per 1 unit in y direction - if (dy) - xstep = dx / fabs(dy); - else - xstep = 0; - while(1) - { - if (x < ds->lightmapX || x >= LIGHTMAP_SIZE) - _printf("VL_LightSurfaceWithVolume: x outside lightmap\n"); - if (y < ds->lightmapY || y >= LIGHTMAP_SIZE) - _printf("VL_LightSurfaceWithVolume: y outside lightmap\n"); - // - n = y * LIGHTMAP_SIZE + x; - polygonedges[n >> 3] |= 1 << (n & 7); - if (x < min_x[y]) - min_x[y] = x; - if (x > max_x[y]) - max_x[y] = x; - if (y == (int) coords[i+1][1]) - break; - xfrac += xstep; - if (dx > 0) - { - if (xfrac > (float) x + 1) - { - x += 1; - // - n = y * LIGHTMAP_SIZE + x; - polygonedges[n >> 3] |= 1 << (n & 7); - if (x < min_x[y]) - min_x[y] = x; - if (x > max_x[y]) - max_x[y] = x; - } - } - else - { - if (xfrac < (float) x) - { - x -= 1; - // - n = y * LIGHTMAP_SIZE + x; - polygonedges[n >> 3] |= 1 << (n & 7); - if (x < min_x[y]) - min_x[y] = x; - if (x > max_x[y]) - max_x[y] = x; - } - } - y += yinc; - } - } - } - } - // map light onto the lightmap - for (y = min_y; y <= max_y; y++) - { - for (x = min_x[y]; x <= max_x[y]; x++) - { - if (ds->surfaceType == MST_PATCH) - { - mesh = test->detailMesh; - VectorCopy( mesh->verts[(y-ds->lightmapY)*mesh->width+x-ds->lightmapX].xyz, base); - VectorCopy( mesh->verts[(y-ds->lightmapY)*mesh->width+x-ds->lightmapX].normal, normal); - //VectorCopy(facet->plane.normal, normal); - } - else - { - VectorMA(ds->lightmapOrigin, (float) x - ds->lightmapX, ds->lightmapVecs[0], base); - VectorMA(base, (float) y - ds->lightmapY, ds->lightmapVecs[1], base); - VectorCopy(facet->plane.normal, normal); - } - if (light->type == LIGHT_POINTSPOT) - { - float distByNormal; - vec3_t pointAtDist; - float radiusAtDist; - float sampleRadius; - vec3_t distToSample; - float coneScale; - - VectorSubtract( light->origin, base, dir ); - - distByNormal = -DotProduct( dir, light->normal ); - if ( distByNormal < 0 ) { - continue; - } - VectorMA( light->origin, distByNormal, light->normal, pointAtDist ); - radiusAtDist = light->radiusByDist * distByNormal; - - VectorSubtract( base, pointAtDist, distToSample ); - sampleRadius = VectorLength( distToSample ); - - if ( sampleRadius >= radiusAtDist ) { - continue; // outside the cone - } - if ( sampleRadius <= radiusAtDist - 32 ) { - coneScale = 1.0; // fully inside - } else { - coneScale = ( radiusAtDist - sampleRadius ) / 32.0; - } - - dist = VectorNormalize( dir, dir ); - // clamp the distance to prevent super hot spots - if ( dist < 16 ) { - dist = 16; - } - angle = DotProduct( normal, dir ); - if (angle > 1) - angle = 1; - if (angle > 0) { - if ( light->atten_angletype == LAAT_QUADRATIC ) { - angle = 1 - angle; - angle *= angle; - angle = 1 - angle; - } - else if ( light->atten_angletype == LAAT_DOUBLEQUADRATIC ) { - angle = 1 - angle; - angle *= angle * angle; - angle = 1 - angle; - } - } - if (light->atten_anglescale > 0) { - angle /= light->atten_anglescale; - if (angle > 1) - angle = 1; - } - if (light->atten_distscale > 0) { - distscale = light->atten_distscale; - } - else { - distscale = 1; - } - // - if ( light->atten_disttype == LDAT_NOSCALE ) { - add = angle * coneScale; - } - else if ( light->atten_disttype == LDAT_LINEAR ) { - add = angle * light->photons * lightLinearScale * coneScale - dist * distscale; - if ( add < 0 ) { - add = 0; - } - } - else { - add = light->photons / ( dist * dist * distscale) * angle * coneScale; - } - if (add <= 1.0) - continue; - } - else if (light->type == LIGHT_POINTFAKESURFACE) - { - // calculate the contribution - add = PointToPolygonFormFactor( base, normal, &light->w ); - if ( add <= 0 ) { - if ( light->twosided ) { - add = -add; - } else { - continue; - } - } - } - else if (light->type == LIGHT_SURFACEDIRECTED) - { - //VectorCopy(light->normal, dir); - //VectorInverse(dir); - // project the light map pixel origin onto the area light source plane - d = DotProduct(base, light->normal) - DotProduct(light->normal, light->w.points[0]); - VectorMA(base, -d, light->normal, origin); - VectorSubtract(origin, base, dir); - dist = VectorNormalize(dir, dir); - if ( dist < 16 ) { - dist = 16; - } - // - angle = DotProduct( normal, dir ); - if (angle > 1) - angle = 1; - if (angle > 0) { - if ( light->atten_angletype == LAAT_QUADRATIC ) { - angle = 1 - angle; - angle *= angle; - angle = 1 - angle; - } - else if ( light->atten_angletype == LAAT_DOUBLEQUADRATIC ) { - angle = 1 - angle; - angle *= angle * angle; - angle = 1 - angle; - } - } - if (light->atten_anglescale > 0) { - angle /= light->atten_anglescale; - if (angle > 1) - angle = 1; - } - if (light->atten_distscale > 0) { - distscale = light->atten_distscale; - } - else { - distscale = 1; - } - if ( light->atten_disttype == LDAT_NOSCALE ) { - add = angle; - } - else if ( light->atten_disttype == LDAT_LINEAR ) { - add = angle * light->photons * lightLinearScale - dist * distscale; - if ( add < 0 ) { - add = 0; - } - } else { //default quadratic - add = light->photons / ( dist * dist * distscale) * angle; - } - if (add <= 0) - continue; - } - else //normal radial point light - { - VectorSubtract(light->origin, base, dir); - dist = VectorNormalize(dir, dir); - if ( dist < 16 ) { - dist = 16; - } - angle = DotProduct( normal, dir ); - if (angle > 1) - angle = 1; - if (angle > 0) { - if ( light->atten_angletype == LAAT_QUADRATIC ) { - angle = 1 - angle; - angle *= angle; - angle = 1 - angle; - } - else if ( light->atten_angletype == LAAT_DOUBLEQUADRATIC ) { - angle = 1 - angle; - angle *= angle * angle; - angle = 1 - angle; - } - } - if (light->atten_anglescale > 0) { - angle /= light->atten_anglescale; - if (angle > 1) - angle = 1; - } - if (light->atten_distscale > 0) { - distscale = light->atten_distscale; - } - else { - distscale = 1; - } - if ( light->atten_disttype == LDAT_NOSCALE ) { - add = angle; - } - else if ( light->atten_disttype == LDAT_LINEAR ) { - add = angle * light->photons * lightLinearScale - dist * distscale; - if ( add < 0 ) { - add = 0; - } - } else { - add = light->photons / ( dist * dist * distscale) * angle; - } - if (add <= 1.0) - continue; - } - // - k = (ds->lightmapNum * LIGHTMAP_HEIGHT + y) * LIGHTMAP_WIDTH + x; - //if on one of the edges - n = y * LIGHTMAP_SIZE + x; - if ((polygonedges[n >> 3] & (1 << (n & 7)) )) - { - // multiply 'add' by the relative area being lit of the total visible lightmap pixel area - // - // first create a winding for the lightmap pixel - if (ds->surfaceType == MST_PATCH) - { - mesh = test->detailMesh; - if (y-ds->lightmapY >= mesh->height-1) - _printf("y outside mesh\n"); - if (x-ds->lightmapX >= mesh->width-1) - _printf("x outside mesh\n"); - VectorCopy( mesh->verts[(y-ds->lightmapY)*mesh->width+x-ds->lightmapX].xyz, w.points[0]); - VectorCopy( mesh->verts[(y+1-ds->lightmapY)*mesh->width+x-ds->lightmapX].xyz, w.points[1]); - VectorCopy( mesh->verts[(y+1-ds->lightmapY)*mesh->width+x+1-ds->lightmapX].xyz, w.points[2]); - VectorCopy( mesh->verts[(y-ds->lightmapY)*mesh->width+x+1-ds->lightmapX].xyz, w.points[3]); - w.numpoints = 4; - } - else - { - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT - ds->lightmapX, ds->lightmapVecs[0], w.points[0]); - VectorMA(w.points[0], (float) y - LIGHTMAP_PIXELSHIFT - ds->lightmapY, ds->lightmapVecs[1], w.points[0]); - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT - ds->lightmapX, ds->lightmapVecs[0], w.points[1]); - VectorMA(w.points[1], (float) y - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapY, ds->lightmapVecs[1], w.points[1]); - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapX, ds->lightmapVecs[0], w.points[2]); - VectorMA(w.points[2], (float) y - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapY, ds->lightmapVecs[1], w.points[2]); - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapX, ds->lightmapVecs[0], w.points[3]); - VectorMA(w.points[3], (float) y - LIGHTMAP_PIXELSHIFT - ds->lightmapY, ds->lightmapVecs[1], w.points[3]); - w.numpoints = 4; - } - // - // take the visible area of the lightmap pixel into account - // - //area = WindingArea(&w); - area = lightmappixelarea[k]; - if (area <= 0) - continue; - // chop the lightmap pixel winding with the light volume - for (i = 0; i < volume->numplanes; i++) - { - //if totally on the back - if (VL_ChopWinding(&w, &volume->planes[i], 0) == SIDE_BACK) - break; - } - // if the lightmap pixel is partly inside the light volume - if (i >= volume->numplanes) - { - insidearea = WindingArea(&w); - if (insidearea <= 0) - i = 0; - add = add * insidearea / area; - } - else - { - //DebugNet_DrawWinding(&w, 2); - continue; // this shouldn't happen - } - } - // get the light filter from all the translucent surfaces the light volume went through - VL_GetFilter(light, volume, base, filter); - // - color = &lightFloats[k*3]; - color[0] += add * light->color[0] * filter[0]; - color[1] += add * light->color[1] * filter[1]; - color[2] += add * light->color[2] * filter[2]; - } - } - - MutexUnlock(test->mutex); -} - -#endif - -/* -============= -VL_SplitLightVolume -============= -*/ -int VL_SplitLightVolume(lightvolume_t *volume, lightvolume_t *back, plane_t *split, float epsilon) -{ - lightvolume_t f, b; - vec_t dists[128]; - int sides[128]; - int counts[3]; - vec_t dot; - int i, j; - vec_t *p1, *p2; - vec3_t mid; - - counts[0] = counts[1] = counts[2] = 0; - - // determine sides for each point - for (i = 0; i < volume->numplanes; i++) - { - dot = DotProduct (volume->points[i], split->normal); - dot -= split->dist; - dists[i] = dot; - if (dot > epsilon) - sides[i] = SIDE_FRONT; - else if (dot < -epsilon) - sides[i] = SIDE_BACK; - else - { - sides[i] = SIDE_ON; - } - counts[sides[i]]++; - } - - if (!counts[1]) - return 0; // completely on front side - - if (!counts[0]) - return 1; // completely on back side - - sides[i] = sides[0]; - dists[i] = dists[0]; - - f.numplanes = 0; - b.numplanes = 0; - - for (i = 0; i < volume->numplanes; i++) - { - p1 = volume->points[i]; - - if (f.numplanes >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VL_SplitLightVolume -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return 0; // can't chop -- fall back to original - } - if (b.numplanes >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VL_SplitLightVolume -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return 0; // can't chop -- fall back to original - } - - if (sides[i] == SIDE_ON) - { - VectorCopy(p1, f.points[f.numplanes]); - VectorCopy(p1, b.points[b.numplanes]); - if (sides[i+1] == SIDE_BACK) - { - f.planes[f.numplanes] = *split; - b.planes[b.numplanes] = volume->planes[i]; - } - else if (sides[i+1] == SIDE_FRONT) - { - f.planes[f.numplanes] = volume->planes[i]; - b.planes[b.numplanes] = *split; - VectorInverse(b.planes[b.numplanes].normal); - b.planes[b.numplanes].dist = -b.planes[b.numplanes].dist; - } - else //this shouldn't happen - { - f.planes[f.numplanes] = *split; - b.planes[b.numplanes] = *split; - VectorInverse(b.planes[b.numplanes].normal); - b.planes[b.numplanes].dist = -b.planes[b.numplanes].dist; - } - f.numplanes++; - b.numplanes++; - continue; - } - - if (sides[i] == SIDE_FRONT) - { - VectorCopy (p1, f.points[f.numplanes]); - f.planes[f.numplanes] = volume->planes[i]; - f.numplanes++; - } - if (sides[i] == SIDE_BACK) - { - VectorCopy (p1, b.points[b.numplanes]); - b.planes[b.numplanes] = volume->planes[i]; - b.numplanes++; - } - - if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) - continue; - - if (f.numplanes >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VL_SplitLightVolume -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return 0; // can't chop -- fall back to original - } - if (b.numplanes >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VL_SplitLightVolume -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return 0; // can't chop -- fall back to original - } - - // generate a split point - p2 = volume->points[(i+1)%volume->numplanes]; - - dot = dists[i] / (dists[i]-dists[i+1]); - for (j=0 ; j<3 ; j++) - { // avoid round off error when possible - if (split->normal[j] == 1) - mid[j] = split->dist; - else if (split->normal[j] == -1) - mid[j] = -split->dist; - else - mid[j] = p1[j] + dot*(p2[j]-p1[j]); - } - - VectorCopy (mid, f.points[f.numplanes]); - VectorCopy(mid, b.points[b.numplanes]); - if (sides[i+1] == SIDE_BACK) - { - f.planes[f.numplanes] = *split; - b.planes[b.numplanes] = volume->planes[i]; - } - else - { - f.planes[f.numplanes] = volume->planes[i]; - b.planes[b.numplanes] = *split; - VectorInverse(b.planes[b.numplanes].normal); - b.planes[b.numplanes].dist = -b.planes[b.numplanes].dist; - } - f.numplanes++; - b.numplanes++; - } - memcpy(volume->points, f.points, sizeof(vec3_t) * f.numplanes); - memcpy(volume->planes, f.planes, sizeof(plane_t) * f.numplanes); - volume->numplanes = f.numplanes; - memcpy(back->points, b.points, sizeof(vec3_t) * b.numplanes); - memcpy(back->planes, b.planes, sizeof(plane_t) * b.numplanes); - back->numplanes = b.numplanes; - - return 2; -} - -/* -============= -VL_PlaneForEdgeToWinding -============= -*/ -void VL_PlaneForEdgeToWinding(vec3_t p1, vec3_t p2, winding_t *w, int windingonfront, plane_t *plane) -{ - int i, j; - float length, d; - vec3_t v1, v2; - - VectorSubtract(p2, p1, v1); - for (i = 0; i < w->numpoints; i++) - { - VectorSubtract (w->points[i], p1, v2); - - plane->normal[0] = v1[1]*v2[2] - v1[2]*v2[1]; - plane->normal[1] = v1[2]*v2[0] - v1[0]*v2[2]; - plane->normal[2] = v1[0]*v2[1] - v1[1]*v2[0]; - - // if points don't make a valid plane, skip it - length = plane->normal[0] * plane->normal[0] - + plane->normal[1] * plane->normal[1] - + plane->normal[2] * plane->normal[2]; - - if (length < ON_EPSILON) - continue; - - length = 1/sqrt(length); - - plane->normal[0] *= length; - plane->normal[1] *= length; - plane->normal[2] *= length; - - plane->dist = DotProduct (w->points[i], plane->normal); - // - for (j = 0; j < w->numpoints; j++) - { - if (j == i) - continue; - d = DotProduct(w->points[j], plane->normal) - plane->dist; - if (windingonfront) - { - if (d < -ON_EPSILON) - break; - } - else - { - if (d > ON_EPSILON) - break; - } - } - if (j >= w->numpoints) - return; - } -} - -/* -============= -VL_R_CastLightAtSurface -============= -*/ -void VL_R_FloodLight(vlight_t *light, lightvolume_t *volume, int cluster, int firstportal); - -void VL_R_CastLightAtSurface(vlight_t *light, lightvolume_t *volume) -{ - lsurfaceTest_t *test; - int i, n; - - // light the surface with this volume - VL_LightSurfaceWithVolume(volume->surfaceNum, volume->facetNum, light, volume); - // - test = lsurfaceTest[ volume->surfaceNum ]; - // if this is not a translucent surface - if ( !(test->shader->surfaceFlags & SURF_ALPHASHADOW) && !(test->shader->contents & CONTENTS_TRANSLUCENT)) - return; - // - if (volume->numtransFacets >= MAX_TRANSLUCENTFACETS) - Error("a light valume went through more than %d translucent facets", MAX_TRANSLUCENTFACETS); - //add this translucent surface to the list - volume->transSurfaces[volume->numtransFacets] = volume->surfaceNum; - volume->transFacets[volume->numtransFacets] = volume->facetNum; - volume->numtransFacets++; - //clear the tested facets except the translucent ones - memset(volume->facetTested, 0, sizeof(volume->facetTested)); - for (i = 0; i < volume->numtransFacets; i++) - { - test = lsurfaceTest[ volume->transSurfaces[i] ]; - n = test->facets[volume->transFacets[i]].num; - volume->facetTested[n >> 3] |= 1 << (n & 7); - } - memset(volume->clusterTested, 0, sizeof(volume->clusterTested)); - volume->endplane = volume->farplane; - volume->surfaceNum = -1; - volume->facetNum = 0; - VL_R_FloodLight(light, volume, volume->cluster, 0); - if (volume->surfaceNum >= 0) - { - VL_R_CastLightAtSurface(light, volume); - } -} - -/* -============= -VL_R_SplitLightVolume -============= -*/ -int numvolumes = 0; - -int VL_R_SplitLightVolume(vlight_t *light, lightvolume_t *volume, plane_t *split, int cluster, int firstportal) -{ - lightvolume_t back; - int res; - - // - res = VL_SplitLightVolume(volume, &back, split, 0.1); - // if the volume was split - if (res == 2) - { - memcpy(back.clusterTested, volume->clusterTested, sizeof(back.clusterTested)); - memcpy(back.facetTested, volume->facetTested, sizeof(back.facetTested)); - back.num = numvolumes++; - back.endplane = volume->endplane; - back.surfaceNum = volume->surfaceNum; - back.facetNum = volume->facetNum; - back.type = volume->type; - back.cluster = volume->cluster; - back.farplane = volume->farplane; - if (volume->numtransFacets > 0) - { - memcpy(back.transFacets, volume->transFacets, sizeof(back.transFacets)); - memcpy(back.transSurfaces, volume->transSurfaces, sizeof(back.transSurfaces)); - } - back.numtransFacets = volume->numtransFacets; - // - // flood the volume at the back of the split plane - VL_R_FloodLight(light, &back, cluster, firstportal); - // if the back volume hit a surface - if (back.surfaceNum >= 0) - { - VL_R_CastLightAtSurface(light, &back); - } - } - return res; -} - -/* -============= -VL_R_FloodLight -============= -*/ -void VL_R_FloodLight(vlight_t *light, lightvolume_t *volume, int cluster, int firstportal) -{ - int i, j, k, res, surfaceNum, backfaceculled, testculled; - float d; - winding_t winding, tmpwinding; - lleaf_t *leaf; - lportal_t *p; - lsurfaceTest_t *test; - lFacet_t *facet; - vec3_t dir1, dir2; - plane_t plane; - - // DebugNet_RemoveAllPolys(); - // VL_DrawLightVolume(light, volume); - - // if the first portal is not zero then we've checked all occluders in this leaf already - if (firstportal == 0) - { - // check all potential occluders in this leaf - for (i = 0; i < leafs[cluster].numSurfaces; i++) - { - surfaceNum = clustersurfaces[leafs[cluster].firstSurface + i]; - // - test = lsurfaceTest[ surfaceNum ]; - if ( !test ) - continue; - // - testculled = qfalse; - // use surface as an occluder - for (j = 0; j < test->numFacets; j++) - { - // use each facet as an occluder - facet = &test->facets[j]; - // - // memcpy(winding.points, facet->points, sizeof(vec3_t) * facet->numpoints); - // winding.numpoints = facet->numpoints; - // DebugNet_DrawWinding(&winding, 5); - // - // if the facet was tested already - if ( volume->facetTested[facet->num >> 3] & (1 << (facet->num & 7)) ) - continue; - volume->facetTested[facet->num >> 3] |= 1 << (facet->num & 7); - // backface culling for planar surfaces - backfaceculled = qfalse; - if (!test->patch && !test->trisoup) - { - if (volume->type == VOLUME_NORMAL) - { - // facet backface culling - d = DotProduct(light->origin, facet->plane.normal) - facet->plane.dist; - if (d < 0) - { - // NOTE: this doesn't work too great because of sometimes very bad tesselation - // of surfaces that are supposed to be flat - // FIXME: to work around this problem we should make sure that all facets - // created from planar surfaces use the lightmapVecs normal vector - /* - if ( !test->shader->twoSided ) - { - // skip all other facets of this surface as well because they are in the same plane - for (k = 0; k < test->numFacets; k++) - { - facet = &test->facets[k]; - volume->facetTested[facet->num >> 3] |= 1 << (facet->num & 7); - } - }*/ - backfaceculled = qtrue; - } - } - else - { - // FIXME: if all light source winding points are at the back of the facet - // plane then backfaceculled = qtrue - } - } - else // backface culling per facet for patches and triangle soups - { - if (volume->type == VOLUME_NORMAL) - { - // facet backface culling - d = DotProduct(light->origin, facet->plane.normal) - facet->plane.dist; - if (d < 0) - backfaceculled = qtrue; - } - else - { - // FIXME: if all light source winding points are at the back of the facet - // plane then backfaceculled = qtrue - } - } - /* chopping does this already - // check if this facet is totally or partly in front of the volume end plane - for (k = 0; k < facet->numpoints; k++) - { - d = DotProduct(volume->endplane.normal, facet->points[k]) - volume->endplane.dist; - if (d > ON_EPSILON) - break; - } - // if this facet is outside the light volume - if (k >= facet->numpoints) - continue; - */ - // - if (backfaceculled) - { - // if the facet is not two sided - if ( !nobackfaceculling && !test->shader->twoSided ) - continue; - // flip the winding - for (k = 0; k < facet->numpoints; k++) - VectorCopy(facet->points[k], winding.points[facet->numpoints - k - 1]); - winding.numpoints = facet->numpoints; - } - else - { - memcpy(winding.points, facet->points, sizeof(vec3_t) * facet->numpoints); - winding.numpoints = facet->numpoints; - } - // - if (!testculled) - { - testculled = qtrue; - // fast check if the surface sphere is totally behind the volume end plane - d = DotProduct(volume->endplane.normal, test->origin) - volume->endplane.dist; - if (d < -test->radius) - { - for (k = 0; k < test->numFacets; k++) - { - facet = &test->facets[k]; - volume->facetTested[facet->num >> 3] |= 1 << (facet->num & 7); - } - break; - } - for (k = 0; k < volume->numplanes; k++) - { - d = DotProduct(volume->planes[k].normal, test->origin) - volume->planes[k].dist; - if (d < - test->radius) - { - for (k = 0; k < test->numFacets; k++) - { - facet = &test->facets[k]; - volume->facetTested[facet->num >> 3] |= 1 << (facet->num & 7); - } - break; - } - } - if (k < volume->numplanes) - break; - } - //NOTE: we have to chop the facet winding with the volume end plane because - // the faces in Q3 are not stitched together nicely - res = VL_ChopWinding(&winding, &volume->endplane, 0.01); - // if the facet is on or at the back of the volume end plane - if (res == SIDE_BACK || res == SIDE_ON) - continue; - // check if the facet winding is totally or partly inside the light volume - memcpy(&tmpwinding, &winding, sizeof(winding_t)); - for (k = 0; k < volume->numplanes; k++) - { - res = VL_ChopWinding(&tmpwinding, &volume->planes[k], 0.01); - if (res == SIDE_BACK || res == SIDE_ON) - break; - } - // if no part of the light volume is occluded by this facet - if (k < volume->numplanes) - continue; - // - for (k = 0; k < winding.numpoints; k++) - { - if (volume->type == VOLUME_DIRECTED) - { - VectorSubtract(winding.points[(k+1) % winding.numpoints], winding.points[k], dir1); - CrossProduct(light->normal, dir1, plane.normal); - VectorNormalize(plane.normal, plane.normal); - plane.dist = DotProduct(plane.normal, winding.points[k]); - } - else - { - VectorSubtract(winding.points[(k+1) % winding.numpoints], winding.points[k], dir1); - VectorSubtract(light->origin, winding.points[k], dir2); - CrossProduct(dir1, dir2, plane.normal); - VectorNormalize(plane.normal, plane.normal); - plane.dist = DotProduct(plane.normal, winding.points[k]); - } - res = VL_R_SplitLightVolume(light, volume, &plane, cluster, 0); - if (res == 1) - break; //the facet wasn't really inside the volume - } - if (k >= winding.numpoints) - { - volume->endplane = facet->plane; - if (backfaceculled) - { - VectorInverse(volume->endplane.normal); - volume->endplane.dist = -volume->endplane.dist; - } - volume->surfaceNum = surfaceNum; - volume->facetNum = j; - } - } - } - } - // we've tested all occluders in this cluster - volume->clusterTested[cluster >> 3] |= 1 << (cluster & 7); - // flood light through the portals of the current leaf - leaf = &leafs[cluster]; - for (i = firstportal; i < leaf->numportals; i++) - { - p = leaf->portals[i]; - // - // memcpy(&winding, p->winding, sizeof(winding_t)); - // DebugNet_DrawWinding(&winding, 5); - // if already flooded into the cluster this portal leads to - if ( volume->clusterTested[p->leaf >> 3] & (1 << (p->leaf & 7)) ) - continue; - // - if (volume->type == VOLUME_NORMAL) - { - // portal backface culling - d = DotProduct(light->origin, p->plane.normal) - p->plane.dist; - if (d > 0) // portal plane normal points into neighbour cluster - continue; - } - else - { - // FIXME: if all light source winding points are at the back of this portal - // plane then there's no need to flood through - } - // check if this portal is totally or partly in front of the volume end plane - // fast check with portal sphere - d = DotProduct(volume->endplane.normal, p->origin) - volume->endplane.dist; - if (d < -p->radius) - continue; - for (j = 0; j < p->winding->numpoints; j++) - { - d = DotProduct(volume->endplane.normal, p->winding->points[j]) - volume->endplane.dist; - if (d > -0.01) - break; - } - // if this portal is totally behind the light volume end plane - if (j >= p->winding->numpoints) - continue; - //distance from point light to portal - d = DotProduct(p->plane.normal, light->origin) - p->plane.dist; - // only check if a point light is Not *on* the portal - if (volume->type != VOLUME_NORMAL || fabs(d) > 0.1) - { - // check if the portal is partly or totally inside the light volume - memcpy(&winding, p->winding, sizeof(winding_t)); - for (j = 0; j < volume->numplanes; j++) - { - res = VL_ChopWinding(&winding, &volume->planes[j], 0.01); - if (res == SIDE_BACK || res == SIDE_ON) - break; - } - // if the light volume does not go through this portal at all - if (j < volume->numplanes) - continue; - } - // chop the light volume with the portal - for (k = 0; k < p->winding->numpoints; k++) - { - if (volume->type == VOLUME_DIRECTED) - { - VectorSubtract(p->winding->points[(k+1) % p->winding->numpoints], p->winding->points[k], dir1); - CrossProduct(light->normal, dir1, plane.normal); - VectorNormalize(plane.normal, plane.normal); - plane.dist = DotProduct(plane.normal, p->winding->points[k]); - } - else - { - VectorSubtract(p->winding->points[(k+1) % p->winding->numpoints], p->winding->points[k], dir1); - VectorSubtract(light->origin, p->winding->points[k], dir2); - CrossProduct(dir1, dir2, plane.normal); - VectorNormalize(plane.normal, plane.normal); - plane.dist = DotProduct(plane.normal, p->winding->points[k]); - } - res = VL_R_SplitLightVolume(light, volume, &plane, cluster, i+1); - if (res == 1) - break; //volume didn't really go through the portal - } - // if the light volume went through the portal - if (k >= p->winding->numpoints) - { - // flood through the portal - VL_R_FloodLight(light, volume, p->leaf, 0); - } - } -} - -/* -============= -VL_R_FloodAreaSpotLight -============= -*/ -void VL_FloodAreaSpotLight(vlight_t *light, winding_t *w, int leafnum) -{ -} - -/* -============= -VL_R_SubdivideAreaSpotLight -============= -*/ -void VL_R_SubdivideAreaSpotLight(vlight_t *light, int nodenum, winding_t *w) -{ - int leafnum, res; - dnode_t *node; - dplane_t *plane; - winding_t back; - plane_t split; - - while(nodenum >= 0) - { - node = &dnodes[nodenum]; - plane = &dplanes[node->planeNum]; - - VectorCopy(plane->normal, split.normal); - split.dist = plane->dist; - res = VL_SplitWinding (w, &back, &split, 0.1); - - if (res == SIDE_FRONT) - { - nodenum = node->children[0]; - } - else if (res == SIDE_BACK) - { - nodenum = node->children[1]; - } - else if (res == SIDE_ON) - { - memcpy(&back, w, sizeof(winding_t)); - VL_R_SubdivideAreaSpotLight(light, node->children[1], &back); - nodenum = node->children[0]; - } - else - { - VL_R_SubdivideAreaSpotLight(light, node->children[1], &back); - nodenum = node->children[0]; - } - } - leafnum = -nodenum - 1; - if (dleafs[leafnum].cluster != -1) - { - VL_FloodAreaSpotLight(light, w, leafnum); - } -} - -/* -============= -VL_R_FloodRadialAreaLight -============= -*/ -void VL_FloodRadialAreaLight(vlight_t *light, winding_t *w, int leafnum) -{ -} - -/* -============= -VL_R_SubdivideRadialAreaLight -============= -*/ -void VL_R_SubdivideRadialAreaLight(vlight_t *light, int nodenum, winding_t *w) -{ - int leafnum, res; - dnode_t *node; - dplane_t *plane; - winding_t back; - plane_t split; - - while(nodenum >= 0) - { - node = &dnodes[nodenum]; - plane = &dplanes[node->planeNum]; - - VectorCopy(plane->normal, split.normal); - split.dist = plane->dist; - res = VL_SplitWinding (w, &back, &split, 0.1); - - if (res == SIDE_FRONT) - { - nodenum = node->children[0]; - } - else if (res == SIDE_BACK) - { - nodenum = node->children[1]; - } - else if (res == SIDE_ON) - { - memcpy(&back, w, sizeof(winding_t)); - VL_R_SubdivideRadialAreaLight(light, node->children[1], &back); - nodenum = node->children[0]; - } - else - { - VL_R_SubdivideRadialAreaLight(light, node->children[1], &back); - nodenum = node->children[0]; - } - } - leafnum = -nodenum - 1; - if (dleafs[leafnum].cluster != -1) - { - VL_FloodRadialAreaLight(light, w, leafnum); - } -} - -/* -============= -VL_R_FloodDirectedLight -============= -*/ -void VL_FloodDirectedLight(vlight_t *light, winding_t *w, int leafnum) -{ - int i; - float dist; - lightvolume_t volume; - vec3_t dir; - - if (light->atten_disttype == LDAT_NOSCALE) - { - // light travels without decrease in intensity over distance - dist = MAX_WORLD_COORD; - } - else - { - if ( light->atten_disttype == LDAT_LINEAR ) - dist = light->photons * lightLinearScale; - else - dist = sqrt(light->photons); - } - - memset(&volume, 0, sizeof(lightvolume_t)); - for (i = 0; i < w->numpoints; i++) - { - VectorMA(w->points[i], dist, light->normal, volume.points[i]); - VectorSubtract(w->points[(i+1)%w->numpoints], w->points[i], dir); - CrossProduct(light->normal, dir, volume.planes[i].normal); - VectorNormalize(volume.planes[i].normal, volume.planes[i].normal); - volume.planes[i].dist = DotProduct(volume.planes[i].normal, w->points[i]); - } - volume.numplanes = w->numpoints; - VectorCopy(light->normal, volume.endplane.normal); - VectorInverse(volume.endplane.normal); - volume.endplane.dist = DotProduct(volume.endplane.normal, volume.points[0]); - volume.farplane = volume.endplane; - volume.surfaceNum = -1; - volume.type = VOLUME_DIRECTED; - volume.cluster = dleafs[leafnum].cluster; - VL_R_FloodLight(light, &volume, volume.cluster, 0); - if (volume.surfaceNum >= 0) - { - VL_R_CastLightAtSurface(light, &volume); - } -} - -/* -============= -VL_R_SubdivideDirectedAreaLight -============= -*/ -void VL_R_SubdivideDirectedAreaLight(vlight_t *light, int nodenum, winding_t *w) -{ - int leafnum, res; - dnode_t *node; - dplane_t *plane; - winding_t back; - plane_t split; - - while(nodenum >= 0) - { - node = &dnodes[nodenum]; - plane = &dplanes[node->planeNum]; - - VectorCopy(plane->normal, split.normal); - split.dist = plane->dist; - res = VL_SplitWinding (w, &back, &split, 0.1); - - if (res == SIDE_FRONT) - { - nodenum = node->children[0]; - } - else if (res == SIDE_BACK) - { - nodenum = node->children[1]; - } - else if (res == SIDE_ON) - { - memcpy(&back, w, sizeof(winding_t)); - VL_R_SubdivideDirectedAreaLight(light, node->children[1], &back); - nodenum = node->children[0]; - } - else - { - VL_R_SubdivideDirectedAreaLight(light, node->children[1], &back); - nodenum = node->children[0]; - } - } - leafnum = -nodenum - 1; - if (dleafs[leafnum].cluster != -1) - { - VL_FloodDirectedLight(light, w, leafnum); - } -} - -/* -============= -VL_FloodLight -============= -*/ -void VL_FloodLight(vlight_t *light) -{ - lightvolume_t volume; - dleaf_t *leaf; - int leafnum, i, j, k, dir[2][4] = {{1, 1, -1, -1}, {1, -1, -1, 1}}; - float a, step, dist, radius, windingdist; - vec3_t vec, r, p, temp; - winding_t winding; - - switch(light->type) - { - case LIGHT_POINTRADIAL: - { - // source is a point - // light radiates in all directions - // creates sharp shadows - // - // create 6 volumes shining in the axis directions - // what about: 4 tetrahedrons instead? - // - if ( light->atten_disttype == LDAT_LINEAR ) - dist = light->photons * lightLinearScale; - else - dist = sqrt(light->photons); - //always put the winding at a large distance to avoid epsilon issues - windingdist = MAX_WORLD_COORD; - if (dist > windingdist) - windingdist = dist; - // - leafnum = VL_LightLeafnum(light->origin); - leaf = &dleafs[leafnum]; - if (leaf->cluster == -1) - { - light->insolid = qtrue; - break; - } - // for each axis - for (i = 0; i < 3; i++) - { - // for both directions on the axis - for (j = -1; j <= 1; j += 2) - { - memset(&volume, 0, sizeof(lightvolume_t)); - volume.numplanes = 0; - for (k = 0; k < 4; k ++) - { - volume.points[volume.numplanes][i] = light->origin[i] + j * windingdist; - volume.points[volume.numplanes][(i+1)%3] = light->origin[(i+1)%3] + dir[0][k] * windingdist; - volume.points[volume.numplanes][(i+2)%3] = light->origin[(i+2)%3] + dir[1][k] * windingdist; - volume.numplanes++; - } - if (j >= 0) - { - VectorCopy(volume.points[0], temp); - VectorCopy(volume.points[2], volume.points[0]); - VectorCopy(temp, volume.points[2]); - } - for (k = 0; k < volume.numplanes; k++) - { - VL_PlaneFromPoints(&volume.planes[k], light->origin, volume.points[(k+1)%volume.numplanes], volume.points[k]); - } - VectorCopy(light->origin, temp); - temp[i] += (float) j * dist; - VectorClear(volume.endplane.normal); - volume.endplane.normal[i] = -j; - volume.endplane.dist = DotProduct(volume.endplane.normal, temp); //DotProduct(volume.endplane.normal, volume.points[0]); - volume.farplane = volume.endplane; - volume.cluster = leaf->cluster; - volume.surfaceNum = -1; - volume.type = VOLUME_NORMAL; - // - memset(volume.facetTested, 0, sizeof(volume.facetTested)); - memset(volume.clusterTested, 0, sizeof(volume.clusterTested)); - VL_R_FloodLight(light, &volume, leaf->cluster, 0); - if (volume.surfaceNum >= 0) - { - VL_R_CastLightAtSurface(light, &volume); - } - } - } - break; - } - case LIGHT_POINTSPOT: - { - // source is a point - // light is targetted - // creates sharp shadows - // - // what about using brushes to shape spot lights? that'd be pretty cool - // - if ( light->atten_disttype == LDAT_LINEAR ) - dist = light->photons * lightLinearScale; - else - dist = sqrt(light->photons); - dist *= 2; - // - windingdist = 4096; - if (dist > windingdist) - windingdist = dist; - //take 8 times the cone radius because the spotlight also lights outside the cone - radius = 8 * windingdist * light->radiusByDist; - // - memset(&volume, 0, sizeof(lightvolume_t)); - leafnum = VL_LightLeafnum(light->origin); - leaf = &dleafs[leafnum]; - if (leaf->cluster == -1) - { - light->insolid = qtrue; - break; - } - // - VectorClear(vec); - for (i = 0; i < 3; i++) - { - if (light->normal[i] > -0.9 && light->normal[i] < 0.9) - { - vec[i] = 1; - break; - } - } - CrossProduct(light->normal, vec, r); - VectorScale(r, radius, p); - volume.numplanes = 0; - step = 45; - for (a = step / 2; a < 360 + step / 2; a += step) - { - RotatePointAroundVector(volume.points[volume.numplanes], light->normal, p, a); - VectorAdd(light->origin, volume.points[volume.numplanes], volume.points[volume.numplanes]); - VectorMA(volume.points[volume.numplanes], windingdist, light->normal, volume.points[volume.numplanes]); - volume.numplanes++; - } - for (i = 0; i < volume.numplanes; i++) - { - VL_PlaneFromPoints(&volume.planes[i], light->origin, volume.points[(i+1)%volume.numplanes], volume.points[i]); - } - VectorMA(light->origin, dist, light->normal, temp); - VectorCopy(light->normal, volume.endplane.normal); - VectorInverse(volume.endplane.normal); - volume.endplane.dist = DotProduct(volume.endplane.normal, temp);//DotProduct(volume.endplane.normal, volume.points[0]); - volume.farplane = volume.endplane; - volume.cluster = leaf->cluster; - volume.surfaceNum = -1; - volume.type = VOLUME_NORMAL; - // - memset(volume.facetTested, 0, sizeof(volume.facetTested)); - memset(volume.clusterTested, 0, sizeof(volume.clusterTested)); - VL_R_FloodLight(light, &volume, leaf->cluster, 0); - if (volume.surfaceNum >= 0) - { - VL_R_CastLightAtSurface(light, &volume); - } - break; - } - case LIGHT_POINTFAKESURFACE: - { - float value; - int n, axis; - vec3_t v, vecs[2]; - - if ( light->atten_disttype == LDAT_LINEAR ) - dist = light->photons * lightLinearScale; - else - dist = sqrt(light->photons); - //always put the winding at a large distance to avoid epsilon issues - windingdist = 4096; - if (dist > windingdist) - windingdist = dist; - // - VectorMA(light->origin, 0.1, light->normal, light->origin); - // - leafnum = VL_LightLeafnum(light->origin); - leaf = &dleafs[leafnum]; - if (leaf->cluster == -1) - { - light->insolid = qtrue; - break; - } - value = 0; - for (i = 0; i < 3; i++) - { - if (fabs(light->normal[i]) > value) - { - value = fabs(light->normal[i]); - axis = i; - } - } - for (i = 0; i < 2; i++) - { - VectorClear(v); - v[(axis + 1 + i) % 3] = 1; - CrossProduct(light->normal, v, vecs[i]); - } - //cast 4 volumes at the front of the surface - for (i = -1; i <= 1; i += 2) - { - for (j = -1; j <= 1; j += 2) - { - for (n = 0; n < 2; n++) - { - memset(&volume, 0, sizeof(lightvolume_t)); - volume.numplanes = 3; - VectorMA(light->origin, i * windingdist, vecs[0], volume.points[(i == j) == n]); - VectorMA(light->origin, j * windingdist, vecs[1], volume.points[(i != j) == n]); - VectorMA(light->origin, windingdist, light->normal, volume.points[2]); - for (k = 0; k < volume.numplanes; k++) - { - VL_PlaneFromPoints(&volume.planes[k], light->origin, volume.points[(k+1)%volume.numplanes], volume.points[k]); - } - VL_PlaneFromPoints(&volume.endplane, volume.points[0], volume.points[1], volume.points[2]); - VectorMA(light->origin, dist, light->normal, temp); - volume.endplane.dist = DotProduct(volume.endplane.normal, temp); - if (DotProduct(light->origin, volume.endplane.normal) - volume.endplane.dist > 0) - break; - } - volume.farplane = volume.endplane; - volume.cluster = leaf->cluster; - volume.surfaceNum = -1; - volume.type = VOLUME_NORMAL; - // - memset(volume.facetTested, 0, sizeof(volume.facetTested)); - memset(volume.clusterTested, 0, sizeof(volume.clusterTested)); - - VL_R_FloodLight(light, &volume, leaf->cluster, 0); - if (volume.surfaceNum >= 0) - { - VL_R_CastLightAtSurface(light, &volume); - } - } - } - break; - } - case LIGHT_SURFACEDIRECTED: - { - // source is an area defined by a winding - // the light is unidirectional - // creates sharp shadows - // for instance sun light or laser light - // - memcpy(&winding, &light->w, sizeof(winding_t)); - VL_R_SubdivideDirectedAreaLight(light, 0, &winding); - break; - } - case LIGHT_SURFACERADIAL: - { - // source is an area defined by a winding - // the light radiates in all directions at the front of the winding plane - // - memcpy(&winding, &light->w, sizeof(winding_t)); - VL_R_SubdivideRadialAreaLight(light, 0, &winding); - break; - } - case LIGHT_SURFACESPOT: - { - // source is an area defined by a winding - // light is targetted but not unidirectional - // - memcpy(&winding, &light->w, sizeof(winding_t)); - VL_R_SubdivideAreaSpotLight(light, 0, &winding); - break; - } - } -} - -/* -============= -VL_FloodLightThread -============= -*/ -void VL_FloodLightThread(int num) -{ - VL_FloodLight(vlights[num]); -} - -/* -============= -VL_TestLightLeafs -============= -*/ -void VL_TestLightLeafs(void) -{ - int leafnum, i; - vlight_t *light; - dleaf_t *leaf; - - for (i = 0; i < numvlights; i++) - { - light = vlights[i]; - if (light->type != LIGHT_POINTRADIAL && - light->type != LIGHT_POINTSPOT) - continue; - leafnum = VL_LightLeafnum(light->origin); - leaf = &dleafs[leafnum]; - if (leaf->cluster == -1) - if (light->type == LIGHT_POINTRADIAL) - qprintf("light in solid at %1.1f %1.1f %1.1f\n", light->origin[0], light->origin[1], light->origin[2]); - else if (light->type == LIGHT_POINTSPOT) - qprintf("spot light in solid at %1.1f %1.1f %1.1f\n", light->origin[0], light->origin[1], light->origin[2]); - } -} - - -/* -============= -VL_DoForcedTraceLight -============= -*/ -// from light.c -void TraceLtm( int num ); - -void VL_DoForcedTraceLight(int num) -{ - dsurface_t *ds; - shaderInfo_t *si; - - ds = &drawSurfaces[num]; - - if ( ds->surfaceType == MST_TRIANGLE_SOUP ) - return; - - if ( ds->lightmapNum < 0 ) - return; - - // always light entity surfaces with the old light algorithm - if ( !entitySurface[num] ) - { - si = ShaderInfoForShader( dshaders[ ds->shaderNum].shader ); - - if (defaulttracelight) - { - if (si->forceVLight) - return; - } - else - { - if (!si->forceTraceLight) - return; - } - } - - TraceLtm(num); -} - -/* -============= -VL_DoForcedTraceLightSurfaces -============= -*/ -void VL_DoForcedTraceLightSurfaces(void) -{ - _printf( "forced trace light\n" ); - RunThreadsOnIndividual( numDrawSurfaces, qtrue, VL_DoForcedTraceLight ); -} - -float *oldLightFloats; - -/* -============= -VL_SurfaceRadiosity -============= -*/ -void VL_SurfaceRadiosity( int num ) { - dsurface_t *ds; - mesh_t *mesh; - shaderInfo_t *si; - lsurfaceTest_t *test; - int x, y, k; - vec3_t base, normal; - float *color, area; - vlight_t vlight; - - ds = &drawSurfaces[num]; - - if ( ds->lightmapNum < 0 ) { - return; // doesn't have a lightmap - } - - // vertex-lit triangle model - if ( ds->surfaceType == MST_TRIANGLE_SOUP ) { - return; - } - - si = ShaderInfoForShader( dshaders[ ds->shaderNum].shader ); - test = lsurfaceTest[ num ]; - - if (!test) { - return; - } - - for (x = 0; x < ds->lightmapWidth; x++) { - for (y = 0; y < ds->lightmapHeight; y++) { - // - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - area = lightmappixelarea[k]; - if (area <= 0) - continue; - // - if (ds->surfaceType == MST_PATCH) - { - mesh = test->detailMesh; - VectorCopy( mesh->verts[y*mesh->width+x].xyz, base); - VectorCopy( mesh->verts[y*mesh->width+x].normal, normal); - } - else - { - VectorMA(ds->lightmapOrigin, (float) x, ds->lightmapVecs[0], base); - VectorMA(base, (float) y, ds->lightmapVecs[1], base); - VectorCopy(test->facets[0].plane.normal, normal); - } - // create ligth from base - memset(&vlight, 0, sizeof(vlight_t)); - color = &oldLightFloats[k*3]; - // a few units away from the surface - VectorMA(base, 5, normal, vlight.origin); - ColorNormalize(color, vlight.color); - // ok this is crap - vlight.photons = VectorLength(color) * 0.05 * lightPointScale / (area * radiosity_scale); - // what about using a front facing light only ? - vlight.type = LIGHT_POINTRADIAL; - // flood the light from this lightmap pixel - VL_FloodLight(&vlight); - // only one thread at a time may write to the lightmap of this surface - MutexLock(test->mutex); - // don't light the lightmap pixel itself - lightFloats[k*3] = oldLightFloats[k*3]; - lightFloats[k*3+1] = oldLightFloats[k*3+1]; - lightFloats[k*3+2] = oldLightFloats[k*3+2]; - // - MutexUnlock(test->mutex); - } - } -} - -/* -============= -VL_Radiosity - -this aint working real well but it's fun to play with. -============= -*/ -void VL_Radiosity(void) { - - oldLightFloats = lightFloats; - lightFloats = (float *) malloc(numLightBytes * sizeof(float)); - memcpy(lightFloats, oldLightFloats, numLightBytes * sizeof(float)); - _printf("%7i surfaces\n", numDrawSurfaces); - RunThreadsOnIndividual( numDrawSurfaces, qtrue, VL_SurfaceRadiosity ); - free(oldLightFloats); -} - -/* -============= -VL_LightWorld -============= -*/ -void VL_LightWorld(void) -{ - int i, numcastedvolumes, numvlightsinsolid; - float f; - - // find the optional world ambient - GetVectorForKey( &entities[0], "_color", lightAmbientColor ); - f = FloatForKey( &entities[0], "ambient" ); - VectorScale( lightAmbientColor, f, lightAmbientColor ); - /* - _printf("\r%6d lights out of %d", 0, numvlights); - for (i = 0; i < numvlights; i++) - { - _printf("\r%6d", i); - VL_FloodLight(vlights[i]); - } - _printf("\r%6d lights out of %d\n", i, numvlights); - */ - _printf("%7i lights\n", numvlights); - RunThreadsOnIndividual( numvlights, qtrue, VL_FloodLightThread ); - - numcastedvolumes = 0; - for ( i = 0 ; i < numDrawSurfaces ; i++ ) { - if (lsurfaceTest[i]) - numcastedvolumes += lsurfaceTest[i]->numvolumes; - } - _printf("%7i light volumes casted\n", numcastedvolumes); - numvlightsinsolid = 0; - for (i = 0; i < numvlights; i++) - { - if (vlights[i]->insolid) - numvlightsinsolid++; - } - _printf("%7i lights in solid\n", numvlightsinsolid); - // - radiosity_scale = 1; - for (i = 0; i < radiosity; i++) { - VL_Radiosity(); - radiosity_scale <<= 1; - } - // - VL_StoreLightmap(); - // redo surfaces with the old light algorithm when needed - VL_DoForcedTraceLightSurfaces(); -} - -/* -============= -VL_CreateEntityLights -============= -*/ -entity_t *FindTargetEntity( const char *target ); - -void VL_CreateEntityLights (void) -{ - int i, c_entityLights; - vlight_t *dl; - entity_t *e, *e2; - const char *name; - const char *target; - vec3_t dest; - const char *_color; - float intensity; - int spawnflags; - - // - c_entityLights = 0; - _printf("Creating entity lights...\n"); - // - for ( i = 0 ; i < num_entities ; i++ ) { - e = &entities[i]; - name = ValueForKey (e, "classname"); - if (strncmp (name, "light", 5)) - continue; - - dl = malloc(sizeof(*dl)); - memset (dl, 0, sizeof(*dl)); - - spawnflags = FloatForKey (e, "spawnflags"); - if ( spawnflags & 1 ) { - dl->atten_disttype = LDAT_LINEAR; - } - if ( spawnflags & 2 ) { - dl->atten_disttype = LDAT_NOSCALE; - } - if ( spawnflags & 4 ) { - dl->atten_angletype = LAAT_QUADRATIC; - } - if ( spawnflags & 8 ) { - dl->atten_angletype = LAAT_DOUBLEQUADRATIC; - } - - dl->atten_distscale = FloatForKey(e, "atten_distscale"); - dl->atten_anglescale = FloatForKey(e, "atten_anglescale"); - - GetVectorForKey (e, "origin", dl->origin); - dl->style = FloatForKey (e, "_style"); - if (!dl->style) - dl->style = FloatForKey (e, "style"); - if (dl->style < 0) - dl->style = 0; - - intensity = FloatForKey (e, "light"); - if (!intensity) - intensity = FloatForKey (e, "_light"); - if (!intensity) - intensity = 300; - _color = ValueForKey (e, "_color"); - if (_color && _color[0]) - { - sscanf (_color, "%f %f %f", &dl->color[0],&dl->color[1],&dl->color[2]); - ColorNormalize (dl->color, dl->color); - } - else - dl->color[0] = dl->color[1] = dl->color[2] = 1.0; - - intensity = intensity * lightPointScale; - dl->photons = intensity; - - dl->type = LIGHT_POINTRADIAL; - - // lights with a target will be spotlights - target = ValueForKey (e, "target"); - - if ( target[0] ) { - float radius; - float dist; - - e2 = FindTargetEntity (target); - if (!e2) { - _printf ("WARNING: light at (%i %i %i) has missing target\n", - (int)dl->origin[0], (int)dl->origin[1], (int)dl->origin[2]); - } else { - GetVectorForKey (e2, "origin", dest); - VectorSubtract (dest, dl->origin, dl->normal); - dist = VectorNormalize (dl->normal, dl->normal); - radius = FloatForKey (e, "radius"); - if ( !radius ) { - radius = 64; - } - if ( !dist ) { - dist = 64; - } - dl->radiusByDist = (radius + 16) / dist; - dl->type = LIGHT_POINTSPOT; - } - } - vlights[numvlights++] = dl; - c_entityLights++; - } - _printf("%7i entity lights\n", c_entityLights); -} - -/* -================== -VL_SubdivideAreaLight -================== -*/ -void VL_SubdivideAreaLight( shaderInfo_t *ls, winding_t *w, vec3_t normal, - float areaSubdivide, qboolean backsplash ) { - float area, value, intensity; - vlight_t *dl, *dl2; - vec3_t mins, maxs; - int axis; - winding_t *front, *back; - vec3_t planeNormal; - float planeDist; - - if ( !w ) { - return; - } - - WindingBounds( w, mins, maxs ); - - // check for subdivision - for ( axis = 0 ; axis < 3 ; axis++ ) { - if ( maxs[axis] - mins[axis] > areaSubdivide ) { - VectorClear( planeNormal ); - planeNormal[axis] = 1; - planeDist = ( maxs[axis] + mins[axis] ) * 0.5; - ClipWindingEpsilon ( w, planeNormal, planeDist, ON_EPSILON, &front, &back ); - VL_SubdivideAreaLight( ls, front, normal, areaSubdivide, qfalse ); - VL_SubdivideAreaLight( ls, back, normal, areaSubdivide, qfalse ); - FreeWinding( w ); - return; - } - } - - // create a light from this - area = WindingArea (w); - if ( area <= 0 || area > 20000000 ) { - return; - } - - dl = malloc(sizeof(*dl)); - memset (dl, 0, sizeof(*dl)); - dl->type = LIGHT_POINTFAKESURFACE; - - WindingCenter( w, dl->origin ); - memcpy(dl->w.points, w->points, sizeof(vec3_t) * w->numpoints); - dl->w.numpoints = w->numpoints; - VectorCopy ( normal, dl->normal); - VectorCopy ( normal, dl->plane); - dl->plane[3] = DotProduct( dl->origin, normal ); - - value = ls->value; - intensity = value * area * lightAreaScale; - VectorAdd( dl->origin, dl->normal, dl->origin ); - - VectorCopy( ls->color, dl->color ); - - dl->photons = intensity; - - // emitColor is irrespective of the area - VectorScale( ls->color, value*lightFormFactorValueScale*lightAreaScale, dl->emitColor ); - // - VectorCopy(dl->emitColor, dl->color); - - dl->si = ls; - - if ( ls->contents & CONTENTS_FOG ) { - dl->twosided = qtrue; - } - - vlights[numvlights++] = dl; - - // optionally create a point backsplash light - if ( backsplash && ls->backsplashFraction > 0 ) { - - dl2 = malloc(sizeof(*dl)); - memset (dl2, 0, sizeof(*dl2)); - dl2->type = LIGHT_POINTRADIAL; - - VectorMA( dl->origin, ls->backsplashDistance, normal, dl2->origin ); - - VectorCopy( ls->color, dl2->color ); - - dl2->photons = dl->photons * ls->backsplashFraction; - dl2->si = ls; - - vlights[numvlights++] = dl2; - } -} - -/* -================== -VL_CreateFakeSurfaceLights -================== -*/ -void VL_CreateFakeSurfaceLights( void ) { - int i, j, side; - dsurface_t *ds; - shaderInfo_t *ls; - winding_t *w; - lFacet_t *f; - vlight_t *dl; - vec3_t origin; - drawVert_t *dv; - int c_surfaceLights; - float lightSubdivide; - vec3_t normal; - - - c_surfaceLights = 0; - _printf ("Creating surface lights...\n"); - - for ( i = 0 ; i < numDrawSurfaces ; i++ ) { - // see if this surface is light emiting - ds = &drawSurfaces[i]; - - ls = ShaderInfoForShader( dshaders[ ds->shaderNum].shader ); - if ( ls->value == 0 ) { - continue; - } - - // determine how much we need to chop up the surface - if ( ls->lightSubdivide ) { - lightSubdivide = ls->lightSubdivide; - } else { - lightSubdivide = lightDefaultSubdivide; - } - - c_surfaceLights++; - - // an autosprite shader will become - // a point light instead of an area light - if ( ls->autosprite ) { - // autosprite geometry should only have four vertexes - if ( lsurfaceTest[i] ) { - // curve or misc_model - f = lsurfaceTest[i]->facets; - if ( lsurfaceTest[i]->numFacets != 1 || f->numpoints != 4 ) { - _printf( "WARNING: surface at (%i %i %i) has autosprite shader but isn't a quad\n", - (int)f->points[0], (int)f->points[1], (int)f->points[2] ); - } - VectorAdd( f->points[0], f->points[1], origin ); - VectorAdd( f->points[2], origin, origin ); - VectorAdd( f->points[3], origin, origin ); - VectorScale( origin, 0.25, origin ); - } else { - // normal polygon - dv = &drawVerts[ ds->firstVert ]; - if ( ds->numVerts != 4 ) { - _printf( "WARNING: surface at (%i %i %i) has autosprite shader but %i verts\n", - (int)dv->xyz[0], (int)dv->xyz[1], (int)dv->xyz[2] ); - continue; - } - - VectorAdd( dv[0].xyz, dv[1].xyz, origin ); - VectorAdd( dv[2].xyz, origin, origin ); - VectorAdd( dv[3].xyz, origin, origin ); - VectorScale( origin, 0.25, origin ); - } - - dl = malloc(sizeof(*dl)); - memset (dl, 0, sizeof(*dl)); - VectorCopy( origin, dl->origin ); - VectorCopy( ls->color, dl->color ); - dl->photons = ls->value * lightPointScale; - dl->type = LIGHT_POINTRADIAL; - vlights[numvlights++] = dl; - continue; - } - - // possibly create for both sides of the polygon - for ( side = 0 ; side <= ls->twoSided ; side++ ) { - // create area lights - if ( lsurfaceTest[i] ) { - // curve or misc_model - for ( j = 0 ; j < lsurfaceTest[i]->numFacets ; j++ ) { - f = lsurfaceTest[i]->facets + j; - w = AllocWinding( f->numpoints ); - w->numpoints = f->numpoints; - memcpy( w->points, f->points, f->numpoints * 12 ); - - VectorCopy( f->plane.normal, normal ); - if ( side ) { - winding_t *t; - - t = w; - w = ReverseWinding( t ); - FreeWinding( t ); - VectorSubtract( vec3_origin, normal, normal ); - } - VL_SubdivideAreaLight( ls, w, normal, lightSubdivide, qtrue ); - } - } else { - // normal polygon - - w = AllocWinding( ds->numVerts ); - w->numpoints = ds->numVerts; - for ( j = 0 ; j < ds->numVerts ; j++ ) { - VectorCopy( drawVerts[ds->firstVert+j].xyz, w->points[j] ); - } - VectorCopy( ds->lightmapVecs[2], normal ); - if ( side ) { - winding_t *t; - - t = w; - w = ReverseWinding( t ); - FreeWinding( t ); - VectorSubtract( vec3_origin, normal, normal ); - } - VL_SubdivideAreaLight( ls, w, normal, lightSubdivide, qtrue ); - } - } - } - - _printf( "%7i light emitting surfaces\n", c_surfaceLights ); -} - - -/* -================== -VL_WindingForBrushSide -================== -*/ -winding_t *VL_WindingForBrushSide(dbrush_t *brush, int side, winding_t *w) -{ - int i, res; - winding_t *tmpw; - plane_t plane; - - VectorCopy(dplanes[ dbrushsides[ brush->firstSide + side ].planeNum ].normal, plane.normal); - VectorInverse(plane.normal); - plane.dist = -dplanes[ dbrushsides[ brush->firstSide + side ].planeNum ].dist; - tmpw = BaseWindingForPlane( plane.normal, plane.dist ); - memcpy(w->points, tmpw->points, sizeof(vec3_t) * tmpw->numpoints); - w->numpoints = tmpw->numpoints; - - for (i = 0; i < brush->numSides; i++) - { - if (i == side) - continue; - VectorCopy(dplanes[ dbrushsides[ brush->firstSide + i ].planeNum ].normal, plane.normal); - VectorInverse(plane.normal); - plane.dist = -dplanes[ dbrushsides[ brush->firstSide + i ].planeNum ].dist; - res = VL_ChopWinding(w, &plane, 0.1); - if (res == SIDE_BACK) - return NULL; - } - return w; -} - -/* -================== -VL_CreateSkyLights -================== -*/ -void VL_CreateSkyLights(void) -{ - int i, j, c_skyLights; - dbrush_t *b; - shaderInfo_t *si; - dbrushside_t *s; - vlight_t *dl; - vec3_t sunColor, sunDir = { 0.45, 0.3, 0.9 }; - float d; - - VectorNormalize(sunDir, sunDir); - VectorInverse(sunDir); - - c_skyLights = 0; - _printf("Creating sky lights...\n"); - // find the sky shader - for ( i = 0 ; i < numDrawSurfaces ; i++ ) { - si = ShaderInfoForShader( dshaders[ drawSurfaces[i].shaderNum ].shader ); - if ( si->surfaceFlags & SURF_SKY ) { - VectorCopy( si->sunLight, sunColor ); - VectorCopy( si->sunDirection, sunDir ); - VectorInverse(sunDir); - break; - } - } - - // find the brushes - for ( i = 0 ; i < numbrushes ; i++ ) { - b = &dbrushes[i]; - for ( j = 0 ; j < b->numSides ; j++ ) { - s = &dbrushsides[ b->firstSide + j ]; - if ( dshaders[ s->shaderNum ].surfaceFlags & SURF_SKY ) { - //if this surface doesn't face in the same direction as the sun - d = DotProduct(dplanes[ s->planeNum ].normal, sunDir); - if (d <= 0) - continue; - // - dl = malloc(sizeof(*dl)); - memset (dl, 0, sizeof(*dl)); - VectorCopy(sunColor, dl->color); - VectorCopy(sunDir, dl->normal); - VectorCopy(dplanes[ s->planeNum ].normal, dl->plane); - dl->plane[3] = dplanes[ s->planeNum ].dist; - dl->type = LIGHT_SURFACEDIRECTED; - dl->atten_disttype = LDAT_NOSCALE; - VL_WindingForBrushSide(b, j, &dl->w); -// DebugNet_DrawWinding(&dl->w, 2); - // - vlights[numvlights++] = dl; - c_skyLights++; - } - } - } - _printf("%7i light emitting sky surfaces\n", c_skyLights); -} - -/* -================== -VL_SetPortalSphere -================== -*/ -void VL_SetPortalSphere (lportal_t *p) -{ - int i; - vec3_t total, dist; - winding_t *w; - float r, bestr; - - w = p->winding; - VectorCopy (vec3_origin, total); - for (i=0 ; i<w->numpoints ; i++) - { - VectorAdd (total, w->points[i], total); - } - - for (i=0 ; i<3 ; i++) - total[i] /= w->numpoints; - - bestr = 0; - for (i=0 ; i<w->numpoints ; i++) - { - VectorSubtract (w->points[i], total, dist); - r = VectorLength (dist); - if (r > bestr) - bestr = r; - } - VectorCopy (total, p->origin); - p->radius = bestr; -} - -/* -================== -VL_PlaneFromWinding -================== -*/ -void VL_PlaneFromWinding (winding_t *w, plane_t *plane) -{ - vec3_t v1, v2; - - //calc plane - VectorSubtract (w->points[2], w->points[1], v1); - VectorSubtract (w->points[0], w->points[1], v2); - CrossProduct (v2, v1, plane->normal); - VectorNormalize (plane->normal, plane->normal); - plane->dist = DotProduct (w->points[0], plane->normal); -} - -/* -================== -VL_AllocWinding -================== -*/ -winding_t *VL_AllocWinding (int points) -{ - winding_t *w; - int size; - - if (points > MAX_POINTS_ON_WINDING) - Error ("NewWinding: %i points", points); - - size = (int)((winding_t *)0)->points[points]; - w = malloc (size); - memset (w, 0, size); - - return w; -} - -/* -============ -VL_LoadPortals -============ -*/ -void VL_LoadPortals (char *name) -{ - int i, j, hint; - lportal_t *p; - lleaf_t *l; - char magic[80]; - FILE *f; - int numpoints; - winding_t *w; - int leafnums[2]; - plane_t plane; - // - - if (!strcmp(name,"-")) - f = stdin; - else - { - f = fopen(name, "r"); - if (!f) - Error ("LoadPortals: couldn't read %s\n",name); - } - - if (fscanf (f,"%79s\n%i\n%i\n%i\n",magic, &portalclusters, &numportals, &numfaces) != 4) - Error ("LoadPortals: failed to read header"); - if (strcmp(magic, PORTALFILE)) - Error ("LoadPortals: not a portal file"); - - _printf ("%6i portalclusters\n", portalclusters); - _printf ("%6i numportals\n", numportals); - _printf ("%6i numfaces\n", numfaces); - - if (portalclusters >= MAX_CLUSTERS) - Error ("more than %d clusters in portal file\n", MAX_CLUSTERS); - - // each file portal is split into two memory portals - portals = malloc(2*numportals*sizeof(lportal_t)); - memset (portals, 0, 2*numportals*sizeof(lportal_t)); - - leafs = malloc(portalclusters*sizeof(lleaf_t)); - memset (leafs, 0, portalclusters*sizeof(lleaf_t)); - - for (i=0, p=portals ; i<numportals ; i++) - { - if (fscanf (f, "%i %i %i ", &numpoints, &leafnums[0], &leafnums[1]) != 3) - Error ("LoadPortals: reading portal %i", i); - if (numpoints > MAX_POINTS_ON_WINDING) - Error ("LoadPortals: portal %i has too many points", i); - if ( (unsigned)leafnums[0] > portalclusters - || (unsigned)leafnums[1] > portalclusters) - Error ("LoadPortals: reading portal %i", i); - if (fscanf (f, "%i ", &hint) != 1) - Error ("LoadPortals: reading hint state"); - - w = p->winding = VL_AllocWinding (numpoints); - w->numpoints = numpoints; - - for (j=0 ; j<numpoints ; j++) - { - double v[3]; - int k; - - // scanf into double, then assign to vec_t - // so we don't care what size vec_t is - if (fscanf (f, "(%lf %lf %lf ) " - , &v[0], &v[1], &v[2]) != 3) - Error ("LoadPortals: reading portal %i", i); - for (k=0 ; k<3 ; k++) - w->points[j][k] = v[k]; - } - fscanf (f, "\n"); - - // calc plane - VL_PlaneFromWinding (w, &plane); - - // create forward portal - l = &leafs[leafnums[0]]; - if (l->numportals == MAX_PORTALS_ON_LEAF) - Error ("Leaf with too many portals"); - l->portals[l->numportals] = p; - l->numportals++; - - p->winding = w; - VectorSubtract (vec3_origin, plane.normal, p->plane.normal); - p->plane.dist = -plane.dist; - p->leaf = leafnums[1]; - VL_SetPortalSphere (p); - p++; - - // create backwards portal - l = &leafs[leafnums[1]]; - if (l->numportals == MAX_PORTALS_ON_LEAF) - Error ("Leaf with too many portals"); - l->portals[l->numportals] = p; - l->numportals++; - - p->winding = VL_AllocWinding(w->numpoints); - p->winding->numpoints = w->numpoints; - for (j=0 ; j<w->numpoints ; j++) - { - VectorCopy (w->points[w->numpoints-1-j], p->winding->points[j]); - } - - p->plane = plane; - p->leaf = leafnums[0]; - VL_SetPortalSphere (p); - p++; - - } - - fclose (f); -} - -/* -============ -VLightMain -============ -*/ -int VLightMain (int argc, char **argv) { - int i; - double start, end; - const char *value; - - _printf ("----- VLighting ----\n"); - - for (i=1 ; i<argc ; i++) { - if (!strcmp(argv[i],"-v")) { - verbose = qtrue; - } else if (!strcmp(argv[i],"-threads")) { - numthreads = atoi (argv[i+1]); - _printf("num threads = %d\n", numthreads); - i++; - } else if (!strcmp(argv[i],"-area")) { - lightAreaScale *= atof(argv[i+1]); - _printf ("area light scaling at %f\n", lightAreaScale); - i++; - } else if (!strcmp(argv[i],"-point")) { - lightPointScale *= atof(argv[i+1]); - _printf ("point light scaling at %f\n", lightPointScale); - i++; - } else if (!strcmp(argv[i], "-samplesize")) { - samplesize = atoi(argv[i+1]); - if (samplesize < 1) samplesize = 1; - i++; - _printf("lightmap sample size is %dx%d units\n", samplesize, samplesize); - } else if (!strcmp(argv[i], "-novertex")) { - novertexlighting = qtrue; - _printf("no vertex lighting = true\n"); - } else if (!strcmp(argv[i], "-nogrid")) { - nogridlighting = qtrue; - _printf("no grid lighting = true\n"); - } else if (!strcmp(argv[i], "-nostitching")) { - nostitching = qtrue; - _printf("no stitching = true\n"); - } else if (!strcmp(argv[i], "-noalphashading")) { - noalphashading = qtrue; - _printf("no alpha shading = true\n"); - } else if (!strcmp(argv[i], "-nocolorshading")) { - nocolorshading = qtrue; - _printf("old style alpha shading = true\n"); - } else if (!strcmp(argv[i], "-nobackfaceculling")) { - nobackfaceculling = qtrue; - _printf("no backface culling = true\n"); - } else if (!strcmp(argv[i], "-tracelight")) { - defaulttracelight = qtrue; - _printf("default trace light = true\n"); - } else if (!strcmp(argv[i], "-radiosity")) { - radiosity = atoi(argv[i+1]); - _printf("radiosity = %d\n", radiosity); - i++; - } else { - break; - } - } - - ThreadSetDefault (); - - if (i != argc - 1) { - _printf("usage: q3map -vlight [-<switch> [-<switch> ...]] <mapname>\n" - "\n" - "Switches:\n" - " v = verbose output\n" - " threads <X> = set number of threads to X\n" - " area <V> = set the area light scale to V\n" - " point <W> = set the point light scale to W\n" - " novertex = don't calculate vertex lighting\n" - " nogrid = don't calculate light grid for dynamic model lighting\n" - " nostitching = no polygon stitching before lighting\n" - " noalphashading = don't use alpha shading\n" - " nocolorshading = don't use color alpha shading\n" - " tracelight = use old light algorithm by default\n" - " samplesize <N> = set the lightmap pixel size to NxN units\n"); - exit(0); - } - - SetQdirFromPath (argv[i]); - -#ifdef _WIN32 - InitPakFile(gamedir, NULL); -#endif - - strcpy (source, ExpandArg(argv[i])); - StripExtension (source); - DefaultExtension (source, ".bsp"); - - LoadShaderInfo(); - - _printf ("reading %s\n", source); - - LoadBSPFile (source); - ParseEntities(); - - value = ValueForKey( &entities[0], "gridsize" ); - if (strlen(value)) { - sscanf( value, "%f %f %f", &gridSize[0], &gridSize[1], &gridSize[2] ); - _printf("grid size = {%1.1f, %1.1f, %1.1f}\n", gridSize[0], gridSize[1], gridSize[2]); - } - - CountLightmaps(); - - StripExtension (source); - DefaultExtension (source, ".prt"); - - VL_LoadPortals(source); - - // set surfaceOrigin - SetEntityOrigins(); - - // grid and vertex lighting - GridAndVertexLighting(); - -#ifdef DEBUGNET - DebugNet_Setup(); -#endif - - start = clock(); - - lightFloats = (float *) malloc(numLightBytes * sizeof(float)); - memset(lightFloats, 0, numLightBytes * sizeof(float)); - - VL_InitSurfacesForTesting(); - - VL_CalcVisibleLightmapPixelArea(); - - numvlights = 0; - VL_CreateEntityLights(); - VL_CreateFakeSurfaceLights(); - VL_CreateSkyLights(); - - VL_TestLightLeafs(); - - VL_LightWorld(); - -#ifndef LIGHTPOLYS - StripExtension (source); - DefaultExtension (source, ".bsp"); - _printf ("writing %s\n", source); - WriteBSPFile (source); -#endif - - end = clock(); - - _printf ("%5.2f seconds elapsed\n", (end-start) / CLK_TCK); - -#ifdef LIGHTPOLYS - VL_DrawLightWindings(); -#endif - -#ifdef DEBUGNET - DebugNet_Shutdown(); -#endif - return 0; -} diff --git a/q3map/makefile b/q3map/makefile deleted file mode 100644 index ff8d6c1..0000000 --- a/q3map/makefile +++ /dev/null @@ -1,148 +0,0 @@ - -CFLAGS = -c -LDFLAGS = -ODIR = /q3/q3map - -EXEBASE = q3map -EXE = $(ODIR)/$(EXEBASE) -all: $(EXE) - -_irix: - make "CFLAGS = -c -Ofast=ip27 -OPT:IEEE_arithmetic=3 -I../common -Xcpluscomm " "LDFLAGS = -Ofast=ip27 -OPT:IEEE_arithmetic=3 -g" - -_irixdebug: - make "CFLAGS = -c -O2 -g -I../common -Xcpluscomm" "LDFLAGS = -g" - -_irixinst: - make "_irix" - make "install" - -clean: - rm -f $(ODIR)/*.o $(EXE) - -install: - cp $(EXE) /quake3_bin - chmod 0777 /quake3_bin/$(EXEBASE) - -installtest: - cp $(EXE) /quake3_bin/$(EXEBASE)_test - chmod 0777 /quake3_bin/$(EXEBASE)_test - - -FILES = $(ODIR)/fog.o $(ODIR)/brush.o $(ODIR)/tjunction.o $(ODIR)/vis.o $(ODIR)/visflow.o \ -$(ODIR)/light.o $(ODIR)/lightmaps.o $(ODIR)/bspfile.o \ -$(ODIR)/cmdlib.o $(ODIR)/patch.o $(ODIR)/mesh.o $(ODIR)/nodraw.o $(ODIR)/glfile.o \ -$(ODIR)/leakfile.o $(ODIR)/map.o $(ODIR)/mathlib.o $(ODIR)/polylib.o $(ODIR)/aselib.o \ -$(ODIR)/imagelib.o $(ODIR)/portals.o $(ODIR)/prtfile.o $(ODIR)/bsp.o $(ODIR)/surface.o \ -$(ODIR)/scriplib.o $(ODIR)/shaders.o $(ODIR)/threads.o $(ODIR)/tree.o \ -$(ODIR)/writebsp.o $(ODIR)/facebsp.o $(ODIR)/misc_model.o $(ODIR)/light_trace.o - -$(EXE) : $(FILES) - cc -o $(EXE) $(LDFLAGS) $(FILES) -lm - -$(ODIR)/surface.o : surface.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/fog.o : fog.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/brush.o : brush.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/tjunction.o : tjunction.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/lightmaps.o : lightmaps.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/brushbsp.o : brushbsp.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/facebsp.o : facebsp.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/patch.o : patch.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/mesh.o : mesh.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/misc_model.o : misc_model.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/nodraw.o : nodraw.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/glfile.o : glfile.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/leakfile.o : leakfile.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/map.o : map.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/portals.o : portals.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/prtfile.o : prtfile.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/bsp.o : bsp.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/tree.o : tree.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/shaders.o : shaders.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/writebsp.o : writebsp.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/csg.o : csg.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i - - -$(ODIR)/vis.o : vis.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/visflow.o : visflow.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i - - -$(ODIR)/light.o : light.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/light_trace.o : light_trace.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i - -$(ODIR)/cmdlib.o : ../common/cmdlib.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/mathlib.o : ../common/mathlib.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/polylib.o : ../common/polylib.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/aselib.o : ../common/aselib.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/imagelib.o : ../common/imagelib.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/scriplib.o : ../common/scriplib.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/threads.o : ../common/threads.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i -$(ODIR)/bspfile.o : ../common/bspfile.c - cc $(CFLAGS) -E $? | tr -d '\015' > /tmp/temp.i - cc $(CFLAGS) -o $@ /tmp/temp.i - - diff --git a/q3map/map.c b/q3map/map.c deleted file mode 100644 index 3de6ede..0000000 --- a/q3map/map.c +++ /dev/null @@ -1,1251 +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 -=========================================================================== -*/ -// map.c - -#include "qbsp.h" - - -int entitySourceBrushes; // to track editor brush numbers - -int numMapPatches; - -// undefine to make plane finding use linear sort -#define USE_HASHING -#define PLANE_HASHES 1024 -plane_t *planehash[PLANE_HASHES]; - -plane_t mapplanes[MAX_MAP_PLANES]; -int nummapplanes; - -// as brushes and patches are read in, the shaders are stored out in order -// here, so -onlytextures can just copy them out over the existing shaders -// in the drawSurfaces -char mapIndexedShaders[MAX_MAP_BRUSHSIDES][MAX_QPATH]; -int numMapIndexedShaders; - -vec3_t map_mins, map_maxs; - -entity_t *mapent; - - - -int c_boxbevels; -int c_edgebevels; - -int c_areaportals; -int c_detail; -int c_structural; - -// brushes are parsed into a temporary array of sides, -// which will have the bevels added and duplicates -// removed before the final brush is allocated -bspbrush_t *buildBrush; - - -void TestExpandBrushes (void); -void SetTerrainTextures( void ); -void ParseTerrain( void ); - - -/* -============================================================================= - -PLANE FINDING - -============================================================================= -*/ - - -/* -================ -PlaneEqual -================ -*/ -#define NORMAL_EPSILON 0.00001 -#define DIST_EPSILON 0.01 -qboolean PlaneEqual (plane_t *p, vec3_t normal, vec_t dist) -{ -#if 1 - if ( - fabs(p->normal[0] - normal[0]) < NORMAL_EPSILON - && fabs(p->normal[1] - normal[1]) < NORMAL_EPSILON - && fabs(p->normal[2] - normal[2]) < NORMAL_EPSILON - && fabs(p->dist - dist) < DIST_EPSILON ) - return qtrue; -#else - if (p->normal[0] == normal[0] - && p->normal[1] == normal[1] - && p->normal[2] == normal[2] - && p->dist == dist) - return qtrue; -#endif - return qfalse; -} - -/* -================ -AddPlaneToHash -================ -*/ -void AddPlaneToHash (plane_t *p) -{ - int hash; - - hash = (int)fabs(p->dist) / 8; - hash &= (PLANE_HASHES-1); - - p->hash_chain = planehash[hash]; - planehash[hash] = p; -} - -/* -================ -CreateNewFloatPlane -================ -*/ -int CreateNewFloatPlane (vec3_t normal, vec_t dist) -{ - plane_t *p, temp; - - if (VectorLength(normal) < 0.5) - { - _printf( "FloatPlane: bad normal\n"); - return -1; - } - - // create a new plane - if (nummapplanes+2 > MAX_MAP_PLANES) - Error ("MAX_MAP_PLANES"); - - p = &mapplanes[nummapplanes]; - VectorCopy (normal, p->normal); - p->dist = dist; - p->type = (p+1)->type = PlaneTypeForNormal (p->normal); - - VectorSubtract (vec3_origin, normal, (p+1)->normal); - (p+1)->dist = -dist; - - nummapplanes += 2; - - // allways put axial planes facing positive first - if (p->type < 3) - { - if (p->normal[0] < 0 || p->normal[1] < 0 || p->normal[2] < 0) - { - // flip order - temp = *p; - *p = *(p+1); - *(p+1) = temp; - - AddPlaneToHash (p); - AddPlaneToHash (p+1); - return nummapplanes - 1; - } - } - - AddPlaneToHash (p); - AddPlaneToHash (p+1); - return nummapplanes - 2; -} - -/* -============== -SnapVector -============== -*/ -void SnapVector (vec3_t normal) -{ - int i; - - for (i=0 ; i<3 ; i++) - { - if ( fabs(normal[i] - 1) < NORMAL_EPSILON ) - { - VectorClear (normal); - normal[i] = 1; - break; - } - if ( fabs(normal[i] - -1) < NORMAL_EPSILON ) - { - VectorClear (normal); - normal[i] = -1; - break; - } - } -} - -/* -============== -SnapPlane -============== -*/ -void SnapPlane (vec3_t normal, vec_t *dist) -{ - SnapVector (normal); - - if (fabs(*dist-Q_rint(*dist)) < DIST_EPSILON) - *dist = Q_rint(*dist); -} - -/* -============= -FindFloatPlane - -============= -*/ -#ifndef USE_HASHING -int FindFloatPlane (vec3_t normal, vec_t dist) -{ - int i; - plane_t *p; - - SnapPlane (normal, &dist); - for (i=0, p=mapplanes ; i<nummapplanes ; i++, p++) - { - if (PlaneEqual (p, normal, dist)) - return i; - } - - return CreateNewFloatPlane (normal, dist); -} -#else -int FindFloatPlane (vec3_t normal, vec_t dist) -{ - int i; - plane_t *p; - int hash, h; - - SnapPlane (normal, &dist); - hash = (int)fabs(dist) / 8; - hash &= (PLANE_HASHES-1); - - // search the border bins as well - for (i=-1 ; i<=1 ; i++) - { - h = (hash+i)&(PLANE_HASHES-1); - for (p = planehash[h] ; p ; p=p->hash_chain) - { - if (PlaneEqual (p, normal, dist)) - return p-mapplanes; - } - } - - return CreateNewFloatPlane (normal, dist); -} -#endif - -/* -================ -MapPlaneFromPoints -================ -*/ -int MapPlaneFromPoints (vec3_t p0, vec3_t p1, vec3_t p2) { - vec3_t t1, t2, normal; - vec_t dist; - - VectorSubtract (p0, p1, t1); - VectorSubtract (p2, p1, t2); - CrossProduct (t1, t2, normal); - VectorNormalize (normal, normal); - - dist = DotProduct (p0, normal); - - return FindFloatPlane (normal, dist); -} - - -//==================================================================== - -/* -=========== -SetBrushContents - -The contents on all sides of a brush should be the same -Sets contentsShader, contents, opaque, and detail -=========== -*/ -void SetBrushContents( bspbrush_t *b ) { - int contents, c2; - side_t *s; - int i; - qboolean mixed; - int allFlags; - - s = &b->sides[0]; - contents = s->contents; - b->contentShader = s->shaderInfo; - mixed = qfalse; - - allFlags = 0; - - for ( i=1 ; i<b->numsides ; i++, s++ ) { - s = &b->sides[i]; - - if ( !s->shaderInfo ) { - continue; - } - - c2 = s->contents; - if (c2 != contents) { - mixed = qtrue; - } - - allFlags |= s->surfaceFlags; - } - - if ( mixed ) { - qprintf ("Entity %i, Brush %i: mixed face contents\n" - , b->entitynum, b->brushnum); - } - - if ( ( contents & CONTENTS_DETAIL ) && ( contents & CONTENTS_STRUCTURAL ) ) { - _printf ("Entity %i, Brush %i: mixed CONTENTS_DETAIL and CONTENTS_STRUCTURAL\n" - , num_entities-1, entitySourceBrushes ); - contents &= ~CONTENTS_DETAIL; - } - - // the fulldetail flag will cause detail brushes to be - // treated like normal brushes - if ( fulldetail ) { - contents &= ~CONTENTS_DETAIL; - } - - // all translucent brushes that aren't specirically made structural will - // be detail - if ( ( contents & CONTENTS_TRANSLUCENT ) && !( contents & CONTENTS_STRUCTURAL ) ) { - contents |= CONTENTS_DETAIL; - } - - if ( contents & CONTENTS_DETAIL ) { - c_detail++; - b->detail = qtrue; - } else { - c_structural++; - b->detail = qfalse; - } - - if ( contents & CONTENTS_TRANSLUCENT ) { - b->opaque = qfalse; - } else { - b->opaque = qtrue; - } - - if ( contents & CONTENTS_AREAPORTAL ) { - c_areaportals++; - } - - b->contents = contents; -} - - -//============================================================================ - -/* -================= -AddBrushBevels - -Adds any additional planes necessary to allow the brush being -built to be expanded against axial bounding boxes -================= -*/ -void AddBrushBevels( void ) { - int axis, dir; - int i, order; - side_t sidetemp; - side_t *s; - vec3_t normal; - float dist; - - // - // add the axial planes - // - order = 0; - for (axis=0 ; axis <3 ; axis++) - { - for (dir=-1 ; dir <= 1 ; dir+=2, order++) - { - // see if the plane is allready present - for ( i=0, s=buildBrush->sides ; i < buildBrush->numsides ; i++,s++ ) { - if (mapplanes[s->planenum].normal[axis] == dir) - break; - } - - if (i == buildBrush->numsides ) - { // add a new side - if ( buildBrush->numsides == MAX_BUILD_SIDES ) { - Error( "MAX_BUILD_SIDES" ); - } - memset( s, 0, sizeof( *s ) ); - buildBrush->numsides++; - VectorClear (normal); - normal[axis] = dir; - if (dir == 1) - dist = buildBrush->maxs[axis]; - else - dist = -buildBrush->mins[axis]; - s->planenum = FindFloatPlane (normal, dist); - s->contents = buildBrush->sides[0].contents; - s->bevel = qtrue; - c_boxbevels++; - } - - // if the plane is not in it canonical order, swap it - if (i != order) - { - sidetemp = buildBrush->sides[order]; - buildBrush->sides[order] = buildBrush->sides[i]; - buildBrush->sides[i] = sidetemp; - } - } - } - - // - // add the edge bevels - // - if ( buildBrush->numsides == 6 ) { - return; // pure axial - } else { - int j, k, l; - float d; - winding_t *w, *w2; - side_t *s2; - vec3_t vec, vec2; - - // test the non-axial plane edges - // this code tends to cause some problems... - for (i=6 ; i<buildBrush->numsides ; i++) - { - s = buildBrush->sides + i; - w = s->winding; - if (!w) - continue; - for (j=0 ; j<w->numpoints ; j++) - { - k = (j+1)%w->numpoints; - VectorSubtract (w->p[j], w->p[k], vec); - if (VectorNormalize (vec, vec) < 0.5) - continue; - SnapVector (vec); - for (k=0 ; k<3 ; k++) - if ( vec[k] == -1 || vec[k] == 1) - break; // axial - if (k != 3) - continue; // only test non-axial edges - - // try the six possible slanted axials from this edge - for (axis=0 ; axis <3 ; axis++) - { - for (dir=-1 ; dir <= 1 ; dir+=2) - { - // construct a plane - VectorClear (vec2); - vec2[axis] = dir; - CrossProduct (vec, vec2, normal); - if (VectorNormalize (normal, normal) < 0.5) - continue; - dist = DotProduct (w->p[j], normal); - - // if all the points on all the sides are - // behind this plane, it is a proper edge bevel - for (k=0 ; k < buildBrush->numsides ; k++) - { - // if this plane has allready been used, skip it - if (PlaneEqual (&mapplanes[buildBrush->sides[k].planenum] - , normal, dist) ) - break; - - w2 = buildBrush->sides[k].winding; - if (!w2) - continue; - for (l=0 ; l<w2->numpoints ; l++) - { - d = DotProduct (w2->p[l], normal) - dist; - if (d > 0.1) - break; // point in front - } - if (l != w2->numpoints) - break; - } - - if (k != buildBrush->numsides) - continue; // wasn't part of the outer hull - // add this plane - if ( buildBrush->numsides == MAX_BUILD_SIDES ) { - Error( "MAX_BUILD_SIDES" ); - } - - s2 = &buildBrush->sides[buildBrush->numsides]; - buildBrush->numsides++; - memset( s2, 0, sizeof( *s2 ) ); - - s2->planenum = FindFloatPlane (normal, dist); - s2->contents = buildBrush->sides[0].contents; - s2->bevel = qtrue; - c_edgebevels++; - } - } - } - } - } -} - -/* -=============== -AddBackSides - -fog volumes need to have inside faces created -=============== -*/ -void AddBackSides( void ) { -/* - bspbrush_t *b; - int i, originalSides; - side_t *s; - side_t *newSide; - - b = buildBrush; - originalSides = b->numsides; - for ( i = 0 ; i < originalSides ; i++ ) { - s = &b->sides[i]; - if ( !s->shaderInfo ) { - continue; - } - if ( !(s->shaderInfo->contents & CONTENTS_FOG) ) { - continue; - } - - // duplicate the up-facing side - if ( mapplanes[ s->planenum ].normal[2] == 1 ) { - newSide = &b->sides[ b->numsides ]; - b->numsides++; - - *newSide = *s; - newSide->backSide = qtrue; - newSide->planenum = s->planenum ^ 1; // opposite side - } - } -*/ -} - -/* -=============== -FinishBrush - -Produces a final brush based on the buildBrush->sides array -and links it to the current entity -=============== -*/ -bspbrush_t *FinishBrush( void ) { - bspbrush_t *b; - - // liquids may need to have extra sides created for back sides - AddBackSides(); - - // create windings for sides and bounds for brush - if ( !CreateBrushWindings( buildBrush ) ) { - // don't keep this brush - return NULL; - } - - // brushes that will not be visible at all are forced to be detail - if ( buildBrush->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) ) - { - buildBrush->detail = qtrue; - c_detail++; - } - - // - // origin brushes are removed, but they set - // the rotation origin for the rest of the brushes - // in the entity. After the entire entity is parsed, - // the planenums and texinfos will be adjusted for - // the origin brush - // - if ( buildBrush->contents & CONTENTS_ORIGIN ) - { - char string[32]; - vec3_t origin; - - if (num_entities == 1) { - _printf ("Entity %i, Brush %i: origin brushes not allowed in world\n" - , num_entities - 1, entitySourceBrushes); - return NULL; - } - - VectorAdd (buildBrush->mins, buildBrush->maxs, origin); - VectorScale (origin, 0.5, origin); - - sprintf (string, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]); - SetKeyValue (&entities[num_entities - 1], "origin", string); - - VectorCopy (origin, entities[num_entities - 1].origin); - - // don't keep this brush - return NULL; - } - - if ( buildBrush->contents & CONTENTS_AREAPORTAL ) { - if (num_entities != 1) { - _printf ("Entity %i, Brush %i: areaportals only allowed in world\n" - , num_entities - 1, entitySourceBrushes); - return NULL; - } - } - - AddBrushBevels (); - - // keep it - b = CopyBrush( buildBrush ); - - b->entitynum = num_entities-1; - b->brushnum = entitySourceBrushes; - - b->original = b; - - b->next = mapent->brushes; - mapent->brushes = b; - - return b; -} - -//====================================================================== - - -/* -================== -textureAxisFromPlane -================== -*/ -vec3_t baseaxis[18] = -{ -{0,0,1}, {1,0,0}, {0,-1,0}, // floor -{0,0,-1}, {1,0,0}, {0,-1,0}, // ceiling -{1,0,0}, {0,1,0}, {0,0,-1}, // west wall -{-1,0,0}, {0,1,0}, {0,0,-1}, // east wall -{0,1,0}, {1,0,0}, {0,0,-1}, // south wall -{0,-1,0}, {1,0,0}, {0,0,-1} // north wall -}; - -void TextureAxisFromPlane(plane_t *pln, vec3_t xv, vec3_t yv) -{ - int bestaxis; - vec_t dot,best; - int i; - - best = 0; - bestaxis = 0; - - for (i=0 ; i<6 ; i++) - { - dot = DotProduct (pln->normal, baseaxis[i*3]); - if (dot > best) - { - best = dot; - bestaxis = i; - } - } - - VectorCopy (baseaxis[bestaxis*3+1], xv); - VectorCopy (baseaxis[bestaxis*3+2], yv); -} - - - -/* -================= -QuakeTextureVecs - -Creates world-to-texture mapping vecs for crappy quake plane arrangements -================= -*/ -void QuakeTextureVecs( plane_t *plane, vec_t shift[2], vec_t rotate, vec_t scale[2], - vec_t mappingVecs[2][4] ) { - - vec3_t vecs[2]; - int sv, tv; - vec_t ang, sinv, cosv; - vec_t ns, nt; - int i, j; - - TextureAxisFromPlane(plane, vecs[0], vecs[1]); - - if (!scale[0]) - scale[0] = 1; - if (!scale[1]) - scale[1] = 1; - - // rotate axis - if (rotate == 0) - { sinv = 0 ; cosv = 1; } - else if (rotate == 90) - { sinv = 1 ; cosv = 0; } - else if (rotate == 180) - { sinv = 0 ; cosv = -1; } - else if (rotate == 270) - { sinv = -1 ; cosv = 0; } - else - { - ang = rotate / 180 * Q_PI; - sinv = sin(ang); - cosv = cos(ang); - } - - if (vecs[0][0]) - sv = 0; - else if (vecs[0][1]) - sv = 1; - else - sv = 2; - - if (vecs[1][0]) - tv = 0; - else if (vecs[1][1]) - tv = 1; - else - tv = 2; - - for (i=0 ; i<2 ; i++) { - ns = cosv * vecs[i][sv] - sinv * vecs[i][tv]; - nt = sinv * vecs[i][sv] + cosv * vecs[i][tv]; - vecs[i][sv] = ns; - vecs[i][tv] = nt; - } - - for (i=0 ; i<2 ; i++) - for (j=0 ; j<3 ; j++) - mappingVecs[i][j] = vecs[i][j] / scale[i]; - - mappingVecs[0][3] = shift[0]; - mappingVecs[1][3] = shift[1]; -} - -//====================================================================== - -/* -================= -ParseRawBrush - -Just parses the sides into buildBrush->sides[], nothing else. -no validation, back plane removal, etc. - -Timo - 08/26/99 -added brush epairs parsing ( ignoring actually ) -Timo - 08/04/99 -added exclusive brush primitive parsing -Timo - 08/08/99 -support for old brush format back in -NOTE : it would be "cleaner" to have seperate functions to parse between old and new brushes -================= -*/ -void ParseRawBrush( ) { - side_t *side; - vec3_t planepts[3]; - int planenum; - shaderInfo_t *si; - // old brushes - vec_t shift[2]; - vec_t rotate; - vec_t scale[2]; - char name[MAX_QPATH]; - char shader[MAX_QPATH]; - int flags; - - buildBrush->numsides = 0; - buildBrush->detail = qfalse; - - if (g_bBrushPrimit==BPRIMIT_NEWBRUSHES) - MatchToken( "{" ); - - do - { - if (!GetToken (qtrue)) - break; - if (!strcmp (token, "}") ) - break; - //Timo : brush primitive : here we may have to jump over brush epairs ( only used in editor ) - if (g_bBrushPrimit==BPRIMIT_NEWBRUSHES) - { - do - { - if (strcmp (token, "(") ) - GetToken( qfalse ); - else - break; - GetToken( qtrue ); - } while (1); - } - UnGetToken(); - - if ( buildBrush->numsides == MAX_BUILD_SIDES ) { - Error( "MAX_BUILD_SIDES" ); - } - - side = &buildBrush->sides[ buildBrush->numsides ]; - memset( side, 0, sizeof( *side ) ); - buildBrush->numsides++; - - // read the three point plane definition - Parse1DMatrix( 3, planepts[0] ); - Parse1DMatrix( 3, planepts[1] ); - Parse1DMatrix( 3, planepts[2] ); - - if (g_bBrushPrimit==BPRIMIT_NEWBRUSHES) - // read the texture matrix - Parse2DMatrix( 2, 3, (float *)side->texMat ); - - // read the texturedef - GetToken (qfalse); - strcpy (name, token); - - // save the shader name for retexturing - if ( numMapIndexedShaders == MAX_MAP_BRUSHSIDES ) { - Error( "MAX_MAP_BRUSHSIDES" ); - } - strcpy( mapIndexedShaders[numMapIndexedShaders], name ); - numMapIndexedShaders++; - - if (g_bBrushPrimit==BPRIMIT_OLDBRUSHES) - { - GetToken (qfalse); - shift[0] = atoi(token); - GetToken (qfalse); - shift[1] = atoi(token); - GetToken (qfalse); - rotate = atoi(token); - GetToken (qfalse); - scale[0] = atof(token); - GetToken (qfalse); - scale[1] = atof(token); - } - - // find default flags and values - sprintf( shader, "textures/%s", name ); - si = ShaderInfoForShader( shader ); - side->shaderInfo = si; - side->surfaceFlags = si->surfaceFlags; - side->value = si->value; - side->contents = si->contents; - - // allow override of default flags and values - // in Q3, the only thing you can override is DETAIL - if (TokenAvailable()) - { - GetToken (qfalse); -// side->contents = atoi(token); - flags = atoi(token); - if ( flags & CONTENTS_DETAIL ) { - side->contents |= CONTENTS_DETAIL; - } - - GetToken (qfalse); -// td.flags = atoi(token); - - GetToken (qfalse); -// td.value = atoi(token); - } - - - // find the plane number - planenum = MapPlaneFromPoints (planepts[0], planepts[1], planepts[2]); - side->planenum = planenum; - - if (g_bBrushPrimit==BPRIMIT_OLDBRUSHES) - // get the texture mapping for this texturedef / plane combination - QuakeTextureVecs( &mapplanes[planenum], shift, rotate, scale, side->vecs ); - - } while (1); - - if (g_bBrushPrimit==BPRIMIT_NEWBRUSHES) - { - UnGetToken(); - MatchToken( "}" ); - MatchToken( "}" ); - } -} - -/* -================= -RemoveDuplicateBrushPlanes - -Returns false if the brush has a mirrored set of planes, -meaning it encloses no volume. -Also removes planes without any normal -================= -*/ -qboolean RemoveDuplicateBrushPlanes( bspbrush_t * b ) { - int i, j, k; - side_t *sides; - - sides = b->sides; - - for ( i = 1 ; i < b->numsides ; i++ ) { - - // check for a degenerate plane - if ( sides[i].planenum == -1) { - _printf ("Entity %i, Brush %i: degenerate plane\n" - , b->entitynum, b->brushnum); - // remove it - for ( k = i + 1 ; k < b->numsides ; k++ ) { - sides[k-1] = sides[k]; - } - b->numsides--; - i--; - continue; - } - - // check for duplication and mirroring - for ( j = 0 ; j < i ; j++ ) { - if ( sides[i].planenum == sides[j].planenum ) { - _printf ("Entity %i, Brush %i: duplicate plane\n" - , b->entitynum, b->brushnum); - // remove the second duplicate - for ( k = i + 1 ; k < b->numsides ; k++ ) { - sides[k-1] = sides[k]; - } - b->numsides--; - i--; - break; - } - - if ( sides[i].planenum == (sides[j].planenum ^ 1) ) { - // mirror plane, brush is invalid - _printf ("Entity %i, Brush %i: mirrored plane\n" - , b->entitynum, b->brushnum); - return qfalse; - } - } - } - return qtrue; -} - - -/* -================= -ParseBrush - - qboolean parameter to true -> parse new brush primitive format ( else use old format ) -================= -*/ -void ParseBrush (void) { - bspbrush_t *b; - - ParseRawBrush(); - - buildBrush->portalareas[0] = -1; - buildBrush->portalareas[1] = -1; - buildBrush->entitynum = num_entities-1; - buildBrush->brushnum = entitySourceBrushes; - - // if there are mirrored planes, the entire brush is invalid - if ( !RemoveDuplicateBrushPlanes( buildBrush ) ) { - return; - } - - // get the content for the entire brush - SetBrushContents( buildBrush ); - - // allow detail brushes to be removed - if (nodetail && (buildBrush->contents & CONTENTS_DETAIL) ) { - FreeBrush( buildBrush ); - return; - } - - // allow water brushes to be removed - if (nowater && (buildBrush->contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER)) ) { - FreeBrush( buildBrush ); - return; - } - - b = FinishBrush( ); - if ( !b ) { - return; - } -} - - -/* -================ -MoveBrushesToWorld - -Takes all of the brushes from the current entity and -adds them to the world's brush list. - -Used by func_group -================ -*/ -void MoveBrushesToWorld (entity_t *mapent) { - bspbrush_t *b, *next; - parseMesh_t *pm; - - // move brushes - for ( b = mapent->brushes ; b ; b = next ) { - next = b->next; - - b->next = entities[0].brushes; - entities[0].brushes = b; - } - mapent->brushes = NULL; - - // move patches - if ( mapent->patches ) { - - for ( pm = mapent->patches ; pm->next ; pm = pm->next ) { - } - - pm->next = entities[0].patches; - entities[0].patches = mapent->patches; - - mapent->patches = NULL; - } -} - - -/* -================ -AdjustBrushesForOrigin -================ -*/ -void AdjustBrushesForOrigin( entity_t *ent ) { - bspbrush_t *b; - int i; - side_t *s; - vec_t newdist; - parseMesh_t *p; - - for ( b = ent->brushes ; b ; b = b->next ) { - for (i=0 ; i<b->numsides ; i++) { - s = &b->sides[i]; - newdist = mapplanes[s->planenum].dist - - DotProduct (mapplanes[s->planenum].normal, ent->origin); - s->planenum = FindFloatPlane (mapplanes[s->planenum].normal, newdist); - } - CreateBrushWindings(b); - } - - for ( p = ent->patches ; p ; p = p->next ) { - for ( i = 0 ; i < p->mesh.width*p->mesh.height ; i++ ) { - VectorSubtract( p->mesh.verts[i].xyz, ent->origin, p->mesh.verts[i].xyz ); - } - } - -} - -/* -================ -ParseMapEntity -================ -*/ -qboolean ParseMapEntity (void) { - epair_t *e; - - if (!GetToken (qtrue)) - return qfalse; - - if (strcmp (token, "{") ) - { - Error ("ParseEntity: { not found, found %s on line %d - last entity was at: <%4.2f, %4.2f, %4.2f>...", token, scriptline, entities[num_entities].origin[0], entities[num_entities].origin[1], entities[num_entities].origin[2]); - } - - if (num_entities == MAX_MAP_ENTITIES) - Error ("num_entities == MAX_MAP_ENTITIES"); - - entitySourceBrushes = 0; - - mapent = &entities[num_entities]; - num_entities++; - memset (mapent, 0, sizeof(*mapent)); - - do - { - if (!GetToken (qtrue)) - Error ("ParseEntity: EOF without closing brace"); - if (!strcmp (token, "}") ) - break; - - if (!strcmp (token, "{") ) { - // parse a brush or patch - if (!GetToken (qtrue)) - break; - if ( !strcmp( token, "patchDef2" ) ) { - numMapPatches++; - ParsePatch(); - } else if ( !strcmp( token, "terrainDef" ) ) { - ParseTerrain(); - } else if ( !strcmp( token, "brushDef" ) ) { - if (g_bBrushPrimit==BPRIMIT_OLDBRUSHES) - Error("old brush format not allowed in new brush format map"); - g_bBrushPrimit=BPRIMIT_NEWBRUSHES; - // parse brush primitive - ParseBrush(); - } - else - { - if (g_bBrushPrimit==BPRIMIT_NEWBRUSHES) - Error("new brush format not allowed in old brush format map"); - g_bBrushPrimit=BPRIMIT_OLDBRUSHES; - // parse old brush format - UnGetToken(); - ParseBrush(); - } - entitySourceBrushes++; - } - else - { - // parse a key / value pair - e = ParseEpair (); - e->next = mapent->epairs; - mapent->epairs = e; - } - } while (1); - - GetVectorForKey (mapent, "origin", mapent->origin); - - // - // if there was an origin brush, offset all of the planes and texinfo - // for all the brushes in the entity - if (mapent->origin[0] || mapent->origin[1] || mapent->origin[2]) { - AdjustBrushesForOrigin( mapent ); - } - - // group_info entities are just for editor grouping - // ignored - // FIXME: leak! - if (!strcmp("group_info", ValueForKey (mapent, "classname"))) - { - num_entities--; - return qtrue; - } - - // group entities are just for editor convenience - // toss all brushes into the world entity - if (!strcmp ("func_group", ValueForKey (mapent, "classname"))) - { - if ( !strcmp ("1", ValueForKey (mapent, "terrain"))) { - SetTerrainTextures(); - } - MoveBrushesToWorld (mapent); - num_entities--; - return qtrue; - } - - return qtrue; -} - -//=================================================================== - - -/* -================ -LoadMapFile -================ -*/ -void LoadMapFile (char *filename) { - bspbrush_t *b; - - qprintf ("--- LoadMapFile ---\n"); - _printf ("Loading map file %s\n", filename); - - LoadScriptFile (filename); - - num_entities = 0; - numMapDrawSurfs = 0; - c_detail = 0; - - g_bBrushPrimit = BPRIMIT_UNDEFINED; - - // allocate a very large temporary brush for building - // the brushes as they are loaded - buildBrush = AllocBrush( MAX_BUILD_SIDES ); - - while (ParseMapEntity ()) - { - } - - ClearBounds (map_mins, map_maxs); - for ( b = entities[0].brushes ; b ; b=b->next ) { - AddPointToBounds( b->mins, map_mins, map_maxs ); - AddPointToBounds( b->maxs, map_mins, map_maxs ); - } - - qprintf ("%5i total world brushes\n", CountBrushList( entities[0].brushes ) ); - qprintf ("%5i detail brushes\n", c_detail ); - qprintf ("%5i patches\n", numMapPatches); - qprintf ("%5i boxbevels\n", c_boxbevels); - qprintf ("%5i edgebevels\n", c_edgebevels); - qprintf ("%5i entities\n", num_entities); - qprintf ("%5i planes\n", nummapplanes); - qprintf ("%5i areaportals\n", c_areaportals); - qprintf ("size: %5.0f,%5.0f,%5.0f to %5.0f,%5.0f,%5.0f\n", map_mins[0],map_mins[1],map_mins[2], - map_maxs[0],map_maxs[1],map_maxs[2]); - - if ( fakemap ) { - WriteBspBrushMap ("fakemap.map", entities[0].brushes ); - } - - if ( testExpand ) { - TestExpandBrushes (); - } -} - - -//==================================================================== - - -/* -================ -TestExpandBrushes - -Expands all the brush planes and saves a new map out to -allow visual inspection of the clipping bevels -================ -*/ -void TestExpandBrushes( void ) { - side_t *s; - int i, j; - bspbrush_t *brush, *list, *copy; - vec_t dist; - plane_t *plane; - - list = NULL; - - for ( brush = entities[0].brushes ; brush ; brush = brush->next ) { - copy = CopyBrush( brush ); - copy->next = list; - list = copy; - - // expand all the planes - for ( i=0 ; i<brush->numsides ; i++ ) { - s = brush->sides + i; - plane = &mapplanes[s->planenum]; - dist = plane->dist; - for (j=0 ; j<3 ; j++) { - dist += fabs( 16 * plane->normal[j] ); - } - s->planenum = FindFloatPlane( plane->normal, dist ); - } - - } - - WriteBspBrushMap ( "expanded.map", entities[0].brushes ); - - Error ("can't proceed after expanding brushes"); -} diff --git a/q3map/mesh.c b/q3map/mesh.c deleted file mode 100644 index e2b3010..0000000 --- a/q3map/mesh.c +++ /dev/null @@ -1,682 +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" - - -/* -=============================================================== - -MESH SUBDIVISION - -=============================================================== -*/ - - -int originalWidths[MAX_EXPANDED_AXIS]; -int originalHeights[MAX_EXPANDED_AXIS]; - -int neighbors[8][2] = { - {0,1}, {1,1}, {1,0}, {1,-1}, {0,-1}, {-1,-1}, {-1,0}, {-1,1} -}; - -/* -============ -LerpDrawVert -============ -*/ -void LerpDrawVert( drawVert_t *a, drawVert_t *b, drawVert_t *out ) { - out->xyz[0] = 0.5 * (a->xyz[0] + b->xyz[0]); - out->xyz[1] = 0.5 * (a->xyz[1] + b->xyz[1]); - out->xyz[2] = 0.5 * (a->xyz[2] + b->xyz[2]); - - out->st[0] = 0.5 * (a->st[0] + b->st[0]); - out->st[1] = 0.5 * (a->st[1] + b->st[1]); - - out->lightmap[0] = 0.5 * (a->lightmap[0] + b->lightmap[0]); - out->lightmap[1] = 0.5 * (a->lightmap[1] + b->lightmap[1]); - - out->color[0] = (a->color[0] + b->color[0]) >> 1; - out->color[1] = (a->color[1] + b->color[1]) >> 1; - out->color[2] = (a->color[2] + b->color[2]) >> 1; - out->color[3] = (a->color[3] + b->color[3]) >> 1; -} - - -void FreeMesh( mesh_t *m ) { - free( m->verts ); - free( m ); -} - -void PrintMesh( mesh_t *m ) { - int i, j; - - for ( i = 0 ; i < m->height ; i++ ) { - for ( j = 0 ; j < m->width ; j++ ) { - _printf("(%5.2f %5.2f %5.2f) " - , m->verts[i*m->width+j].xyz[0] - , m->verts[i*m->width+j].xyz[1] - , m->verts[i*m->width+j].xyz[2] ); - } - _printf("\n"); - } -} - - -mesh_t *CopyMesh( mesh_t *mesh ) { - mesh_t *out; - int size; - - out = malloc( sizeof( *out ) ); - out->width = mesh->width; - out->height = mesh->height; - - size = out->width * out->height * sizeof( *out->verts ); - out->verts = malloc( size ); - memcpy( out->verts, mesh->verts, size ); - - return out; -} - - -/* -================= -TransposeMesh - -Returns a transposed copy of the mesh, freeing the original -================= -*/ -mesh_t *TransposeMesh( mesh_t *in ) { - int w, h; - mesh_t *out; - - out = malloc( sizeof( *out ) ); - out->width = in->height; - out->height = in->width; - out->verts = malloc( out->width * out->height * sizeof( drawVert_t ) ); - - for ( h = 0 ; h < in->height ; h++ ) { - for ( w = 0 ; w < in->width ; w++ ) { - out->verts[ w * in->height + h ] = in->verts[ h * in->width + w ]; - } - } - - FreeMesh( in ); - - return out; -} - -void InvertMesh( mesh_t *in ) { - int w, h; - drawVert_t temp; - - for ( h = 0 ; h < in->height ; h++ ) { - for ( w = 0 ; w < in->width / 2 ; w++ ) { - temp = in->verts[ h * in->width + w ]; - in->verts[ h * in->width + w ] = in->verts[ h * in->width + in->width - 1 - w ]; - in->verts[ h * in->width + in->width - 1 - w ] = temp; - } - } -} - -/* -================= -MakeMeshNormals - -================= -*/ -void MakeMeshNormals( mesh_t in ) { - int i, j, k, dist; - vec3_t normal; - vec3_t sum; - int count; - vec3_t base; - vec3_t delta; - int x, y; - drawVert_t *dv; - vec3_t around[8], temp; - qboolean good[8]; - qboolean wrapWidth, wrapHeight; - float len; - - wrapWidth = qfalse; - for ( i = 0 ; i < in.height ; i++ ) { - VectorSubtract( in.verts[i*in.width].xyz, - in.verts[i*in.width+in.width-1].xyz, delta ); - len = VectorLength( delta ); - if ( len > 1.0 ) { - break; - } - } - if ( i == in.height ) { - wrapWidth = qtrue; - } - - wrapHeight = qfalse; - for ( i = 0 ; i < in.width ; i++ ) { - VectorSubtract( in.verts[i].xyz, - in.verts[i + (in.height-1)*in.width].xyz, delta ); - len = VectorLength( delta ); - if ( len > 1.0 ) { - break; - } - } - if ( i == in.width) { - wrapHeight = qtrue; - } - - - for ( i = 0 ; i < in.width ; i++ ) { - for ( j = 0 ; j < in.height ; j++ ) { - count = 0; - dv = &in.verts[j*in.width+i]; - VectorCopy( dv->xyz, base ); - for ( k = 0 ; k < 8 ; k++ ) { - VectorClear( around[k] ); - good[k] = qfalse; - - for ( dist = 1 ; dist <= 3 ; dist++ ) { - x = i + neighbors[k][0] * dist; - y = j + neighbors[k][1] * dist; - if ( wrapWidth ) { - if ( x < 0 ) { - x = in.width - 1 + x; - } else if ( x >= in.width ) { - x = 1 + x - in.width; - } - } - if ( wrapHeight ) { - if ( y < 0 ) { - y = in.height - 1 + y; - } else if ( y >= in.height ) { - y = 1 + y - in.height; - } - } - - if ( x < 0 || x >= in.width || y < 0 || y >= in.height ) { - break; // edge of patch - } - VectorSubtract( in.verts[y*in.width+x].xyz, base, temp ); - if ( VectorNormalize( temp, temp ) == 0 ) { - continue; // degenerate edge, get more dist - } else { - good[k] = qtrue; - VectorCopy( temp, around[k] ); - break; // good edge - } - } - } - - VectorClear( sum ); - for ( k = 0 ; k < 8 ; k++ ) { - if ( !good[k] || !good[(k+1)&7] ) { - continue; // didn't get two points - } - CrossProduct( around[(k+1)&7], around[k], normal ); - if ( VectorNormalize( normal, normal ) == 0 ) { - continue; - } - VectorAdd( normal, sum, sum ); - count++; - } - if ( count == 0 ) { -//_printf("bad normal\n"); - count = 1; - } - VectorNormalize( sum, dv->normal ); - } - } -} - -/* -================= -PutMeshOnCurve - -Drops the aproximating points onto the curve -================= -*/ -void PutMeshOnCurve( mesh_t in ) { - int i, j, l; - float prev, next; - - // put all the aproximating points on the curve - for ( i = 0 ; i < in.width ; i++ ) { - for ( j = 1 ; j < in.height ; j += 2 ) { - for ( l = 0 ; l < 3 ; l++ ) { - prev = ( in.verts[j*in.width+i].xyz[l] + in.verts[(j+1)*in.width+i].xyz[l] ) * 0.5; - next = ( in.verts[j*in.width+i].xyz[l] + in.verts[(j-1)*in.width+i].xyz[l] ) * 0.5; - in.verts[j*in.width+i].xyz[l] = ( prev + next ) * 0.5; - } - } - } - - for ( j = 0 ; j < in.height ; j++ ) { - for ( i = 1 ; i < in.width ; i += 2 ) { - for ( l = 0 ; l < 3 ; l++ ) { - prev = ( in.verts[j*in.width+i].xyz[l] + in.verts[j*in.width+i+1].xyz[l] ) * 0.5; - next = ( in.verts[j*in.width+i].xyz[l] + in.verts[j*in.width+i-1].xyz[l] ) * 0.5; - in.verts[j*in.width+i].xyz[l] = ( prev + next ) * 0.5; - } - } - } -} - - -/* -================= -SubdivideMesh - -================= -*/ -mesh_t *SubdivideMesh( mesh_t in, float maxError, float minLength ) { - int i, j, k, l; - drawVert_t prev, next, mid; - vec3_t prevxyz, nextxyz, midxyz; - vec3_t delta; - float len; - mesh_t out; - drawVert_t expand[MAX_EXPANDED_AXIS][MAX_EXPANDED_AXIS]; - - out.width = in.width; - out.height = in.height; - - for ( i = 0 ; i < in.width ; i++ ) { - for ( j = 0 ; j < in.height ; j++ ) { - expand[j][i] = in.verts[j*in.width+i]; - } - } - - for ( i = 0 ; i < in.height ; i++ ) { - originalHeights[i] = i; - } - for ( i = 0 ; i < in.width ; i++ ) { - originalWidths[i] = i; - } - - // horizontal subdivisions - for ( j = 0 ; j + 2 < out.width ; j += 2 ) { - // check subdivided midpoints against control points - for ( i = 0 ; i < out.height ; i++ ) { - for ( l = 0 ; l < 3 ; l++ ) { - prevxyz[l] = expand[i][j+1].xyz[l] - expand[i][j].xyz[l]; - nextxyz[l] = expand[i][j+2].xyz[l] - expand[i][j+1].xyz[l]; - midxyz[l] = (expand[i][j].xyz[l] + expand[i][j+1].xyz[l] * 2 - + expand[i][j+2].xyz[l] ) * 0.25; - } - - // if the span length is too long, force a subdivision - if ( VectorLength( prevxyz ) > minLength - || VectorLength( nextxyz ) > minLength ) { - break; - } - - // see if this midpoint is off far enough to subdivide - VectorSubtract( expand[i][j+1].xyz, midxyz, delta ); - len = VectorLength( delta ); - if ( len > maxError ) { - break; - } - } - - if ( out.width + 2 >= MAX_EXPANDED_AXIS ) { - break; // can't subdivide any more - } - - if ( i == out.height ) { - continue; // didn't need subdivision - } - - // insert two columns and replace the peak - out.width += 2; - - for ( k = out.width - 1 ; k > j + 3 ; k-- ) { - originalWidths[k] = originalWidths[k-2]; - } - originalWidths[j+3] = originalWidths[j+1]; - originalWidths[j+2] = originalWidths[j+1]; - originalWidths[j+1] = originalWidths[j]; - - for ( i = 0 ; i < out.height ; i++ ) { - LerpDrawVert( &expand[i][j], &expand[i][j+1], &prev ); - LerpDrawVert( &expand[i][j+1], &expand[i][j+2], &next ); - LerpDrawVert( &prev, &next, &mid ); - - for ( k = out.width - 1 ; k > j + 3 ; k-- ) { - expand[i][k] = expand[i][k-2]; - } - expand[i][j + 1] = prev; - expand[i][j + 2] = mid; - expand[i][j + 3] = next; - } - - // back up and recheck this set again, it may need more subdivision - j -= 2; - - } - - // vertical subdivisions - for ( j = 0 ; j + 2 < out.height ; j += 2 ) { - // check subdivided midpoints against control points - for ( i = 0 ; i < out.width ; i++ ) { - for ( l = 0 ; l < 3 ; l++ ) { - prevxyz[l] = expand[j+1][i].xyz[l] - expand[j][i].xyz[l]; - nextxyz[l] = expand[j+2][i].xyz[l] - expand[j+1][i].xyz[l]; - midxyz[l] = (expand[j][i].xyz[l] + expand[j+1][i].xyz[l] * 2 - + expand[j+2][i].xyz[l] ) * 0.25; - } - - // if the span length is too long, force a subdivision - if ( VectorLength( prevxyz ) > minLength - || VectorLength( nextxyz ) > minLength ) { - break; - } - // see if this midpoint is off far enough to subdivide - VectorSubtract( expand[j+1][i].xyz, midxyz, delta ); - len = VectorLength( delta ); - if ( len > maxError ) { - break; - } - } - - if ( out.height + 2 >= MAX_EXPANDED_AXIS ) { - break; // can't subdivide any more - } - - if ( i == out.width ) { - continue; // didn't need subdivision - } - - // insert two columns and replace the peak - out.height += 2; - - for ( k = out.height - 1 ; k > j + 3 ; k-- ) { - originalHeights[k] = originalHeights[k-2]; - } - originalHeights[j+3] = originalHeights[j+1]; - originalHeights[j+2] = originalHeights[j+1]; - originalHeights[j+1] = originalHeights[j]; - - for ( i = 0 ; i < out.width ; i++ ) { - LerpDrawVert( &expand[j][i], &expand[j+1][i], &prev ); - LerpDrawVert( &expand[j+1][i], &expand[j+2][i], &next ); - LerpDrawVert( &prev, &next, &mid ); - - for ( k = out.height - 1 ; k > j + 3 ; k-- ) { - expand[k][i] = expand[k-2][i]; - } - expand[j+1][i] = prev; - expand[j+2][i] = mid; - expand[j+3][i] = next; - } - - // back up and recheck this set again, it may need more subdivision - j -= 2; - - } - - // collapse the verts - - out.verts = &expand[0][0]; - for ( i = 1 ; i < out.height ; i++ ) { - memmove( &out.verts[i*out.width], expand[i], out.width * sizeof(drawVert_t) ); - } - - return CopyMesh(&out); -} - -/* -================ -ProjectPointOntoVector -================ -*/ -void ProjectPointOntoVector( vec3_t point, vec3_t vStart, vec3_t vEnd, vec3_t vProj ) -{ - vec3_t pVec, vec; - - VectorSubtract( point, vStart, pVec ); - VectorSubtract( vEnd, vStart, vec ); - VectorNormalize( vec, vec ); - // project onto the directional vector for this segment - VectorMA( vStart, DotProduct( pVec, vec ), vec, vProj ); -} - -/* -================ -RemoveLinearMeshColumsRows -================ -*/ -mesh_t *RemoveLinearMeshColumnsRows( mesh_t *in ) { - int i, j, k; - float len, maxLength; - vec3_t proj, dir; - mesh_t out; - drawVert_t expand[MAX_EXPANDED_AXIS][MAX_EXPANDED_AXIS]; - - out.width = in->width; - out.height = in->height; - - for ( i = 0 ; i < in->width ; i++ ) { - for ( j = 0 ; j < in->height ; j++ ) { - expand[j][i] = in->verts[j*in->width+i]; - } - } - - for ( j = 1 ; j < out.width - 1; j++ ) { - maxLength = 0; - for ( i = 0 ; i < out.height ; i++ ) { - ProjectPointOntoVector(expand[i][j].xyz, expand[i][j-1].xyz, expand[i][j+1].xyz, proj); - VectorSubtract(expand[i][j].xyz, proj, dir); - len = VectorLength(dir); - if (len > maxLength) { - maxLength = len; - } - } - if (maxLength < 0.1) - { - out.width--; - for ( i = 0 ; i < out.height ; i++ ) { - for (k = j; k < out.width; k++) { - expand[i][k] = expand[i][k+1]; - } - } - for (k = j; k < out.width; k++) { - originalWidths[k] = originalWidths[k+1]; - } - j--; - } - } - for ( j = 1 ; j < out.height - 1; j++ ) { - maxLength = 0; - for ( i = 0 ; i < out.width ; i++ ) { - ProjectPointOntoVector(expand[j][i].xyz, expand[j-1][i].xyz, expand[j+1][i].xyz, proj); - VectorSubtract(expand[j][i].xyz, proj, dir); - len = VectorLength(dir); - if (len > maxLength) { - maxLength = len; - } - } - if (maxLength < 0.1) - { - out.height--; - for ( i = 0 ; i < out.width ; i++ ) { - for (k = j; k < out.height; k++) { - expand[k][i] = expand[k+1][i]; - } - } - for (k = j; k < out.height; k++) { - originalHeights[k] = originalHeights[k+1]; - } - j--; - } - } - // collapse the verts - out.verts = &expand[0][0]; - for ( i = 1 ; i < out.height ; i++ ) { - memmove( &out.verts[i*out.width], expand[i], out.width * sizeof(drawVert_t) ); - } - - return CopyMesh(&out); -} - -/* -============ -LerpDrawVertAmount -============ -*/ -void LerpDrawVertAmount( drawVert_t *a, drawVert_t *b, float amount, drawVert_t *out ) { - out->xyz[0] = a->xyz[0] + amount * (b->xyz[0] - a->xyz[0]); - out->xyz[1] = a->xyz[1] + amount * (b->xyz[1] - a->xyz[1]); - out->xyz[2] = a->xyz[2] + amount * (b->xyz[2] - a->xyz[2]); - - out->st[0] = a->st[0] + amount * (b->st[0] - a->st[0]); - out->st[1] = a->st[1] + amount * (b->st[1] - a->st[1]); - - out->lightmap[0] = a->lightmap[0] + amount * (b->lightmap[0] - a->lightmap[0]); - out->lightmap[1] = a->lightmap[1] + amount * (b->lightmap[1] - a->lightmap[1]); - - out->color[0] = a->color[0] + amount * (b->color[0] - a->color[0]); - out->color[1] = a->color[1] + amount * (b->color[1] - a->color[1]); - out->color[2] = a->color[2] + amount * (b->color[2] - a->color[2]); - out->color[3] = a->color[3] + amount * (b->color[3] - a->color[3]); - - out->normal[0] = a->normal[0] + amount * (b->normal[0] - a->normal[0]); - out->normal[1] = a->normal[1] + amount * (b->normal[1] - a->normal[1]); - out->normal[2] = a->normal[2] + amount * (b->normal[2] - a->normal[2]); - VectorNormalize(out->normal, out->normal); -} - -/* -================= -SubdivideMeshQuads -================= -*/ -mesh_t *SubdivideMeshQuads( mesh_t *in, float minLength, int maxsize, int widthtable[], int heighttable[]) { - int i, j, k, w, h, maxsubdivisions, subdivisions; - vec3_t dir; - float length, maxLength, amount; - mesh_t out; - drawVert_t expand[MAX_EXPANDED_AXIS][MAX_EXPANDED_AXIS]; - - out.width = in->width; - out.height = in->height; - - for ( i = 0 ; i < in->width ; i++ ) { - for ( j = 0 ; j < in->height ; j++ ) { - expand[j][i] = in->verts[j*in->width+i]; - } - } - - if (maxsize > MAX_EXPANDED_AXIS) - Error("SubdivideMeshQuads: maxsize > MAX_EXPANDED_AXIS"); - - // horizontal subdivisions - - maxsubdivisions = (maxsize - in->width) / (in->width - 1); - - for ( w = 0, j = 0 ; w < in->width - 1; w++, j += subdivisions + 1) { - maxLength = 0; - for ( i = 0 ; i < out.height ; i++ ) { - VectorSubtract(expand[i][j+1].xyz, expand[i][j].xyz, dir); - length = VectorLength( dir ); - if (length > maxLength) { - maxLength = length; - } - } - - subdivisions = (int) (maxLength / minLength); - if (subdivisions > maxsubdivisions) - subdivisions = maxsubdivisions; - - widthtable[w] = subdivisions + 1; - if (subdivisions <= 0) - continue; - - out.width += subdivisions; - - for ( k = out.width - 1; k >= j + subdivisions; k-- ) { - originalWidths[k] = originalWidths[k-subdivisions]; - } - for (k = 1; k <= subdivisions; k++) { - originalWidths[j+k] = originalWidths[j]; - } - - for ( i = 0 ; i < out.height ; i++ ) { - for ( k = out.width - 1 ; k > j + subdivisions; k-- ) { - expand[i][k] = expand[i][k-subdivisions]; - } - for (k = 1; k <= subdivisions; k++) - { - amount = (float) k / (subdivisions + 1); - LerpDrawVertAmount(&expand[i][j], &expand[i][j+subdivisions+1], amount, &expand[i][j+k]); - } - } - } - - maxsubdivisions = (maxsize - in->height) / (in->height - 1); - - for ( h = 0, j = 0 ; h < in->height - 1; h++, j += subdivisions + 1) { - maxLength = 0; - for ( i = 0 ; i < out.width ; i++ ) { - VectorSubtract(expand[j+1][i].xyz, expand[j][i].xyz, dir); - length = VectorLength( dir ); - if (length > maxLength) { - maxLength = length; - } - } - - subdivisions = (int) (maxLength / minLength); - if (subdivisions > maxsubdivisions) - subdivisions = maxsubdivisions; - - heighttable[h] = subdivisions + 1; - if (subdivisions <= 0) - continue; - - out.height += subdivisions; - - for ( k = out.height - 1; k >= j + subdivisions; k-- ) { - originalHeights[k] = originalHeights[k-subdivisions]; - } - for (k = 1; k <= subdivisions; k++) { - originalHeights[j+k] = originalHeights[j]; - } - - for ( i = 0 ; i < out.width ; i++ ) { - for ( k = out.height - 1 ; k > j + subdivisions; k-- ) { - expand[k][i] = expand[k-subdivisions][i]; - } - for (k = 1; k <= subdivisions; k++) - { - amount = (float) k / (subdivisions + 1); - LerpDrawVertAmount(&expand[j][i], &expand[j+subdivisions+1][i], amount, &expand[j+k][i]); - } - } - } - - // collapse the verts - out.verts = &expand[0][0]; - for ( i = 1 ; i < out.height ; i++ ) { - memmove( &out.verts[i*out.width], expand[i], out.width * sizeof(drawVert_t) ); - } - - return CopyMesh(&out); -} diff --git a/q3map/mesh.h b/q3map/mesh.h deleted file mode 100644 index ee338d4..0000000 --- a/q3map/mesh.h +++ /dev/null @@ -1,48 +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 -=========================================================================== -*/ - -// mesh.h - - -typedef struct { - int width, height; - drawVert_t *verts; -} mesh_t; - -#define MAX_EXPANDED_AXIS 128 - -extern int originalWidths[MAX_EXPANDED_AXIS]; -extern int originalHeights[MAX_EXPANDED_AXIS]; - -void FreeMesh( mesh_t *m ); -mesh_t *CopyMesh( mesh_t *mesh ); -void PrintMesh( mesh_t *m ); -mesh_t *TransposeMesh( mesh_t *in ); -void InvertMesh( mesh_t *m ); -mesh_t *SubdivideMesh( mesh_t in, float maxError, float minLength ); -mesh_t *SubdivideMeshQuads( mesh_t *in, float minLength, int maxsize, int widthtable[], int heighttable[]); -mesh_t *RemoveLinearMeshColumnsRows( mesh_t *in ); -void MakeMeshNormals( mesh_t in ); -void PutMeshOnCurve( mesh_t in ); - - -void MakeNormalVectors (vec3_t forward, vec3_t right, vec3_t up); diff --git a/q3map/misc_model.c b/q3map/misc_model.c deleted file mode 100644 index cd003d6..0000000 --- a/q3map/misc_model.c +++ /dev/null @@ -1,472 +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" -#include "aselib.h" -#ifdef _WIN32 -#ifdef _TTIMOBUILD -#include "pakstuff.h" -#else -#include "../libs/pakstuff.h" -#endif -#endif - - -typedef struct { - char modelName[1024]; - md3Header_t *header; -} loadedModel_t; - -int c_triangleModels; -int c_triangleSurfaces; -int c_triangleVertexes; -int c_triangleIndexes; - - -#define MAX_LOADED_MODELS 1024 -loadedModel_t loadedModels[MAX_LOADED_MODELS]; -int numLoadedModels; - -/* -================= -R_LoadMD3 -================= -*/ -#define LL(x) x=LittleLong(x) -md3Header_t *R_LoadMD3( const char *mod_name ) { - int i, j; - md3Header_t *md3; - md3Frame_t *frame; - md3Surface_t *surf; - md3Triangle_t *tri; - md3St_t *st; - md3XyzNormal_t *xyz; - int version; - char filename[1024]; - int len; - - sprintf( filename, "%s%s", gamedir, mod_name ); - len = TryLoadFile( filename, (void **)&md3 ); -#ifdef _WIN32 - if ( len <= 0 ) { - len = PakLoadAnyFile(filename, (void **)&md3); - } -#endif - if ( len <= 0 ) { - return NULL; - } - - version = LittleLong (md3->version); - if (version != MD3_VERSION) { - _printf( "R_LoadMD3: %s has wrong version (%i should be %i)\n", - mod_name, version, MD3_VERSION); - return NULL; - } - - LL(md3->ident); - LL(md3->version); - LL(md3->numFrames); - LL(md3->numTags); - LL(md3->numSurfaces); - LL(md3->numSkins); - LL(md3->ofsFrames); - LL(md3->ofsTags); - LL(md3->ofsSurfaces); - LL(md3->ofsEnd); - - if ( md3->numFrames < 1 ) { - _printf( "R_LoadMD3: %s has no frames\n", mod_name ); - return NULL; - } - - // we don't need to swap tags in the renderer, they aren't used - - // swap all the frames - frame = (md3Frame_t *) ( (byte *)md3 + md3->ofsFrames ); - for ( i = 0 ; i < md3->numFrames ; i++, frame++) { - frame->radius = LittleFloat( frame->radius ); - for ( j = 0 ; j < 3 ; j++ ) { - frame->bounds[0][j] = LittleFloat( frame->bounds[0][j] ); - frame->bounds[1][j] = LittleFloat( frame->bounds[1][j] ); - frame->localOrigin[j] = LittleFloat( frame->localOrigin[j] ); - } - } - - // swap all the surfaces - surf = (md3Surface_t *) ( (byte *)md3 + md3->ofsSurfaces ); - for ( i = 0 ; i < md3->numSurfaces ; i++) { - - LL(surf->ident); - LL(surf->flags); - LL(surf->numFrames); - LL(surf->numShaders); - LL(surf->numTriangles); - LL(surf->ofsTriangles); - LL(surf->numVerts); - LL(surf->ofsShaders); - LL(surf->ofsSt); - LL(surf->ofsXyzNormals); - LL(surf->ofsEnd); - - if ( surf->numVerts > SHADER_MAX_VERTEXES ) { - Error ("R_LoadMD3: %s has more than %i verts on a surface (%i)", - mod_name, SHADER_MAX_VERTEXES, surf->numVerts ); - } - if ( surf->numTriangles*3 > SHADER_MAX_INDEXES ) { - Error ("R_LoadMD3: %s has more than %i triangles on a surface (%i)", - mod_name, SHADER_MAX_INDEXES / 3, surf->numTriangles ); - } - - // swap all the triangles - tri = (md3Triangle_t *) ( (byte *)surf + surf->ofsTriangles ); - for ( j = 0 ; j < surf->numTriangles ; j++, tri++ ) { - LL(tri->indexes[0]); - LL(tri->indexes[1]); - LL(tri->indexes[2]); - } - - // swap all the ST - st = (md3St_t *) ( (byte *)surf + surf->ofsSt ); - for ( j = 0 ; j < surf->numVerts ; j++, st++ ) { - st->st[0] = LittleFloat( st->st[0] ); - st->st[1] = LittleFloat( st->st[1] ); - } - - // swap all the XyzNormals - xyz = (md3XyzNormal_t *) ( (byte *)surf + surf->ofsXyzNormals ); - for ( j = 0 ; j < surf->numVerts * surf->numFrames ; j++, xyz++ ) - { - xyz->xyz[0] = LittleShort( xyz->xyz[0] ); - xyz->xyz[1] = LittleShort( xyz->xyz[1] ); - xyz->xyz[2] = LittleShort( xyz->xyz[2] ); - - xyz->normal = LittleShort( xyz->normal ); - } - - - // find the next surface - surf = (md3Surface_t *)( (byte *)surf + surf->ofsEnd ); - } - - return md3; -} - - -/* -================ -LoadModel -================ -*/ -md3Header_t *LoadModel( const char *modelName ) { - int i; - loadedModel_t *lm; - - // see if we already have it loaded - for ( i = 0, lm = loadedModels ; i < numLoadedModels ; i++, lm++ ) { - if ( !strcmp( modelName, lm->modelName ) ) { - return lm->header; - } - } - - // load it - if ( numLoadedModels == MAX_LOADED_MODELS ) { - Error( "MAX_LOADED_MODELS" ); - } - numLoadedModels++; - - strcpy( lm->modelName, modelName ); - - lm->header = R_LoadMD3( modelName ); - - return lm->header; -} - -/* -============ -InsertMD3Model - -Convert a model entity to raw geometry surfaces and insert it in the tree -============ -*/ -void InsertMD3Model( const char *modelName, vec3_t origin, float angle, tree_t *tree ) { - int i, j; - md3Header_t *md3; - md3Surface_t *surf; - md3Shader_t *shader; - md3Triangle_t *tri; - md3St_t *st; - md3XyzNormal_t *xyz; - drawVert_t *outv; - float lat, lng; - float angleCos, angleSin; - mapDrawSurface_t *out; - vec3_t temp; - - angle = angle / 180 * Q_PI; - angleCos = cos( angle ); - angleSin = sin( angle ); - - // load the model - md3 = LoadModel( modelName ); - if ( !md3 ) { - return; - } - - // each md3 surface will become a new bsp surface - - c_triangleModels++; - c_triangleSurfaces += md3->numSurfaces; - - // expand, translate, and rotate the vertexes - // swap all the surfaces - surf = (md3Surface_t *) ( (byte *)md3 + md3->ofsSurfaces ); - for ( i = 0 ; i < md3->numSurfaces ; i++) { - // allocate a surface - out = AllocDrawSurf(); - out->miscModel = qtrue; - - shader = (md3Shader_t *) ( (byte *)surf + surf->ofsShaders ); - - out->shaderInfo = ShaderInfoForShader( shader->name ); - - out->numVerts = surf->numVerts; - out->verts = malloc( out->numVerts * sizeof( out->verts[0] ) ); - - out->numIndexes = surf->numTriangles * 3; - out->indexes = malloc( out->numIndexes * sizeof( out->indexes[0] ) ); - - out->lightmapNum = -1; - out->fogNum = -1; - - // emit the indexes - c_triangleIndexes += surf->numTriangles * 3; - tri = (md3Triangle_t *) ( (byte *)surf + surf->ofsTriangles ); - for ( j = 0 ; j < surf->numTriangles ; j++, tri++ ) { - out->indexes[j*3+0] = tri->indexes[0]; - out->indexes[j*3+1] = tri->indexes[1]; - out->indexes[j*3+2] = tri->indexes[2]; - } - - // emit the vertexes - st = (md3St_t *) ( (byte *)surf + surf->ofsSt ); - xyz = (md3XyzNormal_t *) ( (byte *)surf + surf->ofsXyzNormals ); - - c_triangleVertexes += surf->numVerts; - for ( j = 0 ; j < surf->numVerts ; j++, st++, xyz++ ) { - outv = &out->verts[ j ]; - - outv->st[0] = st->st[0]; - outv->st[1] = st->st[1]; - - outv->lightmap[0] = 0; - outv->lightmap[1] = 0; - - // the colors will be set by the lighting pass - outv->color[0] = 255; - outv->color[1] = 255; - outv->color[2] = 255; - outv->color[3] = 255; - - outv->xyz[0] = origin[0] + MD3_XYZ_SCALE * ( xyz->xyz[0] * angleCos - xyz->xyz[1] * angleSin ); - outv->xyz[1] = origin[1] + MD3_XYZ_SCALE * ( xyz->xyz[0] * angleSin + xyz->xyz[1] * angleCos ); - outv->xyz[2] = origin[2] + MD3_XYZ_SCALE * ( xyz->xyz[2] ); - - // decode the lat/lng normal to a 3 float normal - lat = ( xyz->normal >> 8 ) & 0xff; - lng = ( xyz->normal & 0xff ); - lat *= Q_PI/128; - lng *= Q_PI/128; - - temp[0] = cos(lat) * sin(lng); - temp[1] = sin(lat) * sin(lng); - temp[2] = cos(lng); - - // rotate the normal - outv->normal[0] = temp[0] * angleCos - temp[1] * angleSin; - outv->normal[1] = temp[0] * angleSin + temp[1] * angleCos; - outv->normal[2] = temp[2]; - } - - // find the next surface - surf = (md3Surface_t *)( (byte *)surf + surf->ofsEnd ); - } - -} - -//============================================================================== - - -/* -============ -InsertASEModel - -Convert a model entity to raw geometry surfaces and insert it in the tree -============ -*/ -void InsertASEModel( const char *modelName, vec3_t origin, float angle, tree_t *tree ) { - int i, j; - drawVert_t *outv; - float angleCos, angleSin; - mapDrawSurface_t *out; - int numSurfaces; - const char *name; - polyset_t *pset; - int numFrames; - char filename[1024]; - - sprintf( filename, "%s%s", gamedir, modelName ); - - angle = angle / 180 * Q_PI; - angleCos = cos( angle ); - angleSin = sin( angle ); - - // load the model - ASE_Load( filename, qfalse, qfalse ); - - // each ase surface will become a new bsp surface - numSurfaces = ASE_GetNumSurfaces(); - - c_triangleModels++; - c_triangleSurfaces += numSurfaces; - - // expand, translate, and rotate the vertexes - // swap all the surfaces - for ( i = 0 ; i < numSurfaces ; i++) { - name = ASE_GetSurfaceName( i ); - - pset = ASE_GetSurfaceAnimation( i, &numFrames, -1, -1, -1 ); - if ( !name || !pset ) { - continue; - } - - // allocate a surface - out = AllocDrawSurf(); - out->miscModel = qtrue; - - out->shaderInfo = ShaderInfoForShader( pset->materialname ); - - out->numVerts = 3 * pset->numtriangles; - out->verts = malloc( out->numVerts * sizeof( out->verts[0] ) ); - - out->numIndexes = 3 * pset->numtriangles; - out->indexes = malloc( out->numIndexes * sizeof( out->indexes[0] ) ); - - out->lightmapNum = -1; - out->fogNum = -1; - - // emit the indexes - c_triangleIndexes += out->numIndexes; - for ( j = 0 ; j < out->numIndexes ; j++ ) { - out->indexes[j] = j; - } - - // emit the vertexes - c_triangleVertexes += out->numVerts; - for ( j = 0 ; j < out->numVerts ; j++ ) { - int index; - triangle_t *tri; - - index = j % 3; - tri = &pset->triangles[ j / 3 ]; - - outv = &out->verts[ j ]; - - outv->st[0] = tri->texcoords[index][0]; - outv->st[1] = tri->texcoords[index][1]; - - outv->lightmap[0] = 0; - outv->lightmap[1] = 0; - - // the colors will be set by the lighting pass - outv->color[0] = 255; - outv->color[1] = 255; - outv->color[2] = 255; - outv->color[3] = 255; - - outv->xyz[0] = origin[0] + tri->verts[index][0]; - outv->xyz[1] = origin[1] + tri->verts[index][1]; - outv->xyz[2] = origin[2] + tri->verts[index][2]; - - // rotate the normal - outv->normal[0] = tri->normals[index][0]; - outv->normal[1] = tri->normals[index][1]; - outv->normal[2] = tri->normals[index][2]; - } - } - -} - - -//============================================================================== - - - -/* -===================== -AddTriangleModels -===================== -*/ -void AddTriangleModels( tree_t *tree ) { - int entity_num; - entity_t *entity; - - qprintf("----- AddTriangleModels -----\n"); - - for ( entity_num=1 ; entity_num< num_entities ; entity_num++ ) { - entity = &entities[entity_num]; - - // convert misc_models into raw geometry - if ( !Q_stricmp( "misc_model", ValueForKey( entity, "classname" ) ) ) { - const char *model; - vec3_t origin; - float angle; - - // get the angle for rotation FIXME: support full matrix positioning - angle = FloatForKey( entity, "angle" ); - - GetVectorForKey( entity, "origin", origin ); - - model = ValueForKey( entity, "model" ); - if ( !model[0] ) { - _printf("WARNING: misc_model at %i %i %i without a model key\n", (int)origin[0], - (int)origin[1], (int)origin[2] ); - continue; - } - if ( strstr( model, ".md3" ) || strstr( model, ".MD3" ) ) { - InsertMD3Model( model, origin, angle, tree ); - continue; - } - if ( strstr( model, ".ase" ) || strstr( model, ".ASE" ) ) { - InsertASEModel( model, origin, angle, tree ); - continue; - } - _printf( "Unknown misc_model type: %s\n", model ); - continue; - } - } - - qprintf( "%5i triangle models\n", c_triangleModels ); - qprintf( "%5i triangle surfaces\n", c_triangleSurfaces ); - qprintf( "%5i triangle vertexes\n", c_triangleVertexes ); - qprintf( "%5i triangle indexes\n", c_triangleIndexes ); -} - diff --git a/q3map/nodraw.c b/q3map/nodraw.c deleted file mode 100644 index 7503a48..0000000 --- a/q3map/nodraw.c +++ /dev/null @@ -1,47 +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" - -vec3_t draw_mins, draw_maxs; -qboolean drawflag; - -void Draw_ClearWindow (void) -{ -} - -//============================================================ - -#define GLSERV_PORT 25001 - - -void GLS_BeginScene (void) -{ -} - -void GLS_Winding (winding_t *w, int code) -{ -} - -void GLS_EndScene (void) -{ -} diff --git a/q3map/patch.c b/q3map/patch.c deleted file mode 100644 index df461d6..0000000 --- a/q3map/patch.c +++ /dev/null @@ -1,286 +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" - - -void PrintCtrl( vec3_t ctrl[9] ) { - int i, j; - - for ( i = 0 ; i < 3 ; i++ ) { - for ( j = 0 ; j < 3 ; j++ ) { - _printf("(%5.2f %5.2f %5.2f) ", ctrl[i*3+j][0], ctrl[i*3+j][1], ctrl[i*3+j][2] ); - } - _printf("\n"); - } -} - -/* -================ -DrawSurfaceForMesh -================ -*/ -mapDrawSurface_t *DrawSurfaceForMesh( mesh_t *m ) { - mapDrawSurface_t *ds; - int i, j; - mesh_t *copy; - - // to make valid normals for patches with degenerate edges, - // we need to make a copy of the mesh and put the aproximating - // points onto the curve - copy = CopyMesh( m ); - PutMeshOnCurve( *copy ); - MakeMeshNormals( *copy ); - for ( j = 0 ; j < m->width ; j++ ) { - for ( i = 0 ; i < m->height ; i++ ) { - VectorCopy( copy->verts[i*m->width+j].normal, m->verts[i*m->width+j].normal ); - } - } - FreeMesh( copy ); - - ds = AllocDrawSurf(); - ds->mapBrush = NULL; - ds->side = NULL; - - ds->patch = qtrue; - ds->patchWidth = m->width; - ds->patchHeight = m->height; - ds->numVerts = ds->patchWidth * ds->patchHeight; - ds->verts = malloc( ds->numVerts * sizeof( *ds->verts ) ); - memcpy( ds->verts, m->verts, ds->numVerts * sizeof( *ds->verts ) ); - - ds->lightmapNum = -1; - ds->fogNum = -1; - - return ds; -} - -/* -================= -ParsePatch - -Creates a mapDrawSurface_t from the patch text -================= -*/ -void ParsePatch( void ) { - vec_t info[5]; - int i, j; - parseMesh_t *pm; - char texture[MAX_QPATH]; - char shader[MAX_QPATH]; - mesh_t m; - drawVert_t *verts; - epair_t *ep; - - MatchToken( "{" ); - - // get texture - GetToken (qtrue); - strcpy( texture, token ); - - // save the shader name for retexturing - if ( numMapIndexedShaders == MAX_MAP_BRUSHSIDES ) { - Error( "MAX_MAP_BRUSHSIDES" ); - } - strcpy( mapIndexedShaders[numMapIndexedShaders], texture ); - numMapIndexedShaders++; - - - Parse1DMatrix( 5, info ); - m.width = info[0]; - m.height = info[1]; - m.verts = verts = malloc( m.width * m.height * sizeof( m.verts[0] ) ); - - if ( m.width < 0 || m.width > MAX_PATCH_SIZE - || m.height < 0 || m.height > MAX_PATCH_SIZE ) { - Error("ParsePatch: bad size"); - } - - MatchToken( "(" ); - for ( j = 0 ; j < m.width ; j++ ) { - MatchToken( "(" ); - for ( i = 0 ; i < m.height ; i++ ) { - Parse1DMatrix( 5, verts[i*m.width+j].xyz ); - } - MatchToken( ")" ); - } - MatchToken( ")" ); - - // if brush primitives format, we may have some epairs to ignore here - GetToken(qtrue); - if (g_bBrushPrimit!=BPRIMIT_OLDBRUSHES && strcmp(token,"}")) - { - // NOTE: we leak that! - ep = ParseEpair(); - } - else - UnGetToken(); - - MatchToken( "}" ); - MatchToken( "}" ); - - if ( noCurveBrushes ) { - return; - } - - // find default flags and values - pm = malloc( sizeof( *pm ) ); - memset( pm, 0, sizeof( *pm ) ); - - sprintf( shader, "textures/%s", texture ); - pm->shaderInfo = ShaderInfoForShader( shader ); - pm->mesh = m; - - // link to the entity - pm->next = mapent->patches; - mapent->patches = pm; -} - - -void GrowGroup_r( int patchNum, int patchCount, const byte *bordering, byte *group ) { - int i; - const byte *row; - - if ( group[patchNum] ) { - return; - } - group[patchNum] = 1; - row = bordering + patchNum * patchCount; - for ( i = 0 ; i < patchCount ; i++ ) { - if ( row[i] ) { - GrowGroup_r( i, patchCount, bordering, group ); - } - } -} - - -/* -===================== -PatchMapDrawSurfs - -Any patches that share an edge need to choose their -level of detail as a unit, otherwise the edges would -pull apart. -===================== -*/ -void PatchMapDrawSurfs( entity_t *e ) { - parseMesh_t *pm; - parseMesh_t *check, *scan; - mapDrawSurface_t *ds; - int patchCount, groupCount; - int i, j, k, l, c1, c2; - drawVert_t *v1, *v2; - vec3_t bounds[2]; - byte *bordering; - parseMesh_t *meshes[MAX_MAP_DRAW_SURFS]; - qboolean grouped[MAX_MAP_DRAW_SURFS]; - byte group[MAX_MAP_DRAW_SURFS]; - - qprintf( "----- PatchMapDrawSurfs -----\n" ); - - patchCount = 0; - for ( pm = e->patches ; pm ; pm = pm->next ) { - meshes[patchCount] = pm; - patchCount++; - } - - if ( !patchCount ) { - return; - } - bordering = malloc( patchCount * patchCount ); - memset( bordering, 0, patchCount * patchCount ); - - // build the bordering matrix - for ( k = 0 ; k < patchCount ; k++ ) { - bordering[k*patchCount+k] = 1; - - for ( l = k+1 ; l < patchCount ; l++ ) { - check = meshes[k]; - scan = meshes[l]; - c1 = scan->mesh.width * scan->mesh.height; - v1 = scan->mesh.verts; - - for ( i = 0 ; i < c1 ; i++, v1++ ) { - c2 = check->mesh.width * check->mesh.height; - v2 = check->mesh.verts; - for ( j = 0 ; j < c2 ; j++, v2++ ) { - if ( fabs( v1->xyz[0] - v2->xyz[0] ) < 1.0 - && fabs( v1->xyz[1] - v2->xyz[1] ) < 1.0 - && fabs( v1->xyz[2] - v2->xyz[2] ) < 1.0 ) { - break; - } - } - if ( j != c2 ) { - break; - } - } - if ( i != c1 ) { - // we have a connection - bordering[k*patchCount+l] = - bordering[l*patchCount+k] = 1; - } else { - // no connection - bordering[k*patchCount+l] = - bordering[l*patchCount+k] = 0; - } - - } - } - - // build groups - memset( grouped, 0, sizeof(grouped) ); - groupCount = 0; - for ( i = 0 ; i < patchCount ; i++ ) { - if ( !grouped[i] ) { - groupCount++; - } - - // recursively find all patches that belong in the same group - memset( group, 0, patchCount ); - GrowGroup_r( i, patchCount, bordering, group ); - - // bound them - ClearBounds( bounds[0], bounds[1] ); - for ( j = 0 ; j < patchCount ; j++ ) { - if ( group[j] ) { - grouped[j] = qtrue; - scan = meshes[j]; - c1 = scan->mesh.width * scan->mesh.height; - v1 = scan->mesh.verts; - for ( k = 0 ; k < c1 ; k++, v1++ ) { - AddPointToBounds( v1->xyz, bounds[0], bounds[1] ); - } - } - } - - // create drawsurf - scan = meshes[i]; - scan->grouped = qtrue; - ds = DrawSurfaceForMesh( &scan->mesh ); - ds->shaderInfo = scan->shaderInfo; - VectorCopy( bounds[0], ds->lightmapVecs[0] ); - VectorCopy( bounds[1], ds->lightmapVecs[1] ); - } - - qprintf( "%5i patches\n", patchCount ); - qprintf( "%5i patch LOD groups\n", groupCount ); -} - diff --git a/q3map/portals.c b/q3map/portals.c deleted file mode 100644 index 059760f..0000000 --- a/q3map/portals.c +++ /dev/null @@ -1,843 +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_active_portals; -int c_peak_portals; -int c_boundary; -int c_boundary_sides; - -/* -=========== -AllocPortal -=========== -*/ -portal_t *AllocPortal (void) -{ - portal_t *p; - - if (numthreads == 1) - c_active_portals++; - if (c_active_portals > c_peak_portals) - c_peak_portals = c_active_portals; - - p = malloc (sizeof(portal_t)); - memset (p, 0, sizeof(portal_t)); - - return p; -} - -void FreePortal (portal_t *p) -{ - if (p->winding) - FreeWinding (p->winding); - if (numthreads == 1) - c_active_portals--; - free (p); -} - -//============================================================== - -/* -============= -Portal_Passable - -Returns true if the portal has non-opaque leafs on both sides -============= -*/ -qboolean Portal_Passable(portal_t *p) { - if (!p->onnode) { - return qfalse; // to global outsideleaf - } - - if (p->nodes[0]->planenum != PLANENUM_LEAF - || p->nodes[1]->planenum != PLANENUM_LEAF) { - Error ("Portal_EntityFlood: not a leaf"); - } - - if ( !p->nodes[0]->opaque && !p->nodes[1]->opaque ) { - return qtrue; - } - - return qfalse; -} - - -//============================================================================= - -int c_tinyportals; - -/* -============= -AddPortalToNodes -============= -*/ -void AddPortalToNodes (portal_t *p, node_t *front, node_t *back) -{ - if (p->nodes[0] || p->nodes[1]) - Error ("AddPortalToNode: allready included"); - - p->nodes[0] = front; - p->next[0] = front->portals; - front->portals = p; - - p->nodes[1] = back; - p->next[1] = back->portals; - back->portals = p; -} - - -/* -============= -RemovePortalFromNode -============= -*/ -void RemovePortalFromNode (portal_t *portal, node_t *l) -{ - portal_t **pp, *t; - -// remove reference to the current portal - pp = &l->portals; - while (1) - { - t = *pp; - if (!t) - Error ("RemovePortalFromNode: portal not in leaf"); - - if ( t == portal ) - break; - - if (t->nodes[0] == l) - pp = &t->next[0]; - else if (t->nodes[1] == l) - pp = &t->next[1]; - else - Error ("RemovePortalFromNode: portal not bounding leaf"); - } - - if (portal->nodes[0] == l) - { - *pp = portal->next[0]; - portal->nodes[0] = NULL; - } - else if (portal->nodes[1] == l) - { - *pp = portal->next[1]; - portal->nodes[1] = NULL; - } -} - -//============================================================================ - -void PrintPortal (portal_t *p) -{ - int i; - winding_t *w; - - w = p->winding; - for (i=0 ; i<w->numpoints ; i++) - _printf ("(%5.0f,%5.0f,%5.0f)\n",w->p[i][0] - , w->p[i][1], w->p[i][2]); -} - -/* -================ -MakeHeadnodePortals - -The created portals will face the global outside_node -================ -*/ -#define SIDESPACE 8 -void MakeHeadnodePortals (tree_t *tree) -{ - vec3_t bounds[2]; - int i, j, n; - portal_t *p, *portals[6]; - plane_t bplanes[6], *pl; - node_t *node; - - node = tree->headnode; - -// pad with some space so there will never be null volume leafs - for (i=0 ; i<3 ; i++) - { - bounds[0][i] = tree->mins[i] - SIDESPACE; - bounds[1][i] = tree->maxs[i] + SIDESPACE; - if ( bounds[0][i] >= bounds[1][i] ) { - Error( "Backwards tree volume" ); - } - } - - tree->outside_node.planenum = PLANENUM_LEAF; - tree->outside_node.brushlist = NULL; - tree->outside_node.portals = NULL; - tree->outside_node.opaque = qfalse; - - for (i=0 ; i<3 ; i++) - for (j=0 ; j<2 ; j++) - { - n = j*3 + i; - - p = AllocPortal (); - portals[n] = p; - - pl = &bplanes[n]; - memset (pl, 0, sizeof(*pl)); - if (j) - { - pl->normal[i] = -1; - pl->dist = -bounds[j][i]; - } - else - { - pl->normal[i] = 1; - pl->dist = bounds[j][i]; - } - p->plane = *pl; - p->winding = BaseWindingForPlane (pl->normal, pl->dist); - AddPortalToNodes (p, node, &tree->outside_node); - } - -// clip the basewindings by all the other planes - for (i=0 ; i<6 ; i++) - { - for (j=0 ; j<6 ; j++) - { - if (j == i) - continue; - ChopWindingInPlace (&portals[i]->winding, bplanes[j].normal, bplanes[j].dist, ON_EPSILON); - } - } -} - -//=================================================== - - -/* -================ -BaseWindingForNode -================ -*/ -#define BASE_WINDING_EPSILON 0.001 -#define SPLIT_WINDING_EPSILON 0.001 - -winding_t *BaseWindingForNode (node_t *node) -{ - winding_t *w; - node_t *n; - plane_t *plane; - vec3_t normal; - vec_t dist; - - w = BaseWindingForPlane (mapplanes[node->planenum].normal - , mapplanes[node->planenum].dist); - - // clip by all the parents - for (n=node->parent ; n && w ; ) - { - plane = &mapplanes[n->planenum]; - - if (n->children[0] == node) - { // take front - ChopWindingInPlace (&w, plane->normal, plane->dist, BASE_WINDING_EPSILON); - } - else - { // take back - VectorSubtract (vec3_origin, plane->normal, normal); - dist = -plane->dist; - ChopWindingInPlace (&w, normal, dist, BASE_WINDING_EPSILON); - } - node = n; - n = n->parent; - } - - return w; -} - -//============================================================ - -/* -================== -MakeNodePortal - -create the new portal by taking the full plane winding for the cutting plane -and clipping it by all of parents of this node -================== -*/ -void MakeNodePortal (node_t *node) -{ - portal_t *new_portal, *p; - winding_t *w; - vec3_t normal; - float dist; - int side; - - w = BaseWindingForNode (node); - - // clip the portal by all the other portals in the node - for (p = node->portals ; p && w; p = p->next[side]) - { - if (p->nodes[0] == node) - { - side = 0; - VectorCopy (p->plane.normal, normal); - dist = p->plane.dist; - } - else if (p->nodes[1] == node) - { - side = 1; - VectorSubtract (vec3_origin, p->plane.normal, normal); - dist = -p->plane.dist; - } - else - Error ("CutNodePortals_r: mislinked portal"); - - ChopWindingInPlace (&w, normal, dist, CLIP_EPSILON); - } - - if (!w) - { - return; - } - - if (WindingIsTiny (w)) - { - c_tinyportals++; - FreeWinding (w); - return; - } - - new_portal = AllocPortal (); - new_portal->plane = mapplanes[node->planenum]; - new_portal->onnode = node; - new_portal->winding = w; - new_portal->hint = node->hint; - AddPortalToNodes (new_portal, node->children[0], node->children[1]); -} - - -/* -============== -SplitNodePortals - -Move or split the portals that bound node so that the node's -children have portals instead of node. -============== -*/ -void SplitNodePortals (node_t *node) -{ - portal_t *p, *next_portal, *new_portal; - node_t *f, *b, *other_node; - int side; - plane_t *plane; - winding_t *frontwinding, *backwinding; - - plane = &mapplanes[node->planenum]; - f = node->children[0]; - b = node->children[1]; - - for (p = node->portals ; p ; p = next_portal) - { - if (p->nodes[0] == node) - side = 0; - else if (p->nodes[1] == node) - side = 1; - else - Error ("SplitNodePortals: mislinked portal"); - next_portal = p->next[side]; - - other_node = p->nodes[!side]; - RemovePortalFromNode (p, p->nodes[0]); - RemovePortalFromNode (p, p->nodes[1]); - -// -// cut the portal into two portals, one on each side of the cut plane -// - ClipWindingEpsilon (p->winding, plane->normal, plane->dist, - SPLIT_WINDING_EPSILON, &frontwinding, &backwinding); - - if (frontwinding && WindingIsTiny(frontwinding)) - { - if (!f->tinyportals) - VectorCopy(frontwinding->p[0], f->referencepoint); - f->tinyportals++; - if (!other_node->tinyportals) - VectorCopy(frontwinding->p[0], other_node->referencepoint); - other_node->tinyportals++; - - FreeWinding (frontwinding); - frontwinding = NULL; - c_tinyportals++; - } - - if (backwinding && WindingIsTiny(backwinding)) - { - if (!b->tinyportals) - VectorCopy(backwinding->p[0], b->referencepoint); - b->tinyportals++; - if (!other_node->tinyportals) - VectorCopy(backwinding->p[0], other_node->referencepoint); - other_node->tinyportals++; - - FreeWinding (backwinding); - backwinding = NULL; - c_tinyportals++; - } - - if (!frontwinding && !backwinding) - { // tiny windings on both sides - continue; - } - - if (!frontwinding) - { - FreeWinding (backwinding); - if (side == 0) - AddPortalToNodes (p, b, other_node); - else - AddPortalToNodes (p, other_node, b); - continue; - } - if (!backwinding) - { - FreeWinding (frontwinding); - if (side == 0) - AddPortalToNodes (p, f, other_node); - else - AddPortalToNodes (p, other_node, f); - continue; - } - - // the winding is split - new_portal = AllocPortal (); - *new_portal = *p; - new_portal->winding = backwinding; - FreeWinding (p->winding); - p->winding = frontwinding; - - if (side == 0) - { - AddPortalToNodes (p, f, other_node); - AddPortalToNodes (new_portal, b, other_node); - } - else - { - AddPortalToNodes (p, other_node, f); - AddPortalToNodes (new_portal, other_node, b); - } - } - - node->portals = NULL; -} - - -/* -================ -CalcNodeBounds -================ -*/ -void CalcNodeBounds (node_t *node) -{ - portal_t *p; - int s; - int i; - - // calc mins/maxs for both leafs and nodes - ClearBounds (node->mins, node->maxs); - for (p = node->portals ; p ; p = p->next[s]) - { - s = (p->nodes[1] == node); - for (i=0 ; i<p->winding->numpoints ; i++) - AddPointToBounds (p->winding->p[i], node->mins, node->maxs); - } -} - -/* -================== -MakeTreePortals_r -================== -*/ -void MakeTreePortals_r (node_t *node) -{ - int i; - - CalcNodeBounds (node); - if (node->mins[0] >= node->maxs[0]) - { - _printf ("WARNING: node without a volume\n"); - _printf("node has %d tiny portals\n", node->tinyportals); - _printf("node reference point %1.2f %1.2f %1.2f\n", node->referencepoint[0], - node->referencepoint[1], - node->referencepoint[2]); - } - - for (i=0 ; i<3 ; i++) - { - if (node->mins[i] < MIN_WORLD_COORD || node->maxs[i] > MAX_WORLD_COORD) - { - _printf ("WARNING: node with unbounded volume\n"); - break; - } - } - if (node->planenum == PLANENUM_LEAF) - return; - - MakeNodePortal (node); - SplitNodePortals (node); - - MakeTreePortals_r (node->children[0]); - MakeTreePortals_r (node->children[1]); -} - -/* -================== -MakeTreePortals -================== -*/ -void MakeTreePortals (tree_t *tree) -{ - qprintf( "----- MakeTreePortals -----\n"); - MakeHeadnodePortals (tree); - MakeTreePortals_r (tree->headnode); - qprintf("%6d tiny portals\n", c_tinyportals); -} - -/* -========================================================= - -FLOOD ENTITIES - -========================================================= -*/ - -int c_floodedleafs; - -/* -============= -FloodPortals_r -============= -*/ -void FloodPortals_r (node_t *node, int dist) { - portal_t *p; - int s; - - if ( node->occupied ) { - return; - } - - if ( node->opaque ) { - return; - } - - c_floodedleafs++; - node->occupied = dist; - - for (p=node->portals ; p ; p = p->next[s]) { - s = (p->nodes[1] == node); - FloodPortals_r (p->nodes[!s], dist+1); - } -} - -/* -============= -PlaceOccupant -============= -*/ -qboolean PlaceOccupant (node_t *headnode, vec3_t origin, entity_t *occupant) -{ - node_t *node; - vec_t d; - plane_t *plane; - - // find the leaf to start in - node = headnode; - while (node->planenum != PLANENUM_LEAF) - { - plane = &mapplanes[node->planenum]; - d = DotProduct (origin, plane->normal) - plane->dist; - if (d >= 0) - node = node->children[0]; - else - node = node->children[1]; - } - - if ( node->opaque ) - return qfalse; - node->occupant = occupant; - - FloodPortals_r (node, 1); - - return qtrue; -} - -/* -============= -FloodEntities - -Marks all nodes that can be reached by entites -============= -*/ -qboolean FloodEntities( tree_t *tree ) { - int i; - vec3_t origin; - const char *cl; - qboolean inside; - node_t *headnode; - - headnode = tree->headnode; - qprintf ("--- FloodEntities ---\n"); - inside = qfalse; - tree->outside_node.occupied = 0; - - c_floodedleafs = 0; - for (i=1 ; i<num_entities ; i++) - { - GetVectorForKey (&entities[i], "origin", origin); - if (VectorCompare(origin, vec3_origin)) - continue; - - cl = ValueForKey (&entities[i], "classname"); - - origin[2] += 1; // so objects on floor are ok - - if (PlaceOccupant (headnode, origin, &entities[i])) - inside = qtrue; - } - - qprintf("%5i flooded leafs\n", c_floodedleafs ); - - if (!inside) - { - qprintf ("no entities in open -- no filling\n"); - } - else if (tree->outside_node.occupied) - { - qprintf ("entity reached from outside -- no filling\n"); - } - - return (qboolean)(inside && !tree->outside_node.occupied); -} - -/* -========================================================= - -FLOOD AREAS - -========================================================= -*/ - -int c_areas; - -/* -============= -FloodAreas_r -============= -*/ -void FloodAreas_r (node_t *node) -{ - portal_t *p; - int s; - bspbrush_t *b; - - if ( node->areaportal ) { - // - if ( node->area == -1 ) { - node->area = c_areas; - } - // this node is part of an area portal brush - b = node->brushlist->original; - - // if the current area has allready touched this - // portal, we are done - if (b->portalareas[0] == c_areas || b->portalareas[1] == c_areas) - return; - - // note the current area as bounding the portal - if (b->portalareas[1] != -1) - { - _printf ("WARNING: areaportal brush %i touches > 2 areas\n", b->brushnum ); - return; - } - if (b->portalareas[0] != -1) { - b->portalareas[1] = c_areas; - } else { - b->portalareas[0] = c_areas; - } - - return; - } - - if (node->area != -1) { - return; // allready got it - } - if ( node->cluster == -1 ) { - return; - } - - node->area = c_areas; - - for (p=node->portals ; p ; p = p->next[s]) - { - s = (p->nodes[1] == node); - - if ( !Portal_Passable(p) ) - continue; - - FloodAreas_r (p->nodes[!s]); - } -} - - -/* -============= -FindAreas_r - -Just decend the tree, and for each node that hasn't had an -area set, flood fill out from there -============= -*/ -void FindAreas_r (node_t *node) -{ - if (node->planenum != PLANENUM_LEAF) - { - FindAreas_r (node->children[0]); - FindAreas_r (node->children[1]); - return; - } - - if (node->opaque) - return; - - if (node->areaportal) - return; - - if (node->area != -1) - return; // allready got it - - FloodAreas_r (node); - c_areas++; -} - -/* -============= -CheckAreas_r -============= -*/ -void CheckAreas_r (node_t *node) -{ - bspbrush_t *b; - - if (node->planenum != PLANENUM_LEAF) - { - CheckAreas_r (node->children[0]); - CheckAreas_r (node->children[1]); - return; - } - - if (node->opaque) - return; - - if (node->cluster != -1) - if (node->area == -1) - _printf("WARNING: cluster %d has area set to -1\n", node->cluster); - if (node->areaportal) - { - b = node->brushlist->original; - - // check if the areaportal touches two areas - if (b->portalareas[0] == -1 || b->portalareas[1] == -1) - _printf ("WARNING: areaportal brush %i doesn't touch two areas\n", b->brushnum); - } -} - -/* -============= -FloodAreas - -Mark each leaf with an area, bounded by CONTENTS_AREAPORTAL -============= -*/ -void FloodAreas (tree_t *tree) -{ - qprintf ("--- FloodAreas ---\n"); - FindAreas_r( tree->headnode ); - - // check for areaportal brushes that don't touch two areas - CheckAreas_r( tree->headnode ); - - qprintf ("%5i areas\n", c_areas); -} - -//====================================================== - -int c_outside; -int c_inside; -int c_solid; - -void FillOutside_r (node_t *node) -{ - if (node->planenum != PLANENUM_LEAF) - { - FillOutside_r (node->children[0]); - FillOutside_r (node->children[1]); - return; - } - - // anything not reachable by an entity - // can be filled away - if (!node->occupied) { - if ( !node->opaque ) { - c_outside++; - node->opaque = qtrue; - } else { - c_solid++; - } - } else { - c_inside++; - } - -} - -/* -============= -FillOutside - -Fill all nodes that can't be reached by entities -============= -*/ -void FillOutside (node_t *headnode) -{ - c_outside = 0; - c_inside = 0; - c_solid = 0; - qprintf ("--- FillOutside ---\n"); - FillOutside_r (headnode); - qprintf ("%5i solid leafs\n", c_solid); - qprintf ("%5i leafs filled\n", c_outside); - qprintf ("%5i inside leafs\n", c_inside); -} - - -//============================================================== - diff --git a/q3map/prtfile.c b/q3map/prtfile.c deleted file mode 100644 index 6a7bb15..0000000 --- a/q3map/prtfile.c +++ /dev/null @@ -1,272 +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" - -/* -============================================================================== - -PORTAL FILE GENERATION - -Save out name.prt for qvis to read -============================================================================== -*/ - - -#define PORTALFILE "PRT1" - -FILE *pf; -int num_visclusters; // clusters the player can be in -int num_visportals; -int num_solidfaces; - -void WriteFloat (FILE *f, vec_t v) -{ - if ( fabs(v - Q_rint(v)) < 0.001 ) - fprintf (f,"%i ",(int)Q_rint(v)); - else - fprintf (f,"%f ",v); -} - -/* -================= -WritePortalFile_r -================= -*/ -void WritePortalFile_r (node_t *node) -{ - int i, s; - portal_t *p; - winding_t *w; - vec3_t normal; - vec_t dist; - - // decision node - if (node->planenum != PLANENUM_LEAF) { - WritePortalFile_r (node->children[0]); - WritePortalFile_r (node->children[1]); - return; - } - - if (node->opaque) { - return; - } - - for (p = node->portals ; p ; p=p->next[s]) - { - w = p->winding; - s = (p->nodes[1] == node); - if (w && p->nodes[0] == node) - { - if (!Portal_Passable(p)) - continue; - // write out to the file - - // sometimes planes get turned around when they are very near - // the changeover point between different axis. interpret the - // plane the same way vis will, and flip the side orders if needed - // FIXME: is this still relevent? - WindingPlane (w, normal, &dist); - if ( DotProduct (p->plane.normal, normal) < 0.99 ) - { // backwards... - fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[1]->cluster, p->nodes[0]->cluster); - } - else - fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[0]->cluster, p->nodes[1]->cluster); - if (p->hint) - fprintf (pf, "1 "); - else - fprintf (pf, "0 "); - for (i=0 ; i<w->numpoints ; i++) - { - fprintf (pf,"("); - WriteFloat (pf, w->p[i][0]); - WriteFloat (pf, w->p[i][1]); - WriteFloat (pf, w->p[i][2]); - fprintf (pf,") "); - } - fprintf (pf,"\n"); - } - } - -} - -/* -================= -WriteFaceFile_r -================= -*/ -void WriteFaceFile_r (node_t *node) -{ - int i, s; - portal_t *p; - winding_t *w; - - // decision node - if (node->planenum != PLANENUM_LEAF) { - WriteFaceFile_r (node->children[0]); - WriteFaceFile_r (node->children[1]); - return; - } - - if (node->opaque) { - return; - } - - for (p = node->portals ; p ; p=p->next[s]) - { - w = p->winding; - s = (p->nodes[1] == node); - if (w) - { - if (Portal_Passable(p)) - continue; - // write out to the file - - if (p->nodes[0] == node) - { - fprintf (pf,"%i %i ",w->numpoints, p->nodes[0]->cluster); - for (i=0 ; i<w->numpoints ; i++) - { - fprintf (pf,"("); - WriteFloat (pf, w->p[i][0]); - WriteFloat (pf, w->p[i][1]); - WriteFloat (pf, w->p[i][2]); - fprintf (pf,") "); - } - fprintf (pf,"\n"); - } - else - { - fprintf (pf,"%i %i ",w->numpoints, p->nodes[1]->cluster); - for (i = w->numpoints-1; i >= 0; i--) - { - fprintf (pf,"("); - WriteFloat (pf, w->p[i][0]); - WriteFloat (pf, w->p[i][1]); - WriteFloat (pf, w->p[i][2]); - fprintf (pf,") "); - } - fprintf (pf,"\n"); - } - } - } -} - -/* -================ -NumberLeafs_r -================ -*/ -void NumberLeafs_r (node_t *node) -{ - portal_t *p; - - if ( node->planenum != PLANENUM_LEAF ) { - // decision node - node->cluster = -99; - NumberLeafs_r (node->children[0]); - NumberLeafs_r (node->children[1]); - return; - } - - node->area = -1; - - if ( node->opaque ) { - // solid block, viewpoint never inside - node->cluster = -1; - return; - } - - node->cluster = num_visclusters; - num_visclusters++; - - // count the portals - for (p = node->portals ; p ; ) - { - if (p->nodes[0] == node) // only write out from first leaf - { - if (Portal_Passable(p)) - num_visportals++; - else - num_solidfaces++; - p = p->next[0]; - } - else - { - if (!Portal_Passable(p)) - num_solidfaces++; - p = p->next[1]; - } - } -} - - -/* -================ -NumberClusters -================ -*/ -void NumberClusters(tree_t *tree) { - num_visclusters = 0; - num_visportals = 0; - num_solidfaces = 0; - - qprintf ("--- NumberClusters ---\n"); - - // set the cluster field in every leaf and count the total number of portals - NumberLeafs_r (tree->headnode); - - qprintf ("%5i visclusters\n", num_visclusters); - qprintf ("%5i visportals\n", num_visportals); - qprintf ("%5i solidfaces\n", num_solidfaces); -} - -/* -================ -WritePortalFile -================ -*/ -void WritePortalFile (tree_t *tree) -{ - char filename[1024]; - - qprintf ("--- WritePortalFile ---\n"); - - // write the file - sprintf (filename, "%s.prt", source); - _printf ("writing %s\n", filename); - pf = fopen (filename, "w"); - if (!pf) - Error ("Error opening %s", filename); - - fprintf (pf, "%s\n", PORTALFILE); - fprintf (pf, "%i\n", num_visclusters); - fprintf (pf, "%i\n", num_visportals); - fprintf (pf, "%i\n", num_solidfaces); - - WritePortalFile_r(tree->headnode); - WriteFaceFile_r(tree->headnode); - - fclose (pf); -} - diff --git a/q3map/q3map.sln b/q3map/q3map.sln deleted file mode 100644 index e0b2699..0000000 --- a/q3map/q3map.sln +++ /dev/null @@ -1,56 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 8.00 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jpeg6", "..\libs\jpeg6\jpeg6.vcproj", "{A862AD26-94DD-4618-A814-F6AACA0B2FE3}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pak", "..\libs\pak\pak.vcproj", "{F2ACC9D7-D628-4624-864F-87FE58787625}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "q3map", "q3map.vcproj", "{F1162C55-66E7-4486-B1F3-071CFAA78332}" - ProjectSection(ProjectDependencies) = postProject - {F2ACC9D7-D628-4624-864F-87FE58787625} = {F2ACC9D7-D628-4624-864F-87FE58787625} - {A862AD26-94DD-4618-A814-F6AACA0B2FE3} = {A862AD26-94DD-4618-A814-F6AACA0B2FE3} - EndProjectSection -EndProject -Global - GlobalSection(SourceCodeControl) = preSolution - SccNumberOfProjects = 3 - SccProjectUniqueName0 = ..\\libs\\jpeg6\\jpeg6.vcproj - SccProjectName0 = \u0022$/source/q3radiant\u0022,\u0020FEFAAAAA - SccLocalPath0 = ..\\q3radiant - SccProvider0 = MSSCCI:Perforce\u0020SCM - SccProjectFilePathRelativizedFromConnection0 = ..\\libs\\jpeg6\\ - SccProjectUniqueName1 = ..\\libs\\pak\\pak.vcproj - SccProjectName1 = \u0022$/source/q3radiant\u0022,\u0020FEFAAAAA - SccLocalPath1 = ..\\q3radiant - SccProvider1 = MSSCCI:Perforce\u0020SCM - SccProjectFilePathRelativizedFromConnection1 = ..\\libs\\pak\\ - SccProjectUniqueName2 = q3map.vcproj - SccProjectName2 = \u0022$/source/q3map\u0022,\u0020PADAAAAA - SccLocalPath2 = . - SccProvider2 = MSSCCI:Perforce\u0020SCM - EndGlobalSection - GlobalSection(SolutionConfiguration) = preSolution - Debug = Debug - Release = Release - EndGlobalSection - GlobalSection(ProjectConfiguration) = postSolution - {A862AD26-94DD-4618-A814-F6AACA0B2FE3}.Debug.ActiveCfg = Debug|Win32 - {A862AD26-94DD-4618-A814-F6AACA0B2FE3}.Debug.Build.0 = Debug|Win32 - {A862AD26-94DD-4618-A814-F6AACA0B2FE3}.Release.ActiveCfg = Release|Win32 - {A862AD26-94DD-4618-A814-F6AACA0B2FE3}.Release.Build.0 = Release|Win32 - {F2ACC9D7-D628-4624-864F-87FE58787625}.Debug.ActiveCfg = Debug|Win32 - {F2ACC9D7-D628-4624-864F-87FE58787625}.Debug.Build.0 = Debug|Win32 - {F2ACC9D7-D628-4624-864F-87FE58787625}.Release.ActiveCfg = Release|Win32 - {F2ACC9D7-D628-4624-864F-87FE58787625}.Release.Build.0 = Release|Win32 - {F1162C55-66E7-4486-B1F3-071CFAA78332}.Debug.ActiveCfg = Debug|Win32 - {F1162C55-66E7-4486-B1F3-071CFAA78332}.Debug.Build.0 = Debug|Win32 - {F1162C55-66E7-4486-B1F3-071CFAA78332}.Release.ActiveCfg = Release|Win32 - {F1162C55-66E7-4486-B1F3-071CFAA78332}.Release.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - EndGlobalSection - GlobalSection(ExtensibilityAddIns) = postSolution - EndGlobalSection -EndGlobal diff --git a/q3map/q3map.vcproj b/q3map/q3map.vcproj deleted file mode 100644 index 6fa6606..0000000 --- a/q3map/q3map.vcproj +++ /dev/null @@ -1,1606 +0,0 @@ -<?xml version="1.0" encoding="Windows-1252"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="7.10" - Name="q3map" - SccProjectName=""$/source/q3map", PADAAAAA" - SccLocalPath="."> - <Platforms> - <Platform - Name="Win32"/> - </Platforms> - <Configurations> - <Configuration - Name="Debug|Win32" - OutputDirectory=".\Debug" - IntermediateDirectory=".\Debug" - ConfigurationType="1" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="../common,c:\quake3\common,c:\quake3\libs" - PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE" - RuntimeLibrary="1" - UsePrecompiledHeader="2" - PrecompiledHeaderFile=".\Debug/q3map.pch" - AssemblerListingLocation=".\Debug/" - ObjectFile=".\Debug/" - ProgramDataBaseFileName=".\Debug/" - BrowseInformation="1" - WarningLevel="3" - SuppressStartupBanner="TRUE" - DebugInformationFormat="4" - CompileAs="0"/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCLinkerTool" - AdditionalDependencies="glaux.lib glu32.lib wsock32.lib opengl32.lib odbc32.lib odbccp32.lib ..\libs\pakd.lib ..\libs\jpeg6d.lib" - OutputFile=".\Debug/q3map.exe" - LinkIncremental="2" - SuppressStartupBanner="TRUE" - GenerateDebugInformation="TRUE" - ProgramDatabaseFile=".\Debug/q3map.pdb" - SubSystem="1" - StackReserveSize="4194304" - TargetMachine="1"/> - <Tool - Name="VCMIDLTool" - TypeLibraryName=".\Debug/q3map.tlb" - HeaderFileName=""/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCResourceCompilerTool" - PreprocessorDefinitions="_DEBUG" - Culture="1033"/> - <Tool - Name="VCWebServiceProxyGeneratorTool"/> - <Tool - Name="VCXMLDataGeneratorTool"/> - <Tool - Name="VCWebDeploymentTool"/> - <Tool - Name="VCManagedWrapperGeneratorTool"/> - <Tool - Name="VCAuxiliaryManagedWrapperGeneratorTool"/> - </Configuration> - <Configuration - Name="Release|Win32" - OutputDirectory=".\Release" - IntermediateDirectory=".\Release" - ConfigurationType="1" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - InlineFunctionExpansion="1" - AdditionalIncludeDirectories="../common,c:\quake3\common,c:\quake3\libs" - PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE" - StringPooling="TRUE" - RuntimeLibrary="0" - EnableFunctionLevelLinking="TRUE" - UsePrecompiledHeader="2" - PrecompiledHeaderFile=".\Release/q3map.pch" - AssemblerListingLocation=".\Release/" - ObjectFile=".\Release/" - ProgramDataBaseFileName=".\Release/" - WarningLevel="3" - SuppressStartupBanner="TRUE" - DebugInformationFormat="3" - CompileAs="0"/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCLinkerTool" - AdditionalDependencies="glaux.lib glu32.lib wsock32.lib opengl32.lib odbc32.lib odbccp32.lib ..\libs\pak.lib ..\libs\jpeg6.lib" - OutputFile=".\Release/q3map.exe" - LinkIncremental="1" - SuppressStartupBanner="TRUE" - GenerateDebugInformation="TRUE" - ProgramDatabaseFile=".\Release/q3map.pdb" - SubSystem="1" - StackReserveSize="4194304" - TargetMachine="1"/> - <Tool - Name="VCMIDLTool" - TypeLibraryName=".\Release/q3map.tlb" - HeaderFileName=""/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCResourceCompilerTool" - PreprocessorDefinitions="NDEBUG" - Culture="1033"/> - <Tool - Name="VCWebServiceProxyGeneratorTool"/> - <Tool - Name="VCXMLDataGeneratorTool"/> - <Tool - Name="VCWebDeploymentTool"/> - <Tool - Name="VCManagedWrapperGeneratorTool"/> - <Tool - Name="VCAuxiliaryManagedWrapperGeneratorTool"/> - </Configuration> - <Configuration - Name="DebugTTimo|Win32" - OutputDirectory=".\q3map___Win32_DebugTTimo" - IntermediateDirectory=".\q3map___Win32_DebugTTimo" - ConfigurationType="1" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="../common,../../Libs,c:\quake3\common,c:\quake3\libs" - PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_TTIMOBUILD" - RuntimeLibrary="1" - UsePrecompiledHeader="2" - PrecompiledHeaderFile=".\q3map___Win32_DebugTTimo/q3map.pch" - AssemblerListingLocation=".\q3map___Win32_DebugTTimo/" - ObjectFile=".\q3map___Win32_DebugTTimo/" - ProgramDataBaseFileName=".\q3map___Win32_DebugTTimo/" - BrowseInformation="1" - WarningLevel="3" - SuppressStartupBanner="TRUE" - DebugInformationFormat="4" - CompileAs="0"/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCLinkerTool" - AdditionalDependencies="glaux.lib glu32.lib wsock32.lib opengl32.lib odbc32.lib odbccp32.lib pakd.lib jpeg6d.lib" - OutputFile=".\q3map___Win32_DebugTTimo/q3map.exe" - LinkIncremental="2" - SuppressStartupBanner="TRUE" - AdditionalLibraryDirectories="../../Libs" - GenerateDebugInformation="TRUE" - ProgramDatabaseFile=".\q3map___Win32_DebugTTimo/q3map.pdb" - SubSystem="1" - StackReserveSize="4194304" - TargetMachine="1"/> - <Tool - Name="VCMIDLTool" - TypeLibraryName=".\q3map___Win32_DebugTTimo/q3map.tlb" - HeaderFileName=""/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCResourceCompilerTool" - PreprocessorDefinitions="_DEBUG" - Culture="1033"/> - <Tool - Name="VCWebServiceProxyGeneratorTool"/> - <Tool - Name="VCXMLDataGeneratorTool"/> - <Tool - Name="VCWebDeploymentTool"/> - <Tool - Name="VCManagedWrapperGeneratorTool"/> - <Tool - Name="VCAuxiliaryManagedWrapperGeneratorTool"/> - </Configuration> - <Configuration - Name="ReleaseTTimo|Win32" - OutputDirectory=".\q3map___Win32_ReleaseTTimo" - IntermediateDirectory=".\q3map___Win32_ReleaseTTimo" - ConfigurationType="1" - UseOfMFC="0" - ATLMinimizesCRunTimeLibraryUsage="FALSE" - CharacterSet="2"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - InlineFunctionExpansion="1" - AdditionalIncludeDirectories="../common,../../Libs,c:\quake3\common,c:\quake3\libs" - PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_TTIMOBUILD" - StringPooling="TRUE" - RuntimeLibrary="0" - EnableFunctionLevelLinking="TRUE" - UsePrecompiledHeader="2" - PrecompiledHeaderFile=".\q3map___Win32_ReleaseTTimo/q3map.pch" - AssemblerListingLocation=".\q3map___Win32_ReleaseTTimo/" - ObjectFile=".\q3map___Win32_ReleaseTTimo/" - ProgramDataBaseFileName=".\q3map___Win32_ReleaseTTimo/" - WarningLevel="3" - SuppressStartupBanner="TRUE" - DebugInformationFormat="3" - CompileAs="0"/> - <Tool - Name="VCCustomBuildTool"/> - <Tool - Name="VCLinkerTool" - AdditionalDependencies="glaux.lib glu32.lib wsock32.lib opengl32.lib odbc32.lib odbccp32.lib pak.lib jpeg6.lib" - OutputFile=".\q3map___Win32_ReleaseTTimo/q3map.exe" - LinkIncremental="1" - SuppressStartupBanner="TRUE" - AdditionalLibraryDirectories="../../Libs" - GenerateDebugInformation="TRUE" - ProgramDatabaseFile=".\q3map___Win32_ReleaseTTimo/q3map.pdb" - SubSystem="1" - StackReserveSize="4194304" - TargetMachine="1"/> - <Tool - Name="VCMIDLTool" - TypeLibraryName=".\q3map___Win32_ReleaseTTimo/q3map.tlb" - HeaderFileName=""/> - <Tool - Name="VCPostBuildEventTool"/> - <Tool - Name="VCPreBuildEventTool"/> - <Tool - Name="VCPreLinkEventTool"/> - <Tool - Name="VCResourceCompilerTool" - PreprocessorDefinitions="NDEBUG" - Culture="1033"/> - <Tool - Name="VCWebServiceProxyGeneratorTool"/> - <Tool - Name="VCXMLDataGeneratorTool"/> - <Tool - Name="VCWebDeploymentTool"/> - <Tool - Name="VCManagedWrapperGeneratorTool"/> - <Tool - Name="VCAuxiliaryManagedWrapperGeneratorTool"/> - </Configuration> - </Configurations> - <References> - </References> - <Files> - <File - RelativePath="..\common\aselib.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="brush.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="brush_primit.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="bsp.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="..\common\bspfile.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="..\common\cmdlib.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="facebsp.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="fog.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="gldraw.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="glfile.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="..\common\imagelib.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="leakfile.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="light.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="light_trace.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="lightmaps.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="lightv.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="map.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="..\common\mathlib.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="mesh.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="misc_model.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="..\common\mutex.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="patch.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="..\common\polylib.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="portals.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="prtfile.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="..\common\scriplib.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="shaders.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="soundv.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="surface.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="terrain.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="..\common\threads.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="tjunction.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="tree.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="vis.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="visflow.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - <File - RelativePath="writebsp.c"> - <FileConfiguration - Name="Debug|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="Release|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - <FileConfiguration - Name="DebugTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="0" - AdditionalIncludeDirectories="" - PreprocessorDefinitions="" - BrowseInformation="1"/> - </FileConfiguration> - <FileConfiguration - Name="ReleaseTTimo|Win32"> - <Tool - Name="VCCLCompilerTool" - Optimization="2" - AdditionalIncludeDirectories="" - PreprocessorDefinitions=""/> - </FileConfiguration> - </File> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/q3map/qbsp.h b/q3map/qbsp.h deleted file mode 100644 index 7c7cfba..0000000 --- a/q3map/qbsp.h +++ /dev/null @@ -1,455 +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 "cmdlib.h" -#include "mathlib.h" -#include "scriplib.h" -#include "polylib.h" -#include "imagelib.h" -#include "threads.h" -#include "bspfile.h" -#include "shaders.h" -#include "mesh.h" - - -#define MAX_PATCH_SIZE 32 - -#define CLIP_EPSILON 0.1 -#define PLANENUM_LEAF -1 - -#define HINT_PRIORITY 1000 - -typedef struct parseMesh_s { - struct parseMesh_s *next; - mesh_t mesh; - shaderInfo_t *shaderInfo; - - qboolean grouped; // used during shared edge grouping - struct parseMesh_s *groupChain; -} parseMesh_t; - -typedef struct bspface_s { - struct bspface_s *next; - int planenum; - int priority; // added to value calculation - qboolean checked; - qboolean hint; - winding_t *w; -} bspface_t; - -typedef struct plane_s { - vec3_t normal; - vec_t dist; - int type; - struct plane_s *hash_chain; -} plane_t; - -typedef struct side_s { - int planenum; - - float texMat[2][3]; // brush primitive texture matrix - // for old brush coordinates mode - float vecs[2][4]; // texture coordinate mapping - - winding_t *winding; - winding_t *visibleHull; // convex hull of all visible fragments - - struct shaderInfo_s *shaderInfo; - - int contents; // from shaderInfo - int surfaceFlags; // from shaderInfo - int value; // from shaderInfo - - qboolean visible; // choose visble planes first - qboolean bevel; // don't ever use for bsp splitting, and don't bother - // making windings for it - qboolean backSide; // generated side for a q3map_backShader -} side_t; - - -#define MAX_BRUSH_SIDES 1024 - -typedef struct bspbrush_s { - struct bspbrush_s *next; - - int entitynum; // editor numbering - int brushnum; // editor numbering - - struct shaderInfo_s *contentShader; - - int contents; - qboolean detail; - qboolean opaque; - int outputNumber; // set when the brush is written to the file list - - int portalareas[2]; - - struct bspbrush_s *original; // chopped up brushes will reference the originals - - vec3_t mins, maxs; - int numsides; - side_t sides[6]; // variably sized -} bspbrush_t; - - - -typedef struct drawsurf_s { - shaderInfo_t *shaderInfo; - - bspbrush_t *mapBrush; // not valid for patches - side_t *side; // not valid for patches - - struct drawsurf_s *nextOnShader; // when sorting by shader for lightmaps - - int fogNum; // set by FogDrawSurfs - - int lightmapNum; // -1 = no lightmap - int lightmapX, lightmapY; - int lightmapWidth, lightmapHeight; - - int numVerts; - drawVert_t *verts; - - int numIndexes; - int *indexes; - - // for faces only - int planeNum; - - vec3_t lightmapOrigin; // also used for flares - vec3_t lightmapVecs[3]; // also used for flares - - // for patches only - qboolean patch; - int patchWidth; - int patchHeight; - - // for misc_models only - qboolean miscModel; - - qboolean flareSurface; -} mapDrawSurface_t; - -typedef struct drawSurfRef_s { - struct drawSurfRef_s *nextRef; - int outputNumber; -} drawSurfRef_t; - -typedef struct node_s { - // both leafs and nodes - int planenum; // -1 = leaf node - struct node_s *parent; - vec3_t mins, maxs; // valid after portalization - bspbrush_t *volume; // one for each leaf/node - - // nodes only - side_t *side; // the side that created the node - struct node_s *children[2]; - qboolean hint; - int tinyportals; - vec3_t referencepoint; - - // leafs only - qboolean opaque; // view can never be inside - qboolean areaportal; - int cluster; // for portalfile writing - int area; // for areaportals - bspbrush_t *brushlist; // fragments of all brushes in this leaf - drawSurfRef_t *drawSurfReferences; // references to patches pushed down - - int occupied; // 1 or greater can reach entity - entity_t *occupant; // for leak file testing - - struct portal_s *portals; // also on nodes during construction -} node_t; - -typedef struct portal_s { - plane_t plane; - node_t *onnode; // NULL = outside box - node_t *nodes[2]; // [0] = front side of plane - struct portal_s *next[2]; - winding_t *winding; - - qboolean sidefound; // false if ->side hasn't been checked - qboolean hint; - side_t *side; // NULL = non-visible -} portal_t; - -typedef struct { - node_t *headnode; - node_t outside_node; - vec3_t mins, maxs; -} tree_t; - -extern int entity_num; - - -extern qboolean noprune; -extern qboolean nodetail; -extern qboolean fulldetail; -extern qboolean nowater; -extern qboolean noCurveBrushes; -extern qboolean fakemap; -extern qboolean coplanar; -extern qboolean nofog; -extern qboolean testExpand; -extern qboolean showseams; - -extern vec_t microvolume; - -extern char outbase[32]; -extern char source[1024]; - -extern int samplesize; //sample size in units -extern int novertexlighting; -extern int nogridlighting; - -//============================================================================= - -// brush.c - -int CountBrushList (bspbrush_t *brushes); -bspbrush_t *AllocBrush (int numsides); -void FreeBrush (bspbrush_t *brushes); -void FreeBrushList (bspbrush_t *brushes); -bspbrush_t *CopyBrush (bspbrush_t *brush); -void DrawBrushList (bspbrush_t *brush); -void WriteBrushList (char *name, bspbrush_t *brush, qboolean onlyvis); -void PrintBrush (bspbrush_t *brush); -qboolean BoundBrush (bspbrush_t *brush); -qboolean CreateBrushWindings (bspbrush_t *brush); -bspbrush_t *BrushFromBounds (vec3_t mins, vec3_t maxs); -vec_t BrushVolume (bspbrush_t *brush); -void WriteBspBrushMap (char *name, bspbrush_t *list); - -void FilterDetailBrushesIntoTree( entity_t *e, tree_t *tree ); -void FilterStructuralBrushesIntoTree( entity_t *e, tree_t *tree ); - -//============================================================================= - -// map.c - -extern int entitySourceBrushes; - -// mapplanes[ num^1 ] will always be the mirror or mapplanes[ num ] -// nummapplanes will always be even -extern plane_t mapplanes[MAX_MAP_PLANES]; -extern int nummapplanes; - -extern vec3_t map_mins, map_maxs; - -extern char mapIndexedShaders[MAX_MAP_BRUSHSIDES][MAX_QPATH]; -extern int numMapIndexedShaders; - -extern entity_t *mapent; - -#define MAX_BUILD_SIDES 300 -extern bspbrush_t *buildBrush; - - -void LoadMapFile (char *filename); -int FindFloatPlane (vec3_t normal, vec_t dist); -int PlaneTypeForNormal (vec3_t normal); -bspbrush_t *FinishBrush( void ); -mapDrawSurface_t *AllocDrawSurf( void ); -mapDrawSurface_t *DrawSurfaceForSide( bspbrush_t *b, side_t *s, winding_t *w ); - -//============================================================================= - -//============================================================================= - -// draw.c - -extern vec3_t draw_mins, draw_maxs; -extern qboolean drawflag; - -void Draw_ClearWindow (void); -void DrawWinding (winding_t *w); - -void GLS_BeginScene (void); -void GLS_Winding (winding_t *w, int code); -void GLS_EndScene (void); - -//============================================================================= - -// csg - -bspbrush_t *MakeBspBrushList ( bspbrush_t *brushes, vec3_t clipmins, vec3_t clipmaxs); - -//============================================================================= - -// brushbsp - -#define PSIDE_FRONT 1 -#define PSIDE_BACK 2 -#define PSIDE_BOTH (PSIDE_FRONT|PSIDE_BACK) -#define PSIDE_FACING 4 - -int BoxOnPlaneSide (vec3_t mins, vec3_t maxs, plane_t *plane); -qboolean WindingIsTiny (winding_t *w); - -void SplitBrush (bspbrush_t *brush, int planenum, - bspbrush_t **front, bspbrush_t **back); - -tree_t *AllocTree (void); -node_t *AllocNode (void); - -tree_t *BrushBSP (bspbrush_t *brushlist, vec3_t mins, vec3_t maxs); - -//============================================================================= - -// portals.c - -void MakeHeadnodePortals (tree_t *tree); -void MakeNodePortal (node_t *node); -void SplitNodePortals (node_t *node); - -qboolean Portal_Passable(portal_t *p); - -qboolean FloodEntities (tree_t *tree); -void FillOutside (node_t *headnode); -void FloodAreas (tree_t *tree); -bspface_t *VisibleFaces(entity_t *e, tree_t *tree); -void FreePortal (portal_t *p); - -void MakeTreePortals (tree_t *tree); - -//============================================================================= - -// glfile.c - -void OutputWinding( winding_t *w, FILE *glview ); -void WriteGLView( tree_t *tree, char *source ); - -//============================================================================= - -// leakfile.c - -void LeakFile( tree_t *tree ); - -//============================================================================= - -// prtfile.c - -void NumberClusters( tree_t *tree ); -void WritePortalFile( tree_t *tree ); - -//============================================================================= - -// writebsp.c - -void SetModelNumbers (void); -void SetLightStyles (void); - -int EmitShader( const char *shader ); - -void BeginBSPFile (void); -void EndBSPFile (void); - -void BeginModel (void); -void EndModel( node_t *headnode ); - - -//============================================================================= - -// tree.c - -void FreeTree (tree_t *tree); -void FreeTree_r (node_t *node); -void PrintTree_r (node_t *node, int depth); -void FreeTreePortals_r (node_t *node); - -//============================================================================= - -// patch.c - -extern int numMapPatches; - -mapDrawSurface_t *DrawSurfaceForMesh( mesh_t *m ); -void ParsePatch( void ); -mesh_t *SubdivideMesh( mesh_t in, float maxError, float minLength ); -void PatchMapDrawSurfs( entity_t *e ); - -//============================================================================= - -// lightmap.c - -void AllocateLightmaps( entity_t *e ); - -//============================================================================= - -// tjunction.c - -void FixTJunctions( entity_t *e ); - - -//============================================================================= - -// fog.c - -void FogDrawSurfs( void ); -winding_t *WindingFromDrawSurf( mapDrawSurface_t *ds ); - -//============================================================================= - -// facebsp.c - -bspface_t *BspFaceForPortal( portal_t *p ); -bspface_t *MakeStructuralBspFaceList( bspbrush_t *list ); -bspface_t *MakeVisibleBspFaceList( bspbrush_t *list ); -tree_t *FaceBSP( bspface_t *list ); - -//============================================================================= - -// misc_model.c - -extern int c_triangleModels; -extern int c_triangleSurfaces; -extern int c_triangleVertexes; -extern int c_triangleIndexes; - -void AddTriangleModels( tree_t *tree ); - -//============================================================================= - -// surface.c - -extern mapDrawSurface_t mapDrawSurfs[MAX_MAP_DRAW_SURFS]; -extern int numMapDrawSurfs; - -mapDrawSurface_t *AllocDrawSurf( void ); -void MergeSides( entity_t *e, tree_t *tree ); -void SubdivideDrawSurfs( entity_t *e, tree_t *tree ); -void MakeDrawSurfaces( bspbrush_t *b ); -void ClipSidesIntoTree( entity_t *e, tree_t *tree ); -void FilterDrawsurfsIntoTree( entity_t *e, tree_t *tree ); - -//============================================================================== - -// brush_primit.c - -#define BPRIMIT_UNDEFINED 0 -#define BPRIMIT_OLDBRUSHES 1 -#define BPRIMIT_NEWBRUSHES 2 -extern int g_bBrushPrimit; - -void ComputeAxisBase( vec3_t normal, vec3_t texX, vec3_t texY); diff --git a/q3map/shaders.c b/q3map/shaders.c deleted file mode 100644 index 4adfcf0..0000000 --- a/q3map/shaders.c +++ /dev/null @@ -1,608 +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 <string.h> -#include <math.h> -#include "cmdlib.h" -#include "mathlib.h" -#include "imagelib.h" -#include "scriplib.h" - -#ifdef _TTIMOBUILD -#include "../common/qfiles.h" -#include "../common/surfaceflags.h" -#else -#include "../code/qcommon/qfiles.h" -#include "../code/game/surfaceflags.h" -#endif - -#include "shaders.h" -#ifdef _WIN32 - -#ifdef _TTIMOBUILD -#include "pakstuff.h" -#include "jpeglib.h" -#else -#include "../libs/pakstuff.h" -#include "../libs/jpeglib.h" -#endif - -#endif - - -// 5% backsplash by default -#define DEFAULT_BACKSPLASH_FRACTION 0.05 -#define DEFAULT_BACKSPLASH_DISTANCE 24 - - -#define MAX_SURFACE_INFO 4096 - -shaderInfo_t defaultInfo; -shaderInfo_t shaderInfo[MAX_SURFACE_INFO]; -int numShaderInfo; - - -typedef struct { - char *name; - int clearSolid, surfaceFlags, contents; -} infoParm_t; - -infoParm_t infoParms[] = { - // server relevant contents - {"water", 1, 0, CONTENTS_WATER }, - {"slime", 1, 0, CONTENTS_SLIME }, // mildly damaging - {"lava", 1, 0, CONTENTS_LAVA }, // very damaging - {"playerclip", 1, 0, CONTENTS_PLAYERCLIP }, - {"monsterclip", 1, 0, CONTENTS_MONSTERCLIP }, - {"nodrop", 1, 0, CONTENTS_NODROP }, // don't drop items or leave bodies (death fog, lava, etc) - {"nonsolid", 1, SURF_NONSOLID, 0}, // clears the solid flag - - // utility relevant attributes - {"origin", 1, 0, CONTENTS_ORIGIN }, // center of rotating brushes - {"trans", 0, 0, CONTENTS_TRANSLUCENT }, // don't eat contained surfaces - {"detail", 0, 0, CONTENTS_DETAIL }, // don't include in structural bsp - {"structural", 0, 0, CONTENTS_STRUCTURAL }, // force into structural bsp even if trnas - {"areaportal", 1, 0, CONTENTS_AREAPORTAL }, // divides areas - {"clusterportal",1, 0, CONTENTS_CLUSTERPORTAL },// for bots - {"donotenter", 1, 0, CONTENTS_DONOTENTER }, // for bots - {"botclip", 1, 0, CONTENTS_BOTCLIP }, // for bots - {"nobotclip", 0, 0, CONTENTS_NOBOTCLIP }, // don't use for bot clipping - - {"fog", 1, 0, CONTENTS_FOG}, // carves surfaces entering - {"sky", 0, SURF_SKY, 0 }, // emit light from an environment map - {"lightfilter", 0, SURF_LIGHTFILTER, 0 }, // filter light going through it - {"alphashadow", 0, SURF_ALPHASHADOW, 0 }, // test light on a per-pixel basis - {"hint", 0, SURF_HINT, 0 }, // use as a primary splitter - - // server attributes - {"slick", 0, SURF_SLICK, 0 }, - {"noimpact", 0, SURF_NOIMPACT, 0 }, // don't make impact explosions or marks - {"nomarks", 0, SURF_NOMARKS, 0 }, // don't make impact marks, but still explode - {"ladder", 0, SURF_LADDER, 0 }, - {"nodamage", 0, SURF_NODAMAGE, 0 }, - {"metalsteps", 0, SURF_METALSTEPS,0 }, - {"flesh", 0, SURF_FLESH, 0 }, - {"nosteps", 0, SURF_NOSTEPS, 0 }, - - // drawsurf attributes - {"nodraw", 0, SURF_NODRAW, 0 }, // don't generate a drawsurface (or a lightmap) - {"pointlight", 0, SURF_POINTLIGHT, 0 }, // sample lighting at vertexes - {"nolightmap", 0, SURF_NOLIGHTMAP,0 }, // don't generate a lightmap - {"nodlight", 0, SURF_NODLIGHT, 0 }, // don't ever add dynamic lights - {"dust", 0, SURF_DUST, 0} // leave dust trail when walking on this surface -}; - - -/* -=============== -LoadShaderImage -=============== -*/ - -byte* LoadImageFile(char *filename, qboolean *bTGA) -{ - byte *buffer = NULL; - int nLen = 0; - *bTGA = qtrue; - if (FileExists(filename)) - { - LoadFileBlock(filename, &buffer); - } -#ifdef _WIN32 - else - { - PakLoadAnyFile(filename, &buffer); - } -#endif - if ( buffer == NULL) - { - nLen = strlen(filename); - filename[nLen-3] = 'j'; - filename[nLen-2] = 'p'; - filename[nLen-1] = 'g'; - if (FileExists(filename)) - { - LoadFileBlock(filename, &buffer); - } -#ifdef _WIN32 - else - { - PakLoadAnyFile(filename, &buffer); - } -#endif - if ( buffer ) - { - *bTGA = qfalse; - } - } - return buffer; -} - -/* -=============== -LoadShaderImage -=============== -*/ -static void LoadShaderImage( shaderInfo_t *si ) { - char filename[1024]; - int i, count; - float color[4]; - byte *buffer; - qboolean bTGA = qtrue; - - // look for the lightimage if it is specified - if ( si->lightimage[0] ) { - sprintf( filename, "%s%s", gamedir, si->lightimage ); - DefaultExtension( filename, ".tga" ); - buffer = LoadImageFile(filename, &bTGA); - if ( buffer != NULL) { - goto loadTga; - } - } - - // look for the editorimage if it is specified - if ( si->editorimage[0] ) { - sprintf( filename, "%s%s", gamedir, si->editorimage ); - DefaultExtension( filename, ".tga" ); - buffer = LoadImageFile(filename, &bTGA); - if ( buffer != NULL) { - goto loadTga; - } - } - - // just try the shader name with a .tga - // on unix, we have case sensitivity problems... - sprintf( filename, "%s%s.tga", gamedir, si->shader ); - buffer = LoadImageFile(filename, &bTGA); - if ( buffer != NULL) { - goto loadTga; - } - - sprintf( filename, "%s%s.TGA", gamedir, si->shader ); - buffer = LoadImageFile(filename, &bTGA); - if ( buffer != NULL) { - goto loadTga; - } - - // couldn't load anything - _printf("WARNING: Couldn't find image for shader %s\n", si->shader ); - - si->color[0] = 1; - si->color[1] = 1; - si->color[2] = 1; - si->width = 64; - si->height = 64; - si->pixels = malloc( si->width * si->height * 4 ); - memset ( si->pixels, 255, si->width * si->height * 4 ); - return; - - // load the image to get dimensions and color -loadTga: - if ( bTGA) { - LoadTGABuffer( buffer, &si->pixels, &si->width, &si->height ); - } - else { -#ifdef _WIN32 - LoadJPGBuff(buffer, &si->pixels, &si->width, &si->height ); -#endif - } - - free(buffer); - - count = si->width * si->height; - - VectorClear( color ); - color[ 3 ] = 0; - for ( i = 0 ; i < count ; i++ ) { - color[0] += si->pixels[ i * 4 + 0 ]; - color[1] += si->pixels[ i * 4 + 1 ]; - color[2] += si->pixels[ i * 4 + 2 ]; - color[3] += si->pixels[ i * 4 + 3 ]; - } - ColorNormalize( color, si->color ); - VectorScale( color, 1.0/count, si->averageColor ); -} - -/* -=============== -AllocShaderInfo -=============== -*/ -static shaderInfo_t *AllocShaderInfo( void ) { - shaderInfo_t *si; - - if ( numShaderInfo == MAX_SURFACE_INFO ) { - Error( "MAX_SURFACE_INFO" ); - } - si = &shaderInfo[ numShaderInfo ]; - numShaderInfo++; - - // set defaults - - si->contents = CONTENTS_SOLID; - - si->backsplashFraction = DEFAULT_BACKSPLASH_FRACTION; - si->backsplashDistance = DEFAULT_BACKSPLASH_DISTANCE; - - si->lightmapSampleSize = 0; - si->forceTraceLight = qfalse; - si->forceVLight = qfalse; - si->patchShadows = qfalse; - si->vertexShadows = qfalse; - si->noVertexShadows = qfalse; - si->forceSunLight = qfalse; - si->vertexScale = 1.0; - si->notjunc = qfalse; - - return si; -} - -/* -=============== -ShaderInfoForShader -=============== -*/ -shaderInfo_t *ShaderInfoForShader( const char *shaderName ) { - int i; - shaderInfo_t *si; - char shader[MAX_QPATH]; - - // strip off extension - strcpy( shader, shaderName ); - StripExtension( shader ); - - // search for it - for ( i = 0 ; i < numShaderInfo ; i++ ) { - si = &shaderInfo[ i ]; - if ( !Q_stricmp( shader, si->shader ) ) { - if ( !si->width ) { - LoadShaderImage( si ); - } - return si; - } - } - - si = AllocShaderInfo(); - strcpy( si->shader, shader ); - - LoadShaderImage( si ); - - return si; -} - -/* -=============== -ParseShaderFile -=============== -*/ -static void ParseShaderFile( const char *filename ) { - int i; - int numInfoParms = sizeof(infoParms) / sizeof(infoParms[0]); - shaderInfo_t *si; - -// qprintf( "shaderFile: %s\n", filename ); - LoadScriptFile( filename ); - while ( 1 ) { - if ( !GetToken( qtrue ) ) { - break; - } - - si = AllocShaderInfo(); - strcpy( si->shader, token ); - MatchToken( "{" ); - while ( 1 ) { - if ( !GetToken( qtrue ) ) { - break; - } - if ( !strcmp( token, "}" ) ) { - break; - } - - // skip internal braced sections - if ( !strcmp( token, "{" ) ) { - si->hasPasses = qtrue; - while ( 1 ) { - if ( !GetToken( qtrue ) ) { - break; - } - if ( !strcmp( token, "}" ) ) { - break; - } - } - continue; - } - - if ( !Q_stricmp( token, "surfaceparm" ) ) { - GetToken( qfalse ); - for ( i = 0 ; i < numInfoParms ; i++ ) { - if ( !Q_stricmp( token, infoParms[i].name ) ) { - si->surfaceFlags |= infoParms[i].surfaceFlags; - si->contents |= infoParms[i].contents; - if ( infoParms[i].clearSolid ) { - si->contents &= ~CONTENTS_SOLID; - } - break; - } - } - if ( i == numInfoParms ) { - // we will silently ignore all tokens beginning with qer, - // which are QuakeEdRadient parameters - if ( Q_strncasecmp( token, "qer", 3 ) ) { - _printf( "Unknown surfaceparm: \"%s\"\n", token ); - } - } - continue; - } - - - // qer_editorimage <image> - if ( !Q_stricmp( token, "qer_editorimage" ) ) { - GetToken( qfalse ); - strcpy( si->editorimage, token ); - DefaultExtension( si->editorimage, ".tga" ); - continue; - } - - // q3map_lightimage <image> - if ( !Q_stricmp( token, "q3map_lightimage" ) ) { - GetToken( qfalse ); - strcpy( si->lightimage, token ); - DefaultExtension( si->lightimage, ".tga" ); - continue; - } - - // q3map_surfacelight <value> - if ( !Q_stricmp( token, "q3map_surfacelight" ) ) { - GetToken( qfalse ); - si->value = atoi( token ); - continue; - } - - // q3map_lightsubdivide <value> - if ( !Q_stricmp( token, "q3map_lightsubdivide" ) ) { - GetToken( qfalse ); - si->lightSubdivide = atoi( token ); - continue; - } - - // q3map_lightmapsamplesize <value> - if ( !Q_stricmp( token, "q3map_lightmapsamplesize" ) ) { - GetToken( qfalse ); - si->lightmapSampleSize = atoi( token ); - continue; - } - - // q3map_tracelight - if ( !Q_stricmp( token, "q3map_tracelight" ) ) { - si->forceTraceLight = qtrue; - continue; - } - - // q3map_vlight - if ( !Q_stricmp( token, "q3map_vlight" ) ) { - si->forceVLight = qtrue; - continue; - } - - // q3map_patchshadows - if ( !Q_stricmp( token, "q3map_patchshadows" ) ) { - si->patchShadows = qtrue; - continue; - } - - // q3map_vertexshadows - if ( !Q_stricmp( token, "q3map_vertexshadows" ) ) { - si->vertexShadows = qtrue; - continue; - } - - // q3map_novertexshadows - if ( !Q_stricmp( token, "q3map_novertexshadows" ) ) { - si->noVertexShadows = qtrue; - continue; - } - - // q3map_forcesunlight - if ( !Q_stricmp( token, "q3map_forcesunlight" ) ) { - si->forceSunLight = qtrue; - continue; - } - - // q3map_vertexscale - if ( !Q_stricmp( token, "q3map_vertexscale" ) ) { - GetToken( qfalse ); - si->vertexScale = atof(token); - continue; - } - - // q3map_notjunc - if ( !Q_stricmp( token, "q3map_notjunc" ) ) { - si->notjunc = qtrue; - continue; - } - - // q3map_globaltexture - if ( !Q_stricmp( token, "q3map_globaltexture" ) ) { - si->globalTexture = qtrue; - continue; - } - - // q3map_backsplash <percent> <distance> - if ( !Q_stricmp( token, "q3map_backsplash" ) ) { - GetToken( qfalse ); - si->backsplashFraction = atof( token ) * 0.01; - GetToken( qfalse ); - si->backsplashDistance = atof( token ); - continue; - } - - // q3map_backshader <shader> - if ( !Q_stricmp( token, "q3map_backshader" ) ) { - GetToken( qfalse ); - strcpy( si->backShader, token ); - continue; - } - - // q3map_flare <shader> - if ( !Q_stricmp( token, "q3map_flare" ) ) { - GetToken( qfalse ); - strcpy( si->flareShader, token ); - continue; - } - - // light <value> - // old style flare specification - if ( !Q_stricmp( token, "light" ) ) { - GetToken( qfalse ); - strcpy( si->flareShader, "flareshader" ); - continue; - } - - // q3map_sun <red> <green> <blue> <intensity> <degrees> <elivation> - // color will be normalized, so it doesn't matter what range you use - // intensity falls off with angle but not distance 100 is a fairly bright sun - // degree of 0 = from the east, 90 = north, etc. altitude of 0 = sunrise/set, 90 = noon - if ( !Q_stricmp( token, "q3map_sun" ) ) { - float a, b; - - GetToken( qfalse ); - si->sunLight[0] = atof( token ); - GetToken( qfalse ); - si->sunLight[1] = atof( token ); - GetToken( qfalse ); - si->sunLight[2] = atof( token ); - - VectorNormalize( si->sunLight, si->sunLight); - - GetToken( qfalse ); - a = atof( token ); - VectorScale( si->sunLight, a, si->sunLight); - - GetToken( qfalse ); - a = atof( token ); - a = a / 180 * Q_PI; - - GetToken( qfalse ); - b = atof( token ); - b = b / 180 * Q_PI; - - si->sunDirection[0] = cos( a ) * cos( b ); - si->sunDirection[1] = sin( a ) * cos( b ); - si->sunDirection[2] = sin( b ); - - si->surfaceFlags |= SURF_SKY; - continue; - } - - // tesssize is used to force liquid surfaces to subdivide - if ( !Q_stricmp( token, "tesssize" ) ) { - GetToken( qfalse ); - si->subdivisions = atof( token ); - continue; - } - - // cull none will set twoSided - if ( !Q_stricmp( token, "cull" ) ) { - GetToken( qfalse ); - if ( !Q_stricmp( token, "none" ) ) { - si->twoSided = qtrue; - } - continue; - } - - - // deformVertexes autosprite[2] - // we catch this so autosprited surfaces become point - // lights instead of area lights - if ( !Q_stricmp( token, "deformVertexes" ) ) { - GetToken( qfalse ); - if ( !Q_strncasecmp( token, "autosprite", 10 ) ) { - si->autosprite = qtrue; - si->contents = CONTENTS_DETAIL; - } - continue; - } - - - // ignore all other tokens on the line - - while ( TokenAvailable() ) { - GetToken( qfalse ); - } - } - } -} - -/* -=============== -LoadShaderInfo -=============== -*/ -#define MAX_SHADER_FILES 64 -void LoadShaderInfo( void ) { - char filename[1024]; - int i; - char *shaderFiles[MAX_SHADER_FILES]; - int numShaderFiles; - - sprintf( filename, "%sscripts/shaderlist.txt", gamedir ); - LoadScriptFile( filename ); - - numShaderFiles = 0; - while ( 1 ) { - if ( !GetToken( qtrue ) ) { - break; - } - shaderFiles[numShaderFiles] = malloc(MAX_OS_PATH); - strcpy( shaderFiles[ numShaderFiles ], token ); - numShaderFiles++; - } - - for ( i = 0 ; i < numShaderFiles ; i++ ) { - sprintf( filename, "%sscripts/%s.shader", gamedir, shaderFiles[i] ); - ParseShaderFile( filename ); - free(shaderFiles[i]); - } - - qprintf( "%5i shaderInfo\n", numShaderInfo); -} - diff --git a/q3map/shaders.h b/q3map/shaders.h deleted file mode 100644 index 27918bb..0000000 --- a/q3map/shaders.h +++ /dev/null @@ -1,71 +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 -=========================================================================== -*/ - - -typedef struct shaderInfo_s { - char shader[MAX_QPATH]; - int surfaceFlags; - int contents; - int value; - - char backShader[MAX_QPATH]; // for surfaces that generate different front and back passes - char flareShader[MAX_QPATH]; // for light flares - - float subdivisions; // from a "tesssize xxx" - float backsplashFraction; // floating point value, usually 0.05 - float backsplashDistance; // default 16 - float lightSubdivide; // default 120 - int lightmapSampleSize; // lightmap sample size - - qboolean hasPasses; // false if the shader doesn't define any rendering passes - - qboolean globalTexture; // don't normalize texture repeats - - qboolean twoSided; // cull none - qboolean autosprite; // autosprite shaders will become point lights - // instead of area lights - qboolean lightFilter; // light rays that cross surfaces of this type - // should test against the filter image - qboolean forceTraceLight; // always use -light for this surface - qboolean forceVLight; // always use -vlight for this surface - qboolean patchShadows; // have patches casting shadows when using -light for this surface - qboolean vertexShadows; // shadows will be casted at this surface even when vertex lit - qboolean noVertexShadows; // no shadows will be casted at this surface in vertex lighting - qboolean forceSunLight; // force sun light at this surface even tho we might not calculate shadows in vertex lighting - qboolean notjunc; // don't use this surface for tjunction fixing - float vertexScale; // vertex light scale - - char editorimage[MAX_QPATH]; // use this image to generate texture coordinates - char lightimage[MAX_QPATH]; // use this image to generate color / averageColor - vec3_t color; // colorNormalized - vec3_t averageColor; - - int width, height; - byte *pixels; - - vec3_t sunLight; - vec3_t sunDirection; -} shaderInfo_t; - -void LoadShaderInfo( void ); -shaderInfo_t *ShaderInfoForShader( const char *shader ); - diff --git a/q3map/soundv.c b/q3map/soundv.c deleted file mode 100644 index e7a57b6..0000000 --- a/q3map/soundv.c +++ /dev/null @@ -1,5742 +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 -=========================================================================== -*/ -/***************************************************************************** - * name: soundv.c - *****************************************************************************/ - -#include "cmdlib.h" -#include "mathlib.h" -#include "bspfile.h" -#include "imagelib.h" -#include "threads.h" -#include "mutex.h" -#include "scriplib.h" - -#include "shaders.h" -#include "mesh.h" - -#ifdef _WIN32 -//Improve floating-point consistency. -#pragma optimize( "p", on ) -#endif - -#ifdef _WIN32 -#include "../libs/pakstuff.h" -#endif - -#define MAX_CLUSTERS 16384 -#define MAX_PORTALS 32768 -#define MAX_FACETS 65536 -#define MAX_LIGHTS 16384 - -#define LIGHTMAP_SIZE 128 - -#define LIGHTMAP_PIXELSHIFT 0.5 - -//#define LIGHTMAP_PATCHSHIFT - -#define PORTALFILE "PRT1" - -#define ON_EPSILON 0.1 - -#define VectorSet(v, x, y, z) v[0] = x;v[1] = y;v[2] = z; - -typedef struct -{ - vec3_t normal; - float dist; -} plane_t; - -#define MAX_POINTS_ON_WINDING 64 -//NOTE: whenever this is overflowed parts of lightmaps might end up not being lit -#define MAX_POINTS_ON_FIXED_WINDING 48 - -typedef struct -{ - int numpoints; - vec3_t points[MAX_POINTS_ON_FIXED_WINDING]; // variable sized -} winding_t; - -typedef struct -{ - plane_t plane; // normal pointing into neighbor - int leaf; // neighbor - winding_t *winding; - vec3_t origin; // for fast clip testing - float radius; -} lportal_t; - -#define MAX_PORTALS_ON_LEAF 128 -typedef struct lleaf_s -{ - int numportals; - lportal_t *portals[MAX_PORTALS_ON_LEAF]; - // - int numSurfaces; - int firstSurface; -} lleaf_t; - -typedef struct lFacet_s -{ - int num; - plane_t plane; - vec3_t points[4]; // - int numpoints; - float lightmapCoords[4][2]; - plane_t boundaries[4]; // negative is outside the bounds - float textureMatrix[2][4]; // texture coordinates for translucency - float lightmapMatrix[2][4]; // lightmap texture coordinates - vec3_t mins; - int x, y, width, height; -} lFacet_t; - -typedef struct lsurfaceTest_s -{ - vec3_t mins, maxs; - vec3_t origin; - float radius; - qboolean patch; // true if this is a patch - qboolean trisoup; // true if this is a triangle soup - int numFacets; - lFacet_t *facets; - mesh_t *detailMesh; // detailed mesh with points for each lmp - shaderInfo_t *shader; // for translucency - mutex_t *mutex; - int numvolumes; // number of volumes casted at this surface - // - int always_tracelight; - int always_vsound; -} lsurfaceTest_t; - -//volume types -#define VOLUME_NORMAL 0 -#define VOLUME_DIRECTED 1 - -#define MAX_TRANSLUCENTFACETS 32 - -typedef struct lightvolume_s -{ - int num; - int cluster; //cluster this light volume started in - plane_t endplane; //end plane - plane_t farplane; //original end plane - vec3_t points[MAX_POINTS_ON_WINDING]; //end winding points - plane_t planes[MAX_POINTS_ON_WINDING]; //volume bounding planes - int numplanes; //number of volume bounding planes - int type; //light volume type - //list with translucent surfaces the volume went through - int transFacets[MAX_TRANSLUCENTFACETS]; - int transSurfaces[MAX_TRANSLUCENTFACETS]; - int numtransFacets; - //clusters already tested - byte clusterTested[MAX_CLUSTERS/8]; - //facets already tested - byte facetTested[MAX_FACETS/8]; - int facetNum; //number of the facet blocking the light in this volume - int surfaceNum; //number of the surface blocking the light in this volume -} lightvolume_t; - -//light types -#define LIGHT_POINTRADIAL 1 -#define LIGHT_POINTSPOT 2 -#define LIGHT_POINTFAKESURFACE 3 -#define LIGHT_SURFACEDIRECTED 4 -#define LIGHT_SURFACERADIAL 5 -#define LIGHT_SURFACESPOT 6 - -//light distance attenuation types -#define LDAT_QUADRATIC 0 -#define LDAT_LINEAR 1 -#define LDAT_NOSCALE 2 - -//light angle attenuation types -#define LAAT_NORMAL 0 -#define LAAT_QUADRATIC 1 -#define LAAT_DOUBLEQUADRATIC 2 - -typedef struct vsound_s -{ - vec3_t origin; //light origin, for point lights - winding_t w; //light winding, for area lights - vec4_t plane; //light winding plane - vec3_t normal; //direction of the light - int type; //light type - vec3_t color; //light color - qboolean twosided; //radiates light at both sides of the winding - int style; //light style (not used) - int atten_disttype; //light distance attenuation type - int atten_angletype; //light angle attenuation type - float atten_distscale; //distance attenuation scale - float atten_anglescale; //angle attenuation scale - float radiusByDist; //radius by distance for spot lights - float photons; //emitted photons - float intensity; //intensity - vec3_t emitColor; //full out-of-gamut value (not used) - struct shaderInfo_s *si; //shader info - int insolid; //set when light is in solid -} vsound_t; - -static float lightLinearScale = 1.0 / 8000; -static float lightPointScale = 7500; -static float lightAreaScale = 0.25; -static float lightFormFactorValueScale = 3; -static int lightDefaultSubdivide = 999; // vary by surface size? -static vec3_t lightAmbientColor; - -static int portalclusters, numportals, numfaces; -static lleaf_t *leafs; -static lportal_t *portals; -static int numvsounds = 0; -static vsound_t *vsounds[MAX_LIGHTS]; -static int nostitching = 0; -static int noalphashading = 0; -static int nocolorshading = 0; -static int nobackfaceculling = 0; -static int defaulttracelight = 0; -static int radiosity = 0; -static int radiosity_scale; - -static int clustersurfaces[MAX_MAP_LEAFFACES]; -static int numclustersurfaces = 0; -static lsurfaceTest_t *lsurfaceTest[MAX_MAP_DRAW_SURFS]; -static int numfacets; -static float lightmappixelarea[MAX_MAP_LIGHTING/3]; -static float *lightFloats;//[MAX_MAP_LIGHTING]; - -// from polylib.c -winding_t *AllocWinding (int points); -void FreeWinding (winding_t *w); -void WindingCenter (winding_t *w, vec3_t center); -void WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs); -vec_t WindingArea (winding_t *w); -winding_t *BaseWindingForPlane (vec3_t normal, vec_t dist); -void ClipWindingEpsilon (winding_t *in, vec3_t normal, vec_t dist, - vec_t epsilon, winding_t **front, winding_t **back); -winding_t *ReverseWinding (winding_t *w); - -// from light.c -extern char source[1024]; -extern vec3_t surfaceOrigin[ MAX_MAP_DRAW_SURFS ]; -extern int entitySurface[ MAX_MAP_DRAW_SURFS ]; -extern int samplesize; -extern qboolean patchshadows; -extern vec3_t gridSize; - -float PointToPolygonFormFactor( const vec3_t point, const vec3_t normal, const winding_t *w ); -void ColorToBytes( const float *color, byte *colorBytes ); -void CountLightmaps( void ); -void GridAndVertexLighting( void ); -void SetEntityOrigins( void ); - - -//#define DEBUGNET - -#ifdef DEBUGNET - -#include "l_net.h" - -socket_t *debug_socket; - -/* -===================== -DebugNet_Setup -===================== -*/ -void DebugNet_Setup(void) -{ - address_t address; - int i; - - Net_Setup(); - Net_StringToAddress("127.0.0.1:28000", &address); - for (i = 0; i < 10; i++) - { - debug_socket = Net_Connect(&address, 28005 + i); - if (debug_socket) - break; - } -} - -/* -===================== -DebugNet_Shutdown -===================== -*/ -void DebugNet_Shutdown(void) -{ - netmessage_t msg; - - if (debug_socket) - { - NMSG_Clear(&msg); - NMSG_WriteByte(&msg, 1); - Net_Send(debug_socket, &msg); - Net_Disconnect(debug_socket); - } - debug_socket = NULL; - Net_Shutdown(); -} - -/* -===================== -DebugNet_RemoveAllPolys -===================== -*/ -void DebugNet_RemoveAllPolys(void) -{ - netmessage_t msg; - - if (!debug_socket) - return; - NMSG_Clear(&msg); - NMSG_WriteByte(&msg, 2); //remove all debug polys - Net_Send(debug_socket, &msg); -} - -/* -==================== -DebugNet_DrawWinding -===================== -*/ -void DebugNet_DrawWinding(winding_t *w, int color) -{ - netmessage_t msg; - int i; - - if (!debug_socket) - return; - NMSG_Clear(&msg); - NMSG_WriteByte(&msg, 0); //draw a winding - NMSG_WriteByte(&msg, w->numpoints); //number of points - NMSG_WriteLong(&msg, color); //color - for (i = 0; i < w->numpoints; i++) - { - NMSG_WriteFloat(&msg, w->points[i][0]); - NMSG_WriteFloat(&msg, w->points[i][1]); - NMSG_WriteFloat(&msg, w->points[i][2]); - } - Net_Send(debug_socket, &msg); -} - -/* -===================== -DebugNet_DrawLine -===================== -*/ -void DebugNet_DrawLine(vec3_t p1, vec3_t p2, int color) -{ - netmessage_t msg; - - if (!debug_socket) - return; - NMSG_Clear(&msg); - NMSG_WriteByte(&msg, 1); //draw a line - NMSG_WriteLong(&msg, color); //color - NMSG_WriteFloat(&msg, p1[0]); - NMSG_WriteFloat(&msg, p1[1]); - NMSG_WriteFloat(&msg, p1[2]); - NMSG_WriteFloat(&msg, p2[0]); - NMSG_WriteFloat(&msg, p2[1]); - NMSG_WriteFloat(&msg, p2[2]); - Net_Send(debug_socket, &msg); -} - -/* -===================== -DebugNet_DrawMesh -===================== -*/ -void DebugNet_DrawMesh(mesh_t *mesh) -{ - int i, j; - float dot; - drawVert_t *v1, *v2, *v3, *v4; - winding_t winding; - plane_t plane; - vec3_t d1, d2; - - for ( i = 0 ; i < mesh->width - 1 ; i++ ) { - for ( j = 0 ; j < mesh->height - 1 ; j++ ) { - - v1 = mesh->verts + j * mesh->width + i; - v2 = v1 + 1; - v3 = v1 + mesh->width + 1; - v4 = v1 + mesh->width; - - VectorSubtract( v4->xyz, v1->xyz, d1 ); - VectorSubtract( v3->xyz, v1->xyz, d2 ); - CrossProduct( d2, d1, plane.normal ); - if ( VectorNormalize( plane.normal, plane.normal ) != 0 ) - { - plane.dist = DotProduct( v1->xyz, plane.normal ); - dot = DotProduct(plane.normal, v2->xyz) - plane.dist; - if (fabs(dot) < 0.1) - { - VectorCopy(v1->xyz, winding.points[0]); - VectorCopy(v4->xyz, winding.points[1]); - VectorCopy(v3->xyz, winding.points[2]); - VectorCopy(v2->xyz, winding.points[3]); - winding.numpoints = 4; - DebugNet_DrawWinding(&winding, 2); - continue; - } - } - - winding.numpoints = 3; - VectorCopy(v1->xyz, winding.points[0]); - VectorCopy(v4->xyz, winding.points[1]); - VectorCopy(v3->xyz, winding.points[2]); - DebugNet_DrawWinding(&winding, 2); - - VectorCopy(v1->xyz, winding.points[0]); - VectorCopy(v3->xyz, winding.points[1]); - VectorCopy(v2->xyz, winding.points[2]); - DebugNet_DrawWinding(&winding, 2); - } - } -} - -/* -===================== -VS_DrawLightVolume -===================== -*/ -int VS_ChopWinding (winding_t *in, plane_t *split, float epsilon); - -void VS_DrawLightVolume(vsound_t *light, lightvolume_t *volume) -{ - winding_t w; - int i; - vec3_t p2, invsound; - - memcpy(w.points, volume->points, volume->numplanes * sizeof(vec3_t)); - w.numpoints = volume->numplanes; - DebugNet_DrawWinding(&w, 2); - - if (volume->type == VOLUME_DIRECTED) - { - VectorCopy(light->normal, invsound); - VectorInverse(invsound); - for (i = 0; i < volume->numplanes; i++) - { - VectorCopy(volume->points[i], w.points[0]); - VectorCopy(volume->points[(i+1) % volume->numplanes], w.points[1]); - VectorMA(w.points[1], MAX_WORLD_COORD, invsound, w.points[2]); - VectorMA(w.points[0], MAX_WORLD_COORD, invsound, w.points[3]); - w.numpoints = 4; - DebugNet_DrawWinding(&w, 2); - VectorMA(volume->points[i], 8, volume->planes[i].normal, p2); - DebugNet_DrawLine(volume->points[i], p2, 3); - } - } - else - { - // - VectorCopy(light->origin, w.points[0]); - w.numpoints = 3; - for (i = 0; i < volume->numplanes; i++) - { - VectorCopy(volume->points[i], w.points[1]); - VectorCopy(volume->points[(i+1) % volume->numplanes], w.points[2]); - VS_ChopWinding(&w, &volume->endplane, 0); - DebugNet_DrawWinding(&w, 2); - VectorMA(volume->points[i], 8, volume->planes[i].normal, p2); - DebugNet_DrawLine(volume->points[i], p2, 3); - } - } -} - -/* -============= -VS_DrawLightmapPixel -============= -*/ -void VS_DrawLightmapPixel(int surfaceNum, int x, int y, int color) -{ - winding_t w; - dsurface_t *ds; - mesh_t *mesh; - - ds = &drawSurfaces[surfaceNum]; - - if (ds->surfaceType == MST_PATCH) - { - mesh = lsurfaceTest[surfaceNum]->detailMesh; - VectorCopy( mesh->verts[(y-ds->lightmapY)*mesh->width+x-ds->lightmapX].xyz, w.points[0]); - VectorCopy( mesh->verts[(y+1-ds->lightmapY)*mesh->width+x-ds->lightmapX].xyz, w.points[1]); - VectorCopy( mesh->verts[(y+1-ds->lightmapY)*mesh->width+x+1-ds->lightmapX].xyz, w.points[2]); - VectorCopy( mesh->verts[(y-ds->lightmapY)*mesh->width+x+1-ds->lightmapX].xyz, w.points[3]); - w.numpoints = 4; - } - else - { - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT - ds->lightmapX, ds->lightmapVecs[0], w.points[0]); - VectorMA(w.points[0], (float) y - LIGHTMAP_PIXELSHIFT - ds->lightmapY, ds->lightmapVecs[1], w.points[0]); - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT - ds->lightmapX, ds->lightmapVecs[0], w.points[1]); - VectorMA(w.points[1], (float) y - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapY, ds->lightmapVecs[1], w.points[1]); - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapX, ds->lightmapVecs[0], w.points[2]); - VectorMA(w.points[2], (float) y - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapY, ds->lightmapVecs[1], w.points[2]); - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapX, ds->lightmapVecs[0], w.points[3]); - VectorMA(w.points[3], (float) y - LIGHTMAP_PIXELSHIFT - ds->lightmapY, ds->lightmapVecs[1], w.points[3]); - w.numpoints = 4; - } - DebugNet_DrawWinding(&w, color); -} - -/* -============ -VS_DrawPortals -============ -*/ -void VS_DrawPortals(void) -{ - int j; - lportal_t *p; - - for (j = 0; j < numportals * 2; j++) - { - p = portals + j; - DebugNet_DrawWinding(p->winding, 1); - } -} - -/* -============ -VS_DrawLeaf -============ -*/ -void VS_DrawLeaf(int cluster) -{ - int i; - lleaf_t *leaf; - lportal_t *p; - - leaf = &leafs[cluster]; - for (i = 0; i < leaf->numportals; i++) - { - p = leaf->portals[i]; - DebugNet_DrawWinding(p->winding, 1); - } -} - -#endif //DEBUGNET - -/* -============= -VS_SplitWinding -============= -*/ -int VS_SplitWinding (winding_t *in, winding_t *back, plane_t *split, float epsilon) -{ - vec_t dists[128]; - int sides[128]; - int counts[3]; - vec_t dot; - int i, j; - vec_t *p1, *p2; - vec3_t mid; - winding_t out; - winding_t *neww; - - counts[0] = counts[1] = counts[2] = 0; - - // determine sides for each point - for (i=0 ; i<in->numpoints ; i++) - { - dot = DotProduct (in->points[i], split->normal); - dot -= split->dist; - dists[i] = dot; - if (dot > epsilon) - sides[i] = SIDE_FRONT; - else if (dot < -epsilon) - sides[i] = SIDE_BACK; - else - { - sides[i] = SIDE_ON; - } - counts[sides[i]]++; - } - - if (!counts[SIDE_BACK]) - { - if (!counts[SIDE_FRONT]) - return SIDE_ON; - else - return SIDE_FRONT; - } - - if (!counts[SIDE_FRONT]) - { - return SIDE_BACK; - } - - sides[i] = sides[0]; - dists[i] = dists[0]; - - neww = &out; - - neww->numpoints = 0; - back->numpoints = 0; - - for (i=0 ; i<in->numpoints ; i++) - { - p1 = in->points[i]; - - if (neww->numpoints >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VS_SplitWinding -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return SIDE_FRONT; // can't chop -- fall back to original - } - if (back->numpoints >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VS_SplitWinding -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return SIDE_FRONT; - } - - if (sides[i] == SIDE_ON) - { - VectorCopy (p1, neww->points[neww->numpoints]); - neww->numpoints++; - VectorCopy (p1, back->points[back->numpoints]); - back->numpoints++; - continue; - } - - if (sides[i] == SIDE_FRONT) - { - VectorCopy (p1, neww->points[neww->numpoints]); - neww->numpoints++; - } - if (sides[i] == SIDE_BACK) - { - VectorCopy (p1, back->points[back->numpoints]); - back->numpoints++; - } - - if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) - continue; - - if (neww->numpoints >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VS_SplitWinding -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return SIDE_FRONT; // can't chop -- fall back to original - } - - if (back->numpoints >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VS_SplitWinding -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return SIDE_FRONT; // can't chop -- fall back to original - } - - // generate a split point - p2 = in->points[(i+1)%in->numpoints]; - - dot = dists[i] / (dists[i]-dists[i+1]); - for (j=0 ; j<3 ; j++) - { // avoid round off error when possible - if (split->normal[j] == 1) - mid[j] = split->dist; - else if (split->normal[j] == -1) - mid[j] = -split->dist; - else - mid[j] = p1[j] + dot*(p2[j]-p1[j]); - } - - VectorCopy (mid, neww->points[neww->numpoints]); - neww->numpoints++; - VectorCopy (mid, back->points[back->numpoints]); - back->numpoints++; - } - memcpy(in, &out, sizeof(winding_t)); - - return SIDE_CROSS; -} - -/* -===================== -VS_LinkSurfaceIntoCluster -===================== -*/ -void VS_LinkSurfaceIntoCluster(int cluster, int surfaceNum) -{ - lleaf_t *leaf; - int i; - - leaf = &leafs[cluster]; - - for (i = 0; i < leaf->numSurfaces; i++) - { - if (clustersurfaces[leaf->firstSurface + i] == surfaceNum) - return; - } - for (i = numclustersurfaces; i > leaf->firstSurface + leaf->numSurfaces; i--) - clustersurfaces[i] = clustersurfaces[i-1]; - for (i = 0; i < portalclusters; i++) - { - if (i == cluster) - continue; - if (leafs[i].firstSurface >= leaf->firstSurface + leaf->numSurfaces) - leafs[i].firstSurface++; - } - clustersurfaces[leaf->firstSurface + leaf->numSurfaces] = surfaceNum; - leaf->numSurfaces++; - numclustersurfaces++; - if (numclustersurfaces >= MAX_MAP_LEAFFACES) - Error("MAX_MAP_LEAFFACES"); -} - -/* -===================== -VS_R_LinkSurface -===================== -*/ -void VS_R_LinkSurface(int nodenum, int surfaceNum, winding_t *w) -{ - int leafnum, cluster, res; - dnode_t *node; - dplane_t *plane; - winding_t back; - plane_t split; - - while(nodenum >= 0) - { - node = &dnodes[nodenum]; - plane = &dplanes[node->planeNum]; - - VectorCopy(plane->normal, split.normal); - split.dist = plane->dist; - res = VS_SplitWinding (w, &back, &split, 0.1); - - if (res == SIDE_FRONT) - { - nodenum = node->children[0]; - } - else if (res == SIDE_BACK) - { - nodenum = node->children[1]; - } - else if (res == SIDE_ON) - { - memcpy(&back, w, sizeof(winding_t)); - VS_R_LinkSurface(node->children[1], surfaceNum, &back); - nodenum = node->children[0]; - } - else - { - VS_R_LinkSurface(node->children[1], surfaceNum, &back); - nodenum = node->children[0]; - } - } - leafnum = -nodenum - 1; - cluster = dleafs[leafnum].cluster; - if (cluster != -1) - { - VS_LinkSurfaceIntoCluster(cluster, surfaceNum); - } -} - -/* -===================== -VS_LinkSurfaces - -maybe link each facet seperately instead of the test surfaces? -===================== -*/ -void VS_LinkSurfaces(void) -{ - int i, j; - lsurfaceTest_t *test; - lFacet_t *facet; - winding_t winding; - - for ( i = 0 ; i < numDrawSurfaces ; i++ ) - { - test = lsurfaceTest[ i ]; - if (!test) - continue; - for (j = 0; j < test->numFacets; j++) - { - facet = &test->facets[j]; - memcpy(winding.points, facet->points, facet->numpoints * sizeof(vec3_t)); - winding.numpoints = facet->numpoints; - VS_R_LinkSurface(0, i, &winding); - } - } -} - -/* -===================== -VS_TextureMatrixFromPoints -===================== -*/ -void VS_TextureMatrixFromPoints( lFacet_t *f, drawVert_t *a, drawVert_t *b, drawVert_t *c ) { - int i, j; - float t; - float m[3][4]; - float s; - - // This is an incredibly stupid way of solving a three variable equation - for ( i = 0 ; i < 2 ; i++ ) { - - m[0][0] = a->xyz[0]; - m[0][1] = a->xyz[1]; - m[0][2] = a->xyz[2]; - m[0][3] = a->st[i]; - - m[1][0] = b->xyz[0]; - m[1][1] = b->xyz[1]; - m[1][2] = b->xyz[2]; - m[1][3] = b->st[i]; - - m[2][0] = c->xyz[0]; - m[2][1] = c->xyz[1]; - m[2][2] = c->xyz[2]; - m[2][3] = c->st[i]; - - if ( fabs(m[1][0]) > fabs(m[0][0]) && fabs(m[1][0]) > fabs(m[2][0]) ) { - for ( j = 0 ; j < 4 ; j ++ ) { - t = m[0][j]; - m[0][j] = m[1][j]; - m[1][j] = t; - } - } else if ( fabs(m[2][0]) > fabs(m[0][0]) && fabs(m[2][0]) > fabs(m[1][0]) ) { - for ( j = 0 ; j < 4 ; j ++ ) { - t = m[0][j]; - m[0][j] = m[2][j]; - m[2][j] = t; - } - } - - s = 1.0 / m[0][0]; - m[0][0] *= s; - m[0][1] *= s; - m[0][2] *= s; - m[0][3] *= s; - - s = m[1][0]; - m[1][0] -= m[0][0] * s; - m[1][1] -= m[0][1] * s; - m[1][2] -= m[0][2] * s; - m[1][3] -= m[0][3] * s; - - s = m[2][0]; - m[2][0] -= m[0][0] * s; - m[2][1] -= m[0][1] * s; - m[2][2] -= m[0][2] * s; - m[2][3] -= m[0][3] * s; - - if ( fabs(m[2][1]) > fabs(m[1][1]) ) { - for ( j = 0 ; j < 4 ; j ++ ) { - t = m[1][j]; - m[1][j] = m[2][j]; - m[2][j] = t; - } - } - - s = 1.0 / m[1][1]; - m[1][0] *= s; - m[1][1] *= s; - m[1][2] *= s; - m[1][3] *= s; - - s = m[2][1];// / m[1][1]; - m[2][0] -= m[1][0] * s; - m[2][1] -= m[1][1] * s; - m[2][2] -= m[1][2] * s; - m[2][3] -= m[1][3] * s; - - s = 1.0 / m[2][2]; - m[2][0] *= s; - m[2][1] *= s; - m[2][2] *= s; - m[2][3] *= s; - - f->textureMatrix[i][2] = m[2][3]; - f->textureMatrix[i][1] = m[1][3] - f->textureMatrix[i][2] * m[1][2]; - f->textureMatrix[i][0] = m[0][3] - f->textureMatrix[i][2] * m[0][2] - f->textureMatrix[i][1] * m[0][1]; - - f->textureMatrix[i][3] = 0; -/* - s = fabs( DotProduct( a->xyz, f->textureMatrix[i] ) - a->st[i] ); - if ( s > 0.01 ) { - Error( "Bad textureMatrix" ); - } - s = fabs( DotProduct( b->xyz, f->textureMatrix[i] ) - b->st[i] ); - if ( s > 0.01 ) { - Error( "Bad textureMatrix" ); - } - s = fabs( DotProduct( c->xyz, f->textureMatrix[i] ) - c->st[i] ); - if ( s > 0.01 ) { - Error( "Bad textureMatrix" ); - } -*/ - } -} - -/* -===================== -VS_LightmapMatrixFromPoints -===================== -*/ -void VS_LightmapMatrixFromPoints( dsurface_t *dsurf, shaderInfo_t *si, lFacet_t *f, drawVert_t *a, drawVert_t *b, drawVert_t *c ) { - int i, j; - float t; - float m[3][4], al, bl, cl; - float s; - int h, w, ssize; - vec3_t mins, maxs, delta, size, planeNormal; - drawVert_t *verts; - static int message; - - // vertex-lit triangle model - if ( dsurf->surfaceType == MST_TRIANGLE_SOUP ) { - return; - } - - if ( dsurf->lightmapNum < 0 ) { - return; // doesn't need lighting - } - - VectorClear(f->mins); - if (dsurf->surfaceType != MST_PATCH) - { - ssize = samplesize; - if (si->lightmapSampleSize) - ssize = si->lightmapSampleSize; - ClearBounds( mins, maxs ); - verts = &drawVerts[dsurf->firstVert]; - for ( i = 0 ; i < dsurf->numVerts ; i++ ) { - AddPointToBounds( verts[i].xyz, mins, maxs ); - } - // round to the lightmap resolution - for ( i = 0 ; i < 3 ; i++ ) { - mins[i] = ssize * floor( mins[i] / ssize ); - maxs[i] = ssize * ceil( maxs[i] / ssize ); - f->mins[i] = mins[i]; - size[i] = (maxs[i] - mins[i]) / ssize + 1; - } - // the two largest axis will be the lightmap size - VectorClear(f->lightmapMatrix[0]); - f->lightmapMatrix[0][3] = 0; - VectorClear(f->lightmapMatrix[1]); - f->lightmapMatrix[1][3] = 0; - - planeNormal[0] = fabs( dsurf->lightmapVecs[2][0] ); - planeNormal[1] = fabs( dsurf->lightmapVecs[2][1] ); - planeNormal[2] = fabs( dsurf->lightmapVecs[2][2] ); - - if ( planeNormal[0] >= planeNormal[1] && planeNormal[0] >= planeNormal[2] ) { - w = size[1]; - h = size[2]; - f->lightmapMatrix[0][1] = 1.0 / ssize; - f->lightmapMatrix[1][2] = 1.0 / ssize; - } else if ( planeNormal[1] >= planeNormal[0] && planeNormal[1] >= planeNormal[2] ) { - w = size[0]; - h = size[2]; - f->lightmapMatrix[0][0] = 1.0 / ssize; - f->lightmapMatrix[1][2] = 1.0 / ssize; - } else { - w = size[0]; - h = size[1]; - f->lightmapMatrix[0][0] = 1.0 / ssize; - f->lightmapMatrix[1][1] = 1.0 / ssize; - } - if ( w > LIGHTMAP_WIDTH ) { - VectorScale ( f->lightmapMatrix[0], (float)LIGHTMAP_SIZE/w, f->lightmapMatrix[0] ); - } - - if ( h > LIGHTMAP_HEIGHT ) { - VectorScale ( f->lightmapMatrix[1], (float)LIGHTMAP_SIZE/h, f->lightmapMatrix[1] ); - } - VectorSubtract(a->xyz, f->mins, delta); - s = (DotProduct( delta, f->lightmapMatrix[0] ) + dsurf->lightmapX + 0.5) / LIGHTMAP_SIZE; - if ( fabs(s - a->lightmap[0]) > 0.01 ) { - _printf( "Bad lightmapMatrix" ); - } - t = (DotProduct( delta, f->lightmapMatrix[1] ) + dsurf->lightmapY + 0.5) / LIGHTMAP_SIZE; - if ( fabs(t - a->lightmap[1]) > 0.01 ) { - _printf( "Bad lightmapMatrix" ); - } - VectorSubtract(b->xyz, f->mins, delta); - s = (DotProduct( delta, f->lightmapMatrix[0] ) + dsurf->lightmapX + 0.5) / LIGHTMAP_SIZE; - if ( fabs(s - b->lightmap[0]) > 0.01 ) { - _printf( "Bad lightmapMatrix" ); - } - t = (DotProduct( delta, f->lightmapMatrix[1] ) + dsurf->lightmapY + 0.5) / LIGHTMAP_SIZE; - if ( fabs(t - b->lightmap[1]) > 0.01 ) { - _printf( "Bad lightmapMatrix" ); - } - VectorSubtract(c->xyz, f->mins, delta); - s = (DotProduct( delta, f->lightmapMatrix[0] ) + dsurf->lightmapX + 0.5) / LIGHTMAP_SIZE; - if ( fabs(s - c->lightmap[0]) > 0.01 ) { - _printf( "Bad lightmapMatrix" ); - } - t = (DotProduct( delta, f->lightmapMatrix[1] ) + dsurf->lightmapY + 0.5) / LIGHTMAP_SIZE; - if ( fabs(t - c->lightmap[1]) > 0.01 ) { - _printf( "Bad lightmapMatrix" ); - } - VectorAdd(f->mins, surfaceOrigin[dsurf - drawSurfaces], f->mins); - return; - } - // This is an incredibly stupid way of solving a three variable equation - for ( i = 0 ; i < 2 ; i++ ) { - - if (i) - al = a->lightmap[i] - ((float) dsurf->lightmapY + 0.5) / LIGHTMAP_SIZE; - else - al = a->lightmap[i] - ((float) dsurf->lightmapX + 0.5) / LIGHTMAP_SIZE; - - m[0][0] = a->xyz[0] - f->mins[0]; - m[0][1] = a->xyz[1] - f->mins[1]; - m[0][2] = a->xyz[2] - f->mins[2]; - m[0][3] = al; - - if (i) - bl = b->lightmap[i] - ((float) dsurf->lightmapY + 0.5) / LIGHTMAP_SIZE; - else - bl = b->lightmap[i] - ((float) dsurf->lightmapX + 0.5) / LIGHTMAP_SIZE; - - m[1][0] = b->xyz[0] - f->mins[0]; - m[1][1] = b->xyz[1] - f->mins[1]; - m[1][2] = b->xyz[2] - f->mins[2]; - m[1][3] = bl; - - if (i) - cl = c->lightmap[i] - ((float) dsurf->lightmapY + 0.5) / LIGHTMAP_SIZE; - else - cl = c->lightmap[i] - ((float) dsurf->lightmapX + 0.5) / LIGHTMAP_SIZE; - - m[2][0] = c->xyz[0] - f->mins[0]; - m[2][1] = c->xyz[1] - f->mins[1]; - m[2][2] = c->xyz[2] - f->mins[2]; - m[2][3] = cl; - - if ( fabs(m[1][0]) > fabs(m[0][0]) && fabs(m[1][0]) >= fabs(m[2][0]) ) { - for ( j = 0 ; j < 4 ; j ++ ) { - t = m[0][j]; - m[0][j] = m[1][j]; - m[1][j] = t; - } - } else if ( fabs(m[2][0]) > fabs(m[0][0]) && fabs(m[2][0]) >= fabs(m[1][0]) ) { - for ( j = 0 ; j < 4 ; j ++ ) { - t = m[0][j]; - m[0][j] = m[2][j]; - m[2][j] = t; - } - } - - if (m[0][0]) - { - s = 1.0 / m[0][0]; - m[0][0] *= s; - m[0][1] *= s; - m[0][2] *= s; - m[0][3] *= s; - - s = m[1][0]; - m[1][0] -= m[0][0] * s; - m[1][1] -= m[0][1] * s; - m[1][2] -= m[0][2] * s; - m[1][3] -= m[0][3] * s; - - s = m[2][0]; - m[2][0] -= m[0][0] * s; - m[2][1] -= m[0][1] * s; - m[2][2] -= m[0][2] * s; - m[2][3] -= m[0][3] * s; - } - - if ( fabs(m[2][1]) > fabs(m[1][1]) ) { - for ( j = 0 ; j < 4 ; j ++ ) { - t = m[1][j]; - m[1][j] = m[2][j]; - m[2][j] = t; - } - } - - if (m[1][1]) - { - s = 1.0 / m[1][1]; - m[1][0] *= s; - m[1][1] *= s; - m[1][2] *= s; - m[1][3] *= s; - - s = m[2][1]; - m[2][0] -= m[1][0] * s; - m[2][1] -= m[1][1] * s; - m[2][2] -= m[1][2] * s; - m[2][3] -= m[1][3] * s; - } - - if (m[2][2]) - { - s = 1.0 / m[2][2]; - m[2][0] *= s; - m[2][1] *= s; - m[2][2] *= s; - m[2][3] *= s; - } - - f->lightmapMatrix[i][2] = m[2][3]; - f->lightmapMatrix[i][1] = m[1][3] - f->lightmapMatrix[i][2] * m[1][2]; - f->lightmapMatrix[i][0] = m[0][3] - f->lightmapMatrix[i][2] * m[0][2] - f->lightmapMatrix[i][1] * m[0][1]; - - f->lightmapMatrix[i][3] = 0; - - VectorSubtract(a->xyz, f->mins, delta); - s = fabs( DotProduct( delta, f->lightmapMatrix[i] ) - al ); - if ( s > 0.01 ) { - if (!message) - _printf( "Bad lightmapMatrix\n" ); - message = qtrue; - } - VectorSubtract(b->xyz, f->mins, delta); - s = fabs( DotProduct( delta, f->lightmapMatrix[i] ) - bl ); - if ( s > 0.01 ) { - if (!message) - _printf( "Bad lightmapMatrix\n" ); - message = qtrue; - } - VectorSubtract(c->xyz, f->mins, delta); - s = fabs( DotProduct( delta, f->lightmapMatrix[i] ) - cl ); - if ( s > 0.01 ) { - if (!message) - _printf( "Bad lightmapMatrix\n" ); - message = qtrue; - } - VectorAdd(f->mins, surfaceOrigin[dsurf - drawSurfaces], f->mins); - } -} - -/* -============= -Plane_Equal -============= -*/ -#define NORMAL_EPSILON 0.0001 -#define DIST_EPSILON 0.02 - -static int Plane_Equal(plane_t *a, plane_t *b, int flip) -{ - vec3_t normal; - float dist; - - if (flip) { - normal[0] = - b->normal[0]; - normal[1] = - b->normal[1]; - normal[2] = - b->normal[2]; - dist = - b->dist; - } - else { - normal[0] = b->normal[0]; - normal[1] = b->normal[1]; - normal[2] = b->normal[2]; - dist = b->dist; - } - if ( - fabs(a->normal[0] - normal[0]) < NORMAL_EPSILON - && fabs(a->normal[1] - normal[1]) < NORMAL_EPSILON - && fabs(a->normal[2] - normal[2]) < NORMAL_EPSILON - && fabs(a->dist - dist) < DIST_EPSILON ) - return qtrue; - return qfalse; -} - -/* -============= -VS_PlaneFromPoints -============= -*/ -qboolean VS_PlaneFromPoints( plane_t *plane, const vec3_t a, const vec3_t b, const vec3_t c ) { - vec3_t d1, d2; - - VectorSubtract( b, a, d1 ); - VectorSubtract( c, a, d2 ); - CrossProduct( d2, d1, plane->normal ); - if ( VectorNormalize( plane->normal, plane->normal ) == 0 ) { - return qfalse; - } - - plane->dist = DotProduct( a, plane->normal ); - return qtrue; -} - -/* -===================== -VS_GenerateBoundaryForPoints -===================== -*/ -void VS_GenerateBoundaryForPoints( plane_t *boundary, plane_t *plane, vec3_t a, vec3_t b ) { - vec3_t d1; - - // make a perpendicular vector to the edge and the surface - VectorSubtract( a, b, d1 ); - CrossProduct( plane->normal, d1, boundary->normal ); - VectorNormalize( boundary->normal, boundary->normal ); - boundary->dist = DotProduct( a, boundary->normal ); -} - -/* -===================== -VS_GenerateFacetFor3Points -===================== -*/ -qboolean VS_GenerateFacetFor3Points( dsurface_t *dsurf, shaderInfo_t *si, lFacet_t *f, drawVert_t *a, drawVert_t *b, drawVert_t *c ) { - // - vec3_t dir; - int i; - - // if we can't generate a valid plane for the points, ignore the facet - if ( !VS_PlaneFromPoints( &f->plane, a->xyz, b->xyz, c->xyz ) ) { - f->numpoints = 0; - return qfalse; - } - - f->num = numfacets++; - - VectorAdd( a->xyz, surfaceOrigin[dsurf - drawSurfaces], f->points[0] ); - VectorAdd( b->xyz, surfaceOrigin[dsurf - drawSurfaces], f->points[1] ); - VectorAdd( c->xyz, surfaceOrigin[dsurf - drawSurfaces], f->points[2] ); - - f->lightmapCoords[0][0] = a->lightmap[0]; - f->lightmapCoords[0][1] = a->lightmap[1]; - f->lightmapCoords[1][0] = b->lightmap[0]; - f->lightmapCoords[1][1] = b->lightmap[1]; - f->lightmapCoords[2][0] = c->lightmap[0]; - f->lightmapCoords[2][1] = c->lightmap[1]; - - VS_GenerateBoundaryForPoints( &f->boundaries[0], &f->plane, f->points[0], f->points[1] ); - VS_GenerateBoundaryForPoints( &f->boundaries[1], &f->plane, f->points[1], f->points[2] ); - VS_GenerateBoundaryForPoints( &f->boundaries[2], &f->plane, f->points[2], f->points[0] ); - - for (i = 0; i < 3; i++) - { - VectorSubtract(f->points[(i+1)%3], f->points[i], dir); - if (VectorLength(dir) < 0.1) - return qfalse; - } - - VS_TextureMatrixFromPoints( f, a, b, c ); - VS_LightmapMatrixFromPoints( dsurf, si, f, a, b, c ); - - f->numpoints = 3; - - return qtrue; -} - -/* -===================== -VS_GenerateFacetFor4Points - -Attempts to use four points as a planar quad -===================== -*/ -#define PLANAR_EPSILON 0.1 -qboolean VS_GenerateFacetFor4Points( dsurface_t *dsurf, shaderInfo_t *si, lFacet_t *f, drawVert_t *a, drawVert_t *b, drawVert_t *c, drawVert_t *d ) { - float dist; - vec3_t dir; - int i; - plane_t plane; - - // if we can't generate a valid plane for the points, ignore the facet - if ( !VS_PlaneFromPoints( &f->plane, a->xyz, b->xyz, c->xyz ) ) { - f->numpoints = 0; - return qfalse; - } - - // if the fourth point is also on the plane, we can make a quad facet - dist = DotProduct( d->xyz, f->plane.normal ) - f->plane.dist; - if ( fabs( dist ) > PLANAR_EPSILON ) { - f->numpoints = 0; - return qfalse; - } - - VectorAdd( a->xyz, surfaceOrigin[dsurf - drawSurfaces], f->points[0] ); - VectorAdd( b->xyz, surfaceOrigin[dsurf - drawSurfaces], f->points[1] ); - VectorAdd( c->xyz, surfaceOrigin[dsurf - drawSurfaces], f->points[2] ); - VectorAdd( d->xyz, surfaceOrigin[dsurf - drawSurfaces], f->points[3] ); - - for (i = 1; i < 4; i++) - { - if ( !VS_PlaneFromPoints( &plane, f->points[i], f->points[(i+1) % 4], f->points[(i+2) % 4]) ) { - f->numpoints = 0; - return qfalse; - } - - if (!Plane_Equal(&f->plane, &plane, qfalse)) { - f->numpoints = 0; - return qfalse; - } - } - - f->lightmapCoords[0][0] = a->lightmap[0]; - f->lightmapCoords[0][1] = a->lightmap[1]; - f->lightmapCoords[1][0] = b->lightmap[0]; - f->lightmapCoords[1][1] = b->lightmap[1]; - f->lightmapCoords[2][0] = c->lightmap[0]; - f->lightmapCoords[2][1] = c->lightmap[1]; - f->lightmapCoords[3][0] = d->lightmap[0]; - f->lightmapCoords[3][1] = d->lightmap[1]; - - VS_GenerateBoundaryForPoints( &f->boundaries[0], &f->plane, f->points[0], f->points[1] ); - VS_GenerateBoundaryForPoints( &f->boundaries[1], &f->plane, f->points[1], f->points[2] ); - VS_GenerateBoundaryForPoints( &f->boundaries[2], &f->plane, f->points[2], f->points[3] ); - VS_GenerateBoundaryForPoints( &f->boundaries[3], &f->plane, f->points[3], f->points[0] ); - - for (i = 0; i < 4; i++) - { - VectorSubtract(f->points[(i+1)%4], f->points[i], dir); - if (VectorLength(dir) < 0.1) - return qfalse; - } - - VS_TextureMatrixFromPoints( f, a, b, c ); - VS_LightmapMatrixFromPoints( dsurf, si, f, a, b, c ); - - f->num = numfacets++; - f->numpoints = 4; - - return qtrue; -} - -/* -=============== -VS_SphereFromBounds -=============== -*/ -void VS_SphereFromBounds( vec3_t mins, vec3_t maxs, vec3_t origin, float *radius ) { - vec3_t temp; - - VectorAdd( mins, maxs, origin ); - VectorScale( origin, 0.5, origin ); - VectorSubtract( maxs, origin, temp ); - *radius = VectorLength( temp ); -} - -/* -==================== -VS_FacetsForTriangleSurface -==================== -*/ -void VS_FacetsForTriangleSurface( dsurface_t *dsurf, shaderInfo_t *si, lsurfaceTest_t *test ) { - int i; - drawVert_t *v1, *v2, *v3, *v4; - int count; - int i1, i2, i3, i4, i5, i6; - - test->patch = qfalse; - if (dsurf->surfaceType == MST_TRIANGLE_SOUP) - test->trisoup = qtrue; - else - test->trisoup = qfalse; - test->numFacets = dsurf->numIndexes / 3; - test->facets = malloc( sizeof( test->facets[0] ) * test->numFacets ); - test->shader = si; - - count = 0; - for ( i = 0 ; i < test->numFacets ; i++ ) { - i1 = drawIndexes[ dsurf->firstIndex + i*3 ]; - i2 = drawIndexes[ dsurf->firstIndex + i*3 + 1 ]; - i3 = drawIndexes[ dsurf->firstIndex + i*3 + 2 ]; - - v1 = &drawVerts[ dsurf->firstVert + i1 ]; - v2 = &drawVerts[ dsurf->firstVert + i2 ]; - v3 = &drawVerts[ dsurf->firstVert + i3 ]; - - // try and make a quad out of two triangles - if ( i != test->numFacets - 1 ) { - i4 = drawIndexes[ dsurf->firstIndex + i*3 + 3 ]; - i5 = drawIndexes[ dsurf->firstIndex + i*3 + 4 ]; - i6 = drawIndexes[ dsurf->firstIndex + i*3 + 5 ]; - if ( i4 == i3 && i5 == i2 ) { - v4 = &drawVerts[ dsurf->firstVert + i6 ]; - if ( VS_GenerateFacetFor4Points( dsurf, si, &test->facets[count], v1, v2, v4, v3 ) ) { - count++; - i++; // skip next tri - continue; - } - } - } - - if (VS_GenerateFacetFor3Points( dsurf, si, &test->facets[count], v1, v2, v3 )) { - count++; - } - } - - // we may have turned some pairs into quads - test->numFacets = count; -} - -/* -==================== -VS_FacetsForPatch -==================== -*/ -void VS_FacetsForPatch( dsurface_t *dsurf, int surfaceNum, shaderInfo_t *si, lsurfaceTest_t *test ) { - int i, j, x, y; - drawVert_t *v1, *v2, *v3, *v4; - int count, ssize; - mesh_t mesh; - mesh_t *subdivided, *detailmesh, *newmesh; - int widthtable[LIGHTMAP_SIZE], heighttable[LIGHTMAP_SIZE]; - - mesh.width = dsurf->patchWidth; - mesh.height = dsurf->patchHeight; - mesh.verts = &drawVerts[ dsurf->firstVert ]; - - newmesh = SubdivideMesh( mesh, 8, 999 ); - PutMeshOnCurve( *newmesh ); - MakeMeshNormals( *newmesh ); - - subdivided = RemoveLinearMeshColumnsRows( newmesh ); - FreeMesh(newmesh); - - // DebugNet_RemoveAllPolys(); - // DebugNet_DrawMesh(subdivided); - - ssize = samplesize; - if (si->lightmapSampleSize) - ssize = si->lightmapSampleSize; - - if ( dsurf->lightmapNum >= 0 ) { - - detailmesh = SubdivideMeshQuads( subdivided, ssize, LIGHTMAP_SIZE, widthtable, heighttable); - test->detailMesh = detailmesh; - - // DebugNet_RemoveAllPolys(); - // DebugNet_DrawMesh(detailmesh); - - if ( detailmesh->width != dsurf->lightmapWidth || detailmesh->height != dsurf->lightmapHeight ) { - Error( "Mesh lightmap miscount"); - } - } - else { - test->detailMesh = NULL; - memset(widthtable, 0, sizeof(widthtable)); - memset(heighttable, 0, sizeof(heighttable)); - } - - test->patch = qtrue; - test->trisoup = qfalse; - test->numFacets = ( subdivided->width - 1 ) * ( subdivided->height - 1 ) * 2; - test->facets = malloc( sizeof( test->facets[0] ) * test->numFacets ); - test->shader = si; - - count = 0; - x = 0; - for ( i = 0 ; i < subdivided->width - 1 ; i++ ) { - y = 0; - for ( j = 0 ; j < subdivided->height - 1 ; j++ ) { - - v1 = subdivided->verts + j * subdivided->width + i; - v2 = v1 + 1; - v3 = v1 + subdivided->width + 1; - v4 = v1 + subdivided->width; - - if ( VS_GenerateFacetFor4Points( dsurf, si, &test->facets[count], v1, v4, v3, v2 ) ) { - test->facets[count].x = x; - test->facets[count].y = y; - test->facets[count].width = widthtable[i]; - test->facets[count].height = heighttable[j]; - count++; - } else { - if (VS_GenerateFacetFor3Points( dsurf, si, &test->facets[count], v1, v4, v3 )) { - test->facets[count].x = x; - test->facets[count].y = y; - test->facets[count].width = widthtable[i]; - test->facets[count].height = heighttable[j]; - count++; - } - if (VS_GenerateFacetFor3Points( dsurf, si, &test->facets[count], v1, v3, v2 )) { - test->facets[count].x = x; - test->facets[count].y = y; - test->facets[count].width = widthtable[i]; - test->facets[count].height = heighttable[j]; - count++; - } - } - y += heighttable[j]; - } - x += widthtable[i]; - } - test->numFacets = count; - - FreeMesh(subdivided); -} - -/* -===================== -VS_InitSurfacesForTesting -===================== -*/ -void VS_InitSurfacesForTesting( void ) { - - int i, j, k; - dsurface_t *dsurf; - lsurfaceTest_t *test; - shaderInfo_t *si; - lFacet_t *facet; - - for ( i = 0 ; i < numDrawSurfaces ; i++ ) { - // don't light the entity surfaces with vsound - if ( entitySurface[i] ) - continue; - // - dsurf = &drawSurfaces[ i ]; - if ( !dsurf->numIndexes && !dsurf->patchWidth ) { - continue; - } - - si = ShaderInfoForShader( dshaders[ dsurf->shaderNum].shader ); - // if the surface is translucent and does not cast an alpha shadow - if ( (si->contents & CONTENTS_TRANSLUCENT) && !(si->surfaceFlags & SURF_ALPHASHADOW) ) { - // if the surface has no lightmap - if ( dsurf->lightmapNum < 0 ) - continue; - } - - test = malloc( sizeof( *test ) ); - memset(test, 0, sizeof( *test )); - test->mutex = MutexAlloc(); - test->numvolumes = 0; - if (si->forceTraceLight) - test->always_tracelight = qtrue; - else if (si->forceVLight) - test->always_vsound = qtrue; - lsurfaceTest[i] = test; - - if ( dsurf->surfaceType == MST_TRIANGLE_SOUP || dsurf->surfaceType == MST_PLANAR ) { - VS_FacetsForTriangleSurface( dsurf, si, test ); - } else if ( dsurf->surfaceType == MST_PATCH ) { - VS_FacetsForPatch( dsurf, i, si, test ); - } - if (numfacets >= MAX_FACETS) - Error("numfacets >= MAX_FACETS (%d)", MAX_FACETS); - - ClearBounds( test->mins, test->maxs ); - for (j = 0; j < test->numFacets; j++) - { - facet = &test->facets[j]; - for ( k = 0 ; k < facet->numpoints; k++) { - AddPointToBounds( facet->points[k], test->mins, test->maxs ); - } - } - VS_SphereFromBounds( test->mins, test->maxs, test->origin, &test->radius ); - } - _printf("%6d facets\n", numfacets); - _printf("linking surfaces...\n"); - VS_LinkSurfaces(); -} - -/* -============= -VS_ChopWinding -============= -*/ -int VS_ChopWinding (winding_t *in, plane_t *split, float epsilon) -{ - vec_t dists[128]; - int sides[128]; - int counts[3]; - vec_t dot; - int i, j; - vec_t *p1, *p2; - vec3_t mid; - winding_t out; - winding_t *neww; - - counts[0] = counts[1] = counts[2] = 0; - - // determine sides for each point - for (i=0 ; i<in->numpoints ; i++) - { - dot = DotProduct (in->points[i], split->normal); - dot -= split->dist; - dists[i] = dot; - if (dot > epsilon) - sides[i] = SIDE_FRONT; - else if (dot < -epsilon) - sides[i] = SIDE_BACK; - else - { - sides[i] = SIDE_ON; - } - counts[sides[i]]++; - } - - if (!counts[SIDE_BACK]) - { - if (!counts[SIDE_FRONT]) - return SIDE_ON; - else - return SIDE_FRONT; - } - - if (!counts[SIDE_FRONT]) - { - return SIDE_BACK; - } - - sides[i] = sides[0]; - dists[i] = dists[0]; - - neww = &out; - - neww->numpoints = 0; - - for (i=0 ; i<in->numpoints ; i++) - { - p1 = in->points[i]; - - if (neww->numpoints >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VS_ChopWinding -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return SIDE_FRONT; // can't chop -- fall back to original - } - - if (sides[i] == SIDE_ON) - { - VectorCopy (p1, neww->points[neww->numpoints]); - neww->numpoints++; - continue; - } - - if (sides[i] == SIDE_FRONT) - { - VectorCopy (p1, neww->points[neww->numpoints]); - neww->numpoints++; - } - - if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) - continue; - - if (neww->numpoints >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VS_ChopWinding -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return SIDE_FRONT; // can't chop -- fall back to original - } - - // generate a split point - p2 = in->points[(i+1)%in->numpoints]; - - dot = dists[i] / (dists[i]-dists[i+1]); - for (j=0 ; j<3 ; j++) - { // avoid round off error when possible - if (split->normal[j] == 1) - mid[j] = split->dist; - else if (split->normal[j] == -1) - mid[j] = -split->dist; - else - mid[j] = p1[j] + dot*(p2[j]-p1[j]); - } - - VectorCopy (mid, neww->points[neww->numpoints]); - neww->numpoints++; - } - memcpy(in, &out, sizeof(winding_t)); - - return SIDE_CROSS; -} - -/* -============= -VS_ChopWindingWithBrush - - returns all winding fragments outside the brush -============= -*/ -int VS_ChopWindingWithBrush(winding_t *w, dbrush_t *brush, winding_t *outwindings, int maxout) -{ - int i, res, numout; - winding_t front, back; - plane_t plane; - - numout = 0; - memcpy(front.points, w->points, w->numpoints * sizeof(vec3_t)); - front.numpoints = w->numpoints; - for (i = 0; i < brush->numSides; i++) - { - VectorCopy(dplanes[ dbrushsides[ brush->firstSide + i ].planeNum ].normal, plane.normal); - VectorInverse(plane.normal); - plane.dist = -dplanes[ dbrushsides[ brush->firstSide + i ].planeNum ].dist; - res = VS_SplitWinding(&front, &back, &plane, 0.1); - if (res == SIDE_BACK || res == SIDE_ON) - { - memcpy(outwindings[0].points, w->points, w->numpoints * sizeof(vec3_t)); - outwindings[0].numpoints = w->numpoints; - return 1; //did not intersect - } - if (res != SIDE_FRONT) - { - if (numout >= maxout) - { - _printf("WARNING: VS_ChopWindingWithBrush: more than %d windings\n", maxout); - return 0; - } - memcpy(outwindings[numout].points, back.points, back.numpoints * sizeof(vec3_t)); - outwindings[numout].numpoints = back.numpoints; - numout++; - } - } - return numout; -} - -/* -============= -VS_WindingAreaOutsideBrushes -============= -*/ -float VS_WindingAreaOutsideBrushes(winding_t *w, int *brushnums, int numbrushes) -{ - int i, j, numwindings[2], n; - winding_t windingsbuf[2][64]; - dbrush_t *brush; - float area; - - memcpy(windingsbuf[0][0].points, w->points, w->numpoints * sizeof(vec3_t)); - windingsbuf[0][0].numpoints = w->numpoints; - numwindings[0] = 1; - for (i = 0; i < numbrushes; i++) - { - brush = &dbrushes[brushnums[i]]; - if (!(dshaders[brush->shaderNum].contentFlags & ( - CONTENTS_LAVA - | CONTENTS_SLIME - | CONTENTS_WATER - | CONTENTS_FOG - | CONTENTS_AREAPORTAL - | CONTENTS_PLAYERCLIP - | CONTENTS_MONSTERCLIP - | CONTENTS_CLUSTERPORTAL - | CONTENTS_DONOTENTER - | CONTENTS_BODY - | CONTENTS_CORPSE - | CONTENTS_TRANSLUCENT - | CONTENTS_TRIGGER - | CONTENTS_NODROP) ) && - (dshaders[brush->shaderNum].contentFlags & CONTENTS_SOLID) ) - { - numwindings[!(i & 1)] = 0; - for (j = 0; j < numwindings[i&1]; j++) - { - n = VS_ChopWindingWithBrush(&windingsbuf[i&1][j], brush, - &windingsbuf[!(i&1)][numwindings[!(i&1)]], - 64 - numwindings[!(i&1)]); - numwindings[!(i&1)] += n; - } - if (!numwindings[!(i&1)]) - return 0; - } - else - { - for (j = 0; j < numwindings[i&1]; j++) - { - windingsbuf[!(i&1)][j] = windingsbuf[i&1][j]; - } - numwindings[!(i&1)] = numwindings[i&1]; - } - } - area = 0; - for (j = 0; j < numwindings[i&1]; j++) - { - area += WindingArea(&windingsbuf[i&1][j]); - } - return area; -} - -/* -============= -VS_R_WindingAreaOutsideSolid -============= -*/ -float VS_R_WindingAreaOutsideSolid(winding_t *w, vec3_t normal, int nodenum) -{ - int leafnum, res; - float area; - dnode_t *node; - dleaf_t *leaf; - dplane_t *plane; - winding_t back; - plane_t split; - - area = 0; - while(nodenum >= 0) - { - node = &dnodes[nodenum]; - plane = &dplanes[node->planeNum]; - - VectorCopy(plane->normal, split.normal); - split.dist = plane->dist; - res = VS_SplitWinding (w, &back, &split, 0.1); - - if (res == SIDE_FRONT) - { - nodenum = node->children[0]; - } - else if (res == SIDE_BACK) - { - nodenum = node->children[1]; - } - else if (res == SIDE_ON) - { - if (DotProduct(normal, plane->normal) > 0) - nodenum = node->children[0]; - else - nodenum = node->children[1]; - } - else - { - area += VS_R_WindingAreaOutsideSolid(&back, normal, node->children[1]); - nodenum = node->children[0]; - } - } - leafnum = -nodenum - 1; - leaf = &dleafs[leafnum]; - if (leaf->cluster != -1) - { - area += VS_WindingAreaOutsideBrushes(w, &dleafbrushes[leaf->firstLeafBrush], leaf->numLeafBrushes); - } - return area; -} - -/* -============= -VS_WindingAreaOutsideSolid -============= -*/ -float VS_WindingAreaOutsideSolid(winding_t *w, vec3_t normal) -{ - return VS_R_WindingAreaOutsideSolid(w, normal, 0); -} - -/* -============= -VS_ChopWindingWithFacet -============= -*/ -float VS_ChopWindingWithFacet(winding_t *w, lFacet_t *facet) -{ - int i; - - for (i = 0; i < facet->numpoints; i++) - { - if (VS_ChopWinding(w, &facet->boundaries[i], 0) == SIDE_BACK) - return 0; - } - if (nostitching) - return WindingArea(w); - else - return VS_WindingAreaOutsideSolid(w, facet->plane.normal); -} - -/* -============= -VS_CalcVisibleLightmapPixelArea - -nice brute force ;) -============= -*/ -void VS_CalcVisibleLightmapPixelArea(void) -{ - int i, j, x, y, k; - dsurface_t *ds; - lsurfaceTest_t *test; - mesh_t *mesh; - winding_t w, tmpw; - float area; - - _printf("calculating visible lightmap pixel area...\n"); - for ( i = 0 ; i < numDrawSurfaces ; i++ ) - { - test = lsurfaceTest[ i ]; - if (!test) - continue; - ds = &drawSurfaces[ i ]; - - if ( ds->lightmapNum < 0 ) - continue; - - for (y = 0; y < ds->lightmapHeight; y++) - { - for (x = 0; x < ds->lightmapWidth; x++) - { - if (ds->surfaceType == MST_PATCH) - { - if (y == ds->lightmapHeight-1) - continue; - if (x == ds->lightmapWidth-1) - continue; - mesh = lsurfaceTest[i]->detailMesh; - VectorCopy( mesh->verts[y*mesh->width+x].xyz, w.points[0]); - VectorCopy( mesh->verts[(y+1)*mesh->width+x].xyz, w.points[1]); - VectorCopy( mesh->verts[(y+1)*mesh->width+x+1].xyz, w.points[2]); - VectorCopy( mesh->verts[y*mesh->width+x+1].xyz, w.points[3]); - w.numpoints = 4; - if (nostitching) - area = WindingArea(&w); - else - area = VS_WindingAreaOutsideSolid(&w, mesh->verts[y*mesh->width+x].normal); - } - else - { - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT, ds->lightmapVecs[0], w.points[0]); - VectorMA(w.points[0], (float) y - LIGHTMAP_PIXELSHIFT, ds->lightmapVecs[1], w.points[0]); - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT, ds->lightmapVecs[0], w.points[3]); - VectorMA(w.points[3], (float) y - LIGHTMAP_PIXELSHIFT + 1, ds->lightmapVecs[1], w.points[3]); - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT + 1, ds->lightmapVecs[0], w.points[2]); - VectorMA(w.points[2], (float) y - LIGHTMAP_PIXELSHIFT + 1, ds->lightmapVecs[1], w.points[2]); - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT + 1, ds->lightmapVecs[0], w.points[1]); - VectorMA(w.points[1], (float) y - LIGHTMAP_PIXELSHIFT, ds->lightmapVecs[1], w.points[1]); - w.numpoints = 4; - area = 0; - for (j = 0; j < test->numFacets; j++) - { - memcpy(&tmpw, &w, sizeof(winding_t)); - area += VS_ChopWindingWithFacet(&tmpw, &test->facets[j]); - } - } - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - lightmappixelarea[k] = area; - } - } - } -} - -/* -============= -VS_FindAdjacentSurface -============= -*/ -int VS_FindAdjacentSurface(int surfaceNum, int facetNum, vec3_t p1, vec3_t p2, int *sNum, int *fNum, int *point) -{ - int i, j, k; - lsurfaceTest_t *test; - lFacet_t *facet; - dsurface_t *ds; - float *fp1, *fp2; - vec3_t dir; - plane_t *facetplane; - // winding_t w; - - facetplane = &lsurfaceTest[surfaceNum]->facets[facetNum].plane; - // DebugNet_RemoveAllPolys(); - // memcpy(w.points, lsurfaceTest[surfaceNum]->facets[facetNum].points, - // lsurfaceTest[surfaceNum]->facets[facetNum].numpoints * sizeof(vec3_t)); - // w.numpoints = lsurfaceTest[surfaceNum]->facets[facetNum].numpoints; - // DebugNet_DrawWinding(&w, 2); - for ( i = 0 ; i < numDrawSurfaces ; i++ ) - { - if (i == surfaceNum) - continue; - test = lsurfaceTest[ i ]; - if (!test) - continue; - if (test->trisoup)// || test->patch) - continue; - ds = &drawSurfaces[i]; - if ( ds->lightmapNum < 0 ) - continue; - //if this surface is not even near the edge - VectorSubtract(p1, test->origin, dir); - if (fabs(dir[0]) > test->radius || - fabs(dir[1]) > test->radius || - fabs(dir[1]) > test->radius) - { - VectorSubtract(p2, test->origin, dir); - if (fabs(dir[0]) > test->radius || - fabs(dir[1]) > test->radius || - fabs(dir[1]) > test->radius) - { - continue; - } - } - // - for (j = 0; j < test->numFacets; j++) - { - facet = &test->facets[j]; - // - //if (!Plane_Equal(&facet->plane, facetplane, qfalse)) - if (DotProduct(facet->plane.normal, facetplane->normal) < 0.9) - { - if (!test->trisoup && !test->patch) - break; - continue; - } - // - for (k = 0; k < facet->numpoints; k++) - { - fp1 = facet->points[k]; - if (fabs(p2[0] - fp1[0]) < 0.1 && - fabs(p2[1] - fp1[1]) < 0.1 && - fabs(p2[2] - fp1[2]) < 0.1) - { - fp2 = facet->points[(k+1) % facet->numpoints]; - if (fabs(p1[0] - fp2[0]) < 0.1 && - fabs(p1[1] - fp2[1]) < 0.1 && - fabs(p1[2] - fp2[2]) < 0.1) - { - // memcpy(w.points, facet->points, facet->numpoints * sizeof(vec3_t)); - // w.numpoints = facet->numpoints; - // DebugNet_DrawWinding(&w, 1); - *sNum = i; - *fNum = j; - *point = k; - return qtrue; - } - } - /* - else if (fabs(p1[0] - fp1[0]) < 0.1 && - fabs(p1[1] - fp1[1]) < 0.1 && - fabs(p1[2] - fp1[2]) < 0.1) - { - fp2 = facet->points[(k+1) % facet->numpoints]; - if (fabs(p2[0] - fp2[0]) < 0.1 && - fabs(p2[1] - fp2[1]) < 0.1 && - fabs(p2[2] - fp2[2]) < 0.1) - { - // memcpy(w.points, facet->points, facet->numpoints * sizeof(vec3_t)); - // w.numpoints = facet->numpoints; - // DebugNet_DrawWinding(&w, 1); - *sNum = i; - *fNum = j; - *point = k; - return qtrue; - } - } - //*/ - } - } - } - return qfalse; -} - -/* -============= -VS_SmoothenLightmapEdges - -this code is used to smoothen lightmaps across surface edges -============= -*/ -void VS_SmoothenLightmapEdges(void) -{ - int i, j, k, coords1[2][2]; - float coords2[2][2]; - int x1, y1, xinc1, yinc1, k1, k2; - float x2, y2, xinc2, yinc2, length; - int surfaceNum, facetNum, point; - lsurfaceTest_t *test; - lFacet_t *facet1, *facet2; - dsurface_t *ds1, *ds2; - float *p[2], s, t, *color1, *color2; - vec3_t dir, cross; - - for ( i = 0 ; i < numDrawSurfaces ; i++ ) - { - test = lsurfaceTest[ i ]; - if (!test) - continue; - if (test->trisoup)// || test->patch) - continue; - ds1 = &drawSurfaces[i]; - if ( ds1->lightmapNum < 0 ) - continue; - for (j = 0; j < test->numFacets; j++) - { - facet1 = &test->facets[j]; - // - for (k = 0; k < facet1->numpoints; k++) - { - p[0] = facet1->points[k]; - p[1] = facet1->points[(k+1)%facet1->numpoints]; - // - coords1[0][0] = facet1->lightmapCoords[k][0] * LIGHTMAP_SIZE; - coords1[0][1] = facet1->lightmapCoords[k][1] * LIGHTMAP_SIZE; - coords1[1][0] = facet1->lightmapCoords[(k+1)%facet1->numpoints][0] * LIGHTMAP_SIZE; - coords1[1][1] = facet1->lightmapCoords[(k+1)%facet1->numpoints][1] * LIGHTMAP_SIZE; - if (coords1[0][0] >= LIGHTMAP_SIZE) - coords1[0][0] = LIGHTMAP_SIZE-1; - if (coords1[0][1] >= LIGHTMAP_SIZE) - coords1[0][1] = LIGHTMAP_SIZE-1; - if (coords1[1][0] >= LIGHTMAP_SIZE) - coords1[1][0] = LIGHTMAP_SIZE-1; - if (coords1[1][1] >= LIGHTMAP_SIZE) - coords1[1][1] = LIGHTMAP_SIZE-1; - // try one row or column further because on flat faces the lightmap can - // extend beyond the edge - VectorSubtract(p[1], p[0], dir); - VectorNormalize(dir, dir); - CrossProduct(dir, facet1->plane.normal, cross); - // - if (coords1[0][0] - coords1[1][0] == 0) - { - s = DotProduct( cross, facet1->lightmapMatrix[0] ); - coords1[0][0] += s < 0 ? 1 : -1; - coords1[1][0] += s < 0 ? 1 : -1; - if (coords1[0][0] < ds1->lightmapX || coords1[0][0] >= ds1->lightmapX + ds1->lightmapWidth) - { - coords1[0][0] += s < 0 ? -1 : 1; - coords1[1][0] += s < 0 ? -1 : 1; - } - length = fabs(coords1[1][1] - coords1[0][1]); - } - else if (coords1[0][1] - coords1[1][1] == 0) - { - t = DotProduct( cross, facet1->lightmapMatrix[1] ); - coords1[0][1] += t < 0 ? 1 : -1; - coords1[1][1] += t < 0 ? 1 : -1; - if (coords1[0][1] < ds1->lightmapY || coords1[0][1] >= ds1->lightmapY + ds1->lightmapHeight) - { - coords1[0][1] += t < 0 ? -1 : 1; - coords1[1][1] += t < 0 ? -1 : 1; - } - length = fabs(coords1[1][0] - coords1[0][0]); - } - else - { - //the edge is not parallell to one of the lightmap axis - continue; - } - // - x1 = coords1[0][0]; - y1 = coords1[0][1]; - xinc1 = coords1[1][0] - coords1[0][0]; - if (xinc1 < 0) xinc1 = -1; - if (xinc1 > 0) xinc1 = 1; - yinc1 = coords1[1][1] - coords1[0][1]; - if (yinc1 < 0) yinc1 = -1; - if (yinc1 > 0) yinc1 = 1; - // the edge should be parallell to one of the lightmap axis - if (xinc1 != 0 && yinc1 != 0) - continue; - // - if (!VS_FindAdjacentSurface(i, j, p[0], p[1], &surfaceNum, &facetNum, &point)) - continue; - // - ds2 = &drawSurfaces[surfaceNum]; - facet2 = &lsurfaceTest[surfaceNum]->facets[facetNum]; - coords2[0][0] = facet2->lightmapCoords[(point+1)%facet2->numpoints][0] * LIGHTMAP_SIZE; - coords2[0][1] = facet2->lightmapCoords[(point+1)%facet2->numpoints][1] * LIGHTMAP_SIZE; - coords2[1][0] = facet2->lightmapCoords[point][0] * LIGHTMAP_SIZE; - coords2[1][1] = facet2->lightmapCoords[point][1] * LIGHTMAP_SIZE; - if (coords2[0][0] >= LIGHTMAP_SIZE) - coords2[0][0] = LIGHTMAP_SIZE-1; - if (coords2[0][1] >= LIGHTMAP_SIZE) - coords2[0][1] = LIGHTMAP_SIZE-1; - if (coords2[1][0] >= LIGHTMAP_SIZE) - coords2[1][0] = LIGHTMAP_SIZE-1; - if (coords2[1][1] >= LIGHTMAP_SIZE) - coords2[1][1] = LIGHTMAP_SIZE-1; - // - x2 = coords2[0][0]; - y2 = coords2[0][1]; - xinc2 = coords2[1][0] - coords2[0][0]; - if (length) - xinc2 = xinc2 / length; - yinc2 = coords2[1][1] - coords2[0][1]; - if (length) - yinc2 = yinc2 / length; - // the edge should be parallell to one of the lightmap axis - if ((int) xinc2 != 0 && (int) yinc2 != 0) - continue; - // - while(1) - { - k1 = ( ds1->lightmapNum * LIGHTMAP_HEIGHT + y1) * LIGHTMAP_WIDTH + x1; - k2 = ( ds2->lightmapNum * LIGHTMAP_HEIGHT + ((int) y2)) * LIGHTMAP_WIDTH + ((int) x2); - color1 = lightFloats + k1*3; - color2 = lightFloats + k2*3; - if (lightmappixelarea[k1] < 0.01) - { - color1[0] = color2[0]; - color1[1] = color2[1]; - color1[2] = color2[2]; - } - else - { - color1[0] = (float) color2[0] * 0.7 + (float) color1[0] * 0.3; - color1[1] = (float) color2[1] * 0.7 + (float) color1[1] * 0.3; - color1[2] = (float) color2[2] * 0.7 + (float) color1[2] * 0.3; - } - // - if (x1 == coords1[1][0] && - y1 == coords1[1][1]) - break; - x1 += xinc1; - y1 += yinc1; - x2 += xinc2; - y2 += yinc2; - if (x2 < ds2->lightmapX) - x2 = ds2->lightmapX; - if (x2 >= ds2->lightmapX + ds2->lightmapWidth) - x2 = ds2->lightmapX + ds2->lightmapWidth-1; - if (y2 < ds2->lightmapY) - y2 = ds2->lightmapY; - if (y2 >= ds2->lightmapY + ds2->lightmapHeight) - y2 = ds2->lightmapY + ds2->lightmapHeight-1; - } - } - } - } -} - -/* -============= -VS_FixLightmapEdges -============= -*/ -void VS_FixLightmapEdges(void) -{ - int i, j, x, y, k, foundvalue, height, width, index; - int pos, top, bottom; - dsurface_t *ds; - lsurfaceTest_t *test; - float color[3]; - float *ptr; - byte filled[(LIGHTMAP_SIZE+1) * (LIGHTMAP_SIZE+1) / 8]; - float lightmap_edge_epsilon; - - lightmap_edge_epsilon = 0.1 * samplesize; - for ( i = 0 ; i < numDrawSurfaces ; i++ ) - { - test = lsurfaceTest[ i ]; - if (!test) - continue; - ds = &drawSurfaces[ i ]; - - if ( ds->lightmapNum < 0 ) - continue; - if (ds->surfaceType == MST_PATCH) - { - height = ds->lightmapHeight - 1; - width = ds->lightmapWidth - 1; - } - else - { - height = ds->lightmapHeight; - width = ds->lightmapWidth; - } - memset(filled, 0, sizeof(filled)); -// printf("\n"); - for (x = 0; x < width; x++) - { - for (y = 0; y < height; y++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - if (lightmappixelarea[k] > lightmap_edge_epsilon) - { - index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x; - filled[index >> 3] |= 1 << (index & 7); -// printf("*"); - } -// else -// printf("_"); - } -// printf("\n"); - } - for (y = 0; y < height; y++) - { - pos = -2; - for (x = 0; x < width; x++) - { - index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x; - if (pos == -2) - { - if (filled[index >> 3] & (1 << (index & 7))) - pos = -1; - } - else if (pos == -1) - { - if (!(filled[index >> 3] & (1 << (index & 7)))) - pos = x - 1; - } - else - { - if (filled[index >> 3] & (1 << (index & 7))) - { - bottom = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + pos; - top = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - for (j = 0; j < (x - pos + 1) / 2; j++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + pos + j + 1; - index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + pos + j + 1; - filled[index >> 3] |= 1 << (index & 7); - (lightFloats + k*3)[0] = (lightFloats + top*3)[0]; - (lightFloats + k*3)[1] = (lightFloats + top*3)[1]; - (lightFloats + k*3)[2] = (lightFloats + top*3)[2]; - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x - j - 1; - index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x - j - 1; - filled[index >> 3] |= 1 << (index & 7); - (lightFloats + k*3)[0] = (lightFloats + bottom*3)[0]; - (lightFloats + k*3)[1] = (lightFloats + bottom*3)[1]; - (lightFloats + k*3)[2] = (lightFloats + bottom*3)[2]; - } - pos = -1; - } - } - } - } - for (x = 0; x < width; x++) - { - pos = -2; - for (y = 0; y < height; y++) - { - index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x; - if (pos == -2) - { - if (filled[index >> 3] & (1 << (index & 7))) - pos = -1; - } - else if (pos == -1) - { - if (!(filled[index >> 3] & (1 << (index & 7)))) - pos = y - 1; - } - else - { - if (filled[index >> 3] & (1 << (index & 7))) - { - bottom = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + pos) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - top = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - for (j = 0; j < (y - pos + 1) / 2; j++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + pos + j + 1) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - index = (ds->lightmapY + pos + j + 1) * LIGHTMAP_WIDTH + ds->lightmapX + x; - filled[index >> 3] |= 1 << (index & 7); - (lightFloats + k*3)[0] = (lightFloats + top*3)[0]; - (lightFloats + k*3)[1] = (lightFloats + top*3)[1]; - (lightFloats + k*3)[2] = (lightFloats + top*3)[2]; - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y - j - 1) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - index = (ds->lightmapY + y - j - 1) * LIGHTMAP_WIDTH + ds->lightmapX + x; - filled[index >> 3] |= 1 << (index & 7); - (lightFloats + k*3)[0] = (lightFloats + bottom*3)[0]; - (lightFloats + k*3)[1] = (lightFloats + bottom*3)[1]; - (lightFloats + k*3)[2] = (lightFloats + bottom*3)[2]; - } - pos = -1; - } - } - } - } - for (y = 0; y < height; y++) - { - foundvalue = qfalse; - for (x = 0; x < width; x++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x; - if (foundvalue) - { - if (filled[index >> 3] & (1 << (index & 7))) - { - ptr = lightFloats + k*3; - color[0] = ptr[0]; - color[1] = ptr[1]; - color[2] = ptr[2]; - } - else - { - ptr = lightFloats + k*3; - ptr[0] = color[0]; - ptr[1] = color[1]; - ptr[2] = color[2]; - filled[index >> 3] |= 1 << (index & 7); - } - } - else - { - if (filled[index >> 3] & (1 << (index & 7))) - { - ptr = lightFloats + k*3; - color[0] = ptr[0]; - color[1] = ptr[1]; - color[2] = ptr[2]; - foundvalue = qtrue; - } - } - } - foundvalue = qfalse; - for (x = width-1; x >= 0; x--) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x; - if (foundvalue) - { - if (filled[index >> 3] & (1 << (index & 7))) - { - ptr = lightFloats + k*3; - color[0] = ptr[0]; - color[1] = ptr[1]; - color[2] = ptr[2]; - } - else - { - ptr = lightFloats + k*3; - ptr[0] = color[0]; - ptr[1] = color[1]; - ptr[2] = color[2]; - filled[index >> 3] |= 1 << (index & 7); - } - } - else - { - if (filled[index >> 3] & (1 << (index & 7))) - { - ptr = lightFloats + k*3; - color[0] = ptr[0]; - color[1] = ptr[1]; - color[2] = ptr[2]; - foundvalue = qtrue; - } - } - } - } - for (x = 0; x < width; x++) - { - foundvalue = qfalse; - for (y = 0; y < height; y++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x; - if (foundvalue) - { - if (filled[index >> 3] & (1 << (index & 7))) - { - ptr = lightFloats + k*3; - color[0] = ptr[0]; - color[1] = ptr[1]; - color[2] = ptr[2]; - } - else - { - ptr = lightFloats + k*3; - ptr[0] = color[0]; - ptr[1] = color[1]; - ptr[2] = color[2]; - filled[index >> 3] |= 1 << (index & 7); - } - } - else - { - if (filled[index >> 3] & (1 << (index & 7))) - { - ptr = lightFloats + k*3; - color[0] = ptr[0]; - color[1] = ptr[1]; - color[2] = ptr[2]; - foundvalue = qtrue; - } - } - } - foundvalue = qfalse; - for (y = height-1; y >= 0; y--) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x; - if (foundvalue) - { - if (filled[index >> 3] & (1 << (index & 7))) - { - ptr = lightFloats + k*3; - color[0] = ptr[0]; - color[1] = ptr[1]; - color[2] = ptr[2]; - } - else - { - ptr = lightFloats + k*3; - ptr[0] = color[0]; - ptr[1] = color[1]; - ptr[2] = color[2]; - filled[index >> 3] |= 1 << (index & 7); - } - } - else - { - if (filled[index >> 3] & (1 << (index & 7))) - { - ptr = lightFloats + k*3; - color[0] = ptr[0]; - color[1] = ptr[1]; - color[2] = ptr[2]; - foundvalue = qtrue; - } - } - } - } - if (ds->surfaceType == MST_PATCH) - { - x = ds->lightmapWidth-1; - for (y = 0; y < ds->lightmapHeight; y++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - ptr = lightFloats + k*3; - ptr[0] = (lightFloats + (k-1)*3)[0]; - ptr[1] = (lightFloats + (k-1)*3)[1]; - ptr[2] = (lightFloats + (k-1)*3)[2]; - } - y = ds->lightmapHeight-1; - for (x = 0; x < ds->lightmapWidth; x++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - ptr = lightFloats + k*3; - ptr[0] = (lightFloats + (k-LIGHTMAP_WIDTH)*3)[0]; - ptr[1] = (lightFloats + (k-LIGHTMAP_WIDTH)*3)[1]; - ptr[2] = (lightFloats + (k-LIGHTMAP_WIDTH)*3)[2]; - } - } - /* - //colored debug edges - if (ds->surfaceType == MST_PATCH) - { - x = ds->lightmapWidth-1; - for (y = 0; y < ds->lightmapHeight; y++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - ptr = lightFloats + k*3; - ptr[0] = 255; - ptr[1] = 0; - ptr[2] = 0; - } - y = ds->lightmapHeight-1; - for (x = 0; x < ds->lightmapWidth; x++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - ptr = lightFloats + k*3; - ptr[0] = 0; - ptr[1] = 255; - ptr[2] = 0; - } - } - //*/ - } - // - VS_SmoothenLightmapEdges(); -} - -/* -============= -VS_ShiftPatchLightmaps -============= -*/ -void VS_ShiftPatchLightmaps(void) -{ - int i, j, x, y, k; - drawVert_t *verts; - dsurface_t *ds; - lsurfaceTest_t *test; - float *ptr; - - for ( i = 0 ; i < numDrawSurfaces ; i++ ) - { - test = lsurfaceTest[ i ]; - if (!test) - continue; - ds = &drawSurfaces[ i ]; - - if ( ds->lightmapNum < 0 ) - continue; - if (ds->surfaceType != MST_PATCH) - continue; - for (x = ds->lightmapWidth; x > 0; x--) - { - for (y = 0; y <= ds->lightmapHeight; y++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - ptr = lightFloats + k*3; - ptr[0] = (lightFloats + (k-1)*3)[0]; - ptr[1] = (lightFloats + (k-1)*3)[1]; - ptr[2] = (lightFloats + (k-1)*3)[2]; - } - } - for (y = ds->lightmapHeight; y > 0; y--) - { - for (x = 0; x <= ds->lightmapWidth; x++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - ptr = lightFloats + k*3; - ptr[0] = (lightFloats + (k-LIGHTMAP_WIDTH)*3)[0]; - ptr[1] = (lightFloats + (k-LIGHTMAP_WIDTH)*3)[1]; - ptr[2] = (lightFloats + (k-LIGHTMAP_WIDTH)*3)[2]; - } - } - verts = &drawVerts[ ds->firstVert ]; - for ( j = 0 ; j < ds->patchHeight * ds->patchWidth; j++ ) - { - verts[j].lightmap[0] += 0.5 / LIGHTMAP_WIDTH; - verts[j].lightmap[1] += 0.5 / LIGHTMAP_HEIGHT; - } - ds->lightmapHeight++; - ds->lightmapWidth++; - } -} - -/* -============= -VS_StoreLightmap -============= -*/ -void VS_StoreLightmap(void) -{ - int i, x, y, k; - dsurface_t *ds; - lsurfaceTest_t *test; - float *src; - byte *dst; - - _printf("storing lightmaps...\n"); - //fix lightmap edges before storing them - VS_FixLightmapEdges(); - // -#ifdef LIGHTMAP_PATCHSHIFT - VS_ShiftPatchLightmaps(); -#endif - // - for ( i = 0 ; i < numDrawSurfaces ; i++ ) - { - test = lsurfaceTest[ i ]; - if (!test) - continue; - ds = &drawSurfaces[ i ]; - - if ( ds->lightmapNum < 0 ) - continue; - - for (y = 0; y < ds->lightmapHeight; y++) - { - for (x = 0; x < ds->lightmapWidth; x++) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - VectorAdd((lightFloats + k*3), lightAmbientColor, (lightFloats + k*3)); - src = &lightFloats[k*3]; - dst = lightBytes + k*3; - ColorToBytes(src, dst); - } - } - } -} - -/* -============= -PointInLeafnum -============= -*/ -static int PointInLeafnum(vec3_t point) -{ - int nodenum; - vec_t dist; - dnode_t *node; - dplane_t *plane; - - nodenum = 0; - while (nodenum >= 0) - { - node = &dnodes[nodenum]; - plane = &dplanes[node->planeNum]; - dist = DotProduct (point, plane->normal) - plane->dist; - if (dist > 0) - nodenum = node->children[0]; - else - nodenum = node->children[1]; - } - - return -nodenum - 1; -} - -/* -============= -VS_PointInLeafnum_r -============= -*/ -int VS_PointInLeafnum_r(vec3_t point, int nodenum) -{ - int leafnum; - vec_t dist; - dnode_t *node; - dplane_t *plane; - - while (nodenum >= 0) - { - node = &dnodes[nodenum]; - plane = &dplanes[node->planeNum]; - dist = DotProduct (point, plane->normal) - plane->dist; - if (dist > 0.1) - { - nodenum = node->children[0]; - } - else if (dist < -0.1) - { - nodenum = node->children[1]; - } - else - { - leafnum = VS_PointInLeafnum_r(point, node->children[0]); - if (dleafs[leafnum].cluster != -1) - return leafnum; - nodenum = node->children[1]; - } - } - - leafnum = -nodenum - 1; - return leafnum; -} - -/* -============= -VS_PointInLeafnum -============= -*/ -int VS_PointInLeafnum(vec3_t point) -{ - return VS_PointInLeafnum_r(point, 0); -} - -/* -============= -VS_LightLeafnum -============= -*/ -int VS_LightLeafnum(vec3_t point) -{ - /* - int leafnum; - dleaf_t *leaf; - float x, y, z; - vec3_t test; - - leafnum = VS_PointInLeafnum(point); - leaf = &dleafs[leafnum]; - if (leaf->cluster != -1) - return leafnum; - for (z = 1; z >= -1; z -= 1) - { - for (x = 1; x >= -1; x -= 1) - { - for (y = 1; y >= -1; y -= 1) - { - VectorCopy(point, test); - test[0] += x; - test[1] += y; - test[2] += z; - leafnum = VS_PointInLeafnum(test); - leaf = &dleafs[leafnum]; - if (leaf->cluster != -1) - { - VectorCopy(test, point); - return leafnum; - } - } - } - } - return leafnum; - */ - return VS_PointInLeafnum(point); -} - -//#define LIGHTPOLYS - -#ifdef LIGHTPOLYS - -winding_t *lightwindings[MAX_MAP_DRAW_SURFS]; -int numlightwindings; - -/* -============= -VS_DrawLightWindings -============= -*/ -void VS_DrawLightWindings(void) -{ - int i; - for (i = 0; i < numlightwindings; i++) - { -#ifdef DEBUGNET - DebugNet_DrawWinding(lightwindings[i], 1); -#endif - } -} - -/* -============= -VS_LightSurfaceWithVolume -============= -*/ -void VS_LightSurfaceWithVolume(int surfaceNum, int facetNum, vsound_t *light, lightvolume_t *volume) -{ - winding_t *w; - lsurfaceTest_t *test; - lFacet_t *facet; - int i; - - test = lsurfaceTest[ surfaceNum ]; - facet = &test->facets[ facetNum ]; - - // - w = (winding_t *) malloc(sizeof(winding_t)); - memcpy(w->points, facet->points, sizeof(vec3_t) * facet->numpoints); - w->numpoints = facet->numpoints; - - for (i = 0; i < volume->numplanes; i++) - { - //if totally on the back - if (VS_ChopWinding(w, &volume->planes[i], 0.01) == SIDE_BACK) - return; - } - lightwindings[numlightwindings] = w; - numlightwindings++; - if (numlightwindings >= MAX_MAP_DRAW_SURFS) - Error("MAX_LIGHTWINDINGS"); -} - -#else - -/* -============= -VS_LightSurfaceWithVolume -============= -*/ -/* -int VS_PointInsideLightVolume(vec3_t point, lightvolume_t *volume) -{ - int i; - float d; - - for (i = 0; i < volume->numplanes; i++) - { - d = DotProduct(volume->planes[i].normal, point) - volume->planes[i].dist; - if (d < 0) return qfalse; - } - return qtrue; -} - -void VS_LightSurfaceWithVolume( int surfaceNum, int facetNum, vsound_t *light, lightvolume_t *volume ) -{ - dsurface_t *ds; - int i, j, k; - int numPositions; - vec3_t base, normal, color; - int sampleWidth, sampleHeight; - vec3_t lightmapOrigin, lightmapVecs[2], dir; - unsigned char *ptr; - float add, dist, angle; - mesh_t * mesh; - - ds = &drawSurfaces[surfaceNum]; - - // vertex-lit triangle model - if ( ds->surfaceType == MST_TRIANGLE_SOUP ) { - return; - } - - if ( ds->lightmapNum < 0 ) { - return; // doesn't need lighting - } - - if ( ds->surfaceType == MST_PATCH ) { - mesh = lsurfaceTest[surfaceNum]->detailMesh; - } else { - VectorCopy( ds->lightmapVecs[2], normal ); - - VectorCopy( ds->lightmapOrigin, lightmapOrigin ); - VectorCopy( ds->lightmapVecs[0], lightmapVecs[0] ); - VectorCopy( ds->lightmapVecs[1], lightmapVecs[1] ); - } - - sampleWidth = ds->lightmapWidth; - sampleHeight = ds->lightmapHeight; - - //calculate lightmap - for ( i = 0 ; i < sampleWidth; i++ ) { - for ( j = 0 ; j < sampleHeight; j++ ) { - - if ( ds->patchWidth ) { - numPositions = 9; - VectorCopy( mesh->verts[j*mesh->width+i].normal, normal ); - // VectorNormalize( normal, normal ); - // push off of the curve a bit - VectorMA( mesh->verts[j*mesh->width+i].xyz, 1, normal, base ); - -// MakeNormalVectors( normal, lightmapVecs[0], lightmapVecs[1] ); - } else { - numPositions = 9; - for ( k = 0 ; k < 3 ; k++ ) { - base[k] = lightmapOrigin[k] + normal[k] - + ((float) i) * lightmapVecs[0][k] - + ((float) j) * lightmapVecs[1][k]; - } - } - VectorAdd( base, surfaceOrigin[ surfaceNum ], base ); - - VectorSubtract(base, light->origin, dir); - dist = VectorNormalize(dir, dir); - if ( dist < 16 ) { - dist = 16; - } - angle = 1;//DotProduct( normal, dir ); //1; - if (angle > 1) - angle = 1; - if ( light->atten_disttype == LDAT_LINEAR ) { - add = angle * light->photons * lightLinearScale - dist; - if ( add < 0 ) { - add = 0; - } - } else { - add = light->photons / ( dist * dist ) * angle; - } - if (add <= 1.0) - continue; - - if (VS_PointInsideLightVolume(base, volume)) - { - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + j) - * LIGHTMAP_WIDTH + ds->lightmapX + i; - ptr = lightBytes + k*3; - color[0] = (float) ptr[0] + add * light->color[0]; - color[1] = (float) ptr[1] + add * light->color[1]; - color[2] = (float) ptr[2] + add * light->color[2]; - ColorToBytes(color, ptr); - } - } - } -} -*/ - -/* -============= -VS_GetFilter - -FIXME: don't use a lightmap pixel origin but use the four corner points - to map part of a translucent surface onto the lightmap pixel -============= -*/ -void VS_GetFilter(vsound_t *light, lightvolume_t *volume, vec3_t lmp, vec3_t filter) -{ - lFacet_t *facet; - lsurfaceTest_t *test; - float d, d1, d2, frac, s, t, ns; - int i, j, is, it, b; - int x, y, u, v, numsamples, radius, color[4], largest; - byte *image; - vec3_t point, origin, total; - - VectorSet(filter, 1, 1, 1); - - if (noalphashading) - return; - - if (volume->numtransFacets <= 0) - return; - - if (light->type == LIGHT_SURFACEDIRECTED) - { - // project the light map pixel origin onto the area light source plane - d = DotProduct(lmp, light->normal) - DotProduct(light->normal, light->w.points[0]); - VectorMA(lmp, -d, light->normal, origin); - } - else - { - VectorCopy(light->origin, origin); - } - for (i = 0; i < volume->numtransFacets; i++) - { - test = lsurfaceTest[ volume->transSurfaces[i] ]; - facet = &test->facets[ volume->transFacets[i] ]; - // if this surface does not cast an alpha shadow - if ( !(test->shader->surfaceFlags & SURF_ALPHASHADOW) ) - continue; - // if there are no texture pixel available - if ( !test->shader->pixels ) { - continue; - } - // - d1 = DotProduct( origin, facet->plane.normal) - facet->plane.dist; - d2 = DotProduct( lmp, facet->plane.normal ) - facet->plane.dist; - // this should never happen because the light volume went through the facet - if ( ( d1 < 0 ) == ( d2 < 0 ) ) { - continue; - } - // calculate the crossing point - frac = d1 / ( d1 - d2 ); - - for ( j = 0 ; j < 3 ; j++ ) { - point[j] = origin[j] + frac * ( lmp[j] - origin[j] ); - } - - s = DotProduct( point, facet->textureMatrix[0] ) + facet->textureMatrix[0][3]; - t = DotProduct( point, facet->textureMatrix[1] ) + facet->textureMatrix[1][3]; - if (s < 0) - s = 0; - if (t < 0) - t = 0; - - s = s - floor( s ); - t = t - floor( t ); - - is = s * test->shader->width; - it = t * test->shader->height; - - //if old style alpha shading - if (nocolorshading) { - image = test->shader->pixels + 4 * ( it * test->shader->width + is ); - - // alpha filter - b = image[3]; - - // alpha test makes this a binary option - b = b < 128 ? 0 : 255; - - filter[0] = filter[0] * (255-b) / 255; - filter[1] = filter[1] * (255-b) / 255; - filter[2] = filter[2] * (255-b) / 255; - } - else { - VectorClear(total); - numsamples = 0; - radius = 2; - for ( u = -radius; u <= radius; u++ ) - { - x = is + u; - if ( x < 0 || x >= test->shader->width) - continue; - for ( v = -radius; v <= radius; v++ ) - { - y = it + v; - if ( y < 0 || y >= test->shader->height) - continue; - - image = test->shader->pixels + 4 * ( y * test->shader->width + x ); - color[0] = image[0]; - color[1] = image[1]; - color[2] = image[2]; - largest = 0; - for (j = 0; j < 3; j++) - if (image[j] > largest) - largest = image[j]; - if (largest <= 0 || image[3] == 0) { - color[0] = 255; - color[1] = 255; - color[2] = 255; - largest = 255; - } - total[0] += ((float) color[0]/largest) * (255-image[3]) / 255.0; - total[1] += ((float) color[1]/largest) * (255-image[3]) / 255.0; - total[2] += ((float) color[2]/largest) * (255-image[3]) / 255.0; - numsamples++; - } - } - ns = numsamples; - // - filter[0] *= total[0] / ns; - filter[1] *= total[1] / ns; - filter[2] *= total[2] / ns; - } - } -} - -/* -============= -VS_LightSurfaceWithVolume -============= -*/ -void VS_LightSurfaceWithVolume( int surfaceNum, int facetNum, vsound_t *light, lightvolume_t *volume ) -{ - int i; - dsurface_t *ds; - lFacet_t *facet; - lsurfaceTest_t *test; - winding_t w; - vec3_t base, dir, delta, normal, filter, origin; - int min_x[LIGHTMAP_SIZE+2], max_x[LIGHTMAP_SIZE+2]; - int min_y, max_y, k, x, y, n; - float *color, distscale; - float d, add, angle, dist, area, insidearea, coords[MAX_POINTS_ON_WINDING+1][2]; - mesh_t *mesh; - byte polygonedges[(LIGHTMAP_SIZE+1) * (LIGHTMAP_SIZE+1) / 8]; - - - ds = &drawSurfaces[surfaceNum]; - - // vertex-lit triangle model - if ( ds->surfaceType == MST_TRIANGLE_SOUP ) { - return; - } - - if ( ds->lightmapNum < 0 ) { - return; // doesn't need lighting - } - - test = lsurfaceTest[ surfaceNum ]; - facet = &test->facets[ facetNum ]; - - if (defaulttracelight && !test->always_vsound) - return; - if (test->always_tracelight) - return; - - memcpy(w.points, facet->points, sizeof(vec3_t) * facet->numpoints); - w.numpoints = facet->numpoints; - - for (i = 0; i < volume->numplanes; i++) - { - //if totally on the back - if (VS_ChopWinding(&w, &volume->planes[i], 0.01) == SIDE_BACK) - return; - } - - // only one thread at a time may write to the lightmap of this surface - MutexLock(test->mutex); - - test->numvolumes++; - - if (ds->surfaceType == MST_PATCH) - { - // FIXME: reduce size and don't mark all as edge - min_y = ds->lightmapY + facet->y; - max_y = ds->lightmapY + facet->y + facet->height - 1; - for (y = min_y; y <= max_y; y++) - { - min_x[y] = ds->lightmapX + facet->x; - max_x[y] = ds->lightmapX + facet->x + facet->width - 1; - for (x = min_x[y]; x <= max_x[y]; x++) - { - n = y * LIGHTMAP_SIZE + x; - polygonedges[n >> 3] |= 1 << (n & 7); - } - } - } - else - { - for (i = 0; i < w.numpoints; i++) - { - float s, t; - - if (i >= MAX_POINTS_ON_WINDING) - _printf("coords overflow\n"); - if (ds->surfaceType != MST_PATCH) - { - VectorSubtract(w.points[i], facet->mins, delta); - s = DotProduct( delta, facet->lightmapMatrix[0] ) + ds->lightmapX + 0.5; - t = DotProduct( delta, facet->lightmapMatrix[1] ) + ds->lightmapY + 0.5; - if (s >= LIGHTMAP_SIZE) - s = LIGHTMAP_SIZE - 0.5; - if (s < 0) - s = 0; - if (t >= LIGHTMAP_SIZE) - t = LIGHTMAP_SIZE - 0.5; - if (t < 0) - t = 0; - coords[i][0] = s; - coords[i][1] = t; - } - else - { - s = DotProduct( w.points[i], facet->lightmapMatrix[0] ) + facet->lightmapMatrix[0][3]; - t = DotProduct( w.points[i], facet->lightmapMatrix[1] ) + facet->lightmapMatrix[1][3]; - - s = s - floor( s ); - t = t - floor( t ); - - coords[i][0] = ds->lightmapX + s * LIGHTMAP_SIZE;// + 0.5; - coords[i][1] = ds->lightmapY + t * LIGHTMAP_SIZE;// + 0.5; - - if (coords[i][0] >= LIGHTMAP_SIZE) - coords[i][0] -= LIGHTMAP_SIZE; - if (coords[i][1] >= LIGHTMAP_SIZE) - coords[i][1] -= LIGHTMAP_SIZE; - if (coords[i][0] < ds->lightmapX) - coords[i][0] = ds->lightmapX; - if (coords[i][1] < ds->lightmapY) - coords[i][1] = ds->lightmapY; - } - x = coords[i][0]; - y = coords[i][1]; - if (x < ds->lightmapX || x >= LIGHTMAP_SIZE) - _printf("VS_LightSurfaceWithVolume: x outside lightmap\n"); - if (y < ds->lightmapY || y >= LIGHTMAP_SIZE) - _printf("VS_LightSurfaceWithVolume: y outside lightmap\n"); - } - coords[i][0] = coords[0][0]; - coords[i][1] = coords[0][1]; - - // - min_y = LIGHTMAP_SIZE; - max_y = 0; - for (i = 0; i < LIGHTMAP_SIZE; i++) - { - min_x[i] = LIGHTMAP_SIZE; - max_x[i] = 0; - } - memset(polygonedges, 0, sizeof(polygonedges)); - // scan convert the polygon onto the lightmap - // for each edge it marks *every* lightmap pixel the edge goes through - // so no brasenham and no scan conversion used for texture mapping but - // more something like ray casting - // this is necesary because we need all lightmap pixels totally or partly - // inside the light volume. these lightmap pixels are only lit for the part - // that they are inside the light volume. - for (i = 0; i < w.numpoints; i++) - { - float xf, yf, dx, dy, xstep, ystep, xfrac, yfrac; - int xinc, yinc; - - xf = coords[i][0]; - yf = coords[i][1]; - dx = coords[i+1][0] - xf; - dy = coords[i+1][1] - yf; - // - x = (int) xf; - y = (int) yf; - // - if (y < min_y) - min_y = y; - if (y > max_y) - max_y = y; - // - if (fabs(dx) > fabs(dy)) - { - if (dx > 0) - { - // y fraction at integer x below fractional x - yfrac = yf + (floor(xf) - xf) * dy / dx; - xinc = 1; - } - else if (dx < 0) - { - // y fraction at integer x above fractional x - yfrac = yf + (floor(xf) + 1 - xf) * dy / dx; - xinc = -1; - } - else - { - yfrac = yf; - xinc = 0; - } - // step in y direction per 1 unit in x direction - if (dx) - ystep = dy / fabs(dx); - else - ystep = 0; - while(1) - { - if (x < ds->lightmapX || x >= LIGHTMAP_SIZE) - _printf("VS_LightSurfaceWithVolume: x outside lightmap\n"); - if (y < ds->lightmapY || y >= LIGHTMAP_SIZE) - _printf("VS_LightSurfaceWithVolume: y outside lightmap\n"); - // - n = y * LIGHTMAP_SIZE + x; - polygonedges[n >> 3] |= 1 << (n & 7); - if (x < min_x[y]) - min_x[y] = x; - if (x > max_x[y]) - max_x[y] = x; - if (x == (int) coords[i+1][0]) - break; - yfrac += ystep; - if (dy > 0) - { - if (yfrac > (float) y + 1) - { - y += 1; - // - n = y * LIGHTMAP_SIZE + x; - polygonedges[n >> 3] |= 1 << (n & 7); - if (x < min_x[y]) - min_x[y] = x; - if (x > max_x[y]) - max_x[y] = x; - } - } - else - { - if (yfrac < (float) y) - { - y -= 1; - // - n = y * LIGHTMAP_SIZE + x; - polygonedges[n >> 3] |= 1 << (n & 7); - if (x < min_x[y]) - min_x[y] = x; - if (x > max_x[y]) - max_x[y] = x; - } - } - x += xinc; - } - } - else - { - if (dy > 0) - { - //x fraction at integer y below fractional y - xfrac = xf + (floor(yf) - yf) * dx / dy; - yinc = 1; - } - else if (dy < 0) - { - //x fraction at integer y above fractional y - xfrac = xf + (floor(yf) + 1 - yf) * dx / dy; - yinc = -1; - } - else - { - xfrac = xf; - yinc = 0; - } - // step in x direction per 1 unit in y direction - if (dy) - xstep = dx / fabs(dy); - else - xstep = 0; - while(1) - { - if (x < ds->lightmapX || x >= LIGHTMAP_SIZE) - _printf("VS_LightSurfaceWithVolume: x outside lightmap\n"); - if (y < ds->lightmapY || y >= LIGHTMAP_SIZE) - _printf("VS_LightSurfaceWithVolume: y outside lightmap\n"); - // - n = y * LIGHTMAP_SIZE + x; - polygonedges[n >> 3] |= 1 << (n & 7); - if (x < min_x[y]) - min_x[y] = x; - if (x > max_x[y]) - max_x[y] = x; - if (y == (int) coords[i+1][1]) - break; - xfrac += xstep; - if (dx > 0) - { - if (xfrac > (float) x + 1) - { - x += 1; - // - n = y * LIGHTMAP_SIZE + x; - polygonedges[n >> 3] |= 1 << (n & 7); - if (x < min_x[y]) - min_x[y] = x; - if (x > max_x[y]) - max_x[y] = x; - } - } - else - { - if (xfrac < (float) x) - { - x -= 1; - // - n = y * LIGHTMAP_SIZE + x; - polygonedges[n >> 3] |= 1 << (n & 7); - if (x < min_x[y]) - min_x[y] = x; - if (x > max_x[y]) - max_x[y] = x; - } - } - y += yinc; - } - } - } - } - // map light onto the lightmap - for (y = min_y; y <= max_y; y++) - { - for (x = min_x[y]; x <= max_x[y]; x++) - { - if (ds->surfaceType == MST_PATCH) - { - mesh = test->detailMesh; - VectorCopy( mesh->verts[(y-ds->lightmapY)*mesh->width+x-ds->lightmapX].xyz, base); - VectorCopy( mesh->verts[(y-ds->lightmapY)*mesh->width+x-ds->lightmapX].normal, normal); - //VectorCopy(facet->plane.normal, normal); - } - else - { - VectorMA(ds->lightmapOrigin, (float) x - ds->lightmapX, ds->lightmapVecs[0], base); - VectorMA(base, (float) y - ds->lightmapY, ds->lightmapVecs[1], base); - VectorCopy(facet->plane.normal, normal); - } - if (light->type == LIGHT_POINTSPOT) - { - float distByNormal; - vec3_t pointAtDist; - float radiusAtDist; - float sampleRadius; - vec3_t distToSample; - float coneScale; - - VectorSubtract( light->origin, base, dir ); - - distByNormal = -DotProduct( dir, light->normal ); - if ( distByNormal < 0 ) { - continue; - } - VectorMA( light->origin, distByNormal, light->normal, pointAtDist ); - radiusAtDist = light->radiusByDist * distByNormal; - - VectorSubtract( base, pointAtDist, distToSample ); - sampleRadius = VectorLength( distToSample ); - - if ( sampleRadius >= radiusAtDist ) { - continue; // outside the cone - } - if ( sampleRadius <= radiusAtDist - 32 ) { - coneScale = 1.0; // fully inside - } else { - coneScale = ( radiusAtDist - sampleRadius ) / 32.0; - } - - dist = VectorNormalize( dir, dir ); - // clamp the distance to prevent super hot spots - if ( dist < 16 ) { - dist = 16; - } - angle = DotProduct( normal, dir ); - if (angle > 1) - angle = 1; - if (angle > 0) { - if ( light->atten_angletype == LAAT_QUADRATIC ) { - angle = 1 - angle; - angle *= angle; - angle = 1 - angle; - } - else if ( light->atten_angletype == LAAT_DOUBLEQUADRATIC ) { - angle = 1 - angle; - angle *= angle * angle; - angle = 1 - angle; - } - } - if (light->atten_anglescale > 0) { - angle /= light->atten_anglescale; - if (angle > 1) - angle = 1; - } - if (light->atten_distscale > 0) { - distscale = light->atten_distscale; - } - else { - distscale = 1; - } - // - if ( light->atten_disttype == LDAT_NOSCALE ) { - add = angle * coneScale; - } - else if ( light->atten_disttype == LDAT_LINEAR ) { - add = angle * light->photons * lightLinearScale * coneScale - dist * distscale; - if ( add < 0 ) { - add = 0; - } - } - else { - add = light->photons / ( dist * dist * distscale) * angle * coneScale; - } - if (add <= 1.0) - continue; - } - else if (light->type == LIGHT_POINTFAKESURFACE) - { - // calculate the contribution - add = PointToPolygonFormFactor( base, normal, &light->w ); - if ( add <= 0 ) { - if ( light->twosided ) { - add = -add; - } else { - continue; - } - } - } - else if (light->type == LIGHT_SURFACEDIRECTED) - { - //VectorCopy(light->normal, dir); - //VectorInverse(dir); - // project the light map pixel origin onto the area light source plane - d = DotProduct(base, light->normal) - DotProduct(light->normal, light->w.points[0]); - VectorMA(base, -d, light->normal, origin); - VectorSubtract(origin, base, dir); - dist = VectorNormalize(dir, dir); - if ( dist < 16 ) { - dist = 16; - } - // - angle = DotProduct( normal, dir ); - if (angle > 1) - angle = 1; - if (angle > 0) { - if ( light->atten_angletype == LAAT_QUADRATIC ) { - angle = 1 - angle; - angle *= angle; - angle = 1 - angle; - } - else if ( light->atten_angletype == LAAT_DOUBLEQUADRATIC ) { - angle = 1 - angle; - angle *= angle * angle; - angle = 1 - angle; - } - } - if (light->atten_anglescale > 0) { - angle /= light->atten_anglescale; - if (angle > 1) - angle = 1; - } - if (light->atten_distscale > 0) { - distscale = light->atten_distscale; - } - else { - distscale = 1; - } - if ( light->atten_disttype == LDAT_NOSCALE ) { - add = angle; - } - else if ( light->atten_disttype == LDAT_LINEAR ) { - add = angle * light->photons * lightLinearScale - dist * distscale; - if ( add < 0 ) { - add = 0; - } - } else { //default quadratic - add = light->photons / ( dist * dist * distscale) * angle; - } - if (add <= 0) - continue; - } - else //normal radial point light - { - VectorSubtract(light->origin, base, dir); - dist = VectorNormalize(dir, dir); - if ( dist < 16 ) { - dist = 16; - } - angle = DotProduct( normal, dir ); - if (angle > 1) - angle = 1; - if (angle > 0) { - if ( light->atten_angletype == LAAT_QUADRATIC ) { - angle = 1 - angle; - angle *= angle; - angle = 1 - angle; - } - else if ( light->atten_angletype == LAAT_DOUBLEQUADRATIC ) { - angle = 1 - angle; - angle *= angle * angle; - angle = 1 - angle; - } - } - if (light->atten_anglescale > 0) { - angle /= light->atten_anglescale; - if (angle > 1) - angle = 1; - } - if (light->atten_distscale > 0) { - distscale = light->atten_distscale; - } - else { - distscale = 1; - } - if ( light->atten_disttype == LDAT_NOSCALE ) { - add = angle; - } - else if ( light->atten_disttype == LDAT_LINEAR ) { - add = angle * light->photons * lightLinearScale - dist * distscale; - if ( add < 0 ) { - add = 0; - } - } else { - add = light->photons / ( dist * dist * distscale) * angle; - } - if (add <= 1.0) - continue; - } - // - k = (ds->lightmapNum * LIGHTMAP_HEIGHT + y) * LIGHTMAP_WIDTH + x; - //if on one of the edges - n = y * LIGHTMAP_SIZE + x; - if ((polygonedges[n >> 3] & (1 << (n & 7)) )) - { - // multiply 'add' by the relative area being lit of the total visible lightmap pixel area - // - // first create a winding for the lightmap pixel - if (ds->surfaceType == MST_PATCH) - { - mesh = test->detailMesh; - if (y-ds->lightmapY >= mesh->height-1) - _printf("y outside mesh\n"); - if (x-ds->lightmapX >= mesh->width-1) - _printf("x outside mesh\n"); - VectorCopy( mesh->verts[(y-ds->lightmapY)*mesh->width+x-ds->lightmapX].xyz, w.points[0]); - VectorCopy( mesh->verts[(y+1-ds->lightmapY)*mesh->width+x-ds->lightmapX].xyz, w.points[1]); - VectorCopy( mesh->verts[(y+1-ds->lightmapY)*mesh->width+x+1-ds->lightmapX].xyz, w.points[2]); - VectorCopy( mesh->verts[(y-ds->lightmapY)*mesh->width+x+1-ds->lightmapX].xyz, w.points[3]); - w.numpoints = 4; - } - else - { - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT - ds->lightmapX, ds->lightmapVecs[0], w.points[0]); - VectorMA(w.points[0], (float) y - LIGHTMAP_PIXELSHIFT - ds->lightmapY, ds->lightmapVecs[1], w.points[0]); - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT - ds->lightmapX, ds->lightmapVecs[0], w.points[1]); - VectorMA(w.points[1], (float) y - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapY, ds->lightmapVecs[1], w.points[1]); - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapX, ds->lightmapVecs[0], w.points[2]); - VectorMA(w.points[2], (float) y - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapY, ds->lightmapVecs[1], w.points[2]); - VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapX, ds->lightmapVecs[0], w.points[3]); - VectorMA(w.points[3], (float) y - LIGHTMAP_PIXELSHIFT - ds->lightmapY, ds->lightmapVecs[1], w.points[3]); - w.numpoints = 4; - } - // - // take the visible area of the lightmap pixel into account - // - //area = WindingArea(&w); - area = lightmappixelarea[k]; - if (area <= 0) - continue; - // chop the lightmap pixel winding with the light volume - for (i = 0; i < volume->numplanes; i++) - { - //if totally on the back - if (VS_ChopWinding(&w, &volume->planes[i], 0) == SIDE_BACK) - break; - } - // if the lightmap pixel is partly inside the light volume - if (i >= volume->numplanes) - { - insidearea = WindingArea(&w); - if (insidearea <= 0) - i = 0; - add = add * insidearea / area; - } - else - { - //DebugNet_DrawWinding(&w, 2); - continue; // this shouldn't happen - } - } - // get the light filter from all the translucent surfaces the light volume went through - VS_GetFilter(light, volume, base, filter); - // - color = &lightFloats[k*3]; - color[0] += add * light->color[0] * filter[0]; - color[1] += add * light->color[1] * filter[1]; - color[2] += add * light->color[2] * filter[2]; - } - } - - MutexUnlock(test->mutex); -} - -#endif - -/* -============= -VS_SplitLightVolume -============= -*/ -int VS_SplitLightVolume(lightvolume_t *volume, lightvolume_t *back, plane_t *split, float epsilon) -{ - lightvolume_t f, b; - vec_t dists[128]; - int sides[128]; - int counts[3]; - vec_t dot; - int i, j; - vec_t *p1, *p2; - vec3_t mid; - - counts[0] = counts[1] = counts[2] = 0; - - // determine sides for each point - for (i = 0; i < volume->numplanes; i++) - { - dot = DotProduct (volume->points[i], split->normal); - dot -= split->dist; - dists[i] = dot; - if (dot > epsilon) - sides[i] = SIDE_FRONT; - else if (dot < -epsilon) - sides[i] = SIDE_BACK; - else - { - sides[i] = SIDE_ON; - } - counts[sides[i]]++; - } - - if (!counts[1]) - return 0; // completely on front side - - if (!counts[0]) - return 1; // completely on back side - - sides[i] = sides[0]; - dists[i] = dists[0]; - - f.numplanes = 0; - b.numplanes = 0; - - for (i = 0; i < volume->numplanes; i++) - { - p1 = volume->points[i]; - - if (f.numplanes >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VS_SplitLightVolume -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return 0; // can't chop -- fall back to original - } - if (b.numplanes >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VS_SplitLightVolume -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return 0; // can't chop -- fall back to original - } - - if (sides[i] == SIDE_ON) - { - VectorCopy(p1, f.points[f.numplanes]); - VectorCopy(p1, b.points[b.numplanes]); - if (sides[i+1] == SIDE_BACK) - { - f.planes[f.numplanes] = *split; - b.planes[b.numplanes] = volume->planes[i]; - } - else if (sides[i+1] == SIDE_FRONT) - { - f.planes[f.numplanes] = volume->planes[i]; - b.planes[b.numplanes] = *split; - VectorInverse(b.planes[b.numplanes].normal); - b.planes[b.numplanes].dist = -b.planes[b.numplanes].dist; - } - else //this shouldn't happen - { - f.planes[f.numplanes] = *split; - b.planes[b.numplanes] = *split; - VectorInverse(b.planes[b.numplanes].normal); - b.planes[b.numplanes].dist = -b.planes[b.numplanes].dist; - } - f.numplanes++; - b.numplanes++; - continue; - } - - if (sides[i] == SIDE_FRONT) - { - VectorCopy (p1, f.points[f.numplanes]); - f.planes[f.numplanes] = volume->planes[i]; - f.numplanes++; - } - if (sides[i] == SIDE_BACK) - { - VectorCopy (p1, b.points[b.numplanes]); - b.planes[b.numplanes] = volume->planes[i]; - b.numplanes++; - } - - if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) - continue; - - if (f.numplanes >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VS_SplitLightVolume -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return 0; // can't chop -- fall back to original - } - if (b.numplanes >= MAX_POINTS_ON_FIXED_WINDING) - { - _printf("WARNING: VS_SplitLightVolume -> MAX_POINTS_ON_FIXED_WINDING overflowed\n"); - return 0; // can't chop -- fall back to original - } - - // generate a split point - p2 = volume->points[(i+1)%volume->numplanes]; - - dot = dists[i] / (dists[i]-dists[i+1]); - for (j=0 ; j<3 ; j++) - { // avoid round off error when possible - if (split->normal[j] == 1) - mid[j] = split->dist; - else if (split->normal[j] == -1) - mid[j] = -split->dist; - else - mid[j] = p1[j] + dot*(p2[j]-p1[j]); - } - - VectorCopy (mid, f.points[f.numplanes]); - VectorCopy(mid, b.points[b.numplanes]); - if (sides[i+1] == SIDE_BACK) - { - f.planes[f.numplanes] = *split; - b.planes[b.numplanes] = volume->planes[i]; - } - else - { - f.planes[f.numplanes] = volume->planes[i]; - b.planes[b.numplanes] = *split; - VectorInverse(b.planes[b.numplanes].normal); - b.planes[b.numplanes].dist = -b.planes[b.numplanes].dist; - } - f.numplanes++; - b.numplanes++; - } - memcpy(volume->points, f.points, sizeof(vec3_t) * f.numplanes); - memcpy(volume->planes, f.planes, sizeof(plane_t) * f.numplanes); - volume->numplanes = f.numplanes; - memcpy(back->points, b.points, sizeof(vec3_t) * b.numplanes); - memcpy(back->planes, b.planes, sizeof(plane_t) * b.numplanes); - back->numplanes = b.numplanes; - - return 2; -} - -/* -============= -VS_PlaneForEdgeToWinding -============= -*/ -void VS_PlaneForEdgeToWinding(vec3_t p1, vec3_t p2, winding_t *w, int windingonfront, plane_t *plane) -{ - int i, j; - float length, d; - vec3_t v1, v2; - - VectorSubtract(p2, p1, v1); - for (i = 0; i < w->numpoints; i++) - { - VectorSubtract (w->points[i], p1, v2); - - plane->normal[0] = v1[1]*v2[2] - v1[2]*v2[1]; - plane->normal[1] = v1[2]*v2[0] - v1[0]*v2[2]; - plane->normal[2] = v1[0]*v2[1] - v1[1]*v2[0]; - - // if points don't make a valid plane, skip it - length = plane->normal[0] * plane->normal[0] - + plane->normal[1] * plane->normal[1] - + plane->normal[2] * plane->normal[2]; - - if (length < ON_EPSILON) - continue; - - length = 1/sqrt(length); - - plane->normal[0] *= length; - plane->normal[1] *= length; - plane->normal[2] *= length; - - plane->dist = DotProduct (w->points[i], plane->normal); - // - for (j = 0; j < w->numpoints; j++) - { - if (j == i) - continue; - d = DotProduct(w->points[j], plane->normal) - plane->dist; - if (windingonfront) - { - if (d < -ON_EPSILON) - break; - } - else - { - if (d > ON_EPSILON) - break; - } - } - if (j >= w->numpoints) - return; - } -} - -/* -============= -VS_R_CastLightAtSurface -============= -*/ -void VS_R_FloodLight(vsound_t *light, lightvolume_t *volume, int cluster, int firstportal); - -void VS_R_CastLightAtSurface(vsound_t *light, lightvolume_t *volume) -{ - lsurfaceTest_t *test; - int i, n; - - // light the surface with this volume - VS_LightSurfaceWithVolume(volume->surfaceNum, volume->facetNum, light, volume); - // - test = lsurfaceTest[ volume->surfaceNum ]; - // if this is not a translucent surface - if ( !(test->shader->surfaceFlags & SURF_ALPHASHADOW) && !(test->shader->contents & CONTENTS_TRANSLUCENT)) - return; - // - if (volume->numtransFacets >= MAX_TRANSLUCENTFACETS) - Error("a light valume went through more than %d translucent facets", MAX_TRANSLUCENTFACETS); - //add this translucent surface to the list - volume->transSurfaces[volume->numtransFacets] = volume->surfaceNum; - volume->transFacets[volume->numtransFacets] = volume->facetNum; - volume->numtransFacets++; - //clear the tested facets except the translucent ones - memset(volume->facetTested, 0, sizeof(volume->facetTested)); - for (i = 0; i < volume->numtransFacets; i++) - { - test = lsurfaceTest[ volume->transSurfaces[i] ]; - n = test->facets[volume->transFacets[i]].num; - volume->facetTested[n >> 3] |= 1 << (n & 7); - } - memset(volume->clusterTested, 0, sizeof(volume->clusterTested)); - volume->endplane = volume->farplane; - volume->surfaceNum = -1; - volume->facetNum = 0; - VS_R_FloodLight(light, volume, volume->cluster, 0); - if (volume->surfaceNum >= 0) - { - VS_R_CastLightAtSurface(light, volume); - } -} - -/* -============= -VS_R_SplitLightVolume -============= -*/ -static int numvolumes = 0; - -int VS_R_SplitLightVolume(vsound_t *light, lightvolume_t *volume, plane_t *split, int cluster, int firstportal) -{ - lightvolume_t back; - int res; - - // - res = VS_SplitLightVolume(volume, &back, split, 0.1); - // if the volume was split - if (res == 2) - { - memcpy(back.clusterTested, volume->clusterTested, sizeof(back.clusterTested)); - memcpy(back.facetTested, volume->facetTested, sizeof(back.facetTested)); - back.num = numvolumes++; - back.endplane = volume->endplane; - back.surfaceNum = volume->surfaceNum; - back.facetNum = volume->facetNum; - back.type = volume->type; - back.cluster = volume->cluster; - back.farplane = volume->farplane; - if (volume->numtransFacets > 0) - { - memcpy(back.transFacets, volume->transFacets, sizeof(back.transFacets)); - memcpy(back.transSurfaces, volume->transSurfaces, sizeof(back.transSurfaces)); - } - back.numtransFacets = volume->numtransFacets; - // - // flood the volume at the back of the split plane - VS_R_FloodLight(light, &back, cluster, firstportal); - // if the back volume hit a surface - if (back.surfaceNum >= 0) - { - VS_R_CastLightAtSurface(light, &back); - } - } - return res; -} - -/* -============= -VS_R_FloodLight -============= -*/ -void VS_R_FloodLight(vsound_t *light, lightvolume_t *volume, int cluster, int firstportal) -{ - int i, j, k, res, surfaceNum, backfaceculled, testculled; - float d; - winding_t winding, tmpwinding; - lleaf_t *leaf; - lportal_t *p; - lsurfaceTest_t *test; - lFacet_t *facet; - vec3_t dir1, dir2; - plane_t plane; - - // DebugNet_RemoveAllPolys(); - // VS_DrawLightVolume(light, volume); - - // if the first portal is not zero then we've checked all occluders in this leaf already - if (firstportal == 0) - { - // check all potential occluders in this leaf - for (i = 0; i < leafs[cluster].numSurfaces; i++) - { - surfaceNum = clustersurfaces[leafs[cluster].firstSurface + i]; - // - test = lsurfaceTest[ surfaceNum ]; - if ( !test ) - continue; - // - testculled = qfalse; - // use surface as an occluder - for (j = 0; j < test->numFacets; j++) - { - // use each facet as an occluder - facet = &test->facets[j]; - // - // memcpy(winding.points, facet->points, sizeof(vec3_t) * facet->numpoints); - // winding.numpoints = facet->numpoints; - // DebugNet_DrawWinding(&winding, 5); - // - // if the facet was tested already - if ( volume->facetTested[facet->num >> 3] & (1 << (facet->num & 7)) ) - continue; - volume->facetTested[facet->num >> 3] |= 1 << (facet->num & 7); - // backface culling for planar surfaces - backfaceculled = qfalse; - if (!test->patch && !test->trisoup) - { - if (volume->type == VOLUME_NORMAL) - { - // facet backface culling - d = DotProduct(light->origin, facet->plane.normal) - facet->plane.dist; - if (d < 0) - { - // NOTE: this doesn't work too great because of sometimes very bad tesselation - // of surfaces that are supposed to be flat - // FIXME: to work around this problem we should make sure that all facets - // created from planar surfaces use the lightmapVecs normal vector - /* - if ( !test->shader->twoSided ) - { - // skip all other facets of this surface as well because they are in the same plane - for (k = 0; k < test->numFacets; k++) - { - facet = &test->facets[k]; - volume->facetTested[facet->num >> 3] |= 1 << (facet->num & 7); - } - }*/ - backfaceculled = qtrue; - } - } - else - { - // FIXME: if all light source winding points are at the back of the facet - // plane then backfaceculled = qtrue - } - } - else // backface culling per facet for patches and triangle soups - { - if (volume->type == VOLUME_NORMAL) - { - // facet backface culling - d = DotProduct(light->origin, facet->plane.normal) - facet->plane.dist; - if (d < 0) - backfaceculled = qtrue; - } - else - { - // FIXME: if all light source winding points are at the back of the facet - // plane then backfaceculled = qtrue - } - } - /* chopping does this already - // check if this facet is totally or partly in front of the volume end plane - for (k = 0; k < facet->numpoints; k++) - { - d = DotProduct(volume->endplane.normal, facet->points[k]) - volume->endplane.dist; - if (d > ON_EPSILON) - break; - } - // if this facet is outside the light volume - if (k >= facet->numpoints) - continue; - */ - // - if (backfaceculled) - { - // if the facet is not two sided - if ( !nobackfaceculling && !test->shader->twoSided ) - continue; - // flip the winding - for (k = 0; k < facet->numpoints; k++) - VectorCopy(facet->points[k], winding.points[facet->numpoints - k - 1]); - winding.numpoints = facet->numpoints; - } - else - { - memcpy(winding.points, facet->points, sizeof(vec3_t) * facet->numpoints); - winding.numpoints = facet->numpoints; - } - // - if (!testculled) - { - testculled = qtrue; - // fast check if the surface sphere is totally behind the volume end plane - d = DotProduct(volume->endplane.normal, test->origin) - volume->endplane.dist; - if (d < -test->radius) - { - for (k = 0; k < test->numFacets; k++) - { - facet = &test->facets[k]; - volume->facetTested[facet->num >> 3] |= 1 << (facet->num & 7); - } - break; - } - for (k = 0; k < volume->numplanes; k++) - { - d = DotProduct(volume->planes[k].normal, test->origin) - volume->planes[k].dist; - if (d < - test->radius) - { - for (k = 0; k < test->numFacets; k++) - { - facet = &test->facets[k]; - volume->facetTested[facet->num >> 3] |= 1 << (facet->num & 7); - } - break; - } - } - if (k < volume->numplanes) - break; - } - //NOTE: we have to chop the facet winding with the volume end plane because - // the faces in Q3 are not stitched together nicely - res = VS_ChopWinding(&winding, &volume->endplane, 0.01); - // if the facet is on or at the back of the volume end plane - if (res == SIDE_BACK || res == SIDE_ON) - continue; - // check if the facet winding is totally or partly inside the light volume - memcpy(&tmpwinding, &winding, sizeof(winding_t)); - for (k = 0; k < volume->numplanes; k++) - { - res = VS_ChopWinding(&tmpwinding, &volume->planes[k], 0.01); - if (res == SIDE_BACK || res == SIDE_ON) - break; - } - // if no part of the light volume is occluded by this facet - if (k < volume->numplanes) - continue; - // - for (k = 0; k < winding.numpoints; k++) - { - if (volume->type == VOLUME_DIRECTED) - { - VectorSubtract(winding.points[(k+1) % winding.numpoints], winding.points[k], dir1); - CrossProduct(light->normal, dir1, plane.normal); - VectorNormalize(plane.normal, plane.normal); - plane.dist = DotProduct(plane.normal, winding.points[k]); - } - else - { - VectorSubtract(winding.points[(k+1) % winding.numpoints], winding.points[k], dir1); - VectorSubtract(light->origin, winding.points[k], dir2); - CrossProduct(dir1, dir2, plane.normal); - VectorNormalize(plane.normal, plane.normal); - plane.dist = DotProduct(plane.normal, winding.points[k]); - } - res = VS_R_SplitLightVolume(light, volume, &plane, cluster, 0); - if (res == 1) - break; //the facet wasn't really inside the volume - } - if (k >= winding.numpoints) - { - volume->endplane = facet->plane; - if (backfaceculled) - { - VectorInverse(volume->endplane.normal); - volume->endplane.dist = -volume->endplane.dist; - } - volume->surfaceNum = surfaceNum; - volume->facetNum = j; - } - } - } - } - // we've tested all occluders in this cluster - volume->clusterTested[cluster >> 3] |= 1 << (cluster & 7); - // flood light through the portals of the current leaf - leaf = &leafs[cluster]; - for (i = firstportal; i < leaf->numportals; i++) - { - p = leaf->portals[i]; - // - // memcpy(&winding, p->winding, sizeof(winding_t)); - // DebugNet_DrawWinding(&winding, 5); - // if already flooded into the cluster this portal leads to - if ( volume->clusterTested[p->leaf >> 3] & (1 << (p->leaf & 7)) ) - continue; - // - if (volume->type == VOLUME_NORMAL) - { - // portal backface culling - d = DotProduct(light->origin, p->plane.normal) - p->plane.dist; - if (d > 0) // portal plane normal points into neighbour cluster - continue; - } - else - { - // FIXME: if all light source winding points are at the back of this portal - // plane then there's no need to flood through - } - // check if this portal is totally or partly in front of the volume end plane - // fast check with portal sphere - d = DotProduct(volume->endplane.normal, p->origin) - volume->endplane.dist; - if (d < -p->radius) - continue; - for (j = 0; j < p->winding->numpoints; j++) - { - d = DotProduct(volume->endplane.normal, p->winding->points[j]) - volume->endplane.dist; - if (d > -0.01) - break; - } - // if this portal is totally behind the light volume end plane - if (j >= p->winding->numpoints) - continue; - //distance from point light to portal - d = DotProduct(p->plane.normal, light->origin) - p->plane.dist; - // only check if a point light is Not *on* the portal - if (volume->type != VOLUME_NORMAL || fabs(d) > 0.1) - { - // check if the portal is partly or totally inside the light volume - memcpy(&winding, p->winding, sizeof(winding_t)); - for (j = 0; j < volume->numplanes; j++) - { - res = VS_ChopWinding(&winding, &volume->planes[j], 0.01); - if (res == SIDE_BACK || res == SIDE_ON) - break; - } - // if the light volume does not go through this portal at all - if (j < volume->numplanes) - continue; - } - // chop the light volume with the portal - for (k = 0; k < p->winding->numpoints; k++) - { - if (volume->type == VOLUME_DIRECTED) - { - VectorSubtract(p->winding->points[(k+1) % p->winding->numpoints], p->winding->points[k], dir1); - CrossProduct(light->normal, dir1, plane.normal); - VectorNormalize(plane.normal, plane.normal); - plane.dist = DotProduct(plane.normal, p->winding->points[k]); - } - else - { - VectorSubtract(p->winding->points[(k+1) % p->winding->numpoints], p->winding->points[k], dir1); - VectorSubtract(light->origin, p->winding->points[k], dir2); - CrossProduct(dir1, dir2, plane.normal); - VectorNormalize(plane.normal, plane.normal); - plane.dist = DotProduct(plane.normal, p->winding->points[k]); - } - res = VS_R_SplitLightVolume(light, volume, &plane, cluster, i+1); - if (res == 1) - break; //volume didn't really go through the portal - } - // if the light volume went through the portal - if (k >= p->winding->numpoints) - { - // flood through the portal - VS_R_FloodLight(light, volume, p->leaf, 0); - } - } -} - -/* -============= -VS_R_FloodAreaSpotLight -============= -*/ -void VS_FloodAreaSpotLight(vsound_t *light, winding_t *w, int leafnum) -{ -} - -/* -============= -VS_R_SubdivideAreaSpotLight -============= -*/ -void VS_R_SubdivideAreaSpotLight(vsound_t *light, int nodenum, winding_t *w) -{ - int leafnum, res; - dnode_t *node; - dplane_t *plane; - winding_t back; - plane_t split; - - while(nodenum >= 0) - { - node = &dnodes[nodenum]; - plane = &dplanes[node->planeNum]; - - VectorCopy(plane->normal, split.normal); - split.dist = plane->dist; - res = VS_SplitWinding (w, &back, &split, 0.1); - - if (res == SIDE_FRONT) - { - nodenum = node->children[0]; - } - else if (res == SIDE_BACK) - { - nodenum = node->children[1]; - } - else if (res == SIDE_ON) - { - memcpy(&back, w, sizeof(winding_t)); - VS_R_SubdivideAreaSpotLight(light, node->children[1], &back); - nodenum = node->children[0]; - } - else - { - VS_R_SubdivideAreaSpotLight(light, node->children[1], &back); - nodenum = node->children[0]; - } - } - leafnum = -nodenum - 1; - if (dleafs[leafnum].cluster != -1) - { - VS_FloodAreaSpotLight(light, w, leafnum); - } -} - -/* -============= -VS_R_FloodRadialAreaLight -============= -*/ -void VS_FloodRadialAreaLight(vsound_t *light, winding_t *w, int leafnum) -{ -} - -/* -============= -VS_R_SubdivideRadialAreaLight -============= -*/ -void VS_R_SubdivideRadialAreaLight(vsound_t *light, int nodenum, winding_t *w) -{ - int leafnum, res; - dnode_t *node; - dplane_t *plane; - winding_t back; - plane_t split; - - while(nodenum >= 0) - { - node = &dnodes[nodenum]; - plane = &dplanes[node->planeNum]; - - VectorCopy(plane->normal, split.normal); - split.dist = plane->dist; - res = VS_SplitWinding (w, &back, &split, 0.1); - - if (res == SIDE_FRONT) - { - nodenum = node->children[0]; - } - else if (res == SIDE_BACK) - { - nodenum = node->children[1]; - } - else if (res == SIDE_ON) - { - memcpy(&back, w, sizeof(winding_t)); - VS_R_SubdivideRadialAreaLight(light, node->children[1], &back); - nodenum = node->children[0]; - } - else - { - VS_R_SubdivideRadialAreaLight(light, node->children[1], &back); - nodenum = node->children[0]; - } - } - leafnum = -nodenum - 1; - if (dleafs[leafnum].cluster != -1) - { - VS_FloodRadialAreaLight(light, w, leafnum); - } -} - -/* -============= -VS_R_FloodDirectedLight -============= -*/ -void VS_FloodDirectedLight(vsound_t *light, winding_t *w, int leafnum) -{ - int i; - float dist; - lightvolume_t volume; - vec3_t dir; - - if (light->atten_disttype == LDAT_NOSCALE) - { - // light travels without decrease in intensity over distance - dist = MAX_WORLD_COORD; - } - else - { - if ( light->atten_disttype == LDAT_LINEAR ) - dist = light->photons * lightLinearScale; - else - dist = sqrt(light->photons); - } - - memset(&volume, 0, sizeof(lightvolume_t)); - for (i = 0; i < w->numpoints; i++) - { - VectorMA(w->points[i], dist, light->normal, volume.points[i]); - VectorSubtract(w->points[(i+1)%w->numpoints], w->points[i], dir); - CrossProduct(light->normal, dir, volume.planes[i].normal); - VectorNormalize(volume.planes[i].normal, volume.planes[i].normal); - volume.planes[i].dist = DotProduct(volume.planes[i].normal, w->points[i]); - } - volume.numplanes = w->numpoints; - VectorCopy(light->normal, volume.endplane.normal); - VectorInverse(volume.endplane.normal); - volume.endplane.dist = DotProduct(volume.endplane.normal, volume.points[0]); - volume.farplane = volume.endplane; - volume.surfaceNum = -1; - volume.type = VOLUME_DIRECTED; - volume.cluster = dleafs[leafnum].cluster; - VS_R_FloodLight(light, &volume, volume.cluster, 0); - if (volume.surfaceNum >= 0) - { - VS_R_CastLightAtSurface(light, &volume); - } -} - -/* -============= -VS_R_SubdivideDirectedAreaLight -============= -*/ -void VS_R_SubdivideDirectedAreaLight(vsound_t *light, int nodenum, winding_t *w) -{ - int leafnum, res; - dnode_t *node; - dplane_t *plane; - winding_t back; - plane_t split; - - while(nodenum >= 0) - { - node = &dnodes[nodenum]; - plane = &dplanes[node->planeNum]; - - VectorCopy(plane->normal, split.normal); - split.dist = plane->dist; - res = VS_SplitWinding (w, &back, &split, 0.1); - - if (res == SIDE_FRONT) - { - nodenum = node->children[0]; - } - else if (res == SIDE_BACK) - { - nodenum = node->children[1]; - } - else if (res == SIDE_ON) - { - memcpy(&back, w, sizeof(winding_t)); - VS_R_SubdivideDirectedAreaLight(light, node->children[1], &back); - nodenum = node->children[0]; - } - else - { - VS_R_SubdivideDirectedAreaLight(light, node->children[1], &back); - nodenum = node->children[0]; - } - } - leafnum = -nodenum - 1; - if (dleafs[leafnum].cluster != -1) - { - VS_FloodDirectedLight(light, w, leafnum); - } -} - -/* -============= -VS_FloodLight -============= -*/ -void VS_FloodLight(vsound_t *light) -{ - lightvolume_t volume; - dleaf_t *leaf; - int leafnum, i, j, k, dir[2][4] = {{1, 1, -1, -1}, {1, -1, -1, 1}}; - float a, step, dist, radius, windingdist; - vec3_t vec, r, p, temp; - winding_t winding; - - switch(light->type) - { - case LIGHT_POINTRADIAL: - { - // source is a point - // light radiates in all directions - // creates sharp shadows - // - // create 6 volumes shining in the axis directions - // what about: 4 tetrahedrons instead? - // - if ( light->atten_disttype == LDAT_LINEAR ) - dist = light->photons * lightLinearScale; - else - dist = sqrt(light->photons); - //always put the winding at a large distance to avoid epsilon issues - windingdist = MAX_WORLD_COORD; - if (dist > windingdist) - windingdist = dist; - // - leafnum = VS_LightLeafnum(light->origin); - leaf = &dleafs[leafnum]; - if (leaf->cluster == -1) - { - light->insolid = qtrue; - break; - } - // for each axis - for (i = 0; i < 3; i++) - { - // for both directions on the axis - for (j = -1; j <= 1; j += 2) - { - memset(&volume, 0, sizeof(lightvolume_t)); - volume.numplanes = 0; - for (k = 0; k < 4; k ++) - { - volume.points[volume.numplanes][i] = light->origin[i] + j * windingdist; - volume.points[volume.numplanes][(i+1)%3] = light->origin[(i+1)%3] + dir[0][k] * windingdist; - volume.points[volume.numplanes][(i+2)%3] = light->origin[(i+2)%3] + dir[1][k] * windingdist; - volume.numplanes++; - } - if (j >= 0) - { - VectorCopy(volume.points[0], temp); - VectorCopy(volume.points[2], volume.points[0]); - VectorCopy(temp, volume.points[2]); - } - for (k = 0; k < volume.numplanes; k++) - { - VS_PlaneFromPoints(&volume.planes[k], light->origin, volume.points[(k+1)%volume.numplanes], volume.points[k]); - } - VectorCopy(light->origin, temp); - temp[i] += (float) j * dist; - VectorClear(volume.endplane.normal); - volume.endplane.normal[i] = -j; - volume.endplane.dist = DotProduct(volume.endplane.normal, temp); //DotProduct(volume.endplane.normal, volume.points[0]); - volume.farplane = volume.endplane; - volume.cluster = leaf->cluster; - volume.surfaceNum = -1; - volume.type = VOLUME_NORMAL; - // - memset(volume.facetTested, 0, sizeof(volume.facetTested)); - memset(volume.clusterTested, 0, sizeof(volume.clusterTested)); - VS_R_FloodLight(light, &volume, leaf->cluster, 0); - if (volume.surfaceNum >= 0) - { - VS_R_CastLightAtSurface(light, &volume); - } - } - } - break; - } - case LIGHT_POINTSPOT: - { - // source is a point - // light is targetted - // creates sharp shadows - // - // what about using brushes to shape spot lights? that'd be pretty cool - // - if ( light->atten_disttype == LDAT_LINEAR ) - dist = light->photons * lightLinearScale; - else - dist = sqrt(light->photons); - dist *= 2; - // - windingdist = 4096; - if (dist > windingdist) - windingdist = dist; - //take 8 times the cone radius because the spotlight also lights outside the cone - radius = 8 * windingdist * light->radiusByDist; - // - memset(&volume, 0, sizeof(lightvolume_t)); - leafnum = VS_LightLeafnum(light->origin); - leaf = &dleafs[leafnum]; - if (leaf->cluster == -1) - { - light->insolid = qtrue; - break; - } - // - VectorClear(vec); - for (i = 0; i < 3; i++) - { - if (light->normal[i] > -0.9 && light->normal[i] < 0.9) - { - vec[i] = 1; - break; - } - } - CrossProduct(light->normal, vec, r); - VectorScale(r, radius, p); - volume.numplanes = 0; - step = 45; - for (a = step / 2; a < 360 + step / 2; a += step) - { - RotatePointAroundVector(volume.points[volume.numplanes], light->normal, p, a); - VectorAdd(light->origin, volume.points[volume.numplanes], volume.points[volume.numplanes]); - VectorMA(volume.points[volume.numplanes], windingdist, light->normal, volume.points[volume.numplanes]); - volume.numplanes++; - } - for (i = 0; i < volume.numplanes; i++) - { - VS_PlaneFromPoints(&volume.planes[i], light->origin, volume.points[(i+1)%volume.numplanes], volume.points[i]); - } - VectorMA(light->origin, dist, light->normal, temp); - VectorCopy(light->normal, volume.endplane.normal); - VectorInverse(volume.endplane.normal); - volume.endplane.dist = DotProduct(volume.endplane.normal, temp);//DotProduct(volume.endplane.normal, volume.points[0]); - volume.farplane = volume.endplane; - volume.cluster = leaf->cluster; - volume.surfaceNum = -1; - volume.type = VOLUME_NORMAL; - // - memset(volume.facetTested, 0, sizeof(volume.facetTested)); - memset(volume.clusterTested, 0, sizeof(volume.clusterTested)); - VS_R_FloodLight(light, &volume, leaf->cluster, 0); - if (volume.surfaceNum >= 0) - { - VS_R_CastLightAtSurface(light, &volume); - } - break; - } - case LIGHT_POINTFAKESURFACE: - { - float value; - int n, axis; - vec3_t v, vecs[2]; - - if ( light->atten_disttype == LDAT_LINEAR ) - dist = light->photons * lightLinearScale; - else - dist = sqrt(light->photons); - //always put the winding at a large distance to avoid epsilon issues - windingdist = 4096; - if (dist > windingdist) - windingdist = dist; - // - VectorMA(light->origin, 0.1, light->normal, light->origin); - // - leafnum = VS_LightLeafnum(light->origin); - leaf = &dleafs[leafnum]; - if (leaf->cluster == -1) - { - light->insolid = qtrue; - break; - } - value = 0; - for (i = 0; i < 3; i++) - { - if (fabs(light->normal[i]) > value) - { - value = fabs(light->normal[i]); - axis = i; - } - } - for (i = 0; i < 2; i++) - { - VectorClear(v); - v[(axis + 1 + i) % 3] = 1; - CrossProduct(light->normal, v, vecs[i]); - } - //cast 4 volumes at the front of the surface - for (i = -1; i <= 1; i += 2) - { - for (j = -1; j <= 1; j += 2) - { - for (n = 0; n < 2; n++) - { - memset(&volume, 0, sizeof(lightvolume_t)); - volume.numplanes = 3; - VectorMA(light->origin, i * windingdist, vecs[0], volume.points[(i == j) == n]); - VectorMA(light->origin, j * windingdist, vecs[1], volume.points[(i != j) == n]); - VectorMA(light->origin, windingdist, light->normal, volume.points[2]); - for (k = 0; k < volume.numplanes; k++) - { - VS_PlaneFromPoints(&volume.planes[k], light->origin, volume.points[(k+1)%volume.numplanes], volume.points[k]); - } - VS_PlaneFromPoints(&volume.endplane, volume.points[0], volume.points[1], volume.points[2]); - VectorMA(light->origin, dist, light->normal, temp); - volume.endplane.dist = DotProduct(volume.endplane.normal, temp); - if (DotProduct(light->origin, volume.endplane.normal) - volume.endplane.dist > 0) - break; - } - volume.farplane = volume.endplane; - volume.cluster = leaf->cluster; - volume.surfaceNum = -1; - volume.type = VOLUME_NORMAL; - // - memset(volume.facetTested, 0, sizeof(volume.facetTested)); - memset(volume.clusterTested, 0, sizeof(volume.clusterTested)); - - VS_R_FloodLight(light, &volume, leaf->cluster, 0); - if (volume.surfaceNum >= 0) - { - VS_R_CastLightAtSurface(light, &volume); - } - } - } - break; - } - case LIGHT_SURFACEDIRECTED: - { - // source is an area defined by a winding - // the light is unidirectional - // creates sharp shadows - // for instance sun light or laser light - // - memcpy(&winding, &light->w, sizeof(winding_t)); - VS_R_SubdivideDirectedAreaLight(light, 0, &winding); - break; - } - case LIGHT_SURFACERADIAL: - { - // source is an area defined by a winding - // the light radiates in all directions at the front of the winding plane - // - memcpy(&winding, &light->w, sizeof(winding_t)); - VS_R_SubdivideRadialAreaLight(light, 0, &winding); - break; - } - case LIGHT_SURFACESPOT: - { - // source is an area defined by a winding - // light is targetted but not unidirectional - // - memcpy(&winding, &light->w, sizeof(winding_t)); - VS_R_SubdivideAreaSpotLight(light, 0, &winding); - break; - } - } -} - -/* -============= -VS_FloodLightThread -============= -*/ -void VS_FloodLightThread(int num) -{ - VS_FloodLight(vsounds[num]); -} - -/* -============= -VS_TestLightLeafs -============= -*/ -void VS_TestLightLeafs(void) -{ - int leafnum, i; - vsound_t *light; - dleaf_t *leaf; - - for (i = 0; i < numvsounds; i++) - { - light = vsounds[i]; - if (light->type != LIGHT_POINTRADIAL && - light->type != LIGHT_POINTSPOT) - continue; - leafnum = VS_LightLeafnum(light->origin); - leaf = &dleafs[leafnum]; - if (leaf->cluster == -1) - if (light->type == LIGHT_POINTRADIAL) - qprintf("light in solid at %1.1f %1.1f %1.1f\n", light->origin[0], light->origin[1], light->origin[2]); - else if (light->type == LIGHT_POINTSPOT) - qprintf("spot light in solid at %1.1f %1.1f %1.1f\n", light->origin[0], light->origin[1], light->origin[2]); - } -} - - -/* -============= -VS_DoForcedTraceLight -============= -*/ -// from light.c -void TraceLtm( int num ); - -void VS_DoForcedTraceLight(int num) -{ - dsurface_t *ds; - shaderInfo_t *si; - - ds = &drawSurfaces[num]; - - if ( ds->surfaceType == MST_TRIANGLE_SOUP ) - return; - - if ( ds->lightmapNum < 0 ) - return; - - // always light entity surfaces with the old light algorithm - if ( !entitySurface[num] ) - { - si = ShaderInfoForShader( dshaders[ ds->shaderNum].shader ); - - if (defaulttracelight) - { - if (si->forceVLight) - return; - } - else - { - if (!si->forceTraceLight) - return; - } - } - - TraceLtm(num); -} - -/* -============= -VS_DoForcedTraceLightSurfaces -============= -*/ -void VS_DoForcedTraceLightSurfaces(void) -{ - _printf( "forced trace light\n" ); - RunThreadsOnIndividual( numDrawSurfaces, qtrue, VS_DoForcedTraceLight ); -} - -float *oldLightFloats; - -/* -============= -VS_SurfaceRadiosity -============= -*/ -void VS_SurfaceRadiosity( int num ) { - dsurface_t *ds; - mesh_t *mesh; - shaderInfo_t *si; - lsurfaceTest_t *test; - int x, y, k; - vec3_t base, normal; - float *color, area; - vsound_t vsound; - - ds = &drawSurfaces[num]; - - if ( ds->lightmapNum < 0 ) { - return; // doesn't have a lightmap - } - - // vertex-lit triangle model - if ( ds->surfaceType == MST_TRIANGLE_SOUP ) { - return; - } - - si = ShaderInfoForShader( dshaders[ ds->shaderNum].shader ); - test = lsurfaceTest[ num ]; - - if (!test) { - return; - } - - for (x = 0; x < ds->lightmapWidth; x++) { - for (y = 0; y < ds->lightmapHeight; y++) { - // - k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y) - * LIGHTMAP_WIDTH + ds->lightmapX + x; - area = lightmappixelarea[k]; - if (area <= 0) - continue; - // - if (ds->surfaceType == MST_PATCH) - { - mesh = test->detailMesh; - VectorCopy( mesh->verts[y*mesh->width+x].xyz, base); - VectorCopy( mesh->verts[y*mesh->width+x].normal, normal); - } - else - { - VectorMA(ds->lightmapOrigin, (float) x, ds->lightmapVecs[0], base); - VectorMA(base, (float) y, ds->lightmapVecs[1], base); - VectorCopy(test->facets[0].plane.normal, normal); - } - // create ligth from base - memset(&vsound, 0, sizeof(vsound_t)); - color = &oldLightFloats[k*3]; - // a few units away from the surface - VectorMA(base, 5, normal, vsound.origin); - ColorNormalize(color, vsound.color); - // ok this is crap - vsound.photons = VectorLength(color) * 0.05 * lightPointScale / (area * radiosity_scale); - // what about using a front facing light only ? - vsound.type = LIGHT_POINTRADIAL; - // flood the light from this lightmap pixel - VS_FloodLight(&vsound); - // only one thread at a time may write to the lightmap of this surface - MutexLock(test->mutex); - // don't light the lightmap pixel itself - lightFloats[k*3] = oldLightFloats[k*3]; - lightFloats[k*3+1] = oldLightFloats[k*3+1]; - lightFloats[k*3+2] = oldLightFloats[k*3+2]; - // - MutexUnlock(test->mutex); - } - } -} - -/* -============= -VS_Radiosity - -this aint working real well but it's fun to play with. -============= -*/ -void VS_Radiosity(void) { - - oldLightFloats = lightFloats; - lightFloats = (float *) malloc(numLightBytes * sizeof(float)); - memcpy(lightFloats, oldLightFloats, numLightBytes * sizeof(float)); - _printf("%7i surfaces\n", numDrawSurfaces); - RunThreadsOnIndividual( numDrawSurfaces, qtrue, VS_SurfaceRadiosity ); - free(oldLightFloats); -} - -/* -============= -VS_LightWorld -============= -*/ -void VS_LightWorld(void) -{ - int i, numcastedvolumes, numvsoundsinsolid; - float f; - - // find the optional world ambient - GetVectorForKey( &entities[0], "_color", lightAmbientColor ); - f = FloatForKey( &entities[0], "ambient" ); - VectorScale( lightAmbientColor, f, lightAmbientColor ); - /* - _printf("\r%6d lights out of %d", 0, numvsounds); - for (i = 0; i < numvsounds; i++) - { - _printf("\r%6d", i); - VS_FloodLight(vsounds[i]); - } - _printf("\r%6d lights out of %d\n", i, numvsounds); - */ - _printf("%7i lights\n", numvsounds); - RunThreadsOnIndividual( numvsounds, qtrue, VS_FloodLightThread ); - - numcastedvolumes = 0; - for ( i = 0 ; i < numDrawSurfaces ; i++ ) { - if (lsurfaceTest[i]) - numcastedvolumes += lsurfaceTest[i]->numvolumes; - } - _printf("%7i light volumes casted\n", numcastedvolumes); - numvsoundsinsolid = 0; - for (i = 0; i < numvsounds; i++) - { - if (vsounds[i]->insolid) - numvsoundsinsolid++; - } - _printf("%7i lights in solid\n", numvsoundsinsolid); - // - radiosity_scale = 1; - for (i = 0; i < radiosity; i++) { - VS_Radiosity(); - radiosity_scale <<= 1; - } - // - VS_StoreLightmap(); - // redo surfaces with the old light algorithm when needed - VS_DoForcedTraceLightSurfaces(); -} - -/* -============= -VS_CreateEntitySpeakers -============= -*/ -entity_t *FindTargetEntity( const char *target ); - -void VS_CreateEntitySpeakers (void) -{ - int i, c_entityLights; - vsound_t *dl; - entity_t *e, *e2; - const char *name; - const char *target; - vec3_t dest; - const char *_color; - float intensity; - int spawnflags; - - // - c_entityLights = 0; - _printf("Creating entity lights...\n"); - // - for ( i = 0 ; i < num_entities ; i++ ) { - e = &entities[i]; - name = ValueForKey (e, "classname"); - if (strncmp (name, "speaker", 7)) - continue; - - dl = malloc(sizeof(*dl)); - memset (dl, 0, sizeof(*dl)); - - spawnflags = FloatForKey (e, "spawnflags"); - if ( spawnflags & 1 ) { - dl->atten_disttype = LDAT_LINEAR; - } - if ( spawnflags & 2 ) { - dl->atten_disttype = LDAT_NOSCALE; - } - if ( spawnflags & 4 ) { - dl->atten_angletype = LAAT_QUADRATIC; - } - if ( spawnflags & 8 ) { - dl->atten_angletype = LAAT_DOUBLEQUADRATIC; - } - - dl->atten_distscale = FloatForKey(e, "atten_distscale"); - dl->atten_anglescale = FloatForKey(e, "atten_anglescale"); - - GetVectorForKey (e, "origin", dl->origin); - dl->style = FloatForKey (e, "_style"); - if (!dl->style) - dl->style = FloatForKey (e, "style"); - if (dl->style < 0) - dl->style = 0; - - intensity = FloatForKey (e, "light"); - if (!intensity) - intensity = FloatForKey (e, "_light"); - if (!intensity) - intensity = 300; - _color = ValueForKey (e, "_color"); - if (_color && _color[0]) - { - sscanf (_color, "%f %f %f", &dl->color[0],&dl->color[1],&dl->color[2]); - ColorNormalize (dl->color, dl->color); - } - else - dl->color[0] = dl->color[1] = dl->color[2] = 1.0; - - intensity = intensity * lightPointScale; - dl->photons = intensity; - - dl->type = LIGHT_POINTRADIAL; - - // lights with a target will be spotlights - target = ValueForKey (e, "target"); - - if ( target[0] ) { - float radius; - float dist; - - e2 = FindTargetEntity (target); - if (!e2) { - _printf ("WARNING: light at (%i %i %i) has missing target\n", - (int)dl->origin[0], (int)dl->origin[1], (int)dl->origin[2]); - } else { - GetVectorForKey (e2, "origin", dest); - VectorSubtract (dest, dl->origin, dl->normal); - dist = VectorNormalize (dl->normal, dl->normal); - radius = FloatForKey (e, "radius"); - if ( !radius ) { - radius = 64; - } - if ( !dist ) { - dist = 64; - } - dl->radiusByDist = (radius + 16) / dist; - dl->type = LIGHT_POINTSPOT; - } - } - vsounds[numvsounds++] = dl; - c_entityLights++; - } - _printf("%7i entity lights\n", c_entityLights); -} - -/* -================== -VS_SubdivideAreaLight -================== -*/ -void VS_SubdivideAreaLight( shaderInfo_t *ls, winding_t *w, vec3_t normal, - float areaSubdivide, qboolean backsplash ) { - float area, value, intensity; - vsound_t *dl, *dl2; - vec3_t mins, maxs; - int axis; - winding_t *front, *back; - vec3_t planeNormal; - float planeDist; - - if ( !w ) { - return; - } - - WindingBounds( w, mins, maxs ); - - // check for subdivision - for ( axis = 0 ; axis < 3 ; axis++ ) { - if ( maxs[axis] - mins[axis] > areaSubdivide ) { - VectorClear( planeNormal ); - planeNormal[axis] = 1; - planeDist = ( maxs[axis] + mins[axis] ) * 0.5; - ClipWindingEpsilon ( w, planeNormal, planeDist, ON_EPSILON, &front, &back ); - VS_SubdivideAreaLight( ls, front, normal, areaSubdivide, qfalse ); - VS_SubdivideAreaLight( ls, back, normal, areaSubdivide, qfalse ); - FreeWinding( w ); - return; - } - } - - // create a light from this - area = WindingArea (w); - if ( area <= 0 || area > 20000000 ) { - return; - } - - dl = malloc(sizeof(*dl)); - memset (dl, 0, sizeof(*dl)); - dl->type = LIGHT_POINTFAKESURFACE; - - WindingCenter( w, dl->origin ); - memcpy(dl->w.points, w->points, sizeof(vec3_t) * w->numpoints); - dl->w.numpoints = w->numpoints; - VectorCopy ( normal, dl->normal); - VectorCopy ( normal, dl->plane); - dl->plane[3] = DotProduct( dl->origin, normal ); - - value = ls->value; - intensity = value * area * lightAreaScale; - VectorAdd( dl->origin, dl->normal, dl->origin ); - - VectorCopy( ls->color, dl->color ); - - dl->photons = intensity; - - // emitColor is irrespective of the area - VectorScale( ls->color, value*lightFormFactorValueScale*lightAreaScale, dl->emitColor ); - // - VectorCopy(dl->emitColor, dl->color); - - dl->si = ls; - - if ( ls->contents & CONTENTS_FOG ) { - dl->twosided = qtrue; - } - - vsounds[numvsounds++] = dl; - - // optionally create a point backsplash light - if ( backsplash && ls->backsplashFraction > 0 ) { - - dl2 = malloc(sizeof(*dl)); - memset (dl2, 0, sizeof(*dl2)); - dl2->type = LIGHT_POINTRADIAL; - - VectorMA( dl->origin, ls->backsplashDistance, normal, dl2->origin ); - - VectorCopy( ls->color, dl2->color ); - - dl2->photons = dl->photons * ls->backsplashFraction; - dl2->si = ls; - - vsounds[numvsounds++] = dl2; - } -} - -/* -================== -VS_CreateFakeSurfaceLights -================== -*/ -void VS_CreateFakeSurfaceLights( void ) { - int i, j, side; - dsurface_t *ds; - shaderInfo_t *ls; - winding_t *w; - lFacet_t *f; - vsound_t *dl; - vec3_t origin; - drawVert_t *dv; - int c_surfaceLights; - float lightSubdivide; - vec3_t normal; - - - c_surfaceLights = 0; - _printf ("Creating surface lights...\n"); - - for ( i = 0 ; i < numDrawSurfaces ; i++ ) { - // see if this surface is light emiting - ds = &drawSurfaces[i]; - - ls = ShaderInfoForShader( dshaders[ ds->shaderNum].shader ); - if ( ls->value == 0 ) { - continue; - } - - // determine how much we need to chop up the surface - if ( ls->lightSubdivide ) { - lightSubdivide = ls->lightSubdivide; - } else { - lightSubdivide = lightDefaultSubdivide; - } - - c_surfaceLights++; - - // an autosprite shader will become - // a point light instead of an area light - if ( ls->autosprite ) { - // autosprite geometry should only have four vertexes - if ( lsurfaceTest[i] ) { - // curve or misc_model - f = lsurfaceTest[i]->facets; - if ( lsurfaceTest[i]->numFacets != 1 || f->numpoints != 4 ) { - _printf( "WARNING: surface at (%i %i %i) has autosprite shader but isn't a quad\n", - (int)f->points[0], (int)f->points[1], (int)f->points[2] ); - } - VectorAdd( f->points[0], f->points[1], origin ); - VectorAdd( f->points[2], origin, origin ); - VectorAdd( f->points[3], origin, origin ); - VectorScale( origin, 0.25, origin ); - } else { - // normal polygon - dv = &drawVerts[ ds->firstVert ]; - if ( ds->numVerts != 4 ) { - _printf( "WARNING: surface at (%i %i %i) has autosprite shader but %i verts\n", - (int)dv->xyz[0], (int)dv->xyz[1], (int)dv->xyz[2] ); - continue; - } - - VectorAdd( dv[0].xyz, dv[1].xyz, origin ); - VectorAdd( dv[2].xyz, origin, origin ); - VectorAdd( dv[3].xyz, origin, origin ); - VectorScale( origin, 0.25, origin ); - } - - dl = malloc(sizeof(*dl)); - memset (dl, 0, sizeof(*dl)); - VectorCopy( origin, dl->origin ); - VectorCopy( ls->color, dl->color ); - dl->photons = ls->value * lightPointScale; - dl->type = LIGHT_POINTRADIAL; - vsounds[numvsounds++] = dl; - continue; - } - - // possibly create for both sides of the polygon - for ( side = 0 ; side <= ls->twoSided ; side++ ) { - // create area lights - if ( lsurfaceTest[i] ) { - // curve or misc_model - for ( j = 0 ; j < lsurfaceTest[i]->numFacets ; j++ ) { - f = lsurfaceTest[i]->facets + j; - w = AllocWinding( f->numpoints ); - w->numpoints = f->numpoints; - memcpy( w->points, f->points, f->numpoints * 12 ); - - VectorCopy( f->plane.normal, normal ); - if ( side ) { - winding_t *t; - - t = w; - w = ReverseWinding( t ); - FreeWinding( t ); - VectorSubtract( vec3_origin, normal, normal ); - } - VS_SubdivideAreaLight( ls, w, normal, lightSubdivide, qtrue ); - } - } else { - // normal polygon - - w = AllocWinding( ds->numVerts ); - w->numpoints = ds->numVerts; - for ( j = 0 ; j < ds->numVerts ; j++ ) { - VectorCopy( drawVerts[ds->firstVert+j].xyz, w->points[j] ); - } - VectorCopy( ds->lightmapVecs[2], normal ); - if ( side ) { - winding_t *t; - - t = w; - w = ReverseWinding( t ); - FreeWinding( t ); - VectorSubtract( vec3_origin, normal, normal ); - } - VS_SubdivideAreaLight( ls, w, normal, lightSubdivide, qtrue ); - } - } - } - - _printf( "%7i light emitting surfaces\n", c_surfaceLights ); -} - - -/* -================== -VS_WindingForBrushSide -================== -*/ -winding_t *VS_WindingForBrushSide(dbrush_t *brush, int side, winding_t *w) -{ - int i, res; - winding_t *tmpw; - plane_t plane; - - VectorCopy(dplanes[ dbrushsides[ brush->firstSide + side ].planeNum ].normal, plane.normal); - VectorInverse(plane.normal); - plane.dist = -dplanes[ dbrushsides[ brush->firstSide + side ].planeNum ].dist; - tmpw = BaseWindingForPlane( plane.normal, plane.dist ); - memcpy(w->points, tmpw->points, sizeof(vec3_t) * tmpw->numpoints); - w->numpoints = tmpw->numpoints; - - for (i = 0; i < brush->numSides; i++) - { - if (i == side) - continue; - VectorCopy(dplanes[ dbrushsides[ brush->firstSide + i ].planeNum ].normal, plane.normal); - VectorInverse(plane.normal); - plane.dist = -dplanes[ dbrushsides[ brush->firstSide + i ].planeNum ].dist; - res = VS_ChopWinding(w, &plane, 0.1); - if (res == SIDE_BACK) - return NULL; - } - return w; -} - -/* -================== -VS_CreateSkyLights -================== -*/ -void VS_CreateSkyLights(void) -{ - int i, j, c_skyLights; - dbrush_t *b; - shaderInfo_t *si; - dbrushside_t *s; - vsound_t *dl; - vec3_t sunColor, sunDir = { 0.45, 0.3, 0.9 }; - float d; - - VectorNormalize(sunDir, sunDir); - VectorInverse(sunDir); - - c_skyLights = 0; - _printf("Creating sky lights...\n"); - // find the sky shader - for ( i = 0 ; i < numDrawSurfaces ; i++ ) { - si = ShaderInfoForShader( dshaders[ drawSurfaces[i].shaderNum ].shader ); - if ( si->surfaceFlags & SURF_SKY ) { - VectorCopy( si->sunLight, sunColor ); - VectorCopy( si->sunDirection, sunDir ); - VectorInverse(sunDir); - break; - } - } - - // find the brushes - for ( i = 0 ; i < numbrushes ; i++ ) { - b = &dbrushes[i]; - for ( j = 0 ; j < b->numSides ; j++ ) { - s = &dbrushsides[ b->firstSide + j ]; - if ( dshaders[ s->shaderNum ].surfaceFlags & SURF_SKY ) { - //if this surface doesn't face in the same direction as the sun - d = DotProduct(dplanes[ s->planeNum ].normal, sunDir); - if (d <= 0) - continue; - // - dl = malloc(sizeof(*dl)); - memset (dl, 0, sizeof(*dl)); - VectorCopy(sunColor, dl->color); - VectorCopy(sunDir, dl->normal); - VectorCopy(dplanes[ s->planeNum ].normal, dl->plane); - dl->plane[3] = dplanes[ s->planeNum ].dist; - dl->type = LIGHT_SURFACEDIRECTED; - dl->atten_disttype = LDAT_NOSCALE; - VS_WindingForBrushSide(b, j, &dl->w); -// DebugNet_DrawWinding(&dl->w, 2); - // - vsounds[numvsounds++] = dl; - c_skyLights++; - } - } - } - _printf("%7i light emitting sky surfaces\n", c_skyLights); -} - -/* -================== -VS_SetPortalSphere -================== -*/ -void VS_SetPortalSphere (lportal_t *p) -{ - int i; - vec3_t total, dist; - winding_t *w; - float r, bestr; - - w = p->winding; - VectorCopy (vec3_origin, total); - for (i=0 ; i<w->numpoints ; i++) - { - VectorAdd (total, w->points[i], total); - } - - for (i=0 ; i<3 ; i++) - total[i] /= w->numpoints; - - bestr = 0; - for (i=0 ; i<w->numpoints ; i++) - { - VectorSubtract (w->points[i], total, dist); - r = VectorLength (dist); - if (r > bestr) - bestr = r; - } - VectorCopy (total, p->origin); - p->radius = bestr; -} - -/* -================== -VS_PlaneFromWinding -================== -*/ -void VS_PlaneFromWinding (winding_t *w, plane_t *plane) -{ - vec3_t v1, v2; - - //calc plane - VectorSubtract (w->points[2], w->points[1], v1); - VectorSubtract (w->points[0], w->points[1], v2); - CrossProduct (v2, v1, plane->normal); - VectorNormalize (plane->normal, plane->normal); - plane->dist = DotProduct (w->points[0], plane->normal); -} - -/* -================== -VS_AllocWinding -================== -*/ -winding_t *VS_AllocWinding (int points) -{ - winding_t *w; - int size; - - if (points > MAX_POINTS_ON_WINDING) - Error ("NewWinding: %i points", points); - - size = (int)((winding_t *)0)->points[points]; - w = malloc (size); - memset (w, 0, size); - - return w; -} - -/* -============ -VS_LoadPortals -============ -*/ -void VS_LoadPortals (char *name) -{ - int i, j, hint; - lportal_t *p; - lleaf_t *l; - char magic[80]; - FILE *f; - int numpoints; - winding_t *w; - int leafnums[2]; - plane_t plane; - // - - if (!strcmp(name,"-")) - f = stdin; - else - { - f = fopen(name, "r"); - if (!f) - Error ("LoadPortals: couldn't read %s\n",name); - } - - if (fscanf (f,"%79s\n%i\n%i\n%i\n",magic, &portalclusters, &numportals, &numfaces) != 4) - Error ("LoadPortals: failed to read header"); - if (strcmp(magic, PORTALFILE)) - Error ("LoadPortals: not a portal file"); - - _printf ("%6i portalclusters\n", portalclusters); - _printf ("%6i numportals\n", numportals); - _printf ("%6i numfaces\n", numfaces); - - if (portalclusters >= MAX_CLUSTERS) - Error ("more than %d clusters in portal file\n", MAX_CLUSTERS); - - // each file portal is split into two memory portals - portals = malloc(2*numportals*sizeof(lportal_t)); - memset (portals, 0, 2*numportals*sizeof(lportal_t)); - - leafs = malloc(portalclusters*sizeof(lleaf_t)); - memset (leafs, 0, portalclusters*sizeof(lleaf_t)); - - for (i=0, p=portals ; i<numportals ; i++) - { - if (fscanf (f, "%i %i %i ", &numpoints, &leafnums[0], &leafnums[1]) != 3) - Error ("LoadPortals: reading portal %i", i); - if (numpoints > MAX_POINTS_ON_WINDING) - Error ("LoadPortals: portal %i has too many points", i); - if ( (unsigned)leafnums[0] > portalclusters - || (unsigned)leafnums[1] > portalclusters) - Error ("LoadPortals: reading portal %i", i); - if (fscanf (f, "%i ", &hint) != 1) - Error ("LoadPortals: reading hint state"); - - w = p->winding = VS_AllocWinding (numpoints); - w->numpoints = numpoints; - - for (j=0 ; j<numpoints ; j++) - { - double v[3]; - int k; - - // scanf into double, then assign to vec_t - // so we don't care what size vec_t is - if (fscanf (f, "(%lf %lf %lf ) " - , &v[0], &v[1], &v[2]) != 3) - Error ("LoadPortals: reading portal %i", i); - for (k=0 ; k<3 ; k++) - w->points[j][k] = v[k]; - } - fscanf (f, "\n"); - - // calc plane - VS_PlaneFromWinding (w, &plane); - - // create forward portal - l = &leafs[leafnums[0]]; - if (l->numportals == MAX_PORTALS_ON_LEAF) - Error ("Leaf with too many portals"); - l->portals[l->numportals] = p; - l->numportals++; - - p->winding = w; - VectorSubtract (vec3_origin, plane.normal, p->plane.normal); - p->plane.dist = -plane.dist; - p->leaf = leafnums[1]; - VS_SetPortalSphere (p); - p++; - - // create backwards portal - l = &leafs[leafnums[1]]; - if (l->numportals == MAX_PORTALS_ON_LEAF) - Error ("Leaf with too many portals"); - l->portals[l->numportals] = p; - l->numportals++; - - p->winding = VS_AllocWinding(w->numpoints); - p->winding->numpoints = w->numpoints; - for (j=0 ; j<w->numpoints ; j++) - { - VectorCopy (w->points[w->numpoints-1-j], p->winding->points[j]); - } - - p->plane = plane; - p->leaf = leafnums[0]; - VS_SetPortalSphere (p); - p++; - - } - - fclose (f); -} - -/* -============ -VLightMain -============ -*/ -int VSoundMain (int argc, char **argv) { - int i; - double start, end; - const char *value; - - _printf ("----- VLighting ----\n"); - - for (i=1 ; i<argc ; i++) { - if (!strcmp(argv[i],"-v")) { - verbose = qtrue; - } else if (!strcmp(argv[i],"-threads")) { - numthreads = atoi (argv[i+1]); - _printf("num threads = %d\n", numthreads); - i++; - } else if (!strcmp(argv[i],"-area")) { - lightAreaScale *= atof(argv[i+1]); - _printf ("area light scaling at %f\n", lightAreaScale); - i++; - } else if (!strcmp(argv[i],"-point")) { - lightPointScale *= atof(argv[i+1]); - _printf ("point light scaling at %f\n", lightPointScale); - i++; - } else if (!strcmp(argv[i], "-samplesize")) { - samplesize = atoi(argv[i+1]); - if (samplesize < 1) samplesize = 1; - i++; - _printf("lightmap sample size is %dx%d units\n", samplesize, samplesize); - } else if (!strcmp(argv[i], "-nostitching")) { - nostitching = qtrue; - _printf("no stitching = true\n"); - } else if (!strcmp(argv[i], "-noalphashading")) { - noalphashading = qtrue; - _printf("no alpha shading = true\n"); - } else if (!strcmp(argv[i], "-nocolorshading")) { - nocolorshading = qtrue; - _printf("old style alpha shading = true\n"); - } else if (!strcmp(argv[i], "-nobackfaceculling")) { - nobackfaceculling = qtrue; - _printf("no backface culling = true\n"); - } else if (!strcmp(argv[i], "-tracelight")) { - defaulttracelight = qtrue; - _printf("default trace light = true\n"); - } else if (!strcmp(argv[i], "-radiosity")) { - radiosity = atoi(argv[i+1]); - _printf("radiosity = %d\n", radiosity); - i++; - } else { - break; - } - } - - ThreadSetDefault (); - - if (i != argc - 1) { - _printf("usage: q3map -vsound [-<switch> [-<switch> ...]] <mapname>\n" - "\n" - "Switches:\n" - " v = verbose output\n" - " threads <X> = set number of threads to X\n" - " area <V> = set the area light scale to V\n" - " point <W> = set the point light scale to W\n" - " novertex = don't calculate vertex lighting\n" - " nogrid = don't calculate light grid for dynamic model lighting\n" - " nostitching = no polygon stitching before lighting\n" - " noalphashading = don't use alpha shading\n" - " nocolorshading = don't use color alpha shading\n" - " tracelight = use old light algorithm by default\n" - " samplesize <N> = set the lightmap pixel size to NxN units\n"); - exit(0); - } - - SetQdirFromPath (argv[i]); - -#ifdef _WIN32 - InitPakFile(gamedir, NULL); -#endif - - strcpy (source, ExpandArg(argv[i])); - StripExtension (source); - DefaultExtension (source, ".bsp"); - - LoadShaderInfo(); - - _printf ("reading %s\n", source); - - LoadBSPFile (source); - ParseEntities(); - - value = ValueForKey( &entities[0], "gridsize" ); - if (strlen(value)) { - sscanf( value, "%f %f %f", &gridSize[0], &gridSize[1], &gridSize[2] ); - _printf("grid size = {%1.1f, %1.1f, %1.1f}\n", gridSize[0], gridSize[1], gridSize[2]); - } - - CountLightmaps(); - - StripExtension (source); - DefaultExtension (source, ".prt"); - - VS_LoadPortals(source); - - // set surfaceOrigin - SetEntityOrigins(); - - // grid and vertex lighting - GridAndVertexLighting(); - -#ifdef DEBUGNET - DebugNet_Setup(); -#endif - - start = clock(); - - lightFloats = (float *) malloc(numLightBytes * sizeof(float)); - memset(lightFloats, 0, numLightBytes * sizeof(float)); - - VS_InitSurfacesForTesting(); - - VS_CalcVisibleLightmapPixelArea(); - - numvsounds = 0; - VS_CreateEntitySpeakers(); - VS_CreateFakeSurfaceLights(); - VS_CreateSkyLights(); - - VS_TestLightLeafs(); - - VS_LightWorld(); - -#ifndef LIGHTPOLYS - StripExtension (source); - DefaultExtension (source, ".bsp"); - _printf ("writing %s\n", source); - WriteBSPFile (source); -#endif - - end = clock(); - - _printf ("%5.2f seconds elapsed\n", (end-start) / CLK_TCK); - -#ifdef LIGHTPOLYS - VS_DrawLightWindings(); -#endif - -#ifdef DEBUGNET - DebugNet_Shutdown(); -#endif - return 0; -} diff --git a/q3map/surface.c b/q3map/surface.c deleted file mode 100644 index 75daf1c..0000000 --- a/q3map/surface.c +++ /dev/null @@ -1,1158 +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" - - -mapDrawSurface_t mapDrawSurfs[MAX_MAP_DRAW_SURFS]; -int numMapDrawSurfs; - -/* -============================================================================= - -DRAWSURF CONSTRUCTION - -============================================================================= -*/ - -/* -================= -AllocDrawSurf -================= -*/ -mapDrawSurface_t *AllocDrawSurf( void ) { - mapDrawSurface_t *ds; - - if ( numMapDrawSurfs >= MAX_MAP_DRAW_SURFS ) { - Error( "MAX_MAP_DRAW_SURFS"); - } - ds = &mapDrawSurfs[ numMapDrawSurfs ]; - numMapDrawSurfs++; - - return ds; -} - -/* -================= -DrawSurfaceForSide -================= -*/ -#define SNAP_FLOAT_TO_INT 8 -#define SNAP_INT_TO_FLOAT (1.0/SNAP_FLOAT_TO_INT) - -mapDrawSurface_t *DrawSurfaceForSide( bspbrush_t *b, side_t *s, winding_t *w ) { - mapDrawSurface_t *ds; - int i, j; - shaderInfo_t *si; - drawVert_t *dv; - float mins[2], maxs[2]; - - // brush primitive : - // axis base - vec3_t texX,texY; - vec_t x,y; - - if ( w->numpoints > 64 ) { - Error( "DrawSurfaceForSide: w->numpoints = %i", w->numpoints ); - } - - si = s->shaderInfo; - - ds = AllocDrawSurf(); - - ds->shaderInfo = si; - ds->mapBrush = b; - ds->side = s; - ds->fogNum = -1; - ds->numVerts = w->numpoints; - ds->verts = malloc( ds->numVerts * sizeof( *ds->verts ) ); - memset( ds->verts, 0, ds->numVerts * sizeof( *ds->verts ) ); - - mins[0] = mins[1] = 99999; - maxs[0] = maxs[1] = -99999; - - // 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; - - // round the xyz to a given precision - for ( i = 0 ; i < 3 ; i++ ) { - dv->xyz[i] = SNAP_INT_TO_FLOAT * floor( w->p[j][i] * SNAP_FLOAT_TO_INT + 0.5 ); - } - - 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]; - } - - for ( i = 0 ; i < 2 ; i++ ) { - if ( dv->st[i] < mins[i] ) { - mins[i] = dv->st[i]; - } - if ( dv->st[i] > maxs[i] ) { - maxs[i] = dv->st[i]; - } - } - - // 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 ds; -} - - -//========================================================================= - - - - -typedef struct { - int planenum; - shaderInfo_t *shaderInfo; - int count; -} sideRef_t; - -#define MAX_SIDE_REFS MAX_MAP_PLANES - -sideRef_t sideRefs[MAX_SIDE_REFS]; -int numSideRefs; - -void AddSideRef( side_t *side ) { - int i; - - for ( i = 0 ; i < numSideRefs ; i++ ) { - if ( side->planenum == sideRefs[i].planenum - && side->shaderInfo == sideRefs[i].shaderInfo ) { - sideRefs[i].count++; - return; - } - } - - if ( numSideRefs == MAX_SIDE_REFS ) { - Error( "MAX_SIDE_REFS" ); - } - - sideRefs[i].planenum = side->planenum; - sideRefs[i].shaderInfo = side->shaderInfo; - sideRefs[i].count++; - numSideRefs++; -} - - -/* -===================== -MergeSides - -===================== -*/ -void MergeSides( entity_t *e, tree_t *tree ) { - int i; - - qprintf( "----- MergeSides -----\n"); - - for ( i = e->firstDrawSurf ; i < numMapDrawSurfs ; i++ ) { -// AddSideRef( side ); - } - - qprintf( "%5i siderefs\n", numSideRefs ); -} - -//===================================================================== - -/* -=================== -SubdivideDrawSurf -=================== -*/ -void SubdivideDrawSurf( mapDrawSurface_t *ds, winding_t *w, float subdivisions ) { - int i; - int axis; - vec3_t bounds[2]; - const float epsilon = 0.1; - int subFloor, subCeil; - winding_t *frontWinding, *backWinding; - mapDrawSurface_t *newds; - - if ( !w ) { - return; - } - if ( w->numpoints < 3 ) { - Error( "SubdivideDrawSurf: Bad w->numpoints" ); - } - - ClearBounds( bounds[0], bounds[1] ); - for ( i = 0 ; i < w->numpoints ; i++ ) { - AddPointToBounds( w->p[i], bounds[0], bounds[1] ); - } - - for ( axis = 0 ; axis < 3 ; axis++ ) { - vec3_t planePoint = { 0, 0, 0 }; - vec3_t planeNormal = { 0, 0, 0 }; - float d; - - subFloor = floor( bounds[0][axis] / subdivisions ) * subdivisions; - subCeil = ceil( bounds[1][axis] / subdivisions ) * subdivisions; - - planePoint[axis] = subFloor + subdivisions; - planeNormal[axis] = -1; - - d = DotProduct( planePoint, planeNormal ); - - // subdivide if necessary - if ( subCeil - subFloor > subdivisions ) { - // gotta clip polygon into two polygons - ClipWindingEpsilon( w, planeNormal, d, epsilon, &frontWinding, &backWinding ); - - // the clip may not produce two polygons if it was epsilon close - if ( !frontWinding ) { - w = backWinding; - } else if ( !backWinding ) { - w = frontWinding; - } else { - SubdivideDrawSurf( ds, frontWinding, subdivisions ); - SubdivideDrawSurf( ds, backWinding, subdivisions ); - - return; - } - } - } - - // emit this polygon - newds = DrawSurfaceForSide( ds->mapBrush, ds->side, w ); - newds->fogNum = ds->fogNum; -} - - -/* -===================== -SubdivideDrawSurfs - -Chop up surfaces that have subdivision attributes -===================== -*/ -void SubdivideDrawSurfs( entity_t *e, tree_t *tree ) { - int i; - mapDrawSurface_t *ds; - int numBaseDrawSurfs; - winding_t *w; - float subdivision; - shaderInfo_t *si; - - qprintf( "----- SubdivideDrawSurfs -----\n"); - numBaseDrawSurfs = numMapDrawSurfs; - for ( i = e->firstDrawSurf ; i < numBaseDrawSurfs ; i++ ) { - ds = &mapDrawSurfs[i]; - - // only subdivide brush sides, not patches or misc_models - if ( !ds->side ) { - continue; - } - - // check subdivision for shader - si = ds->side->shaderInfo; - if ( !si ) { - continue; - } - - if (ds->shaderInfo->autosprite || si->autosprite) { - continue; - } - - subdivision = si->subdivisions; - if ( !subdivision ) { - continue; - } - - w = WindingFromDrawSurf( ds ); - ds->numVerts = 0; // remove this reference - SubdivideDrawSurf( ds, w, subdivision ); - } - -} - - -//=================================================================================== - -/* -==================== -ClipSideIntoTree_r - -Adds non-opaque leaf fragments to the convex hull -==================== -*/ -void ClipSideIntoTree_r( winding_t *w, side_t *side, node_t *node ) { - plane_t *plane; - winding_t *front, *back; - - if ( !w ) { - return; - } - - if ( node->planenum != PLANENUM_LEAF ) { - if ( side->planenum == node->planenum ) { - ClipSideIntoTree_r( w, side, node->children[0] ); - return; - } - if ( side->planenum == ( node->planenum ^ 1) ) { - ClipSideIntoTree_r( w, side, node->children[1] ); - return; - } - - plane = &mapplanes[ node->planenum ]; - ClipWindingEpsilon ( w, plane->normal, plane->dist, - ON_EPSILON, &front, &back ); - FreeWinding( w ); - - ClipSideIntoTree_r( front, side, node->children[0] ); - ClipSideIntoTree_r( back, side, node->children[1] ); - - return; - } - - // if opaque leaf, don't add - if ( !node->opaque ) { - AddWindingToConvexHull( w, &side->visibleHull, mapplanes[ side->planenum ].normal ); - } - - FreeWinding( w ); - return; -} - - -/* -===================== -ClipSidesIntoTree - -Creates side->visibleHull for all visible sides - -The drawsurf for a side will consist of the convex hull of -all points in non-opaque clusters, which allows overlaps -to be trimmed off automatically. -===================== -*/ -void ClipSidesIntoTree( entity_t *e, tree_t *tree ) { - bspbrush_t *b; - int i; - winding_t *w; - side_t *side, *newSide; - shaderInfo_t *si; - - qprintf( "----- ClipSidesIntoTree -----\n"); - - for ( b = e->brushes ; b ; b = b->next ) { - for ( i = 0 ; i < b->numsides ; i++ ) { - side = &b->sides[i]; - if ( !side->winding) { - continue; - } - w = CopyWinding( side->winding ); - side->visibleHull = NULL; - ClipSideIntoTree_r( w, side, tree->headnode ); - - w = side->visibleHull; - if ( !w ) { - continue; - } - si = side->shaderInfo; - if ( !si ) { - continue; - } - // don't create faces for non-visible sides - if ( si->surfaceFlags & SURF_NODRAW ) { - continue; - } - - // always use the original quad winding for auto sprites - if ( side->shaderInfo->autosprite ) { - w = side->winding; - } - // - if ( side->bevel ) { - Error( "monkey tried to create draw surface for brush bevel" ); - } - // save this winding as a visible surface - DrawSurfaceForSide( b, side, w ); - - // make a back side for it if needed - if ( !(si->contents & CONTENTS_FOG) ) { - continue; - } - - // duplicate the up-facing side - w = ReverseWinding( w ); - - newSide = malloc( sizeof( *side ) ); - *newSide = *side; - newSide->visibleHull = w; - newSide->planenum ^= 1; - - // save this winding as a visible surface - DrawSurfaceForSide( b, newSide, w ); - - } - } -} - -/* -=================================================================================== - - FILTER REFERENCES DOWN THE TREE - -=================================================================================== -*/ - -/* -==================== -FilterDrawSurfIntoTree - -Place a reference to the given drawsurf in every leaf it contacts -We assume that the point mesh aproximation to the curve will get a -reference into all the leafs we need. -==================== -*/ -int FilterMapDrawSurfIntoTree( vec3_t point, mapDrawSurface_t *ds, node_t *node ) { - drawSurfRef_t *dsr; - float d; - plane_t *plane; - int c; - - if ( node->planenum != PLANENUM_LEAF ) { - plane = &mapplanes[ node->planenum ]; - d = DotProduct( point, plane->normal ) - plane->dist; - c = 0; - if ( d >= -ON_EPSILON ) { - c += FilterMapDrawSurfIntoTree( point, ds, node->children[0] ); - } - if ( d <= ON_EPSILON ) { - c += FilterMapDrawSurfIntoTree( point, ds, node->children[1] ); - } - return c; - } - - // if opaque leaf, don't add - if ( node->opaque ) { - return 0; - } - - // add the drawsurf if it hasn't been already - for ( dsr = node->drawSurfReferences ; dsr ; dsr = dsr->nextRef ) { - if ( dsr->outputNumber == numDrawSurfaces ) { - return 0; // already referenced - } - } - - dsr = malloc( sizeof( *dsr ) ); - dsr->outputNumber = numDrawSurfaces; - dsr->nextRef = node->drawSurfReferences; - node->drawSurfReferences = dsr; - return 1; -} - -/* -==================== -FilterDrawSurfIntoTree_r - -Place a reference to the given drawsurf in every leaf it is in -==================== -*/ -int FilterMapDrawSurfIntoTree_r( winding_t *w, mapDrawSurface_t *ds, node_t *node ) { - drawSurfRef_t *dsr; - plane_t *plane; - int total; - winding_t *front, *back; - - if ( node->planenum != PLANENUM_LEAF ) { - plane = &mapplanes[ node->planenum ]; - ClipWindingEpsilon ( w, plane->normal, plane->dist, - ON_EPSILON, &front, &back ); - - total = 0; - if ( front ) { - total += FilterMapDrawSurfIntoTree_r( front, ds, node->children[0] ); - } - if ( back ) { - total += FilterMapDrawSurfIntoTree_r( back, ds, node->children[1] ); - } - - FreeWinding( w ); - return total; - } - - // if opaque leaf, don't add - if ( node->opaque ) { - return 0; - } - - // add the drawsurf if it hasn't been already - for ( dsr = node->drawSurfReferences ; dsr ; dsr = dsr->nextRef ) { - if ( dsr->outputNumber == numDrawSurfaces ) { - return 0; // already referenced - } - } - - dsr = malloc( sizeof( *dsr ) ); - dsr->outputNumber = numDrawSurfaces; - dsr->nextRef = node->drawSurfReferences; - node->drawSurfReferences = dsr; - return 1; -} - -/* -==================== -FilterSideIntoTree_r - -Place a reference to the given drawsurf in every leaf it contacts -==================== -*/ -int FilterSideIntoTree_r( winding_t *w, side_t *side, mapDrawSurface_t *ds, node_t *node ) { - drawSurfRef_t *dsr; - plane_t *plane; - winding_t *front, *back; - int total; - - if ( !w ) { - return 0; - } - - if ( node->planenum != PLANENUM_LEAF ) { - if ( side->planenum == node->planenum ) { - return FilterSideIntoTree_r( w, side, ds, node->children[0] ); - } - if ( side->planenum == ( node->planenum ^ 1) ) { - return FilterSideIntoTree_r( w, side, ds, node->children[1] ); - } - - plane = &mapplanes[ node->planenum ]; - ClipWindingEpsilon ( w, plane->normal, plane->dist, - ON_EPSILON, &front, &back ); - - total = FilterSideIntoTree_r( front, side, ds, node->children[0] ); - total += FilterSideIntoTree_r( back, side, ds, node->children[1] ); - - FreeWinding( w ); - return total; - } - - // if opaque leaf, don't add - if ( node->opaque ) { - return 0; - } - - dsr = malloc( sizeof( *dsr ) ); - dsr->outputNumber = numDrawSurfaces; - dsr->nextRef = node->drawSurfReferences; - node->drawSurfReferences = dsr; - - FreeWinding( w ); - return 1; -} - - -/* -===================== -FilterFaceIntoTree -===================== -*/ -int FilterFaceIntoTree( mapDrawSurface_t *ds, tree_t *tree ) { - int l; - winding_t *w; - - w = WindingFromDrawSurf( ds ); - l = FilterSideIntoTree_r( w, ds->side, ds, tree->headnode ); - - return l; -} - - - -/* -===================== -FilterPatchSurfIntoTree -===================== -*/ -#define SUBDIVISION_LIMIT 8.0 -int FilterPatchSurfIntoTree( mapDrawSurface_t *ds, tree_t *tree ) { - int i, j; - int l; - mesh_t baseMesh, *subdividedMesh; - winding_t *w; - - baseMesh.width = ds->patchWidth; - baseMesh.height = ds->patchHeight; - baseMesh.verts = ds->verts; - subdividedMesh = SubdivideMesh( baseMesh, SUBDIVISION_LIMIT, 32 ); - - l = 0; - for (i = 0; i < subdividedMesh->width-1; i++) { - for (j = 0; j < subdividedMesh->height-1; j++) { - w = AllocWinding(3); - VectorCopy(subdividedMesh->verts[j * subdividedMesh->width + i].xyz, w->p[0]); - VectorCopy(subdividedMesh->verts[j * subdividedMesh->width + i + 1].xyz, w->p[1]); - VectorCopy(subdividedMesh->verts[(j+1) * subdividedMesh->width + i].xyz, w->p[2]); - w->numpoints = 3; - l += FilterMapDrawSurfIntoTree_r( w, ds, tree->headnode ); - w = AllocWinding(3); - VectorCopy(subdividedMesh->verts[j * subdividedMesh->width + i + 1].xyz, w->p[0]); - VectorCopy(subdividedMesh->verts[(j+1) * subdividedMesh->width + i + 1].xyz, w->p[1]); - VectorCopy(subdividedMesh->verts[(j+1) * subdividedMesh->width + i].xyz, w->p[2]); - w->numpoints = 3; - l += FilterMapDrawSurfIntoTree_r( w, ds, tree->headnode ); - } - } - - // also use the old point filtering into the tree - for ( i = 0 ; i < subdividedMesh->width * subdividedMesh->height ; i++ ) { - l += FilterMapDrawSurfIntoTree( subdividedMesh->verts[i].xyz, ds, tree->headnode ); - } - - free(subdividedMesh); - - return l; -} - - -/* -===================== -FilterMiscModelSurfIntoTree -===================== -*/ -int FilterMiscModelSurfIntoTree( mapDrawSurface_t *ds, tree_t *tree ) { - int i; - int l; - winding_t *w; - - l = 0; - for (i = 0; i < ds->numIndexes-2; i++) { - w = AllocWinding(3); - VectorCopy(ds->verts[ds->indexes[i]].xyz, w->p[0]); - VectorCopy(ds->verts[ds->indexes[i+1]].xyz, w->p[1]); - VectorCopy(ds->verts[ds->indexes[i+2]].xyz, w->p[2]); - w->numpoints = 3; - l += FilterMapDrawSurfIntoTree_r( w, ds, tree->headnode ); - } - - // also use the old point filtering into the tree - for ( i = 0 ; i < ds->numVerts ; i++ ) { - l += FilterMapDrawSurfIntoTree( ds->verts[i].xyz, ds, tree->headnode ); - } - - return l; -} - -/* -===================== -FilterFlareSurfIntoTree -===================== -*/ -int FilterFlareSurfIntoTree( mapDrawSurface_t *ds, tree_t *tree ) { - return FilterMapDrawSurfIntoTree( ds->lightmapOrigin, ds, tree->headnode ); -} - - -//====================================================================== - -int c_stripSurfaces, c_fanSurfaces; - -/* -================== -IsTriangleDegenerate - -Returns qtrue if all three points are collinear or backwards -=================== -*/ -#define COLINEAR_AREA 10 -static qboolean IsTriangleDegenerate( drawVert_t *points, int a, int b, int c ) { - vec3_t v1, v2, v3; - float d; - - VectorSubtract( points[b].xyz, points[a].xyz, v1 ); - VectorSubtract( points[c].xyz, points[a].xyz, v2 ); - CrossProduct( v1, v2, v3 ); - d = VectorLength( v3 ); - - // assume all very small or backwards triangles will cause problems - if ( d < COLINEAR_AREA ) { - return qtrue; - } - - return qfalse; -} - -/* -=============== -SurfaceAsTriFan - -The surface can't be represented as a single tristrip without -leaving a degenerate triangle (and therefore a crack), so add -a point in the middle and create (points-1) triangles in fan order -=============== -*/ -static void SurfaceAsTriFan( dsurface_t *ds ) { - int i; - int colorSum[4]; - drawVert_t *mid, *v; - - // create a new point in the center of the face - if ( numDrawVerts == MAX_MAP_DRAW_VERTS ) { - Error( "MAX_MAP_DRAW_VERTS" ); - } - mid = &drawVerts[ numDrawVerts ]; - numDrawVerts++; - - colorSum[0] = colorSum[1] = colorSum[2] = colorSum[3] = 0; - - v = drawVerts + ds->firstVert; - for (i = 0 ; i < ds->numVerts ; i++, v++ ) { - VectorAdd( mid->xyz, v->xyz, mid->xyz ); - mid->st[0] += v->st[0]; - mid->st[1] += v->st[1]; - mid->lightmap[0] += v->lightmap[0]; - mid->lightmap[1] += v->lightmap[1]; - - colorSum[0] += v->color[0]; - colorSum[1] += v->color[1]; - colorSum[2] += v->color[2]; - colorSum[3] += v->color[3]; - } - - mid->xyz[0] /= ds->numVerts; - mid->xyz[1] /= ds->numVerts; - mid->xyz[2] /= ds->numVerts; - - mid->st[0] /= ds->numVerts; - mid->st[1] /= ds->numVerts; - - mid->lightmap[0] /= ds->numVerts; - mid->lightmap[1] /= ds->numVerts; - - mid->color[0] = colorSum[0] / ds->numVerts; - mid->color[1] = colorSum[1] / ds->numVerts; - mid->color[2] = colorSum[2] / ds->numVerts; - mid->color[3] = colorSum[3] / ds->numVerts; - - VectorCopy((drawVerts+ds->firstVert)->normal, mid->normal ); - - // fill in indices in trifan order - if ( numDrawIndexes + ds->numVerts*3 > MAX_MAP_DRAW_INDEXES ) { - Error( "MAX_MAP_DRAWINDEXES" ); - } - ds->firstIndex = numDrawIndexes; - ds->numIndexes = ds->numVerts*3; - - //FIXME - // should be: for ( i = 0 ; i < ds->numVerts ; i++ ) { - // set a break point and test this in a map - //for ( i = 0 ; i < ds->numVerts*3 ; i++ ) { - for ( i = 0 ; i < ds->numVerts ; i++ ) { - drawIndexes[numDrawIndexes++] = ds->numVerts; - drawIndexes[numDrawIndexes++] = i; - drawIndexes[numDrawIndexes++] = (i+1) % ds->numVerts; - } - - ds->numVerts++; -} - - -/* -================ -SurfaceAsTristrip - -Try to create indices that make (points-2) triangles in tristrip order -================ -*/ -#define MAX_INDICES 1024 -static void SurfaceAsTristrip( dsurface_t *ds ) { - int i; - int rotate; - int numIndices; - int ni; - int a, b, c; - int indices[MAX_INDICES]; - - // determine the triangle strip order - numIndices = ( ds->numVerts - 2 ) * 3; - if ( numIndices > MAX_INDICES ) { - Error( "MAX_INDICES exceeded for surface" ); - } - - // try all possible orderings of the points looking - // for a strip order that isn't degenerate - for ( rotate = 0 ; rotate < ds->numVerts ; rotate++ ) { - for ( ni = 0, i = 0 ; i < ds->numVerts - 2 - i ; i++ ) { - a = ( ds->numVerts - 1 - i + rotate ) % ds->numVerts; - b = ( i + rotate ) % ds->numVerts; - c = ( ds->numVerts - 2 - i + rotate ) % ds->numVerts; - - if ( IsTriangleDegenerate( drawVerts + ds->firstVert, a, b, c ) ) { - break; - } - indices[ni++] = a; - indices[ni++] = b; - indices[ni++] = c; - - if ( i + 1 != ds->numVerts - 1 - i ) { - a = ( ds->numVerts - 2 - i + rotate ) % ds->numVerts; - b = ( i + rotate ) % ds->numVerts; - c = ( i + 1 + rotate ) % ds->numVerts; - - if ( IsTriangleDegenerate( drawVerts + ds->firstVert, a, b, c ) ) { - break; - } - indices[ni++] = a; - indices[ni++] = b; - indices[ni++] = c; - } - } - if ( ni == numIndices ) { - break; // got it done without degenerate triangles - } - } - - // if any triangle in the strip is degenerate, - // render from a centered fan point instead - if ( ni < numIndices ) { - c_fanSurfaces++; - SurfaceAsTriFan( ds ); - return; - } - - // a normal tristrip - c_stripSurfaces++; - - if ( numDrawIndexes + ni > MAX_MAP_DRAW_INDEXES ) { - Error( "MAX_MAP_DRAW_INDEXES" ); - } - ds->firstIndex = numDrawIndexes; - ds->numIndexes = ni; - - memcpy( drawIndexes + numDrawIndexes, indices, ni * sizeof(int) ); - numDrawIndexes += ni; -} - -/* -=============== -EmitPlanarSurf -=============== -*/ -void EmitPlanarSurf( mapDrawSurface_t *ds ) { - int j; - dsurface_t *out; - drawVert_t *outv; - - if ( numDrawSurfaces == MAX_MAP_DRAW_SURFS ) { - Error( "MAX_MAP_DRAW_SURFS" ); - } - out = &drawSurfaces[ numDrawSurfaces ]; - numDrawSurfaces++; - - out->surfaceType = MST_PLANAR; - out->shaderNum = EmitShader( ds->shaderInfo->shader ); - out->firstVert = numDrawVerts; - out->numVerts = ds->numVerts; - out->fogNum = ds->fogNum; - out->lightmapNum = ds->lightmapNum; - out->lightmapX = ds->lightmapX; - out->lightmapY = ds->lightmapY; - out->lightmapWidth = ds->lightmapWidth; - out->lightmapHeight = ds->lightmapHeight; - - VectorCopy( ds->lightmapOrigin, out->lightmapOrigin ); - VectorCopy( ds->lightmapVecs[0], out->lightmapVecs[0] ); - VectorCopy( ds->lightmapVecs[1], out->lightmapVecs[1] ); - VectorCopy( ds->lightmapVecs[2], out->lightmapVecs[2] ); - - for ( j = 0 ; j < ds->numVerts ; j++ ) { - if ( numDrawVerts == MAX_MAP_DRAW_VERTS ) { - Error( "MAX_MAP_DRAW_VERTS" ); - } - outv = &drawVerts[ numDrawVerts ]; - numDrawVerts++; - memcpy( outv, &ds->verts[ j ], sizeof( *outv ) ); - outv->color[0] = 255; - outv->color[1] = 255; - outv->color[2] = 255; - outv->color[3] = 255; - } - - // create the indexes - SurfaceAsTristrip( out ); -} - - -/* -=============== -EmitPatchSurf -=============== -*/ -void EmitPatchSurf( mapDrawSurface_t *ds ) { - int j; - dsurface_t *out; - drawVert_t *outv; - - if ( numDrawSurfaces == MAX_MAP_DRAW_SURFS ) { - Error( "MAX_MAP_DRAW_SURFS" ); - } - out = &drawSurfaces[ numDrawSurfaces ]; - numDrawSurfaces++; - - out->surfaceType = MST_PATCH; - out->shaderNum = EmitShader( ds->shaderInfo->shader ); - out->firstVert = numDrawVerts; - out->numVerts = ds->numVerts; - out->firstIndex = numDrawIndexes; - out->numIndexes = ds->numIndexes; - out->patchWidth = ds->patchWidth; - out->patchHeight = ds->patchHeight; - out->fogNum = ds->fogNum; - out->lightmapNum = ds->lightmapNum; - out->lightmapX = ds->lightmapX; - out->lightmapY = ds->lightmapY; - out->lightmapWidth = ds->lightmapWidth; - out->lightmapHeight = ds->lightmapHeight; - - VectorCopy( ds->lightmapOrigin, out->lightmapOrigin ); - VectorCopy( ds->lightmapVecs[0], out->lightmapVecs[0] ); - VectorCopy( ds->lightmapVecs[1], out->lightmapVecs[1] ); - VectorCopy( ds->lightmapVecs[2], out->lightmapVecs[2] ); - - for ( j = 0 ; j < ds->numVerts ; j++ ) { - if ( numDrawVerts == MAX_MAP_DRAW_VERTS ) { - Error( "MAX_MAP_DRAW_VERTS" ); - } - outv = &drawVerts[ numDrawVerts ]; - numDrawVerts++; - memcpy( outv, &ds->verts[ j ], sizeof( *outv ) ); - outv->color[0] = 255; - outv->color[1] = 255; - outv->color[2] = 255; - outv->color[3] = 255; - } - - for ( j = 0 ; j < ds->numIndexes ; j++ ) { - if ( numDrawIndexes == MAX_MAP_DRAW_INDEXES ) { - Error( "MAX_MAP_DRAW_INDEXES" ); - } - drawIndexes[ numDrawIndexes ] = ds->indexes[ j ]; - numDrawIndexes++; - } -} - -/* -=============== -EmitFlareSurf -=============== -*/ -void EmitFlareSurf( mapDrawSurface_t *ds ) { - dsurface_t *out; - - if ( numDrawSurfaces == MAX_MAP_DRAW_SURFS ) { - Error( "MAX_MAP_DRAW_SURFS" ); - } - out = &drawSurfaces[ numDrawSurfaces ]; - numDrawSurfaces++; - - out->surfaceType = MST_FLARE; - out->shaderNum = EmitShader( ds->shaderInfo->shader ); - out->fogNum = ds->fogNum; - - VectorCopy( ds->lightmapOrigin, out->lightmapOrigin ); - VectorCopy( ds->lightmapVecs[0], out->lightmapVecs[0] ); // color - VectorCopy( ds->lightmapVecs[2], out->lightmapVecs[2] ); -} - - -/* -=============== -EmitModelSurf -=============== -*/ -void EmitModelSurf( mapDrawSurface_t *ds ) { - int j; - dsurface_t *out; - drawVert_t *outv; - - if ( numDrawSurfaces == MAX_MAP_DRAW_SURFS ) { - Error( "MAX_MAP_DRAW_SURFS" ); - } - out = &drawSurfaces[ numDrawSurfaces ]; - numDrawSurfaces++; - - out->surfaceType = MST_TRIANGLE_SOUP; - out->shaderNum = EmitShader( ds->shaderInfo->shader ); - out->firstVert = numDrawVerts; - out->numVerts = ds->numVerts; - out->firstIndex = numDrawIndexes; - out->numIndexes = ds->numIndexes; - out->patchWidth = ds->patchWidth; - out->patchHeight = ds->patchHeight; - out->fogNum = ds->fogNum; - out->lightmapNum = ds->lightmapNum; - out->lightmapX = ds->lightmapX; - out->lightmapY = ds->lightmapY; - out->lightmapWidth = ds->lightmapWidth; - out->lightmapHeight = ds->lightmapHeight; - - VectorCopy( ds->lightmapOrigin, out->lightmapOrigin ); - VectorCopy( ds->lightmapVecs[0], out->lightmapVecs[0] ); - VectorCopy( ds->lightmapVecs[1], out->lightmapVecs[1] ); - VectorCopy( ds->lightmapVecs[2], out->lightmapVecs[2] ); - - for ( j = 0 ; j < ds->numVerts ; j++ ) { - if ( numDrawVerts == MAX_MAP_DRAW_VERTS ) { - Error( "MAX_MAP_DRAW_VERTS" ); - } - outv = &drawVerts[ numDrawVerts ]; - numDrawVerts++; - memcpy( outv, &ds->verts[ j ], sizeof( *outv ) ); - outv->color[0] = 255; - outv->color[1] = 255; - outv->color[2] = 255; - } - - for ( j = 0 ; j < ds->numIndexes ; j++ ) { - if ( numDrawIndexes == MAX_MAP_DRAW_INDEXES ) { - Error( "MAX_MAP_DRAW_INDEXES" ); - } - drawIndexes[ numDrawIndexes ] = ds->indexes[ j ]; - numDrawIndexes++; - } -} - -//====================================================================== - -/* -================== -CreateFlareSurface - -Light flares from surface lights become -================== -*/ -void CreateFlareSurface( mapDrawSurface_t *faceDs ) { - mapDrawSurface_t *ds; - int i; - - ds = AllocDrawSurf(); - - if ( faceDs->shaderInfo->flareShader[0] ) { - ds->shaderInfo = ShaderInfoForShader( faceDs->shaderInfo->flareShader ); - } else { - ds->shaderInfo = ShaderInfoForShader( "flareshader" ); - } - ds->flareSurface = qtrue; - VectorCopy( faceDs->lightmapVecs[2], ds->lightmapVecs[2] ); - - // find midpoint - VectorClear( ds->lightmapOrigin ); - for ( i = 0 ; i < faceDs->numVerts ; i++ ) { - VectorAdd( ds->lightmapOrigin, faceDs->verts[i].xyz, ds->lightmapOrigin ); - } - VectorScale( ds->lightmapOrigin, 1.0/faceDs->numVerts, ds->lightmapOrigin ); - - VectorMA( ds->lightmapOrigin, 2, ds->lightmapVecs[2], ds->lightmapOrigin ); - - VectorCopy( faceDs->shaderInfo->color, ds->lightmapVecs[0] ); - - // FIXME: fog -} - -/* -===================== -FilterDrawsurfsIntoTree - -Upon completion, all drawsurfs that actually generate a reference -will have been emited to the bspfile arrays, and the references -will have valid final indexes -===================== -*/ -void FilterDrawsurfsIntoTree( entity_t *e, tree_t *tree ) { - int i; - mapDrawSurface_t *ds; - int refs; - int c_surfs, c_refs; - - qprintf( "----- FilterDrawsurfsIntoTree -----\n"); - - c_surfs = 0; - c_refs = 0; - for ( i = e->firstDrawSurf ; i < numMapDrawSurfs ; i++ ) { - ds = &mapDrawSurfs[i]; - - if ( !ds->numVerts && !ds->flareSurface ) { - continue; - } - if ( ds->miscModel ) { - refs = FilterMiscModelSurfIntoTree( ds, tree ); - EmitModelSurf( ds ); - } else if ( ds->patch ) { - refs = FilterPatchSurfIntoTree( ds, tree ); - EmitPatchSurf( ds ); - } else if ( ds->flareSurface ) { - refs = FilterFlareSurfIntoTree( ds, tree ); - EmitFlareSurf( ds ); - } else { - refs = FilterFaceIntoTree( ds, tree ); -// if ( ds->shaderInfo->value >= 1000 ) { // ds->shaderInfo->flareShader[0] ) { - if ( ds->shaderInfo->flareShader[0] ) { - CreateFlareSurface( ds ); - } - EmitPlanarSurf( ds ); - } - if ( refs > 0 ) { - c_surfs++; - c_refs += refs; - } - } - qprintf( "%5i emited drawsurfs\n", c_surfs ); - qprintf( "%5i references\n", c_refs ); - qprintf( "%5i stripfaces\n", c_stripSurfaces ); - qprintf( "%5i fanfaces\n", c_fanSurfaces ); -} - - - diff --git a/q3map/terrain.c b/q3map/terrain.c deleted file mode 100644 index 129ac08..0000000 --- a/q3map/terrain.c +++ /dev/null @@ -1,1255 +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" -#include <assert.h> - -#define SURF_WIDTH 2048 -#define SURF_HEIGHT 2048 - -#define GROW_VERTS 512 -#define GROW_INDICES 512 -#define GROW_SURFACES 128 - -#define VectorSet(v, x, y, z) v[0] = x;v[1] = y;v[2] = z; - -void QuakeTextureVecs( plane_t *plane, vec_t shift[2], vec_t rotate, vec_t scale[2], vec_t mappingVecs[2][4] ); - -typedef struct { - shaderInfo_t *shader; - int x, y; - - int maxVerts; - int numVerts; - drawVert_t *verts; - - int maxIndexes; - int numIndexes; - int *indexes; -} terrainSurf_t; - -static terrainSurf_t *surfaces = NULL; -static terrainSurf_t *lastSurface = NULL; -static int numsurfaces = 0; -static int maxsurfaces = 0; - -/* -================ -ShaderForLayer -================ -*/ -shaderInfo_t *ShaderForLayer( int minlayer, int maxlayer, const char *shadername ) { - char shader[ MAX_QPATH ]; - - if ( minlayer == maxlayer ) { - sprintf( shader, "textures/%s_%d", shadername, maxlayer ); - } else { - sprintf( shader, "textures/%s_%dto%d", shadername, minlayer, maxlayer ); - } - - return ShaderInfoForShader( shader ); -} - -/* -================ -CompareVert -================ -*/ -qboolean CompareVert( drawVert_t *v1, drawVert_t *v2, qboolean checkst ) { - int i; - - for( i = 0; i < 3; i++ ) { - if ( floor( v1->xyz[ i ] + 0.1 ) != floor( v2->xyz[ i ] + 0.1 ) ) { - return qfalse; - } - if ( checkst && ( ( v1->st[ 0 ] != v2->st[ 0 ] ) || ( v1->st[ 1 ] != v2->st[ 1 ] ) ) ) { - return qfalse; - } - } - - return qtrue; -} - -/* -================ -LoadAlphaMap -================ -*/ -byte *LoadAlphaMap( int *num_layers, int *alphawidth, int *alphaheight ) { - int *alphamap32; - byte *alphamap; - const char *alphamapname; - char ext[ 128 ]; - int width; - int height; - int layers; - int size; - int i; - - assert( alphawidth ); - assert( alphaheight ); - assert( num_layers ); - - layers = atoi( ValueForKey( mapent, "layers" ) ); - if ( layers < 1 ) { - Error ("SetTerrainTextures: invalid value for 'layers' (%d)", layers ); - } - - alphamapname = ValueForKey( mapent, "alphamap" ); - if ( !alphamapname[ 0 ] ) { - Error ("LoadAlphaMap: No alphamap specified on terrain" ); - } - - ExtractFileExtension( alphamapname, ext); - if ( !Q_stricmp( ext, "tga" ) ) { - Load32BitImage( ExpandGamePath( alphamapname ), &alphamap32, &width, &height ); - - size = width * height; - alphamap = malloc( size ); - for( i = 0; i < size; i++ ) { - alphamap[ i ] = ( ( alphamap32[ i ] & 0xff ) * layers ) / 256; - if ( alphamap[ i ] >= layers ) { - alphamap[ i ] = layers - 1; - } - } - } else { - Load256Image( ExpandGamePath( alphamapname ), &alphamap, NULL, &width, &height ); - size = width * height; - for( i = 0; i < size; i++ ) { - if ( alphamap[ i ] >= layers ) { - alphamap[ i ] = layers - 1; - } - } - } - - if ( ( width < 2 ) || ( height < 2 ) ) { - Error ("LoadAlphaMap: alphamap width/height must be at least 2x2." ); - } - - *num_layers = layers; - *alphawidth = width; - *alphaheight = height; - - return alphamap; -} - -/* -================ -CalcTerrainSize -================ -*/ -void CalcTerrainSize( vec3_t mins, vec3_t maxs, vec3_t size ) { - bspbrush_t *brush; - int i; - const char *key; - - // calculate the size of the terrain - ClearBounds( mins, maxs ); - for( brush = mapent->brushes; brush != NULL; brush = brush->next ) { - AddPointToBounds( brush->mins, mins, maxs ); - AddPointToBounds( brush->maxs, mins, maxs ); - } - - key = ValueForKey( mapent, "min" ); - if ( key[ 0 ] ) { - GetVectorForKey( mapent, "min", mins ); - } - - key = ValueForKey( mapent, "max" ); - if ( key[ 0 ] ) { - GetVectorForKey( mapent, "max", maxs ); - } - - for( i = 0; i < 3; i++ ) { - mins[ i ] = floor( mins[ i ] + 0.1 ); - maxs[ i ] = floor( maxs[ i ] + 0.1 ); - } - - VectorSubtract( maxs, mins, size ); - - if ( ( size[ 0 ] <= 0 ) || ( size[ 1 ] <= 0 ) ) { - Error ("CalcTerrainSize: Invalid terrain size: %fx%f", size[ 0 ], size[ 1 ] ); - } -} - -/* -================== -IsTriangleDegenerate - -Returns qtrue if all three points are collinear or backwards -=================== -*/ -#define COLINEAR_AREA 10 -static qboolean IsTriangleDegenerate( drawVert_t *points, int a, int b, int c ) { - vec3_t v1, v2, v3; - float d; - - VectorSubtract( points[b].xyz, points[a].xyz, v1 ); - VectorSubtract( points[c].xyz, points[a].xyz, v2 ); - CrossProduct( v1, v2, v3 ); - d = VectorLength( v3 ); - - // assume all very small or backwards triangles will cause problems - if ( d < COLINEAR_AREA ) { - return qtrue; - } - - return qfalse; -} - -/* -=============== -SideAsTriFan - -The surface can't be represented as a single tristrip without -leaving a degenerate triangle (and therefore a crack), so add -a point in the middle and create (points-1) triangles in fan order -=============== -*/ -static void SideAsTriFan( terrainSurf_t *surf, int *index, int num ) { - int i; - int colorSum[4]; - drawVert_t *mid, *v; - - // make sure we have enough space for a new vert - if ( surf->numVerts >= surf->maxVerts ) { - surf->maxVerts += GROW_VERTS; - surf->verts = realloc( surf->verts, surf->maxVerts * sizeof( *surf->verts ) ); - } - - // create a new point in the center of the face - mid = &surf->verts[ surf->numVerts ]; - surf->numVerts++; - - colorSum[0] = colorSum[1] = colorSum[2] = colorSum[3] = 0; - - for (i = 0 ; i < num; i++ ) { - v = &surf->verts[ index[ i ] ]; - VectorAdd( mid->xyz, v->xyz, mid->xyz ); - mid->st[0] += v->st[0]; - mid->st[1] += v->st[1]; - mid->lightmap[0] += v->lightmap[0]; - mid->lightmap[1] += v->lightmap[1]; - - colorSum[0] += v->color[0]; - colorSum[1] += v->color[1]; - colorSum[2] += v->color[2]; - colorSum[3] += v->color[3]; - } - - mid->xyz[0] /= num; - mid->xyz[1] /= num; - mid->xyz[2] /= num; - - mid->st[0] /= num; - mid->st[1] /= num; - - mid->lightmap[0] /= num; - mid->lightmap[1] /= num; - - mid->color[0] = colorSum[0] / num; - mid->color[1] = colorSum[1] / num; - mid->color[2] = colorSum[2] / num; - mid->color[3] = colorSum[3] / num; - - // fill in indices in trifan order - if ( surf->numIndexes + num * 3 > surf->maxIndexes ) { - surf->maxIndexes = surf->numIndexes + num * 3; - surf->indexes = realloc( surf->indexes, surf->maxIndexes * sizeof( *surf->indexes ) ); - } - - - for ( i = 0 ; i < num; i++ ) { - surf->indexes[ surf->numIndexes++ ] = surf->numVerts - 1; - surf->indexes[ surf->numIndexes++ ] = index[ i ]; - surf->indexes[ surf->numIndexes++ ] = index[ (i+1) % ( surf->numVerts - 1 ) ]; - } -} -/* -================ -SideAsTristrip - -Try to create indices that make (points-2) triangles in tristrip order -================ -*/ -#define MAX_INDICES 1024 -static void SideAsTristrip( terrainSurf_t *surf, int *index, int num ) { - int i; - int rotate; - int numIndices; - int ni; - int a, b, c; - int indices[ MAX_INDICES ]; - - // determine the triangle strip order - numIndices = ( num - 2 ) * 3; - if ( numIndices > MAX_INDICES ) { - Error( "MAX_INDICES exceeded for surface" ); - } - - // try all possible orderings of the points looking - // for a strip order that isn't degenerate - for ( rotate = 0 ; rotate < num; rotate++ ) { - for ( ni = 0, i = 0 ; i < num - 2 - i ; i++ ) { - a = index[ ( num - 1 - i + rotate ) % num ]; - b = index[ ( i + rotate ) % num ]; - c = index[ ( num - 2 - i + rotate ) % num ]; - - if ( IsTriangleDegenerate( surf->verts, a, b, c ) ) { - break; - } - indices[ni++] = a; - indices[ni++] = b; - indices[ni++] = c; - - if ( i + 1 != num - 1 - i ) { - a = index[ ( num - 2 - i + rotate ) % num ]; - b = index[ ( i + rotate ) % num ]; - c = index[ ( i + 1 + rotate ) % num ]; - - if ( IsTriangleDegenerate( surf->verts, a, b, c ) ) { - break; - } - indices[ni++] = a; - indices[ni++] = b; - indices[ni++] = c; - } - } - if ( ni == numIndices ) { - break; // got it done without degenerate triangles - } - } - - // if any triangle in the strip is degenerate, - // render from a centered fan point instead - if ( ni < numIndices ) { - SideAsTriFan( surf, index, num ); - return; - } - - // a normal tristrip - if ( surf->numIndexes + ni > surf->maxIndexes ) { - surf->maxIndexes = surf->numIndexes + ni; - surf->indexes = realloc( surf->indexes, surf->maxIndexes * sizeof( *surf->indexes ) ); - } - - memcpy( surf->indexes + surf->numIndexes, indices, ni * sizeof( *surf->indexes ) ); - surf->numIndexes += ni; -} - -/* -================ -CreateTerrainSurface -================ -*/ -void CreateTerrainSurface( terrainSurf_t *surf, shaderInfo_t *shader ) { - int i, j, k; - drawVert_t *out; - drawVert_t *in; - mapDrawSurface_t *newsurf; - - newsurf = AllocDrawSurf(); - - newsurf->miscModel = qtrue; - newsurf->shaderInfo = shader; - newsurf->lightmapNum = -1; - newsurf->fogNum = -1; - newsurf->numIndexes = surf->numIndexes; - newsurf->numVerts = surf->numVerts; - - // copy the indices - newsurf->indexes = malloc( surf->numIndexes * sizeof( *newsurf->indexes ) ); - memcpy( newsurf->indexes, surf->indexes, surf->numIndexes * sizeof( *newsurf->indexes ) ); - - // allocate the vertices - newsurf->verts = malloc( surf->numVerts * sizeof( *newsurf->verts ) ); - memset( newsurf->verts, 0, surf->numVerts * sizeof( *newsurf->verts ) ); - - // calculate the surface verts - out = newsurf->verts; - for( i = 0; i < newsurf->numVerts; i++, out++ ) { - VectorCopy( surf->verts[ i ].xyz, out->xyz ); - - // set the texture coordinates - out->st[ 0 ] = surf->verts[ i ].st[ 0 ]; - out->st[ 1 ] = surf->verts[ i ].st[ 1 ]; - - // the colors will be set by the lighting pass - out->color[0] = 255; - out->color[1] = 255; - out->color[2] = 255; - out->color[3] = surf->verts[ i ].color[ 3 ]; - - // calculate the vertex normal - VectorClear( out->normal ); - for( j = 0; j < numsurfaces; j++ ) { - in = surfaces[ j ].verts; - for( k = 0; k < surfaces[ j ].numVerts; k++, in++ ) { - if ( CompareVert( out, in, qfalse ) ) { - VectorAdd( out->normal, in->normal, out->normal ); - } - } - } - - VectorNormalize( out->normal, out->normal ); - } -} - -/* -================ -EmitTerrainVerts -================ -*/ -void EmitTerrainVerts( side_t *side, terrainSurf_t *surf, int maxlayer, int alpha[ MAX_POINTS_ON_WINDING ], qboolean projecttexture ) { - int i; - int j; - drawVert_t *vert; - int *indices; - int numindices; - int maxindices; - int xyplane; - vec3_t xynorm = { 0, 0, 1 }; - vec_t shift[ 2 ] = { 0, 0 }; - vec_t scale[ 2 ] = { 0.5, 0.5 }; - float vecs[ 2 ][ 4 ]; - static int numtimes = 0; - - numtimes++; - - if ( !surf->verts ) { - surf->numVerts = 0; - surf->maxVerts = GROW_VERTS; - surf->verts = malloc( surf->maxVerts * sizeof( *surf->verts ) ); - - surf->numIndexes = 0; - surf->maxIndexes = GROW_INDICES; - surf->indexes = malloc( surf->maxIndexes * sizeof( *surf->indexes ) ); - } - - // calculate the texture coordinate vectors - xyplane = FindFloatPlane( xynorm, 0 ); - QuakeTextureVecs( &mapplanes[ xyplane ], shift, 0, scale, vecs ); - - // emit the vertexes - numindices = 0; - maxindices = surf->maxIndexes; - indices = malloc ( maxindices * sizeof( *indices ) ); - - for ( i = 0; i < side->winding->numpoints; i++ ) { - vert = &surf->verts[ surf->numVerts ]; - - // set the final alpha value--0 for texture 1, 255 for texture 2 - if ( alpha[ i ] < maxlayer ) { - vert->color[3] = 0; - } else { - vert->color[3] = 255; - } - - vert->xyz[ 0 ] = floor( side->winding->p[ i ][ 0 ] + 0.1f ); - vert->xyz[ 1 ] = floor( side->winding->p[ i ][ 1 ] + 0.1f ); - vert->xyz[ 2 ] = floor( side->winding->p[ i ][ 2 ] + 0.1f ); - - // set the texture coordinates - if ( projecttexture ) { - vert->st[0] = ( vecs[0][3] + DotProduct( vecs[ 0 ], vert->xyz ) ) / surf->shader->width; - vert->st[1] = ( vecs[1][3] + DotProduct( vecs[ 1 ], vert->xyz ) ) / surf->shader->height; - } else { - vert->st[0] = ( side->vecs[0][3] + DotProduct( side->vecs[ 0 ], vert->xyz ) ) / surf->shader->width; - vert->st[1] = ( side->vecs[1][3] + DotProduct( side->vecs[ 1 ], vert->xyz ) ) / surf->shader->height; - } - - VectorCopy( mapplanes[ side->planenum ].normal, vert->normal ); - - for( j = 0; j < surf->numVerts; j++ ) { - if ( CompareVert( vert, &surf->verts[ j ], qtrue ) ) { - break; - } - } - - if ( numindices >= maxindices ) { - maxindices += GROW_INDICES; - indices = realloc( indices, maxindices * sizeof( *indices ) ); - } - - if ( j != surf->numVerts ) { - indices[ numindices++ ] = j; - } else { - indices[ numindices++ ] = surf->numVerts; - surf->numVerts++; - if ( surf->numVerts >= surf->maxVerts ) { - surf->maxVerts += GROW_VERTS; - surf->verts = realloc( surf->verts, surf->maxVerts * sizeof( *surf->verts ) ); - } - } - } - - SideAsTristrip( surf, indices, numindices ); - - free( indices ); -} - -/* -================ -SurfaceForShader -================ -*/ -terrainSurf_t *SurfaceForShader( shaderInfo_t *shader, int x, int y ) { - int i; - - if ( lastSurface && ( lastSurface->shader == shader ) && ( lastSurface->x == x ) && ( lastSurface->y == y ) ) { - return lastSurface; - } - - lastSurface = surfaces; - for( i = 0; i < numsurfaces; i++, lastSurface++ ) { - if ( ( lastSurface->shader == shader ) && ( lastSurface->x == x ) && ( lastSurface->y == y ) ) { - return lastSurface; - } - } - - if ( numsurfaces >= maxsurfaces ) { - maxsurfaces += GROW_SURFACES; - surfaces = realloc( surfaces, maxsurfaces * sizeof( *surfaces ) ); - memset( surfaces + numsurfaces + 1, 0, ( maxsurfaces - numsurfaces - 1 ) * sizeof( *surfaces ) ); - } - - lastSurface= &surfaces[ numsurfaces++ ]; - lastSurface->shader = shader; - lastSurface->x = x; - lastSurface->y = y; - - return lastSurface; -} - -/* -================ -SetTerrainTextures -================ -*/ -void SetTerrainTextures( void ) { - int i; - int x, y; - int layer; - int minlayer, maxlayer; - float s, t; - float min_s, min_t; - int alpha[ MAX_POINTS_ON_WINDING ]; - shaderInfo_t *si, *terrainShader; - bspbrush_t *brush; - side_t *side; - const char *shadername; - vec3_t mins, maxs; - vec3_t size; - int surfwidth, surfheight, surfsize; - terrainSurf_t *surf; - byte *alphamap; - int alphawidth, alphaheight; - int num_layers; - extern qboolean onlyents; - - if ( onlyents ) { - return; - } - - shadername = ValueForKey( mapent, "shader" ); - if ( !shadername[ 0 ] ) { - Error ("SetTerrainTextures: shader not specified" ); - } - - alphamap = LoadAlphaMap( &num_layers, &alphawidth, &alphaheight ); - - mapent->firstDrawSurf = numMapDrawSurfs; - - // calculate the size of the terrain - CalcTerrainSize( mins, maxs, size ); - - surfwidth = ( size[ 0 ] + SURF_WIDTH - 1 ) / SURF_WIDTH; - surfheight = ( size[ 1 ] + SURF_HEIGHT - 1 ) / SURF_HEIGHT; - surfsize = surfwidth * surfheight; - - lastSurface = NULL; - numsurfaces = 0; - maxsurfaces = 0; - for( i = num_layers; i > 0; i-- ) { - maxsurfaces += i * surfsize; - } - surfaces = malloc( maxsurfaces * sizeof( *surfaces ) ); - memset( surfaces, 0, maxsurfaces * sizeof( *surfaces ) ); - - terrainShader = ShaderInfoForShader( "textures/common/terrain" ); - - for( brush = mapent->brushes; brush != NULL; brush = brush->next ) { - // only create surfaces for sides marked as terrain - for( side = brush->sides; side < &brush->sides[ brush->numsides ]; side++ ) { - if ( !side->shaderInfo ) { - continue; - } - - if ( ( ( side->surfaceFlags | side->shaderInfo->surfaceFlags ) & SURF_NODRAW ) && !strstr( side->shaderInfo->shader, "terrain" ) ) { - continue; - } - - minlayer = num_layers; - maxlayer = 0; - - // project each point of the winding onto the alphamap to determine which - // textures to blend - min_s = 1.0; - min_t = 1.0; - for( i = 0; i < side->winding->numpoints; i++ ) { - s = floor( side->winding->p[ i ][ 0 ] + 0.1f - mins[ 0 ] ) / size[ 0 ]; - t = floor( side->winding->p[ i ][ 1 ] + 0.1f - mins[ 0 ] ) / size[ 1 ]; - - if ( s < 0 ) { - s = 0; - } - - if ( t < 0 ) { - t = 0; - } - - if ( s >= 1.0 ) { - s = 1.0; - } - - if ( t >= 1.0 ) { - t = 1.0; - } - - if ( s < min_s ) { - min_s = s; - } - - if ( t < min_t ) { - min_t = t; - } - - x = ( alphawidth - 1 ) * s; - y = ( alphaheight - 1 ) * t; - - layer = alphamap[ x + y * alphawidth ]; - if ( layer < minlayer ) { - minlayer = layer; - } - - if ( layer > maxlayer ) { - maxlayer = layer; - } - - alpha[ i ] = layer; - } - - x = min_s * surfwidth; - if ( x >= surfwidth ) { - x = surfwidth - 1; - } - - y = min_t * surfheight; - if ( y >= surfheight ) { - y = surfheight - 1; - } - - if ( strstr( side->shaderInfo->shader, "terrain" ) ) { - si = ShaderForLayer( minlayer, maxlayer, shadername ); - if ( showseams ) { - for( i = 0; i < side->winding->numpoints; i++ ) { - if ( ( alpha[ i ] != minlayer ) && ( alpha[ i ] != maxlayer ) ) { - si = ShaderInfoForShader( "textures/common/white" ); - break; - } - } - } - surf = SurfaceForShader( si, x, y ); - EmitTerrainVerts( side, surf, maxlayer, alpha, qtrue ); - } else { - si = side->shaderInfo; - side->shaderInfo = terrainShader; - surf = SurfaceForShader( si, x, y ); - EmitTerrainVerts( side, surf, maxlayer, alpha, qfalse ); - } - } - } - - // create the final surfaces - for( surf = surfaces, i = 0; i < numsurfaces; i++, surf++ ) { - if ( surf->numVerts ) { - CreateTerrainSurface( surf, surf->shader ); - } - } - - // - // clean up any allocated memory - // - for( surf = surfaces, i = 0; i < numsurfaces; i++, surf++ ) { - if ( surf->verts ) { - free( surf->verts ); - free( surf->indexes ); - } - } - free( alphamap ); - free( surfaces ); - - surfaces = NULL; - lastSurface = NULL; - numsurfaces = 0; - maxsurfaces = 0; -} - -/***************************************************************************** - - New terrain code - -******************************************************************************/ - -typedef struct terrainFace_s { - shaderInfo_t *shaderInfo; - //texdef_t texdef; - - float vecs[ 2 ][ 4 ]; // texture coordinate mapping -} terrainFace_t; - -typedef struct terrainVert_s { - vec3_t xyz; - terrainFace_t tri; -} terrainVert_t; - -typedef struct terrainMesh_s { - float scale_x; - float scale_y; - vec3_t origin; - - int width, height; - terrainVert_t *map; -} terrainMesh_t; - -terrainVert_t *Terrain_GetVert( terrainMesh_t *pm, int x, int y ) { - return &pm->map[ x + y * pm->width ]; -} - -void Terrain_GetTriangles( terrainMesh_t *pm, int x, int y, terrainVert_t **verts ) { - if ( ( x + y ) & 1 ) { - // first tri - verts[ 0 ] = Terrain_GetVert( pm, x, y ); - verts[ 1 ] = Terrain_GetVert( pm, x, y + 1 ); - verts[ 2 ] = Terrain_GetVert( pm, x + 1, y + 1 ); - - // second tri - verts[ 3 ] = verts[ 2 ]; - verts[ 4 ] = Terrain_GetVert( pm, x + 1, y ); - verts[ 5 ] = verts[ 0 ]; - } else { - // first tri - verts[ 0 ] = Terrain_GetVert( pm, x, y ); - verts[ 1 ] = Terrain_GetVert( pm, x, y + 1 ); - verts[ 2 ] = Terrain_GetVert( pm, x + 1, y ); - - // second tri - verts[ 3 ] = verts[ 2 ]; - verts[ 4 ] = verts[ 1 ]; - verts[ 5 ] = Terrain_GetVert( pm, x + 1, y + 1 ); - } -} - -/* -================ -EmitTerrainVerts2 -================ -*/ -void EmitTerrainVerts2( terrainSurf_t *surf, terrainVert_t **verts, int alpha[ 3 ] ) { - int i; - int j; - drawVert_t *vert; - int *indices; - int numindices; - int maxindices; - int xyplane; - vec3_t xynorm = { 0, 0, 1 }; - vec_t shift[ 2 ] = { 0, 0 }; - vec_t scale[ 2 ] = { 0.5, 0.5 }; - float vecs[ 2 ][ 4 ]; - vec4_t plane; - - if ( !surf->verts ) { - surf->numVerts = 0; - surf->maxVerts = GROW_VERTS; - surf->verts = malloc( surf->maxVerts * sizeof( *surf->verts ) ); - - surf->numIndexes = 0; - surf->maxIndexes = GROW_INDICES; - surf->indexes = malloc( surf->maxIndexes * sizeof( *surf->indexes ) ); - } - - // calculate the texture coordinate vectors - xyplane = FindFloatPlane( xynorm, 0 ); - QuakeTextureVecs( &mapplanes[ xyplane ], shift, 0, scale, vecs ); - - // emit the vertexes - numindices = 0; - maxindices = surf->maxIndexes; - assert( maxindices >= 0 ); - indices = malloc ( maxindices * sizeof( *indices ) ); - - PlaneFromPoints( plane, verts[ 0 ]->xyz, verts[ 1 ]->xyz, verts[ 2 ]->xyz ); - - for ( i = 0; i < 3; i++ ) { - vert = &surf->verts[ surf->numVerts ]; - - if ( alpha[ i ] ) { - vert->color[3] = 255; - } else { - vert->color[3] = 0; - } - - vert->xyz[ 0 ] = floor( verts[ i ]->xyz[ 0 ] + 0.1f ); - vert->xyz[ 1 ] = floor( verts[ i ]->xyz[ 1 ] + 0.1f ); - vert->xyz[ 2 ] = floor( verts[ i ]->xyz[ 2 ] + 0.1f ); - - // set the texture coordinates - vert->st[0] = ( vecs[0][3] + DotProduct( vecs[ 0 ], vert->xyz ) ) / surf->shader->width; - vert->st[1] = ( vecs[1][3] + DotProduct( vecs[ 1 ], vert->xyz ) ) / surf->shader->height; - - VectorCopy( plane, vert->normal ); - - for( j = 0; j < surf->numVerts; j++ ) { - if ( CompareVert( vert, &surf->verts[ j ], qtrue ) ) { - break; - } - } - - if ( numindices >= maxindices ) { - maxindices += GROW_INDICES; - indices = realloc( indices, maxindices * sizeof( *indices ) ); - } - - if ( j != surf->numVerts ) { - indices[ numindices++ ] = j; - } else { - indices[ numindices++ ] = surf->numVerts; - surf->numVerts++; - if ( surf->numVerts >= surf->maxVerts ) { - surf->maxVerts += GROW_VERTS; - surf->verts = realloc( surf->verts, surf->maxVerts * sizeof( *surf->verts ) ); - } - } - } - - SideAsTristrip( surf, indices, numindices ); - - free( indices ); -} - -int MapPlaneFromPoints( vec3_t p0, vec3_t p1, vec3_t p2 ); -void QuakeTextureVecs( plane_t *plane, vec_t shift[2], vec_t rotate, vec_t scale[2], vec_t mappingVecs[2][4] ); -qboolean RemoveDuplicateBrushPlanes( bspbrush_t *b ); -void SetBrushContents( bspbrush_t *b ); - -void AddBrushSide( vec3_t v1, vec3_t v2, vec3_t v3, shaderInfo_t *terrainShader ) { - side_t *side; - int planenum; - - side = &buildBrush->sides[ buildBrush->numsides ]; - memset( side, 0, sizeof( *side ) ); - buildBrush->numsides++; - - side->shaderInfo = terrainShader; - - // find the plane number - planenum = MapPlaneFromPoints( v1, v2, v3 ); - side->planenum = planenum; -} - -void MakeBrushFromTriangle( vec3_t v1, vec3_t v2, vec3_t v3, shaderInfo_t *terrainShader ) { - bspbrush_t *b; - vec3_t d1; - vec3_t d2; - vec3_t d3; - - VectorSet( d1, v1[ 0 ], v1[ 1 ], MIN_WORLD_COORD + 10 ); //FIXME - VectorSet( d2, v2[ 0 ], v2[ 1 ], MIN_WORLD_COORD + 10 ); - VectorSet( d3, v3[ 0 ], v3[ 1 ], MIN_WORLD_COORD + 10 ); - - buildBrush->numsides = 0; - buildBrush->detail = qfalse; - - AddBrushSide( v1, v2, v3, terrainShader ); - AddBrushSide( v1, d1, v2, terrainShader ); - AddBrushSide( v2, d2, v3, terrainShader ); - AddBrushSide( v3, d3, v1, terrainShader ); - AddBrushSide( d3, d2, d1, terrainShader ); - - buildBrush->portalareas[0] = -1; - buildBrush->portalareas[1] = -1; - buildBrush->entitynum = num_entities-1; - buildBrush->brushnum = entitySourceBrushes; - - // if there are mirrored planes, the entire brush is invalid - if ( !RemoveDuplicateBrushPlanes( buildBrush ) ) { - return; - } - - // get the content for the entire brush - SetBrushContents( buildBrush ); - buildBrush->contents |= CONTENTS_DETAIL; - - b = FinishBrush(); - if ( !b ) { - return; - } -} - -void MakeTerrainIntoBrushes( terrainMesh_t *tm ) { - int index[ 6 ]; - int y; - int x; - terrainVert_t *verts; - shaderInfo_t *terrainShader; - - terrainShader = ShaderInfoForShader( "textures/common/terrain" ); - - verts = tm->map; - for( y = 0; y < tm->height - 1; y++ ) { - for( x = 0; x < tm->width - 1; x++ ) { - if ( ( x + y ) & 1 ) { - // first tri - index[ 0 ] = x + y * tm->width; - index[ 1 ] = x + ( y + 1 ) * tm->width; - index[ 2 ] = ( x + 1 ) + ( y + 1 ) * tm->width; - index[ 3 ] = ( x + 1 ) + ( y + 1 ) * tm->width; - index[ 4 ] = ( x + 1 ) + y * tm->width; - index[ 5 ] = x + y * tm->width; - } else { - // first tri - index[ 0 ] = x + y * tm->width; - index[ 1 ] = x + ( y + 1 ) * tm->width; - index[ 2 ] = ( x + 1 ) + y * tm->width; - index[ 3 ] = ( x + 1 ) + y * tm->width; - index[ 4 ] = x + ( y + 1 ) * tm->width; - index[ 5 ] = ( x + 1 ) + ( y + 1 ) * tm->width; - } - - MakeBrushFromTriangle( verts[ index[ 0 ] ].xyz, verts[ index[ 1 ] ].xyz, verts[ index[ 2 ] ].xyz, terrainShader ); - MakeBrushFromTriangle( verts[ index[ 3 ] ].xyz, verts[ index[ 4 ] ].xyz, verts[ index[ 5 ] ].xyz, terrainShader ); - } - } -} - -void Terrain_ParseFace( terrainFace_t *face ) { - shaderInfo_t *si; - vec_t shift[ 2 ]; - vec_t rotate; - vec_t scale[ 2 ]; - char name[ MAX_QPATH ]; - char shader[ MAX_QPATH ]; - plane_t p; - - // read the texturedef - GetToken( qfalse ); - strcpy( name, token ); - - GetToken( qfalse ); - shift[ 0 ] = atof(token); - GetToken( qfalse ); - shift[ 1 ] = atof( token ); - GetToken( qfalse ); - rotate = atof( token ); - GetToken( qfalse ); - scale[ 0 ] = atof( token ); - GetToken( qfalse ); - scale[ 1 ] = atof( token ); - - // find default flags and values - sprintf( shader, "textures/%s", name ); - si = ShaderInfoForShader( shader ); - face->shaderInfo = si; - //face->texdef = si->texdef; - - // skip over old contents - GetToken( qfalse ); - - // skip over old flags - GetToken( qfalse ); - - // skip over old value - GetToken( qfalse ); - - //Surface_Parse( &face->texdef ); - //Surface_BuildTexdef( &face->texdef ); - - // make a fake horizontal plane - VectorSet( p.normal, 0, 0, 1 ); - p.dist = 0; - p.type = PlaneTypeForNormal( p.normal ); - - QuakeTextureVecs( &p, shift, rotate, scale, face->vecs ); -} - -#define MAX_TERRAIN_TEXTURES 128 -static int numtextures = 0;; -static shaderInfo_t *textures[ MAX_TERRAIN_TEXTURES ]; - -void Terrain_AddTexture( shaderInfo_t *texture ) { - int i; - - if ( !texture ) { - return; - } - - for( i = 0; i < numtextures; i++ ) { - if ( textures[ i ] == texture ) { - return; - } - } - - if ( numtextures >= MAX_TERRAIN_TEXTURES ) { - Error( "Too many textures on terrain" ); - return; - } - - textures[ numtextures++ ] = texture; -} - -int LayerForShader( shaderInfo_t *shader ) { - int i; - int l; - - l = strlen( shader->shader ); - for( i = l - 1; i >= 0; i-- ) { - if ( shader->shader[ i ] == '_' ) { - return atoi( &shader->shader[ i + 1 ] ); - break; - } - } - - return 0; -} - -/* -================= -ParseTerrain - -Creates a mapDrawSurface_t from the terrain text -================= -*/ - -void ParseTerrain( void ) { - int i, j; - int x, y; - int x1, y1; - terrainMesh_t t; - int index; - terrainVert_t *verts[ 6 ]; - int num_layers; - int layer, minlayer, maxlayer; - int alpha[ 6 ]; - shaderInfo_t *si, *terrainShader; - int surfwidth, surfheight, surfsize; - terrainSurf_t *surf; - char shadername[ MAX_QPATH ]; - - mapent->firstDrawSurf = numMapDrawSurfs; - - memset( &t, 0, sizeof( t ) ); - - MatchToken( "{" ); - - // get width - GetToken( qtrue ); - t.width = atoi( token ); - - // get height - GetToken( qfalse ); - t.height = atoi( token ); - - // get scale_x - GetToken( qfalse ); - t.scale_x = atof( token ); - - // get scale_y - GetToken( qfalse ); - t.scale_y = atof( token ); - - // get origin - GetToken( qtrue ); - t.origin[ 0 ] = atof( token ); - GetToken( qfalse ); - t.origin[ 1 ] = atof( token ); - GetToken( qfalse ); - t.origin[ 2 ] = atof( token ); - - t.map = malloc( t.width * t.height * sizeof( t.map[ 0 ] ) ); - - if ( t.width <= 0 || t.height <= 0 ) { - Error( "ParseTerrain: bad size" ); - } - - numtextures = 0; - index = 0; - for ( i = 0; i < t.height; i++ ) { - for( j = 0; j < t.width; j++, index++ ) { - // get height - GetToken( qtrue ); - t.map[ index ].xyz[ 0 ] = t.origin[ 0 ] + t.scale_x * ( float )j; - t.map[ index ].xyz[ 1 ] = t.origin[ 1 ] + t.scale_y * ( float )i; - t.map[ index ].xyz[ 2 ] = t.origin[ 2 ] + atof( token ); - - Terrain_ParseFace( &t.map[ index ].tri ); - Terrain_AddTexture( t.map[ index ].tri.shaderInfo ); - } - } - - MatchToken( "}" ); - MatchToken( "}" ); - - MakeTerrainIntoBrushes( &t ); - - surfwidth = ( ( t.scale_x * t.width ) + SURF_WIDTH - 1 ) / SURF_WIDTH; - surfheight = ( ( t.scale_y * t.height ) + SURF_HEIGHT - 1 ) / SURF_HEIGHT; - surfsize = surfwidth * surfheight; - - //FIXME - num_layers = 0; - for( i = 0; i < numtextures; i++ ) { - layer = LayerForShader( textures[ i ] ) + 1; - if ( layer > num_layers ) { - num_layers = layer; - } - } - num_layers = 4; - - memset( alpha, 0, sizeof( alpha ) ); - - lastSurface = NULL; - numsurfaces = 0; - maxsurfaces = 0; - for( i = num_layers; i > 0; i-- ) { - maxsurfaces += i * surfsize; - } - - surfaces = malloc( maxsurfaces * sizeof( *surfaces ) ); - memset( surfaces, 0, maxsurfaces * sizeof( *surfaces ) ); - - terrainShader = ShaderInfoForShader( "textures/common/terrain" ); - - // get the shadername - if ( Q_strncasecmp( textures[ 0 ]->shader, "textures/", 9 ) == 0 ) { - strcpy( shadername, &textures[ 0 ]->shader[ 9 ] ); - } else { - strcpy( shadername, textures[ 0 ]->shader ); - } - j = strlen( shadername ); - for( i = j - 1; i >= 0; i-- ) { - if ( shadername[ i ] == '_' ) { - shadername[ i ] = 0; - break; - } - } - - for( y = 0; y < t.height - 1; y++ ) { - for( x = 0; x < t.width - 1; x++ ) { - Terrain_GetTriangles( &t, x, y, verts ); - - x1 = ( ( float )x / ( float )( t.width - 1 ) ) * surfwidth; - if ( x1 >= surfwidth ) { - x1 = surfwidth - 1; - } - - y1 = ( ( float )y / ( float )( t.height - 1 ) ) * surfheight; - if ( y1 >= surfheight ) { - y1 = surfheight - 1; - } - - maxlayer = minlayer = LayerForShader( verts[ 0 ]->tri.shaderInfo ); - for( i = 0; i < 3; i++ ) { - layer = LayerForShader( verts[ i ]->tri.shaderInfo ); - if ( layer < minlayer ) { - minlayer = layer; - } - if ( layer > maxlayer ) { - maxlayer = layer; - } - } - - for( i = 0; i < 3; i++ ) { - layer = LayerForShader( verts[ i ]->tri.shaderInfo ); - if ( layer > minlayer ) { - alpha[ i ] = 1.0f; - } else { - alpha[ i ] = 0.0f; - } - } - - si = ShaderForLayer( minlayer, maxlayer, shadername ); - surf = SurfaceForShader( si, x1, y1 ); - EmitTerrainVerts2( surf, &verts[ 0 ], &alpha[ 0 ] ); - - // second triangle - maxlayer = minlayer = LayerForShader( verts[ 3 ]->tri.shaderInfo ); - for( i = 3; i < 6; i++ ) { - layer = LayerForShader( verts[ i ]->tri.shaderInfo ); - if ( layer < minlayer ) { - minlayer = layer; - } - if ( layer > maxlayer ) { - maxlayer = layer; - } - } - - for( i = 3; i < 6; i++ ) { - layer = LayerForShader( verts[ i ]->tri.shaderInfo ); - if ( layer > minlayer ) { - alpha[ i ] = 1.0f; - } else { - alpha[ i ] = 0.0f; - } - } - - si = ShaderForLayer( minlayer, maxlayer, shadername ); - surf = SurfaceForShader( si, x1, y1 ); - EmitTerrainVerts2( surf, &verts[ 3 ], &alpha[ 3 ] ); - } - } - - // create the final surfaces - for( surf = surfaces, i = 0; i < numsurfaces; i++, surf++ ) { - if ( surf->numVerts ) { - CreateTerrainSurface( surf, surf->shader ); - } - } - - // - // clean up any allocated memory - // - for( surf = surfaces, i = 0; i < numsurfaces; i++, surf++ ) { - if ( surf->verts ) { - free( surf->verts ); - free( surf->indexes ); - } - } - free( surfaces ); - - surfaces = NULL; - lastSurface = NULL; - numsurfaces = 0; - maxsurfaces = 0; - - free( t.map ); -} - diff --git a/q3map/tjunction.c b/q3map/tjunction.c deleted file mode 100644 index a1acabe..0000000 --- a/q3map/tjunction.c +++ /dev/null @@ -1,551 +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" - -typedef struct edgePoint_s { - float intercept; - vec3_t xyz; - struct edgePoint_s *prev, *next; -} edgePoint_t; - -typedef struct edgeLine_s { - vec3_t normal1; - float dist1; - - vec3_t normal2; - float dist2; - - vec3_t origin; - vec3_t dir; - - edgePoint_t chain; // unused element of doubly linked list -} edgeLine_t; - -typedef struct { - float length; - drawVert_t *dv[2]; -} originalEdge_t; - -#define MAX_ORIGINAL_EDGES 0x10000 -originalEdge_t originalEdges[MAX_ORIGINAL_EDGES]; -int numOriginalEdges; - - -#define MAX_EDGE_LINES 0x10000 -edgeLine_t edgeLines[MAX_EDGE_LINES]; -int numEdgeLines; - -int c_degenerateEdges; -int c_addedVerts; -int c_totalVerts; - -int c_natural, c_rotate, c_cant; - -// these should be whatever epsilon we actually expect, -// plus SNAP_INT_TO_FLOAT -#define LINE_POSITION_EPSILON 0.25 -#define POINT_ON_LINE_EPSILON 0.25 - -/* -==================== -InsertPointOnEdge -==================== -*/ -void InsertPointOnEdge( vec3_t v, edgeLine_t *e ) { - vec3_t delta; - float d; - edgePoint_t *p, *scan; - - VectorSubtract( v, e->origin, delta ); - d = DotProduct( delta, e->dir ); - - p = malloc( sizeof(edgePoint_t) ); - p->intercept = d; - VectorCopy( v, p->xyz ); - - if ( e->chain.next == &e->chain ) { - e->chain.next = e->chain.prev = p; - p->next = p->prev = &e->chain; - return; - } - - scan = e->chain.next; - for ( ; scan != &e->chain ; scan = scan->next ) { - d = p->intercept - scan->intercept; - if ( d > -LINE_POSITION_EPSILON && d < LINE_POSITION_EPSILON ) { - free( p ); - return; // the point is already set - } - - if ( p->intercept < scan->intercept ) { - // insert here - p->prev = scan->prev; - p->next = scan; - scan->prev->next = p; - scan->prev = p; - return; - } - } - - // add at the end - p->prev = scan->prev; - p->next = scan; - scan->prev->next = p; - scan->prev = p; -} - - -/* -==================== -AddEdge -==================== -*/ -int AddEdge( vec3_t v1, vec3_t v2, qboolean createNonAxial ) { - int i; - edgeLine_t *e; - float d; - vec3_t dir; - - VectorSubtract( v2, v1, dir ); - d = VectorNormalize( dir, dir ); - if ( d < 0.1 ) { - // if we added a 0 length vector, it would make degenerate planes - c_degenerateEdges++; - return -1; - } - - if ( !createNonAxial ) { - if ( fabs( dir[0] + dir[1] + dir[2] ) != 1.0 ) { - if ( numOriginalEdges == MAX_ORIGINAL_EDGES ) { - Error( "MAX_ORIGINAL_EDGES" ); - } - originalEdges[ numOriginalEdges ].dv[0] = (drawVert_t *)v1; - originalEdges[ numOriginalEdges ].dv[1] = (drawVert_t *)v2; - originalEdges[ numOriginalEdges ].length = d; - numOriginalEdges++; - return -1; - } - } - - for ( i = 0 ; i < numEdgeLines ; i++ ) { - e = &edgeLines[i]; - - d = DotProduct( v1, e->normal1 ) - e->dist1; - if ( d < -POINT_ON_LINE_EPSILON || d > POINT_ON_LINE_EPSILON ) { - continue; - } - d = DotProduct( v1, e->normal2 ) - e->dist2; - if ( d < -POINT_ON_LINE_EPSILON || d > POINT_ON_LINE_EPSILON ) { - continue; - } - - d = DotProduct( v2, e->normal1 ) - e->dist1; - if ( d < -POINT_ON_LINE_EPSILON || d > POINT_ON_LINE_EPSILON ) { - continue; - } - d = DotProduct( v2, e->normal2 ) - e->dist2; - if ( d < -POINT_ON_LINE_EPSILON || d > POINT_ON_LINE_EPSILON ) { - continue; - } - - // this is the edge - InsertPointOnEdge( v1, e ); - InsertPointOnEdge( v2, e ); - return i; - } - - // create a new edge - if ( numEdgeLines >= MAX_EDGE_LINES ) { - Error( "MAX_EDGE_LINES" ); - } - - e = &edgeLines[ numEdgeLines ]; - numEdgeLines++; - - e->chain.next = e->chain.prev = &e->chain; - - VectorCopy( v1, e->origin ); - VectorCopy( dir, e->dir ); - - MakeNormalVectors( e->dir, e->normal1, e->normal2 ); - e->dist1 = DotProduct( e->origin, e->normal1 ); - e->dist2 = DotProduct( e->origin, e->normal2 ); - - InsertPointOnEdge( v1, e ); - InsertPointOnEdge( v2, e ); - - return numEdgeLines - 1; -} - -/* -==================== -AddSurfaceEdges -==================== -*/ -void AddSurfaceEdges( mapDrawSurface_t *ds ) { - int i; - - for ( i = 0 ; i < ds->numVerts ; i++ ) { - // save the edge number in the lightmap field - // so we don't need to look it up again - ds->verts[i].lightmap[0] = - AddEdge( ds->verts[i].xyz, ds->verts[(i+1) % ds->numVerts].xyz, qfalse ); - } -} - -/* -================ -ColinearEdge -================ -*/ -qboolean ColinearEdge( vec3_t v1, vec3_t v2, vec3_t v3 ) { - vec3_t midpoint, dir, offset, on; - float d; - - VectorSubtract( v2, v1, midpoint ); - VectorSubtract( v3, v1, dir ); - d = VectorNormalize( dir, dir ); - if ( d == 0 ) { - return qfalse; // degenerate - } - - d = DotProduct( midpoint, dir ); - VectorScale( dir, d, on ); - VectorSubtract( midpoint, on, offset ); - d = VectorLength ( offset ); - - if ( d < 0.1 ) { - return qtrue; - } - - return qfalse; -} - -/* -==================== -AddPatchEdges - -Add colinear border edges, which will fix some classes of patch to -brush tjunctions -==================== -*/ -void AddPatchEdges( mapDrawSurface_t *ds ) { - int i; - float *v1, *v2, *v3; - - for ( i = 0 ; i < ds->patchWidth - 2; i+=2 ) { - v1 = ds->verts[ i ].xyz; - v2 = ds->verts[ i + 1 ].xyz; - v3 = ds->verts[ i + 2 ].xyz; - - // if v2 is the midpoint of v1 to v3, add an edge from v1 to v3 - if ( ColinearEdge( v1, v2, v3 ) ) { - AddEdge( v1, v3, qfalse ); - } - - v1 = ds->verts[ ( ds->patchHeight - 1 ) * ds->patchWidth + i ].xyz; - v2 = ds->verts[ ( ds->patchHeight - 1 ) * ds->patchWidth + i + 1 ].xyz; - v3 = ds->verts[ ( ds->patchHeight - 1 ) * ds->patchWidth + i + 2 ].xyz; - - // if v2 is on the v1 to v3 line, add an edge from v1 to v3 - if ( ColinearEdge( v1, v2, v3 ) ) { - AddEdge( v1, v3, qfalse ); - } - } - - for ( i = 0 ; i < ds->patchHeight - 2 ; i+=2 ) { - v1 = ds->verts[ i * ds->patchWidth ].xyz; - v2 = ds->verts[ ( i + 1 ) * ds->patchWidth ].xyz; - v3 = ds->verts[ ( i + 2 ) * ds->patchWidth ].xyz; - - // if v2 is the midpoint of v1 to v3, add an edge from v1 to v3 - if ( ColinearEdge( v1, v2, v3 ) ) { - AddEdge( v1, v3, qfalse ); - } - - v1 = ds->verts[ ( ds->patchWidth - 1 ) + i * ds->patchWidth ].xyz; - v2 = ds->verts[ ( ds->patchWidth - 1 ) + ( i + 1 ) * ds->patchWidth ].xyz; - v3 = ds->verts[ ( ds->patchWidth - 1 ) + ( i + 2 ) * ds->patchWidth ].xyz; - - // if v2 is the midpoint of v1 to v3, add an edge from v1 to v3 - if ( ColinearEdge( v1, v2, v3 ) ) { - AddEdge( v1, v3, qfalse ); - } - } - - -} - - -/* -==================== -FixSurfaceJunctions -==================== -*/ -#define MAX_SURFACE_VERTS 256 -void FixSurfaceJunctions( mapDrawSurface_t *ds ) { - int i, j, k; - edgeLine_t *e; - edgePoint_t *p; - int originalVerts; - int counts[MAX_SURFACE_VERTS]; - int originals[MAX_SURFACE_VERTS]; - int firstVert[MAX_SURFACE_VERTS]; - drawVert_t verts[MAX_SURFACE_VERTS], *v1, *v2; - int numVerts; - float start, end, frac; - vec3_t delta; - - originalVerts = ds->numVerts; - - numVerts = 0; - for ( i = 0 ; i < ds->numVerts ; i++ ) { - counts[i] = 0; - firstVert[i] = numVerts; - - // copy first vert - if ( numVerts == MAX_SURFACE_VERTS ) { - Error( "MAX_SURFACE_VERTS" ); - } - verts[numVerts] = ds->verts[i]; - originals[numVerts] = i; - numVerts++; - - // check to see if there are any t junctions before the next vert - v1 = &ds->verts[i]; - v2 = &ds->verts[ (i+1) % ds->numVerts ]; - - j = (int)ds->verts[i].lightmap[0]; - if ( j == -1 ) { - continue; // degenerate edge - } - e = &edgeLines[ j ]; - - VectorSubtract( v1->xyz, e->origin, delta ); - start = DotProduct( delta, e->dir ); - - VectorSubtract( v2->xyz, e->origin, delta ); - end = DotProduct( delta, e->dir ); - - - if ( start < end ) { - p = e->chain.next; - } else { - p = e->chain.prev; - } - - for ( ; p != &e->chain ; ) { - if ( start < end ) { - if ( p->intercept > end - ON_EPSILON ) { - break; - } - } else { - if ( p->intercept < end + ON_EPSILON ) { - break; - } - } - - if ( - ( start < end && p->intercept > start + ON_EPSILON ) || - ( start > end && p->intercept < start - ON_EPSILON ) ) { - // insert this point - if ( numVerts == MAX_SURFACE_VERTS ) { - Error( "MAX_SURFACE_VERTS" ); - } - - // take the exact intercept point - VectorCopy( p->xyz, verts[ numVerts ].xyz ); - - // copy the normal - VectorCopy( v1->normal, verts[ numVerts ].normal ); - - // interpolate the texture coordinates - frac = ( p->intercept - start ) / ( end - start ); - for ( j = 0 ; j < 2 ; j++ ) { - verts[ numVerts ].st[j] = v1->st[j] + - frac * ( v2->st[j] - v1->st[j] ); - } - originals[numVerts] = i; - numVerts++; - counts[i]++; - } - - if ( start < end ) { - p = p->next; - } else { - p = p->prev; - } - } - } - - c_addedVerts += numVerts - ds->numVerts; - c_totalVerts += numVerts; - - - // FIXME: check to see if the entire surface degenerated - // after snapping - - // rotate the points so that the initial vertex is between - // two non-subdivided edges - for ( i = 0 ; i < numVerts ; i++ ) { - if ( originals[ (i+1) % numVerts ] == originals[ i ] ) { - continue; - } - j = (i + numVerts - 1 ) % numVerts; - k = (i + numVerts - 2 ) % numVerts; - if ( originals[ j ] == originals[ k ] ) { - continue; - } - break; - } - - if ( i == 0 ) { - // fine the way it is - c_natural++; - - ds->numVerts = numVerts; - ds->verts = malloc( numVerts * sizeof( *ds->verts ) ); - memcpy( ds->verts, verts, numVerts * sizeof( *ds->verts ) ); - - return; - } - if ( i == numVerts ) { - // create a vertex in the middle to start the fan - c_cant++; - -/* - memset ( &verts[numVerts], 0, sizeof( verts[numVerts] ) ); - for ( i = 0 ; i < numVerts ; i++ ) { - for ( j = 0 ; j < 10 ; j++ ) { - verts[numVerts].xyz[j] += verts[i].xyz[j]; - } - } - for ( j = 0 ; j < 10 ; j++ ) { - verts[numVerts].xyz[j] /= numVerts; - } - - i = numVerts; - numVerts++; -*/ - } else { - // just rotate the vertexes - c_rotate++; - - } - - ds->numVerts = numVerts; - ds->verts = malloc( numVerts * sizeof( *ds->verts ) ); - - for ( j = 0 ; j < ds->numVerts ; j++ ) { - ds->verts[j] = verts[ ( j + i ) % ds->numVerts ]; - } -} - -/* -================ -EdgeCompare -================ -*/ -int EdgeCompare( const void *elem1, const void *elem2 ) { - float d1, d2; - - d1 = ((originalEdge_t *)elem1)->length; - d2 = ((originalEdge_t *)elem2)->length; - - if ( d1 < d2 ) { - return -1; - } - if ( d2 > d1 ) { - return 1; - } - return 0; -} - - -/* -================ -FixTJunctions - -Call after the surface list has been pruned, but before lightmap allocation -================ -*/ -void FixTJunctions( entity_t *ent ) { - int i; - mapDrawSurface_t *ds; - int axialEdgeLines; - originalEdge_t *e; - - qprintf("----- FixTJunctions -----\n"); - - numEdgeLines = 0; - numOriginalEdges = 0; - - // add all the edges - // this actually creates axial edges, but it - // only creates originalEdge_t structures - // for non-axial edges - for ( i = ent->firstDrawSurf ; i < numMapDrawSurfs ; i++ ) { - ds = &mapDrawSurfs[i]; - if ( ds->patch ) { - AddPatchEdges( ds ); - } else if ( ds->shaderInfo->autosprite || ds->shaderInfo->notjunc || ds->miscModel ) { - // miscModels don't add tjunctions - } else { - AddSurfaceEdges( ds ); - } - } - - axialEdgeLines = numEdgeLines; - - // sort the non-axial edges by length - qsort( originalEdges, numOriginalEdges, sizeof(originalEdges[0]), EdgeCompare ); - - // add the non-axial edges, longest first - // this gives the most accurate edge description - for ( i = 0 ; i < numOriginalEdges ; i++ ) { - e = &originalEdges[i]; - e->dv[0]->lightmap[0] = AddEdge( e->dv[0]->xyz, e->dv[1]->xyz, qtrue ); - } - - qprintf( "%6i axial edge lines\n", axialEdgeLines ); - qprintf( "%6i non-axial edge lines\n", numEdgeLines - axialEdgeLines ); - qprintf( "%6i degenerate edges\n", c_degenerateEdges ); - - // insert any needed vertexes - for ( i = ent->firstDrawSurf ; i < numMapDrawSurfs ; i++ ) { - ds = &mapDrawSurfs[i]; - if ( ds->patch ) { - continue; - } - if ( ds->shaderInfo->autosprite || ds->shaderInfo->notjunc || ds->miscModel ) { - continue; - } - - FixSurfaceJunctions( ds ); - } - - qprintf( "%6i verts added for tjunctions\n", c_addedVerts ); - qprintf( "%6i total verts\n", c_totalVerts ); - qprintf( "%6i naturally ordered\n", c_natural ); - qprintf( "%6i rotated orders\n", c_rotate ); - qprintf( "%6i can't order\n", c_cant ); -} diff --git a/q3map/tree.c b/q3map/tree.c deleted file mode 100644 index f400db1..0000000 --- a/q3map/tree.c +++ /dev/null @@ -1,146 +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" - - -extern int c_nodes; - -void RemovePortalFromNode (portal_t *portal, node_t *l); - -node_t *NodeForPoint (node_t *node, vec3_t origin) -{ - plane_t *plane; - vec_t d; - - while (node->planenum != PLANENUM_LEAF) - { - plane = &mapplanes[node->planenum]; - d = DotProduct (origin, plane->normal) - plane->dist; - if (d >= 0) - node = node->children[0]; - else - node = node->children[1]; - } - - return node; -} - - - -/* -============= -FreeTreePortals_r -============= -*/ -void FreeTreePortals_r (node_t *node) -{ - portal_t *p, *nextp; - int s; - - // free children - if (node->planenum != PLANENUM_LEAF) - { - FreeTreePortals_r (node->children[0]); - FreeTreePortals_r (node->children[1]); - } - - // free portals - for (p=node->portals ; p ; p=nextp) - { - s = (p->nodes[1] == node); - nextp = p->next[s]; - - RemovePortalFromNode (p, p->nodes[!s]); - FreePortal (p); - } - node->portals = NULL; -} - -/* -============= -FreeTree_r -============= -*/ -void FreeTree_r (node_t *node) -{ - // free children - if (node->planenum != PLANENUM_LEAF) - { - FreeTree_r (node->children[0]); - FreeTree_r (node->children[1]); - } - - // free bspbrushes - FreeBrushList (node->brushlist); - - // free the node - if (node->volume) - FreeBrush (node->volume); - - if (numthreads == 1) - c_nodes--; - free (node); -} - - -/* -============= -FreeTree -============= -*/ -void FreeTree (tree_t *tree) -{ - FreeTreePortals_r (tree->headnode); - FreeTree_r (tree->headnode); - free (tree); -} - -//=============================================================== - -void PrintTree_r (node_t *node, int depth) -{ - int i; - plane_t *plane; - bspbrush_t *bb; - - for (i=0 ; i<depth ; i++) - _printf (" "); - if (node->planenum == PLANENUM_LEAF) - { - if (!node->brushlist) - _printf ("NULL\n"); - else - { - for (bb=node->brushlist ; bb ; bb=bb->next) - _printf ("%i ", bb->original->brushnum); - _printf ("\n"); - } - return; - } - - plane = &mapplanes[node->planenum]; - _printf ("#%i (%5.2f %5.2f %5.2f):%5.2f\n", node->planenum, - plane->normal[0], plane->normal[1], plane->normal[2], - plane->dist); - PrintTree_r (node->children[0], depth+1); - PrintTree_r (node->children[1], depth+1); -} diff --git a/q3map/vis.c b/q3map/vis.c deleted file mode 100644 index 329d192..0000000 --- a/q3map/vis.c +++ /dev/null @@ -1,1197 +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 -=========================================================================== -*/ -// vis.c - -#include "vis.h" -#include "threads.h" -#include "stdlib.h" -#ifdef _WIN32 -#include "../libs/pakstuff.h" -#endif - - -#define VIS_HEADER_SIZE 8 - -extern char outbase[32]; - -int numportals; -int portalclusters; -int numfaces; - -char inbase[32]; - -vportal_t *portals; -leaf_t *leafs; - -vportal_t *faces; -leaf_t *faceleafs; - -int c_portaltest, c_portalpass, c_portalcheck; - -int leafbytes; // (portalclusters+63)>>3 -int leaflongs; - -int portalbytes, portallongs; - -qboolean fastvis; -qboolean noPassageVis; -qboolean passageVisOnly; -qboolean mergevis; -qboolean nosort; -qboolean saveprt; - -int testlevel = 2; - -int totalvis; - -vportal_t *sorted_portals[MAX_MAP_PORTALS*2]; - -void PassageMemory(void); - - -//============================================================================= - -void PlaneFromWinding (winding_t *w, plane_t *plane) -{ - vec3_t v1, v2; - -// calc plane - VectorSubtract (w->points[2], w->points[1], v1); - VectorSubtract (w->points[0], w->points[1], v2); - CrossProduct (v2, v1, plane->normal); - VectorNormalize (plane->normal, plane->normal); - plane->dist = DotProduct (w->points[0], plane->normal); -} - - -/* -================== -NewWinding -================== -*/ -winding_t *NewWinding (int points) -{ - winding_t *w; - int size; - - if (points > MAX_POINTS_ON_WINDING) - Error ("NewWinding: %i points", points); - - size = (int)((winding_t *)0)->points[points]; - w = malloc (size); - memset (w, 0, size); - - return w; -} - - - -void prl(leaf_t *l) -{ - int i; - vportal_t *p; - plane_t pl; - - for (i=0 ; i<l->numportals ; i++) - { - p = l->portals[i]; - pl = p->plane; - _printf ("portal %4i to leaf %4i : %7.1f : (%4.1f, %4.1f, %4.1f)\n",(int)(p-portals),p->leaf,pl.dist, pl.normal[0], pl.normal[1], pl.normal[2]); - } -} - - -//============================================================================= - -/* -============= -SortPortals - -Sorts the portals from the least complex, so the later ones can reuse -the earlier information. -============= -*/ -int PComp (const void *a, const void *b) -{ - if ( (*(vportal_t **)a)->nummightsee == (*(vportal_t **)b)->nummightsee) - return 0; - if ( (*(vportal_t **)a)->nummightsee < (*(vportal_t **)b)->nummightsee) - return -1; - return 1; -} -void SortPortals (void) -{ - int i; - - for (i=0 ; i<numportals*2 ; i++) - sorted_portals[i] = &portals[i]; - - if (nosort) - return; - qsort (sorted_portals, numportals*2, sizeof(sorted_portals[0]), PComp); -} - - -/* -============== -LeafVectorFromPortalVector -============== -*/ -int LeafVectorFromPortalVector (byte *portalbits, byte *leafbits) -{ - int i, j, leafnum; - vportal_t *p; - int c_leafs; - - - for (i=0 ; i<numportals*2 ; i++) - { - if (portalbits[i>>3] & (1<<(i&7)) ) - { - p = portals+i; - leafbits[p->leaf>>3] |= (1<<(p->leaf&7)); - } - } - - for (j = 0; j < portalclusters; j++) - { - leafnum = j; - while (leafs[leafnum].merged >= 0) - leafnum = leafs[leafnum].merged; - //if the merged leaf is visible then the original leaf is visible - if (leafbits[leafnum>>3] & (1<<(leafnum&7))) - { - leafbits[j>>3] |= (1<<(j&7)); - } - } - - c_leafs = CountBits (leafbits, portalclusters); - - return c_leafs; -} - - -/* -=============== -ClusterMerge - -Merges the portal visibility for a leaf -=============== -*/ -void ClusterMerge (int leafnum) -{ - leaf_t *leaf; - byte portalvector[MAX_PORTALS/8]; - byte uncompressed[MAX_MAP_LEAFS/8]; - int i, j; - int numvis, mergedleafnum; - vportal_t *p; - int pnum; - - // OR together all the portalvis bits - - mergedleafnum = leafnum; - while(leafs[mergedleafnum].merged >= 0) - mergedleafnum = leafs[mergedleafnum].merged; - - memset (portalvector, 0, portalbytes); - leaf = &leafs[mergedleafnum]; - for (i = 0; i < leaf->numportals; i++) - { - p = leaf->portals[i]; - if (p->removed) - continue; - - if (p->status != stat_done) - Error ("portal not done"); - for (j=0 ; j<portallongs ; j++) - ((long *)portalvector)[j] |= ((long *)p->portalvis)[j]; - pnum = p - portals; - portalvector[pnum>>3] |= 1<<(pnum&7); - } - - memset (uncompressed, 0, leafbytes); - - uncompressed[mergedleafnum>>3] |= (1<<(mergedleafnum&7)); - // convert portal bits to leaf bits - numvis = LeafVectorFromPortalVector (portalvector, uncompressed); - -// if (uncompressed[leafnum>>3] & (1<<(leafnum&7))) -// _printf ("WARNING: Leaf portals saw into leaf\n"); - -// uncompressed[leafnum>>3] |= (1<<(leafnum&7)); - - numvis++; // count the leaf itself - - totalvis += numvis; - - qprintf ("cluster %4i : %4i visible\n", leafnum, numvis); - - memcpy (visBytes + VIS_HEADER_SIZE + leafnum*leafbytes, uncompressed, leafbytes); -} - -/* -================== -CalcPortalVis -================== -*/ -void CalcPortalVis (void) -{ -#ifdef MREDEBUG - _printf("%6d portals out of %d", 0, numportals*2); - //get rid of the counter - RunThreadsOnIndividual (numportals*2, qfalse, PortalFlow); -#else - RunThreadsOnIndividual (numportals*2, qtrue, PortalFlow); -#endif - -} - -/* -================== -CalcPassageVis -================== -*/ -void CalcPassageVis(void) -{ - PassageMemory(); - -#ifdef MREDEBUG - _printf("%6d portals out of %d", 0, numportals*2); - RunThreadsOnIndividual (numportals*2, qfalse, CreatePassages); - _printf("\n"); - _printf("%6d portals out of %d", 0, numportals*2); - RunThreadsOnIndividual (numportals*2, qfalse, PassageFlow); - _printf("\n"); -#else - RunThreadsOnIndividual (numportals*2, qtrue, CreatePassages); - RunThreadsOnIndividual (numportals*2, qtrue, PassageFlow); -#endif -} - -/* -================== -CalcPassagePortalVis -================== -*/ -void CalcPassagePortalVis(void) -{ - PassageMemory(); - -#ifdef MREDEBUG - _printf("%6d portals out of %d", 0, numportals*2); - RunThreadsOnIndividual (numportals*2, qfalse, CreatePassages); - _printf("\n"); - _printf("%6d portals out of %d", 0, numportals*2); - RunThreadsOnIndividual (numportals*2, qfalse, PassagePortalFlow); - _printf("\n"); -#else - RunThreadsOnIndividual (numportals*2, qtrue, CreatePassages); - RunThreadsOnIndividual (numportals*2, qtrue, PassagePortalFlow); -#endif -} - -/* -================== -CalcFastVis -================== -*/ -void CalcFastVis(void) -{ - int i; - - // fastvis just uses mightsee for a very loose bound - for (i=0 ; i<numportals*2 ; i++) - { - portals[i].portalvis = portals[i].portalflood; - portals[i].status = stat_done; - } -} - -/* -================== -CalcVis -================== -*/ -void CalcVis (void) -{ - int i; - - RunThreadsOnIndividual (numportals*2, qtrue, BasePortalVis); - -// RunThreadsOnIndividual (numportals*2, qtrue, BetterPortalVis); - - SortPortals (); - - if (fastvis) { - CalcFastVis(); - } - else if ( noPassageVis ) { - CalcPortalVis(); - } - else if ( passageVisOnly ) { - CalcPassageVis(); - } - else { - CalcPassagePortalVis(); - } - // - // assemble the leaf vis lists by oring and compressing the portal lists - // - _printf("creating leaf vis...\n"); - for (i=0 ; i<portalclusters ; i++) - ClusterMerge (i); - - _printf( "Total visible clusters: %i\n", totalvis ); - _printf( "Average clusters visible: %i\n", totalvis / portalclusters ); -} - -/* -================== -SetPortalSphere -================== -*/ -void SetPortalSphere (vportal_t *p) -{ - int i; - vec3_t total, dist; - winding_t *w; - float r, bestr; - - w = p->winding; - VectorCopy (vec3_origin, total); - for (i=0 ; i<w->numpoints ; i++) - { - VectorAdd (total, w->points[i], total); - } - - for (i=0 ; i<3 ; i++) - total[i] /= w->numpoints; - - bestr = 0; - for (i=0 ; i<w->numpoints ; i++) - { - VectorSubtract (w->points[i], total, dist); - r = VectorLength (dist); - if (r > bestr) - bestr = r; - } - VectorCopy (total, p->origin); - p->radius = bestr; -} - -/* -============= -Winding_PlanesConcave -============= -*/ -#define WCONVEX_EPSILON 0.2 - -int Winding_PlanesConcave(winding_t *w1, winding_t *w2, - vec3_t normal1, vec3_t normal2, - float dist1, float dist2) -{ - int i; - - if (!w1 || !w2) return qfalse; - - // check if one of the points of winding 1 is at the front of the plane of winding 2 - for (i = 0; i < w1->numpoints; i++) - { - if (DotProduct(normal2, w1->points[i]) - dist2 > WCONVEX_EPSILON) return qtrue; - } - // check if one of the points of winding 2 is at the front of the plane of winding 1 - for (i = 0; i < w2->numpoints; i++) - { - if (DotProduct(normal1, w2->points[i]) - dist1 > WCONVEX_EPSILON) return qtrue; - } - - return qfalse; -} - -/* -============ -TryMergeLeaves -============ -*/ -int TryMergeLeaves(int l1num, int l2num) -{ - int i, j, k, n, numportals; - plane_t plane1, plane2; - leaf_t *l1, *l2; - vportal_t *p1, *p2; - vportal_t *portals[MAX_PORTALS_ON_LEAF]; - - for (k = 0; k < 2; k++) - { - if (k) l1 = &leafs[l1num]; - else l1 = &faceleafs[l1num]; - for (i = 0; i < l1->numportals; i++) - { - p1 = l1->portals[i]; - if (p1->leaf == l2num) continue; - for (n = 0; n < 2; n++) - { - if (n) l2 = &leafs[l2num]; - else l2 = &faceleafs[l2num]; - for (j = 0; j < l2->numportals; j++) - { - p2 = l2->portals[j]; - if (p2->leaf == l1num) continue; - // - plane1 = p1->plane; - plane2 = p2->plane; - if (Winding_PlanesConcave(p1->winding, p2->winding, plane1.normal, plane2.normal, plane1.dist, plane2.dist)) - return qfalse; - } - } - } - } - for (k = 0; k < 2; k++) - { - if (k) - { - l1 = &leafs[l1num]; - l2 = &leafs[l2num]; - } - else - { - l1 = &faceleafs[l1num]; - l2 = &faceleafs[l2num]; - } - numportals = 0; - //the leaves can be merged now - for (i = 0; i < l1->numportals; i++) - { - p1 = l1->portals[i]; - if (p1->leaf == l2num) - { - p1->removed = qtrue; - continue; - } - portals[numportals++] = p1; - } - for (j = 0; j < l2->numportals; j++) - { - p2 = l2->portals[j]; - if (p2->leaf == l1num) - { - p2->removed = qtrue; - continue; - } - portals[numportals++] = p2; - } - for (i = 0; i < numportals; i++) - { - l2->portals[i] = portals[i]; - } - l2->numportals = numportals; - l1->merged = l2num; - } - return qtrue; -} - -/* -============ -UpdatePortals -============ -*/ -void UpdatePortals(void) -{ - int i; - vportal_t *p; - - for (i = 0; i < numportals * 2; i++) - { - p = &portals[i]; - if (p->removed) - continue; - while(leafs[p->leaf].merged >= 0) - p->leaf = leafs[p->leaf].merged; - } -} - -/* -============ -MergeLeaves - -try to merge leaves but don't merge through hint splitters -============ -*/ -void MergeLeaves(void) -{ - int i, j, nummerges, totalnummerges; - leaf_t *leaf; - vportal_t *p; - - totalnummerges = 0; - do - { - nummerges = 0; - for (i = 0; i < portalclusters; i++) - { - leaf = &leafs[i]; - //if this leaf is merged already - if (leaf->merged >= 0) - continue; - // - for (j = 0; j < leaf->numportals; j++) - { - p = leaf->portals[j]; - // - if (p->removed) - continue; - //never merge through hint portals - if (p->hint) - continue; - if (TryMergeLeaves(i, p->leaf)) - { - UpdatePortals(); - nummerges++; - break; - } - } - } - totalnummerges += nummerges; - } while (nummerges); - _printf("%6d leaves merged\n", totalnummerges); -} - -/* -============ -TryMergeWinding -============ -*/ -#define CONTINUOUS_EPSILON 0.005 - -winding_t *TryMergeWinding (winding_t *f1, winding_t *f2, vec3_t planenormal) -{ - vec_t *p1, *p2, *p3, *p4, *back; - winding_t *newf; - int i, j, k, l; - vec3_t normal, delta; - vec_t dot; - qboolean keep1, keep2; - - - // - // find a common edge - // - p1 = p2 = NULL; // stop compiler warning - j = 0; // - - for (i = 0; i < f1->numpoints; i++) - { - p1 = f1->points[i]; - p2 = f1->points[(i+1) % f1->numpoints]; - for (j = 0; j < f2->numpoints; j++) - { - p3 = f2->points[j]; - p4 = f2->points[(j+1) % f2->numpoints]; - for (k = 0; k < 3; k++) - { - if (fabs(p1[k] - p4[k]) > 0.1)//EQUAL_EPSILON) //ME - break; - if (fabs(p2[k] - p3[k]) > 0.1)//EQUAL_EPSILON) //ME - break; - } //end for - if (k==3) - break; - } //end for - if (j < f2->numpoints) - break; - } //end for - - if (i == f1->numpoints) - return NULL; // no matching edges - - // - // check slope of connected lines - // if the slopes are colinear, the point can be removed - // - back = f1->points[(i+f1->numpoints-1)%f1->numpoints]; - VectorSubtract (p1, back, delta); - CrossProduct (planenormal, delta, normal); - VectorNormalize (normal, normal); - - back = f2->points[(j+2)%f2->numpoints]; - VectorSubtract (back, p1, delta); - dot = DotProduct (delta, normal); - if (dot > CONTINUOUS_EPSILON) - return NULL; // not a convex polygon - keep1 = (qboolean)(dot < -CONTINUOUS_EPSILON); - - back = f1->points[(i+2)%f1->numpoints]; - VectorSubtract (back, p2, delta); - CrossProduct (planenormal, delta, normal); - VectorNormalize (normal, normal); - - back = f2->points[(j+f2->numpoints-1)%f2->numpoints]; - VectorSubtract (back, p2, delta); - dot = DotProduct (delta, normal); - if (dot > CONTINUOUS_EPSILON) - return NULL; // not a convex polygon - keep2 = (qboolean)(dot < -CONTINUOUS_EPSILON); - - // - // build the new polygon - // - newf = NewWinding (f1->numpoints + f2->numpoints); - - // copy first polygon - for (k=(i+1)%f1->numpoints ; k != i ; k=(k+1)%f1->numpoints) - { - if (k==(i+1)%f1->numpoints && !keep2) - continue; - - VectorCopy (f1->points[k], newf->points[newf->numpoints]); - newf->numpoints++; - } - - // copy second polygon - for (l= (j+1)%f2->numpoints ; l != j ; l=(l+1)%f2->numpoints) - { - if (l==(j+1)%f2->numpoints && !keep1) - continue; - VectorCopy (f2->points[l], newf->points[newf->numpoints]); - newf->numpoints++; - } - - return newf; -} - -/* -============ -MergeLeafPortals -============ -*/ -void MergeLeafPortals(void) -{ - int i, j, k, nummerges, hintsmerged; - leaf_t *leaf; - vportal_t *p1, *p2; - winding_t *w; - - nummerges = 0; - hintsmerged = 0; - for (i = 0; i < portalclusters; i++) - { - leaf = &leafs[i]; - if (leaf->merged >= 0) continue; - for (j = 0; j < leaf->numportals; j++) - { - p1 = leaf->portals[j]; - if (p1->removed) - continue; - for (k = j+1; k < leaf->numportals; k++) - { - p2 = leaf->portals[k]; - if (p2->removed) - continue; - if (p1->leaf == p2->leaf) - { - w = TryMergeWinding(p1->winding, p2->winding, p1->plane.normal); - if (w) - { - FreeWinding(p1->winding); - p1->winding = w; - if (p1->hint && p2->hint) - hintsmerged++; - p1->hint |= p2->hint; - SetPortalSphere(p1); - p2->removed = qtrue; - nummerges++; - i--; - break; - } - } - } - if (k < leaf->numportals) - break; - } - } - _printf("%6d portals merged\n", nummerges); - _printf("%6d hint portals merged\n", hintsmerged); -} - - -/* -============ -WritePortals -============ -*/ -int CountActivePortals(void) -{ - int num, hints, j; - vportal_t *p; - - num = 0; - hints = 0; - for (j = 0; j < numportals * 2; j++) - { - p = portals + j; - if (p->removed) - continue; - if (p->hint) - hints++; - num++; - } - _printf("%6d active portals\n", num); - _printf("%6d hint portals\n", hints); - return num; -} - -/* -============ -WritePortals -============ -*/ -void WriteFloat (FILE *f, vec_t v); - -void WritePortals(char *filename) -{ - int i, j, num; - FILE *pf; - vportal_t *p; - winding_t *w; - - // write the file - pf = fopen (filename, "w"); - if (!pf) - Error ("Error opening %s", filename); - - num = 0; - for (j = 0; j < numportals * 2; j++) - { - p = portals + j; - if (p->removed) - continue; -// if (!p->hint) -// continue; - num++; - } - - fprintf (pf, "%s\n", PORTALFILE); - fprintf (pf, "%i\n", 0); - fprintf (pf, "%i\n", num);// + numfaces); - fprintf (pf, "%i\n", 0); - - for (j = 0; j < numportals * 2; j++) - { - p = portals + j; - if (p->removed) - continue; -// if (!p->hint) -// continue; - w = p->winding; - fprintf (pf,"%i %i %i ",w->numpoints, 0, 0); - fprintf (pf, "%d ", p->hint); - for (i=0 ; i<w->numpoints ; i++) - { - fprintf (pf,"("); - WriteFloat (pf, w->points[i][0]); - WriteFloat (pf, w->points[i][1]); - WriteFloat (pf, w->points[i][2]); - fprintf (pf,") "); - } - fprintf (pf,"\n"); - } - - /* - for (j = 0; j < numfaces; j++) - { - p = faces + j; - w = p->winding; - fprintf (pf,"%i %i %i ",w->numpoints, 0, 0); - fprintf (pf, "0 "); - for (i=0 ; i<w->numpoints ; i++) - { - fprintf (pf,"("); - WriteFloat (pf, w->points[i][0]); - WriteFloat (pf, w->points[i][1]); - WriteFloat (pf, w->points[i][2]); - fprintf (pf,") "); - } - fprintf (pf,"\n"); - }*/ - - fclose (pf); -} - -/* -============ -LoadPortals -============ -*/ -void LoadPortals (char *name) -{ - int i, j, hint; - vportal_t *p; - leaf_t *l; - char magic[80]; - FILE *f; - int numpoints; - winding_t *w; - int leafnums[2]; - plane_t plane; - - if (!strcmp(name,"-")) - f = stdin; - else - { - f = fopen(name, "r"); - if (!f) - Error ("LoadPortals: couldn't read %s\n",name); - } - - if (fscanf (f,"%79s\n%i\n%i\n%i\n",magic, &portalclusters, &numportals, &numfaces) != 4) - Error ("LoadPortals: failed to read header"); - if (strcmp(magic,PORTALFILE)) - Error ("LoadPortals: not a portal file"); - - _printf ("%6i portalclusters\n", portalclusters); - _printf ("%6i numportals\n", numportals); - _printf ("%6i numfaces\n", numfaces); - - // these counts should take advantage of 64 bit systems automatically - leafbytes = ((portalclusters+63)&~63)>>3; - leaflongs = leafbytes/sizeof(long); - - portalbytes = ((numportals*2+63)&~63)>>3; - portallongs = portalbytes/sizeof(long); - - // each file portal is split into two memory portals - portals = malloc(2*numportals*sizeof(vportal_t)); - memset (portals, 0, 2*numportals*sizeof(vportal_t)); - - leafs = malloc(portalclusters*sizeof(leaf_t)); - memset (leafs, 0, portalclusters*sizeof(leaf_t)); - - for (i = 0; i < portalclusters; i++) - leafs[i].merged = -1; - - numVisBytes = VIS_HEADER_SIZE + portalclusters*leafbytes; - - ((int *)visBytes)[0] = portalclusters; - ((int *)visBytes)[1] = leafbytes; - - for (i=0, p=portals ; i<numportals ; i++) - { - if (fscanf (f, "%i %i %i ", &numpoints, &leafnums[0], &leafnums[1]) != 3) - Error ("LoadPortals: reading portal %i", i); - if (numpoints > MAX_POINTS_ON_WINDING) - Error ("LoadPortals: portal %i has too many points", i); - if ( (unsigned)leafnums[0] > portalclusters - || (unsigned)leafnums[1] > portalclusters) - Error ("LoadPortals: reading portal %i", i); - if (fscanf (f, "%i ", &hint) != 1) - Error ("LoadPortals: reading hint state"); - - w = p->winding = NewWinding (numpoints); - w->numpoints = numpoints; - - for (j=0 ; j<numpoints ; j++) - { - double v[3]; - int k; - - // scanf into double, then assign to vec_t - // so we don't care what size vec_t is - if (fscanf (f, "(%lf %lf %lf ) " - , &v[0], &v[1], &v[2]) != 3) - Error ("LoadPortals: reading portal %i", i); - for (k=0 ; k<3 ; k++) - w->points[j][k] = v[k]; - } - fscanf (f, "\n"); - - // calc plane - PlaneFromWinding (w, &plane); - - // create forward portal - l = &leafs[leafnums[0]]; - if (l->numportals == MAX_PORTALS_ON_LEAF) - Error ("Leaf with too many portals"); - l->portals[l->numportals] = p; - l->numportals++; - - p->num = i+1; - p->hint = hint; - p->winding = w; - VectorSubtract (vec3_origin, plane.normal, p->plane.normal); - p->plane.dist = -plane.dist; - p->leaf = leafnums[1]; - SetPortalSphere (p); - p++; - - // create backwards portal - l = &leafs[leafnums[1]]; - if (l->numportals == MAX_PORTALS_ON_LEAF) - Error ("Leaf with too many portals"); - l->portals[l->numportals] = p; - l->numportals++; - - p->num = i+1; - p->hint = hint; - p->winding = NewWinding(w->numpoints); - p->winding->numpoints = w->numpoints; - for (j=0 ; j<w->numpoints ; j++) - { - VectorCopy (w->points[w->numpoints-1-j], p->winding->points[j]); - } - - p->plane = plane; - p->leaf = leafnums[0]; - SetPortalSphere (p); - p++; - - } - - faces = malloc(2*numfaces*sizeof(vportal_t)); - memset (faces, 0, 2*numfaces*sizeof(vportal_t)); - - faceleafs = malloc(portalclusters*sizeof(leaf_t)); - memset(faceleafs, 0, portalclusters*sizeof(leaf_t)); - - for (i = 0, p = faces; i < numfaces; i++) - { - if (fscanf (f, "%i %i ", &numpoints, &leafnums[0]) != 2) - Error ("LoadPortals: reading portal %i", i); - - w = p->winding = NewWinding (numpoints); - w->numpoints = numpoints; - - for (j=0 ; j<numpoints ; j++) - { - double v[3]; - int k; - - // scanf into double, then assign to vec_t - // so we don't care what size vec_t is - if (fscanf (f, "(%lf %lf %lf ) " - , &v[0], &v[1], &v[2]) != 3) - Error ("LoadPortals: reading portal %i", i); - for (k=0 ; k<3 ; k++) - w->points[j][k] = v[k]; - } - fscanf (f, "\n"); - - // calc plane - PlaneFromWinding (w, &plane); - - l = &faceleafs[leafnums[0]]; - l->merged = -1; - if (l->numportals == MAX_PORTALS_ON_LEAF) - Error ("Leaf with too many faces"); - l->portals[l->numportals] = p; - l->numportals++; - - p->num = i+1; - p->winding = w; - // normal pointing out of the leaf - VectorSubtract (vec3_origin, plane.normal, p->plane.normal); - p->plane.dist = -plane.dist; - p->leaf = -1; - SetPortalSphere (p); - p++; - } - - fclose (f); -} - - -/* -================ -CalcPHS - -Calculate the PHS (Potentially Hearable Set) -by ORing together all the PVS visible from a leaf -================ -*/ -void CalcPHS (void) -{ - int i, j, k, l, index; - int bitbyte; - long *dest, *src; - byte *scan; - int count; - byte uncompressed[MAX_MAP_LEAFS/8]; - - _printf ("Building PHS...\n"); - - count = 0; - for (i=0 ; i<portalclusters ; i++) - { - scan = visBytes + i*leafbytes; - memcpy (uncompressed, scan, leafbytes); - for (j=0 ; j<leafbytes ; j++) - { - bitbyte = scan[j]; - if (!bitbyte) - continue; - for (k=0 ; k<8 ; k++) - { - if (! (bitbyte & (1<<k)) ) - continue; - // OR this pvs row into the phs - index = ((j<<3)+k); - if (index >= portalclusters) - Error ("Bad bit in PVS"); // pad bits should be 0 - src = (long *)(visBytes + index*leafbytes); - dest = (long *)uncompressed; - for (l=0 ; l<leaflongs ; l++) - ((long *)uncompressed)[l] |= src[l]; - } - } - for (j=0 ; j<portalclusters ; j++) - if (uncompressed[j>>3] & (1<<(j&7)) ) - count++; - - // FIXME: copy it off - } - - _printf ("Average clusters hearable: %i\n", count/portalclusters); -} - -/* -=========== -VisMain -=========== -*/ -int VisMain (int argc, char **argv) -{ - char portalfile[1024]; - char name[1024]; - int i; - double start, end; - - _printf ("---- vis ----\n"); - - verbose = qfalse; - for (i=1 ; i<argc ; i++) { - if (!strcmp(argv[i],"-threads")) { - numthreads = atoi (argv[i+1]); - i++; - } else if (!strcmp(argv[i],"-threads")) { - numthreads = atoi (argv[i+1]); - i++; - } else if (!strcmp(argv[i], "-fast")) { - _printf ("fastvis = true\n"); - fastvis = qtrue; - } else if (!strcmp(argv[i], "-merge")) { - _printf ("merge = true\n"); - mergevis = qtrue; - } else if (!strcmp(argv[i], "-nopassage")) { - _printf ("nopassage = true\n"); - noPassageVis = qtrue; - } else if (!strcmp(argv[i], "-passageOnly")) { - _printf("passageOnly = true\n"); - passageVisOnly = qtrue; - } else if (!strcmp(argv[i], "-level")) { - testlevel = atoi(argv[i+1]); - _printf ("testlevel = %i\n", testlevel); - i++; - } else if (!strcmp(argv[i], "-v")) { - _printf ("verbose = true\n"); - verbose = qtrue; - } else if (!strcmp (argv[i],"-nosort")) { - _printf ("nosort = true\n"); - nosort = qtrue; - } else if (!strcmp (argv[i],"-saveprt")) { - _printf ("saveprt = true\n"); - saveprt = qtrue; - } else if (!strcmp (argv[i],"-tmpin")) { - strcpy (inbase, "/tmp"); - } else if (!strcmp (argv[i],"-tmpout")) { - strcpy (outbase, "/tmp"); - } else if (argv[i][0] == '-') { - Error ("Unknown option \"%s\"", argv[i]); - } else { - break; - } - } - - if (i != argc - 1) - Error ("usage: vis [-threads #] [-level 0-4] [-fast] [-v] bspfile"); - -#ifdef MREDEBUG - start = clock(); -#else - start = I_FloatTime (); -#endif - - ThreadSetDefault (); - - SetQdirFromPath (argv[i]); - -#ifdef _WIN32 - InitPakFile(gamedir, NULL); -#endif - - // load the bsp - sprintf (name, "%s%s", inbase, ExpandArg(argv[i])); - StripExtension (name); - strcat (name, ".bsp"); - _printf ("reading %s\n", name); - LoadBSPFile (name); - - // load the portal file - sprintf (portalfile, "%s%s", inbase, ExpandArg(argv[i])); - StripExtension (portalfile); - strcat (portalfile, ".prt"); - _printf ("reading %s\n", portalfile); - LoadPortals (portalfile); - - if (mergevis) - { - MergeLeaves(); - MergeLeafPortals(); - } - - CountActivePortals(); -// WritePortals("maps/hints.prs"); - - _printf ("visdatasize:%i\n", numVisBytes); - - CalcVis (); - -// CalcPHS (); - - // delete the prt file - if ( !saveprt ) { - remove( portalfile ); - } - - // write the bsp file - _printf ("writing %s\n", name); - WriteBSPFile (name); - -#ifdef MREDEBUG - end = clock(); - _printf ("%5.2f seconds elapsed\n", (end-start) / CLK_TCK); -#else - end = I_FloatTime (); - _printf ("%5.2f seconds elapsed\n", end-start); -#endif - return 0; -} - diff --git a/q3map/vis.h b/q3map/vis.h deleted file mode 100644 index 8eed728..0000000 --- a/q3map/vis.h +++ /dev/null @@ -1,162 +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 -=========================================================================== -*/ -// vis.h - -#include "cmdlib.h" -#include "mathlib.h" -#include "bspfile.h" - -#define MAX_PORTALS 32768 - -#define PORTALFILE "PRT1" - -#define ON_EPSILON 0.1 - -//#define MREDEBUG - -// seperator caching helps a bit -#define SEPERATORCACHE - -// can't have more seperators than the max number of points on a winding -#define MAX_SEPERATORS 64 - -typedef struct -{ - vec3_t normal; - float dist; -} plane_t; - -#define MAX_POINTS_ON_WINDING 64 -#define MAX_POINTS_ON_FIXED_WINDING 12 - -typedef struct -{ - int numpoints; - vec3_t points[MAX_POINTS_ON_FIXED_WINDING]; // variable sized -} winding_t; - -winding_t *NewWinding (int points); -void FreeWinding (winding_t *w); -winding_t *CopyWinding (winding_t *w); - - -typedef struct passage_s -{ - struct passage_s *next; - byte cansee[1]; //all portals that can be seen through this passage -} passage_t; - -typedef enum {stat_none, stat_working, stat_done} vstatus_t; -typedef struct -{ - int num; - qboolean hint; // true if this portal was created from a hint splitter - qboolean removed; - plane_t plane; // normal pointing into neighbor - int leaf; // neighbor - - vec3_t origin; // for fast clip testing - float radius; - - winding_t *winding; - vstatus_t status; - byte *portalfront; // [portals], preliminary - byte *portalflood; // [portals], intermediate - byte *portalvis; // [portals], final - - int nummightsee; // bit count on portalflood for sort - passage_t *passages; // there are just as many passages as there - // are portals in the leaf this portal leads to -} vportal_t; - -#define MAX_PORTALS_ON_LEAF 128 -typedef struct leaf_s -{ - int numportals; - int merged; - vportal_t *portals[MAX_PORTALS_ON_LEAF]; -} leaf_t; - - -typedef struct pstack_s -{ - byte mightsee[MAX_PORTALS/8]; // bit string - struct pstack_s *next; - leaf_t *leaf; - vportal_t *portal; // portal exiting - winding_t *source; - winding_t *pass; - - winding_t windings[3]; // source, pass, temp in any order - int freewindings[3]; - - plane_t portalplane; - int depth; -#ifdef SEPERATORCACHE - plane_t seperators[2][MAX_SEPERATORS]; - int numseperators[2]; -#endif -} pstack_t; - -typedef struct -{ - vportal_t *base; - int c_chains; - pstack_t pstack_head; -} threaddata_t; - - - -extern int numportals; -extern int portalclusters; - -extern vportal_t *portals; -extern leaf_t *leafs; - -extern int c_portaltest, c_portalpass, c_portalcheck; -extern int c_portalskip, c_leafskip; -extern int c_vistest, c_mighttest; -extern int c_chains; - -extern byte *vismap, *vismap_p, *vismap_end; // past visfile - -extern int testlevel; - -extern byte *uncompressed; - -extern int leafbytes, leaflongs; -extern int portalbytes, portallongs; - - -void LeafFlow (int leafnum); - - -void BasePortalVis(int portalnum); -void BetterPortalVis(int portalnum); -void PortalFlow(int portalnum); -void PassagePortalFlow(int portalnum); -void CreatePassages(int portalnum); -void PassageFlow(int portalnum); - -extern vportal_t *sorted_portals[MAX_MAP_PORTALS*2]; - -int CountBits (byte *bits, int numbits); diff --git a/q3map/visflow.c b/q3map/visflow.c deleted file mode 100644 index 5948b08..0000000 --- a/q3map/visflow.c +++ /dev/null @@ -1,1657 +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 "vis.h" - -/* - - each portal will have a list of all possible to see from first portal - - if (!thread->portalmightsee[portalnum]) - - portal mightsee - - for p2 = all other portals in leaf - get sperating planes - for all portals that might be seen by p2 - mark as unseen if not present in seperating plane - flood fill a new mightsee - save as passagemightsee - - - void CalcMightSee (leaf_t *leaf, -*/ - -int CountBits (byte *bits, int numbits) -{ - int i; - int c; - - c = 0; - for (i=0 ; i<numbits ; i++) - if (bits[i>>3] & (1<<(i&7)) ) - c++; - - return c; -} - -int c_fullskip; -int c_portalskip, c_leafskip; -int c_vistest, c_mighttest; - -int c_chop, c_nochop; - -int active; - -void CheckStack (leaf_t *leaf, threaddata_t *thread) -{ - pstack_t *p, *p2; - - for (p=thread->pstack_head.next ; p ; p=p->next) - { -// _printf ("="); - if (p->leaf == leaf) - Error ("CheckStack: leaf recursion"); - for (p2=thread->pstack_head.next ; p2 != p ; p2=p2->next) - if (p2->leaf == p->leaf) - Error ("CheckStack: late leaf recursion"); - } -// _printf ("\n"); -} - - -winding_t *AllocStackWinding (pstack_t *stack) -{ - int i; - - for (i=0 ; i<3 ; i++) - { - if (stack->freewindings[i]) - { - stack->freewindings[i] = 0; - return &stack->windings[i]; - } - } - - Error ("AllocStackWinding: failed"); - - return NULL; -} - -void FreeStackWinding (winding_t *w, pstack_t *stack) -{ - int i; - - i = w - stack->windings; - - if (i<0 || i>2) - return; // not from local - - if (stack->freewindings[i]) - Error ("FreeStackWinding: allready free"); - stack->freewindings[i] = 1; -} - -/* -============== -VisChopWinding - -============== -*/ -winding_t *VisChopWinding (winding_t *in, pstack_t *stack, plane_t *split) -{ - vec_t dists[128]; - int sides[128]; - int counts[3]; - vec_t dot; - int i, j; - vec_t *p1, *p2; - vec3_t mid; - winding_t *neww; - - counts[0] = counts[1] = counts[2] = 0; - - // determine sides for each point - for (i=0 ; i<in->numpoints ; i++) - { - dot = DotProduct (in->points[i], split->normal); - dot -= split->dist; - dists[i] = dot; - if (dot > ON_EPSILON) - sides[i] = SIDE_FRONT; - else if (dot < -ON_EPSILON) - sides[i] = SIDE_BACK; - else - { - sides[i] = SIDE_ON; - } - counts[sides[i]]++; - } - - if (!counts[1]) - return in; // completely on front side - - if (!counts[0]) - { - FreeStackWinding (in, stack); - return NULL; - } - - sides[i] = sides[0]; - dists[i] = dists[0]; - - neww = AllocStackWinding (stack); - - neww->numpoints = 0; - - for (i=0 ; i<in->numpoints ; i++) - { - p1 = in->points[i]; - - if (neww->numpoints == MAX_POINTS_ON_FIXED_WINDING) - { - FreeStackWinding (neww, stack); - return in; // can't chop -- fall back to original - } - - if (sides[i] == SIDE_ON) - { - VectorCopy (p1, neww->points[neww->numpoints]); - neww->numpoints++; - continue; - } - - if (sides[i] == SIDE_FRONT) - { - VectorCopy (p1, neww->points[neww->numpoints]); - neww->numpoints++; - } - - if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) - continue; - - if (neww->numpoints == MAX_POINTS_ON_FIXED_WINDING) - { - FreeStackWinding (neww, stack); - return in; // can't chop -- fall back to original - } - - // generate a split point - p2 = in->points[(i+1)%in->numpoints]; - - dot = dists[i] / (dists[i]-dists[i+1]); - for (j=0 ; j<3 ; j++) - { // avoid round off error when possible - if (split->normal[j] == 1) - mid[j] = split->dist; - else if (split->normal[j] == -1) - mid[j] = -split->dist; - else - mid[j] = p1[j] + dot*(p2[j]-p1[j]); - } - - VectorCopy (mid, neww->points[neww->numpoints]); - neww->numpoints++; - } - - // free the original winding - FreeStackWinding (in, stack); - - return neww; -} - -/* -============== -ClipToSeperators - -Source, pass, and target are an ordering of portals. - -Generates seperating planes canidates by taking two points from source and one -point from pass, and clips target by them. - -If target is totally clipped away, that portal can not be seen through. - -Normal clip keeps target on the same side as pass, which is correct if the -order goes source, pass, target. If the order goes pass, source, target then -flipclip should be set. -============== -*/ -winding_t *ClipToSeperators (winding_t *source, winding_t *pass, winding_t *target, qboolean flipclip, pstack_t *stack) -{ - int i, j, k, l; - plane_t plane; - vec3_t v1, v2; - float d; - vec_t length; - int counts[3]; - qboolean fliptest; - - // check all combinations - for (i=0 ; i<source->numpoints ; i++) - { - l = (i+1)%source->numpoints; - VectorSubtract (source->points[l] , source->points[i], v1); - - // find a vertex of pass that makes a plane that puts all of the - // vertexes of pass on the front side and all of the vertexes of - // source on the back side - for (j=0 ; j<pass->numpoints ; j++) - { - VectorSubtract (pass->points[j], source->points[i], v2); - - plane.normal[0] = v1[1]*v2[2] - v1[2]*v2[1]; - plane.normal[1] = v1[2]*v2[0] - v1[0]*v2[2]; - plane.normal[2] = v1[0]*v2[1] - v1[1]*v2[0]; - - // if points don't make a valid plane, skip it - - length = plane.normal[0] * plane.normal[0] - + plane.normal[1] * plane.normal[1] - + plane.normal[2] * plane.normal[2]; - - if (length < ON_EPSILON) - continue; - - length = 1/sqrt(length); - - plane.normal[0] *= length; - plane.normal[1] *= length; - plane.normal[2] *= length; - - plane.dist = DotProduct (pass->points[j], plane.normal); - - // - // find out which side of the generated seperating plane has the - // source portal - // -#if 1 - fliptest = qfalse; - for (k=0 ; k<source->numpoints ; k++) - { - if (k == i || k == l) - continue; - d = DotProduct (source->points[k], plane.normal) - plane.dist; - if (d < -ON_EPSILON) - { // source is on the negative side, so we want all - // pass and target on the positive side - fliptest = qfalse; - break; - } - else if (d > ON_EPSILON) - { // source is on the positive side, so we want all - // pass and target on the negative side - fliptest = qtrue; - break; - } - } - if (k == source->numpoints) - continue; // planar with source portal -#else - fliptest = flipclip; -#endif - // - // flip the normal if the source portal is backwards - // - if (fliptest) - { - VectorSubtract (vec3_origin, plane.normal, plane.normal); - plane.dist = -plane.dist; - } -#if 1 - // - // if all of the pass portal points are now on the positive side, - // this is the seperating plane - // - counts[0] = counts[1] = counts[2] = 0; - for (k=0 ; k<pass->numpoints ; k++) - { - if (k==j) - continue; - d = DotProduct (pass->points[k], plane.normal) - plane.dist; - if (d < -ON_EPSILON) - break; - else if (d > ON_EPSILON) - counts[0]++; - else - counts[2]++; - } - if (k != pass->numpoints) - continue; // points on negative side, not a seperating plane - - if (!counts[0]) - continue; // planar with seperating plane -#else - k = (j+1)%pass->numpoints; - d = DotProduct (pass->points[k], plane.normal) - plane.dist; - if (d < -ON_EPSILON) - continue; - k = (j+pass->numpoints-1)%pass->numpoints; - d = DotProduct (pass->points[k], plane.normal) - plane.dist; - if (d < -ON_EPSILON) - continue; -#endif - // - // flip the normal if we want the back side - // - if (flipclip) - { - VectorSubtract (vec3_origin, plane.normal, plane.normal); - plane.dist = -plane.dist; - } - -#ifdef SEPERATORCACHE - stack->seperators[flipclip][stack->numseperators[flipclip]] = plane; - if (++stack->numseperators[flipclip] >= MAX_SEPERATORS) - Error("MAX_SEPERATORS"); -#endif - //MrE: fast check first - d = DotProduct (stack->portal->origin, plane.normal) - plane.dist; - //if completely at the back of the seperator plane - if (d < -stack->portal->radius) - return NULL; - //if completely on the front of the seperator plane - if (d > stack->portal->radius) - break; - - // - // clip target by the seperating plane - // - target = VisChopWinding (target, stack, &plane); - if (!target) - return NULL; // target is not visible - - break; // optimization by Antony Suter - } - } - - return target; -} - -/* -================== -RecursiveLeafFlow - -Flood fill through the leafs -If src_portal is NULL, this is the originating leaf -================== -*/ -void RecursiveLeafFlow (int leafnum, threaddata_t *thread, pstack_t *prevstack) -{ - pstack_t stack; - vportal_t *p; - plane_t backplane; - leaf_t *leaf; - int i, j, n; - long *test, *might, *prevmight, *vis, more; - int pnum; - - thread->c_chains++; - - leaf = &leafs[leafnum]; -// CheckStack (leaf, thread); - - prevstack->next = &stack; - - stack.next = NULL; - stack.leaf = leaf; - stack.portal = NULL; - stack.depth = prevstack->depth + 1; - -#ifdef SEPERATORCACHE - stack.numseperators[0] = 0; - stack.numseperators[1] = 0; -#endif - - might = (long *)stack.mightsee; - vis = (long *)thread->base->portalvis; - - // check all portals for flowing into other leafs - for (i = 0; i < leaf->numportals; i++) - { - p = leaf->portals[i]; - if (p->removed) - continue; - pnum = p - portals; - - /* MrE: portal trace debug code - { - int portaltrace[] = {13, 16, 17, 37}; - pstack_t *s; - - s = &thread->pstack_head; - for (j = 0; s->next && j < sizeof(portaltrace)/sizeof(int) - 1; j++, s = s->next) - { - if (s->portal->num != portaltrace[j]) - break; - } - if (j >= sizeof(portaltrace)/sizeof(int) - 1) - { - if (p->num == portaltrace[j]) - n = 0; //traced through all the portals - } - } - */ - - if ( ! (prevstack->mightsee[pnum >> 3] & (1<<(pnum&7)) ) ) - { - continue; // can't possibly see it - } - - // if the portal can't see anything we haven't allready seen, skip it - if (p->status == stat_done) - { - test = (long *)p->portalvis; - } - else - { - test = (long *)p->portalflood; - } - - more = 0; - prevmight = (long *)prevstack->mightsee; - for (j=0 ; j<portallongs ; j++) - { - might[j] = prevmight[j] & test[j]; - more |= (might[j] & ~vis[j]); - } - - if (!more && - (thread->base->portalvis[pnum>>3] & (1<<(pnum&7))) ) - { // can't see anything new - continue; - } - - // get plane of portal, point normal into the neighbor leaf - stack.portalplane = p->plane; - VectorSubtract (vec3_origin, p->plane.normal, backplane.normal); - backplane.dist = -p->plane.dist; - -// c_portalcheck++; - - stack.portal = p; - stack.next = NULL; - stack.freewindings[0] = 1; - stack.freewindings[1] = 1; - stack.freewindings[2] = 1; - -#if 1 - { - float d; - - d = DotProduct (p->origin, thread->pstack_head.portalplane.normal); - d -= thread->pstack_head.portalplane.dist; - if (d < -p->radius) - { - continue; - } - else if (d > p->radius) - { - stack.pass = p->winding; - } - else - { - stack.pass = VisChopWinding (p->winding, &stack, &thread->pstack_head.portalplane); - if (!stack.pass) - continue; - } - } -#else - stack.pass = VisChopWinding (p->winding, &stack, &thread->pstack_head.portalplane); - if (!stack.pass) - continue; -#endif - - -#if 1 - { - float d; - - d = DotProduct (thread->base->origin, p->plane.normal); - d -= p->plane.dist; - //MrE: vis-bug fix - //if (d > p->radius) - if (d > thread->base->radius) - { - continue; - } - //MrE: vis-bug fix - //if (d < -p->radius) - else if (d < -thread->base->radius) - { - stack.source = prevstack->source; - } - else - { - stack.source = VisChopWinding (prevstack->source, &stack, &backplane); - //FIXME: shouldn't we create a new source origin and radius for fast checks? - if (!stack.source) - continue; - } - } -#else - stack.source = VisChopWinding (prevstack->source, &stack, &backplane); - if (!stack.source) - continue; -#endif - - if (!prevstack->pass) - { // the second leaf can only be blocked if coplanar - - // mark the portal as visible - thread->base->portalvis[pnum>>3] |= (1<<(pnum&7)); - - RecursiveLeafFlow (p->leaf, thread, &stack); - continue; - } - -#ifdef SEPERATORCACHE - if (stack.numseperators[0]) - { - for (n = 0; n < stack.numseperators[0]; n++) - { - stack.pass = VisChopWinding (stack.pass, &stack, &stack.seperators[0][n]); - if (!stack.pass) - break; // target is not visible - } - if (n < stack.numseperators[0]) - continue; - } - else - { - stack.pass = ClipToSeperators (prevstack->source, prevstack->pass, stack.pass, qfalse, &stack); - } -#else - stack.pass = ClipToSeperators (stack.source, prevstack->pass, stack.pass, qfalse, &stack); -#endif - if (!stack.pass) - continue; - -#ifdef SEPERATORCACHE - if (stack.numseperators[1]) - { - for (n = 0; n < stack.numseperators[1]; n++) - { - stack.pass = VisChopWinding (stack.pass, &stack, &stack.seperators[1][n]); - if (!stack.pass) - break; // target is not visible - } - } - else - { - stack.pass = ClipToSeperators (prevstack->pass, prevstack->source, stack.pass, qtrue, &stack); - } -#else - stack.pass = ClipToSeperators (prevstack->pass, stack.source, stack.pass, qtrue, &stack); -#endif - if (!stack.pass) - continue; - - // mark the portal as visible - thread->base->portalvis[pnum>>3] |= (1<<(pnum&7)); - - // flow through it for real - RecursiveLeafFlow (p->leaf, thread, &stack); - // - stack.next = NULL; - } -} - -/* -=============== -PortalFlow - -generates the portalvis bit vector -=============== -*/ -void PortalFlow (int portalnum) -{ - threaddata_t data; - int i; - vportal_t *p; - int c_might, c_can; - -#ifdef MREDEBUG - _printf("\r%6d", portalnum); -#endif - - p = sorted_portals[portalnum]; - - if (p->removed) - { - p->status = stat_done; - return; - } - - p->status = stat_working; - - c_might = CountBits (p->portalflood, numportals*2); - - memset (&data, 0, sizeof(data)); - data.base = p; - - data.pstack_head.portal = p; - data.pstack_head.source = p->winding; - data.pstack_head.portalplane = p->plane; - data.pstack_head.depth = 0; - for (i=0 ; i<portallongs ; i++) - ((long *)data.pstack_head.mightsee)[i] = ((long *)p->portalflood)[i]; - - RecursiveLeafFlow (p->leaf, &data, &data.pstack_head); - - p->status = stat_done; - - c_can = CountBits (p->portalvis, numportals*2); - - qprintf ("portal:%4i mightsee:%4i cansee:%4i (%i chains)\n", - (int)(p - portals), c_might, c_can, data.c_chains); -} - -/* -================== -RecursivePassageFlow -================== -*/ -void RecursivePassageFlow (vportal_t *portal, threaddata_t *thread, pstack_t *prevstack) -{ - pstack_t stack; - vportal_t *p; - leaf_t *leaf; - passage_t *passage, *nextpassage; - int i, j; - long *might, *vis, *prevmight, *cansee, *portalvis, more; - int pnum; - - leaf = &leafs[portal->leaf]; - - prevstack->next = &stack; - - stack.next = NULL; - stack.depth = prevstack->depth + 1; - - vis = (long *)thread->base->portalvis; - - passage = portal->passages; - nextpassage = passage; - // check all portals for flowing into other leafs - for (i = 0; i < leaf->numportals; i++, passage = nextpassage) - { - p = leaf->portals[i]; - if ( p->removed ) { - continue; - } - nextpassage = passage->next; - pnum = p - portals; - - if ( ! (prevstack->mightsee[pnum >> 3] & (1<<(pnum&7)) ) ) { - continue; // can't possibly see it - } - - // mark the portal as visible - thread->base->portalvis[pnum>>3] |= (1<<(pnum&7)); - - prevmight = (long *)prevstack->mightsee; - cansee = (long *)passage->cansee; - might = (long *)stack.mightsee; - memcpy(might, prevmight, portalbytes); - if (p->status == stat_done) - portalvis = (long *) p->portalvis; - else - portalvis = (long *) p->portalflood; - more = 0; - for (j = 0; j < portallongs; j++) - { - if (*might) - { - *might &= *cansee++ & *portalvis++; - more |= (*might & ~vis[j]); - } - else - { - cansee++; - portalvis++; - } - might++; - } - - if ( !more ) { - // can't see anything new - continue; - } - - // flow through it for real - RecursivePassageFlow(p, thread, &stack); - - stack.next = NULL; - } -} - -/* -=============== -PassageFlow -=============== -*/ -void PassageFlow (int portalnum) -{ - threaddata_t data; - int i; - vportal_t *p; -// int c_might, c_can; - -#ifdef MREDEBUG - _printf("\r%6d", portalnum); -#endif - - p = sorted_portals[portalnum]; - - if (p->removed) - { - p->status = stat_done; - return; - } - - p->status = stat_working; - -// c_might = CountBits (p->portalflood, numportals*2); - - memset (&data, 0, sizeof(data)); - data.base = p; - - data.pstack_head.portal = p; - data.pstack_head.source = p->winding; - data.pstack_head.portalplane = p->plane; - data.pstack_head.depth = 0; - for (i=0 ; i<portallongs ; i++) - ((long *)data.pstack_head.mightsee)[i] = ((long *)p->portalflood)[i]; - - RecursivePassageFlow (p, &data, &data.pstack_head); - - p->status = stat_done; - - /* - c_can = CountBits (p->portalvis, numportals*2); - - qprintf ("portal:%4i mightsee:%4i cansee:%4i (%i chains)\n", - (int)(p - portals), c_might, c_can, data.c_chains); - */ -} - -/* -================== -RecursivePassagePortalFlow -================== -*/ -void RecursivePassagePortalFlow (vportal_t *portal, threaddata_t *thread, pstack_t *prevstack) -{ - pstack_t stack; - vportal_t *p; - leaf_t *leaf; - plane_t backplane; - passage_t *passage, *nextpassage; - int i, j, n; - long *might, *vis, *prevmight, *cansee, *portalvis, more; - int pnum; - -// thread->c_chains++; - - leaf = &leafs[portal->leaf]; -// CheckStack (leaf, thread); - - prevstack->next = &stack; - - stack.next = NULL; - stack.leaf = leaf; - stack.portal = NULL; - stack.depth = prevstack->depth + 1; - -#ifdef SEPERATORCACHE - stack.numseperators[0] = 0; - stack.numseperators[1] = 0; -#endif - - vis = (long *)thread->base->portalvis; - - passage = portal->passages; - nextpassage = passage; - // check all portals for flowing into other leafs - for (i = 0; i < leaf->numportals; i++, passage = nextpassage) - { - p = leaf->portals[i]; - if (p->removed) - continue; - nextpassage = passage->next; - pnum = p - portals; - - if ( ! (prevstack->mightsee[pnum >> 3] & (1<<(pnum&7)) ) ) - continue; // can't possibly see it - - prevmight = (long *)prevstack->mightsee; - cansee = (long *)passage->cansee; - might = (long *)stack.mightsee; - memcpy(might, prevmight, portalbytes); - if (p->status == stat_done) - portalvis = (long *) p->portalvis; - else - portalvis = (long *) p->portalflood; - more = 0; - for (j = 0; j < portallongs; j++) - { - if (*might) - { - *might &= *cansee++ & *portalvis++; - more |= (*might & ~vis[j]); - } - else - { - cansee++; - portalvis++; - } - might++; - } - - if (!more && (thread->base->portalvis[pnum>>3] & (1<<(pnum&7))) ) - { // can't see anything new - continue; - } - - // get plane of portal, point normal into the neighbor leaf - stack.portalplane = p->plane; - VectorSubtract (vec3_origin, p->plane.normal, backplane.normal); - backplane.dist = -p->plane.dist; - -// c_portalcheck++; - - stack.portal = p; - stack.next = NULL; - stack.freewindings[0] = 1; - stack.freewindings[1] = 1; - stack.freewindings[2] = 1; - -#if 1 - { - float d; - - d = DotProduct (p->origin, thread->pstack_head.portalplane.normal); - d -= thread->pstack_head.portalplane.dist; - if (d < -p->radius) - { - continue; - } - else if (d > p->radius) - { - stack.pass = p->winding; - } - else - { - stack.pass = VisChopWinding (p->winding, &stack, &thread->pstack_head.portalplane); - if (!stack.pass) - continue; - } - } -#else - stack.pass = VisChopWinding (p->winding, &stack, &thread->pstack_head.portalplane); - if (!stack.pass) - continue; -#endif - - -#if 1 - { - float d; - - d = DotProduct (thread->base->origin, p->plane.normal); - d -= p->plane.dist; - //MrE: vis-bug fix - //if (d > p->radius) - if (d > thread->base->radius) - { - continue; - } - //MrE: vis-bug fix - //if (d < -p->radius) - else if (d < -thread->base->radius) - { - stack.source = prevstack->source; - } - else - { - stack.source = VisChopWinding (prevstack->source, &stack, &backplane); - //FIXME: shouldn't we create a new source origin and radius for fast checks? - if (!stack.source) - continue; - } - } -#else - stack.source = VisChopWinding (prevstack->source, &stack, &backplane); - if (!stack.source) - continue; -#endif - - if (!prevstack->pass) - { // the second leaf can only be blocked if coplanar - - // mark the portal as visible - thread->base->portalvis[pnum>>3] |= (1<<(pnum&7)); - - RecursivePassagePortalFlow (p, thread, &stack); - continue; - } - -#ifdef SEPERATORCACHE - if (stack.numseperators[0]) - { - for (n = 0; n < stack.numseperators[0]; n++) - { - stack.pass = VisChopWinding (stack.pass, &stack, &stack.seperators[0][n]); - if (!stack.pass) - break; // target is not visible - } - if (n < stack.numseperators[0]) - continue; - } - else - { - stack.pass = ClipToSeperators (prevstack->source, prevstack->pass, stack.pass, qfalse, &stack); - } -#else - stack.pass = ClipToSeperators (stack.source, prevstack->pass, stack.pass, qfalse, &stack); -#endif - if (!stack.pass) - continue; - -#ifdef SEPERATORCACHE - if (stack.numseperators[1]) - { - for (n = 0; n < stack.numseperators[1]; n++) - { - stack.pass = VisChopWinding (stack.pass, &stack, &stack.seperators[1][n]); - if (!stack.pass) - break; // target is not visible - } - } - else - { - stack.pass = ClipToSeperators (prevstack->pass, prevstack->source, stack.pass, qtrue, &stack); - } -#else - stack.pass = ClipToSeperators (prevstack->pass, stack.source, stack.pass, qtrue, &stack); -#endif - if (!stack.pass) - continue; - - // mark the portal as visible - thread->base->portalvis[pnum>>3] |= (1<<(pnum&7)); - - // flow through it for real - RecursivePassagePortalFlow(p, thread, &stack); - // - stack.next = NULL; - } -} - -/* -=============== -PassagePortalFlow -=============== -*/ -void PassagePortalFlow (int portalnum) -{ - threaddata_t data; - int i; - vportal_t *p; -// int c_might, c_can; - -#ifdef MREDEBUG - _printf("\r%6d", portalnum); -#endif - - p = sorted_portals[portalnum]; - - if (p->removed) - { - p->status = stat_done; - return; - } - - p->status = stat_working; - -// c_might = CountBits (p->portalflood, numportals*2); - - memset (&data, 0, sizeof(data)); - data.base = p; - - data.pstack_head.portal = p; - data.pstack_head.source = p->winding; - data.pstack_head.portalplane = p->plane; - data.pstack_head.depth = 0; - for (i=0 ; i<portallongs ; i++) - ((long *)data.pstack_head.mightsee)[i] = ((long *)p->portalflood)[i]; - - RecursivePassagePortalFlow (p, &data, &data.pstack_head); - - p->status = stat_done; - - /* - c_can = CountBits (p->portalvis, numportals*2); - - qprintf ("portal:%4i mightsee:%4i cansee:%4i (%i chains)\n", - (int)(p - portals), c_might, c_can, data.c_chains); - */ -} - -winding_t *PassageChopWinding (winding_t *in, winding_t *out, plane_t *split) -{ - vec_t dists[128]; - int sides[128]; - int counts[3]; - vec_t dot; - int i, j; - vec_t *p1, *p2; - vec3_t mid; - winding_t *neww; - - counts[0] = counts[1] = counts[2] = 0; - - // determine sides for each point - for (i=0 ; i<in->numpoints ; i++) - { - dot = DotProduct (in->points[i], split->normal); - dot -= split->dist; - dists[i] = dot; - if (dot > ON_EPSILON) - sides[i] = SIDE_FRONT; - else if (dot < -ON_EPSILON) - sides[i] = SIDE_BACK; - else - { - sides[i] = SIDE_ON; - } - counts[sides[i]]++; - } - - if (!counts[1]) - return in; // completely on front side - - if (!counts[0]) - { - return NULL; - } - - sides[i] = sides[0]; - dists[i] = dists[0]; - - neww = out; - - neww->numpoints = 0; - - for (i=0 ; i<in->numpoints ; i++) - { - p1 = in->points[i]; - - if (neww->numpoints == MAX_POINTS_ON_FIXED_WINDING) - { - return in; // can't chop -- fall back to original - } - - if (sides[i] == SIDE_ON) - { - VectorCopy (p1, neww->points[neww->numpoints]); - neww->numpoints++; - continue; - } - - if (sides[i] == SIDE_FRONT) - { - VectorCopy (p1, neww->points[neww->numpoints]); - neww->numpoints++; - } - - if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) - continue; - - if (neww->numpoints == MAX_POINTS_ON_FIXED_WINDING) - { - return in; // can't chop -- fall back to original - } - - // generate a split point - p2 = in->points[(i+1)%in->numpoints]; - - dot = dists[i] / (dists[i]-dists[i+1]); - for (j=0 ; j<3 ; j++) - { // avoid round off error when possible - if (split->normal[j] == 1) - mid[j] = split->dist; - else if (split->normal[j] == -1) - mid[j] = -split->dist; - else - mid[j] = p1[j] + dot*(p2[j]-p1[j]); - } - - VectorCopy (mid, neww->points[neww->numpoints]); - neww->numpoints++; - } - - return neww; -} - -/* -=============== -AddSeperators -=============== -*/ -int AddSeperators (winding_t *source, winding_t *pass, qboolean flipclip, plane_t *seperators, int maxseperators) -{ - int i, j, k, l; - plane_t plane; - vec3_t v1, v2; - float d; - vec_t length; - int counts[3], numseperators; - qboolean fliptest; - - numseperators = 0; - // check all combinations - for (i=0 ; i<source->numpoints ; i++) - { - l = (i+1)%source->numpoints; - VectorSubtract (source->points[l] , source->points[i], v1); - - // find a vertex of pass that makes a plane that puts all of the - // vertexes of pass on the front side and all of the vertexes of - // source on the back side - for (j=0 ; j<pass->numpoints ; j++) - { - VectorSubtract (pass->points[j], source->points[i], v2); - - plane.normal[0] = v1[1]*v2[2] - v1[2]*v2[1]; - plane.normal[1] = v1[2]*v2[0] - v1[0]*v2[2]; - plane.normal[2] = v1[0]*v2[1] - v1[1]*v2[0]; - - // if points don't make a valid plane, skip it - - length = plane.normal[0] * plane.normal[0] - + plane.normal[1] * plane.normal[1] - + plane.normal[2] * plane.normal[2]; - - if (length < ON_EPSILON) - continue; - - length = 1/sqrt(length); - - plane.normal[0] *= length; - plane.normal[1] *= length; - plane.normal[2] *= length; - - plane.dist = DotProduct (pass->points[j], plane.normal); - - // - // find out which side of the generated seperating plane has the - // source portal - // -#if 1 - fliptest = qfalse; - for (k=0 ; k<source->numpoints ; k++) - { - if (k == i || k == l) - continue; - d = DotProduct (source->points[k], plane.normal) - plane.dist; - if (d < -ON_EPSILON) - { // source is on the negative side, so we want all - // pass and target on the positive side - fliptest = qfalse; - break; - } - else if (d > ON_EPSILON) - { // source is on the positive side, so we want all - // pass and target on the negative side - fliptest = qtrue; - break; - } - } - if (k == source->numpoints) - continue; // planar with source portal -#else - fliptest = flipclip; -#endif - // - // flip the normal if the source portal is backwards - // - if (fliptest) - { - VectorSubtract (vec3_origin, plane.normal, plane.normal); - plane.dist = -plane.dist; - } -#if 1 - // - // if all of the pass portal points are now on the positive side, - // this is the seperating plane - // - counts[0] = counts[1] = counts[2] = 0; - for (k=0 ; k<pass->numpoints ; k++) - { - if (k==j) - continue; - d = DotProduct (pass->points[k], plane.normal) - plane.dist; - if (d < -ON_EPSILON) - break; - else if (d > ON_EPSILON) - counts[0]++; - else - counts[2]++; - } - if (k != pass->numpoints) - continue; // points on negative side, not a seperating plane - - if (!counts[0]) - continue; // planar with seperating plane -#else - k = (j+1)%pass->numpoints; - d = DotProduct (pass->points[k], plane.normal) - plane.dist; - if (d < -ON_EPSILON) - continue; - k = (j+pass->numpoints-1)%pass->numpoints; - d = DotProduct (pass->points[k], plane.normal) - plane.dist; - if (d < -ON_EPSILON) - continue; -#endif - // - // flip the normal if we want the back side - // - if (flipclip) - { - VectorSubtract (vec3_origin, plane.normal, plane.normal); - plane.dist = -plane.dist; - } - - if (numseperators >= maxseperators) - Error("max seperators"); - seperators[numseperators] = plane; - numseperators++; - break; - } - } - return numseperators; -} - -/* -=============== -CreatePassages - -MrE: create passages from one portal to all the portals in the leaf the portal leads to - every passage has a cansee bit string with all the portals that can be - seen through the passage -=============== -*/ -void CreatePassages(int portalnum) -{ - int i, j, k, n, numseperators, numsee; - float d; - vportal_t *portal, *p, *target; - leaf_t *leaf; - passage_t *passage, *lastpassage; - plane_t seperators[MAX_SEPERATORS*2]; - winding_t *w; - winding_t in, out, *res; - -#ifdef MREDEBUG - _printf("\r%6d", portalnum); -#endif - - portal = sorted_portals[portalnum]; - - if (portal->removed) - { - portal->status = stat_done; - return; - } - - lastpassage = NULL; - leaf = &leafs[portal->leaf]; - for (i = 0; i < leaf->numportals; i++) - { - target = leaf->portals[i]; - if (target->removed) - continue; - - passage = (passage_t *) malloc(sizeof(passage_t) + portalbytes); - memset(passage, 0, sizeof(passage_t) + portalbytes); - numseperators = AddSeperators(portal->winding, target->winding, qfalse, seperators, MAX_SEPERATORS*2); - numseperators += AddSeperators(target->winding, portal->winding, qtrue, &seperators[numseperators], MAX_SEPERATORS*2-numseperators); - - passage->next = NULL; - if (lastpassage) - lastpassage->next = passage; - else - portal->passages = passage; - lastpassage = passage; - - numsee = 0; - //create the passage->cansee - for (j = 0; j < numportals * 2; j++) - { - p = &portals[j]; - if (p->removed) - continue; - if ( ! (target->portalflood[j >> 3] & (1<<(j&7)) ) ) - continue; - if ( ! (portal->portalflood[j >> 3] & (1<<(j&7)) ) ) - continue; - for (k = 0; k < numseperators; k++) - { - // - d = DotProduct (p->origin, seperators[k].normal) - seperators[k].dist; - //if completely at the back of the seperator plane - if (d < -p->radius + ON_EPSILON) - break; - w = p->winding; - for (n = 0; n < w->numpoints; n++) - { - d = DotProduct (w->points[n], seperators[k].normal) - seperators[k].dist; - //if at the front of the seperator - if (d > ON_EPSILON) - break; - } - //if no points are at the front of the seperator - if (n >= w->numpoints) - break; - } - if (k < numseperators) - continue; - memcpy(&in, p->winding, sizeof(winding_t)); - for (k = 0; k < numseperators; k++) - { - res = PassageChopWinding(&in, &out, &seperators[k]); - if (res == &out) - memcpy(&in, &out, sizeof(winding_t)); - if (res == NULL) - break; - } - if (k < numseperators) - continue; - passage->cansee[j >> 3] |= (1<<(j&7)); - numsee++; - } - } -} - -void PassageMemory(void) -{ - int i, j, totalmem, totalportals; - vportal_t *portal, *target; - leaf_t *leaf; - - totalmem = 0; - totalportals = 0; - for (i = 0; i < numportals; i++) - { - portal = sorted_portals[i]; - if (portal->removed) - continue; - leaf = &leafs[portal->leaf]; - for (j = 0; j < leaf->numportals; j++) - { - target = leaf->portals[j]; - if (target->removed) - continue; - totalmem += sizeof(passage_t) + portalbytes; - totalportals++; - } - } - _printf("%7i average number of passages per leaf\n", totalportals / numportals); - _printf("%7i MB required passage memory\n", totalmem >> 10 >> 10); -} - -/* -=============================================================================== - -This is a rough first-order aproximation that is used to trivially reject some -of the final calculations. - - -Calculates portalfront and portalflood bit vectors - -thinking about: - -typedef struct passage_s -{ - struct passage_s *next; - struct portal_s *to; - stryct sep_s *seperators; - byte *mightsee; -} passage_t; - -typedef struct portal_s -{ - struct passage_s *passages; - int leaf; // leaf portal faces into -} portal_s; - -leaf = portal->leaf -clear -for all portals - - -calc portal visibility - clear bit vector - for all passages - passage visibility - - -for a portal to be visible to a passage, it must be on the front of -all seperating planes, and both portals must be behind the new portal - -=============================================================================== -*/ - -int c_flood, c_vis; - - -/* -================== -SimpleFlood - -================== -*/ -void SimpleFlood (vportal_t *srcportal, int leafnum) -{ - int i; - leaf_t *leaf; - vportal_t *p; - int pnum; - - leaf = &leafs[leafnum]; - - for (i=0 ; i<leaf->numportals ; i++) - { - p = leaf->portals[i]; - if (p->removed) - continue; - pnum = p - portals; - if ( ! (srcportal->portalfront[pnum>>3] & (1<<(pnum&7)) ) ) - continue; - - if (srcportal->portalflood[pnum>>3] & (1<<(pnum&7)) ) - continue; - - srcportal->portalflood[pnum>>3] |= (1<<(pnum&7)); - - SimpleFlood (srcportal, p->leaf); - } -} - -/* -============== -BasePortalVis -============== -*/ -void BasePortalVis (int portalnum) -{ - int j, k; - vportal_t *tp, *p; - float d; - winding_t *w; - - p = portals+portalnum; - - if (p->removed) - return; - - p->portalfront = malloc (portalbytes); - memset (p->portalfront, 0, portalbytes); - - p->portalflood = malloc (portalbytes); - memset (p->portalflood, 0, portalbytes); - - p->portalvis = malloc (portalbytes); - memset (p->portalvis, 0, portalbytes); - - for (j=0, tp = portals ; j<numportals*2 ; j++, tp++) - { - if (j == portalnum) - continue; - if (tp->removed) - continue; - /* - if (farplanedist >= 0) - { - vec3_t dir; - VectorSubtract(p->origin, tp->origin, dir); - if (VectorLength(dir) > farplanedist - p->radius - tp->radius) - continue; - } - */ - w = tp->winding; - for (k=0 ; k<w->numpoints ; k++) - { - d = DotProduct (w->points[k], p->plane.normal) - - p->plane.dist; - if (d > ON_EPSILON) - break; - } - if (k == w->numpoints) - continue; // no points on front - - w = p->winding; - for (k=0 ; k<w->numpoints ; k++) - { - d = DotProduct (w->points[k], tp->plane.normal) - - tp->plane.dist; - if (d < -ON_EPSILON) - break; - } - if (k == w->numpoints) - continue; // no points on front - - p->portalfront[j>>3] |= (1<<(j&7)); - } - - SimpleFlood (p, p->leaf); - - p->nummightsee = CountBits (p->portalflood, numportals*2); -// _printf ("portal %i: %i mightsee\n", portalnum, p->nummightsee); - c_flood += p->nummightsee; -} - - - - - -/* -=============================================================================== - -This is a second order aproximation - -Calculates portalvis bit vector - -WAAAAAAY too slow. - -=============================================================================== -*/ - -/* -================== -RecursiveLeafBitFlow - -================== -*/ -void RecursiveLeafBitFlow (int leafnum, byte *mightsee, byte *cansee) -{ - vportal_t *p; - leaf_t *leaf; - int i, j; - long more; - int pnum; - byte newmight[MAX_PORTALS/8]; - - leaf = &leafs[leafnum]; - - // check all portals for flowing into other leafs - for (i=0 ; i<leaf->numportals ; i++) - { - p = leaf->portals[i]; - if (p->removed) - continue; - pnum = p - portals; - - // if some previous portal can't see it, skip - if (! (mightsee[pnum>>3] & (1<<(pnum&7)) ) ) - continue; - - // if this portal can see some portals we mightsee, recurse - more = 0; - for (j=0 ; j<portallongs ; j++) - { - ((long *)newmight)[j] = ((long *)mightsee)[j] - & ((long *)p->portalflood)[j]; - more |= ((long *)newmight)[j] & ~((long *)cansee)[j]; - } - - if (!more) - continue; // can't see anything new - - cansee[pnum>>3] |= (1<<(pnum&7)); - - RecursiveLeafBitFlow (p->leaf, newmight, cansee); - } -} - -/* -============== -BetterPortalVis -============== -*/ -void BetterPortalVis (int portalnum) -{ - vportal_t *p; - - p = portals+portalnum; - - if (p->removed) - return; - - RecursiveLeafBitFlow (p->leaf, p->portalflood, p->portalvis); - - // build leaf vis information - p->nummightsee = CountBits (p->portalvis, numportals*2); - c_vis += p->nummightsee; -} - - diff --git a/q3map/writebsp.c b/q3map/writebsp.c deleted file mode 100644 index 7b9e3ff..0000000 --- a/q3map/writebsp.c +++ /dev/null @@ -1,418 +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" - -/* -============ -EmitShader -============ -*/ -int EmitShader( const char *shader ) { - int i; - shaderInfo_t *si; - - if ( !shader ) { - shader = "noshader"; - } - - for ( i = 0 ; i < numShaders ; i++ ) { - if ( !Q_stricmp( shader, dshaders[i].shader ) ) { - return i; - } - } - - if ( i == MAX_MAP_SHADERS ) { - Error( "MAX_MAP_SHADERS" ); - } - numShaders++; - strcpy( dshaders[i].shader, shader ); - - si = ShaderInfoForShader( shader ); - dshaders[i].surfaceFlags = si->surfaceFlags; - dshaders[i].contentFlags = si->contents; - - return i; -} - - -/* -============ -EmitPlanes - -There is no oportunity to discard planes, because all of the original -brushes will be saved in the map. -============ -*/ -void EmitPlanes (void) -{ - int i; - dplane_t *dp; - plane_t *mp; - - mp = mapplanes; - for (i=0 ; i<nummapplanes ; i++, mp++) - { - dp = &dplanes[numplanes]; - VectorCopy ( mp->normal, dp->normal); - dp->dist = mp->dist; - numplanes++; - } -} - - - -/* -================== -EmitLeaf -================== -*/ -void EmitLeaf (node_t *node) -{ - dleaf_t *leaf_p; - bspbrush_t *b; - drawSurfRef_t *dsr; - - // emit a leaf - if (numleafs >= MAX_MAP_LEAFS) - Error ("MAX_MAP_LEAFS"); - - leaf_p = &dleafs[numleafs]; - numleafs++; - - leaf_p->cluster = node->cluster; - leaf_p->area = node->area; - - // - // write bounding box info - // - VectorCopy (node->mins, leaf_p->mins); - VectorCopy (node->maxs, leaf_p->maxs); - - // - // write the leafbrushes - // - leaf_p->firstLeafBrush = numleafbrushes; - for ( b = node->brushlist ; b ; b = b->next ) { - if ( numleafbrushes >= MAX_MAP_LEAFBRUSHES ) { - Error( "MAX_MAP_LEAFBRUSHES" ); - } - dleafbrushes[numleafbrushes] = b->original->outputNumber; - numleafbrushes++; - } - leaf_p->numLeafBrushes = numleafbrushes - leaf_p->firstLeafBrush; - - // - // write the surfaces visible in this leaf - // - if ( node->opaque ) { - return; // no leaffaces in solids - } - - // add the drawSurfRef_t drawsurfs - leaf_p->firstLeafSurface = numleafsurfaces; - for ( dsr = node->drawSurfReferences ; dsr ; dsr = dsr->nextRef ) { - if ( numleafsurfaces >= MAX_MAP_LEAFFACES) - Error ("MAX_MAP_LEAFFACES"); - dleafsurfaces[numleafsurfaces] = dsr->outputNumber; - numleafsurfaces++; - } - - - leaf_p->numLeafSurfaces = numleafsurfaces - leaf_p->firstLeafSurface; -} - - -/* -============ -EmitDrawNode_r -============ -*/ -int EmitDrawNode_r (node_t *node) -{ - dnode_t *n; - int i; - - if (node->planenum == PLANENUM_LEAF) - { - EmitLeaf (node); - return -numleafs; - } - - // emit a node - if (numnodes == MAX_MAP_NODES) - Error ("MAX_MAP_NODES"); - n = &dnodes[numnodes]; - numnodes++; - - VectorCopy (node->mins, n->mins); - VectorCopy (node->maxs, n->maxs); - - if (node->planenum & 1) - Error ("WriteDrawNodes_r: odd planenum"); - n->planeNum = node->planenum; - - // - // recursively output the other nodes - // - for (i=0 ; i<2 ; i++) - { - if (node->children[i]->planenum == PLANENUM_LEAF) - { - n->children[i] = -(numleafs + 1); - EmitLeaf (node->children[i]); - } - else - { - n->children[i] = numnodes; - EmitDrawNode_r (node->children[i]); - } - } - - return n - dnodes; -} - -//========================================================= - - - -/* -============ -SetModelNumbers -============ -*/ -void SetModelNumbers (void) -{ - int i; - int models; - char value[10]; - - models = 1; - for ( i=1 ; i<num_entities ; i++ ) { - if ( entities[i].brushes || entities[i].patches ) { - sprintf ( value, "*%i", models ); - models++; - SetKeyValue (&entities[i], "model", value); - } - } - -} - -/* -============ -SetLightStyles -============ -*/ -#define MAX_SWITCHED_LIGHTS 32 -void SetLightStyles (void) -{ - int stylenum; - const char *t; - entity_t *e; - int i, j; - char value[10]; - char lighttargets[MAX_SWITCHED_LIGHTS][64]; - - - // any light that is controlled (has a targetname) - // must have a unique style number generated for it - - stylenum = 0; - for (i=1 ; i<num_entities ; i++) - { - e = &entities[i]; - - t = ValueForKey (e, "classname"); - if (Q_strncasecmp (t, "light", 5)) - continue; - t = ValueForKey (e, "targetname"); - if (!t[0]) - continue; - - // find this targetname - for (j=0 ; j<stylenum ; j++) - if (!strcmp (lighttargets[j], t)) - break; - if (j == stylenum) - { - if (stylenum == MAX_SWITCHED_LIGHTS) - Error ("stylenum == MAX_SWITCHED_LIGHTS"); - strcpy (lighttargets[j], t); - stylenum++; - } - sprintf (value, "%i", 32 + j); - SetKeyValue (e, "style", value); - } - -} - -//=========================================================== - -/* -================== -BeginBSPFile -================== -*/ -void BeginBSPFile( void ) { - // these values may actually be initialized - // if the file existed when loaded, so clear them explicitly - nummodels = 0; - numnodes = 0; - numbrushsides = 0; - numleafsurfaces = 0; - numleafbrushes = 0; - - // leave leaf 0 as an error, because leafs are referenced as - // negative number nodes - numleafs = 1; -} - - -/* -============ -EndBSPFile -============ -*/ -void EndBSPFile( void ) { - char path[1024]; - - EmitPlanes (); - UnparseEntities (); - - // write the map - sprintf (path, "%s.bsp", source); - _printf ("Writing %s\n", path); - WriteBSPFile (path); -} - - -//=========================================================== - -/* -============ -EmitBrushes -============ -*/ -void EmitBrushes ( bspbrush_t *brushes ) { - int j; - dbrush_t *db; - bspbrush_t *b; - dbrushside_t *cp; - - for ( b = brushes ; b ; b = b->next ) { - if ( numbrushes == MAX_MAP_BRUSHES ) { - Error( "MAX_MAP_BRUSHES" ); - } - b->outputNumber = numbrushes; - db = &dbrushes[numbrushes]; - numbrushes++; - - db->shaderNum = EmitShader( b->contentShader->shader ); - db->firstSide = numbrushsides; - - // don't emit any generated backSide sides - db->numSides = 0; - for ( j=0 ; j<b->numsides ; j++ ) { - if ( b->sides[j].backSide ) { - continue; - } - if ( numbrushsides == MAX_MAP_BRUSHSIDES ) { - Error( "MAX_MAP_BRUSHSIDES "); - } - cp = &dbrushsides[numbrushsides]; - db->numSides++; - numbrushsides++; - cp->planeNum = b->sides[j].planenum; - cp->shaderNum = EmitShader( b->sides[j].shaderInfo->shader ); - } - } - -} - - -/* -================== -BeginModel -================== -*/ -void BeginModel( void ) { - dmodel_t *mod; - bspbrush_t *b; - entity_t *e; - vec3_t mins, maxs; - parseMesh_t *p; - int i; - - if ( nummodels == MAX_MAP_MODELS ) { - Error( "MAX_MAP_MODELS" ); - } - mod = &dmodels[nummodels]; - - // - // bound the brushes - // - e = &entities[entity_num]; - - ClearBounds (mins, maxs); - for ( b = e->brushes ; b ; b = b->next ) { - if ( !b->numsides ) { - continue; // not a real brush (origin brush, etc) - } - AddPointToBounds (b->mins, mins, maxs); - AddPointToBounds (b->maxs, mins, maxs); - } - - for ( p = e->patches ; p ; p = p->next ) { - for ( i = 0 ; i < p->mesh.width * p->mesh.height ; i++ ) { - AddPointToBounds( p->mesh.verts[i].xyz, mins, maxs ); - } - } - - VectorCopy (mins, mod->mins); - VectorCopy (maxs, mod->maxs); - - mod->firstSurface = numDrawSurfaces; - mod->firstBrush = numbrushes; - - EmitBrushes( e->brushes ); -} - - - - -/* -================== -EndModel -================== -*/ -void EndModel( node_t *headnode ) { - dmodel_t *mod; - - qprintf ("--- EndModel ---\n"); - - mod = &dmodels[nummodels]; - EmitDrawNode_r (headnode); - mod->numSurfaces = numDrawSurfaces - mod->firstSurface; - mod->numBrushes = numbrushes - mod->firstBrush; - - nummodels++; -} - |