SO3Engine
SO3Sky.cpp
Go to the documentation of this file.
1/*
2-----------------------------------------------------------------------------
3This source file is part of OpenSpace3D
4For the latest info, see http://www.openspace3d.com
5
6Copyright (c) 2012 I-maginer
7
8This program is free software; you can redistribute it and/or modify it under
9the terms of the GNU Lesser General Public License as published by the Free Software
10Foundation; either version 2 of the License, or (at your option) any later
11version.
12
13This program is distributed in the hope that it will be useful, but WITHOUT
14ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
16
17You should have received a copy of the GNU Lesser General Public License along with
18this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19Place - Suite 330, Boston, MA 02111-1307, USA, or go to
20http://www.gnu.org/copyleft/lesser.txt
21
22-----------------------------------------------------------------------------
23*/
24
32#include "SO3Renderer/SO3Root.h"
40
41namespace SO3
42{
43
44SSky::SSky(SEnvironment* parent, const std::string& skyName) : SEnvironmentComponent(parent, skyName)
45{
46 // Init member pointers
47 parentScene = parent->GetScene();
48 skyxManager = 0;
49
50 // Store default params
51 cloudsAnimationSpeed = 1.0f;
52 cloudsCeilingHeight = 100.0f;
53 cachedMoonTextureName = "SkyX_Moon.png";
54 skyxOptions.RayleighMultiplier = 0.003075f;
55 skyxOptions.MieMultiplier = 0.00125f;
56 skyxOptions.InnerRadius = 5.92f;
57 skyxOptions.OuterRadius = 6.3311f;
58 skyxOptions.SunIntensity = 15;
59 skyLightingMode = SO3_SKY_LDR;
60 skyLightningEnable = false;
61
62 // Create our custom moon & sun positions provider
63 astronomicalModel = new SSkyAstronomicalModel(this);
64
65 // Create sky subcomponents
66
67 const Ogre::RenderSystemCapabilities* caps = Ogre::Root::getSingleton().getRenderSystem()->getCapabilities();
68 if (caps && caps->hasCapability(Ogre::RSC_TEXTURE_3D))
69 volumetricClouds = new CloudVolumetric(this);
70 else
71 volumetricClouds = 0;
72
73 layeredClouds = new CloudLayered(this);
74}
75
76SSky::SSky() : SEnvironmentComponent(0, "")
77{
78 // Forbiden (private)
79}
80
82{
83 // Call the "SComponent::Clean" parent class function, must be done here cause it call some SSky virtual functions.
84 Cleanup();
85
86 // Delete skyx
87 SO3_SAFE_DELETE(skyxManager);
88
89 // Delete Sky object.
90 SO3_SAFE_DELETE(layeredClouds);
91 SO3_SAFE_DELETE(volumetricClouds);
92 SO3_SAFE_DELETE(astronomicalModel);
93}
94
95void SSky::SetEnableImpl(const bool& enableComponent)
96{
97 if(enableComponent)
98 {
99 if(!skyxManager)
100 {
101 // Create Skyx object
102 skyxManager = new SkyX::SkyX(parentScene->GetOgreScenePointer(), astronomicalModel);
103
104 // Initialise
105 // skyxManager->getMeshManager()->setUnderHorizonParams();
106 skyxManager->setTimeMultiplier(parentEnvironment->GetTimeSpeedFactor() / SO3_SKY_DEFAULT_TIME_MULTIPLIER);
107 skyxManager->create();
108 skyxManager->getMeshManager()->getEntity()->setVisibilityFlags(SO3_VISIBILITY_FLAG_INVISIBLE_ENVIRONMENT|SO3_VISIBILITY_MASK_VISIBLE_WATER_RTT);
109
110 // Re-apply all parameters
111 skyxManager->getAtmosphereManager()->setOptions(skyxOptions);
112 SetHDREnable(skyLightingMode == SO3_SKY_HDR);
113
114 // To avoid sky clipping
115 skyxManager->getMeshManager()->setRadiusMultiplier(0.80f);
116
117 //TODO add as SKY parameter
118 skyxManager->getMoonManager()->setMoonSize(0.120f);
119
120 // Register all the viewports
122 SEnvironmentComponent::ViewportList::iterator iViewport = viewportList.begin();
123 while(iViewport != viewportList.end())
124 {
125 bool hasStereo = (*iViewport)->IsStereoViewportRegistered();
126 if (hasStereo)
127 (*iViewport)->UnregisterStereoViewport();
128
129 RegisterViewportImpl(*iViewport);
130
131 if (hasStereo)
132 (*iViewport)->RegisterStereoViewport();
133
134 iViewport++;
135 }
136
137 if (volumetricClouds)
138 volumetricClouds->SetEnableImpl(volumetricClouds->GetEnabled());
139
140 layeredClouds->SetEnableImpl(layeredClouds->GetEnabled());
141 }
142 }
143 else
144 {
145 if(skyxManager)
146 {
147 // Unregister all the viewports
149 SEnvironmentComponent::ViewportList::iterator iViewport = viewportList.begin();
150 while(iViewport != viewportList.end())
151 {
152 bool hasStereo = (*iViewport)->IsStereoViewportRegistered();
153 if (hasStereo)
154 (*iViewport)->UnregisterStereoViewport();
155
156 UnregisterViewportImpl(*iViewport);
157
158 if (hasStereo)
159 (*iViewport)->RegisterStereoViewport();
160
161 iViewport++;
162 }
163
164 if (volumetricClouds)
165 volumetricClouds->SetEnableImpl(false);
166
167 layeredClouds->SetEnableImpl(false);
168
169 // Delete skyx
170 skyxManager->remove();
171 SO3_SAFE_DELETE(skyxManager);
172 }
173 }
174}
175
177{
178 if(skyxManager)
179 {
180 Ogre::Viewport* ogreViewport = viewport->GetOgreViewPortPointer();
181 ogreViewport->getTarget()->removeListener(skyxManager);
182 ogreViewport->getTarget()->addListener(skyxManager);
184 }
185}
186
188{
189 if(skyxManager)
190 {
191 Ogre::Viewport* ogreViewport = viewport->GetOgreViewPortPointer();
192 if (volumetricClouds)
193 volumetricClouds->UnregisterCamera(ogreViewport->getCamera());
194
195 ogreViewport->getTarget()->removeListener(skyxManager);
197 }
198}
199
200void SSky::AddViewport(Ogre::Viewport* viewport)
201{
202 if(skyxManager)
203 {
204 viewport->getTarget()->removeListener(skyxManager);
205 viewport->getTarget()->addListener(skyxManager);
207 }
208}
209
210void SSky::RemoveViewport(Ogre::Viewport* viewport)
211{
212 if(skyxManager)
213 {
214 if (volumetricClouds)
215 volumetricClouds->UnregisterCamera(viewport->getCamera());
216
217 viewport->getTarget()->removeListener(skyxManager);
219 }
220}
221
222void SSky::UnregisterCameraImpl(Ogre::Camera* cam)
223{
224 if(skyxManager && volumetricClouds)
225 {
226 volumetricClouds->UnregisterCamera(cam);
227 }
228}
229
230SkyX::SkyX* SSky::GetSkyX()
231{
232 return skyxManager;
233}
234
236{
237}
238
239void SSky::Update(const Ogre::Real& updateTime)
240{
241 if(skyxManager)
242 {
243 // Update layer clouds
244 layeredClouds->Update(updateTime);
245
246 // Update layer clouds
247 if (volumetricClouds)
248 volumetricClouds->Update(updateTime);
249
250 std::string moonNewTextureName = parentEnvironment->GetMoon()->GetTextureName();
251 if(cachedMoonTextureName != moonNewTextureName)
252 {
253 try
254 {
255 Ogre::MaterialPtr moonMaterial = static_cast<Ogre::MaterialPtr> (Ogre::MaterialManager::getSingleton().getByName(skyxManager->getGPUManager()->getMoonMaterialName()));
256 if(moonMaterial)
257 {
258 Ogre::Material::Techniques techList = moonMaterial->getSupportedTechniques();
259 if(techList.size() > 0)
260 {
261 Ogre::Technique* ogreTechnique = techList[0];
262 Ogre::Pass* ogrePass = ogreTechnique->getPasses()[0];
263 if(ogrePass != 0)
264 {
265 Ogre::TextureUnitState* ogreTextureUnit = ogrePass->getTextureUnitState(0);
266 if(ogreTextureUnit != 0)
267 {
268 ogreTextureUnit->setTextureName(moonNewTextureName);
269 cachedMoonTextureName = moonNewTextureName;
270 }
271 }
272 }
273 }
274 }
275 catch(const Ogre::Exception&)
276 {
277 // Do nothing
278 }
279 }
280
281 // Pause the sky rendering?
283 skyxManager->setTimeMultiplier(0.0f);
284 else
285 {
286 // Big Hack!!!
287 float speed = parentEnvironment->GetTimeSpeedFactor();
288 if((speed > -1) && (speed < 1))
289 {
290 // Not true, but avoid the layered cloud animation to stop. The stars rotation will be un-noticiable.
291 skyxManager->setTimeMultiplier(1.0f / SO3_SKY_DEFAULT_TIME_MULTIPLIER);
292 }
293 else
294 {
295 skyxManager->setTimeMultiplier(parentEnvironment->GetTimeSpeedFactor() / SO3_SKY_DEFAULT_TIME_MULTIPLIER);
296 }
297 }
298
299 // Update skyx
300 skyxManager->update(updateTime);
301 }
302}
303
305{
306 SSky::SkyComponent* component = 0;
307 switch(componentType)
308 {
310 component = layeredClouds;
311 break;
313 component = volumetricClouds;
314 break;
315 default:
316 OGRE_EXCEPT(Ogre::Exception::ERR_INVALIDPARAMS, "Invalid sky component type requested!", "SSky::GetComponent");
317 break;
318 }
319 return component;
320}
321
323{
324 return volumetricClouds;
325}
326
328{
329 return layeredClouds;
330}
331
333{
334 return cloudsAnimationSpeed;
335}
336
337void SSky::SetAnimationSpeed(const float& animationSpeed)
338{
339 cloudsAnimationSpeed = animationSpeed;
340}
341
343{
344 return cloudsCeilingHeight;
345}
346
347void SSky::SetCloudCeiling(const float& newCloudCeiling)
348{
349 float oldCloudCeiling = cloudsCeilingHeight;
350 std::vector<int> layerIndexes = layeredClouds->GetLayerIndexes();
351 std::vector<int>::iterator iLayerIndexes = layerIndexes.begin();
352 while(iLayerIndexes != layerIndexes.end())
353 {
354 float layerHeightAboveCeiling = layeredClouds->GetHeightFromCloudCeiling(*iLayerIndexes);
355 cloudsCeilingHeight = newCloudCeiling;
356 layeredClouds->SetHeightFromCloudCeiling((*iLayerIndexes), layerHeightAboveCeiling);
357 cloudsCeilingHeight = oldCloudCeiling;
358 iLayerIndexes++;
359 }
360 cloudsCeilingHeight = newCloudCeiling;
361}
362
364{
365 return (skyLightingMode == SO3_SKY_HDR);
366}
367
368void SSky::SetHDREnable(const bool& enable)
369{
370 if(enable)
371 {
372 skyLightingMode = SO3_SKY_HDR;
373 if(skyxManager)
374 skyxManager->setLightingMode(SkyX::SkyX::LM_HDR);
375 }
376 else
377 {
378 skyLightingMode = SO3_SKY_LDR;
379 if(skyxManager)
380 skyxManager->setLightingMode(SkyX::SkyX::LM_LDR);
381 }
382}
383
385{
386 return skyLightningEnable;
387}
388
389void SSky::SetLightningEnable(const bool& enable)
390{
391 if (skyxManager && volumetricClouds && GetComponent(SSky::SO3_SKY_COMPONENT_VOLUMETRIC_CLOUD)->GetEnabled())
392 {
393 SkyX::VCloudsManager* skyxVolumetricCloudsManager = skyxManager->getVCloudsManager();
394 SkyX::VClouds::VClouds* skyxVolumetricClouds = skyxVolumetricCloudsManager->getVClouds();
395
396 skyxVolumetricClouds->getLightningManager()->setEnabled(enable);
397 skyxVolumetricClouds->getLightningManager()->setAverageLightningApparitionTime(0.5f);
398 skyxVolumetricClouds->getLightningManager()->setLightningColor(Ogre::Vector3(1,0.976,0.92));
399 skyxVolumetricClouds->getLightningManager()->setLightningTimeMultiplier(2);
400 }
401
402 skyLightningEnable = enable;
403}
404
405void SSky::AddLightning(const Ogre::Vector3 from, const Ogre::Vector3 dir, const Ogre::Real length)
406{
407 if (skyxManager && volumetricClouds && GetComponent(SSky::SO3_SKY_COMPONENT_VOLUMETRIC_CLOUD)->GetEnabled() && skyLightningEnable)
408 {
409 SkyX::VCloudsManager* skyxVolumetricCloudsManager = skyxManager->getVCloudsManager();
410 SkyX::VClouds::VClouds* skyxVolumetricClouds = skyxVolumetricCloudsManager->getVClouds();
411
412 skyxVolumetricClouds->getLightningManager()->addLightning(from, dir, length);
413 }
414}
415
416
417/**********************************/
418/* Base cloud class. */
419/* Do not use directly, must be */
420/* derivated. */
421/**********************************/
422SSky::SkyComponent::SkyComponent(SSky* parentSkyInstance, const SSky::SkyComponentType& component) : componentType(component)
423{
424 parentSky = parentSkyInstance;
425 skyComponentEnable = false;
426}
427
428SSky::SkyComponent::SkyComponent() : componentType(SSky::SO3_SKY_COMPONENT_NONE)
429{
430 // Forbiden constructor (private)
431}
432
434{
435 parentSky = 0;
436}
437
439{
440 return skyComponentEnable;
441}
442
443void SSky::SkyComponent::SetEnableImpl(const bool& enableComponent)
444{
445}
446
448{
449}
450
451void SSky::SkyComponent::SetEnabled(const bool& enable)
452{
453 SetEnableImpl(enable);
454 skyComponentEnable = enable;
455}
456
458{
459 return componentType;
460}
461
462/**********************************/
463/* Basic layer cloud */
464/**********************************/
465SSky::CloudLayered::CloudLayered(SSky* parentSkyInstance) : SSky::SkyComponent(parentSkyInstance, SSky::SO3_SKY_COMPONENT_LAYERER_CLOUD)
466{
467}
468
469SSky::CloudLayered::CloudLayered() : SSky::SkyComponent(0, SSky::SO3_SKY_COMPONENT_NONE)
470{
471 // Forbiden constructor (private)
472}
473
475{
476 RemoveAllLayers();
477}
478
479void SSky::CloudLayered::SetEnableImpl(const bool& enableComponent)
480{
481 SkyX::SkyX* skyxManager = parentSky->GetSkyX();
482 if(skyxManager)
483 {
484 if(enableComponent)
485 {
486 CloudLayerOptionsMap::iterator iCloudLayerOptionsMap = cloudLayerOptionsMap.begin();
487 while(iCloudLayerOptionsMap != cloudLayerOptionsMap.end())
488 {
489 // Apply layer options.
490 ApplyLayerOptions(iCloudLayerOptionsMap->first);
491 iCloudLayerOptionsMap++;
492 }
493 }
494 else
495 {
496 // Remove any remaining CloudLayer instances.
497 skyxManager->getCloudsManager()->removeAll();
498
499 cloudLayerMap.clear();
500 }
501 }
502}
503
504void SSky::CloudLayered::Update(const Ogre::Real& updateTime)
505{
506 if(GetEnabled())
507 {
508 CloudLayerOptionsMap::iterator iCloudLayerOptionsMap = cloudLayerOptionsMap.begin();
509 while(iCloudLayerOptionsMap!=cloudLayerOptionsMap.end())
510 {
511 SkyX::CloudLayer::Options* skyxCloudLayerOptions = iCloudLayerOptionsMap->second;
512 skyxCloudLayerOptions->WindDirection = Ogre::Vector2(parentSky->GetEnvironment()->GetWindDirection().x, -parentSky->GetEnvironment()->GetWindDirection().y);
513
514 // Auto-updated params
515 float environmentHumidity = parentSky->GetEnvironment()->GetHumidity();
516 skyxCloudLayerOptions->DetailAttenuation = 2.0f - (0.020f * environmentHumidity);
517
518 // Do not animate while environment is paused
519 if(parentSky->GetEnvironment()->GetPaused())
520 skyxCloudLayerOptions->TimeMultiplier = 0.0f;
521 else
522 {
523 float speed = parentSky->GetEnvironment()->GetTimeSpeedFactor();
524 if((speed > -1) && (speed < 1))
525 {
526 if(speed < 0)
527 skyxCloudLayerOptions->TimeMultiplier = -SO3_SKY_DEFAULT_TIME_MULTIPLIER * parentSky->GetEnvironment()->GetWindSpeed() * 0.1f;
528 else
529 skyxCloudLayerOptions->TimeMultiplier = SO3_SKY_DEFAULT_TIME_MULTIPLIER * parentSky->GetEnvironment()->GetWindSpeed() * 0.1f;
530 }
531 else
532 {
533 if(speed < 0)
534 skyxCloudLayerOptions->TimeMultiplier = -SO3_SKY_DEFAULT_TIME_MULTIPLIER / speed * parentSky->GetEnvironment()->GetWindSpeed() * 0.1f;
535 else
536 skyxCloudLayerOptions->TimeMultiplier = SO3_SKY_DEFAULT_TIME_MULTIPLIER / speed * parentSky->GetEnvironment()->GetWindSpeed() * 0.1f;
537 }
538 }
539
540 // Apply layer options.
541 ApplyLayerOptions(iCloudLayerOptionsMap->first);
542 iCloudLayerOptionsMap++;
543 }
544 }
545}
546
547unsigned int SSky::CloudLayered::AddLayer(const Ogre::Real& heightFromCloudCeiling, const Ogre::Real& scale, const Ogre::Real& distanceAttenuation, const Ogre::Real& detailAttenuation, const Ogre::Real& heightVolume, const Ogre::Real& volumetricDisplacement)
548{
549 // Find the lower index
550 unsigned int lowerIndex = 1;
551 if(!cloudLayerOptionsMap.empty())
552 {
553 bool lowerIndexFound = false;
554 while(!lowerIndexFound)
555 {
556 if(cloudLayerOptionsMap.find(lowerIndex) != cloudLayerOptionsMap.end())
557 lowerIndex++;
558 else
559 lowerIndexFound = true;
560 }
561 }
562
563 // Initialise layer options
564 SkyX::CloudLayer::Options* skyxCloudLayerOptions = new SkyX::CloudLayer::Options();
565 skyxCloudLayerOptions->Height = parentSky->GetCloudCeiling() + heightFromCloudCeiling;
566 skyxCloudLayerOptions->Scale = scale;
567 skyxCloudLayerOptions->DistanceAttenuation = distanceAttenuation;
568 skyxCloudLayerOptions->DetailAttenuation = detailAttenuation;
569 skyxCloudLayerOptions->HeightVolume = heightVolume;
570 skyxCloudLayerOptions->VolumetricDisplacement = volumetricDisplacement;
571 skyxCloudLayerOptions->WindDirection = Ogre::Vector2(parentSky->GetEnvironment()->GetWindDirection().x, -parentSky->GetEnvironment()->GetWindDirection().y);
572 float speed = parentSky->GetEnvironment()->GetTimeSpeedFactor();
573 if((speed > -1) && (speed < 1))
574 {
575 if(speed < 0)
576 skyxCloudLayerOptions->TimeMultiplier = -SO3_SKY_DEFAULT_TIME_MULTIPLIER * parentSky->GetEnvironment()->GetWindSpeed() * 0.1f;
577 else
578 skyxCloudLayerOptions->TimeMultiplier = SO3_SKY_DEFAULT_TIME_MULTIPLIER * parentSky->GetEnvironment()->GetWindSpeed() * 0.1f;
579 }
580 else
581 {
582 if(speed < 0)
583 skyxCloudLayerOptions->TimeMultiplier = -SO3_SKY_DEFAULT_TIME_MULTIPLIER / speed * parentSky->GetEnvironment()->GetWindSpeed() * 0.1f;
584 else
585 skyxCloudLayerOptions->TimeMultiplier = SO3_SKY_DEFAULT_TIME_MULTIPLIER / speed * parentSky->GetEnvironment()->GetWindSpeed() * 0.1f;
586 }
587
588 cloudLayerOptionsMap.insert(CloudLayerOptionsMap::value_type(lowerIndex, skyxCloudLayerOptions));
589 ApplyLayerOptions(lowerIndex);
590
591 // Return the index of this layer
592 return lowerIndex;
593}
594
595void SSky::CloudLayered::ApplyLayerOptions(const unsigned int& index)
596{
597 SkyX::SkyX* skyxManager = parentSky->GetSkyX();
598 if(skyxManager != 0)
599 {
600 CloudLayerOptionsMap::iterator iLayerOptions = cloudLayerOptionsMap.find(index);
601 CloudLayerMap::iterator iLayer = cloudLayerMap.find(index);
602 if(iLayer == cloudLayerMap.end())
603 {
604 // The layer does not exist in skyx, so create it
605 SkyX::CloudLayer* skyxCloudLayer = skyxManager->getCloudsManager()->add(*(iLayerOptions->second));
606
607 // Store the layer index
608 cloudLayerMap.insert(CloudLayerMap::value_type(index, skyxCloudLayer));
609 }
610 else
611 {
612 // Apply option on the existing layer.
613 iLayer->second->setOptions(*(iLayerOptions->second));
614 }
615 }
616 else
617 {
618 // Remove any remaining CloudLayer instances.
619 cloudLayerMap.clear();
620 }
621}
622
623void SSky::CloudLayered::RemoveLayer(const unsigned int& index)
624{
625 CloudLayerOptionsMap::iterator iSearchedLayerOptions = cloudLayerOptionsMap.find(index);
626 if(iSearchedLayerOptions == cloudLayerOptionsMap.end())
627 OGRE_EXCEPT(Ogre::Exception::ERR_ITEM_NOT_FOUND, "Cannot remove cloud layer, there's no layer associated with this index!", "SSky::CloudLayered::RemoveLayer");
628
629 // Destroy from skyx cloud manager
630 SkyX::SkyX* skyxManager = parentSky->GetSkyX();
631 CloudLayerMap::iterator iSearchedLayer = cloudLayerMap.find(index);
632 if(iSearchedLayer != cloudLayerMap.end())
633 {
634 if(skyxManager)
635 skyxManager->getCloudsManager()->remove(iSearchedLayer->second);
636
637 // Erase even if not present in skyx, because it means that we have an invalid pointer stored.
638 cloudLayerMap.erase(iSearchedLayer);
639 }
640
641 // Remove from the list
642 cloudLayerOptionsMap.erase(iSearchedLayerOptions);
643}
644
646{
647 SkyX::SkyX* skyxManager = parentSky->GetSkyX();
648 if(skyxManager)
649 skyxManager->getCloudsManager()->removeAll();
650
651 cloudLayerMap.clear();
652 cloudLayerOptionsMap.clear();
653}
654
656{
657 std::vector<int> layerIndexes;
658 CloudLayerOptionsMap::iterator iLayerOptions = cloudLayerOptionsMap.begin();
659 while(iLayerOptions != cloudLayerOptionsMap.end())
660 {
661 layerIndexes.push_back(iLayerOptions->first);
662 iLayerOptions++;
663 }
664 return layerIndexes;
665}
666
667SkyX::CloudLayer::Options* SSky::CloudLayered::GetLayerOptions(const unsigned int& index)
668{
669 CloudLayerOptionsMap::iterator iSearchedLayerOption = cloudLayerOptionsMap.find(index);
670 if(iSearchedLayerOption == cloudLayerOptionsMap.end())
671 OGRE_EXCEPT(Ogre::Exception::ERR_ITEM_NOT_FOUND, "Cannot find cloud layer, there's no layer associated with this index!", "SSky::CloudLayered::GetLayerOptions");
672
673 return iSearchedLayerOption->second;
674}
675
676void SSky::CloudLayered::SetParameters(const unsigned int& index, const float& heightFromCloudCeiling, const float& scale, const float& attenuationDistance, const float& attenuationDetail, const float& heightVolume, const float& volumetricDisplacement)
677{
678 SkyX::CloudLayer::Options* skyxCloudLayerOptions = GetLayerOptions(index);
679 skyxCloudLayerOptions->Height = parentSky->GetCloudCeiling() + heightFromCloudCeiling;
680 skyxCloudLayerOptions->Scale = scale;
681 skyxCloudLayerOptions->DistanceAttenuation = attenuationDistance;
682 skyxCloudLayerOptions->DetailAttenuation = attenuationDetail;
683 skyxCloudLayerOptions->HeightVolume = heightVolume;
684 skyxCloudLayerOptions->VolumetricDisplacement = volumetricDisplacement;
685 ApplyLayerOptions(index);
686}
687
688Ogre::Real SSky::CloudLayered::GetHeightFromCloudCeiling(const unsigned int& index)
689{
690 return (parentSky->GetCloudCeiling() - GetLayerOptions(index)->Height);
691}
692
693void SSky::CloudLayered::SetHeightFromCloudCeiling(const unsigned int& index, const Ogre::Real& newHeightFromCloudCeiling)
694{
695 GetLayerOptions(index)->Height = parentSky->GetCloudCeiling() + newHeightFromCloudCeiling;
696 ApplyLayerOptions(index);
697}
698
699Ogre::Real SSky::CloudLayered::GetScale(const unsigned int& index)
700{
701 return GetLayerOptions(index)->Scale;
702}
703
704void SSky::CloudLayered::SetScale(const unsigned int& index, const Ogre::Real& newScale)
705{
706 GetLayerOptions(index)->Scale = newScale;
707 ApplyLayerOptions(index);
708}
709
710Ogre::Real SSky::CloudLayered::GetAttenuationDistance(const unsigned int& index)
711{
712 return GetLayerOptions(index)->DistanceAttenuation;
713}
714
715void SSky::CloudLayered::SetAttenuationDistance(const unsigned int& index, const Ogre::Real& newAttenuationDistance)
716{
717 GetLayerOptions(index)->DistanceAttenuation = newAttenuationDistance;
718 ApplyLayerOptions(index);
719}
720
721Ogre::Real SSky::CloudLayered::GetAttenuationDetail(const unsigned int& index)
722{
723 return GetLayerOptions(index)->DetailAttenuation;
724}
725
726void SSky::CloudLayered::SetAttenuationDetail(const unsigned int& index, const Ogre::Real& newAttenuationDetail)
727{
728 GetLayerOptions(index)->DetailAttenuation = newAttenuationDetail;
729 ApplyLayerOptions(index);
730}
731
732Ogre::Real SSky::CloudLayered::GetHeightVolume(const unsigned int& index)
733{
734 return GetLayerOptions(index)->HeightVolume;
735}
736
737void SSky::CloudLayered::SetHeightVolume(const unsigned int& index, const Ogre::Real& newHeightVolume)
738{
739 GetLayerOptions(index)->HeightVolume = newHeightVolume;
740 ApplyLayerOptions(index);
741}
742
743Ogre::Real SSky::CloudLayered::GetVolumetricDisplacement(const unsigned int& index)
744{
745 return GetLayerOptions(index)->VolumetricDisplacement;
746}
747
748void SSky::CloudLayered::SetVolumetricDisplacement(const unsigned int& index, const Ogre::Real& newVolumetricDisplacement)
749{
750 GetLayerOptions(index)->VolumetricDisplacement = newVolumetricDisplacement;
751 ApplyLayerOptions(index);
752}
753
754/**********************************/
755/* Advanced volumetric cloud */
756/**********************************/
757SSky::CloudVolumetric::CloudVolumetric(SSky* parentSkyInstance) : SSky::SkyComponent(parentSkyInstance, SSky::SO3_SKY_COMPONENT_VOLUMETRIC_CLOUD)
758{
759}
760
761SSky::CloudVolumetric::CloudVolumetric() : SSky::SkyComponent(0, SSky::SO3_SKY_COMPONENT_NONE)
762{
763 // Forbiden constructor (private)
764}
765
767{
768 SkyX::SkyX* skyxManager = parentSky->GetSkyX();
769 if(skyxManager)
770 {
771 skyxManager->getVCloudsManager()->remove();
772 }
773}
774
776{
777 SkyX::SkyX* skyxManager = parentSky->GetSkyX();
778 if(skyxManager)
779 {
780 // Init some useful ptr
781 SkyX::VCloudsManager* skyxVolumetricCloudsManager = skyxManager->getVCloudsManager();
782 SkyX::VClouds::VClouds* skyxVolumetricClouds = skyxVolumetricCloudsManager->getVClouds();
783 skyxVolumetricClouds->unregisterCamera(cam);
784 }
785}
786
787void SSky::CloudVolumetric::SetEnableImpl(const bool& enableComponent)
788{
789 SkyX::SkyX* skyxManager = parentSky->GetSkyX();
790 if(skyxManager)
791 {
792 // Init some useful ptr
793 SkyX::VCloudsManager* skyxVolumetricCloudsManager = skyxManager->getVCloudsManager();
794 SkyX::VClouds::VClouds* skyxVolumetricClouds = skyxVolumetricCloudsManager->getVClouds();
795
796 if(enableComponent)
797 {
798 skyxVolumetricCloudsManager->setAutoupdate(false);
799
800 // Should we create or destroy the 3D clouds?
801 if(!skyxVolumetricCloudsManager->isCreated())
802 {
803 // Set height params before calling create!
804 cachedHumidity = parentSky->GetEnvironment()->GetHumidity();
805 cachedCloudCeiling = parentSky->GetCloudCeiling();
806
807 // Change default sun gradient, no need to change ambient gradient.
808 CheckSunColourGradient(true);
809
810 // Initialise wind speed
811 cachedWindDirection = parentSky->GetEnvironment()->GetWindDirection();
812 cachedWindSpeed = parentSky->GetEnvironment()->GetWindSpeed();
813 if(parentSky->GetEnvironment()->GetTimeSpeedFactor() < 0)
814 cachedWindSpeed = -cachedWindSpeed;
815
816 // Stop clouds animations if wind direction vector is setted to (0;0).
817 if(cachedWindDirection.squaredLength() == 0.0f)
818 skyxVolumetricCloudsManager->setWindSpeed(0.0f);
819 else
820 skyxVolumetricCloudsManager->setWindSpeed(parentSky->GetAnimationSpeed() * cachedWindSpeed * 0.5f * (cachedCloudCeiling / 7.5f));
821
822 // Initialise wind direction. ATan2 instead of ATan to avoid division by zero.
823 skyxVolumetricClouds->setWindDirection(Ogre::Math::ATan2(cachedWindDirection.x, -cachedWindDirection.y));
824
825 // Create & apply our options. Radius is computed from default values
826 float radius = 100.0f * cachedCloudCeiling / 7.5f;
827 skyxVolumetricCloudsManager->create(radius);
828
829 // Update humidity
830 skyxVolumetricClouds->setWheater(cachedHumidity / 100.0f, std::min(1.0f, cachedHumidity / 75.0f), false);
831
832 // Lightning
833 skyxVolumetricClouds->getLightningManager()->setEnabled(parentSky->GetLightningEnable());
834 skyxVolumetricClouds->getLightningManager()->setAverageLightningApparitionTime(0.5f);
835 skyxVolumetricClouds->getLightningManager()->setLightningColor(Ogre::Vector3(1,0.976,0.92));
836 skyxVolumetricClouds->getLightningManager()->setLightningTimeMultiplier(2);
837
838 skyxVolumetricCloudsManager->getVClouds()->getDataManager()->setUpdateTime(5.0f);
839 }
840 }
841 else if((skyxVolumetricCloudsManager->isCreated()) && (!enableComponent))
842 {
843 // Destroy
844 skyxManager->getVCloudsManager()->remove();
845 }
846 }
847}
848
849void SSky::CloudVolumetric::Update(const Ogre::Real& updateTime)
850{
851 SkyX::SkyX* skyxManager = parentSky->GetSkyX();
852 if(skyxManager)
853 {
854 // Init some useful ptr
855 SkyX::VCloudsManager* skyxVolumetricCloudsManager = skyxManager->getVCloudsManager();
856 SkyX::VClouds::VClouds* skyxVolumetricClouds = skyxVolumetricCloudsManager->getVClouds();
857
858 // Should we update params?
859 if(skyxVolumetricCloudsManager->isCreated())
860 {
861 // Update wind speed? !Cloud ceiling scale the geometry, so adapt the speed with the geometry size!
862 float newCloudCeiling = parentSky->GetCloudCeiling();
863 Ogre::Vector2 newWindDirection = parentSky->GetEnvironment()->GetWindDirection();
864 float newWindSpeed = parentSky->GetEnvironment()->GetWindSpeed();
865 if(parentSky->GetEnvironment()->GetTimeSpeedFactor() < 0)
866 newWindSpeed = -newWindSpeed;
867
868 // Stop clouds animations if wind direction vector is setted to (0;0).
869 if((cachedWindSpeed != newWindSpeed) || (cachedCloudCeiling != newCloudCeiling) || (cachedWindDirection != newWindDirection))
870 {
871 if(newWindDirection.squaredLength() == 0.0f)
872 skyxVolumetricCloudsManager->setWindSpeed(0.0f);
873 else
874 skyxVolumetricCloudsManager->setWindSpeed(parentSky->GetAnimationSpeed() * newWindSpeed * 0.5f * (newCloudCeiling / 7.5f));
875 }
876
877 // Update wind direction? ATan2 instead of ATan to avoid division by zero.
878 if(cachedWindDirection != newWindDirection)
879 skyxVolumetricClouds->setWindDirection(Ogre::Math::ATan2(newWindDirection.x, -newWindDirection.y));
880
881 // Updtate humidity
882 float newHumidity = parentSky->GetEnvironment()->GetHumidity();
883 if(cachedHumidity != newHumidity)
884 skyxVolumetricClouds->setWheater(newHumidity / 100.0f, std::min(1.0f, newHumidity / 75.0f), true);
885
886 // Update sun / moon color
887 CheckSunColourGradient();
888
889 // Update cloud height?
890 if(cachedCloudCeiling != newCloudCeiling)
891 {
892 // Destroy and re-create clouds, ugly, but skyx works this way for now...
893 float radius = 100.0f * newCloudCeiling / 7.5f;
894 skyxVolumetricCloudsManager->remove();
895 skyxVolumetricCloudsManager->create(radius);
896 }
897
898 cachedHumidity = newHumidity;
899 cachedCloudCeiling = newCloudCeiling;
900 cachedWindSpeed = newWindSpeed;
901 cachedWindDirection = newWindDirection;
902 }
903 }
904}
905
906void SSky::CloudVolumetric::CheckSunColourGradient(const bool& force)
907{
908 float moonLightTreshold = 0.4125f;
909 SSun* sun = parentSky->GetEnvironment()->GetSun();
910 SMoon* moon = parentSky->GetEnvironment()->GetMoon();
911
912 Ogre::ColourValue newSunColour = sun->GetLightColour();
913 Ogre::ColourValue newMoonColour = moon->GetLightColour();
914 if((newSunColour != cachedSunLightColour) || (newMoonColour != cachedMoonLightColour) || force)
915 {
916 sunGradient.clear();
917 Ogre::ColourValue lightSourceColour = sun->GetLightColour((0.9f - moonLightTreshold) / (1.0f - moonLightTreshold));
918 sunGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(lightSourceColour.r, lightSourceColour.g, lightSourceColour.b), 1.0f));
919 lightSourceColour = sun->GetLightColour((0.75f - moonLightTreshold) / (1.0f - moonLightTreshold));
920 sunGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(lightSourceColour.r, lightSourceColour.g, lightSourceColour.b), 0.75f));
921 lightSourceColour = sun->GetLightColour((0.5625f - moonLightTreshold) / (1.0f - moonLightTreshold));
922 sunGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(lightSourceColour.r, lightSourceColour.g, lightSourceColour.b), 0.5625f));
923 lightSourceColour = sun->GetLightColour((0.5f - moonLightTreshold) / (1.0f - moonLightTreshold));
924 sunGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(lightSourceColour.r, lightSourceColour.g, lightSourceColour.b), 0.5f));
925 lightSourceColour = sun->GetLightColour((0.4725f - moonLightTreshold) / (1.0f - moonLightTreshold));
926 sunGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(lightSourceColour.r, lightSourceColour.g, lightSourceColour.b), 0.4725f));
927 lightSourceColour = sun->GetLightColour((0.45f - moonLightTreshold) / (1.0f - moonLightTreshold));
928 sunGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(lightSourceColour.r, lightSourceColour.g, lightSourceColour.b), 0.45f));
929 sunGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(0.0, 0.0, 0.0), 0.4125f)); // Sun-Moon threshold
930 lightSourceColour = moon->GetLightColour((0.45f - moonLightTreshold) / (1.0f - moonLightTreshold));
931 sunGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(lightSourceColour.r, lightSourceColour.g, lightSourceColour.b), 0.25f));
932 lightSourceColour = moon->GetLightColour((0.75f - moonLightTreshold) / (1.0f - moonLightTreshold));
933 sunGradient.addCFrame(SkyX::ColorGradient::ColorFrame(Ogre::Vector3(lightSourceColour.r, lightSourceColour.g, lightSourceColour.b), 0.0f));
934
935 SkyX::SkyX* skyxManager = parentSky->GetSkyX();
936 if(skyxManager)
937 skyxManager->getVCloudsManager()->setSunGradient(sunGradient);
938
939 cachedSunLightColour = newSunColour;
940 cachedMoonLightColour = newMoonColour;
941 }
942}
943
944}
std::set< SViewPort * > ViewportList
void _NotifyEnvironmentComponentUnRegisterRenderTarget(Ogre::Viewport *targetViewport)
void _NotifyEnvironmentComponentRegisterRenderTarget(Ogre::Viewport *targetViewport)
std::string GetTextureName()
Definition SO3Moon.cpp:80
Ogre::SceneManager * GetOgreScenePointer()
Definition SO3Scene.cpp:449
void SetVolumetricDisplacement(const unsigned int &index, const Ogre::Real &newVolumetricDisplacement)
Definition SO3Sky.cpp:748
virtual void Update(const Ogre::Real &updateTime)
Definition SO3Sky.cpp:504
void SetHeightFromCloudCeiling(const unsigned int &index, const Ogre::Real &newHeightFromCloudCeiling)
Definition SO3Sky.cpp:693
void SetAttenuationDistance(const unsigned int &index, const Ogre::Real &newAttenuationDistance)
Definition SO3Sky.cpp:715
Ogre::Real GetAttenuationDetail(const unsigned int &index)
Definition SO3Sky.cpp:721
void SetHeightVolume(const unsigned int &index, const Ogre::Real &newHeightVolume)
Definition SO3Sky.cpp:737
void SetParameters(const unsigned int &index, const float &heightFromCloudCeiling, const float &scale, const float &attenuationDistance, const float &attenuationDetail, const float &heightVolume, const float &volumetricDisplacement)
Definition SO3Sky.cpp:676
void RemoveLayer(const unsigned int &index)
Definition SO3Sky.cpp:623
Ogre::Real GetHeightFromCloudCeiling(const unsigned int &index)
Definition SO3Sky.cpp:688
void SetScale(const unsigned int &index, const Ogre::Real &newScale)
Definition SO3Sky.cpp:704
std::vector< int > GetLayerIndexes()
Definition SO3Sky.cpp:655
void SetAttenuationDetail(const unsigned int &index, const Ogre::Real &newAttenuationDetail)
Definition SO3Sky.cpp:726
Ogre::Real GetAttenuationDistance(const unsigned int &index)
Definition SO3Sky.cpp:710
Ogre::Real GetVolumetricDisplacement(const unsigned int &index)
Definition SO3Sky.cpp:743
virtual void SetEnableImpl(const bool &enableComponent)
Definition SO3Sky.cpp:479
unsigned int AddLayer(const Ogre::Real &heightFromCloudCeiling=0.0f, const Ogre::Real &scale=0.001f, const Ogre::Real &distanceAttenuation=0.05f, const Ogre::Real &detailAttenuation=1.0f, const Ogre::Real &heightVolume=0.25f, const Ogre::Real &volumetricDisplacement=0.01f)
Definition SO3Sky.cpp:547
Ogre::Real GetHeightVolume(const unsigned int &index)
Definition SO3Sky.cpp:732
Ogre::Real GetScale(const unsigned int &index)
Definition SO3Sky.cpp:699
virtual void SetEnableImpl(const bool &enableComponent)
Definition SO3Sky.cpp:787
virtual void Update(const Ogre::Real &updateTime)
Definition SO3Sky.cpp:849
virtual void UnregisterCamera(Ogre::Camera *cam)
Definition SO3Sky.cpp:775
SkyComponentType GetType()
Definition SO3Sky.cpp:457
void SetEnabled(const bool &enable)
Definition SO3Sky.cpp:451
virtual void SetEnableImpl(const bool &enableComponent)
Definition SO3Sky.cpp:443
virtual void UnregisterCamera(Ogre::Camera *cam)
Definition SO3Sky.cpp:447
SSky::CloudVolumetric * GetCloudVolumetric()
Definition SO3Sky.cpp:322
SSky::CloudLayered * GetCloudLayered()
Definition SO3Sky.cpp:327
void RemoveViewport(Ogre::Viewport *viewport)
Definition SO3Sky.cpp:210
void AddLightning(const Ogre::Vector3 from, const Ogre::Vector3 dir, const Ogre::Real length)
Definition SO3Sky.cpp:405
float GetAnimationSpeed()
Definition SO3Sky.cpp:332
float GetCloudCeiling()
Definition SO3Sky.cpp:342
virtual void UnregisterViewportImpl(SViewPort *viewport)
Definition SO3Sky.cpp:187
virtual void Update(const Ogre::Real &updateTime)
Definition SO3Sky.cpp:239
void SetLightningEnable(const bool &enable)
Definition SO3Sky.cpp:389
bool GetHDREnable()
Definition SO3Sky.cpp:363
@ SO3_SKY_HDR
High dynamic range.
Definition SO3Sky.h:63
@ SO3_SKY_LDR
Low dynamic range.
Definition SO3Sky.h:62
void SetAnimationSpeed(const float &animationSpeed)
Definition SO3Sky.cpp:337
bool GetLightningEnable()
Definition SO3Sky.cpp:384
void SetHDREnable(const bool &enable)
Definition SO3Sky.cpp:368
void SetCloudCeiling(const float &newCloudCeiling)
Definition SO3Sky.cpp:347
virtual void UnregisterCameraImpl(Ogre::Camera *cam)
Definition SO3Sky.cpp:222
SkyX::SkyX * GetSkyX()
Definition SO3Sky.cpp:230
virtual void RegisterViewportImpl(SViewPort *viewport)
Definition SO3Sky.cpp:176
virtual void SetEnableImpl(const bool &enableComponent)
Definition SO3Sky.cpp:95
SkyComponent * GetComponent(const SkyComponentType &componentType)
Definition SO3Sky.cpp:304
void AddViewport(Ogre::Viewport *viewport)
Definition SO3Sky.cpp:200
SkyComponentType
Definition SO3Sky.h:52
@ SO3_SKY_COMPONENT_VOLUMETRIC_CLOUD
Definition SO3Sky.h:55
@ SO3_SKY_COMPONENT_LAYERER_CLOUD
Definition SO3Sky.h:54
@ SO3_SKY_COMPONENT_NONE
Definition SO3Sky.h:53
virtual void UpdateCamera(SViewPort *viewport)
Definition SO3Sky.cpp:235
const Ogre::ColourValue GetLightColour(const float &level=1.0f) const
SEnvironment * GetEnvironment()
Ogre::Viewport * GetOgreViewPortPointer()