/* -*-c++-*- osgVisual - Copyright (C) 2009-2010 Torben Dannhauer * * This library is based on OpenSceneGraph, open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * osgVisual requires for some proprietary modules a license from the correspondig manufacturer. * You have to aquire licenses for all used proprietary modules. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. * * This file is based on the OSG example of the Silverlining SDK: * Copyright (c) 2008 Sundog Software, LLC. All rights reserved worldwide. */ #include #include #include #include #include #include using namespace SilverLining; using namespace osgVisual; skySilverLining_skyDrawable::skySilverLining_skyDrawable() : osg::Drawable() , _view(0) , _skyboxSize(0) { setDataVariance(osg::Object::DYNAMIC); setUseVertexBufferObjects(false); setUseDisplayList(false); cloudLayerSlots.clear(); newCloudLayersToAdd = false; } skySilverLining_skyDrawable::skySilverLining_skyDrawable(osgViewer::Viewer* view) : osg::Drawable() , _view(view) , _skyboxSize(0) { setDataVariance(osg::Object::DYNAMIC); setUseVertexBufferObjects(false); setUseDisplayList(false); cloudLayerSlots.clear(); newCloudLayersToAdd = false; } void skySilverLining_skyDrawable::setLighting(SilverLining::Atmosphere *atmosphere) const { osg::Light *light = _view->getLight(); osg::Vec4 ambient, diffuse; osg::Vec3 direction; if (atmosphere && light) { float ra, ga, ba, rd, gd, bd, x, y, z; atmosphere->GetAmbientColor(&ra, &ga, &ba); atmosphere->GetSunOrMoonColor(&rd, &gd, &bd); atmosphere->GetSunOrMoonPosition(&x, &y, &z); direction = osg::Vec3(x, y, z); ambient = osg::Vec4(ra, ga, ba, 1.0); diffuse = osg::Vec4(rd, gd, bd, 1.0); // xform the light direction into camera coordinates osg::Quat view = _view->getCamera()->getViewMatrix().getRotate(); //direction = view * direction; direction.normalize(); light->setAmbient(ambient); light->setDiffuse(diffuse); light->setSpecular(osg::Vec4(0,0,0,1)); light->setPosition(osg::Vec4(direction.x(), direction.y(), direction.z(), 0)); } } void skySilverLining_skyDrawable::setSceneFog(SilverLining::Atmosphere *atmosphere) const { glEnable(GL_FOG); glFogi(GL_FOG_MODE, GL_EXP); //float hazeR, hazeG, hazeB; //double hazeDepth, hazeDensity; //atmosphere->GetHaze(hazeR, hazeG, hazeB, hazeDepth, hazeDensity); //hazeDensity = 1.0 / 40000; //hazeDensity = 0; float hazeDensity = 1.0 / atmosphere->GetConditions()->GetVisibility(); // Decrease fog density with altitude, to avoid fog effects through the vacuum of space. static const double H = 8435.0; // Pressure scale height of Earth's atmosphere double isothermalEffect = exp(-(atmosphere->GetConditions()->GetLocation().GetAltitude() / H)); if (isothermalEffect <= 0) isothermalEffect = 1E-9; if (isothermalEffect > 1.0) isothermalEffect = 1.0; hazeDensity *= isothermalEffect; bool silverLiningHandledTheFog = false; if (atmosphere->GetFogEnabled()) { float density, r, g, b; // Note, the fog color returned is already lit atmosphere->GetFogSettings(&density, &r, &g, &b); if (density > hazeDensity) { glFogf(GL_FOG_DENSITY, density); GLfloat fogColor[4] = {r, g, b, 1.0}; glFogfv(GL_FOG_COLOR, fogColor); silverLiningHandledTheFog = true; } } if (!silverLiningHandledTheFog) { GLfloat fogColor[4]; //atmosphere->GetHorizonColor(yaw, &fogColor[0], &fogColor[1], &fogColor[2]); // New version of this call: SL_1.94 /** \todo transmit the yaw value of the center channel to all slaves for consistent fog color. */ atmosphere->GetHorizonColor( 0, &fogColor[0], &fogColor[1], &fogColor[2]); glFogfv(GL_FOG_COLOR, fogColor); glFogf(GL_FOG_DENSITY, hazeDensity); } // _fog = new osg::Fog; //_objectsNode = erde oder object, das mit nebel bedacht werden soll //_objectsNode->getOrCreateStateSet()->setAttributeAndModes(_fog.get()); //fog->setMode(osg::Fog::EXP); // float hazeDensity = 0;//1.0 / 10000.0; //0.000075f // bool silverLiningHandledTheFog = false; // if (atmosphere->GetFogEnabled()) // { // float density, r, g, b; // atmosphere->GetFogSettings(&density, &r, &g, &b); // if (density > hazeDensity) // { // fog->setDensity(density); // fog->setColor(osg::Vec4(r, g, b, 1.0)); // silverLiningHandledTheFog = true; // } // } // if (!silverLiningHandledTheFog) // { // float r, g, b; // atmosphere->GetHorizonColor(0, &r, &g, &b); // fog->setDensity(hazeDensity); // fog->setColor(osg::Vec4(r, g, b, 1.0)); // } } void skySilverLining_skyDrawable::initializeSilverLining(skySilverLining_atmosphereReference *ar) { if (ar && !ar->atmosphereInitialized) { ar->atmosphereInitialized = true; // only try once. SilverLining::Atmosphere *atmosphere = ar->atmosphere; if (atmosphere) { srand(1234); // constant random seed to ensure consistent clouds across windows // Update the path below to where you installed SilverLining's resources folder. //int ret = atmosphere->Initialize(SilverLining::Atmosphere::OPENGL, "C:\\Program Files\\SilverLining SDK\\resources\\", true, 0); int ret = atmosphere->Initialize(SilverLining::Atmosphere::OPENGL, "../resources/sky_silverlining/", true, 0); if (ret != SilverLining::Atmosphere::E_NOERROR) { printf("SilverLining failed to initialize; error code %d.\n", ret); printf("Check that the path to the SilverLining installation directory is set properly "); printf("in skySilverLining_skyDrawable.cpp (in SkyDrawable::initializeSilverLining)\n"); exit(0); } // Let SilverLining know which way is up. OSG usually has Z going up. //atmosphere->SetUpVector(0, 0, 1); //atmosphere->SetRightVector(1, 0, 0); atmosphere->SetUpVector(0.662994, 0.136169, 0.736136); atmosphere->SetRightVector(-0.201185, 0.979553, 0.0); // Set our location (change this to your own latitude and longitude) SilverLining::Location loc; loc.SetAltitude(0); loc.SetLatitude(47); loc.SetLongitude(11); atmosphere->GetConditions()->SetLocation(loc); // Set the sstem time in PST SilverLining::LocalTime t; t.SetFromSystemTime(); t.SetTimeZone(CET); atmosphere->GetConditions()->SetTime(t); // Setting Up Visibility atmosphere->GetConditions()->SetVisibility(40000); // Setting Up Haze atmosphere->GetConditions()->SetTurbidity(2.2); atmosphere->GetConditions()->EnableTimePassage( true, 5000 ); } // if atmosphere ENDE } // If atmosphere not initialized ENDE } void skySilverLining_skyDrawable::drawImplementation(osg::RenderInfo& renderInfo) const { skySilverLining_atmosphereReference *ar = dynamic_cast(renderInfo.getCurrentCamera()->getUserData()); SilverLining::Atmosphere *atmosphere = 0; if (ar) atmosphere = ar->atmosphere; renderInfo.getState()->disableAllVertexArrays(); if (atmosphere) { initializeSilverLining(ar); const_cast(this)->seedAndAddCloudLayers(atmosphere); atmosphere->BeginFrame(true, true, _skyboxSize); setLighting(atmosphere); setSceneFog(atmosphere); } renderInfo.getState()->dirtyAllVertexArrays(); } void skySilverLining_skyDrawable::addCloudLayer(cloudLayerSlot *cloudLayerSlot_) { OpenThreads::ScopedLock sLock(cloudLayersToAddMutex); cloudLayerSlots.push_back( cloudLayerSlot_ ); newCloudLayersToAdd = true; } void skySilverLining_skyDrawable::seedAndAddCloudLayers(SilverLining::Atmosphere *atmosphere) { // Only try to add if anything to do.. if ( newCloudLayersToAdd ) { OpenThreads::ScopedLock sLock(cloudLayersToAddMutex); for ( unsigned int i=0; cloudLayerSlots.size() > 0; i++) { // Seed cloudLayer cloudLayerSlots.back()->cloudLayerPointer->SeedClouds(*atmosphere); //cloudLayerSlots.back()->cloudLayerPointer->SetEnabled( false ); // Todo: testing, please remove //cloudLayerSlots.back()->cloudLayerPointer->SetEnabled( true, 30000); // Todo: testing, please remove // add cloudLayer to atmosphere cloudLayerSlots.back()->cloudLayerHandle = atmosphere->GetConditions()->AddCloudLayer( cloudLayerSlots.back()->cloudLayerPointer ); // Delete this cloudLayer from the ToDo list. cloudLayerSlots.pop_back(); } // Note nothing to do. newCloudLayersToAdd = false; } }