//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
bool CVRADDispColl::Create( CCoreDispInfo *pDisp )
{
	// Base class create.
	if( !CDispCollTree::Create( pDisp ) )
		return false;

	// Allocate VRad specific memory.
	m_aLuxelCoords.SetSize( GetSize() );
	m_aVertNormals.SetSize( GetSize() );

	// VRad specific base surface data.
	CCoreDispSurface *pSurf = pDisp->GetSurface();
	m_iParent = pSurf->GetHandle();

	// VRad specific displacement surface data.
	for ( int iVert = 0; iVert < m_aVerts.Count(); ++iVert )
	{
		pDisp->GetNormal( iVert, m_aVertNormals[iVert] );
		pDisp->GetLuxelCoord( 0, iVert, m_aLuxelCoords[iVert] );
	}

	// Re-calculate the lightmap size (in uv) so that the luxels give
	// a better world-space uniform approx. due to the non-linear nature
	// of the displacement surface in uv-space
	dface_t *pFace = &g_pFaces[m_iParent];
	if( pFace )
	{
		CalcSampleRadius2AndBox( pFace );	
	}

	return true;
}
static bool FindEdge( 
	CCoreDispInfo *pInfo,
	Vector const &vPoint1,
	Vector const &vPoint2,
	int &iEdge 
	)
{
	CCoreDispSurface *pSurface = pInfo->GetSurface();

	for( iEdge=0; iEdge < 4; iEdge++ )
	{
		if( VectorsAreEqual( vPoint1, pSurface->GetPoint( iEdge ), 0.01f ) &&
			VectorsAreEqual( vPoint2, pSurface->GetPoint( (iEdge+1) & 3), 0.01f ) )
		{
			return true;
		}
	}
	
	return false;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
bool CVRADDispColl::Create( CCoreDispInfo *pDisp )
{
	// save the face index for later reference
	CCoreDispSurface *pSurf = pDisp->GetSurface();
	m_ndxParent = pSurf->GetHandle();

	// save the size of the displacement surface
	m_Power = pDisp->GetPower();

	// save the displacement to base face point offset
	m_PointOffset = pSurf->GetPointStartIndex();

	//
	// get base surface points and normals
	//
	int i;
	m_PointCount = pSurf->GetPointCount();
	for( i = 0; i < m_PointCount; i++ )
	{
		Vector point, normal;
		pSurf->GetPoint( i, point );
		pSurf->GetPointNormal( i, normal );

		m_Points[i].Init( point[0], point[1], point[2] );
		m_PointNormals[i].Init( normal[0], normal[1], normal[2] );
	}

	// create the collision data
	if( !CDispCollTree::Create( pDisp ) )
		return false;

	// Set up the luxel data
	m_pLuxelCoords = new Vector2D[GetSize()];
	assert( m_pLuxelCoords );
	for ( i = GetSize(); --i >= 0; )
	{
		pDisp->GetLuxelCoord( 0, i, m_pLuxelCoords[i] );	
	}


	//
	// re-calculate the lightmap size (in uv) so that the luxels give
	// a better world-space uniform approx. due to the non-linear nature
	// of the displacement surface in uv-space
	//
	dface_t *pFace = &dfaces[m_ndxParent];
	if( pFace )
	{
		CalcSampleRadius2AndBox( pFace );	
	}

	//
	// create the vrad specific node data - build for radiosity transfer,
	// don't create for direct lighting only!
	//
	m_pVNodes = new VNode_t[m_NodeCount];
	if( !m_pVNodes )
		return false;
	
	BuildVNodes();

	return true;
}
// 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();
}
Exemple #5
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();
}