source: osgVisual/src/sky_Silverlining/skySilverLining_skyDrawable.cpp @ 171

Last change on this file since 171 was 144, checked in by Torben Dannhauer, 14 years ago

start to move osgVisual from argument based configuratiobn to xml file based configuration

File size: 10.7 KB
Line 
1/* -*-c++-*- osgVisual - Copyright (C) 2009-2010 Torben Dannhauer
2 *
3 * This library is based on OpenSceneGraph, open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * osgVisual requires for some proprietary modules a license from the correspondig manufacturer.
9 * You have to aquire licenses for all used proprietary modules.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * OpenSceneGraph Public License for more details.
15 *
16 * This file is based on the OSG example of the Silverlining SDK:
17 * Copyright (c) 2008 Sundog Software, LLC. All rights reserved worldwide.
18*/
19
20#include <skySilverLining_skyDrawable.h>
21#include <SilverLining.h>
22#include <skySilverLining_AtmosphereReference.h>
23
24#include <GL/gl.h>
25#include <GL/glu.h>
26#include <assert.h>
27
28
29
30using namespace SilverLining;
31using namespace osgVisual;
32
33skySilverLining_skyDrawable::skySilverLining_skyDrawable()
34        : osg::Drawable()
35                , _view(0)
36                , _skyboxSize(0)
37{
38    setDataVariance(osg::Object::DYNAMIC);
39    setUseVertexBufferObjects(false);
40    setUseDisplayList(false);
41        pendingNewCloudLayers.clear();
42        newCloudLayersToAdd = false;
43}
44
45skySilverLining_skyDrawable::skySilverLining_skyDrawable(osgViewer::Viewer* view,  osg::CoordinateSystemNode* csn_)
46        : osg::Drawable()
47        , _view(view)
48                , _skyboxSize(0)
49{
50    setDataVariance(osg::Object::DYNAMIC);
51    setUseVertexBufferObjects(false);
52    setUseDisplayList(false);
53        pendingNewCloudLayers.clear();
54        newCloudLayersToAdd = false;
55        sceneRoot = csn_;
56}
57
58void skySilverLining_skyDrawable::setLighting(SilverLining::Atmosphere *atmosphere) const
59{
60    osg::Light *light = _view->getLight();
61    osg::Vec4 ambient, diffuse;
62    osg::Vec3 direction;
63
64    if (atmosphere && light)
65    {
66        float ra, ga, ba, rd, gd, bd, x, y, z;
67        atmosphere->GetAmbientColor(&ra, &ga, &ba);
68        atmosphere->GetSunOrMoonColor(&rd, &gd, &bd);
69        atmosphere->GetSunOrMoonPosition(&x, &y, &z);
70
71        direction = osg::Vec3(x, y, z);
72        ambient = osg::Vec4(ra, ga, ba, 1.0);
73        diffuse = osg::Vec4(rd, gd, bd, 1.0);
74
75        // xform the light direction into camera coordinates
76        osg::Quat view = _view->getCamera()->getViewMatrix().getRotate();
77        //direction = view * direction;
78        direction.normalize();
79
80        light->setAmbient(ambient);
81        light->setDiffuse(diffuse);
82        light->setSpecular(osg::Vec4(0,0,0,1));
83        light->setPosition(osg::Vec4(direction.x(), direction.y(), direction.z(), 0));
84    }
85}
86
87void skySilverLining_skyDrawable::setSceneFog(SilverLining::Atmosphere *atmosphere) const
88{   
89        osg::ref_ptr<osg::Fog> fog = new osg::Fog;
90    fog->setMode(osg::Fog::EXP);
91        //fog->setUseRadialFog( true );
92
93        //_objectsNode  = erde oder object, das mit nebel bedacht werden soll   
94        sceneRoot->getOrCreateStateSet()->setAttributeAndModes(fog.get());
95
96        //float hazeR, hazeG, hazeB;
97        //double hazeDepth, hazeDensity;
98        //atmosphere->GetHaze(hazeR, hazeG, hazeB, hazeDepth, hazeDensity);
99
100    //hazeDensity = 1.0 / 40000;
101        //hazeDensity = 0;
102        float hazeDensity = 1.0 / atmosphere->GetConditions()->GetVisibility();
103
104    // Decrease fog density with altitude, to avoid fog effects through the vacuum of space.
105    static const double H = 8435.0; // Pressure scale height of Earth's atmosphere
106    double isothermalEffect = exp(-(atmosphere->GetConditions()->GetLocation().GetAltitude() / H));     
107    if (isothermalEffect <= 0) isothermalEffect = 1E-9;
108    if (isothermalEffect > 1.0) isothermalEffect = 1.0;
109    hazeDensity *= isothermalEffect;
110
111    bool silverLiningHandledTheFog = false;
112
113    if (atmosphere->GetFogEnabled())
114    {
115            float density, r, g, b;
116            // Note, the fog color returned is already lit
117            atmosphere->GetFogSettings(&density, &r, &g, &b);
118
119            if (density > hazeDensity)
120            {
121                                fog->setDensity(density);
122                                fog->setColor(osg::Vec4(r, g, b, 1.0));
123
124                                silverLiningHandledTheFog = true;
125            }
126    }
127   
128    if (!silverLiningHandledTheFog)
129    {
130                float r, g, b;
131                atmosphere->GetHorizonColor(0, &r, &g, &b);// New version of this call: since SL_1.94 /** \todo transmit the yaw value of the center channel to all slaves for consistent fog color. */
132
133                fog->setDensity(hazeDensity);
134                fog->setColor(osg::Vec4(r, g, b, 1.0));
135    }
136
137}
138
139void skySilverLining_skyDrawable::initializeSilverLining(skySilverLining_atmosphereReference *ar)
140{
141    if (ar && !ar->atmosphereInitialized)
142    {
143        ar->atmosphereInitialized = true; // only try once.
144                SilverLining::Atmosphere *atmosphere = ar->atmosphere;
145
146                if (atmosphere)
147        {
148
149                        srand(1234); // constant random seed to ensure consistent clouds across windows
150
151            // Update the path below to where you installed SilverLining's resources folder.
152            //int ret = atmosphere->Initialize(SilverLining::Atmosphere::OPENGL, "C:\\Program Files\\SilverLining SDK\\resources\\", true, 0);
153                        int ret = atmosphere->Initialize(SilverLining::Atmosphere::OPENGL, "../resources/sky_silverlining/", true, 0);
154            if (ret != SilverLining::Atmosphere::E_NOERROR)
155            {
156                printf("SilverLining failed to initialize; error code %d.\n", ret);
157                printf("Check that the path to the SilverLining installation directory is set properly ");
158                printf("in skySilverLining_skyDrawable.cpp (in SkyDrawable::initializeSilverLining)\n");
159                exit(0);
160            }
161
162            // Let SilverLining know which way is up. OSG usually has Z going up.
163                        atmosphere->SetUpVector(0.662994, 0.136169, 0.736136);
164                        atmosphere->SetRightVector(-0.201185, 0.979553, 0.0);
165
166            // Set our location (change this to your own latitude and longitude)
167            SilverLining::Location loc;
168            loc.SetAltitude(0);
169            loc.SetLatitude(47);
170            loc.SetLongitude(11);
171            atmosphere->GetConditions()->SetLocation(loc);
172
173            // Set the system time in PST
174            SilverLining::LocalTime t;
175            t.SetFromSystemTime();
176                        t.SetTimeZone(CET);
177            atmosphere->GetConditions()->SetTime(t);
178
179                        // Setting Up Visibility
180                        atmosphere->GetConditions()->SetVisibility(40000);
181
182                        // Setting Up Haze
183                        atmosphere->GetConditions()->SetTurbidity(2.2);
184
185                        // Setting up time passage
186                        atmosphere->GetConditions()->EnableTimePassage( true, 5000 );
187                       
188                }       // if atmosphere ENDE
189
190    }   // If atmosphere not initialized ENDE
191}
192
193void skySilverLining_skyDrawable::drawImplementation(osg::RenderInfo& renderInfo) const
194{
195        skySilverLining_atmosphereReference *ar = dynamic_cast<skySilverLining_atmosphereReference *>(renderInfo.getCurrentCamera()->getUserData());
196        SilverLining::Atmosphere *atmosphere = 0;
197
198        if (ar) atmosphere = ar->atmosphere;
199
200        renderInfo.getState()->disableAllVertexArrays();
201
202    if (atmosphere)
203    {
204        initializeSilverLining(ar);
205                const_cast<skySilverLining_skyDrawable*>(this)->seedAndAddCloudLayers(atmosphere);
206
207
208        atmosphere->BeginFrame(true, true, _skyboxSize);
209        setLighting(atmosphere);
210                setSceneFog(atmosphere);
211    }
212
213        renderInfo.getState()->dirtyAllVertexArrays();
214}
215
216void skySilverLining_skyDrawable::addCloudLayerOrder(cloudlayerOrder newCL)
217{
218        OpenThreads::ScopedLock<OpenThreads::Mutex> sLock(cloudLayersToAddMutex); 
219        pendingNewCloudLayers.push_back( newCL );
220        newCloudLayersToAdd = true;
221}
222
223void skySilverLining_skyDrawable::seedAndAddCloudLayers(SilverLining::Atmosphere *atmosphere)
224{
225        // Only try to add if anything to do..
226        if ( newCloudLayersToAdd )
227        {
228                OpenThreads::ScopedLock<OpenThreads::Mutex> sLock(cloudLayersToAddMutex); 
229
230                for ( unsigned int i=0; i<pendingNewCloudLayers.size(); i++)    // Configure & Seed cloudLayer
231                {
232                        // Calculation earth radius on specified lat lon position
233                        double radius;
234                        cloudlayerOrder newCL = pendingNewCloudLayers[i];
235                        if ( !util::calculateEarthRadiusAtWGS84Coordinate(newCL.lat, newCL.lon, sceneRoot, radius) )
236                        {
237                                OSG_ALWAYS << "ERROR: skySilverLining_skyDrawable::seedAndAddCloudLayers() - Unable to deterine earth radius for lat=" <<newCL.lat<< " lon="<<newCL.lat<<std::endl;
238                                return;
239                        }
240
241                        // generate Cloud Layer
242                        SilverLining::CloudLayer *cloudLayer_;
243                        cloudLayer_ = SilverLining::CloudLayerFactory::Create(newCL.cloudtype);
244                        cloudLayer_->SetBaseAltitude( newCL.baseHeight + radius);
245                        cloudLayer_->SetThickness(newCL.thickness);
246                        cloudLayer_->SetBaseLength(newCL.baseLength);
247                        cloudLayer_->SetBaseWidth(newCL.baseWidth);
248                        cloudLayer_->SetDensity(newCL.density);
249                        cloudLayer_->SetLayerPosition( 0.0, 0.0 );
250                        cloudLayer_->GenerateShadowMaps(false);
251                        //cloudLayer_->SetIsInfinite( true );
252
253
254                        //Save cloudlayer information into SLOT
255                        newCL.assocCloudLayerSlot->used = true;
256                        newCL.assocCloudLayerSlot->enabled = true;
257                        newCL.assocCloudLayerSlot->cloudLayerPointer = cloudLayer_;
258                        switch(newCL.cloudtype)
259                        {
260                        case 0: newCL.assocCloudLayerSlot->typeName = "CIRROCUMULUS";                           // High planar cloud puffs             
261                                break;
262                        case 1: newCL.assocCloudLayerSlot->typeName = "CIRRUS_FIBRATUS";                        // High, thicker and fibrous clouds that signal changing weather
263                                break;
264                        case 2: newCL.assocCloudLayerSlot->typeName = "STRATUS";                                        // Low clouds represented as a slab
265                                break;
266                        case 3: newCL.assocCloudLayerSlot->typeName = "CUMULUS_MEDIOCRIS";          // Low, puffy clouds on fair days
267                                break;
268                        case 4: newCL.assocCloudLayerSlot->typeName = "CUMULUS_CONGESTUS";          // Large cumulus clouds that could turn into a thunderhead
269                                break;
270                        case 5: newCL.assocCloudLayerSlot->typeName = "CUMULONIMBUS_CAPPILATUS";    // Big storm clouds.
271                                break;
272                        case 6: newCL.assocCloudLayerSlot->typeName = "STRATOCUMULUS";                          // Low, dense, puffy clouds with some sun breaks between them.
273                                break;
274                        default: OSG_NOTIFY( osg::FATAL ) << "skySilverLining_skyDrawable::seedAndAddCloudLayers() - Invalid cloud type." << std::cout;
275                                 break;
276                        };
277
278                        // Seed Cloudlayer
279                        cloudLayer_->SeedClouds(*atmosphere);
280       
281                        // Add cloudLayer to atmosphere
282                        newCL.assocCloudLayerSlot->cloudLayerHandle = atmosphere->GetConditions()->AddCloudLayer( cloudLayer_ );
283                }
284
285                //Clear the ToDo List
286                pendingNewCloudLayers.clear();
287
288                // Note nothing to do.
289                newCloudLayersToAdd = false;
290        }
291}
292
293void skySilverLining_skyDrawable::shutdown()
294{
295        sceneRoot = NULL;
296}
Note: See TracBrowser for help on using the repository browser.