00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifdef HAVE_CONFIG_H
00023 # include <simgear_config.h>
00024 #endif
00025
00026 #include <simgear/compiler.h>
00027
00028 #include "SGVasiDrawable.hxx"
00029
00030 struct SGVasiDrawable::LightData {
00031 LightData(const SGVec3f& p, const SGVec3f& n, const SGVec3f& up) :
00032 position(p),
00033 normal(n),
00034 horizontal(normalize(cross(up, n))),
00035 normalCrossHorizontal(normalize(cross(n, horizontal)))
00036 { }
00037
00038 void draw(const SGVec4f& color) const
00039 {
00040 glBegin(GL_POINTS);
00041 glColor4fv(color.data());
00042 glNormal3fv(normal.data());
00043 glVertex3fv(position.data());
00044 glEnd();
00045 }
00046
00047 SGVec3f position;
00048 SGVec3f normal;
00049 SGVec3f horizontal;
00050 SGVec3f normalCrossHorizontal;
00051 };
00052
00053 SGVasiDrawable::SGVasiDrawable(const SGVasiDrawable& vd, const osg::CopyOp&) :
00054 _lights(vd._lights),
00055 _red(vd._red),
00056 _white(vd._white)
00057 {
00058 setUseDisplayList(false);
00059 setSupportsDisplayList(false);
00060 }
00061
00062 SGVasiDrawable::SGVasiDrawable(const SGVec4f& red, const SGVec4f& white) :
00063 _red(red),
00064 _white(white)
00065 {
00066 setUseDisplayList(false);
00067 setSupportsDisplayList(false);
00068 }
00069
00070 void
00071 SGVasiDrawable::addLight(const SGVec3f& position, const SGVec3f& normal,
00072 const SGVec3f& up, float azimutDeg)
00073 {
00074 SGVec3f horizontal(normalize(cross(up, normal)));
00075 SGVec3f zeroGlideSlope = normalize(cross(horizontal, up));
00076 SGQuatf rotation = SGQuatf::fromAngleAxisDeg(azimutDeg, horizontal);
00077 SGVec3f azimutGlideSlope = rotation.transform(zeroGlideSlope);
00078 addLight(position, azimutGlideSlope, up);
00079 }
00080
00081 void
00082 SGVasiDrawable::addLight(const SGVec3f& position, const SGVec3f& normal,
00083 const SGVec3f& up)
00084 {
00085 _lights.push_back(LightData(position, normal, up));
00086 }
00087
00088 void
00089 SGVasiDrawable::drawImplementation(osg::RenderInfo& renderInfo) const
00090 {
00091
00092
00093
00094
00095 osg::Matrix m;
00096 m.invert(renderInfo.getState()->getModelViewMatrix());
00097 SGVec3f eyePoint(toSG(m.preMult(osg::Vec3(0, 0, 0))));
00098
00099
00100 for (unsigned i = 0; i < _lights.size(); ++i)
00101 draw(eyePoint, _lights[i]);
00102 }
00103
00104 osg::BoundingBox
00105 SGVasiDrawable::computeBound() const
00106 {
00107 osg::BoundingBox bb;
00108 for (unsigned i = 0; i < _lights.size(); ++i)
00109 bb.expandBy(toOsg(_lights[i].position));
00110
00111
00112 bb.expandBy(bb._min - osg::Vec3(1, 1, 1));
00113 bb.expandBy(bb._max + osg::Vec3(1, 1, 1));
00114 return bb;
00115 }
00116
00117 SGVec4f
00118 SGVasiDrawable::getColor(float angleDeg) const
00119 {
00120 float transDeg = 0.05f;
00121 if (angleDeg < -transDeg) {
00122 return _red;
00123 } else if (angleDeg < transDeg) {
00124 float fac = angleDeg*0.5f/transDeg + 0.5f;
00125 return _red + fac*(_white - _red);
00126 } else {
00127 return _white;
00128 }
00129 }
00130
00131 void
00132 SGVasiDrawable::draw(const SGVec3f& eyePoint, const LightData& light) const
00133 {
00134
00135 SGVec3f lightToEye = eyePoint - light.position;
00136
00137
00138 if (dot(lightToEye, light.normal) < SGLimitsf::min())
00139 return;
00140
00141
00142
00143 SGVec3f projLightToEye = lightToEye
00144 - light.horizontal*dot(lightToEye, light.horizontal);
00145
00146
00147 float sqrProjLightToEyeLength = dot(projLightToEye, projLightToEye);
00148 if (sqrProjLightToEyeLength < 1e-3*1e-3)
00149 return;
00150
00151
00152 float dotProd = dot(projLightToEye, light.normalCrossHorizontal);
00153 float sinAngle = dotProd/sqrt(sqrProjLightToEyeLength);
00154 if (sinAngle < -1)
00155 sinAngle = -1;
00156 if (1 < sinAngle)
00157 sinAngle = 1;
00158
00159 float angleDeg = SGMiscf::rad2deg(asin(sinAngle));
00160 light.draw(getColor(angleDeg));
00161 }
00162