[32] | 1 | #pragma once |
---|
[221] | 2 | /* -*-c++-*- osgVisual - Copyright (C) 2009-2011 Torben Dannhauer |
---|
[32] | 3 | * |
---|
| 4 | * This library is based on OpenSceneGraph, open source and may be redistributed and/or modified under |
---|
| 5 | * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or |
---|
| 6 | * (at your option) any later version. The full license is in LICENSE file |
---|
| 7 | * included with this distribution, and on the openscenegraph.org website. |
---|
| 8 | * |
---|
| 9 | * osgVisual requires for some proprietary modules a license from the correspondig manufacturer. |
---|
| 10 | * You have to aquire licenses for all used proprietary modules. |
---|
| 11 | * |
---|
| 12 | * This library is distributed in the hope that it will be useful, |
---|
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
| 15 | * OpenSceneGraph Public License for more details. |
---|
| 16 | * |
---|
| 17 | * This file is based on the OSG example of the Silverlining SDK: |
---|
| 18 | * Copyright (c) 2008 Sundog Software, LLC. All rights reserved worldwide. |
---|
| 19 | */ |
---|
| 20 | |
---|
| 21 | #include <SilverLining.h> |
---|
| 22 | #include <osg/Camera> |
---|
| 23 | #include <osg/CullSettings> |
---|
| 24 | #include <osgAnimation/Animation> |
---|
| 25 | #include <skySilverLining_skyDrawable.h> |
---|
| 26 | #include <visual_util.h> |
---|
| 27 | |
---|
| 28 | |
---|
| 29 | |
---|
| 30 | namespace osgVisual |
---|
| 31 | { |
---|
| 32 | |
---|
| 33 | /** |
---|
| 34 | * \brief This class intercepts OSG's method for automatically computing the near and far clip planes, taking into |
---|
| 35 | account SilverLining's objects in the scene (sky box, clouds, and possibly an atmospheric limb.) |
---|
| 36 | * |
---|
| 37 | * @todo : Create interface to control nearplane while tracking near plane. |
---|
| 38 | * |
---|
| 39 | * @author Torben Dannhauer |
---|
| 40 | * @date Sep 2009 |
---|
| 41 | */ |
---|
| 42 | class skySilverLining_projectionMatrixCallback : public osg::CullSettings::ClampProjectionMatrixCallback |
---|
| 43 | { |
---|
[88] | 44 | #include <leakDetection.h> |
---|
[32] | 45 | public: |
---|
| 46 | /** |
---|
| 47 | * \brief Constructor : Initializes the attributes with valid values. |
---|
| 48 | * |
---|
| 49 | * @todo : why is CSN required. |
---|
| 50 | * |
---|
| 51 | * @param atm : Pointer to the atmosphere object. |
---|
| 52 | * @param cam : Pointer to the rendering camera. |
---|
| 53 | * @param csn_ : Pointer to the coordinatesystemode. |
---|
| 54 | */ |
---|
| 55 | skySilverLining_projectionMatrixCallback(SilverLining::Atmosphere *atm, osg::Camera *cam, osg::CoordinateSystemNode *csn_) : osg::CullSettings::ClampProjectionMatrixCallback(), |
---|
| 56 | atmosphere(atm), camera(cam), csn(csn_), skyDrawable(0), minFar(90000), maxNear(2) |
---|
| 57 | { |
---|
[87] | 58 | #include <leakDetection.h> |
---|
| 59 | |
---|
[32] | 60 | stockCullVisitor = osgUtil::CullVisitor::create(); |
---|
| 61 | //stockCullVisitor->setNearFarRatio( 0.00005 ); |
---|
| 62 | |
---|
| 63 | samplerClipPlanes = new osgAnimation::Vec2LinearSampler; |
---|
| 64 | keys = samplerClipPlanes->getOrCreateKeyframeContainer(); |
---|
| 65 | |
---|
| 66 | // Flughöhe near far |
---|
| 67 | keys->push_back(osgAnimation::Vec2Keyframe( 0.0, osg::Vec2( 1.0, 80000.0))); |
---|
| 68 | keys->push_back(osgAnimation::Vec2Keyframe( 50.0, osg::Vec2( 5.0, 90000.0))); |
---|
[292] | 69 | keys->push_back(osgAnimation::Vec2Keyframe( 500.0, osg::Vec2( 5.0, 100000.0))); |
---|
| 70 | keys->push_back(osgAnimation::Vec2Keyframe( 1000.0, osg::Vec2( 10.0, 100000.0))); |
---|
[32] | 71 | //keys->push_back(osgAnimation::Vec2Keyframe( 10000.0, osg::Vec2( 100.0, 1000000.0))); |
---|
| 72 | //keys->push_back(osgAnimation::Vec2Keyframe(1000000.0, osg::Vec2(100000.0, 200000000.0))); |
---|
[292] | 73 | keys->push_back(osgAnimation::Vec2Keyframe( 10000.0, osg::Vec2( 50.0, 1000000.0))); |
---|
| 74 | keys->push_back(osgAnimation::Vec2Keyframe( 1000000.0, osg::Vec2( 100.0, 200000000.0))); |
---|
| 75 | keys->push_back(osgAnimation::Vec2Keyframe( 2000000.0, osg::Vec2( 250.0, 200000000.0))); |
---|
| 76 | keys->push_back(osgAnimation::Vec2Keyframe( 3000000.0, osg::Vec2( 500.0, 200000000.0))); |
---|
| 77 | keys->push_back(osgAnimation::Vec2Keyframe( 4000000.0, osg::Vec2( 1000.0, 200000000.0))); |
---|
| 78 | keys->push_back(osgAnimation::Vec2Keyframe( 5000000.0, osg::Vec2(10000.0, 200000000.0))); |
---|
| 79 | keys->push_back(osgAnimation::Vec2Keyframe( 6000000.0, osg::Vec2( 10000.0, 200000000.0))); |
---|
| 80 | keys->push_back(osgAnimation::Vec2Keyframe( 7000000.0, osg::Vec2( 100000.0, 200000000.0))); |
---|
| 81 | keys->push_back(osgAnimation::Vec2Keyframe( 8000000.0, osg::Vec2(1000000.0, 200000000.0))); |
---|
| 82 | keys->push_back(osgAnimation::Vec2Keyframe( 9000000.0, osg::Vec2(1250000.0, 200000000.0))); |
---|
| 83 | keys->push_back(osgAnimation::Vec2Keyframe(10000000.0, osg::Vec2(2500000.0, 200000000.0))); |
---|
| 84 | keys->push_back(osgAnimation::Vec2Keyframe(11000000.0, osg::Vec2(5000000.0, 200000000.0))); |
---|
| 85 | keys->push_back(osgAnimation::Vec2Keyframe(12000000.0, osg::Vec2(7500000.0, 200000000.0))); |
---|
| 86 | keys->push_back(osgAnimation::Vec2Keyframe(50000000.0, osg::Vec2(15000000.0,2000000000.0))); |
---|
[32] | 87 | |
---|
| 88 | } |
---|
| 89 | |
---|
| 90 | /** |
---|
| 91 | * \brief This functions sets the pointer to the skyDrawable. This pointer is requiered to adjust the skybox size. |
---|
| 92 | * |
---|
| 93 | * @param sd : Pointer to the skyDrawable to store. |
---|
| 94 | */ |
---|
| 95 | void setSkyDrawable(skySilverLining_skyDrawable *sd) {skyDrawable = sd;} |
---|
| 96 | |
---|
| 97 | protected: |
---|
| 98 | /** |
---|
| 99 | * \brief Implementation for float values to clamp the projection matrix. |
---|
| 100 | * |
---|
| 101 | * @param projection : Projection Matrix. |
---|
| 102 | * @param znear : Near value of the projection matrix. |
---|
| 103 | * @param zfar : Far value of the projection matrix. |
---|
| 104 | * @return : True if successful |
---|
| 105 | */ |
---|
| 106 | bool clampProjectionMatrixImplementation(osg::Matrixf& projection, double& znear, double& zfar) const |
---|
| 107 | { |
---|
| 108 | computeNearFar( znear, zfar ); |
---|
| 109 | //OSG_NOTIFY( osg::ALWAYS ) << "znear: " << znear << ", zfar: " << zfar << std::endl; |
---|
| 110 | |
---|
[112] | 111 | if (skyDrawable) |
---|
[32] | 112 | { |
---|
| 113 | skyDrawable->setSkyboxSize(((zfar - znear) * 0.5 + znear) * 2.0); |
---|
| 114 | } |
---|
| 115 | |
---|
| 116 | double fovy, ar, zn, zf; |
---|
| 117 | camera->getProjectionMatrixAsPerspective(fovy, ar, zn, zf); |
---|
| 118 | camera->setProjectionMatrixAsPerspective(fovy, ar, znear, zfar); |
---|
| 119 | |
---|
| 120 | return true; |
---|
| 121 | } |
---|
| 122 | |
---|
| 123 | /** |
---|
| 124 | * \brief Implementation for double values to clamp the projection matrix. |
---|
| 125 | * |
---|
| 126 | * @param projection : Projection Matrix. |
---|
| 127 | * @param znear : Near value of the projection matrix. |
---|
| 128 | * @param zfar : Far value of the projection matrix. |
---|
| 129 | * @return : True if successful |
---|
| 130 | */ |
---|
| 131 | bool clampProjectionMatrixImplementation(osg::Matrixd& projection, double& znear, double& zfar) const |
---|
| 132 | { |
---|
| 133 | computeNearFar( znear, zfar ); |
---|
| 134 | //OSG_NOTIFY( osg::ALWAYS ) << "znear: " << znear << ", zfar: " << zfar << std::endl; |
---|
| 135 | |
---|
[112] | 136 | if (skyDrawable) |
---|
[32] | 137 | { |
---|
| 138 | skyDrawable->setSkyboxSize(((zfar - znear) * 0.5 + znear) * 2.0); |
---|
| 139 | } |
---|
| 140 | |
---|
| 141 | double fovy, ar, zn, zf; |
---|
| 142 | camera->getProjectionMatrixAsPerspective(fovy, ar, zn, zf); |
---|
| 143 | //OSG_NOTIFY( osg::ALWAYS ) << "znear: " << znear << ", zfar: " << zfar << ", zn: " << zn << std::endl; |
---|
| 144 | camera->setProjectionMatrixAsPerspective(fovy, ar, znear, zfar); |
---|
| 145 | |
---|
| 146 | return true; |
---|
| 147 | } |
---|
| 148 | |
---|
| 149 | /** |
---|
| 150 | * \brief This function computes the near and far value against the cloud objects of silverlining. |
---|
| 151 | * |
---|
| 152 | * @param znear : Referenced to store the calculated near value into. |
---|
| 153 | * @param zfar : Referenced to store the calculated far value into. |
---|
| 154 | */ |
---|
| 155 | void computeNearFarClouds(double &znear, double &zfar) const |
---|
| 156 | { |
---|
| 157 | const double fudge = 5000.0; |
---|
| 158 | double minDist = 1E10; double maxDist = -1E10; |
---|
| 159 | |
---|
| 160 | // Retrieve all atmosphere objects. |
---|
[133] | 161 | SL_VECTOR(SilverLining::ObjectHandle) &objects = atmosphere->GetObjects(); |
---|
[32] | 162 | int size = objects.size(); |
---|
| 163 | |
---|
| 164 | osg::Vec3d eye, dirVector, upVector; |
---|
| 165 | camera->getViewMatrixAsLookAt(eye,dirVector,upVector); // Get XYZ from camera |
---|
| 166 | //osg::Vec3d camPos = camera->getViewMatrix().getTrans(); |
---|
| 167 | osg::Vec3d camPos = eye; |
---|
| 168 | osg::Vec3d up = camPos; |
---|
| 169 | up.normalize(); |
---|
| 170 | osg::Vec3d down = up * -1.0; |
---|
| 171 | |
---|
| 172 | double dToOrigin = camPos.length(); |
---|
| 173 | |
---|
| 174 | // Calculations if atmopshere is rendered from space |
---|
| 175 | bool hasLimb = atmosphere->GetConfigOptionBoolean("enable-atmosphere-from-space"); |
---|
[133] | 176 | OSG_ALWAYS << "has limb " << hasLimb << std::endl; |
---|
[32] | 177 | if (hasLimb) |
---|
| 178 | { |
---|
| 179 | // Compute distance to edge of atmospheric limb |
---|
| 180 | double earthRadius = atmosphere->GetConfigOptionDouble("earth-radius-meters"); |
---|
| 181 | double atmosphereHeight = earthRadius + atmosphere->GetConfigOptionDouble("atmosphere-height"); |
---|
| 182 | double atmosphereThickness = atmosphere->GetConfigOptionDouble("atmosphere-scale-height-meters") + earthRadius; |
---|
| 183 | if (dToOrigin > atmosphereThickness) // Bail if limb not rendered |
---|
| 184 | { |
---|
| 185 | double dToLimbEdge = sqrt(dToOrigin * dToOrigin + atmosphereHeight * atmosphereHeight); |
---|
| 186 | maxDist = dToLimbEdge; |
---|
| 187 | double dToLimbBase = sqrt(dToOrigin * dToOrigin + earthRadius * earthRadius); |
---|
| 188 | minDist = dToLimbBase; |
---|
| 189 | } |
---|
| 190 | } |
---|
| 191 | |
---|
| 192 | // Walk through all objects and check if they influence the near plane or far plane |
---|
[130] | 193 | SL_VECTOR(SilverLining::ObjectHandle)::iterator it; |
---|
[32] | 194 | for (it = objects.begin(); it != objects.end(); it++) |
---|
| 195 | { |
---|
| 196 | float ox, oy, oz; |
---|
| 197 | atmosphere->GetObjectPosition(*it, ox, oy, oz); |
---|
| 198 | osg::Vec3d oPos(ox, oy, oz); |
---|
| 199 | double oHeight = oPos.length(); |
---|
| 200 | osg::Vec3d testVec = camPos; |
---|
| 201 | // Compare distance to origin of the camera and the object. wenn objecte nah aneinander: |
---|
| 202 | //vertikal shiften, um eine erkennbare Distanz errechnen zu können. |
---|
| 203 | if (dToOrigin > oHeight) |
---|
| 204 | { |
---|
| 205 | testVec = camPos + down * 100.0; // 100 for floating point precision problems |
---|
| 206 | } |
---|
| 207 | else |
---|
| 208 | { |
---|
| 209 | testVec = camPos + up * 100.0; |
---|
| 210 | } |
---|
| 211 | |
---|
| 212 | const double farFarAway = 500000; |
---|
| 213 | |
---|
| 214 | double dist = atmosphere->GetObjectDistance(*it, testVec.x(), testVec.y(), testVec.z(), |
---|
| 215 | (float)camPos.x(), (float)camPos.y(), (float)camPos.z()); |
---|
| 216 | |
---|
| 217 | |
---|
| 218 | if (dist < farFarAway) // an intersection was found |
---|
| 219 | { |
---|
| 220 | if (dist < minDist) minDist = dist; |
---|
| 221 | if (dist > maxDist) maxDist = dist; |
---|
| 222 | } |
---|
| 223 | } // For (all objects) END |
---|
| 224 | |
---|
| 225 | double fovy, ar, zn, zf; |
---|
| 226 | camera->getProjectionMatrixAsPerspective(fovy, ar, zn, zf); |
---|
| 227 | double halfFovx = (fovy * ar) * 0.5; |
---|
| 228 | minDist *= cos(halfFovx * (3.14159265 / 180.0)); |
---|
| 229 | |
---|
| 230 | znear = minDist - fudge; |
---|
| 231 | zfar = maxDist + fudge; |
---|
| 232 | |
---|
| 233 | //clamp the near plane if low above ground. |
---|
| 234 | double x,y,z,hat; |
---|
[112] | 235 | util::getXYZofCamera( camera, x, y, z ); |
---|
| 236 | if( util::queryHeightAboveTerrainInWorld( hat, csn, x, y, z ) ) |
---|
[32] | 237 | { |
---|
| 238 | if (hat < 80 ) |
---|
| 239 | { |
---|
| 240 | znear = maxNear; |
---|
| 241 | } |
---|
| 242 | } |
---|
| 243 | //OSG_NOTIFY( osg::ALWAYS ) << "Near: " << znear << ", Far: " << zfar << std::endl; |
---|
| 244 | } |
---|
| 245 | |
---|
| 246 | void computeNearFar( double& near_, double& far_ ) const |
---|
| 247 | { |
---|
| 248 | double x,y,z,hat; |
---|
| 249 | near_ = 2; |
---|
| 250 | far_ = 125000; |
---|
[112] | 251 | util::getXYZofCamera( camera, x, y, z ); |
---|
| 252 | if( util::queryHeightAboveTerrainInWorld( hat, csn, x, y, z ) ) |
---|
[32] | 253 | { |
---|
| 254 | osg::Vec2 planesNearFar; |
---|
| 255 | samplerClipPlanes->getValueAt(hat, planesNearFar); |
---|
| 256 | |
---|
| 257 | near_ = planesNearFar.x(); |
---|
| 258 | far_ = planesNearFar.y(); |
---|
| 259 | |
---|
| 260 | //OSG_NOTIFY( osg::ALWAYS ) << "hat: " << hat << ", near: " << near_ << ", far: " << far_ << std::endl; |
---|
| 261 | } // IF HAT END |
---|
| 262 | else |
---|
| 263 | OSG_NOTIFY( osg::FATAL ) << "ERROR: Unable to Compute NearFar!" << std::endl; |
---|
| 264 | |
---|
| 265 | if (near_ < 0.5 ) near_ = 0.5; |
---|
| 266 | } |
---|
| 267 | |
---|
| 268 | |
---|
| 269 | /** |
---|
| 270 | * Pointer to the Cullvisitor which applies the projection matrix. |
---|
| 271 | */ |
---|
[107] | 272 | osg::ref_ptr<osgUtil::CullVisitor> stockCullVisitor; |
---|
[32] | 273 | |
---|
| 274 | /** |
---|
| 275 | * Pointer to silverlinings atmosphere instance. |
---|
| 276 | */ |
---|
| 277 | SilverLining::Atmosphere *atmosphere; |
---|
| 278 | |
---|
| 279 | /** |
---|
| 280 | * Pointer to the camera on which the callback is installed |
---|
| 281 | */ |
---|
[112] | 282 | osg::Camera *camera; |
---|
[32] | 283 | |
---|
| 284 | /** |
---|
| 285 | * Pointer to the skyDrawable |
---|
| 286 | */ |
---|
[112] | 287 | skySilverLining_skyDrawable *skyDrawable; |
---|
[32] | 288 | |
---|
| 289 | /** |
---|
| 290 | * ? |
---|
| 291 | * @todo: wofür ist diese variable nötig? |
---|
| 292 | */ |
---|
[112] | 293 | osg::CoordinateSystemNode *csn; |
---|
[32] | 294 | |
---|
| 295 | |
---|
| 296 | osg::ref_ptr<osgAnimation::Vec2LinearSampler> samplerClipPlanes; |
---|
| 297 | osg::ref_ptr<osgAnimation::Vec2KeyframeContainer> keys; |
---|
| 298 | |
---|
| 299 | /** |
---|
| 300 | * Minimal far distance. The far plane is never nearer than this value. |
---|
| 301 | */ |
---|
| 302 | double minFar; |
---|
| 303 | |
---|
| 304 | /** |
---|
| 305 | * Maximal near distance. The near plane is never farther than this value. |
---|
| 306 | * It is used to clamp the near plane on a fix near value if the camera is low above ground |
---|
| 307 | */ |
---|
| 308 | double maxNear; |
---|
| 309 | }; |
---|
| 310 | |
---|
| 311 | } // END NAMESPACE |
---|