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

Last change on this file since 87 was 87, checked in by Torben Dannhauer, 14 years ago

Introductes VS 2008 Memory Leak Debugging.
Todo: Compile on Linux and compare with Valgrind, VS 2008 seems to be awkward in leak debugging

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