// NeL - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #ifndef NL_LANDSCAPE_H #define NL_LANDSCAPE_H #include "nel/misc/types_nl.h" #include "nel/misc/class_id.h" #include "nel/misc/smart_ptr.h" #include "nel/misc/triangle.h" #include "nel/3d/zone.h" #include "nel/3d/tile_bank.h" #include "nel/3d/patch_rdr_pass.h" #include "nel/3d/vertex_buffer.h" #include "nel/3d/index_buffer.h" #include "nel/3d/material.h" #include "nel/3d/tile_far_bank.h" #include "nel/3d/texture_near.h" #include "nel/3d/quad_grid.h" #include "nel/misc/block_memory.h" #include "nel/3d/landscapevb_allocator.h" #include "nel/3d/landscape_face_vector_manager.h" #include "nel/3d/tess_face_priority_list.h" #include "nel/3d/point_light_influence.h" #include "nel/3d/shadow_poly_receiver.h" #include #define NL_MAX_SIZE_OF_TEXTURE_EDGE_SHIFT (NL_MAX_TILES_BY_PATCH_EDGE_SHIFT+NL_NUM_PIXELS_ON_FAR_TILE_EDGE_SHIFT) #define NL_MAX_SIZE_OF_TEXTURE_EDGE (1< BindErrors; public: EBadBind() {} ~EBadBind() throw () {} virtual const char *what() const throw(); }; struct ULandscapeTileCallback; // *************************************************************************** /** * A landscape. Use CZone to build zone, and use landscape to dynamically add/remove them, for render. * * Limits: * - 65535 zones max in whole world (16 bits ZoneId ). * - 65535 patchs max by zone. * - patch order 2x2 minimum. * - patch order 16x16 maximum. * - connectivity on a edge: 1/1, 1/2, or 1/4. * - connectivity on a edge of a zone: 1/1 only. * - The value of Noise amplitude is global and cannot go over 1 meter (+- 1m). * Sorry, this is a FIXED (for ever) value which should NEVER change (because of Gfx database). * * If you use the tiles mapped on the patches, load the near bank file (.bank) and the far bank file (.farbank) * by seralizing TileBank and TileFarBank with those files. Then call initTileBanks. * * \author Lionel Berenguier * \author Nevrax France * \date 2000 */ class CLandscape : public NLMISC::CRefCount { public: // The bank of tiles information. Each time you change the bank, you should call CLandscape::initTileBanks(); CTileBank TileBank; CTileFarBank TileFarBank; class CLandscapeModel *OwnerModel; public: /// Constructor CLandscape(); /// Destructor. clear(). virtual ~CLandscape(); /// \name Init/Build. // @{ /// init the landscape VBuffers, texture cache etc... void init(); /** Add a zone which should be builded (or loaded), but not compiled. CLandscape compile it. * The contents of newZone are copied into the landscape. * \param newZone the new zone. * \return true if OK, false otherwise. As example, Fail if newZone is already connected. */ bool addZone(const CZone &newZone); /** remove a zone by its unique Id. * The zone is release()-ed (disconnected), then deleted. * \param zoneId the zone to be removed. * \return true if OK, false otherwise. As example, Fail if zone is not connected. */ bool removeZone(uint16 zoneId); /// Disconnect, and Delete all zones. void clear(); /// Verify the binding of patchs of all zones. throw EBadBind if error. void checkBinds() throw(EBadBind); /// Verify the binding of patchs of one zone. throw EBadBind if error. nop if zone not loaded. void checkBinds(uint16 zoneId) throw(EBadBind); /** * Build tileBank. Call this after loading the near and far tile banks. * * \return true if ok, false else. If false, far texture will be desactived. */ bool initTileBanks (); // @} /// \name Landscape Parameters. // @{ /// Set tile near distance. Default 50.f. maximized to length of Far alpha transition). void setTileNear (float tileNear); /// Get tile near distance. float getTileNear () const {return _TileDistNear;} /// Set threshold for subdivsion quality. The lower is threshold, the more the landscape is subdivided. Default: 0.001. void setThreshold (float thre); /// Get threshold. float getThreshold () const {return _Threshold;} void setRefineMode(bool enabled) {_RefineMode= enabled;} bool getRefineMode() const {return _RefineMode;} /// Set Maximum Tile subdivision. Valid values must be in [0..4] (assert). Default is 0 (for now :) ). void setTileMaxSubdivision (uint tileDiv); /// Get Maximum Tile subdivision. uint getTileMaxSubdivision (); /// Enable the noise or not. NB: only new tesselation computed is modified, so you should call it only at init time. void setNoiseMode(bool enabled); bool getNoiseMode() const; // invalidate all the tiles (force the tiles callbakc to be called again) void invalidateAllTiles(); // Store it by landscape, and not only globally in CLandscapeGlobals statics. // @} /// \name Render methods. // @{ /** * A driver is needed for VB allocation. The VB will be allocated only the first time the landscape is clipped. * Because no VB are created for invisible patchs. * call setDriver() before any clip(). */ void setDriver(IDriver *drv); /** Clip the landscape according to frustum. * Planes must be normalized. */ void clip(const CVector &refineCenter, const std::vector &pyramid); /** Refine/Geomorph the tesselation of the landscape. */ void refine(const CVector &refineCenter); /** Render the landscape. * A more precise clip is made on TessBlocks. pyramid should be the same as one passed to clip(). * For optimisation, this pyramid should contains only the Left/Right and Top/Bottom clip planes, in this order. * \param refineCenter should be the position of the camera * \param frontVector should be the J vector of the camera */ void render(const CVector &refineCenter, const CVector &frontVector, const CPlane pyramid[NL3D_TESSBLOCK_NUM_CLIP_PLANE], bool doTileAddPass=false); /// Refine/Geomorph ALL the tesselation of the landscape, from the view point refineCenter. Even if !RefineMode. void refineAll(const CVector &refineCenter); /// This is especially for Pacs. exlude a patch to be refineAll()ed. void excludePatchFromRefineAll(sint zoneId, uint patch, bool exclude); /** This is especially for Pacs. Each Vertex->EndPos which is not a corner of a patch * is set to the mean of its 2 shared Patchs. * NB: Works with special cases of rectangular patchs and binded patchs. */ void averageTesselationVertices(); // Profile at Current landscape state (nlinfos) void profileRender(); // Get the Last refine pos setuped at refine(); const CVector &getOldRefineCenter() const {return _OldRefineCenter;} // @} /// \name Collision methods. // @{ /** Build the set of faces of landscape, which are IN a bbox. Useful for collisions. * The faces are builded at Tile level (2m*2m). * \param bbox the bbox where faces are searched. * \param faces the result of the build. * \param faceSplit if true, Only faces which are IN or partialy IN the bbox are returned. Else the clipping is done * on patch level. Worst, but faster. */ void buildCollideFaces(const CAABBoxExt &bbox, std::vector &faces, bool faceSplit); /** Build the set of faces of landscape, from a certain patch. Useful for collisions. Triangles are built first in S * then T order. There is two triangles by tiles. So the number of triangles for a patch is 2*OrderS*OrderT. */ void buildCollideFaces(sint zoneId, sint patch, std::vector &faces); /** method relatively identical than buildCollideFaces(bbox....). Differences below: * NB: this method use first a quadgrid to locate patchs of interest, then for each patch, it uses a * convex hull subdivion to search in O(logn) what part of the patch to insert. * \param bbox the bbox to test against. NB: you should modify your bbox according to heighfield. * \param triangles array to be filled (array first cleared, then elements added). * \param tileTessLevel 0,1 or 2 size of the triangles (2*2m, 1*1m or 0.5*0.5m). Level of subdivision of a tile. */ void buildTrianglesInBBox(const CAABBox &bbox, std::vector &triangles, uint8 tileTessLevel); /** Same as buildTrianglesInBBox(), but fill blockId instead of raw triangles. * NB: this method use first a quadgrid to locate patchs of interest, then for each patch, it uses a * convex hull subdivion to search in O(logn) what part of the patch to insert. * \param bbox the bbox to test against. NB: you should modify your bbox according to heighfield. * \param paBlockIds array to be filled (no clear performed, elements added). */ void buildPatchBlocksInBBox(const CAABBox &bbox, std::vector &paBlockIds); /** Fill a CPatchQuadBlock, from its required PatchId. * nlassert(PatchId size is less than NL_PATCH_BLOCK_MAX_QUAD) */ void fillPatchQuadBlock(CPatchQuadBlock &quadBlock) const; /** From the current tesselation of a patch of landscape, and a UV in this patch, return tesselated position. * NB: return Null if patch not found. */ CVector getTesselatedPos(const CPatchIdent &patchId, const CUV &uv) const; /** From the current tesselation of landscape, build the list of leaves faces. * Warning: ptrs are only valid between 2 tesselation (2 calls of Scene::render() or 2 calls of refine*() etc...) */ void getTessellationLeaves(std::vector &leaves) const; /** Get the camera 3rd person collision against the TileFaces (ie only under approx 50 m) * return a [0,1] value. 0 => collision at start. 1 => no collision. * \param radius is the radius of the 'cylinder' * \param cone if true, the object tested is a cone (radius goes to end) */ float getCameraCollision(const CVector &start, const CVector &end, float radius, bool cone); /** Get the ray collision against the TileFaces (ie only under approx 50 m) * return a [0,1] value. 0 => collision at start. 1 => no collision. */ float getRayCollision(const CVector &start, const CVector &end); // @} /// \name Accessors. // @{ /** Get a zone pointer. * * \param zoneId the zone of the update. * \return Return a zone pointer. NULL if the zone doesn't exist or isn't loaded. */ CZone* getZone (sint zoneId); /** Get a zone pointer. * * \param zoneId the zone of the update. * \return Return a zone pointer. NULL if the zone doesn't exist or isn't loaded. */ const CZone* getZone (sint zoneId) const; /** Return list of zone loaded. */ void getZoneList(std::vector &zoneIds) const; /// From an Id, return the name of the zone, in the form "150_EM", without extension. static void buildZoneName(sint zoneId, std::string &zoneName); // @} /// \name Tile mgt. // @{ /// Force a range of tiles to be loaded in the driver... void flushTiles(IDriver *drv, uint32 tileStart, uint32 nbTiles); /** Force a range of tiles to be unloaded. You should call changePatchTextureAndColor() on all patch * or ensure that all zones are deleted. */ void releaseTiles(uint32 tileStart, uint32 nbTiles); /// Delete All tiles. All zones must be deleted before (nlassert) void releaseAllTiles(); /// Return the texture for a tile Id. Useful for Tile edition. NLMISC::CSmartPtr getTileTexture(uint16 tileId, CTile::TBitmap bitmapType, CVector &uvScaleBias); /// Return the tile element for a patch at specific UV. Useful for getting surface data. Return NULL if not found. CTileElement *getTileElement(const CPatchIdent &patchId, const CUV &uv); // @} /// \name Lighting. // @{ /** * Setup the light color use for static illumination. * * \param diffuse is the color of the diffuse componante of the lighting. * \param ambiant is the color of the ambiante componante of the lighting. * \param multiply is the multiply factor. Final color is (diffuse*multiply*shading+ambiant*(1.0-shading)) */ void setupStaticLight (const CRGBA &diffuse, const CRGBA &ambiant, float multiply); /** * Get the light color by shading table. * * \return a CRGBA[256] array. It give the static light color for a shading value. */ const CRGBA* getStaticLight () const { return _LightValue; } /** * Setup the equivalent material diffuse component used for both Static and Dynamic PointLights. * Default is White. */ void setPointLightDiffuseMaterial(CRGBA diffuse); /** * \see setPointLightDiffuseMaterial */ CRGBA getPointLightDiffuseMaterial () const { return _PointLightDiffuseMaterial; } /** * Enable automatic near lightmap computing. use setupStaticLight(). * Default is disabled. * NB: calling this method won't flush all texture near already computed. */ void enableAutomaticLighting(bool enable); /** * For automatic near lightmap computing (if enabled): setup the lightdir * * \param lightDir is the direction of the light vector used for the lighting. NB: the vector is normalized. */ void setupAutomaticLightDir(const CVector &lightDir); /// return true if AutomaticLighting is enabled. bool getAutomaticLighting() const {return _AutomaticLighting;} /// return the light direction setuped in enableAutomaticLighting(). const CVector &getAutomaticLightDir() const {return _AutomaticLightDir;} /** This method remove all PointLights in all Zones, and hence reset TileLightInfluences. */ void removeAllPointLights(); /// update the Light factor for all pointLights in All zones, according to scene LightGroups and AnimatedLights. void setPointLightFactor(const CScene &scene); // To init lightmap information void initAnimatedLightIndex(const CScene &scene); // @} /// \name HeightField DeltaZ. // @{ /// return the HeightField DeltaZ for the 2D position. (0,0,dZ) is returned. CVector getHeightFieldDeltaZ(float x, float y) const; /** set the HeightField data. NB: take lot of place in memory. * only one is possible. You should setup this heightfield around the zones which will be loaded. * It is applied only when a zone is loaded, so you should setup it 2km around the user, each time you move too far * from a previous place (eg 160m from last setup). */ void setHeightField(const CHeightMap &hf); // @} /// Micro-Vegetation. // @{ /** init the vegetable layer models in the CScene (see CVegetableManager). * NB: MOT stuff (called by CLandscapeModel), don't use it. */ void createVegetableBlendLayersModels(CScene *scene); /** set the vegetable manager Time (in seconds) * NB: MOT stuff (called by CLandscapeModel), don't use it. */ void setVegetableTime(double time); /** set the vegetable manager System Time (in seconds) for update lighting * NB: MOT stuff (called by CLandscapeModel), don't use it. */ void setVegetableUpdateLightingTime(double time); /** enable the vegetable management in landscape. Valid only if VertexShader is OK. * if true, register TileBank vegetables Shape to manager. */ void enableVegetable(bool enable); /** return if the vegetable management is actually activated: * actually return _VerexShaderOk && _VegetableEnabled. */ bool isVegetableActive() const; /** load a texture for the vegetable, lookup in CPath */ void loadVegetableTexture(const std::string &textureFileName); /** setup lighting ambient and diffuse for vegetable. */ void setupVegetableLighting(const CRGBA &ambient, const CRGBA &diffuse, const CVector &directionalLight); /** set the vegetable Wind for animation. * All thoses variables may be modified each frame without penalty. * * \param windDir is the direction of the wind. NB: only XY direction is kept. * \param windFreq is the frequency for the animation (speed) * \param windPower is the power of the wind, and is a factor (0..1) of Bend * \param windBendMin is a value in (0..1) which indicate how much the vegetables are bended at minimum * (for very powerfull wind) */ void setVegetableWind(const CVector &windDir, float windFreq, float windPower, float windBendMin); /** return the number of faces displayed in Driver with the vegetable manager. * Out CPrimitiveProfile::NTriangles displayed by vegetable part is returned. */ uint getNumVegetableFaceRendered() const; /** set the frequency of Vegetable lighting update. If freq==1, ALL lighted igs are updated each second. * e.g: if 1/20, then every 20 seconds, all Igs are updated. * If you set 0, no update will be done at all (this is the default setup!!). */ void setVegetableUpdateLightingFrequency(float freq); /** Debug purpose only : setup the colors of the patch of all the currently loaded zones * so that it shows which tiles have vegetable disabled, or are above, below water. * User provides a table with 4 colors for each state : * color 0 = above water * color 1 = underwater * color 2 = intersect water * color 3 = vegetable disabled */ void setupColorsFromTileFlags(const NLMISC::CRGBA colors[4]); /** Set a density ratio [0, 1] to possibly reduce the amount of micro vegetable drawn. Default to 1 */ void setVegetableDensity(float density); /** Get the density ratio [0, 1] of micro vegetable drawn. Default to 1 */ float getVegetableDensity() const; // @} /// \name Lightmap get interface. // @{ /// Get the lumel under the position. return 255 if invalid patchId. uint8 getLumel(const CPatchIdent &patchId, const CUV &uv) const; /// Append lights under the position to pointLightList. Do nothing if invalid patchId. void appendTileLightInfluences(const CPatchIdent &patchId, const CUV &uv, std::vector &pointLightList) const; // @} /// \name Precision ZBuffer mgt. // @{ /** Set the ModelPosition (for Precision ZBuffer purpose). NB: the model Pos may be floor-ed * (for greater float precision). Should be setup to the camera position each frame. * * NB: if vertexProgram is used, it is as faster as before (because of geomorph done each frame, * and because of VP MAD instruction). * NB: if vertexProgram is not used, it is a little slower, because of the substraction. */ void setPZBModelPosition(const CVector &pos); /** \see setPZBModelPosition() */ const CVector &getPZBModelPosition() const {return _PZBModelPosition;} // @} /// \name UpdateLighting management // @{ /** update the lighting of patch, within a certain amount of time. * called by CLandscapeModel */ void updateLighting(double time); /** set the frequency of lighting update. If freq==1, ALL patchs are updated each second. * e.g: if 1/20, then every 20 seconds, all patchs are updated. * If you set 0, no update will be done at all (this is the default setup!!). */ void setUpdateLightingFrequency(float freq); /** update the lighting of ALL patch (slow method). NB: work even if UpdateLightingFrequency==0 * Additionaly, vegetables are also ALL updated. */ void updateLightingAll(); // @} /// \name Dynamic Lighting management // @{ /** Compute dynamic lightmaps * \param pls list of pointLigths to influence landscape */ void computeDynamicLighting(const std::vector &pls); /** For bench only. return approximate ammount of memory taken by dynamic lightmap in RAM. * This is sizeof(global Texture in RAM) + all patchDLMContext. * NB: not so slow, but do not call in final release. */ uint getDynamicLightingMemoryLoad() const; /** Set PointLight Max Attenuation End landscape support. Every pointLight AttEnd is clamped to this value. * Default is 30.f. */ void setDynamicLightingMaxAttEnd(float maxAttEnd); /** see setDynamicLightingMaxAttEnd() */ float getDynamicLightingMaxAttEnd() const {return _DLMMaxAttEnd;} /** For Vegetable Dynamic ligthing only: this is an approximate color of all vegetables. * Default is (180, 180, 180). */ void setDLMGlobalVegetableColor(CRGBA gvc); /** see setDLMGlobalVegetableColor() */ CRGBA getDLMGlobalVegetableColor() const {return _DLMGlobalVegetableColor;} // @} /// \name Dynamic ShadowMap // @{ void receiveShadowMap(IDriver *drv, CShadowMap *shadowMap, const CVector &casterPos, const CMaterial &shadowMat, const CVector &pzb); // @} /// \name Tile added/removed callback // @{ void addTileCallback(ULandscapeTileCallback *cb); void removeTileCallback(ULandscapeTileCallback *cb); bool isTileCallback(ULandscapeTileCallback *cb) const; const std::vector &getTileCallbacks() const { return _TileCallbacks; } // @} // lockBuffers(), called by updateGlobalsAndLockBuffers(). void lockBuffers (); // unlockBuffers. This is the END call for updateGlobalsAndLockBuffers(). void unlockBuffers (bool force = false); // Check if buffers are locked bool isLocked() const { return _LockCount != 0; } // for advanced use (decal rendering) CShadowPolyReceiver &getShadowPolyReceiver() { return _ShadowPolyReceiver; } // modify ZBuffer test of landscape material virtual void setZFunc(CMaterial::ZFunc val); // ******************************** private: // Private part used by CTessFace / CPatch / CZone. friend class CTessFace; friend class CPatch; friend class CZone; std::vector _TileCallbacks; /// \name Allocators. // @{ CBlockMemory TessFaceAllocator; CBlockMemory TessVertexAllocator; CBlockMemory TessNearVertexAllocator; CBlockMemory TessFarVertexAllocator; CBlockMemory TileMaterialAllocator; CBlockMemory TileFaceAllocator; CTessFace *newTessFace(); CTessVertex *newTessVertex(); CTessNearVertex *newTessNearVertex(); CTessFarVertex *newTessFarVertex(); CTileMaterial *newTileMaterial(); CTileFace *newTileFace(); void deleteTessFace(CTessFace *f); void deleteTessVertex(CTessVertex *v); void deleteTessNearVertex(CTessNearVertex *v); void deleteTessFarVertex(CTessFarVertex *v); void deleteTileMaterial(CTileMaterial *tm); void deleteTileFace(CTileFace *tf); // Allocator of FaceVector for allocation of packed triangles indices. CLandscapeFaceVectorManager _FaceVectorManager; // This is not a valid TessBlock. But it is used as a Root for modification list. // Can't use a ptr, because of ~CTessBlock(). CTessBlock _TessBlockModificationRoot; // @} // Return the render pass for a far texture here. CPatchRdrPass *getFarRenderPass(CPatch* pPatch, uint farIndex, float& far1UScale, float& far1VScale, float& far1UBias, float& far1VBias, bool& bRot); // Free the render pass for a far texture here. void freeFarRenderPass (CPatch* pPatch, CPatchRdrPass* pass, uint farIndex); // Return the render pass for a tile Id, and a patch Lightmap. CPatchRdrPass *getTileRenderPass(uint16 tileId, bool additiveRdrPass); // Return the UvScaleBias for a tile Id. uv.z has the scale info. uv.x has the BiasU, and uv.y has the BiasV. // if bitmap type is CTile::alpha, Return also the additionla rot for alpha (else 0). void getTileUvScaleBiasRot(uint16 tileId, CTile::TBitmap bitmapType, CVector &uvScaleBias, uint8 &rotAlpha); // release Far render pass/reset Tile/Far render. Delete also VB, and FaceVectors void resetRenderFarAndDeleteVBFV(); /// For changing TileMaxSubdivision. force tesselation to be under tile. void forceMergeAtTileLevel(); // Update globals value to CTessFace, and lock Buffers if possible. void updateGlobalsAndLockBuffers (const CVector &refineCenter); // update TheFaceVector for which the faces may have been modified during refine(), refineAll() etc.... void updateTessBlocksFaceVector(); // System: update UL links, but don't call _TextureFars.erase() void clearFarRenderPass (CPatchRdrPass* pass); private: TZoneMap Zones; // Parameters. float _TileDistNear; float _Threshold; bool _RefineMode; float _FarTransition; uint _TileMaxSubdivision; // For VertexProgram. true if change has occured in threshold since the last render(). float _VPThresholdChange; /// \name VertexBuffer mgt. // @{ CRefPtr _Driver; CLandscapeVBAllocator _Far0VB; CLandscapeVBAllocator _Far1VB; CLandscapeVBAllocator _TileVB; uint _LockCount; // Lock counter // True if we can compute Geomorph and Alpha with VertexShader. bool _VertexShaderOk; // For CZone::refreshTesselationGeometry(). bool _RenderMustRefillVB; // @} // Tiles Types. //============= // Texture Map. Use a RefPtr because TileTextureMap must not reference the object, but the ptr. typedef NLMISC::CRefPtr RPTexture; typedef std::map TTileTextureMap; typedef TTileTextureMap::iterator ItTileTextureMap; // RdrPass Set. typedef std::set TTileRdrPassSet; typedef TTileRdrPassSet::iterator ItTileRdrPassSet; typedef NLMISC::CSmartPtr TSPRenderPass; // The additional realtime structure for a tile. struct CTileInfo { // NB: CSmartPtr are not used for simplicity, and because of TTileRdrPassSet... // CPatchRdrPass::RefCount are excplictly incremented/decremented... // The rdrpass for diffuse+Alpha material. CPatchRdrPass *DiffuseRdrPass; // The rdrpass for additive material (may be NULL if no additive part). CPatchRdrPass *AdditiveRdrPass; // The scale/Bias to access those tiles in the big texture. // uv.z has the scale info. uv.x has the BiasU, and uv.y has the BiasV. // Manages the demi-texel on tile border too. CVector DiffuseUvScaleBias; CVector AlphaUvScaleBias; CVector AdditiveUvScaleBias; // The additional rotation for this tile, in alpha. uint8 RotAlpha; }; // Tiles Data. //============= // The map of tile texture loaded. TTileTextureMap TileTextureMap; // The set of tile Rdr Pass. TTileRdrPassSet TileRdrPassSet; // The parrallel array of tile of those existing in TileBank. size of NbTilesMax. std::vector TileInfos; // The Lightmap rdrpass for tiles. // must have a vector of pointer, because of vector reallocation. std::vector _TextureNears; uint _NFreeLightMaps; // The Tile material. CMaterial TileMaterial; // The Far material. CMaterial FarMaterial; // *** Far texture // ** Some types // The vector of far render pass // must have a vector of pointer, because of vector reallocation. typedef std::vector::iterator ItSPRenderPassVector; std::vector _TextureFars; bool _FarInitialized; // Used internaly by initTileBanks bool eraseTileFarIfNotGood (uint tileNumber, uint sizeOrder0, uint sizeOrder1, uint sizeOrder2); // *** Lighting CRGBA _LightValue[256]; bool _AutomaticLighting; CVector _AutomaticLightDir; private: // Internal only. Force load of the tile (with TileBank). void loadTile(uint16 tileId); void releaseTile(uint16 tileId); ITexture *findTileTexture(const std::string &textName, bool clamp); CPatchRdrPass *findTileRdrPass(const CPatchRdrPass &pass); // Tile LightMap mgt. NB: a lightmap is now a 2x2 tiles lightmap (10x10 pixels). // @{ // Compute and get a lightmapId/lightmap renderpass. // lightmap returned is to be uses with getTileRenderPass(). The id returned must be stored. uint getTileLightMap(CRGBA map[NL_TILE_LIGHTMAP_SIZE*NL_TILE_LIGHTMAP_SIZE], CPatchRdrPass *&lightmapRdrPass); // tileLightMapId must be the id returned by getTileLightMap(). void getTileLightMapUvInfo(uint tileLightMapId, CVector &uvScaleBias); // tileLightMapId must be the id returned by getTileLightMap(). void releaseTileLightMap(uint tileLightMapId); // refill a lightmap already computed. tileLightMapId must be the id returned by getTileLightMap(). void refillTileLightMap(uint tileLightMapId, CRGBA map[NL_TILE_LIGHTMAP_SIZE*NL_TILE_LIGHTMAP_SIZE]); // @} // check a zone, adding error to exception. void checkZoneBinds(CZone &curZone, EBadBind &bindError); /** A Bezier patch of One value only. * NB: unlike CBezierPatch, layout is inverted on Y. (NB: same formulas...) */ struct CBezierPatchZ { /// The vertices a,b,c,d of the quad patch. float Vertices[4]; /// The tangents ab, ba, bc, cb, cd, dc, da, ad. NB: tangents are points, not vectors. float Tangents[8]; /// The interiors, ia,ib,ic,id. NB: interiors are points, not vectors. float Interiors[4]; /// make default Interiors, according to Vertices and Tangents. void makeInteriors(); /// Evaluate. float eval(float s, float t) const; // s,t coordinates for quad. }; // HeightFields. struct CHeightField { std::vector ZPatchs; /// The origin of the bottom-left corner of this heightmap. float OriginX, OriginY; /// The size of one Element ot this HeightMap (eg: 160x160 for a zone). float SizeX, SizeY; float OOSizeX, OOSizeY; /// The size of this array. Heights.size uint Width, Height; }; CHeightField _HeightField; /// \name Visual Collision system. // @{ // A CPatchIdent, with a ptr to the compiled CPatch struct CPatchIdentEx : public CPatchIdent { const CPatch *Patch; }; /// The QuadGrid of patch. CQuadGrid _PatchQuadGrid; static const uint _PatchQuadGridSize; static const float _PatchQuadGridEltSize; /** This method search only on the given patch. * NB: this method use a convex hull subdivion to search in O(logn) what part of the patch to insert. * \param bbox the bbox to test against. * \param triangles array to be filled (no clear performed, elements added). * \param tileTessLevel 0,1 or 2 size of the triangles (2*2m, 1*1m or 0.5*0.5m). Level of subdivision of a tile. */ void addTrianglesInBBox(const CPatchIdentEx &paIdEx, const CAABBox &bbox, std::vector &triangles, uint8 tileTessLevel) const; /** private version of buildPatchBlocksInBBox, searching only for one patch. */ void addPatchBlocksInBBox(const CPatchIdentEx &paIdEx, const CAABBox &bbox, std::vector &paBlockIds); // @} /// Noise Geometry. // @{ // guess. bool _NoiseEnabled; // @} /// Priority list. // @{ /// The priority list of faces which may need to split CTessFacePriorityList _SplitPriorityList; /// The priority list of faces which may need to merge CTessFacePriorityList _MergePriorityList; /// OldRefineCenter setuped in prec refine() CVector _OldRefineCenter; bool _MustRefineAllAtNextRefine; /// newTessFace() append the face to _RootNewLeaves. CTessFacePListNode _RootNewLeaves; // @} /// Micro-Vegetation. // @{ /// The VegetableManager. (ptr only for include speed). CVegetableManager *_VegetableManager; /// Tells if the Vegetable Managemnt is enabled. bool _VegetableManagerEnabled; /// Tells if the current driver support vegetable. bool _DriverOkForVegetable; /// List of VegetableBlock, to be tested for creation each frame. CTessList _VegetableBlockList; /** For a given tile Id, look into tileSet, and get the tile vegetable descriptor * \param tileId the tile [0..65535] to get the list of vegetable to create. */ const CTileVegetableDesc &getTileVegetableDesc(uint16 tileId); // @} /// \name Precision ZBuffer mgt. // @{ /** \see setPZBModelPosition() */ CVector _PZBModelPosition; // @} /// \name UpdateLighting management // @{ // Last update time. double _ULPrecTime; bool _ULPrecTimeInit; double _ULTime; /// Frequency of update. float _ULFrequency; /// Far UpdateLighting. sint _ULTotalFarPixels; /// Current number of far pixels to update. If negative, I have some advance. float _ULFarPixelsToUpdate; /// The current TextureFar rendered. CTextureFar *_ULRootTextureFar; /// Near UpdateLighting. sint _ULTotalNearPixels; /// Current number of near pixels to update. If negative, I have some advance. float _ULNearPixelsToUpdate; /// The current patch rendered. CPatch *_ULRootNearPatch; /// Current tessBlock id in the current patch processed uint _ULNearCurrentTessBlockId; /// Used by Patch to link/unlink from _ULRootNearPatch void linkPatchToNearUL(CPatch *patch); void unlinkPatchFromNearUL(CPatch *patch); /// Update All Far texture, given a ratio along total lumels void updateLightingTextureFar(float ratio); /// Update All Near texture, given a ratio along total lumels void updateLightingTextureNear(float ratio); // @} /// \name DynamicLighting management // @{ /// The dynamic lightmap Texture. NLMISC::CSmartPtr _TextureDLM; /// for CPatch. CTextureDLM *getTextureDLM() const {return (CTextureDLM*)(ITexture*)_TextureDLM;} /// List of DLM Context. CPatchDLMContextList *_PatchDLMContextList; /// for CPatch. CPatchDLMContextList *getPatchDLMContextList() const {return _PatchDLMContextList;} /// Max AttEnd float _DLMMaxAttEnd; /// an approximate value used to simulate diffuse material of vegetables CRGBA _DLMGlobalVegetableColor; /// The diffuse material of landscape, used for StaticPointLights and DynamicPointLights CRGBA _PointLightDiffuseMaterial; // @} /// \name Dynamic ShadowMap // @{ CShadowPolyReceiver _ShadowPolyReceiver; void appendToShadowPolyReceiver(CTessFace *face); void removeFromShadowPolyReceiver(CTessFace *face); // @} /// \name Texture Profiling // @{ NLMISC::CSmartPtr _TextureTileCategory; NLMISC::CSmartPtr _TextureFarCategory; NLMISC::CSmartPtr _TextureNearCategory; // @} }; } // NL3D #endif // NL_LANDSCAPE_H /* End of landscape.h */