// Written by Curtis Olson, started December 1997.
// SSG-ified by Curtis Olson, February 2000.
//
-// Copyright (C) 1997-2000 Curtis L. Olson - curt@flightgear.org
+// Copyright (C) 1997-2000 Curtis L. Olson - http://www.flightgear.org/~curt
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Library General Public License for more details.
//
-// You should have received a copy of the GNU Library General Public
-// License along with this library; if not, write to the
-// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-// Boston, MA 02111-1307, USA.
-//
-// $Id$
-
+// 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
-#ifdef HAVE_WINDOWS_H
-# include <windows.h>
-#endif
-
#include <math.h>
+#include <iterator>
-#include <GL/gl.h>
+#include <simgear/compiler.h>
-#include <plib/sg.h>
+#include <osg/Array>
+#include <osg/Geode>
+#include <osg/Geometry>
+#include <osg/Node>
+#include <osg/Math>
+#include <osg/MatrixTransform>
+#include <osg/Material>
+#include <osg/ShadeModel>
+#include <osg/PrimitiveSet>
#include <simgear/debug/logstream.hxx>
+#include <simgear/math/Math.hxx>
+#include <simgear/scene/util/VectorArrayAdapter.hxx>
#include "dome.hxx"
-
-#ifdef __MWERKS__
-# pragma global_optimizer off
-#endif
-
+using namespace osg;
+using namespace simgear;
// proportions of max dimensions fed to the build() routine
static const float center_elev = 1.0;
-static const float upper_radius = 0.6;
-static const float upper_elev = 0.15;
+namespace
+{
+struct DomeParam
+{
+ float radius;
+ float elev;
+} domeParams[] = {{.5, .8660}, // 60deg from horizon
+ {.8660, .5}, // 30deg from horizon
+ // Original dome horizon vertices
+ {0.9701, 0.2425}, {0.9960, 0.0885},
+ {1.0, 0.0}, {0.9922, -0.1240}};
+
+const int numRings = sizeof(domeParams) / sizeof(domeParams[0]);
+const int numBands = 12;
+const int halfBands = numBands/2;
+}
-static const float middle_radius = 0.9;
-static const float middle_elev = 0.08;
+static const float upper_radius = 0.9701; // (.6, 0.15)
+static const float upper_elev = 0.2425;
+
+static const float middle_radius = 0.9960; // (.9, .08)
+static const float middle_elev = 0.0885;
static const float lower_radius = 1.0;
static const float lower_elev = 0.0;
-static const float bottom_radius = 0.8;
-static const float bottom_elev = -0.1;
-
-
-// Set up dome rendering callbacks
-static int sgSkyDomePreDraw( ssgEntity *e ) {
- /* cout << endl << "Dome Pre Draw" << endl << "----------------"
- << endl << endl; */
-
- ssgLeaf *f = (ssgLeaf *)e;
- if ( f -> hasState () ) f->getState()->apply() ;
-
- glPushAttrib( GL_DEPTH_BUFFER_BIT | GL_FOG_BIT );
- // cout << "push error = " << glGetError() << endl;
-
- glDisable( GL_DEPTH_TEST );
- glDisable( GL_FOG );
-
- return true;
-}
-
-static int sgSkyDomePostDraw( ssgEntity *e ) {
- /* cout << endl << "Dome Post Draw" << endl << "----------------"
- << endl << endl; */
-
- glPopAttrib();
- // cout << "pop error = " << glGetError() << endl;
-
- return true;
-}
+static const float bottom_radius = 0.9922; // (.8, -.1)
+static const float bottom_elev = -0.1240;
// Constructor
SGSkyDome::SGSkyDome( void ) {
+ asl = 0;
}
SGSkyDome::~SGSkyDome( void ) {
}
+// Generate indices for a dome mesh. Assume a center vertex at 0, then
+// rings of vertices. Each ring's vertices are stored together. An
+// even number of longitudinal bands are assumed.
-// initialize the sky object and connect it into our scene graph
-ssgBranch * SGSkyDome::build( double hscale, double vscale ) {
- sgVec4 color;
-
- double theta;
- int i;
-
- // set up the state
- dome_state = new ssgSimpleState();
- dome_state->setShadeModel( GL_SMOOTH );
- dome_state->disable( GL_LIGHTING );
- dome_state->disable( GL_CULL_FACE );
- dome_state->disable( GL_TEXTURE_2D );
- dome_state->enable( GL_COLOR_MATERIAL );
- dome_state->setColourMaterial( GL_AMBIENT_AND_DIFFUSE );
- dome_state->setMaterial( GL_EMISSION, 0, 0, 0, 1 );
- dome_state->setMaterial( GL_SPECULAR, 0, 0, 0, 1 );
- dome_state->disable( GL_BLEND );
- dome_state->disable( GL_ALPHA_TEST );
-
- // initialize arrays
- center_disk_vl = new ssgVertexArray( 14 );
- center_disk_cl = new ssgColourArray( 14 );
-
- upper_ring_vl = new ssgVertexArray( 26 );
- upper_ring_cl = new ssgColourArray( 26 );
-
- middle_ring_vl = new ssgVertexArray( 26 );
- middle_ring_cl = new ssgColourArray( 26 );
-
- lower_ring_vl = new ssgVertexArray( 26 );
- lower_ring_cl = new ssgColourArray( 26 );
-
- // initially seed to all blue
- sgSetVec4( color, 0.0, 0.0, 1.0, 1.0 );
-
- // generate the raw vertex data
- sgVec3 center_vertex;
- sgVec3 upper_vertex[12];
- sgVec3 middle_vertex[12];
- sgVec3 lower_vertex[12];
- sgVec3 bottom_vertex[12];
-
- sgSetVec3( center_vertex, 0.0, 0.0, center_elev * vscale );
-
- for ( i = 0; i < 12; i++ ) {
- theta = (i * 30.0) * SGD_DEGREES_TO_RADIANS;
-
- sgSetVec3( upper_vertex[i],
- cos(theta) * upper_radius * hscale,
- sin(theta) * upper_radius * hscale,
- upper_elev * vscale );
-
- sgSetVec3( middle_vertex[i],
- cos(theta) * middle_radius * hscale,
- sin(theta) * middle_radius * hscale,
- middle_elev * vscale );
-
- sgSetVec3( lower_vertex[i],
- cos(theta) * lower_radius * hscale,
- sin(theta) * lower_radius * hscale,
- lower_elev * vscale );
-
- sgSetVec3( bottom_vertex[i],
- cos(theta) * bottom_radius * hscale,
- sin(theta) * bottom_radius * hscale,
- bottom_elev * vscale );
+namespace
+{
+// Calculate the index of a vertex in the grid by using its address in
+// the array that holds its location.
+struct GridIndex
+{
+ VectorArrayAdapter<Vec3Array> gridAdapter;
+ Vec3Array& grid;
+ GridIndex(Vec3Array& array, int rowStride, int baseOffset) :
+ gridAdapter(array, rowStride, baseOffset), grid(array)
+ {
}
-
- // generate the center disk vertex/color arrays
- center_disk_vl->add( center_vertex );
- center_disk_cl->add( color );
- for ( i = 11; i >= 0; i-- ) {
- center_disk_vl->add( upper_vertex[i] );
- center_disk_cl->add( color );
+ unsigned short operator() (int ring, int band)
+ {
+ return (unsigned short)(&gridAdapter(ring, band) - &grid[0]);
}
- center_disk_vl->add( upper_vertex[11] );
- center_disk_cl->add( color );
-
- // generate the upper ring
- for ( i = 0; i < 12; i++ ) {
- upper_ring_vl->add( middle_vertex[i] );
- upper_ring_cl->add( color );
-
- upper_ring_vl->add( upper_vertex[i] );
- upper_ring_cl->add( color );
+};
+}
+void SGSkyDome::makeDome(int rings, int bands, DrawElementsUShort& elements)
+{
+ std::back_insert_iterator<DrawElementsUShort> pusher
+ = std::back_inserter(elements);
+ GridIndex grid(*dome_vl, numBands, 1);
+ for (int i = 0; i < bands; i += 2) {
+ *pusher = 0; *pusher = grid(0, i); *pusher = grid(0, i + 1);
+ // down a band
+ for (int j = 0; j < rings - 1; ++j) {
+ *pusher = grid(j, i); *pusher = grid(j, i + 1);
+ *pusher = grid(j + 1, i + 1);
+ *pusher = grid(j, i); *pusher = grid(j + 1, i + 1);
+ *pusher = grid(j + 1, i);
+ }
+ // and up the next one
+ for (int j = rings - 1; j > 0; --j) {
+ *pusher = grid(j, i + 1); *pusher = grid(j - 1, i + 1);
+ *pusher = grid(j, (i + 2) % bands);
+ *pusher = grid(j, (i + 2) % bands); *pusher = grid(j - 1, i + 1);
+ *pusher = grid(j - 1, (i + 2) % bands);
+ }
+ *pusher = grid(0, i + 1); *pusher = 0;
+ *pusher = grid(0, (i + 2) % bands);
}
- upper_ring_vl->add( middle_vertex[0] );
- upper_ring_cl->add( color );
-
- upper_ring_vl->add( upper_vertex[0] );
- upper_ring_cl->add( color );
-
- // generate middle ring
- for ( i = 0; i < 12; i++ ) {
- middle_ring_vl->add( lower_vertex[i] );
- middle_ring_cl->add( color );
+}
- middle_ring_vl->add( middle_vertex[i] );
- middle_ring_cl->add( color );
- }
- middle_ring_vl->add( lower_vertex[0] );
- middle_ring_cl->add( color );
+// initialize the sky object and connect it into our scene graph
+osg::Node*
+SGSkyDome::build( double hscale, double vscale ) {
- middle_ring_vl->add( middle_vertex[0] );
- middle_ring_cl->add( color );
+ osg::Geode* geode = new osg::Geode;
- // generate lower ring
- for ( i = 0; i < 12; i++ ) {
- lower_ring_vl->add( bottom_vertex[i] );
- lower_ring_cl->add( color );
+ // set up the state
+ osg::StateSet* stateSet = geode->getOrCreateStateSet();
+ stateSet->setRenderBinDetails(-10, "RenderBin");
+
+ osg::ShadeModel* shadeModel = new osg::ShadeModel;
+ shadeModel->setMode(osg::ShadeModel::SMOOTH);
+ stateSet->setAttributeAndModes(shadeModel);
+ stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
+ stateSet->setMode(GL_FOG, osg::StateAttribute::OFF);
+ stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
+ stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
+ stateSet->setMode(GL_BLEND, osg::StateAttribute::OFF);
+ stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::OFF);
+ osg::Material* material = new osg::Material;
+ stateSet->setAttribute(material);
+
+ dome_vl = new osg::Vec3Array(1 + numRings * numBands);
+ dome_cl = new osg::Vec3Array(1 + numRings * numBands);
+ // generate the raw vertex data
- lower_ring_vl->add( lower_vertex[i] );
- lower_ring_cl->add( color );
+ (*dome_vl)[0].set(0.0, 0.0, center_elev * vscale);
+ simgear::VectorArrayAdapter<Vec3Array> vertices(*dome_vl, numBands, 1);
+
+ for ( int i = 0; i < numBands; ++i ) {
+ double theta = (i * 30) * SGD_DEGREES_TO_RADIANS;
+ double sTheta = hscale*sin(theta);
+ double cTheta = hscale*cos(theta);
+ for (int j = 0; j < numRings; ++j) {
+ vertices(j, i).set(cTheta * domeParams[j].radius,
+ sTheta * domeParams[j].radius,
+ domeParams[j].elev * vscale);
+ }
}
- lower_ring_vl->add( bottom_vertex[0] );
- lower_ring_cl->add( color );
-
- lower_ring_vl->add( lower_vertex[0] );
- lower_ring_cl->add( color );
+ DrawElementsUShort* domeElements
+ = new osg::DrawElementsUShort(GL_TRIANGLES);
+ makeDome(numRings, numBands, *domeElements);
+ osg::Geometry* geom = new Geometry;
+ geom->setName("Dome Elements");
+ geom->setUseDisplayList(false);
+ geom->setVertexArray(dome_vl.get());
+ geom->setColorArray(dome_cl.get());
+ geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
+ geom->setNormalBinding(osg::Geometry::BIND_OFF);
+ geom->addPrimitiveSet(domeElements);
+ geode->addDrawable(geom);
// force a repaint of the sky colors with ugly defaults
- sgVec4 fog_color;
- sgSetVec4( fog_color, 1.0, 1.0, 1.0, 1.0 );
- repaint( color, fog_color, 0.0, 5000.0 );
-
- // build the ssg scene graph sub tree for the sky and connected
- // into the provide scene graph branch
- ssgVtxTable *center_disk, *upper_ring, *middle_ring, *lower_ring;
-
- center_disk = new ssgVtxTable( GL_TRIANGLE_FAN,
- center_disk_vl, NULL, NULL, center_disk_cl );
+ repaint(SGVec3f(1, 1, 1), SGVec3f(1, 1, 1), SGVec3f(1, 1, 1), 0.0, 5000.0 );
+ dome_transform = new osg::MatrixTransform;
+ dome_transform->addChild(geode);
- upper_ring = new ssgVtxTable( GL_TRIANGLE_STRIP,
- upper_ring_vl, NULL, NULL, upper_ring_cl );
-
- middle_ring = new ssgVtxTable( GL_TRIANGLE_STRIP,
- middle_ring_vl, NULL, NULL, middle_ring_cl );
-
- lower_ring = new ssgVtxTable( GL_TRIANGLE_STRIP,
- lower_ring_vl, NULL, NULL, lower_ring_cl );
-
- center_disk->setState( dome_state );
- upper_ring->setState( dome_state );
- middle_ring->setState( dome_state );
- lower_ring->setState( dome_state );
-
- dome_transform = new ssgTransform;
- dome_transform->addKid( center_disk );
- dome_transform->addKid( upper_ring );
- dome_transform->addKid( middle_ring );
- dome_transform->addKid( lower_ring );
-
- // not entirely satisfying. We are depending here that the first
- // thing we add to a parent is the first drawn
- center_disk->setCallback( SSG_CALLBACK_PREDRAW, sgSkyDomePreDraw );
- center_disk->setCallback( SSG_CALLBACK_POSTDRAW, sgSkyDomePostDraw );
-
- upper_ring->setCallback( SSG_CALLBACK_PREDRAW, sgSkyDomePreDraw );
- upper_ring->setCallback( SSG_CALLBACK_POSTDRAW, sgSkyDomePostDraw );
-
- middle_ring->setCallback( SSG_CALLBACK_PREDRAW, sgSkyDomePreDraw );
- middle_ring->setCallback( SSG_CALLBACK_POSTDRAW, sgSkyDomePostDraw );
-
- lower_ring->setCallback( SSG_CALLBACK_PREDRAW, sgSkyDomePreDraw );
- lower_ring->setCallback( SSG_CALLBACK_POSTDRAW, sgSkyDomePostDraw );
+ return dome_transform.get();
+}
- return dome_transform;
+static void fade_to_black(osg::Vec3 sky_color[], float asl, int count) {
+ const float ref_asl = 10000.0f;
+ const float d = exp( - asl / ref_asl );
+ for(int i = 0; i < count ; i++)
+ sky_color[i] *= d;
}
+inline void clampColor(osg::Vec3& color)
+{
+ color.x() = osg::clampTo(color.x(), 0.0f, 1.0f);
+ color.y() = osg::clampTo(color.y(), 0.0f, 1.0f);
+ color.z() = osg::clampTo(color.z(), 0.0f, 1.0f);
+}
// repaint the sky colors based on current value of sun_angle, sky,
// and fog colors. This updates the color arrays for ssgVtxTable.
// 0 degrees = high noon
// 90 degrees = sun rise/set
// 180 degrees = darkest midnight
-bool SGSkyDome::repaint( sgVec4 sky_color, sgVec4 fog_color, double sun_angle,
- double vis )
+bool
+SGSkyDome::repaint( const SGVec3f& sun_color, const SGVec3f& sky_color,
+ const SGVec3f& fog_color, double sun_angle, double vis )
{
- double diff, prev_sun_angle = 999.0;
- sgVec3 outer_param, outer_amt, outer_diff;
- sgVec3 middle_param, middle_amt, middle_diff;
- int i, j;
-
- if (prev_sun_angle == sun_angle)
- return true;
-
- prev_sun_angle = sun_angle;
+ SGVec3f outer_param, outer_diff;
+ SGVec3f middle_param, middle_diff;
// Check for sunrise/sunset condition
- if (sun_angle > 80.0) // && (sun_angle < 100.0) )
- {
+ if (sun_angle > 80) {
// 0.0 - 0.4
- sgSetVec3( outer_param,
- (10.0 - fabs(90.0 - sun_angle)) / 20.0,
- (10.0 - fabs(90.0 - sun_angle)) / 40.0,
- -(10.0 - fabs(90.0 - sun_angle)) / 30.0 );
-
- sgSetVec3( middle_param,
- (10.0 - fabs(90.0 - sun_angle)) / 40.0,
- (10.0 - fabs(90.0 - sun_angle)) / 80.0,
- 0.0 );
-
- sgScaleVec3( outer_diff, outer_param, 1.0 / 6.0 );
-
- sgScaleVec3( middle_diff, middle_param, 1.0 / 6.0 );
+ double sunAngleFactor = 10.0 - fabs(90.0 - sun_angle);
+ static const SGVec3f outerConstant(1.0 / 20.0, 1.0 / 40.0, -1.0 / 30.0);
+ static const SGVec3f middleConstant(1.0 / 40.0, 1.0 / 80.0, 0.0);
+ outer_param = sunAngleFactor * outerConstant;
+ middle_param = sunAngleFactor * middleConstant;
+ outer_diff = (1.0 / 6.0) * outer_param;
+ middle_diff = (1.0 / 6.0) * middle_param;
} else {
- sgSetVec3( outer_param, 0.0, 0.0, 0.0 );
- sgSetVec3( middle_param, 0.0, 0.0, 0.0 );
-
- sgSetVec3( outer_diff, 0.0, 0.0, 0.0 );
- sgSetVec3( middle_diff, 0.0, 0.0, 0.0 );
+ outer_param = SGVec3f(0, 0, 0);
+ middle_param = SGVec3f(0, 0, 0);
+ outer_diff = SGVec3f(0, 0, 0);
+ middle_diff = SGVec3f(0, 0, 0);
}
// printf(" outer_red_param = %.2f outer_red_diff = %.2f\n",
// outer_red_param, outer_red_diff);
// calculate transition colors between sky and fog
- sgCopyVec3( outer_amt, outer_param );
- sgCopyVec3( middle_amt, middle_param );
+ SGVec3f outer_amt = outer_param;
+ SGVec3f middle_amt = middle_param;
//
// First, recalulate the basic colors
//
- sgVec4 center_color;
- sgVec4 upper_color[12];
- sgVec4 middle_color[12];
- sgVec4 lower_color[12];
- sgVec4 bottom_color[12];
-
- double vis_factor, cvf = vis;
-
- if (cvf > 45000)
- cvf = 45000;
-
- if ( vis < 3000.0 ) {
- vis_factor = (vis - 1000.0) / 2000.0;
- if ( vis_factor < 0.0 ) {
- vis_factor = 0.0;
- }
- } else {
- vis_factor = 1.0;
- }
-
- for ( j = 0; j < 3; j++ ) {
- diff = sky_color[j] - fog_color[j];
- center_color[j] = sky_color[j] - diff * ( 1.0 - vis_factor );
- }
- center_color[3] = 1.0;
-
- for ( i = 0; i < 6; i++ ) {
- for ( j = 0; j < 3; j++ ) {
- diff = sky_color[j] - fog_color[j];
-
- // printf("sky = %.2f fog = %.2f diff = %.2f\n",
- // l->sky_color[j], l->fog_color[j], diff);
-
- upper_color[i][j] = sky_color[j] - diff *
- ( 1.0 - vis_factor * (0.7 + 0.3 * cvf/45000) );
- middle_color[i][j] = sky_color[j] - diff *
- ( 1.0 - vis_factor * (0.1 + 0.85 * cvf/45000) )
- + middle_amt[j];
- lower_color[i][j] = fog_color[j] + outer_amt[j];
-
- if ( upper_color[i][j] > 1.0 ) { upper_color[i][j] = 1.0; }
- if ( upper_color[i][j] < 0.0 ) { upper_color[i][j] = 0.0; }
- if ( middle_color[i][j] > 1.0 ) { middle_color[i][j] = 1.0; }
- if ( middle_color[i][j] < 0.0 ) { middle_color[i][j] = 0.0; }
- if ( lower_color[i][j] > 1.0 ) { lower_color[i][j] = 1.0; }
- if ( lower_color[i][j] < 0.0 ) { lower_color[i][j] = 0.0; }
- }
- upper_color[i][3] = middle_color[i][3] = lower_color[i][3] = 1.0;
-
- for ( j = 0; j < 3; j++ ) {
- outer_amt[j] -= outer_diff[j];
- middle_amt[j] -= middle_diff[j];
- }
-
- /*
- printf("upper_color[%d] = %.2f %.2f %.2f %.2f\n", i, upper_color[i][0],
- upper_color[i][1], upper_color[i][2], upper_color[i][3]);
- printf("middle_color[%d] = %.2f %.2f %.2f %.2f\n", i,
- middle_color[i][0], middle_color[i][1], middle_color[i][2],
- middle_color[i][3]);
- printf("lower_color[%d] = %.2f %.2f %.2f %.2f\n", i,
- lower_color[i][0], lower_color[i][1], lower_color[i][2],
- lower_color[i][3]);
- */
- }
-
- sgSetVec3( outer_amt, 0.0, 0.0, 0.0 );
- sgSetVec3( middle_amt, 0.0, 0.0, 0.0 );
-
- for ( i = 6; i < 12; i++ ) {
- for ( j = 0; j < 3; j++ ) {
- diff = sky_color[j] - fog_color[j];
-
- // printf("sky = %.2f fog = %.2f diff = %.2f\n",
- // sky_color[j], fog_color[j], diff);
-
- upper_color[i][j] = sky_color[j] - diff *
- ( 1.0 - vis_factor * (0.7 + 0.3 * cvf/45000) );
- middle_color[i][j] = sky_color[j] - diff *
- ( 1.0 - vis_factor * (0.1 + 0.85 * cvf/45000) )
- + middle_amt[j];
- lower_color[i][j] = fog_color[j] + outer_amt[j];
-
- if ( upper_color[i][j] > 1.0 ) { upper_color[i][j] = 1.0; }
- if ( upper_color[i][j] < 0.0 ) { upper_color[i][j] = 0.0; }
- if ( middle_color[i][j] > 1.0 ) { middle_color[i][j] = 1.0; }
- if ( middle_color[i][j] < 0.0 ) { middle_color[i][j] = 0.0; }
- if ( lower_color[i][j] > 1.0 ) { lower_color[i][j] = 1.0; }
- if ( lower_color[i][j] < 0.0 ) { lower_color[i][j] = 0.0; }
- }
- upper_color[i][3] = middle_color[i][3] = lower_color[i][3] = 1.0;
-
- for ( j = 0; j < 3; j++ ) {
- outer_amt[j] += outer_diff[j];
- middle_amt[j] += middle_diff[j];
- }
-
- /*
- printf("upper_color[%d] = %.2f %.2f %.2f %.2f\n", i, upper_color[i][0],
- upper_color[i][1], upper_color[i][2], upper_color[i][3]);
- printf("middle_color[%d] = %.2f %.2f %.2f %.2f\n", i,
- middle_color[i][0], middle_color[i][1], middle_color[i][2],
- middle_color[i][3]);
- printf("lower_color[%d] = %.2f %.2f %.2f %.2f\n", i,
- lower_color[i][0], lower_color[i][1], lower_color[i][2],
- lower_color[i][3]);
- */
- }
-
- for ( i = 0; i < 12; i++ ) {
- sgCopyVec4( bottom_color[i], fog_color );
- }
-
- //
- // Second, assign the basic colors to the object color arrays
- //
-
- float *slot;
- int counter;
-
- // update the center disk color arrays
- counter = 0;
- slot = center_disk_cl->get( counter++ );
- // sgVec4 red;
- // sgSetVec4( red, 1.0, 0.0, 0.0, 1.0 );
- sgCopyVec4( slot, center_color );
- for ( i = 11; i >= 0; i-- ) {
- slot = center_disk_cl->get( counter++ );
- sgCopyVec4( slot, upper_color[i] );
- }
- slot = center_disk_cl->get( counter++ );
- sgCopyVec4( slot, upper_color[11] );
-
- // generate the upper ring
- counter = 0;
- for ( i = 0; i < 12; i++ ) {
- slot = upper_ring_cl->get( counter++ );
- sgCopyVec4( slot, middle_color[i] );
-
- slot = upper_ring_cl->get( counter++ );
- sgCopyVec4( slot, upper_color[i] );
- }
- slot = upper_ring_cl->get( counter++ );
- sgCopyVec4( slot, middle_color[0] );
-
- slot = upper_ring_cl->get( counter++ );
- sgCopyVec4( slot, upper_color[0] );
-
- // generate middle ring
- counter = 0;
- for ( i = 0; i < 12; i++ ) {
- slot = middle_ring_cl->get( counter++ );
- sgCopyVec4( slot, lower_color[i] );
-
- slot = middle_ring_cl->get( counter++ );
- sgCopyVec4( slot, middle_color[i] );
+ // Magic factors for coloring the sky according visibility and
+ // zenith angle.
+ const double cvf = osg::clampBelow(vis, 45000.0);
+ const double vis_factor = osg::clampTo((vis - 1000.0) / 2000.0, 0.0, 1.0);
+ const float upperVisFactor = 1.0 - vis_factor * (0.7 + 0.3 * cvf/45000);
+ const float middleVisFactor = 1.0 - vis_factor * (0.1 + 0.85 * cvf/45000);
+
+ (*dome_cl)[0] = toOsg(sky_color);
+ simgear::VectorArrayAdapter<Vec3Array> colors(*dome_cl, numBands, 1);
+ const double saif = sun_angle/SG_PI;
+ static const SGVec3f blueShift(0.8, 1.0, 1.2);
+ const SGVec3f skyFogDelta = sky_color - fog_color;
+ const SGVec3f sunSkyDelta = sun_color - sky_color;
+ // For now the colors of the upper two rings are linearly
+ // interpolated between the zenith color and the first horizon
+ // ring color.
+
+ for (int i = 0; i < halfBands+1; i++) {
+ SGVec3f diff = mult(skyFogDelta, blueShift);
+ diff *= (0.8 + saif - ((halfBands-i)/10));
+ colors(2, i) = toOsg(sky_color - upperVisFactor * diff);
+ colors(3, i) = toOsg(sky_color - middleVisFactor * diff + middle_amt);
+ colors(4, i) = toOsg(fog_color + outer_amt);
+ colors(0, i) = simgear::math::lerp(toOsg(sky_color), colors(2, i), .3942);
+ colors(1, i) = simgear::math::lerp(toOsg(sky_color), colors(2, i), .7885);
+ for (int j = 0; j < numRings - 1; ++j)
+ clampColor(colors(j, i));
+ outer_amt -= outer_diff;
+ middle_amt -= middle_diff;
}
- slot = middle_ring_cl->get( counter++ );
- sgCopyVec4( slot, lower_color[0] );
-
- slot = middle_ring_cl->get( counter++ );
- sgCopyVec4( slot, middle_color[0] );
-
- // generate lower ring
- counter = 0;
- for ( i = 0; i < 12; i++ ) {
- slot = lower_ring_cl->get( counter++ );
- sgCopyVec4( slot, bottom_color[i] );
- slot = lower_ring_cl->get( counter++ );
- sgCopyVec4( slot, lower_color[i] );
- }
- slot = lower_ring_cl->get( counter++ );
- sgCopyVec4( slot, bottom_color[0] );
+ for (int i = halfBands+1; i < numBands; ++i)
+ for (int j = 0; j < 5; ++j)
+ colors(j, i) = colors(j, numBands - i);
- slot = lower_ring_cl->get( counter++ );
- sgCopyVec4( slot, lower_color[0] );
+ fade_to_black(&(*dome_cl)[0], asl * center_elev, 1);
+ for (int i = 0; i < numRings - 1; ++i)
+ fade_to_black(&colors(i, 0), (asl+0.05f) * domeParams[i].elev,
+ numBands);
+ for ( int i = 0; i < numBands; i++ )
+ colors(numRings - 1, i) = toOsg(fog_color);
+ dome_cl->dirty();
return true;
}
// lat specifies a rotation about the new Y axis
// spin specifies a rotation about the new Z axis (and orients the
// sunrise/set effects
-bool SGSkyDome::reposition( sgVec3 p, double lon, double lat, double spin ) {
- sgMat4 T, LON, LAT, SPIN;
- sgVec3 axis;
+bool
+SGSkyDome::reposition( const SGVec3f& p, double _asl,
+ double lon, double lat, double spin ) {
+ asl = _asl;
+
+ osg::Matrix T, LON, LAT, SPIN;
// Translate to view position
// Point3D zero_elev = current_view.get_cur_zero_elev();
// xglTranslatef( zero_elev.x(), zero_elev.y(), zero_elev.z() );
- sgMakeTransMat4( T, p );
+ T.makeTranslate( toOsg(p) );
// printf(" Translated to %.2f %.2f %.2f\n",
// zero_elev.x, zero_elev.y, zero_elev.z );
// lon * SGD_RADIANS_TO_DEGREES,
// lat * SGD_RADIANS_TO_DEGREES);
// xglRotatef( lon * SGD_RADIANS_TO_DEGREES, 0.0, 0.0, 1.0 );
- sgSetVec3( axis, 0.0, 0.0, 1.0 );
- sgMakeRotMat4( LON, lon * SGD_RADIANS_TO_DEGREES, axis );
+ LON.makeRotate(lon, osg::Vec3(0, 0, 1));
// xglRotatef( 90.0 - f->get_Latitude() * SGD_RADIANS_TO_DEGREES,
// 0.0, 1.0, 0.0 );
- sgSetVec3( axis, 0.0, 1.0, 0.0 );
- sgMakeRotMat4( LAT, 90.0 - lat * SGD_RADIANS_TO_DEGREES, axis );
+ LAT.makeRotate(90.0 * SGD_DEGREES_TO_RADIANS - lat, osg::Vec3(0, 1, 0));
// xglRotatef( l->sun_rotation * SGD_RADIANS_TO_DEGREES, 0.0, 0.0, 1.0 );
- sgSetVec3( axis, 0.0, 0.0, 1.0 );
- sgMakeRotMat4( SPIN, spin * SGD_RADIANS_TO_DEGREES, axis );
-
- sgMat4 TRANSFORM;
-
- sgCopyMat4( TRANSFORM, T );
- sgPreMultMat4( TRANSFORM, LON );
- sgPreMultMat4( TRANSFORM, LAT );
- sgPreMultMat4( TRANSFORM, SPIN );
-
- sgCoord skypos;
- sgSetCoord( &skypos, TRANSFORM );
-
- dome_transform->setTransform( &skypos );
+ SPIN.makeRotate(spin, osg::Vec3(0, 0, 1));
+ dome_transform->setMatrix( SPIN*LAT*LON*T );
return true;
}