Starting to work on an independent sky implimentation that can be used by

any ssg application and can have it's components driven realistically based
on time.
This commit is contained in:
curt
2000-03-02 00:56:35 +00:00
parent 41218272c4
commit 86892d87e9
7 changed files with 1667 additions and 0 deletions

8
simgear/sky/Makefile.am Normal file
View File

@@ -0,0 +1,8 @@
noinst_LIBRARIES = libSky.a
libSky_a_SOURCES = \
skydome.cxx skydome.hxx \
skysun.cxx skysun.hxx \
sphere.cxx sphere.hxx
INCLUDES += -I$(top_builddir) -I$(top_builddir)/src

822
simgear/sky/skydome.cxx Normal file
View File

@@ -0,0 +1,822 @@
// skydome.cxx -- model sky with an upside down "bowl"
//
// Written by Curtis Olson, started December 1997.
// SSG-ified by Curtis Olson, February 2000.
//
// Copyright (C) 1997-2000 Curtis L. Olson - curt@flightgear.org
//
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// $Id$
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef HAVE_WINDOWS_H
# include <windows.h>
#endif
#include <math.h>
#include <GL/glut.h>
#include <simgear/xgl/xgl.h>
#include <simgear/constants.h>
#include <simgear/debug/logstream.hxx>
#include <simgear/math/fg_random.h>
// #include <Aircraft/aircraft.hxx>
// #include <FDM/flight.hxx>
// #include <Main/views.hxx>
// #include <Time/event.hxx>
// #include <Time/fg_time.hxx>
#include "skydome.hxx"
#ifdef __MWERKS__
# pragma global_optimizer off
#endif
// in meters of course
#define CENTER_ELEV 25000.0
#define UPPER_RADIUS 50000.0
#define UPPER_ELEV 20000.0
#define MIDDLE_RADIUS 70000.0
#define MIDDLE_ELEV 8000.0
#define LOWER_RADIUS 80000.0
#define LOWER_ELEV 0.0
#define BOTTOM_RADIUS 50000.0
#define BOTTOM_ELEV -2000.0
// static float inner_vertex[12][3];
// static float middle_vertex[12][3];
// static float outer_vertex[12][3];
// static float bottom_vertex[12][3];
// static GLubyte upper_color[12][4];
// static GLubyte middle_color[12][4];
// static GLubyte lower_color[12][4];
// Defined the shared sky object here
FGSkyDome current_sky;
// Constructor
FGSkyDome::FGSkyDome( void ) {
}
// Destructor
FGSkyDome::~FGSkyDome( void ) {
}
// initialize the sky object and connect it into our scene graph
bool FGSkyDome::initialize( ) {
sgVec3 color;
float theta;
int i;
// create the scene graph for the dome
dome = new ssgRoot;
dome->setName( "Sky Dome" );
// set up the state
dome_state = new ssgSimpleState();
dome_state->setShadeModel( GL_SMOOTH );
dome_state->disable( GL_LIGHTING );
dome_state->disable( GL_DEPTH_TEST );
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 );
// 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
sgSetVec3( color, 0.0, 0.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 );
for ( i = 0; i < 12; i++ ) {
theta = (i * 30.0) * DEG_TO_RAD;
sgSetVec3( upper_vertex[i],
cos(theta) * UPPER_RADIUS,
sin(theta) * UPPER_RADIUS,
UPPER_ELEV );
sgSetVec3( middle_vertex[i],
cos((double)theta) * MIDDLE_RADIUS,
sin((double)theta) * MIDDLE_RADIUS,
MIDDLE_ELEV );
sgSetVec3( lower_vertex[i],
cos((double)theta) * LOWER_RADIUS,
sin((double)theta) * LOWER_RADIUS,
LOWER_ELEV );
sgSetVec3( bottom_vertex[i],
cos((double)theta) * BOTTOM_RADIUS,
sin((double)theta) * BOTTOM_RADIUS,
BOTTOM_ELEV );
}
// 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 );
}
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 );
}
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 );
middle_ring_vl->add( middle_vertex[0] );
middle_ring_cl->add( color );
// generate lower ring
for ( i = 0; i < 12; i++ ) {
lower_ring_vl->add( bottom_vertex[i] );
lower_ring_cl->add( color );
lower_ring_vl->add( lower_vertex[i] );
lower_ring_cl->add( color );
}
lower_ring_vl->add( bottom_vertex[0] );
lower_ring_cl->add( color );
lower_ring_vl->add( lower_vertex[0] );
lower_ring_cl->add( color );
// force a repaint of the sky colors with ugly defaults
sgVec3 fog_color;
sgSetVec3( fog_color, 1.0, 1.0, 1.0 );
repaint( color, fog_color, 0.0 );
// build the ssg scene graph sub tree for the sky and connected
// into the provide scene graph branch
dome_selector = new ssgSelector;
dome_transform = new ssgTransform;
ssgVtxTable *center_disk, *upper_ring, *middle_ring, *lower_ring;
center_disk = new ssgVtxTable( GL_TRIANGLE_FAN,
center_disk_vl, NULL, NULL, center_disk_cl );
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->addKid( center_disk );
dome_transform->addKid( upper_ring );
dome_transform->addKid( middle_ring );
dome_transform->addKid( lower_ring );
dome_selector->addKid( dome_transform );
dome_selector->clrTraversalMaskBits( SSGTRAV_HOT );
dome->addKid( dome_selector );
return true;
}
// repaint the sky colors based on current value of sun_angle, sky,
// and fog colors. This updates the color arrays for ssgVtxTable.
// sun angle in degrees relative to verticle
// 0 degrees = high noon
// 90 degrees = sun rise/set
// 180 degrees = darkest midnight
bool FGSkyDome::repaint( sgVec3 sky_color, sgVec3 fog_color, double sun_angle ) {
double diff;
sgVec3 outer_param, outer_amt, outer_diff;
sgVec3 middle_param, middle_amt, middle_diff;
int i, j;
// Check for sunrise/sunset condition
if ( (sun_angle > 80.0) && (sun_angle < 100.0) ) {
// 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 );
} 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 );
}
// 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 );
//
// First, recalulate the basic colors
//
sgVec3 upper_color[12];
sgVec3 middle_color[12];
sgVec3 lower_color[12];
sgVec3 bottom_color[12];
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 * 0.3;
middle_color[i][j] = sky_color[j] - diff * 0.9 + 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.1 ) { upper_color[i][j] = 0.1; }
if ( middle_color[i][j] > 1.0 ) { middle_color[i][j] = 1.0; }
if ( middle_color[i][j] < 0.1 ) { middle_color[i][j] = 0.1; }
if ( lower_color[i][j] > 1.0 ) { lower_color[i][j] = 1.0; }
if ( lower_color[i][j] < 0.1 ) { lower_color[i][j] = 0.1; }
}
// upper_color[i][3] = middle_color[i][3] = lower_color[i][3] =
// (GLubyte)(sky_color[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 * 0.3;
middle_color[i][j] = sky_color[j] - diff * 0.9 + 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.1 ) { upper_color[i][j] = 0.1; }
if ( middle_color[i][j] > 1.0 ) { middle_color[i][j] = 1.0; }
if ( middle_color[i][j] < 0.1 ) { middle_color[i][j] = 0.1; }
if ( lower_color[i][j] > 1.0 ) { lower_color[i][j] = 1.0; }
if ( lower_color[i][j] < 35 ) { lower_color[i][j] = 35; }
}
// upper_color[i][3] = middle_color[i][3] = lower_color[i][3] =
// (GLubyte)(sky_color[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++ ) {
sgCopyVec3( 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++ );
// sgVec3 red;
// sgSetVec3( red, 1.0, 0.0, 0.0 );
sgCopyVec3( slot, sky_color );
for ( i = 11; i >= 0; i-- ) {
slot = center_disk_cl->get( counter++ );
sgCopyVec3( slot, upper_color[i] );
}
slot = center_disk_cl->get( counter++ );
sgCopyVec3( slot, upper_color[11] );
// generate the upper ring
counter = 0;
for ( i = 0; i < 12; i++ ) {
slot = upper_ring_cl->get( counter++ );
sgCopyVec3( slot, middle_color[i] );
slot = upper_ring_cl->get( counter++ );
sgCopyVec3( slot, upper_color[i] );
}
slot = upper_ring_cl->get( counter++ );
sgCopyVec3( slot, middle_color[0] );
slot = upper_ring_cl->get( counter++ );
sgCopyVec3( slot, upper_color[0] );
// generate middle ring
counter = 0;
for ( i = 0; i < 12; i++ ) {
slot = middle_ring_cl->get( counter++ );
sgCopyVec3( slot, lower_color[i] );
slot = middle_ring_cl->get( counter++ );
sgCopyVec3( slot, middle_color[i] );
}
slot = middle_ring_cl->get( counter++ );
sgCopyVec3( slot, lower_color[0] );
slot = middle_ring_cl->get( counter++ );
sgCopyVec3( slot, middle_color[0] );
// generate lower ring
counter = 0;
for ( i = 0; i < 12; i++ ) {
slot = lower_ring_cl->get( counter++ );
sgCopyVec3( slot, bottom_color[i] );
slot = lower_ring_cl->get( counter++ );
sgCopyVec3( slot, lower_color[i] );
}
slot = lower_ring_cl->get( counter++ );
sgCopyVec3( slot, bottom_color[0] );
slot = lower_ring_cl->get( counter++ );
sgCopyVec3( slot, lower_color[0] );
return true;
}
// reposition the sky at the specified origin and orientation
// lon specifies a rotation about the Z axis
// 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 FGSkyDome::reposition( sgVec3 p, double lon, double lat, double spin ) {
sgMat4 T, LON, LAT, SPIN;
sgVec3 axis;
// 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 );
// printf(" Translated to %.2f %.2f %.2f\n",
// zero_elev.x, zero_elev.y, zero_elev.z );
// Rotate to proper orientation
// printf(" lon = %.2f lat = %.2f\n", FG_Longitude * RAD_TO_DEG,
// FG_Latitude * RAD_TO_DEG);
// xglRotatef( f->get_Longitude() * RAD_TO_DEG, 0.0, 0.0, 1.0 );
sgSetVec3( axis, 0.0, 0.0, 1.0 );
sgMakeRotMat4( LON, lon * RAD_TO_DEG, axis );
// xglRotatef( 90.0 - f->get_Latitude() * RAD_TO_DEG, 0.0, 1.0, 0.0 );
sgSetVec3( axis, 0.0, 1.0, 0.0 );
sgMakeRotMat4( LAT, 90.0 - lat * RAD_TO_DEG, axis );
// xglRotatef( l->sun_rotation * RAD_TO_DEG, 0.0, 0.0, 1.0 );
sgSetVec3( axis, 0.0, 0.0, 1.0 );
sgMakeRotMat4( SPIN, spin * RAD_TO_DEG, axis );
sgMat4 TRANSFORM;
sgCopyMat4( TRANSFORM, T );
sgPreMultMat4( TRANSFORM, LON );
sgPreMultMat4( TRANSFORM, LAT );
sgPreMultMat4( TRANSFORM, SPIN );
sgCoord skypos;
sgSetCoord( &skypos, TRANSFORM );
dome_transform->setTransform( &skypos );
return true;
}
// Draw the skydome
bool FGSkyDome::draw() {
ssgCullAndDraw( dome );
return true;
}
#if 0
// depricated code from here to the end
// Calculate the sky structure vertices
void fgSkyVerticesInit() {
float theta;
int i;
FG_LOG(FG_ASTRO, FG_INFO, " Generating the sky dome vertices.");
for ( i = 0; i < 12; i++ ) {
theta = (i * 30.0) * DEG_TO_RAD;
inner_vertex[i][0] = cos(theta) * UPPER_RADIUS;
inner_vertex[i][1] = sin(theta) * UPPER_RADIUS;
inner_vertex[i][2] = UPPER_ELEV;
// printf(" %.2f %.2f\n", cos(theta) * UPPER_RADIUS,
// sin(theta) * UPPER_RADIUS);
middle_vertex[i][0] = cos((double)theta) * MIDDLE_RADIUS;
middle_vertex[i][1] = sin((double)theta) * MIDDLE_RADIUS;
middle_vertex[i][2] = MIDDLE_ELEV;
outer_vertex[i][0] = cos((double)theta) * LOWER_RADIUS;
outer_vertex[i][1] = sin((double)theta) * LOWER_RADIUS;
outer_vertex[i][2] = LOWER_ELEV;
bottom_vertex[i][0] = cos((double)theta) * BOTTOM_RADIUS;
bottom_vertex[i][1] = sin((double)theta) * BOTTOM_RADIUS;
bottom_vertex[i][2] = BOTTOM_ELEV;
}
}
// (Re)calculate the sky colors at each vertex
void fgSkyColorsInit() {
fgLIGHT *l;
double sun_angle, diff;
double outer_param[3], outer_amt[3], outer_diff[3];
double middle_param[3], middle_amt[3], middle_diff[3];
int i, j;
l = &cur_light_params;
FG_LOG( FG_ASTRO, FG_INFO,
" Generating the sky colors for each vertex." );
// setup for the possibility of sunset effects
sun_angle = l->sun_angle * RAD_TO_DEG;
// fgPrintf( FG_ASTRO, FG_INFO,
// " Sun angle in degrees = %.2f\n", sun_angle);
if ( (sun_angle > 80.0) && (sun_angle < 100.0) ) {
// 0.0 - 0.4
outer_param[0] = (10.0 - fabs(90.0 - sun_angle)) / 20.0;
outer_param[1] = (10.0 - fabs(90.0 - sun_angle)) / 40.0;
outer_param[2] = -(10.0 - fabs(90.0 - sun_angle)) / 30.0;
// outer_param[2] = 0.0;
middle_param[0] = (10.0 - fabs(90.0 - sun_angle)) / 40.0;
middle_param[1] = (10.0 - fabs(90.0 - sun_angle)) / 80.0;
middle_param[2] = 0.0;
outer_diff[0] = outer_param[0] / 6.0;
outer_diff[1] = outer_param[1] / 6.0;
outer_diff[2] = outer_param[2] / 6.0;
middle_diff[0] = middle_param[0] / 6.0;
middle_diff[1] = middle_param[1] / 6.0;
middle_diff[2] = middle_param[2] / 6.0;
} else {
outer_param[0] = outer_param[1] = outer_param[2] = 0.0;
middle_param[0] = middle_param[1] = middle_param[2] = 0.0;
outer_diff[0] = outer_diff[1] = outer_diff[2] = 0.0;
middle_diff[0] = middle_diff[1] = middle_diff[2] = 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
for ( j = 0; j < 3; j++ ) {
outer_amt[j] = outer_param[j];
middle_amt[j] = middle_param[j];
}
for ( i = 0; i < 6; i++ ) {
for ( j = 0; j < 3; j++ ) {
diff = l->sky_color[j] - l->fog_color[j];
// printf("sky = %.2f fog = %.2f diff = %.2f\n",
// l->sky_color[j], l->fog_color[j], diff);
upper_color[i][j] = (GLubyte)((l->sky_color[j] - diff * 0.3) * 255);
middle_color[i][j] = (GLubyte)((l->sky_color[j] - diff * 0.9
+ middle_amt[j]) * 255);
lower_color[i][j] = (GLubyte)((l->fog_color[j] + outer_amt[j])
* 255);
if ( upper_color[i][j] > 255 ) { upper_color[i][j] = 255; }
if ( upper_color[i][j] < 25 ) { upper_color[i][j] = 25; }
if ( middle_color[i][j] > 255 ) { middle_color[i][j] = 255; }
if ( middle_color[i][j] < 25 ) { middle_color[i][j] = 25; }
if ( lower_color[i][j] > 255 ) { lower_color[i][j] = 255; }
if ( lower_color[i][j] < 25 ) { lower_color[i][j] = 25; }
}
upper_color[i][3] = middle_color[i][3] = lower_color[i][3] =
(GLubyte)(l->sky_color[3] * 255);
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 ( j = 0; j < 3; j++ ) {
outer_amt[j] = 0.0;
middle_amt[j] = 0.0;
}
for ( i = 6; i < 12; i++ ) {
for ( j = 0; j < 3; j++ ) {
diff = l->sky_color[j] - l->fog_color[j];
// printf("sky = %.2f fog = %.2f diff = %.2f\n",
// l->sky_color[j], l->fog_color[j], diff);
upper_color[i][j] = (GLubyte)((l->sky_color[j] - diff * 0.3) * 255);
middle_color[i][j] = (GLubyte)((l->sky_color[j] - diff * 0.9
+ middle_amt[j]) * 255);
lower_color[i][j] = (GLubyte)((l->fog_color[j] + outer_amt[j])
* 255);
if ( upper_color[i][j] > 255 ) { upper_color[i][j] = 255; }
if ( upper_color[i][j] < 25 ) { upper_color[i][j] = 25; }
if ( middle_color[i][j] > 255 ) { middle_color[i][j] = 255; }
if ( middle_color[i][j] < 25 ) { middle_color[i][j] = 25; }
if ( lower_color[i][j] > 255 ) { lower_color[i][j] = 255; }
if ( lower_color[i][j] < 35 ) { lower_color[i][j] = 35; }
}
upper_color[i][3] = middle_color[i][3] = lower_color[i][3] =
(GLubyte)(l->sky_color[3] * 255);
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]);
*/
}
}
// Initialize the sky structure and colors
void fgSkyInit() {
FG_LOG( FG_ASTRO, FG_INFO, "Initializing the sky" );
fgSkyVerticesInit();
// regester fgSkyColorsInit() as an event to be run periodically
global_events.Register( "fgSkyColorsInit()", fgSkyColorsInit,
fgEVENT::FG_EVENT_READY, 30000);
}
// Draw the Sky
void fgSkyRender() {
FGInterface *f;
fgLIGHT *l;
GLubyte sky_color[4];
GLubyte upper_color[4];
GLubyte middle_color[4];
GLubyte lower_color[4];
double diff;
int i;
f = current_aircraft.fdm_state;
l = &cur_light_params;
// printf("Rendering the sky.\n");
// calculate the proper colors
for ( i = 0; i < 3; i++ ) {
diff = l->sky_color[i] - l->adj_fog_color[i];
// printf("sky = %.2f fog = %.2f diff = %.2f\n",
// l->sky_color[j], l->adj_fog_color[j], diff);
upper_color[i] = (GLubyte)((l->sky_color[i] - diff * 0.3) * 255);
middle_color[i] = (GLubyte)((l->sky_color[i] - diff * 0.9) * 255);
lower_color[i] = (GLubyte)(l->adj_fog_color[i] * 255);
}
upper_color[3] = middle_color[3] = lower_color[3] =
(GLubyte)(l->adj_fog_color[3] * 255);
xglPushMatrix();
// Translate to view position
Point3D zero_elev = current_view.get_cur_zero_elev();
xglTranslatef( zero_elev.x(), zero_elev.y(), zero_elev.z() );
// printf(" Translated to %.2f %.2f %.2f\n",
// zero_elev.x, zero_elev.y, zero_elev.z );
// Rotate to proper orientation
// printf(" lon = %.2f lat = %.2f\n", FG_Longitude * RAD_TO_DEG,
// FG_Latitude * RAD_TO_DEG);
xglRotatef( f->get_Longitude() * RAD_TO_DEG, 0.0, 0.0, 1.0 );
xglRotatef( 90.0 - f->get_Latitude() * RAD_TO_DEG, 0.0, 1.0, 0.0 );
xglRotatef( l->sun_rotation * RAD_TO_DEG, 0.0, 0.0, 1.0 );
// Draw inner/center section of sky*/
xglBegin( GL_TRIANGLE_FAN );
for ( i = 0; i < 4; i++ ) {
sky_color[i] = (GLubyte)(l->sky_color[i] * 255);
}
xglColor4fv(l->sky_color);
xglVertex3f(0.0, 0.0, CENTER_ELEV);
for ( i = 11; i >= 0; i-- ) {
xglColor4ubv( upper_color );
xglVertex3fv( inner_vertex[i] );
}
xglColor4ubv( upper_color );
xglVertex3fv( inner_vertex[11] );
xglEnd();
// Draw the middle ring
xglBegin( GL_TRIANGLE_STRIP );
for ( i = 0; i < 12; i++ ) {
xglColor4ubv( middle_color );
// 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]);
// xglColor4f(1.0, 0.0, 0.0, 1.0);
xglVertex3fv( middle_vertex[i] );
xglColor4ubv( upper_color );
// 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]);
// xglColor4f(0.0, 0.0, 1.0, 1.0);
xglVertex3fv( inner_vertex[i] );
}
xglColor4ubv( middle_color );
// xglColor4f(1.0, 0.0, 0.0, 1.0);
xglVertex3fv( middle_vertex[0] );
xglColor4ubv( upper_color );
// xglColor4f(0.0, 0.0, 1.0, 1.0);
xglVertex3fv( inner_vertex[0] );
xglEnd();
// Draw the outer ring
xglBegin( GL_TRIANGLE_STRIP );
for ( i = 0; i < 12; i++ ) {
xglColor4ubv( lower_color );
xglVertex3fv( outer_vertex[i] );
xglColor4ubv( middle_color );
xglVertex3fv( middle_vertex[i] );
}
xglColor4ubv( lower_color );
xglVertex3fv( outer_vertex[0] );
xglColor4ubv( middle_color );
xglVertex3fv( middle_vertex[0] );
xglEnd();
// Draw the bottom skirt
xglBegin( GL_TRIANGLE_STRIP );
xglColor4ubv( lower_color );
for ( i = 0; i < 12; i++ ) {
xglVertex3fv( bottom_vertex[i] );
xglVertex3fv( outer_vertex[i] );
}
xglVertex3fv( bottom_vertex[0] );
xglVertex3fv( outer_vertex[0] );
xglEnd();
xglPopMatrix();
}
#endif

114
simgear/sky/skydome.hxx Normal file
View File

@@ -0,0 +1,114 @@
// skydome.hxx -- model sky with an upside down "bowl"
//
// Written by Curtis Olson, started December 1997.
// SSG-ified by Curtis Olson, February 2000.
//
// Copyright (C) 1997-2000 Curtis L. Olson - curt@flightgear.org
//
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// $Id$
#ifndef _SKYDOME_HXX
#define _SKYDOME_HXX
#ifndef __cplusplus
# error This library requires C++
#endif
#include <plib/ssg.h> // plib include
class FGSkyDome {
// scene graph root for the skydome
ssgRoot *dome;
ssgSelector *dome_selector;
ssgTransform *dome_transform;
ssgSimpleState *dome_state;
ssgVertexArray *center_disk_vl;
ssgColourArray *center_disk_cl;
ssgVertexArray *upper_ring_vl;
ssgColourArray *upper_ring_cl;
ssgVertexArray *middle_ring_vl;
ssgColourArray *middle_ring_cl;
ssgVertexArray *lower_ring_vl;
ssgColourArray *lower_ring_cl;
public:
// Constructor
FGSkyDome( void );
// Destructor
~FGSkyDome( void );
// initialize the sky object and connect it into our scene graph
// root
bool initialize();
// repaint the sky colors based on current value of sun_angle,
// sky, and fog colors. This updates the color arrays for
// ssgVtxTable.
// sun angle in degrees relative to verticle
// 0 degrees = high noon
// 90 degrees = sun rise/set
// 180 degrees = darkest midnight
bool repaint( sgVec3 sky_color, sgVec3 fog_color, double sun_angle );
// reposition the sky at the specified origin and orientation
// lon specifies a rotation about the Z axis
// 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 reposition( sgVec3 p, double lon, double lat, double spin );
// Draw the skydome
bool draw();
// enable the sky in the scene graph (default)
void enable() { dome_selector->select( 1 ); }
// disable the sky in the scene graph. The leaf node is still
// there, how ever it won't be traversed on the cullandrender
// phase.
void disable() { dome_selector->select( 0 ); }
};
extern FGSkyDome current_sky;
// (Re)generate the display list
// void fgSkyInit();
// (Re)calculate the sky colors at each vertex
// void fgSkyColorsInit();
// Draw the Sky
// void fgSkyRender();
#endif // _SKYDOM_HXX

438
simgear/sky/skysun.cxx Normal file
View File

@@ -0,0 +1,438 @@
// skysun.hxx -- draw a sun object
//
// Written by Durk Talsma. Originally started October 1997, for distribution
// with the FlightGear project. Version 2 was written in August and
// September 1998. This code is based upon algorithms and data kindly
// provided by Mr. Paul Schlyter. (pausch@saaf.se).
//
// Separated out rendering pieces and converted to ssg by Curt Olson,
// March 2000
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// $Id$
// #ifdef __BORLANDC__
// # define exception c_exception
// #endif
// #include <math.h>
// #include <simgear/debug/logstream.hxx>
// #include <Time/sunpos.hxx>
// #include <Time/light.hxx>
// #include <Main/options.hxx>
#include "skysun.hxx"
// Constructor
FGSkySun::FGSkySun( void ) {
}
// Destructor
FGSkySun::~FGSkySun( void ) {
}
// initialize the sun object and connect it into our scene graph root
bool FGSkySun::initialize() {
sgVec3 color;
float theta;
int i;
// create the scene graph for the dome
skysun = new ssgRoot;
skysun->setName( "Sky Sun" );
// set up the state
sun_state = new ssgSimpleState();
sun_state->setShadeModel( GL_SMOOTH );
sun_state->disable( GL_LIGHTING );
sun_state->disable( GL_DEPTH_TEST );
sun_state->disable( GL_CULL_FACE );
sun_state->disable( GL_TEXTURE_2D );
sun_state->disable( GL_COLOR_MATERIAL );
sun_state->setColourMaterial( GL_AMBIENT_AND_DIFFUSE );
// initially seed to all white
sgSetVec3( color, 1.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 );
for ( i = 0; i < 12; i++ ) {
theta = (i * 30.0) * DEG_TO_RAD;
sgSetVec3( upper_vertex[i],
cos(theta) * UPPER_RADIUS,
sin(theta) * UPPER_RADIUS,
UPPER_ELEV );
sgSetVec3( middle_vertex[i],
cos((double)theta) * MIDDLE_RADIUS,
sin((double)theta) * MIDDLE_RADIUS,
MIDDLE_ELEV );
sgSetVec3( lower_vertex[i],
cos((double)theta) * LOWER_RADIUS,
sin((double)theta) * LOWER_RADIUS,
LOWER_ELEV );
sgSetVec3( bottom_vertex[i],
cos((double)theta) * BOTTOM_RADIUS,
sin((double)theta) * BOTTOM_RADIUS,
BOTTOM_ELEV );
}
// 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 );
}
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 );
}
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 );
middle_ring_vl->add( middle_vertex[0] );
middle_ring_cl->add( color );
// generate lower ring
for ( i = 0; i < 12; i++ ) {
lower_ring_vl->add( bottom_vertex[i] );
lower_ring_cl->add( color );
lower_ring_vl->add( lower_vertex[i] );
lower_ring_cl->add( color );
}
lower_ring_vl->add( bottom_vertex[0] );
lower_ring_cl->add( color );
lower_ring_vl->add( lower_vertex[0] );
lower_ring_cl->add( color );
// force a repaint of the sky colors with ugly defaults
sgVec3 fog_color;
sgSetVec3( fog_color, 1.0, 1.0, 1.0 );
repaint( color, fog_color, 0.0 );
// build the ssg scene graph sub tree for the sky and connected
// into the provide scene graph branch
dome_selector = new ssgSelector;
dome_transform = new ssgTransform;
ssgVtxTable *center_disk, *upper_ring, *middle_ring, *lower_ring;
center_disk = new ssgVtxTable( GL_TRIANGLE_FAN,
center_disk_vl, NULL, NULL, center_disk_cl );
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->addKid( center_disk );
dome_transform->addKid( upper_ring );
dome_transform->addKid( middle_ring );
dome_transform->addKid( lower_ring );
dome_selector->addKid( dome_transform );
dome_selector->clrTraversalMaskBits( SSGTRAV_HOT );
dome->addKid( dome_selector );
return true;
}
#if 0
/*************************************************************************
* Star::Star(FGTime *t)
* Public constructor for class Star
* Argument: The current time.
* the hard coded orbital elements our sun are passed to
* CelestialBody::CelestialBody();
* note that the word sun is avoided, in order to prevent some compilation
* problems on sun systems
************************************************************************/
Star::Star(FGTime *t) :
CelestialBody (0.000000, 0.0000000000,
0.0000, 0.00000,
282.9404, 4.7093500E-5,
1.0000000, 0.000000,
0.016709, -1.151E-9,
356.0470, 0.98560025850, t)
{
FG_LOG( FG_GENERAL, FG_INFO, "Initializing Sun Texture");
#ifdef GL_VERSION_1_1
xglGenTextures(1, &sun_texid);
xglBindTexture(GL_TEXTURE_2D, sun_texid);
#elif GL_EXT_texture_object
xglGenTexturesEXT(1, &sun_texid);
xglBindTextureEXT(GL_TEXTURE_2D, sun_texid);
#else
# error port me
#endif
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
setTexture();
glTexImage2D( GL_TEXTURE_2D,
0,
GL_RGBA,
256, 256,
0,
GL_RGBA, GL_UNSIGNED_BYTE,
sun_texbuf);
SunObject = gluNewQuadric();
if(SunObject == NULL)
{
printf("gluNewQuadric(SunObject) failed !\n");
exit(0);
}
//SunList = 0;
distance = 0.0;
}
Star::~Star()
{
//delete SunObject;
delete [] sun_texbuf;
}
static int texWidth = 256; /* 64x64 is plenty */
void Star::setTexture()
{
int texSize;
//void *textureBuf;
GLubyte *p;
int i,j;
double radius;
texSize = texWidth*texWidth;
sun_texbuf = new GLubyte[texSize*4];
if (!sun_texbuf)
return; // Ugly!
p = sun_texbuf;
radius = (double)(texWidth / 2);
for (i=0; i < texWidth; i++) {
for (j=0; j < texWidth; j++) {
double x, y, d;
*p = 0xff;
*(p+1) = 0xff;
*(p+2) = 0xff;
x = fabs((double)(i - (texWidth / 2)));
y = fabs((double)(j - (texWidth / 2)));
d = sqrt((x * x) + (y * y));
if (d < radius) {
double t = 1.0 - (d / radius); // t is 1.0 at center, 0.0 at edge */
// inverse square looks nice
*(p+3) = (int)((double) 0xff * (t*t));
} else {
*(p+3) = 0x00;
}
p += 4;
}
}
//gluBuild2DMipmaps(GL_TEXTURE_2D, 1, texWidth, texWidth,
// GL_LUMINANCE,
// GL_UNSIGNED_BYTE, textureBuf);
//free(textureBuf);
}
/*************************************************************************
* void Jupiter::updatePosition(FGTime *t, Star *ourSun)
*
* calculates the current position of our sun.
*************************************************************************/
void Star::updatePosition(FGTime *t)
{
double
actTime, eccAnom,
xv, yv, v, r,
xe, ye, ze, ecl;
updateOrbElements(t);
actTime = fgCalcActTime(t);
ecl = DEG_TO_RAD * (23.4393 - 3.563E-7 * actTime); // Angle in Radians
eccAnom = fgCalcEccAnom(M, e); // Calculate the eccentric Anomaly (also known as solving Kepler's equation)
xv = cos(eccAnom) - e;
yv = sqrt (1.0 - e*e) * sin(eccAnom);
v = atan2 (yv, xv); // the sun's true anomaly
distance = r = sqrt (xv*xv + yv*yv); // and its distance
lonEcl = v + w; // the sun's true longitude
latEcl = 0;
// convert the sun's true longitude to ecliptic rectangular
// geocentric coordinates (xs, ys)
xs = r * cos (lonEcl);
ys = r * sin (lonEcl);
// convert ecliptic coordinates to equatorial rectangular
// geocentric coordinates
xe = xs;
ye = ys * cos (ecl);
ze = ys * sin (ecl);
// And finally, calculate right ascension and declination
rightAscension = atan2 (ye, xe);
declination = atan2 (ze, sqrt (xe*xe + ye*ye));
}
void Star::newImage(void)
{
/*static float stars[3];
stars[0] = 0.0;
stars[1] = 0.0;
stars[2] = 1.0;*/
fgLIGHT *l = &cur_light_params;
float sun_angle = l->sun_angle;
if( sun_angle*RAD_TO_DEG < 100 ) { // else no need to draw sun
double x_2, x_4, x_8, x_10;
GLfloat ambient;
GLfloat amb[4];
int sun_size = 550;
// daily variation sun gets larger near horizon
/*if(sun_angle*RAD_TO_DEG > 84.0 && sun_angle*RAD_TO_DEG < 95)
{
double sun_grow = 9*fabs(94-sun_angle*RAD_TO_DEG);
sun_size = (int)(sun_size + sun_size * cos(sun_grow*DEG_TO_RAD));
}*/
x_2 = sun_angle * sun_angle;
x_4 = x_2 * x_2;
x_8 = x_4 * x_4;
x_10 = x_8 * x_2;
ambient = (float)(0.4 * pow (1.1, - x_10 / 30.0));
if (ambient < 0.3) ambient = 0.3;
if (ambient > 1.0) ambient = 1.0;
amb[0] = ((ambient * 6.0) - 1.0); // minimum value = 0.8
amb[1] = ((ambient * 11.0) - 3.0); // minimum value = 0.3
amb[2] = ((ambient * 12.0) - 3.6); // minimum value = 0.0
amb[3] = 1.00;
if (amb[0] > 1.0) amb[0] = 1.0;
if (amb[1] > 1.0) amb[1] = 1.0;
if (amb[2] > 1.0) amb[2] = 1.0;
xglColor3fv(amb);
glPushMatrix();
{
xglRotatef(((RAD_TO_DEG * rightAscension)- 90.0), 0.0, 0.0, 1.0);
xglRotatef((RAD_TO_DEG * declination), 1.0, 0.0, 0.0);
xglTranslatef(0,60000,0);
if (current_options.get_textures())
{
glEnable(GL_TEXTURE_2D); // TEXTURE ENABLED
glEnable(GL_BLEND); // BLEND ENABLED
// glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ;
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glBindTexture(GL_TEXTURE_2D, sun_texid);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-5000, 0.0, -5000);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 5000, 0.0, -5000);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 5000, 0.0, 5000);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-5000, 0.0, 5000);
glEnd();
}
xglDisable(GL_TEXTURE_2D); // TEXTURE DISABLED
xglDisable(GL_BLEND); // BLEND DISABLED
}
glPopMatrix();
glDisable(GL_LIGHTING); // LIGHTING DISABLED
glDisable(GL_BLEND); // BLEND DISABLED
glPushMatrix();
{
xglRotatef(((RAD_TO_DEG * rightAscension)- 90.0), 0.0, 0.0, 1.0);
xglRotatef((RAD_TO_DEG * declination), 1.0, 0.0, 0.0);
xglColor4fv(amb);
xglTranslatef(0,60000,0);
gluSphere( SunObject, sun_size, 10, 10 );
}
glPopMatrix();
glDisable(GL_TEXTURE_2D); // TEXTURE DISABLED
glDisable(GL_BLEND); // BLEND DISABLED
}
}
#endif

150
simgear/sky/skysun.hxx Normal file
View File

@@ -0,0 +1,150 @@
// skysun.hxx -- draw a sun object
//
// Written by Durk Talsma. Originally started October 1997, for distribution
// with the FlightGear project. Version 2 was written in August and
// September 1998. This code is based upon algorithms and data kindly
// provided by Mr. Paul Schlyter. (pausch@saaf.se).
//
// Separated out rendering pieces and converted to ssg by Curt Olson,
// March 2000
//
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// $Id$
#ifndef _SKYSUN_HXX_
#define _SKYSUN_HXX_
#include <plib/ssg.h>
class FGSkySun {
// scene graph root for the skysun
ssgRoot *skysun;
ssgSelector *sun_selector;
ssgTransform *sun_transform;
ssgSimpleState *sun_state;
ssgSimpleState *halo_state;
public:
// Constructor
FGSkySun( void );
// Destructor
~FGSkySun( void );
// initialize the sun object and connect it into our scene graph
// root
bool initialize();
// repaint the sun colors based on current value of sun_anglein
// degrees relative to verticle
// 0 degrees = high noon
// 90 degrees = sun rise/set
// 180 degrees = darkest midnight
bool repaint( sgVec3 sky_color, sgVec3 fog_color, double sun_angle );
// reposition the sun at the specified right ascension and
// declination
bool reposition( double rightAscension, double declination );
// Draw the sun
bool draw();
// enable the sun in the scene graph (default)
void enable() { sun_selector->select( 1 ); }
// disable the sun in the scene graph. The leaf node is still
// there, how ever it won't be traversed on the cullandrender
// phase.
void disable() { sun_selector->select( 0 ); }
};
#if 0
class Star : public CelestialBody
{
private:
//double longitude; // the sun's true longitude - this is depreciated by
// CelestialBody::lonEcl
double xs, ys; // the sun's rectangular geocentric coordinates
double distance; // the sun's distance to the earth
GLUquadricObj *SunObject;
GLuint sun_texid;
GLubyte *sun_texbuf;
void setTexture();
public:
Star (FGTime *t);
~Star();
void updatePosition(FGTime *t);
double getM();
double getw();
//double getLon();
double getxs();
double getys();
double getDistance();
void newImage();
};
inline double Star::getM()
{
return M;
}
inline double Star::getw()
{
return w;
}
inline double Star::getxs()
{
return xs;
}
inline double Star::getys()
{
return ys;
}
inline double Star::getDistance()
{
return distance;
}
#endif
#endif // _SKYSUN_HXX_

106
simgear/sky/sphere.cxx Normal file
View File

@@ -0,0 +1,106 @@
// sphere.cxx -- build an ssg sphere object
//
// Pulled straight out of MesaGLU/quadratic.c
//
// Original gluSphere code is Copyright (C) 1999-2000 Brian Paul and
// licensed under the GPL
//
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// $Id$
#include <plib/ssg.h>
// return a sphere object as an ssgBranch
ssgBranch *ssgMakeSphere( double radius, int slices, int stacks ) {
float rho, drho, theta, dtheta;
float x, y, z;
float s, t, ds, dt;
int i, j, imin, imax;
float nsign = 1.0;
ssgBranch *sphere = new ssgBranch;
sgVec2 vec2;
sgVec3 vec3;
drho = M_PI / (float) stacks;
dtheta = 2.0 * M_PI / (float) slices;
/* texturing: s goes from 0.0/0.25/0.5/0.75/1.0 at +y/+x/-y/-x/+y
axis t goes from -1.0/+1.0 at z = -radius/+radius (linear along
longitudes) cannot use triangle fan on texturing (s coord. at
top/bottom tip varies) */
ds = 1.0 / slices;
dt = 1.0 / stacks;
t = 1.0; /* because loop now runs from 0 */
imin = 0;
imax = stacks;
/* build slices as quad strips */
for ( i = imin; i < imax; i++ ) {
ssgVertexArray *vl = new ssgVertexArray();
ssgNormalArray *nl = new ssgNormalArray();
ssgTexCoordArray *tl = new ssgTexCoordArray();
rho = i * drho;
s = 0.0;
for ( j = 0; j <= slices; j++ ) {
theta = (j == slices) ? 0.0 : j * dtheta;
x = -sin(theta) * sin(rho);
y = cos(theta) * sin(rho);
z = nsign * cos(rho);
// glNormal3f( x*nsign, y*nsign, z*nsign );
sgSetVec3( vec3, x*nsign, y*nsign, z*nsign );
nl->add( vec3 );
// glTexCoord2f(s,t);
sgSetVec2( vec2, 2, t );
tl->add( vec2 );
// glVertex3f( x*radius, y*radius, z*radius );
sgSetVec3( vec3, x*radius, y*radius, z*radius );
vl->add( vec3 );
x = -sin(theta) * sin(rho+drho);
y = cos(theta) * sin(rho+drho);
z = nsign * cos(rho+drho);
// glNormal3f( x*nsign, y*nsign, z*nsign );
sgSetVec3( vec3, x*nsign, y*nsign, z*nsign );
nl->add( vec3 );
// glTexCoord2f(s,t-dt);
sgSetVec2( vec2, s, t-dt );
tl->add( vec2 );
s += ds;
// glVertex3f( x*radius, y*radius, z*radius );
sgSetVec3( vec3, x*radius, y*radius, z*radius );
vl->add( vec3 );
}
ssgLeaf *slice =
new ssgVtxTable ( GL_TRIANGLE_STRIP, vl, nl, tl, NULL );
sphere->addKid( slice );
t -= dt;
}
return sphere;
}

29
simgear/sky/sphere.hxx Normal file
View File

@@ -0,0 +1,29 @@
// sphere.hxx -- build an ssg sphere object
//
// Pulled straight out of MesaGLU/quadratic.c
//
// Original gluSphere code is Copyright (C) 1999-2000 Brian Paul and
// licensed under the GPL
//
// 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// $Id$
#include <plib/ssg.h>
// return a sphere object as an ssgBranch
ssgBranch *ssgMakeSphere( double radius, int slices, int stacks );