diff --git a/src/modules/graphic/ssggraph/CMakeLists.txt b/src/modules/graphic/ssggraph/CMakeLists.txt index fef99ecb5..82372e429 100644 --- a/src/modules/graphic/ssggraph/CMakeLists.txt +++ b/src/modules/graphic/ssggraph/CMakeLists.txt @@ -5,7 +5,8 @@ SET(SSGGRAPH_SOURCES CarSoundData.cpp CarSoundData.h SoundInterface.cpp SoundInterface.h PlibSoundInterface.cpp PlibSoundInterface.h OpenalSoundInterface.cpp OpenalSoundInterface.h - grCelestialBody.cpp grCloudLayer.cpp grSky.cpp grSky.h + #grCelestialBody.cpp + grMoon.cpp grSun.cpp grCloudLayer.cpp grSky.cpp grSky.h grSkyDome.cpp grSphere.cpp grSphere.h grStars.cpp grboard.cpp grboard.h grcam.cpp grcam.h grcar.cpp grcar.h grcarlight.cpp grcarlight.h grmain.cpp grmain.h diff --git a/src/modules/graphic/ssggraph/grMoon.cpp b/src/modules/graphic/ssggraph/grMoon.cpp new file mode 100644 index 000000000..5657669e5 --- /dev/null +++ b/src/modules/graphic/ssggraph/grMoon.cpp @@ -0,0 +1,147 @@ +/*************************************************************************** + + file : grMoon.cpp + copyright : (C) 2009 by Xavier Bertaux (based on ssgasky plib code) + web : http://www.speed-dreams.org + version : $Id: grSky.cpp 3162 2010-12-05 13:11:22Z pouillot $ + + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + + + +#include "grSky.h" +#include "grSphere.h" + +static int grMoonOrbPreDraw( ssgEntity *e ) +{ + ssgLeaf *f = (ssgLeaf *)e; + if ( f -> hasState () ) f->getState()->apply() ; + + glPushAttrib( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT ); + glDisable( GL_DEPTH_TEST ); + glDisable( GL_FOG ); + glBlendFunc ( GL_SRC_ALPHA, GL_ONE ); + return true; +} + +static int grMoonOrbPostDraw( ssgEntity *e ) +{ + glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + glPopAttrib(); + return true; +} + +// Constructor +cGrMoon::cGrMoon( void ) : + prev_moon_angle(-1) +{ +} + +// Destructor +cGrMoon::~cGrMoon( void ) +{ +} + +// build the moon object +ssgBranch * cGrMoon::build( const char *moon_path, double moon_size ) +{ + orb_state = new ssgSimpleState(); + orb_state->setTexture( moon_path ); + orb_state->setShadeModel( GL_SMOOTH ); + orb_state->enable( GL_LIGHTING ); + orb_state->enable( GL_CULL_FACE ); + orb_state->enable( GL_TEXTURE_2D ); + orb_state->enable( GL_COLOR_MATERIAL ); + orb_state->setColourMaterial( GL_DIFFUSE ); + orb_state->setMaterial( GL_AMBIENT, 0, 0, 0, 1.0 ); + orb_state->setMaterial( GL_EMISSION, 0.0, 0.0, 0.0, 1 ); + orb_state->setMaterial( GL_SPECULAR, 0, 0, 0, 1 ); + orb_state->enable( GL_BLEND ); + orb_state->enable( GL_ALPHA_TEST ); + orb_state->setAlphaClamp( 0.01 ); + + cl = new ssgColourArray( 1 ); + sgVec4 color; + sgSetVec4( color, 1.0, 1.0, 1.0, 1.0 ); + cl->add( color ); + + ssgBranch *orb = grMakeSphere( orb_state, cl, moon_size, 15, 15, + grMoonOrbPreDraw, grMoonOrbPostDraw ); + + repaint( 0.0 ); + + moon_transform = new ssgTransform; + moon_transform->addKid( orb ); + + return moon_transform; +} + +bool cGrMoon::repaint( double moon_angle ) +{ + if (prev_moon_angle != moon_angle) + { + prev_moon_angle = moon_angle; + + float moon_factor = 4*cos(moon_angle); + + if (moon_factor > 1) moon_factor = 1.0; + if (moon_factor < -1) moon_factor = -1.0; + moon_factor = moon_factor/2 + 0.5; + + sgVec4 color; + color[1] = sqrt(moon_factor); + color[0] = sqrt(color[1]); + color[2] = moon_factor * moon_factor; + color[2] *= color[2]; + color[3] = 1.0; + + grGammaCorrectRGB( color ); + + float *ptr; + ptr = cl->get( 0 ); + sgCopyVec4( ptr, color ); + } + + return true; +} + +bool cGrMoon::reposition( sgVec3 p, double angle, double rightAscension, double declination, double moon_dist ) +{ + sgMat4 T1, T2, GST, RA, DEC; + sgVec3 axis; + sgVec3 v; + + sgMakeTransMat4( T1, p ); + + sgSetVec3( axis, 0.0, 0.0, -1.0 ); + sgMakeRotMat4( GST, (float)angle, axis ); + sgSetVec3( axis, 0.0, 0.0, 1.0 ); + sgMakeRotMat4( RA, ((float)rightAscension * SGD_RADIANS_TO_DEGREES) - 90.0, axis ); + sgSetVec3( axis, 1.0, 0.0, 0.0 ); + sgMakeRotMat4( DEC, (float)declination * SGD_RADIANS_TO_DEGREES, axis ); + sgSetVec3( v, 0.0, moon_dist, 0.0 ); + sgMakeTransMat4( T2, v ); + + sgMat4 TRANSFORM; + sgCopyMat4( TRANSFORM, T1 ); + sgPreMultMat4( TRANSFORM, GST ); + sgPreMultMat4( TRANSFORM, RA ); + sgPreMultMat4( TRANSFORM, DEC ); + sgPreMultMat4( TRANSFORM, T2 ); + + sgCoord skypos; + sgSetCoord( &skypos, TRANSFORM ); + + moon_transform->setTransform( &skypos ); + + return true; +} \ No newline at end of file diff --git a/src/modules/graphic/ssggraph/grSky.cpp b/src/modules/graphic/ssggraph/grSky.cpp index 5ac791225..62c5a1bac 100644 --- a/src/modules/graphic/ssggraph/grSky.cpp +++ b/src/modules/graphic/ssggraph/grSky.cpp @@ -22,36 +22,39 @@ // Used for rise/set effects (flat earth - no rotation of skydome considered here ) void calc_celestial_angles( const sgVec3 body, const sgVec3 view, double& angle, double& rotation ) { - sgVec3 pos; - sgSubVec3(pos, body, view); - angle = (90*SGD_DEGREES_TO_RADIANS) - atan2(pos[2], sqrt(pos[0]*pos[0] + pos[1]*pos[1])); - rotation = (90*SGD_DEGREES_TO_RADIANS) - atan2(pos[0], pos[1]); + sgVec3 pos; + sgSubVec3(pos, body, view); + angle = (90*SGD_DEGREES_TO_RADIANS) - atan2(pos[2], sqrt(pos[0]*pos[0] + pos[1]*pos[1])); + rotation = (90*SGD_DEGREES_TO_RADIANS) - atan2(pos[0], pos[1]); } cGrSky::cGrSky( void ) { - dome = 0; - planets = 0; - stars = 0; - sol_ref = 0; - pre_root = 0; - post_root = 0; + dome = 0; + sun = 0; + moon = 0; + planets = 0; + stars = 0; + pre_root = 0; + post_root = 0; - effective_visibility = visibility = 10000.0; + effective_visibility = visibility = 10000.0; - // near cloud visibility state variables - in_puff = false; - puff_length = 0; - puff_progression = 0; - ramp_up = 0.15; - ramp_down = 0.15; + // near cloud visibility state variables + in_puff = false; + puff_length = 0; + puff_progression = 0; + ramp_up = 0.15; + ramp_down = 0.15; } cGrSky::~cGrSky( void ) { delete dome; + delete sun; + delete moon; delete planets; delete stars; delete pre_root; @@ -60,15 +63,18 @@ cGrSky::~cGrSky( void ) void cGrSky::build( double h_radius, double v_radius, + const char *sun_path, const char *ihalo_path, const char *ohalo_path, + float sun_size, const char *moon_path, float moon_size, int nplanets, sgdVec3 *planet_data, - int nstars, sgdVec3 *star_data ) + int nstars, sgdVec3 *star_data, float humidity, float visibility ) { delete dome; + delete sun; + delete moon; delete planets; delete stars; delete pre_root; delete post_root; - bodies.removeAll(); clouds.removeAll(); // build new @@ -81,19 +87,27 @@ void cGrSky::build( double h_radius, double v_radius, pre_transform = new ssgTransform; post_transform = new ssgTransform; - bodies_transform = new ssgTransform; + sun_transform = new ssgTransform; + moon_transform = new ssgTransform; stars_transform = new ssgTransform; dome = new cGrSkyDome; pre_transform -> addKid( dome->build( h_radius, v_radius ) ); + sun = new cGrSun; + sun_transform -> addKid( sun->build( sun_path, ihalo_path, ohalo_path, sun_size, humidity, visibility)); + + moon = new cGrMoon; + moon_transform -> addKid( moon->build( moon_path, moon_size )); + planets = new cGrStars; stars_transform -> addKid( planets->build( nplanets, planet_data, h_radius ) ); stars = new cGrStars; stars_transform -> addKid( stars->build( nstars, star_data, h_radius ) ); - pre_transform -> addKid( bodies_transform ); + pre_transform -> addKid( sun_transform ); + pre_transform -> addKid( moon_transform ); pre_transform -> addKid( stars_transform ); pre_selector->addKid( pre_transform ); @@ -107,7 +121,7 @@ void cGrSky::build( double h_radius, double v_radius, } -cGrCelestialBody* +/*cGrCelestialBody* cGrSky::addBody( const char *body_tex_path, const char *ihalo_tex_path, const char *ohalo_tex_path, double size, double dist, bool sol ) { cGrCelestialBody* body = new cGrCelestialBody; @@ -136,7 +150,7 @@ cGrSky::addBody( ssgSimpleState *orb_state, ssgSimpleState *ihalo_state, ssgSimp sol_ref = body; return body; -} +}*/ cGrCloudLayer* @@ -161,41 +175,39 @@ cGrSky::addCloud( ssgSimpleState *cloud_state, float span, float elevation, floa bool cGrSky::repositionFlat( sgVec3 view_pos, double spin, double dt ) { - int i; - double angle; - double rotation; - sgCoord pos; + int i; + double angle; + double rotation; + sgCoord pos; - for ( i = 0; i < bodies.getNum (); i++ ) - { - cGrCelestialBody *body = bodies.get(i); - body->reposition( view_pos, 0 ); + sun->reposition( view_pos, 0 ); + moon->reposition( view_pos, 0 ); // Calc angles for rise/set effects - body->getPosition ( & pos ); + sun->getPosition ( & pos ); calc_celestial_angles( pos.xyz, view_pos, angle, rotation ); - body->setAngle( angle ); - body->setRotation( rotation ); - } + sun->setAngle( angle ); + sun->setRotation( rotation ); - for ( i = 0; i < clouds.getNum (); i++ ) - { - clouds.get(i)->repositionFlat( view_pos, dt ); - } - planets->reposition( view_pos, 0 ); - stars->reposition( view_pos, 0 ); + for ( i = 0; i < clouds.getNum (); i++ ) + { + clouds.get(i)->repositionFlat( view_pos, dt ); + } - if ( sol_ref ) - { - dome->repositionFlat( view_pos, sol_ref->getRotation() ); - } - else - { - dome->repositionFlat( view_pos, spin ); - } + planets->reposition( view_pos, 0 ); + stars->reposition( view_pos, 0 ); - return true; + /*if ( sol_ref ) + { + dome->repositionFlat( view_pos, sol_ref->getRotation() ); + } + else + {*/ + dome->repositionFlat( view_pos, spin ); + //} + + return true; } @@ -207,12 +219,11 @@ bool cGrSky::reposition( sgVec3 view_pos, sgVec3 zero_elev, sgVec3 view_up, doub dome->reposition( zero_elev, lon, lat, spin ); - for ( i = 0; i < bodies.getNum (); i++ ) - bodies.get(i)->reposition( view_pos, angle ); - for ( i = 0; i < clouds.getNum (); i++ ) clouds.get(i)->reposition( zero_elev, view_up, lon, lat, alt, dt ); + sun->reposition( view_pos, angle); + moon->reposition(view_pos, angle); planets->reposition( view_pos, angle ); stars->reposition( view_pos, angle ); @@ -233,12 +244,11 @@ bool cGrSky::repaint( sgVec4 sky_color, sgVec4 fog_color, sgVec4 cloud_color, do dome->repaint( sky_color, fog_color, sol_angle, effective_visibility ); - for ( i = 0; i < bodies.getNum (); i++ ) - bodies.get(i)->repaint(); - for ( i = 0; i < clouds.getNum (); i++ ) clouds.get(i)->repaint( cloud_color ); + sun->repaint( sol_angle, effective_visibility ); + moon->repaint( sol_angle ); planets->repaint( sol_angle, nplanets, planet_data ); stars->repaint( sol_angle, nstars, star_data ); } diff --git a/src/modules/graphic/ssggraph/grSky.h b/src/modules/graphic/ssggraph/grSky.h index 24dd17285..5d2814e78 100644 --- a/src/modules/graphic/ssggraph/grSky.h +++ b/src/modules/graphic/ssggraph/grSky.h @@ -22,15 +22,199 @@ #include "plib/ssg.h" -class cGrCelestialBody; -class cGrCelestialBodyList; +//class cGrCelestialBody; +//class cGrCelestialBodyList; +class cGrSun; +class cGrMoon; class cGrCloudLayer; class cGrCloudLayerList; class cGrStars; class cGrSkyDome; class cGrSky; -class cGrCelestialBody +class cGrMoon +{ + ssgTransform *moon_transform; + ssgSimpleState *orb_state; + ssgSimpleState *halo_state; + + ssgColourArray *cl; + + ssgVertexArray *halo_vl; + ssgTexCoordArray *halo_tl; + + double prev_moon_angle; + double moon_angle; + double moon_size; + double moon_dist; + double moonAscension; + double moondeclination; + + +public: + + // Constructor + cGrMoon( void ); + + // Destructor + ~cGrMoon( void ); + + // build the moon object + ssgBranch *build( const char* moon_path, double moon_size ); + + // repaint the moon colors based on current value of moon_anglein + // degrees relative to verticle + // 0 degrees = high noon + // 90 degrees = moon rise/set + // 180 degrees = darkest midnight + + //bool repaint(double moon_angle); + + /*bool reposition( sgVec3 p, double angle, + double rightAscension, double declination, + double moon_dist );*/ + + bool reposition(sgVec3 p, double moon_angle) + { + return reposition (p, moon_angle, moonAscension, moondeclination, moon_dist); + } + + bool reposition(sgVec3 p, double moon_angle, double moonAscension, double moondeclination, double moon_dist); + bool repaint(double moon_angle); + + void setmoonRightAscension ( double ra ) { moonAscension = ra; } + double getRightAscension () { return moonAscension; } + + void setmoonDeclination ( double decl ) { moondeclination = decl; } + double getmoonDeclination () { return moondeclination; } +}; + +class cGrSun +{ + ssgTransform *sun_transform; + ssgSimpleState *sun_state; + ssgSimpleState *ihalo_state; + ssgSimpleState *ohalo_state; + + ssgColourArray *sun_cl; + ssgColourArray *ihalo_cl; + ssgColourArray *ohalo_cl; + + ssgVertexArray *sun_vl; + ssgVertexArray *ihalo_vl; + ssgVertexArray *ohalo_vl; + + ssgTexCoordArray *sun_tl; + ssgTexCoordArray *ihalo_tl; + ssgTexCoordArray *ohalo_tl; + + GLuint sun_texid; + GLubyte *sun_texbuf; + + double visibility; + double prev_sun_angle; + double sun_angle; + double sun_rotation; + + // used by reposition + double sun_right_ascension; + double sun_declination; + double sun_dist; + double path_distance; + +public: + + // Constructor + cGrSun( void ); + + // Destructor + ~cGrSun( void ); + + // return the sun object + ssgBranch *build( const char* sun_path, const char *ihalo_path, const char* ohalo_path, float sun_size, float humidity, float visibility ); + + // 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( double sun_angle, double new_visibility ); + + // reposition the sun at the specified right ascension and + // declination, offset by our current position (p) so that it + // appears fixed at a great distance from the viewer. Also add in + // an optional rotation (i.e. for the current time of day.) + + /*bool reposition( sgVec3 p, double angle, + double rightAscension, double declination, + double sun_dist, double lat, double alt_asl, double sun_angle );*/ + + bool reposition( sgVec3 p, double sun_angle ) + { + return reposition ( p, sun_angle, sun_right_ascension, sun_declination, sun_dist ); + } + + bool reposition( sgVec3 p, double sun_angle, double rightAscension, double declination, double dist ); + + void getPosition (sgCoord* p) + { + sgMat4 Xform; + sun_transform->getTransform(Xform); + sgSetCoord(p, Xform); + } + + void setAngle (double angle) + { + sun_angle = angle; + } + + double getAngle () + { + return sun_angle; + } + + void setRotation (double rotation) + { + sun_rotation = rotation; + } + double getRotation () + { + return sun_rotation; + } + + void setRightAscension (double ra) + { + sun_right_ascension = ra; + } + double getRightAscension () + { + return sun_right_ascension; + } + + void setDeclination ( double decl ) + { + sun_declination = decl; + } + double getDeclination () + { + return sun_declination; + } + + void setDist ( double dist ) + { + sun_dist = dist; + } + double getDist () + { + return sun_dist; + } + + // retrun the current color of the sun + inline float *get_color() { return ohalo_cl->get( 0 ); } + double effective_visibility; +}; + +/*class cGrCelestialBody { private: @@ -117,7 +301,7 @@ public: delete get (i) ; ssgSimpleList::removeAll () ; } -} ; +} ;*/ class cGrCloudLayer @@ -273,8 +457,8 @@ private: // components of the sky cGrSkyDome *dome; - cGrCelestialBody* sol_ref; - cGrCelestialBodyList bodies; + cGrSun *sun; + cGrMoon *moon; cGrCloudLayerList clouds; cGrStars *planets; cGrStars *stars; @@ -283,7 +467,7 @@ private: ssgSelector *pre_selector, *post_selector; ssgTransform *pre_transform, *post_transform; - ssgTransform *bodies_transform, *stars_transform; + ssgTransform *sun_transform, *moon_transform, *stars_transform; // visibility float visibility; @@ -302,13 +486,11 @@ public: ~cGrSky( void ); void build( double h_radius, double v_radius, + const char *sun_path, const char *ihalo_path, + const char *ohalo_path, float sun_size, + const char *moon_path, float moon_size, int nplanets, sgdVec3 *planet_data, - int nstars, sgdVec3 *star_data); - - cGrCelestialBody* addBody( const char *body_tex_path, const char *ihalo_path, const char* ohalo_path, double size, double dist, bool sol = false ); - cGrCelestialBody* addBody( ssgSimpleState *orb_state, ssgSimpleState *ihalo_state, ssgSimpleState *ohalo_state, double size, double dist, bool sol = false ); - cGrCelestialBody* getBody(int i) { return bodies.get(i); } - int getBodyCount() { return bodies.getNum(); } + int nstars, sgdVec3 *star_data, float humidity, float visibility); cGrCloudLayer* addCloud( const char *cloud_tex_path, float span, float elevation, float thickness, float transition ); cGrCloudLayer* addCloud( ssgSimpleState *cloud_state, float span, float elevation, float thickness, float transition ); @@ -391,190 +573,4 @@ inline void grGammaRestoreC(float *color, float reff = 2.5, float system = syste *color = (float)pow(*color, system/reff); }; -#if O -class cGrMoon -{ - ssgTransform *moon_transform; - ssgSimpleState *orb_state; - ssgSimpleState *halo_state; - - ssgColourArray *cl; - - ssgVertexArray *halo_vl; - ssgTexCoordArray *halo_tl; - - double prev_moon_angle; - double moon_angle; - double moon_rotation; - - // used by reposition - double moon_right_ascension; - double moon_declination; - double moon_dist; - -public: - - // Constructor - cGrMoon( void ); - - // Destructor - ~cGrMoon( void ); - - // build the moon object - ssgBranch *build( const char* body_tex_path, double moon_size ); - - // repaint the moon colors based on current value of moon_anglein - // degrees relative to verticle - // 0 degrees = high noon - // 90 degrees = moon rise/set - // 180 degrees = darkest midnight - - //bool repaint(double moon_angle); - - /*bool reposition( sgVec3 p, double angle, - double rightAscension, double declination, - double moon_dist );*/ - - /*bool reposition(sgVec3 p, double moon_angle) - { - return reposition (p, moon_angle, rightAscension, declination, moon_dist); - }*/ - - bool reposition(sgVec3 p, double moon_angle, double rightAscension, double declination, double moon_dist); - - /*bool repaint() - { - return repaint (moon_angle); - }*/ - bool repaint(double moon_angle); - - void getPosition (sgCoord* p) - { - sgMat4 Xform; - moon_transform->getTransform(Xform); - sgSetCoord(p, Xform); - } - - void setAngle (double angle) - { - moon_angle = angle; - } - double getAngle () - { - return moon_angle; - } - - void setRotation (double rotation) - { - moon_rotation = rotation; - } - double getRotation () - { - return moon_rotation; - } - - void setRightAscension (double ra) - { - moon_right_ascension = ra; - } - double getRightAscension () - { - return moon_right_ascension; - } - - void setDeclination ( double decl ) - { - moon_declination = decl; - } - double getDeclination () - { - return moon_declination; - } - - void setDist ( double dist ) - { - moon_dist = dist; - } - double getDist () - { - return moon_dist; - } - - inline float *getColor() - { - return cl->get( 0 ); - } -}; - -// Not used. - -class cGrSun -{ - ssgTransform *sun_transform; - ssgSimpleState *sun_state; - ssgSimpleState *ihalo_state; - ssgSimpleState *ohalo_state; - - ssgColourArray *sun_cl; - ssgColourArray *ihalo_cl; - ssgColourArray *ohalo_cl; - - ssgVertexArray *sun_vl; - ssgVertexArray *ihalo_vl; - ssgVertexArray *ohalo_vl; - - ssgTexCoordArray *sun_tl; - ssgTexCoordArray *ihalo_tl; - ssgTexCoordArray *ohalo_tl; - - GLuint sun_texid; - GLubyte *sun_texbuf; - - double visibility; - double prev_sun_angle; - // distance of light traveling through the atmosphere - double path_distance; - -public: - - // Constructor - cGrSun( void ); - - // Destructor - ~cGrSun( void ); - - // return the sun object - ssgBranch *build( const char* body_tex_path, const char* halo_tex_path, double sun_size); - - // 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( double sun_angle, double new_visibility ); - - // reposition the sun at the specified right ascension and - // declination, offset by our current position (p) so that it - // appears fixed at a great distance from the viewer. Also add in - // an optional rotation (i.e. for the current time of day.) - - /*bool reposition( sgVec3 p, double angle, - double rightAscension, double declination, - double sun_dist, double lat, double alt_asl, double sun_angle );*/ - - bool reposition( sgVec3 p, double sun_angle ) - { - return reposition ( p, angle, sun_right_ascension, sun_declination, sun_body_dist ); - } - - bool reposition( sgVec3 p, double sun_angle, double rightAscension, double declination, double dist ); - - // retrun the current color of the sun - inline float *get_color() { return ohalo_cl->get( 0 ); } - - // return the texture id of the sun halo texture - inline GLuint get_texture_id() { return ohalo_state->getTextureHandle(); } -}; -#endif - #endif diff --git a/src/modules/graphic/ssggraph/grSun.cpp b/src/modules/graphic/ssggraph/grSun.cpp new file mode 100644 index 000000000..56c480c26 --- /dev/null +++ b/src/modules/graphic/ssggraph/grSun.cpp @@ -0,0 +1,409 @@ +/*************************************************************************** + + file : grSun.cpp + copyright : (C) 2009 by Xavier Bertaux (based on ssgasky plib code) + web : http://www.speed-dreams.org + version : $Id: grSky.cpp 3162 2010-12-05 13:11:22Z pouillot $ + + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ + +#include +#include +#include "grSky.h" +#include "grSphere.h" + +static float sun_exp2_punch_through; + +// Set up sun rendering call backs +static int grSunPreDraw( ssgEntity *e ) +{ + ssgLeaf *f = (ssgLeaf *)e; + if ( f -> hasState () ) f->getState()->apply() ; + + glPushAttrib( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_FOG_BIT ); + glDisable( GL_DEPTH_TEST ); + glDisable( GL_FOG ); + glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ; + return true; +} + +static int grSunPostDraw( ssgEntity *e ) +{ + glPopAttrib(); + return true; +} + +static int grSunHaloPreDraw( ssgEntity *e ) +{ + ssgLeaf *f = (ssgLeaf *)e; + if ( f -> hasState () ) f->getState()->apply(); + + glPushAttrib( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_FOG_BIT ); + glDisable( GL_DEPTH_TEST ); + glFogf (GL_FOG_DENSITY, sun_exp2_punch_through); + glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ; + + return true; +} + +static int grSunHaloPostDraw( ssgEntity *e ) +{ + glPopAttrib(); + return true; +} + +// Constructor +cGrSun::cGrSun( void ) +{ + prev_sun_angle = -9999.0; + visibility = -9999.0; +} + +// Destructor +cGrSun::~cGrSun( void ) +{ +} + +ssgBranch * cGrSun::build( const char *sun_path, const char *ihalo_path, const char *ohalo_path, float sun_size, float humidity, float visibility ) +{ + sgVec4 color; + sgSetVec4( color, 1.0, 1.0, 1.0, 1.0 ); + + sun_cl = new ssgColourArray( 1 ); + sun_cl->add( color ); + + ihalo_cl = new ssgColourArray( 1 ); + ihalo_cl->add( color ); + + ohalo_cl = new ssgColourArray( 1 ); + ohalo_cl->add( color ); + + //repaint( 0.0, 1.0 ); + + // set up the sun-state + sun_state = new ssgSimpleState(); + sun_state->setShadeModel( GL_SMOOTH ); + sun_state->disable( GL_LIGHTING ); + sun_state->disable( GL_CULL_FACE ); + sun_state->setTexture( sun_path); + sun_state->enable( GL_TEXTURE_2D ); + sun_state->enable( GL_COLOR_MATERIAL ); + sun_state->setColourMaterial( GL_AMBIENT_AND_DIFFUSE ); + sun_state->setMaterial( GL_EMISSION, 0, 0, 0, 1 ); + sun_state->setMaterial( GL_SPECULAR, 0, 0, 0, 1 ); + sun_state->enable( GL_BLEND ); + sun_state->setAlphaClamp( 0.01 ); + sun_state->enable( GL_ALPHA_TEST ); + + // Build ssg structure + + sgVec3 va; + sun_vl = new ssgVertexArray; + sgSetVec3( va, -sun_size, 0.0, -sun_size ); + sun_vl->add( va ); + sgSetVec3( va, sun_size, 0.0, -sun_size ); + sun_vl->add( va ); + sgSetVec3( va, -sun_size, 0.0, sun_size ); + sun_vl->add( va ); + sgSetVec3( va, sun_size, 0.0, sun_size ); + sun_vl->add( va ); + + sgVec2 vb; + sun_tl = new ssgTexCoordArray; + sgSetVec2( vb, 0.0f, 0.0f ); + sun_tl->add( vb ); + sgSetVec2( vb, 1.0, 0.0 ); + sun_tl->add( vb ); + sgSetVec2( vb, 0.0, 1.0 ); + sun_tl->add( vb ); + sgSetVec2( vb, 1.0, 1.0 ); + sun_tl->add( vb ); + + ssgBranch *sun = grMakeSphere( sun_state, sun_cl, sun_size, 15, 15, + grSunPreDraw, grSunPostDraw ); + + repaint( 0.0, 1.0 ); + + ihalo_state = new ssgSimpleState(); + ihalo_state->setTexture( ihalo_path ); + ihalo_state->enable( GL_TEXTURE_2D ); + ihalo_state->disable( GL_LIGHTING ); + ihalo_state->setShadeModel( GL_SMOOTH ); + ihalo_state->disable( GL_CULL_FACE ); + ihalo_state->enable( GL_COLOR_MATERIAL ); + ihalo_state->setColourMaterial( GL_AMBIENT_AND_DIFFUSE ); + ihalo_state->setMaterial( GL_EMISSION, 0, 0, 0, 1 ); + ihalo_state->setMaterial( GL_SPECULAR, 0, 0, 0, 1 ); + ihalo_state->enable( GL_ALPHA_TEST ); + ihalo_state->setAlphaClamp(0.01); + ihalo_state->enable ( GL_BLEND ) ; + + float ihalo_size = sun_size * 2.0; + sgVec3 vc; + ihalo_vl = new ssgVertexArray; + sgSetVec3( vc, -ihalo_size, 0.0, -ihalo_size ); + ihalo_vl->add( vc ); + sgSetVec3( vc, ihalo_size, 0.0, -ihalo_size ); + ihalo_vl->add( vc ); + sgSetVec3( vc, -ihalo_size, 0.0, ihalo_size ); + ihalo_vl->add( vc ); + sgSetVec3( vc, ihalo_size, 0.0, ihalo_size ); + ihalo_vl->add( vc ); + + sgVec2 vd; + ihalo_tl = new ssgTexCoordArray; + sgSetVec2( vd, 0.0f, 0.0f ); + ihalo_tl->add( vd ); + sgSetVec2( vd, 1.0, 0.0 ); + ihalo_tl->add( vd ); + sgSetVec2( vd, 0.0, 1.0 ); + ihalo_tl->add( vd ); + sgSetVec2( vd, 1.0, 1.0 ); + ihalo_tl->add( vd ); + + ssgLeaf *ihalo = new ssgVtxTable ( GL_TRIANGLE_STRIP, ihalo_vl, NULL, ihalo_tl, ihalo_cl ); + ihalo->setState( ihalo_state ); + + ohalo_state = new ssgSimpleState(); + ohalo_state->setTexture( ohalo_path ); + ohalo_state->enable( GL_TEXTURE_2D ); + ohalo_state->disable( GL_LIGHTING ); + ohalo_state->setShadeModel( GL_SMOOTH ); + ohalo_state->disable( GL_CULL_FACE ); + ohalo_state->enable( GL_COLOR_MATERIAL ); + ohalo_state->setColourMaterial( GL_AMBIENT_AND_DIFFUSE ); + ohalo_state->setMaterial( GL_EMISSION, 0, 0, 0, 1 ); + ohalo_state->setMaterial( GL_SPECULAR, 0, 0, 0, 1 ); + ohalo_state->enable( GL_ALPHA_TEST ); + ohalo_state->setAlphaClamp(0.01); + ohalo_state->enable ( GL_BLEND ) ; + + float ohalo_size = (float)sun_size * 7.0; + sgVec3 ve; + ohalo_vl = new ssgVertexArray; + sgSetVec3( ve, -ohalo_size, 0.0, -ohalo_size ); + ohalo_vl->add( ve ); + sgSetVec3( ve, ohalo_size, 0.0, -ohalo_size ); + ohalo_vl->add( ve ); + sgSetVec3( ve, -ohalo_size, 0.0, ohalo_size ); + ohalo_vl->add( ve ); + sgSetVec3( ve, ohalo_size, 0.0, ohalo_size ); + ohalo_vl->add( ve ); + + sgVec2 vf; + ohalo_tl = new ssgTexCoordArray; + sgSetVec2( vf, 0.0f, 0.0f ); + ohalo_tl->add( vf ); + sgSetVec2( vf, 1.0, 0.0 ); + ohalo_tl->add( vf ); + sgSetVec2( vf, 0.0, 1.0 ); + ohalo_tl->add( vf ); + sgSetVec2( vf, 1.0, 1.0 ); + ohalo_tl->add( vf ); + + ssgLeaf *ohalo = new ssgVtxTable ( GL_TRIANGLE_STRIP, ohalo_vl, NULL, ohalo_tl, ohalo_cl ); + ohalo->setState( ohalo_state ); + + sun_transform = new ssgTransform; + + ihalo->setCallback( SSG_CALLBACK_PREDRAW, grSunHaloPreDraw ); + ihalo->setCallback( SSG_CALLBACK_POSTDRAW, grSunHaloPostDraw ); + ohalo->setCallback( SSG_CALLBACK_PREDRAW, grSunHaloPreDraw ); + ohalo->setCallback( SSG_CALLBACK_POSTDRAW, grSunHaloPostDraw ); + + sun_transform->addKid( ohalo ); + sun_transform->addKid( ihalo ); + sun_transform->addKid( sun ); + + return sun_transform; +} + +bool cGrSun::repaint( double sun_angle, double new_visibility ) +{ + if ( visibility != new_visibility ) + { + visibility = new_visibility; + + static const float sqrt_m_log01 = sqrt( -log( 0.01 ) ); + sun_exp2_punch_through = sqrt_m_log01 / ( visibility * 15 ); + } + + if ( prev_sun_angle != sun_angle ) + { + prev_sun_angle = sun_angle; + + float aerosol_factor; + if ( visibility < 100 ) + { + aerosol_factor = 8000; + } + else + { + aerosol_factor = 80.5 / log( visibility / 100 ); + } + + float rel_humidity, density_avg; + + /*if ( !env_node ) + {*/ + rel_humidity = 0.5; + density_avg = 0.7; + /*} + else + { + //rel_humidity = env_node->getFloatValue( "relative-humidity" ); + //density_avg = env_node->getFloatValue( "atmosphere/density-tropo-avg" ); + }*/ + + sgVec4 i_halo_color, o_halo_color, sun_color; + + float red_scat_f = ( aerosol_factor * path_distance * density_avg ) / 5E+07; + sun_color[0] = 1 - red_scat_f; + i_halo_color[0] = 1 - ( 1.1 * red_scat_f ); + o_halo_color[0] = 1 - ( 1.4 * red_scat_f ); + + // Green - 546.1 nm + float green_scat_f = ( aerosol_factor * path_distance * density_avg ) / 8.8938E+06; + sun_color[1] = 1 - green_scat_f; + i_halo_color[1] = 1 - ( 1.1 * green_scat_f ); + o_halo_color[1] = 1 - ( 1.4 * green_scat_f ); + + // Blue - 435.8 nm + float blue_scat_f = ( aerosol_factor * path_distance * density_avg ) / 3.607E+06; + sun_color[2] = 1 - blue_scat_f; + i_halo_color[2] = 1 - ( 1.1 * blue_scat_f ); + o_halo_color[2] = 1 - ( 1.4 * blue_scat_f ); + + // Alpha + sun_color[3] = 1; + i_halo_color[3] = 1; + + o_halo_color[3] = blue_scat_f; + if ( ( new_visibility < 10000 ) && ( blue_scat_f > 1 )) + { + o_halo_color[3] = 2 - blue_scat_f; + } + + float saturation = 1 - ( rel_humidity / 200 ); + sun_color[1] += (( 1 - saturation ) * ( 1 - sun_color[1] )); + sun_color[2] += (( 1 - saturation ) * ( 1 - sun_color[2] )); + + i_halo_color[1] += (( 1 - saturation ) * ( 1 - i_halo_color[1] )); + i_halo_color[2] += (( 1 - saturation ) * ( 1 - i_halo_color[2] )); + + o_halo_color[1] += (( 1 - saturation ) * ( 1 - o_halo_color[1] )); + o_halo_color[2] += (( 1 - saturation ) * ( 1 - o_halo_color[2] )); + + // just to make sure we're in the limits + if ( sun_color[0] < 0 ) sun_color[0] = 0; + else if ( sun_color[0] > 1) sun_color[0] = 1; + if ( i_halo_color[0] < 0 ) i_halo_color[0] = 0; + else if ( i_halo_color[0] > 1) i_halo_color[0] = 1; + if ( o_halo_color[0] < 0 ) o_halo_color[0] = 0; + else if ( o_halo_color[0] > 1) o_halo_color[0] = 1; + + if ( sun_color[1] < 0 ) sun_color[1] = 0; + else if ( sun_color[1] > 1) sun_color[1] = 1; + if ( i_halo_color[1] < 0 ) i_halo_color[1] = 0; + else if ( i_halo_color[1] > 1) i_halo_color[1] = 1; + if ( o_halo_color[1] < 0 ) o_halo_color[1] = 0; + else if ( o_halo_color[1] > 1) o_halo_color[1] = 1; + + if ( sun_color[2] < 0 ) sun_color[2] = 0; + else if ( sun_color[2] > 1) sun_color[2] = 1; + if ( i_halo_color[2] < 0 ) i_halo_color[2] = 0; + else if ( i_halo_color[2] > 1) i_halo_color[2] = 1; + if ( o_halo_color[2] < 0 ) o_halo_color[2] = 0; + else if ( o_halo_color[2] > 1) o_halo_color[2] = 1; + if ( o_halo_color[3] < 0 ) o_halo_color[2] = 0; + else if ( o_halo_color[3] > 1) o_halo_color[3] = 1; + + + grGammaCorrectRGB( i_halo_color ); + grGammaCorrectRGB( o_halo_color ); + grGammaCorrectRGB( sun_color ); + + + float *ptr; + ptr = sun_cl->get( 0 ); + sgCopyVec4( ptr, sun_color ); + ptr = ihalo_cl->get( 0 ); + sgCopyVec4( ptr, i_halo_color ); + ptr = ohalo_cl->get( 0 ); + sgCopyVec4( ptr, o_halo_color ); + } + + return true; +} + +bool cGrSun::reposition( sgVec3 p, double angle, double rightAscension, double declination, double sun_dist ) +{ + sgMat4 T1, T2, GST, RA, DEC; + sgVec3 axis; + sgVec3 v; + + sgMakeTransMat4( T1, p ); + sgSetVec3( axis, 0.0, 0.0, -1.0 ); + sgMakeRotMat4( GST, (float)angle, axis ); + sgSetVec3( axis, 0.0, 0.0, 1.0 ); + sgMakeRotMat4( RA, ((float)rightAscension * SGD_RADIANS_TO_DEGREES) - 90.0, axis ); + sgSetVec3( axis, 1.0, 0.0, 0.0 ); + sgMakeRotMat4( DEC, (float)declination * SGD_RADIANS_TO_DEGREES, axis ); + + sgSetVec3( v, 0.0, sun_dist, 0.0 ); + sgMakeTransMat4( T2, v ); + + sgMat4 TRANSFORM; + sgCopyMat4( TRANSFORM, T1 ); + sgPreMultMat4( TRANSFORM, GST ); + sgPreMultMat4( TRANSFORM, RA ); + sgPreMultMat4( TRANSFORM, DEC ); + sgPreMultMat4( TRANSFORM, T2 ); + + sgCoord skypos; + sgSetCoord( &skypos, TRANSFORM ); + + sun_transform->setTransform( &skypos ); + + if ( prev_sun_angle != sun_angle ) + { + if ( sun_angle == 0 ) sun_angle = 0.1; + const double r_earth_pole = 6356752.314; + const double r_tropo_pole = 6356752.314 + 8000; + const double epsilon_earth2 = 6.694380066E-3; + const double epsilon_tropo2 = 9.170014946E-3; + + double r_tropo = r_tropo_pole / sqrt ( 1 - ( epsilon_tropo2 * pow ( cos( 0.0 ), 2 ))); + double r_earth = r_earth_pole / sqrt ( 1 - ( epsilon_earth2 * pow ( cos( 0.0 ), 2 ))); + + double position_radius = r_earth; + + double gamma = SG_PI - sun_angle; + double sin_beta = ( position_radius * sin ( gamma ) ) / r_tropo; + double alpha = SG_PI - gamma - asin( sin_beta ); + + path_distance = sqrt( pow( position_radius, 2 ) + pow( r_tropo, 2 ) + - ( 2 * position_radius * r_tropo * cos( alpha ) )); + + double alt_half = sqrt( pow ( r_tropo, 2 ) + pow( path_distance / 2, 2 ) - r_tropo * path_distance * cos( asin( sin_beta )) ) - r_earth; + + if ( alt_half < 0.0 ) alt_half = 0.0; + + /*if ( env_node ) + { + //env_node->setDoubleValue( "atmosphere/altitude-troposphere-top", r_tropo - r_earth ); + //env_node->setDoubleValue( "atmosphere/altitude-half-to-sun", alt_half ); + }*/ + } + + return true; +} \ No newline at end of file diff --git a/src/modules/graphic/ssggraph/grbackground.cpp b/src/modules/graphic/ssggraph/grbackground.cpp index 49389b3ee..36381ea6a 100755 --- a/src/modules/graphic/ssggraph/grbackground.cpp +++ b/src/modules/graphic/ssggraph/grbackground.cpp @@ -50,8 +50,6 @@ static const int NMaxStars = 1000; static const int NMaxPlanets = 0; //No planets displayed for the moment static const int NMaxCloudLayers = 3; -enum {eCBSun = 0, eCBMoon, NMaxCelestianBodies}; // Celestial bodies in the sky. - static const sgVec4 Black = { 0.0f, 0.0f, 0.0f, 1.0f } ; static const sgVec4 White = { 1.0f, 1.0f, 1.0f, 1.0f } ; static const sgVec4 TranslucentWhite = { 1.0f, 1.0f, 1.0f, 0.8f } ; @@ -96,8 +94,10 @@ static ssgBranch *SunAnchor = NULL; static ssgRoot *TheBackground = NULL; static ssgTransform *TheSun = NULL; -static cGrCelestialBody *TheCelestBodies[NMaxCelestianBodies] = { NULL, NULL }; +//static cGrCelestialBody *TheCelestBodies[NMaxCelestianBodies] = { NULL, NULL }; static cGrSky *TheSky = NULL; +static cGrSun *Sun = NULL; +static cGrMoon *Moon = NULL; static sgdVec3 *AStarsData = NULL; static sgdVec3 *APlanetsData = NULL; @@ -218,17 +218,18 @@ grInitBackground() //Build the sky TheSky = new cGrSky; - TheSky->build(grSkyDomeDistance, grSkyDomeDistance, NPlanets, APlanetsData, NStars, AStarsData); - - //Add the Sun itself + const double domeSizeRatio = grSkyDomeDistance / 80000.0; - TheCelestBodies[eCBSun] = TheSky->addBody(NULL, "data/textures/halo.rgba", "data/textures/outer_halo.rgba", - 2500 * domeSizeRatio, grSkyDomeDistance, /*isSun=*/true); + + TheSky->build(grSkyDomeDistance, grSkyDomeDistance, "data/textures/halo.rgba", "data/textures/halo.rgba", "data/textures/outer_halo.rgba", + 2500 * domeSizeRatio, "data/textures/moon.rgba", 2000 * domeSizeRatio, NPlanets, APlanetsData, NStars, AStarsData, 0.5f, visibility); + + //Add the Sun itself GLfloat sunAscension = grTrack->local.sunascension; grSunDeclination = (float)(15 * (double)timeOfDay / 3600 - 90.0); - TheCelestBodies[eCBSun]->setDeclination ( DEG2RAD(grSunDeclination)); - TheCelestBodies[eCBSun]->setRightAscension ( sunAscension ); + Sun->setDeclination ( DEG2RAD(grSunDeclination)); + Sun->setRightAscension ( sunAscension ); GfLogInfo(" Sun : time of day = %02d:%02d:%02d (declination = %.1f deg), " "ascension = %.1f deg\n", @@ -236,8 +237,6 @@ grInitBackground() grSunDeclination, RAD2DEG(sunAscension)); // Add the Moon (TODO: Find a better solution than this random positioning !) - TheCelestBodies[eCBMoon] = TheSky->addBody ( "data/textures/moon.rgba",NULL, NULL, - 2000 * domeSizeRatio, grSkyDomeDistance); if ( grSunDeclination > 180 ) grMoonDeclination = 3.0 + (rand() % 40); else @@ -245,8 +244,8 @@ grInitBackground() const float moonAscension = (float)(rand() % 360); - TheCelestBodies[eCBMoon]->setDeclination ( DEG2RAD(grMoonDeclination) ); - TheCelestBodies[eCBMoon]->setRightAscension ( DEG2RAD(moonAscension) ); + Moon->setmoonDeclination ( DEG2RAD(grMoonDeclination) ); + Moon->setmoonRightAscension ( DEG2RAD(moonAscension) ); GfLogInfo(" Moon : declination = %.1f deg, ascension = %.1f deg\n", grMoonDeclination, moonAscension); @@ -335,7 +334,7 @@ grInitBackground() // Set up the light source to the Sun position. sgCoord sunPosition; - TheCelestBodies[eCBSun]->getPosition(&sunPosition); + Sun->getPosition(&sunPosition); light->setPosition(sunPosition.xyz); // Initialize the whole sky dome. @@ -378,7 +377,7 @@ grInitBackground() const GLfloat fog_exp2_density = sqrt_m_log01 / visibility; //Setup overall light level according to rain if any - const float sol_angle = (float)TheCelestBodies[eCBSun]->getAngle(); + const float sol_angle = (float)Sun->getAngle(); const float sky_brightness = (float)(1.0 + cos(sol_angle)) / 2.0f; float scene_brightness = (float)pow(sky_brightness, 0.5f); @@ -413,7 +412,7 @@ grInitBackground() NPlanets, APlanetsData, NStars, AStarsData); sgCoord solpos; - TheCelestBodies[eCBSun]->getPosition(&solpos); + Sun->getPosition(&solpos); light->setPosition(solpos.xyz); SceneAmbiant[0] = BaseAmbiant[0] * scene_brightness; @@ -1020,19 +1019,19 @@ grUpdateSky(double currentTime, double accelTime) if (grSunDeclination >= 360.0f) grSunDeclination -= 360.0f; - TheCelestBodies[eCBSun]->setDeclination ( DEG2RAD(grSunDeclination) ); + Sun->setDeclination ( DEG2RAD(grSunDeclination) ); // 2) Update moon position grMoonDeclination += deltaDecl; if (grMoonDeclination >= 360.0f) grMoonDeclination -= 360.0f; - TheCelestBodies[eCBMoon]->setDeclination ( DEG2RAD(grMoonDeclination) ); + Moon->setmoonDeclination ( DEG2RAD(grMoonDeclination) ); lastTimeLowSpeed = nextTimeLowSpeed; } // 3) Update scene color and light - const float sol_angle = (float)TheCelestBodies[eCBSun]->getAngle(); + const float sol_angle = (float)Sun->getAngle(); const float sky_brightness = (float)(1.0 + cos(sol_angle)) / 2.0f; float scene_brightness = (float)pow(sky_brightness, 0.5f); @@ -1070,7 +1069,7 @@ grUpdateSky(double currentTime, double accelTime) // 3c) update the main light position (it's at the sun position !) sgCoord solpos; - TheCelestBodies[eCBSun]-> getPosition(&solpos); + Sun-> getPosition(&solpos); ssgGetLight(0)-> setPosition(solpos.xyz); // 3c) update scene colors.