📄 soundv.c
字号:
/*****************************************************************************
* name: lightv.c
* programmer: MrElusive
*
* desc: global illumination algorithm using light volumes
*
* problems: intersecting geometry is only lit for the part visible to a
* light, this can cause dark edges where polygons intersect
*
* darkened edges can also appear where flat surfaces meet
* when they are not stitched together nicely
*
* - lightmaps on patches are shifted half a pixel, fix this in lightmap.c
* enable LIGHTMAP_PATCHSHIFT, tho this makes the bsp incompatible for -light
* - lightmap edges are only smoothened across surface edges if the edge
* is parallell to one of the lightmap axis, fix this?
*****************************************************************************/
#include "cmdlib.h"
#include "mathlib.h"
#include "bspfile.h"
#include "imagelib.h"
#include "threads.h"
#include "mutex.h"
#include "scriplib.h"
#include "shaders.h"
#include "mesh.h"
#ifdef _WIN32
//Improve floating-point consistency.
#pragma optimize( "p", on )
#endif
#ifdef _WIN32
#include "../libs/pakstuff.h"
#endif
#define MAX_CLUSTERS 16384
#define MAX_PORTALS 32768
#define MAX_FACETS 65536
#define MAX_LIGHTS 16384
#define LIGHTMAP_SIZE 128
#define LIGHTMAP_PIXELSHIFT 0.5
//#define LIGHTMAP_PATCHSHIFT
#define PORTALFILE "PRT1"
#define ON_EPSILON 0.1
#define VectorSet(v, x, y, z) v[0] = x;v[1] = y;v[2] = z;
typedef struct
{
vec3_t normal;
float dist;
} plane_t;
#define MAX_POINTS_ON_WINDING 64
//NOTE: whenever this is overflowed parts of lightmaps might end up not being lit
#define MAX_POINTS_ON_FIXED_WINDING 48
typedef struct
{
int numpoints;
vec3_t points[MAX_POINTS_ON_FIXED_WINDING]; // variable sized
} winding_t;
typedef struct
{
plane_t plane; // normal pointing into neighbor
int leaf; // neighbor
winding_t *winding;
vec3_t origin; // for fast clip testing
float radius;
} lportal_t;
#define MAX_PORTALS_ON_LEAF 128
typedef struct lleaf_s
{
int numportals;
lportal_t *portals[MAX_PORTALS_ON_LEAF];
//
int numSurfaces;
int firstSurface;
} lleaf_t;
typedef struct lFacet_s
{
int num;
plane_t plane;
vec3_t points[4]; //
int numpoints;
float lightmapCoords[4][2];
plane_t boundaries[4]; // negative is outside the bounds
float textureMatrix[2][4]; // texture coordinates for translucency
float lightmapMatrix[2][4]; // lightmap texture coordinates
vec3_t mins;
int x, y, width, height;
} lFacet_t;
typedef struct lsurfaceTest_s
{
vec3_t mins, maxs;
vec3_t origin;
float radius;
qboolean patch; // true if this is a patch
qboolean trisoup; // true if this is a triangle soup
int numFacets;
lFacet_t *facets;
mesh_t *detailMesh; // detailed mesh with points for each lmp
shaderInfo_t *shader; // for translucency
mutex_t *mutex;
int numvolumes; // number of volumes casted at this surface
//
int always_tracelight;
int always_vlight;
} lsurfaceTest_t;
//volume types
#define VOLUME_NORMAL 0
#define VOLUME_DIRECTED 1
#define MAX_TRANSLUCENTFACETS 32
typedef struct lightvolume_s
{
int num;
int cluster; //cluster this light volume started in
plane_t endplane; //end plane
plane_t farplane; //original end plane
vec3_t points[MAX_POINTS_ON_WINDING]; //end winding points
plane_t planes[MAX_POINTS_ON_WINDING]; //volume bounding planes
int numplanes; //number of volume bounding planes
int type; //light volume type
//list with translucent surfaces the volume went through
int transFacets[MAX_TRANSLUCENTFACETS];
int transSurfaces[MAX_TRANSLUCENTFACETS];
int numtransFacets;
//clusters already tested
byte clusterTested[MAX_CLUSTERS/8];
//facets already tested
byte facetTested[MAX_FACETS/8];
int facetNum; //number of the facet blocking the light in this volume
int surfaceNum; //number of the surface blocking the light in this volume
} lightvolume_t;
//light types
#define LIGHT_POINTRADIAL 1
#define LIGHT_POINTSPOT 2
#define LIGHT_POINTFAKESURFACE 3
#define LIGHT_SURFACEDIRECTED 4
#define LIGHT_SURFACERADIAL 5
#define LIGHT_SURFACESPOT 6
//light distance attenuation types
#define LDAT_QUADRATIC 0
#define LDAT_LINEAR 1
#define LDAT_NOSCALE 2
//light angle attenuation types
#define LAAT_NORMAL 0
#define LAAT_QUADRATIC 1
#define LAAT_DOUBLEQUADRATIC 2
typedef struct vlight_s
{
vec3_t origin; //light origin, for point lights
winding_t w; //light winding, for area lights
vec4_t plane; //light winding plane
vec3_t normal; //direction of the light
int type; //light type
vec3_t color; //light color
qboolean twosided; //radiates light at both sides of the winding
int style; //light style (not used)
int atten_disttype; //light distance attenuation type
int atten_angletype; //light angle attenuation type
float atten_distscale; //distance attenuation scale
float atten_anglescale; //angle attenuation scale
float radiusByDist; //radius by distance for spot lights
float photons; //emitted photons
float intensity; //intensity
vec3_t emitColor; //full out-of-gamut value (not used)
struct shaderInfo_s *si; //shader info
int insolid; //set when light is in solid
} vlight_t;
float lightLinearScale = 1.0 / 8000;
float lightPointScale = 7500;
float lightAreaScale = 0.25;
float lightFormFactorValueScale = 3;
int lightDefaultSubdivide = 999; // vary by surface size?
vec3_t lightAmbientColor;
int portalclusters, numportals, numfaces;
lleaf_t *leafs;
lportal_t *portals;
int numvlights = 0;
vlight_t *vlights[MAX_LIGHTS];
int nostitching = 0;
int noalphashading = 0;
int nocolorshading = 0;
int nobackfaceculling = 0;
int defaulttracelight = 0;
int radiosity = 0;
int radiosity_scale;
int clustersurfaces[MAX_MAP_LEAFFACES];
int numclustersurfaces = 0;
lsurfaceTest_t *lsurfaceTest[MAX_MAP_DRAW_SURFS];
int numfacets;
float lightmappixelarea[MAX_MAP_LIGHTING/3];
float *lightFloats;//[MAX_MAP_LIGHTING];
// from polylib.c
winding_t *AllocWinding (int points);
void FreeWinding (winding_t *w);
void WindingCenter (winding_t *w, vec3_t center);
void WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs);
vec_t WindingArea (winding_t *w);
winding_t *BaseWindingForPlane (vec3_t normal, vec_t dist);
void ClipWindingEpsilon (winding_t *in, vec3_t normal, vec_t dist,
vec_t epsilon, winding_t **front, winding_t **back);
winding_t *ReverseWinding (winding_t *w);
// from light.c
extern char source[1024];
extern vec3_t surfaceOrigin[ MAX_MAP_DRAW_SURFS ];
extern int entitySurface[ MAX_MAP_DRAW_SURFS ];
extern int samplesize;
extern int novertexlighting;
extern int nogridlighting;
extern qboolean patchshadows;
extern vec3_t gridSize;
float PointToPolygonFormFactor( const vec3_t point, const vec3_t normal, const winding_t *w );
void ColorToBytes( const float *color, byte *colorBytes );
void CountLightmaps( void );
void GridAndVertexLighting( void );
void SetEntityOrigins( void );
//#define DEBUGNET
#ifdef DEBUGNET
#include "l_net.h"
socket_t *debug_socket;
/*
=====================
DebugNet_Setup
=====================
*/
void DebugNet_Setup(void)
{
address_t address;
int i;
Net_Setup();
Net_StringToAddress("127.0.0.1:28000", &address);
for (i = 0; i < 10; i++)
{
debug_socket = Net_Connect(&address, 28005 + i);
if (debug_socket)
break;
}
}
/*
=====================
DebugNet_Shutdown
=====================
*/
void DebugNet_Shutdown(void)
{
netmessage_t msg;
if (debug_socket)
{
NMSG_Clear(&msg);
NMSG_WriteByte(&msg, 1);
Net_Send(debug_socket, &msg);
Net_Disconnect(debug_socket);
}
debug_socket = NULL;
Net_Shutdown();
}
/*
=====================
DebugNet_RemoveAllPolys
=====================
*/
void DebugNet_RemoveAllPolys(void)
{
netmessage_t msg;
if (!debug_socket)
return;
NMSG_Clear(&msg);
NMSG_WriteByte(&msg, 2); //remove all debug polys
Net_Send(debug_socket, &msg);
}
/*
====================
DebugNet_DrawWinding
=====================
*/
void DebugNet_DrawWinding(winding_t *w, int color)
{
netmessage_t msg;
int i;
if (!debug_socket)
return;
NMSG_Clear(&msg);
NMSG_WriteByte(&msg, 0); //draw a winding
NMSG_WriteByte(&msg, w->numpoints); //number of points
NMSG_WriteLong(&msg, color); //color
for (i = 0; i < w->numpoints; i++)
{
NMSG_WriteFloat(&msg, w->points[i][0]);
NMSG_WriteFloat(&msg, w->points[i][1]);
NMSG_WriteFloat(&msg, w->points[i][2]);
}
Net_Send(debug_socket, &msg);
}
/*
=====================
DebugNet_DrawLine
=====================
*/
void DebugNet_DrawLine(vec3_t p1, vec3_t p2, int color)
{
netmessage_t msg;
if (!debug_socket)
return;
NMSG_Clear(&msg);
NMSG_WriteByte(&msg, 1); //draw a line
NMSG_WriteLong(&msg, color); //color
NMSG_WriteFloat(&msg, p1[0]);
NMSG_WriteFloat(&msg, p1[1]);
NMSG_WriteFloat(&msg, p1[2]);
NMSG_WriteFloat(&msg, p2[0]);
NMSG_WriteFloat(&msg, p2[1]);
NMSG_WriteFloat(&msg, p2[2]);
Net_Send(debug_socket, &msg);
}
/*
=====================
DebugNet_DrawMesh
=====================
*/
void DebugNet_DrawMesh(mesh_t *mesh)
{
int i, j;
float dot;
drawVert_t *v1, *v2, *v3, *v4;
winding_t winding;
plane_t plane;
vec3_t d1, d2;
for ( i = 0 ; i < mesh->width - 1 ; i++ ) {
for ( j = 0 ; j < mesh->height - 1 ; j++ ) {
v1 = mesh->verts + j * mesh->width + i;
v2 = v1 + 1;
v3 = v1 + mesh->width + 1;
v4 = v1 + mesh->width;
VectorSubtract( v4->xyz, v1->xyz, d1 );
VectorSubtract( v3->xyz, v1->xyz, d2 );
CrossProduct( d2, d1, plane.normal );
if ( VectorNormalize( plane.normal, plane.normal ) != 0 )
{
plane.dist = DotProduct( v1->xyz, plane.normal );
dot = DotProduct(plane.normal, v2->xyz) - plane.dist;
if (fabs(dot) < 0.1)
{
VectorCopy(v1->xyz, winding.points[0]);
VectorCopy(v4->xyz, winding.points[1]);
VectorCopy(v3->xyz, winding.points[2]);
VectorCopy(v2->xyz, winding.points[3]);
winding.numpoints = 4;
DebugNet_DrawWinding(&winding, 2);
continue;
}
}
winding.numpoints = 3;
VectorCopy(v1->xyz, winding.points[0]);
VectorCopy(v4->xyz, winding.points[1]);
VectorCopy(v3->xyz, winding.points[2]);
DebugNet_DrawWinding(&winding, 2);
VectorCopy(v1->xyz, winding.points[0]);
VectorCopy(v3->xyz, winding.points[1]);
VectorCopy(v2->xyz, winding.points[2]);
DebugNet_DrawWinding(&winding, 2);
}
}
}
/*
=====================
VL_DrawLightVolume
=====================
*/
int VL_ChopWinding (winding_t *in, plane_t *split, float epsilon);
void VL_DrawLightVolume(vlight_t *light, lightvolume_t *volume)
{
winding_t w;
int i;
vec3_t p2, invlight;
memcpy(w.points, volume->points, volume->numplanes * sizeof(vec3_t));
w.numpoints = volume->numplanes;
DebugNet_DrawWinding(&w, 2);
if (volume->type == VOLUME_DIRECTED)
{
VectorCopy(light->normal, invlight);
VectorInverse(invlight);
for (i = 0; i < volume->numplanes; i++)
{
VectorCopy(volume->points[i], w.points[0]);
VectorCopy(volume->points[(i+1) % volume->numplanes], w.points[1]);
VectorMA(w.points[1], MAX_WORLD_COORD, invlight, w.points[2]);
VectorMA(w.points[0], MAX_WORLD_COORD, invlight, w.points[3]);
w.numpoints = 4;
DebugNet_DrawWinding(&w, 2);
VectorMA(volume->points[i], 8, volume->planes[i].normal, p2);
DebugNet_DrawLine(volume->points[i], p2, 3);
}
}
else
{
//
VectorCopy(light->origin, w.points[0]);
w.numpoints = 3;
for (i = 0; i < volume->numplanes; i++)
{
VectorCopy(volume->points[i], w.points[1]);
VectorCopy(volume->points[(i+1) % volume->numplanes], w.points[2]);
VL_ChopWinding(&w, &volume->endplane, 0);
DebugNet_DrawWinding(&w, 2);
VectorMA(volume->points[i], 8, volume->planes[i].normal, p2);
DebugNet_DrawLine(volume->points[i], p2, 3);
}
}
}
/*
=============
VL_DrawLightmapPixel
=============
*/
void VL_DrawLightmapPixel(int surfaceNum, int x, int y, int color)
{
winding_t w;
dsurface_t *ds;
mesh_t *mesh;
ds = &drawSurfaces[surfaceNum];
if (ds->surfaceType == MST_PATCH)
{
mesh = lsurfaceTest[surfaceNum]->detailMesh;
VectorCopy( mesh->verts[(y-ds->lightmapY)*mesh->width+x-ds->lightmapX].xyz, w.points[0]);
VectorCopy( mesh->verts[(y+1-ds->lightmapY)*mesh->width+x-ds->lightmapX].xyz, w.points[1]);
VectorCopy( mesh->verts[(y+1-ds->lightmapY)*mesh->width+x+1-ds->lightmapX].xyz, w.points[2]);
VectorCopy( mesh->verts[(y-ds->lightmapY)*mesh->width+x+1-ds->lightmapX].xyz, w.points[3]);
w.numpoints = 4;
}
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -