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

soundv.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  * name:        soundv.c
00024  *****************************************************************************/
00025 
00026 #include "cmdlib.h"
00027 #include "mathlib.h"
00028 #include "bspfile.h"
00029 #include "imagelib.h"
00030 #include "threads.h"
00031 #include "mutex.h"
00032 #include "scriplib.h"
00033 
00034 #include "shaders.h"
00035 #include "mesh.h"
00036 
00037 #ifdef _WIN32
00038 //Improve floating-point consistency.
00039 #pragma optimize( "p", on )
00040 #endif
00041 
00042 #ifdef _WIN32
00043 #include "../libs/pakstuff.h"
00044 #endif
00045 
00046 #define MAX_CLUSTERS        16384
00047 #define MAX_PORTALS         32768
00048 #define MAX_FACETS          65536
00049 #define MAX_LIGHTS          16384
00050 
00051 #define LIGHTMAP_SIZE       128
00052 
00053 #define LIGHTMAP_PIXELSHIFT     0.5
00054 
00055 //#define LIGHTMAP_PATCHSHIFT
00056 
00057 #define PORTALFILE  "PRT1"
00058 
00059 #define ON_EPSILON  0.1
00060 
00061 #define VectorSet(v, x, y, z)       v[0] = x;v[1] = y;v[2] = z;
00062 
00063 typedef struct
00064 {
00065     vec3_t      normal;
00066     float       dist;
00067 } plane_t;
00068 
00069 #define MAX_POINTS_ON_WINDING   64
00070 //NOTE: whenever this is overflowed parts of lightmaps might end up not being lit
00071 #define MAX_POINTS_ON_FIXED_WINDING 48
00072 
00073 typedef struct
00074 {
00075     int     numpoints;
00076     vec3_t  points[MAX_POINTS_ON_FIXED_WINDING];            // variable sized
00077 } winding_t;
00078 
00079 typedef struct
00080 {
00081     plane_t     plane;  // normal pointing into neighbor
00082     int         leaf;   // neighbor
00083     winding_t   *winding;
00084     vec3_t      origin; // for fast clip testing
00085     float       radius;
00086 } lportal_t;
00087 
00088 #define MAX_PORTALS_ON_LEAF     128
00089 typedef struct lleaf_s
00090 {
00091     int         numportals;
00092     lportal_t   *portals[MAX_PORTALS_ON_LEAF];
00093     //
00094     int         numSurfaces;
00095     int         firstSurface;
00096 } lleaf_t;
00097 
00098 typedef struct lFacet_s
00099 {
00100     int     num;
00101     plane_t plane;
00102     vec3_t  points[4];              //
00103     int     numpoints;
00104     float   lightmapCoords[4][2];
00105     plane_t boundaries[4];          // negative is outside the bounds
00106     float   textureMatrix[2][4];    // texture coordinates for translucency
00107     float   lightmapMatrix[2][4];   // lightmap texture coordinates
00108     vec3_t  mins;
00109     int     x, y, width, height;
00110 } lFacet_t;
00111 
00112 typedef struct lsurfaceTest_s
00113 {
00114     vec3_t          mins, maxs;
00115     vec3_t          origin;
00116     float           radius;
00117     qboolean        patch;          // true if this is a patch
00118     qboolean        trisoup;        // true if this is a triangle soup
00119     int             numFacets;
00120     lFacet_t        *facets;
00121     mesh_t          *detailMesh;    // detailed mesh with points for each lmp
00122     shaderInfo_t    *shader;        // for translucency
00123     mutex_t         *mutex;
00124     int             numvolumes;     // number of volumes casted at this surface
00125     //
00126     int             always_tracelight;
00127     int             always_vsound;
00128 } lsurfaceTest_t;
00129 
00130 //volume types
00131 #define VOLUME_NORMAL           0
00132 #define VOLUME_DIRECTED         1
00133 
00134 #define MAX_TRANSLUCENTFACETS   32
00135 
00136 typedef struct lightvolume_s
00137 {
00138     int num;
00139     int cluster;                            //cluster this light volume started in
00140     plane_t endplane;                       //end plane
00141     plane_t farplane;                       //original end plane
00142     vec3_t points[MAX_POINTS_ON_WINDING];   //end winding points
00143     plane_t planes[MAX_POINTS_ON_WINDING];  //volume bounding planes
00144     int numplanes;                          //number of volume bounding planes
00145     int type;                               //light volume type
00146     //list with translucent surfaces the volume went through
00147     int transFacets[MAX_TRANSLUCENTFACETS];
00148     int transSurfaces[MAX_TRANSLUCENTFACETS];
00149     int numtransFacets;
00150     //clusters already tested
00151     byte clusterTested[MAX_CLUSTERS/8];
00152     //facets already tested
00153     byte facetTested[MAX_FACETS/8];
00154     int facetNum;           //number of the facet blocking the light in this volume
00155     int surfaceNum;         //number of the surface blocking the light in this volume
00156 } lightvolume_t;
00157 
00158 //light types
00159 #define LIGHT_POINTRADIAL           1
00160 #define LIGHT_POINTSPOT             2
00161 #define LIGHT_POINTFAKESURFACE      3
00162 #define LIGHT_SURFACEDIRECTED       4
00163 #define LIGHT_SURFACERADIAL         5
00164 #define LIGHT_SURFACESPOT           6
00165 
00166 //light distance attenuation types
00167 #define LDAT_QUADRATIC              0
00168 #define LDAT_LINEAR                 1
00169 #define LDAT_NOSCALE                2
00170 
00171 //light angle attenuation types
00172 #define LAAT_NORMAL                 0
00173 #define LAAT_QUADRATIC              1
00174 #define LAAT_DOUBLEQUADRATIC        2
00175 
00176 typedef struct vsound_s
00177 {
00178     vec3_t origin;              //light origin, for point lights
00179     winding_t w;                //light winding, for area lights
00180     vec4_t plane;               //light winding plane
00181     vec3_t normal;              //direction of the light
00182     int type;                   //light type
00183     vec3_t color;               //light color
00184     qboolean twosided;          //radiates light at both sides of the winding
00185     int style;                  //light style (not used)
00186     int atten_disttype;         //light distance attenuation type
00187     int atten_angletype;        //light angle attenuation type
00188     float atten_distscale;      //distance attenuation scale
00189     float atten_anglescale;     //angle attenuation scale
00190     float radiusByDist;         //radius by distance for spot lights
00191     float photons;              //emitted photons
00192     float intensity;            //intensity
00193     vec3_t emitColor;           //full out-of-gamut value (not used)
00194     struct shaderInfo_s *si;    //shader info
00195     int insolid;                //set when light is in solid
00196 } vsound_t;
00197 
00198 static float    lightLinearScale            = 1.0 / 8000;
00199 static float    lightPointScale             = 7500;
00200 static float    lightAreaScale              = 0.25;
00201 static float    lightFormFactorValueScale   = 3;
00202 static int      lightDefaultSubdivide       = 999;      // vary by surface size?
00203 static vec3_t   lightAmbientColor;
00204 
00205 static int          portalclusters, numportals, numfaces;
00206 static lleaf_t      *leafs;
00207 static lportal_t    *portals;
00208 static int          numvsounds = 0;
00209 static vsound_t *vsounds[MAX_LIGHTS];
00210 static int          nostitching = 0;
00211 static int          noalphashading = 0;
00212 static int          nocolorshading = 0;
00213 static int          nobackfaceculling = 0;
00214 static int          defaulttracelight = 0;
00215 static int          radiosity = 0;
00216 static int          radiosity_scale;
00217 
00218 static int              clustersurfaces[MAX_MAP_LEAFFACES];
00219 static int              numclustersurfaces = 0;
00220 static lsurfaceTest_t   *lsurfaceTest[MAX_MAP_DRAW_SURFS];
00221 static int              numfacets;
00222 static float            lightmappixelarea[MAX_MAP_LIGHTING/3];
00223 static float            *lightFloats;//[MAX_MAP_LIGHTING];
00224 
00225 // from polylib.c
00226 winding_t   *AllocWinding (int points);
00227 void        FreeWinding (winding_t *w);
00228 void        WindingCenter (winding_t *w, vec3_t center);
00229 void        WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs);
00230 vec_t       WindingArea (winding_t *w);
00231 winding_t   *BaseWindingForPlane (vec3_t normal, vec_t dist);
00232 void        ClipWindingEpsilon (winding_t *in, vec3_t normal, vec_t dist, 
00233                 vec_t epsilon, winding_t **front, winding_t **back);
00234 winding_t   *ReverseWinding (winding_t *w);
00235 
00236 // from light.c
00237 extern char     source[1024];
00238 extern vec3_t   surfaceOrigin[ MAX_MAP_DRAW_SURFS ];
00239 extern int      entitySurface[ MAX_MAP_DRAW_SURFS ];
00240 extern int      samplesize;
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 VS_DrawLightVolume
00421 =====================
00422 */
00423 int VS_ChopWinding (winding_t *in, plane_t *split, float epsilon);
00424 
00425 void VS_DrawLightVolume(vsound_t *light, lightvolume_t *volume)
00426 {
00427     winding_t w;
00428     int i;
00429     vec3_t p2, invsound;
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, invsound);
00438         VectorInverse(invsound);
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, invsound, w.points[2]);
00444             VectorMA(w.points[0], MAX_WORLD_COORD, invsound, 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             VS_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 VS_DrawLightmapPixel
00471 =============
00472 */
00473 void VS_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 VS_DrawPortals
00508 ============
00509 */
00510 void VS_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 VS_DrawLeaf
00525 ============
00526 */
00527 void VS_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 VS_SplitWinding
00546 =============
00547 */
00548 int VS_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: VS_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: VS_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: VS_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: VS_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 VS_LinkSurfaceIntoCluster
00677 =====================
00678 */
00679 void VS_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 VS_R_LinkSurface
00710 =====================
00711 */
00712 void VS_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 = VS_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             VS_R_LinkSurface(node->children[1], surfaceNum, &back);
00741             nodenum = node->children[0];
00742         }
00743         else
00744         {
00745             VS_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         VS_LinkSurfaceIntoCluster(cluster, surfaceNum);
00754     }
00755 }
00756 
00757 /*
00758 =====================
00759 VS_LinkSurfaces
00760 
00761 maybe link each facet seperately instead of the test surfaces?
00762 =====================
00763 */
00764 void VS_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             VS_R_LinkSurface(0, i, &winding);
00782         }
00783     }
00784 }
00785 
00786 /*
00787 =====================
00788 VS_TextureMatrixFromPoints
00789 =====================
00790 */
00791 void VS_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 VS_LightmapMatrixFromPoints
00898 =====================
00899 */
00900 void VS_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 static 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] = -