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
|