// Setup a CCoreDispInfo given a mapdispinfo_t.
// If pFace is non-NULL, then lightmap texture coordinates will be generated.
void DispMapToCoreDispInfo( 
	mapdispinfo_t *pMapDisp,
	CCoreDispInfo *pCoreDispInfo,
	dface_t *pFace )
{
	winding_t *pWinding = pMapDisp->face.originalface->winding;

	Assert( pWinding->numpoints == 4 );

	//
	// set initial surface data
	//
	CCoreDispSurface *pSurf = pCoreDispInfo->GetSurface();

	texinfo_t *pTexInfo = &texinfo[ pMapDisp->face.texinfo ];

	// init material contents
	pMapDisp->contents = textureref[pTexInfo->texdata].contents;
	if (!(pMapDisp->contents & (ALL_VISIBLE_CONTENTS | CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) ) )
	{
		pMapDisp->contents |= CONTENTS_SOLID;
	}

	pSurf->SetContents( pMapDisp->contents );

	// Calculate the lightmap coordinates.
	Vector2D lmCoords[4] = {Vector2D(0,0),Vector2D(0,1),Vector2D(1,0),Vector2D(1,1)};
	Vector2D tCoords[4] = {Vector2D(0,0),Vector2D(0,1),Vector2D(1,0),Vector2D(1,1)};
	if( pFace )
	{
		Assert( pFace->numedges == 4 );

		Vector pt[4];
		for( int i=0; i < 4; i++ )
			pt[i] = pWinding->p[i];

		CalcTextureCoordsAtPoints( 
			pTexInfo->lightmapVecsLuxelsPerWorldUnits,
			pFace->m_LightmapTextureMinsInLuxels,
			pt,
			4,
			lmCoords );

		int zeroOffset[2] = {0,0};
		CalcTextureCoordsAtPoints( 
			pTexInfo->textureVecsTexelsPerWorldUnits,
			zeroOffset,
			pt,
			4,
			tCoords );
	}
	
	//
	// set face point data ...
	//
	pSurf->SetPointCount( 4 );
	for( int i = 0; i < 4; i++ )
	{
		// position
		pSurf->SetPoint( i, pWinding->p[i] );
		for( int j = 0; j < ( NUM_BUMP_VECTS + 1 ); ++j )
		{
			pSurf->SetLuxelCoord( j, i, lmCoords[i] );
		}
		pSurf->SetTexCoord( i, tCoords[i] );
	}
	
	//
	// reset surface given start info
	//
	pSurf->SetPointStart( pMapDisp->startPosition );
	pSurf->FindSurfPointStartIndex();
	pSurf->AdjustSurfPointData();

	//
	// adjust face lightmap data - this will be done a bit more accurately
	// when the common code get written, for now it works!!! (GDC, E3)
	//
	Vector points[4];
	for( int ndxPt = 0; ndxPt < 4; ndxPt++ )
	{
		points[ndxPt] = pSurf->GetPoint( ndxPt );
	}
	Vector edgeU = points[3] - points[0];
	Vector edgeV = points[1] - points[0];
	bool bUMajor = ( edgeU.Length() > edgeV.Length() );

	if( pFace )
	{
		int lightmapWidth = pFace->m_LightmapTextureSizeInLuxels[0];
		int lightmapHeight = pFace->m_LightmapTextureSizeInLuxels[1];
		if ( ( bUMajor && ( lightmapHeight > lightmapWidth ) ) || 
			 ( !bUMajor && ( lightmapWidth > lightmapHeight ) ) )
		{
			pFace->m_LightmapTextureSizeInLuxels[0] = lightmapHeight;
			pFace->m_LightmapTextureSizeInLuxels[1] = lightmapWidth;

			lightmapWidth = lightmapHeight;
			lightmapHeight = pFace->m_LightmapTextureSizeInLuxels[1];
		}

		for ( int ndxBump = 0; ndxBump < ( NUM_BUMP_VECTS + 1 ); ndxBump++ )
		{
			pSurf->SetLuxelCoord( ndxBump, 0, Vector2D( 0.0f, 0.0f ) );
			pSurf->SetLuxelCoord( ndxBump, 1, Vector2D( 0.0f, ( float )lightmapHeight ) );
			pSurf->SetLuxelCoord( ndxBump, 2, Vector2D( ( float )lightmapWidth, ( float )lightmapHeight ) );
			pSurf->SetLuxelCoord( ndxBump, 3, Vector2D( ( float )lightmapWidth, 0.0f ) );
		}
	}

	// Setup the displacement vectors and offsets.
	int size = ( ( ( 1 << pMapDisp->power ) + 1 ) * ( ( 1 << pMapDisp->power ) + 1 ) );

	Vector vectorDisps[2048];
	float dispDists[2048];
	Assert( size < sizeof(vectorDisps)/sizeof(vectorDisps[0]) );

	for( int j = 0; j < size; j++ )
	{
		Vector v;
		float dist;

		VectorScale( pMapDisp->vectorDisps[j], pMapDisp->dispDists[j], v );
		VectorAdd( v, pMapDisp->vectorOffsets[j], v );
		
		dist = VectorLength( v );
		VectorNormalize( v );
		
		vectorDisps[j] = v;
		dispDists[j] = dist;
	}


	// Use CCoreDispInfo to setup the actual vertex positions.
	pCoreDispInfo->InitDispInfo( pMapDisp->power, pMapDisp->minTess, pMapDisp->smoothingAngle,
						 pMapDisp->alphaValues, vectorDisps, dispDists );
	pCoreDispInfo->Create();
}
示例#2
0
// Setup a CCoreDispInfo given a mapdispinfo_t.
// If pFace is non-NULL, then lightmap texture coordinates will be generated.
void DispMapToCoreDispInfo( mapdispinfo_t *pMapDisp, CCoreDispInfo *pCoreDispInfo, dface_t *pFace, int *pSwappedTexInfos )
{
	winding_t *pWinding = pMapDisp->face.originalface->winding;

	Assert( pWinding->numpoints == 4 );

	//
	// set initial surface data
	//
	CCoreDispSurface *pSurf = pCoreDispInfo->GetSurface();

	texinfo_t *pTexInfo = &texinfo[ pMapDisp->face.texinfo ];
	Assert( pTexInfo != NULL );

	// init material contents
	pMapDisp->contents = pMapDisp->face.contents;
	if (!(pMapDisp->contents & (ALL_VISIBLE_CONTENTS | CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) ) )
	{
		pMapDisp->contents |= CONTENTS_SOLID;
	}

	pSurf->SetContents( pMapDisp->contents );

	// Calculate the lightmap coordinates.
	Vector2D tCoords[4] = {Vector2D(0,0),Vector2D(0,1),Vector2D(1,0),Vector2D(1,1)};
	if( pFace )
	{
		Assert( pFace->numedges == 4 );

		Vector pt[4];
		for( int i=0; i < 4; i++ )
			pt[i] = pWinding->p[i];

		int zeroOffset[2] = {0,0};
		CalcTextureCoordsAtPoints( 
			pTexInfo->textureVecsTexelsPerWorldUnits,
			zeroOffset,
			pt,
			4,
			tCoords );
	}
	
	//
	// set face point data ...
	//
	pSurf->SetPointCount( 4 );
	for( int i = 0; i < 4; i++ )
	{
		// position
		pSurf->SetPoint( i, pWinding->p[i] );
		pSurf->SetTexCoord( i, tCoords[i] );
	}
	
	// reset surface given start info
	pSurf->SetPointStart( pMapDisp->startPosition );
	pSurf->FindSurfPointStartIndex();
	pSurf->AdjustSurfPointData();

	// Set the luxel coordinates on the base displacement surface.
	Vector vecTmp( pTexInfo->lightmapVecsLuxelsPerWorldUnits[0][0],
				   pTexInfo->lightmapVecsLuxelsPerWorldUnits[0][1],
				   pTexInfo->lightmapVecsLuxelsPerWorldUnits[0][2] );
	int nLuxelsPerWorldUnit = static_cast<int>( 1.0f / VectorLength( vecTmp ) );
	Vector vecU( pTexInfo->lightmapVecsLuxelsPerWorldUnits[0][0],
				 pTexInfo->lightmapVecsLuxelsPerWorldUnits[0][1],
				 pTexInfo->lightmapVecsLuxelsPerWorldUnits[0][2] );
	Vector vecV( pTexInfo->lightmapVecsLuxelsPerWorldUnits[1][0],
				 pTexInfo->lightmapVecsLuxelsPerWorldUnits[1][1],
				 pTexInfo->lightmapVecsLuxelsPerWorldUnits[1][2] );
	bool bSwap = pSurf->CalcLuxelCoords( nLuxelsPerWorldUnit, false, vecU, vecV );

	// Set the face m_LightmapExtents
	if ( pFace )
	{
		pFace->m_LightmapTextureSizeInLuxels[0] = pSurf->GetLuxelU();
		pFace->m_LightmapTextureSizeInLuxels[1] = pSurf->GetLuxelV();
		if ( bSwap )
		{
			if ( pSwappedTexInfos[ pMapDisp->face.texinfo ] < 0 )
			{
				// Create a new texinfo to hold the swapped data.
				// We must do this because other surfaces may want the non-swapped data
				// This fixes a lighting bug in d2_prison_08 where many non-displacement surfaces
				// were pitch black, in addition to bugs in other maps I bet.

				// NOTE: Copy here because adding a texinfo could realloc.
				texinfo_t temp = *pTexInfo;
				memcpy( temp.lightmapVecsLuxelsPerWorldUnits[0], pTexInfo->lightmapVecsLuxelsPerWorldUnits[1], 4 * sizeof(float) );
				memcpy( temp.lightmapVecsLuxelsPerWorldUnits[1], pTexInfo->lightmapVecsLuxelsPerWorldUnits[0], 4 * sizeof(float) );
				temp.lightmapVecsLuxelsPerWorldUnits[1][0] *= -1.0f;
				temp.lightmapVecsLuxelsPerWorldUnits[1][1] *= -1.0f;
				temp.lightmapVecsLuxelsPerWorldUnits[1][2] *= -1.0f;
				temp.lightmapVecsLuxelsPerWorldUnits[1][3] *= -1.0f;
				pSwappedTexInfos[ pMapDisp->face.texinfo ] = texinfo.AddToTail( temp );
			}
			pMapDisp->face.texinfo = pSwappedTexInfos[ pMapDisp->face.texinfo ];
		}

		// NOTE: This is here to help future-proof code, since there are codepaths where
		// pTexInfo can be made invalid (texinfo.AddToTail above).
		pTexInfo = NULL;
	}

	// Setup the displacement vectors and offsets.
	int size = ( ( ( 1 << pMapDisp->power ) + 1 ) * ( ( 1 << pMapDisp->power ) + 1 ) );

	Vector vectorDisps[2048];
	float dispDists[2048];
	Assert( size < sizeof(vectorDisps)/sizeof(vectorDisps[0]) );

	for( int j = 0; j < size; j++ )
	{
		Vector v;
		float dist;

		VectorScale( pMapDisp->vectorDisps[j], pMapDisp->dispDists[j], v );
		VectorAdd( v, pMapDisp->vectorOffsets[j], v );
		
		dist = VectorLength( v );
		VectorNormalize( v );
		
		vectorDisps[j] = v;
		dispDists[j] = dist;
	}


	// Use CCoreDispInfo to setup the actual vertex positions.
	pCoreDispInfo->InitDispInfo( pMapDisp->power, pMapDisp->minTess, pMapDisp->smoothingAngle,
						 pMapDisp->alphaValues, vectorDisps, dispDists );
	pCoreDispInfo->Create();
}