// 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 .
#include "std3d.h"
#include "nel/3d/landscape_user.h"
#include "nel/misc/file.h"
#include "nel/misc/path.h"
#include "nel/misc/hierarchical_timer.h"
#include "nel/misc/progress_callback.h"
using namespace NLMISC;
namespace NL3D
{
H_AUTO_DECL( NL3D_UI_Landscape )
H_AUTO_DECL( NL3D_Render_Landscape_updateLightingAll )
H_AUTO_DECL( NL3D_Load_Landscape )
#define NL3D_HAUTO_UI_LANDSCAPE H_AUTO_USE( NL3D_UI_Landscape )
#define NL3D_HAUTO_LANDSCAPE_UPDATE_LIGHTING_ALL H_AUTO_USE( NL3D_Render_Landscape_updateLightingAll )
#define NL3D_HAUTO_LOAD_LANDSCAPE H_AUTO_USE( NL3D_Load_Landscape )
// ***************************************************************************
CLandscapeUser::~CLandscapeUser()
{
// must ensure all loading is ended
removeAllZones();
// then delete
_Scene->deleteModel(_Landscape);
_Landscape= NULL;
}
//****************************************************************************
void CLandscapeUser::setZonePath(const std::string &zonePath)
{
NL3D_HAUTO_UI_LANDSCAPE;
_ZoneManager.setZonePath(zonePath);
}
//****************************************************************************
void CLandscapeUser::invalidateAllTiles()
{
_Landscape->Landscape.invalidateAllTiles();
}
//****************************************************************************
void CLandscapeUser::loadBankFiles(const std::string &tileBankFile, const std::string &farBankFile)
{
NL3D_HAUTO_LOAD_LANDSCAPE;
// Release all OLD tiles
_Landscape->Landscape.releaseAllTiles();
// Clear the bank
_Landscape->Landscape.TileBank.clear ();
// First, load the banks.
//=======================
CIFile bankFile(CPath::lookup(tileBankFile));
_Landscape->Landscape.TileBank.serial(bankFile);
// All textures path are relative!
_Landscape->Landscape.TileBank.makeAllPathRelative();
// Use DDS!!!
_Landscape->Landscape.TileBank.makeAllExtensionDDS();
// No absolute path
_Landscape->Landscape.TileBank.setAbsPath ("");
CIFile farbankFile(CPath::lookup(farBankFile));
_Landscape->Landscape.TileFarBank.serial(farbankFile);
bankFile.close();
farbankFile.close();
}
//****************************************************************************
void CLandscapeUser::flushTiles (NLMISC::IProgressCallback &progress)
{
// After loading the TileBank, and before initTileBanks(), must load the vegetables descritpor
_Landscape->Landscape.TileBank.loadTileVegetableDescs();
// init the TileBanks descriptors
if ( ! _Landscape->Landscape.initTileBanks() )
{
nlwarning( "You need to recompute bank.farbank for the far textures" );
}
// Count tiles
uint tileCount = 0;
sint ts;
for (ts=0; ts<_Landscape->Landscape.TileBank.getTileSetCount (); ts++)
{
CTileSet *tileSet=_Landscape->Landscape.TileBank.getTileSet (ts);
tileCount += tileSet->getNumTile128();
tileCount += tileSet->getNumTile256();
tileCount += CTileSet::count;
}
// Second, temporary, flushTiles.
//===============================
uint tile = 0;
for (ts=0; ts<_Landscape->Landscape.TileBank.getTileSetCount (); ts++)
{
CTileSet *tileSet=_Landscape->Landscape.TileBank.getTileSet (ts);
sint tl;
for (tl=0; tlgetNumTile128(); tl++)
{
// Progress bar
progress.progress ((float)tile/(float)tileCount);
tile++;
_Landscape->Landscape.flushTiles (_Scene->getDriver(), (uint16)tileSet->getTile128(tl), 1);
}
for (tl=0; tlgetNumTile256(); tl++)
{
// Progress bar
progress.progress ((float)tile/(float)tileCount);
tile++;
_Landscape->Landscape.flushTiles (_Scene->getDriver(), (uint16)tileSet->getTile256(tl), 1);
}
for (tl=0; tlLandscape.flushTiles (_Scene->getDriver(), (uint16)tileSet->getTransition(tl)->getTile (), 1);
}
}
}
//****************************************************************************
void CLandscapeUser::loadAllZonesAround(const CVector &pos, float radius, std::vector &zonesAdded)
{
NL3D_HAUTO_LOAD_LANDSCAPE;
zonesAdded.clear();
_ZoneManager.checkZonesAround ((uint)pos.x, (uint)(-pos.y), (uint)radius);
while (_ZoneManager.isLoading())
{
CZoneManager::SZoneManagerWork Work;
if (_ZoneManager.isWorkComplete(Work))
{
nlassert(!Work.ZoneRemoved);
if (Work.ZoneAdded)
{
if (Work.Zone == (CZone*)-1)
{
nlwarning ("Can't load zone %s", Work.NameZoneAdded.c_str ());
}
else
{
_Landscape->Landscape.addZone (*Work.Zone);
delete Work.Zone;
std::string zoneadd = Work.NameZoneAdded;
zoneadd = zoneadd.substr(0, zoneadd.find('.'));
zonesAdded.push_back(zoneadd);
}
}
}
else
{
nlSleep (1);
}
_ZoneManager.checkZonesAround ((uint)pos.x, (uint)(-pos.y), (uint)radius);
}
// Yoyo: must check the binds of the zones.
_Landscape->Landscape.checkBinds();
}
//****************************************************************************
void CLandscapeUser::refreshAllZonesAround(const CVector &pos, float radius, std::vector &zonesAdded, std::vector &zonesRemoved,
NLMISC::IProgressCallback &progress, const std::vector *validZoneIds)
{
NL3D_HAUTO_LOAD_LANDSCAPE;
zonesAdded.clear();
zonesRemoved.clear();
std::string za, zr;
_ZoneManager.checkZonesAround ((uint)pos.x, (uint)(-pos.y), (uint)radius, validZoneIds);
refreshZonesAround (pos, radius, za, zr);
// Zone to load
uint zoneToLoad = _ZoneManager.getNumZoneLeftToLoad ();
while (_ZoneManager.isLoading() || _ZoneManager.isRemoving())
{
// Progress bar
if (zoneToLoad != 0)
progress.progress ((float)(zoneToLoad-_ZoneManager.getNumZoneLeftToLoad ())/(float)zoneToLoad);
refreshZonesAround (pos, radius, za, zr);
// some zone added or removed??
if(za != "")
zonesAdded.push_back(za);
if(zr != "")
zonesRemoved.push_back(zr);
_ZoneManager.checkZonesAround ((uint)pos.x, (uint)(-pos.y), (uint)radius);
if (_ZoneManager.isLoading())
nlSleep (0);
}
}
// ***************************************************************************
void CLandscapeUser::getAllZoneLoaded(std::vector &zoneLoaded) const
{
// Build the list of zoneId.
std::vector zoneIds;
_Landscape->Landscape.getZoneList(zoneIds);
// transcript
zoneLoaded.clear();
zoneLoaded.resize(zoneIds.size());
for(uint i=0;i dummy;
loadAllZonesAround(pos, radius, dummy);
}
//****************************************************************************
void CLandscapeUser::refreshZonesAround(const CVector &pos, float radius)
{
NL3D_HAUTO_LOAD_LANDSCAPE;
std::string dummy1, dummy2;
refreshZonesAround(pos, radius, dummy1, dummy2);
}
//****************************************************************************
void CLandscapeUser::refreshZonesAround(const CVector &pos, float radius, std::string &zoneAdded, std::string &zoneRemoved, const std::vector *validZoneIds)
{
NL3D_HAUTO_LOAD_LANDSCAPE;
zoneRemoved= "";
zoneAdded= "";
CZoneManager::SZoneManagerWork Work;
// Check if new zone must be added to landscape
if (_ZoneManager.isWorkComplete(Work))
{
if (Work.ZoneAdded)
{
if (Work.Zone == (CZone*)-1)
{
nlwarning ("Can't load zone %s", Work.NameZoneAdded.c_str ());
}
else
{
_Landscape->Landscape.addZone(*Work.Zone);
// Yoyo: must check the binds of the new inserted zone.
try
{
_Landscape->Landscape.checkBinds(Work.Zone->getZoneId());
}
catch (EBadBind &e)
{
nlwarning ("Bind error : %s", e.what());
nlstopex(("Zone Data Bind Error. Please send a report. You may continue but it should crash!"));
}
delete Work.Zone;
zoneAdded = Work.NameZoneAdded;
zoneAdded = zoneAdded.substr(0, zoneAdded.find('.'));
}
}
// Check if a zone must be removed from landscape
if (Work.ZoneRemoved)
{
_Landscape->Landscape.removeZone (Work.IdZoneToRemove);
zoneRemoved = Work.NameZoneRemoved;
zoneRemoved = zoneRemoved.substr(0, zoneRemoved.find('.'));
}
}
_ZoneManager.checkZonesAround((uint)pos.x, (uint)(-pos.y), (uint)radius, validZoneIds);
}
//****************************************************************************
void CLandscapeUser::removeAllZones()
{
NL3D_HAUTO_LOAD_LANDSCAPE;
// Ensure Async Loading is ended
CZoneManager::SZoneManagerWork Work;
while (_ZoneManager.isLoading())
{
if (_ZoneManager.isWorkComplete(Work))
{
// Zone to add?
if (Work.ZoneAdded)
{
if (Work.Zone == (CZone*)-1)
{
nlwarning ("Can't load zone %s", Work.NameZoneAdded.c_str ());
}
else
{
// just discard it! cause will be all cleared below
delete Work.Zone;
}
}
// Zone to remove?
if (Work.ZoneRemoved)
{
_Landscape->Landscape.removeZone (Work.IdZoneToRemove);
}
}
else
{
nlSleep(1);
}
}
// Then do a full clear
_Landscape->Landscape.clear();
_ZoneManager.clear();
}
//****************************************************************************
void CLandscapeUser::setupStaticLight (const CRGBA &diffuse, const CRGBA &ambiant, float multiply)
{
NL3D_HAUTO_UI_LANDSCAPE;
_Landscape->Landscape.setupStaticLight(diffuse, ambiant, multiply);
}
//****************************************************************************
void CLandscapeUser::setThreshold (float thre)
{
NL3D_HAUTO_UI_LANDSCAPE;
_Landscape->Landscape.setThreshold(thre);
}
//****************************************************************************
float CLandscapeUser::getThreshold () const
{
NL3D_HAUTO_UI_LANDSCAPE;
return _Landscape->Landscape.getThreshold();
}
//****************************************************************************
void CLandscapeUser::setTileNear (float tileNear)
{
NL3D_HAUTO_UI_LANDSCAPE;
_Landscape->Landscape.setTileNear(tileNear);
}
//****************************************************************************
float CLandscapeUser::getTileNear () const
{
NL3D_HAUTO_UI_LANDSCAPE;
return _Landscape->Landscape.getTileNear();
}
//****************************************************************************
void CLandscapeUser::setTileMaxSubdivision (uint tileDiv)
{
NL3D_HAUTO_UI_LANDSCAPE;
_Landscape->Landscape.setTileMaxSubdivision(tileDiv);
}
//****************************************************************************
uint CLandscapeUser::getTileMaxSubdivision ()
{
NL3D_HAUTO_UI_LANDSCAPE;
return _Landscape->Landscape.getTileMaxSubdivision();
}
//****************************************************************************
std::string CLandscapeUser::getZoneName(const CVector &pos)
{
NL3D_HAUTO_UI_LANDSCAPE;
return _ZoneManager.getZoneName((uint)pos.x, (uint)(-pos.y), 0, 0).first;
}
//****************************************************************************
CVector CLandscapeUser::getHeightFieldDeltaZ(float x, float y) const
{
NL3D_HAUTO_UI_LANDSCAPE;
return _Landscape->Landscape.getHeightFieldDeltaZ(x,y);
}
//****************************************************************************
void CLandscapeUser::setHeightField(const CHeightMap &hf)
{
NL3D_HAUTO_UI_LANDSCAPE;
_Landscape->Landscape.setHeightField(hf);
}
//****************************************************************************
void CLandscapeUser::enableVegetable(bool enable)
{
NL3D_HAUTO_UI_LANDSCAPE;
_Landscape->Landscape.enableVegetable(enable);
}
//****************************************************************************
void CLandscapeUser::loadVegetableTexture(const std::string &textureFileName)
{
NL3D_HAUTO_LOAD_LANDSCAPE;
_Landscape->Landscape.loadVegetableTexture(textureFileName);
}
//****************************************************************************
void CLandscapeUser::setupVegetableLighting(const CRGBA &ambient, const CRGBA &diffuse, const CVector &directionalLight)
{
NL3D_HAUTO_UI_LANDSCAPE;
_Landscape->Landscape.setupVegetableLighting(ambient, diffuse, directionalLight);
}
//****************************************************************************
void CLandscapeUser::setVegetableWind(const CVector &windDir, float windFreq, float windPower, float windBendMin)
{
NL3D_HAUTO_UI_LANDSCAPE;
_Landscape->Landscape.setVegetableWind(windDir, windFreq, windPower, windBendMin);
}
//****************************************************************************
void CLandscapeUser::setVegetableUpdateLightingFrequency(float freq)
{
NL3D_HAUTO_UI_LANDSCAPE;
_Landscape->Landscape.setVegetableUpdateLightingFrequency(freq);
}
//****************************************************************************
void CLandscapeUser::setUpdateLightingFrequency(float freq)
{
NL3D_HAUTO_UI_LANDSCAPE;
_Landscape->Landscape.setUpdateLightingFrequency(freq);
}
//****************************************************************************
void CLandscapeUser::enableAdditive (bool enable)
{
NL3D_HAUTO_UI_LANDSCAPE;
_Landscape->enableAdditive(enable);
}
//****************************************************************************
bool CLandscapeUser::isAdditiveEnabled () const
{
NL3D_HAUTO_UI_LANDSCAPE;
return _Landscape->isAdditive ();
}
//****************************************************************************
void CLandscapeUser::setPointLightDiffuseMaterial(CRGBA diffuse)
{
NL3D_HAUTO_UI_LANDSCAPE;
_Landscape->Landscape.setPointLightDiffuseMaterial(diffuse);
}
//****************************************************************************
CRGBA CLandscapeUser::getPointLightDiffuseMaterial () const
{
NL3D_HAUTO_UI_LANDSCAPE;
return _Landscape->Landscape.getPointLightDiffuseMaterial();
}
//****************************************************************************
void CLandscapeUser::setDLMGlobalVegetableColor(CRGBA gvc)
{
NL3D_HAUTO_UI_LANDSCAPE;
_Landscape->Landscape.setDLMGlobalVegetableColor(gvc);
}
//****************************************************************************
CRGBA CLandscapeUser::getDLMGlobalVegetableColor() const
{
NL3D_HAUTO_UI_LANDSCAPE;
return _Landscape->Landscape.getDLMGlobalVegetableColor();
}
//****************************************************************************
void CLandscapeUser::updateLightingAll()
{
NL3D_HAUTO_LANDSCAPE_UPDATE_LIGHTING_ALL;
_Landscape->Landscape.updateLightingAll();
}
//****************************************************************************
void CLandscapeUser::postfixTileFilename (const char *postfix)
{
NL3D_HAUTO_LANDSCAPE_UPDATE_LIGHTING_ALL;
_Landscape->Landscape.TileBank.postfixTileFilename (postfix);
}
//****************************************************************************
void CLandscapeUser::postfixTileVegetableDesc (const char *postfix)
{
NL3D_HAUTO_LANDSCAPE_UPDATE_LIGHTING_ALL;
_Landscape->Landscape.TileBank.postfixTileVegetableDesc (postfix);
}
// ***************************************************************************
void CLandscapeUser::enableReceiveShadowMap(bool state)
{
_Landscape->enableReceiveShadowMap(state);
}
// ***************************************************************************
bool CLandscapeUser::canReceiveShadowMap() const
{
return _Landscape->canReceiveShadowMap();
}
// ***************************************************************************
void CLandscapeUser::setRefineCenterAuto(bool mode)
{
_Landscape->setRefineCenterAuto(mode);
}
// ***************************************************************************
void CLandscapeUser::setRefineCenterUser(const CVector &refineCenter)
{
_Landscape->setRefineCenterUser(refineCenter);
}
// ***************************************************************************
bool CLandscapeUser::getRefineCenterAuto() const
{
return _Landscape->getRefineCenterAuto();
}
// ***************************************************************************
const CVector &CLandscapeUser::getRefineCenterUser() const
{
return _Landscape->getRefineCenterUser();
}
// ***************************************************************************
void CLandscapeUser::addTileCallback(ULandscapeTileCallback *cb)
{
NL3D_HAUTO_UI_LANDSCAPE;
_Landscape->Landscape.addTileCallback(cb);
}
// ***************************************************************************
void CLandscapeUser::removeTileCallback(ULandscapeTileCallback *cb)
{
NL3D_HAUTO_UI_LANDSCAPE;
_Landscape->Landscape.removeTileCallback(cb);
}
// ***************************************************************************
bool CLandscapeUser::isTileCallback(ULandscapeTileCallback *cb)
{
NL3D_HAUTO_UI_LANDSCAPE;
return _Landscape->Landscape.isTileCallback(cb);
}
// ***************************************************************************
void CLandscapeUser::setZFunc(UMaterial::ZFunc val)
{
NL3D_HAUTO_UI_LANDSCAPE;
_Landscape->Landscape.setZFunc((CMaterial::ZFunc)val);
}
// ***************************************************************************
const CZone* CLandscapeUser::getZone (sint zoneId) const
{
NL3D_HAUTO_UI_LANDSCAPE;
return _Landscape->Landscape.getZone(zoneId);
}
// ***************************************************************************
void CLandscapeUser::setVegetableDensity(float density)
{
NL3D_HAUTO_UI_LANDSCAPE;
_Landscape->Landscape.setVegetableDensity(density);
}
// ***************************************************************************
float CLandscapeUser::getVegetableDensity() const
{
NL3D_HAUTO_UI_LANDSCAPE;
return _Landscape->Landscape.getVegetableDensity();
}
// ***************************************************************************
float CLandscapeUser::getRayCollision(const NLMISC::CVector &start, const NLMISC::CVector &end)
{
NL3D_HAUTO_UI_LANDSCAPE;
return _Landscape->Landscape.getRayCollision(start, end);
}
} // NL3D