1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2013 Laszlo KIS-ADAM (dfighter) <dfighter1985@gmail.com>
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/>.
25 #include "nel/misc/file.h"
26 #include "zone_util.h"
28 #include "client_cfg.h"
29 #include "nel/3d/u_driver.h"
32 #include "interface_v3/interface_manager.h"
33 #include "interface_v3/group_map.h"
34 #include "client_cfg.h"
37 using namespace NLMISC
;
39 H_AUTO_DECL(RZ_FogMap
)
41 //===================================================================
42 void CFogState::setupInDriver(NL3D::UDriver
&drv
)
45 // Are we in wireframe ?
46 bool filled
= (drv
.getPolygonMode() == NL3D::UDriver::Filled
);
48 if (FogEnabled
&& filled
&& ClientCfg
.Fog
)
51 drv
.setupFog(FogStartDist
, FogEndDist
, FogColor
);
59 //===================================================================
60 CFogMap::CFogMap() : _MinCoord(0, 0), _MaxCoord(0, 0)
64 //===================================================================
65 void CFogMap::worldPosToMapPos(float inX
, float inY
, float &outX
, float &outY
) const
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
)
76 NLMISC::clamp(dayNight
, 0.f
, 1.f
);
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
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
);
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
;
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
;
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
;
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
;
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
)
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
)
171 CVector2f minCoord
, maxCoord
;
172 if (!getPosFromZoneName(desc
.ZoneMin
, minCoord
) || !getPosFromZoneName(desc
.ZoneMax
, maxCoord
))
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);
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());
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());
230 catch(const NLMISC::EStream
&e
)