source: osgVisual/include/sky_Silverlining/skySilverLining_ProjectionMatrixCallback.h @ 122

Last change on this file since 122 was 112, checked in by Torben Dannhauer, 14 years ago
File size: 10.7 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        std::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                if (hasLimb)
167                {
168                        // Compute distance to edge of atmospheric limb
169                        double earthRadius = atmosphere->GetConfigOptionDouble("earth-radius-meters");
170                        double atmosphereHeight = earthRadius + atmosphere->GetConfigOptionDouble("atmosphere-height");
171                        double atmosphereThickness = atmosphere->GetConfigOptionDouble("atmosphere-scale-height-meters") + earthRadius;
172                        if (dToOrigin > atmosphereThickness) // Bail if limb not rendered
173                        {
174                                double dToLimbEdge = sqrt(dToOrigin * dToOrigin + atmosphereHeight * atmosphereHeight);
175                                maxDist = dToLimbEdge;
176                                double dToLimbBase = sqrt(dToOrigin * dToOrigin + earthRadius * earthRadius);
177                                minDist = dToLimbBase;
178                        }
179                }
180
181                // Walk through all objects and check if they influence the near plane or far plane
182        std::vector<SilverLining::ObjectHandle>::iterator it;
183        for (it = objects.begin(); it != objects.end(); it++)
184        {
185            float ox, oy, oz;
186            atmosphere->GetObjectPosition(*it, ox, oy, oz);
187            osg::Vec3d oPos(ox, oy, oz);
188            double oHeight = oPos.length();
189            osg::Vec3d testVec = camPos;
190                        // Compare distance to origin of the camera and the object. wenn objecte nah aneinander:
191                        //vertikal shiften, um eine erkennbare Distanz errechnen zu können.
192            if (dToOrigin > oHeight)
193            {
194                testVec = camPos + down * 100.0; // 100 for floating point precision problems
195            }
196            else
197            {
198                testVec = camPos + up * 100.0;
199            }
200           
201            const double farFarAway = 500000;
202
203            double dist = atmosphere->GetObjectDistance(*it, testVec.x(), testVec.y(), testVec.z(),
204                                (float)camPos.x(), (float)camPos.y(), (float)camPos.z());
205
206
207            if (dist < farFarAway) // an intersection was found
208            {
209                if (dist < minDist) minDist = dist;
210                if (dist > maxDist) maxDist = dist;
211            }
212        }       // For (all objects) END
213
214        double fovy, ar, zn, zf;
215        camera->getProjectionMatrixAsPerspective(fovy, ar, zn, zf);
216        double halfFovx = (fovy * ar) * 0.5;
217        minDist *= cos(halfFovx * (3.14159265 / 180.0));
218
219        znear = minDist - fudge;
220        zfar = maxDist + fudge;
221
222                //clamp the near plane if low above ground.
223            double x,y,z,hat;
224            util::getXYZofCamera( camera, x, y, z );
225                if( util::queryHeightAboveTerrainInWorld( hat, csn, x, y, z ) )
226                {
227                        if (hat < 80 ) 
228                        {
229                                znear = maxNear;
230                        }
231                }
232            //OSG_NOTIFY( osg::ALWAYS ) << "Near: " << znear << ", Far: " << zfar << std::endl;
233    }
234
235        void computeNearFar( double& near_, double& far_ ) const
236        {
237                double x,y,z,hat;
238                near_ = 2;
239                far_ = 125000;
240            util::getXYZofCamera( camera, x, y, z );
241                if( util::queryHeightAboveTerrainInWorld( hat, csn, x, y, z ) )
242                {
243                        osg::Vec2 planesNearFar;
244                        samplerClipPlanes->getValueAt(hat, planesNearFar);
245
246                        near_ = planesNearFar.x();
247                        far_  = planesNearFar.y();
248
249                        //OSG_NOTIFY( osg::ALWAYS ) << "hat: " << hat << ", near: " << near_ << ", far: " << far_ << std::endl;
250                } // IF HAT END
251                else 
252                        OSG_NOTIFY( osg::FATAL ) << "ERROR: Unable to Compute NearFar!" << std::endl;
253
254                if (near_ < 0.5 ) near_ = 0.5;
255        }
256
257   
258        /**
259         * Pointer to the Cullvisitor which applies the projection matrix.
260         */ 
261        osg::ref_ptr<osgUtil::CullVisitor> stockCullVisitor;
262
263        /**
264         * Pointer to silverlinings atmosphere instance.
265         */ 
266    SilverLining::Atmosphere *atmosphere;
267
268        /**
269         * Pointer to the camera on which the callback is installed
270         */ 
271    osg::Camera *camera;
272
273        /**
274         * Pointer to the skyDrawable
275         */ 
276        skySilverLining_skyDrawable *skyDrawable;
277
278        /**
279         * ?
280         * @todo: wofür ist diese variable nötig?
281         */ 
282        osg::CoordinateSystemNode *csn;
283
284
285        osg::ref_ptr<osgAnimation::Vec2LinearSampler> samplerClipPlanes;
286        osg::ref_ptr<osgAnimation::Vec2KeyframeContainer> keys;
287
288        /**
289         * Minimal far distance. The far plane is never nearer than this value.
290         */ 
291        double minFar;
292
293        /**
294         * Maximal near distance. The near plane is never farther than this value.
295         * It is used to clamp the near plane on a fix near value if the camera is low above ground
296         */ 
297        double maxNear;
298};
299
300}       // END NAMESPACE
Note: See TracBrowser for help on using the repository browser.