summaryrefslogtreecommitdiff
path: root/hammer/DispShore.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /hammer/DispShore.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'hammer/DispShore.cpp')
-rw-r--r--hammer/DispShore.cpp1234
1 files changed, 1234 insertions, 0 deletions
diff --git a/hammer/DispShore.cpp b/hammer/DispShore.cpp
new file mode 100644
index 0000000..96b40b6
--- /dev/null
+++ b/hammer/DispShore.cpp
@@ -0,0 +1,1234 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+//
+//=============================================================================
+
+#include <stdafx.h>
+#include "FaceEditSheet.h"
+#include "MainFrm.h"
+#include "GlobalFunctions.h"
+#include "MapDisp.h"
+#include "DispShore.h"
+#include "utlvector.h"
+#include "mapdoc.h"
+#include "mapworld.h"
+#include "mapsolid.h"
+#include "materialsystem/imesh.h"
+#include "Material.h"
+#include "collisionutils.h"
+#include "TextureSystem.h"
+#include "mapoverlay.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include <tier0/memdbgon.h>
+
+IMPLEMENT_MAPCLASS( CMapOverlayTransition )
+
+#define DISPSHORE_WIDTH_WORLD 25.0f
+#define DISPSHORE_WIDTH_WATER 25.0f
+#define DISPSHORE_VECTOR_EPS 0.1f
+#define DISPSHORE_SURF_LENGTH 120.0f
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+Shoreline_t::Shoreline_t()
+{
+ m_nShorelineId = -1;
+ m_aSegments.Purge();
+ m_aOverlays.Purge();
+ m_flLength = 0.0f;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+Shoreline_t::~Shoreline_t()
+{
+ m_aSegments.Purge();
+ m_aOverlays.Purge();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void Shoreline_t::AddSegment( Vector &vecPoint0, Vector &vecPoint1,
+ Vector &vecNormal, float flWaterZ,
+ CMapFace *pWaterFace, EditDispHandle_t hDisp )
+{
+ // Check for duplicates!
+ int nSegmentCount = m_aSegments.Count();
+ int iSegment;
+ for ( iSegment = 0; iSegment < nSegmentCount; ++iSegment )
+ {
+ if ( VectorsAreEqual( m_aSegments[iSegment].m_vecPoints[0], vecPoint0, DISPSHORE_VECTOR_EPS ) )
+ {
+ if ( VectorsAreEqual( m_aSegments[iSegment].m_vecPoints[1], vecPoint1, DISPSHORE_VECTOR_EPS ) )
+ return;
+ }
+
+ if ( VectorsAreEqual( m_aSegments[iSegment].m_vecPoints[1], vecPoint0, DISPSHORE_VECTOR_EPS ) )
+ {
+ if ( VectorsAreEqual( m_aSegments[iSegment].m_vecPoints[0], vecPoint1, DISPSHORE_VECTOR_EPS ) )
+ return;
+ }
+ }
+
+ iSegment = m_aSegments.AddToTail();
+
+ Vector vecEdge, vecCross;
+ VectorSubtract( vecPoint1, vecPoint0, vecEdge );
+ CrossProduct( vecNormal, vecEdge, vecCross );
+ if ( vecCross.z >= 0.0f )
+ {
+ VectorCopy( vecPoint1, m_aSegments[iSegment].m_vecPoints[0] );
+ VectorCopy( vecPoint0, m_aSegments[iSegment].m_vecPoints[1] );
+ }
+ else
+ {
+ VectorCopy( vecPoint0, m_aSegments[iSegment].m_vecPoints[0] );
+ VectorCopy( vecPoint1, m_aSegments[iSegment].m_vecPoints[1] );
+ }
+
+ VectorCopy( vecNormal, m_aSegments[iSegment].m_vecNormals[0] );
+ VectorCopy( vecNormal, m_aSegments[iSegment].m_vecNormals[1] );
+
+ m_aSegments[iSegment].m_hDisp = hDisp;
+ m_aSegments[iSegment].m_flWaterZ = flWaterZ;
+ m_aSegments[iSegment].m_iStartPoint = 0;
+ m_aSegments[iSegment].m_bTouch = false;
+ m_aSegments[iSegment].m_bCreated = false;
+ m_aSegments[iSegment].m_vecCenter.Init();
+
+ m_aSegments[iSegment].m_WorldFace.m_bAdjWinding = false;
+ m_aSegments[iSegment].m_WaterFace.m_bAdjWinding = false;
+ for ( int i = 0; i < 4; ++i )
+ {
+ m_aSegments[iSegment].m_WorldFace.m_vecPoints[i].Init();
+ m_aSegments[iSegment].m_WorldFace.m_vecTexCoords[i].Init();
+ m_aSegments[iSegment].m_WorldFace.m_pFaces[i] = NULL;
+
+ m_aSegments[iSegment].m_WaterFace.m_vecPoints[i].Init();
+ m_aSegments[iSegment].m_WaterFace.m_vecTexCoords[i].Init();
+ m_aSegments[iSegment].m_WaterFace.m_pFaces[i] = NULL;
+ }
+}
+
+//=============================================================================
+//
+// CDispShoreManager
+//
+class CDispShoreManager : public IDispShoreManager
+{
+public:
+
+ CDispShoreManager();
+ ~CDispShoreManager();
+
+ // Interface.
+ bool Init( void );
+ void Shutdown( void );
+
+ int GetShorelineCount( void );
+ Shoreline_t *GetShoreline( int nShorelineId );
+ void AddShoreline( int nShorelineId );
+ void RemoveShoreline( int nShorelineId );
+ void BuildShoreline( int nShorelineId, CUtlVector<CMapFace*> &aFaces, CUtlVector<CMapFace*> &aWaterFaces );
+
+ void Draw( CRender3D *pRender );
+ void DebugDraw( CRender3D *pRender );
+
+private:
+
+ void BuildShorelineSegments( Shoreline_t *pShoreline, CUtlVector<CMapFace*> &aFaces, CUtlVector<CMapFace*> &aWaterFaces );
+ void AverageShorelineNormals( Shoreline_t *pShoreline );
+ void BuildShorelineOverlayPoints( Shoreline_t *pShoreline, CUtlVector<CMapFace*> &aWaterFaces );
+ void BuildShorelineOverlayPoint( Shoreline_t *pShoreline, int iSegment, CUtlVector<CMapFace*> &aWaterFaces );
+ bool TexcoordShoreline( Shoreline_t *pShoreline );
+ void ShorelineLength( Shoreline_t *pShoreline );
+ void GenerateTexCoord( Shoreline_t *pShoreline, int iSegment, float flLengthToSegment, bool bEnd );
+ void BuildShorelineOverlays( Shoreline_t *pShoreline );
+ void CreateOverlays( Shoreline_t *pShoreline, int iSegment );
+
+ void DrawShorelines( int iShoreline );
+ void DrawShorelineNormals( int iShoreline );
+ void DrawShorelineOverlayPoints( CRender3D *pRender, int iShoreline );
+
+ bool ConnectShorelineSegments( Shoreline_t *pShoreline );
+ int FindShorelineStart( Shoreline_t *pShoreline );
+
+ bool IsTouched( Shoreline_t *pShoreline, int iSegment ) { return pShoreline->m_aSegments[iSegment].m_bTouch; }
+
+private:
+
+ CUtlVector<Shoreline_t> m_aShorelines;
+
+ // Displacement face and water face cache - for building.
+ CUtlVector<CMapDisp*> m_aDispCache;
+};
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+static CDispShoreManager s_DispShoreManager;
+
+IDispShoreManager *GetShoreManager( void )
+{
+ return &s_DispShoreManager;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CDispShoreManager::CDispShoreManager()
+{
+ m_aDispCache.Purge();
+ m_aShorelines.Purge();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CDispShoreManager::~CDispShoreManager()
+{
+ m_aDispCache.Purge();
+ m_aShorelines.Purge();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool CDispShoreManager::Init( void )
+{
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDispShoreManager::Shutdown( void )
+{
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+int CDispShoreManager::GetShorelineCount( void )
+{
+ return m_aShorelines.Count();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+Shoreline_t *CDispShoreManager::GetShoreline( int nShorelineId )
+{
+ int nShorelineCount = m_aShorelines.Count();
+ for ( int iShoreline = 0; iShoreline < nShorelineCount; ++iShoreline )
+ {
+ if ( m_aShorelines[iShoreline].m_nShorelineId == nShorelineId )
+ return &m_aShorelines[iShoreline];
+ }
+
+ return NULL;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDispShoreManager::AddShoreline( int nShorelineId )
+{
+ // Check to see if the id is already taken, if so remove it and re-add it.
+ RemoveShoreline( nShorelineId );
+
+ int iShoreline = m_aShorelines.AddToTail();
+ m_aShorelines[iShoreline].m_nShorelineId = nShorelineId;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDispShoreManager::RemoveShoreline( int nShorelineId )
+{
+ int nShorelineCount = m_aShorelines.Count();
+ for ( int iShoreline = ( nShorelineCount - 1 ); iShoreline >= 0; --iShoreline )
+ {
+ if ( m_aShorelines[iShoreline].m_nShorelineId == nShorelineId )
+ {
+ m_aShorelines.Remove( iShoreline );
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDispShoreManager::BuildShoreline( int nShorelineId, CUtlVector<CMapFace*> &aFaces, CUtlVector<CMapFace*> &aWaterFaces )
+{
+ // Verify faces to build a shoreline.
+ if ( ( aFaces.Count() == 0 ) ||( aWaterFaces.Count() == 0 ) )
+ return;
+
+ Shoreline_t *pShoreline = GetShoreline( nShorelineId );
+ if ( pShoreline )
+ {
+ BuildShorelineSegments( pShoreline, aFaces, aWaterFaces );
+ AverageShorelineNormals( pShoreline );
+ BuildShorelineOverlayPoints( pShoreline, aWaterFaces );
+ TexcoordShoreline( pShoreline );
+ BuildShorelineOverlays( pShoreline );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDispShoreManager::BuildShorelineSegments( Shoreline_t *pShoreline, CUtlVector<CMapFace*> &aFaces, CUtlVector<CMapFace*> &aWaterFaces )
+{
+ int nWaterFaceCount = aWaterFaces.Count();
+ for ( int iWaterFace = 0; iWaterFace < nWaterFaceCount; ++iWaterFace )
+ {
+ int nFaceCount = aFaces.Count();
+ for ( int iFace = 0; iFace < nFaceCount; ++iFace )
+ {
+ CMapFace *pFace = aFaces.Element( iFace );
+ if ( pFace )
+ {
+ if ( !pFace->HasDisp() )
+ {
+ // Ignore for now!
+ }
+ else
+ {
+ // Displacement.
+ CMapDisp *pDisp = EditDispMgr()->GetDisp( pFace->GetDisp() );
+ if ( pDisp )
+ {
+ pDisp->CreateShoreOverlays( aWaterFaces[iWaterFace], pShoreline );
+ }
+ }
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDispShoreManager::AverageShorelineNormals( Shoreline_t *pShoreline )
+{
+ int nSegmentCount = pShoreline->m_aSegments.Count();
+ if ( nSegmentCount == 0 )
+ return;
+
+ for ( int iSegment1 = 0; iSegment1 < nSegmentCount; ++iSegment1 )
+ {
+ for ( int iSegment2 = iSegment1 + 1; iSegment2 < nSegmentCount; ++iSegment2 )
+ {
+ int iPoint1 = -1;
+ int iPoint2 = -1;
+
+ if ( VectorsAreEqual( pShoreline->m_aSegments[iSegment1].m_vecPoints[0],
+ pShoreline->m_aSegments[iSegment2].m_vecPoints[0], DISPSHORE_VECTOR_EPS ) )
+ {
+ iPoint1 = 0;
+ iPoint2 = 0;
+ }
+
+ if ( VectorsAreEqual( pShoreline->m_aSegments[iSegment1].m_vecPoints[0],
+ pShoreline->m_aSegments[iSegment2].m_vecPoints[1], DISPSHORE_VECTOR_EPS ) )
+ {
+ iPoint1 = 0;
+ iPoint2 = 1;
+ }
+
+ if ( VectorsAreEqual( pShoreline->m_aSegments[iSegment1].m_vecPoints[1],
+ pShoreline->m_aSegments[iSegment2].m_vecPoints[0], DISPSHORE_VECTOR_EPS ) )
+ {
+ iPoint1 = 1;
+ iPoint2 = 0;
+ }
+
+ if ( VectorsAreEqual( pShoreline->m_aSegments[iSegment1].m_vecPoints[1],
+ pShoreline->m_aSegments[iSegment2].m_vecPoints[1], DISPSHORE_VECTOR_EPS ) )
+ {
+ iPoint1 = 1;
+ iPoint2 = 1;
+ }
+
+ if ( ( iPoint1 != -1 ) && ( iPoint2 != -1 ) )
+ {
+ pShoreline->m_aSegments[iSegment2].m_vecPoints[iPoint2] = pShoreline->m_aSegments[iSegment1].m_vecPoints[iPoint1];
+ Vector vecNormal = pShoreline->m_aSegments[iSegment1].m_vecNormals[iPoint1] + pShoreline->m_aSegments[iSegment2].m_vecNormals[iPoint2];
+ VectorNormalize( vecNormal );
+ pShoreline->m_aSegments[iSegment1].m_vecNormals[iPoint1] = vecNormal;
+ pShoreline->m_aSegments[iSegment2].m_vecNormals[iPoint2] = vecNormal;
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDispShoreManager::BuildShorelineOverlayPoints( Shoreline_t *pShoreline, CUtlVector<CMapFace*> &aWaterFaces )
+{
+ int nSegmentCount = pShoreline->m_aSegments.Count();
+ if ( nSegmentCount == 0 )
+ return;
+
+ for ( int iSegment = 0; iSegment < nSegmentCount; ++iSegment )
+ {
+ BuildShorelineOverlayPoint( pShoreline, iSegment, aWaterFaces );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDispShoreManager::BuildShorelineOverlayPoint( Shoreline_t *pShoreline, int iSegment, CUtlVector<CMapFace*> &aWaterFaces )
+{
+ // Get the displacement manager and segment displacement.
+ CMapDisp *pDisp = EditDispMgr()->GetDisp( pShoreline->m_aSegments[iSegment].m_hDisp );
+ if ( !pDisp )
+ return;
+
+ IWorldEditDispMgr *pDispMgr = GetActiveWorldEditDispManager();
+ if( !pDispMgr )
+ return;
+
+ // Build a bounding box from the world points.
+ Vector vecPoints[4];
+ vecPoints[0] = pShoreline->m_aSegments[iSegment].m_vecPoints[0];
+ vecPoints[3] = pShoreline->m_aSegments[iSegment].m_vecPoints[1];
+ vecPoints[1] = vecPoints[0] + ( pShoreline->m_aSegments[iSegment].m_vecNormals[0] * pShoreline->m_ShoreData.m_flWidths[0] );
+ vecPoints[2] = vecPoints[3] + ( pShoreline->m_aSegments[iSegment].m_vecNormals[1] * pShoreline->m_ShoreData.m_flWidths[0] );
+
+ Vector vecWorldMin = vecPoints[0];
+ Vector vecWorldMax = vecPoints[0];
+ for ( int iPoint = 1; iPoint < 4; ++iPoint )
+ {
+ for ( int iAxis = 0; iAxis < 3; ++iAxis )
+ {
+ if ( vecPoints[iPoint][iAxis] < vecWorldMin[iAxis] )
+ {
+ vecWorldMin[iAxis] = vecPoints[iPoint][iAxis];
+ }
+
+ if ( vecPoints[iPoint][iAxis] > vecWorldMax[iAxis] )
+ {
+ vecWorldMax[iAxis] = vecPoints[iPoint][iAxis];
+ }
+ }
+ }
+
+ for ( int iAxis = 0; iAxis < 2; ++iAxis )
+ {
+ vecWorldMin[iAxis] -= 1.0f;
+ vecWorldMax[iAxis] += 1.0f;
+ }
+ vecWorldMin.z -= 150.0f;
+ vecWorldMax.z += 150.0f;
+
+ // Build a list of displacements that intersect the bounding box.
+ CUtlVector<CMapDisp*> m_aDispList;
+ m_aDispList.Purge();
+
+ Vector vecDispMin, vecDispMax;
+ int nDispCount = pDispMgr->WorldCount();
+ for ( int iDisp = 0; iDisp < nDispCount; ++iDisp )
+ {
+ CMapDisp *pCurDisp = pDispMgr->GetFromWorld( iDisp );
+ if ( !pCurDisp )
+ continue;
+
+ if ( pCurDisp == pDisp )
+ continue;
+
+ // Check for intersections.
+ pCurDisp->GetBoundingBox( vecDispMin, vecDispMax );
+ if ( IsBoxIntersectingBox( vecWorldMin, vecWorldMax, vecDispMin, vecDispMax ) )
+ {
+ m_aDispList.AddToTail( pCurDisp );
+ }
+ }
+
+ // World points.
+ CMapFace *pFace = static_cast<CMapFace*>( pDisp->GetParent() );
+ for ( int iFace = 0; iFace < 4; ++iFace )
+ {
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_pFaces[iFace] = pFace;
+ }
+
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecPoints[0] = pShoreline->m_aSegments[iSegment].m_vecPoints[0];
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecPoints[3] = pShoreline->m_aSegments[iSegment].m_vecPoints[1];
+
+ Vector vecPoint = pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecPoints[0] + ( pShoreline->m_aSegments[iSegment].m_vecNormals[0] * pShoreline->m_ShoreData.m_flWidths[0] );
+ Vector vecStart( vecPoint.x, vecPoint.y, vecPoint.z + 150.0f );
+ Vector vecEnd( vecPoint.x, vecPoint.y, vecPoint.z - 150.0f );
+ Vector vecHit, vecHitNormal;
+ CMapFace *pHitFace = pFace;
+ if ( !pDisp->TraceLine( vecHit, vecHitNormal, vecStart, vecEnd ) )
+ {
+ nDispCount = m_aDispList.Count();
+ int iDisp;
+ for ( iDisp = 0; iDisp < nDispCount; ++iDisp )
+ {
+ if ( m_aDispList[iDisp]->TraceLine( vecHit, vecHitNormal, vecStart, vecEnd ) )
+ {
+ pHitFace = ( CMapFace* )m_aDispList[iDisp]->GetParent();
+ break;
+ }
+ }
+
+ if ( iDisp == nDispCount )
+ {
+ pDisp->TraceLineSnapTo( vecHit, vecHitNormal, vecStart, vecEnd );
+ }
+ }
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecPoints[1] = vecHit;
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_pFaces[1] = pHitFace;
+
+ vecPoint = pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecPoints[3] + ( pShoreline->m_aSegments[iSegment].m_vecNormals[1] * pShoreline->m_ShoreData.m_flWidths[0] );
+ vecStart.Init( vecPoint.x, vecPoint.y, vecPoint.z + 150.0f );
+ vecEnd.Init( vecPoint.x, vecPoint.y, vecPoint.z - 150.0f );
+ pHitFace = pFace;
+ if ( !pDisp->TraceLine( vecHit, vecHitNormal, vecStart, vecEnd ) )
+ {
+ nDispCount = m_aDispList.Count();
+ int iDisp;
+ for ( iDisp = 0; iDisp < nDispCount; ++iDisp )
+ {
+ if ( m_aDispList[iDisp]->TraceLine( vecHit, vecHitNormal, vecStart, vecEnd ) )
+ {
+ pHitFace = ( CMapFace* )m_aDispList[iDisp]->GetParent();
+ break;
+ }
+ }
+
+ if ( iDisp == nDispCount )
+ {
+ pDisp->TraceLineSnapTo( vecHit, vecHitNormal, vecStart, vecEnd );
+ }
+ }
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecPoints[2] = vecHit;
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_pFaces[2] = pHitFace;
+
+ // Water points.
+ pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecPoints[0] = pShoreline->m_aSegments[iSegment].m_vecPoints[0] + ( pShoreline->m_aSegments[iSegment].m_vecNormals[0] * -pShoreline->m_ShoreData.m_flWidths[1] );
+ pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecPoints[1] = pShoreline->m_aSegments[iSegment].m_vecPoints[0];
+ pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecPoints[2] = pShoreline->m_aSegments[iSegment].m_vecPoints[1];
+ pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecPoints[3] = pShoreline->m_aSegments[iSegment].m_vecPoints[1] + ( pShoreline->m_aSegments[iSegment].m_vecNormals[1] * -pShoreline->m_ShoreData.m_flWidths[1] );
+ int nWaterFaceCount = aWaterFaces.Count();
+ for ( int iWaterFace = 0; iWaterFace < nWaterFaceCount; ++iWaterFace )
+ {
+ CMapFace *pWaterFace = aWaterFaces.Element( iWaterFace );
+ if ( pWaterFace )
+ {
+ for ( int iWaterPoint = 0; iWaterPoint < 4; ++iWaterPoint )
+ {
+ vecPoint = pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecPoints[iWaterPoint];
+ vecStart.Init( vecPoint.x, vecPoint.y, vecPoint.z + 150.0f );
+ vecEnd.Init( vecPoint.x, vecPoint.y, vecPoint.z - 150.0f );
+ if ( pWaterFace->TraceLineInside( vecHit, vecHitNormal, vecStart, vecEnd ) )
+ {
+ pShoreline->m_aSegments[iSegment].m_WaterFace.m_pFaces[iWaterPoint] = pWaterFace;
+ }
+ }
+ }
+ }
+
+ // Water face clean up!
+ int nNoFaceCount = false;
+ for ( int iWaterPoint = 0; iWaterPoint < 4; ++iWaterPoint )
+ {
+ if ( !pShoreline->m_aSegments[iSegment].m_WaterFace.m_pFaces[iWaterPoint] )
+ {
+ ++nNoFaceCount;
+ }
+ }
+ if ( ( nNoFaceCount > 0 ) && ( nNoFaceCount < 4 ) )
+ {
+ // Find a valid face.
+ CMapFace *pWaterFace = NULL;
+ for ( int iWaterPoint = 0; iWaterPoint < 4; ++iWaterPoint )
+ {
+ if ( pShoreline->m_aSegments[iSegment].m_WaterFace.m_pFaces[iWaterPoint] )
+ {
+ pWaterFace = pShoreline->m_aSegments[iSegment].m_WaterFace.m_pFaces[iWaterPoint];
+ break;
+ }
+ }
+
+ for ( int iWaterPoint = 0; iWaterPoint < 4; ++iWaterPoint )
+ {
+ if ( !pShoreline->m_aSegments[iSegment].m_WaterFace.m_pFaces[iWaterPoint] )
+ {
+ pShoreline->m_aSegments[iSegment].m_WaterFace.m_pFaces[iWaterPoint] = pWaterFace;
+ }
+ }
+ }
+
+ // Center.
+ pShoreline->m_aSegments[iSegment].m_vecCenter = ( pShoreline->m_aSegments[iSegment].m_vecPoints[0] + pShoreline->m_aSegments[iSegment].m_vecPoints[1] ) * 0.5f;
+
+ // Check winding.
+ Vector vecEdge0, vecEdge1, vecCross;
+
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_bAdjWinding = false;
+ VectorSubtract( pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecPoints[1], pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecPoints[0], vecEdge0 );
+ VectorSubtract( pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecPoints[2], pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecPoints[0], vecEdge1 );
+ VectorNormalize( vecEdge0 );
+ VectorNormalize( vecEdge1 );
+ CrossProduct( vecEdge1, vecEdge0, vecCross );
+ if ( vecCross.z < 0.0f )
+ {
+ // Adjust winding.
+ Vector vecTmp = pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecPoints[1];
+ CMapFace *pTmpFace = pShoreline->m_aSegments[iSegment].m_WorldFace.m_pFaces[1];
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecPoints[1] = pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecPoints[3];
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_pFaces[1] = pShoreline->m_aSegments[iSegment].m_WorldFace.m_pFaces[3];
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecPoints[3] = vecTmp;
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_pFaces[3] = pTmpFace;
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_bAdjWinding = true;
+ }
+
+ pShoreline->m_aSegments[iSegment].m_WaterFace.m_bAdjWinding = false;
+ VectorSubtract( pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecPoints[1], pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecPoints[0], vecEdge0 );
+ VectorSubtract( pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecPoints[2], pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecPoints[0], vecEdge1 );
+ VectorNormalize( vecEdge0 );
+ VectorNormalize( vecEdge1 );
+ CrossProduct( vecEdge1, vecEdge0, vecCross );
+ if ( vecCross.z < 0.0f )
+ {
+ // Adjust winding.
+ Vector vecTmp = pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecPoints[1];
+ CMapFace *pTmpFace = pShoreline->m_aSegments[iSegment].m_WaterFace.m_pFaces[1];
+ pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecPoints[1] = pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecPoints[3];
+ pShoreline->m_aSegments[iSegment].m_WaterFace.m_pFaces[1] = pShoreline->m_aSegments[iSegment].m_WaterFace.m_pFaces[3];
+ pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecPoints[3] = vecTmp;
+ pShoreline->m_aSegments[iSegment].m_WaterFace.m_pFaces[3] = pTmpFace;
+ pShoreline->m_aSegments[iSegment].m_WaterFace.m_bAdjWinding = true;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool CDispShoreManager::TexcoordShoreline( Shoreline_t *pShoreline )
+{
+ int nSegmentCount = pShoreline->m_aSegments.Count();
+ if ( nSegmentCount == 0 )
+ return false;
+
+ // Conncect the shoreline segments to produce a continuous shoreline.
+ if ( !ConnectShorelineSegments( pShoreline ) )
+ return false;
+
+ ShorelineLength( pShoreline );
+
+ float flLengthToSegment = 0.0f;
+ int nSortedSegmentCount = pShoreline->m_aSortedSegments.Count();
+ for ( int iSegment = 0; iSegment < nSortedSegmentCount; ++iSegment )
+ {
+ int iSortSegment = pShoreline->m_aSortedSegments[iSegment];
+
+ GenerateTexCoord( pShoreline, iSortSegment, flLengthToSegment, false );
+
+ Vector vecEdge;
+ VectorSubtract( pShoreline->m_aSegments[iSortSegment].m_vecPoints[1], pShoreline->m_aSegments[iSortSegment].m_vecPoints[0], vecEdge );
+ flLengthToSegment += vecEdge.Length();
+
+ GenerateTexCoord( pShoreline, iSortSegment, flLengthToSegment, true );
+ }
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool CDispShoreManager::ConnectShorelineSegments( Shoreline_t *pShoreline )
+{
+ // Reset/recreate the shoreline sorted segment list.
+ pShoreline->m_aSortedSegments.Purge();
+
+ int iSegment = FindShorelineStart( pShoreline );
+ if ( iSegment == -1 )
+ {
+ iSegment = 0;
+ }
+
+ int nSegmentCount = pShoreline->m_aSegments.Count();
+ while ( iSegment != -1 )
+ {
+ int iSegment2;
+ for ( iSegment2 = 0; iSegment2 < nSegmentCount; ++iSegment2 )
+ {
+ if ( iSegment2 == iSegment )
+ continue;
+
+ bool bIsTouching0 = false;
+ if ( VectorsAreEqual( pShoreline->m_aSegments[iSegment].m_vecPoints[0], pShoreline->m_aSegments[iSegment2].m_vecPoints[0], DISPSHORE_VECTOR_EPS ) ) { bIsTouching0 = true; }
+ if ( VectorsAreEqual( pShoreline->m_aSegments[iSegment].m_vecPoints[1], pShoreline->m_aSegments[iSegment2].m_vecPoints[0], DISPSHORE_VECTOR_EPS ) ) { bIsTouching0 = true; }
+ bool bIsTouching1 = false;
+ if ( VectorsAreEqual( pShoreline->m_aSegments[iSegment].m_vecPoints[0], pShoreline->m_aSegments[iSegment2].m_vecPoints[1], DISPSHORE_VECTOR_EPS ) ) { bIsTouching1 = true; }
+ if ( VectorsAreEqual( pShoreline->m_aSegments[iSegment].m_vecPoints[1], pShoreline->m_aSegments[iSegment2].m_vecPoints[1], DISPSHORE_VECTOR_EPS ) ) { bIsTouching1 = true; }
+
+ if ( ( bIsTouching0 || bIsTouching1 ) && !IsTouched( pShoreline, iSegment2 ) )
+ {
+ pShoreline->m_aSegments[iSegment2].m_iStartPoint = 0;
+ if ( bIsTouching1 )
+ {
+ pShoreline->m_aSegments[iSegment2].m_iStartPoint = 1;
+ }
+
+ pShoreline->m_aSortedSegments.AddToTail( iSegment2 );
+ pShoreline->m_aSegments[iSegment2].m_bTouch = true;
+ break;
+ }
+ }
+
+ if ( iSegment2 != nSegmentCount )
+ {
+ iSegment = iSegment2;
+ }
+ else
+ {
+ iSegment = -1;
+ }
+ }
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+int CDispShoreManager::FindShorelineStart( Shoreline_t *pShoreline )
+{
+ // Find a segment that doesn't have any (fewest) matching point data.
+ int nSegmentCount = pShoreline->m_aSegments.Count();
+ for ( int iSegment = 0; iSegment < nSegmentCount; ++iSegment )
+ {
+ int nTouchCount = 0;
+ int iStartPoint = -1;
+ for ( int iSegment2 = 0; iSegment2 < nSegmentCount; ++iSegment2 )
+ {
+ if ( iSegment == iSegment2 )
+ continue;
+
+ if ( VectorsAreEqual( pShoreline->m_aSegments[iSegment].m_vecPoints[0], pShoreline->m_aSegments[iSegment2].m_vecPoints[0], DISPSHORE_VECTOR_EPS ) )
+ {
+ ++nTouchCount;
+ iStartPoint = 1;
+ }
+ if ( VectorsAreEqual( pShoreline->m_aSegments[iSegment].m_vecPoints[0], pShoreline->m_aSegments[iSegment2].m_vecPoints[1], DISPSHORE_VECTOR_EPS ) )
+ {
+ ++nTouchCount;
+ iStartPoint = 1;
+ }
+ if ( VectorsAreEqual( pShoreline->m_aSegments[iSegment].m_vecPoints[1], pShoreline->m_aSegments[iSegment2].m_vecPoints[0], DISPSHORE_VECTOR_EPS ) )
+ {
+ ++nTouchCount;
+ iStartPoint = 0;
+ }
+ if ( VectorsAreEqual( pShoreline->m_aSegments[iSegment].m_vecPoints[1], pShoreline->m_aSegments[iSegment2].m_vecPoints[1], DISPSHORE_VECTOR_EPS ) )
+ {
+ ++nTouchCount;
+ iStartPoint = 0;
+ }
+ }
+
+ if ( nTouchCount == 1 )
+ {
+ pShoreline->m_aSegments[iSegment].m_iStartPoint = iStartPoint;
+ pShoreline->m_aSortedSegments.AddToTail( iSegment );
+ pShoreline->m_aSegments[iSegment].m_bTouch = true;
+ return iSegment;
+ }
+ }
+
+ return -1;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDispShoreManager::ShorelineLength( Shoreline_t *pShoreline )
+{
+ float flLength = 0.0f;
+ int nSegmentCount = pShoreline->m_aSegments.Count();
+ for ( int iSegment = 0; iSegment < nSegmentCount; ++iSegment )
+ {
+ Vector vecEdge;
+ VectorSubtract( pShoreline->m_aSegments[iSegment].m_vecPoints[1], pShoreline->m_aSegments[iSegment].m_vecPoints[0], vecEdge );
+ flLength += vecEdge.Length();
+ }
+
+ pShoreline->m_flLength = flLength;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDispShoreManager::GenerateTexCoord( Shoreline_t *pShoreline, int iSegment, float flLengthToSegment, bool bEnd )
+{
+ float flValue = pShoreline->m_ShoreData.m_vecLengthTexcoord[1] - pShoreline->m_ShoreData.m_vecLengthTexcoord[0];
+
+ if ( pShoreline->m_aSegments[iSegment].m_iStartPoint == 0 )
+ {
+ if ( !bEnd )
+ {
+ float flRatio = flLengthToSegment / pShoreline->m_flLength;
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecTexCoords[0].x = flValue * flRatio;
+ pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecTexCoords[0].x = flValue * flRatio;
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecTexCoords[0].y = pShoreline->m_ShoreData.m_vecWidthTexcoord[1] * 0.5f;
+ pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecTexCoords[0].y = pShoreline->m_ShoreData.m_vecWidthTexcoord[0];
+
+ if ( pShoreline->m_aSegments[iSegment].m_WorldFace.m_bAdjWinding )
+ {
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecTexCoords[3].x = flValue * flRatio;
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecTexCoords[3].y = pShoreline->m_ShoreData.m_vecWidthTexcoord[1];
+ }
+ else
+ {
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecTexCoords[1].x = flValue * flRatio;
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecTexCoords[1].y = pShoreline->m_ShoreData.m_vecWidthTexcoord[1];
+ }
+
+ if ( pShoreline->m_aSegments[iSegment].m_WaterFace.m_bAdjWinding )
+ {
+ pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecTexCoords[3].x = flValue * flRatio;
+ pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecTexCoords[3].y = pShoreline->m_ShoreData.m_vecWidthTexcoord[1] * 0.5f;
+ }
+ else
+ {
+ pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecTexCoords[1].x = flValue * flRatio;
+ pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecTexCoords[1].y = pShoreline->m_ShoreData.m_vecWidthTexcoord[1] * 0.5f;
+ }
+ }
+ else
+ {
+ float flRatio = flLengthToSegment / pShoreline->m_flLength;
+
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecTexCoords[2].x = flValue * flRatio;
+ pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecTexCoords[2].x = flValue * flRatio;
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecTexCoords[2].y = pShoreline->m_ShoreData.m_vecWidthTexcoord[1];
+ pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecTexCoords[2].y = pShoreline->m_ShoreData.m_vecWidthTexcoord[1] * 0.5f;
+
+ if ( pShoreline->m_aSegments[iSegment].m_WorldFace.m_bAdjWinding )
+ {
+ flRatio = flLengthToSegment / pShoreline->m_flLength;
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecTexCoords[1].x = flValue * flRatio;
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecTexCoords[1].y = pShoreline->m_ShoreData.m_vecWidthTexcoord[1] * 0.5f;
+ }
+ else
+ {
+ flRatio = flLengthToSegment / pShoreline->m_flLength;
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecTexCoords[3].x = flValue * flRatio;
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecTexCoords[3].y = pShoreline->m_ShoreData.m_vecWidthTexcoord[1] * 0.5f;
+ }
+
+ if ( pShoreline->m_aSegments[iSegment].m_WaterFace.m_bAdjWinding )
+ {
+ flRatio = flLengthToSegment / pShoreline->m_flLength;
+ pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecTexCoords[1].x = flValue * flRatio;
+ pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecTexCoords[1].y = pShoreline->m_ShoreData.m_vecWidthTexcoord[0];
+ }
+ else
+ {
+ flRatio = flLengthToSegment / pShoreline->m_flLength;
+ pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecTexCoords[3].x = flValue * flRatio;
+ pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecTexCoords[3].y = pShoreline->m_ShoreData.m_vecWidthTexcoord[0];
+ }
+ }
+ }
+ else
+ {
+ if ( !bEnd )
+ {
+ float flRatio = flLengthToSegment / pShoreline->m_flLength;
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecTexCoords[2].x = flValue * flRatio;
+ pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecTexCoords[2].x = flValue * flRatio;
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecTexCoords[2].y = pShoreline->m_ShoreData.m_vecWidthTexcoord[1];
+ pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecTexCoords[2].y = pShoreline->m_ShoreData.m_vecWidthTexcoord[1] * 0.5f;
+
+ if ( pShoreline->m_aSegments[iSegment].m_WorldFace.m_bAdjWinding )
+ {
+ flRatio = flLengthToSegment / pShoreline->m_flLength;
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecTexCoords[1].x = flValue * flRatio;
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecTexCoords[1].y = pShoreline->m_ShoreData.m_vecWidthTexcoord[1] * 0.5f;
+ }
+ else
+ {
+ flRatio = flLengthToSegment / pShoreline->m_flLength;
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecTexCoords[3].x = flValue * flRatio;
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecTexCoords[3].y = pShoreline->m_ShoreData.m_vecWidthTexcoord[1] * 0.5f;
+ }
+
+ if ( pShoreline->m_aSegments[iSegment].m_WaterFace.m_bAdjWinding )
+ {
+ flRatio = flLengthToSegment / pShoreline->m_flLength;
+ pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecTexCoords[1].x = flValue * flRatio;
+ pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecTexCoords[1].y = pShoreline->m_ShoreData.m_vecWidthTexcoord[0];
+ }
+ else
+ {
+ flRatio = flLengthToSegment / pShoreline->m_flLength;
+ pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecTexCoords[3].x = flValue * flRatio;
+ pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecTexCoords[3].y = pShoreline->m_ShoreData.m_vecWidthTexcoord[0];
+ }
+ }
+ else
+ {
+ float flRatio = flLengthToSegment / pShoreline->m_flLength;
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecTexCoords[0].x = flValue * flRatio;
+ pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecTexCoords[0].x = flValue * flRatio;
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecTexCoords[0].y = pShoreline->m_ShoreData.m_vecWidthTexcoord[1] * 0.5f;
+ pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecTexCoords[0].y = pShoreline->m_ShoreData.m_vecWidthTexcoord[0];
+
+ if ( pShoreline->m_aSegments[iSegment].m_WorldFace.m_bAdjWinding )
+ {
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecTexCoords[3].x = flValue * flRatio;
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecTexCoords[3].y = pShoreline->m_ShoreData.m_vecWidthTexcoord[1];
+ }
+ else
+ {
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecTexCoords[1].x = flValue * flRatio;
+ pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecTexCoords[1].y = pShoreline->m_ShoreData.m_vecWidthTexcoord[1];
+ }
+
+ if ( pShoreline->m_aSegments[iSegment].m_WaterFace.m_bAdjWinding )
+ {
+ pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecTexCoords[3].x = flValue * flRatio;
+ pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecTexCoords[3].y = pShoreline->m_ShoreData.m_vecWidthTexcoord[1] * 0.5f;
+ }
+ else
+ {
+ pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecTexCoords[1].x = flValue * flRatio;
+ pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecTexCoords[1].y = pShoreline->m_ShoreData.m_vecWidthTexcoord[1] * 0.5f;
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDispShoreManager::BuildShorelineOverlays( Shoreline_t *pShoreline )
+{
+ // Reset the list.
+ if ( pShoreline->m_aOverlays.Count() != 0 )
+ {
+ pShoreline->m_aOverlays.Purge();
+ }
+
+ int nSegmentCount = pShoreline->m_aSegments.Count();
+ if ( nSegmentCount == 0 )
+ return;
+
+ CMapDoc *pDoc = CMapDoc::GetActiveMapDoc();
+ if ( !pDoc )
+ return;
+
+ for ( int iSegment = 0; iSegment < nSegmentCount; ++iSegment )
+ {
+ CMapDisp *pDisp = EditDispMgr()->GetDisp( pShoreline->m_aSegments[iSegment].m_hDisp );
+ if ( !pDisp )
+ continue;
+
+ CMapFace *pFace = ( CMapFace* )pDisp->GetParent();
+ if ( !pFace )
+ continue;
+
+ CreateOverlays( pShoreline, iSegment );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDispShoreManager::CreateOverlays( Shoreline_t *pShoreline, int iSegment )
+{
+ // Create the face list than this overlay will act upon.
+ CUtlVector<CMapFace*> aWorldFaces;
+ CUtlVector<CMapFace*> aWaterFaces;
+ for ( int iFace = 0; iFace < 4; ++iFace )
+ {
+ if ( !pShoreline->m_aSegments[iSegment].m_WorldFace.m_pFaces[iFace] ||
+ !pShoreline->m_aSegments[iSegment].m_WaterFace.m_pFaces[iFace] )
+ return;
+
+ // World
+ if ( aWorldFaces.Find( pShoreline->m_aSegments[iSegment].m_WorldFace.m_pFaces[iFace] ) == -1 )
+ {
+ aWorldFaces.AddToTail( pShoreline->m_aSegments[iSegment].m_WorldFace.m_pFaces[iFace] );
+ }
+
+ // Water
+ if ( aWaterFaces.Find( pShoreline->m_aSegments[iSegment].m_WaterFace.m_pFaces[iFace] ) == -1 )
+ {
+ aWaterFaces.AddToTail( pShoreline->m_aSegments[iSegment].m_WaterFace.m_pFaces[iFace] );
+ }
+ }
+
+ // Create and add data to the world overlay.
+ int iOverlay = pShoreline->m_aOverlays.AddToTail();
+ CMapOverlay *pOverlay = &pShoreline->m_aOverlays[iOverlay];
+
+ pOverlay->SetOverlayType( OVERLAY_TYPE_SHORE );
+
+ pOverlay->Basis_Init( aWorldFaces[0] );
+ pOverlay->Handles_Init( aWorldFaces[0] );
+ pOverlay->SideList_Init( aWorldFaces[0] );
+
+ int nFaceCount = aWorldFaces.Count();
+ for ( int iFace = 1; iFace < nFaceCount; ++iFace )
+ {
+ pOverlay->SideList_AddFace( aWorldFaces[iFace] );
+ }
+
+ pOverlay->SetLoaded( true );
+
+ pOverlay->HandleMoveTo( 0, pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecPoints[0], pShoreline->m_aSegments[iSegment].m_WorldFace.m_pFaces[0] );
+ pOverlay->HandleMoveTo( 1, pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecPoints[1], pShoreline->m_aSegments[iSegment].m_WorldFace.m_pFaces[1] );
+ pOverlay->HandleMoveTo( 2, pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecPoints[2], pShoreline->m_aSegments[iSegment].m_WorldFace.m_pFaces[2] );
+ pOverlay->HandleMoveTo( 3, pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecPoints[3], pShoreline->m_aSegments[iSegment].m_WorldFace.m_pFaces[3] );
+
+ if ( !pShoreline->m_ShoreData.m_pTexture )
+ {
+ pOverlay->SetMaterial( "decals/decal_signroute004b" );
+ }
+ else
+ {
+ pOverlay->SetMaterial( pShoreline->m_ShoreData.m_pTexture );
+ }
+ pOverlay->SetTexCoords( pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecTexCoords );
+
+ pOverlay->CalcBounds( true );
+
+ pOverlay->DoClip();
+ pOverlay->PostUpdate( Notify_Changed );
+
+ // Create and add data to the water overlay.
+ iOverlay = pShoreline->m_aOverlays.AddToTail();
+ pOverlay = &pShoreline->m_aOverlays[iOverlay];
+
+ pOverlay->SetOverlayType( OVERLAY_TYPE_SHORE );
+
+ pOverlay->Basis_Init( aWaterFaces[0] );
+ pOverlay->Handles_Init( aWaterFaces[0] );
+ pOverlay->SideList_Init( aWaterFaces[0] );
+
+ nFaceCount = aWaterFaces.Count();
+ for ( int iFace = 1; iFace < nFaceCount; ++iFace )
+ {
+ pOverlay->SideList_AddFace( aWaterFaces[iFace] );
+ }
+
+ pOverlay->SetLoaded( true );
+
+ pOverlay->HandleMoveTo( 0, pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecPoints[0], pShoreline->m_aSegments[iSegment].m_WaterFace.m_pFaces[0] );
+ pOverlay->HandleMoveTo( 1, pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecPoints[1], pShoreline->m_aSegments[iSegment].m_WaterFace.m_pFaces[1] );
+ pOverlay->HandleMoveTo( 2, pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecPoints[2], pShoreline->m_aSegments[iSegment].m_WaterFace.m_pFaces[2] );
+ pOverlay->HandleMoveTo( 3, pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecPoints[3], pShoreline->m_aSegments[iSegment].m_WaterFace.m_pFaces[3] );
+
+ if ( !pShoreline->m_ShoreData.m_pTexture )
+ {
+ pOverlay->SetMaterial( "decals/decal_signroute004b" );
+ }
+ else
+ {
+ pOverlay->SetMaterial( pShoreline->m_ShoreData.m_pTexture );
+ }
+ pOverlay->SetTexCoords( pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecTexCoords );
+
+ pOverlay->SetOverlayType( OVERLAY_TYPE_SHORE );
+
+ pOverlay->CalcBounds( true );
+
+ pOverlay->DoClip();
+ pOverlay->PostUpdate( Notify_Changed );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDispShoreManager::Draw( CRender3D *pRender )
+{
+ int nShoreCount = m_aShorelines.Count();
+ for ( int iShore = 0; iShore < nShoreCount; ++iShore )
+ {
+ Shoreline_t *pShoreline = &m_aShorelines[iShore];
+ if ( pShoreline )
+ {
+ int nOverlayCount = pShoreline->m_aOverlays.Count();
+ for ( int iOverlay = 0; iOverlay < nOverlayCount; ++iOverlay )
+ {
+ CMapOverlay *pOverlay = &pShoreline->m_aOverlays[iOverlay];
+ if ( pOverlay )
+ {
+ pOverlay->Render3D( pRender );
+ }
+ }
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDispShoreManager::DebugDraw( CRender3D *pRender )
+{
+ pRender->SetRenderMode( RENDER_MODE_WIREFRAME );
+
+ int nShorelineCount = GetShorelineCount();
+ for ( int iShoreline = 0; iShoreline < nShorelineCount; ++iShoreline )
+ {
+ DrawShorelines( iShoreline );
+ DrawShorelineNormals( iShoreline );
+ DrawShorelineOverlayPoints( pRender, iShoreline );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDispShoreManager::DrawShorelines( int iShoreline )
+{
+ Shoreline_t *pShoreline = &m_aShorelines[iShoreline];
+ if ( pShoreline )
+ {
+ int nSegmentCount = pShoreline->m_aSegments.Count();
+ if ( nSegmentCount == 0 )
+ return;
+
+ CMeshBuilder meshBuilder;
+ CMatRenderContextPtr pRenderContext( MaterialSystemInterface() );
+ IMesh* pMesh = pRenderContext->GetDynamicMesh();
+ meshBuilder.Begin( pMesh, MATERIAL_LINES, ( nSegmentCount * 2 ) );
+
+ for ( int iSegment = 0; iSegment < nSegmentCount; ++iSegment )
+ {
+ meshBuilder.Color3f( 1.0f, 0.0f, 0.0f );
+ meshBuilder.Position3f( pShoreline->m_aSegments[iSegment].m_vecPoints[0].x,
+ pShoreline->m_aSegments[iSegment].m_vecPoints[0].y,
+ pShoreline->m_aSegments[iSegment].m_vecPoints[0].z + 50.0f );
+ meshBuilder.AdvanceVertex();
+
+ meshBuilder.Color3f( 1.0f, 0.0f, 0.0f );
+ meshBuilder.Position3f( pShoreline->m_aSegments[iSegment].m_vecPoints[1].x,
+ pShoreline->m_aSegments[iSegment].m_vecPoints[1].y,
+ pShoreline->m_aSegments[iSegment].m_vecPoints[1].z + 50.0f );
+ meshBuilder.AdvanceVertex();
+ }
+
+ meshBuilder.End();
+ pMesh->Draw();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDispShoreManager::DrawShorelineNormals( int iShoreline )
+{
+#define DISPSHORE_NORMAL_SCALE 25.0f
+
+ Shoreline_t *pShoreline = &m_aShorelines[iShoreline];
+ if ( pShoreline )
+ {
+ int nSegmentCount = pShoreline->m_aSegments.Count();
+ if ( nSegmentCount == 0 )
+ return;
+
+ CMeshBuilder meshBuilder;
+ CMatRenderContextPtr pRenderContext( materials );
+ IMesh* pMesh = pRenderContext->GetDynamicMesh();
+ meshBuilder.Begin( pMesh, MATERIAL_LINES, ( nSegmentCount * 4 ) );
+
+ for ( int iSegment = 0; iSegment < nSegmentCount; ++iSegment )
+ {
+ // Normal for vertex 0.
+ meshBuilder.Color3f( 1.0f, 1.0f, 0.0f );
+ meshBuilder.Position3f( pShoreline->m_aSegments[iSegment].m_vecPoints[0].x,
+ pShoreline->m_aSegments[iSegment].m_vecPoints[0].y,
+ pShoreline->m_aSegments[iSegment].m_vecPoints[0].z + 50.0f );
+ meshBuilder.AdvanceVertex();
+
+ meshBuilder.Color3f( 1.0f, 1.0f, 0.0f );
+ meshBuilder.Position3f( pShoreline->m_aSegments[iSegment].m_vecPoints[0].x + ( pShoreline->m_aSegments[iSegment].m_vecNormals[0].x * DISPSHORE_NORMAL_SCALE ),
+ pShoreline->m_aSegments[iSegment].m_vecPoints[0].y + ( pShoreline->m_aSegments[iSegment].m_vecNormals[0].y * DISPSHORE_NORMAL_SCALE ),
+ pShoreline->m_aSegments[iSegment].m_vecPoints[0].z + 50.0f + ( pShoreline->m_aSegments[iSegment].m_vecNormals[0].z * DISPSHORE_NORMAL_SCALE ) );
+ meshBuilder.AdvanceVertex();
+
+ // Normal for vertex 1.
+ meshBuilder.Color3f( 1.0f, 1.0f, 0.0f );
+ meshBuilder.Position3f( pShoreline->m_aSegments[iSegment].m_vecPoints[1].x,
+ pShoreline->m_aSegments[iSegment].m_vecPoints[1].y,
+ pShoreline->m_aSegments[iSegment].m_vecPoints[1].z + 50.0f );
+ meshBuilder.AdvanceVertex();
+
+ meshBuilder.Color3f( 1.0f, 1.0f, 0.0f );
+ meshBuilder.Position3f( pShoreline->m_aSegments[iSegment].m_vecPoints[1].x + ( pShoreline->m_aSegments[iSegment].m_vecNormals[1].x * DISPSHORE_NORMAL_SCALE ),
+ pShoreline->m_aSegments[iSegment].m_vecPoints[1].y + ( pShoreline->m_aSegments[iSegment].m_vecNormals[1].y * DISPSHORE_NORMAL_SCALE ),
+ pShoreline->m_aSegments[iSegment].m_vecPoints[1].z + 50.0f + ( pShoreline->m_aSegments[iSegment].m_vecNormals[1].z * DISPSHORE_NORMAL_SCALE ) );
+ meshBuilder.AdvanceVertex();
+ }
+
+ meshBuilder.End();
+ pMesh->Draw();
+ }
+
+#undef DISPSHORE_NORMAL_SCALE
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CDispShoreManager::DrawShorelineOverlayPoints( CRender3D *pRender, int iShoreline )
+{
+#define DISPSHORE_BOX_SIZE 5.0f
+
+ Shoreline_t *pShoreline = &m_aShorelines[iShoreline];
+ if ( pShoreline )
+ {
+ int nSegmentCount = pShoreline->m_aSegments.Count();
+ if ( nSegmentCount == 0 )
+ return;
+
+ Vector vecWorldMin, vecWorldMax;
+ for ( int iSegment = 0; iSegment < nSegmentCount; ++iSegment )
+ {
+ for ( int iWorldPoint = 0; iWorldPoint < 4; ++iWorldPoint )
+ {
+ vecWorldMin = pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecPoints[iWorldPoint];
+ vecWorldMax = pShoreline->m_aSegments[iSegment].m_WorldFace.m_vecPoints[iWorldPoint];
+ for ( int iAxis = 0; iAxis < 3; ++iAxis )
+ {
+ vecWorldMin[iAxis] -= DISPSHORE_BOX_SIZE;
+ vecWorldMax[iAxis] += DISPSHORE_BOX_SIZE;
+ }
+
+ pRender->RenderBox( vecWorldMin, vecWorldMax, 255, 0, 0, SELECT_NONE );
+ }
+
+ for ( int iWorldPoint = 0; iWorldPoint < 4; ++iWorldPoint )
+ {
+ vecWorldMin = pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecPoints[iWorldPoint];
+ vecWorldMax = pShoreline->m_aSegments[iSegment].m_WaterFace.m_vecPoints[iWorldPoint];
+ for ( int iAxis = 0; iAxis < 3; ++iAxis )
+ {
+ vecWorldMin[iAxis] -= DISPSHORE_BOX_SIZE;
+ vecWorldMax[iAxis] += DISPSHORE_BOX_SIZE;
+ }
+
+ pRender->RenderBox( vecWorldMin, vecWorldMax, 0, 0, 255, SELECT_NONE );
+ }
+ }
+ }
+
+#undef DISPSHORE_BOX_SIZE
+}
+