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 bool use_caelum = vm->GetHAL()->GetConfigBool(vm->GetHAL()->configfile, "Skyscraper.Frontend.Caelum", true);
82 bool sky_result = true;
83
84 if (use_caelum == true)
85 {
86 //load Caelum plugin
87 try
88 {
89 new Caelum::CaelumPlugin();
90 Caelum::CaelumPlugin::getSingleton().initialise();
91 }
92 catch (Ogre::Exception &e)
93 {
94 if (e.getDescription() != "!msSingleton failed. There can be only one singleton")
95 ReportFatalError("Error initializing Caelum plugin:\nDetails: " + e.getDescription());
96 return;
97 }
98 sky_result = InitSky(engine);
99 }
100
101 //create old sky if Caelum is turned off, or failed to initialize
102 if (sky_result == false || use_caelum == false)
103 engine->GetSystem()->CreateSky();
104}
105
107{
108 //initialize sky
109
110 if (!engine)
111 return false;
112
113 if (vm->GetHAL()->Renderer == "Direct3D11")
114 return true;
115
116 //ensure graphics card and render system are capable of Caelum's shaders
117 if (vm->GetHAL()->Renderer == "Direct3D9")
118 {
119 //on DirectX, Caelum requires a card capable of 3.0 shader levels, which would be
120 //an ATI Radeon HD 2000, nVidia Geforce 6, Intel G965 or newer
121 //Intel cards: http://www.intel.com/support/graphics/sb/cs-014257.htm
122 Ogre::RenderSystemCapabilities::ShaderProfiles profiles = vm->GetHAL()->mRoot->getRenderSystem()->getCapabilities()->getSupportedShaderProfiles();
123
124 //for general sky, require both DirectX pixel and vertex shaders 2.0
125 if (profiles.find("ps_2_0") == profiles.end() ||
126 profiles.find("vs_2_0") == profiles.end())
127 return ReportFatalError("Error initializing Caelum: 2.0 shaders not supported");
128
129 //for clouds, require either DirectX pixel shaders 3.0 or nVidia fragment shaders 4.0
130 if (profiles.find("ps_3_0") == profiles.end() &&
131 profiles.find("fp40") == profiles.end())
132 return ReportFatalError("Error initializing Caelum: 3.0 fragment shaders not supported");
133
134 //for clouds, require either DirectX vetex shaders 3.0 or nVidia vertex shaders 4.0
135 if (profiles.find("vs_3_0") == profiles.end() &&
136 profiles.find("vp40") == profiles.end())
137 return ReportFatalError("Error initializing Caelum: 3.0 vertex shaders not supported");
138 }
139
140 if (vm->GetHAL()->Renderer == "OpenGL")
141 {
142 //on OpenGL, Caelum requires hardware support for shaders (OpenGL 2.0 or newer)
143 Ogre::RenderSystemCapabilities::ShaderProfiles profiles = vm->GetHAL()->mRoot->getRenderSystem()->getCapabilities()->getSupportedShaderProfiles();
144
145 //require OpenGL ARB fragment programs
146 if (profiles.find("arbfp1") == profiles.end())
147 return ReportFatalError("Error initializing Caelum: fragment programs not supported");
148
149 //require OpenGL ARB vertex programs
150 if (profiles.find("arbvp1") == profiles.end())
151 return ReportFatalError("Error initializing Caelum: vertex programs not supported");
152 }
153
154 //load Caelum resources
155 try
156 {
157 Ogre::ResourceGroupManager::getSingleton().addResourceLocation("data/caelum", "FileSystem", "Caelum", false);
158 Ogre::ResourceGroupManager::getSingleton().initialiseResourceGroup("Caelum");
159
160 if (!mCaelumSystem)
161 mCaelumSystem = new Caelum::CaelumSystem(vm->GetHAL()->mRoot, vm->GetHAL()->GetSceneManager(), Caelum::CaelumSystem::CAELUM_COMPONENTS_NONE);
162 Caelum::CaelumPlugin::getSingleton().loadCaelumSystemFromScript(mCaelumSystem, SkyName);
163 }
164 catch (Ogre::Exception &e)
165 {
166#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)
167 ReportFatalError("Error initializing Caelum:\nDetails: " + e.getDescription());
168#endif
169 sky_error = true;
170 }
171 catch (...)
172 {
173 ReportFatalError("Error initializing Caelum");
174 sky_error = true;
175 }
176
177 if (!mCaelumSystem)
178 {
179 sky_error = true;
180 return false;
181 }
182
183 //attach caelum to running viewport
184 try
185 {
186 for (size_t i = 0; i < vm->GetHAL()->mViewports.size(); i++)
187 {
188 mCaelumSystem->attachViewport(vm->GetHAL()->mViewports[i]);
189 }
190 mCaelumSystem->setAutoNotifyCameraChanged(false);
191 mCaelumSystem->setSceneFogDensityMultiplier(vm->GetHAL()->GetConfigFloat(vm->GetHAL()->configfile, "Skyscraper.Frontend.Caelum.FogMultiplier", 0.1) / 1000);
192 if (vm->GetHAL()->GetConfigBool(vm->GetHAL()->configfile, "Skyscraper.Frontend.Caelum.EnableFog", true) == false)
193 mCaelumSystem->setManageSceneFog(Ogre::FOG_NONE);
194 mCaelumSystem->setManageAmbientLight(vm->GetHAL()->GetConfigBool(vm->GetHAL()->configfile, "Skyscraper.Frontend.Caelum.ModifyAmbient", false));
195
196 //fix sky rotation
197 Quaternion rot(Degree(180.0), Vector3::UNIT_Y);
198 mCaelumSystem->getCaelumGroundNode()->setOrientation(rot);
199 mCaelumSystem->getCaelumCameraNode()->setOrientation(rot);
200
201 //have sky use SBS scaling factor
202 Real scale = 1 / engine->GetSystem()->UnitScale;
203 mCaelumSystem->getCaelumGroundNode()->setScale(scale, scale, scale);
204 mCaelumSystem->getCaelumCameraNode()->setScale(scale, scale, scale);
205 }
206 catch (Ogre::Exception &e)
207 {
208 ReportFatalError("Error setting Caelum parameters:\nDetails: " + e.getDescription());
209 sky_error = true;
210 }
211 catch (...)
212 {
213 ReportFatalError("Error setting Caelum parameters");
214 sky_error = true;
215 }
216
217 //set sky time multiplier if not already set
218 if (SkyMult == 0)
219 SkyMult = mCaelumSystem->getTimeScale();
220
221 //set location if specified
222 if (new_location == true)
223 {
224 mCaelumSystem->setObserverLatitude(Degree(latitude));
225 mCaelumSystem->setObserverLongitude(Degree(longitude));
226 new_location = false;
227 }
228
229 //use system time if specified
230 if (vm->GetHAL()->GetConfigBool(vm->GetHAL()->configfile, "Skyscraper.Frontend.Caelum.UseSystemTime", false) == true && new_time == false)
232
233 //set date/time if specified
234 if (new_time == true)
235 {
236 mCaelumSystem->setJulianDay(datetime);
237 new_time = false;
238 }
239
240 return true;
241}
242
244{
245 //update sky
246
247 SBS_PROFILE_MAIN("Sky");
248
249 if (mCaelumSystem)
250 {
251 for (size_t i = 0; i < vm->GetHAL()->mCameras.size(); i++)
252 {
253 mCaelumSystem->notifyCameraChanged(vm->GetHAL()->mCameras[i]);
254 }
255 mCaelumSystem->setTimeScale(SkyMult);
256 mCaelumSystem->updateSubcomponents(Real(vm->GetActiveEngine()->GetSystem()->GetElapsedTime()) / 1000);
257 }
258}
259
260void SkySystem::SetLocation(Real latitude, Real longitude)
261{
262 this->latitude = latitude;
263 this->longitude = longitude;
264 new_location = true;
265}
266
268{
269 //set date and time to current time in UTC
270
271 //get current time
272 time_t now = time(0);
273
274 //convert time to GMT
275 tm* gmtm = gmtime(&now);
276 if (gmtm == NULL)
277 return;
278
279 //convert time to Julian and set it
280 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);
281 SetDateTime(julian);
282}
283
284void SkySystem::SetDateTime(double julian_date_time)
285{
286 datetime = julian_date_time;
287 new_time = true;
288
289 if (mCaelumSystem)
290 mCaelumSystem->setJulianDay(datetime);
291}
292
293void SkySystem::GetTime(int &hour, int &minute, int &second)
294{
295 hour = -1;
296 minute = -1;
297 second = -1.0;
298
299 if (!mCaelumSystem)
300 return;
301
302 Caelum::LongReal julian = mCaelumSystem->getJulianDay(), sec;
303 int year, month, day;
304 Caelum::Astronomy::getGregorianDateTimeFromJulianDay(julian, year, month, day, hour, minute, sec);
305 second = (int)sec;
306}
307
308void SkySystem::GetDate(int &year, int &month, int &day)
309{
310 Caelum::LongReal julian = mCaelumSystem->getJulianDay(), second;
311 int hour, minute;
312 Caelum::Astronomy::getGregorianDateTimeFromJulianDay(julian, year, month, day, hour, minute, second);
313 second = (int)second;
314}
315
316void SkySystem::EnableSky(bool value)
317{
318 //enable or disable sky system
319
320 //enable/disable old skybox system in engine 0
321 if (vm->GetEngine(0))
322 vm->GetEngine(0)->GetSystem()->EnableSkybox(value);
323
324 //enable/disable Caelum sky system
325 if (mCaelumSystem)
326 {
327 mCaelumSystem->getCaelumGroundNode()->setVisible(value);
328 mCaelumSystem->getCaelumCameraNode()->setVisible(value);
329 }
330}
331
332void SkySystem::Report(const std::string &message)
333{
334 vm->GetHAL()->Report(message, "sky:");
335}
336
337bool SkySystem::ReportError(const std::string &message)
338{
339 return vm->GetHAL()->ReportError(message, "sky:");
340}
341
342bool SkySystem::ReportFatalError(const std::string &message)
343{
344 return vm->GetHAL()->ReportFatalError(message, "sky:");
345}
346
347}
Real UnitScale
Definition sbs.h:185
void CreateSky()
Definition sbs.cpp:1553
unsigned long GetElapsedTime()
Definition sbs.cpp:3326
void EnableSkybox(bool value)
Definition sbs.cpp:1541
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:893
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:337
void GetTime(int &hour, int &minute, int &second)
Definition sky.cpp:293
Caelum::CaelumSystem * mCaelumSystem
Definition sky.h:59
void SetDateTime(double julian_date_time)
Definition sky.cpp:284
void SetDateTimeNow()
Definition sky.cpp:267
bool InitSky(EngineContext *engine)
Definition sky.cpp:106
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:308
bool ReportFatalError(const std::string &message)
Definition sky.cpp:342
void EnableSky(bool value)
Definition sky.cpp:316
SkySystem(VM *vm)
Definition sky.cpp:38
void Report(const std::string &message)
Definition sky.cpp:332
void SetLocation(Real latitude, Real longitude)
Definition sky.cpp:260
std::string SkyName
Definition sky.h:55
HAL * GetHAL()
Definition vm.cpp:134
EngineContext * GetActiveEngine()
Definition vm.h:81
EngineContext * GetEngine(int number)
Definition vm.cpp:438
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