static void AddNeighbor( const CCoreDispInfo *pListBase, CCoreDispInfo *pMain, int iEdge, // Which of pMain's sides this is on. int iSub, // Which sub neighbor this takes up in pSide. NeighborSpan span, // What span this fills in pMain. CCoreDispInfo *pOther, int iNeighborEdge, NeighborSpan nbSpan ) { // The edge iteration before coming in here goes 0-1, 1-2, 2-3, 3-4. // This flips the sense of CORNER_TO_MIDPOINT/MIDPOINT_TO_CORNER on the right and // bottom edges and is undone here. span = NeighborSpanFlip( iEdge, span ); nbSpan = NeighborSpanFlip( iNeighborEdge, nbSpan ); // Get the subspan this fills on our displacement. CDispSubNeighbor *pSub = &pMain->GetEdgeNeighbor(iEdge)->m_SubNeighbors[iSub]; // Which subspan does this use in the neighbor? CDispSubNeighbor *pNeighborSub; if ( nbSpan == MIDPOINT_TO_CORNER ) pNeighborSub = &pOther->GetEdgeNeighbor(iNeighborEdge)->m_SubNeighbors[1]; else pNeighborSub = &pOther->GetEdgeNeighbor(iNeighborEdge)->m_SubNeighbors[0]; // Make sure this slot isn't used on either displacement. if ( pSub->IsValid() || pNeighborSub->IsValid() ) { ExecuteOnce( Warning( "Found a displacement edge abutting multiple other edges.\n" ) ); return; } // Now just copy the data into each displacement. pSub->m_iNeighbor = pOther - pListBase; pSub->m_NeighborOrientation = g_CoreDispNeighborOrientationMap[iEdge][iNeighborEdge]; pSub->m_Span = span; pSub->m_NeighborSpan = nbSpan; pNeighborSub->m_iNeighbor = pMain - pListBase; pNeighborSub->m_NeighborOrientation = g_CoreDispNeighborOrientationMap[iNeighborEdge][iEdge]; pNeighborSub->m_Span = nbSpan; pNeighborSub->m_NeighborSpan = span; #if defined( _DEBUG ) // Walk an iterator over the new connection to make sure it works. CDispSubEdgeIterator it; it.Start( pMain, iEdge, iSub ); while ( it.Next() ) { CVertIndex nbIndex; TransformIntoNeighbor( pMain, iEdge, it.GetVertIndex(), nbIndex ); } #endif }
void BlendEdges( CCoreDispInfo **ppListBase, int listSize ) { for ( int iDisp=0; iDisp < listSize; iDisp++ ) { CCoreDispInfo *pDisp = ppListBase[iDisp]; for ( int iEdge=0; iEdge < 4; iEdge++ ) { CDispNeighbor *pEdge = pDisp->GetEdgeNeighbor( iEdge ); for ( int iSub=0; iSub < 2; iSub++ ) { CDispSubNeighbor *pSub = &pEdge->m_SubNeighbors[iSub]; if ( !pSub->IsValid() ) continue; CCoreDispInfo *pNeighbor = ppListBase[ pSub->GetNeighborIndex() ]; int iEdgeDim = g_EdgeDims[iEdge]; CDispSubEdgeIterator it; it.Start( pDisp, iEdge, iSub, true ); // Get setup on the first corner vert. it.Next(); CVertIndex viPrevPos = it.GetVertIndex(); while ( it.Next() ) { // Blend the two. if ( !it.IsLastVert() ) { Vector vAverage = pDisp->GetNormal( it.GetVertIndex() ) + pNeighbor->GetNormal( it.GetNBVertIndex() ); VectorNormalize( vAverage ); pDisp->SetNormal( it.GetVertIndex(), vAverage ); pNeighbor->SetNormal( it.GetNBVertIndex(), vAverage ); #if defined( USE_SCRATCHPAD ) ScratchPad_DrawArrowSimple( g_pPad, pDisp->GetVert( it.GetVertIndex() ), pDisp->GetNormal( it.GetVertIndex() ), Vector( 1, 0, 0 ), 25 ); #endif } // Now blend the in-between verts (if this edge is high-res). int iPrevPos = viPrevPos[ !iEdgeDim ]; int iCurPos = it.GetVertIndex()[ !iEdgeDim ]; for ( int iTween = iPrevPos+1; iTween < iCurPos; iTween++ ) { float flPercent = RemapVal( iTween, iPrevPos, iCurPos, 0, 1 ); Vector vNormal; VectorLerp( pDisp->GetNormal( viPrevPos ), pDisp->GetNormal( it.GetVertIndex() ), flPercent, vNormal ); VectorNormalize( vNormal ); CVertIndex viTween; viTween[iEdgeDim] = it.GetVertIndex()[ iEdgeDim ]; viTween[!iEdgeDim] = iTween; pDisp->SetNormal( viTween, vNormal ); #if defined( USE_SCRATCHPAD ) ScratchPad_DrawArrowSimple( g_pPad, pDisp->GetVert( viTween ), pDisp->GetNormal( viTween ), Vector( 1, 0.5, 0 ), 25 ); #endif } viPrevPos = it.GetVertIndex(); } } } } }