3 * Copyright (C) 2006-2007 Mathias Froehlich
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.
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.
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,
23 # include <simgear_config.h>
26 #include <simgear/compiler.h>
28 #include "SGVasiDrawable.hxx"
30 struct SGVasiDrawable::LightData {
31 LightData(const SGVec3f& p, const SGVec3f& n, const SGVec3f& up) :
34 horizontal(normalize(cross(up, n))),
35 normalCrossHorizontal(normalize(cross(n, horizontal)))
38 void draw(const SGVec4f& color) const
41 glColor4fv(color.data());
42 glNormal3fv(normal.data());
43 glVertex3fv(position.data());
50 SGVec3f normalCrossHorizontal;
53 SGVasiDrawable::SGVasiDrawable(const SGVasiDrawable& vd, const osg::CopyOp&) :
58 setUseDisplayList(false);
59 setSupportsDisplayList(false);
62 SGVasiDrawable::SGVasiDrawable(const SGVec4f& red, const SGVec4f& white) :
66 setUseDisplayList(false);
67 setSupportsDisplayList(false);
71 SGVasiDrawable::addLight(const SGVec3f& position, const SGVec3f& normal,
72 const SGVec3f& up, float azimutDeg)
74 SGVec3f horizontal(normalize(cross(up, normal)));
75 SGVec3f zeroGlideSlope = normalize(cross(horizontal, up));
76 SGQuatf rotation = SGQuatf::fromAngleAxisDeg(azimutDeg, horizontal);
77 SGVec3f azimutGlideSlope = rotation.transform(zeroGlideSlope);
78 addLight(position, azimutGlideSlope, up);
82 SGVasiDrawable::addLight(const SGVec3f& position, const SGVec3f& normal,
85 _lights.push_back(LightData(position, normal, up));
89 SGVasiDrawable::drawImplementation(osg::RenderInfo& renderInfo) const
91 // Make sure we have the current state set
92 // renderInfo.getState()->apply();
94 // Retrieve the eye point in local coords
96 m.invert(renderInfo.getState()->getModelViewMatrix());
97 SGVec3f eyePoint(toSG(m.preMult(osg::Vec3(0, 0, 0))));
100 for (unsigned i = 0; i < _lights.size(); ++i)
101 draw(eyePoint, _lights[i]);
105 SGVasiDrawable::computeBound() const
108 for (unsigned i = 0; i < _lights.size(); ++i)
109 bb.expandBy(toOsg(_lights[i].position));
111 // blow up to avoid being victim to small feature culling ...
112 bb.expandBy(bb._min - osg::Vec3(1, 1, 1));
113 bb.expandBy(bb._max + osg::Vec3(1, 1, 1));
118 SGVasiDrawable::getColor(float angleDeg) const
120 float transDeg = 0.05f;
121 if (angleDeg < -transDeg) {
123 } else if (angleDeg < transDeg) {
124 float fac = angleDeg*0.5f/transDeg + 0.5f;
125 return _red + fac*(_white - _red);
132 SGVasiDrawable::draw(const SGVec3f& eyePoint, const LightData& light) const
134 // vector pointing from the light position to the eye
135 SGVec3f lightToEye = eyePoint - light.position;
137 // dont' draw, we are behind it
138 if (dot(lightToEye, light.normal) < SGLimitsf::min())
141 // Now project the eye point vector into the plane defined by the
142 // glideslope direction and the up direction
143 SGVec3f projLightToEye = lightToEye
144 - light.horizontal*dot(lightToEye, light.horizontal);
146 // dont' draw, if we are to near, looks like we are already behind
147 float sqrProjLightToEyeLength = dot(projLightToEye, projLightToEye);
148 if (sqrProjLightToEyeLength < 1e-3*1e-3)
151 // the scalar product of the glide slope up direction with the eye vector
152 float dotProd = dot(projLightToEye, light.normalCrossHorizontal);
153 float sinAngle = dotProd/sqrt(sqrProjLightToEyeLength);
159 float angleDeg = SGMiscf::rad2deg(asin(sinAngle));
160 light.draw(getColor(angleDeg));