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 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
|
// Copyright (C) 2002-2012 Nikolaus Gebhardt
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
// The code for the TerrainSceneNode is based on the GeoMipMapSceneNode
// developed by Spintz. He made it available for Irrlicht and allowed it to be
// distributed under this licence. I only modified some parts. A lot of thanks go to him.
#ifndef __C_TERRAIN_SCENE_NODE_H__
#define __C_TERRAIN_SCENE_NODE_H__
#include "ITerrainSceneNode.h"
#include "IDynamicMeshBuffer.h"
#include "path.h"
namespace irr
{
namespace io
{
class IFileSystem;
class IReadFile;
}
namespace scene
{
struct SMesh;
class ITextSceneNode;
//! A scene node for displaying terrain using the geo mip map algorithm.
class CTerrainSceneNode : public ITerrainSceneNode
{
public:
//! constructor
//! \param parent: The node which this node is a child of. Making this node a child of another node, or
//! making it a parent of another node is yet untested and most likely does not work properly.
//! \param mgr: Pointer to the scene manager.
//! \param id: The id of the node
//! \param maxLOD: The maximum LOD ( Level of Detail ) for the node.
//! \param patchSize: An E_GEOMIPMAP_PATCH_SIZE enumeration defining the size of each patch of the terrain.
//! \param position: The absolute position of this node.
//! \param rotation: The absolute rotation of this node. ( NOT YET IMPLEMENTED )
//! \param scale: The scale factor for the terrain. If you're using a heightmap of size 128x128 and would like
//! your terrain to be 12800x12800 in game units, then use a scale factor of ( core::vector ( 100.0f, 100.0f, 100.0f ).
//! If you use a Y scaling factor of 0.0f, then your terrain will be flat.
CTerrainSceneNode(ISceneNode* parent, ISceneManager* mgr, io::IFileSystem* fs, s32 id,
s32 maxLOD = 4, E_TERRAIN_PATCH_SIZE patchSize = ETPS_17,
const core::vector3df& position = core::vector3df(0.0f, 0.0f, 0.0f),
const core::vector3df& rotation = core::vector3df(0.0f, 0.0f, 0.0f),
const core::vector3df& scale = core::vector3df(1.0f, 1.0f, 1.0f));
virtual ~CTerrainSceneNode();
//! Initializes the terrain data. Loads the vertices from the heightMapFile.
virtual bool loadHeightMap(io::IReadFile* file,
video::SColor vertexColor = video::SColor ( 255, 255, 255, 255 ), s32 smoothFactor = 0 );
//! Initializes the terrain data. Loads the vertices from the heightMapFile.
virtual bool loadHeightMapRAW(io::IReadFile* file, s32 bitsPerPixel = 16,
bool signedData=true, bool floatVals=false, s32 width=0, video::SColor vertexColor = video::SColor ( 255, 255, 255, 255 ), s32 smoothFactor = 0 );
//! Returns the material based on the zero based index i. This scene node only uses
//! 1 material.
//! \param i: Zero based index i. UNUSED, left in for virtual purposes.
//! \return Returns the single material this scene node uses.
virtual video::SMaterial& getMaterial(u32 i);
//! Returns amount of materials used by this scene node ( always 1 )
//! \return Returns current count of materials used by this scene node ( always 1 )
virtual u32 getMaterialCount() const;
//! Gets the last scaling factor applied to the scene node. This value only represents the
//! last scaling factor presented to the node. For instance, if you make create the node
//! with a scale factor of ( 1.0f, 1.0f, 1.0f ) then call setScale ( 50.0f, 5.0f, 50.0f ),
//! then make another call to setScale with the values ( 2.0f, 2.0f, 2.0f ), this will return
//! core::vector3df ( 2.0f, 2.0f, 2.0f ), although the total scaling of the scene node is
//! core::vector3df ( 100.0f, 10.0f, 100.0f ).
//! \return Returns the last scaling factor passed to the scene node.
virtual const core::vector3df& getScale() const
{
return TerrainData.Scale;
}
//! Scales the scene nodes vertices by the vector specified.
//! \param scale: Scaling factor to apply to the node.
virtual void setScale(const core::vector3df& scale);
//! Gets the last rotation factor applied to the scene node.
//! \return Returns the last rotation factor applied to the scene node.
virtual const core::vector3df& getRotation() const
{
return TerrainData.Rotation;
}
//! Rotates the node. This only modifies the relative rotation of the node.
//! \param rotation: New rotation of the node in degrees.
virtual void setRotation(const core::vector3df& rotation);
//! Sets the pivot point for rotation of this node.
//! NOTE: The default for the RotationPivot will be the center of the individual tile.
virtual void setRotationPivot( const core::vector3df& pivot );
//! Gets the last positioning vector applied to the scene node.
//! \return Returns the last position vector applied to the scene node.
virtual const core::vector3df& getPosition() const
{
return TerrainData.Position;
}
//! Moves the scene nodes vertices by the vector specified.
//! \param newpos: Vector specifying how much to move each vertex of the scene node.
virtual void setPosition(const core::vector3df& newpos);
//! Updates the scene nodes indices if the camera has moved or rotated by a certain
//! threshold, which can be changed using the SetCameraMovementDeltaThreshold and
//! SetCameraRotationDeltaThreshold functions. This also determines if a given patch
//! for the scene node is within the view frustum and if it's not the indices are not
//! generated for that patch.
virtual void OnRegisterSceneNode();
//! Render the scene node
virtual void render();
//! Return the bounding box of the entire terrain.
virtual const core::aabbox3d<f32>& getBoundingBox() const;
//! Return the bounding box of a patch
virtual const core::aabbox3d<f32>& getBoundingBox(s32 patchX, s32 patchZ) const;
//! Return the number of indices currently used to draw the scene node.
virtual u32 getIndexCount() const { return IndicesToRender; }
//! Returns the mesh
virtual IMesh* getMesh();
//! Returns a pointer to the buffer used by the terrain (most users will not need this)
virtual IMeshBuffer* getRenderBuffer() { return RenderBuffer; }
//! Gets the meshbuffer data based on a specified Level of Detail.
//! \param mb: A reference to an IDynamicMeshBuffer object
//! \param LOD: The Level Of Detail you want the indices from.
virtual void getMeshBufferForLOD(IDynamicMeshBuffer& mb, s32 LOD=0) const;
//! Gets the indices for a specified patch at a specified Level of Detail.
//! \param indices: A reference to an array of u32 indices.
//! \param patchX: Patch x coordinate.
//! \param patchZ: Patch z coordinate.
//! \param LOD: The level of detail to get for that patch. If -1, then get
//! the CurrentLOD. If the CurrentLOD is set to -1, meaning it's not shown,
//! then it will retrieve the triangles at the highest LOD (0).
//! \return: Number of indices put into the buffer.
virtual s32 getIndicesForPatch(core::array<u32>& indices,
s32 patchX, s32 patchZ, s32 LOD=0);
//! Populates an array with the CurrentLOD of each patch.
//! \param LODs: A reference to a core::array<s32> to hold the values
//! \return Returns the number of elements in the array
virtual s32 getCurrentLODOfPatches(core::array<s32>& LODs) const;
//! Manually sets the LOD of a patch
//! \param patchX: Patch x coordinate.
//! \param patchZ: Patch z coordinate.
//! \param LOD: The level of detail to set the patch to.
virtual void setLODOfPatch(s32 patchX, s32 patchZ, s32 LOD=0);
//! Returns center of terrain.
virtual const core::vector3df& getTerrainCenter() const
{
return TerrainData.Center;
}
//! Returns center of terrain.
virtual f32 getHeight( f32 x, f32 y ) const;
//! Sets the movement camera threshold which is used to determine when to recalculate
//! indices for the scene node. The default value is 10.0f.
virtual void setCameraMovementDelta(f32 delta)
{
CameraMovementDelta = delta;
}
//! Sets the rotation camera threshold which is used to determine when to recalculate
//! indices for the scene node. The default value is 1.0f.
virtual void setCameraRotationDelta(f32 delta)
{
CameraRotationDelta = delta;
}
//! Sets whether or not the node should dynamically update it its associated selector when
//! the geomipmap data changes.
//! param bVal: Boolean value representing whether or not to update selector dynamically.
//! NOTE: Temporarily disabled while working out issues with DynamicSelectorUpdate
virtual void setDynamicSelectorUpdate(bool bVal ) { DynamicSelectorUpdate = false; }
//! Override the default generation of distance thresholds for determining the LOD a patch
//! is rendered at. If any LOD is overridden, then the scene node will no longer apply
//! scaling factors to these values. If you override these distances and then apply
//! a scale to the scene node, it is your responsibility to update the new distances to
//! work best with your new terrain size.
virtual bool overrideLODDistance( s32 LOD, f64 newDistance );
//! Scales the two textures
virtual void scaleTexture(f32 scale = 1.0f, f32 scale2 = 0.0f);
//! Returns type of the scene node
virtual ESCENE_NODE_TYPE getType() const {return ESNT_TERRAIN;}
//! Writes attributes of the scene node.
virtual void serializeAttributes(io::IAttributes* out,
io::SAttributeReadWriteOptions* options=0) const;
//! Reads attributes of the scene node.
virtual void deserializeAttributes(io::IAttributes* in,
io::SAttributeReadWriteOptions* options=0);
//! Creates a clone of this scene node and its children.
virtual ISceneNode* clone(ISceneNode* newParent,
ISceneManager* newManager);
private:
friend class CTerrainTriangleSelector;
struct SPatch
{
SPatch()
: Top(0), Bottom(0), Right(0), Left(0), CurrentLOD(-1)
{
}
SPatch* Top;
SPatch* Bottom;
SPatch* Right;
SPatch* Left;
s32 CurrentLOD;
core::aabbox3df BoundingBox;
core::vector3df Center;
};
struct STerrainData
{
STerrainData(s32 patchSize, s32 maxLOD, const core::vector3df& position, const core::vector3df& rotation, const core::vector3df& scale)
: Patches(0), Size(0), Position(position), Rotation(rotation),
Scale(scale), PatchSize(patchSize), CalcPatchSize(patchSize-1),
PatchCount(0), MaxLOD(maxLOD)
{
}
SPatch* Patches;
s32 Size;
core::vector3df Position;
core::vector3df Rotation;
core::vector3df RotationPivot;
core::vector3df Scale;
core::vector3df Center;
s32 PatchSize;
s32 CalcPatchSize;
s32 PatchCount;
s32 MaxLOD;
core::aabbox3df BoundingBox;
core::array<f64> LODDistanceThreshold;
};
virtual void preRenderCalculationsIfNeeded();
virtual void preRenderLODCalculations();
virtual void preRenderIndicesCalculations();
//! get indices when generating index data for patches at varying levels of detail.
u32 getIndex(const s32 PatchX, const s32 PatchZ, const s32 PatchIndex, u32 vX, u32 vZ) const;
//! smooth the terrain
void smoothTerrain(IDynamicMeshBuffer* mb, s32 smoothFactor);
//! calculate smooth normals
void calculateNormals(IDynamicMeshBuffer* mb);
//! create patches, stuff that needs to only be done once for patches goes here.
void createPatches();
//! calculate the internal STerrainData structure
void calculatePatchData();
//! calculate or recalculate the distance thresholds
void calculateDistanceThresholds(bool scalechanged = false);
//! sets the CurrentLOD of all patches to the specified LOD
void setCurrentLODOfPatches(s32 i);
//! sets the CurrentLOD of TerrainData patches to the LODs specified in the array
void setCurrentLODOfPatches(const core::array<s32>& lodarray);
//! Apply transformation changes( scale, position, rotation )
void applyTransformation();
STerrainData TerrainData;
SMesh* Mesh;
IDynamicMeshBuffer *RenderBuffer;
u32 VerticesToRender;
u32 IndicesToRender;
bool DynamicSelectorUpdate;
bool OverrideDistanceThreshold;
bool UseDefaultRotationPivot;
bool ForceRecalculation;
core::vector3df OldCameraPosition;
core::vector3df OldCameraRotation;
core::vector3df OldCameraUp;
f32 OldCameraFOV;
f32 CameraMovementDelta;
f32 CameraRotationDelta;
f32 CameraFOVDelta;
// needed for (de)serialization
f32 TCoordScale1;
f32 TCoordScale2;
s32 SmoothFactor;
io::path HeightmapFile;
io::IFileSystem* FileSystem;
};
} // end namespace scene
} // end namespace irr
#endif // __C_TERRAIN_SCENE_NODE_H__
|