Skyscraper 2.0
sky.cpp
Go to the documentation of this file.
1/*
2 Skyscraper 2.0 - Sky System
3 Copyright (C)2004-2024 Ryan Thoryk
4 https://www.skyscrapersim.net
5 https://sourceforge.net/projects/skyscraper/
6 Contact - ryan@skyscrapersim.net
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21*/
22
23#include <OgreRoot.h>
24#include "globals.h"
25#include "sbs.h"
26#include "profiler.h"
27#include "vm.h"
28#include "hal.h"
29#include "enginecontext.h"
30#include "sky.h"
31
32using namespace SBS;
33
34namespace Skyscraper {
35
36//Sky System
37
39{
40 this->vm = vm;
41 SkyMult = 0;
42 mCaelumSystem = 0;
43 new_location = false;
44 new_time = false;
45 latitude = 0.0;
46 longitude = 0.0;
47 datetime = 0.0;
48 sky_error = 0;
49}
50
52{
53 //delete Caelum
54 if (mCaelumSystem)
55 delete mCaelumSystem;
56}
57
59{
60 //unload Caelum sky system
61
62 new_time = false;
63
64 if (mCaelumSystem)
65 {
66 Caelum::CaelumPlugin* ptr = Caelum::CaelumPlugin::getSingletonPtr();
67 mCaelumSystem->clear();
68 mCaelumSystem->detachAllViewports();
69 delete mCaelumSystem;
70 mCaelumSystem = 0;
71 Ogre::ResourceGroupManager::getSingleton().destroyResourceGroup("Caelum");
72 Caelum::CaelumPlugin::getSingleton().shutdown();
73 delete ptr;
74 }
75}
76
78{
79 //create sky system
80
81 //load Caelum plugin
82 if (vm->GetHAL()->GetConfigBool(vm->GetHAL()->configfile, "Skyscraper.Frontend.Caelum", true) == true)
83 {
84 try
85 {
86 new Caelum::CaelumPlugin();
87 Caelum::CaelumPlugin::getSingleton().initialise();
88 }
89 catch (Ogre::Exception &e)
90 {
91 if (e.getDescription() != "!msSingleton failed. There can be only one singleton")
92 ReportFatalError("Error initializing Caelum plugin:\nDetails: " + e.getDescription());
93 return;
94 }
95 }
96
97 /*(if (sky_error == true)
98 {
99 engine->GetSystem()->CreateSky();
100 return;
101 }*/
102
103 bool sky_result = true;
104 if (vm->GetHAL()->GetConfigBool(vm->GetHAL()->configfile, "Skyscraper.Frontend.Caelum", true) == true)
105 sky_result = InitSky(engine);
106
107 //create old sky if Caelum is turned off, or failed to initialize
108 if (sky_result == false)
109 engine->GetSystem()->CreateSky();
110}
111
113{
114 //initialize sky
115
116 if (!engine)
117 return false;
118
119 if (vm->GetHAL()->Renderer == "Direct3D11")
120 return true;
121
122 //ensure graphics card and render system are capable of Caelum's shaders
123 if (vm->GetHAL()->Renderer == "Direct3D9")
124 {
125 //on DirectX, Caelum requires a card capable of 3.0 shader levels, which would be
126 //an ATI Radeon HD 2000, nVidia Geforce 6, Intel G965 or newer
127 //Intel cards: http://www.intel.com/support/graphics/sb/cs-014257.htm
128 Ogre::RenderSystemCapabilities::ShaderProfiles profiles = vm->GetHAL()->mRoot->getRenderSystem()->getCapabilities()->getSupportedShaderProfiles();
129
130 //for general sky, require both DirectX pixel and vertex shaders 2.0
131 if (profiles.find("ps_2_0") == profiles.end() ||
132 profiles.find("vs_2_0") == profiles.end())
133 return ReportFatalError("Error initializing Caelum: 2.0 shaders not supported");
134
135 //for clouds, require either DirectX pixel shaders 3.0 or nVidia fragment shaders 4.0
136 if (profiles.find("ps_3_0") == profiles.end() &&
137 profiles.find("fp40") == profiles.end())
138 return ReportFatalError("Error initializing Caelum: 3.0 fragment shaders not supported");
139
140 //for clouds, require either DirectX vetex shaders 3.0 or nVidia vertex shaders 4.0
141 if (profiles.find("vs_3_0") == profiles.end() &&
142 profiles.find("vp40") == profiles.end())
143 return ReportFatalError("Error initializing Caelum: 3.0 vertex shaders not supported");
144 }
145
146 if (vm->GetHAL()->Renderer == "OpenGL")
147 {
148 //on OpenGL, Caelum requires hardware support for shaders (OpenGL 2.0 or newer)
149 Ogre::RenderSystemCapabilities::ShaderProfiles profiles = vm->GetHAL()->mRoot->getRenderSystem()->getCapabilities()->getSupportedShaderProfiles();
150
151 //require OpenGL ARB fragment programs
152 if (profiles.find("arbfp1") == profiles.end())
153 return ReportFatalError("Error initializing Caelum: fragment programs not supported");
154
155 //require OpenGL ARB vertex programs
156 if (profiles.find("arbvp1") == profiles.end())
157 return ReportFatalError("Error initializing Caelum: vertex programs not supported");
158 }
159
160 //load Caelum resources
161 try
162 {
163 Ogre::ResourceGroupManager::getSingleton().addResourceLocation("data/caelum", "FileSystem", "Caelum", false);
164 Ogre::ResourceGroupManager::getSingleton().initialiseResourceGroup("Caelum");
165
166 if (!mCaelumSystem)
167 mCaelumSystem = new Caelum::CaelumSystem(vm->GetHAL()->mRoot, vm->GetHAL()->GetSceneManager(), Caelum::CaelumSystem::CAELUM_COMPONENTS_NONE);
168 Caelum::CaelumPlugin::getSingleton().loadCaelumSystemFromScript(mCaelumSystem, SkyName);
169 }
170 catch (Ogre::Exception &e)
171 {
172#if OGRE_PLATFORM != OGRE_PLATFORM_APPLE //ignore Caelum errors on Mac, due to a Cg error (Cg is not available on ARM CPUs, and is not bundled with the Mac version)
173 ReportFatalError("Error initializing Caelum:\nDetails: " + e.getDescription());
174#endif
175 sky_error = true;
176 }
177 catch (...)
178 {
179 ReportFatalError("Error initializing Caelum");
180 sky_error = true;
181 }
182
183 if (!mCaelumSystem)
184 {
185 sky_error = true;
186 return false;
187 }
188
189 //attach caelum to running viewport
190 try
191 {
192 for (size_t i = 0; i < vm->GetHAL()->mViewports.size(); i++)
193 {
194 mCaelumSystem->attachViewport(vm->GetHAL()->mViewports[i]);
195 }
196 mCaelumSystem->setAutoNotifyCameraChanged(false);
197 mCaelumSystem->setSceneFogDensityMultiplier(vm->GetHAL()->GetConfigFloat(vm->GetHAL()->configfile, "Skyscraper.Frontend.Caelum.FogMultiplier", 0.1) / 1000);
198 if (vm->GetHAL()->GetConfigBool(vm->GetHAL()->configfile, "Skyscraper.Frontend.Caelum.EnableFog", true) == false)
199 mCaelumSystem->setManageSceneFog(Ogre::FOG_NONE);
200 mCaelumSystem->setManageAmbientLight(vm->GetHAL()->GetConfigBool(vm->GetHAL()->configfile, "Skyscraper.Frontend.Caelum.ModifyAmbient", false));
201
202 //fix sky rotation
203 Quaternion rot(Degree(180.0), Vector3::UNIT_Y);
204 mCaelumSystem->getCaelumGroundNode()->setOrientation(rot);
205 mCaelumSystem->getCaelumCameraNode()->setOrientation(rot);
206
207 //have sky use SBS scaling factor
208 Real scale = 1 / engine->GetSystem()->UnitScale;
209 mCaelumSystem->getCaelumGroundNode()->setScale(scale, scale, scale);
210 mCaelumSystem->getCaelumCameraNode()->setScale(scale, scale, scale);
211 }
212 catch (Ogre::Exception &e)
213 {
214 ReportFatalError("Error setting Caelum parameters:\nDetails: " + e.getDescription());
215 sky_error = true;
216 }
217 catch (...)
218 {
219 ReportFatalError("Error setting Caelum parameters");
220 sky_error = true;
221 }
222
223 //set sky time multiplier if not already set
224 if (SkyMult == 0)
225 SkyMult = mCaelumSystem->getTimeScale();
226
227 //set location if specified
228 if (new_location == true)
229 {
230 mCaelumSystem->setObserverLatitude(Degree(latitude));
231 mCaelumSystem->setObserverLongitude(Degree(longitude));
232 new_location = false;
233 }
234
235 //use system time if specified
236 if (vm->GetHAL()->GetConfigBool(vm->GetHAL()->configfile, "Skyscraper.Frontend.Caelum.UseSystemTime", false) == true && new_time == false)
238
239 //set date/time if specified
240 if (new_time == true)
241 {
242 mCaelumSystem->setJulianDay(datetime);
243 new_time = false;
244 }
245
246 return true;
247}
248
250{
251 //update sky
252
253 SBS_PROFILE_MAIN("Sky");
254
255 if (mCaelumSystem)
256 {
257 for (size_t i = 0; i < vm->GetHAL()->mCameras.size(); i++)
258 {
259 mCaelumSystem->notifyCameraChanged(vm->GetHAL()->mCameras[i]);
260 }
261 mCaelumSystem->setTimeScale(SkyMult);
262 mCaelumSystem->updateSubcomponents(Real(vm->GetActiveEngine()->GetSystem()->GetElapsedTime()) / 1000);
263 }
264}
265
266void SkySystem::SetLocation(Real latitude, Real longitude)
267{
268 this->latitude = latitude;
269 this->longitude = longitude;
270 new_location = true;
271}
272
274{
275 //set date and time to current time in UTC
276
277 //get current time
278 time_t now = time(0);
279
280 //convert time to GMT
281 tm* gmtm = gmtime(&now);
282 if (gmtm == NULL)
283 return;
284
285 //convert time to Julian and set it
286 double julian = Caelum::Astronomy::getJulianDayFromGregorianDateTime(gmtm->tm_year + 1900, gmtm->tm_mon + 1, gmtm->tm_mday, gmtm->tm_hour, gmtm->tm_min, gmtm->tm_sec);
287 SetDateTime(julian);
288}
289
290void SkySystem::SetDateTime(double julian_date_time)
291{
292 datetime = julian_date_time;
293 new_time = true;
294
295 if (mCaelumSystem)
296 mCaelumSystem->setJulianDay(datetime);
297}
298
299void SkySystem::GetTime(int &hour, int &minute, int &second)
300{
301 hour = -1;
302 minute = -1;
303 second = -1.0;
304
305 if (!mCaelumSystem)
306 return;
307
308 Caelum::LongReal julian = mCaelumSystem->getJulianDay(), sec;
309 int year, month, day;
310 Caelum::Astronomy::getGregorianDateTimeFromJulianDay(julian, year, month, day, hour, minute, sec);
311 second = (int)sec;
312}
313
314void SkySystem::GetDate(int &year, int &month, int &day)
315{
316 Caelum::LongReal julian = mCaelumSystem->getJulianDay(), second;
317 int hour, minute;
318 Caelum::Astronomy::getGregorianDateTimeFromJulianDay(julian, year, month, day, hour, minute, second);
319 second = (int)second;
320}
321
322void SkySystem::EnableSky(bool value)
323{
324 //enable or disable sky system
325
326 //enable/disable old skybox system in engine 0
327 if (vm->GetEngine(0))
328 vm->GetEngine(0)->GetSystem()->EnableSkybox(value);
329
330 //enable/disable Caelum sky system
331 if (mCaelumSystem)
332 {
333 mCaelumSystem->getCaelumGroundNode()->setVisible(value);
334 mCaelumSystem->getCaelumCameraNode()->setVisible(value);
335 }
336}
337
338void SkySystem::Report(const std::string &message)
339{
340 vm->GetHAL()->Report(message, "sky:");
341}
342
343bool SkySystem::ReportError(const std::string &message)
344{
345 return vm->GetHAL()->ReportError(message, "sky:");
346}
347
348bool SkySystem::ReportFatalError(const std::string &message)
349{
350 return vm->GetHAL()->ReportFatalError(message, "sky:");
351}
352
353}
Real UnitScale
Definition sbs.h:185
void CreateSky()
Definition sbs.cpp:1510
unsigned long GetElapsedTime()
Definition sbs.cpp:3296
void EnableSkybox(bool value)
Definition sbs.cpp:1498
bool ReportFatalError(const std::string &message, const std::string &prompt)
Definition hal.cpp:256
std::string Renderer
Definition hal.h:88
Ogre::SceneManager * GetSceneManager()
Definition hal.cpp:895
std::vector< Ogre::Viewport * > mViewports
Definition hal.h:93
Real GetConfigFloat(Ogre::ConfigFile *file, const std::string &key, Real default_value)
Definition hal.cpp:307
bool GetConfigBool(Ogre::ConfigFile *file, const std::string &key, bool default_value)
Definition hal.cpp:299
std::vector< Ogre::Camera * > mCameras
Definition hal.h:90
void Report(const std::string &message, const std::string &prompt)
Definition hal.cpp:219
bool ReportError(const std::string &message, const std::string &prompt)
Definition hal.cpp:237
Ogre::Root * mRoot
Definition hal.h:91
Ogre::ConfigFile * configfile
Definition hal.h:97
bool ReportError(const std::string &message)
Definition sky.cpp:343
void GetTime(int &hour, int &minute, int &second)
Definition sky.cpp:299
Caelum::CaelumSystem * mCaelumSystem
Definition sky.h:59
void SetDateTime(double julian_date_time)
Definition sky.cpp:290
void SetDateTimeNow()
Definition sky.cpp:273
bool InitSky(EngineContext *engine)
Definition sky.cpp:112
void CreateSky(EngineContext *engine)
Definition sky.cpp:77
double datetime
Definition sky.h:68
void GetDate(int &year, int &month, int &day)
Definition sky.cpp:314
bool ReportFatalError(const std::string &message)
Definition sky.cpp:348
void EnableSky(bool value)
Definition sky.cpp:322
SkySystem(VM *vm)
Definition sky.cpp:38
void Report(const std::string &message)
Definition sky.cpp:338
void SetLocation(Real latitude, Real longitude)
Definition sky.cpp:266
std::string SkyName
Definition sky.h:55
HAL * GetHAL()
Definition vm.cpp:128
EngineContext * GetActiveEngine()
Definition vm.h:81
EngineContext * GetEngine(int number)
Definition vm.cpp:432
Ogre::Real Real
Definition globals.h:57
Ogre::Quaternion Quaternion
Definition globals.h:60
Ogre::Degree Degree
Definition globals.h:61
#define SBS_PROFILE_MAIN(name)
Definition profiler.h:132