📄 lightv.c
字号:
count++;
} else {
if (VL_GenerateFacetFor3Points( dsurf, si, &test->facets[count], v1, v4, v3 )) {
test->facets[count].x = x;
test->facets[count].y = y;
test->facets[count].width = widthtable[i];
test->facets[count].height = heighttable[j];
count++;
}
if (VL_GenerateFacetFor3Points( dsurf, si, &test->facets[count], v1, v3, v2 )) {
test->facets[count].x = x;
test->facets[count].y = y;
test->facets[count].width = widthtable[i];
test->facets[count].height = heighttable[j];
count++;
}
}
y += heighttable[j];
}
x += widthtable[i];
}
test->numFacets = count;
FreeMesh(subdivided);
}
/*
=====================
VL_InitSurfacesForTesting
=====================
*/
void VL_InitSurfacesForTesting( void ) {
int i, j, k;
dsurface_t *dsurf;
lsurfaceTest_t *test;
shaderInfo_t *si;
lFacet_t *facet;
for ( i = 0 ; i < numDrawSurfaces ; i++ ) {
// don't light the entity surfaces with vlight
if ( entitySurface[i] )
continue;
//
dsurf = &drawSurfaces[ i ];
if ( !dsurf->numIndexes && !dsurf->patchWidth ) {
continue;
}
si = ShaderInfoForShader( dshaders[ dsurf->shaderNum].shader );
// if the surface is translucent and does not cast an alpha shadow
if ( (si->contents & CONTENTS_TRANSLUCENT) && !(si->surfaceFlags & SURF_ALPHASHADOW) ) {
// if the surface has no lightmap
if ( dsurf->lightmapNum < 0 )
continue;
}
test = malloc( sizeof( *test ) );
memset(test, 0, sizeof( *test ));
test->mutex = MutexAlloc();
test->numvolumes = 0;
if (si->forceTraceLight)
test->always_tracelight = qtrue;
else if (si->forceVLight)
test->always_vlight = qtrue;
lsurfaceTest[i] = test;
if ( dsurf->surfaceType == MST_TRIANGLE_SOUP || dsurf->surfaceType == MST_PLANAR ) {
VL_FacetsForTriangleSurface( dsurf, si, test );
} else if ( dsurf->surfaceType == MST_PATCH ) {
VL_FacetsForPatch( dsurf, i, si, test );
}
if (numfacets >= MAX_FACETS)
Error("numfacets >= MAX_FACETS (%d)", MAX_FACETS);
ClearBounds( test->mins, test->maxs );
for (j = 0; j < test->numFacets; j++)
{
facet = &test->facets[j];
for ( k = 0 ; k < facet->numpoints; k++) {
AddPointToBounds( facet->points[k], test->mins, test->maxs );
}
}
VL_SphereFromBounds( test->mins, test->maxs, test->origin, &test->radius );
}
_printf("%6d facets\n", numfacets);
_printf("linking surfaces...\n");
VL_LinkSurfaces();
}
/*
=============
VL_ChopWinding
=============
*/
int VL_ChopWinding (winding_t *in, plane_t *split, float epsilon)
{
vec_t dists[128];
int sides[128];
int counts[3];
vec_t dot;
int i, j;
vec_t *p1, *p2;
vec3_t mid;
winding_t out;
winding_t *neww;
counts[0] = counts[1] = counts[2] = 0;
// determine sides for each point
for (i=0 ; i<in->numpoints ; i++)
{
dot = DotProduct (in->points[i], split->normal);
dot -= split->dist;
dists[i] = dot;
if (dot > epsilon)
sides[i] = SIDE_FRONT;
else if (dot < -epsilon)
sides[i] = SIDE_BACK;
else
{
sides[i] = SIDE_ON;
}
counts[sides[i]]++;
}
if (!counts[SIDE_BACK])
{
if (!counts[SIDE_FRONT])
return SIDE_ON;
else
return SIDE_FRONT;
}
if (!counts[SIDE_FRONT])
{
return SIDE_BACK;
}
sides[i] = sides[0];
dists[i] = dists[0];
neww = &out;
neww->numpoints = 0;
for (i=0 ; i<in->numpoints ; i++)
{
p1 = in->points[i];
if (neww->numpoints >= MAX_POINTS_ON_FIXED_WINDING)
{
_printf("WARNING: VL_ChopWinding -> MAX_POINTS_ON_FIXED_WINDING overflowed\n");
return SIDE_FRONT; // can't chop -- fall back to original
}
if (sides[i] == SIDE_ON)
{
VectorCopy (p1, neww->points[neww->numpoints]);
neww->numpoints++;
continue;
}
if (sides[i] == SIDE_FRONT)
{
VectorCopy (p1, neww->points[neww->numpoints]);
neww->numpoints++;
}
if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
continue;
if (neww->numpoints >= MAX_POINTS_ON_FIXED_WINDING)
{
_printf("WARNING: VL_ChopWinding -> MAX_POINTS_ON_FIXED_WINDING overflowed\n");
return SIDE_FRONT; // can't chop -- fall back to original
}
// generate a split point
p2 = in->points[(i+1)%in->numpoints];
dot = dists[i] / (dists[i]-dists[i+1]);
for (j=0 ; j<3 ; j++)
{ // avoid round off error when possible
if (split->normal[j] == 1)
mid[j] = split->dist;
else if (split->normal[j] == -1)
mid[j] = -split->dist;
else
mid[j] = p1[j] + dot*(p2[j]-p1[j]);
}
VectorCopy (mid, neww->points[neww->numpoints]);
neww->numpoints++;
}
memcpy(in, &out, sizeof(winding_t));
return SIDE_CROSS;
}
/*
=============
VL_ChopWindingWithBrush
returns all winding fragments outside the brush
=============
*/
int VL_ChopWindingWithBrush(winding_t *w, dbrush_t *brush, winding_t *outwindings, int maxout)
{
int i, res, numout;
winding_t front, back;
plane_t plane;
numout = 0;
memcpy(front.points, w->points, w->numpoints * sizeof(vec3_t));
front.numpoints = w->numpoints;
for (i = 0; i < brush->numSides; i++)
{
VectorCopy(dplanes[ dbrushsides[ brush->firstSide + i ].planeNum ].normal, plane.normal);
VectorInverse(plane.normal);
plane.dist = -dplanes[ dbrushsides[ brush->firstSide + i ].planeNum ].dist;
res = VL_SplitWinding(&front, &back, &plane, 0.1);
if (res == SIDE_BACK || res == SIDE_ON)
{
memcpy(outwindings[0].points, w->points, w->numpoints * sizeof(vec3_t));
outwindings[0].numpoints = w->numpoints;
return 1; //did not intersect
}
if (res != SIDE_FRONT)
{
if (numout >= maxout)
{
_printf("WARNING: VL_ChopWindingWithBrush: more than %d windings\n", maxout);
return 0;
}
memcpy(outwindings[numout].points, back.points, back.numpoints * sizeof(vec3_t));
outwindings[numout].numpoints = back.numpoints;
numout++;
}
}
return numout;
}
/*
=============
VL_WindingAreaOutsideBrushes
=============
*/
float VL_WindingAreaOutsideBrushes(winding_t *w, int *brushnums, int numbrushes)
{
int i, j, numwindings[2], n;
winding_t windingsbuf[2][64];
dbrush_t *brush;
float area;
memcpy(windingsbuf[0][0].points, w->points, w->numpoints * sizeof(vec3_t));
windingsbuf[0][0].numpoints = w->numpoints;
numwindings[0] = 1;
for (i = 0; i < numbrushes; i++)
{
brush = &dbrushes[brushnums[i]];
if (!(dshaders[brush->shaderNum].contentFlags & (
CONTENTS_LAVA
| CONTENTS_SLIME
| CONTENTS_WATER
| CONTENTS_FOG
| CONTENTS_AREAPORTAL
| CONTENTS_PLAYERCLIP
| CONTENTS_MONSTERCLIP
| CONTENTS_CLUSTERPORTAL
| CONTENTS_DONOTENTER
| CONTENTS_BODY
| CONTENTS_CORPSE
| CONTENTS_TRANSLUCENT
| CONTENTS_TRIGGER
| CONTENTS_NODROP) ) &&
(dshaders[brush->shaderNum].contentFlags & CONTENTS_SOLID) )
{
numwindings[!(i & 1)] = 0;
for (j = 0; j < numwindings[i&1]; j++)
{
n = VL_ChopWindingWithBrush(&windingsbuf[i&1][j], brush,
&windingsbuf[!(i&1)][numwindings[!(i&1)]],
64 - numwindings[!(i&1)]);
numwindings[!(i&1)] += n;
}
if (!numwindings[!(i&1)])
return 0;
}
else
{
for (j = 0; j < numwindings[i&1]; j++)
{
windingsbuf[!(i&1)][j] = windingsbuf[i&1][j];
}
numwindings[!(i&1)] = numwindings[i&1];
}
}
area = 0;
for (j = 0; j < numwindings[i&1]; j++)
{
area += WindingArea(&windingsbuf[i&1][j]);
}
return area;
}
/*
=============
VL_R_WindingAreaOutsideSolid
=============
*/
float VL_R_WindingAreaOutsideSolid(winding_t *w, vec3_t normal, int nodenum)
{
int leafnum, res;
float area;
dnode_t *node;
dleaf_t *leaf;
dplane_t *plane;
winding_t back;
plane_t split;
area = 0;
while(nodenum >= 0)
{
node = &dnodes[nodenum];
plane = &dplanes[node->planeNum];
VectorCopy(plane->normal, split.normal);
split.dist = plane->dist;
res = VL_SplitWinding (w, &back, &split, 0.1);
if (res == SIDE_FRONT)
{
nodenum = node->children[0];
}
else if (res == SIDE_BACK)
{
nodenum = node->children[1];
}
else if (res == SIDE_ON)
{
if (DotProduct(normal, plane->normal) > 0)
nodenum = node->children[0];
else
nodenum = node->children[1];
}
else
{
area += VL_R_WindingAreaOutsideSolid(&back, normal, node->children[1]);
nodenum = node->children[0];
}
}
leafnum = -nodenum - 1;
leaf = &dleafs[leafnum];
if (leaf->cluster != -1)
{
area += VL_WindingAreaOutsideBrushes(w, &dleafbrushes[leaf->firstLeafBrush], leaf->numLeafBrushes);
}
return area;
}
/*
=============
VL_WindingAreaOutsideSolid
=============
*/
float VL_WindingAreaOutsideSolid(winding_t *w, vec3_t normal)
{
return VL_R_WindingAreaOutsideSolid(w, normal, 0);
}
/*
=============
VL_ChopWindingWithFacet
=============
*/
float VL_ChopWindingWithFacet(winding_t *w, lFacet_t *facet)
{
int i;
for (i = 0; i < facet->numpoints; i++)
{
if (VL_ChopWinding(w, &facet->boundaries[i], 0) == SIDE_BACK)
return 0;
}
if (nostitching)
return WindingArea(w);
else
return VL_WindingAreaOutsideSolid(w, facet->plane.normal);
}
/*
=============
VL_CalcVisibleLightmapPixelArea
nice brute force ;)
=============
*/
void VL_CalcVisibleLightmapPixelArea(void)
{
int i, j, x, y, k;
dsurface_t *ds;
lsurfaceTest_t *test;
mesh_t *mesh;
winding_t w, tmpw;
float area;
_printf("calculating visible lightmap pixel area...\n");
for ( i = 0 ; i < numDrawSurfaces ; i++ )
{
test = lsurfaceTest[ i ];
if (!test)
continue;
ds = &drawSurfaces[ i ];
if ( ds->lightmapNum < 0 )
continue;
for (y = 0; y < ds->lightmapHeight; y++)
{
for (x = 0; x < ds->lightmapWidth; x++)
{
if (ds->surfaceType == MST_PATCH)
{
if (y == ds->lightmapHeight-1)
continue;
if (x == ds->lightmapWidth-1)
continue;
mesh = lsurfaceTest[i]->detailMesh;
VectorCopy( mesh->verts[y*mesh->width+x].xyz, w.points[0]);
VectorCopy( mesh->verts[(y+1)*mesh->width+x].xyz, w.points[1]);
VectorCopy( mesh->verts[(y+1)*mesh->width+x+1].xyz, w.points[2]);
VectorCopy( mesh->verts[y*mesh->width+x+1].xyz, w.points[3]);
w.numpoints = 4;
if (nostitching)
area = WindingArea(&w);
else
area = VL_WindingAreaOutsideSolid(&w, mesh->verts[y*mesh->width+x].normal);
}
else
{
VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT, ds->lightmapVecs[0], w.points[0]);
VectorMA(w.points[0], (float) y - LIGHTMAP_PIXELSHIFT, ds->lightmapVecs[1], w.points[0]);
VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT, ds->lightmapVecs[0], w.points[3]);
VectorMA(w.points[3], (float) y - LIGHTMAP_PIXELSHIFT + 1, ds->lightmapVecs[1], w.points[3]);
VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT + 1, ds->lightmapVecs[0], w.points[2]);
VectorMA(w.points[2], (float) y - LIGHTMAP_PIXELSHIFT + 1, ds->lightmapVecs[1], w.points[2]);
VectorMA(ds->lightmapOrigin, (float) x - LIGHTMAP_PIXELSHIFT + 1, ds->lightmapVecs[0], w.points[1]);
VectorMA(w.points[1], (float) y - LIGHTMAP_PIXELSHIFT, ds->lightmapVecs[1], w.points[1]);
w.numpoints = 4;
area = 0;
for (j = 0; j < test->numFacets; j++)
{
memcpy(&tmpw, &w, sizeof(winding_t));
area += VL_ChopWindingWithFacet(&tmpw, &test->facets[j]);
}
}
k = ( ds->lightmapNum * LIGHTMAP_HEIGHT + ds->lightmapY + y)
* LIGHTMAP_WIDTH + ds->lightmapX + x;
lightmappixelarea[k] = area;
}
}
}
}
/*
=============
VL_FindAdjacentSurface
=============
*/
int VL_FindAdjacentSurface(int surfaceNum, int facetNum, vec3_t p1, vec3_t p2, int *sNum, int *fNum, int *point)
{
int i, j, k;
lsurfaceTest_t *test;
lFacet_t *facet;
dsurface_t *ds;
float *fp1, *fp2;
vec3_t dir;
plane_t *facetplane;
// winding_t w;
facetplane = &lsurfaceTest[surfaceNum]->facets[facetNum].plane;
// DebugNet_RemoveAllPolys();
// memcpy(w.points, lsurfaceTest[surfaceNum]->facets[facetNum].points,
// lsurfaceTest[surfaceNum]->facets[facetNum].numpoints * sizeof(vec3_t));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -