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 #include <simgear/scene/util/OsgMath.hxx>
32 struct SGVasiDrawable::LightData {
33 LightData(const SGVec3f& p, const SGVec3f& n, const SGVec3f& up) :
36 horizontal(normalize(cross(up, n))),
37 normalCrossHorizontal(normalize(cross(n, horizontal)))
40 void draw(const SGVec4f& color) const
43 glColor4fv(color.data());
44 glNormal3fv(normal.data());
45 glVertex3fv(position.data());
52 SGVec3f normalCrossHorizontal;
55 SGVasiDrawable::SGVasiDrawable(const SGVasiDrawable& vd, const osg::CopyOp&) :
60 setUseDisplayList(false);
61 setSupportsDisplayList(false);
64 SGVasiDrawable::SGVasiDrawable(const SGVec4f& red, const SGVec4f& white) :
68 setUseDisplayList(false);
69 setSupportsDisplayList(false);
73 SGVasiDrawable::addLight(const SGVec3f& position, const SGVec3f& normal,
74 const SGVec3f& up, float azimutDeg)
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);
84 SGVasiDrawable::addLight(const SGVec3f& position, const SGVec3f& normal,
87 _lights.push_back(LightData(position, normal, up));
91 SGVasiDrawable::drawImplementation(osg::RenderInfo& renderInfo) const
93 // Make sure we have the current state set
94 // renderInfo.getState()->apply();
96 // Retrieve the eye point in local coords
98 m.invert(renderInfo.getState()->getModelViewMatrix());
99 SGVec3f eyePoint(toSG(m.preMult(osg::Vec3(0, 0, 0))));
102 for (unsigned i = 0; i < _lights.size(); ++i)
103 draw(eyePoint, _lights[i]);
107 SGVasiDrawable::computeBound() const
110 for (unsigned i = 0; i < _lights.size(); ++i)
111 bb.expandBy(toOsg(_lights[i].position));
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));
120 SGVasiDrawable::getColor(float angleDeg) const
122 float transDeg = 0.05f;
123 if (angleDeg < -transDeg) {
125 } else if (angleDeg < transDeg) {
126 float fac = angleDeg*0.5f/transDeg + 0.5f;
127 return _red + fac*(_white - _red);
134 SGVasiDrawable::draw(const SGVec3f& eyePoint, const LightData& light) const
136 // vector pointing from the light position to the eye
137 SGVec3f lightToEye = eyePoint - light.position;
139 // dont' draw, we are behind it
140 if (dot(lightToEye, light.normal) < SGLimitsf::min())
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);
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)
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);
161 float angleDeg = SGMiscf::rad2deg(asin(sinAngle));
162 light.draw(getColor(angleDeg));