Modified Files: simgear/math/SGGeod.cxx simgear/math/SGQuat.hxx simgear/math/SGVec2.hxx simgear/math/SGVec3.hxx simgear/math/SGVec4.hxx simgear/scene/material/Effect.cxx simgear/scene/model/SGInteractionAnimation.cxx simgear/scene/model/SGMaterialAnimation.cxx simgear/scene/model/SGRotateTransform.cxx simgear/scene/model/SGScaleTransform.cxx simgear/scene/model/SGTranslateTransform.cxx simgear/scene/model/animation.cxx simgear/scene/model/particles.cxx simgear/scene/model/placement.cxx simgear/scene/model/shadanim.cxx simgear/scene/sky/CloudShaderGeometry.cxx simgear/scene/sky/cloud.cxx simgear/scene/sky/cloudfield.cxx simgear/scene/sky/dome.cxx simgear/scene/sky/sky.cxx simgear/scene/tgdb/GroundLightManager.cxx simgear/scene/tgdb/SGOceanTile.cxx simgear/scene/tgdb/SGTexturedTriangleBin.hxx simgear/scene/tgdb/SGVasiDrawable.cxx simgear/scene/tgdb/TreeBin.cxx simgear/scene/tgdb/obj.cxx simgear/scene/tgdb/pt_lights.cxx simgear/scene/util/SGUpdateVisitor.hxx
163 lines
4.5 KiB
C++
163 lines
4.5 KiB
C++
/* -*-c++-*-
|
|
*
|
|
* Copyright (C) 2006-2007 Mathias Froehlich
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License as
|
|
* published by the Free Software Foundation; either version 2 of the
|
|
* License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
* MA 02110-1301, USA.
|
|
*
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include <simgear_config.h>
|
|
#endif
|
|
|
|
#include <simgear/compiler.h>
|
|
|
|
#include "SGVasiDrawable.hxx"
|
|
|
|
struct SGVasiDrawable::LightData {
|
|
LightData(const SGVec3f& p, const SGVec3f& n, const SGVec3f& up) :
|
|
position(p),
|
|
normal(n),
|
|
horizontal(normalize(cross(up, n))),
|
|
normalCrossHorizontal(normalize(cross(n, horizontal)))
|
|
{ }
|
|
|
|
void draw(const SGVec4f& color) const
|
|
{
|
|
glBegin(GL_POINTS);
|
|
glColor4fv(color.data());
|
|
glNormal3fv(normal.data());
|
|
glVertex3fv(position.data());
|
|
glEnd();
|
|
}
|
|
|
|
SGVec3f position;
|
|
SGVec3f normal;
|
|
SGVec3f horizontal;
|
|
SGVec3f normalCrossHorizontal;
|
|
};
|
|
|
|
SGVasiDrawable::SGVasiDrawable(const SGVasiDrawable& vd, const osg::CopyOp&) :
|
|
_lights(vd._lights),
|
|
_red(vd._red),
|
|
_white(vd._white)
|
|
{
|
|
setUseDisplayList(false);
|
|
setSupportsDisplayList(false);
|
|
}
|
|
|
|
SGVasiDrawable::SGVasiDrawable(const SGVec4f& red, const SGVec4f& white) :
|
|
_red(red),
|
|
_white(white)
|
|
{
|
|
setUseDisplayList(false);
|
|
setSupportsDisplayList(false);
|
|
}
|
|
|
|
void
|
|
SGVasiDrawable::addLight(const SGVec3f& position, const SGVec3f& normal,
|
|
const SGVec3f& up, float azimutDeg)
|
|
{
|
|
SGVec3f horizontal(normalize(cross(up, normal)));
|
|
SGVec3f zeroGlideSlope = normalize(cross(horizontal, up));
|
|
SGQuatf rotation = SGQuatf::fromAngleAxisDeg(azimutDeg, horizontal);
|
|
SGVec3f azimutGlideSlope = rotation.transform(zeroGlideSlope);
|
|
addLight(position, azimutGlideSlope, up);
|
|
}
|
|
|
|
void
|
|
SGVasiDrawable::addLight(const SGVec3f& position, const SGVec3f& normal,
|
|
const SGVec3f& up)
|
|
{
|
|
_lights.push_back(LightData(position, normal, up));
|
|
}
|
|
|
|
void
|
|
SGVasiDrawable::drawImplementation(osg::RenderInfo& renderInfo) const
|
|
{
|
|
// Make sure we have the current state set
|
|
// renderInfo.getState()->apply();
|
|
|
|
// Retrieve the eye point in local coords
|
|
osg::Matrix m;
|
|
m.invert(renderInfo.getState()->getModelViewMatrix());
|
|
SGVec3f eyePoint(toSG(m.preMult(osg::Vec3(0, 0, 0))));
|
|
|
|
// paint the points
|
|
for (unsigned i = 0; i < _lights.size(); ++i)
|
|
draw(eyePoint, _lights[i]);
|
|
}
|
|
|
|
osg::BoundingBox
|
|
SGVasiDrawable::computeBound() const
|
|
{
|
|
osg::BoundingBox bb;
|
|
for (unsigned i = 0; i < _lights.size(); ++i)
|
|
bb.expandBy(toOsg(_lights[i].position));
|
|
|
|
// blow up to avoid being victim to small feature culling ...
|
|
bb.expandBy(bb._min - osg::Vec3(1, 1, 1));
|
|
bb.expandBy(bb._max + osg::Vec3(1, 1, 1));
|
|
return bb;
|
|
}
|
|
|
|
SGVec4f
|
|
SGVasiDrawable::getColor(float angleDeg) const
|
|
{
|
|
float transDeg = 0.05f;
|
|
if (angleDeg < -transDeg) {
|
|
return _red;
|
|
} else if (angleDeg < transDeg) {
|
|
float fac = angleDeg*0.5f/transDeg + 0.5f;
|
|
return _red + fac*(_white - _red);
|
|
} else {
|
|
return _white;
|
|
}
|
|
}
|
|
|
|
void
|
|
SGVasiDrawable::draw(const SGVec3f& eyePoint, const LightData& light) const
|
|
{
|
|
// vector pointing from the light position to the eye
|
|
SGVec3f lightToEye = eyePoint - light.position;
|
|
|
|
// dont' draw, we are behind it
|
|
if (dot(lightToEye, light.normal) < SGLimitsf::min())
|
|
return;
|
|
|
|
// Now project the eye point vector into the plane defined by the
|
|
// glideslope direction and the up direction
|
|
SGVec3f projLightToEye = lightToEye
|
|
- light.horizontal*dot(lightToEye, light.horizontal);
|
|
|
|
// dont' draw, if we are to near, looks like we are already behind
|
|
float sqrProjLightToEyeLength = dot(projLightToEye, projLightToEye);
|
|
if (sqrProjLightToEyeLength < 1e-3*1e-3)
|
|
return;
|
|
|
|
// the scalar product of the glide slope up direction with the eye vector
|
|
float dotProd = dot(projLightToEye, light.normalCrossHorizontal);
|
|
float sinAngle = dotProd/sqrt(sqrProjLightToEyeLength);
|
|
if (sinAngle < -1)
|
|
sinAngle = -1;
|
|
if (1 < sinAngle)
|
|
sinAngle = 1;
|
|
|
|
float angleDeg = SGMiscf::rad2deg(asin(sinAngle));
|
|
light.draw(getColor(angleDeg));
|
|
}
|
|
|