1 | /* |
---|
2 | orxonox - the future of 3D-vertical-scrollers |
---|
3 | |
---|
4 | Copyright (C) 2006 orx |
---|
5 | |
---|
6 | This program is free software; you can redistribute it and/or modify |
---|
7 | it under the terms of the GNU General Public License as published by |
---|
8 | the Free Software Foundation; either version 2, or (at your option) |
---|
9 | any later version. |
---|
10 | |
---|
11 | ### File Specific: |
---|
12 | main programmer: Marco Biasini |
---|
13 | |
---|
14 | */ |
---|
15 | |
---|
16 | |
---|
17 | #ifndef TERRAIN_PAGE_H |
---|
18 | #define TERRAIN_PAGE_H |
---|
19 | #define USE_VBO |
---|
20 | #include "terrain_quad.h" |
---|
21 | #include <stdio.h> |
---|
22 | |
---|
23 | |
---|
24 | class TerrainPage; |
---|
25 | class Terrain; |
---|
26 | typedef TerrainPage *pTerrainPage; |
---|
27 | |
---|
28 | struct Vertex { |
---|
29 | TexCoord t; |
---|
30 | Vector p; |
---|
31 | }; |
---|
32 | |
---|
33 | typedef Vertex *pVertex; |
---|
34 | |
---|
35 | typedef struct { |
---|
36 | Vector correct; |
---|
37 | Vector real; |
---|
38 | float diff; |
---|
39 | } LODError, *pLODError; |
---|
40 | |
---|
41 | class TerrainPage : public TerrainQuad { |
---|
42 | public: |
---|
43 | enum { TP_LEFT = 0, TP_RIGHT = 1, TP_BOTTOM = 2, TP_TOP = 3 }; |
---|
44 | const static int MAX_LODS = 5; |
---|
45 | |
---|
46 | /** |
---|
47 | * Creates a new terrain page with its lower left corner set |
---|
48 | * to C = ( _xOffset, _zOffset ), where the two values specify |
---|
49 | * the offset in the height-map. |
---|
50 | * The size of the page, as well as the scaling factors are read |
---|
51 | * from the _owner terrain page. |
---|
52 | */ |
---|
53 | TerrainPage( Terrain *_owner, int _xOffset, int _zOffset ); |
---|
54 | |
---|
55 | /** |
---|
56 | * This is used only internally for communication between the TerrainPage and |
---|
57 | * the Terrain class itself. |
---|
58 | */ |
---|
59 | inline bool isActive() { return active; } |
---|
60 | |
---|
61 | virtual ~TerrainPage(); |
---|
62 | /** |
---|
63 | * @brief Makes the terrain look as if it were created with the given level of |
---|
64 | * detail. |
---|
65 | */ |
---|
66 | void mimick( int _level ) {} |
---|
67 | |
---|
68 | /** |
---|
69 | * @brief Draws a box around the TerrainPage. For debugging purposes. |
---|
70 | */ |
---|
71 | void drawBox(); |
---|
72 | |
---|
73 | /** |
---|
74 | * @brief Calculates the smallest fitting axis aligned bounding box for this TerrainPage. |
---|
75 | */ |
---|
76 | virtual void calculateBounds(); |
---|
77 | |
---|
78 | |
---|
79 | /** |
---|
80 | * @brief Sets the visibility to _flag. If the visibility changed, the vertex and |
---|
81 | * index arrays are allocated or freed, respectively. |
---|
82 | */ |
---|
83 | inline void setVisibility( bool _flag ); |
---|
84 | |
---|
85 | /** |
---|
86 | * @brief Prepares the page for rendering. |
---|
87 | */ |
---|
88 | void show( ); |
---|
89 | |
---|
90 | /** |
---|
91 | * @brief Frees most of the memory for economomical reasons. |
---|
92 | */ |
---|
93 | void hide( ); |
---|
94 | |
---|
95 | /** |
---|
96 | * @brief Updates the tesselation if necessary. |
---|
97 | */ |
---|
98 | void updateTesselation( ); |
---|
99 | |
---|
100 | /** |
---|
101 | * @return The current tesselation level. |
---|
102 | */ |
---|
103 | int getLOD() { return currentLOD; } |
---|
104 | |
---|
105 | /** |
---|
106 | * @return The curren tween factor. This is a floating point value between 0.0f |
---|
107 | * and 1.0f |
---|
108 | */ |
---|
109 | float getTween() { return 0.0f; } |
---|
110 | |
---|
111 | /** |
---|
112 | * @brief Determines the new LOD which should be used by this terrain page based on |
---|
113 | * the distance from the camera. |
---|
114 | * |
---|
115 | * No geometry is updated in this method. You need to call |
---|
116 | * updateTesselation() in order to see a change in geometry. This method is |
---|
117 | * just a recommondation for the LOD. It might be invalid due to outer |
---|
118 | * constraints. |
---|
119 | */ |
---|
120 | int chooseLOD(); |
---|
121 | |
---|
122 | /** |
---|
123 | * If the terrain pages tesselation level changed between the last and the |
---|
124 | * current frame, this function returns true, else you'll get false as the |
---|
125 | * return value. |
---|
126 | * @return True if the page needs an update and false if not. |
---|
127 | */ |
---|
128 | bool isDirty() { return forceTesselation; } |
---|
129 | |
---|
130 | /** |
---|
131 | * @brief Calculates the maximal errors for every LOD. |
---|
132 | */ |
---|
133 | void calculateErrors(); |
---|
134 | |
---|
135 | /** |
---|
136 | * @brief Calculates the error for the given LOD. We just need to know the "worst" |
---|
137 | * vertex for choosing an appropriate LOD. |
---|
138 | */ |
---|
139 | void calculateError( int _lod ); |
---|
140 | |
---|
141 | |
---|
142 | /** |
---|
143 | * Tests if the terrain page would cull against the viewing frustum. |
---|
144 | */ |
---|
145 | bool cull( ); |
---|
146 | |
---|
147 | bool needsRetesselation(); |
---|
148 | /** |
---|
149 | * Sets the neighbors of this terrain page. pass null if a neighbor if this |
---|
150 | * pages is at the border. |
---|
151 | */ |
---|
152 | inline void setNeighbors( pTerrainPage _left, pTerrainPage _right, |
---|
153 | pTerrainPage _top, pTerrainPage _bottom ) |
---|
154 | { |
---|
155 | left = _left; right = _right; top = _top; bottom = _bottom; |
---|
156 | } |
---|
157 | |
---|
158 | /** |
---|
159 | * Sets the position of the TerrainPage. Is this needed? |
---|
160 | */ |
---|
161 | inline void setPosition( const Vector& _pos ) |
---|
162 | { |
---|
163 | position.x = _pos.x; |
---|
164 | position.y = _pos.y; |
---|
165 | position.z = _pos.z; |
---|
166 | } |
---|
167 | |
---|
168 | pTerrainPage getLeft() { return left; } |
---|
169 | pTerrainPage getRight() { return right; } |
---|
170 | pTerrainPage getBottom() { return bottom; } |
---|
171 | pTerrainPage getTop() { return top; } |
---|
172 | |
---|
173 | /** |
---|
174 | * Does what exactly what the name says and nothing more. |
---|
175 | */ |
---|
176 | void draw( ); |
---|
177 | |
---|
178 | /** |
---|
179 | * @return the next active page |
---|
180 | */ |
---|
181 | inline pTerrainPage getNext() { return next; } |
---|
182 | void setLayerVisibility( int _layer, LayerVisibility _lv ); |
---|
183 | bool hasMaterial( int _layer ); |
---|
184 | /** |
---|
185 | * Returns the previous active page |
---|
186 | */ |
---|
187 | inline pTerrainPage getPrevious() { return previous; } |
---|
188 | inline int getCurrentLOD() { return currentLOD; } |
---|
189 | /** |
---|
190 | * @return Returns the wanted LOD. Make sure you call this method after a call to |
---|
191 | * chooseLOD() or you will get screwed values. |
---|
192 | */ |
---|
193 | inline int getWantedLOD() { return wantedLOD; } |
---|
194 | |
---|
195 | /** |
---|
196 | * @brief Removes the page from the active page list. |
---|
197 | */ |
---|
198 | void deactivate(); |
---|
199 | |
---|
200 | /** |
---|
201 | * @brief Inserts the page into the active page list. |
---|
202 | */ |
---|
203 | void activate(); |
---|
204 | |
---|
205 | inline void setWantedLOD( int _lod ) |
---|
206 | { |
---|
207 | if ( _lod >= TerrainPage::MAX_LODS ) |
---|
208 | wantedLOD = TerrainPage::MAX_LODS-1; |
---|
209 | else if ( _lod < 0 ) |
---|
210 | wantedLOD = 0; |
---|
211 | else |
---|
212 | wantedLOD = _lod; |
---|
213 | } |
---|
214 | |
---|
215 | protected: |
---|
216 | |
---|
217 | /** |
---|
218 | * @brief Tesselates one row of the terrain page. |
---|
219 | * @param _z The z-offset of the row |
---|
220 | * @param _xStride Defines the step-size horizontally |
---|
221 | * @param _zStride Defines the step-size vertically. |
---|
222 | * @param _adaptLeft True if the left neighbor has a coarser |
---|
223 | * tesselation level. |
---|
224 | * @param _adaptRight True if the right neighbor has a coarser |
---|
225 | * tesselation level. |
---|
226 | */ |
---|
227 | void tesselateRow( int _z, int _xStride, int _zStride, bool _adaptLeft, bool _adaptRight ); |
---|
228 | void tesselateTopRow( int _z, int _stride, bool _adaptLeft, bool _adaptRight ); |
---|
229 | void tesselateBottomRow( int _z, int _stride, bool _adaptLeft, bool _adaptRight ); |
---|
230 | /** |
---|
231 | * @brief Returns four boolean values in the oder |
---|
232 | */ |
---|
233 | void determineBorderAdaption( bool _adapt[] ); |
---|
234 | |
---|
235 | /** |
---|
236 | * @brief Adds the given index to the index-array |
---|
237 | */ |
---|
238 | inline void addIndex( unsigned short _index ); |
---|
239 | |
---|
240 | /** |
---|
241 | * @brief We programmers are very lazy :) This method just adds the last added index |
---|
242 | * again. |
---|
243 | */ |
---|
244 | inline void addAgain(); |
---|
245 | |
---|
246 | |
---|
247 | void getCoord( int _x, int _z, TexCoord& _coord) const; |
---|
248 | |
---|
249 | /** |
---|
250 | * Fills _vertex with the vertex information at index. |
---|
251 | */ |
---|
252 | void getVertex( int _x, int _z, Vector& _vertex ) const; |
---|
253 | |
---|
254 | /** |
---|
255 | * Use this method to safely get a vertex at location ( _x, _z ). If it wasn't |
---|
256 | * created before, this method does that for you. |
---|
257 | */ |
---|
258 | unsigned short getIndex( int _x, int _z ); |
---|
259 | void tesselateLevelFourPage( bool _adapt[] ); |
---|
260 | /** |
---|
261 | * Generates the tesselation for the given level of detail. |
---|
262 | */ |
---|
263 | void tesselate( int _lod ); |
---|
264 | |
---|
265 | float getAltitude( int _x, int _z ) const; |
---|
266 | |
---|
267 | int currentLOD, |
---|
268 | wantedLOD; |
---|
269 | pTerrainPage left, |
---|
270 | right, |
---|
271 | top, |
---|
272 | bottom; |
---|
273 | bool forceTesselation; |
---|
274 | bool active; |
---|
275 | pVertex vertices; |
---|
276 | unsigned short *indices; |
---|
277 | unsigned short *indexHash; |
---|
278 | int numIndices; |
---|
279 | int numVertices; |
---|
280 | LayerVisibility layerVisibility[8]; |
---|
281 | bool hasfull; |
---|
282 | #ifdef USE_VBO |
---|
283 | GLuint ibIdentifier, |
---|
284 | vbIdentifier; |
---|
285 | #endif |
---|
286 | bool isVisible; |
---|
287 | pTerrainPage next; |
---|
288 | pTerrainPage previous; |
---|
289 | LODError *errors; |
---|
290 | Vector position; |
---|
291 | }; |
---|
292 | |
---|
293 | inline void TerrainPage::setVisibility( bool _flag ) |
---|
294 | { |
---|
295 | if ( _flag ) { |
---|
296 | if ( !isVisible ) { |
---|
297 | isVisible = true; |
---|
298 | show( ); |
---|
299 | } |
---|
300 | active = true; |
---|
301 | } |
---|
302 | else { |
---|
303 | if ( isVisible ) { |
---|
304 | isVisible = false; |
---|
305 | hide( ); |
---|
306 | } |
---|
307 | } |
---|
308 | } |
---|
309 | |
---|
310 | inline void TerrainPage::addIndex( unsigned short _index ) |
---|
311 | { |
---|
312 | indices[numIndices] = _index; numIndices++; |
---|
313 | } |
---|
314 | |
---|
315 | inline void TerrainPage::addAgain() |
---|
316 | { |
---|
317 | indices[numIndices] = indices[numIndices-1]; numIndices++; |
---|
318 | } |
---|
319 | |
---|
320 | #endif |
---|