You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1234 lines
45 KiB
1234 lines
45 KiB
//========= Copyright © 1996-2004, Valve LLC, 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
|
|
}
|
|
|