aboutsummaryrefslogtreecommitdiff
path: root/sp/src/public/disp_powerinfo.h
blob: 0abd03573637ae4e7fbf92d405992033987380a3 (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
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: This module defines the CPowerInfo class, which contains a 
//          whole bunch of precalculated data for each displacement power.
//          It holds data that indicates how to tesselate, how to access
//          neighbor displacements, etc.
//
// $NoKeywords: $
//=============================================================================//

#ifndef DISP_POWERINFO_H
#define DISP_POWERINFO_H
#ifdef _WIN32
#pragma once
#endif


#include "disp_vertindex.h"
#include "bspfile.h"


#define NUM_POWERINFOS				(MAX_MAP_DISP_POWER+1)


struct DispNodeInfo_t
{
	enum
	{
		// Indicates if any children at all have triangles
		CHILDREN_HAVE_TRIANGLES = 0x1
	};


	// Indicates which tesselation indices are associated with a node
	unsigned short	m_FirstTesselationIndex;
	unsigned char	m_Count;
	unsigned char	m_Flags;
};


// ------------------------------------------------------------------------ //
// CTesselateWindings are used to tell what order a node needs to visit
// vertices while tesselating.
// ------------------------------------------------------------------------ //
class CTesselateVert
{
public:
				CTesselateVert( CVertIndex const &index, int iNode );

	CVertIndex	m_Index;
	short			m_iNode;	// Which node this vert is a part of (-1 on left, right, up, and down).
};


class CTesselateWinding
{
public:
	CTesselateVert	*m_Verts;
	short			m_nVerts;	// (includes the last vert)
};


class CVertDependency
{
public:
	
	// Returns false if there is no dependency stored here.
	bool		IsValid()	{ return m_iVert.x != -1; }


public:
			
	// The vert index is in the same power as the source displacement.
	// It is also wrapped, so for example, on the middle of the right edge
	// of a 3x3, it will have a dependency on the 3x3's root node (1,1), and it
	// will have another (1,1) entry that references a neighbor.
	CVertIndex	m_iVert;

	// This is -1 if the vert exists inside the source displacement.
	// It is one of the NEIGHBOREDGE_ codes above if it reaches into a neighbor.
	short		m_iNeighbor;
};


// Precalculated data about displacement vertices.
class CVertInfo
{
public:
					CVertInfo();

	// These are the vertices that this vertex depends on (vertices that must be 
	// active for this vert to exist).
	CVertDependency	m_Dependencies[2];

	// These are the vertices that have this vert in their m_Dependencies.
	enum			{ NUM_REVERSE_DEPENDENCIES=4 };
	CVertDependency	m_ReverseDependencies[NUM_REVERSE_DEPENDENCIES];

	short			m_iNodeLevel;		// -1 if this is not a node. Otherwise, the recursion level
										// of this node (root node = 1).
	CVertIndex		m_iParent;			// x=-1 if this is a not a node or if it's the root node.
};


class CTwoUShorts
{
public:
	unsigned short	m_Values[2];
};


class CFourVerts
{
public:
	CVertIndex		m_Verts[4];
};


// Used for referencing triangles in the fully-tesselated displacement by index.
class CTriInfo
{
public:
	unsigned short	m_Indices[3];
};


// Precalculated data for displacements of a certain power.
class CPowerInfo
{
public:
						CPowerInfo( 
							CVertInfo *pVertInfo, 
							CFourVerts *pSideVerts,
							CFourVerts *pChildVerts,
							CFourVerts *pSideVertCorners,
							CTwoUShorts *pErrorEdges,
							CTriInfo *pTriInfos );

	int					GetPower() const		{ return m_Power; }
	int					GetSideLength() const	{ return m_SideLength; }
	const CVertIndex&	GetRootNode() const		{ return m_RootNode; }
	int					GetMidPoint() const		{ return m_MidPoint; } // Half the edge length.

	// Get at the tri list.
	int					GetNumTriInfos() const		{ return m_nTriInfos; }
	const CTriInfo*		GetTriInfo( int i ) const	{ return &m_pTriInfos[i]; }

	// Get the number of vertices in a displacement of this power.
	int					GetNumVerts() const			{ return m_MaxVerts; }
	
	// Return a corner point index. Indexed by the CORNER_ defines.
	const CVertIndex&	GetCornerPointIndex( int iCorner ) const;


public:

	CVertInfo			*m_pVertInfo;
	CFourVerts			*m_pSideVerts;	// The 4 side verts for each node.
	CFourVerts			*m_pChildVerts;	// The 4 children for each node.
	CFourVerts			*m_pSideVertCorners;
	CTwoUShorts			*m_pErrorEdges;			// These are the edges
												// that are used to measure the screenspace
												// error with respect to each vert.

	CTriInfo			*m_pTriInfos;
	int					m_nTriInfos;
	
	int					m_Power;

	CVertIndex			m_RootNode;
	int					m_SideLength;
	int					m_SideLengthM1;			// Side length minus 1.
	int					m_MidPoint;				// Side length / 2.
	int					m_MaxVerts;				// m_SideLength * m_SideLength
	int					m_NodeCount;			// total # of nodes, including children

	// Precalculated increments if you're using a bit vector to represent nodes.
	// Starting at level 0 of the tree, this stores the increment between the nodes at this
	// level. Vectors holding node data are stored in preorder traversal, and these
	// increments tell the number of elements between nodes at each level.
	int					m_NodeIndexIncrements[MAX_MAP_DISP_POWER];

	CVertIndex			m_EdgeStartVerts[4];
	CVertIndex			m_EdgeIncrements[4];

	CVertIndex			m_NeighborStartVerts[4][4];	// [side][orientation]
	CVertIndex			m_NeighborIncrements[4][4];	// [side][orientation]


private:
	friend void InitPowerInfo( CPowerInfo *pInfo, int iMaxPower );

	CVertIndex			m_CornerPointIndices[4];
};


// ----------------------------------------------------------------------------- //
// Globals.
// ----------------------------------------------------------------------------- //

// Indexed by the TWINDING_ enums.
extern CTesselateWinding	g_TWinding;


// ----------------------------------------------------------------------------- //
// Functions.
// ----------------------------------------------------------------------------- //

// Valid indices are MIN_MAP_DISP_POWER through (and including) MAX_MAP_DISP_POWER.
const CPowerInfo* GetPowerInfo( int iPower );


#endif // DISP_POWERINFO_H