[8319] | 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 |
---|
[8569] | 19 | #define USE_VBO |
---|
[8319] | 20 | #include "terrain_quad.h" |
---|
| 21 | #include <stdio.h> |
---|
| 22 | |
---|
| 23 | |
---|
| 24 | class TerrainPage; |
---|
| 25 | class Terrain; |
---|
| 26 | typedef TerrainPage *pTerrainPage; |
---|
| 27 | |
---|
[8569] | 28 | struct Vertex { |
---|
| 29 | TexCoord t; |
---|
| 30 | Triple p; |
---|
| 31 | }; |
---|
| 32 | |
---|
| 33 | typedef Vertex *pVertex; |
---|
| 34 | |
---|
[8319] | 35 | typedef struct { |
---|
| 36 | Triple correct; |
---|
| 37 | Triple real; |
---|
| 38 | float diff; |
---|
| 39 | } LODError, *pLODError; |
---|
| 40 | |
---|
| 41 | class TerrainPage : public TerrainQuad { |
---|
| 42 | public: |
---|
[8349] | 43 | enum { TP_LEFT = 0, TP_RIGHT = 1, TP_BOTTOM = 2, TP_TOP = 3 }; |
---|
[8641] | 44 | const static int MAX_LODS = 5; |
---|
[8775] | 45 | |
---|
[8319] | 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 ); |
---|
[8321] | 54 | |
---|
[8320] | 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; } |
---|
[8319] | 60 | |
---|
[8775] | 61 | virtual ~TerrainPage(); |
---|
[8319] | 62 | /** |
---|
[8321] | 63 | * @brief Makes the terrain look as if it were created with the given level of |
---|
[8319] | 64 | * detail. |
---|
| 65 | */ |
---|
| 66 | void mimick( int _level ) {} |
---|
| 67 | |
---|
[8320] | 68 | /** |
---|
[8321] | 69 | * @brief Draws a box around the TerrainPage. For debugging purposes. |
---|
[8320] | 70 | */ |
---|
[8319] | 71 | void drawBox(); |
---|
[8320] | 72 | |
---|
| 73 | /** |
---|
[8321] | 74 | * @brief Calculates the smallest fitting axis aligned bounding box for this TerrainPage. |
---|
[8320] | 75 | */ |
---|
[8319] | 76 | virtual void calculateBounds(); |
---|
[8320] | 77 | |
---|
| 78 | |
---|
[8319] | 79 | /** |
---|
[8770] | 80 | * @brief Sets the visibility to _flag. If the visibility changed, the vertex and |
---|
| 81 | * index arrays are allocated or freed, respectively. |
---|
[8319] | 82 | */ |
---|
| 83 | inline void setVisibility( bool _flag ); |
---|
| 84 | |
---|
| 85 | /** |
---|
[8321] | 86 | * @brief Prepares the page for rendering. |
---|
[8319] | 87 | */ |
---|
| 88 | void show( ); |
---|
[8320] | 89 | |
---|
| 90 | /** |
---|
[8321] | 91 | * @brief Frees most of the memory for economomical reasons. |
---|
[8320] | 92 | */ |
---|
[8319] | 93 | void hide( ); |
---|
[8320] | 94 | |
---|
[8319] | 95 | /** |
---|
[8321] | 96 | * @brief Updates the tesselation if necessary. |
---|
[8319] | 97 | */ |
---|
| 98 | void updateTesselation( ); |
---|
| 99 | |
---|
| 100 | /** |
---|
[8321] | 101 | * @return The current tesselation level. |
---|
[8319] | 102 | */ |
---|
| 103 | int getLOD() { return currentLOD; } |
---|
| 104 | |
---|
| 105 | /** |
---|
[8770] | 106 | * @return The curren tween factor. This is a floating point value between 0.0f |
---|
| 107 | * and 1.0f |
---|
[8319] | 108 | */ |
---|
| 109 | float getTween() { return 0.0f; } |
---|
| 110 | |
---|
| 111 | /** |
---|
[8321] | 112 | * @brief Determines the new LOD which should be used by this terrain page based on |
---|
[8319] | 113 | * the distance from the camera. |
---|
[8321] | 114 | * |
---|
| 115 | * No geometry is updated in this method. You need to call |
---|
[8319] | 116 | * updateTesselation() in order to see a change in geometry. This method is |
---|
[8349] | 117 | * just a recommondation for the LOD. It might be invalid due to outer |
---|
| 118 | * constraints. |
---|
[8319] | 119 | */ |
---|
| 120 | int chooseLOD(); |
---|
[8320] | 121 | |
---|
[8319] | 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. |
---|
[8321] | 126 | * @return True if the page needs an update and false if not. |
---|
[8319] | 127 | */ |
---|
[8320] | 128 | bool isDirty() { return forceTesselation; } |
---|
[8319] | 129 | |
---|
| 130 | /** |
---|
[8321] | 131 | * @brief Calculates the maximal errors for every LOD. |
---|
[8319] | 132 | */ |
---|
| 133 | void calculateErrors(); |
---|
| 134 | |
---|
| 135 | /** |
---|
[8321] | 136 | * @brief Calculates the error for the given LOD. We just need to know the "worst" |
---|
[8319] | 137 | * vertex for choosing an appropriate LOD. |
---|
| 138 | */ |
---|
| 139 | void calculateError( int _lod ); |
---|
[8320] | 140 | |
---|
| 141 | |
---|
[8319] | 142 | /** |
---|
| 143 | * Tests if the terrain page would cull against the viewing frustum. |
---|
| 144 | */ |
---|
| 145 | bool cull( ); |
---|
[8349] | 146 | |
---|
| 147 | bool needsRetesselation(); |
---|
[8319] | 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 | } |
---|
[8320] | 157 | |
---|
| 158 | /** |
---|
| 159 | * Sets the position of the TerrainPage. Is this needed? |
---|
| 160 | */ |
---|
[8319] | 161 | inline void setPosition( const Triple& _pos ) |
---|
| 162 | { |
---|
| 163 | position.x = _pos.x; |
---|
| 164 | position.y = _pos.y; |
---|
| 165 | position.z = _pos.z; |
---|
| 166 | } |
---|
[8349] | 167 | |
---|
| 168 | pTerrainPage getLeft() { return left; } |
---|
| 169 | pTerrainPage getRight() { return right; } |
---|
| 170 | pTerrainPage getBottom() { return bottom; } |
---|
| 171 | pTerrainPage getTop() { return top; } |
---|
[8319] | 172 | |
---|
| 173 | /** |
---|
| 174 | * Does what exactly what the name says and nothing more. |
---|
| 175 | */ |
---|
| 176 | void draw( ); |
---|
| 177 | |
---|
[8320] | 178 | /** |
---|
[8321] | 179 | * @return the next active page |
---|
[8320] | 180 | */ |
---|
[8319] | 181 | inline pTerrainPage getNext() { return next; } |
---|
[8745] | 182 | void setLayerVisibility( int _layer, LayerVisibility _lv ); |
---|
| 183 | bool hasMaterial( int _layer ); |
---|
[8320] | 184 | /** |
---|
| 185 | * Returns the previous active page |
---|
| 186 | */ |
---|
[8319] | 187 | inline pTerrainPage getPrevious() { return previous; } |
---|
[8349] | 188 | inline int getCurrentLOD() { return currentLOD; } |
---|
[8320] | 189 | /** |
---|
[8321] | 190 | * @return Returns the wanted LOD. Make sure you call this method after a call to |
---|
[8320] | 191 | * chooseLOD() or you will get screwed values. |
---|
| 192 | */ |
---|
[8319] | 193 | inline int getWantedLOD() { return wantedLOD; } |
---|
[8320] | 194 | |
---|
| 195 | /** |
---|
[8321] | 196 | * @brief Removes the page from the active page list. |
---|
[8320] | 197 | */ |
---|
[8319] | 198 | void deactivate(); |
---|
[8320] | 199 | |
---|
| 200 | /** |
---|
[8321] | 201 | * @brief Inserts the page into the active page list. |
---|
[8320] | 202 | */ |
---|
[8319] | 203 | void activate(); |
---|
[8745] | 204 | |
---|
[8548] | 205 | inline void setWantedLOD( int _lod ) |
---|
| 206 | { |
---|
[8593] | 207 | if ( _lod >= TerrainPage::MAX_LODS ) |
---|
| 208 | wantedLOD = TerrainPage::MAX_LODS-1; |
---|
| 209 | else if ( _lod < 0 ) |
---|
[8569] | 210 | wantedLOD = 0; |
---|
[8548] | 211 | else |
---|
| 212 | wantedLOD = _lod; |
---|
[8593] | 213 | } |
---|
| 214 | |
---|
[8548] | 215 | protected: |
---|
| 216 | |
---|
| 217 | /** |
---|
| 218 | * @brief Tesselates one row of the terrain page. |
---|
| 219 | * @param _z The z-offset of the row |
---|
[8684] | 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. |
---|
[8548] | 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 ); |
---|
[8741] | 228 | void tesselateTopRow( int _z, int _stride, bool _adaptLeft, bool _adaptRight ); |
---|
| 229 | void tesselateBottomRow( int _z, int _stride, bool _adaptLeft, bool _adaptRight ); |
---|
[8548] | 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, Triple& _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 | */ |
---|
[8641] | 258 | unsigned short getIndex( int _x, int _z ); |
---|
| 259 | void tesselateLevelFourPage( bool _adapt[] ); |
---|
[8548] | 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; |
---|
[8569] | 275 | pVertex vertices; |
---|
[8548] | 276 | unsigned short *indices; |
---|
| 277 | unsigned short *indexHash; |
---|
| 278 | int numIndices; |
---|
| 279 | int numVertices; |
---|
[8745] | 280 | LayerVisibility layerVisibility[8]; |
---|
| 281 | bool hasfull; |
---|
[8569] | 282 | #ifdef USE_VBO |
---|
| 283 | GLuint ibIdentifier, |
---|
| 284 | vbIdentifier; |
---|
| 285 | #endif |
---|
[8548] | 286 | bool isVisible; |
---|
| 287 | pTerrainPage next; |
---|
| 288 | pTerrainPage previous; |
---|
| 289 | LODError *errors; |
---|
| 290 | Triple position; |
---|
[8319] | 291 | }; |
---|
| 292 | |
---|
| 293 | inline void TerrainPage::setVisibility( bool _flag ) |
---|
| 294 | { |
---|
| 295 | if ( _flag ) { |
---|
| 296 | if ( !isVisible ) { |
---|
| 297 | isVisible = true; |
---|
| 298 | show( ); |
---|
| 299 | } |
---|
[8328] | 300 | active = true; |
---|
[8319] | 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 |
---|