Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

lightv.c

Go to the documentation of this file.
00001 /*
00002 ===========================================================================
00003 Copyright (C) 1999-2005 Id Software, Inc.
00004 
00005 This file is part of Quake III Arena source code.
00006 
00007 Quake III Arena source code is free software; you can redistribute it
00008 and/or modify it under the terms of the GNU General Public License as
00009 published by the Free Software Foundation; either version 2 of the License,
00010 or (at your option) any later version.
00011 
00012 Quake III Arena source code is distributed in the hope that it will be
00013 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 GNU General Public License for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Foobar; if not, write to the Free Software
00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00020 ===========================================================================
00021 */
00022 
00023 
00024 #include "cmdlib.h"
00025 #include "mathlib.h"
00026 #include "bspfile.h"
00027 #include "imagelib.h"
00028 #include "threads.h"
00029 #include "mutex.h"
00030 #include "scriplib.h"
00031 
00032 #include "shaders.h"
00033 #include "mesh.h"
00034 
00035 #ifdef _WIN32
00036 //Improve floating-point consistency.
00037 #pragma optimize( "p", on )
00038 #endif
00039 
00040 #ifdef _WIN32
00041 #include "../libs/pakstuff.h"
00042 #endif
00043 
00044 #define MAX_CLUSTERS        16384
00045 #define MAX_PORTALS         32768
00046 #define MAX_FACETS          65536
00047 #define MAX_LIGHTS          16384
00048 
00049 #define LIGHTMAP_SIZE       128
00050 
00051 #define LIGHTMAP_PIXELSHIFT     0.5
00052 
00053 //#define LIGHTMAP_PATCHSHIFT
00054 
00055 #define PORTALFILE  "PRT1"
00056 
00057 #define ON_EPSILON  0.1
00058 
00059 #define VectorSet(v, x, y, z)       v[0] = x;v[1] = y;v[2] = z;
00060 
00061 typedef struct
00062 {
00063     vec3_t      normal;
00064     float       dist;
00065 } plane_t;
00066 
00067 #define MAX_POINTS_ON_WINDING   64
00068 //NOTE: whenever this is overflowed parts of lightmaps might end up not being lit
00069 #define MAX_POINTS_ON_FIXED_WINDING 48
00070 
00071 typedef struct
00072 {
00073     int     numpoints;
00074     vec3_t  points[MAX_POINTS_ON_FIXED_WINDING];            // variable sized
00075 } winding_t;
00076 
00077 typedef struct
00078 {
00079     plane_t     plane;  // normal pointing into neighbor
00080     int         leaf;   // neighbor
00081     winding_t   *winding;
00082     vec3_t      origin; // for fast clip testing
00083     float       radius;
00084 } lportal_t;
00085 
00086 #define MAX_PORTALS_ON_LEAF     128
00087 typedef struct lleaf_s
00088 {
00089     int         numportals;
00090     lportal_t   *portals[MAX_PORTALS_ON_LEAF];
00091     //
00092     int         numSurfaces;
00093     int         firstSurface;
00094 } lleaf_t;
00095 
00096 typedef struct lFacet_s
00097 {
00098     int     num;
00099     plane_t plane;
00100     vec3_t  points[4];              //
00101     int     numpoints;
00102     float   lightmapCoords[4][2];
00103     plane_t boundaries[4];          // negative is outside the bounds
00104     float   textureMatrix[2][4];    // texture coordinates for translucency
00105     float   lightmapMatrix[2][4];   // lightmap texture coordinates
00106     vec3_t  mins;
00107     int     x, y, width, height;
00108 } lFacet_t;
00109 
00110 typedef struct lsurfaceTest_s
00111 {
00112     vec3_t          mins, maxs;
00113     vec3_t          origin;
00114     float           radius;
00115     qboolean        patch;          // true if this is a patch
00116     qboolean        trisoup;        // true if this is a triangle soup
00117     int             numFacets;
00118     lFacet_t        *facets;
00119     mesh_t          *detailMesh;    // detailed mesh with points for each lmp
00120     shaderInfo_t    *shader;        // for translucency
00121     mutex_t         *mutex;
00122     int             numvolumes;     // number of volumes casted at this surface
00123     //
00124     int             always_tracelight;
00125     int             always_vlight;
00126 } lsurfaceTest_t;
00127 
00128 //volume types
00129 #define VOLUME_NORMAL           0
00130 #define VOLUME_DIRECTED         1
00131 
00132 #define MAX_TRANSLUCENTFACETS   32
00133 
00134 typedef struct lightvolume_s
00135 {
00136     int num;
00137     int cluster;                            //cluster this light volume started in
00138     plane_t endplane;                       //end plane
00139     plane_t farplane;                       //original end plane
00140     vec3_t points[MAX_POINTS_ON_WINDING];   //end winding points
00141     plane_t planes[MAX_POINTS_ON_WINDING];  //volume bounding planes
00142     int numplanes;                          //number of volume bounding planes
00143     int type;                               //light volume type
00144     //list with translucent surfaces the volume went through
00145     int transFacets[MAX_TRANSLUCENTFACETS];
00146     int transSurfaces[MAX_TRANSLUCENTFACETS];
00147     int numtransFacets;
00148     //clusters already tested
00149     byte clusterTested[MAX_CLUSTERS/8];
00150     //facets already tested
00151     byte facetTested[MAX_FACETS/8];
00152     int facetNum;           //number of the facet blocking the light in this volume
00153     int surfaceNum;         //number of the surface blocking the light in this volume
00154 } lightvolume_t;
00155 
00156 //light types
00157 #define LIGHT_POINTRADIAL           1
00158 #define LIGHT_POINTSPOT             2
00159 #define LIGHT_POINTFAKESURFACE      3
00160 #define LIGHT_SURFACEDIRECTED       4
00161 #define LIGHT_SURFACERADIAL         5
00162 #define LIGHT_SURFACESPOT           6
00163 
00164 //light distance attenuation types
00165 #define LDAT_QUADRATIC              0
00166 #define LDAT_LINEAR                 1
00167 #define LDAT_NOSCALE                2
00168 
00169 //light angle attenuation types
00170 #define LAAT_NORMAL                 0
00171 #define LAAT_QUADRATIC              1
00172 #define LAAT_DOUBLEQUADRATIC        2
00173 
00174 typedef struct vlight_s
00175 {
00176     vec3_t origin;              //light origin, for point lights
00177     winding_t w;                //light winding, for area lights
00178     vec4_t plane;               //light winding plane
00179     vec3_t normal;              //direction of the light
00180     int type;                   //light type
00181     vec3_t color;               //light color
00182     qboolean twosided;          //radiates light at both sides of the winding
00183     int style;                  //light style (not used)
00184     int atten_disttype;         //light distance attenuation type
00185     int atten_angletype;        //light angle attenuation type
00186     float atten_distscale;      //distance attenuation scale
00187     float atten_anglescale;     //angle attenuation scale
00188     float radiusByDist;         //radius by distance for spot lights
00189     float photons;              //emitted photons
00190     float intensity;            //intensity
00191     vec3_t emitColor;           //full out-of-gamut value (not used)
00192     struct shaderInfo_s *si;    //shader info
00193     int insolid;                //set when light is in solid
00194 } vlight_t;
00195 
00196 float   lightLinearScale            = 1.0 / 8000;
00197 float   lightPointScale             = 7500;
00198 float   lightAreaScale              = 0.25;
00199 float   lightFormFactorValueScale   = 3;
00200 int     lightDefaultSubdivide       = 999;      // vary by surface size?
00201 vec3_t  lightAmbientColor;
00202 
00203 int         portalclusters, numportals, numfaces;
00204 lleaf_t     *leafs;
00205 lportal_t   *portals;
00206 int         numvlights = 0;
00207 vlight_t    *vlights[MAX_LIGHTS];
00208 int         nostitching = 0;
00209 int         noalphashading = 0;
00210 int         nocolorshading = 0;
00211 int         nobackfaceculling = 0;
00212 int         defaulttracelight = 0;
00213 int         radiosity = 0;
00214 int         radiosity_scale;
00215 
00216 int             clustersurfaces[MAX_MAP_LEAFFACES];
00217 int             numclustersurfaces = 0;
00218 lsurfaceTest_t  *lsurfaceTest[MAX_MAP_DRAW_SURFS];
00219 int             numfacets;
00220 float           lightmappixelarea[MAX_MAP_LIGHTING/3];
00221 float           *lightFloats;//[MAX_MAP_LIGHTING];
00222 
00223 // from polylib.c
00224 winding_t   *AllocWinding (int points);
00225 void        FreeWinding (winding_t *w);
00226 void        WindingCenter (winding_t *w, vec3_t center);
00227 void        WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs);
00228 vec_t       WindingArea (winding_t *w);
00229 winding_t   *BaseWindingForPlane (vec3_t normal, vec_t dist);
00230 void        ClipWindingEpsilon (winding_t *in, vec3_t normal, vec_t dist, 
00231                 vec_t epsilon, winding_t **front, winding_t **back);
00232 winding_t   *ReverseWinding (winding_t *w);
00233 
00234 // from light.c
00235 extern char     source[1024];
00236 extern vec3_t   surfaceOrigin[ MAX_MAP_DRAW_SURFS ];
00237 extern int      entitySurface[ MAX_MAP_DRAW_SURFS ];
00238 extern int      samplesize;
00239 extern int      novertexlighting;
00240 extern int      nogridlighting;
00241 extern qboolean patchshadows;
00242 extern vec3_t   gridSize;
00243 
00244 float PointToPolygonFormFactor( const vec3_t point, const vec3_t normal, const winding_t *w );
00245 void ColorToBytes( const float *color, byte *colorBytes );
00246 void CountLightmaps( void );
00247 void GridAndVertexLighting( void );
00248 void SetEntityOrigins( void );
00249 
00250 
00251 //#define DEBUGNET
00252 
00253 #ifdef DEBUGNET
00254 
00255 #include "l_net.h"
00256 
00257 socket_t *debug_socket;
00258 
00259 /*
00260 =====================
00261 DebugNet_Setup
00262 =====================
00263 */
00264 void DebugNet_Setup(void)
00265 {
00266     address_t address;
00267     int i;
00268 
00269     Net_Setup();
00270     Net_StringToAddress("127.0.0.1:28000", &address);
00271     for (i = 0; i < 10; i++)
00272     {
00273         debug_socket = Net_Connect(&address, 28005 + i);
00274         if (debug_socket)
00275             break;
00276     }
00277 }
00278 
00279 /*
00280 =====================
00281 DebugNet_Shutdown
00282 =====================
00283 */
00284 void DebugNet_Shutdown(void)
00285 {
00286     netmessage_t msg;
00287 
00288     if (debug_socket)
00289     {
00290         NMSG_Clear(&msg);
00291         NMSG_WriteByte(&msg, 1);
00292         Net_Send(debug_socket, &msg);
00293         Net_Disconnect(debug_socket);
00294     }
00295     debug_socket = NULL;
00296     Net_Shutdown();
00297 }
00298 
00299 /*
00300 =====================
00301 DebugNet_RemoveAllPolys
00302 =====================
00303 */
00304 void DebugNet_RemoveAllPolys(void)
00305 {
00306     netmessage_t msg;
00307 
00308     if (!debug_socket)
00309         return;
00310     NMSG_Clear(&msg);
00311     NMSG_WriteByte(&msg, 2);        //remove all debug polys
00312     Net_Send(debug_socket, &msg);
00313 }
00314 
00315 /*
00316 ====================
00317 DebugNet_DrawWinding
00318 =====================
00319 */
00320 void DebugNet_DrawWinding(winding_t *w, int color)
00321 {
00322     netmessage_t msg;
00323     int i;
00324 
00325     if (!debug_socket)
00326         return;
00327     NMSG_Clear(&msg);
00328     NMSG_WriteByte(&msg, 0);                //draw a winding
00329     NMSG_WriteByte(&msg, w->numpoints);     //number of points
00330     NMSG_WriteLong(&msg, color);            //color
00331     for (i = 0; i < w->numpoints; i++)
00332     {
00333         NMSG_WriteFloat(&msg, w->points[i][0]);
00334         NMSG_WriteFloat(&msg, w->points[i][1]);
00335         NMSG_WriteFloat(&msg, w->points[i][2]);
00336     }
00337     Net_Send(debug_socket, &msg);
00338 }
00339 
00340 /*
00341 =====================
00342 DebugNet_DrawLine
00343 =====================
00344 */
00345 void DebugNet_DrawLine(vec3_t p1, vec3_t p2, int color)
00346 {
00347     netmessage_t msg;
00348 
00349     if (!debug_socket)
00350         return;
00351     NMSG_Clear(&msg);
00352     NMSG_WriteByte(&msg, 1);                //draw a line
00353     NMSG_WriteLong(&msg, color);            //color
00354     NMSG_WriteFloat(&msg, p1[0]);
00355     NMSG_WriteFloat(&msg, p1[1]);
00356     NMSG_WriteFloat(&msg, p1[2]);
00357     NMSG_WriteFloat(&msg, p2[0]);
00358     NMSG_WriteFloat(&msg, p2[1]);
00359     NMSG_WriteFloat(&msg, p2[2]);
00360     Net_Send(debug_socket, &msg);
00361 }
00362 
00363 /*
00364 =====================
00365 DebugNet_DrawMesh
00366 =====================
00367 */
00368 void DebugNet_DrawMesh(mesh_t *mesh)
00369 {
00370     int i, j;
00371     float dot;
00372     drawVert_t  *v1, *v2, *v3, *v4;
00373     winding_t winding;
00374     plane_t plane;
00375     vec3_t d1, d2;
00376 
00377     for ( i = 0 ; i < mesh->width - 1 ; i++ ) {
00378         for ( j = 0 ; j < mesh->height - 1 ; j++ ) {
00379 
00380             v1 = mesh->verts + j * mesh->width + i;
00381             v2 = v1 + 1;
00382             v3 = v1 + mesh->width + 1;
00383             v4 = v1 + mesh->width;
00384 
00385             VectorSubtract( v4->xyz, v1->xyz, d1 );
00386             VectorSubtract( v3->xyz, v1->xyz, d2 );
00387             CrossProduct( d2, d1, plane.normal );
00388             if ( VectorNormalize( plane.normal, plane.normal ) != 0 )
00389             {
00390                 plane.dist = DotProduct( v1->xyz, plane.normal );
00391                 dot = DotProduct(plane.normal, v2->xyz) - plane.dist;
00392                 if (fabs(dot) < 0.1)
00393                 {
00394                     VectorCopy(v1->xyz, winding.points[0]);
00395                     VectorCopy(v4->xyz, winding.points[1]);
00396                     VectorCopy(v3->xyz, winding.points[2]);
00397                     VectorCopy(v2->xyz, winding.points[3]);
00398                     winding.numpoints = 4;
00399                     DebugNet_DrawWinding(&winding, 2);
00400                     continue;
00401                 }
00402             }
00403 
00404             winding.numpoints = 3;
00405             VectorCopy(v1->xyz, winding.points[0]);
00406             VectorCopy(v4->xyz, winding.points[1]);
00407             VectorCopy(v3->xyz, winding.points[2]);
00408             DebugNet_DrawWinding(&winding, 2);
00409 
00410             VectorCopy(v1->xyz, winding.points[0]);
00411             VectorCopy(v3->xyz, winding.points[1]);
00412             VectorCopy(v2->xyz, winding.points[2]);
00413             DebugNet_DrawWinding(&winding, 2);
00414         }
00415     }
00416 }
00417 
00418 /*
00419 =====================
00420 VL_DrawLightVolume
00421 =====================
00422 */
00423 int VL_ChopWinding (winding_t *in, plane_t *split, float epsilon);
00424 
00425 void VL_DrawLightVolume(vlight_t *light, lightvolume_t *volume)
00426 {
00427     winding_t w;
00428     int i;
00429     vec3_t p2, invlight;
00430 
00431     memcpy(w.points, volume->points, volume->numplanes * sizeof(vec3_t));
00432     w.numpoints = volume->numplanes;
00433     DebugNet_DrawWinding(&w, 2);
00434 
00435     if (volume->type == VOLUME_DIRECTED)
00436     {
00437         VectorCopy(light->normal, invlight);
00438         VectorInverse(invlight);
00439         for (i = 0; i < volume->numplanes; i++)
00440         {
00441             VectorCopy(volume->points[i], w.points[0]);
00442             VectorCopy(volume->points[(i+1) % volume->numplanes], w.points[1]);
00443             VectorMA(w.points[1], MAX_WORLD_COORD, invlight, w.points[2]);
00444             VectorMA(w.points[0], MAX_WORLD_COORD, invlight, w.points[3]);
00445             w.numpoints = 4;
00446             DebugNet_DrawWinding(&w, 2);
00447             VectorMA(volume->points[i], 8, volume->planes[i].normal, p2);
00448             DebugNet_DrawLine(volume->points[i], p2, 3);
00449         }
00450     }
00451     else
00452     {
00453         //
00454         VectorCopy(light->origin, w.points[0]);
00455         w.numpoints = 3;
00456         for (i = 0; i < volume->numplanes; i++)
00457         {
00458             VectorCopy(volume->points[i], w.points[1]);
00459             VectorCopy(volume->points[(i+1) % volume->numplanes], w.points[2]);
00460             VL_ChopWinding(&w, &volume->endplane, 0);
00461             DebugNet_DrawWinding(&w, 2);
00462             VectorMA(volume->points[i], 8, volume->planes[i].normal, p2);
00463             DebugNet_DrawLine(volume->points[i], p2, 3);
00464         }
00465     }
00466 }
00467 
00468 /*
00469 =============
00470 VL_DrawLightmapPixel
00471 =============
00472 */
00473 void VL_DrawLightmapPixel(int surfaceNum, int x, int y, int color)
00474 {
00475     winding_t w;
00476     dsurface_t *ds;
00477     mesh_t *mesh;
00478 
00479     ds = &drawSurfaces[surfaceNum];
00480 
00481     if (ds->surfaceType == MST_PATCH)
00482     {
00483         mesh = lsurfaceTest[surfaceNum]->detailMesh;
00484         VectorCopy( mesh->verts[(y-ds->lightmapY)*mesh->width+x-ds->lightmapX].xyz, w.points[0]);
00485         VectorCopy( mesh->verts[(y+1-ds->lightmapY)*mesh->width+x-ds->lightmapX].xyz, w.points[1]);
00486         VectorCopy( mesh->verts[(y+1-ds->lightmapY)*mesh->width+x+1-ds->lightmapX].xyz, w.points[2]);
00487         VectorCopy( mesh->verts[(y-ds->lightmapY)*mesh->width+x+1-ds->lightmapX].xyz, w.points[3]);
00488         w.numpoints = 4;
00489     }
00490     else
00491     {
00492         VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT - ds->lightmapX, ds->lightmapVecs[0], w.points[0]);
00493         VectorMA(w.points[0], (float) y - LIGHTMAP_PIXELSHIFT - ds->lightmapY, ds->lightmapVecs[1], w.points[0]);
00494         VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT - ds->lightmapX, ds->lightmapVecs[0], w.points[1]);
00495         VectorMA(w.points[1], (float) y - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapY, ds->lightmapVecs[1], w.points[1]);
00496         VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapX, ds->lightmapVecs[0], w.points[2]);
00497         VectorMA(w.points[2], (float) y - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapY, ds->lightmapVecs[1], w.points[2]);
00498         VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapX, ds->lightmapVecs[0], w.points[3]);
00499         VectorMA(w.points[3], (float) y - LIGHTMAP_PIXELSHIFT - ds->lightmapY, ds->lightmapVecs[1], w.points[3]);
00500         w.numpoints = 4;
00501     }
00502     DebugNet_DrawWinding(&w, color);
00503 }
00504 
00505 /*
00506 ============
00507 VL_DrawPortals
00508 ============
00509 */
00510 void VL_DrawPortals(void)
00511 {
00512     int j;
00513     lportal_t *p;
00514 
00515     for (j = 0; j < numportals * 2; j++)
00516     {
00517         p = portals + j;
00518         DebugNet_DrawWinding(p->winding, 1);
00519     }
00520 }
00521 
00522 /*
00523 ============
00524 VL_DrawLeaf
00525 ============
00526 */
00527 void VL_DrawLeaf(int cluster)
00528 {
00529     int i;
00530     lleaf_t *leaf;
00531     lportal_t *p;
00532 
00533     leaf = &leafs[cluster];
00534     for (i = 0; i < leaf->numportals; i++)
00535     {
00536         p = leaf->portals[i];
00537         DebugNet_DrawWinding(p->winding, 1);
00538     }
00539 }
00540 
00541 #endif //DEBUGNET
00542 
00543 /*
00544 =============
00545 VL_SplitWinding
00546 =============
00547 */
00548 int VL_SplitWinding (winding_t *in, winding_t *back, plane_t *split, float epsilon)
00549 {
00550     vec_t   dists[128];
00551     int     sides[128];
00552     int     counts[3];
00553     vec_t   dot;
00554     int     i, j;
00555     vec_t   *p1, *p2;
00556     vec3_t  mid;
00557     winding_t out;
00558     winding_t   *neww;
00559 
00560     counts[0] = counts[1] = counts[2] = 0;
00561 
00562     // determine sides for each point
00563     for (i=0 ; i<in->numpoints ; i++)
00564     {
00565         dot = DotProduct (in->points[i], split->normal);
00566         dot -= split->dist;
00567         dists[i] = dot;
00568         if (dot > epsilon)
00569             sides[i] = SIDE_FRONT;
00570         else if (dot < -epsilon)
00571             sides[i] = SIDE_BACK;
00572         else
00573         {
00574             sides[i] = SIDE_ON;
00575         }
00576         counts[sides[i]]++;
00577     }
00578 
00579     if (!counts[SIDE_BACK])
00580     {
00581         if (!counts[SIDE_FRONT])
00582             return SIDE_ON;
00583         else
00584             return SIDE_FRONT;
00585     }
00586     
00587     if (!counts[SIDE_FRONT])
00588     {
00589         return SIDE_BACK;
00590     }
00591 
00592     sides[i] = sides[0];
00593     dists[i] = dists[0];
00594     
00595     neww = &out;
00596 
00597     neww->numpoints = 0;
00598     back->numpoints = 0;
00599 
00600     for (i=0 ; i<in->numpoints ; i++)
00601     {
00602         p1 = in->points[i];
00603 
00604         if (neww->numpoints >= MAX_POINTS_ON_FIXED_WINDING)
00605         {
00606             _printf("WARNING: VL_SplitWinding -> MAX_POINTS_ON_FIXED_WINDING overflowed\n");
00607             return SIDE_FRONT;      // can't chop -- fall back to original
00608         }
00609         if (back->numpoints >= MAX_POINTS_ON_FIXED_WINDING)
00610         {
00611             _printf("WARNING: VL_SplitWinding -> MAX_POINTS_ON_FIXED_WINDING overflowed\n");
00612             return SIDE_FRONT;
00613         }
00614 
00615         if (sides[i] == SIDE_ON)
00616         {
00617             VectorCopy (p1, neww->points[neww->numpoints]);
00618             neww->numpoints++;
00619             VectorCopy (p1, back->points[back->numpoints]);
00620             back->numpoints++;
00621             continue;
00622         }
00623     
00624         if (sides[i] == SIDE_FRONT)
00625         {
00626             VectorCopy (p1, neww->points[neww->numpoints]);
00627             neww->numpoints++;
00628         }
00629         if (sides[i] == SIDE_BACK)
00630         {
00631             VectorCopy (p1, back->points[back->numpoints]);
00632             back->numpoints++;
00633         }
00634         
00635         if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
00636             continue;
00637             
00638         if (neww->numpoints >= MAX_POINTS_ON_FIXED_WINDING)
00639         {
00640             _printf("WARNING: VL_SplitWinding -> MAX_POINTS_ON_FIXED_WINDING overflowed\n");
00641             return SIDE_FRONT;      // can't chop -- fall back to original
00642         }
00643 
00644         if (back->numpoints >= MAX_POINTS_ON_FIXED_WINDING)
00645         {
00646             _printf("WARNING: VL_SplitWinding -> MAX_POINTS_ON_FIXED_WINDING overflowed\n");
00647             return SIDE_FRONT;      // can't chop -- fall back to original
00648         }
00649 
00650         // generate a split point
00651         p2 = in->points[(i+1)%in->numpoints];
00652         
00653         dot = dists[i] / (dists[i]-dists[i+1]);
00654         for (j=0 ; j<3 ; j++)
00655         {   // avoid round off error when possible
00656             if (split->normal[j] == 1)
00657                 mid[j] = split->dist;
00658             else if (split->normal[j] == -1)
00659                 mid[j] = -split->dist;
00660             else
00661                 mid[j] = p1[j] + dot*(p2[j]-p1[j]);
00662         }
00663             
00664         VectorCopy (mid, neww->points[neww->numpoints]);
00665         neww->numpoints++;
00666         VectorCopy (mid, back->points[back->numpoints]);
00667         back->numpoints++;
00668     }
00669     memcpy(in, &out, sizeof(winding_t));
00670     
00671     return SIDE_CROSS;
00672 }
00673 
00674 /*
00675 =====================
00676 VL_LinkSurfaceIntoCluster
00677 =====================
00678 */
00679 void VL_LinkSurfaceIntoCluster(int cluster, int surfaceNum)
00680 {
00681     lleaf_t *leaf;
00682     int i;
00683 
00684     leaf = &leafs[cluster];
00685 
00686     for (i = 0; i < leaf->numSurfaces; i++)
00687     {
00688         if (clustersurfaces[leaf->firstSurface + i] == surfaceNum)
00689             return;
00690     }
00691     for (i = numclustersurfaces; i > leaf->firstSurface + leaf->numSurfaces; i--)
00692         clustersurfaces[i] = clustersurfaces[i-1];
00693     for (i = 0; i < portalclusters; i++)
00694     {
00695         if (i == cluster)
00696             continue;
00697         if (leafs[i].firstSurface >= leaf->firstSurface + leaf->numSurfaces)
00698             leafs[i].firstSurface++;
00699     }
00700     clustersurfaces[leaf->firstSurface + leaf->numSurfaces] = surfaceNum;
00701     leaf->numSurfaces++;
00702     numclustersurfaces++;
00703     if (numclustersurfaces >= MAX_MAP_LEAFFACES)
00704         Error("MAX_MAP_LEAFFACES");
00705 }
00706 
00707 /*
00708 =====================
00709 VL_R_LinkSurface
00710 =====================
00711 */
00712 void VL_R_LinkSurface(int nodenum, int surfaceNum, winding_t *w)
00713 {
00714     int leafnum, cluster, res;
00715     dnode_t *node;
00716     dplane_t *plane;
00717     winding_t back;
00718     plane_t split;
00719 
00720     while(nodenum >= 0)
00721     {
00722         node = &dnodes[nodenum];
00723         plane = &dplanes[node->planeNum];
00724 
00725         VectorCopy(plane->normal, split.normal);
00726         split.dist = plane->dist;
00727         res = VL_SplitWinding (w, &back, &split, 0.1);
00728 
00729         if (res == SIDE_FRONT)
00730         {
00731             nodenum = node->children[0];
00732         }
00733         else if (res == SIDE_BACK)
00734         {
00735             nodenum = node->children[1];
00736         }
00737         else if (res == SIDE_ON)
00738         {
00739             memcpy(&back, w, sizeof(winding_t));
00740             VL_R_LinkSurface(node->children[1], surfaceNum, &back);
00741             nodenum = node->children[0];
00742         }
00743         else
00744         {
00745             VL_R_LinkSurface(node->children[1], surfaceNum, &back);
00746             nodenum = node->children[0];
00747         }
00748     }
00749     leafnum = -nodenum - 1;
00750     cluster = dleafs[leafnum].cluster;
00751     if (cluster != -1)
00752     {
00753         VL_LinkSurfaceIntoCluster(cluster, surfaceNum);
00754     }
00755 }
00756 
00757 /*
00758 =====================
00759 VL_LinkSurfaces
00760 
00761 maybe link each facet seperately instead of the test surfaces?
00762 =====================
00763 */
00764 void VL_LinkSurfaces(void)
00765 {
00766     int i, j;
00767     lsurfaceTest_t *test;
00768     lFacet_t *facet;
00769     winding_t winding;
00770 
00771     for ( i = 0 ; i < numDrawSurfaces ; i++ )
00772     {
00773         test = lsurfaceTest[ i ];
00774         if (!test)
00775             continue;
00776         for (j = 0; j < test->numFacets; j++)
00777         {
00778             facet = &test->facets[j];
00779             memcpy(winding.points, facet->points, facet->numpoints * sizeof(vec3_t));
00780             winding.numpoints = facet->numpoints;
00781             VL_R_LinkSurface(0, i, &winding);
00782         }
00783     }
00784 }
00785 
00786 /*
00787 =====================
00788 VL_TextureMatrixFromPoints
00789 =====================
00790 */
00791 void VL_TextureMatrixFromPoints( lFacet_t *f, drawVert_t *a, drawVert_t *b, drawVert_t *c ) {
00792     int         i, j;
00793     float       t;
00794     float       m[3][4];
00795     float       s;
00796 
00797     // This is an incredibly stupid way of solving a three variable equation
00798     for ( i = 0 ; i < 2 ; i++ ) {
00799 
00800         m[0][0] = a->xyz[0];
00801         m[0][1] = a->xyz[1];
00802         m[0][2] = a->xyz[2];
00803         m[0][3] = a->st[i];
00804 
00805         m[1][0] = b->xyz[0];
00806         m[1][1] = b->xyz[1];
00807         m[1][2] = b->xyz[2];
00808         m[1][3] = b->st[i];
00809 
00810         m[2][0] = c->xyz[0];
00811         m[2][1] = c->xyz[1];
00812         m[2][2] = c->xyz[2];
00813         m[2][3] = c->st[i];
00814 
00815         if ( fabs(m[1][0]) > fabs(m[0][0]) && fabs(m[1][0]) > fabs(m[2][0]) ) {
00816             for ( j = 0 ; j < 4 ; j ++ ) {
00817                 t = m[0][j];
00818                 m[0][j] = m[1][j];
00819                 m[1][j] = t;
00820             }
00821         } else if ( fabs(m[2][0]) > fabs(m[0][0]) && fabs(m[2][0]) > fabs(m[1][0]) ) {
00822             for ( j = 0 ; j < 4 ; j ++ ) {
00823                 t = m[0][j];
00824                 m[0][j] = m[2][j];
00825                 m[2][j] = t;
00826             }
00827         }
00828 
00829         s = 1.0 / m[0][0];
00830         m[0][0] *= s;
00831         m[0][1] *= s;
00832         m[0][2] *= s;
00833         m[0][3] *= s;
00834 
00835         s = m[1][0];
00836         m[1][0] -= m[0][0] * s;
00837         m[1][1] -= m[0][1] * s;
00838         m[1][2] -= m[0][2] * s;
00839         m[1][3] -= m[0][3] * s;
00840 
00841         s = m[2][0];
00842         m[2][0] -= m[0][0] * s;
00843         m[2][1] -= m[0][1] * s;
00844         m[2][2] -= m[0][2] * s;
00845         m[2][3] -= m[0][3] * s;
00846 
00847         if ( fabs(m[2][1]) > fabs(m[1][1]) ) {
00848             for ( j = 0 ; j < 4 ; j ++ ) {
00849                 t = m[1][j];
00850                 m[1][j] = m[2][j];
00851                 m[2][j] = t;
00852             }
00853         }
00854 
00855         s = 1.0 / m[1][1];
00856         m[1][0] *= s;
00857         m[1][1] *= s;
00858         m[1][2] *= s;
00859         m[1][3] *= s;
00860 
00861         s = m[2][1];// / m[1][1];
00862         m[2][0] -= m[1][0] * s;
00863         m[2][1] -= m[1][1] * s;
00864         m[2][2] -= m[1][2] * s;
00865         m[2][3] -= m[1][3] * s;
00866 
00867         s = 1.0 / m[2][2];
00868         m[2][0] *= s;
00869         m[2][1] *= s;
00870         m[2][2] *= s;
00871         m[2][3] *= s;
00872 
00873         f->textureMatrix[i][2] = m[2][3];
00874         f->textureMatrix[i][1] = m[1][3] - f->textureMatrix[i][2] * m[1][2];
00875         f->textureMatrix[i][0] = m[0][3] - f->textureMatrix[i][2] * m[0][2] - f->textureMatrix[i][1] * m[0][1];
00876 
00877         f->textureMatrix[i][3] = 0;
00878 /*
00879         s = fabs( DotProduct( a->xyz, f->textureMatrix[i] ) - a->st[i] );
00880         if ( s > 0.01 ) {
00881             Error( "Bad textureMatrix" );
00882         }
00883         s = fabs( DotProduct( b->xyz, f->textureMatrix[i] ) - b->st[i] );
00884         if ( s > 0.01 ) {
00885             Error( "Bad textureMatrix" );
00886         }
00887         s = fabs( DotProduct( c->xyz, f->textureMatrix[i] ) - c->st[i] );
00888         if ( s > 0.01 ) {
00889             Error( "Bad textureMatrix" );
00890         }
00891 */
00892     }
00893 }
00894 
00895 /*
00896 =====================
00897 VL_LightmapMatrixFromPoints
00898 =====================
00899 */
00900 void VL_LightmapMatrixFromPoints( dsurface_t *dsurf, shaderInfo_t *si, lFacet_t *f, drawVert_t *a, drawVert_t *b, drawVert_t *c ) {
00901     int         i, j;
00902     float       t;
00903     float       m[3][4], al, bl, cl;
00904     float       s;
00905     int         h, w, ssize;
00906     vec3_t      mins, maxs, delta, size, planeNormal;
00907     drawVert_t  *verts;
00908     static int  message;
00909 
00910     // vertex-lit triangle model
00911     if ( dsurf->surfaceType == MST_TRIANGLE_SOUP ) {
00912         return;
00913     }
00914     
00915     if ( dsurf->lightmapNum < 0 ) {
00916         return;     // doesn't need lighting
00917     }
00918 
00919     VectorClear(f->mins);
00920     if (dsurf->surfaceType != MST_PATCH)
00921     {
00922         ssize = samplesize;
00923         if (si->lightmapSampleSize)
00924             ssize = si->lightmapSampleSize;
00925         ClearBounds( mins, maxs );
00926         verts = &drawVerts[dsurf->firstVert];
00927         for ( i = 0 ; i < dsurf->numVerts ; i++ ) {
00928             AddPointToBounds( verts[i].xyz, mins, maxs );
00929         }
00930         // round to the lightmap resolution
00931         for ( i = 0 ; i < 3 ; i++ ) {
00932             mins[i] = ssize * floor( mins[i] / ssize );
00933             maxs[i] = ssize * ceil( maxs[i] / ssize );
00934             f->mins[i] = mins[i];
00935             size[i] = (maxs[i] - mins[i]) / ssize + 1;
00936         }
00937         // the two largest axis will be the lightmap size
00938         VectorClear(f->lightmapMatrix[0]);
00939         f->lightmapMatrix[0][3] = 0;
00940         VectorClear(f->lightmapMatrix[1]);
00941         f->lightmapMatrix[1][3] = 0;
00942 
00943         planeNormal[0] = fabs( dsurf->lightmapVecs[2][0] );
00944         planeNormal[1] = fabs( dsurf->lightmapVecs[2][1] );
00945         planeNormal[2] = fabs( dsurf->lightmapVecs[2][2] );
00946 
00947         if ( planeNormal[0] >= planeNormal[1] && planeNormal[0] >= planeNormal[2] ) {
00948             w = size[1];
00949             h = size[2];
00950             f->lightmapMatrix[0][1] = 1.0 / ssize;
00951             f->lightmapMatrix[1][2] = 1.0 / ssize;
00952         } else if ( planeNormal[1] >= planeNormal[0] && planeNormal[1] >= planeNormal[2] ) {
00953             w = size[0];
00954             h = size[2];
00955             f->lightmapMatrix[0][0] = 1.0 / ssize;
00956             f->lightmapMatrix[1][2] = 1.0 / ssize;
00957         } else {
00958             w = size[0];
00959             h = size[1];
00960             f->lightmapMatrix[0][0] = 1.0 / ssize;
00961             f->lightmapMatrix[1][1] = 1.0 / ssize;
00962         }
00963         if ( w > LIGHTMAP_WIDTH ) {
00964             VectorScale ( f->lightmapMatrix[0], (float)LIGHTMAP_SIZE/w, f->lightmapMatrix[0] );
00965         }
00966         
00967         if ( h > LIGHTMAP_HEIGHT ) {
00968             VectorScale ( f->lightmapMatrix[1], (float)LIGHTMAP_SIZE/h, f->lightmapMatrix[1] );
00969         }
00970         VectorSubtract(a->xyz, f->mins, delta);
00971         s = (DotProduct( delta, f->lightmapMatrix[0] ) + dsurf->lightmapX + 0.5) / LIGHTMAP_SIZE;
00972         if ( fabs(s - a->lightmap[0]) > 0.01 ) {
00973             _printf( "Bad lightmapMatrix" );
00974         }
00975         t = (DotProduct( delta, f->lightmapMatrix[1] ) + dsurf->lightmapY + 0.5) / LIGHTMAP_SIZE;
00976         if ( fabs(t - a->lightmap[1]) > 0.01 ) {
00977             _printf( "Bad lightmapMatrix" );
00978         }
00979         VectorSubtract(b->xyz, f->mins, delta);
00980         s = (DotProduct( delta, f->lightmapMatrix[0] ) + dsurf->lightmapX + 0.5) / LIGHTMAP_SIZE;
00981         if ( fabs(s - b->lightmap[0]) > 0.01 ) {
00982             _printf( "Bad lightmapMatrix" );
00983         }
00984         t = (DotProduct( delta, f->lightmapMatrix[1] ) + dsurf->lightmapY + 0.5) / LIGHTMAP_SIZE;
00985         if ( fabs(t - b->lightmap[1]) > 0.01 ) {
00986             _printf( "Bad lightmapMatrix" );
00987         }
00988         VectorSubtract(c->xyz, f->mins, delta);
00989         s = (DotProduct( delta, f->lightmapMatrix[0] ) + dsurf->lightmapX + 0.5) / LIGHTMAP_SIZE;
00990         if ( fabs(s - c->lightmap[0]) > 0.01 ) {
00991             _printf( "Bad lightmapMatrix" );
00992         }
00993         t = (DotProduct( delta, f->lightmapMatrix[1] ) + dsurf->lightmapY + 0.5) / LIGHTMAP_SIZE;
00994         if ( fabs(t - c->lightmap[1]) > 0.01 ) {
00995             _printf( "Bad lightmapMatrix" );
00996         }
00997         VectorAdd(f->mins, surfaceOrigin[dsurf - drawSurfaces], f->mins);
00998         return;
00999     }
01000     // This is an incredibly stupid way of solving a three variable equation
01001     for ( i = 0 ; i < 2 ; i++ ) {
01002 
01003         if (i)
01004             al = a->lightmap[i] - ((float) dsurf->lightmapY + 0.5) / LIGHTMAP_SIZE;
01005         else
01006             al = a->lightmap[i] - ((float) dsurf->lightmapX + 0.5) / LIGHTMAP_SIZE;
01007 
01008         m[0][0] = a->xyz[0] - f->mins[0];
01009         m[0][1] = a->xyz[1] - f->mins[1];
01010         m[0][2] = a->xyz[2] - f->mins[2];
01011         m[0][3] = al;
01012 
01013         if (i)
01014             bl = b->lightmap[i] - ((float) dsurf->lightmapY + 0.5) / LIGHTMAP_SIZE;
01015         else
01016             bl = b->lightmap[i] - ((float) dsurf->lightmapX + 0.5) / LIGHTMAP_SIZE;
01017 
01018         m[1][0] = b->xyz[0] - f->mins[0];
01019         m[1][1] = b->xyz[1] - f->mins[1];
01020         m[1][2] = b->xyz[2] - f->mins[2];
01021         m[1][3] = bl;
01022 
01023         if (i)
01024             cl = c->lightmap[i] - ((float) dsurf->lightmapY + 0.5) / LIGHTMAP_SIZE;
01025         else
01026             cl = c->lightmap[i] - ((float) dsurf->lightmapX + 0.5) / LIGHTMAP_SIZE;
01027 
01028         m[2][0] = c->xyz[0] - f->mins[0];
01029         m[2][1] = c->xyz[1] - f->mins[1];
01030         m[2][2] = c->xyz[2] - f->mins[2];
01031         m[2][3] = cl;
01032 
01033         if ( fabs(m[1][0]) > fabs(m[0][0]) && fabs(m[1][0]) >= fabs(m[2][0]) ) {
01034             for ( j = 0 ; j < 4 ; j ++ ) {
01035                 t = m[0][j];
01036                 m[0][j] = m[1][j];
01037                 m[1][j] = t;
01038             }
01039         } else if ( fabs(m[2][0]) > fabs(m[0][0]) && fabs(m[2][0]) >= fabs(m[1][0]) ) {
01040             for ( j = 0 ; j < 4 ; j ++ ) {
01041                 t = m[0][j];
01042                 m[0][j] = m[2][j];
01043                 m[2][j] = t;
01044             }
01045         }
01046 
01047         if (m[0][0])
01048         {
01049             s = 1.0 / m[0][0];
01050             m[0][0] *= s;
01051             m[0][1] *= s;
01052             m[0][2] *= s;
01053             m[0][3] *= s;
01054 
01055             s = m[1][0];
01056             m[1][0] -= m[0][0] * s;
01057             m[1][1] -= m[0][1] * s;
01058             m[1][2] -= m[0][2] * s;
01059             m[1][3] -= m[0][3] * s;
01060 
01061             s = m[2][0];
01062             m[2][0] -= m[0][0] * s;
01063             m[2][1] -= m[0][1] * s;
01064             m[2][2] -= m[0][2] * s;
01065             m[2][3] -= m[0][3] * s;
01066         }
01067 
01068         if ( fabs(m[2][1]) > fabs(m[1][1]) ) {
01069             for ( j = 0 ; j < 4 ; j ++ ) {
01070                 t = m[1][j];
01071                 m[1][j] = m[2][j];
01072                 m[2][j] = t;
01073             }
01074         }
01075 
01076         if (m[1][1])
01077         {
01078             s = 1.0 / m[1][1];
01079             m[1][0] *= s;
01080             m[1][1] *= s;
01081             m[1][2] *= s;
01082             m[1][3] *= s;
01083 
01084             s = m[2][1];
01085             m[2][0] -= m[1][0] * s;
01086             m[2][1] -= m[1][1] * s;
01087             m[2][2] -= m[1][2] * s;
01088             m[2][3] -= m[1][3] * s;
01089         }
01090 
01091         if (m[2][2])
01092         {
01093             s = 1.0 / m[2][2];
01094             m[2][0] *= s;
01095             m[2][1] *= s;
01096             m[2][2] *= s;
01097             m[2][3] *= s;
01098         }
01099 
01100         f->lightmapMatrix[i][2] = m[2][3];
01101         f->lightmapMatrix[i][1] = m[1][3] - f->lightmapMatrix[i][2] * m[1][2];
01102         f->lightmapMatrix[i][0] = m[0][3] - f->lightmapMatrix[i][2] * m[0][2] - f->lightmapMatrix[i][1] * m[0][1];
01103 
01104         f->lightmapMatrix[i][3] = 0;
01105 
01106         VectorSubtract(a->xyz, f->mins, delta);
01107         s = fabs( DotProduct( delta, f->lightmapMatrix[i] ) - al );
01108         if ( s > 0.01 ) {
01109             if (!message)
01110                 _printf( "Bad lightmapMatrix\n" );
01111             message = qtrue;
01112         }
01113         VectorSubtract(b->xyz, f->mins, delta);
01114         s = fabs( DotProduct( delta, f->lightmapMatrix[i] ) - bl );
01115         if ( s > 0.01 ) {
01116             if (!message)
01117                 _printf( "Bad lightmapMatrix\n" );
01118             message = qtrue;
01119         }
01120         VectorSubtract(c->xyz, f->mins, delta);
01121         s = fabs( DotProduct( delta, f->lightmapMatrix[i] ) - cl );
01122         if ( s > 0.01 ) {
01123             if (!message)
01124                 _printf( "Bad lightmapMatrix\n" );
01125             message = qtrue;
01126         }
01127         VectorAdd(f->mins, surfaceOrigin[dsurf - drawSurfaces], f->mins);
01128     }
01129 }
01130 
01131 /*
01132 =============
01133 Plane_Equal
01134 =============
01135 */
01136 #define NORMAL_EPSILON  0.0001
01137 #define DIST_EPSILON    0.02
01138 
01139 int Plane_Equal(plane_t *a, plane_t *b, int flip)
01140 {
01141     vec3_t normal;
01142     float dist;
01143 
01144     if (flip) {
01145         normal[0] = - b->normal[0];
01146         normal[1] = - b->normal[1];
01147         normal[2] = - b->normal[2];
01148         dist = - b->dist;
01149     }
01150     else {
01151         normal[0] = b->normal[0];
01152         normal[1] = b->normal[1];
01153         normal[2] = b->normal[2];
01154         dist = b->dist;
01155     }
01156     if (
01157        fabs(a->normal[0] - normal[0]) < NORMAL_EPSILON
01158     && fabs(a->normal[1] - normal[1]) < NORMAL_EPSILON
01159     && fabs(a->normal[2] - normal[2]) < NORMAL_EPSILON
01160     && fabs(a->dist - dist) < DIST_EPSILON )
01161         return qtrue;
01162     return qfalse;
01163 }
01164 
01165 /*
01166 =============
01167 VL_PlaneFromPoints
01168 =============
01169 */
01170 qboolean VL_PlaneFromPoints( plane_t *plane, const vec3_t a, const vec3_t b, const vec3_t c ) {
01171     vec3_t  d1, d2;
01172 
01173     VectorSubtract( b, a, d1 );
01174     VectorSubtract( c, a, d2 );
01175     CrossProduct( d2, d1, plane->normal );
01176     if ( VectorNormalize( plane->normal, plane->normal ) == 0 ) {
01177         return qfalse;
01178     }
01179 
01180     plane->dist =