//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- 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(); }
// 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(); }