00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
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
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
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];
00075 } winding_t;
00076
00077 typedef struct
00078 {
00079 plane_t plane;
00080 int leaf;
00081 winding_t *winding;
00082 vec3_t origin;
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];
00104 float textureMatrix[2][4];
00105 float lightmapMatrix[2][4];
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;
00116 qboolean trisoup;
00117 int numFacets;
00118 lFacet_t *facets;
00119 mesh_t *detailMesh;
00120 shaderInfo_t *shader;
00121 mutex_t *mutex;
00122 int numvolumes;
00123
00124 int always_tracelight;
00125 int always_vlight;
00126 } lsurfaceTest_t;
00127
00128
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;
00138 plane_t endplane;
00139 plane_t farplane;
00140 vec3_t points[MAX_POINTS_ON_WINDING];
00141 plane_t planes[MAX_POINTS_ON_WINDING];
00142 int numplanes;
00143 int type;
00144
00145 int transFacets[MAX_TRANSLUCENTFACETS];
00146 int transSurfaces[MAX_TRANSLUCENTFACETS];
00147 int numtransFacets;
00148
00149 byte clusterTested[MAX_CLUSTERS/8];
00150
00151 byte facetTested[MAX_FACETS/8];
00152 int facetNum;
00153 int surfaceNum;
00154 } lightvolume_t;
00155
00156
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
00165 #define LDAT_QUADRATIC 0
00166 #define LDAT_LINEAR 1
00167 #define LDAT_NOSCALE 2
00168
00169
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;
00177 winding_t w;
00178 vec4_t plane;
00179 vec3_t normal;
00180 int type;
00181 vec3_t color;
00182 qboolean twosided;
00183 int style;
00184 int atten_disttype;
00185 int atten_angletype;
00186 float atten_distscale;
00187 float atten_anglescale;
00188 float radiusByDist;
00189 float photons;
00190 float intensity;
00191 vec3_t emitColor;
00192 struct shaderInfo_s *si;
00193 int insolid;
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;
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;
00222
00223
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
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
00252
00253 #ifdef DEBUGNET
00254
00255 #include "l_net.h"
00256
00257 socket_t *debug_socket;
00258
00259
00260
00261
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
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
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);
00312 Net_Send(debug_socket, &msg);
00313 }
00314
00315
00316
00317
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);
00329 NMSG_WriteByte(&msg, w->numpoints);
00330 NMSG_WriteLong(&msg, 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
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);
00353 NMSG_WriteLong(&msg, 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
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
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
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
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
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
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
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;
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;
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;
00648 }
00649
00650
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 {
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
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
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
00760
00761
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
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
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];
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
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892 }
00893 }
00894
00895
00896
00897
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
00911 if ( dsurf->surfaceType == MST_TRIANGLE_SOUP ) {
00912 return;
00913 }
00914
00915 if ( dsurf->lightmapNum < 0 ) {
00916 return;
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
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
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
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
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
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 = DotProduct( a, plane->normal );
01181 return qtrue;
01182 }
01183
01184
01185
01186
01187
01188
01189 void VL_GenerateBoundaryForPoints( plane_t *boundary, plane_t *plane, vec3_t a, vec3_t b ) {
01190 vec3_t d1;
01191
01192
01193 VectorSubtract( a, b, d1 );
01194 CrossProduct( plane->normal, d1, boundary->normal );
01195 VectorNormalize( boundary->normal, boundary->normal );
01196 boundary->dist = DotProduct( a, boundary->normal );
01197 }
01198
01199
01200
01201
01202
01203
01204 qboolean VL_GenerateFacetFor3Points( dsurface_t *dsurf, shaderInfo_t *si, lFacet_t *f, drawVert_t *a, drawVert_t *b, drawVert_t *c ) {
01205
01206 vec3_t dir;
01207 int i;
01208
01209
01210 if ( !VL_PlaneFromPoints( &f->plane, a->xyz, b->xyz, c->xyz ) ) {
01211 f->numpoints = 0;
01212 return qfalse;
01213 }
01214
01215 f->num = numfacets++;
01216
01217 VectorAdd( a->xyz, surfaceOrigin[dsurf - drawSurfaces], f->points[0] );
01218 VectorAdd( b->xyz, surfaceOrigin[dsurf - drawSurfaces], f->points[1] );
01219 VectorAdd( c->xyz, surfaceOrigin[dsurf - drawSurfaces], f->points[2] );
01220
01221 f->lightmapCoords[0][0] = a->lightmap[0];
01222 f->lightmapCoords[0][1] = a->lightmap[1];
01223 f->lightmapCoords[1][0] = b->lightmap[0];
01224 f->lightmapCoords[1][1] = b->lightmap[1];
01225 f->lightmapCoords[2][0] = c->lightmap[0];
01226 f->lightmapCoords[2][1] = c->lightmap[1];
01227
01228 VL_GenerateBoundaryForPoints( &f->boundaries[0], &f->plane, f->points[0], f->points[1] );
01229 VL_GenerateBoundaryForPoints( &f->boundaries[1], &f->plane, f->points[1], f->points[2] );
01230 VL_GenerateBoundaryForPoints( &f->boundaries[2], &f->plane, f->points[2], f->points[0] );
01231
01232 for (i = 0; i < 3; i++)
01233 {
01234 VectorSubtract(f->points[(i+1)%3], f->points[i], dir);
01235 if (VectorLength(dir) < 0.1)
01236 return qfalse;
01237 }
01238
01239 VL_TextureMatrixFromPoints( f, a, b, c );
01240 VL_LightmapMatrixFromPoints( dsurf, si, f, a, b, c );
01241
01242 f->numpoints = 3;
01243
01244 return qtrue;
01245 }
01246
01247
01248
01249
01250
01251
01252
01253
01254 #define PLANAR_EPSILON 0.1
01255 qboolean VL_GenerateFacetFor4Points( dsurface_t *dsurf, shaderInfo_t *si, lFacet_t *f, drawVert_t *a, drawVert_t *b, drawVert_t *c, drawVert_t *d ) {
01256 float dist;
01257 vec3_t dir;
01258 int i;
01259 plane_t plane;
01260
01261
01262 if ( !VL_PlaneFromPoints( &f->plane, a->xyz, b->xyz, c->xyz ) ) {
01263 f->numpoints = 0;
01264 return qfalse;
01265 }
01266
01267
01268 dist = DotProduct( d->xyz, f->plane.normal ) - f->plane.dist;
01269 if ( fabs( dist ) > PLANAR_EPSILON ) {
01270 f->numpoints = 0;
01271 return qfalse;
01272 }
01273
01274 VectorAdd( a->xyz, surfaceOrigin[dsurf - drawSurfaces], f->points[0] );
01275 VectorAdd( b->xyz, surfaceOrigin[dsurf - drawSurfaces], f->points[1] );
01276 VectorAdd( c->xyz, surfaceOrigin[dsurf - drawSurfaces], f->points[2] );
01277 VectorAdd( d->xyz, surfaceOrigin[dsurf - drawSurfaces], f->points[3] );
01278
01279 for (i = 1; i < 4; i++)
01280 {
01281 if ( !VL_PlaneFromPoints( &plane, f->points[i], f->points[(i+1) % 4], f->points[(i+2) % 4]) ) {
01282 f->numpoints = 0;
01283 return qfalse;
01284 }
01285
01286 if (!Plane_Equal(&f->plane, &plane, qfalse)) {
01287 f->numpoints = 0;
01288 return qfalse;
01289 }
01290 }
01291
01292 f->lightmapCoords[0][0] = a->lightmap[0];
01293 f->lightmapCoords[0][1] = a->lightmap[1];
01294 f->lightmapCoords[1][0] = b->lightmap[0];
01295 f->lightmapCoords[1][1] = b->lightmap[1];
01296 f->lightmapCoords[2][0] = c->lightmap[0];
01297 f->lightmapCoords[2][1] = c->lightmap[1];
01298 f->lightmapCoords[3][0] = d->lightmap[0];
01299 f->lightmapCoords[3][1] = d->lightmap[1];
01300
01301 VL_GenerateBoundaryForPoints( &f->boundaries[0], &f->plane, f->points[0], f->points[1] );
01302 VL_GenerateBoundaryForPoints( &f->boundaries[1], &f->plane, f->points[1], f->points[2] );
01303 VL_GenerateBoundaryForPoints( &f->boundaries[2], &f->plane, f->points[2], f->points[3] );
01304 VL_GenerateBoundaryForPoints( &f->boundaries[3], &f->plane, f->points[3], f->points[0] );
01305
01306 for (i = 0; i < 4; i++)
01307 {
01308 VectorSubtract(f->points[(i+1)%4], f->points[i], dir);
01309 if (VectorLength(dir) < 0.1)
01310 return qfalse;
01311 }
01312
01313 VL_TextureMatrixFromPoints( f, a, b, c );
01314 VL_LightmapMatrixFromPoints( dsurf, si, f, a, b, c );
01315
01316 f->num = numfacets++;
01317 f->numpoints = 4;
01318
01319 return qtrue;
01320 }
01321
01322
01323
01324
01325
01326
01327 void VL_SphereFromBounds( vec3_t mins, vec3_t maxs, vec3_t origin, float *radius ) {
01328 vec3_t temp;
01329
01330 VectorAdd( mins, maxs, origin );
01331 VectorScale( origin, 0.5, origin );
01332 VectorSubtract( maxs, origin, temp );
01333 *radius = VectorLength( temp );
01334 }
01335
01336
01337
01338
01339
01340
01341 void VL_FacetsForTriangleSurface( dsurface_t *dsurf, shaderInfo_t *si, lsurfaceTest_t *test ) {
01342 int i;
01343 drawVert_t *v1, *v2, *v3, *v4;
01344 int count;
01345 int i1, i2, i3, i4, i5, i6;
01346
01347 test->patch = qfalse;
01348 if (dsurf->surfaceType == MST_TRIANGLE_SOUP)
01349 test->trisoup = qtrue;
01350 else
01351 test->trisoup = qfalse;
01352 test->numFacets = dsurf->numIndexes / 3;
01353 test->facets = malloc( sizeof( test->facets[0] ) * test->numFacets );
01354 test->shader = si;
01355
01356 count = 0;
01357 for ( i = 0 ; i < test->numFacets ; i++ ) {
01358 i1 = drawIndexes[ dsurf->firstIndex + i*3 ];
01359 i2 = drawIndexes[ dsurf->firstIndex + i*3 + 1 ];
01360 i3 = drawIndexes[ dsurf->firstIndex + i*3 + 2 ];
01361
01362 v1 = &drawVerts[ dsurf->firstVert + i1 ];
01363 v2 = &drawVerts[ dsurf->firstVert + i2 ];
01364 v3 = &drawVerts[ dsurf->firstVert + i3 ];
01365
01366
01367 if ( i != test->numFacets - 1 ) {
01368 i4 = drawIndexes[ dsurf->firstIndex + i*3 + 3 ];
01369 i5 = drawIndexes[ dsurf->firstIndex + i*3 + 4 ];
01370 i6 = drawIndexes[ dsurf->firstIndex + i*3 + 5 ];
01371 if ( i4 == i3 && i5 == i2 ) {
01372 v4 = &drawVerts[ dsurf->firstVert + i6 ];
01373 if ( VL_GenerateFacetFor4Points( dsurf, si, &test->facets[count], v1, v2, v4, v3 ) ) {
01374 count++;
01375 i++;
01376 continue;
01377 }
01378 }
01379 }
01380
01381 if (VL_GenerateFacetFor3Points( dsurf, si, &test->facets[count], v1, v2, v3 )) {
01382 count++;
01383 }
01384 }
01385
01386
01387 test->numFacets = count;
01388 }
01389
01390
01391
01392
01393
01394
01395 void VL_FacetsForPatch( dsurface_t *dsurf, int surfaceNum, shaderInfo_t *si, lsurfaceTest_t *test ) {
01396 int i, j, x, y;
01397 drawVert_t *v1, *v2, *v3, *v4;
01398 int count, ssize;
01399 mesh_t mesh;
01400 mesh_t *subdivided, *detailmesh, *newmesh;
01401 int widthtable[LIGHTMAP_SIZE], heighttable[LIGHTMAP_SIZE];
01402
01403 mesh.width = dsurf->patchWidth;
01404 mesh.height = dsurf->patchHeight;
01405 mesh.verts = &drawVerts[ dsurf->firstVert ];
01406
01407 newmesh = SubdivideMesh( mesh, 8, 999 );
01408 PutMeshOnCurve( *newmesh );
01409 MakeMeshNormals( *newmesh );
01410
01411 subdivided = RemoveLinearMeshColumnsRows( newmesh );
01412 FreeMesh(newmesh);
01413
01414
01415
01416
01417 ssize = samplesize;
01418 if (si->lightmapSampleSize)
01419 ssize = si->lightmapSampleSize;
01420
01421 if ( dsurf->lightmapNum >= 0 ) {
01422
01423 detailmesh = SubdivideMeshQuads( subdivided, ssize, LIGHTMAP_SIZE, widthtable, heighttable);
01424 test->detailMesh = detailmesh;
01425
01426
01427
01428
01429 if ( detailmesh->width != dsurf->lightmapWidth || detailmesh->height != dsurf->lightmapHeight ) {
01430 Error( "Mesh lightmap miscount");
01431 }
01432 }
01433 else {
01434 test->detailMesh = NULL;
01435 memset(widthtable, 0, sizeof(widthtable));
01436 memset(heighttable, 0, sizeof(heighttable));
01437 }
01438
01439 test->patch = qtrue;
01440 test->trisoup = qfalse;
01441 test->numFacets = ( subdivided->width - 1 ) * ( subdivided->height - 1 ) * 2;
01442 test->facets = malloc( sizeof( test->facets[0] ) * test->numFacets );
01443 test->shader = si;
01444
01445 count = 0;
01446 x = 0;
01447 for ( i = 0 ; i < subdivided->width - 1 ; i++ ) {
01448 y = 0;
01449 for ( j = 0 ; j < subdivided->height - 1 ; j++ ) {
01450
01451 v1 = subdivided->verts + j * subdivided->width + i;
01452 v2 = v1 + 1;
01453 v3 = v1 + subdivided->width + 1;
01454 v4 = v1 + subdivided->width;
01455
01456 if ( VL_GenerateFacetFor4Points( dsurf, si, &test->facets[count], v1, v4, v3, v2 ) ) {
01457 test->facets[count].x = x;
01458 test->facets[count].y = y;
01459 test->facets[count].width = widthtable[i];
01460 test->facets[count].height = heighttable[j];
01461 count++;
01462 } else {
01463 if (VL_GenerateFacetFor3Points( dsurf, si, &test->facets[count], v1, v4, v3 )) {
01464 test->facets[count].x = x;
01465 test->facets[count].y = y;
01466 test->facets[count].width = widthtable[i];
01467 test->facets[count].height = heighttable[j];
01468 count++;
01469 }
01470 if (VL_GenerateFacetFor3Points( dsurf, si, &test->facets[count], v1, v3, v2 )) {
01471 test->facets[count].x = x;
01472 test->facets[count].y = y;
01473 test->facets[count].width = widthtable[i];
01474 test->facets[count].height = heighttable[j];
01475 count++;
01476 }
01477 }
01478 y += heighttable[j];
01479 }
01480 x += widthtable[i];
01481 }
01482 test->numFacets = count;
01483
01484 FreeMesh(subdivided);
01485 }
01486
01487
01488
01489
01490
01491
01492 void VL_InitSurfacesForTesting( void ) {
01493
01494 int i, j, k;
01495 dsurface_t *dsurf;
01496 lsurfaceTest_t *test;
01497 shaderInfo_t *si;
01498 lFacet_t *facet;
01499
01500 for ( i = 0 ; i < numDrawSurfaces ; i++ ) {
01501
01502 if ( entitySurface[i] )
01503 continue;
01504
01505 dsurf = &drawSurfaces[ i ];
01506 if ( !dsurf->numIndexes && !dsurf->patchWidth ) {
01507 continue;
01508 }
01509
01510 si = ShaderInfoForShader( dshaders[ dsurf->shaderNum].shader );
01511
01512 if ( (si->contents & CONTENTS_TRANSLUCENT) && !(si->surfaceFlags & SURF_ALPHASHADOW) ) {
01513
01514 if ( dsurf->lightmapNum < 0 )
01515 continue;
01516 }
01517
01518 test = malloc( sizeof( *test ) );
01519 memset(test, 0, sizeof( *test ));
01520 test->mutex = MutexAlloc();
01521 test->numvolumes = 0;
01522 if (si->forceTraceLight)
01523 test->always_tracelight = qtrue;
01524 else if (si->forceVLight)
01525 test->always_vlight = qtrue;
01526 lsurfaceTest[i] = test;
01527
01528 if ( dsurf->surfaceType == MST_TRIANGLE_SOUP || dsurf->surfaceType == MST_PLANAR ) {
01529 VL_FacetsForTriangleSurface( dsurf, si, test );
01530 } else if ( dsurf->surfaceType == MST_PATCH ) {
01531 VL_FacetsForPatch( dsurf, i, si, test );
01532 }
01533 if (numfacets >= MAX_FACETS)
01534 Error("numfacets >= MAX_FACETS (%d)", MAX_FACETS);
01535
01536 ClearBounds( test->mins, test->maxs );
01537 for (j = 0; j < test->numFacets; j++)
01538 {
01539 facet = &test->facets[j];
01540 for ( k = 0 ; k < facet->numpoints; k++) {
01541 AddPointToBounds( facet->points[k], test->mins, test->maxs );
01542 }
01543 }
01544 VL_SphereFromBounds( test->mins, test->maxs, test->origin, &test->radius );
01545 }
01546 _printf("%6d facets\n", numfacets);
01547 _printf("linking surfaces...\n");
01548 VL_LinkSurfaces();
01549 }
01550
01551
01552
01553
01554
01555
01556 int VL_ChopWinding (winding_t *in, plane_t *split, float epsilon)
01557 {
01558 vec_t dists[128];
01559 int sides[128];
01560 int counts[3];
01561 vec_t dot;
01562 int i, j;
01563 vec_t *p1, *p2;
01564 vec3_t mid;
01565 winding_t out;
01566 winding_t *neww;
01567
01568 counts[0] = counts[1] = counts[2] = 0;
01569
01570
01571 for (i=0 ; i<in->numpoints ; i++)
01572 {
01573 dot = DotProduct (in->points[i], split->normal);
01574 dot -= split->dist;
01575 dists[i] = dot;
01576 if (dot > epsilon)
01577 sides[i] = SIDE_FRONT;
01578 else if (dot < -epsilon)
01579 sides[i] = SIDE_BACK;
01580 else
01581 {
01582 sides[i] = SIDE_ON;
01583 }
01584 counts[sides[i]]++;
01585 }
01586
01587 if (!counts[SIDE_BACK])
01588 {
01589 if (!counts[SIDE_FRONT])
01590 return SIDE_ON;
01591 else
01592 return SIDE_FRONT;
01593 }
01594
01595 if (!counts[SIDE_FRONT])
01596 {
01597 return SIDE_BACK;
01598 }
01599
01600 sides[i] = sides[0];
01601 dists[i] = dists[0];
01602
01603 neww = &out;
01604
01605 neww->numpoints = 0;
01606
01607 for (i=0 ; i<in->numpoints ; i++)
01608 {
01609 p1 = in->points[i];
01610
01611 if (neww->numpoints >= MAX_POINTS_ON_FIXED_WINDING)
01612 {
01613 _printf("WARNING: VL_ChopWinding -> MAX_POINTS_ON_FIXED_WINDING overflowed\n");
01614 return SIDE_FRONT;
01615 }
01616
01617 if (sides[i] == SIDE_ON)
01618 {
01619 VectorCopy (p1, neww->points[neww->numpoints]);
01620 neww->numpoints++;
01621 continue;
01622 }
01623
01624 if (sides[i] == SIDE_FRONT)
01625 {
01626 VectorCopy (p1, neww->points[neww->numpoints]);
01627 neww->numpoints++;
01628 }
01629
01630 if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
01631 continue;
01632
01633 if (neww->numpoints >= MAX_POINTS_ON_FIXED_WINDING)
01634 {
01635 _printf("WARNING: VL_ChopWinding -> MAX_POINTS_ON_FIXED_WINDING overflowed\n");
01636 return SIDE_FRONT;
01637 }
01638
01639
01640 p2 = in->points[(i+1)%in->numpoints];
01641
01642 dot = dists[i] / (dists[i]-dists[i+1]);
01643 for (j=0 ; j<3 ; j++)
01644 {
01645 if (split->normal[j] == 1)
01646 mid[j] = split->dist;
01647 else if (split->normal[j] == -1)
01648 mid[j] = -split->dist;
01649 else
01650 mid[j] = p1[j] + dot*(p2[j]-p1[j]);
01651 }
01652
01653 VectorCopy (mid, neww->points[neww->numpoints]);
01654 neww->numpoints++;
01655 }
01656 memcpy(in, &out, sizeof(winding_t));
01657
01658 return SIDE_CROSS;
01659 }
01660
01661
01662
01663
01664
01665
01666
01667
01668 int VL_ChopWindingWithBrush(winding_t *w, dbrush_t *brush, winding_t *outwindings, int maxout)
01669 {
01670 int i, res, numout;
01671 winding_t front, back;
01672 plane_t plane;
01673
01674 numout = 0;
01675 memcpy(front.points, w->points, w->numpoints * sizeof(vec3_t));
01676 front.numpoints = w->numpoints;
01677 for (i = 0; i < brush->numSides; i++)
01678 {
01679 VectorCopy(dplanes[ dbrushsides[ brush->firstSide + i ].planeNum ].normal, plane.normal);
01680 VectorInverse(plane.normal);
01681 plane.dist = -dplanes[ dbrushsides[ brush->firstSide + i ].planeNum ].dist;
01682 res = VL_SplitWinding(&front, &back, &plane, 0.1);
01683 if (res == SIDE_BACK || res == SIDE_ON)
01684 {
01685 memcpy(outwindings[0].points, w->points, w->numpoints * sizeof(vec3_t));
01686 outwindings[0].numpoints = w->numpoints;
01687 return 1;
01688 }
01689 if (res != SIDE_FRONT)
01690 {
01691 if (numout >= maxout)
01692 {
01693 _printf("WARNING: VL_ChopWindingWithBrush: more than %d windings\n", maxout);
01694 return 0;
01695 }
01696 memcpy(outwindings[numout].points, back.points, back.numpoints * sizeof(vec3_t));
01697 outwindings[numout].numpoints = back.numpoints;
01698 numout++;
01699 }
01700 }
01701 return numout;
01702 }
01703
01704
01705
01706
01707
01708
01709 float VL_WindingAreaOutsideBrushes(winding_t *w, int *brushnums, int numbrushes)
01710 {
01711 int i, j, numwindings[2], n;
01712 winding_t windingsbuf[2][64];
01713 dbrush_t *brush;
01714 float area;
01715
01716 memcpy(windingsbuf[0][0].points, w->points, w->numpoints * sizeof(vec3_t));
01717 windingsbuf[0][0].numpoints = w->numpoints;
01718 numwindings[0] = 1;
01719 for (i = 0; i < numbrushes; i++)
01720 {
01721 brush = &dbrushes[brushnums[i]];
01722 if (!(dshaders[brush->shaderNum].contentFlags & (
01723 CONTENTS_LAVA
01724 | CONTENTS_SLIME
01725 | CONTENTS_WATER
01726 | CONTENTS_FOG
01727 | CONTENTS_AREAPORTAL
01728 | CONTENTS_PLAYERCLIP
01729 | CONTENTS_MONSTERCLIP
01730 | CONTENTS_CLUSTERPORTAL
01731 | CONTENTS_DONOTENTER
01732 | CONTENTS_BODY
01733 | CONTENTS_CORPSE
01734 | CONTENTS_TRANSLUCENT
01735 | CONTENTS_TRIGGER
01736 | CONTENTS_NODROP) ) &&
01737 (dshaders[brush->shaderNum].contentFlags & CONTENTS_SOLID) )
01738 {
01739 numwindings[!(i & 1)] = 0;
01740 for (j = 0; j < numwindings[i&1]; j++)
01741 {
01742 n = VL_ChopWindingWithBrush(&windingsbuf[i&1][j], brush,
01743 &windingsbuf[!(i&1)][numwindings[!(i&1)]],
01744 64 - numwindings[!(i&1)]);
01745 numwindings[!(i&1)] += n;
01746 }
01747 if (!numwindings[!(i&1)])
01748 return 0;
01749 }
01750 else
01751 {
01752 for (j = 0; j < numwindings[i&1]; j++)
01753 {
01754 windingsbuf[!(i&1)][j] = windingsbuf[i&1][j];
01755 }
01756 numwindings[!(i&1)] = numwindings[i&1];
01757 }
01758 }
01759 area = 0;
01760 for (j = 0; j < numwindings[i&1]; j++)
01761 {
01762 area += WindingArea(&windingsbuf[i&1][j]);
01763 }
01764 return area;
01765 }
01766
01767
01768
01769
01770
01771
01772 float VL_R_WindingAreaOutsideSolid(winding_t *w, vec3_t normal, int nodenum)
01773 {
01774 int leafnum, res;
01775 float area;
01776 dnode_t *node;
01777 dleaf_t *leaf;
01778 dplane_t *plane;
01779 winding_t back;
01780 plane_t split;
01781
01782 area = 0;
01783 while(nodenum >= 0)
01784 {
01785 node = &dnodes[nodenum];
01786 plane = &dplanes[node->planeNum];
01787
01788 VectorCopy(plane->normal, split.normal);
01789 split.dist = plane->dist;
01790 res = VL_SplitWinding (w, &back, &split, 0.1);
01791
01792 if (res == SIDE_FRONT)
01793 {
01794 nodenum = node->children[0];
01795 }
01796 else if (res == SIDE_BACK)
01797 {
01798 nodenum = node->children[1];
01799 }
01800 else if (res == SIDE_ON)
01801 {
01802 if (DotProduct(normal, plane->normal) > 0)
01803 nodenum = node->children[0];
01804 else
01805 nodenum = node->children[1];
01806 }
01807 else
01808 {
01809 area += VL_R_WindingAreaOutsideSolid(&back, normal, node->children[1]);
01810 nodenum = node->children[0];
01811 }
01812 }
01813 leafnum = -nodenum - 1;
01814 leaf = &dleafs[leafnum];
01815 if (leaf->cluster != -1)
01816 {
01817 area += VL_WindingAreaOutsideBrushes(w, &dleafbrushes[leaf->firstLeafBrush], leaf->numLeafBrushes);
01818 }
01819 return area;
01820 }
01821
01822
01823
01824
01825
01826
01827 float VL_WindingAreaOutsideSolid(winding_t *w, vec3_t normal)
01828 {
01829 return VL_R_WindingAreaOutsideSolid(w, normal, 0);
01830 }
01831
01832
01833
01834
01835
01836
01837 float VL_ChopWindingWithFacet(winding_t *w, lFacet_t *facet)
01838 {
01839 int i;
01840
01841 for (i = 0; i < facet->numpoints; i++)
01842 {
01843 if (VL_ChopWinding(w, &facet->boundaries[i], 0) == SIDE_BACK)
01844 return 0;
01845 }
01846 if (nostitching)
01847 return WindingArea(w);
01848 else
01849 return VL_WindingAreaOutsideSolid(w, facet->plane.normal);
01850 }
01851
01852
01853
01854
01855
01856
01857
01858
01859 void VL_CalcVisibleLightmapPixelArea(void)
01860 {
01861 int i, j, x, y, k;
01862 dsurface_t *ds;
01863 lsurfaceTest_t *test;
01864 mesh_t *mesh;
01865 winding_t w, tmpw;
01866 float area;
01867
01868 _printf("calculating visible lightmap pixel area...\n");
01869 for ( i = 0 ; i < numDrawSurfaces ; i++ )
01870 {
01871 test = lsurfaceTest[ i ];
01872 if (!test)
01873 continue;
01874 ds = &drawSurfaces[ i ];
01875
01876 if ( ds->lightmapNum < 0 )
01877 continue;
01878
01879 for (y = 0; y < ds->lightmapHeight; y++)
01880 {
01881 for (x = 0; x < ds->lightmapWidth; x++)
01882 {
01883 if (ds->surfaceType == MST_PATCH)
01884 {
01885 if (y == ds->lightmapHeight-1)
01886 continue;
01887 if (x == ds->lightmapWidth-1)
01888 continue;
01889 mesh = lsurfaceTest[i]->detailMesh;
01890 VectorCopy( mesh->verts[y*mesh->width+x].xyz, w.points[0]);
01891 VectorCopy( mesh->verts[(y+1)*mesh->width+x].xyz, w.points[1]);
01892 VectorCopy( mesh->verts[(y+1)*mesh->width+x+1].xyz, w.points[2]);
01893 VectorCopy( mesh->verts[y*mesh->width+x+1].xyz, w.points[3]);
01894 w.numpoints = 4;
01895 if (nostitching)
01896 area = WindingArea(&w);
01897 else
01898 area = VL_WindingAreaOutsideSolid(&w, mesh->verts[y*mesh->width+x].normal);
01899 }
01900 else
01901 {
01902 VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT, ds->lightmapVecs[0], w.points[0]);
01903 VectorMA(w.points[0], (float) y - LIGHTMAP_PIXELSHIFT, ds->lightmapVecs[1], w.points[0]);
01904 VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT, ds->lightmapVecs[0], w.points[3]);
01905 VectorMA(w.points[3], (float) y - LIGHTMAP_PIXELSHIFT + 1, ds->lightmapVecs[1], w.points[3]);
01906 VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT + 1, ds->lightmapVecs[0], w.points[2]);
01907 VectorMA(w.points[2], (float) y - LIGHTMAP_PIXELSHIFT + 1, ds->lightmapVecs[1], w.points[2]);
01908 VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT + 1, ds->lightmapVecs[0], w.points[1]);
01909 VectorMA(w.points[1], (float) y - LIGHTMAP_PIXELSHIFT, ds->lightmapVecs[1], w.points[1]);
01910 w.numpoints = 4;
01911 area = 0;
01912 for (j = 0; j < test->numFacets; j++)
01913 {
01914 memcpy(&tmpw, &w, sizeof(winding_t));
01915 area += VL_ChopWindingWithFacet(&tmpw, &test->facets[j]);
01916 }
01917 }
01918 k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y)
01919 * LIGHTMAP_WIDTH + ds->lightmapX + x;
01920 lightmappixelarea[k] = area;
01921 }
01922 }
01923 }
01924 }
01925
01926
01927
01928
01929
01930
01931 int VL_FindAdjacentSurface(int surfaceNum, int facetNum, vec3_t p1, vec3_t p2, int *sNum, int *fNum, int *point)
01932 {
01933 int i, j, k;
01934 lsurfaceTest_t *test;
01935 lFacet_t *facet;
01936 dsurface_t *ds;
01937 float *fp1, *fp2;
01938 vec3_t dir;
01939 plane_t *facetplane;
01940
01941
01942 facetplane = &lsurfaceTest[surfaceNum]->facets[facetNum].plane;
01943
01944
01945
01946
01947
01948 for ( i = 0 ; i < numDrawSurfaces ; i++ )
01949 {
01950 if (i == surfaceNum)
01951 continue;
01952 test = lsurfaceTest[ i ];
01953 if (!test)
01954 continue;
01955 if (test->trisoup)
01956 continue;
01957 ds = &drawSurfaces[i];
01958 if ( ds->lightmapNum < 0 )
01959 continue;
01960
01961 VectorSubtract(p1, test->origin, dir);
01962 if (fabs(dir[0]) > test->radius ||
01963 fabs(dir[1]) > test->radius ||
01964 fabs(dir[1]) > test->radius)
01965 {
01966 VectorSubtract(p2, test->origin, dir);
01967 if (fabs(dir[0]) > test->radius ||
01968 fabs(dir[1]) > test->radius ||
01969 fabs(dir[1]) > test->radius)
01970 {
01971 continue;
01972 }
01973 }
01974
01975 for (j = 0; j < test->numFacets; j++)
01976 {
01977 facet = &test->facets[j];
01978
01979
01980 if (DotProduct(facet->plane.normal, facetplane->normal) < 0.9)
01981 {
01982 if (!test->trisoup && !test->patch)
01983 break;
01984 continue;
01985 }
01986
01987 for (k = 0; k < facet->numpoints; k++)
01988 {
01989 fp1 = facet->points[k];
01990 if (fabs(p2[0] - fp1[0]) < 0.1 &&
01991 fabs(p2[1] - fp1[1]) < 0.1 &&
01992 fabs(p2[2] - fp1[2]) < 0.1)
01993 {
01994 fp2 = facet->points[(k+1) % facet->numpoints];
01995 if (fabs(p1[0] - fp2[0]) < 0.1 &&
01996 fabs(p1[1] - fp2[1]) < 0.1 &&
01997 fabs(p1[2] - fp2[2]) < 0.1)
01998 {
01999
02000
02001
02002 *sNum = i;
02003 *fNum = j;
02004 *point = k;
02005 return qtrue;
02006 }
02007 }
02008
02009
02010
02011
02012
02013
02014
02015
02016
02017
02018
02019
02020
02021
02022
02023
02024
02025
02026
02027
02028 }
02029 }
02030 }
02031 return qfalse;
02032 }
02033
02034
02035
02036
02037
02038
02039
02040
02041 void VL_SmoothenLightmapEdges(void)
02042 {
02043 int i, j, k, coords1[2][2];
02044 float coords2[2][2];
02045 int x1, y1, xinc1, yinc1, k1, k2;
02046 float x2, y2, xinc2, yinc2, length;
02047 int surfaceNum, facetNum, point;
02048 lsurfaceTest_t *test;
02049 lFacet_t *facet1, *facet2;
02050 dsurface_t *ds1, *ds2;
02051 float *p[2], s, t, *color1, *color2;
02052 vec3_t dir, cross;
02053
02054 for ( i = 0 ; i < numDrawSurfaces ; i++ )
02055 {
02056 test = lsurfaceTest[ i ];
02057 if (!test)
02058 continue;
02059 if (test->trisoup)
02060 continue;
02061 ds1 = &drawSurfaces[i];
02062 if ( ds1->lightmapNum < 0 )
02063 continue;
02064 for (j = 0; j < test->numFacets; j++)
02065 {
02066 facet1 = &test->facets[j];
02067
02068 for (k = 0; k < facet1->numpoints; k++)
02069 {
02070 p[0] = facet1->points[k];
02071 p[1] = facet1->points[(k+1)%facet1->numpoints];
02072
02073 coords1[0][0] = facet1->lightmapCoords[k][0] * LIGHTMAP_SIZE;
02074 coords1[0][1] = facet1->lightmapCoords[k][1] * LIGHTMAP_SIZE;
02075 coords1[1][0] = facet1->lightmapCoords[(k+1)%facet1->numpoints][0] * LIGHTMAP_SIZE;
02076 coords1[1][1] = facet1->lightmapCoords[(k+1)%facet1->numpoints][1] * LIGHTMAP_SIZE;
02077 if (coords1[0][0] >= LIGHTMAP_SIZE)
02078 coords1[0][0] = LIGHTMAP_SIZE-1;
02079 if (coords1[0][1] >= LIGHTMAP_SIZE)
02080 coords1[0][1] = LIGHTMAP_SIZE-1;
02081 if (coords1[1][0] >= LIGHTMAP_SIZE)
02082 coords1[1][0] = LIGHTMAP_SIZE-1;
02083 if (coords1[1][1] >= LIGHTMAP_SIZE)
02084 coords1[1][1] = LIGHTMAP_SIZE-1;
02085
02086
02087 VectorSubtract(p[1], p[0], dir);
02088 VectorNormalize(dir, dir);
02089 CrossProduct(dir, facet1->plane.normal, cross);
02090
02091 if (coords1[0][0] - coords1[1][0] == 0)
02092 {
02093 s = DotProduct( cross, facet1->lightmapMatrix[0] );
02094 coords1[0][0] += s < 0 ? 1 : -1;
02095 coords1[1][0] += s < 0 ? 1 : -1;
02096 if (coords1[0][0] < ds1->lightmapX || coords1[0][0] >= ds1->lightmapX + ds1->lightmapWidth)
02097 {
02098 coords1[0][0] += s < 0 ? -1 : 1;
02099 coords1[1][0] += s < 0 ? -1 : 1;
02100 }
02101 length = fabs(coords1[1][1] - coords1[0][1]);
02102 }
02103 else if (coords1[0][1] - coords1[1][1] == 0)
02104 {
02105 t = DotProduct( cross, facet1->lightmapMatrix[1] );
02106 coords1[0][1] += t < 0 ? 1 : -1;
02107 coords1[1][1] += t < 0 ? 1 : -1;
02108 if (coords1[0][1] < ds1->lightmapY || coords1[0][1] >= ds1->lightmapY + ds1->lightmapHeight)
02109 {
02110 coords1[0][1] += t < 0 ? -1 : 1;
02111 coords1[1][1] += t < 0 ? -1 : 1;
02112 }
02113 length = fabs(coords1[1][0] - coords1[0][0]);
02114 }
02115 else
02116 {
02117
02118 continue;
02119 }
02120
02121 x1 = coords1[0][0];
02122 y1 = coords1[0][1];
02123 xinc1 = coords1[1][0] - coords1[0][0];
02124 if (xinc1 < 0) xinc1 = -1;
02125 if (xinc1 > 0) xinc1 = 1;
02126 yinc1 = coords1[1][1] - coords1[0][1];
02127 if (yinc1 < 0) yinc1 = -1;
02128 if (yinc1 > 0) yinc1 = 1;
02129
02130 if (xinc1 != 0 && yinc1 != 0)
02131 continue;
02132
02133 if (!VL_FindAdjacentSurface(i, j, p[0], p[1], &surfaceNum, &facetNum, &point))
02134 continue;
02135
02136 ds2 = &drawSurfaces[surfaceNum];
02137 facet2 = &lsurfaceTest[surfaceNum]->facets[facetNum];
02138 coords2[0][0] = facet2->lightmapCoords[(point+1)%facet2->numpoints][0] * LIGHTMAP_SIZE;
02139 coords2[0][1] = facet2->lightmapCoords[(point+1)%facet2->numpoints][1] * LIGHTMAP_SIZE;
02140 coords2[1][0] = facet2->lightmapCoords[point][0] * LIGHTMAP_SIZE;
02141 coords2[1][1] = facet2->lightmapCoords[point][1] * LIGHTMAP_SIZE;
02142 if (coords2[0][0] >= LIGHTMAP_SIZE)
02143 coords2[0][0] = LIGHTMAP_SIZE-1;
02144 if (coords2[0][1] >= LIGHTMAP_SIZE)
02145 coords2[0][1] = LIGHTMAP_SIZE-1;
02146 if (coords2[1][0] >= LIGHTMAP_SIZE)
02147 coords2[1][0] = LIGHTMAP_SIZE-1;
02148 if (coords2[1][1] >= LIGHTMAP_SIZE)
02149 coords2[1][1] = LIGHTMAP_SIZE-1;
02150
02151 x2 = coords2[0][0];
02152 y2 = coords2[0][1];
02153 xinc2 = coords2[1][0] - coords2[0][0];
02154 if (length)
02155 xinc2 = xinc2 / length;
02156 yinc2 = coords2[1][1] - coords2[0][1];
02157 if (length)
02158 yinc2 = yinc2 / length;
02159
02160 if ((int) xinc2 != 0 && (int) yinc2 != 0)
02161 continue;
02162
02163 while(1)
02164 {
02165 k1 = ( ds1->lightmapNum * LIGHTMAP_HEIGHT + y1) * LIGHTMAP_WIDTH + x1;
02166 k2 = ( ds2->lightmapNum * LIGHTMAP_HEIGHT + ((int) y2)) * LIGHTMAP_WIDTH + ((int) x2);
02167 color1 = lightFloats + k1*3;
02168 color2 = lightFloats + k2*3;
02169 if (lightmappixelarea[k1] < 0.01)
02170 {
02171 color1[0] = color2[0];
02172 color1[1] = color2[1];
02173 color1[2] = color2[2];
02174 }
02175 else
02176 {
02177 color1[0] = (float) color2[0] * 0.7 + (float) color1[0] * 0.3;
02178 color1[1] = (float) color2[1] * 0.7 + (float) color1[1] * 0.3;
02179 color1[2] = (float) color2[2] * 0.7 + (float) color1[2] * 0.3;
02180 }
02181
02182 if (x1 == coords1[1][0] &&
02183 y1 == coords1[1][1])
02184 break;
02185 x1 += xinc1;
02186 y1 += yinc1;
02187 x2 += xinc2;
02188 y2 += yinc2;
02189 if (x2 < ds2->lightmapX)
02190 x2 = ds2->lightmapX;
02191 if (x2 >= ds2->lightmapX + ds2->lightmapWidth)
02192 x2 = ds2->lightmapX + ds2->lightmapWidth-1;
02193 if (y2 < ds2->lightmapY)
02194 y2 = ds2->lightmapY;
02195 if (y2 >= ds2->lightmapY + ds2->lightmapHeight)
02196 y2 = ds2->lightmapY + ds2->lightmapHeight-1;
02197 }
02198 }
02199 }
02200 }
02201 }
02202
02203
02204
02205
02206
02207
02208 void VL_FixLightmapEdges(void)
02209 {
02210 int i, j, x, y, k, foundvalue, height, width, index;
02211 int pos, top, bottom;
02212 dsurface_t *ds;
02213 lsurfaceTest_t *test;
02214 float color[3];
02215 float *ptr;
02216 byte filled[(LIGHTMAP_SIZE+1) * (LIGHTMAP_SIZE+1) / 8];
02217 float lightmap_edge_epsilon;
02218
02219 lightmap_edge_epsilon = 0.1 * samplesize;
02220 for ( i = 0 ; i < numDrawSurfaces ; i++ )
02221 {
02222 test = lsurfaceTest[ i ];
02223 if (!test)
02224 continue;
02225 ds = &drawSurfaces[ i ];
02226
02227 if ( ds->lightmapNum < 0 )
02228 continue;
02229 if (ds->surfaceType == MST_PATCH)
02230 {
02231 height = ds->lightmapHeight - 1;
02232 width = ds->lightmapWidth - 1;
02233 }
02234 else
02235 {
02236 height = ds->lightmapHeight;
02237 width = ds->lightmapWidth;
02238 }
02239 memset(filled, 0, sizeof(filled));
02240
02241 for (x = 0; x < width; x++)
02242 {
02243 for (y = 0; y < height; y++)
02244 {
02245 k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y)
02246 * LIGHTMAP_WIDTH + ds->lightmapX + x;
02247 if (lightmappixelarea[k] > lightmap_edge_epsilon)
02248 {
02249 index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x;
02250 filled[index >> 3] |= 1 << (index & 7);
02251
02252 }
02253
02254
02255 }
02256
02257 }
02258 for (y = 0; y < height; y++)
02259 {
02260 pos = -2;
02261 for (x = 0; x < width; x++)
02262 {
02263 index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x;
02264 if (pos == -2)
02265 {
02266 if (filled[index >> 3] & (1 << (index & 7)))
02267 pos = -1;
02268 }
02269 else if (pos == -1)
02270 {
02271 if (!(filled[index >> 3] & (1 << (index & 7))))
02272 pos = x - 1;
02273 }
02274 else
02275 {
02276 if (filled[index >> 3] & (1 << (index & 7)))
02277 {
02278 bottom = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y)
02279 * LIGHTMAP_WIDTH + ds->lightmapX + pos;
02280 top = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y)
02281 * LIGHTMAP_WIDTH + ds->lightmapX + x;
02282 for (j = 0; j < (x - pos + 1) / 2; j++)
02283 {
02284 k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y)
02285 * LIGHTMAP_WIDTH + ds->lightmapX + pos + j + 1;
02286 index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + pos + j + 1;
02287 filled[index >> 3] |= 1 << (index & 7);
02288 (lightFloats + k*3)[0] = (lightFloats + top*3)[0];
02289 (lightFloats + k*3)[1] = (lightFloats + top*3)[1];
02290 (lightFloats + k*3)[2] = (lightFloats + top*3)[2];
02291 k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y)
02292 * LIGHTMAP_WIDTH + ds->lightmapX + x - j - 1;
02293 index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x - j - 1;
02294 filled[index >> 3] |= 1 << (index & 7);
02295 (lightFloats + k*3)[0] = (lightFloats + bottom*3)[0];
02296 (lightFloats + k*3)[1] = (lightFloats + bottom*3)[1];
02297 (lightFloats + k*3)[2] = (lightFloats + bottom*3)[2];
02298 }
02299 pos = -1;
02300 }
02301 }
02302 }
02303 }
02304 for (x = 0; x < width; x++)
02305 {
02306 pos = -2;
02307 for (y = 0; y < height; y++)
02308 {
02309 index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x;
02310 if (pos == -2)
02311 {
02312 if (filled[index >> 3] & (1 << (index & 7)))
02313 pos = -1;
02314 }
02315 else if (pos == -1)
02316 {
02317 if (!(filled[index >> 3] & (1 << (index & 7))))
02318 pos = y - 1;
02319 }
02320 else
02321 {
02322 if (filled[index >> 3] & (1 << (index & 7)))
02323 {
02324 bottom = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + pos)
02325 * LIGHTMAP_WIDTH + ds->lightmapX + x;
02326 top = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y)
02327 * LIGHTMAP_WIDTH + ds->lightmapX + x;
02328 for (j = 0; j < (y - pos + 1) / 2; j++)
02329 {
02330 k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + pos + j + 1)
02331 * LIGHTMAP_WIDTH + ds->lightmapX + x;
02332 index = (ds->lightmapY + pos + j + 1) * LIGHTMAP_WIDTH + ds->lightmapX + x;
02333 filled[index >> 3] |= 1 << (index & 7);
02334 (lightFloats + k*3)[0] = (lightFloats + top*3)[0];
02335 (lightFloats + k*3)[1] = (lightFloats + top*3)[1];
02336 (lightFloats + k*3)[2] = (lightFloats + top*3)[2];
02337 k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y - j - 1)
02338 * LIGHTMAP_WIDTH + ds->lightmapX + x;
02339 index = (ds->lightmapY + y - j - 1) * LIGHTMAP_WIDTH + ds->lightmapX + x;
02340 filled[index >> 3] |= 1 << (index & 7);
02341 (lightFloats + k*3)[0] = (lightFloats + bottom*3)[0];
02342 (lightFloats + k*3)[1] = (lightFloats + bottom*3)[1];
02343 (lightFloats + k*3)[2] = (lightFloats + bottom*3)[2];
02344 }
02345 pos = -1;
02346 }
02347 }
02348 }
02349 }
02350 for (y = 0; y < height; y++)
02351 {
02352 foundvalue = qfalse;
02353 for (x = 0; x < width; x++)
02354 {
02355 k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y)
02356 * LIGHTMAP_WIDTH + ds->lightmapX + x;
02357 index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x;
02358 if (foundvalue)
02359 {
02360 if (filled[index >> 3] & (1 << (index & 7)))
02361 {
02362 ptr = lightFloats + k*3;
02363 color[0] = ptr[0];
02364 color[1] = ptr[1];
02365 color[2] = ptr[2];
02366 }
02367 else
02368 {
02369 ptr = lightFloats + k*3;
02370 ptr[0] = color[0];
02371 ptr[1] = color[1];
02372 ptr[2] = color[2];
02373 filled[index >> 3] |= 1 << (index & 7);
02374 }
02375 }
02376 else
02377 {
02378 if (filled[index >> 3] & (1 << (index & 7)))
02379 {
02380 ptr = lightFloats + k*3;
02381 color[0] = ptr[0];
02382 color[1] = ptr[1];
02383 color[2] = ptr[2];
02384 foundvalue = qtrue;
02385 }
02386 }
02387 }
02388 foundvalue = qfalse;
02389 for (x = width-1; x >= 0; x--)
02390 {
02391 k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y)
02392 * LIGHTMAP_WIDTH + ds->lightmapX + x;
02393 index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x;
02394 if (foundvalue)
02395 {
02396 if (filled[index >> 3] & (1 << (index & 7)))
02397 {
02398 ptr = lightFloats + k*3;
02399 color[0] = ptr[0];
02400 color[1] = ptr[1];
02401 color[2] = ptr[2];
02402 }
02403 else
02404 {
02405 ptr = lightFloats + k*3;
02406 ptr[0] = color[0];
02407 ptr[1] = color[1];
02408 ptr[2] = color[2];
02409 filled[index >> 3] |= 1 << (index & 7);
02410 }
02411 }
02412 else
02413 {
02414 if (filled[index >> 3] & (1 << (index & 7)))
02415 {
02416 ptr = lightFloats + k*3;
02417 color[0] = ptr[0];
02418 color[1] = ptr[1];
02419 color[2] = ptr[2];
02420 foundvalue = qtrue;
02421 }
02422 }
02423 }
02424 }
02425 for (x = 0; x < width; x++)
02426 {
02427 foundvalue = qfalse;
02428 for (y = 0; y < height; y++)
02429 {
02430 k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y)
02431 * LIGHTMAP_WIDTH + ds->lightmapX + x;
02432 index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x;
02433 if (foundvalue)
02434 {
02435 if (filled[index >> 3] & (1 << (index & 7)))
02436 {
02437 ptr = lightFloats + k*3;
02438 color[0] = ptr[0];
02439 color[1] = ptr[1];
02440 color[2] = ptr[2];
02441 }
02442 else
02443 {
02444 ptr = lightFloats + k*3;
02445 ptr[0] = color[0];
02446 ptr[1] = color[1];
02447 ptr[2] = color[2];
02448 filled[index >> 3] |= 1 << (index & 7);
02449 }
02450 }
02451 else
02452 {
02453 if (filled[index >> 3] & (1 << (index & 7)))
02454 {
02455 ptr = lightFloats + k*3;
02456 color[0] = ptr[0];
02457 color[1] = ptr[1];
02458 color[2] = ptr[2];
02459 foundvalue = qtrue;
02460 }
02461 }
02462 }
02463 foundvalue = qfalse;
02464 for (y = height-1; y >= 0; y--)
02465 {
02466 k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y)
02467 * LIGHTMAP_WIDTH + ds->lightmapX + x;
02468 index = (ds->lightmapY + y) * LIGHTMAP_WIDTH + ds->lightmapX + x;
02469 if (foundvalue)
02470 {
02471 if (filled[index >> 3] & (1 << (index & 7)))
02472 {
02473 ptr = lightFloats + k*3;
02474 color[0] = ptr[0];
02475 color[1] = ptr[1];
02476 color[2] = ptr[2];
02477 }
02478 else
02479 {
02480 ptr = lightFloats + k*3;
02481 ptr[0] = color[0];
02482 ptr[1] = color[1];
02483 ptr[2] = color[2];
02484 filled[index >> 3] |= 1 << (index & 7);
02485 }
02486 }
02487 else
02488 {
02489 if (filled[index >> 3] & (1 << (index & 7)))
02490 {
02491 ptr = lightFloats + k*3;
02492 color[0] = ptr[0];
02493 color[1] = ptr[1];
02494 color[2] = ptr[2];
02495 foundvalue = qtrue;
02496 }
02497 }
02498 }
02499 }
02500 if (ds->surfaceType == MST_PATCH)
02501 {
02502 x = ds->lightmapWidth-1;
02503 for (y = 0; y < ds->lightmapHeight; y++)
02504 {
02505 k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y)
02506 * LIGHTMAP_WIDTH + ds->lightmapX + x;
02507 ptr = lightFloats + k*3;
02508 ptr[0] = (lightFloats + (k-1)*3)[0];
02509 ptr[1] = (lightFloats + (k-1)*3)[1];
02510 ptr[2] = (lightFloats + (k-1)*3)[2];
02511 }
02512 y = ds->lightmapHeight-1;
02513 for (x = 0; x < ds->lightmapWidth; x++)
02514 {
02515 k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y)
02516 * LIGHTMAP_WIDTH + ds->lightmapX + x;
02517 ptr = lightFloats + k*3;
02518 ptr[0] = (lightFloats + (k-LIGHTMAP_WIDTH)*3)[0];
02519 ptr[1] = (lightFloats + (k-LIGHTMAP_WIDTH)*3)[1];
02520 ptr[2] = (lightFloats + (k-LIGHTMAP_WIDTH)*3)[2];
02521 }
02522 }
02523
02524
02525
02526
02527
02528
02529
02530
02531
02532
02533
02534
02535
02536
02537
02538
02539
02540
02541
02542
02543
02544
02545
02546
02547
02548
02549 }
02550
02551 VL_SmoothenLightmapEdges();
02552 }
02553
02554
02555
02556
02557
02558
02559 void VL_ShiftPatchLightmaps(void)
02560 {
02561 int i, j, x, y, k;
02562 drawVert_t *verts;
02563 dsurface_t *ds;
02564 lsurfaceTest_t *test;
02565 float *ptr;
02566
02567 for ( i = 0 ; i < numDrawSurfaces ; i++ )
02568 {
02569 test = lsurfaceTest[ i ];
02570 if (!test)
02571 continue;
02572 ds = &drawSurfaces[ i ];
02573
02574 if ( ds->lightmapNum < 0 )
02575 continue;
02576 if (ds->surfaceType != MST_PATCH)
02577 continue;
02578 for (x = ds->lightmapWidth; x > 0; x--)
02579 {
02580 for (y = 0; y <= ds->lightmapHeight; y++)
02581 {
02582 k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y)
02583 * LIGHTMAP_WIDTH + ds->lightmapX + x;
02584 ptr = lightFloats + k*3;
02585 ptr[0] = (lightFloats + (k-1)*3)[0];
02586 ptr[1] = (lightFloats + (k-1)*3)[1];
02587 ptr[2] = (lightFloats + (k-1)*3)[2];
02588 }
02589 }
02590 for (y = ds->lightmapHeight; y > 0; y--)
02591 {
02592 for (x = 0; x <= ds->lightmapWidth; x++)
02593 {
02594 k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y)
02595 * LIGHTMAP_WIDTH + ds->lightmapX + x;
02596 ptr = lightFloats + k*3;
02597 ptr[0] = (lightFloats + (k-LIGHTMAP_WIDTH)*3)[0];
02598 ptr[1] = (lightFloats + (k-LIGHTMAP_WIDTH)*3)[1];
02599 ptr[2] = (lightFloats + (k-LIGHTMAP_WIDTH)*3)[2];
02600 }
02601 }
02602 verts = &drawVerts[ ds->firstVert ];
02603 for ( j = 0 ; j < ds->patchHeight * ds->patchWidth; j++ )
02604 {
02605 verts[j].lightmap[0] += 0.5 / LIGHTMAP_WIDTH;
02606 verts[j].lightmap[1] += 0.5 / LIGHTMAP_HEIGHT;
02607 }
02608 ds->lightmapHeight++;
02609 ds->lightmapWidth++;
02610 }
02611 }
02612
02613
02614
02615
02616
02617
02618 void VL_StoreLightmap(void)
02619 {
02620 int i, x, y, k;
02621 dsurface_t *ds;
02622 lsurfaceTest_t *test;
02623 float *src;
02624 byte *dst;
02625
02626 _printf("storing lightmaps...\n");
02627
02628 VL_FixLightmapEdges();
02629
02630 #ifdef LIGHTMAP_PATCHSHIFT
02631 VL_ShiftPatchLightmaps();
02632 #endif
02633
02634 for ( i = 0 ; i < numDrawSurfaces ; i++ )
02635 {
02636 test = lsurfaceTest[ i ];
02637 if (!test)
02638 continue;
02639 ds = &drawSurfaces[ i ];
02640
02641 if ( ds->lightmapNum < 0 )
02642 continue;
02643
02644 for (y = 0; y < ds->lightmapHeight; y++)
02645 {
02646 for (x = 0; x < ds->lightmapWidth; x++)
02647 {
02648 k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y)
02649 * LIGHTMAP_WIDTH + ds->lightmapX + x;
02650 VectorAdd((lightFloats + k*3), lightAmbientColor, (lightFloats + k*3));
02651 src = &lightFloats[k*3];
02652 dst = lightBytes + k*3;
02653 ColorToBytes(src, dst);
02654 }
02655 }
02656 }
02657 }
02658
02659
02660
02661
02662
02663
02664 int PointInLeafnum(vec3_t point)
02665 {
02666 int nodenum;
02667 vec_t dist;
02668 dnode_t *node;
02669 dplane_t *plane;
02670
02671 nodenum = 0;
02672 while (nodenum >= 0)
02673 {
02674 node = &dnodes[nodenum];
02675 plane = &dplanes[node->planeNum];
02676 dist = DotProduct (point, plane->normal) - plane->dist;
02677 if (dist > 0)
02678 nodenum = node->children[0];
02679 else
02680 nodenum = node->children[1];
02681 }
02682
02683 return -nodenum - 1;
02684 }
02685
02686
02687
02688
02689
02690
02691 int VL_PointInLeafnum_r(vec3_t point, int nodenum)
02692 {
02693 int leafnum;
02694 vec_t dist;
02695 dnode_t *node;
02696 dplane_t *plane;
02697
02698 while (nodenum >= 0)
02699 {
02700 node = &dnodes[nodenum];
02701 plane = &dplanes[node->planeNum];
02702 dist = DotProduct (point, plane->normal) - plane->dist;
02703 if (dist > 0.1)
02704 {
02705 nodenum = node->children[0];
02706 }
02707 else if (dist < -0.1)
02708 {
02709 nodenum = node->children[1];
02710 }
02711 else
02712 {
02713 leafnum = VL_PointInLeafnum_r(point, node->children[0]);
02714 if (dleafs[leafnum].cluster != -1)
02715 return leafnum;
02716 nodenum = node->children[1];
02717 }
02718 }
02719
02720 leafnum = -nodenum - 1;
02721 return leafnum;
02722 }
02723
02724
02725
02726
02727
02728
02729 int VL_PointInLeafnum(vec3_t point)
02730 {
02731 return VL_PointInLeafnum_r(point, 0);
02732 }
02733
02734
02735
02736
02737
02738
02739 int VL_LightLeafnum(vec3_t point)
02740 {
02741
02742
02743
02744
02745
02746
02747
02748
02749
02750
02751
02752
02753
02754
02755
02756
02757
02758
02759
02760
02761
02762
02763
02764
02765
02766
02767
02768
02769
02770
02771
02772
02773 return VL_PointInLeafnum(point);
02774 }
02775
02776
02777
02778 #ifdef LIGHTPOLYS
02779
02780 winding_t *lightwindings[MAX_MAP_DRAW_SURFS];
02781 int numlightwindings;
02782
02783
02784
02785
02786
02787
02788 void VL_DrawLightWindings(void)
02789 {
02790 int i;
02791 for (i = 0; i < numlightwindings; i++)
02792 {
02793 #ifdef DEBUGNET
02794 DebugNet_DrawWinding(lightwindings[i], 1);
02795 #endif
02796 }
02797 }
02798
02799
02800
02801
02802
02803
02804 void VL_LightSurfaceWithVolume(int surfaceNum, int facetNum, vlight_t *light, lightvolume_t *volume)
02805 {
02806 winding_t *w;
02807 lsurfaceTest_t *test;
02808 lFacet_t *facet;
02809 int i;
02810
02811 test = lsurfaceTest[ surfaceNum ];
02812 facet = &test->facets[ facetNum ];
02813
02814
02815 w = (winding_t *) malloc(sizeof(winding_t));
02816 memcpy(w->points, facet->points, sizeof(vec3_t) * facet->numpoints);
02817 w->numpoints = facet->numpoints;
02818
02819 for (i = 0; i < volume->numplanes; i++)
02820 {
02821
02822 if (VL_ChopWinding(w, &volume->planes[i], 0.01) == SIDE_BACK)
02823 return;
02824 }
02825 lightwindings[numlightwindings] = w;
02826 numlightwindings++;
02827 if (numlightwindings >= MAX_MAP_DRAW_SURFS)
02828 Error("MAX_LIGHTWINDINGS");
02829 }
02830
02831 #else
02832
02833
02834
02835
02836
02837
02838
02839
02840
02841
02842
02843
02844
02845
02846
02847
02848
02849
02850
02851
02852
02853
02854
02855
02856
02857
02858
02859
02860
02861
02862
02863
02864
02865
02866
02867
02868
02869
02870
02871
02872
02873
02874
02875
02876
02877
02878
02879
02880
02881
02882
02883
02884
02885
02886
02887
02888
02889
02890
02891
02892
02893
02894
02895
02896
02897
02898
02899
02900
02901
02902
02903
02904
02905
02906
02907
02908
02909
02910
02911
02912
02913
02914
02915
02916
02917
02918
02919
02920
02921
02922
02923
02924
02925
02926
02927
02928
02929
02930
02931
02932
02933
02934
02935
02936
02937
02938
02939
02940
02941
02942
02943
02944
02945
02946
02947
02948
02949
02950
02951
02952 void VL_GetFilter(vlight_t *light, lightvolume_t *volume, vec3_t lmp, vec3_t filter)
02953 {
02954 lFacet_t *facet;
02955 lsurfaceTest_t *test;
02956 float d, d1, d2, frac, s, t, ns;
02957 int i, j, is, it, b;
02958 int x, y, u, v, numsamples, radius, color[4], largest;
02959 byte *image;
02960 vec3_t point, origin, total;
02961
02962 VectorSet(filter, 1, 1, 1);
02963
02964 if (noalphashading)
02965 return;
02966
02967 if (volume->numtransFacets <= 0)
02968 return;
02969
02970 if (light->type == LIGHT_SURFACEDIRECTED)
02971 {
02972
02973 d = DotProduct(lmp, light->normal) - DotProduct(light->normal, light->w.points[0]);
02974 VectorMA(lmp, -d, light->normal, origin);
02975 }
02976 else
02977 {
02978 VectorCopy(light->origin, origin);
02979 }
02980 for (i = 0; i < volume->numtransFacets; i++)
02981 {
02982 test = lsurfaceTest[ volume->transSurfaces[i] ];
02983 facet = &test->facets[ volume->transFacets[i] ];
02984
02985 if ( !(test->shader->surfaceFlags & SURF_ALPHASHADOW) )
02986 continue;
02987
02988 if ( !test->shader->pixels ) {
02989 continue;
02990 }
02991
02992 d1 = DotProduct( origin, facet->plane.normal) - facet->plane.dist;
02993 d2 = DotProduct( lmp, facet->plane.normal ) - facet->plane.dist;
02994
02995 if ( ( d1 < 0 ) == ( d2 < 0 ) ) {
02996 continue;
02997 }
02998
02999 frac = d1 / ( d1 - d2 );
03000
03001 for ( j = 0 ; j < 3 ; j++ ) {
03002 point[j] = origin[j] + frac * ( lmp[j] - origin[j] );
03003 }
03004
03005 s = DotProduct( point, facet->textureMatrix[0] ) + facet->textureMatrix[0][3];
03006 t = DotProduct( point, facet->textureMatrix[1] ) + facet->textureMatrix[1][3];
03007 if (s < 0)
03008 s = 0;
03009 if (t < 0)
03010 t = 0;
03011
03012 s = s - floor( s );
03013 t = t - floor( t );
03014
03015 is = s * test->shader->width;
03016 it = t * test->shader->height;
03017
03018
03019 if (nocolorshading) {
03020 image = test->shader->pixels + 4 * ( it * test->shader->width + is );
03021
03022
03023 b = image[3];
03024
03025
03026 b = b < 128 ? 0 : 255;
03027
03028 filter[0] = filter[0] * (255-b) / 255;
03029 filter[1] = filter[1] * (255-b) / 255;
03030 filter[2] = filter[2] * (255-b) / 255;
03031 }
03032 else {
03033 VectorClear(total);
03034 numsamples = 0;
03035 radius = 2;
03036 for ( u = -radius; u <= radius; u++ )
03037 {
03038 x = is + u;
03039 if ( x < 0 || x >= test->shader->width)
03040 continue;
03041 for ( v = -radius; v <= radius; v++ )
03042 {
03043 y = it + v;
03044 if ( y < 0 || y >= test->shader->height)
03045 continue;
03046
03047 image = test->shader->pixels + 4 * ( y * test->shader->width + x );
03048 color[0] = image[0];
03049 color[1] = image[1];
03050 color[2] = image[2];
03051 largest = 0;
03052 for (j = 0; j < 3; j++)
03053 if (image[j] > largest)
03054 largest = image[j];
03055 if (largest <= 0 || image[3] == 0) {
03056 color[0] = 255;
03057 color[1] = 255;
03058 color[2] = 255;
03059 largest = 255;
03060 }
03061 total[0] += ((float) color[0]/largest) * (255-image[3]) / 255.0;
03062 total[1] += ((float) color[1]/largest) * (255-image[3]) / 255.0;
03063 total[2] += ((float) color[2]/largest) * (255-image[3]) / 255.0;
03064 numsamples++;
03065 }
03066 }
03067 ns = numsamples;
03068
03069 filter[0] *= total[0] / ns;
03070 filter[1] *= total[1] / ns;
03071 filter[2] *= total[2] / ns;
03072 }
03073 }
03074 }
03075
03076
03077
03078
03079
03080
03081 void VL_LightSurfaceWithVolume( int surfaceNum, int facetNum, vlight_t *light, lightvolume_t *volume )
03082 {
03083 int i;
03084 dsurface_t *ds;
03085 lFacet_t *facet;
03086 lsurfaceTest_t *test;
03087 winding_t w;
03088 vec3_t base, dir, delta, normal, filter, origin;
03089 int min_x[LIGHTMAP_SIZE+2], max_x[LIGHTMAP_SIZE+2];
03090 int min_y, max_y, k, x, y, n;
03091 float *color, distscale;
03092 float d, add, angle, dist, area, insidearea, coords[MAX_POINTS_ON_WINDING+1][2];
03093 mesh_t *mesh;
03094 byte polygonedges[(LIGHTMAP_SIZE+1) * (LIGHTMAP_SIZE+1) / 8];
03095
03096
03097 ds = &drawSurfaces[surfaceNum];
03098
03099
03100 if ( ds->surfaceType == MST_TRIANGLE_SOUP ) {
03101 return;
03102 }
03103
03104 if ( ds->lightmapNum < 0 ) {
03105 return;
03106 }
03107
03108 test = lsurfaceTest[ surfaceNum ];
03109 facet = &test->facets[ facetNum ];
03110
03111 if (defaulttracelight && !test->always_vlight)
03112 return;
03113 if (test->always_tracelight)
03114 return;
03115
03116 memcpy(w.points, facet->points, sizeof(vec3_t) * facet->numpoints);
03117 w.numpoints = facet->numpoints;
03118
03119 for (i = 0; i < volume->numplanes; i++)
03120 {
03121
03122 if (VL_ChopWinding(&w, &volume->planes[i], 0.01) == SIDE_BACK)
03123 return;
03124 }
03125
03126
03127 MutexLock(test->mutex);
03128
03129 test->numvolumes++;
03130
03131 if (ds->surfaceType == MST_PATCH)
03132 {
03133
03134 min_y = ds->lightmapY + facet->y;
03135 max_y = ds->lightmapY + facet->y + facet->height - 1;
03136 for (y = min_y; y <= max_y; y++)
03137 {
03138 min_x[y] = ds->lightmapX + facet->x;
03139 max_x[y] = ds->lightmapX + facet->x + facet->width - 1;
03140 for (x = min_x[y]; x <= max_x[y]; x++)
03141 {
03142 n = y * LIGHTMAP_SIZE + x;
03143 polygonedges[n >> 3] |= 1 << (n & 7);
03144 }
03145 }
03146 }
03147 else
03148 {
03149 for (i = 0; i < w.numpoints; i++)
03150 {
03151 float s, t;
03152
03153 if (i >= MAX_POINTS_ON_WINDING)
03154 _printf("coords overflow\n");
03155 if (ds->surfaceType != MST_PATCH)
03156 {
03157 VectorSubtract(w.points[i], facet->mins, delta);
03158 s = DotProduct( delta, facet->lightmapMatrix[0] ) + ds->lightmapX + 0.5;
03159 t = DotProduct( delta, facet->lightmapMatrix[1] ) + ds->lightmapY + 0.5;
03160 if (s >= LIGHTMAP_SIZE)
03161 s = LIGHTMAP_SIZE - 0.5;
03162 if (s < 0)
03163 s = 0;
03164 if (t >= LIGHTMAP_SIZE)
03165 t = LIGHTMAP_SIZE - 0.5;
03166 if (t < 0)
03167 t = 0;
03168 coords[i][0] = s;
03169 coords[i][1] = t;
03170 }
03171 else
03172 {
03173 s = DotProduct( w.points[i], facet->lightmapMatrix[0] ) + facet->lightmapMatrix[0][3];
03174 t = DotProduct( w.points[i], facet->lightmapMatrix[1] ) + facet->lightmapMatrix[1][3];
03175
03176 s = s - floor( s );
03177 t = t - floor( t );
03178
03179 coords[i][0] = ds->lightmapX + s * LIGHTMAP_SIZE;
03180 coords[i][1] = ds->lightmapY + t * LIGHTMAP_SIZE;
03181
03182 if (coords[i][0] >= LIGHTMAP_SIZE)
03183 coords[i][0] -= LIGHTMAP_SIZE;
03184 if (coords[i][1] >= LIGHTMAP_SIZE)
03185 coords[i][1] -= LIGHTMAP_SIZE;
03186 if (coords[i][0] < ds->lightmapX)
03187 coords[i][0] = ds->lightmapX;
03188 if (coords[i][1] < ds->lightmapY)
03189 coords[i][1] = ds->lightmapY;
03190 }
03191 x = coords[i][0];
03192 y = coords[i][1];
03193 if (x < ds->lightmapX || x >= LIGHTMAP_SIZE)
03194 _printf("VL_LightSurfaceWithVolume: x outside lightmap\n");
03195 if (y < ds->lightmapY || y >= LIGHTMAP_SIZE)
03196 _printf("VL_LightSurfaceWithVolume: y outside lightmap\n");
03197 }
03198 coords[i][0] = coords[0][0];
03199 coords[i][1] = coords[0][1];
03200
03201
03202 min_y = LIGHTMAP_SIZE;
03203 max_y = 0;
03204 for (i = 0; i < LIGHTMAP_SIZE; i++)
03205 {
03206 min_x[i] = LIGHTMAP_SIZE;
03207 max_x[i] = 0;
03208 }
03209 memset(polygonedges, 0, sizeof(polygonedges));
03210
03211
03212
03213
03214
03215
03216
03217 for (i = 0; i < w.numpoints; i++)
03218 {
03219 float xf, yf, dx, dy, xstep, ystep, xfrac, yfrac;
03220 int xinc, yinc;
03221
03222 xf = coords[i][0];
03223 yf = coords[i][1];
03224 dx = coords[i+1][0] - xf;
03225 dy = coords[i+1][1] - yf;
03226
03227 x = (int) xf;
03228 y = (int) yf;
03229
03230 if (y < min_y)
03231 min_y = y;
03232 if (y > max_y)
03233 max_y = y;
03234
03235 if (fabs(dx) > fabs(dy))
03236 {
03237 if (dx > 0)
03238 {
03239
03240 yfrac = yf + (floor(xf) - xf) * dy / dx;
03241 xinc = 1;
03242 }
03243 else if (dx < 0)
03244 {
03245
03246 yfrac = yf + (floor(xf) + 1 - xf) * dy / dx;
03247 xinc = -1;
03248 }
03249 else
03250 {
03251 yfrac = yf;
03252 xinc = 0;
03253 }
03254
03255 if (dx)
03256 ystep = dy / fabs(dx);
03257 else
03258 ystep = 0;
03259 while(1)
03260 {
03261 if (x < ds->lightmapX || x >= LIGHTMAP_SIZE)
03262 _printf("VL_LightSurfaceWithVolume: x outside lightmap\n");
03263 if (y < ds->lightmapY || y >= LIGHTMAP_SIZE)
03264 _printf("VL_LightSurfaceWithVolume: y outside lightmap\n");
03265
03266 n = y * LIGHTMAP_SIZE + x;
03267 polygonedges[n >> 3] |= 1 << (n & 7);
03268 if (x < min_x[y])
03269 min_x[y] = x;
03270 if (x > max_x[y])
03271 max_x[y] = x;
03272 if (x == (int) coords[i+1][0])
03273 break;
03274 yfrac += ystep;
03275 if (dy > 0)
03276 {
03277 if (yfrac > (float) y + 1)
03278 {
03279 y += 1;
03280
03281 n = y * LIGHTMAP_SIZE + x;
03282 polygonedges[n >> 3] |= 1 << (n & 7);
03283 if (x < min_x[y])
03284 min_x[y] = x;
03285 if (x > max_x[y])
03286 max_x[y] = x;
03287 }
03288 }
03289 else
03290 {
03291 if (yfrac < (float) y)
03292 {
03293 y -= 1;
03294
03295 n = y * LIGHTMAP_SIZE + x;
03296 polygonedges[n >> 3] |= 1 << (n & 7);
03297 if (x < min_x[y])
03298 min_x[y] = x;
03299 if (x > max_x[y])
03300 max_x[y] = x;
03301 }
03302 }
03303 x += xinc;
03304 }
03305 }
03306 else
03307 {
03308 if (dy > 0)
03309 {
03310
03311 xfrac = xf + (floor(yf) - yf) * dx / dy;
03312 yinc = 1;
03313 }
03314 else if (dy < 0)
03315 {
03316
03317 xfrac = xf + (floor(yf) + 1 - yf) * dx / dy;
03318 yinc = -1;
03319 }
03320 else
03321 {
03322 xfrac = xf;
03323 yinc = 0;
03324 }
03325
03326 if (dy)
03327 xstep = dx / fabs(dy);
03328 else
03329 xstep = 0;
03330 while(1)
03331 {
03332 if (x < ds->lightmapX || x >= LIGHTMAP_SIZE)
03333 _printf("VL_LightSurfaceWithVolume: x outside lightmap\n");
03334 if (y < ds->lightmapY || y >= LIGHTMAP_SIZE)
03335 _printf("VL_LightSurfaceWithVolume: y outside lightmap\n");
03336
03337 n = y * LIGHTMAP_SIZE + x;
03338 polygonedges[n >> 3] |= 1 << (n & 7);
03339 if (x < min_x[y])
03340 min_x[y] = x;
03341 if (x > max_x[y])
03342 max_x[y] = x;
03343 if (y == (int) coords[i+1][1])
03344 break;
03345 xfrac += xstep;
03346 if (dx > 0)
03347 {
03348 if (xfrac > (float) x + 1)
03349 {
03350 x += 1;
03351
03352 n = y * LIGHTMAP_SIZE + x;
03353 polygonedges[n >> 3] |= 1 << (n & 7);
03354 if (x < min_x[y])
03355 min_x[y] = x;
03356 if (x > max_x[y])
03357 max_x[y] = x;
03358 }
03359 }
03360 else
03361 {
03362 if (xfrac < (float) x)
03363 {
03364 x -= 1;
03365
03366 n = y * LIGHTMAP_SIZE + x;
03367 polygonedges[n >> 3] |= 1 << (n & 7);
03368 if (x < min_x[y])
03369 min_x[y] = x;
03370 if (x > max_x[y])
03371 max_x[y] = x;
03372 }
03373 }
03374 y += yinc;
03375 }
03376 }
03377 }
03378 }
03379
03380 for (y = min_y; y <= max_y; y++)
03381 {
03382 for (x = min_x[y]; x <= max_x[y]; x++)
03383 {
03384 if (ds->surfaceType == MST_PATCH)
03385 {
03386 mesh = test->detailMesh;
03387 VectorCopy( mesh->verts[(y-ds->lightmapY)*mesh->width+x-ds->lightmapX].xyz, base);
03388 VectorCopy( mesh->verts[(y-ds->lightmapY)*mesh->width+x-ds->lightmapX].normal, normal);
03389
03390 }
03391 else
03392 {
03393 VectorMA(ds->lightmapOrigin, (float) x - ds->lightmapX, ds->lightmapVecs[0], base);
03394 VectorMA(base, (float) y - ds->lightmapY, ds->lightmapVecs[1], base);
03395 VectorCopy(facet->plane.normal, normal);
03396 }
03397 if (light->type == LIGHT_POINTSPOT)
03398 {
03399 float distByNormal;
03400 vec3_t pointAtDist;
03401 float radiusAtDist;
03402 float sampleRadius;
03403 vec3_t distToSample;
03404 float coneScale;
03405
03406 VectorSubtract( light->origin, base, dir );
03407
03408 distByNormal = -DotProduct( dir, light->normal );
03409 if ( distByNormal < 0 ) {
03410 continue;
03411 }
03412 VectorMA( light->origin, distByNormal, light->normal, pointAtDist );
03413 radiusAtDist = light->radiusByDist * distByNormal;
03414
03415 VectorSubtract( base, pointAtDist, distToSample );
03416 sampleRadius = VectorLength( distToSample );
03417
03418 if ( sampleRadius >= radiusAtDist ) {
03419 continue;
03420 }
03421 if ( sampleRadius <= radiusAtDist - 32 ) {
03422 coneScale = 1.0;
03423 } else {
03424 coneScale = ( radiusAtDist - sampleRadius ) / 32.0;
03425 }
03426
03427 dist = VectorNormalize( dir, dir );
03428
03429 if ( dist < 16 ) {
03430 dist = 16;
03431 }
03432 angle = DotProduct( normal, dir );
03433 if (angle > 1)
03434 angle = 1;
03435 if (angle > 0) {
03436 if ( light->atten_angletype == LAAT_QUADRATIC ) {
03437 angle = 1 - angle;
03438 angle *= angle;
03439 angle = 1 - angle;
03440 }
03441 else if ( light->atten_angletype == LAAT_DOUBLEQUADRATIC ) {
03442 angle = 1 - angle;
03443 angle *= angle * angle;
03444 angle = 1 - angle;
03445 }
03446 }
03447 if (light->atten_anglescale > 0) {
03448 angle /= light->atten_anglescale;
03449 if (angle > 1)
03450 angle = 1;
03451 }
03452 if (light->atten_distscale > 0) {
03453 distscale = light->atten_distscale;
03454 }
03455 else {
03456 distscale = 1;
03457 }
03458
03459 if ( light->atten_disttype == LDAT_NOSCALE ) {
03460 add = angle * coneScale;
03461 }
03462 else if ( light->atten_disttype == LDAT_LINEAR ) {
03463 add = angle * light->photons * lightLinearScale * coneScale - dist * distscale;
03464 if ( add < 0 ) {
03465 add = 0;
03466 }
03467 }
03468 else {
03469 add = light->photons / ( dist * dist * distscale) * angle * coneScale;
03470 }
03471 if (add <= 1.0)
03472 continue;
03473 }
03474 else if (light->type == LIGHT_POINTFAKESURFACE)
03475 {
03476
03477 add = PointToPolygonFormFactor( base, normal, &light->w );
03478 if ( add <= 0 ) {
03479 if ( light->twosided ) {
03480 add = -add;
03481 } else {
03482 continue;
03483 }
03484 }
03485 }
03486 else if (light->type == LIGHT_SURFACEDIRECTED)
03487 {
03488
03489
03490
03491 d = DotProduct(base, light->normal) - DotProduct(light->normal, light->w.points[0]);
03492 VectorMA(base, -d, light->normal, origin);
03493 VectorSubtract(origin, base, dir);
03494 dist = VectorNormalize(dir, dir);
03495 if ( dist < 16 ) {
03496 dist = 16;
03497 }
03498
03499 angle = DotProduct( normal, dir );
03500 if (angle > 1)
03501 angle = 1;
03502 if (angle > 0) {
03503 if ( light->atten_angletype == LAAT_QUADRATIC ) {
03504 angle = 1 - angle;
03505 angle *= angle;
03506 angle = 1 - angle;
03507 }
03508 else if ( light->atten_angletype == LAAT_DOUBLEQUADRATIC ) {
03509 angle = 1 - angle;
03510 angle *= angle * angle;
03511 angle = 1 - angle;
03512 }
03513 }
03514 if (light->atten_anglescale > 0) {
03515 angle /= light->atten_anglescale;
03516 if (angle > 1)
03517 angle = 1;
03518 }
03519 if (light->atten_distscale > 0) {
03520 distscale = light->atten_distscale;
03521 }
03522 else {
03523 distscale = 1;
03524 }
03525 if ( light->atten_disttype == LDAT_NOSCALE ) {
03526 add = angle;
03527 }
03528 else if ( light->atten_disttype == LDAT_LINEAR ) {
03529 add = angle * light->photons * lightLinearScale - dist * distscale;
03530 if ( add < 0 ) {
03531 add = 0;
03532 }
03533 } else {
03534 add = light->photons / ( dist * dist * distscale) * angle;
03535 }
03536 if (add <= 0)
03537 continue;
03538 }
03539 else
03540 {
03541 VectorSubtract(light->origin, base, dir);
03542 dist = VectorNormalize(dir, dir);
03543 if ( dist < 16 ) {
03544 dist = 16;
03545 }
03546 angle = DotProduct( normal, dir );
03547 if (angle > 1)
03548 angle = 1;
03549 if (angle > 0) {
03550 if ( light->atten_angletype == LAAT_QUADRATIC ) {
03551 angle = 1 - angle;
03552 angle *= angle;
03553 angle = 1 - angle;
03554 }
03555 else if ( light->atten_angletype == LAAT_DOUBLEQUADRATIC ) {
03556 angle = 1 - angle;
03557 angle *= angle * angle;
03558 angle = 1 - angle;
03559 }
03560 }
03561 if (light->atten_anglescale > 0) {
03562 angle /= light->atten_anglescale;
03563 if (angle > 1)
03564 angle = 1;
03565 }
03566 if (light->atten_distscale > 0) {
03567 distscale = light->atten_distscale;
03568 }
03569 else {
03570 distscale = 1;
03571 }
03572 if ( light->atten_disttype == LDAT_NOSCALE ) {
03573 add = angle;
03574 }
03575 else if ( light->atten_disttype == LDAT_LINEAR ) {
03576 add = angle * light->photons * lightLinearScale - dist * distscale;
03577 if ( add < 0 ) {
03578 add = 0;
03579 }
03580 } else {
03581 add = light->photons / ( dist * dist * distscale) * angle;
03582 }
03583 if (add <= 1.0)
03584 continue;
03585 }
03586
03587 k = (ds->lightmapNum * LIGHTMAP_HEIGHT + y) * LIGHTMAP_WIDTH + x;
03588
03589 n = y * LIGHTMAP_SIZE + x;
03590 if ((polygonedges[n >> 3] & (1 << (n & 7)) ))
03591 {
03592
03593
03594
03595 if (ds->surfaceType == MST_PATCH)
03596 {
03597 mesh = test->detailMesh;
03598 if (y-ds->lightmapY >= mesh->height-1)
03599 _printf("y outside mesh\n");
03600 if (x-ds->lightmapX >= mesh->width-1)
03601 _printf("x outside mesh\n");
03602 VectorCopy( mesh->verts[(y-ds->lightmapY)*mesh->width+x-ds->lightmapX].xyz, w.points[0]);
03603 VectorCopy( mesh->verts[(y+1-ds->lightmapY)*mesh->width+x-ds->lightmapX].xyz, w.points[1]);
03604 VectorCopy( mesh->verts[(y+1-ds->lightmapY)*mesh->width+x+1-ds->lightmapX].xyz, w.points[2]);
03605 VectorCopy( mesh->verts[(y-ds->lightmapY)*mesh->width+x+1-ds->lightmapX].xyz, w.points[3]);
03606 w.numpoints = 4;
03607 }
03608 else
03609 {
03610 VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT - ds->lightmapX, ds->lightmapVecs[0], w.points[0]);
03611 VectorMA(w.points[0], (float) y - LIGHTMAP_PIXELSHIFT - ds->lightmapY, ds->lightmapVecs[1], w.points[0]);
03612 VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT - ds->lightmapX, ds->lightmapVecs[0], w.points[1]);
03613 VectorMA(w.points[1], (float) y - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapY, ds->lightmapVecs[1], w.points[1]);
03614 VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapX, ds->lightmapVecs[0], w.points[2]);
03615 VectorMA(w.points[2], (float) y - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapY, ds->lightmapVecs[1], w.points[2]);
03616 VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT + 1 - ds->lightmapX, ds->lightmapVecs[0], w.points[3]);
03617 VectorMA(w.points[3], (float) y - LIGHTMAP_PIXELSHIFT - ds->lightmapY, ds->lightmapVecs[1], w.points[3]);
03618 w.numpoints = 4;
03619 }
03620
03621
03622
03623
03624 area = lightmappixelarea[k];
03625 if (area <= 0)
03626 continue;
03627
03628 for (i = 0; i < volume->numplanes; i++)
03629 {
03630
03631 if (VL_ChopWinding(&w, &volume->planes[i], 0) == SIDE_BACK)
03632 break;
03633 }
03634
03635 if (i >= volume->numplanes)
03636 {
03637 insidearea = WindingArea(&w);
03638 if (insidearea <= 0)
03639 i = 0;
03640 add = add * insidearea / area;
03641 }
03642 else
03643 {
03644
03645 continue;
03646 }
03647 }
03648
03649 VL_GetFilter(light, volume, base, filter);
03650
03651 color = &lightFloats[k*3];
03652 color[0] += add * light->color[0] * filter[0];
03653 color[1] += add * light->color[1] * filter[1];
03654 color[2] += add * light->color[2] * filter[2];
03655 }
03656 }
03657
03658 MutexUnlock(test->mutex);
03659 }
03660
03661 #endif
03662
03663
03664
03665
03666
03667
03668 int VL_SplitLightVolume(lightvolume_t *volume, lightvolume_t *back, plane_t *split, float epsilon)
03669 {
03670 lightvolume_t f, b;
03671 vec_t dists[128];
03672 int sides[128];
03673 int counts[3];
03674 vec_t dot;
03675 int i, j;
03676 vec_t *p1, *p2;
03677 vec3_t mid;
03678
03679 counts[0] = counts[1] = counts[2] = 0;
03680
03681
03682 for (i = 0; i < volume->numplanes; i++)
03683 {
03684 dot = DotProduct (volume->points[i], split->normal);
03685 dot -= split->dist;
03686 dists[i] = dot;
03687 if (dot > epsilon)
03688 sides[i] = SIDE_FRONT;
03689 else if (dot < -epsilon)
03690 sides[i] = SIDE_BACK;
03691 else
03692 {
03693 sides[i] = SIDE_ON;
03694 }
03695 counts[sides[i]]++;
03696 }
03697
03698 if (!counts[1])
03699 return 0;
03700
03701 if (!counts[0])
03702 return 1;
03703
03704 sides[i] = sides[0];
03705 dists[i] = dists[0];
03706
03707 f.numplanes = 0;
03708 b.numplanes = 0;
03709
03710 for (i = 0; i < volume->numplanes; i++)
03711 {
03712 p1 = volume->points[i];
03713
03714 if (f.numplanes >= MAX_POINTS_ON_FIXED_WINDING)
03715 {
03716 _printf("WARNING: VL_SplitLightVolume -> MAX_POINTS_ON_FIXED_WINDING overflowed\n");
03717 return 0;
03718 }
03719 if (b.numplanes >= MAX_POINTS_ON_FIXED_WINDING)
03720 {
03721 _printf("WARNING: VL_SplitLightVolume -> MAX_POINTS_ON_FIXED_WINDING overflowed\n");
03722 return 0;
03723 }
03724
03725 if (sides[i] == SIDE_ON)
03726 {
03727 VectorCopy(p1, f.points[f.numplanes]);
03728 VectorCopy(p1, b.points[b.numplanes]);
03729 if (sides[i+1] == SIDE_BACK)
03730 {
03731 f.planes[f.numplanes] = *split;
03732 b.planes[b.numplanes] = volume->planes[i];
03733 }
03734 else if (sides[i+1] == SIDE_FRONT)
03735 {
03736 f.planes[f.numplanes] = volume->planes[i];
03737 b.planes[b.numplanes] = *split;
03738 VectorInverse(b.planes[b.numplanes].normal);
03739 b.planes[b.numplanes].dist = -b.planes[b.numplanes].dist;
03740 }
03741 else
03742 {
03743 f.planes[f.numplanes] = *split;
03744 b.planes[b.numplanes] = *split;
03745 VectorInverse(b.planes[b.numplanes].normal);
03746 b.planes[b.numplanes].dist = -b.planes[b.numplanes].dist;
03747 }
03748 f.numplanes++;
03749 b.numplanes++;
03750 continue;
03751 }
03752
03753 if (sides[i] == SIDE_FRONT)
03754 {
03755 VectorCopy (p1, f.points[f.numplanes]);
03756 f.planes[f.numplanes] = volume->planes[i];
03757 f.numplanes++;
03758 }
03759 if (sides[i] == SIDE_BACK)
03760 {
03761 VectorCopy (p1, b.points[b.numplanes]);
03762 b.planes[b.numplanes] = volume->planes[i];
03763 b.numplanes++;
03764 }
03765
03766 if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
03767 continue;
03768
03769 if (f.numplanes >= MAX_POINTS_ON_FIXED_WINDING)
03770 {
03771 _printf("WARNING: VL_SplitLightVolume -> MAX_POINTS_ON_FIXED_WINDING overflowed\n");
03772 return 0;
03773 }
03774 if (b.numplanes >= MAX_POINTS_ON_FIXED_WINDING)
03775 {
03776 _printf("WARNING: VL_SplitLightVolume -> MAX_POINTS_ON_FIXED_WINDING overflowed\n");
03777 return 0;
03778 }
03779
03780
03781 p2 = volume->points[(i+1)%volume->numplanes];
03782
03783 dot = dists[i] / (dists[i]-dists[i+1]);
03784 for (j=0 ; j<3 ; j++)
03785 {
03786 if (split->normal[j] == 1)
03787 mid[j] = split->dist;
03788 else if (split->normal[j] == -1)
03789 mid[j] = -split->dist;
03790 else
03791 mid[j] = p1[j] + dot*(p2[j]-p1[j]);
03792 }
03793
03794 VectorCopy (mid, f.points[f.numplanes]);
03795 VectorCopy(mid, b.points[b.numplanes]);
03796 if (sides[i+1] == SIDE_BACK)
03797 {
03798 f.planes[f.numplanes] = *split;
03799 b.planes[b.numplanes] = volume->planes[i];
03800 }
03801 else
03802 {
03803 f.planes[f.numplanes] = volume->planes[i];
03804 b.planes[b.numplanes] = *split;
03805 VectorInverse(b.planes[b.numplanes].normal);
03806 b.planes[b.numplanes].dist = -b.planes[b.numplanes].dist;
03807 }
03808 f.numplanes++;
03809 b.numplanes++;
03810 }
03811 memcpy(volume->points, f.points, sizeof(vec3_t) * f.numplanes);
03812 memcpy(volume->planes, f.planes, sizeof(plane_t) * f.numplanes);
03813 volume->numplanes = f.numplanes;
03814 memcpy(back->points, b.points, sizeof(vec3_t) * b.numplanes);
03815 memcpy(back->planes, b.planes, sizeof(plane_t) * b.numplanes);
03816 back->numplanes = b.numplanes;
03817
03818 return 2;
03819 }
03820
03821
03822
03823
03824
03825
03826 void VL_PlaneForEdgeToWinding(vec3_t p1, vec3_t p2, winding_t *w, int windingonfront, plane_t *plane)
03827 {
03828 int i, j;
03829 float length, d;
03830 vec3_t v1, v2;
03831
03832 VectorSubtract(p2, p1, v1);
03833 for (i = 0; i < w->numpoints; i++)
03834 {
03835 VectorSubtract (w->points[i], p1, v2);
03836
03837 plane->normal[0] = v1[1]*v2[2] - v1[2]*v2[1];
03838 plane->normal[1] = v1[2]*v2[0] - v1[0]*v2[2];
03839 plane->normal[2] = v1[0]*v2[1] - v1[1]*v2[0];
03840
03841
03842 length = plane->normal[0] * plane->normal[0]
03843 + plane->normal[1] * plane->normal[1]
03844 + plane->normal[2] * plane->normal[2];
03845
03846 if (length < ON_EPSILON)
03847 continue;
03848
03849 length = 1/sqrt(length);
03850
03851 plane->normal[0] *= length;
03852 plane->normal[1] *= length;
03853 plane->normal[2] *= length;
03854
03855 plane->dist = DotProduct (w->points[i], plane->normal);
03856
03857 for (j = 0; j < w->numpoints; j++)
03858 {
03859 if (j == i)
03860 continue;
03861 d = DotProduct(w->points[j], plane->normal) - plane->dist;
03862 if (windingonfront)
03863 {
03864 if (d < -ON_EPSILON)
03865 break;
03866 }
03867 else
03868 {
03869 if (d > ON_EPSILON)
03870 break;
03871 }
03872 }
03873 if (j >= w->numpoints)
03874 return;
03875 }
03876 }
03877
03878
03879
03880
03881
03882
03883 void VL_R_FloodLight(vlight_t *light, lightvolume_t *volume, int cluster, int firstportal);
03884
03885 void VL_R_CastLightAtSurface(vlight_t *light, lightvolume_t *volume)
03886 {
03887 lsurfaceTest_t *test;
03888 int i, n;
03889
03890
03891 VL_LightSurfaceWithVolume(volume->surfaceNum, volume->facetNum, light, volume);
03892
03893 test = lsurfaceTest[ volume->surfaceNum ];
03894
03895 if ( !(test->shader->surfaceFlags & SURF_ALPHASHADOW) && !(test->shader->contents & CONTENTS_TRANSLUCENT))
03896 return;
03897
03898 if (volume->numtransFacets >= MAX_TRANSLUCENTFACETS)
03899 Error("a light valume went through more than %d translucent facets", MAX_TRANSLUCENTFACETS);
03900
03901 volume->transSurfaces[volume->numtransFacets] = volume->surfaceNum;
03902 volume->transFacets[volume->numtransFacets] = volume->facetNum;
03903 volume->numtransFacets++;
03904
03905 memset(volume->facetTested, 0, sizeof(volume->facetTested));
03906 for (i = 0; i < volume->numtransFacets; i++)
03907 {
03908 test = lsurfaceTest[ volume->transSurfaces[i] ];
03909 n = test->facets[volume->transFacets[i]].num;
03910 volume->facetTested[n >> 3] |= 1 << (n & 7);
03911 }
03912 memset(volume->clusterTested, 0, sizeof(volume->clusterTested));
03913 volume->endplane = volume->farplane;
03914 volume->surfaceNum = -1;
03915 volume->facetNum = 0;
03916 VL_R_FloodLight(light, volume, volume->cluster, 0);
03917 if (volume->surfaceNum >= 0)
03918 {
03919 VL_R_CastLightAtSurface(light, volume);
03920 }
03921 }
03922
03923
03924
03925
03926
03927
03928 int numvolumes = 0;
03929
03930 int VL_R_SplitLightVolume(vlight_t *light, lightvolume_t *volume, plane_t *split, int cluster, int firstportal)
03931 {
03932 lightvolume_t back;
03933 int res;
03934
03935
03936 res = VL_SplitLightVolume(volume, &back, split, 0.1);
03937
03938 if (res == 2)
03939 {
03940 memcpy(back.clusterTested, volume->clusterTested, sizeof(back.clusterTested));
03941 memcpy(back.facetTested, volume->facetTested, sizeof(back.facetTested));
03942 back.num = numvolumes++;
03943 back.endplane = volume->endplane;
03944 back.surfaceNum = volume->surfaceNum;
03945 back.facetNum = volume->facetNum;
03946 back.type = volume->type;
03947 back.cluster = volume->cluster;
03948 back.farplane = volume->farplane;
03949 if (volume->numtransFacets > 0)
03950 {
03951 memcpy(back.transFacets, volume->transFacets, sizeof(back.transFacets));
03952 memcpy(back.transSurfaces, volume->transSurfaces, sizeof(back.transSurfaces));
03953 }
03954 back.numtransFacets = volume->numtransFacets;
03955
03956
03957 VL_R_FloodLight(light, &back, cluster, firstportal);
03958
03959 if (back.surfaceNum >= 0)
03960 {
03961 VL_R_CastLightAtSurface(light, &back);
03962 }
03963 }
03964 return res;
03965 }
03966
03967
03968
03969
03970
03971
03972 void VL_R_FloodLight(vlight_t *light, lightvolume_t *volume, int cluster, int firstportal)
03973 {
03974 int i, j, k, res, surfaceNum, backfaceculled, testculled;
03975 float d;
03976 winding_t winding, tmpwinding;
03977 lleaf_t *leaf;
03978 lportal_t *p;
03979 lsurfaceTest_t *test;
03980 lFacet_t *facet;
03981 vec3_t dir1, dir2;
03982 plane_t plane;
03983
03984
03985
03986
03987
03988 if (firstportal == 0)
03989 {
03990
03991 for (i = 0; i < leafs[cluster].numSurfaces; i++)
03992 {
03993 surfaceNum = clustersurfaces[leafs[cluster].firstSurface + i];
03994
03995 test = lsurfaceTest[ surfaceNum ];
03996 if ( !test )
03997 continue;
03998
03999 testculled = qfalse;
04000
04001 for (j = 0; j < test->numFacets; j++)
04002 {
04003
04004 facet = &test->facets[j];
04005
04006
04007
04008
04009
04010
04011 if ( volume->facetTested[facet->num >> 3] & (1 << (facet->num & 7)) )
04012 continue;
04013 volume->facetTested[facet->num >> 3] |= 1 << (facet->num & 7);
04014
04015 backfaceculled = qfalse;
04016 if (!test->patch && !test->trisoup)
04017 {
04018 if (volume->type == VOLUME_NORMAL)
04019 {
04020
04021 d = DotProduct(light->origin, facet->plane.normal) - facet->plane.dist;
04022 if (d < 0)
04023 {
04024
04025
04026
04027
04028
04029
04030
04031
04032
04033
04034
04035
04036
04037
04038 backfaceculled = qtrue;
04039 }
04040 }
04041 else
04042 {
04043
04044
04045 }
04046 }
04047 else
04048 {
04049 if (volume->type == VOLUME_NORMAL)
04050 {
04051
04052 d = DotProduct(light->origin, facet->plane.normal) - facet->plane.dist;
04053 if (d < 0)
04054 backfaceculled = qtrue;
04055 }
04056 else
04057 {
04058
04059
04060 }
04061 }
04062
04063
04064
04065
04066
04067
04068
04069
04070
04071
04072
04073
04074
04075 if (backfaceculled)
04076 {
04077
04078 if ( !nobackfaceculling && !test->shader->twoSided )
04079 continue;
04080
04081 for (k = 0; k < facet->numpoints; k++)
04082 VectorCopy(facet->points[k], winding.points[facet->numpoints - k - 1]);
04083 winding.numpoints = facet->numpoints;
04084 }
04085 else
04086 {
04087 memcpy(winding.points, facet->points, sizeof(vec3_t) * facet->numpoints);
04088 winding.numpoints = facet->numpoints;
04089 }
04090
04091 if (!testculled)
04092 {
04093 testculled = qtrue;
04094
04095 d = DotProduct(volume->endplane.normal, test->origin) - volume->endplane.dist;
04096 if (d < -test->radius)
04097 {
04098 for (k = 0; k < test->numFacets; k++)
04099 {
04100 facet = &test->facets[k];
04101 volume->facetTested[facet->num >> 3] |= 1 << (facet->num & 7);
04102 }
04103 break;
04104 }
04105 for (k = 0; k < volume->numplanes; k++)
04106 {
04107 d = DotProduct(volume->planes[k].normal, test->origin) - volume->planes[k].dist;
04108 if (d < - test->radius)
04109 {
04110 for (k = 0; k < test->numFacets; k++)
04111 {
04112 facet = &test->facets[k];
04113 volume->facetTested[facet->num >> 3] |= 1 << (facet->num & 7);
04114 }
04115 break;
04116 }
04117 }
04118 if (k < volume->numplanes)
04119 break;
04120 }
04121
04122
04123 res = VL_ChopWinding(&winding, &volume->endplane, 0.01);
04124
04125 if (res == SIDE_BACK || res == SIDE_ON)
04126 continue;
04127
04128 memcpy(&tmpwinding, &winding, sizeof(winding_t));
04129 for (k = 0; k < volume->numplanes; k++)
04130 {
04131 res = VL_ChopWinding(&tmpwinding, &volume->planes[k], 0.01);
04132 if (res == SIDE_BACK || res == SIDE_ON)
04133 break;
04134 }
04135
04136 if (k < volume->numplanes)
04137 continue;
04138
04139 for (k = 0; k < winding.numpoints; k++)
04140 {
04141 if (volume->type == VOLUME_DIRECTED)
04142 {
04143 VectorSubtract(winding.points[(k+1) % winding.numpoints], winding.points[k], dir1);
04144 CrossProduct(light->normal, dir1, plane.normal);
04145 VectorNormalize(plane.normal, plane.normal);
04146 plane.dist = DotProduct(plane.normal, winding.points[k]);
04147 }
04148 else
04149 {
04150 VectorSubtract(winding.points[(k+1) % winding.numpoints], winding.points[k], dir1);
04151 VectorSubtract(light->origin, winding.points[k], dir2);
04152 CrossProduct(dir1, dir2, plane.normal);
04153 VectorNormalize(plane.normal, plane.normal);
04154 plane.dist = DotProduct(plane.normal, winding.points[k]);
04155 }
04156 res = VL_R_SplitLightVolume(light, volume, &plane, cluster, 0);
04157 if (res == 1)
04158 break;
04159 }
04160 if (k >= winding.numpoints)
04161 {
04162 volume->endplane = facet->plane;
04163 if (backfaceculled)
04164 {
04165 VectorInverse(volume->endplane.normal);
04166 volume->endplane.dist = -volume->endplane.dist;
04167 }
04168 volume->surfaceNum = surfaceNum;
04169 volume->facetNum = j;
04170 }
04171 }
04172 }
04173 }
04174
04175 volume->clusterTested[cluster >> 3] |= 1 << (cluster & 7);
04176
04177 leaf = &leafs[cluster];
04178 for (i = firstportal; i < leaf->numportals; i++)
04179 {
04180 p = leaf->portals[i];
04181
04182
04183
04184
04185 if ( volume->clusterTested[p->leaf >> 3] & (1 << (p->leaf & 7)) )
04186 continue;
04187
04188 if (volume->type == VOLUME_NORMAL)
04189 {
04190
04191 d = DotProduct(light->origin, p->plane.normal) - p->plane.dist;
04192 if (d > 0)
04193 continue;
04194 }
04195 else
04196 {
04197
04198
04199 }
04200
04201
04202 d = DotProduct(volume->endplane.normal, p->origin) - volume->endplane.dist;
04203 if (d < -p->radius)
04204 continue;
04205 for (j = 0; j < p->winding->numpoints; j++)
04206 {
04207 d = DotProduct(volume->endplane.normal, p->winding->points[j]) - volume->endplane.dist;
04208 if (d > -0.01)
04209 break;
04210 }
04211
04212 if (j >= p->winding->numpoints)
04213 continue;
04214
04215 d = DotProduct(p->plane.normal, light->origin) - p->plane.dist;
04216
04217 if (volume->type != VOLUME_NORMAL || fabs(d) > 0.1)
04218 {
04219
04220 memcpy(&winding, p->winding, sizeof(winding_t));
04221 for (j = 0; j < volume->numplanes; j++)
04222 {
04223 res = VL_ChopWinding(&winding, &volume->planes[j], 0.01);
04224 if (res == SIDE_BACK || res == SIDE_ON)
04225 break;
04226 }
04227
04228 if (j < volume->numplanes)
04229 continue;
04230 }
04231
04232 for (k = 0; k < p->winding->numpoints; k++)
04233 {
04234 if (volume->type == VOLUME_DIRECTED)
04235 {
04236 VectorSubtract(p->winding->points[(k+1) % p->winding->numpoints], p->winding->points[k], dir1);
04237 CrossProduct(light->normal, dir1, plane.normal);
04238 VectorNormalize(plane.normal, plane.normal);
04239 plane.dist = DotProduct(plane.normal, p->winding->points[k]);
04240 }
04241 else
04242 {
04243 VectorSubtract(p->winding->points[(k+1) % p->winding->numpoints], p->winding->points[k], dir1);
04244 VectorSubtract(light->origin, p->winding->points[k], dir2);
04245 CrossProduct(dir1, dir2, plane.normal);
04246 VectorNormalize(plane.normal, plane.normal);
04247 plane.dist = DotProduct(plane.normal, p->winding->points[k]);
04248 }
04249 res = VL_R_SplitLightVolume(light, volume, &plane, cluster, i+1);
04250 if (res == 1)
04251 break;
04252 }
04253
04254 if (k >= p->winding->numpoints)
04255 {
04256
04257 VL_R_FloodLight(light, volume, p->leaf, 0);
04258 }
04259 }
04260 }
04261
04262
04263
04264
04265
04266
04267 void VL_FloodAreaSpotLight(vlight_t *light, winding_t *w, int leafnum)
04268 {
04269 }
04270
04271
04272
04273
04274
04275
04276 void VL_R_SubdivideAreaSpotLight(vlight_t *light, int nodenum, winding_t *w)
04277 {
04278 int leafnum, res;
04279 dnode_t *node;
04280 dplane_t *plane;
04281 winding_t back;
04282 plane_t split;
04283
04284 while(nodenum >= 0)
04285 {
04286 node = &dnodes[nodenum];
04287 plane = &dplanes[node->planeNum];
04288
04289 VectorCopy(plane->normal, split.normal);
04290 split.dist = plane->dist;
04291 res = VL_SplitWinding (w, &back, &split, 0.1);
04292
04293 if (res == SIDE_FRONT)
04294 {
04295 nodenum = node->children[0];
04296 }
04297 else if (res == SIDE_BACK)
04298 {
04299 nodenum = node->children[1];
04300 }
04301 else if (res == SIDE_ON)
04302 {
04303 memcpy(&back, w, sizeof(winding_t));
04304 VL_R_SubdivideAreaSpotLight(light, node->children[1], &back);
04305 nodenum = node->children[0];
04306 }
04307 else
04308 {
04309 VL_R_SubdivideAreaSpotLight(light, node->children[1], &back);
04310 nodenum = node->children[0];
04311 }
04312 }
04313 leafnum = -nodenum - 1;
04314 if (dleafs[leafnum].cluster != -1)
04315 {
04316 VL_FloodAreaSpotLight(light, w, leafnum);
04317 }
04318 }
04319
04320
04321
04322
04323
04324
04325 void VL_FloodRadialAreaLight(vlight_t *light, winding_t *w, int leafnum)
04326 {
04327 }
04328
04329
04330
04331
04332
04333
04334 void VL_R_SubdivideRadialAreaLight(vlight_t *light, int nodenum, winding_t *w)
04335 {
04336 int leafnum, res;
04337 dnode_t *node;
04338 dplane_t *plane;
04339 winding_t back;
04340 plane_t split;
04341
04342 while(nodenum >= 0)
04343 {
04344 node = &dnodes[nodenum];
04345 plane = &dplanes[node->planeNum];
04346
04347 VectorCopy(plane->normal, split.normal);
04348 split.dist = plane->dist;
04349 res = VL_SplitWinding (w, &back, &split, 0.1);
04350
04351 if (res == SIDE_FRONT)
04352 {
04353 nodenum = node->children[0];
04354 }
04355 else if (res == SIDE_BACK)
04356 {
04357 nodenum = node->children[1];
04358 }
04359 else if (res == SIDE_ON)
04360 {
04361 memcpy(&back, w, sizeof(winding_t));
04362 VL_R_SubdivideRadialAreaLight(light, node->children[1], &back);
04363 nodenum = node->children[0];
04364 }
04365 else
04366 {
04367 VL_R_SubdivideRadialAreaLight(light, node->children[1], &back);
04368 nodenum = node->children[0];
04369 }
04370 }
04371 leafnum = -nodenum - 1;
04372 if (dleafs[leafnum].cluster != -1)
04373 {
04374 VL_FloodRadialAreaLight(light, w, leafnum);
04375 }
04376 }
04377
04378
04379
04380
04381
04382
04383 void VL_FloodDirectedLight(vlight_t *light, winding_t *w, int leafnum)
04384 {
04385 int i;
04386 float dist;
04387 lightvolume_t volume;
04388 vec3_t dir;
04389
04390 if (light->atten_disttype == LDAT_NOSCALE)
04391 {
04392
04393 dist = MAX_WORLD_COORD;
04394 }
04395 else
04396 {
04397 if ( light->atten_disttype == LDAT_LINEAR )
04398 dist = light->photons * lightLinearScale;
04399 else
04400 dist = sqrt(light->photons);
04401 }
04402
04403 memset(&volume, 0, sizeof(lightvolume_t));
04404 for (i = 0; i < w->numpoints; i++)
04405 {
04406 VectorMA(w->points[i], dist, light->normal, volume.points[i]);
04407 VectorSubtract(w->points[(i+1)%w->numpoints], w->points[i], dir);
04408 CrossProduct(light->normal, dir, volume.planes[i].normal);
04409 VectorNormalize(volume.planes[i].normal, volume.planes[i].normal);
04410 volume.planes[i].dist = DotProduct(volume.planes[i].normal, w->points[i]);
04411 }
04412 volume.numplanes = w->numpoints;
04413 VectorCopy(light->normal, volume.endplane.normal);
04414 VectorInverse(volume.endplane.normal);
04415 volume.endplane.dist = DotProduct(volume.endplane.normal, volume.points[0]);
04416 volume.farplane = volume.endplane;
04417 volume.surfaceNum = -1;
04418 volume.type = VOLUME_DIRECTED;
04419 volume.cluster = dleafs[leafnum].cluster;
04420 VL_R_FloodLight(light, &volume, volume.cluster, 0);
04421 if (volume.surfaceNum >= 0)
04422 {
04423 VL_R_CastLightAtSurface(light, &volume);
04424 }
04425 }
04426
04427
04428
04429
04430
04431
04432 void VL_R_SubdivideDirectedAreaLight(vlight_t *light, int nodenum, winding_t *w)
04433 {
04434 int leafnum, res;
04435 dnode_t *node;
04436 dplane_t *plane;
04437 winding_t back;
04438 plane_t split;
04439
04440 while(nodenum >= 0)
04441 {
04442 node = &dnodes[nodenum];
04443 plane = &dplanes[node->planeNum];
04444
04445 VectorCopy(plane->normal, split.normal);
04446 split.dist = plane->dist;
04447 res = VL_SplitWinding (w, &back, &split, 0.1);
04448
04449 if (res == SIDE_FRONT)
04450 {
04451 nodenum = node->children[0];
04452 }
04453 else if (res == SIDE_BACK)
04454 {
04455 nodenum = node->children[1];
04456 }
04457 else if (res == SIDE_ON)
04458 {
04459 memcpy(&back, w, sizeof(winding_t));
04460 VL_R_SubdivideDirectedAreaLight(light, node->children[1], &back);
04461 nodenum = node->children[0];
04462 }
04463 else
04464 {
04465 VL_R_SubdivideDirectedAreaLight(light, node->children[1], &back);
04466 nodenum = node->children[0];
04467 }
04468 }
04469 leafnum = -nodenum - 1;
04470 if (dleafs[leafnum].cluster != -1)
04471 {
04472 VL_FloodDirectedLight(light, w, leafnum);
04473 }
04474 }
04475
04476
04477
04478
04479
04480
04481 void VL_FloodLight(vlight_t *light)
04482 {
04483 lightvolume_t volume;
04484 dleaf_t *leaf;
04485 int leafnum, i, j, k, dir[2][4] = {{1, 1, -1, -1}, {1, -1, -1, 1}};
04486 float a, step, dist, radius, windingdist;
04487 vec3_t vec, r, p, temp;
04488 winding_t winding;
04489
04490 switch(light->type)
04491 {
04492 case LIGHT_POINTRADIAL:
04493 {
04494
04495
04496
04497
04498
04499
04500
04501 if ( light->atten_disttype == LDAT_LINEAR )
04502 dist = light->photons * lightLinearScale;
04503 else
04504 dist = sqrt(light->photons);
04505
04506 windingdist = MAX_WORLD_COORD;
04507 if (dist > windingdist)
04508 windingdist = dist;
04509
04510 leafnum = VL_LightLeafnum(light->origin);
04511 leaf = &dleafs[leafnum];
04512 if (leaf->cluster == -1)
04513 {
04514 light->insolid = qtrue;
04515 break;
04516 }
04517
04518 for (i = 0; i < 3; i++)
04519 {
04520
04521 for (j = -1; j <= 1; j += 2)
04522 {
04523 memset(&volume, 0, sizeof(lightvolume_t));
04524 volume.numplanes = 0;
04525 for (k = 0; k < 4; k ++)
04526 {
04527 volume.points[volume.numplanes][i] = light->origin[i] + j * windingdist;
04528 volume.points[volume.numplanes][(i+1)%3] = light->origin[(i+1)%3] + dir[0][k] * windingdist;
04529 volume.points[volume.numplanes][(i+2)%3] = light->origin[(i+2)%3] + dir[1][k] * windingdist;
04530 volume.numplanes++;
04531 }
04532 if (j >= 0)
04533 {
04534 VectorCopy(volume.points[0], temp);
04535 VectorCopy(volume.points[2], volume.points[0]);
04536 VectorCopy(temp, volume.points[2]);
04537 }
04538 for (k = 0; k < volume.numplanes; k++)
04539 {
04540 VL_PlaneFromPoints(&volume.planes[k], light->origin, volume.points[(k+1)%volume.numplanes], volume.points[k]);
04541 }
04542 VectorCopy(light->origin, temp);
04543 temp[i] += (float) j * dist;
04544 VectorClear(volume.endplane.normal);
04545 volume.endplane.normal[i] = -j;
04546 volume.endplane.dist = DotProduct(volume.endplane.normal, temp);
04547 volume.farplane = volume.endplane;
04548 volume.cluster = leaf->cluster;
04549 volume.surfaceNum = -1;
04550 volume.type = VOLUME_NORMAL;
04551
04552 memset(volume.facetTested, 0, sizeof(volume.facetTested));
04553 memset(volume.clusterTested, 0, sizeof(volume.clusterTested));
04554 VL_R_FloodLight(light, &volume, leaf->cluster, 0);
04555 if (volume.surfaceNum >= 0)
04556 {
04557 VL_R_CastLightAtSurface(light, &volume);
04558 }
04559 }
04560 }
04561 break;
04562 }
04563 case LIGHT_POINTSPOT:
04564 {
04565
04566
04567
04568
04569
04570
04571 if ( light->atten_disttype == LDAT_LINEAR )
04572 dist = light->photons * lightLinearScale;
04573 else
04574 dist = sqrt(light->photons);
04575 dist *= 2;
04576
04577 windingdist = 4096;
04578 if (dist > windingdist)
04579 windingdist = dist;
04580
04581 radius = 8 * windingdist * light->radiusByDist;
04582
04583 memset(&volume, 0, sizeof(lightvolume_t));
04584 leafnum = VL_LightLeafnum(light->origin);
04585 leaf = &dleafs[leafnum];
04586 if (leaf->cluster == -1)
04587 {
04588 light->insolid = qtrue;
04589 break;
04590 }
04591
04592 VectorClear(vec);
04593 for (i = 0; i < 3; i++)
04594 {
04595 if (light->normal[i] > -0.9 && light->normal[i] < 0.9)
04596 {
04597 vec[i] = 1;
04598 break;
04599 }
04600 }
04601 CrossProduct(light->normal, vec, r);
04602 VectorScale(r, radius, p);
04603 volume.numplanes = 0;
04604 step = 45;
04605 for (a = step / 2; a < 360 + step / 2; a += step)
04606 {
04607 RotatePointAroundVector(volume.points[volume.numplanes], light->normal, p, a);
04608 VectorAdd(light->origin, volume.points[volume.numplanes], volume.points[volume.numplanes]);
04609 VectorMA(volume.points[volume.numplanes], windingdist, light->normal, volume.points[volume.numplanes]);
04610 volume.numplanes++;
04611 }
04612 for (i = 0; i < volume.numplanes; i++)
04613 {
04614 VL_PlaneFromPoints(&volume.planes[i], light->origin, volume.points[(i+1)%volume.numplanes], volume.points[i]);
04615 }
04616 VectorMA(light->origin, dist, light->normal, temp);
04617 VectorCopy(light->normal, volume.endplane.normal);
04618 VectorInverse(volume.endplane.normal);
04619 volume.endplane.dist = DotProduct(volume.endplane.normal, temp);
04620 volume.farplane = volume.endplane;
04621 volume.cluster = leaf->cluster;
04622 volume.surfaceNum = -1;
04623 volume.type = VOLUME_NORMAL;
04624
04625 memset(volume.facetTested, 0, sizeof(volume.facetTested));
04626 memset(volume.clusterTested, 0, sizeof(volume.clusterTested));
04627 VL_R_FloodLight(light, &volume, leaf->cluster, 0);
04628 if (volume.surfaceNum >= 0)
04629 {
04630 VL_R_CastLightAtSurface(light, &volume);
04631 }
04632 break;
04633 }
04634 case LIGHT_POINTFAKESURFACE:
04635 {
04636 float value;
04637 int n, axis;
04638 vec3_t v, vecs[2];
04639
04640 if ( light->atten_disttype == LDAT_LINEAR )
04641 dist = light->photons * lightLinearScale;
04642 else
04643 dist = sqrt(light->photons);
04644
04645 windingdist = 4096;
04646 if (dist > windingdist)
04647 windingdist = dist;
04648
04649 VectorMA(light->origin, 0.1, light->normal, light->origin);
04650
04651 leafnum = VL_LightLeafnum(light->origin);
04652 leaf = &dleafs[leafnum];
04653 if (leaf->cluster == -1)
04654 {
04655 light->insolid = qtrue;
04656 break;
04657 }
04658 value = 0;
04659 for (i = 0; i < 3; i++)
04660 {
04661 if (fabs(light->normal[i]) > value)
04662 {
04663 value = fabs(light->normal[i]);
04664 axis = i;
04665 }
04666 }
04667 for (i = 0; i < 2; i++)
04668 {
04669 VectorClear(v);
04670 v[(axis + 1 + i) % 3] = 1;
04671 CrossProduct(light->normal, v, vecs[i]);
04672 }
04673
04674 for (i = -1; i <= 1; i += 2)
04675 {
04676 for (j = -1; j <= 1; j += 2)
04677 {
04678 for (n = 0; n < 2; n++)
04679 {
04680 memset(&volume, 0, sizeof(lightvolume_t));
04681 volume.numplanes = 3;
04682 VectorMA(light->origin, i * windingdist, vecs[0], volume.points[(i == j) == n]);
04683 VectorMA(light->origin, j * windingdist, vecs[1], volume.points[(i != j) == n]);
04684 VectorMA(light->origin, windingdist, light->normal, volume.points[2]);
04685 for (k = 0; k < volume.numplanes; k++)
04686 {
04687 VL_PlaneFromPoints(&volume.planes[k], light->origin, volume.points[(k+1)%volume.numplanes], volume.points[k]);
04688 }
04689 VL_PlaneFromPoints(&volume.endplane, volume.points[0], volume.points[1], volume.points[2]);
04690 VectorMA(light->origin, dist, light->normal, temp);
04691 volume.endplane.dist = DotProduct(volume.endplane.normal, temp);
04692 if (DotProduct(light->origin, volume.endplane.normal) - volume.endplane.dist > 0)
04693 break;
04694 }
04695 volume.farplane = volume.endplane;
04696 volume.cluster = leaf->cluster;
04697 volume.surfaceNum = -1;
04698 volume.type = VOLUME_NORMAL;
04699
04700 memset(volume.facetTested, 0, sizeof(volume.facetTested));
04701 memset(volume.clusterTested, 0, sizeof(volume.clusterTested));
04702
04703 VL_R_FloodLight(light, &volume, leaf->cluster, 0);
04704 if (volume.surfaceNum >= 0)
04705 {
04706 VL_R_CastLightAtSurface(light, &volume);
04707 }
04708 }
04709 }
04710 break;
04711 }
04712 case LIGHT_SURFACEDIRECTED:
04713 {
04714
04715
04716
04717
04718
04719 memcpy(&winding, &light->w, sizeof(winding_t));
04720 VL_R_SubdivideDirectedAreaLight(light, 0, &winding);
04721 break;
04722 }
04723 case LIGHT_SURFACERADIAL:
04724 {
04725
04726
04727
04728 memcpy(&winding, &light->w, sizeof(winding_t));
04729 VL_R_SubdivideRadialAreaLight(light, 0, &winding);
04730 break;
04731 }
04732 case LIGHT_SURFACESPOT:
04733 {
04734
04735
04736
04737 memcpy(&winding, &light->w, sizeof(winding_t));
04738 VL_R_SubdivideAreaSpotLight(light, 0, &winding);
04739 break;
04740 }
04741 }
04742 }
04743
04744
04745
04746
04747
04748
04749 void VL_FloodLightThread(int num)
04750 {
04751 VL_FloodLight(vlights[num]);
04752 }
04753
04754
04755
04756
04757
04758
04759 void VL_TestLightLeafs(void)
04760 {
04761 int leafnum, i;
04762 vlight_t *light;
04763 dleaf_t *leaf;
04764
04765 for (i = 0; i < numvlights; i++)
04766 {
04767 light = vlights[i];
04768 if (light->type != LIGHT_POINTRADIAL &&
04769 light->type != LIGHT_POINTSPOT)
04770 continue;
04771 leafnum = VL_LightLeafnum(light->origin);
04772 leaf = &dleafs[leafnum];
04773 if (leaf->cluster == -1)
04774 if (light->type == LIGHT_POINTRADIAL)
04775 qprintf("light in solid at %1.1f %1.1f %1.1f\n", light->origin[0], light->origin[1], light->origin[2]);
04776 else if (light->type == LIGHT_POINTSPOT)
04777 qprintf("spot light in solid at %1.1f %1.1f %1.1f\n", light->origin[0], light->origin[1], light->origin[2]);
04778 }
04779 }
04780
04781
04782
04783
04784
04785
04786
04787
04788 void TraceLtm( int num );
04789
04790 void VL_DoForcedTraceLight(int num)
04791 {
04792 dsurface_t *ds;
04793 shaderInfo_t *si;
04794
04795 ds = &drawSurfaces[num];
04796
04797 if ( ds->surfaceType == MST_TRIANGLE_SOUP )
04798 return;
04799
04800 if ( ds->lightmapNum < 0 )
04801 return;
04802
04803
04804 if ( !entitySurface[num] )
04805 {
04806 si = ShaderInfoForShader( dshaders[ ds->shaderNum].shader );
04807
04808 if (defaulttracelight)
04809 {
04810 if (si->forceVLight)
04811 return;
04812 }
04813 else
04814 {
04815 if (!si->forceTraceLight)
04816 return;
04817 }
04818 }
04819
04820 TraceLtm(num);
04821 }
04822
04823
04824
04825
04826
04827
04828 void VL_DoForcedTraceLightSurfaces(void)
04829 {
04830 _printf( "forced trace light\n" );
04831 RunThreadsOnIndividual( numDrawSurfaces, qtrue, VL_DoForcedTraceLight );
04832 }
04833
04834 float *oldLightFloats;
04835
04836
04837
04838
04839
04840
04841 void VL_SurfaceRadiosity( int num ) {
04842 dsurface_t *ds;
04843 mesh_t *mesh;
04844 shaderInfo_t *si;
04845 lsurfaceTest_t *test;
04846 int x, y, k;
04847 vec3_t base, normal;
04848 float *color, area;
04849 vlight_t vlight;
04850
04851 ds = &drawSurfaces[num];
04852
04853 if ( ds->lightmapNum < 0 ) {
04854 return;
04855 }
04856
04857
04858 if ( ds->surfaceType == MST_TRIANGLE_SOUP ) {
04859 return;
04860 }
04861
04862 si = ShaderInfoForShader( dshaders[ ds->shaderNum].shader );
04863 test = lsurfaceTest[ num ];
04864
04865 if (!test) {
04866 return;
04867 }
04868
04869 for (x = 0; x < ds->lightmapWidth; x++) {
04870 for (y = 0; y < ds->lightmapHeight; y++) {
04871
04872 k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y)
04873 * LIGHTMAP_WIDTH + ds->lightmapX + x;
04874 area = lightmappixelarea[k];
04875 if (area <= 0)
04876 continue;
04877
04878 if (ds->surfaceType == MST_PATCH)
04879 {
04880 mesh = test->detailMesh;
04881 VectorCopy( mesh->verts[y*mesh->width+x].xyz, base);
04882 VectorCopy( mesh->verts[y*mesh->width+x].normal, normal);
04883 }
04884 else
04885 {
04886 VectorMA(ds->lightmapOrigin, (float) x, ds->lightmapVecs[0], base);
04887 VectorMA(base, (float) y, ds->lightmapVecs[1], base);
04888 VectorCopy(test->facets[0].plane.normal, normal);
04889 }
04890
04891 memset(&vlight, 0, sizeof(vlight_t));
04892 color = &oldLightFloats[k*3];
04893
04894 VectorMA(base, 5, normal, vlight.origin);
04895 ColorNormalize(color, vlight.color);
04896
04897 vlight.photons = VectorLength(color) * 0.05 * lightPointScale / (area * radiosity_scale);
04898
04899 vlight.type = LIGHT_POINTRADIAL;
04900
04901 VL_FloodLight(&vlight);
04902
04903 MutexLock(test->mutex);
04904
04905 lightFloats[k*3] = oldLightFloats[k*3];
04906 lightFloats[k*3+1] = oldLightFloats[k*3+1];
04907 lightFloats[k*3+2] = oldLightFloats[k*3+2];
04908
04909 MutexUnlock(test->mutex);
04910 }
04911 }
04912 }
04913
04914
04915
04916
04917
04918
04919
04920
04921 void VL_Radiosity(void) {
04922
04923 oldLightFloats = lightFloats;
04924 lightFloats = (float *) malloc(numLightBytes * sizeof(float));
04925 memcpy(lightFloats, oldLightFloats, numLightBytes * sizeof(float));
04926 _printf("%7i surfaces\n", numDrawSurfaces);
04927 RunThreadsOnIndividual( numDrawSurfaces, qtrue, VL_SurfaceRadiosity );
04928 free(oldLightFloats);
04929 }
04930
04931
04932
04933
04934
04935
04936 void VL_LightWorld(void)
04937 {
04938 int i, numcastedvolumes, numvlightsinsolid;
04939 float f;
04940
04941
04942 GetVectorForKey( &entities[0], "_color", lightAmbientColor );
04943 f = FloatForKey( &entities[0], "ambient" );
04944 VectorScale( lightAmbientColor, f, lightAmbientColor );
04945
04946
04947
04948
04949
04950
04951
04952
04953
04954 _printf("%7i lights\n", numvlights);
04955 RunThreadsOnIndividual( numvlights, qtrue, VL_FloodLightThread );
04956
04957 numcastedvolumes = 0;
04958 for ( i = 0 ; i < numDrawSurfaces ; i++ ) {
04959 if (lsurfaceTest[i])
04960 numcastedvolumes += lsurfaceTest[i]->numvolumes;
04961 }
04962 _printf("%7i light volumes casted\n", numcastedvolumes);
04963 numvlightsinsolid = 0;
04964 for (i = 0; i < numvlights; i++)
04965 {
04966 if (vlights[i]->insolid)
04967 numvlightsinsolid++;
04968 }
04969 _printf("%7i lights in solid\n", numvlightsinsolid);
04970
04971 radiosity_scale = 1;
04972 for (i = 0; i < radiosity; i++) {
04973 VL_Radiosity();
04974 radiosity_scale <<= 1;
04975 }
04976
04977 VL_StoreLightmap();
04978
04979 VL_DoForcedTraceLightSurfaces();
04980 }
04981
04982
04983
04984
04985
04986
04987 entity_t *FindTargetEntity( const char *target );
04988
04989 void VL_CreateEntityLights (void)
04990 {
04991 int i, c_entityLights;
04992 vlight_t *dl;
04993 entity_t *e, *e2;
04994 const char *name;
04995 const char *target;
04996 vec3_t dest;
04997 const char *_color;
04998 float intensity;
04999 int spawnflags;
05000
05001
05002 c_entityLights = 0;
05003 _printf("Creating entity lights...\n");
05004
05005 for ( i = 0 ; i < num_entities ; i++ ) {
05006 e = &entities[i];
05007 name = ValueForKey (e, "classname");
05008 if (strncmp (name, "light", 5))
05009 continue;
05010
05011 dl = malloc(sizeof(*dl));
05012 memset (dl, 0, sizeof(*dl));
05013
05014 spawnflags = FloatForKey (e, "spawnflags");
05015 if ( spawnflags & 1 ) {
05016 dl->atten_disttype = LDAT_LINEAR;
05017 }
05018 if ( spawnflags & 2 ) {
05019 dl->atten_disttype = LDAT_NOSCALE;
05020 }
05021 if ( spawnflags & 4 ) {
05022 dl->atten_angletype = LAAT_QUADRATIC;
05023 }
05024 if ( spawnflags & 8 ) {
05025 dl->atten_angletype = LAAT_DOUBLEQUADRATIC;
05026 }
05027
05028 dl->atten_distscale = FloatForKey(e, "atten_distscale");
05029 dl->atten_anglescale = FloatForKey(e, "atten_anglescale");
05030
05031 GetVectorForKey (e, "origin", dl->origin);
05032 dl->style = FloatForKey (e, "_style");
05033 if (!dl->style)
05034 dl->style = FloatForKey (e, "style");
05035 if (dl->style < 0)
05036 dl->style = 0;
05037
05038 intensity = FloatForKey (e, "light");
05039 if (!intensity)
05040 intensity = FloatForKey (e, "_light");
05041 if (!intensity)
05042 intensity = 300;
05043 _color = ValueForKey (e, "_color");
05044 if (_color && _color[0])
05045 {
05046 sscanf (_color, "%f %f %f", &dl->color[0],&dl->color[1],&dl->color[2]);
05047 ColorNormalize (dl->color, dl->color);
05048 }
05049 else
05050 dl->color[0] = dl->color[1] = dl->color[2] = 1.0;
05051
05052 intensity = intensity * lightPointScale;
05053 dl->photons = intensity;
05054
05055 dl->type = LIGHT_POINTRADIAL;
05056
05057
05058 target = ValueForKey (e, "target");
05059
05060 if ( target[0] ) {
05061 float radius;
05062 float dist;
05063
05064 e2 = FindTargetEntity (target);
05065 if (!e2) {
05066 _printf ("WARNING: light at (%i %i %i) has missing target\n",
05067 (int)dl->origin[0], (int)dl->origin[1], (int)dl->origin[2]);
05068 } else {
05069 GetVectorForKey (e2, "origin", dest);
05070 VectorSubtract (dest, dl->origin, dl->normal);
05071 dist = VectorNormalize (dl->normal, dl->normal);
05072 radius = FloatForKey (e, "radius");
05073 if ( !radius ) {
05074 radius = 64;
05075 }
05076 if ( !dist ) {
05077 dist = 64;
05078 }
05079 dl->radiusByDist = (radius + 16) / dist;
05080 dl->type = LIGHT_POINTSPOT;
05081 }
05082 }
05083 vlights[numvlights++] = dl;
05084 c_entityLights++;
05085 }
05086 _printf("%7i entity lights\n", c_entityLights);
05087 }
05088
05089
05090
05091
05092
05093
05094 void VL_SubdivideAreaLight( shaderInfo_t *ls, winding_t *w, vec3_t normal,
05095 float areaSubdivide, qboolean backsplash ) {
05096 float area, value, intensity;
05097 vlight_t *dl, *dl2;
05098 vec3_t mins, maxs;
05099 int axis;
05100 winding_t *front, *back;
05101 vec3_t planeNormal;
05102 float planeDist;
05103
05104 if ( !w ) {
05105 return;
05106 }
05107
05108 WindingBounds( w, mins, maxs );
05109
05110
05111 for ( axis = 0 ; axis < 3 ; axis++ ) {
05112 if ( maxs[axis] - mins[axis] > areaSubdivide ) {
05113 VectorClear( planeNormal );
05114 planeNormal[axis] = 1;
05115 planeDist = ( maxs[axis] + mins[axis] ) * 0.5;
05116 ClipWindingEpsilon ( w, planeNormal, planeDist, ON_EPSILON, &front, &back );
05117 VL_SubdivideAreaLight( ls, front, normal, areaSubdivide, qfalse );
05118 VL_SubdivideAreaLight( ls, back, normal, areaSubdivide, qfalse );
05119 FreeWinding( w );
05120 return;
05121 }
05122 }
05123
05124
05125 area = WindingArea (w);
05126 if ( area <= 0 || area > 20000000 ) {
05127 return;
05128 }
05129
05130 dl = malloc(sizeof(*dl));
05131 memset (dl, 0, sizeof(*dl));
05132 dl->type = LIGHT_POINTFAKESURFACE;
05133
05134 WindingCenter( w, dl->origin );
05135 memcpy(dl->w.points, w->points, sizeof(vec3_t) * w->numpoints);
05136 dl->w.numpoints = w->numpoints;
05137 VectorCopy ( normal, dl->normal);
05138 VectorCopy ( normal, dl->plane);
05139 dl->plane[3] = DotProduct( dl->origin, normal );
05140
05141 value = ls->value;
05142 intensity = value * area * lightAreaScale;
05143 VectorAdd( dl->origin, dl->normal, dl->origin );
05144
05145 VectorCopy( ls->color, dl->color );
05146
05147 dl->photons = intensity;
05148
05149
05150 VectorScale( ls->color, value*lightFormFactorValueScale*lightAreaScale, dl->emitColor );
05151
05152 VectorCopy(dl->emitColor, dl->color);
05153
05154 dl->si = ls;
05155
05156 if ( ls->contents & CONTENTS_FOG ) {
05157 dl->twosided = qtrue;
05158 }
05159
05160 vlights[numvlights++] = dl;
05161
05162
05163 if ( backsplash && ls->backsplashFraction > 0 ) {
05164
05165 dl2 = malloc(sizeof(*dl));
05166 memset (dl2, 0, sizeof(*dl2));
05167 dl2->type = LIGHT_POINTRADIAL;
05168
05169 VectorMA( dl->origin, ls->backsplashDistance, normal, dl2->origin );
05170
05171 VectorCopy( ls->color, dl2->color );
05172
05173 dl2->photons = dl->photons * ls->backsplashFraction;
05174 dl2->si = ls;
05175
05176 vlights[numvlights++] = dl2;
05177 }
05178 }
05179
05180
05181
05182
05183
05184
05185 void VL_CreateFakeSurfaceLights( void ) {
05186 int i, j, side;
05187 dsurface_t *ds;
05188 shaderInfo_t *ls;
05189 winding_t *w;
05190 lFacet_t *f;
05191 vlight_t *dl;
05192 vec3_t origin;
05193 drawVert_t *dv;
05194 int c_surfaceLights;
05195 float lightSubdivide;
05196 vec3_t normal;
05197
05198
05199 c_surfaceLights = 0;
05200 _printf ("Creating surface lights...\n");
05201
05202 for ( i = 0 ; i < numDrawSurfaces ; i++ ) {
05203
05204 ds = &drawSurfaces[i];
05205
05206 ls = ShaderInfoForShader( dshaders[ ds->shaderNum].shader );
05207 if ( ls->value == 0 ) {
05208 continue;
05209 }
05210
05211
05212 if ( ls->lightSubdivide ) {
05213 lightSubdivide = ls->lightSubdivide;
05214 } else {
05215 lightSubdivide = lightDefaultSubdivide;
05216 }
05217
05218 c_surfaceLights++;
05219
05220
05221
05222 if ( ls->autosprite ) {
05223
05224 if ( lsurfaceTest[i] ) {
05225
05226 f = lsurfaceTest[i]->facets;
05227 if ( lsurfaceTest[i]->numFacets != 1 || f->numpoints != 4 ) {
05228 _printf( "WARNING: surface at (%i %i %i) has autosprite shader but isn't a quad\n",
05229 (int)f->points[0], (int)f->points[1], (int)f->points[2] );
05230 }
05231 VectorAdd( f->points[0], f->points[1], origin );
05232 VectorAdd( f->points[2], origin, origin );
05233 VectorAdd( f->points[3], origin, origin );
05234 VectorScale( origin, 0.25, origin );
05235 } else {
05236
05237 dv = &drawVerts[ ds->firstVert ];
05238 if ( ds->numVerts != 4 ) {
05239 _printf( "WARNING: surface at (%i %i %i) has autosprite shader but %i verts\n",
05240 (int)dv->xyz[0], (int)dv->xyz[1], (int)dv->xyz[2] );
05241 continue;
05242 }
05243
05244 VectorAdd( dv[0].xyz, dv[1].xyz, origin );
05245 VectorAdd( dv[2].xyz, origin, origin );
05246 VectorAdd( dv[3].xyz, origin, origin );
05247 VectorScale( origin, 0.25, origin );
05248 }
05249
05250 dl = malloc(sizeof(*dl));
05251 memset (dl, 0, sizeof(*dl));
05252 VectorCopy( origin, dl->origin );
05253 VectorCopy( ls->color, dl->color );
05254 dl->photons = ls->value * lightPointScale;
05255 dl->type = LIGHT_POINTRADIAL;
05256 vlights[numvlights++] = dl;
05257 continue;
05258 }
05259
05260
05261 for ( side = 0 ; side <= ls->twoSided ; side++ ) {
05262
05263 if ( lsurfaceTest[i] ) {
05264
05265 for ( j = 0 ; j < lsurfaceTest[i]->numFacets ; j++ ) {
05266 f = lsurfaceTest[i]->facets + j;
05267 w = AllocWinding( f->numpoints );
05268 w->numpoints = f->numpoints;
05269 memcpy( w->points, f->points, f->numpoints * 12 );
05270
05271 VectorCopy( f->plane.normal, normal );
05272 if ( side ) {
05273 winding_t *t;
05274
05275 t = w;
05276 w = ReverseWinding( t );
05277 FreeWinding( t );
05278 VectorSubtract( vec3_origin, normal, normal );
05279 }
05280 VL_SubdivideAreaLight( ls, w, normal, lightSubdivide, qtrue );
05281 }
05282 } else {
05283
05284
05285 w = AllocWinding( ds->numVerts );
05286 w->numpoints = ds->numVerts;
05287 for ( j = 0 ; j < ds->numVerts ; j++ ) {
05288 VectorCopy( drawVerts[ds->firstVert+j].xyz, w->points[j] );
05289 }
05290 VectorCopy( ds->lightmapVecs[2], normal );
05291 if ( side ) {
05292 winding_t *t;
05293
05294 t = w;
05295 w = ReverseWinding( t );
05296 FreeWinding( t );
05297 VectorSubtract( vec3_origin, normal, normal );
05298 }
05299 VL_SubdivideAreaLight( ls, w, normal, lightSubdivide, qtrue );
05300 }
05301 }
05302 }
05303
05304 _printf( "%7i light emitting surfaces\n", c_surfaceLights );
05305 }
05306
05307
05308
05309
05310
05311
05312
05313 winding_t *VL_WindingForBrushSide(dbrush_t *brush, int side, winding_t *w)
05314 {
05315 int i, res;
05316 winding_t *tmpw;
05317 plane_t plane;
05318
05319 VectorCopy(dplanes[ dbrushsides[ brush->firstSide + side ].planeNum ].normal, plane.normal);
05320 VectorInverse(plane.normal);
05321 plane.dist = -dplanes[ dbrushsides[ brush->firstSide + side ].planeNum ].dist;
05322 tmpw = BaseWindingForPlane( plane.normal, plane.dist );
05323 memcpy(w->points, tmpw->points, sizeof(vec3_t) * tmpw->numpoints);
05324 w->numpoints = tmpw->numpoints;
05325
05326 for (i = 0; i < brush->numSides; i++)
05327 {
05328 if (i == side)
05329 continue;
05330 VectorCopy(dplanes[ dbrushsides[ brush->firstSide + i ].planeNum ].normal, plane.normal);
05331 VectorInverse(plane.normal);
05332 plane.dist = -dplanes[ dbrushsides[ brush->firstSide + i ].planeNum ].dist;
05333 res = VL_ChopWinding(w, &plane, 0.1);
05334 if (res == SIDE_BACK)
05335 return NULL;
05336 }
05337 return w;
05338 }
05339
05340
05341
05342
05343
05344
05345 void VL_CreateSkyLights(void)
05346 {
05347 int i, j, c_skyLights;
05348 dbrush_t *b;
05349 shaderInfo_t *si;
05350 dbrushside_t *s;
05351 vlight_t *dl;
05352 vec3_t sunColor, sunDir = { 0.45, 0.3, 0.9 };
05353 float d;
05354
05355 VectorNormalize(sunDir, sunDir);
05356 VectorInverse(sunDir);
05357
05358 c_skyLights = 0;
05359 _printf("Creating sky lights...\n");
05360
05361 for ( i = 0 ; i < numDrawSurfaces ; i++ ) {
05362 si = ShaderInfoForShader( dshaders[ drawSurfaces[i].shaderNum ].shader );
05363 if ( si->surfaceFlags & SURF_SKY ) {
05364 VectorCopy( si->sunLight, sunColor );
05365 VectorCopy( si->sunDirection, sunDir );
05366 VectorInverse(sunDir);
05367 break;
05368 }
05369 }
05370
05371
05372 for ( i = 0 ; i < numbrushes ; i++ ) {
05373 b = &dbrushes[i];
05374 for ( j = 0 ; j < b->numSides ; j++ ) {
05375 s = &dbrushsides[ b->firstSide + j ];
05376 if ( dshaders[ s->shaderNum ].surfaceFlags & SURF_SKY ) {
05377
05378 d = DotProduct(dplanes[ s->planeNum ].normal, sunDir);
05379 if (d <= 0)
05380 continue;
05381
05382 dl = malloc(sizeof(*dl));
05383 memset (dl, 0, sizeof(*dl));
05384 VectorCopy(sunColor, dl->color);
05385 VectorCopy(sunDir, dl->normal);
05386 VectorCopy(dplanes[ s->planeNum ].normal, dl->plane);
05387 dl->plane[3] = dplanes[ s->planeNum ].dist;
05388 dl->type = LIGHT_SURFACEDIRECTED;
05389 dl->atten_disttype = LDAT_NOSCALE;
05390 VL_WindingForBrushSide(b, j, &dl->w);
05391
05392
05393 vlights[numvlights++] = dl;
05394 c_skyLights++;
05395 }
05396 }
05397 }
05398 _printf("%7i light emitting sky surfaces\n", c_skyLights);
05399 }
05400
05401
05402
05403
05404
05405
05406 void VL_SetPortalSphere (lportal_t *p)
05407 {
05408 int i;
05409 vec3_t total, dist;
05410 winding_t *w;
05411 float r, bestr;
05412
05413 w = p->winding;
05414 VectorCopy (vec3_origin, total);
05415 for (i=0 ; i<w->numpoints ; i++)
05416 {
05417 VectorAdd (total, w->points[i], total);
05418 }
05419
05420 for (i=0 ; i<3 ; i++)
05421 total[i] /= w->numpoints;
05422
05423 bestr = 0;
05424 for (i=0 ; i<w->numpoints ; i++)
05425 {
05426 VectorSubtract (w->points[i], total, dist);
05427 r = VectorLength (dist);
05428 if (r > bestr)
05429 bestr = r;
05430 }
05431 VectorCopy (total, p->origin);
05432 p->radius = bestr;
05433 }
05434
05435
05436
05437
05438
05439
05440 void VL_PlaneFromWinding (winding_t *w, plane_t *plane)
05441 {
05442 vec3_t v1, v2;
05443
05444
05445 VectorSubtract (w->points[2], w->points[1], v1);
05446 VectorSubtract (w->points[0], w->points[1], v2);
05447 CrossProduct (v2, v1, plane->normal);
05448 VectorNormalize (plane->normal, plane->normal);
05449 plane->dist = DotProduct (w->points[0], plane->normal);
05450 }
05451
05452
05453
05454
05455
05456
05457 winding_t *VL_AllocWinding (int points)
05458 {
05459 winding_t *w;
05460 int size;
05461
05462 if (points > MAX_POINTS_ON_WINDING)
05463 Error ("NewWinding: %i points", points);
05464
05465 size = (int)((winding_t *)0)->points[points];
05466 w = malloc (size);
05467 memset (w, 0, size);
05468
05469 return w;
05470 }
05471
05472
05473
05474
05475
05476
05477 void VL_LoadPortals (char *name)
05478 {
05479 int i, j, hint;
05480 lportal_t *p;
05481 lleaf_t *l;
05482 char magic[80];
05483 FILE *f;
05484 int numpoints;
05485 winding_t *w;
05486 int leafnums[2];
05487 plane_t plane;
05488
05489
05490 if (!strcmp(name,"-"))
05491 f = stdin;
05492 else
05493 {
05494 f = fopen(name, "r");
05495 if (!f)
05496 Error ("LoadPortals: couldn't read %s\n",name);
05497 }
05498
05499 if (fscanf (f,"%79s\n%i\n%i\n%i\n",magic, &portalclusters, &numportals, &numfaces) != 4)
05500 Error ("LoadPortals: failed to read header");
05501 if (strcmp(magic, PORTALFILE))
05502 Error ("LoadPortals: not a portal file");
05503
05504 _printf ("%6i portalclusters\n", portalclusters);
05505 _printf ("%6i numportals\n", numportals);
05506 _printf ("%6i numfaces\n", numfaces);
05507
05508 if (portalclusters >= MAX_CLUSTERS)
05509 Error ("more than %d clusters in portal file\n", MAX_CLUSTERS);
05510
05511
05512 portals = malloc(2*numportals*sizeof(lportal_t));
05513 memset (portals, 0, 2*numportals*sizeof(lportal_t));
05514
05515 leafs = malloc(portalclusters*sizeof(lleaf_t));
05516 memset (leafs, 0, portalclusters*sizeof(lleaf_t));
05517
05518 for (i=0, p=portals ; i<numportals ; i++)
05519 {
05520 if (fscanf (f, "%i %i %i ", &numpoints, &leafnums[0], &leafnums[1]) != 3)
05521 Error ("LoadPortals: reading portal %i", i);
05522 if (numpoints > MAX_POINTS_ON_WINDING)
05523 Error ("LoadPortals: portal %i has too many points", i);
05524 if ( (unsigned)leafnums[0] > portalclusters
05525 || (unsigned)leafnums[1] > portalclusters)
05526 Error ("LoadPortals: reading portal %i", i);
05527 if (fscanf (f, "%i ", &hint) != 1)
05528 Error ("LoadPortals: reading hint state");
05529
05530 w = p->winding = VL_AllocWinding (numpoints);
05531 w->numpoints = numpoints;
05532
05533 for (j=0 ; j<numpoints ; j++)
05534 {
05535 double v[3];
05536 int k;
05537
05538
05539
05540 if (fscanf (f, "(%lf %lf %lf ) "
05541 , &v[0], &v[1], &v[2]) != 3)
05542 Error ("LoadPortals: reading portal %i", i);
05543 for (k=0 ; k<3 ; k++)
05544 w->points[j][k] = v[k];
05545 }
05546 fscanf (f, "\n");
05547
05548
05549 VL_PlaneFromWinding (w, &plane);
05550
05551
05552 l = &leafs[leafnums[0]];
05553 if (l->numportals == MAX_PORTALS_ON_LEAF)
05554 Error ("Leaf with too many portals");
05555 l->portals[l->numportals] = p;
05556 l->numportals++;
05557
05558 p->winding = w;
05559 VectorSubtract (vec3_origin, plane.normal, p->plane.normal);
05560 p->plane.dist = -plane.dist;
05561 p->leaf = leafnums[1];
05562 VL_SetPortalSphere (p);
05563 p++;
05564
05565
05566 l = &leafs[leafnums[1]];
05567 if (l->numportals == MAX_PORTALS_ON_LEAF)
05568 Error ("Leaf with too many portals");
05569 l->portals[l->numportals] = p;
05570 l->numportals++;
05571
05572 p->winding = VL_AllocWinding(w->numpoints);
05573 p->winding->numpoints = w->numpoints;
05574 for (j=0 ; j<w->numpoints ; j++)
05575 {
05576 VectorCopy (w->points[w->numpoints-1-j], p->winding->points[j]);
05577 }
05578
05579 p->plane = plane;
05580 p->leaf = leafnums[0];
05581 VL_SetPortalSphere (p);
05582 p++;
05583
05584 }
05585
05586 fclose (f);
05587 }
05588
05589
05590
05591
05592
05593
05594 int VLightMain (int argc, char **argv) {
05595 int i;
05596 double start, end;
05597 const char *value;
05598
05599 _printf ("----- VLighting ----\n");
05600
05601 for (i=1 ; i<argc ; i++) {
05602 if (!strcmp(argv[i],"-v")) {
05603 verbose = qtrue;
05604 } else if (!strcmp(argv[i],"-threads")) {
05605 numthreads = atoi (argv[i+1]);
05606 _printf("num threads = %d\n", numthreads);
05607 i++;
05608 } else if (!strcmp(argv[i],"-area")) {
05609 lightAreaScale *= atof(argv[i+1]);
05610 _printf ("area light scaling at %f\n", lightAreaScale);
05611 i++;
05612 } else if (!strcmp(argv[i],"-point")) {
05613 lightPointScale *= atof(argv[i+1]);
05614 _printf ("point light scaling at %f\n", lightPointScale);
05615 i++;
05616 } else if (!strcmp(argv[i], "-samplesize")) {
05617 samplesize = atoi(argv[i+1]);
05618 if (samplesize < 1) samplesize = 1;
05619 i++;
05620 _printf("lightmap sample size is %dx%d units\n", samplesize, samplesize);
05621 } else if (!strcmp(argv[i], "-novertex")) {
05622 novertexlighting = qtrue;
05623 _printf("no vertex lighting = true\n");
05624 } else if (!strcmp(argv[i], "-nogrid")) {
05625 nogridlighting = qtrue;
05626 _printf("no grid lighting = true\n");
05627 } else if (!strcmp(argv[i], "-nostitching")) {
05628 nostitching = qtrue;
05629 _printf("no stitching = true\n");
05630 } else if (!strcmp(argv[i], "-noalphashading")) {
05631 noalphashading = qtrue;
05632 _printf("no alpha shading = true\n");
05633 } else if (!strcmp(argv[i], "-nocolorshading")) {
05634 nocolorshading = qtrue;
05635 _printf("old style alpha shading = true\n");
05636 } else if (!strcmp(argv[i], "-nobackfaceculling")) {
05637 nobackfaceculling = qtrue;
05638 _printf("no backface culling = true\n");
05639 } else if (!strcmp(argv[i], "-tracelight")) {
05640 defaulttracelight = qtrue;
05641 _printf("default trace light = true\n");
05642 } else if (!strcmp(argv[i], "-radiosity")) {
05643 radiosity = atoi(argv[i+1]);
05644 _printf("radiosity = %d\n", radiosity);
05645 i++;
05646 } else {
05647 break;
05648 }
05649 }
05650
05651 ThreadSetDefault ();
05652
05653 if (i != argc - 1) {
05654 _printf("usage: q3map -vlight [-<switch> [-<switch> ...]] <mapname>\n"
05655 "\n"
05656 "Switches:\n"
05657 " v = verbose output\n"
05658 " threads <X> = set number of threads to X\n"
05659 " area <V> = set the area light scale to V\n"
05660 " point <W> = set the point light scale to W\n"
05661 " novertex = don't calculate vertex lighting\n"
05662 " nogrid = don't calculate light grid for dynamic model lighting\n"
05663 " nostitching = no polygon stitching before lighting\n"
05664 " noalphashading = don't use alpha shading\n"
05665 " nocolorshading = don't use color alpha shading\n"
05666 " tracelight = use old light algorithm by default\n"
05667 " samplesize <N> = set the lightmap pixel size to NxN units\n");
05668 exit(0);
05669 }
05670
05671 SetQdirFromPath (argv[i]);
05672
05673 #ifdef _WIN32
05674 InitPakFile(gamedir, NULL);
05675 #endif
05676
05677 strcpy (source, ExpandArg(argv[i]));
05678 StripExtension (source);
05679 DefaultExtension (source, ".bsp");
05680
05681 LoadShaderInfo();
05682
05683 _printf ("reading %s\n", source);
05684
05685 LoadBSPFile (source);
05686 ParseEntities();
05687
05688 value = ValueForKey( &entities[0], "gridsize" );
05689 if (strlen(value)) {
05690 sscanf( value, "%f %f %f", &gridSize[0], &gridSize[1], &gridSize[2] );
05691 _printf("grid size = {%1.1f, %1.1f, %1.1f}\n", gridSize[0], gridSize[1], gridSize[2]);
05692 }
05693
05694 CountLightmaps();
05695
05696 StripExtension (source);
05697 DefaultExtension (source, ".prt");
05698
05699 VL_LoadPortals(source);
05700
05701
05702 SetEntityOrigins();
05703
05704
05705 GridAndVertexLighting();
05706
05707 #ifdef DEBUGNET
05708 DebugNet_Setup();
05709 #endif
05710
05711 start = clock();
05712
05713 lightFloats = (float *) malloc(numLightBytes * sizeof(float));
05714 memset(lightFloats, 0, numLightBytes * sizeof(float));
05715
05716 VL_InitSurfacesForTesting();
05717
05718 VL_CalcVisibleLightmapPixelArea();
05719
05720 numvlights = 0;
05721 VL_CreateEntityLights();
05722 VL_CreateFakeSurfaceLights();
05723 VL_CreateSkyLights();
05724
05725 VL_TestLightLeafs();
05726
05727 VL_LightWorld();
05728
05729 #ifndef LIGHTPOLYS
05730 StripExtension (source);
05731 DefaultExtension (source, ".bsp");
05732 _printf ("writing %s\n", source);
05733 WriteBSPFile (source);
05734 #endif
05735
05736 end = clock();
05737
05738 _printf ("%5.2f seconds elapsed\n", (end-start) / CLK_TCK);
05739
05740 #ifdef LIGHTPOLYS
05741 VL_DrawLightWindings();
05742 #endif
05743
05744 #ifdef DEBUGNET
05745 DebugNet_Shutdown();
05746 #endif
05747 return 0;
05748 }