diff --git a/code/ryzom/server/src/server_share/bmp4image.h b/code/ryzom/common/src/game_share/bmp4image.h
similarity index 100%
rename from code/ryzom/server/src/server_share/bmp4image.h
rename to code/ryzom/common/src/game_share/bmp4image.h
diff --git a/code/ryzom/server/src/ai_data_service/pacs_scan.cpp b/code/ryzom/server/src/ai_data_service/pacs_scan.cpp
index 5fc1ed6b5..28e55559c 100644
--- a/code/ryzom/server/src/ai_data_service/pacs_scan.cpp
+++ b/code/ryzom/server/src/ai_data_service/pacs_scan.cpp
@@ -48,7 +48,7 @@
// Server share
-#include "server_share/bmp4image.h"
+#include "game_share/bmp4image.h"
#include "server_share/continent_container.h"
diff --git a/code/ryzom/tools/CMakeLists.txt b/code/ryzom/tools/CMakeLists.txt
index 0bf9fb632..041ba210e 100644
--- a/code/ryzom/tools/CMakeLists.txt
+++ b/code/ryzom/tools/CMakeLists.txt
@@ -23,9 +23,7 @@ IF(WITH_LIGO AND WITH_NET)
ADD_SUBDIRECTORY(sheets_packer)
ENDIF(WITH_LIGO AND WITH_NET)
-IF(WITH_RYZOM_CLIENT)
- ADD_SUBDIRECTORY(client)
-ENDIF(WITH_RYZOM_CLIENT)
+ADD_SUBDIRECTORY(client)
ADD_SUBDIRECTORY(server)
diff --git a/code/ryzom/tools/client/CMakeLists.txt b/code/ryzom/tools/client/CMakeLists.txt
index ff7516ccc..aabc3142c 100644
--- a/code/ryzom/tools/client/CMakeLists.txt
+++ b/code/ryzom/tools/client/CMakeLists.txt
@@ -1,5 +1,10 @@
-ADD_SUBDIRECTORY( client_patcher )
-IF( WITH_QT )
-ADD_SUBDIRECTORY( client_config_qt )
-ENDIF( WITH_QT )
+IF(WITH_RYZOM_CLIENT)
+ ADD_SUBDIRECTORY( client_patcher )
+
+ IF( WITH_QT )
+ ADD_SUBDIRECTORY( client_config_qt )
+ ENDIF( WITH_QT )
+ENDIF(WITH_RYZOM_CLIENT)
+
+ADD_SUBDIRECTORY( r2_islands_textures )
diff --git a/code/ryzom/tools/client/r2_islands_textures/CMakeLists.txt b/code/ryzom/tools/client/r2_islands_textures/CMakeLists.txt
new file mode 100644
index 000000000..0fc6c65a2
--- /dev/null
+++ b/code/ryzom/tools/client/r2_islands_textures/CMakeLists.txt
@@ -0,0 +1,17 @@
+FILE(GLOB SRC *.cpp *.h)
+
+ADD_EXECUTABLE(r2_islands_textures ${SRC})
+
+INCLUDE_DIRECTORIES(${RZ_SERVER_SRC_DIR} ${LIBXML2_INCLUDE_DIR})
+TARGET_LINK_LIBRARIES(r2_islands_textures
+ ryzom_gameshare
+ ryzom_aishare
+ ${LIBXML2_LIBRARIES}
+ nelmisc
+ nel3d)
+ADD_DEFINITIONS(${LIBXML2_DEFINITIONS})
+
+NL_DEFAULT_PROPS(r2_islands_textures "Ryzom, Tools, Server: R2 Islands Textures")
+NL_ADD_RUNTIME_FLAGS(r2_islands_textures)
+
+INSTALL(TARGETS r2_islands_textures RUNTIME DESTINATION ${RYZOM_BIN_PREFIX} COMPONENT tools)
diff --git a/code/ryzom/tools/client/r2_islands_textures/main.cpp b/code/ryzom/tools/client/r2_islands_textures/main.cpp
new file mode 100644
index 000000000..cbde8b9d4
--- /dev/null
+++ b/code/ryzom/tools/client/r2_islands_textures/main.cpp
@@ -0,0 +1,29 @@
+// Ryzom - 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
+#include "screenshot_islands.h"
+
+using namespace NLMISC;
+using namespace R2;
+
+int main(int argc, char **argv)
+{
+ CScreenshotIslands screenshotIslands = CScreenshotIslands::getInstance();
+ screenshotIslands.buildScreenshots();
+
+ return 0;
+}
diff --git a/code/ryzom/tools/client/r2_islands_textures/screenshot_islands.cpp b/code/ryzom/tools/client/r2_islands_textures/screenshot_islands.cpp
new file mode 100644
index 000000000..e6d490a0a
--- /dev/null
+++ b/code/ryzom/tools/client/r2_islands_textures/screenshot_islands.cpp
@@ -0,0 +1,2326 @@
+// Ryzom - 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 "screenshot_islands.h"
+
+#include
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+// AI share
+#include
+
+#include
+
+#include
+
+using namespace NLMISC;
+using namespace NL3D;
+using namespace std;
+using namespace EGSPD;
+using namespace NLGEORGES;
+using namespace RYAI_MAP_CRUNCH;
+
+
+// The 3d driver
+UDriver *driver = NULL;
+CLandscapeIGManager LandscapeIGManager;
+
+uint ScreenShotWidth;
+uint ScreenShotHeight;
+
+UMaterial sceneMaterial;
+
+namespace R2
+{
+
+const TBufferEntry InteriorValue= (TBufferEntry)(~0u-1);
+const TBufferEntry ValueBorder= (TBufferEntry)(~0u-2);
+const uint32 BigValue= 15*5;
+const float limitValue = 200.0;
+
+//-------------------------------------------------------------------------------------------------
+CScreenshotIslands::CScreenshotIslands()
+{
+ _BackColor = CRGBA(255, 255, 255, 255);
+}
+
+//-------------------------------------------------------------------------------------------------
+void CScreenshotIslands::init()
+{
+ // Create a driver
+ driver = UDriver::createDriver();
+ nlassert(driver);
+
+ sceneMaterial = driver->createMaterial();
+ sceneMaterial.getObjectPtr()->setLighting(true);
+ sceneMaterial.getObjectPtr()->setSpecular(CRGBA(255, 255, 255, 255));
+ sceneMaterial.getObjectPtr()->setShininess(50);
+ sceneMaterial.getObjectPtr()->setDiffuse(CRGBA(100, 100, 100, 255));
+ sceneMaterial.getObjectPtr()->setEmissive(CRGBA(25, 25, 25, 255));
+
+ // load and parse the configfile
+ CConfigFile cf;
+ cf.load("IslandScreenshots.cfg");
+
+ CPath::remapExtension("dds", "tga", true);
+
+ // get the value of searchPaths
+ CConfigFile::CVar * searchPaths = cf.getVarPtr("SearchPaths");
+ if(searchPaths)
+ {
+ for(int i = 0; i < searchPaths->size(); i++)
+ {
+ CPath::addSearchPath(searchPaths->asString(i).c_str(), true, false);
+ }
+ }
+
+ // get the scenario entry points file
+ CConfigFile::CVar * epFile = cf.getVarPtr("CompleteIslandsFile");
+ if(epFile)
+ {
+ _CompleteIslandsFile = epFile->asString();
+ }
+
+ // get the out directory path
+ CConfigFile::CVar * outDir = cf.getVarPtr("OutDir");
+ if(outDir)
+ {
+ _OutDirectory = outDir->asString();
+ }
+
+ // get the vegetation option
+ CConfigFile::CVar * veget = cf.getVarPtr("Vegetation");
+ if(veget)
+ {
+ _Vegetation = veget->asBool();
+ }
+
+ // get the vegetation option
+ CConfigFile::CVar * inverseZTest = cf.getVarPtr("InverseZTest");
+ if(inverseZTest)
+ {
+ _InverseZTest = inverseZTest->asBool();
+ }
+
+ // get list of continents
+ CConfigFile::CVar * continents = cf.getVarPtr("Continents");
+ vector continentsName(continents->size());
+ for(int i = 0; i < continents->size(); i++)
+ {
+ continentsName[i] = continents->asString(i);
+ }
+
+ // get continents data (light, coarseMesh,...)
+ UFormLoader * formLoader;
+ for(uint i=0; i form = formLoader->loadForm(CPath::lookup(georgeFileName).c_str());
+ if(form)
+ {
+ CContinentData continentData;
+
+ UFormElm &formRoot = form->getRootNode();
+
+ const UFormElm *elm;
+ if(formRoot.getNodeByName(&elm, "LightLandscapeDay") && elm)
+ {
+ CDirLightSetup landscapeLightDay;
+ landscapeLightDay.build(*elm);
+ continentData.Ambiant = landscapeLightDay.Ambiant;
+ continentData.Diffuse = landscapeLightDay.Diffuse;
+
+ if(continentsName[i]=="r2_jungle" || continentsName[i]=="r2_forest" || continentsName[i]=="r2_roots")
+ {
+ continentData.Ambiant = CRGBA(255, 255, 255, 255);
+ continentData.Diffuse = CRGBA(255, 255, 255, 255);
+ }
+ }
+
+ formRoot.getValueByName(continentData.IGFile, "LandscapeIG");
+ string zoneMin, zoneMax;
+ formRoot.getValueByName(zoneMin, "ZoneMin");
+ formRoot.getValueByName(zoneMax, "ZoneMax");
+
+ getPosFromZoneName(zoneMin, continentData.ZoneMin);
+ getPosFromZoneName(zoneMax, continentData.ZoneMax);
+
+ string filename;
+ if(formRoot.getValueByName(filename, "Ecosystem"))
+ {
+ UFormLoader *formLoaderEco = UFormLoader::createLoader();
+ if(formLoaderEco)
+ {
+ // Load the form
+ CSmartPtr formEco = formLoaderEco->loadForm(filename.c_str());
+
+ if(formEco)
+ {
+ // Root node
+ UFormElm &formRootEco = formEco->getRootNode();
+
+ // Small bank.
+ formRootEco.getValueByName(continentData.SmallBank, "SmallBank");
+
+ // Far bank.
+ formRootEco.getValueByName(continentData.FarBank, "FarBank");
+
+ // Coarse mesh texture.
+ formRootEco.getValueByName(continentData.CoarseMeshMap, "CoarseMeshMap");
+ }
+ else
+ {
+ nlwarning("CScreenshotIslands::init : Can't load form %s.", filename.c_str());
+ }
+ UFormLoader::releaseLoader(formLoaderEco);
+ }
+ }
+
+ _ContinentsData[continentsName[i]] = continentData;
+ }
+ UFormLoader::releaseLoader(formLoader);
+ }
+
+
+ // load islands
+ loadIslands();
+
+ searchIslandsBorders();
+
+ // get seasons
+ CConfigFile::CVar * seasonSuffixes = cf.getVarPtr("SeasonSuffixes");
+ if(seasonSuffixes)
+ {
+ for(uint i = 0; i < (uint)seasonSuffixes->size(); i++)
+ {
+ _SeasonSuffixes.push_back(seasonSuffixes->asString(i));
+ }
+ }
+
+ // get the meter size in pixels
+ CConfigFile::CVar * meterSize = cf.getVarPtr("MeterPixelSize");
+ if(meterSize)
+ {
+ _MeterPixelSize = meterSize->asInt();
+ }
+}
+
+//-------------------------------------------------------------------------------------------------
+bool CScreenshotIslands::getPosFromZoneName(const std::string &name, NLMISC::CVector2f &dest)
+{
+ if(name.empty())
+ {
+ nlwarning ("getPosFromZoneName(): empty name, can't getPosFromZoneName");
+ return false;
+ }
+
+ static std::string zoneName;
+ static string xStr, yStr;
+ xStr.clear();
+ yStr.clear();
+ zoneName = CFile::getFilenameWithoutExtension(name);
+ uint32 i = 0;
+ while(zoneName[i] != '_')
+ {
+ if(!::isdigit(zoneName[i])) return false;
+ yStr += zoneName[i]; ++i;
+ if(i == zoneName.size())
+ return false;
+ }
+ ++i;
+ while(i < zoneName.size())
+ {
+ if(!::isalpha(zoneName[i])) return false;
+ xStr += (char) ::toupper(zoneName[i]); ++i;
+ }
+ if(xStr.size() != 2) return false;
+ dest.x = 160.f * ((xStr[0] - 'A') * 26 + (xStr[1] - 'A'));
+ dest.y = 160.f * -atoi(yStr.c_str());
+ return true;
+}
+
+//-------------------------------------------------------------------------------------------------
+void CScreenshotIslands::searchIslandsBorders()
+{
+ vector filenames;
+ list zonelFiles;
+
+ map< CVector2f, bool> islandsMap;
+
+ TContinentsData::iterator itCont(_ContinentsData.begin()), lastCont(_ContinentsData.end());
+ for( ; itCont != lastCont ; ++itCont)
+ {
+ // for each continent we recover a map of zonel files whith position of
+ // left/bottom point of each zone for keys
+ filenames.clear();
+ zonelFiles.clear();
+
+ string bnpFileName = itCont->first + ".bnp";
+ CBigFile::getInstance().list(bnpFileName.c_str(), filenames);
+
+ for(uint i=0; i::iterator itZonel(zonelFiles.begin()), lastZonel(zonelFiles.end());
+ for( ; itZonel != lastZonel ; ++itZonel)
+ {
+ CVector2f position;
+ getPosFromZoneName(*itZonel, position);
+
+ islandsMap[position] = true;
+ }
+
+ // search for island borders
+ CContinentData & continent = itCont->second;
+ list< string >::const_iterator itIsland(continent.Islands.begin()), lastIsland(continent.Islands.end());
+ for( ; itIsland != lastIsland ; ++itIsland)
+ {
+ if(_IslandsData.find(itIsland->c_str()) != _IslandsData.end())
+ {
+ const CProximityZone & islandData = _IslandsData[itIsland->c_str()];
+
+ sint32 xmin = islandData.getBoundXMin();
+ sint32 xmax = islandData.getBoundXMax();
+ sint32 ymin = islandData.getBoundYMin();
+ sint32 ymax = islandData.getBoundYMax();
+
+ sint32 width = xmax-xmin;
+ sint32 height = ymax-ymin;
+
+ sint32 zonelXMin = ((uint)(xmin/160)) * 160;
+ sint32 zonelYMin = ((uint)(ymin/160) - 1) * 160;
+ sint32 zonelXMax = ((uint)(xmax/160)) * 160;
+ sint32 zonelYMax = ((uint)(ymax/160) - 1) * 160;
+
+ list< CVector2f > leftBorders, rightBorders, bottomBorders, topBorders;
+
+ // search for left and right borders on lines
+ for(sint32 y = zonelYMin; y<=zonelYMax; y+=160 )
+ {
+ sint32 x=zonelXMin;
+ CVector2f vec((float)x, (float)y);
+ bool lastZoneFull = (islandsMap.find(vec) != islandsMap.end());
+ bool currentZoneFull;
+
+ while(x<=zonelXMax)
+ {
+ vec = CVector2f((float)x, (float)y);
+ currentZoneFull = (islandsMap.find(vec) != islandsMap.end());
+
+ if(lastZoneFull && !currentZoneFull && vec.x-1 >= xmin)
+ {
+ rightBorders.push_back(CVector2f(vec.x-1, vec.y));
+ }
+ else if(!lastZoneFull && currentZoneFull)
+ {
+ leftBorders.push_back(vec);
+ }
+ x += 160;
+ lastZoneFull = currentZoneFull;
+ }
+ }
+
+ // search for bottom and top borders on columns
+ for(sint32 x = zonelXMin; x<=zonelXMax; x+=160 )
+ {
+ sint32 y=zonelYMin;
+ CVector2f vec((float)x, (float)y);
+ bool lastZoneFull = (islandsMap.find(vec) != islandsMap.end());
+ bool currentZoneFull;
+
+ while(y<=zonelYMax)
+ {
+ vec = CVector2f((float)x, (float)y);
+ currentZoneFull = (islandsMap.find(vec) != islandsMap.end());
+
+ if(lastZoneFull && !currentZoneFull && vec.y-1 >= ymin)
+ {
+ topBorders.push_back(CVector2f(vec.x, vec.y-1));
+ }
+ else if(!lastZoneFull && currentZoneFull)
+ {
+ bottomBorders.push_back(vec);
+ }
+ y += 160;
+ lastZoneFull = currentZoneFull;
+ }
+ }
+
+ _BorderIslands[*itIsland + "/right"] = rightBorders;
+ _BorderIslands[*itIsland + "/left"] = leftBorders;
+ _BorderIslands[*itIsland + "/bottom"] = bottomBorders;
+ _BorderIslands[*itIsland + "/top"] = topBorders;
+ }
+ }
+ }
+}
+
+//-------------------------------------------------------------------------------------------------
+void CScreenshotIslands::attenuateIslandBorders(const std::string & islandName, CBitmap & islandBitmap,
+ const CProximityZone & islandData)
+{
+ list< CVector2f > leftBorders, rightBorders, bottomBorders, topBorders;
+ rightBorders = _BorderIslands[islandName + "/right"];
+ leftBorders = _BorderIslands[islandName + "/left"];
+ bottomBorders = _BorderIslands[islandName + "/bottom"];
+ topBorders = _BorderIslands[islandName + "/top"];
+
+ sint32 xmin = islandData.getBoundXMin();
+ sint32 xmax = islandData.getBoundXMax();
+ sint32 ymin = islandData.getBoundYMin();
+ sint32 ymax = islandData.getBoundYMax();
+
+ sint32 width = xmax-xmin;
+ sint32 height = ymax-ymin;
+ uint8 *dest = &(islandBitmap.getPixels(0)[0]);
+
+ list< CVector2f >::iterator itBorder;
+
+ for(itBorder=leftBorders.begin(); itBorder!=leftBorders.end(); itBorder++)
+ {
+ const CVector2f initPoint = *itBorder;
+ sint32 x = (sint32)initPoint.x - xmin;
+ sint32 y = (sint32)initPoint.y - ymin;
+ sint32 maxBorder = 160;
+ if(y<0)
+ {
+ maxBorder += y;
+ y = 0;
+ }
+ sint32 inity = y;
+
+ while(y<(inity+maxBorder) && y<(sint32)height)
+ {
+ double noiseValue = (1+cos(((y-inity)*2*Pi)/maxBorder))*5;
+ double evalNoise = 10 + noiseValue;
+ double diffAlpha = 255/evalNoise;
+
+ CRGBA color = islandBitmap.getPixelColor(x, height-y-1);
+ sint32 currentX = x-1;
+
+ while((currentX>=x-evalNoise) && currentX>=0)
+ {
+ uint8 *pixel = &(islandBitmap.getPixels(0)[((height-y-1)*width + currentX)*4]);
+ uint alpha = (uint)(255-diffAlpha*(x-currentX));
+ uint invAlpha = 255-alpha;
+
+ *pixel = (uint8) (((invAlpha * *pixel) + (alpha * color.R)) >> 8);
+ *(pixel + 1) = (uint8) (((invAlpha * *(pixel + 1)) + (alpha * color.G)) >> 8);
+ *(pixel + 2) = (uint8) (((invAlpha * *(pixel + 2)) + (alpha * color.B)) >> 8);
+ *(pixel + 3) = (uint8) 255;
+
+ currentX--;
+ }
+ y++;
+ }
+ }
+
+ for(itBorder=rightBorders.begin(); itBorder!=rightBorders.end(); itBorder++)
+ {
+ const CVector2f initPoint = *itBorder;
+ sint32 x = (sint32)initPoint.x - xmin;
+ sint32 y = (sint32)initPoint.y - ymin;
+ sint32 maxBorder = 160;
+ if(y<0)
+ {
+ maxBorder += y;
+ y = 0;
+ }
+ sint32 inity = y;
+
+ while(y<(inity+maxBorder) && y<(sint32)height)
+ {
+ double noiseValue = (1+cos(((y-inity)*2*Pi)/maxBorder))*5;
+ double evalNoise = 10 + noiseValue;
+ double diffAlpha = 255/evalNoise;
+
+ CRGBA color = islandBitmap.getPixelColor(x, height-y-1);
+ sint32 currentX = x+1;
+
+ while((currentX<=x+evalNoise) && currentX> 8);
+ *(pixel + 1) = (uint8) (((invAlpha * *(pixel + 1)) + (alpha * color.G)) >> 8);
+ *(pixel + 2) = (uint8) (((invAlpha * *(pixel + 2)) + (alpha * color.B)) >> 8);
+ *(pixel + 3) = (uint8) 255;
+
+ currentX++;
+ }
+
+ y++;
+ }
+ }
+
+ for(itBorder=bottomBorders.begin(); itBorder!=bottomBorders.end(); itBorder++)
+ {
+ const CVector2f initPoint = *itBorder;
+ sint32 x = (sint32)initPoint.x - xmin;
+ sint32 y = (sint32)initPoint.y - ymin;
+ sint32 maxBorder = 160;
+ if(x<0)
+ {
+ maxBorder += x;
+ x = 0;
+ }
+ sint32 initx = x;
+
+ while(x<(initx+maxBorder) && x<(sint32)width)
+ {
+ double noiseValue = (1+cos(((x-initx)*2*Pi)/maxBorder))*5;
+ double evalNoise = 10 + noiseValue;
+ double diffAlpha = 255/evalNoise;
+
+ CRGBA color = islandBitmap.getPixelColor(x, height-y-1);
+ sint32 currentY = y-1;
+
+ while((currentY>=y-evalNoise) && currentY>=0)
+ {
+ uint8 *pixel = &(islandBitmap.getPixels(0)[((height-currentY-1)*width + x)*4]);
+ uint alpha = (uint)(255-diffAlpha*(y-currentY));
+ uint invAlpha = 255-alpha;
+
+ *pixel = (uint8) (((invAlpha * *pixel) + (alpha * color.R)) >> 8);
+ *(pixel + 1) = (uint8) (((invAlpha * *(pixel + 1)) + (alpha * color.G)) >> 8);
+ *(pixel + 2) = (uint8) (((invAlpha * *(pixel + 2)) + (alpha * color.B)) >> 8);
+ *(pixel + 3) = (uint8) 255;
+
+ currentY--;
+ }
+
+ x++;
+ }
+ }
+
+ for(itBorder=topBorders.begin(); itBorder!=topBorders.end(); itBorder++)
+ {
+ const CVector2f initPoint = *itBorder;
+ sint32 x = (sint32)initPoint.x - xmin;
+ sint32 y = (sint32)initPoint.y - ymin;
+ sint32 maxBorder = 160;
+ if(x<0)
+ {
+ maxBorder += x;
+ x = 0;
+ }
+ sint32 initx = x;
+
+ while(x<(initx+maxBorder) && x<(sint32)width)
+ {
+ double noiseValue = (1+cos(((x-initx)*2*Pi)/maxBorder))*5;
+ double evalNoise = 10 + noiseValue;
+ double diffAlpha = 255/evalNoise;
+
+ CRGBA color = islandBitmap.getPixelColor(x, height-y-1);
+ sint32 currentY = y+1;
+
+ while((currentY<=y+evalNoise) && currentY> 8);
+ *(pixel + 1) = (uint8) (((invAlpha * *(pixel + 1)) + (alpha * color.G)) >> 8);
+ *(pixel + 2) = (uint8) (((invAlpha * *(pixel + 2)) + (alpha * color.B)) >> 8);
+ *(pixel + 3) = (uint8) 255;
+
+ currentY++;
+ }
+
+ x++;
+ }
+ }
+}
+
+//-------------------------------------------------------------------------------------------------
+void CScreenshotIslands::buildScreenshots()
+{
+ init();
+ buildIslandsTextures();
+}
+
+//-------------------------------------------------------------------------------------------------
+void CScreenshotIslands::writeProximityBufferToTgaFile(const std::string& fileName,const TBuffer& buffer,uint32 scanWidth,uint32 scanHeight)
+{
+ uint imageWidth = (scanWidth+15)&~15;
+ uint imageHeight = (scanHeight);
+
+ CTGAImageGrey tgaImage;
+ tgaImage.setup((uint16)imageWidth, (uint16)imageHeight, fileName, 0, 0);
+ for (uint32 y=0;y255*5)?255:value/5);
+ }
+ tgaImage.writeLine();
+ }
+}
+
+//-------------------------------------------------------------------------------------------------
+void CScreenshotIslands::processProximityBuffer(TBuffer & inputBuffer, uint32 lineLength, TBuffer& resultBuffer)
+{
+ // a couple of constants to control the range over which our degressive filter is to be applied
+ const uint32 smallValue= 2*5;
+
+ float a = 5*((255.0 - limitValue)/(float(100-BigValue)));
+ float b = (float)(limitValue*5 - a*BigValue);
+
+ // determine numer of lines in the buffer...
+ uint32 numLines= inputBuffer.size()/ lineLength;
+
+ // clear out the result buffer and reset all values to 5*255, remembering that this is the correct value for the image edges
+ resultBuffer.clear();
+ resultBuffer.resize(inputBuffer.size(),(TBufferEntry)5*255);
+
+ for (uint32 y=1;yBigValue) value=5*255;
+ else value= (uint32)(((1.0-cos(Pi*(float(value-smallValue)/(float)(BigValue-smallValue))))/2.0)*float(5*255));
+ */
+
+ if (value==ValueBorder);
+ else if ((value>=0) && (valueBigValue)
+ {
+ if(value==InteriorValue)
+ {
+ value = (uint)(5*limitValue);
+ }
+ else
+ {
+ value = (uint)(a*value+b);
+ if(value > 5*255) value = 5*255;
+ }
+ }
+ else if((value>=smallValue) && (value<=BigValue))
+ {
+ value= (uint32)(((1.0-cos(Pi*(float(value-smallValue)/(float)(BigValue-smallValue))))/2.0)*float(5*limitValue));
+ }
+
+ // store the value into the result buffer
+ resultBuffer[offset]= (TBufferEntry)value;
+ }
+ }
+
+ // modify inputBuffer to store "bigValue" limit
+ for (uint32 y=1;y0)
+ {
+ uint16 nextValue = resultBuffer[offset-1];
+ uint16 prevValue = (TBufferEntry)(5*limitValue);
+ if(nextValue!=(TBufferEntry)(5*limitValue))
+ {
+ uint32 count = x-1;
+ while((count>x-7) && (count>0) && ((nextValue=resultBuffer[lineOffset+count])!=0)
+ && nextValue!=(TBufferEntry)(5*limitValue) && (nextValue!=ValueBorder))
+ {
+ uint16 newValue = (TBufferEntry)(prevValue+5*7);
+ if(newValue < nextValue)
+ {
+ resultBuffer[lineOffset+count] = newValue;
+ }
+
+ prevValue = newValue;
+ count--;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ //columns
+ for (uint32 x=0;x=startOffset)
+ {
+ uint16 nextValue = resultBuffer[offset-lineLength];
+ uint16 prevValue = (TBufferEntry)(5*limitValue);
+ if(nextValue!=(TBufferEntry)(5*limitValue))
+ {
+ uint32 count = offset-lineLength;
+ while((count>offset-7*lineLength) && (count>=startOffset) &&
+ ((nextValue=resultBuffer[count])!=0) && nextValue!=(TBufferEntry)(5*limitValue) && (nextValue!=ValueBorder))
+ {
+ uint16 newValue = (TBufferEntry)(prevValue+5*7);
+ if(newValue < nextValue)
+ {
+ resultBuffer[count] = newValue;
+ }
+
+ prevValue = newValue;
+ count -= lineLength;
+ }
+ }
+ }
+ }
+ }
+ }
+ */
+
+ //-----------------------------------------------------------------------------
+ // search for pixels of borders
+ map< CVector2f, bool > bordersPixels;
+ for (uint32 y=0;y leftBorders, rightBorders, bottomBorders, topBorders;
+ for (uint32 y=0;y0)
+ {
+ for(uint32 xc=(uint32)firstPixelBorder.x; xc<(uint32)(firstPixelBorder.x+nbPixelsBorder); xc++)
+ {
+ if(resultBuffer[(y-1)*lineLength+xc]==(TBufferEntry)(5*255))
+ {
+ bottom = true;
+ break;
+ }
+ }
+ }
+
+ if(y+10)
+ {
+ for(uint32 yc=(uint32)firstPixelBorder.y; yc<(uint32)(firstPixelBorder.y+nbPixelsBorder); yc++)
+ {
+ if(resultBuffer[yc*lineLength+x-1]==(TBufferEntry)(5*255))
+ {
+ left = true;
+ break;
+ }
+ }
+ }
+
+ if(x+1=(uint32)(y-evalNoise)) && yc>=0)
+ {
+ uint16 newValue = (TBufferEntry)(5*(limitValue + diffAlpha*(y-yc)));
+ uint16 currentValue = (TBufferEntry)resultBuffer[yc*lineLength+xc];
+ if(newValue=(uint32)(x-evalNoise)) && xc>=0)
+ {
+ uint16 newValue = (TBufferEntry)(5*(limitValue + diffAlpha*(x-xc)));
+ uint16 currentValue = (TBufferEntry)resultBuffer[yc*lineLength+xc];
+ if(newValue islands;
+ CScenarioEntryPoints scenarioEntryPoints = CScenarioEntryPoints::getInstance();
+
+ scenarioEntryPoints.loadFromFile();
+ const CScenarioEntryPoints::TEntryPoints& entryPoints = scenarioEntryPoints.getEntryPoints();
+
+ CScenarioEntryPoints::TEntryPoints::const_iterator entry(entryPoints.begin()), entryPoint(entryPoints.end());
+ for( ; entry != entryPoint ; ++entry)
+ {
+ islands[entry->Island] = CVector2f((float)entry->X, (float)entry->Y);
+ }
+
+ // search islands of each continent
+ map< string, CVector2f >::iterator itIsland(islands.begin()), lastIsland(islands.end());
+ for( ; itIsland != lastIsland ; ++itIsland)
+ {
+ const CVector2f & entryPoint = itIsland->second;
+
+ // search continent of this island
+ TContinentsData::iterator itCont(_ContinentsData.begin()), lastCont(_ContinentsData.end());
+ for( ; itCont != lastCont ; ++itCont)
+ {
+ CContinentData & continent = itCont->second;
+ CVector2f zoneMax = continent.ZoneMax;
+ CVector2f zoneMin = continent.ZoneMin;
+
+ if((zoneMin.x <= entryPoint.x) && (entryPoint.x <= zoneMax.x)
+ && (zoneMax.y <= entryPoint.y) && (entryPoint.y <= zoneMin.y))
+ {
+ continent.Islands.push_back(itIsland->first);
+ break;
+ }
+ }
+ }
+
+ // search data of each island
+ TContinentsData::iterator itCont(_ContinentsData.begin()), lastCont(_ContinentsData.end());
+ for( ; itCont != lastCont ; ++itCont)
+ {
+ string aiFileName = itCont->first+"_0.cwmap2";
+
+ const CContinentData & continent = itCont->second;
+
+ CProximityMapBuffer continentBuffer;
+ continentBuffer.load(CPath::lookup(aiFileName));
+
+ CProximityMapBuffer::TZones zones;
+ continentBuffer.calculateZones(zones);
+
+ for (uint32 i=0;i::const_iterator itIsland(continent.Islands.begin()), lastIsland(continent.Islands.end());
+ for( ; itIsland != lastIsland ; ++itIsland)
+ {
+ const CVector2f & entryPoint = islands[*itIsland];
+ sint32 xmin = zones[i].getBoundXMin();
+ sint32 xmax = zones[i].getBoundXMax();
+ sint32 ymin = zones[i].getBoundYMin();
+ sint32 ymax = zones[i].getBoundYMax();
+
+ if((xmin <= entryPoint.x) && (entryPoint.x <= xmax)
+ && (ymin <= entryPoint.y) && (entryPoint.y <= ymax))
+ {
+ fileName = _OutDirectory + "/" + *itIsland + "_prox.tga";
+ _IslandsData[*itIsland] = zones[i];
+ break;
+ }
+ }
+
+ // write the processed proximity map to an output file
+ if(fileName != "")
+ {
+ writeProximityBufferToTgaFile(fileName, cleanBuffer, zones[i].getZoneWidth(), zones[i].getZoneHeight());
+ _TempFileNames.push_back(fileName);
+
+ fileName = _OutDirectory + "/" + *itIsland + "_limit.tga";
+ writeProximityBufferToTgaFile(fileName, zoneBuffer, zones[i].getZoneWidth(), zones[i].getZoneHeight());
+ _TempFileNames.push_back(fileName);
+ }
+ else
+ {
+ nlinfo("Zone of island not found, tga not build");
+ }
+ }
+ }
+
+
+ CScenarioEntryPoints::TCompleteIslands completeIslands(entryPoints.size());
+
+ uint completeIslandsNb = 0;
+ for(uint e=0; e::const_iterator itIsland(itCont->second.Islands.begin()), lastIsland(itCont->second.Islands.end());
+ for( ; itIsland != lastIsland ; ++itIsland)
+ {
+ if(*itIsland == entry.Island)
+ {
+ completeIsland.Continent = CSString(itCont->first);
+ if(_IslandsData.find(entry.Island)!=_IslandsData.end())
+ {
+ completeIsland.XMin = _IslandsData[entry.Island].getBoundXMin();
+ completeIsland.YMin = _IslandsData[entry.Island].getBoundYMin();
+ completeIsland.XMax = _IslandsData[entry.Island].getBoundXMax();
+ completeIsland.YMax = _IslandsData[entry.Island].getBoundYMax();
+ completeIslands[completeIslandsNb] = completeIsland;
+ completeIslandsNb++;
+ }
+ break;
+ }
+ }
+ }
+ }
+ completeIslands.resize(completeIslandsNb);
+
+ CScenarioEntryPoints::getInstance().saveXMLFile(completeIslands, _CompleteIslandsFile);
+}
+
+//--------------------------------------------------------------------------------
+
+void CScreenshotIslands::getBuffer(UScene * scene, ULandscape * landscape, CBitmap &btm)
+{
+ //
+ if (ScreenShotWidth && ScreenShotHeight)
+ {
+ UCamera camera = scene->getCam();
+
+ // Destination image
+ CBitmap dest;
+ btm.resize(ScreenShotWidth, ScreenShotHeight, CBitmap::RGBA);
+
+ uint windowWidth = driver->getWindowWidth();
+ uint windowHeight = driver->getWindowHeight();
+
+ uint top;
+ uint bottom = min(windowHeight, ScreenShotHeight);
+ for (top=0; topclearBuffers(_BackColor);
+
+ // store initial frustum and viewport
+ CFrustum Frustum = scene->getCam().getFrustum();
+ CViewport Viewport = scene->getViewport();
+
+ // Build a new frustum
+ CFrustum frustumPart;
+ frustumPart.Left = Frustum.Left+(Frustum.Right-Frustum.Left)*((float)left/(float)ScreenShotWidth);
+ frustumPart.Right = Frustum.Left+(Frustum.Right-Frustum.Left)*((float)right/(float)ScreenShotWidth);
+ frustumPart.Top = ceil(Frustum.Top+(Frustum.Bottom-Frustum.Top)*((float)top/(float)ScreenShotHeight));
+ frustumPart.Bottom = ceil(Frustum.Top+(Frustum.Bottom-Frustum.Top)*((float)bottom/(float)ScreenShotHeight));
+ frustumPart.Near = Frustum.Near;
+ frustumPart.Far = Frustum.Far;
+ frustumPart.Perspective = Frustum.Perspective;
+
+ // Build a new viewport
+ CViewport viewport;
+ viewport.init(0, 0, (float)(right-left)/windowWidth,
+ (float)(bottom-top)/windowHeight);
+
+ // Activate all this
+ scene->getCam().setFrustum(frustumPart);
+ scene->setViewport(viewport);
+
+ scene->setMaxSkeletonsInNotCLodForm(1000000);
+ scene->setPolygonBalancingMode(UScene::PolygonBalancingOff);
+
+ if(_InverseZTest)
+ {
+ // render scene with inversed ZBuffer test (keep greater distances)
+ driver->setColorMask(false, false, false, false);
+ sceneMaterial.setZFunc(UMaterial::less);
+
+ // initialize ZBuffer with leak value
+ driver->setMatrixMode2D11();
+ CQuad quad;
+ quad.V0 = CVector(0.0, 0.0, 0.0);
+ quad.V1 = CVector(1.0, 0.0, 0.0);
+ quad.V2 = CVector(1.0, 1.0, 0.0);
+ quad.V3 = CVector(0.0, 1.0, 0.0);
+
+ driver->drawQuad(quad, sceneMaterial);
+ driver->setMatrixMode3D(camera);
+ driver->setColorMask(true, true, true, true);
+
+ scene->enableElementRender(UScene::FilterWater, false);
+ }
+
+ scene->render();
+
+ // display vegetables with normal ZBuffer test
+ if(_InverseZTest && _Vegetation)
+ {
+ scene->enableElementRender(UScene::FilterWater, false);
+ scene->enableElementRender(UScene::FilterLandscape, false);
+ scene->enableElementRender(UScene::FilterWater, true);
+ scene->render();
+ scene->enableElementRender(UScene::FilterLandscape, true);
+ }
+
+ // Get the bitmap
+ driver->getBuffer(dest);
+ btm.blit(dest, 0, windowHeight-(bottom-top), right-left, bottom-top, left, top);
+
+ // restore camera
+ scene->getCam().setFrustum(Frustum);
+ scene->setViewport(Viewport);
+
+ driver->flush();
+ driver->swapBuffers();
+
+ // Next
+ right = std::min(right+windowWidth, ScreenShotWidth);
+ }
+
+ // Next
+ bottom = std::min(bottom+windowHeight, ScreenShotHeight);
+ }
+ }
+ else
+ {
+ driver->getBuffer(btm);
+ }
+}
+
+
+
+void CScreenshotIslands::buildIslandsTextures()
+{
+ int loop = 0;
+ int maxLoop = 6;
+
+ // Create the window with config file values
+ driver->setDisplay(UDriver::CMode(1024, 768, 32, false));
+
+ // Create a scene
+ UScene * scene = driver->createScene(true);
+ scene->animate(CTime::ticksToSecond(CTime::getPerformanceTime()));
+
+ // Create a camera
+ UCamera camera = scene->getCam();
+ camera.setTransformMode(UTransformable::DirectMatrix);
+
+ // Create and load landscape
+ ULandscape * landscape = scene->createLandscape();
+ if(_InverseZTest)
+ {
+ landscape->setZFunc(UMaterial::greaterequal);
+ }
+ else
+ {
+ landscape->setZFunc(UMaterial::less);
+ }
+
+ //Iteration on seasons
+ list< string >::iterator itSeason(_SeasonSuffixes.begin()), lastSeason(_SeasonSuffixes.end());
+ for( ; itSeason != lastSeason ; ++itSeason)
+ {
+ string seasonSuffix = *itSeason;
+
+ int season;
+ if(seasonSuffix=="_sp") season = CSeason::Spring;
+ else if(seasonSuffix=="_su") season = CSeason::Summer;
+ else if(seasonSuffix=="_au") season = CSeason::Autumn;
+ else if(seasonSuffix=="_wi") season = CSeason::Winter;
+
+ // Iterations on Continents
+ TContinentsData::iterator itCont(_ContinentsData.begin()), lastCont(_ContinentsData.end());
+ for( ; itCont != lastCont ; ++itCont)
+ {
+ const CContinentData & continent = itCont->second;
+
+ // Light init
+ landscape->setupStaticLight(continent.Diffuse, continent.Ambiant, 1.0f);
+
+ string coarseMeshFile = continent.CoarseMeshMap;
+ string coarseMeshWithoutExt = CFile::getFilenameWithoutExtension(coarseMeshFile);
+ string coarseMeshExt = CFile::getExtension(coarseMeshFile);
+ coarseMeshFile = coarseMeshWithoutExt + seasonSuffix + "." + coarseMeshExt;
+ scene->setCoarseMeshManagerTexture(coarseMeshFile.c_str());
+
+ // Load the landscape
+ string farBank = continent.FarBank;
+ string farBankWithoutExt = CFile::getFilenameWithoutExtension(farBank);
+ string farBankExt = CFile::getExtension(farBank);
+ farBank = farBankWithoutExt + seasonSuffix + "." + farBankExt;
+ landscape->loadBankFiles(continent.SmallBank, farBank);
+
+ // Load vegatables
+ LandscapeIGManager.initIG(scene, continent.IGFile, driver, season, NULL);
+
+ // Iterations on Islands
+ list< string >::const_iterator itIsland(continent.Islands.begin()), lastIsland(continent.Islands.end());
+ for( ; itIsland != lastIsland ; ++itIsland)
+ {
+ loop = 0;
+
+ if(_IslandsData.find(itIsland->c_str()) != _IslandsData.end())
+ {
+ const CProximityZone & islandData = _IslandsData[itIsland->c_str()];
+
+ sint32 xmin = islandData.getBoundXMin();
+ sint32 xmax = islandData.getBoundXMax();
+ sint32 ymin = islandData.getBoundYMin();
+ sint32 ymax = islandData.getBoundYMax();
+
+ float width = (float)(xmax-xmin);
+ float height = (float)(ymax-ymin);
+ ScreenShotWidth = (uint)(width*_MeterPixelSize);
+ ScreenShotHeight = (uint)(height*_MeterPixelSize);
+
+ // position in island center
+ float posx = ((float)(xmax+xmin))/2;
+ float posy = ((float)(ymax+ymin))/2;
+ CVector entryPos(posx, posy, 400);
+
+ // Setup camera
+ CMatrix startCamMatrix;
+ startCamMatrix.setPos(entryPos);
+ startCamMatrix.rotateX(-(float)Pi/2);
+ camera.setMatrix(startCamMatrix);
+ camera.setFrustum(width, height, -10000.0f, 10000.0f, false);
+
+ // init lanscape
+ landscape->postfixTileFilename(seasonSuffix.c_str());
+
+ while(loop zonesAdded;
+ vector zonesRemoved;
+ IProgressCallback progress;
+ landscape->refreshAllZonesAround(camera.getMatrix().getPos(), 1000, zonesAdded, zonesRemoved, progress);
+ if(_Vegetation)
+ {
+ LandscapeIGManager.unloadArrayZoneIG(zonesRemoved);
+ LandscapeIGManager.loadArrayZoneIG(zonesAdded);
+
+ vector::iterator itName(zonesAdded.begin()), lastName(zonesAdded.end());
+ for( ; itName != lastName ; ++itName)
+ {
+ UInstanceGroup * instanceGr = LandscapeIGManager.getIG(*itName);
+ if(instanceGr)
+ {
+ uint nbInst = instanceGr->getNumInstance();
+ for(uint i=0; igetNumInstance(); i++)
+ {
+ instanceGr->setCoarseMeshDist(i, 100000);
+ instanceGr->setDistMax(i, 100000);
+ }
+ }
+ }
+ }
+
+ // Clear all buffers
+ driver->clearBuffers(_BackColor);
+
+ if(_InverseZTest)
+ {
+ // render scene with inversed ZBuffer test (keep greater distances)
+ driver->setColorMask(false, false, false, false);
+ sceneMaterial.setZFunc(UMaterial::less);
+
+ // initialize ZBuffer with leak value
+ driver->setMatrixMode2D11();
+ CQuad quad;
+ quad.V0 = CVector(0.0, 0.0, 0.0);
+ quad.V1 = CVector(1.0, 0.0, 0.0);
+ quad.V2 = CVector(1.0, 1.0, 0.0);
+ quad.V3 = CVector(0.0, 1.0, 0.0);
+
+ driver->drawQuad(quad, sceneMaterial);
+ driver->setMatrixMode3D(camera);
+ driver->setColorMask(true, true, true, true);
+
+ scene->enableElementRender(UScene::FilterWater, false);
+ }
+
+ scene->render();
+
+ // display vegetables with normal ZBuffer test
+ if(_InverseZTest && _Vegetation)
+ {
+ scene->enableElementRender(UScene::FilterLandscape, false);
+ scene->enableElementRender(UScene::FilterWater, true);
+ scene->render();
+ scene->enableElementRender(UScene::FilterLandscape, true);
+ }
+
+ // Swap 3d buffers
+ driver->flush();
+ driver->swapBuffers();
+
+ // Pump user input messages
+ driver->EventServer.pump();
+
+ loop += 1;
+
+ // Screenshot
+ if(loop==maxLoop-1)
+ {
+ CBitmap islandBitmap;
+ getBuffer(scene, landscape, islandBitmap);
+
+ buildBackTextureHLS(*itIsland, islandBitmap);
+ }
+ if(loop==maxLoop)
+ {
+ // create srcennshot bitmap of full island
+ CBitmap islandBitmap;
+ getBuffer(scene, landscape, islandBitmap);
+
+ attenuateIslandBorders(*itIsland, islandBitmap, islandData);
+
+ // load proximity bitmap
+ CBitmap proxBitmap;
+ std::string proxFileName = _OutDirectory + "/" + *itIsland + "_prox.tga";
+ CIFile proxFS(proxFileName.c_str());
+ proxBitmap.load(proxFS);
+
+ // resize proximity bitmap
+ CBitmap tempBitmap;
+ int newWidth = islandBitmap.getWidth();
+ int newHeight = islandBitmap.getHeight();
+ tempBitmap.resize(newWidth, newHeight, islandBitmap.PixelFormat);
+ // blit src bitmap
+ tempBitmap.blit(proxBitmap, 0, 0, newWidth, newHeight, 0, 0);
+
+ // swap them
+ proxBitmap.resize(newWidth, newHeight, proxBitmap.PixelFormat);
+ proxBitmap.swap(tempBitmap);
+
+
+ // create final bitmap
+ CBitmap bitmapDest;
+ bitmapDest.resize(islandBitmap.getWidth(), islandBitmap.getHeight(), islandBitmap.PixelFormat);
+
+
+ // mix black and full island bitmaps with blend factor of proximity bitmap pixels
+ uint numPix = islandBitmap.getWidth() * islandBitmap.getHeight();
+
+ const uint8 *alphaProx = &(proxBitmap.getPixels(0)[0]);
+ const uint8 *srcIsland = &(islandBitmap.getPixels(0)[0]);
+ uint8 *dest = &(bitmapDest.getPixels(0)[0]);
+
+
+ const uint8 *srcBack = &(_BackBitmap.getPixels(0)[0]);
+
+ uint8 *endDest = dest + (numPix << 2);
+
+ do
+ {
+ uint invblendFact = (uint) alphaProx[0];
+ uint blendFact = 256 - invblendFact;
+
+ // blend 4 component at each pass
+ *dest = (uint8) (((blendFact * *srcIsland) + (invblendFact * *srcBack)) >> 8);
+ *(dest + 1) = (uint8) (((blendFact * *(srcIsland + 1)) + (invblendFact * *(srcBack + 1))) >> 8);
+ *(dest + 2) = (uint8) (((blendFact * *(srcIsland + 2)) + (invblendFact * *(srcBack + 2))) >> 8);
+ *(dest + 3) = (uint8) 255;
+
+ alphaProx = alphaProx + 4;
+ srcIsland = srcIsland + 4;
+ dest = dest + 4;
+
+ srcBack = srcBack + 4;
+ }
+ while(dest != endDest);
+
+
+ // create tga file of avoidable place in island
+ string textureName = _OutDirectory + "/" + *itIsland + seasonSuffix + ".tga";
+
+ CBitmap bitmapLittle;
+ bitmapLittle.resize(bitmapDest.getWidth(), bitmapDest.getHeight(), bitmapDest.PixelFormat);
+ bitmapLittle = bitmapDest;
+ if(!isPowerOf2(bitmapDest.getWidth()) || !isPowerOf2(bitmapDest.getHeight()) )
+ {
+ uint pow2w = NLMISC::raiseToNextPowerOf2(bitmapDest.getWidth());
+ uint pow2h = NLMISC::raiseToNextPowerOf2(bitmapDest.getHeight());
+ CBitmap enlargedBitmap;
+ enlargedBitmap.resize(pow2w, pow2h, bitmapDest.PixelFormat);
+ // blit src bitmap
+ enlargedBitmap.blit(&bitmapDest, 0, 0);
+ // swap them
+ bitmapDest.swap(enlargedBitmap);
+ }
+
+ COFile fsDest(textureName.c_str());
+ bitmapDest.writeTGA(fsDest,32);
+
+
+ // little tga
+ bitmapLittle.resample(bitmapLittle.getWidth()/10, bitmapLittle.getHeight()/10);
+ if(!isPowerOf2(bitmapLittle.getWidth()) || !isPowerOf2(bitmapLittle.getHeight()) )
+ {
+ uint pow2w = NLMISC::raiseToNextPowerOf2(bitmapLittle.getWidth());
+ uint pow2h = NLMISC::raiseToNextPowerOf2(bitmapLittle.getHeight());
+ CBitmap enlargedBitmap;
+ enlargedBitmap.resize(pow2w, pow2h, bitmapLittle.PixelFormat);
+ // blit src bitmap
+ enlargedBitmap.blit(&bitmapLittle, 0, 0);
+ // swap them
+ bitmapLittle.swap(enlargedBitmap);
+ }
+
+ textureName = _OutDirectory + "/" + *itIsland + seasonSuffix + "_little.tga";
+ COFile fsLittle(textureName.c_str());
+ bitmapLittle.writeTGA(fsLittle,32);
+
+ _BackColor = CRGBA(255, 255, 255, 255);
+ }
+ }
+ }
+ }
+
+ LandscapeIGManager.reset();
+ landscape->removeAllZones();
+ }
+ }
+
+ // remove proximity tga
+ list::iterator itProx(_TempFileNames.begin()), lastProx(_TempFileNames.end());
+ for( ; itProx != lastProx ; ++itProx)
+ {
+ CFile::deleteFile(*itProx);
+ };
+}
+
+//--------------------------------------------------------------------------------
+inline bool RGB2HSV(const CRGBA & rgba, uint & Hue, uint & Sat, uint & Val)
+{
+ double Min_, Max_, Delta, H, S, V;
+
+ H = 0.0;
+ Min_ = min(min(rgba.R, rgba.G), rgba.B);
+ Max_ = max(max(rgba.R, rgba.G), rgba.B);
+ Delta = ( Max_ - Min_);
+ V = Max_;
+
+ if(Max_ != 0.0)
+ {
+ S = 255.0*Delta/Max_;
+ }
+ else
+ {
+ S = 0.0;
+ H = -1;
+ return false;
+ }
+
+ if(rgba.R == Max_)
+ {
+ H = (rgba.G - rgba.B) / Delta;
+ }
+ else if(rgba.G == Max_)
+ {
+ H = 2.0 + (rgba.B - rgba.R) / Delta;
+ }
+ else
+ {
+ H = 4.0 + (rgba.R - rgba.G) / Delta;
+ }
+
+ H = H * 60;
+ if(H < 0.0)
+ {
+ H = H + 360.0;
+ }
+
+ Hue = (uint)H ; // Hue -> 0..360
+ Sat = (uint)S * 100 / 255; // Saturation -> 0..100 %
+ Val = (uint)V * 100 / 255; // Value - > 0..100 %
+
+ return true;
+}
+
+//-------------------------------------------------------------------------------------------------
+inline bool infHLS(const CRGBA & rgba1, const CRGBA & rgba2)
+{
+ uint h1, s1, v1, h2, s2, v2;
+ RGB2HSV(rgba1, h1, s1, v1);
+ RGB2HSV(rgba2, h2, s2, v2);
+
+ if(h1 != h2)
+ {
+ return (h1 < h2);
+ }
+ else if(s1 != s2)
+ {
+ return (s1 < s2);
+ }
+ else
+ {
+ return (v1 < v2);
+ }
+}
+
+//-------------------------------------------------------------------------------------------------
+void CScreenshotIslands::buildBackTextureHLS(const std::string & islandName, const CBitmap & islandBitmap)
+{
+ // load limit bitmap
+ CBitmap limBitmap;
+ std::string limFileName = _OutDirectory + "/" + islandName + "_limit.tga";
+
+ CIFile limFS(limFileName.c_str());
+ limBitmap.load(limFS);
+
+ list< CRGBA > limitPixels;
+
+ // search for colors of limit pixels
+ for(uint x=0; x sortedHLS;
+ list< CRGBA >::iterator itCol, itHLS;
+ bool inserted = false;
+ for(itCol=limitPixels.begin(); itCol!=limitPixels.end(); itCol++)
+ {
+ inserted = false;
+ for(itHLS=sortedHLS.begin(); itHLS!=sortedHLS.end(); ++itHLS)
+ {
+ if(infHLS(*itCol, *itHLS))
+ {
+ sortedHLS.insert(itHLS, *itCol);
+ inserted = true;
+ break;
+ }
+ }
+ if(inserted==false) sortedHLS.push_back(*itCol);
+ }
+
+
+ // keep more filled eighth of circle
+ itHLS = sortedHLS.begin();
+ uint h, s, v;
+ RGB2HSV(*itHLS, h, s, v);
+ list< CRGBA > currentList, maxList;
+
+ for(uint i=0; i<8; i++)
+ {
+ while(itHLS!=sortedHLS.end() && h maxList.size())
+ {
+ maxList.clear();
+ maxList = currentList;
+ currentList.clear();
+ }
+ }
+
+ vector< CRGBA > sortedColors(maxList.size());
+ uint colorsNb = 0;
+ CRGBA lastColor(0, 0, 0, 0);
+ CRGBA maxColor;
+ uint maxColorNb = 0;
+ uint currentColorNb = 0;
+ for(itHLS=maxList.begin(); itHLS!=maxList.end(); ++itHLS)
+ {
+ if(lastColor==*itHLS)
+ {
+ currentColorNb++;
+ }
+ else
+ {
+ currentColorNb = 1;
+ }
+
+ if(currentColorNb>maxColorNb)
+ {
+ maxColorNb = currentColorNb;
+ maxColor = *itHLS;
+ }
+
+ lastColor = *itHLS;
+
+ RGB2HSV(*itHLS, h, s, v);
+ if(v>25 && v<75 && s>25 && s<75)
+ {
+ sortedColors[colorsNb] = *itHLS;
+ colorsNb++;
+ }
+ }
+
+ if(colorsNb < 5)
+ {
+ colorsNb = 0;
+ for(itHLS=maxList.begin(); itHLS!=maxList.end(); ++itHLS)
+ {
+ sortedColors[colorsNb] = *itHLS;
+ colorsNb++;
+ }
+ }
+
+ sortedColors.resize(colorsNb);
+
+ _BackBitmap.resize(islandBitmap.getWidth(), islandBitmap.getHeight(), islandBitmap.PixelFormat);
+
+ if(sortedColors.size()!=0)
+ {
+ _BackColor = maxColor;
+
+ CRandom randomGenerator;
+
+ uint8 * backPixels = &(_BackBitmap.getPixels(0)[0]);
+
+ for(uint x=0; x<_BackBitmap.getWidth(); x++)
+ {
+ for(uint y=0; y<_BackBitmap.getHeight(); y++)
+ {
+ sint32 randomVal = randomGenerator.rand(colorsNb-1);
+ const CRGBA & color = sortedColors[randomVal];
+
+ *backPixels = (uint8) color.R;
+ *(backPixels + 1) = (uint8) color.G;
+ *(backPixels + 2) = (uint8) color.B;
+ *(backPixels + 3) = (uint8) 255;
+
+ backPixels = backPixels+4;
+ }
+ }
+ }
+
+ /*
+ //TEST
+ CBitmap HLSBitmap;
+ HLSBitmap.resize(640, sortedColors.size()*4, islandBitmap.PixelFormat);
+
+ uint8 * hlsPixels = &(HLSBitmap.getPixels(0)[0]);
+
+ for(uint i=0; i < sortedColors.size(); i++)
+ {
+ uint count = 0;
+ while(count<640*4)
+ {
+ *hlsPixels = (uint8) sortedColors[i].R;
+ *(hlsPixels + 1) = (uint8) sortedColors[i].G;
+ *(hlsPixels + 2) = (uint8) sortedColors[i].B;
+ *(hlsPixels + 3) = (uint8) sortedColors[i].A;
+
+ hlsPixels = hlsPixels+4;
+ count++;
+ }
+ }
+
+
+ string textureName = _OutDirectory + "/" + islandName + "_HLS2.tga";
+ COFile fsHLS(textureName.c_str());
+ HLSBitmap.writeTGA(fsHLS,32);
+ */
+}
+
+
+//--------------------------------------------------------------------------------------------------------------
+//--------------------------------------------------------------------------------------------------------------
+
+//-------------------------------------------------------------------------------------------------
+// methods CProximityMapBuffer
+//-------------------------------------------------------------------------------------------------
+
+void CProximityMapBuffer::load(const std::string& name)
+{
+ // load the AI collision map file
+ CWorldMap worldMap;
+ CIFile f(name);
+ f.serial(worldMap);
+
+ // lookup the map bounds
+ CMapPosition min, max;
+ worldMap.getBounds(min, max);
+
+ // calculate a handful of constants relating to the bounds of the image...
+ _ScanWidth = max.x()-min.x();
+ _ScanHeight = max.y()-min.y();
+ _XOffset= min.x();
+ _YOffset= (sint16)min.y();
+
+ // redimension buffer to correct size
+ _Buffer.resize(_ScanWidth*_ScanHeight);
+
+ // setup a position variable to mark the start point of each line
+ CMapPosition scanpos(min.x(),min.y());
+
+ // iterate over the scan area looking for points that are accessible
+ for (uint32 y=0; y<_ScanHeight; ++y, scanpos = scanpos.getStepN())
+ {
+ CMapPosition pos(scanpos);
+
+ // scan a line of the map
+ for (uint32 x=0; x<_ScanWidth; ++x, pos = pos.getStepE())
+ {
+ bool isAccessible= false;
+ // if the cell pointer is NULL it means that the 16x16 cell in question is inaccessible
+ if (worldMap.getRootCellCst(pos) != NULL)
+ {
+ // run through the surfaces in the cell looking for a match for this position (may be as many as 3 surfaces per cell max)
+ for (uint32 ns=0; ns<3; ++ns)
+ {
+ isAccessible |= worldMap.getSafeWorldPosition(pos, CSlot(ns)).isValid();
+ }
+ }
+ // setup the next pixel in the output buffers...
+ _Buffer[y*_ScanWidth+x]= (isAccessible? 0: (TBufferEntry)~0u);
+ }
+ }
+}
+
+//-------------------------------------------------------------------------------------------------
+void CProximityMapBuffer::calculateZones(TZones& zones)
+{
+ // clear out the result buffer before starting work
+ zones.clear();
+
+ // setup a container to hold the accessible points within this buffer
+ typedef std::set TAccessiblePoints;
+ TAccessiblePoints accessiblePoints;
+
+ // start by building the set of all accessible points
+ for (uint32 i=0;i<_Buffer.size();++i)
+ {
+ if (_Buffer[i]==0)
+ accessiblePoints.insert(i);
+ }
+
+ // while there are still points remaining in the set we must have another zone to process
+ while (!accessiblePoints.empty())
+ {
+ // append a new zone to the zones vector and get a refference to it
+ zones.push_back( CProximityZone(_ScanWidth,_ScanHeight,_XOffset,_YOffset) );
+ CProximityZone& theZone= zones.back();
+
+ // setup a todo list representing points that are part of the surface that we are dealing with
+ // that haven't yet been treated to check for neighbours, etc
+ std::vector todo;
+
+ // get hold of the first point in the accessilbe points set and push it onto the todo list
+ todo.push_back(*accessiblePoints.begin());
+ accessiblePoints.erase(todo.back());
+
+ // while we have more points to deal with ...
+ while (!todo.empty())
+ {
+ // pop the next point off the todo list
+ uint32 thePoint= todo.back();
+ todo.pop_back();
+
+ // add the point to the zone
+ theZone.add(thePoint);
+
+ // a little macro for the code to perform for each movement test...
+ #define TEST_MOVE(xoffs,yoffs)\
+ {\
+ TAccessiblePoints::iterator it= accessiblePoints.find(thePoint+xoffs+_ScanWidth*yoffs);\
+ if (it!=accessiblePoints.end())\
+ {\
+ todo.push_back(*it);\
+ accessiblePoints.erase(it);\
+ }\
+ }
+
+ // N, S, W, E moves
+ TEST_MOVE( 0, 1);
+ TEST_MOVE( 0,-1);
+ TEST_MOVE( 1, 0);
+ TEST_MOVE(-1, 0);
+
+ // NW, NE, WS, SE moves
+ TEST_MOVE( 1, 1);
+ TEST_MOVE(-1, 1);
+ TEST_MOVE( 1,-1);
+ TEST_MOVE(-1,-1);
+
+ #undef TEST_MOVE
+ }
+ }
+
+ nlinfo("Found %u zones",zones.size());
+}
+
+//-------------------------------------------------------------------------------------------------
+void CProximityMapBuffer::_prepareBufferForZoneProximityMap(const CProximityZone& zone,TBuffer& zoneBuffer,TOffsetsVector& accessiblePoints)
+{
+ // the length of runs that we consider too short to deal with...
+ const uint32 shortRunLength=5;
+
+ // redimention and initialise the zone buffer
+ uint32 zoneWidth= zone.getZoneWidth();
+ uint32 zoneHeight= zone.getZoneHeight();
+ zoneBuffer.clear();
+ zoneBuffer.resize(zoneWidth*zoneHeight,(TBufferEntry)~0u);
+
+ // setup the buffer's accessible points and prime vects[0] with the set of accessible points in the zone buffer
+ for (uint32 i=0;istartOffset && zoneBuffer[endOffset]!=0; endOffset-= zoneWidth) {}
+
+ for (uint32 offset=startOffset, marker=startOffset;offset<=endOffset;offset+=zoneWidth)
+ {
+ // see if this is an accessible position
+ if (zoneBuffer[offset]!=0)
+ {
+ zoneBuffer[offset]= InteriorValue;
+
+ if(offset-1>=startOffset && zoneBuffer[offset-1]==(TBufferEntry)~0u)
+ {
+ zoneBuffer[offset-1] = ValueBorder;
+ }
+ if(offset+1<=endOffset && zoneBuffer[offset+1]==(TBufferEntry)~0u)
+ {
+ zoneBuffer[offset+1] = ValueBorder;
+ }
+ }
+ }
+ }
+
+ // continue by dealing with all points that belong to a short run in the x direction
+ for (uint32 i=0;istartOffset && zoneBuffer[endOffset]!=0; --endOffset) {}
+
+ for (uint32 offset=startOffset, marker=startOffset;offset<=endOffset;++offset)
+ {
+ // see if this is an accessible position
+ if (zoneBuffer[offset]!=0)
+ {
+ zoneBuffer[offset]= InteriorValue;
+
+ if(offset-zoneWidth>0 && zoneBuffer[offset-zoneWidth]==(TBufferEntry)~0u)
+ {
+ zoneBuffer[offset-zoneWidth] = ValueBorder;
+ }
+ if(offset+zoneWidth BigValue)
+ || (zoneBuffer[val]==ValueBorder && dist > BigValue))
+ continue;
+
+ // write the new distance into this buffer entry
+ zoneBuffer[val]=dist;
+
+ // decompose into x and y in order to manage identification of neighbour cells correctly
+ uint32 x= val% zoneWidth;
+ uint32 y= val/ zoneWidth;
+
+ #define TEST_MOVE(xoffs,yoffs,newDist)\
+ {\
+ if (((uint32)(x+(xoffs)) BigValue) || (zoneBuffer[newVal]==ValueBorder && newDist > BigValue));\
+ if (zoneBuffer[newVal]>(newDist) && !isInterior)\
+ {\
+ zoneBuffer[newVal]=(newDist);\
+ vects[(newDist)&15].push_back(newVal);\
+ ++entriesToTreat;\
+ }\
+ }\
+ }
+
+ // N, S, W, E moves
+ TEST_MOVE( 0, 1,dist+5);
+ TEST_MOVE( 0,-1,dist+5);
+ TEST_MOVE( 1, 0,dist+5);
+ TEST_MOVE(-1, 0,dist+5);
+
+ // NW, NE, WS, SE moves
+ TEST_MOVE( 1, 1,dist+7);
+ TEST_MOVE(-1, 1,dist+7);
+ TEST_MOVE( 1,-1,dist+7);
+ TEST_MOVE(-1,-1,dist+7);
+
+ // NNW, NNE, SSW, SSE moves
+ TEST_MOVE( 1, 2,dist+11);
+ TEST_MOVE(-1, 2,dist+11);
+ TEST_MOVE( 1,-2,dist+11);
+ TEST_MOVE(-1,-2,dist+11);
+
+ // WNW, WSW, ENE, ESE moves
+ TEST_MOVE( 2, 1,dist+11);
+ TEST_MOVE(-2, 1,dist+11);
+ TEST_MOVE( 2,-1,dist+11);
+ TEST_MOVE(-2,-1,dist+11);
+
+ #undef TEST_MOVE
+ }
+
+ // clear out the vector
+ entriesToTreat-= vect.size();
+ vect.clear();
+ }
+}
+
+//-------------------------------------------------------------------------------------------------
+const TBuffer& CProximityMapBuffer::getBuffer() const
+{
+ return _Buffer;
+}
+
+//-------------------------------------------------------------------------------------------------
+uint32 CProximityMapBuffer::getScanHeight() const
+{
+ return _ScanHeight;
+}
+
+//-------------------------------------------------------------------------------------------------
+uint32 CProximityMapBuffer::getScanWidth() const
+{
+ return _ScanWidth;
+}
+
+//-----------------------------------------------------------------------------------------
+//-----------------------------------------------------------------------------------------
+
+//-------------------------------------------------------------------------------------------------
+// methods CProximityZone
+//-------------------------------------------------------------------------------------------------
+
+CProximityZone::CProximityZone(uint32 scanWidth,uint32 scanHeight,sint32 xOffset, sint32 yOffset)
+{
+ _ScanWidth = scanWidth;
+ _ScanHeight = scanHeight;
+ _XOffset = xOffset;
+ _YOffset = yOffset;
+
+ _MaxOffset = scanWidth * scanHeight -1;
+
+ _XMin = ~0u;
+ _YMin = ~0u;
+ _XMax = 0;
+ _YMax = 0;
+
+ _BorderPixels = 30;
+}
+
+//-------------------------------------------------------------------------------------------------
+bool CProximityZone::add(uint32 offset)
+{
+ // make sure the requested point is in the zone
+ if (offset>_MaxOffset)
+ return false;
+
+ // calculate the x and y coordinates of the point
+ uint32 y= offset/ _ScanWidth;
+ uint32 x= offset% _ScanWidth;
+
+ // update the bounding coordinates for this zone
+ if (x<_XMin) _XMin= x;
+ if (x>_XMax) _XMax= x;
+ if (y<_YMin) _YMin= y;
+ if (y>_YMax) _YMax= y;
+
+ // add the point to the vector of points
+ _Offsets.push_back(offset);
+ return true;
+}
+
+//-------------------------------------------------------------------------------------------------
+const CProximityZone::TOffsets& CProximityZone::getOffsets() const
+{
+ return _Offsets;
+}
+
+//-------------------------------------------------------------------------------------------------
+uint32 CProximityZone::getZoneWidth() const
+{
+ return getZoneXMax()- getZoneXMin() +1;
+}
+
+//-------------------------------------------------------------------------------------------------
+uint32 CProximityZone::getZoneHeight() const
+{
+ return getZoneYMax()- getZoneYMin() +1;
+}
+
+//-------------------------------------------------------------------------------------------------
+sint32 CProximityZone::getZoneXMin() const
+{
+ return _XMin-_BorderPixels;
+}
+
+//-------------------------------------------------------------------------------------------------
+sint32 CProximityZone::getZoneYMin() const
+{
+ return _YMin-_BorderPixels;
+}
+
+//-------------------------------------------------------------------------------------------------
+uint32 CProximityZone::getZoneXMax() const
+{
+ return _XMax+_BorderPixels;
+}
+
+//-------------------------------------------------------------------------------------------------
+uint32 CProximityZone::getZoneYMax() const
+{
+ return _YMax+_BorderPixels;
+}
+
+//-------------------------------------------------------------------------------------------------
+uint32 CProximityZone::getBoundXMin() const
+{
+ return _XMin+_XOffset-_BorderPixels;
+}
+
+//-------------------------------------------------------------------------------------------------
+uint32 CProximityZone::getBoundYMin() const
+{
+ return _YMin+_YOffset-_BorderPixels;
+}
+
+//-------------------------------------------------------------------------------------------------
+uint32 CProximityZone::getBoundXMax() const
+{
+ return _XMax+_XOffset+_BorderPixels;
+}
+
+//-------------------------------------------------------------------------------------------------
+uint32 CProximityZone::getBoundYMax() const
+{
+ return _YMax+_YOffset+_BorderPixels;
+}
+
+//-------------------------------------------------------------------------------------------------
+uint32 CProximityZone::remapOffset(uint32 bufferOffset) const
+{
+ // decompose input coordinates into x and y parts
+ uint32 bufferX= bufferOffset% _ScanWidth;
+ uint32 bufferY= bufferOffset/ _ScanWidth;
+
+ // remap the offset from a _Buffer-relative offset to a zone-relative offset
+ return bufferX-getZoneXMin()+ (bufferY-getZoneYMin())*getZoneWidth();
+}
+
+}
+
diff --git a/code/ryzom/tools/client/r2_islands_textures/screenshot_islands.h b/code/ryzom/tools/client/r2_islands_textures/screenshot_islands.h
new file mode 100644
index 000000000..7d47fa3e7
--- /dev/null
+++ b/code/ryzom/tools/client/r2_islands_textures/screenshot_islands.h
@@ -0,0 +1,241 @@
+// Ryzom - 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 CL_SCRRENSHOT_ISLANDS_H
+#define CL_SCRRENSHOT_ISLANDS_H
+
+// Misc
+#include "nel/misc/singleton.h"
+#include "nel/misc/vector_2f.h"
+#include "nel/misc/rgba.h"
+#include "nel/misc/bitmap.h"
+
+#include
+
+namespace NL3D
+{
+ class UScene;
+ class ULandscape;
+}
+
+namespace R2
+{
+ class CProximityZone;
+
+typedef uint16 TBufferEntry;
+typedef std::vector TBuffer;
+typedef std::vector TOffsetsVector;
+
+//-----------------------------------------------------------------------------
+// class CScreenshotIslands
+//-----------------------------------------------------------------------------
+struct CIslandData
+{
+ NLMISC::CVector2f EntryPoint;
+ NLMISC::CVector2f Max;
+ NLMISC::CVector2f Min;
+
+ CIslandData()
+ {
+ EntryPoint = NLMISC::CVector2f(0, 0);
+ Max = NLMISC::CVector2f(0, 0);
+ Min = NLMISC::CVector2f(0, 0);
+ }
+
+ CIslandData(float x, float y)
+ {
+ EntryPoint = NLMISC::CVector2f(x, y);
+ Max = NLMISC::CVector2f(0, 0);
+ Min = NLMISC::CVector2f(0, 0);
+ }
+};
+
+struct CContinentData
+{
+ std::string SmallBank;
+ std::string FarBank;
+ std::string IGFile;
+ std::string CoarseMeshMap;
+ NLMISC::CVector2f ZoneMin;
+ NLMISC::CVector2f ZoneMax;
+ std::list< std::string > Islands;
+ NLMISC::CRGBA Ambiant;
+ NLMISC::CRGBA Diffuse;
+
+ CContinentData() {}
+};
+
+typedef std::map< const std::string, CProximityZone> TIslandsData;
+typedef std::map< NLMISC::CVector2f, bool > TIslandsMap;
+typedef std::map< const std::string, CContinentData > TContinentsData;
+typedef std::map< std::string, std::list< NLMISC::CVector2f > > TIslandsBordersMap;
+
+class CScreenshotIslands : public NLMISC::CSingleton
+{
+
+public:
+
+ CScreenshotIslands();
+
+ void buildScreenshots();
+
+private:
+
+ void init();
+
+ void loadIslands();
+
+ void buildIslandsTextures();
+
+ void getBuffer(NL3D::UScene * scene, NL3D::ULandscape * landscape, NLMISC::CBitmap &btm);
+
+ bool getPosFromZoneName(const std::string &name, NLMISC::CVector2f &dest);
+
+ void writeProximityBufferToTgaFile(const std::string& fileName,const TBuffer& buffer,
+ uint32 scanWidth,uint32 scanHeight);
+
+ void processProximityBuffer(TBuffer& inputBuffer, uint32 lineLength, TBuffer& resultBuffer);
+
+ void buildBackTextureHLS(const std::string & islandName, const NLMISC::CBitmap & islandBitmap);
+
+ void searchIslandsBorders();
+
+ void attenuateIslandBorders(const std::string & islandName, NLMISC::CBitmap & islandBitmap, const CProximityZone & islandData);
+
+ TIslandsData _IslandsData;
+ TIslandsMap _IslandsMap;
+ TContinentsData _ContinentsData;
+ std::list< std::string > _SeasonSuffixes;
+ int _MeterPixelSize;
+ std::string _OutDirectory;
+ std::list< std::string > _TempFileNames;
+ TIslandsBordersMap _BorderIslands;
+ bool _Vegetation;
+ bool _InverseZTest;
+
+ NLMISC::CRGBA _BackColor;
+ NLMISC::CBitmap _BackBitmap;
+ std::string _CompleteIslandsFile;
+};
+
+
+
+
+
+
+class CProximityZone
+{
+public:
+ typedef std::vector TOffsets;
+
+ // ctor
+ // scanWidth and scanHeight define the dimentions of the buffer that this zone is being extracted from
+ // xOffset and yOffset are for re-mapping coordinates from buffer-relative to absolute ryzom world coordinates
+ CProximityZone(uint32 scanWidth=0,uint32 scanHeight=0,sint32 xOffset=0, sint32 yOffset=0);
+
+ // add an 'accessible position' to a zone (offset is y*scanWidth+x)
+ bool add(uint32 offset);
+
+ // zone dimention accessors (note that zone dimentions line up with 160x160 world zones)
+ // note that this means that the zone bounds may extend outside the scan area
+ uint32 getZoneWidth() const;
+ uint32 getZoneHeight() const;
+ sint32 getZoneXMin() const;
+ sint32 getZoneYMin() const;
+ uint32 getZoneXMax() const;
+ uint32 getZoneYMax() const;
+
+ // read accessors for the bounding limits that define the area occupied by the accessible points
+ uint32 getBoundXMin() const;
+ uint32 getBoundYMin() const;
+ uint32 getBoundXMax() const;
+ uint32 getBoundYMax() const;
+
+ // read accessor for the _Offsets vector
+ // this is a vector of offsets into the scan area. It needs to be remapped to zone offsets
+ // via the remapOffset() routine in order to be used to index into a zone buffer
+ const TOffsets& getOffsets() const;
+
+ // remap a scan buffer offset to a zone offset by decomposing into x and y parts and
+ // subtracting getZoneXMin() and getZoneYMin()
+ uint32 remapOffset(uint32 bufferOffset) const;
+
+private:
+ // parameters setup at construction time, giving info on the context that we're in
+ uint32 _ScanWidth;
+ uint32 _ScanHeight;
+ sint32 _XOffset;
+ sint32 _YOffset;
+ uint32 _MaxOffset;
+
+ // the vector of points that are part of this zone
+ TOffsets _Offsets;
+
+ // the min and max coords of the points that are part of this zone
+ uint32 _XMax;
+ uint32 _XMin;
+ uint32 _YMax;
+ uint32 _YMin;
+
+ // border add to bouding zone (pixels number)
+ int _BorderPixels;
+};
+
+//-------------------------------------------------------------------------------------------------
+// class CProximityMapBuffer
+//-------------------------------------------------------------------------------------------------
+
+class CProximityMapBuffer
+{
+public:
+ typedef std::vector TZones;
+
+ // load a cwmap2 file and setup this object from its contents
+ // the 'name' parameter is the full file name of the file to load with path and extension
+ void load(const std::string& name);
+
+ // scan the buffer to generate the set of non-connecting zones that it contains
+ void calculateZones(TZones& zones);
+
+ // generate the proximity map for a given zone
+ void generateZoneProximityMap(const CProximityZone& zone,TBuffer& zoneBuffer);
+
+ // read accessors...
+ const TBuffer& getBuffer() const;
+ uint32 getScanHeight() const;
+ uint32 getScanWidth() const;
+
+ // buffer coordinate to world coordinate offsets...
+ sint32 _XOffset;
+ sint32 _YOffset;
+
+private:
+ // private routine used by generateZoneProximityMap() to setup the zoneBuffer with the accessible points set
+ void _prepareBufferForZoneProximityMap(const CProximityZone& zone,TBuffer& zoneBuffer,TOffsetsVector& accessiblePoints);
+
+private:
+ // the width and heilght of the scan zone (ie the dimentions of the buffer)
+ uint32 _ScanWidth;
+ uint32 _ScanHeight;
+
+ // vector representing 2d array of points [_ScanHeight][_ScanWidth]
+ TBuffer _Buffer;
+};
+
+
+}
+
+#endif
\ No newline at end of file