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) 2014-2020 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
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/>.
23 #include "client_sheets/sky_sheet.h"
30 using namespace NLMISC
;
38 H_AUTO_DECL ( RZ_Client_Render_Sky
)
41 // *************************************************************************************************
49 _PlayListManager
= NULL
;
52 _AnimLengthInSeconds
= 3.f
;
53 _AmbientSunLight
= NULL
;
54 _DiffuseSunLight
= NULL
;
56 _WaterEnvMapCameraHeight
= 0.f
;
57 _WaterEnvMapAlpha
= 255;
60 // *************************************************************************************************
66 // *************************************************************************************************
73 _PlayListManager
->deletePlayList(_PlayList
);
76 if (_AnimationSet
&& _Driver
)
78 _Driver
->deleteAnimationSet(_AnimationSet
);
83 _Scene
->deletePlayListManager(_PlayListManager
);
85 _PlayListManager
= NULL
;
87 for(uint k
= 0; k
< _Bitmaps
.size(); ++k
)
94 if (_IG
) _IG
->removeFromScene(*_Scene
);
96 _Driver
->deleteScene(_Scene
);
102 // *************************************************************************************************
103 void CSky::init(UDriver
*drv
, const CSkySheet
&sheet
, bool forceFallbackVersion
/*= false*/, float numHourInDay
/*= 24.f*/, std::vector
<std::string
> *unsupportedObjects
/*= NULL*/)
108 // create a new scene for the sky
109 _Scene
= _Driver
->createScene(true);
110 _Scene
->setupTransparencySorting(99, 1); // only sort by priority (99 of them)
111 _AnimLengthInSeconds
= sheet
.AnimLengthInSeconds
;
112 // create animation set
113 if (!sheet
.AnimationName
.empty())
115 _PlayListManager
= _Scene
->createPlayListManager();
116 if (_PlayListManager
)
118 _AnimationSet
= _Driver
->createAnimationSet();
119 _PlayList
= _PlayListManager
->createPlayList(_AnimationSet
);
120 if (_AnimationSet
&& _PlayList
)
122 uint animationID
= _AnimationSet
->addAnimation(sheet
.AnimationName
.c_str(), sheet
.AnimationName
.c_str());
123 if (animationID
!= UAnimationSet::NotFound
)
125 _AnimationSet
->build();
126 _PlayList
->setAnimation(0, animationID
);
127 _PlayList
->setTimeOrigin(0, 0);
128 _PlayList
->setWrapMode(0, UPlayList::Repeat
);
132 // no animation loaded
133 _PlayListManager
->deletePlayList(_PlayList
);
134 _Scene
->deletePlayListManager(_PlayListManager
);
135 _Driver
->deleteAnimationSet(_AnimationSet
);
136 _PlayListManager
= NULL
;
138 _AnimationSet
= NULL
;
143 // load instance group of sky
144 _IG
= UInstanceGroup::createInstanceGroup(sheet
.InstanceGroupName
);
147 nlwarning("Couldn't load sky ig : %s", sheet
.InstanceGroupName
.c_str());
151 _IG
->addToScene(*_Scene
, drv
);
152 _Objects
.reserve(sheet
.Objects
.size());
153 // dump name of objects in the scene
154 //nlinfo("Sky scene objects : ");
155 for(uint k
= 0; k
< _IG
->getNumInstance(); ++k
)
157 //nlinfo(_IG->getInstanceName(k).c_str());
158 UInstance i
= _IG
->getInstance(k
); // hide all instances by default
159 if (!i
.empty()) i
.hide();
161 if (unsupportedObjects
) unsupportedObjects
->clear();
162 // map name of a bitmap to the actual bitmap (for reuse of bitmaps)
163 std::map
<std::string
, CBitmap
*> buildShareBitmapByName
;
165 for(uint k
= 0; k
< sheet
.Objects
.size(); ++k
)
168 instance
= _IG
->getByName(sheet
.Objects
[k
].Std
.ShapeName
);
169 // should main instance if driver supports its rendering
170 // hide all the instance at start
171 if (!instance
.empty() && !instance
.supportMaterialRendering(*drv
, forceFallbackVersion
))
173 if (unsupportedObjects
)
175 unsupportedObjects
->push_back(sheet
.Objects
[k
].Std
.ShapeName
);
179 for(uint l
= 0; l
< 2; ++l
)
181 UInstance fallbackInstance
= _IG
->getByName(sheet
.Objects
[k
].FallbackPass
[l
].ShapeName
);
182 if (!fallbackInstance
.empty())
184 fallbackInstance
.hide();
186 so
.init(sheet
.Objects
[k
].FallbackPass
[l
], fallbackInstance
, buildShareBitmapByName
, _Bitmaps
, sheet
.Objects
[k
].VisibleInMainScene
, sheet
.Objects
[k
].VisibleInEnvMap
);
187 _Objects
.push_back(so
);
190 _PlayList
->registerTransform(fallbackInstance
, (sheet
.Objects
[k
].FallbackPass
[l
].ShapeName
+ ".").c_str());
195 else if (!instance
.empty())
198 // uses main instance and hides fallback instances
200 so
.init(sheet
.Objects
[k
].Std
, instance
, buildShareBitmapByName
, _Bitmaps
, sheet
.Objects
[k
].VisibleInMainScene
, sheet
.Objects
[k
].VisibleInEnvMap
);
201 _Objects
.push_back(so
);
202 for(uint l
= 0; l
< 2; ++l
)
204 UInstance fallbackInstance
= _IG
->getByName(sheet
.Objects
[k
].FallbackPass
[l
].ShapeName
);
205 if (!fallbackInstance
.empty()) fallbackInstance
.hide();
209 _PlayList
->registerTransform(instance
, (sheet
.Objects
[k
].Std
.ShapeName
+ ".").c_str());
214 nlwarning("Object not found in scene : %s", sheet
.Objects
[k
].Std
.ShapeName
.c_str());
217 // get gradient that gives sun light color
219 _AmbientSunLight
= buildSharedBitmap(sheet
.AmbientSunLightBitmap
, buildShareBitmapByName
, _Bitmaps
, alreadyBuilt
);
220 _DiffuseSunLight
= buildSharedBitmap(sheet
.DiffuseSunLightBitmap
, buildShareBitmapByName
, _Bitmaps
, alreadyBuilt
);
222 _FogColor
= buildSharedBitmap(sheet
.FogColorBitmap
, buildShareBitmapByName
, _Bitmaps
, alreadyBuilt
);
224 _NumHourInDay
= numHourInDay
;
225 _WaterEnvMapCameraHeight
= sheet
.WaterEnvMapCameraHeight
;
226 _WaterEnvMapAlpha
= sheet
.WaterEnvMapAlpha
;
229 // *************************************************************************************************
230 uint
CSky::setup(const CClientDate
&date
, const CClientDate
&animationDate
, float weatherLevel
, CRGBA fogColor
, const NLMISC::CVector
&sunLightDir
, bool envMapScene
)
232 if (!_Scene
) return 0;
233 uint numVisibleObjects
= 0;
234 uint numObjects
= (uint
)_Objects
.size();
235 float dayPart
= date
.Hour
/ _NumHourInDay
;
236 clamp(dayPart
, 0.f
, 1.f
);
237 clamp(weatherLevel
, 0.f
, 1.f
);
238 for(uint k
= 0; k
< numObjects
; ++k
)
240 if (_Objects
[k
].setup(date
, animationDate
, _NumHourInDay
, weatherLevel
, fogColor
, envMapScene
)) ++ numVisibleObjects
;
243 if (_PlayListManager
)
245 double globalDate
= (double)date
.Hour
/ (double)_NumHourInDay
;
246 //nlinfo("global date = %f", (float) globalDate);
247 _PlayListManager
->animate(_AnimLengthInSeconds
* globalDate
);
249 // compute sunlight for the scene
250 if (_AmbientSunLight
)
252 _Scene
->setSunAmbient(_AmbientSunLight
->getColor(dayPart
, weatherLevel
, true, false));
256 _Scene
->setSunAmbient(CRGBA::White
);
258 if (_DiffuseSunLight
)
260 _Scene
->setSunDiffuse(_DiffuseSunLight
->getColor(dayPart
, weatherLevel
, true, false));
264 _Scene
->setSunDiffuse(CRGBA::White
);
266 _Scene
->setSunSpecular(CRGBA::Black
); // specular not useful for sky
267 _Scene
->setSunDirection(sunLightDir
);
268 return numVisibleObjects
;
271 // *************************************************************************************************
272 NLMISC::CRGBA
CSky::computeFogColor(const CClientDate
&date
, float weatherLevel
) const
274 if (!_FogColor
) return CRGBA::White
;
275 float dayPart
= date
.Hour
/ _NumHourInDay
;
276 clamp(dayPart
, 0.f
, 1.f
);
277 clamp(weatherLevel
, 0.f
, 1.f
);
278 return _FogColor
->getColor(dayPart
, weatherLevel
, true, false);
282 // *************************************************************************************************
283 CBitmap
*buildSharedBitmap(const std::string
&filename
,
284 std::map
<std::string
, CBitmap
*> &bitmapByName
,
285 std::vector
<CBitmap
*> &builtBitmaps
,
289 alreadyBuilt
= false;
290 if (filename
.empty()) return NULL
;
291 std::string lcBMFilename
= toLowerAscii(CFile::getFilenameWithoutExtension(filename
));
292 std::map
<std::string
, CBitmap
*>::iterator it
= bitmapByName
.find(lcBMFilename
);
293 if (it
!= bitmapByName
.end())
296 // bitmap already loaded so reuse it
302 std::string path
= CPath::lookup(filename
, false);
303 if (path
.empty()) return NULL
;
304 CUniquePtr
<CBitmap
> bm(new CBitmap
);
309 if (bm
->load(f
, 0) == 0) return NULL
;
310 builtBitmaps
.push_back(bm
.release());
311 bitmapByName
[lcBMFilename
] = builtBitmaps
.back();
312 // dump bitmap fisrt line
313 return builtBitmaps
.back();
315 catch(const EStream
&)