source: osgVisual/trunk/include/sky_Silverlining/skySilverLining_ProjectionMatrixCallback.h @ 197

Last change on this file since 197 was 133, checked in by Torben Dannhauer, 14 years ago
File size: 10.8 KB
Line 
1#pragma once
2/* -*-c++-*- osgVisual - Copyright (C) 2009-2010 Torben Dannhauer
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
30namespace 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 */ 
42class skySilverLining_projectionMatrixCallback : public osg::CullSettings::ClampProjectionMatrixCallback
43{
44        #include <leakDetection.h>
45public:
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    {
58                #include <leakDetection.h>
59
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)));
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)));
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)));
73                keys->push_back(osgAnimation::Vec2Keyframe(    500.0, osg::Vec2(     5.0,    100000.0)));
74                keys->push_back(osgAnimation::Vec2Keyframe(   1000.0, osg::Vec2(    10.0,    100000.0)));
75                keys->push_back(osgAnimation::Vec2Keyframe(  10000.0, osg::Vec2(   50.0,   1000000.0)));
76                keys->push_back(osgAnimation::Vec2Keyframe(1000000.0, osg::Vec2(100.0, 200000000.0)));
77
78    }
79
80        /**
81         * \brief This functions sets the pointer to the skyDrawable. This pointer is requiered to adjust the skybox size.
82         *
83         * @param sd : Pointer to the skyDrawable to store.
84         */ 
85        void setSkyDrawable(skySilverLining_skyDrawable *sd) {skyDrawable = sd;}
86
87protected:
88        /**
89         * \brief Implementation for float values to clamp the projection matrix.
90         *
91         * @param projection : Projection Matrix.
92         * @param znear : Near value of the projection matrix.
93         * @param zfar : Far value of the projection matrix.
94         * @return : True if successful
95         */ 
96    bool clampProjectionMatrixImplementation(osg::Matrixf& projection, double& znear, double& zfar) const
97    {
98           computeNearFar( znear, zfar );
99           //OSG_NOTIFY( osg::ALWAYS ) << "znear: " << znear << ", zfar: " << zfar << std::endl;
100
101           if (skyDrawable)
102           {
103               skyDrawable->setSkyboxSize(((zfar - znear) * 0.5 + znear) * 2.0);
104           }
105               
106           double fovy, ar, zn, zf;
107       camera->getProjectionMatrixAsPerspective(fovy, ar, zn, zf);
108           camera->setProjectionMatrixAsPerspective(fovy, ar, znear, zfar);
109
110                return true;
111    }
112
113        /**
114         * \brief Implementation for double values to clamp the projection matrix.
115         *
116         * @param projection : Projection Matrix.
117         * @param znear : Near value of the projection matrix.
118         * @param zfar : Far value of the projection matrix.
119         * @return : True if successful
120         */ 
121    bool clampProjectionMatrixImplementation(osg::Matrixd& projection, double& znear, double& zfar) const
122    {
123           computeNearFar( znear, zfar );
124           //OSG_NOTIFY( osg::ALWAYS ) << "znear: " << znear << ", zfar: " << zfar << std::endl;
125
126           if (skyDrawable)
127           {
128               skyDrawable->setSkyboxSize(((zfar - znear) * 0.5 + znear) * 2.0);
129           }
130               
131           double fovy, ar, zn, zf;
132       camera->getProjectionMatrixAsPerspective(fovy, ar, zn, zf);
133           //OSG_NOTIFY( osg::ALWAYS ) << "znear: " << znear << ", zfar: " << zfar << ", zn: " << zn << std::endl;
134           camera->setProjectionMatrixAsPerspective(fovy, ar, znear, zfar);
135
136                return true;
137    }
138
139        /**
140         * \brief This function computes the near and far value against the cloud objects of silverlining.
141         *
142         * @param znear : Referenced to store the calculated near value into.
143         * @param zfar : Referenced to store the calculated far value into.
144         */ 
145    void computeNearFarClouds(double &znear, double &zfar) const
146    {
147                const double fudge = 5000.0;
148        double minDist = 1E10; double maxDist = -1E10;
149
150                // Retrieve all atmosphere objects.
151                SL_VECTOR(SilverLining::ObjectHandle) &objects = atmosphere->GetObjects();
152                int size = objects.size();
153               
154                osg::Vec3d eye, dirVector, upVector;
155                camera->getViewMatrixAsLookAt(eye,dirVector,upVector); // Get XYZ from camera
156                //osg::Vec3d camPos = camera->getViewMatrix().getTrans();
157                osg::Vec3d camPos = eye;
158        osg::Vec3d up = camPos;
159        up.normalize();
160        osg::Vec3d down = up * -1.0;
161
162                double dToOrigin = camPos.length();
163
164                // Calculations if atmopshere is rendered from space
165                bool hasLimb = atmosphere->GetConfigOptionBoolean("enable-atmosphere-from-space");
166                OSG_ALWAYS << "has limb " << hasLimb << std::endl;
167                if (hasLimb)
168                {
169                        // Compute distance to edge of atmospheric limb
170                        double earthRadius = atmosphere->GetConfigOptionDouble("earth-radius-meters");
171                        double atmosphereHeight = earthRadius + atmosphere->GetConfigOptionDouble("atmosphere-height");
172                        double atmosphereThickness = atmosphere->GetConfigOptionDouble("atmosphere-scale-height-meters") + earthRadius;
173                        if (dToOrigin > atmosphereThickness) // Bail if limb not rendered
174                        {
175                                double dToLimbEdge = sqrt(dToOrigin * dToOrigin + atmosphereHeight * atmosphereHeight);
176                                maxDist = dToLimbEdge;
177                                double dToLimbBase = sqrt(dToOrigin * dToOrigin + earthRadius * earthRadius);
178                                minDist = dToLimbBase;
179                        }
180                }
181
182                // Walk through all objects and check if they influence the near plane or far plane
183                SL_VECTOR(SilverLining::ObjectHandle)::iterator it;
184        for (it = objects.begin(); it != objects.end(); it++)
185        {
186            float ox, oy, oz;
187            atmosphere->GetObjectPosition(*it, ox, oy, oz);
188            osg::Vec3d oPos(ox, oy, oz);
189            double oHeight = oPos.length();
190            osg::Vec3d testVec = camPos;
191                        // Compare distance to origin of the camera and the object. wenn objecte nah aneinander:
192                        //vertikal shiften, um eine erkennbare Distanz errechnen zu können.
193            if (dToOrigin > oHeight)
194            {
195                testVec = camPos + down * 100.0; // 100 for floating point precision problems
196            }
197            else
198            {
199                testVec = camPos + up * 100.0;
200            }
201           
202            const double farFarAway = 500000;
203
204            double dist = atmosphere->GetObjectDistance(*it, testVec.x(), testVec.y(), testVec.z(),
205                                (float)camPos.x(), (float)camPos.y(), (float)camPos.z());
206
207
208            if (dist < farFarAway) // an intersection was found
209            {
210                if (dist < minDist) minDist = dist;
211                if (dist > maxDist) maxDist = dist;
212            }
213        }       // For (all objects) END
214
215        double fovy, ar, zn, zf;
216        camera->getProjectionMatrixAsPerspective(fovy, ar, zn, zf);
217        double halfFovx = (fovy * ar) * 0.5;
218        minDist *= cos(halfFovx * (3.14159265 / 180.0));
219
220        znear = minDist - fudge;
221        zfar = maxDist + fudge;
222
223                //clamp the near plane if low above ground.
224            double x,y,z,hat;
225            util::getXYZofCamera( camera, x, y, z );
226                if( util::queryHeightAboveTerrainInWorld( hat, csn, x, y, z ) )
227                {
228                        if (hat < 80 ) 
229                        {
230                                znear = maxNear;
231                        }
232                }
233            //OSG_NOTIFY( osg::ALWAYS ) << "Near: " << znear << ", Far: " << zfar << std::endl;
234    }
235
236        void computeNearFar( double& near_, double& far_ ) const
237        {
238                double x,y,z,hat;
239                near_ = 2;
240                far_ = 125000;
241            util::getXYZofCamera( camera, x, y, z );
242                if( util::queryHeightAboveTerrainInWorld( hat, csn, x, y, z ) )
243                {
244                        osg::Vec2 planesNearFar;
245                        samplerClipPlanes->getValueAt(hat, planesNearFar);
246
247                        near_ = planesNearFar.x();
248                        far_  = planesNearFar.y();
249
250                        //OSG_NOTIFY( osg::ALWAYS ) << "hat: " << hat << ", near: " << near_ << ", far: " << far_ << std::endl;
251                } // IF HAT END
252                else 
253                        OSG_NOTIFY( osg::FATAL ) << "ERROR: Unable to Compute NearFar!" << std::endl;
254
255                if (near_ < 0.5 ) near_ = 0.5;
256        }
257
258   
259        /**
260         * Pointer to the Cullvisitor which applies the projection matrix.
261         */ 
262        osg::ref_ptr<osgUtil::CullVisitor> stockCullVisitor;
263
264        /**
265         * Pointer to silverlinings atmosphere instance.
266         */ 
267    SilverLining::Atmosphere *atmosphere;
268
269        /**
270         * Pointer to the camera on which the callback is installed
271         */ 
272    osg::Camera *camera;
273
274        /**
275         * Pointer to the skyDrawable
276         */ 
277        skySilverLining_skyDrawable *skyDrawable;
278
279        /**
280         * ?
281         * @todo: wofür ist diese variable nötig?
282         */ 
283        osg::CoordinateSystemNode *csn;
284
285
286        osg::ref_ptr<osgAnimation::Vec2LinearSampler> samplerClipPlanes;
287        osg::ref_ptr<osgAnimation::Vec2KeyframeContainer> keys;
288
289        /**
290         * Minimal far distance. The far plane is never nearer than this value.
291         */ 
292        double minFar;
293
294        /**
295         * Maximal near distance. The near plane is never farther than this value.
296         * It is used to clamp the near plane on a fix near value if the camera is low above ground
297         */ 
298        double maxNear;
299};
300
301}       // END NAMESPACE
Note: See TracBrowser for help on using the repository browser.