aboutsummaryrefslogtreecommitdiff
path: root/mp/src/utils/vrad/vrad.h
blob: 0c66aecc7993d644335019d0573e53b81c033198 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: 
//
// $Workfile:     $
// $Date:         $
//
//-----------------------------------------------------------------------------
// $Log: $
//
// $NoKeywords: $
//=============================================================================//

#ifndef VRAD_H
#define VRAD_H
#pragma once


#include "commonmacros.h"
#include "worldsize.h"
#include "cmdlib.h"
#include "mathlib/mathlib.h"
#include "bsplib.h"
#include "polylib.h"
#include "threads.h"
#include "builddisp.h"
#include "VRAD_DispColl.h"
#include "UtlMemory.h"
#include "UtlHash.h"
#include "utlvector.h"
#include "iincremental.h"
#include "raytrace.h"


#ifdef _WIN32
#include <windows.h>
#endif

#include <sys/types.h>
#include <sys/stat.h>

#pragma warning(disable: 4142 4028)
#include <io.h>
#pragma warning(default: 4142 4028)

#include <fcntl.h>
#include <direct.h>
#include <ctype.h>


// Can remove these options if they don't generate problems.
//#define SAMPLEHASH_USE_AREA_PATCHES	// Add patches to sample hash based on their AABB instead of as a single point.
#define SAMPLEHASH_QUERY_ONCE		// Big optimization - causes way less sample hash queries.

extern float dispchop; // "-dispchop" tightest number of luxel widths for a patch, used on edges
extern float g_MaxDispPatchRadius;

//-----------------------------------------------------------------------------
// forward declarations
//-----------------------------------------------------------------------------

struct Ray_t;

#define		TRANSFER_EPSILON		0.0000001

struct directlight_t
{
	int		index;

	directlight_t *next;
	dworldlight_t light;

	byte	*pvs;		// accumulated domain of the light
	int		facenum;	// domain of attached lights
	int		texdata;	// texture source of traced lights

	Vector	snormal;
	Vector	tnormal;
	float	sscale;
	float	tscale;
	float	soffset;
	float	toffset;

	int		dorecalc; // position, vector, spot angle, etc.
	IncrementalLightID	m_IncrementalID;

	// hard-falloff lights (lights that fade to an actual zero). between m_flStartFadeDistance and
	// m_flEndFadeDistance, a smoothstep to zero will be done, so that the light goes to zero at
	// the end.
	float m_flStartFadeDistance;
	float m_flEndFadeDistance;
	float m_flCapDist;										// max distance to feed in

	directlight_t(void)
	{
		m_flEndFadeDistance = -1.0;							// end<start indicates not set
		m_flStartFadeDistance= 0.0;
		m_flCapDist = 1.0e22;

	}
};

struct bumplights_t
{
	Vector	light[NUM_BUMP_VECTS+1];
};


struct transfer_t
{
	int	patch;
	float	transfer;
};


struct LightingValue_t
{
	Vector m_vecLighting;
	float m_flDirectSunAmount;

	FORCEINLINE bool IsValid( void ) const
	{
		return ( m_vecLighting.x >= 0 && 
				 m_vecLighting.y >= 0 && 
				 m_vecLighting.z >= 0 &&
				 m_vecLighting.x < 1e10 && 
				 m_vecLighting.y < 1e10 && 
				 m_vecLighting.z < 1e10 );
	}

	FORCEINLINE void Zero( void )
	{
		m_vecLighting.Init( 0, 0, 0 );
		m_flDirectSunAmount = 0.0;
	}
	
	FORCEINLINE void Scale( float m_flScale )
	{
		m_vecLighting *= m_flScale;
		m_flDirectSunAmount *= m_flScale;
	}

	FORCEINLINE void AddWeighted( LightingValue_t const &src, float flWeight )
	{
		m_vecLighting += flWeight * src.m_vecLighting;
		m_flDirectSunAmount += flWeight * src.m_flDirectSunAmount;
	}

	FORCEINLINE void AddWeighted( Vector const &src, float flWeight )
	{
		m_vecLighting += flWeight * src;
	}

	FORCEINLINE float Intensity( void ) const
	{
		return m_vecLighting.x + m_vecLighting.y + m_vecLighting.z;
	}

	FORCEINLINE void AddLight( float flAmount, Vector const &vecColor, float flSunAmount = 0.0 )
	{
		VectorMA( m_vecLighting, flAmount, vecColor, m_vecLighting );
		m_flDirectSunAmount += flSunAmount;
		Assert( this->IsValid() );
	}


	FORCEINLINE void AddLight( LightingValue_t const &src )
	{
		m_vecLighting += src.m_vecLighting;
		m_flDirectSunAmount += src.m_flDirectSunAmount;
		Assert( this->IsValid() );
	}
	
	FORCEINLINE void Init( float x, float y, float z )
	{
		m_vecLighting.Init( x, y, z );
		m_flDirectSunAmount = 0.0;
	}


};


#define	MAX_PATCHES	(4*65536)

struct CPatch
{
	winding_t	*winding;
	Vector		mins, maxs, face_mins, face_maxs;

	Vector		origin;				// adjusted off face by face normal

	dplane_t	*plane;				// plane (corrected for facing)
	
	unsigned short		m_IterationKey;	// Used to prevent touching the same patch multiple times in the same query.
										// See IncrementPatchIterationKey().
	
	// these are packed into one dword
	unsigned int normalMajorAxis : 2;	// the major axis of base face normal
	unsigned int sky : 1;
	unsigned int needsBumpmap : 1;
	unsigned int pad : 28;

	Vector		normal;				// adjusted for phong shading

	float		planeDist;			// Fixes up patch planes for brush models with an origin brush

	float		chop;				// smallest acceptable width of patch face
	float		luxscale;			// average luxels per world coord
	float		scale[2];			// Scaling of texture in s & t

	bumplights_t totallight;		// accumulated by radiosity
									// does NOT include light
									// accounted for by direct lighting
	Vector		baselight;			// emissivity only
	float		basearea;			// surface per area per baselight instance

	Vector		directlight;		// direct light value
	float		area;

	Vector		reflectivity;		// Average RGB of texture, modified by material type.

	Vector		samplelight;
	float		samplearea;		// for averaging direct light
	int			faceNumber;
	int			clusterNumber;

	int			parent;			// patch index of parent
	int			child1;			// patch index for children
	int			child2;

	int			ndxNext;					// next patch index in face
	int			ndxNextParent;				// next parent patch index in face
	int			ndxNextClusterChild;		// next terminal child index in cluster
//	struct		patch_s		*next;					// next in face
//	struct		patch_s		*nextparent;		    // next in face
//	struct		patch_s		*nextclusterchild;		// next terminal child in cluster

	int			numtransfers;
	transfer_t	*transfers;

	short		indices[3];				// displacement use these for subdivision
};


extern CUtlVector<CPatch>	g_Patches;
extern CUtlVector<int>		g_FacePatches;		// constains all patches, children first
extern CUtlVector<int>		faceParents;		// contains only root patches, use next parent to iterate
extern CUtlVector<int>		clusterChildren;


struct sky_camera_t
{
	Vector origin;
	float world_to_sky;
	float sky_to_world;
	int area;
};

extern int num_sky_cameras;
extern sky_camera_t sky_cameras[MAX_MAP_AREAS];
extern int area_sky_cameras[MAX_MAP_AREAS];
void ProcessSkyCameras();

extern entity_t		*face_entity[MAX_MAP_FACES];
extern Vector		face_offset[MAX_MAP_FACES];		// for rotating bmodels
extern Vector		face_centroids[MAX_MAP_EDGES];
extern int			leafparents[MAX_MAP_LEAFS];
extern int			nodeparents[MAX_MAP_NODES];
extern float		lightscale;
extern float		dlight_threshold;
extern float		coring;
extern qboolean		g_bDumpPatches;
extern bool			bRed2Black;
extern bool         g_bNoSkyRecurse;
extern bool			bDumpNormals;
extern bool			g_bFastAmbient;
extern float		maxchop;
extern FileHandle_t	pFileSamples[4][4];
extern qboolean		g_bLowPriority;
extern qboolean		do_fast;
extern bool			g_bInterrupt;		// Was used with background lighting in WC. Tells VRAD to stop lighting.
extern IIncremental *g_pIncremental;	// null if not doing incremental lighting
extern bool			g_bDumpPropLightmaps;

extern float g_flSkySampleScale;								// extra sampling factor for indirect light

extern bool g_bLargeDispSampleRadius;
extern bool g_bStaticPropPolys;
extern bool g_bTextureShadows;
extern bool g_bShowStaticPropNormals;
extern bool g_bDisablePropSelfShadowing;

extern CUtlVector<char const *> g_NonShadowCastingMaterialStrings;
extern void ForceTextureShadowsOnModel( const char *pModelName );
extern bool IsModelTextureShadowsForced( const char *pModelName );

// Raytracing

#define TRACE_ID_SKY           0x01000000  // sky face ray blocker
#define TRACE_ID_OPAQUE        0x02000000  // everyday light blocking face
#define TRACE_ID_STATICPROP    0x04000000  // static prop - lower bits are prop ID
extern RayTracingEnvironment g_RtEnv;

#include "mpivrad.h"

void MakeShadowSplits (void);

//==============================================

void BuildVisMatrix (void);
void BuildClusterTable( void );
void AddDispsToClusterTable( void );
void FreeVisMatrix (void);
// qboolean CheckVisBit (unsigned int p1, unsigned int p2);
void TouchVMFFile (void);

//==============================================

extern  qboolean do_extra;
extern  qboolean do_fast;
extern  qboolean do_centersamples;
extern  int extrapasses;
extern	Vector ambient;
extern  float maxlight;
extern	unsigned numbounce;
extern  qboolean g_bLogHashData;
extern  bool	debug_extra;
extern	directlight_t	*activelights;
extern	directlight_t	*freelights;

// because of hdr having two face lumps (light styles can cause them to be different, among other
// things), we need to always access (r/w) face data though this pointer
extern dface_t *g_pFaces;


extern bool g_bMPIProps;

extern	byte	nodehit[MAX_MAP_NODES];
extern  float	gamma_value;
extern	float	indirect_sun;
extern	float	smoothing_threshold;
extern	int		dlight_map;

extern float	g_flMaxDispSampleSize;
extern float	g_SunAngularExtent;

extern char		source[MAX_PATH];

// Used by incremental lighting to trivial-reject faces.
// There is a bit in here for each face telling whether or not any of the
// active lights can see the face.
extern CUtlVector<byte> g_FacesVisibleToLights;

void MakeTnodes (dmodel_t *bm);
void PairEdges (void);

void SaveVertexNormals( void );

qboolean IsIncremental(char *filename);
int SaveIncremental(char *filename);
int PartialHead (void);
void BuildFacelights (int facenum, int threadnum);
void PrecompLightmapOffsets();
void FinalLightFace (int threadnum, int facenum);
void PvsForOrigin (Vector& org, byte *pvs);
void ConvertRGBExp32ToRGBA8888( const ColorRGBExp32 *pSrc, unsigned char *pDst, Vector* _optOutLinear = NULL );
void ConvertRGBExp32ToLinear(const ColorRGBExp32 *pSrc, Vector* pDst);
void ConvertLinearToRGBA8888( const Vector *pSrc, unsigned char *pDst );


inline byte PVSCheck( const byte *pvs, int iCluster )
{
	if ( iCluster >= 0 )
	{
		return pvs[iCluster >> 3] & ( 1 << ( iCluster & 7 ) );
	}
	else
	{
		// PointInLeaf still returns -1 for valid points sometimes and rather than 
		// have black samples, we assume the sample is in the PVS.
		return 1;
	}
}

// outputs 1 in fractionVisible if no occlusion, 0 if full occlusion, and in-between values
void TestLine( FourVectors const& start, FourVectors const& stop, fltx4 *pFractionVisible, int static_prop_index_to_ignore=-1);

// returns 1 if the ray sees the sky, 0 if it doesn't, and in-between values for partial coverage
void TestLine_DoesHitSky( FourVectors const& start, FourVectors const& stop,
                          fltx4 *pFractionVisible, bool canRecurse = true, int static_prop_to_skip=-1, bool bDoDebug = false );

// converts any marked brush entities to triangles for shadow casting
void ExtractBrushEntityShadowCasters ( void );
void AddBrushesForRayTrace ( void );

void BaseLightForFace( dface_t *f, Vector& light, float *parea, Vector& reflectivity );
void CreateDirectLights (void);
void GetPhongNormal( int facenum, Vector const& spot, Vector& phongnormal );
int LightForString( char *pLight, Vector& intensity );
void MakeTransfer( int ndxPatch1, int ndxPatch2, transfer_t *all_transfers );
void MakeScales( int ndxPatch, transfer_t *all_transfers );

// Run startup code like initialize mathlib.
void VRAD_Init();

// Load the BSP file and prepare to do the lighting.
// This is called after any command-line parameters have been set.
void VRAD_LoadBSP( char const *pFilename );

int VRAD_Main(int argc, char **argv);

// This performs an actual lighting pass.
// Returns true if the process was interrupted (with g_bInterrupt).
bool RadWorld_Go();

dleaf_t		*PointInLeaf (Vector const& point);
int			ClusterFromPoint( Vector const& point );
winding_t	*WindingFromFace (dface_t *f, Vector& origin );

void WriteWinding (FileHandle_t out, winding_t *w, Vector& color );
void WriteNormal( FileHandle_t out, Vector const &nPos, Vector const &nDir, 
				  float length, Vector const &color );
void WriteLine( FileHandle_t out, const Vector &vecPos1, const Vector &vecPos2, const Vector &color );
void WriteTrace( const char *pFileName, const FourRays &rays, const RayTracingResult& result );

#ifdef STATIC_FOG
qboolean IsFog( dface_t * f );
#endif

#define CONTENTS_EMPTY	0
#define TEX_SPECIAL		(SURF_SKY|SURF_NOLIGHT)

//=============================================================================

// trace.cpp

bool AddDispCollTreesToWorld( void );
int PointLeafnum( Vector const &point );
float TraceLeafBrushes( int leafIndex, const Vector &start, const Vector &end, CBaseTrace &traceOut );

//=============================================================================

// dispinfo.cpp

struct SSE_sampleLightOutput_t
{
	fltx4 m_flDot[NUM_BUMP_VECTS+1];
	fltx4 m_flFalloff;
	fltx4 m_flSunAmount;
};

#define GATHERLFLAGS_FORCE_FAST 1
#define GATHERLFLAGS_IGNORE_NORMALS 2

// SSE Gather light stuff
void GatherSampleLightSSE( SSE_sampleLightOutput_t &out, directlight_t *dl, int facenum, 
					   FourVectors const& pos, FourVectors *pNormals, int normalCount, int iThread,
					   int nLFlags = 0,					// GATHERLFLAGS_xxx
					   int static_prop_to_skip=-1,
					   float flEpsilon = 0.0 );
//void GatherSampleSkyLightSSE( SSE_sampleLightOutput_t &out, directlight_t *dl, int facenum, 
//							 FourVectors const& pos, FourVectors *pNormals, int normalCount, int iThread,
//							 int nLFlags = 0,
//							 int static_prop_to_skip=-1,
//							 float flEpsilon = 0.0 );
//void GatherSampleAmbientSkySSE( SSE_sampleLightOutput_t &out, directlight_t *dl, int facenum, 
//						  FourVectors const& pos, FourVectors *pNormals, int normalCount, int iThread,
//						  int nLFlags = 0,					// GATHERLFLAGS_xxx
//						  int static_prop_to_skip=-1,
//						  float flEpsilon = 0.0 );
//void GatherSampleStandardLightSSE( SSE_sampleLightOutput_t &out, directlight_t *dl, int facenum, 
//						  FourVectors const& pos, FourVectors *pNormals, int normalCount, int iThread,
//						  int nLFlags = 0,					// GATHERLFLAGS_xxx
//						  int static_prop_to_skip=-1,
//						  float flEpsilon = 0.0 );

//-----------------------------------------------------------------------------
// VRad Displacements
//-----------------------------------------------------------------------------

struct facelight_t;
typedef struct radial_s radial_t;
struct lightinfo_t;

// NOTE: should probably come up with a bsptreetested_t struct or something,
//       see below (PropTested_t)
struct DispTested_t
{
	int	m_Enum;
	int	*m_pTested;
};

class IVRadDispMgr
{
public:
	// creation/destruction
	virtual void Init( void ) = 0;
	virtual void Shutdown( void ) = 0;

	// "CalcPoints"
	virtual bool BuildDispSamples( lightinfo_t *pLightInfo, facelight_t *pFaceLight, int ndxFace ) = 0;
	virtual bool BuildDispLuxels( lightinfo_t *pLightInfo, facelight_t *pFaceLight, int ndxFace ) = 0;
	virtual bool BuildDispSamplesAndLuxels_DoFast( lightinfo_t *pLightInfo, facelight_t *pFaceLight, int ndxFace ) = 0;

	// patching functions
	virtual void MakePatches( void ) = 0;
	virtual void SubdividePatch( int iPatch ) = 0;

	// pre "FinalLightFace"
	virtual void InsertSamplesDataIntoHashTable( void ) = 0;
	virtual void InsertPatchSampleDataIntoHashTable( void ) = 0;

	// "FinalLightFace"
	virtual radial_t *BuildLuxelRadial( int ndxFace, int ndxStyle, bool bBump ) = 0;
	virtual bool SampleRadial( int ndxFace, radial_t *pRadial, Vector const &vPos, int ndxLxl, LightingValue_t *pLightSample, int sampleCount, bool bPatch ) = 0;
	virtual radial_t *BuildPatchRadial( int ndxFace, bool bBump ) = 0;

	// utility
	virtual	void GetDispSurfNormal( int ndxFace, Vector &pt, Vector &ptNormal, bool bInside ) = 0;
	virtual void GetDispSurf( int ndxFace, CVRADDispColl **ppDispTree ) = 0;

	// bsp tree functions
	virtual bool ClipRayToDisp( DispTested_t &dispTested, Ray_t const &ray ) = 0;
	virtual bool ClipRayToDispInLeaf( DispTested_t &dispTested, Ray_t const &ray, int ndxLeaf ) = 0;
	virtual void ClipRayToDispInLeaf( DispTested_t &dispTested, Ray_t const &ray, 
				int ndxLeaf, float& dist, dface_t*& pFace, Vector2D& luxelCoord ) = 0;
	virtual void ClipRayToDispInLeaf( DispTested_t &dispTested, Ray_t const &ray, 
		int ndxLeaf, float& dist, Vector *pNormal ) = 0;
	virtual void StartRayTest( DispTested_t &dispTested ) = 0;
	virtual void AddPolysForRayTrace() = 0;

	// general timing -- should be moved!!
	virtual void StartTimer( const char *name ) = 0;
	virtual void EndTimer( void ) = 0;
};

IVRadDispMgr *StaticDispMgr( void );

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
inline bool ValidDispFace( dface_t *pFace )
{
	if( !pFace ) { return false; }
	if( pFace->dispinfo == -1 ) { return false; }
	if( pFace->numedges != 4 ) { return false; }

	return true;
}

#define SAMPLEHASH_VOXEL_SIZE			64.0f
typedef unsigned int SampleHandle_t;				// the upper 16 bits = facelight index (works because max face are 65536)
													// the lower 16 bits = sample index inside of facelight
struct sample_t;
struct SampleData_t
{
	unsigned short				x, y, z;
	CUtlVector<SampleHandle_t>	m_Samples;
};

struct PatchSampleData_t
{
	unsigned short				x, y, z;
	CUtlVector<int>				m_ndxPatches;
};

UtlHashHandle_t SampleData_AddSample( sample_t *pSample, SampleHandle_t sampleHandle );
void PatchSampleData_AddSample( CPatch *pPatch, int ndxPatch );
unsigned short IncrementPatchIterationKey();
void SampleData_Log( void );

extern CUtlHash<SampleData_t>		g_SampleHashTable;
extern CUtlHash<PatchSampleData_t>	g_PatchSampleHashTable;

extern int samplesAdded;
extern int patchSamplesAdded;

//-----------------------------------------------------------------------------
// Computes lighting for the detail props
//-----------------------------------------------------------------------------

void ComputeDetailPropLighting( int iThread );
void ComputeIndirectLightingAtPoint( Vector &position, Vector &normal, Vector &outColor, 
									 int iThread, bool force_fast = false, bool bIgnoreNormals = false );

//-----------------------------------------------------------------------------
// VRad static props
//-----------------------------------------------------------------------------
class IPhysicsCollision;
struct PropTested_t
{
	int m_Enum;
	int* m_pTested;
	IPhysicsCollision *pThreadedCollision;
};

class IVradStaticPropMgr
{
public:
	// methods of IStaticPropMgr
	virtual void Init() = 0;
	virtual void Shutdown() = 0;
	virtual void ComputeLighting( int iThread ) = 0;
	virtual void AddPolysForRayTrace() = 0;
};

//extern PropTested_t s_PropTested[MAX_TOOL_THREADS+1];
extern DispTested_t s_DispTested[MAX_TOOL_THREADS+1];

IVradStaticPropMgr* StaticPropMgr();

extern float ComputeCoverageFromTexture( float b0, float b1, float b2, int32 hitID );

#endif // VRAD_H