]> git.mxchange.org Git - simgear.git/blob - simgear/scene/tgdb/SGVasiDrawable.cxx
Fixed a crash: the singleton needs to be instantiated the first time SGCommandMgr...
[simgear.git] / simgear / scene / tgdb / SGVasiDrawable.cxx
1 /* -*-c++-*-
2  *
3  * Copyright (C) 2006-2007 Mathias Froehlich 
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of the
8  * License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18  * MA 02110-1301, USA.
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #  include <simgear_config.h>
24 #endif
25
26 #include <simgear/compiler.h>
27
28 #include "SGVasiDrawable.hxx"
29
30 #include <simgear/scene/util/OsgMath.hxx>
31
32 struct SGVasiDrawable::LightData {
33   LightData(const SGVec3f& p, const SGVec3f& n, const SGVec3f& up) :
34     position(p),
35     normal(n),
36     horizontal(normalize(cross(up, n))),
37     normalCrossHorizontal(normalize(cross(n, horizontal)))
38   { }
39   
40   void draw(const SGVec4f& color) const
41   {
42     glBegin(GL_POINTS);
43     glColor4fv(color.data());
44     glNormal3fv(normal.data());
45     glVertex3fv(position.data());
46     glEnd();
47   }
48   
49   SGVec3f position;
50   SGVec3f normal;
51   SGVec3f horizontal;
52   SGVec3f normalCrossHorizontal;
53 };
54
55 SGVasiDrawable::SGVasiDrawable(const SGVasiDrawable& vd, const osg::CopyOp&) :
56   _lights(vd._lights),
57   _red(vd._red),
58   _white(vd._white)
59 {
60   setUseDisplayList(false);
61   setSupportsDisplayList(false);
62 }
63
64 SGVasiDrawable::SGVasiDrawable(const SGVec4f& red, const SGVec4f& white) :
65   _red(red),
66   _white(white)
67 {
68   setUseDisplayList(false);
69   setSupportsDisplayList(false);
70 }
71
72 void
73 SGVasiDrawable::addLight(const SGVec3f& position, const SGVec3f& normal,
74                          const SGVec3f& up, float azimutDeg)
75 {
76   SGVec3f horizontal(normalize(cross(up, normal)));
77   SGVec3f zeroGlideSlope = normalize(cross(horizontal, up));
78   SGQuatf rotation = SGQuatf::fromAngleAxisDeg(azimutDeg, horizontal);
79   SGVec3f azimutGlideSlope = rotation.transform(zeroGlideSlope);
80   addLight(position, azimutGlideSlope, up);
81 }
82
83 void
84 SGVasiDrawable::addLight(const SGVec3f& position, const SGVec3f& normal,
85                          const SGVec3f& up)
86 {
87   _lights.push_back(LightData(position, normal, up));
88 }
89
90 void
91 SGVasiDrawable::drawImplementation(osg::RenderInfo& renderInfo) const
92 {
93   // Make sure we have the current state set
94 //   renderInfo.getState()->apply();
95
96   // Retrieve the eye point in local coords
97   osg::Matrix m;
98   m.invert(renderInfo.getState()->getModelViewMatrix());
99   SGVec3f eyePoint(toSG(m.preMult(osg::Vec3(0, 0, 0))));
100   
101   // paint the points
102   for (unsigned i = 0; i < _lights.size(); ++i)
103     draw(eyePoint, _lights[i]);
104 }
105
106 osg::BoundingBox
107 SGVasiDrawable::computeBound() const
108 {
109   osg::BoundingBox bb;
110   for (unsigned i = 0; i < _lights.size(); ++i)
111     bb.expandBy(toOsg(_lights[i].position));
112   
113   // blow up to avoid being victim to small feature culling ...
114   bb.expandBy(bb._min - osg::Vec3(1, 1, 1));
115   bb.expandBy(bb._max + osg::Vec3(1, 1, 1));
116   return bb;
117 }
118
119 SGVec4f
120 SGVasiDrawable::getColor(float angleDeg) const
121 {
122   float transDeg = 0.05f;
123   if (angleDeg < -transDeg) {
124     return _red;
125   } else if (angleDeg < transDeg) {
126     float fac = angleDeg*0.5f/transDeg + 0.5f;
127     return _red + fac*(_white - _red);
128   } else {
129     return _white;
130   }
131 }
132
133 void
134 SGVasiDrawable::draw(const SGVec3f& eyePoint, const LightData& light) const
135 {
136   // vector pointing from the light position to the eye
137   SGVec3f lightToEye = eyePoint - light.position;
138   
139   // dont' draw, we are behind it
140   if (dot(lightToEye, light.normal) < SGLimitsf::min())
141     return;
142   
143   // Now project the eye point vector into the plane defined by the
144   // glideslope direction and the up direction
145   SGVec3f projLightToEye = lightToEye
146     - light.horizontal*dot(lightToEye, light.horizontal);
147   
148   // dont' draw, if we are to near, looks like we are already behind
149   float sqrProjLightToEyeLength = dot(projLightToEye, projLightToEye);
150   if (sqrProjLightToEyeLength < 1e-3*1e-3)
151     return;
152   
153   // the scalar product of the glide slope up direction with the eye vector
154   float dotProd = dot(projLightToEye, light.normalCrossHorizontal);
155   float sinAngle = dotProd/sqrt(sqrProjLightToEyeLength);
156   if (sinAngle < -1)
157     sinAngle = -1;
158   if (1 < sinAngle)
159     sinAngle = 1;
160   
161   float angleDeg = SGMiscf::rad2deg(asin(sinAngle));
162   light.draw(getColor(angleDeg));
163 }
164