-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Here's an implementation of airport runway lighting, including VASI /
PAPI lights, using OSG light points. You can choose to use point sprites
or OpenGL points at runtime, and the "enhanced runway lighting" function
is supported. The relative intensities of the lights will probably have
to be tweaked.
Tim
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org
iD8DBQFFaiYyeDhWHdXrDRURAn+CAJ0Tf6nMRkoO9ZIVHCbPtW5TJN0h1gCgs+vr
C6tAnsaa7P2Flr2Ug9bcx+c=
=j9Tv
-----END PGP SIGNATURE-----
Index: simgear/scene/material/mat.cxx
===================================================================
RCS file: /var/cvs/SimGear-0.3/source/simgear/scene/material/mat.cxx,v
retrieving revision 1.33
diff -d -u -p -r1.33 mat.cxx
--- simgear/scene/material/mat.cxx 10 Nov 2006 05:30:37 -0000 1.33
+++ simgear/scene/material/mat.cxx 26 Nov 2006 23:35:41 -0000
@@ -218,7 +218,9 @@ SGMaterial::init ()
specular[i] = (i < 3) ? 0.0 : 1.0;
diffuse[i] = (i < 3) ? 0.8 : 1.0;
emission[i] = (i < 3) ? 0.0 : 1.0;
+ lightPointColor[i] = 1.0f;
}
+ lightPointIntensity = 1.0f;
}
bool
Index: simgear/scene/material/mat.hxx
===================================================================
RCS file: /var/cvs/SimGear-0.3/source/simgear/scene/material/mat.hxx,v
retrieving revision 1.25
diff -d -u -p -r1.25 mat.hxx
--- simgear/scene/material/mat.hxx 29 Oct 2006 19:27:09 -0000 1.25
+++ simgear/scene/material/mat.hxx 26 Nov 2006 23:35:42 -0000
@@ -208,6 +208,26 @@ public:
*/
SGMaterialGlyph * get_glyph (const string& name) const;
+ /**
+ * Color and intensity for point lights.
+ */
+ inline void setLightPointColor(unsigned r, unsigned g, unsigned b)
+ {
+ lightPointColor[0] = ((float) r) / 255.0f;
+ lightPointColor[1] = ((float) g) / 255.0f;
+ lightPointColor[2] = ((float) b) / 255.0f;
+ lightPointColor[3] = 1.0f;
+ }
+
+ inline const SGVec4f &getLightPointColor() const { return lightPointColor; }
+
+ inline void setLightPointIntensity(unsigned i)
+ {
+ lightPointIntensity = ((float)i) / 255.0;
+ }
+
+ inline float getLightPointIntensity() const { return lightPointIntensity; }
+
protected:
@@ -274,6 +294,9 @@ private:
SGVec4f ambient, diffuse, specular, emission;
double shininess;
+ SGVec4f lightPointColor;
+ float lightPointIntensity;
+
// the list of names for this material. May be empty.
vector<string> _names;
Index: simgear/scene/material/matlib.cxx
===================================================================
RCS file: /var/cvs/SimGear-0.3/source/simgear/scene/material/matlib.cxx,v
retrieving revision 1.25
diff -d -u -p -r1.25 matlib.cxx
--- simgear/scene/material/matlib.cxx 10 Nov 2006 05:30:37 -0000 1.25
+++ simgear/scene/material/matlib.cxx 26 Nov 2006 23:35:42 -0000
@@ -214,91 +214,22 @@ bool SGMaterialLib::load( const string &
}
}
- osg::ref_ptr<osg::StateSet> lightStateSet = new osg::StateSet;
- {
- lightStateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
- lightStateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
-// lightStateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
-
- lightStateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
-
- lightStateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::OFF);
- lightStateSet->setAttribute(new osg::AlphaFunc(osg::AlphaFunc::GREATER, 0.01));
- lightStateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON);
-
- osg::CullFace* cullFace = new osg::CullFace;
- cullFace->setMode(osg::CullFace::BACK);
- lightStateSet->setAttributeAndModes(cullFace, osg::StateAttribute::ON);
-
- osg::BlendFunc* blendFunc = new osg::BlendFunc;
- blendFunc->setFunction(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_SRC_ALPHA);
- lightStateSet->setAttributeAndModes(blendFunc, osg::StateAttribute::ON);
-
- osg::PolygonMode* polygonMode = new osg::PolygonMode;
- polygonMode->setMode(osg::PolygonMode::FRONT, osg::PolygonMode::POINT);
- lightStateSet->setAttribute(polygonMode);
-
-// if (SGPointLightsUseSprites) {
- osg::PointSprite* pointSprite = new osg::PointSprite;
- lightStateSet->setTextureAttributeAndModes(0, pointSprite, osg::StateAttribute::ON);
-// }
-
-// if (SGPointLightsDistanceAttenuation) {
- osg::Point* point = new osg::Point;
- point->setMinSize(2);
- point->setSize(8);
- point->setDistanceAttenuation(osg::Vec3(1.0, 0.001, 0.000001));
- lightStateSet->setAttribute(point);
-// }
-
- osg::PolygonOffset* polygonOffset = new osg::PolygonOffset;
- polygonOffset->setFactor(-1);
- polygonOffset->setUnits(-1);
- lightStateSet->setAttributeAndModes(polygonOffset, osg::StateAttribute::ON);
-
- osg::TexGen* texGen = new osg::TexGen;
- texGen->setMode(osg::TexGen::SPHERE_MAP);
- lightStateSet->setTextureAttribute(0, texGen);
- lightStateSet->setTextureMode(0, GL_TEXTURE_GEN_S, osg::StateAttribute::ON);
- lightStateSet->setTextureMode(0, GL_TEXTURE_GEN_T, osg::StateAttribute::ON);
- osg::TexEnv* texEnv = new osg::TexEnv;
- texEnv->setMode(osg::TexEnv::MODULATE);
- lightStateSet->setTextureAttribute(0, texEnv);
-
- osg::Material* material = new osg::Material;
- lightStateSet->setAttribute(material);
- }
+ // The StateSets aren't actually used by the light point
+ // implementation, but it's probably dangerous not to have
+ // something in the material.
-
// hard coded ground light state
- osg::StateSet *gnd_lights = static_cast<osg::StateSet*>(lightStateSet->clone(osg::CopyOp::DEEP_COPY_ALL));
-// if (SGPointLightsDistanceAttenuation) {
- osg::Point* point = new osg::Point;
- point->setMinSize(1);
- point->setSize(2);
- point->setMaxSize(4);
- point->setDistanceAttenuation(osg::Vec3(1.0, 0.01, 0.0001));
- while (gnd_lights->getAttribute(osg::StateAttribute::POINT)) {
- gnd_lights->removeAttribute(osg::StateAttribute::POINT);
- }
- gnd_lights->setAttribute(point);
-// }
+ osg::StateSet *gnd_lights = new osg::StateSet;
m = new SGMaterial( gnd_lights );
m->add_name("GROUND_LIGHTS");
matlib["GROUND_LIGHTS"] = m;
// hard coded runway white light state
- osg::Texture2D* texture;
- if ( sprite_lighting ) {
- texture = gen_standard_light_sprite(235, 235, 195, 255);
- } else {
- texture = gen_standard_dir_light_map(235, 235, 195, 255);
- }
- osg::StateSet *rwy_white_lights = static_cast<osg::StateSet*>(lightStateSet->clone(osg::CopyOp::DEEP_COPY_ALL));
- rwy_white_lights->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
-
+ osg::StateSet *rwy_white_lights = new osg::StateSet;
m = new SGMaterial( rwy_white_lights );
m->add_name("RWY_WHITE_LIGHTS");
+ m->setLightPointColor(235, 235, 195);
+ m->setLightPointIntensity(255);
matlib["RWY_WHITE_LIGHTS"] = m;
// For backwards compatibility ... remove someday
m->add_name("RUNWAY_LIGHTS");
@@ -307,172 +238,117 @@ bool SGMaterialLib::load( const string &
matlib["RWY_LIGHTS"] = m;
// end of backwards compatitibilty
+ // Hard coded material for REIL lights
+ osg::StateSet *reil_lights = new osg::StateSet;
+ m = new SGMaterial( reil_lights );
+ m->add_name("RWY_REIL_LIGHTS");
+ m->setLightPointColor(235, 235, 195);
+ m->setLightPointIntensity(4096); // Will this work?
+ matlib["RWY_REIL_LIGHTS"] = m;
+
// hard coded runway medium intensity white light state
- if ( sprite_lighting ) {
- texture = gen_standard_light_sprite( 235, 235, 195, 205 );
- } else {
- texture = gen_standard_dir_light_map( 235, 235, 195, 205 );
- }
- osg::StateSet *rwy_white_medium_lights = static_cast<osg::StateSet*>(lightStateSet->clone(osg::CopyOp::DEEP_COPY_ALL));
- rwy_white_medium_lights->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
-
+ osg::StateSet *rwy_white_medium_lights = new osg::StateSet;
m = new SGMaterial( rwy_white_medium_lights );
+ m->setLightPointColor(235, 235, 195);
+ m->setLightPointIntensity(205);
m->add_name("RWY_WHITE_MEDIUM_LIGHTS");
matlib["RWY_WHITE_MEDIUM_LIGHTS"] = m;
// hard coded runway low intensity white light state
- if ( sprite_lighting ) {
- texture = gen_standard_light_sprite( 235, 235, 195, 155 );
- } else {
- texture = gen_standard_dir_light_map( 235, 235, 195, 155 );
- }
- osg::StateSet *rwy_white_low_lights = static_cast<osg::StateSet*>(lightStateSet->clone(osg::CopyOp::DEEP_COPY_ALL));
- rwy_white_medium_lights->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
+ osg::StateSet *rwy_white_low_lights = new osg::StateSet;
m = new SGMaterial( rwy_white_low_lights );
+ m->setLightPointColor(235, 235, 195);
+ m->setLightPointIntensity(155);
m->add_name("RWY_WHITE_LOW_LIGHTS");
matlib["RWY_WHITE_LOW_LIGHTS"] = m;
// hard coded runway yellow light state
- if ( sprite_lighting ) {
- texture = gen_standard_light_sprite( 235, 215, 20, 255 );
- } else {
- texture = gen_standard_dir_light_map( 235, 215, 20, 255 );
- }
- osg::StateSet *rwy_yellow_lights = static_cast<osg::StateSet*>(lightStateSet->clone(osg::CopyOp::DEEP_COPY_ALL));
- rwy_yellow_lights->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
+ osg::StateSet *rwy_yellow_lights = new osg::StateSet;
m = new SGMaterial( rwy_yellow_lights );
+ m->setLightPointColor(235, 215, 20);
+ m->setLightPointIntensity(255);
m->add_name("RWY_YELLOW_LIGHTS");
matlib["RWY_YELLOW_LIGHTS"] = m;
// hard coded runway medium intensity yellow light state
- if ( sprite_lighting ) {
- texture = gen_standard_light_sprite( 235, 215, 20, 205 );
- } else {
- texture = gen_standard_dir_light_map( 235, 215, 20, 205 );
- }
- osg::StateSet *rwy_yellow_medium_lights = static_cast<osg::StateSet*>(lightStateSet->clone(osg::CopyOp::DEEP_COPY_ALL));
- rwy_yellow_medium_lights->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
+ osg::StateSet *rwy_yellow_medium_lights = new osg::StateSet;
m = new SGMaterial( rwy_yellow_medium_lights );
+ m->setLightPointColor(235, 215, 20);
+ m->setLightPointIntensity(205);
m->add_name("RWY_YELLOW_MEDIUM_LIGHTS");
matlib["RWY_YELLOW_MEDIUM_LIGHTS"] = m;
// hard coded runway low intensity yellow light state
- if ( sprite_lighting ) {
- texture = gen_standard_light_sprite( 235, 215, 20, 155 );
- } else {
- texture = gen_standard_dir_light_map( 235, 215, 20, 155 );
- }
- osg::StateSet *rwy_yellow_low_lights = static_cast<osg::StateSet*>(lightStateSet->clone(osg::CopyOp::DEEP_COPY_ALL));
- rwy_yellow_low_lights->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
+ osg::StateSet *rwy_yellow_low_lights = new osg::StateSet;
m = new SGMaterial( rwy_yellow_low_lights );
+ m->setLightPointColor(235, 215, 20);
+ m->setLightPointIntensity(155);
m->add_name("RWY_YELLOW_LOW_LIGHTS");
matlib["RWY_YELLOW_LOW_LIGHTS"] = m;
// hard coded runway red light state
- if ( sprite_lighting ) {
- texture = gen_standard_light_sprite( 235, 90, 90, 255 );
- } else {
- texture = gen_standard_dir_light_map( 235, 90, 90, 255 );
- }
- osg::StateSet *rwy_red_lights = static_cast<osg::StateSet*>(lightStateSet->clone(osg::CopyOp::DEEP_COPY_ALL));
- rwy_red_lights->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
+ osg::StateSet *rwy_red_lights = new osg::StateSet;
m = new SGMaterial( rwy_red_lights );
+ m->setLightPointColor(235, 90, 90);
+ m->setLightPointIntensity(255);
m->add_name("RWY_RED_LIGHTS");
matlib["RWY_RED_LIGHTS"] = m;
// hard coded medium intensity runway red light state
- if ( sprite_lighting ) {
- texture = gen_standard_light_sprite( 235, 90, 90, 205 );
- } else {
- texture = gen_standard_dir_light_map( 235, 90, 90, 205 );
- }
- osg::StateSet *rwy_red_medium_lights = static_cast<osg::StateSet*>(lightStateSet->clone(osg::CopyOp::DEEP_COPY_ALL));
- rwy_red_medium_lights->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
+ osg::StateSet *rwy_red_medium_lights = new osg::StateSet;
m = new SGMaterial( rwy_red_medium_lights );
+ m->setLightPointColor(235, 90, 90);
+ m->setLightPointIntensity(205);
m->add_name("RWY_RED_MEDIUM_LIGHTS");
matlib["RWY_RED_MEDIUM_LIGHTS"] = m;
// hard coded low intensity runway red light state
- if ( sprite_lighting ) {
- texture = gen_standard_light_sprite( 235, 90, 90, 155 );
- } else {
- texture = gen_standard_dir_light_map( 235, 90, 90, 155 );
- }
- osg::StateSet *rwy_red_low_lights = static_cast<osg::StateSet*>(lightStateSet->clone(osg::CopyOp::DEEP_COPY_ALL));
- rwy_red_low_lights->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
+ osg::StateSet *rwy_red_low_lights = new osg::StateSet;
m = new SGMaterial( rwy_red_low_lights );
+ m->setLightPointColor(235, 90, 90);
+ m->setLightPointIntensity(155);
m->add_name("RWY_RED_LOW_LIGHTS");
matlib["RWY_RED_LOW_LIGHTS"] = m;
// hard coded runway green light state
- if ( sprite_lighting ) {
- texture = gen_standard_light_sprite( 20, 235, 20, 255 );
- } else {
- texture = gen_standard_dir_light_map( 20, 235, 20, 255 );
- }
- osg::StateSet *rwy_green_lights = static_cast<osg::StateSet*>(lightStateSet->clone(osg::CopyOp::DEEP_COPY_ALL));
- rwy_green_lights->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
+ osg::StateSet *rwy_green_lights = new osg::StateSet;
m = new SGMaterial( rwy_green_lights );
+ m->setLightPointColor(20, 235, 20);
+ m->setLightPointIntensity(255);
m->add_name("RWY_GREEN_LIGHTS");
matlib["RWY_GREEN_LIGHTS"] = m;
// hard coded medium intensity runway green light state
- if ( sprite_lighting ) {
- texture = gen_standard_light_sprite( 20, 235, 20, 205 );
- } else {
- texture = gen_standard_dir_light_map( 20, 235, 20, 205 );
- }
- osg::StateSet *rwy_green_medium_lights = static_cast<osg::StateSet*>(lightStateSet->clone(osg::CopyOp::DEEP_COPY_ALL));
- rwy_green_medium_lights->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
+ osg::StateSet *rwy_green_medium_lights = new osg::StateSet;
m = new SGMaterial( rwy_green_medium_lights );
+ m->setLightPointColor(20, 235, 20);
+ m->setLightPointIntensity(205);
m->add_name("RWY_GREEN_MEDIUM_LIGHTS");
matlib["RWY_GREEN_MEDIUM_LIGHTS"] = m;
// hard coded low intensity runway green light state
- if ( sprite_lighting ) {
- texture = gen_standard_light_sprite( 20, 235, 20, 155 );
- } else {
- texture = gen_standard_dir_light_map( 20, 235, 20, 155 );
- }
- osg::StateSet *rwy_green_low_lights = static_cast<osg::StateSet*>(lightStateSet->clone(osg::CopyOp::DEEP_COPY_ALL));
- rwy_green_low_lights->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
+ osg::StateSet *rwy_green_low_lights = new osg::StateSet;
m = new SGMaterial( rwy_green_low_lights );
+ m->setLightPointColor(20, 235, 20);
+ m->setLightPointIntensity(155);
m->add_name("RWY_GREEN_LOW_LIGHTS");
matlib["RWY_GREEN_LOW_LIGHTS"] = m;
m->add_name("RWY_GREEN_TAXIWAY_LIGHTS");
matlib["RWY_GREEN_TAXIWAY_LIGHTS"] = m;
// hard coded low intensity taxiway blue light state
- if ( sprite_lighting ) {
- texture = gen_standard_light_sprite( 90, 90, 235, 205 );
- } else {
- texture = gen_taxiway_dir_light_map( 90, 90, 235, 205 );
- }
- osg::StateSet *taxiway_blue_low_lights = static_cast<osg::StateSet*>(lightStateSet->clone(osg::CopyOp::DEEP_COPY_ALL));
- taxiway_blue_low_lights->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
+ osg::StateSet *taxiway_blue_low_lights = new osg::StateSet;
m = new SGMaterial( taxiway_blue_low_lights );
+ m->setLightPointColor(90, 90, 235);
+ m->setLightPointIntensity(205);
m->add_name("RWY_BLUE_TAXIWAY_LIGHTS");
matlib["RWY_BLUE_TAXIWAY_LIGHTS"] = m;
// hard coded runway vasi light state
- if ( sprite_lighting ) {
- texture = gen_standard_light_sprite( 235, 235, 195, 255 );
- } else {
- texture = gen_standard_dir_light_map( 235, 235, 195, 255 );
- }
- osg::StateSet *rwy_vasi_lights = static_cast<osg::StateSet*>(lightStateSet->clone(osg::CopyOp::DEEP_COPY_ALL));
-// if (SGPointLightsDistanceAttenuation) {
- point = new osg::Point;
- point->setMinSize(4);
- point->setSize(10);
- point->setDistanceAttenuation(osg::Vec3(1.0, 0.01, 0.0001));
- while (rwy_vasi_lights->getAttribute(osg::StateAttribute::POINT)) {
- rwy_vasi_lights->removeAttribute(osg::StateAttribute::POINT);
- }
- rwy_vasi_lights->setAttribute(point);
-// }
- rwy_vasi_lights->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
+ osg::StateSet *rwy_vasi_lights = new osg::StateSet;
m = new SGMaterial( rwy_vasi_lights );
+ m->setLightPointColor(235, 235, 195);
+ m->setLightPointIntensity(1024);
m->add_name("RWY_VASI_LIGHTS");
matlib["RWY_VASI_LIGHTS"] = m;
Index: simgear/scene/tgdb/Makefile.am
===================================================================
RCS file: /var/cvs/SimGear-0.3/source/simgear/scene/tgdb/Makefile.am,v
retrieving revision 1.4
diff -d -u -p -r1.4 Makefile.am
--- simgear/scene/tgdb/Makefile.am 30 Dec 2003 05:53:50 -0000 1.4
+++ simgear/scene/tgdb/Makefile.am 26 Nov 2006 23:35:43 -0000
@@ -10,13 +10,15 @@ include_HEADERS = \
obj.hxx \
pt_lights.hxx \
userdata.hxx \
- vasi.hxx
+ vasi.hxx \
+ VasiSector.hxx
libsgtgdb_a_SOURCES = \
apt_signs.cxx \
leaf.cxx \
obj.cxx \
pt_lights.cxx \
- userdata.cxx
+ userdata.cxx \
+ VasiSector.cxx
INCLUDES = -I$(top_srcdir)
Index: simgear/scene/tgdb/VasiSector.cxx
===================================================================
RCS file: simgear/scene/tgdb/VasiSector.cxx
diff -N simgear/scene/tgdb/VasiSector.cxx
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ simgear/scene/tgdb/VasiSector.cxx 26 Nov 2006 23:35:43 -0000
@@ -0,0 +1,54 @@
+// VasiSector.cxx
+//
+// Copyright (C) 2006 Tim Moore [EMAIL PROTECTED]
+//
+// 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.
+//
+// $Id: $
+
+#include "VasiSector.hxx"
+
+// Calculate a local coordinate system for the VASI light. The Z axis
+// is the up vector. The direction vector lies in the positive YZ plane.
+void VasiSector::computeMatrix()
+{
+ osg::Vec3 perp = direction ^ up;
+ perp.normalize();
+ osg::Vec3 coordSysY = up ^ perp;
+ coordSysY.normalize();
+ local_to_LP.set(perp[0], perp[1], perp[2], 0.0,
+ coordSysY[0], coordSysY[1], coordSysY[2], 0.0,
+ up[0], up[1], up[2], 0.0,
+ 0.0, 0.0, 0.0, 1.0);
+ // Project direction vector into the VASI coordinate system, then
+ // into YZ plane.
+ osg::Vec3 dirLocal = local_to_LP * direction;
+ tanDirection = dirLocal[2] / dirLocal[1];
+}
+
+float VasiSector::operator() (const osg::Vec3& eyeLocal) const
+{
+ // Tranform eyeLocal into the LightPoint frame
+ osg::Vec3 EPlp = local_to_LP * eyeLocal;
+ // In the Azimuth?
+ if (EPlp[1] <= 0.0f)
+ return 0.0f;
+ double tanEPlp = EPlp[2] / EPlp[1];
+ if (tanEPlp >= tanDirection)
+ return topSector ? 1.0f : 0.0f;
+ else
+ return topSector ? 0.0f : 1.0f;
+}
+
Index: simgear/scene/tgdb/VasiSector.hxx
===================================================================
RCS file: simgear/scene/tgdb/VasiSector.hxx
diff -N simgear/scene/tgdb/VasiSector.hxx
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ simgear/scene/tgdb/VasiSector.hxx 26 Nov 2006 23:35:43 -0000
@@ -0,0 +1,67 @@
+// VasiSector.hxx
+//
+// Copyright (C) 2006 Tim Moore [EMAIL PROTECTED]
+//
+// 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.
+//
+// $Id: $
+
+#ifndef VASISECTOR
+#define VASISECTOR 1
+
+#include <osgSim/Sector>
+
+// OSG LightPoint sector object for VASI / PAPI lights which avoids
+// percision problems with the OSG DirectionalSector.
+ class VasiSector : public osgSim::Sector {
+ public:
+ VasiSector() :
+ Sector(),
+ direction(0.0f, 1.0f, 0.0f),
+ up(0.0f, 0.0f, 1.0f),
+ tanDirection(0.0),
+ topSector(true) { computeMatrix(); }
+
+ VasiSector(const VasiSector& copy,
+ const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY) :
+ Sector(copy, copyop),
+ direction(copy.direction),
+ up(copy.up),
+ local_to_LP(copy.local_to_LP),
+ tanDirection(copy.tanDirection),
+ topSector(copy.topSector) {}
+
+ VasiSector(const osg::Vec3& _direction, const osg::Vec3& _up,
+ bool _topSector) :
+ Sector(),
+ direction(_direction),
+ up(_up),
+ topSector(_topSector) { computeMatrix(); }
+
+ META_Object(osgSim, VasiSector);
+ const osg::Vec3& getDirection() const { return direction; }
+ const osg::Vec3& getUp() const { return up; }
+ bool getTopSector() const { return topSector; }
+ virtual float operator() (const osg::Vec3& eyeLocal) const;
+
+ protected:
+ void computeMatrix();
+ osg::Vec3 direction ;
+ osg::Vec3 up;
+ osg::Matrix local_to_LP ;
+ double tanDirection;
+ bool topSector;
+ };
+ #endif
Index: simgear/scene/tgdb/pt_lights.cxx
===================================================================
RCS file: /var/cvs/SimGear-0.3/source/simgear/scene/tgdb/pt_lights.cxx,v
retrieving revision 1.12
diff -d -u -p -r1.12 pt_lights.cxx
--- simgear/scene/tgdb/pt_lights.cxx 10 Nov 2006 05:30:38 -0000 1.12
+++ simgear/scene/tgdb/pt_lights.cxx 26 Nov 2006 23:35:44 -0000
@@ -1,9 +1,11 @@
// pt_lights.cxx -- build a 'directional' light on the fly
//
// Written by Curtis Olson, started March 2002.
+// OSG version contributed by Tim Moore [EMAIL PROTECTED]
//
// Copyright (C) 2002 Curtis L. Olson - http://www.flightgear.org/~curt
//
+//
// 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
@@ -24,20 +26,33 @@
# include <simgear_config.h>
#endif
+#include <stdio.h>
#include <osg/Array>
#include <osg/Geometry>
#include <osg/Geode>
#include <osg/LOD>
+#include <osg/Matrixd>
#include <osg/MatrixTransform>
#include <osg/NodeCallback>
#include <osg/NodeVisitor>
#include <osg/Switch>
+#include <osgSim/BlinkSequence>
+#include <osgSim/LightPoint>
+#include <osgSim/LightPointNode>
+#include <osgSim/Sector>
+#include <osgUtil/CullVisitor>
+#include <osg/Material>
+#include <osg/PolygonOffset>
+#include <osg/StateSet>
+#include <osg/Texture2D>
+
#include <simgear/scene/material/mat.hxx>
#include <simgear/screen/extensions.hxx>
#include <simgear/math/sg_random.h>
#include "vasi.hxx"
+#include "VasiSector.hxx"
#include "pt_lights.hxx"
@@ -46,6 +61,34 @@ bool SGPointLightsUseSprites = false;
bool SGPointLightsEnhancedLighting = false;
bool SGPointLightsDistanceAttenuation = false;
+class EnhancedLightingCallback : public osg::NodeCallback
+{
+ public:
+ EnhancedLightingCallback(float intensity) :
+ _intensity(intensity), _lastEnhancedLighting(false) {}
+ EnhancedLightingCallback(const EnhancedLightingCallback &cb) :
+ _intensity(cb._intensity),
+ _lastEnhancedLighting(cb._lastEnhancedLighting) {}
+ virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
+ {
+ osgSim::LightPointNode *lpn
+ = static_cast<osgSim::LightPointNode *>(node);
+ if (_lastEnhancedLighting != SGPointLightsEnhancedLighting) {
+ _lastEnhancedLighting = SGPointLightsEnhancedLighting;
+ int numPoints = lpn->getNumLightPoints();
+ for (int i = 0; i < numPoints; i++) {
+ lpn->getLightPoint(i)._intensity
+ = (SGPointLightsEnhancedLighting ?
+ 4.0f * _intensity : _intensity);
+ }
+ }
+ traverse(node, nv);
+ }
+ protected:
+ virtual ~EnhancedLightingCallback() {}
+ float _intensity;
+ bool _lastEnhancedLighting;
+};
// Specify the way we want to draw directional point lights (assuming the
// appropriate extensions are available.)
@@ -58,434 +101,239 @@ void SGConfigureDirectionalLights( bool
SGPointLightsDistanceAttenuation = distance_attenuation;
}
-static void calc_center_point( const point_list &nodes,
- const int_list &pnt_i,
- Point3D& result ) {
- double minx = nodes[pnt_i[0]][0];
- double maxx = nodes[pnt_i[0]][0];
- double miny = nodes[pnt_i[0]][1];
- double maxy = nodes[pnt_i[0]][1];
- double minz = nodes[pnt_i[0]][2];
- double maxz = nodes[pnt_i[0]][2];
-
- for ( unsigned int i = 0; i < pnt_i.size(); ++i ) {
- Point3D pt = nodes[pnt_i[i]];
- if ( pt[0] < minx ) { minx = pt[0]; }
- if ( pt[0] > maxx ) { minx = pt[0]; }
- if ( pt[1] < miny ) { miny = pt[1]; }
- if ( pt[1] > maxy ) { miny = pt[1]; }
- if ( pt[2] < minz ) { minz = pt[2]; }
- if ( pt[2] > maxz ) { minz = pt[2]; }
- }
-
- result = Point3D((minx + maxx) / 2.0, (miny + maxy) / 2.0,
- (minz + maxz) / 2.0);
-}
-
-
-static osg::Node*
-gen_dir_light_group( const point_list &nodes,
- const point_list &normals,
- const int_list &pnt_i,
- const int_list &nml_i,
- const SGMaterial *mat,
- const osg::Vec3& up, bool vertical, bool vasi )
-{
- Point3D center;
- calc_center_point( nodes, pnt_i, center );
- // cout << center[0] << "," << center[1] << "," << center[2] << endl;
-
+// Stolen from matlib.cxx
+static osg::Texture2D*
+gen_standard_light_sprite( int r, int g, int b, int alpha ) {
+ const int env_tex_res = 32;
+ int half_res = env_tex_res / 2;
- // find a vector perpendicular to the normal.
- osg::Vec3 perp1;
- if ( !vertical ) {
- // normal isn't vertical so we can use up as our first vector
- perp1 = up;
- } else {
- // normal is vertical so we have to work a bit harder to
- // determine our first vector
- osg::Vec3 pt1(nodes[pnt_i[0]][0], nodes[pnt_i[0]][1],
- nodes[pnt_i[0]][2] );
- osg::Vec3 pt2(nodes[pnt_i[1]][0], nodes[pnt_i[1]][1],
- nodes[pnt_i[1]][2] );
+ osg::Image* image = new osg::Image;
+ image->allocateImage(env_tex_res, env_tex_res, 1,
+ GL_RGBA, GL_UNSIGNED_BYTE);
- perp1 = pt2 - pt1;
+ for ( int i = 0; i < env_tex_res; ++i ) {
+ for ( int j = 0; j < env_tex_res; ++j ) {
+ double x = (i - half_res) / (double)half_res;
+ double y = (j - half_res) / (double)half_res;
+ double dist = sqrt(x*x + y*y);
+ if ( dist > 1.0 ) { dist = 1.0; }
+ double bright = cos( dist * SGD_PI_2 );
+ if ( bright < 0.01 ) { bright = 0.0; }
+ unsigned char* env_map = image->data(i, j);
+ env_map[0] = r;
+ env_map[1] = g;
+ env_map[2] = b;
+ env_map[3] = (int)(bright * alpha);
+ }
}
- perp1.normalize();
-
- osg::Vec3Array *vl = new osg::Vec3Array;
- osg::Vec3Array *nl = new osg::Vec3Array;
- osg::Vec4Array *cl = new osg::Vec4Array;
-
- unsigned int i;
- for ( i = 0; i < pnt_i.size(); ++i ) {
- Point3D ppt = nodes[pnt_i[i]] - center;
- osg::Vec3 pt(ppt[0], ppt[1], ppt[2]);
- osg::Vec3 normal(normals[nml_i[i]][0], normals[nml_i[i]][1],
- normals[nml_i[i]][2] );
-
- // calculate a vector perpendicular to dir and up
- osg::Vec3 perp2 = normal^perp1;
- // front face
- osg::Vec3 tmp3 = pt;
- vl->push_back( tmp3 );
- tmp3 += perp1;
- vl->push_back( tmp3 );
- tmp3 += perp2;
- vl->push_back( tmp3 );
-
- nl->push_back( normal );
- nl->push_back( normal );
- nl->push_back( normal );
-
- cl->push_back(osg::Vec4(1, 1, 1, 1));
- cl->push_back(osg::Vec4(1, 1, 1, 0));
- cl->push_back(osg::Vec4(1, 1, 1, 0));
- }
+ osg::Texture2D* texture = new osg::Texture2D;
+ texture->setImage(image);
- osg::Geometry* geometry = new osg::Geometry;
- geometry->setName("Dir Lights " + mat->get_names().front());
- geometry->setVertexArray(vl);
- geometry->setNormalArray(nl);
- geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
- geometry->setColorArray(cl);
- geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
- geometry->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLES, 0, vl->size()));
- osg::Geode* geode = new osg::Geode;
- geode->addDrawable(geometry);
+ return texture;
+}
- if (vasi) {
- // this one is dynamic in its colors, so do not bother with dlists
- geometry->setUseDisplayList(false);
- geometry->setUseVertexBufferObjects(false);
- osg::Vec3 dir(normals[nml_i[0]][0], normals[nml_i[0]][1],
- normals[nml_i[0]][2]);
+typedef std::vector< osg::ref_ptr<osgSim::Sector> > SectorList;
- // calculate the reference position of this vasi and use it
- // to init the vasi structure
- Point3D ppt = nodes[pnt_i[0]] - center;
- osg::Vec3 pt(ppt[0], ppt[1], ppt[2]);
- // up is the "up" vector which is also
- // the reference center point of this tile. The reference
- // center + the coordinate of the first light gives the actual
- // location of the first light.
- pt += up;
+static osg::Vec3 point3d2Vec3(const Point3D &pt)
+{
+ return osg::Vec3(pt[0], pt[1], pt[2]);
+}
- // Set up the callback
- geode->setCullCallback(new SGVasiUpdateCallback(cl, pt, up, dir));
- }
+static osgSim::LightPointNode *
+gen_dir_light_node(const point_list &nodes,
+ const point_list &normals,
+ const int_list &pnt_i,
+ const int_list &nml_i,
+ const SGMaterial *mat,
+ const osg::Vec3& up, bool vertical,
+ float distance,
+ string *name = 0, float intensity = 0.0f)
+{
+ // Share sectors among the points.
+ SectorList sectors(normals.size());
- if ( mat != NULL ) {
- geode->setStateSet(mat->get_state());
+ // It is faster for the osg light point code not to deal with a
+ // sector. If the light directions are vertical, assume that it is
+ // OK to see them from any direction.
+ if (!vertical)
+ for (int i = 0; i < sectors.size(); i++) {
+ osg::Vec3 direction(normals[i][0], normals[i][1], normals[i][2]);
+ sectors[i] = new osgSim::DirectionalSector(direction, osg::PI,
+ osg::PI, 0.0f);
+ }
+ osgSim::LightPointNode *lpn = new osgSim::LightPointNode;
+ // Very large light points look stupid and just don't work well on
+ // some cards (e.g., > 19.0 on ATI FireGL)
+ lpn->setMaxPixelSize(10.0f);
+ osg::StateSet *stateSet = lpn->getOrCreateStateSet();
+ // OSG puts light points in a bin after transparent objects, but
+ // then they can't be seen through those objects (like the Cessna
+ // prop disk!). So, force the light points into an earlier bin.
+ if (stateSet->getBinNumber() != 9)
+ stateSet->setRenderBinDetails(9, "DepthSortedBin");
+ SGVec4f color(1.0f, 1.0f, 1.0f, 1.0f);
+ if (mat) {
+ color = mat->getLightPointColor();
+ if (intensity == 0.0f)
+ intensity = mat->getLightPointIntensity();
+ if (name)
+ lpn->setName(*name);
+ else
+ lpn->setName("Dir Lights " + mat->get_names().front());
} else {
SG_LOG( SG_TERRAIN, SG_ALERT, "Warning: material = NULL" );
}
-
- // put an LOD on each lighting component
- osg::LOD *lod = new osg::LOD;
- lod->addChild( geode, 0, 20000 );
-
- // create the transformation.
- osg::MatrixTransform *trans = new osg::MatrixTransform;
- trans->setMatrix(osg::Matrixd::translate(osg::Vec3d(center[0], center[1], center[2])));
- trans->addChild( lod );
-
- return trans;
+ for (int i = 0; i < pnt_i.size(); i++) {
+ osg::Vec3 position(nodes[pnt_i[i]][0],
+ nodes[pnt_i[i]][1],
+ nodes[pnt_i[i]][2]);
+ osgSim::LightPoint lp(true, position, color.osg(), intensity, .1f,
+ (vertical) ? 0 : sectors[nml_i[i]].get());
+ lpn->addLightPoint(lp);
+ }
+ lpn->setMaxVisibleDistance2(distance * distance);
+ // Set up as a cull callback to avoid changing all the light
+ // points if this node is not visible.
+ lpn->setCullCallback(new EnhancedLightingCallback(intensity));
+ return lpn;
}
-static osg::Node *gen_reil_lights( const point_list &nodes,
- const point_list &normals,
- const int_list &pnt_i,
- const int_list &nml_i,
- SGMaterialLib *matlib,
- const osg::Vec3& up )
+static osgSim::LightPointNode *
+gen_vasi_light_node(const point_list &nodes,
+ const point_list &normals,
+ const int_list &pnt_i,
+ const int_list &nml_i,
+ const SGMaterial *mat,
+ const osg::Vec3& up)
{
- Point3D center;
- calc_center_point( nodes, pnt_i, center );
- // cout << center[0] << "," << center[1] << "," << center[2] << endl;
-
- osg::Vec3 nup = up;
- nup.normalize();
-
- osg::Vec3Array *vl = new osg::Vec3Array;
- osg::Vec3Array *nl = new osg::Vec3Array;
- osg::Vec4Array *cl = new osg::Vec4Array;
-
- unsigned int i;
- for ( i = 0; i < pnt_i.size(); ++i ) {
- Point3D ppt = nodes[pnt_i[i]] - center;
- osg::Vec3 pt(ppt[0], ppt[1], ppt[2]);
- osg::Vec3 normal(normals[nml_i[i]][0], normals[nml_i[i]][1],
- normals[nml_i[i]][2] );
-
- // calculate a vector perpendicular to dir and up
- osg::Vec3 perp = normal^up;
-
- // front face
- osg::Vec3 tmp3 = pt;
- vl->push_back( tmp3 );
- tmp3 += nup;
- vl->push_back( tmp3 );
- tmp3 += perp;
- vl->push_back( tmp3 );
-
- nl->push_back( normal );
- nl->push_back( normal );
- nl->push_back( normal );
-
- cl->push_back(osg::Vec4(1, 1, 1, 1));
- cl->push_back(osg::Vec4(1, 1, 1, 0));
- cl->push_back(osg::Vec4(1, 1, 1, 0));
+ osgSim::LightPointNode *lpn = new osgSim::LightPointNode;
+ // XXX ATI FireGL hack
+ //lpn->setMaxPixelSize(19.0f);
+ lpn->setMaxPixelSize(15.0f);
+ osg::StateSet *stateSet = lpn->getOrCreateStateSet();
+ if (stateSet->getBinNumber() != 9)
+ stateSet->setRenderBinDetails(9, "DepthSortedBin");
+ SGVec4f whiteColor = mat->getLightPointColor();
+ SGVec4f redColor(whiteColor);
+ redColor[1] = redColor[2] = 0.0;
+ float intensity = 8.0;//mat->getLightPointIntensity()
+ lpn->setName("Dir Lights " + mat->get_names().front());
+ for (int i = 0; i < pnt_i.size(); i++) {
+ osg::ref_ptr<VasiSector> redSector
+ = new VasiSector(point3d2Vec3(normals[nml_i[i]]), up, false);
+ osg::ref_ptr<VasiSector> whiteSector
+ = new VasiSector(point3d2Vec3(normals[nml_i[i]]), up, true);
+ osg::Vec3 pnt = point3d2Vec3(nodes[pnt_i[i]]);
+ osgSim::LightPoint redLp(true, pnt, redColor.osg(),
+ intensity, .5f, redSector.get());
+ lpn->addLightPoint(redLp);
+ osgSim::LightPoint whiteLp(true, pnt, whiteColor.osg(),
+ intensity, .5f, whiteSector.get());
+ lpn->addLightPoint(whiteLp);
}
+ lpn->setMaxVisibleDistance2(20000 * 20000);
+ return lpn;
+}
- SGMaterial *mat = matlib->find( "RWY_WHITE_LIGHTS" );
-
- osg::Geometry* geometry = new osg::Geometry;
- geometry->setName("Reil Lights " + mat->get_names().front());
- geometry->setVertexArray(vl);
- geometry->setNormalArray(nl);
- geometry->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
- geometry->setColorArray(cl);
- geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
- geometry->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLES, 0, vl->size()));
- osg::Geode* geode = new osg::Geode;
- geode->addDrawable(geometry);
- if ( mat != NULL ) {
- geode->setStateSet( mat->get_state() );
- } else {
- SG_LOG( SG_TERRAIN, SG_ALERT,
- "Warning: can't find material = RWY_WHITE_LIGHTS" );
+static osgSim::LightPointNode
+*gen_reil_lights_node(const point_list &nodes, const point_list &normals,
+ const int_list &pnt_i, const int_list &nml_i,
+ SGMaterialLib *matlib, const osg::Vec3& up)
+{
+ SGMaterial *mat = matlib->find("RWY_WHITE_LIGHTS");
+ string name = "Reil Lights " + mat->get_names().front();
+ osgSim::LightPointNode *lpn
+ = gen_dir_light_node(nodes, normals, pnt_i, nml_i, mat, up, false,
+ 12000.0f, &name);
+ osgSim::BlinkSequence *blink = new osgSim::BlinkSequence;
+ blink->addPulse(.1, osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
+ blink->addPulse(.9, osg::Vec4(0.0f, 0.0f, 0.0f, 0.0f));
+ unsigned numPoints = lpn->getNumLightPoints();
+ for (int i = 0; i < numPoints; i++) {
+ lpn->getLightPoint(i)._blinkSequence = blink;
}
-
- // OSGFIXME
-// leaf->setCallback( SSG_CALLBACK_PREDRAW, StrobePreDraw );
-// leaf->setCallback( SSG_CALLBACK_POSTDRAW, StrobePostDraw );
-
- // OSGFIXME: implement an update callback that switches on/off
- // based on the osg::FrameStamp
- osg::Switch *reil = new osg::Switch;
-// reil->setDuration( 60 );
-// reil->setLimits( 0, 2 );
-// reil->setMode( SSG_ANIM_SHUTTLE );
-// reil->control( SSG_ANIM_START );
-
- // need to add this twice to work around an ssg bug
- reil->addChild(geode, true);
-
- // put an LOD on each lighting component
- osg::LOD *lod = new osg::LOD;
- lod->addChild( reil, 0, 12000 /*OSGFIXME: hardcoded here?*/);
-
- // create the transformation.
- osg::MatrixTransform *trans = new osg::MatrixTransform;
- trans->setMatrix(osg::Matrixd::translate(osg::Vec3d(center[0], center[1], center[2])));
- trans->addChild( lod );
-
- return trans;
+ return lpn;
}
-
-static osg::Node *gen_odals_lights( const point_list &nodes,
- const point_list &normals,
- const int_list &pnt_i,
- const int_list &nml_i,
- SGMaterialLib *matlib,
- const osg::Vec3& up )
+static osgSim::LightPointNode
+*gen_odals_lights_node(const point_list &nodes, const point_list &normals,
+ const int_list &pnt_i, const int_list &nml_i,
+ SGMaterialLib *matlib, const osg::Vec3& up)
{
- Point3D center;
- calc_center_point( nodes, pnt_i, center );
- // cout << center[0] << "," << center[1] << "," << center[2] << endl;
-
- // OSGFIXME: implement like above
-// osg::Switch *odals = new osg::Switch;
- osg::Group *odals = new osg::Group;
-
- // we don't want directional lights here
- SGMaterial *mat = matlib->find( "GROUND_LIGHTS" );
- if ( mat == NULL ) {
- SG_LOG( SG_TERRAIN, SG_ALERT,
- "Warning: can't material = GROUND_LIGHTS" );
+ SGMaterial *mat = matlib->find("GROUND_LIGHTS");
+ string name = "Odals Lights " + mat->get_names().front();
+ osgSim::LightPointNode *lpn
+ = gen_dir_light_node(nodes, normals, pnt_i, nml_i, mat, up, false,
+ 12000.0f, &name, 4.0f);
+ osgSim::SequenceGroup *seqGroup = new osgSim::SequenceGroup;
+ unsigned numPoints = lpn->getNumLightPoints();
+ // Assume that each light comes on for .1 seconds, next one comes
+ // on .25 seconds after (the start of this pulse).
+ // The last two lights are the runway end strobes and should fire
+ // simultaneously.
+ const double duration = .1;
+ const double phaseShift = .25;
+ double period = (numPoints - 1) * phaseShift;
+ osgSim::BlinkSequence *blink = 0;
+ for (int i = 0; i < numPoints - 1; i++) {
+ blink = new osgSim::BlinkSequence;
+ blink->addPulse(duration, osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
+ blink->addPulse(period - duration, osg::Vec4(0.0f, 0.0f, 0.0f, 0.0f));
+ blink->setSequenceGroup(seqGroup);
+ blink->setPhaseShift(i * phaseShift);
+ lpn->getLightPoint(i)._blinkSequence = blink;
}
+ lpn->getLightPoint(numPoints - 1)._blinkSequence = blink;
+ return lpn;
+}
- osg::Vec3Array *vl = new osg::Vec3Array;
- osg::Vec4Array *cl = new osg::Vec4Array;
-
- cl->push_back(osg::Vec4(1, 1, 1, 1));
-
- // center line strobes
- for ( unsigned i = pnt_i.size() - 1; i >= 2; --i ) {
- Point3D ppt = nodes[pnt_i[i]] - center;
- osg::Vec3 pt(ppt[0], ppt[1], ppt[2]);
- vl->push_back(pt);
+static osgSim::LightPointNode
+*gen_rabbit_lights_node(const point_list &nodes, const point_list &normals,
+ const int_list &pnt_i, const int_list &nml_i,
+ SGMaterialLib *matlib, const osg::Vec3& up)
+{
+ SGMaterial *mat = matlib->find("RWY_WHITE_LIGHTS");
+ string name = "Rabbit Lights " + mat->get_names().front();
+ osgSim::LightPointNode *lpn
+ = gen_dir_light_node(nodes, normals, pnt_i, nml_i, mat, up, false,
+ 12000.0f, &name, 4.0f);
+ osgSim::SequenceGroup *seqGroup = new osgSim::SequenceGroup;
+ unsigned numPoints = lpn->getNumLightPoints();
+ // Assume that each light comes on for .1 seconds, next one comes
+ // on .25 seconds after (the start of this pulse)
+ const double duration = .1;
+ const double phaseShift = .25;
+ double period = numPoints * phaseShift;
+ for (int i = 0; i <numPoints; i++) {
+ osgSim::BlinkSequence *blink = new osgSim::BlinkSequence;
+ blink->addPulse(duration, osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
+ blink->addPulse(period - duration, osg::Vec4(0.0f, 0.0f, 0.0f, 0.0f));
+ blink->setSequenceGroup(seqGroup);
+ blink->setPhaseShift(i * phaseShift);
+ lpn->getLightPoint(i)._blinkSequence = blink;
}
-
- // runway end strobes
-
- Point3D ppt = nodes[pnt_i[0]] - center;
- osg::Vec3 pt(ppt[0], ppt[1], ppt[2]);
- vl->push_back(pt);
-
- ppt = nodes[pnt_i[1]] - center;
- pt = osg::Vec3(ppt[0], ppt[1], ppt[2]);
- vl->push_back(pt);
-
- osg::Geometry* geometry = new osg::Geometry;
- geometry->setName("Odal Lights " + mat->get_names().front());
- geometry->setVertexArray(vl);
- geometry->setColorArray(cl);
- geometry->setColorBinding(osg::Geometry::BIND_OVERALL);
- geometry->addPrimitiveSet(new osg::DrawArrays(GL_POINTS, 0, vl->size()));
- osg::Geode* geode = new osg::Geode;
- geode->addDrawable(geometry);
-
- geode->setStateSet( mat->get_state() );
- // OSGFIXME
-// leaf->setCallback( SSG_CALLBACK_PREDRAW, StrobePreDraw );
-// leaf->setCallback( SSG_CALLBACK_POSTDRAW, StrobePostDraw );
-
- odals->addChild( geode );
-
- // setup animition
-
-// odals->setDuration( 10 );
-// odals->setLimits( 0, pnt_i.size() - 1 );
-// odals->setMode( SSG_ANIM_SHUTTLE );
-// odals->control( SSG_ANIM_START );
-
- // put an LOD on each lighting component
- osg::LOD *lod = new osg::LOD;
- lod->addChild( odals, 0, 12000 /*OSGFIXME hardcoded visibility*/ );
-
- // create the transformation.
- osg::MatrixTransform *trans = new osg::MatrixTransform;
- trans->setMatrix(osg::Matrixd::translate(osg::Vec3d(center[0], center[1], center[2])));
- trans->addChild(lod);
-
- return trans;
+ return lpn;
}
-class SGRabbitUpdateCallback : public osg::NodeCallback {
-public:
- SGRabbitUpdateCallback(double duration) :
- mBaseTime(sg_random()), mDuration(duration)
- {
- if (fabs(mDuration) < 1e-3)
- mDuration = 1e-3;
- mBaseTime -= mDuration*floor(mBaseTime/mDuration);
- }
-
- virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
- {
- assert(dynamic_cast<osg::Switch*>(node));
- osg::Switch* sw = static_cast<osg::Switch*>(node);
- double frameTime = nv->getFrameStamp()->getReferenceTime();
- double timeDiff = (frameTime - mBaseTime)/mDuration;
- double reminder = timeDiff - unsigned(floor(timeDiff));
- unsigned nChildren = sw->getNumChildren();
- unsigned activeChild = unsigned(nChildren*reminder);
- if (nChildren <= activeChild)
- activeChild = nChildren;
- sw->setSingleChildOn(activeChild);
-
- osg::NodeCallback::operator()(node, nv);
- }
+// Choose between the two light point implementations: points or sprites
+class SpriteCallback : public osg::NodeCallback
+{
public:
- double mBaseTime;
- double mDuration;
+ virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
+ {
+ osg::Switch *sw = static_cast<osg::Switch *>(node);
+ sw->setSingleChildOn(SGPointLightsUseSprites ? 1 : 0);
+ traverse(node, nv);
+ }
+protected:
+ ~SpriteCallback() {}
+
};
-
-static osg::Node *gen_rabbit_lights( const point_list &nodes,
- const point_list &normals,
- const int_list &pnt_i,
- const int_list &nml_i,
- SGMaterialLib *matlib,
- const osg::Vec3& up )
-{
- Point3D center;
- calc_center_point( nodes, pnt_i, center );
- // cout << center[0] << "," << center[1] << "," << center[2] << endl;
-
- osg::Vec3 nup = up;
- nup.normalize();
-
- // OSGFIXME: implement like above ...
- osg::Switch *rabbit = new osg::Switch;
- rabbit->setUpdateCallback(new SGRabbitUpdateCallback(10));
-
- SGMaterial *mat = matlib->find( "RWY_WHITE_LIGHTS" );
- if ( mat == NULL ) {
- SG_LOG( SG_TERRAIN, SG_ALERT,
- "Warning: can't material = RWY_WHITE_LIGHTS" );
- }
-
- for ( int i = pnt_i.size() - 1; i >= 0; --i ) {
- osg::Vec3Array *vl = new osg::Vec3Array;
- osg::Vec3Array *nl = new osg::Vec3Array;
- osg::Vec4Array *cl = new osg::Vec4Array;
-
-
- Point3D ppt = nodes[pnt_i[i]] - center;
- osg::Vec3 pt(ppt[0], ppt[1], ppt[2]);
- osg::Vec3 normal(normals[nml_i[i]][0], normals[nml_i[i]][1],
- normals[nml_i[i]][2] );
-
- // calculate a vector perpendicular to dir and up
- osg::Vec3 perp = normal^nup;
-
- // front face
- osg::Vec3 tmp3 = pt;
- vl->push_back( tmp3 );
- tmp3 += nup;
- vl->push_back( tmp3 );
- tmp3 += perp;
- vl->push_back( tmp3 );
-
- nl->push_back(normal);
-
- cl->push_back(osg::Vec4(1, 1, 1, 1));
- cl->push_back(osg::Vec4(1, 1, 1, 0));
- cl->push_back(osg::Vec4(1, 1, 1, 0));
-
- osg::Geometry* geometry = new osg::Geometry;
- geometry->setName("Rabbit Lights " + mat->get_names().front());
- geometry->setVertexArray(vl);
- geometry->setNormalArray(nl);
- geometry->setNormalBinding(osg::Geometry::BIND_OVERALL);
- geometry->setColorArray(cl);
- geometry->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
- geometry->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLES, 0, vl->size()));
- osg::Geode* geode = new osg::Geode;
- geode->addDrawable(geometry);
-
- geode->setStateSet( mat->get_state() );
-
- // OSGFIXME
-// leaf->setCallback( SSG_CALLBACK_PREDRAW, StrobePreDraw );
-// leaf->setCallback( SSG_CALLBACK_POSTDRAW, StrobePostDraw );
-
- rabbit->addChild( geode );
- }
-
-// rabbit->setDuration( 10 );
-// rabbit->setLimits( 0, pnt_i.size() - 1 );
-// rabbit->setMode( SSG_ANIM_SHUTTLE );
-// rabbit->control( SSG_ANIM_START );
-
- // put an LOD on each lighting component
- osg::LOD *lod = new osg::LOD;
- lod->addChild( rabbit, 0, 12000 /*OSGFIXME: hadcoded*/ );
-
- // create the transformation.
- osg::MatrixTransform *trans = new osg::MatrixTransform;
- trans->setMatrix(osg::Matrixd::translate(osg::Vec3d(center[0], center[1], center[2])));
- trans->addChild(lod);
-
- return trans;
-}
-
+static osg::ref_ptr<osg::Texture2D> spriteTexture;
+static osg::ref_ptr<SpriteCallback> spriteCallback;
osg::Node *SGMakeDirectionalLights( const point_list &nodes,
const point_list &normals,
@@ -499,29 +347,49 @@ osg::Node *SGMakeDirectionalLights( cons
nup.normalize();
SGMaterial *mat = matlib->find( material );
+ osgSim::LightPointNode *ptNode = 0;
if ( material == "RWY_REIL_LIGHTS" ) {
// cout << "found a reil" << endl;
- return gen_reil_lights( nodes, normals, pnt_i, nml_i,
- matlib, nup );
+ ptNode = gen_reil_lights_node( nodes, normals, pnt_i, nml_i,
+ matlib, nup );
} else if ( material == "RWY_ODALS_LIGHTS" ) {
// cout << "found a odals" << endl;
- return gen_odals_lights( nodes, normals, pnt_i, nml_i,
- matlib, nup );
+ ptNode = gen_odals_lights_node( nodes, normals, pnt_i, nml_i,
+ matlib, nup );
} else if ( material == "RWY_SEQUENCED_LIGHTS" ) {
// cout << "found a rabbit" << endl;
- return gen_rabbit_lights( nodes, normals, pnt_i, nml_i,
- matlib, nup );
+ ptNode = gen_rabbit_lights_node( nodes, normals, pnt_i, nml_i,
+ matlib, nup );
} else if ( material == "RWY_VASI_LIGHTS" ) {
- return gen_dir_light_group( nodes, normals, pnt_i,
- nml_i, mat, nup, false, true );
+ ptNode = gen_vasi_light_node( nodes, normals, pnt_i, nml_i, mat, nup );
} else if ( material == "RWY_BLUE_TAXIWAY_LIGHTS" ) {
- return gen_dir_light_group( nodes, normals, pnt_i, nml_i, mat, nup,
- true, false );
+ ptNode = gen_dir_light_node( nodes, normals, pnt_i, nml_i, mat, nup,
+ true, 20000.0f );
} else {
- return gen_dir_light_group( nodes, normals, pnt_i, nml_i, mat, nup,
- false, false );
+ ptNode = gen_dir_light_node( nodes, normals, pnt_i, nml_i, mat, nup,
+ false, 20000.0f);
}
-
- return NULL;
+ // Clone the LightPointNode so we can create a version that uses
+ // point sprites
+ osgSim::LightPointNode *spriteNode
+ = static_cast<osgSim::LightPointNode *>(ptNode->clone(osg::CopyOp::DEEP_COPY_STATESETS
+ | osg::CopyOp::DEEP_COPY_STATEATTRIBUTES));
+ spriteNode->setPointSprite();
+ EnhancedLightingCallback *cb
+ = static_cast<EnhancedLightingCallback *>(ptNode->getCullCallback());
+ if (cb)
+ spriteNode->setCullCallback(new EnhancedLightingCallback(*cb));
+ osg::Switch *sw = new osg::Switch;
+ osg::StateSet *stateSet = sw->getOrCreateStateSet();
+ if (!spriteTexture.valid())
+ spriteTexture = gen_standard_light_sprite(255, 255, 255, 255);
+ stateSet->setTextureAttributeAndModes(0, spriteTexture.get(),
+ osg::StateAttribute::OFF);
+ sw->addChild(ptNode, true);
+ sw->addChild(spriteNode, false);
+ if (!spriteCallback.valid())
+ spriteCallback = new SpriteCallback();
+ sw->setUpdateCallback(spriteCallback.get());
+ return sw;
}
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Flightgear-devel mailing list
Flightgear-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/flightgear-devel