⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lightv.c

📁 quake3工具源码。包括生成bsp文件
💻 C
📖 第 1 页 / 共 5 页
字号:
/*****************************************************************************
 * 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 + -