hl2_src-leak-2017/src/hammer/DispShore.cpp

1235 lines
45 KiB
C++

//========= 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
}