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

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

Adding first version of osgVisual!!

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