summaryrefslogtreecommitdiff
path: root/hammer/mapoverlay.h
blob: 980d890699e1fe8077d63cf68d681d078f031433 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: 
//
// $NoKeywords: $
//=============================================================================//

#ifndef MAPOVERLAY_H
#define MAPOVERLAY_H
#pragma once

#include <afxwin.h>
#include "utlvector.h"
#include "MapSideList.h"

class CHelperInfo;
class CMapFace;
class CRender3D;
class CMapView;
class IEditorTexture;

#define OVERLAY_HANDLES_COUNT	4

#define NUM_CLIPFACE_TEXCOORDS	2

#define OVERLAY_TYPE_GENERIC	0x01
#define OVERLAY_TYPE_SHORE		0x02

//=============================================================================
//
// Class Map Overlay
//
class CMapOverlay : public CMapSideList
{
public:

	DECLARE_MAPCLASS( CMapOverlay, CMapSideList );

	// Construction/Deconstruction.
	CMapOverlay();
	~CMapOverlay();

	// Factory for building from a list of string parameters.
	static CMapClass *CreateMapOverlay( CHelperInfo *pInfo, CMapEntity *pParent );

	// Virtual/Interface Implementation.
	virtual void PostloadWorld( CMapWorld *pWorld );

	virtual CMapClass *Copy( bool bUpdateDependencies );
	virtual CMapClass *CopyFrom( CMapClass *pObject, bool bUpdateDependencies );

	void CalcBounds( BOOL bFullUpdate = FALSE );

	virtual void OnParentKeyChanged( const char* szKey, const char* szValue );
	virtual void OnNotifyDependent( CMapClass *pObject, Notify_Dependent_t eNotifyType );

	void DoTransform( const VMatrix &matrix );
	
	void OnPaste( CMapClass *pCopy, CMapWorld *pSourceWorld, CMapWorld *pDestWorld, 
				  const CMapObjectList &OriginalList, CMapObjectList &NewList);
	void OnClone( CMapClass *pClone, CMapWorld *pWorld, 
				  const CMapObjectList &OriginalList, CMapObjectList &NewList );
	void OnUndoRedo( void );

	void Render3D( CRender3D *pRender );

	// Overlay.
	void HandlesReset( void );
	bool HandlesHitTest( CMapView *pView, const Vector2D &vPoint );
	void HandlesDragTo( Vector &vecImpact, CMapFace *pFace );
	void HandleMoveTo( int iHandle, Vector &vecPoint, CMapFace *pFace );
	void SetTexCoords( Vector2D vecTexCoords[4] );
	void GetHandlePos( int iHandle, Vector &vecPos );
	bool IsSelected( void )									{ return ( GetSelectionState() == SELECT_NORMAL ); }

	void DoClip( void );
	void CenterEntity( void );

	void GetPlane( cplane_t &plane );

	int	GetFaceCount( void ) { return m_Faces.Count(); }
	CMapFace *GetFace( int iFace ) { return m_Faces.Element( iFace ); }

	void SetMaterial( const char *szMaterialName );
	void SetMaterial( IEditorTexture *pTexture )		{ m_Material.m_pTexture = pTexture; }
	IEditorTexture* GetMaterial()		{ return m_Material.m_pTexture; }

	// Creation.
	void Basis_Init( CMapFace *pFace );
	void Handles_Init( CMapFace *pFace );
	void SideList_Init( CMapFace *pFace );
	void SideList_AddFace( CMapFace *pFace );
	void SetLoaded( bool bLoaded )				{ m_bLoaded = bLoaded; }

	// Attributes.
	inline virtual bool IsVisualElement( void ) { return true; }
	inline virtual bool ShouldRenderLast( void ) { return true; }
	inline const char* GetDescription() { return ( "Overlay" ); }
	void SetOverlayType( unsigned short uiType )			{ m_uiFlags |= uiType; }
	void ResetOverlayType( unsigned short uiType )			{ m_uiFlags &= ~uiType; }
	unsigned short GetOverlayType( void )					{ return m_uiFlags; }

	ChunkFileResult_t SaveDataToVMF( CChunkFile *pFile, CSaveInfo *pSaveInfo );

private:

	//=========================================================================
	//
	// Basis Data
	//
	struct Basis_t
	{
		CMapFace	*m_pFace;					// Index to the face the basis were derived from	
		Vector		m_vecOrigin;				// Origin of basis vectors (in plane)
		Vector		m_vecAxes[3];				// Basis vectors
		int			m_nAxesFlip[3];				// u, v, n flip values (3 bits x,y,z) - saved off the z components of the first 3 uv points
	};

	void Basis_Clear( void );
	void Basis_SetFace( CMapFace *pFace );
	void Basis_UpdateOrigin( void );
	void Basis_BuildAxes( void );
	void Basis_SetInitialUAxis( Vector const &vecNormal );
	bool Basis_IsValid( void );
	void Basis_Copy( Basis_t *pSrc, Basis_t *pDst );
	void Basis_UpdateParentKey( void );

	// Legacy support.
	void Basis_BuildFromSideList( void );
	void Basis_ToggleAxesFlip( int iAxis, int iComponent );
	bool Basis_IsFlipped( int iAxis, int iComponent );

	//=========================================================================
	//
	// Handle Data
	//		
	struct Handles_t
	{
		int			m_iHit;									 // Index of the selected handle
		Vector2D	m_vecBasisCoords[OVERLAY_HANDLES_COUNT]; // U,V coordinates of the 4 corners in the editable plane (use basis)
		Vector		m_vec3D[OVERLAY_HANDLES_COUNT];			 // World space handles for snap testing
	};
		
	void Handles_Clear( void );
	void Handles_Build3D();
	void Handles_Render3D( CRender3D *pRender );
	void Handles_SurfToOverlayPlane( CMapFace *pFace, Vector const &vSurf, Vector &vPoint );
	void Handles_Copy( Handles_t *pSrc, Handles_t *pDst );
	void Handles_UpdateParentKey( void );
	void Handles_FixOrder();

	//=========================================================================
	//
	// ClipFace Data
	//		
	struct BlendData_t
	{
		void Init()
		{
			m_nType = 0;
			memset(m_iPoints, 0, sizeof(m_iPoints));
			memset(m_flBlends, 0, sizeof(m_flBlends));
		}
		
		int		m_nType;			// type of blend (point, edge, barycentric)
		short	m_iPoints[3];		// displacement point indices
		float	m_flBlends[3];		// blending values
	};

	struct ClipFace_t
	{
		CMapFace					*m_pBuildFace;
		int							m_nPointCount;
		CUtlVector<Vector>			m_aPoints;
		CUtlVector<Vector>			m_aDispPointUVs;		// z is always 0 (need to be this way to share functions!)
		CUtlVector<Vector2D>		m_aTexCoords[NUM_CLIPFACE_TEXCOORDS];
		CUtlVector<BlendData_t>		m_aBlends;
		
		ClipFace_t()
		{
			m_pBuildFace = NULL;
			m_nPointCount = 0;
		}

		~ClipFace_t()				
		{ 
			m_aPoints.Purge(); 
			m_aDispPointUVs.Purge(); 
			m_aBlends.Purge();

			for ( int iCoord = 0; iCoord < NUM_CLIPFACE_TEXCOORDS; ++iCoord )
			{
				m_aTexCoords[iCoord].Purge();
			}
		}
	};

	typedef CUtlVector<ClipFace_t*> ClipFaces_t;

	ClipFace_t *ClipFace_Create( int nSize );
	void		ClipFace_Destroy( ClipFace_t **ppClipFace );
	ClipFace_t *ClipFace_Copy( ClipFace_t *pSrc );

	void		ClipFace_GetBounds( ClipFace_t *pClipFace, Vector &vecMin, Vector &vecMax );

	void		ClipFace_Clip( ClipFace_t *pClipFace, cplane_t *pClipPlane, float flEpsilon, ClipFace_t **ppFront, ClipFace_t **ppBack );
	void		ClipFace_ClipBarycentric( ClipFace_t *pClipFace, cplane_t *pClipPlane, float flEpsilon, int iClip, CMapDisp *pDisp, ClipFace_t **ppFront, ClipFace_t **ppBack );
	void		ClipFace_PreClipDisp( ClipFace_t *pClipFace, CMapDisp *pDisp );
	void		ClipFace_PostClipDisp( void );
	void		ClipFace_ResolveBarycentricClip( CMapDisp *pDisp, ClipFace_t *pClipFace, int iClipFacePoint, const Vector2D &vecPointUV, float *pCoefs, int *pTris, Vector2D *pVertsUV );
	bool		ClipFace_CalcBarycentricCooefs( CMapDisp *pDisp, Vector2D *pVertsUV, const Vector2D &vecPointUV, float *pCoefs );

	int			ClipFace_GetAxisType( cplane_t *pClipPlane );
	void		ClipFace_BuildBlend( ClipFace_t *pClipFace, CMapDisp *pDisp, cplane_t *pClipPlane, int iClip, const Vector &vecUV, const Vector &vecPoint );
	void		ClipFace_CopyBlendFrom( ClipFace_t *pClipFace, BlendData_t *pBlendFrom );
	void		ClipFace_BuildFacesFromBlendedData( ClipFace_t *pClipFace );

	//=========================================================================
	//
	// Material Functions
	//
	struct Material_t
	{
		IEditorTexture				*m_pTexture;		// material
		Vector2D					m_vecTextureU;		// material starting and ending U
		Vector2D					m_vecTextureV;		// material starting and ending V
	};

	void Material_Clear( void );
	void Material_Copy( Material_t *pSrc, Material_t *pDst );
	void Material_TexCoordInit( void );
	void Material_UpdateParentKey( void );

	//=========================================================================
	//
	// Clipping
	//
	void PreClip( void );
	void PostClip( void );
	void DoClipFace( CMapFace *pFace );
	void DoClipDisp( CMapFace *pFace, ClipFace_t *pClippedFace );
	void DoClipDispInV( CMapDisp *pDisp, ClipFaces_t &aCurrentFaces );
	void DoClipDispInU( CMapDisp *pDisp, ClipFaces_t &aCurrentFaces );
	void DoClipDispInUVFromTLToBR( CMapDisp *pDisp, ClipFaces_t &aCurrentFaces );
	void DoClipDispInUVFromBLToTR( CMapDisp *pDisp, ClipFaces_t &aCurrentFaces );

	void Disp_ClipFragments( CMapDisp *pDisp, ClipFaces_t &aDispFragments );
	void Disp_DoClip( CMapDisp *pDisp, ClipFaces_t &aDispFragments, cplane_t &clipPlane, float clipDistStart, int nInterval, int nLoopStart, int nLoopEnd, int nLoopInc );

	//==========================================================================
	//
	// Transform
	//
		
	// Utility
	void OverlayUVToOverlayPlane( const Vector2D &vecUV, Vector &vecPoint );
	void OverlayPlaneToOverlayUV( const Vector &vecPoint, Vector2D &vecUV );
	void WorldToOverlayPlane( const Vector &vecWorld, Vector &vecPoint );
	void OverlayPlaneToWorld( CMapFace *pFace, const Vector &vecPlane, Vector &vecWorld );
	void OverlayPlaneToSurfFromList( const Vector &vecOverlayPoint, Vector &vecSurfPoint );
	bool EntityOnSurfFromListToBaseFacePlane( const Vector &vecWorldPoint, Vector &vecBasePoint );

	bool BuildEdgePlanes( Vector const *pPoints, int pointCount, cplane_t *pEdgePlanes, int edgePlaneCount );
	void UpdateDispBarycentric( void );
	void PostModified( void );
	void GetTriVerts( CMapDisp *pDisp, const Vector2D &vecSurfUV, int *pTris, Vector2D *pVertsUV );

private:

	Basis_t			m_Basis;			// Overlay Basis Data
	Handles_t		m_Handles;			// Overlay Handle Data
	Material_t		m_Material;			// Overlay Material

	ClipFace_t		*m_pOverlayFace;	// Primary Overlay
	ClipFaces_t		m_aRenderFaces;		// Clipped Face Cache (Render Faces)

	unsigned short	m_uiFlags;			//
	bool			m_bLoaded;
};


#endif // MAPOVERLAY_H