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