Resolve "Toggle Free Look with Hotkey"
[ryzomcore.git] / ryzom / client / src / fog_map.cpp
blob5c0a34e771e1b93fa5babdd9ebad24219ff3ef46
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
6 //
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "stdpch.h"
25 #include "nel/misc/file.h"
26 #include "zone_util.h"
27 #include "fog_map.h"
28 #include "client_cfg.h"
29 #include "nel/3d/u_driver.h"
30 #include <algorithm>
32 #include "interface_v3/interface_manager.h"
33 #include "interface_v3/group_map.h"
34 #include "client_cfg.h"
35 #include "global.h"
37 using namespace NLMISC;
39 H_AUTO_DECL(RZ_FogMap)
41 //===================================================================
42 void CFogState::setupInDriver(NL3D::UDriver &drv)
44 H_AUTO_USE(RZ_FogMap)
45 // Are we in wireframe ?
46 bool filled = (drv.getPolygonMode() == NL3D::UDriver::Filled);
48 if (FogEnabled && filled && ClientCfg.Fog)
50 drv.enableFog(true);
51 drv.setupFog(FogStartDist, FogEndDist, FogColor);
53 else
55 drv.enableFog(false);
59 //===================================================================
60 CFogMap::CFogMap() : _MinCoord(0, 0), _MaxCoord(0, 0)
64 //===================================================================
65 void CFogMap::worldPosToMapPos(float inX, float inY, float &outX, float &outY) const
67 H_AUTO_USE(RZ_FogMap)
68 outX = _MinCoord.x != _MaxCoord.x ? (inX - _MinCoord.x) / (_MaxCoord.x - _MinCoord.x) : _MinCoord.x;
69 outY = _MinCoord.y != _MaxCoord.y ? 1.f - (inY - _MinCoord.y) / (_MaxCoord.y - _MinCoord.y) : 1.f - _MinCoord.y;
72 //===================================================================
73 void CFogMap::getFogParams(float startDist, float endDist, float x, float y, float dayNight, float duskRatio, CLightCycleManager::TLightState lightState, CFogState &result)
75 H_AUTO_USE(RZ_FogMap)
76 NLMISC::clamp(dayNight, 0.f, 1.f);
78 float mx, my;
79 worldPosToMapPos(x, y, mx, my);
80 // tmp patch for ring island : lookup dist / depth ahead of current pos -> in matis cliffs, avoids to have too thick
81 // fog when looking inside the lands
82 float ddMx = x;
83 float ddMy = y;
84 CInterfaceManager *im = CInterfaceManager::getInstance();
85 CGroupMap *gm = dynamic_cast<CGroupMap *>(CWidgetManager::getInstance()->getElementFromId("ui:interface:map:content:map_content:actual_map"));
86 if (gm && gm->isIsland())
88 CVector front = MainCam.getMatrix().getJ();
89 ddMx += ClientCfg.FogDistAndDepthLookupBias * front.x;
90 ddMy += ClientCfg.FogDistAndDepthLookupBias * front.y;
93 worldPosToMapPos(ddMx, ddMy, ddMx, ddMy);
95 NLMISC::CRGBAF col0;
96 NLMISC::CRGBAF col1;
97 float blendFactor;
98 switch(lightState)
100 case CLightCycleManager::DayToNight:
101 // See which transition it is : day->dusk or dusk->night ?
102 if (dayNight < duskRatio)
104 col0 = getMapValueFromMapCoord(CFogMapBuild::Day, mx, my, CRGBAF(1.f, 1.f, 1.f));
105 col1 = getMapValueFromMapCoord(CFogMapBuild::Dusk, mx, my, CRGBAF(1.f, 1.f, 1.f));
106 blendFactor = duskRatio != 0.f ? dayNight / duskRatio : 0.f;
108 else
110 col0 = getMapValueFromMapCoord(CFogMapBuild::Dusk, mx, my, CRGBAF(1.f, 1.f, 1.f));
111 col1 = getMapValueFromMapCoord(CFogMapBuild::Night, mx, my, CRGBAF(1.f, 1.f, 1.f));
112 blendFactor = duskRatio != 1.f ? (dayNight - duskRatio) / (1.f - duskRatio) : 0.f;
114 break;
115 default:
116 col0 = getMapValueFromMapCoord(CFogMapBuild::Day, mx, my, CRGBAF(1.f, 1.f, 1.f));
117 col1 = getMapValueFromMapCoord(CFogMapBuild::Night, mx, my, CRGBAF(1.f, 1.f, 1.f));
118 blendFactor = dayNight;
119 break;
121 NLMISC::CRGBAF fogColor = col1 * blendFactor + (1.f - blendFactor) * col0;
123 result.FogColor = fogColor;
125 NLMISC::CRGBAF distanceCol = getMapValueFromMapCoord(CFogMapBuild::Distance, ddMx, ddMy, CRGBAF(0.f, 0.f, 0.f));
126 result.FogStartDist = (distanceCol.R * (endDist - startDist)) + startDist;
128 NLMISC::CRGBAF depthCol = getMapValueFromMapCoord(CFogMapBuild::Depth,ddMx, ddMy, CRGBAF(1.f, 1.f, 1.f));
129 result.FogEndDist = std::min(result.FogStartDist + depthCol.R * (endDist - startDist), endDist);
130 result.FogEnabled = true;
134 //===================================================================
135 NLMISC::CRGBAF CFogMap::getMapValue(TMapType type, float x, float y, NLMISC::CRGBAF defaultValue) const
137 H_AUTO_USE(RZ_FogMap)
138 nlassert(type < CFogMapBuild::NumMap);
139 if (_Map[type].getWidth() == 0) return defaultValue;
140 float mx, my;
141 worldPosToMapPos(x, y, mx, my);
142 return _Map[type].getColor(mx, my);
145 //===================================================================
146 NLMISC::CRGBAF CFogMap::getMapValueFromMapCoord(TMapType type, float x, float y, NLMISC::CRGBAF defaultValue) const
148 H_AUTO_USE(RZ_FogMap)
149 nlassert(type < CFogMapBuild::NumMap);
150 if (_Map[type].getWidth() == 0) return defaultValue;
151 return _Map[type].getColor(x, y);
154 //===================================================================
155 void CFogMap::release()
157 H_AUTO_USE(RZ_FogMap)
158 for(uint k = 0; k < CFogMapBuild::NumMap; ++k)
160 _Map[k].reset();
162 _MinCoord.set(0.f, 0.f);
163 _MaxCoord.set(0.f, 0.f);
166 //===================================================================
167 bool CFogMap::init(const CFogMapBuild &desc)
169 H_AUTO_USE(RZ_FogMap)
170 release();
171 CVector2f minCoord, maxCoord;
172 if (!getPosFromZoneName(desc.ZoneMin, minCoord) || !getPosFromZoneName(desc.ZoneMax, maxCoord))
174 release();
175 return false;
177 return init(desc, minCoord, maxCoord);
180 //===================================================================
181 bool CFogMap::init(const CFogMapBuild &desc, const NLMISC::CVector &minCoord, const NLMISC::CVector &maxCoord)
183 _MinCoord = minCoord;
184 _MaxCoord = maxCoord;
185 if (_MinCoord.x > _MaxCoord.x) std::swap(_MinCoord.x, _MaxCoord.x);
186 if (_MinCoord.y > _MaxCoord.y) std::swap(_MinCoord.y, _MaxCoord.y);
187 _MaxCoord.set(_MaxCoord.x + 160.f, _MaxCoord.y + 160.f);
188 for(uint k = 0; k < CFogMapBuild::NumMap; ++k)
190 _Map[k].resize(0, 0);
191 if (!desc.Map[k].empty())
193 load(_Map[k], desc.Map[k]);
196 // Exception for dusk map : it has been added later, so if the filename is empty, we use the day and night map to get the dusk map
197 if (desc.Map[CFogMapBuild::Dusk].empty())
199 if (_Map[CFogMapBuild::Day].getWidth() != 0 &&
200 _Map[CFogMapBuild::Day].getHeight() != 0 &&
201 _Map[CFogMapBuild::Night].getWidth() != 0 &&
202 _Map[CFogMapBuild::Night].getHeight() != 0)
204 _Map[CFogMapBuild::Dusk].blend(_Map[CFogMapBuild::Day], _Map[CFogMapBuild::Night], 127);
207 return true;
210 //===================================================================
211 void CFogMap::load(NLMISC::CBitmap &bm, const std::string &filename)
213 H_AUTO_USE(RZ_FogMap)
214 std::string lookupName = NLMISC::CPath::lookup(filename, false, true);
215 if (lookupName.empty())
217 nlwarning("couldn't find %s", filename.c_str());
218 return;
220 NLMISC::CIFile inputFile;
221 inputFile.open(lookupName);
224 if (!bm.load(inputFile))
226 nlwarning ("Error while loading fog map %s (bitmap size is multiple of 4?)", lookupName.c_str());
227 inputFile.close();
230 catch(const NLMISC::EStream &e)
232 nlwarning(e.what());
233 inputFile.close();