Пример #1
0
//#define	LIGHTMAP_BLOCK	16
void AllocateLightmapForSurface( mapDrawSurface_t *ds ) {
	vec3_t		mins, maxs, size, exactSize, delta;
	int			i;
	drawVert_t	*verts;
	int			w, h;
	int			x, y, ssize;
	int			axis;
	vec3_t		vecs[2];
	float		s, t;
	vec3_t		origin;
	plane_t		*plane;
	float		d;
	vec3_t		planeNormal;

	if ( ds->patch ) {
		AllocateLightmapForPatch( ds );
		return;
	}

	ssize = samplesize;
	if (ds->shaderInfo->lightmapSampleSize)
		ssize = ds->shaderInfo->lightmapSampleSize;

	plane = &mapplanes[ ds->side->planenum ];

	// bound the surface
	ClearBounds( mins, maxs );
	verts = ds->verts;
	for ( i = 0 ; i < ds->numVerts ; i++ ) {
		AddPointToBounds( verts[i].xyz, mins, maxs );
	}

	// round to the lightmap resolution
	for ( i = 0 ; i < 3 ; i++ ) {
		exactSize[i] = maxs[i] - mins[i];
		mins[i] = ssize * floor( mins[i] / ssize );
		maxs[i] = ssize * ceil( maxs[i] / ssize );
		size[i] = (maxs[i] - mins[i]) / ssize + 1;
	}

	// the two largest axis will be the lightmap size
	memset( vecs, 0, sizeof( vecs ) );

	planeNormal[0] = fabs( plane->normal[0] );
	planeNormal[1] = fabs( plane->normal[1] );
	planeNormal[2] = fabs( plane->normal[2] );

	if ( planeNormal[0] >= planeNormal[1] && planeNormal[0] >= planeNormal[2] ) {
		w = size[1];
		h = size[2];
		axis = 0;
		vecs[0][1] = 1.0 / ssize;
		vecs[1][2] = 1.0 / ssize;
	} else if ( planeNormal[1] >= planeNormal[0] && planeNormal[1] >= planeNormal[2] ) {
		w = size[0];
		h = size[2];
		axis = 1;
		vecs[0][0] = 1.0 / ssize;
		vecs[1][2] = 1.0 / ssize;
	} else {
		w = size[0];
		h = size[1];
		axis = 2;
		vecs[0][0] = 1.0 / ssize;
		vecs[1][1] = 1.0 / ssize;
	}

	if ( !plane->normal[axis] ) {
		Error( "Chose a 0 valued axis" );
	}

	if ( w > LIGHTMAP_WIDTH ) {
		VectorScale ( vecs[0], (float)LIGHTMAP_WIDTH/w, vecs[0] );
		w = LIGHTMAP_WIDTH;
	}
	
	if ( h > LIGHTMAP_HEIGHT ) {
		VectorScale ( vecs[1], (float)LIGHTMAP_HEIGHT/h, vecs[1] );
		h = LIGHTMAP_HEIGHT;
	}
	
	c_exactLightmap += w * h;

	if ( !AllocLMBlock( w, h, &x, &y ) ) {
		PrepareNewLightmap();
		if ( !AllocLMBlock( w, h, &x, &y ) ) {
			Error("Entity %i, brush %i: Lightmap allocation failed", 
				ds->mapBrush->entitynum, ds->mapBrush->brushnum );
		}
	}

	// set the lightmap texture coordinates in the drawVerts
	ds->lightmapNum = numLightmaps - 1;
	ds->lightmapWidth = w;
	ds->lightmapHeight = h;
	ds->lightmapX = x;
	ds->lightmapY = y;

	for ( i = 0 ; i < ds->numVerts ; i++ ) {
		VectorSubtract( verts[i].xyz, mins, delta );
		s = DotProduct( delta, vecs[0] ) + x + 0.5;
		t = DotProduct( delta, vecs[1] ) + y + 0.5;
		verts[i].lightmap[0] = s / LIGHTMAP_WIDTH;
		verts[i].lightmap[1] = t / LIGHTMAP_HEIGHT;
	}

	// calculate the world coordinates of the lightmap samples

	// project mins onto plane to get origin
	d = DotProduct( mins, plane->normal ) - plane->dist;
	d /= plane->normal[ axis ];
	VectorCopy( mins, origin );
	origin[axis] -= d;

	// project stepped lightmap blocks and subtract to get planevecs
	for ( i = 0 ; i < 2 ; i++ ) {
		vec3_t	normalized;
		float	len;

		len = VectorNormalize( vecs[i], normalized );
		VectorScale( normalized, (1.0/len), vecs[i] );
		d = DotProduct( vecs[i], plane->normal );
		d /= plane->normal[ axis ];
		vecs[i][axis] -= d;
	}

	VectorCopy( origin, ds->lightmapOrigin );
	VectorCopy( vecs[0], ds->lightmapVecs[0] );
	VectorCopy( vecs[1], ds->lightmapVecs[1] );
	VectorCopy( plane->normal, ds->lightmapVecs[2] );
}
Пример #2
0
void AllocateLightmapForPatch( mapDrawSurface_t *ds ) {
	int			i, j, k;
	drawVert_t	*verts;
	int			w, h;
	int			x, y;
	float		s, t;
	mesh_t		mesh, *subdividedMesh, *tempMesh, *newmesh;
	int			widthtable[LIGHTMAP_WIDTH], heighttable[LIGHTMAP_HEIGHT], ssize;

	verts = ds->verts;

	mesh.width = ds->patchWidth;
	mesh.height = ds->patchHeight;
	mesh.verts = verts;
	newmesh = SubdivideMesh( mesh, 8, 999 );

	PutMeshOnCurve( *newmesh );
	tempMesh = RemoveLinearMeshColumnsRows( newmesh );
	FreeMesh(newmesh);

	ssize = samplesize;
	if (ds->shaderInfo->lightmapSampleSize)
		ssize = ds->shaderInfo->lightmapSampleSize;

#ifdef LIGHTMAP_PATCHSHIFT
	subdividedMesh = SubdivideMeshQuads( tempMesh, ssize, LIGHTMAP_WIDTH-1, widthtable, heighttable);
#else
	subdividedMesh = SubdivideMeshQuads( tempMesh, ssize, LIGHTMAP_WIDTH, widthtable, heighttable);
#endif

	w = subdividedMesh->width;
	h = subdividedMesh->height;

#ifdef LIGHTMAP_PATCHSHIFT
	w++;
	h++;
#endif

	FreeMesh(subdividedMesh);

	// allocate the lightmap
	c_exactLightmap += w * h;

	if ( !AllocLMBlock( w, h, &x, &y ) ) {
		PrepareNewLightmap();
		if ( !AllocLMBlock( w, h, &x, &y ) ) {
			Error("Entity %i, brush %i: Lightmap allocation failed", 
				ds->mapBrush->entitynum, ds->mapBrush->brushnum );
		}
	}

#ifdef LIGHTMAP_PATCHSHIFT
	w--;
	h--;
#endif

	// set the lightmap texture coordinates in the drawVerts
	ds->lightmapNum = numLightmaps - 1;
	ds->lightmapWidth = w;
	ds->lightmapHeight = h;
	ds->lightmapX = x;
	ds->lightmapY = y;

	for ( i = 0 ; i < ds->patchWidth ; i++ ) {
		for ( k = 0 ; k < w ; k++ ) {
			if ( originalWidths[k] >= i ) {
				break;
			}
		}
		if (k >= w)
			k = w-1;
		s = x + k;
		for ( j = 0 ; j < ds->patchHeight ; j++ ) {
			for ( k = 0 ; k < h ; k++ ) {
				if ( originalHeights[k] >= j ) {
					break;
				}
			}
			if (k >= h)
				k = h-1;
			t = y + k;
			verts[i + j * ds->patchWidth].lightmap[0] = ( s + 0.5 ) / LIGHTMAP_WIDTH;
			verts[i + j * ds->patchWidth].lightmap[1] = ( t + 0.5 ) / LIGHTMAP_HEIGHT;
		}
	}
}
Пример #3
0
void AllocateLightmapForSurface( mapDrawSurface_t *ds )
{
	vec3_t		mins, maxs, size, exactSize, delta;
	int			i;
	drawVert_t	*verts;
	int			w, h;
 	int			x, y, ssize;
	int			axis;
	vec3_t		vecs[ 2 ];
	float		s, t;
	vec3_t		origin;
	vec4_t		plane;
	float		d;
	
	
	/* debug code */
	#if 0
		if( ds->type == SURF_META && ds->planar == qfalse )
			Sys_Printf( "NPMS: %3d vertexes, %s\n", ds->numVerts, ds->shaderInfo->shader );
		else if( ds->type == SURF_META && ds->planar == qtrue )
			Sys_Printf( "PMS:  %3d vertexes, %s\n", ds->numVerts, ds->shaderInfo->shader );
	#endif
	
	/* ydnar: handle planar patches */
	if( noPatchFix == qtrue || (ds->type == SURF_PATCH && ds->planeNum < 0) )
	{
		AllocateLightmapForPatch( ds );
		return;
	}
	
	/* get sample size */
 	ssize = ds->sampleSize;
	
	/* bound the surface */
	ClearBounds( mins, maxs );
	verts = ds->verts;
	for ( i = 0 ; i < ds->numVerts ; i++ )
		AddPointToBounds( verts[i].xyz, mins, maxs );
	
	/* round to the lightmap resolution */
	for( i = 0; i < 3; i++ )
	{
		exactSize[i] = maxs[i] - mins[i];
 		mins[i] = ssize * floor( mins[i] / ssize );
 		maxs[i] = ssize * ceil( maxs[i] / ssize );
 		size[i] = (maxs[i] - mins[i]) / ssize + 1;
	}
	
	/* ydnar: lightmap projection axis is already stored */
	memset( vecs, 0, sizeof( vecs ) );
	
	/* classify the plane (x y or z major) (ydnar: biased to z axis projection) */
	if( ds->lightmapAxis[ 2 ] >= ds->lightmapAxis[ 0 ] && ds->lightmapAxis[ 2 ] >= ds->lightmapAxis[ 1 ] )
	{
		w = size[ 0 ];
		h = size[ 1 ];
		axis = 2;
		vecs[ 0 ][ 0 ] = 1.0 / ssize;
		vecs[ 1 ][ 1 ] = 1.0 / ssize;
	}
	else if( ds->lightmapAxis[ 0 ] >= ds->lightmapAxis[ 1 ] && ds->lightmapAxis[ 0 ] >= ds->lightmapAxis[ 2 ] )
	{
		w = size[ 1 ];
		h = size[ 2 ];
		axis = 0;
		vecs[ 0 ][ 1 ] = 1.0 / ssize;
		vecs[ 1 ][ 2 ] = 1.0 / ssize;
	}
	else
	{
		w = size[ 0 ];
		h = size[ 2 ];
		axis = 1;
		vecs[ 0 ][ 0 ] = 1.0 / ssize;
		vecs[ 1 ][ 2 ] = 1.0 / ssize;
	}
	
	/* odd check, given projection is now precalculated */
	if( ds->lightmapAxis[ axis ] == 0 )
		Error( "Chose a 0 valued axis" );
	
	/* clamp to lightmap texture resolution */
	if( w > LIGHTMAP_WIDTH )
	{
		VectorScale ( vecs[0], (float) LIGHTMAP_WIDTH / w, vecs[0] );
		w = LIGHTMAP_WIDTH;
	}
	if( h > LIGHTMAP_HEIGHT )
	{
		VectorScale ( vecs[1], (float) LIGHTMAP_HEIGHT / h, vecs[1] );
		h = LIGHTMAP_HEIGHT;
	}
	
	
	/* ydnar */
	if( ds->planar == qfalse )
		c_nonplanarLightmap += w * h;
	c_exactLightmap += w * h;
	
	
	if( !AllocLMBlock( w, h, &x, &y ) )
	{
		PrepareNewLightmap();
		if ( !AllocLMBlock( w, h, &x, &y ) )
		{
			Error( "Entity %i, brush %i: Lightmap allocation failed", 
				ds->mapBrush->entitynum, ds->mapBrush->brushnum );
		}
	}

	/* set the lightmap texture coordinates in the drawVerts */
	ds->lightmapNum = numLightmaps - 1;
	ds->lightmapWidth = w;
	ds->lightmapHeight = h;
	ds->lightmapX = x;
	ds->lightmapY = y;
	for ( i = 0 ; i < ds->numVerts ; i++ )
	{
		VectorSubtract( verts[i].xyz, mins, delta );
		s = DotProduct( delta, vecs[0] ) + x + 0.5;
		t = DotProduct( delta, vecs[1] ) + y + 0.5;
		verts[i].lightmap[0] = s / LIGHTMAP_WIDTH;
		verts[i].lightmap[1] = t / LIGHTMAP_HEIGHT;
	}

	/* calculate the world coordinates of the lightmap samples */
	
	/* construct a plane from the first vert and clear bounding box */
	
	/* project mins onto plane to get origin */
	VectorCopy( ds->lightmapVecs[ 2 ], plane );
	plane[ 3 ] = DotProduct( ds->verts[ 0 ].xyz, plane );
	d = DotProduct( mins, plane ) - plane[ 3 ];
	d /= plane[ axis ];
	
	//% d = DotProduct( mins, plane->normal ) - plane->dist;
	//% d /= plane->normal[ axis ];
	VectorCopy( mins, origin );
	origin[ axis ] -= d;

	/* project stepped lightmap blocks and subtract to get planevecs */
	for( i = 0; i < 2; i++ )
	{
		vec3_t	normalized;
		float	len;

		len = VectorNormalize( vecs[i], normalized );
		VectorScale( normalized, (1.0/len), vecs[i] );
		d = DotProduct( vecs[i], plane );
		d /= plane[ axis ];
		//%d = DotProduct( vecs[i], plane->normal );
		//%d /= plane->normal[ axis ];
		vecs[i][axis] -= d;
	}
	
	/* store lightmap origin and vectors (fixme: make this work right) */
	VectorCopy( origin, ds->lightmapOrigin );
	//% VectorCopy( plane->normal, ds->lightmapVecs[ 2 ] );
	
	/* ydnar: lightmap vectors 0 and 1 are used for lod bounds, so don't overwrite */
	if( ds->type == SURF_PATCH )
		c_planarPatch++;
	
	/* store lightmap vectors */
	VectorCopy( vecs[ 0 ], ds->lightmapVecs[ 0 ] );
	VectorCopy( vecs[ 1 ], ds->lightmapVecs[ 1 ] );
	
	/* ydnar: print some stats */
	//Sys_FPrintf( SYS_VRB, "Lightmap block %3d (%3d, %3d) (%3d x %3d) emitted\n", (numLightmaps - 1), x, y, w, h );
}