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

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

Upgraded to Silverlining 2.0

Todo:
Re-enable DEBUg build
correct cloud altitude errors
enable the new ray casting cloud type

File size: 11.0 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();  //todo
152                SL_VECTOR(SilverLining::ObjectHandle) &objects = atmosphere->GetObjects();
153                int size = objects.size();
154               
155                osg::Vec3d eye, dirVector, upVector;
156                camera->getViewMatrixAsLookAt(eye,dirVector,upVector); // Get XYZ from camera
157                //osg::Vec3d camPos = camera->getViewMatrix().getTrans();
158                osg::Vec3d camPos = eye;
159        osg::Vec3d up = camPos;
160        up.normalize();
161        osg::Vec3d down = up * -1.0;
162
163                double dToOrigin = camPos.length();
164
165                // Calculations if atmopshere is rendered from space
166                bool hasLimb = atmosphere->GetConfigOptionBoolean("enable-atmosphere-from-space");
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        //std::vector<SilverLining::ObjectHandle>::iterator it; // todo
184        //for (it = objects.begin(); it != objects.end(); it++) // todo
185                SL_VECTOR(SilverLining::ObjectHandle)::iterator it;
186        for (it = objects.begin(); it != objects.end(); it++)
187        {
188            float ox, oy, oz;
189            atmosphere->GetObjectPosition(*it, ox, oy, oz);
190            osg::Vec3d oPos(ox, oy, oz);
191            double oHeight = oPos.length();
192            osg::Vec3d testVec = camPos;
193                        // Compare distance to origin of the camera and the object. wenn objecte nah aneinander:
194                        //vertikal shiften, um eine erkennbare Distanz errechnen zu können.
195            if (dToOrigin > oHeight)
196            {
197                testVec = camPos + down * 100.0; // 100 for floating point precision problems
198            }
199            else
200            {
201                testVec = camPos + up * 100.0;
202            }
203           
204            const double farFarAway = 500000;
205
206            double dist = atmosphere->GetObjectDistance(*it, testVec.x(), testVec.y(), testVec.z(),
207                                (float)camPos.x(), (float)camPos.y(), (float)camPos.z());
208
209
210            if (dist < farFarAway) // an intersection was found
211            {
212                if (dist < minDist) minDist = dist;
213                if (dist > maxDist) maxDist = dist;
214            }
215        }       // For (all objects) END
216
217        double fovy, ar, zn, zf;
218        camera->getProjectionMatrixAsPerspective(fovy, ar, zn, zf);
219        double halfFovx = (fovy * ar) * 0.5;
220        minDist *= cos(halfFovx * (3.14159265 / 180.0));
221
222        znear = minDist - fudge;
223        zfar = maxDist + fudge;
224
225                //clamp the near plane if low above ground.
226            double x,y,z,hat;
227            util::getXYZofCamera( camera, x, y, z );
228                if( util::queryHeightAboveTerrainInWorld( hat, csn, x, y, z ) )
229                {
230                        if (hat < 80 ) 
231                        {
232                                znear = maxNear;
233                        }
234                }
235            //OSG_NOTIFY( osg::ALWAYS ) << "Near: " << znear << ", Far: " << zfar << std::endl;
236    }
237
238        void computeNearFar( double& near_, double& far_ ) const
239        {
240                double x,y,z,hat;
241                near_ = 2;
242                far_ = 125000;
243            util::getXYZofCamera( camera, x, y, z );
244                if( util::queryHeightAboveTerrainInWorld( hat, csn, x, y, z ) )
245                {
246                        osg::Vec2 planesNearFar;
247                        samplerClipPlanes->getValueAt(hat, planesNearFar);
248
249                        near_ = planesNearFar.x();
250                        far_  = planesNearFar.y();
251
252                        //OSG_NOTIFY( osg::ALWAYS ) << "hat: " << hat << ", near: " << near_ << ", far: " << far_ << std::endl;
253                } // IF HAT END
254                else 
255                        OSG_NOTIFY( osg::FATAL ) << "ERROR: Unable to Compute NearFar!" << std::endl;
256
257                if (near_ < 0.5 ) near_ = 0.5;
258        }
259
260   
261        /**
262         * Pointer to the Cullvisitor which applies the projection matrix.
263         */ 
264        osg::ref_ptr<osgUtil::CullVisitor> stockCullVisitor;
265
266        /**
267         * Pointer to silverlinings atmosphere instance.
268         */ 
269    SilverLining::Atmosphere *atmosphere;
270
271        /**
272         * Pointer to the camera on which the callback is installed
273         */ 
274    osg::Camera *camera;
275
276        /**
277         * Pointer to the skyDrawable
278         */ 
279        skySilverLining_skyDrawable *skyDrawable;
280
281        /**
282         * ?
283         * @todo: wofür ist diese variable nötig?
284         */ 
285        osg::CoordinateSystemNode *csn;
286
287
288        osg::ref_ptr<osgAnimation::Vec2LinearSampler> samplerClipPlanes;
289        osg::ref_ptr<osgAnimation::Vec2KeyframeContainer> keys;
290
291        /**
292         * Minimal far distance. The far plane is never nearer than this value.
293         */ 
294        double minFar;
295
296        /**
297         * Maximal near distance. The near plane is never farther than this value.
298         * It is used to clamp the near plane on a fix near value if the camera is low above ground
299         */ 
300        double maxNear;
301};
302
303}       // END NAMESPACE
Note: See TracBrowser for help on using the repository browser.