source: osgVisual/trunk/src/sky_Silverlining/skySilverLining_skyDrawable.cpp @ 297

Last change on this file since 297 was 296, checked in by Torben Dannhauer, 13 years ago
File size: 11.4 KB
Line 
1/* -*-c++-*- osgVisual - Copyright (C) 2009-2011 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                atmosphere->GetSunOrMoonPositionGeographic(&x, &y, &z);
71               
72
73        direction = osg::Vec3(x, y, z);
74                ambient = osg::Vec4(ra, ga, ba, 1.0);
75        //ambient = osg::Vec4(ra*0.1, ga*0.1, ba*0.1, 1.0);     // For use with shadow
76        diffuse = osg::Vec4(rd, gd, bd, 1.0);
77
78        // xform the light direction into camera coordinates
79        //osg::Quat view = _view->getCamera()->getViewMatrix().getRotate();
80        //direction = view * direction;
81        direction.normalize();
82                OSG_NOTIFY( osg::ALWAYS) << "X: "<<direction.x()<<"  Y: "<<direction.y()<<"  Z:"<<direction.z()<< std::endl;
83               
84double cx,cy,cz;
85util::getXYZofCamera(_view->getCamera(), cx, cy, cz);
86osg::Vec3d up(cx, cy, cz);
87//up.normalize();
88//util::AddCylinderBetweenPoints(osg::Vec3d(cx,cy,cz), direction*15000000 , 5000.0, osg::Vec4d(1.0, 1.0, 0.0, 1 ), sceneRoot);
89util::AddCylinderBetweenPoints(osg::Vec3d(0,0,0), direction*15000000 , 5000.0, osg::Vec4d(0.0, 1.0, 1.0, 1 ), sceneRoot);
90
91
92        light->setAmbient(ambient);
93        light->setDiffuse(diffuse);
94        light->setSpecular(osg::Vec4(0,0,0,1));
95                //light->setSpecular(osg::Vec4(1.0,1.0,1.0,1)); // Test
96        light->setPosition(osg::Vec4(direction.x(), direction.y(), direction.z(), 0));
97    }
98}
99
100void skySilverLining_skyDrawable::setSceneFog(SilverLining::Atmosphere *atmosphere) const
101{   
102        osg::ref_ptr<osg::Fog> fog = new osg::Fog;
103    fog->setMode(osg::Fog::EXP);
104        fog->setUseRadialFog( true );
105
106        //_objectsNode  = erde oder object, das mit nebel bedacht werden soll   
107        sceneRoot->getOrCreateStateSet()->setAttributeAndModes(fog.get());
108
109        //float hazeR, hazeG, hazeB;
110        //double hazeDepth, hazeDensity;
111        //atmosphere->GetHaze(hazeR, hazeG, hazeB, hazeDepth, hazeDensity);
112
113    //hazeDensity = 1.0 / 40000;
114        //hazeDensity = 0;
115        float hazeDensity = 1.0 / atmosphere->GetConditions()->GetVisibility();
116
117    // Decrease fog density with altitude, to avoid fog effects through the vacuum of space.
118    static const double H = 8435.0; // Pressure scale height of Earth's atmosphere
119    double isothermalEffect = exp(-(atmosphere->GetConditions()->GetLocation().GetAltitude() / H));     
120    if (isothermalEffect <= 0) isothermalEffect = 1E-9;
121    if (isothermalEffect > 1.0) isothermalEffect = 1.0;
122    hazeDensity *= isothermalEffect;
123
124    bool silverLiningHandledTheFog = false;
125
126    if (atmosphere->GetFogEnabled())
127    {
128            float density, r, g, b;
129            // Note, the fog color returned is already lit
130            atmosphere->GetFogSettings(&density, &r, &g, &b);
131
132            if (density > hazeDensity)
133            {
134                                fog->setDensity(density);
135                                fog->setColor(osg::Vec4(r, g, b, 1.0));
136
137                                silverLiningHandledTheFog = true;
138            }
139    }
140   
141    if (!silverLiningHandledTheFog)
142    {
143                float r, g, b;
144                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. */
145
146                fog->setDensity(hazeDensity);
147                fog->setColor(osg::Vec4(r, g, b, 1.0));
148    }
149
150}
151
152void skySilverLining_skyDrawable::initializeSilverLining(skySilverLining_atmosphereReference *ar)
153{
154    if (ar && !ar->atmosphereInitialized)
155    {
156        ar->atmosphereInitialized = true; // only try once.
157                SilverLining::Atmosphere *atmosphere = ar->atmosphere;
158
159                if (atmosphere)
160        {
161
162                        srand(1234); // constant random seed to ensure consistent clouds across windows
163
164            // Update the path below to where you installed SilverLining's resources folder.
165            //int ret = atmosphere->Initialize(SilverLining::Atmosphere::OPENGL, "C:\\Program Files\\SilverLining SDK\\resources\\", true, 0);
166                        int ret = atmosphere->Initialize(SilverLining::Atmosphere::OPENGL, "../resources/sky_silverlining/", true, 0);
167            if (ret != SilverLining::Atmosphere::E_NOERROR)
168            {
169                printf("SilverLining failed to initialize; error code %d.\n", ret);
170                printf("Check that the path to the SilverLining installation directory is set properly ");
171                printf("in skySilverLining_skyDrawable.cpp (in SkyDrawable::initializeSilverLining)\n");
172                exit(0);
173            }
174
175            // Let SilverLining know which way is up. OSG usually has Z going up.
176                        atmosphere->SetUpVector(0.662994, 0.136169, 0.736136);
177                        atmosphere->SetRightVector(-0.201185, 0.979553, 0.0);
178
179            // Set our location (change this to your own latitude and longitude)
180            SilverLining::Location loc;
181            loc.SetAltitude(0);
182            loc.SetLatitude(47);
183            loc.SetLongitude(11);
184            atmosphere->GetConditions()->SetLocation(loc);
185
186            // Set the system time in PST
187            SilverLining::LocalTime t;
188            t.SetFromSystemTime();
189                        t.SetTimeZone(CET);
190            atmosphere->GetConditions()->SetTime(t);
191
192                        // Setting Up Visibility
193                        atmosphere->GetConditions()->SetVisibility(40000);
194
195                        // Setting Up Haze
196                        atmosphere->GetConditions()->SetTurbidity(2.2);
197
198                        // Setting up time passage
199                        atmosphere->GetConditions()->EnableTimePassage( true, 5000 );
200                       
201                }       // if atmosphere ENDE
202
203    }   // If atmosphere not initialized ENDE
204}
205
206void skySilverLining_skyDrawable::drawImplementation(osg::RenderInfo& renderInfo) const
207{
208        skySilverLining_atmosphereReference *ar = dynamic_cast<skySilverLining_atmosphereReference *>(renderInfo.getCurrentCamera()->getUserData());
209        SilverLining::Atmosphere *atmosphere = 0;
210
211        if (ar) atmosphere = ar->atmosphere;
212
213        renderInfo.getState()->disableAllVertexArrays();
214
215    if (atmosphere)
216    {
217        initializeSilverLining(ar);
218                const_cast<skySilverLining_skyDrawable*>(this)->seedAndAddCloudLayers(atmosphere);
219
220                atmosphere->DrawSky(true, true, _skyboxSize);
221        setLighting(atmosphere);
222                setSceneFog(atmosphere);
223    }
224
225        renderInfo.getState()->dirtyAllVertexArrays();
226}
227
228void skySilverLining_skyDrawable::addCloudLayerOrder(cloudlayerOrder newCL)
229{
230        OpenThreads::ScopedLock<OpenThreads::Mutex> sLock(cloudLayersToAddMutex); 
231        pendingNewCloudLayers.push_back( newCL );
232        newCloudLayersToAdd = true;
233}
234
235void skySilverLining_skyDrawable::seedAndAddCloudLayers(SilverLining::Atmosphere *atmosphere)
236{
237        // Only try to add if anything to do..
238        if ( newCloudLayersToAdd )
239        {
240                OpenThreads::ScopedLock<OpenThreads::Mutex> sLock(cloudLayersToAddMutex); 
241
242                for ( unsigned int i=0; i<pendingNewCloudLayers.size(); i++)    // Configure & Seed cloudLayer
243                {
244                        // Calculation earth radius on specified lat lon position
245                        double radius;
246                        cloudlayerOrder newCL = pendingNewCloudLayers[i];
247                        if ( !util::calculateEarthRadiusAtWGS84Coordinate(newCL.lat, newCL.lon, sceneRoot, radius) )
248                        {
249                                OSG_ALWAYS << "ERROR: skySilverLining_skyDrawable::seedAndAddCloudLayers() - Unable to deterine earth radius for lat=" <<newCL.lat<< " lon="<<newCL.lat<<std::endl;
250                                return;
251                        }
252
253                        // generate Cloud Layer
254                        SilverLining::CloudLayer *cloudLayer_;
255                        cloudLayer_ = SilverLining::CloudLayerFactory::Create(newCL.cloudtype);
256                        cloudLayer_->SetBaseAltitude( newCL.baseHeight + radius);
257                        cloudLayer_->SetThickness(newCL.thickness);
258                        cloudLayer_->SetBaseLength(newCL.baseLength);
259                        cloudLayer_->SetBaseWidth(newCL.baseWidth);
260                        cloudLayer_->SetDensity(newCL.density);
261                        cloudLayer_->SetLayerPosition( 0.0, 0.0 );
262                        cloudLayer_->GenerateShadowMaps(false);
263                        //cloudLayer_->SetIsInfinite( true );
264
265
266                        //Save cloudlayer information into SLOT
267                        newCL.assocCloudLayerSlot->used = true;
268                        newCL.assocCloudLayerSlot->enabled = true;
269                        newCL.assocCloudLayerSlot->cloudLayerPointer = cloudLayer_;
270                        switch(newCL.cloudtype)
271                        {
272                        case 0: newCL.assocCloudLayerSlot->typeName = "CIRROCUMULUS";                           // High planar cloud puffs             
273                                break;
274                        case 1: newCL.assocCloudLayerSlot->typeName = "CIRRUS_FIBRATUS";                        // High, thicker and fibrous clouds that signal changing weather
275                                break;
276                        case 2: newCL.assocCloudLayerSlot->typeName = "STRATUS";                                        // Low clouds represented as a slab
277                                break;
278                        case 3: newCL.assocCloudLayerSlot->typeName = "CUMULUS_MEDIOCRIS";          // Low, puffy clouds on fair days
279                                break;
280                        case 4: newCL.assocCloudLayerSlot->typeName = "CUMULUS_CONGESTUS";          // Large cumulus clouds that could turn into a thunderhead
281                                break;
282                        case 5: newCL.assocCloudLayerSlot->typeName = "CUMULONIMBUS_CAPPILATUS";    // Big storm clouds.
283                                break;
284                        case 6: newCL.assocCloudLayerSlot->typeName = "STRATOCUMULUS";                          // Low, dense, puffy clouds with some sun breaks between them.
285                                break;
286                        default: OSG_NOTIFY( osg::FATAL ) << "skySilverLining_skyDrawable::seedAndAddCloudLayers() - Invalid cloud type." << std::cout;
287                                 break;
288                        };
289
290                        // Seed Cloudlayer
291                        cloudLayer_->SeedClouds(*atmosphere);
292       
293                        // Add cloudLayer to atmosphere
294                        newCL.assocCloudLayerSlot->cloudLayerHandle = atmosphere->GetConditions()->AddCloudLayer( cloudLayer_ );
295                }
296
297                //Clear the ToDo List
298                pendingNewCloudLayers.clear();
299
300                // Note nothing to do.
301                newCloudLayersToAdd = false;
302        }
303}
304
305void skySilverLining_skyDrawable::shutdown()
306{
307        sceneRoot = NULL;
308}
Note: See TracBrowser for help on using the repository browser.