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

📄 light.c

📁 quake3工具源码。包括生成bsp文件
💻 C
📖 第 1 页 / 共 4 页
字号:

		VectorCopy( origin, baseOrigin );

		// try to nudge the origin around to find a valid point
		for ( step = 9 ; step <= 18 ; step += 9 ) {
			for ( i = 0 ; i < 8 ; i++ ) {
				VectorCopy( baseOrigin, origin );
				if ( i & 1 ) {
					origin[0] += step;
				} else {
					origin[0] -= step;
				}
				if ( i & 2 ) {
					origin[1] += step;
				} else {
					origin[1] -= step;
				}
				if ( i & 4 ) {
					origin[2] += step;
				} else {
					origin[2] -= step;
				}

				if ( !PointInSolid( origin ) ) {
					break;
				}
			}
			if ( i != 8 ) {
				break;
			}
		}
		if ( step > 18 ) {
			// can't find a valid point at all
			for ( i = 0 ; i < 8 ; i++ ) {
				gridData[ num*8 + i ] = 0;
			}
			return;
		}
	}

	VectorClear( summedDir );

	// trace to all the lights

	// find the major light direction, and divide the
	// total light between that along the direction and
	// the remaining in the ambient 
	numCon = 0;
	for ( light = lights ; light ; light = light->next ) {
		vec3_t		add;
		vec3_t		dir;
		float		addSize;

		if ( !LightContributionToPoint( light, origin, add, &tw ) ) {
			continue;
		}

		VectorSubtract( light->origin, origin, dir );
		VectorNormalize( dir, dir );

		VectorCopy( add, contributions[numCon].color );
		VectorCopy( dir, contributions[numCon].dir );
		numCon++;

		addSize = VectorLength( add );
		VectorMA( summedDir, addSize, dir, summedDir );

		if ( numCon == MAX_CONTRIBUTIONS-1 ) {
			break;
		}
	}

	//
	// trace directly to the sun
	//
	SunToPoint( origin, &tw, color );
	addSize = VectorLength( color );
	if ( addSize > 0 ) {
		VectorCopy( color, contributions[numCon].color );
		VectorCopy( sunDirection, contributions[numCon].dir );
		VectorMA( summedDir, addSize, sunDirection, summedDir );
		numCon++;
	}


	// now that we have identified the primary light direction,
	// go back and seperate all the light into directed and ambient
	VectorNormalize( summedDir, summedDir );
	VectorCopy( ambientColor, color );
	VectorClear( directedColor );

	for ( i = 0 ; i < numCon ; i++ ) {
		float	d;

		d = DotProduct( contributions[i].dir, summedDir );
		if ( d < 0 ) {
			d = 0;
		}

		VectorMA( directedColor, d, contributions[i].color, directedColor );

		// the ambient light will be at 1/4 the value of directed light
		d = 0.25 * ( 1.0 - d );
		VectorMA( color, d, contributions[i].color, color );
	}

	// now do some fudging to keep the ambient from being too low
	VectorMA( color, 0.25, directedColor, color );

	//
	// save the resulting value out
	//
	ColorToBytes( color, gridData + num*8 );
	ColorToBytes( directedColor, gridData + num*8 + 3 );

	VectorNormalize( summedDir, summedDir );
	NormalToLatLong( summedDir, gridData + num*8 + 6);
}


/*
=============
SetupGrid
=============
*/
void SetupGrid( void ) {
	int		i;
	vec3_t	maxs;

	for ( i = 0 ; i < 3 ; i++ ) {
		gridMins[i] = gridSize[i] * ceil( dmodels[0].mins[i] / gridSize[i] );
		maxs[i] = gridSize[i] * floor( dmodels[0].maxs[i] / gridSize[i] );
		gridBounds[i] = (maxs[i] - gridMins[i])/gridSize[i] + 1;
	}

	numGridPoints = gridBounds[0] * gridBounds[1] * gridBounds[2];
	if (numGridPoints * 8 >= MAX_MAP_LIGHTGRID)
		Error("MAX_MAP_LIGHTGRID");
	qprintf( "%5i gridPoints\n", numGridPoints );
}

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

/*
=============
RemoveLightsInSolid
=============
*/
void RemoveLightsInSolid(void)
{
	light_t *light, *prev;
	int numsolid = 0;

	prev = NULL;
	for ( light = lights ; light ;  ) {
		if (PointInSolid(light->origin))
		{
			if (prev) prev->next = light->next;
			else lights = light->next;
			if (light->w)
				FreeWinding(light->w);
			free(light);
			numsolid++;
			if (prev)
				light = prev->next;
			else
				light = lights;
		}
		else
		{
			prev = light;
			light = light->next;
		}
	}
	_printf (" %7i lights in solid\n", numsolid);
}

/*
=============
LightWorld
=============
*/
void LightWorld (void) {
	float		f;

	// determine the number of grid points
	SetupGrid();

	// find the optional world ambient
	GetVectorForKey( &entities[0], "_color", ambientColor );
	f = FloatForKey( &entities[0], "ambient" );
	VectorScale( ambientColor, f, ambientColor );

	// create lights out of patches and lights
	qprintf ("--- CreateLights ---\n");
	CreateEntityLights ();
	qprintf ("%i point lights\n", numPointLights);
	qprintf ("%i area lights\n", numAreaLights);

	if (!nogridlighting) {
		qprintf ("--- TraceGrid ---\n");
		RunThreadsOnIndividual( numGridPoints, qtrue, TraceGrid );
		qprintf( "%i x %i x %i = %i grid\n", gridBounds[0], gridBounds[1],
			gridBounds[2], numGridPoints);
	}

	qprintf ("--- TraceLtm ---\n");
	RunThreadsOnIndividual( numDrawSurfaces, qtrue, TraceLtm );
	qprintf( "%5i visible samples\n", c_visible );
	qprintf( "%5i occluded samples\n", c_occluded );
}

/*
========
CreateFilters

EXPERIMENTAL, UNUSED

Look for transparent light filter surfaces.

This will only work for flat 3*3 patches that exactly hold one copy of the texture.
========
*/
#define	PLANAR_PATCH_EPSILON	0.1
void CreateFilters( void ) {
	int				i;
	filter_t		*f;
	dsurface_t		*ds;
	shaderInfo_t	*si;
	drawVert_t		*v1, *v2, *v3;
	vec3_t			d1, d2;
	int				vertNum;

	numFilters = 0;

	return;

	for ( i = 0 ; i < numDrawSurfaces ; i++ ) {
		ds = &drawSurfaces[i];
		if ( !ds->patchWidth ) {
			continue;
		}
		si = ShaderInfoForShader( dshaders[ ds->shaderNum ].shader );
/*
		if ( !(si->surfaceFlags & SURF_LIGHTFILTER) ) {
			continue;
		}
*/

		// we have a filter patch
		v1 = &drawVerts[ ds->firstVert ];

		if ( ds->patchWidth != 3 || ds->patchHeight != 3 ) {
			_printf("WARNING: patch at %i %i %i has SURF_LIGHTFILTER but isn't a 3 by 3\n",
				v1->xyz[0], v1->xyz[1], v1->xyz[2] );
			continue;
		}

		if ( numFilters == MAX_FILTERS ) {
			Error( "MAX_FILTERS" );
		}
		f = &filters[ numFilters ];
		numFilters++;

		v2 = &drawVerts[ ds->firstVert + 2 ];
		v3 = &drawVerts[ ds->firstVert + 6 ];

		VectorSubtract( v2->xyz, v1->xyz, d1 );
		VectorSubtract( v3->xyz, v1->xyz, d2 );
		VectorNormalize( d1, d1 );
		VectorNormalize( d2, d2 );
		CrossProduct( d1, d2, f->plane );
		f->plane[3] = DotProduct( v1->xyz, f->plane );

		// make sure all the control points are on the plane
		for ( vertNum = 0 ; vertNum < ds->numVerts ; vertNum++ ) {
			float	d;

			d = DotProduct( drawVerts[ ds->firstVert + vertNum ].xyz, f->plane ) - f->plane[3];
			if ( fabs( d ) > PLANAR_PATCH_EPSILON ) {
				break;
			}
		}
		if ( vertNum != ds->numVerts ) {
			numFilters--;
			_printf("WARNING: patch at %i %i %i has SURF_LIGHTFILTER but isn't flat\n",
				v1->xyz[0], v1->xyz[1], v1->xyz[2] );
			continue;
		}
	}

	f = &filters[0];
	numFilters = 1;

	f->plane[0] = 1;
	f->plane[1] = 0;
	f->plane[2] = 0;
	f->plane[3] = 448;

	f->origin[0] = 448;
	f->origin[1] = 192;
	f->origin[2] = 0;

	f->vectors[0][0] = 0;
	f->vectors[0][1] = -1.0 / 128;
	f->vectors[0][2] = 0;

	f->vectors[1][0] = 0;
	f->vectors[1][1] = 0;
	f->vectors[1][2] = 1.0 / 128;

	f->si = ShaderInfoForShader( "textures/hell/blocks11ct" );
}

/*
=============
VertexLightingThread
=============
*/
void VertexLightingThread(int num) {
	dsurface_t	*ds;
	traceWork_t	tw;
	shaderInfo_t *si;

	ds = &drawSurfaces[num];

	// vertex-lit triangle model
	if ( ds->surfaceType == MST_TRIANGLE_SOUP ) {
		return;
	}

	if (novertexlighting)
		return;

	if ( ds->lightmapNum == -1 ) {
		return;	// doesn't need lighting at all
	}

	si = ShaderInfoForShader( dshaders[ ds->shaderNum].shader );

	// calculate the vertex lighting for gouraud shade mode
	VertexLighting( ds, si->vertexShadows, si->forceSunLight, si->vertexScale, &tw );
}

/*
=============
TriSoupLightingThread
=============
*/
void TriSoupLightingThread(int num) {
	dsurface_t	*ds;
	traceWork_t	tw;
	shaderInfo_t *si;

	ds = &drawSurfaces[num];
	si = ShaderInfoForShader( dshaders[ ds->shaderNum].shader );

	// vertex-lit triangle model
	if ( ds->surfaceType == MST_TRIANGLE_SOUP ) {
		VertexLighting( ds, !si->noVertexShadows, si->forceSunLight, 1.0, &tw );
	}
}

/*
=============
GridAndVertexLighting
=============
*/
void GridAndVertexLighting(void) {
	SetupGrid();

	FindSkyBrushes();
	CreateFilters();
	InitTrace();
	CreateEntityLights ();
	CreateSurfaceLights();

	if (!nogridlighting) {
		_printf ("--- TraceGrid ---\n");
		RunThreadsOnIndividual( numGridPoints, qtrue, TraceGrid );
	}

	if (!novertexlighting) {
		_printf ("--- Vertex Lighting ---\n");
		RunThreadsOnIndividual( numDrawSurfaces, qtrue, VertexLightingThread );
	}

	_printf("--- Model Lighting ---\n");
	RunThreadsOnIndividual( numDrawSurfaces, qtrue, TriSoupLightingThread );
}

/*
========
LightMain

========
*/
int LightMain (int argc, char **argv) {
	int			i;
	double		start, end;
	const char	*value;

	_printf ("----- Lighting ----\n");

	verbose = qfalse;

	for (i=1 ; i<argc ; i++) {
		if (!strcmp(argv[i],"-tempname"))
    {
      i++;
    } else if (!strcmp(argv[i],"-v")) {
			verbose = qtrue;
		} else if (!strcmp(argv[i],"-threads")) {
			numthreads = atoi (argv[i+1]);
			i++;
		} else if (!strcmp(argv[i],"-area")) {
			areaScale *= atof(argv[i+1]);
			_printf ("area light scaling at %f\n", areaScale);
			i++;
		} else if (!strcmp(argv[i],"-point")) {
			pointScale *= atof(argv[i+1]);
			_printf ("point light scaling at %f\n", pointScale);
			i++;
		} else if (!strcmp(argv[i],"-notrace")) {
			notrace = qtrue;
			_printf ("No occlusion tracing\n");
		} else if (!strcmp(argv[i],"-patchshadows")) {
			patchshadows = qtrue;
			_printf ("Patch shadow casting enabled\n");
		} else if (!strcmp(argv[i],"-extra")) {
			extra = qtrue;
			_printf ("Extra detail tracing\n");
		} else if (!strcmp(argv[i],"-extrawide")) {
			extra = qtrue;
			extraWide = qtrue;
			_printf ("Extra wide detail tracing\n");
		} else if (!strcmp(argv[i], "-samplesize")) {
			samplesize = atoi(argv[i+1]);
			if (samplesize < 1) samplesize = 1;
			i++;
			_printf("lightmap sample size is %dx%d units\n", samplesize, samplesize);
		} else if (!strcmp(argv[i], "-novertex")) {
			novertexlighting = qtrue;
			_printf("no vertex lighting = true\n");
		} else if (!strcmp(argv[i], "-nogrid")) {
			nogridlighting = qtrue;
			_printf("no grid lighting = true\n");
		} else if (!strcmp(argv[i],"-border")) {
			lightmapBorder = qtrue;
			_printf ("Adding debug border to lightmaps\n");
		} else if (!strcmp(argv[i],"-nosurf")) {
			noSurfaces = qtrue;
			_printf ("Not tracing against surfaces\n" );
		} else if (!strcmp(argv[i],"-dump")) {
			dump = qtrue;
			_printf ("Dumping occlusion maps\n");
		} else {
			break;
		}
	}

	ThreadSetDefault ();

	if (i != argc - 1) {
		_printf("usage: q3map -light [-<switch> [-<switch> ...]] <mapname>\n"
				"\n"
				"Switches:\n"
				"   v              = verbose output\n"
				"   threads <X>    = set number of threads to X\n"
				"   area <V>       = set the area light scale to V\n"
				"   point <W>      = set the point light scale to W\n"
				"   notrace        = don't cast any shadows\n"
				"   extra          = enable super sampling for anti-aliasing\n"
				"   extrawide      = same as extra but smoothen more\n"
				"   nogrid         = don't calculate light grid for dynamic model lighting\n"
				"   novertex       = don't calculate vertex lighting\n"
				"   samplesize <N> = set the lightmap pixel size to NxN units\n");
		exit(0);
	}

	start = I_FloatTime ();

	SetQdirFromPath (argv[i]);	

#ifdef _WIN32
	InitPakFile(gamedir, NULL);
#endif

	strcpy (source, ExpandArg(argv[i]));
	StripExtension (source);
	DefaultExtension (source, ".bsp");

	LoadShaderInfo();

	_printf ("reading %s\n", source);

	LoadBSPFile (source);

	FindSkyBrushes();

	ParseEntities();

	value = ValueForKey( &entities[0], "gridsize" );
	if (strlen(value)) {
		sscanf( value, "%f %f %f", &gridSize[0], &gridSize[1], &gridSize[2] );
		_printf("grid size = {%1.1f, %1.1f, %1.1f}\n", gridSize[0], gridSize[1], gridSize[2]);
	}

	CreateFilters();

	InitTrace();

	SetEntityOrigins();

	CountLightmaps();

	CreateSurfaceLights();

	LightWorld();

	_printf ("writing %s\n", source);
	WriteBSPFile (source);

	end = I_FloatTime ();
	_printf ("%5.0f seconds elapsed\n", end-start);
	
	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -