1 // Copyright (C) 2002-2012 Nikolaus Gebhardt 2 // This file is part of the "Irrlicht Engine". 3 // For conditions of distribution and use, see copyright notice in irrlicht.h 4 5 // The code for the TerrainSceneNode is based on the GeoMipMapSceneNode 6 // developed by Spintz. He made it available for Irrlicht and allowed it to be 7 // distributed under this licence. I only modified some parts. A lot of thanks go to him. 8 9 #ifndef __C_TERRAIN_SCENE_NODE_H__ 10 #define __C_TERRAIN_SCENE_NODE_H__ 11 12 #include "ITerrainSceneNode.h" 13 #include "IDynamicMeshBuffer.h" 14 #include "path.h" 15 16 namespace irr 17 { 18 namespace io 19 { 20 class IFileSystem; 21 class IReadFile; 22 } 23 namespace scene 24 { 25 struct SMesh; 26 class ITextSceneNode; 27 28 //! A scene node for displaying terrain using the geo mip map algorithm. 29 class CTerrainSceneNode : public ITerrainSceneNode 30 { 31 public: 32 33 //! constructor 34 //! \param parent: The node which this node is a child of. Making this node a child of another node, or 35 //! making it a parent of another node is yet untested and most likely does not work properly. 36 //! \param mgr: Pointer to the scene manager. 37 //! \param id: The id of the node 38 //! \param maxLOD: The maximum LOD ( Level of Detail ) for the node. 39 //! \param patchSize: An E_GEOMIPMAP_PATCH_SIZE enumeration defining the size of each patch of the terrain. 40 //! \param position: The absolute position of this node. 41 //! \param rotation: The absolute rotation of this node. ( NOT YET IMPLEMENTED ) 42 //! \param scale: The scale factor for the terrain. If you're using a heightmap of size 128x128 and would like 43 //! your terrain to be 12800x12800 in game units, then use a scale factor of ( core::vector ( 100.0f, 100.0f, 100.0f ). 44 //! If you use a Y scaling factor of 0.0f, then your terrain will be flat. 45 CTerrainSceneNode(ISceneNode* parent, ISceneManager* mgr, io::IFileSystem* fs, s32 id, 46 s32 maxLOD = 4, E_TERRAIN_PATCH_SIZE patchSize = ETPS_17, 47 const core::vector3df& position = core::vector3df(0.0f, 0.0f, 0.0f), 48 const core::vector3df& rotation = core::vector3df(0.0f, 0.0f, 0.0f), 49 const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f)); 50 51 virtual ~CTerrainSceneNode(); 52 53 //! Initializes the terrain data. Loads the vertices from the heightMapFile. 54 virtual bool loadHeightMap(io::IReadFile* file, 55 video::SColor vertexColor = video::SColor ( 255, 255, 255, 255 ), s32 smoothFactor = 0 ); 56 57 //! Initializes the terrain data. Loads the vertices from the heightMapFile. 58 virtual bool loadHeightMapRAW(io::IReadFile* file, s32 bitsPerPixel = 16, 59 bool signedData=true, bool floatVals=false, s32 width=0, video::SColor vertexColor = video::SColor ( 255, 255, 255, 255 ), s32 smoothFactor = 0 ); 60 61 //! Returns the material based on the zero based index i. This scene node only uses 62 //! 1 material. 63 //! \param i: Zero based index i. UNUSED, left in for virtual purposes. 64 //! \return Returns the single material this scene node uses. 65 virtual video::SMaterial& getMaterial(u32 i); 66 67 //! Returns amount of materials used by this scene node ( always 1 ) 68 //! \return Returns current count of materials used by this scene node ( always 1 ) 69 virtual u32 getMaterialCount() const; 70 71 //! Gets the last scaling factor applied to the scene node. This value only represents the 72 //! last scaling factor presented to the node. For instance, if you make create the node 73 //! with a scale factor of ( 1.0f, 1.0f, 1.0f ) then call setScale ( 50.0f, 5.0f, 50.0f ), 74 //! then make another call to setScale with the values ( 2.0f, 2.0f, 2.0f ), this will return 75 //! core::vector3df ( 2.0f, 2.0f, 2.0f ), although the total scaling of the scene node is 76 //! core::vector3df ( 100.0f, 10.0f, 100.0f ). 77 //! \return Returns the last scaling factor passed to the scene node. getScale()78 virtual const core::vector3df& getScale() const 79 { 80 return TerrainData.Scale; 81 } 82 83 //! Scales the scene nodes vertices by the vector specified. 84 //! \param scale: Scaling factor to apply to the node. 85 virtual void setScale(const core::vector3df& scale); 86 87 //! Gets the last rotation factor applied to the scene node. 88 //! \return Returns the last rotation factor applied to the scene node. getRotation()89 virtual const core::vector3df& getRotation() const 90 { 91 return TerrainData.Rotation; 92 } 93 94 //! Rotates the node. This only modifies the relative rotation of the node. 95 //! \param rotation: New rotation of the node in degrees. 96 virtual void setRotation(const core::vector3df& rotation); 97 98 //! Sets the pivot point for rotation of this node. 99 //! NOTE: The default for the RotationPivot will be the center of the individual tile. 100 virtual void setRotationPivot( const core::vector3df& pivot ); 101 102 //! Gets the last positioning vector applied to the scene node. 103 //! \return Returns the last position vector applied to the scene node. getPosition()104 virtual const core::vector3df& getPosition() const 105 { 106 return TerrainData.Position; 107 } 108 109 //! Moves the scene nodes vertices by the vector specified. 110 //! \param newpos: Vector specifying how much to move each vertex of the scene node. 111 virtual void setPosition(const core::vector3df& newpos); 112 113 //! Updates the scene nodes indices if the camera has moved or rotated by a certain 114 //! threshold, which can be changed using the SetCameraMovementDeltaThreshold and 115 //! SetCameraRotationDeltaThreshold functions. This also determines if a given patch 116 //! for the scene node is within the view frustum and if it's not the indices are not 117 //! generated for that patch. 118 virtual void OnRegisterSceneNode(); 119 120 //! Render the scene node 121 virtual void render(); 122 123 //! Return the bounding box of the entire terrain. 124 virtual const core::aabbox3d<f32>& getBoundingBox() const; 125 126 //! Return the bounding box of a patch 127 virtual const core::aabbox3d<f32>& getBoundingBox(s32 patchX, s32 patchZ) const; 128 129 //! Return the number of indices currently used to draw the scene node. getIndexCount()130 virtual u32 getIndexCount() const { return IndicesToRender; } 131 132 //! Returns the mesh 133 virtual IMesh* getMesh(); 134 135 //! Returns a pointer to the buffer used by the terrain (most users will not need this) getRenderBuffer()136 virtual IMeshBuffer* getRenderBuffer() { return RenderBuffer; } 137 138 //! Gets the meshbuffer data based on a specified Level of Detail. 139 //! \param mb: A reference to an IDynamicMeshBuffer object 140 //! \param LOD: The Level Of Detail you want the indices from. 141 virtual void getMeshBufferForLOD(IDynamicMeshBuffer& mb, s32 LOD=0) const; 142 143 //! Gets the indices for a specified patch at a specified Level of Detail. 144 //! \param indices: A reference to an array of u32 indices. 145 //! \param patchX: Patch x coordinate. 146 //! \param patchZ: Patch z coordinate. 147 //! \param LOD: The level of detail to get for that patch. If -1, then get 148 //! the CurrentLOD. If the CurrentLOD is set to -1, meaning it's not shown, 149 //! then it will retrieve the triangles at the highest LOD (0). 150 //! \return: Number of indices put into the buffer. 151 virtual s32 getIndicesForPatch(core::array<u32>& indices, 152 s32 patchX, s32 patchZ, s32 LOD=0); 153 154 //! Populates an array with the CurrentLOD of each patch. 155 //! \param LODs: A reference to a core::array<s32> to hold the values 156 //! \return Returns the number of elements in the array 157 virtual s32 getCurrentLODOfPatches(core::array<s32>& LODs) const; 158 159 //! Manually sets the LOD of a patch 160 //! \param patchX: Patch x coordinate. 161 //! \param patchZ: Patch z coordinate. 162 //! \param LOD: The level of detail to set the patch to. 163 virtual void setLODOfPatch(s32 patchX, s32 patchZ, s32 LOD=0); 164 165 //! Returns center of terrain. getTerrainCenter()166 virtual const core::vector3df& getTerrainCenter() const 167 { 168 return TerrainData.Center; 169 } 170 171 //! Returns center of terrain. 172 virtual f32 getHeight( f32 x, f32 y ) const; 173 174 //! Sets the movement camera threshold which is used to determine when to recalculate 175 //! indices for the scene node. The default value is 10.0f. setCameraMovementDelta(f32 delta)176 virtual void setCameraMovementDelta(f32 delta) 177 { 178 CameraMovementDelta = delta; 179 } 180 181 //! Sets the rotation camera threshold which is used to determine when to recalculate 182 //! indices for the scene node. The default value is 1.0f. setCameraRotationDelta(f32 delta)183 virtual void setCameraRotationDelta(f32 delta) 184 { 185 CameraRotationDelta = delta; 186 } 187 188 //! Sets whether or not the node should dynamically update it its associated selector when 189 //! the geomipmap data changes. 190 //! param bVal: Boolean value representing whether or not to update selector dynamically. 191 //! NOTE: Temporarily disabled while working out issues with DynamicSelectorUpdate setDynamicSelectorUpdate(bool bVal)192 virtual void setDynamicSelectorUpdate(bool bVal ) { DynamicSelectorUpdate = false; } 193 194 //! Override the default generation of distance thresholds for determining the LOD a patch 195 //! is rendered at. If any LOD is overridden, then the scene node will no longer apply 196 //! scaling factors to these values. If you override these distances and then apply 197 //! a scale to the scene node, it is your responsibility to update the new distances to 198 //! work best with your new terrain size. 199 virtual bool overrideLODDistance( s32 LOD, f64 newDistance ); 200 201 //! Scales the two textures 202 virtual void scaleTexture(f32 scale = 1.0f, f32 scale2 = 0.0f); 203 204 //! Returns type of the scene node getType()205 virtual ESCENE_NODE_TYPE getType() const {return ESNT_TERRAIN;} 206 207 //! Writes attributes of the scene node. 208 virtual void serializeAttributes(io::IAttributes* out, 209 io::SAttributeReadWriteOptions* options=0) const; 210 211 //! Reads attributes of the scene node. 212 virtual void deserializeAttributes(io::IAttributes* in, 213 io::SAttributeReadWriteOptions* options=0); 214 215 //! Creates a clone of this scene node and its children. 216 virtual ISceneNode* clone(ISceneNode* newParent, 217 ISceneManager* newManager); 218 219 private: 220 friend class CTerrainTriangleSelector; 221 222 struct SPatch 223 { SPatchSPatch224 SPatch() 225 : Top(0), Bottom(0), Right(0), Left(0), CurrentLOD(-1) 226 { 227 } 228 229 SPatch* Top; 230 SPatch* Bottom; 231 SPatch* Right; 232 SPatch* Left; 233 s32 CurrentLOD; 234 core::aabbox3df BoundingBox; 235 core::vector3df Center; 236 }; 237 238 struct STerrainData 239 { STerrainDataSTerrainData240 STerrainData(s32 patchSize, s32 maxLOD, const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale) 241 : Patches(0), Size(0), Position(position), Rotation(rotation), 242 Scale(scale), PatchSize(patchSize), CalcPatchSize(patchSize-1), 243 PatchCount(0), MaxLOD(maxLOD) 244 { 245 } 246 247 SPatch* Patches; 248 s32 Size; 249 core::vector3df Position; 250 core::vector3df Rotation; 251 core::vector3df RotationPivot; 252 core::vector3df Scale; 253 core::vector3df Center; 254 s32 PatchSize; 255 s32 CalcPatchSize; 256 s32 PatchCount; 257 s32 MaxLOD; 258 core::aabbox3df BoundingBox; 259 core::array<f64> LODDistanceThreshold; 260 }; 261 262 263 virtual void preRenderCalculationsIfNeeded(); 264 265 virtual void preRenderLODCalculations(); 266 virtual void preRenderIndicesCalculations(); 267 268 //! get indices when generating index data for patches at varying levels of detail. 269 u32 getIndex(const s32 PatchX, const s32 PatchZ, const s32 PatchIndex, u32 vX, u32 vZ) const; 270 271 //! smooth the terrain 272 void smoothTerrain(IDynamicMeshBuffer* mb, s32 smoothFactor); 273 274 //! calculate smooth normals 275 void calculateNormals(IDynamicMeshBuffer* mb); 276 277 //! create patches, stuff that needs to only be done once for patches goes here. 278 void createPatches(); 279 280 //! calculate the internal STerrainData structure 281 void calculatePatchData(); 282 283 //! calculate or recalculate the distance thresholds 284 void calculateDistanceThresholds(bool scalechanged = false); 285 286 //! sets the CurrentLOD of all patches to the specified LOD 287 void setCurrentLODOfPatches(s32 i); 288 289 //! sets the CurrentLOD of TerrainData patches to the LODs specified in the array 290 void setCurrentLODOfPatches(const core::array<s32>& lodarray); 291 292 //! Apply transformation changes( scale, position, rotation ) 293 void applyTransformation(); 294 295 STerrainData TerrainData; 296 SMesh* Mesh; 297 298 IDynamicMeshBuffer *RenderBuffer; 299 300 u32 VerticesToRender; 301 u32 IndicesToRender; 302 303 bool DynamicSelectorUpdate; 304 bool OverrideDistanceThreshold; 305 bool UseDefaultRotationPivot; 306 bool ForceRecalculation; 307 308 core::vector3df OldCameraPosition; 309 core::vector3df OldCameraRotation; 310 core::vector3df OldCameraUp; 311 f32 OldCameraFOV; 312 f32 CameraMovementDelta; 313 f32 CameraRotationDelta; 314 f32 CameraFOVDelta; 315 316 // needed for (de)serialization 317 f32 TCoordScale1; 318 f32 TCoordScale2; 319 s32 SmoothFactor; 320 io::path HeightmapFile; 321 io::IFileSystem* FileSystem; 322 }; 323 324 325 } // end namespace scene 326 } // end namespace irr 327 328 #endif // __C_TERRAIN_SCENE_NODE_H__ 329 330 331