1 // vasi.hxx -- a class to hold some critical vasi data
3 // Written by Curtis Olson, started December 2003.
5 // Copyright (C) 2003 Curtis L. Olson - http://www.flightgear.org/~curt
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.
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.
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.
28 # error This library requires C++
31 #include <simgear/compiler.h>
33 #include <osg/io_utils>
34 #include <osg/ref_ptr>
36 #include <osg/NodeCallback>
37 #include <osg/NodeVisitor>
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 {
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)
54 mGlideSlopeUp.normalize();
55 mGlideSlopeDir.normalize();
57 virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
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;
65 osg::Vec3 projEyePoint = eyePoint - normal * (eyePoint*normal);
67 double projEyePointLength = projEyePoint.length();
68 if (fabs(projEyePointLength) < 1e-3)
71 double aSinAngle = projEyePoint*mGlideSlopeUp/projEyePointLength;
77 double angle = asin(aSinAngle)*SGD_RADIANS_TO_DEGREES;
81 // call the base implementation
82 osg::NodeCallback::operator()(node, nv);
85 // color the vasi/papi correctly based on angle in degree
86 void set_color( double angle_deg ) {
87 unsigned count = mVasiColorArray->size();
97 if ( angle_deg < ref - trans ) {
99 } else if ( angle_deg < ref + trans ) {
100 color = 1.0 - (ref + trans - angle_deg) * (1 / (2 * trans) );
104 for ( unsigned i = 0; i < 3; ++i ) {
105 (*mVasiColorArray)[i][1] = color;
106 (*mVasiColorArray)[i][2] = color;
111 if ( angle_deg < ref - trans ) {
113 } else if ( angle_deg < ref + trans ) {
114 color = 1.0 - (ref + trans - angle_deg) * (1 / (2 * trans) );
118 for ( unsigned i = 3; i < 6; ++i ) {
119 (*mVasiColorArray)[i][1] = color;
120 (*mVasiColorArray)[i][2] = color;
125 if ( angle_deg < ref - trans ) {
127 } else if ( angle_deg < ref + trans ) {
128 color = 1.0 - (ref + trans - angle_deg) * (1 / (2 * trans) );
132 for ( unsigned i = 6; i < 9; ++i ) {
133 (*mVasiColorArray)[i][1] = color;
134 (*mVasiColorArray)[i][2] = color;
139 if ( angle_deg < ref - trans ) {
141 } else if ( angle_deg < ref + trans ) {
142 color = 1.0 - (ref + trans - angle_deg) * (1 / (2 * trans) );
146 for ( unsigned i = 9; i < 12; ++i ) {
147 (*mVasiColorArray)[i][1] = color;
148 (*mVasiColorArray)[i][2] = color;
150 } else if ( count == 36 ) {
151 // probably vasi, first 18 are downwind bar (2.5 deg)
153 if ( angle_deg < ref - trans ) {
155 } else if ( angle_deg < ref + trans ) {
156 color = 1.0 - (ref + trans - angle_deg) * (1 / (2 * trans) );
160 for ( unsigned i = 0; i < 18; ++i ) {
161 (*mVasiColorArray)[i][1] = color;
162 (*mVasiColorArray)[i][2] = color;
165 // last 6 are upwind bar (3.0 deg)
167 if ( angle_deg < ref - trans ) {
169 } else if ( angle_deg < ref + trans ) {
170 color = 1.0 - (ref + trans - angle_deg) * (1 / (2 * trans) );
174 for ( unsigned i = 18; i < 36; ++i ) {
175 (*mVasiColorArray)[i][1] = color;
176 (*mVasiColorArray)[i][2] = color;
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;
186 // Finally mark the color array dirty
187 mVasiColorArray->dirty();
191 osg::ref_ptr<osg::Vec4Array> mVasiColorArray;
192 osg::Vec3 mReferencePoint;
193 osg::Vec3 mGlideSlopeUp;
194 osg::Vec3 mGlideSlopeDir;
197 #endif // _SG_VASI_HXX