]> git.mxchange.org Git - simgear.git/blob - simgear/scene/tgdb/vasi.hxx
Modified Files:
[simgear.git] / simgear / scene / tgdb / vasi.hxx
1 // vasi.hxx -- a class to hold some critical vasi data
2 //
3 // Written by Curtis Olson, started December 2003.
4 //
5 // Copyright (C) 2003  Curtis L. Olson  - http://www.flightgear.org/~curt
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 //
21 // $Id$
22
23
24 #ifndef _SG_VASI_HXX
25 #define _SG_VASI_HXX
26
27 #ifndef __cplusplus
28 # error This library requires C++
29 #endif
30
31 #include <simgear/compiler.h>
32
33 #include <osg/io_utils>
34 #include <osg/ref_ptr>
35 #include <osg/Array>
36 #include <osg/NodeCallback>
37 #include <osg/NodeVisitor>
38 #include <osg/Vec3>
39
40 /// Callback that updates the colors of a VASI according to the view direction
41 /// Notet that we need the eyepoint which is only available during culling
42 /// So this will be a cull callback ...
43 class SGVasiUpdateCallback : public osg::NodeCallback {
44 public:
45   SGVasiUpdateCallback(osg::Vec4Array* vasiColorArray,
46                        const osg::Vec3& referencePoint,
47                        const osg::Vec3& glideSlopeUp,
48                        const osg::Vec3& glideSlopeDir) :
49     mVasiColorArray(vasiColorArray),
50     mReferencePoint(referencePoint),
51     mGlideSlopeUp(glideSlopeUp),
52     mGlideSlopeDir(glideSlopeDir)
53   {
54     mGlideSlopeUp.normalize();
55     mGlideSlopeDir.normalize();
56   }
57   virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
58   {
59     // Rerieve the eye point relative to the vasi reference point
60     osg::Vec3 eyePoint = nv->getEyePoint() - mReferencePoint;
61     // Now project the eye point vector into the plane defined by the
62     // glideslope direction and the up direction
63     osg::Vec3 normal = mGlideSlopeUp^mGlideSlopeDir;
64     normal.normalize();
65     osg::Vec3 projEyePoint = eyePoint - normal * (eyePoint*normal);
66
67     double projEyePointLength = projEyePoint.length();
68     if (fabs(projEyePointLength) < 1e-3)
69       set_color(3);
70     else {
71       double aSinAngle = projEyePoint*mGlideSlopeUp/projEyePointLength;
72       if (aSinAngle < -1)
73         aSinAngle = -1;
74       if (1 < aSinAngle)
75         aSinAngle = 1;
76       
77       double angle = asin(aSinAngle)*SGD_RADIANS_TO_DEGREES;
78       set_color(angle);
79     }
80
81     // call the base implementation
82     osg::NodeCallback::operator()(node, nv);
83   }
84
85   // color the vasi/papi correctly based on angle in degree
86   void set_color( double angle_deg ) {
87     unsigned count = mVasiColorArray->size();
88     double trans = 0.05;
89     double color = 1;
90     double ref;
91     
92     if ( count == 12 ) {
93       // PAPI configuration
94       
95       // papi D
96       ref = 3.5;
97       if ( angle_deg < ref - trans ) {
98         color = 0.0;
99       } else if ( angle_deg < ref + trans ) {
100         color = 1.0 - (ref + trans - angle_deg) * (1 / (2 * trans) );
101       } else {
102         color = 1.0;
103       }
104       for ( unsigned i = 0; i < 3; ++i ) {
105         (*mVasiColorArray)[i][1] = color;
106         (*mVasiColorArray)[i][2] = color;
107       }
108       
109       // papi C
110       ref = 3.167;
111       if ( angle_deg < ref - trans ) {
112         color = 0.0;
113       } else if ( angle_deg < ref + trans ) {
114         color = 1.0 - (ref + trans - angle_deg) * (1 / (2 * trans) );
115       } else {
116         color = 1.0;
117       }
118       for ( unsigned i = 3; i < 6; ++i ) {
119         (*mVasiColorArray)[i][1] = color;
120         (*mVasiColorArray)[i][2] = color;
121       }
122       
123       // papi B
124       ref = 2.833;
125       if ( angle_deg < ref - trans ) {
126         color = 0.0;
127       } else if ( angle_deg < ref + trans ) {
128         color = 1.0 - (ref + trans - angle_deg) * (1 / (2 * trans) );
129       } else {
130         color = 1.0;
131       }
132       for ( unsigned i = 6; i < 9; ++i ) {
133         (*mVasiColorArray)[i][1] = color;
134         (*mVasiColorArray)[i][2] = color;
135       }
136       
137       // papi A
138       ref = 2.5;
139       if ( angle_deg < ref - trans ) {
140         color = 0.0;
141       } else if ( angle_deg < ref + trans ) {
142         color = 1.0 - (ref + trans - angle_deg) * (1 / (2 * trans) );
143       } else {
144         color = 1.0;
145       }
146       for ( unsigned i = 9; i < 12; ++i ) {
147         (*mVasiColorArray)[i][1] = color;
148         (*mVasiColorArray)[i][2] = color;
149       }
150     } else if ( count == 36 ) {
151       // probably vasi, first 18 are downwind bar (2.5 deg)
152       ref = 2.5;
153       if ( angle_deg < ref - trans ) {
154         color = 0.0;
155       } else if ( angle_deg < ref + trans ) {
156         color = 1.0 - (ref + trans - angle_deg) * (1 / (2 * trans) );
157       } else {
158         color = 1.0;
159       }
160       for ( unsigned i = 0; i < 18; ++i ) {
161         (*mVasiColorArray)[i][1] = color;
162         (*mVasiColorArray)[i][2] = color;
163       }
164       
165       // last 6 are upwind bar (3.0 deg)
166       ref = 3.0;
167       if ( angle_deg < ref - trans ) {
168         color = 0.0;
169       } else if ( angle_deg < ref + trans ) {
170         color = 1.0 - (ref + trans - angle_deg) * (1 / (2 * trans) );
171       } else {
172         color = 1.0;
173       }
174       for ( unsigned i = 18; i < 36; ++i ) {
175         (*mVasiColorArray)[i][1] = color;
176         (*mVasiColorArray)[i][2] = color;
177       }
178     } else {
179       // fail safe
180       cout << "unknown vasi/papi configuration, count = " << count << endl;
181       for ( unsigned i = 0; i < count; ++i ) {
182         (*mVasiColorArray)[i][1] = color;
183         (*mVasiColorArray)[i][2] = color;
184       }
185     }
186     // Finally mark the color array dirty
187     mVasiColorArray->dirty();
188   }
189
190 private:
191   osg::ref_ptr<osg::Vec4Array> mVasiColorArray;
192   osg::Vec3 mReferencePoint;
193   osg::Vec3 mGlideSlopeUp;
194   osg::Vec3 mGlideSlopeDir;
195 };
196
197 #endif // _SG_VASI_HXX