mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-03-22 15:05:03 +01:00
moon phases, sun & moon billboards
This commit is contained in:
75
World.cpp
75
World.cpp
@@ -158,6 +158,29 @@ simulation_time::daymonth( WORD &Day, WORD &Month, WORD const Year, WORD const Y
|
||||
Day = Yearday - daytab[ leap ][ idx - 1 ];
|
||||
}
|
||||
|
||||
int
|
||||
simulation_time::julian_day() const {
|
||||
|
||||
int yy = ( m_time.wYear < 0 ? m_time.wYear + 1 : m_time.wYear ) - std::floor( ( 12 - m_time.wMonth ) / 10.f );
|
||||
int mm = m_time.wMonth + 9;
|
||||
if( mm >= 12 ) { mm -= 12; }
|
||||
|
||||
int K1 = std::floor( 365.25 * ( yy + 4712 ) );
|
||||
int K2 = std::floor( 30.6 * mm + 0.5 );
|
||||
|
||||
// for dates in Julian calendar
|
||||
int JD = K1 + K2 + m_time.wDay + 59;
|
||||
// for dates in Gregorian calendar; 2299160 is October 15th, 1582
|
||||
const int gregorianswitchday = 2299160;
|
||||
if( JD > gregorianswitchday ) {
|
||||
|
||||
int K3 = std::floor( std::floor( ( yy * 0.01 ) + 49 ) * 0.75 ) - 38;
|
||||
JD -= K3;
|
||||
}
|
||||
|
||||
return JD;
|
||||
}
|
||||
|
||||
TWorld::TWorld()
|
||||
{
|
||||
// randomize();
|
||||
@@ -2503,58 +2526,6 @@ world_environment::update() {
|
||||
::glClearColor( skydomecolour.x, skydomecolour.y, skydomecolour.z, 1.0f ); // kolor nieba
|
||||
}
|
||||
|
||||
void
|
||||
world_environment::render() {
|
||||
|
||||
GfxRenderer.Bind( 0 );
|
||||
|
||||
::glDisable( GL_LIGHTING );
|
||||
::glDisable( GL_DEPTH_TEST );
|
||||
::glDepthMask( GL_FALSE );
|
||||
::glPushMatrix();
|
||||
::glTranslatef( Global::pCameraPosition.x, Global::pCameraPosition.y, Global::pCameraPosition.z );
|
||||
|
||||
// setup fog
|
||||
if( Global::fFogEnd > 0 ) {
|
||||
// fog setup
|
||||
::glFogfv( GL_FOG_COLOR, Global::FogColor );
|
||||
/*
|
||||
::glFogf( GL_FOG_START, Global::fFogStart );
|
||||
::glFogf( GL_FOG_END, Global::fFogEnd );
|
||||
*/
|
||||
::glFogf( GL_FOG_DENSITY, 1.0f / Global::fFogEnd );
|
||||
::glEnable( GL_FOG );
|
||||
}
|
||||
else { ::glDisable( GL_FOG ); }
|
||||
|
||||
m_skydome.Render();
|
||||
m_stars.render();
|
||||
float const duskfactor = 1.0f - clamp( std::abs(m_sun.getAngle()), 0.0f, 12.0f ) / 12.0f;
|
||||
float3 suncolor = interpolate(
|
||||
m_skydome.GetAverageColor(),
|
||||
float3( 235.0f / 255.0f, 140.0f / 255.0f, 36.0f / 255.0f ),
|
||||
duskfactor ) * m_skydome.GetAverageColor().z;
|
||||
|
||||
m_clouds.Render(
|
||||
interpolate( m_skydome.GetAverageColor(), suncolor, duskfactor * 0.65f )
|
||||
// m_skydome.GetAverageColor()
|
||||
* ( 1.0f - Global::Overcast * 0.5f ) // overcast darkens the clouds
|
||||
* 2.5f ); // arbitrary adjustment factor
|
||||
|
||||
if( DebugModeFlag == true ) {
|
||||
// mark sun position for easier debugging
|
||||
m_sun.render();
|
||||
m_moon.render();
|
||||
}
|
||||
Global::DayLight.apply_angle();
|
||||
Global::DayLight.apply_intensity();
|
||||
|
||||
::glPopMatrix();
|
||||
::glDepthMask( GL_TRUE );
|
||||
::glEnable( GL_DEPTH_TEST );
|
||||
::glEnable( GL_LIGHTING );
|
||||
}
|
||||
|
||||
void
|
||||
world_environment::time( int const Hour, int const Minute, int const Second ) {
|
||||
|
||||
|
||||
6
World.h
6
World.h
@@ -19,7 +19,6 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "stars.h"
|
||||
#include "skydome.h"
|
||||
#include "mczapkie/mover.h"
|
||||
#include "renderer.h"
|
||||
|
||||
// wrapper for simulation time
|
||||
class simulation_time {
|
||||
@@ -38,6 +37,8 @@ public:
|
||||
second() const { return ( m_time.wMilliseconds * 0.001 + m_time.wSecond ); }
|
||||
int
|
||||
year_day() const { return m_yearday; }
|
||||
int
|
||||
julian_day() const;
|
||||
|
||||
private:
|
||||
// calculates day of year from given date
|
||||
@@ -61,10 +62,11 @@ extern simulation_time Time;
|
||||
// wrapper for environment elements -- sky, sun, stars, clouds etc
|
||||
class world_environment {
|
||||
|
||||
friend opengl_renderer;
|
||||
|
||||
public:
|
||||
void init();
|
||||
void update();
|
||||
void render();
|
||||
void time( int const Hour = -1, int const Minute = -1, int const Second = -1 );
|
||||
|
||||
private:
|
||||
|
||||
325
moon.cpp
Normal file
325
moon.cpp
Normal file
@@ -0,0 +1,325 @@
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "moon.h"
|
||||
#include "globals.h"
|
||||
#include "mtable.h"
|
||||
#include "usefull.h"
|
||||
#include "world.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// cSun -- class responsible for dynamic calculation of position and intensity of the Sun,
|
||||
|
||||
cMoon::cMoon() {
|
||||
|
||||
setLocation( 19.00f, 52.00f ); // default location roughly in centre of Poland
|
||||
m_observer.press = 1013.0; // surface pressure, millibars
|
||||
m_observer.temp = 15.0; // ambient dry-bulb temperature, degrees C
|
||||
|
||||
TIME_ZONE_INFORMATION timezoneinfo; // TODO: timezone dependant on geographic location
|
||||
::GetTimeZoneInformation( &timezoneinfo );
|
||||
m_observer.timezone = -timezoneinfo.Bias / 60.0f;
|
||||
}
|
||||
|
||||
cMoon::~cMoon() { gluDeleteQuadric( moonsphere ); }
|
||||
|
||||
void
|
||||
cMoon::init() {
|
||||
|
||||
moonsphere = gluNewQuadric();
|
||||
gluQuadricNormals( moonsphere, GLU_SMOOTH );
|
||||
// NOTE: we're calculating phase just once, because it's unlikely simulation will last a few days,
|
||||
// plus a sudden texture change would be pretty jarring
|
||||
phase();
|
||||
}
|
||||
|
||||
void
|
||||
cMoon::update() {
|
||||
|
||||
move();
|
||||
Math3D::vector3 position( 0.0f, 0.0f, -2000.0f );
|
||||
position.RotateX( (float)( m_body.elevref * ( M_PI / 180.0 ) ) );
|
||||
position.RotateY( (float)( -m_body.hrang * ( M_PI / 180.0 ) ) );
|
||||
|
||||
m_position = position;
|
||||
}
|
||||
|
||||
void
|
||||
cMoon::render() {
|
||||
|
||||
glColor4f( 225.0f/255.0f, 225.0f/255.0f, 255.0f/255.0f, 1.f );
|
||||
// debug line to locate the sun easier
|
||||
Math3D::vector3 position = m_position;
|
||||
glBegin( GL_LINES );
|
||||
glVertex3f( position.x, position.y, position.z );
|
||||
glVertex3f( position.x, 0.0f, position.z );
|
||||
glEnd();
|
||||
glPushMatrix();
|
||||
glTranslatef( position.x, position.y, position.z );
|
||||
gluSphere( moonsphere, /* (float)( Global::ScreenHeight / Global::FieldOfView ) * 0.5 * */ ( m_body.distance / 60.2666 ) * 9.037461, 12, 12 );
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
Math3D::vector3
|
||||
cMoon::getDirection() {
|
||||
|
||||
Math3D::vector3 position( 0.f, 0.f, -1.f );
|
||||
position.RotateX( (float)( m_body.elevref * (M_PI/180.0)) );
|
||||
position.RotateY( (float)( -m_body.hrang * (M_PI/180.0)) );
|
||||
position.Normalize();
|
||||
return position;
|
||||
}
|
||||
|
||||
float
|
||||
cMoon::getAngle() const {
|
||||
|
||||
return (float)m_body.elevref;
|
||||
}
|
||||
|
||||
float cMoon::getIntensity() {
|
||||
|
||||
irradiance();
|
||||
// NOTE: we don't have irradiance model for the moon so we cheat here
|
||||
// calculating intensity of the sun instead, and returning 15% of the value,
|
||||
// which roughly matches how much sunlight is reflected by the moon
|
||||
// We alter the intensity further based on current phase of the moon
|
||||
auto const phasefactor = 1.0f - std::abs( m_phase - 29.53f * 0.5f ) / ( 29.53 * 0.5f );
|
||||
return (float)( m_body.etr/ 1399.0 ) * phasefactor * 0.15f; // arbitrary scaling factor taken from etrn value
|
||||
}
|
||||
|
||||
void cMoon::setLocation( float const Longitude, float const Latitude ) {
|
||||
|
||||
// convert fraction from geographical base of 6o minutes
|
||||
m_observer.longitude = (int)Longitude + (Longitude - (int)(Longitude)) * 100.0 / 60.0;
|
||||
m_observer.latitude = (int)Latitude + (Latitude - (int)(Latitude)) * 100.0 / 60.0 ;
|
||||
}
|
||||
|
||||
// sets current time, overriding one acquired from the system clock
|
||||
void cMoon::setTime( int const Hour, int const Minute, int const Second ) {
|
||||
|
||||
m_observer.hour = clamp( Hour, -1, 23 );
|
||||
m_observer.minute = clamp( Minute, -1, 59 );
|
||||
m_observer.second = clamp( Second, -1, 59 );
|
||||
}
|
||||
|
||||
void cMoon::setTemperature( float const Temperature ) {
|
||||
|
||||
m_observer.temp = Temperature;
|
||||
}
|
||||
|
||||
void cMoon::setPressure( float const Pressure ) {
|
||||
|
||||
m_observer.press = Pressure;
|
||||
}
|
||||
|
||||
void cMoon::move() {
|
||||
|
||||
static double radtodeg = 57.295779513; // converts from radians to degrees
|
||||
static double degtorad = 0.0174532925; // converts from degrees to radians
|
||||
|
||||
SYSTEMTIME localtime = Simulation::Time.data(); // time for the calculation
|
||||
|
||||
if( m_observer.hour >= 0 ) { localtime.wHour = m_observer.hour; }
|
||||
if( m_observer.minute >= 0 ) { localtime.wMinute = m_observer.minute; }
|
||||
if( m_observer.second >= 0 ) { localtime.wSecond = m_observer.second; }
|
||||
|
||||
double ut = localtime.wHour
|
||||
+ localtime.wMinute / 60.0 // too low resolution, noticeable skips
|
||||
+ localtime.wSecond / 3600.0; // good enough in normal circumstances
|
||||
/*
|
||||
+ localtime.wMilliseconds / 3600000.0; // for really smooth movement
|
||||
*/
|
||||
double daynumber = 367 * localtime.wYear
|
||||
- 7 * ( localtime.wYear + ( localtime.wMonth + 9 ) / 12 ) / 4
|
||||
+ 275 * localtime.wMonth / 9
|
||||
+ localtime.wDay
|
||||
- 730530
|
||||
+ ( ut / 24.0 );
|
||||
|
||||
// Universal Coordinated (Greenwich standard) time
|
||||
m_observer.utime = ut * 3600.0;
|
||||
m_observer.utime = m_observer.utime / 3600.0 - m_observer.timezone;
|
||||
|
||||
// obliquity of the ecliptic
|
||||
m_body.oblecl = clamp_circular( 23.4393 - 3.563e-7 * daynumber );
|
||||
// moon parameters
|
||||
double longascnode = clamp_circular( 125.1228 - 0.0529538083 * daynumber ); // N, degrees
|
||||
double const inclination = 5.1454; // i, degrees
|
||||
double const mndistance = 60.2666; // a, in earth radii
|
||||
// argument of perigee
|
||||
double const perigeearg = clamp_circular( 318.0634 + 0.1643573223 * daynumber ); // w, degrees
|
||||
// mean anomaly
|
||||
m_body.mnanom = clamp_circular( 115.3654 + 13.0649929509 * daynumber ); // M, degrees
|
||||
// eccentricity
|
||||
double const e = 0.054900;
|
||||
// eccentric anomaly
|
||||
double E0 = m_body.mnanom + radtodeg * e * std::sin( degtorad * m_body.mnanom ) * ( 1.0 + e * std::cos( degtorad * m_body.mnanom ) );
|
||||
double E1 = E0 - ( E0 - radtodeg * e * std::sin( degtorad * E0 ) - m_body.mnanom ) / ( 1.0 - e * std::cos( degtorad * E0 ) );
|
||||
while( std::abs( E0 - E1 ) > 0.005 ) { // arbitrary precision tolerance threshold
|
||||
E0 = E1;
|
||||
E1 = E0 - ( E0 - radtodeg * e * std::sin( degtorad * E0 ) - m_body.mnanom ) / ( 1.0 - e * std::cos( degtorad * E0 ) );
|
||||
}
|
||||
double const E = E1;
|
||||
// lunar orbit plane rectangular coordinates
|
||||
double const xv = mndistance * ( std::cos( degtorad * E ) - e );
|
||||
double const yv = mndistance * std::sin( degtorad * E ) * std::sqrt( 1.0 - e*e );
|
||||
// distance
|
||||
m_body.distance = std::sqrt( xv*xv + yv*yv ); // r
|
||||
// true anomaly
|
||||
m_body.tranom = clamp_circular( radtodeg * std::atan2( yv, xv ) ); // v
|
||||
// ecliptic rectangular coordinates
|
||||
double const vpluswinrad = degtorad * ( m_body.tranom + perigeearg );
|
||||
double const xeclip = m_body.distance * ( std::cos( degtorad * longascnode ) * std::cos( vpluswinrad ) - std::sin( degtorad * longascnode ) * std::sin( vpluswinrad ) * std::cos( degtorad * inclination ) );
|
||||
double const yeclip = m_body.distance * ( std::sin( degtorad * longascnode ) * std::cos( vpluswinrad ) + std::cos( degtorad * longascnode ) * std::sin( vpluswinrad ) * std::cos( degtorad * inclination ) );
|
||||
double const zeclip = m_body.distance * std::sin( vpluswinrad ) * std::sin( degtorad * inclination );
|
||||
// ecliptic coordinates
|
||||
double ecliplat = radtodeg * std::atan2( zeclip, std::sqrt( xeclip*xeclip + yeclip*yeclip ) );
|
||||
m_body.eclong = clamp_circular( radtodeg * std::atan2( yeclip, xeclip ) );
|
||||
// distance
|
||||
m_body.distance = std::sqrt( xeclip*xeclip + yeclip*yeclip + zeclip*zeclip );
|
||||
// perturbations
|
||||
// NOTE: perturbation calculation can be safely disabled if we don't mind error of 1-2 degrees
|
||||
// Sun's mean anomaly: Ms (already computed)
|
||||
double const sunmnanom = clamp_circular( 356.0470 + 0.9856002585 * daynumber ); // M
|
||||
// Sun's mean longitude: Ls (already computed)
|
||||
double const sunphlong = clamp_circular( 282.9404 + 4.70935e-5 * daynumber );
|
||||
double const sunmnlong = clamp_circular( sunphlong + sunmnanom ); // L = w + M
|
||||
// Moon's mean anomaly: Mm (already computed)
|
||||
// Moon's mean longitude: Lm = N + w + M (for the Moon)
|
||||
m_body.mnlong = clamp_circular( longascnode + perigeearg + m_body.mnanom );
|
||||
// Moon's mean elongation: D = Lm - Ls
|
||||
double const mnelong = clamp_circular( m_body.mnlong - sunmnlong );
|
||||
// Moon's argument of latitude: F = Lm - N
|
||||
double const arglat = clamp_circular( m_body.mnlong - longascnode );
|
||||
// longitude perturbations
|
||||
double const pertevection = -1.274 * std::sin( degtorad * ( m_body.mnanom - 2.0 * mnelong ) ); // Evection
|
||||
double const pertvariation = +0.658 * std::sin( degtorad * ( 2.0 * mnelong ) ); // Variation
|
||||
double const pertyearlyeqt = -0.186 * std::sin( degtorad * sunmnanom ); // Yearly equation
|
||||
// latitude perturbations
|
||||
double const pertlat = -0.173 * std::sin( degtorad * ( arglat - 2.0 * mnelong ) );
|
||||
|
||||
m_body.eclong += pertevection + pertvariation + pertyearlyeqt;
|
||||
ecliplat += pertlat;
|
||||
// declination
|
||||
m_body.declin = radtodeg * std::asin( std::sin (m_body.oblecl * degtorad) * std::sin(m_body.eclong * degtorad) );
|
||||
|
||||
// right ascension
|
||||
double top = std::cos( degtorad * m_body.oblecl ) * std::sin( degtorad * m_body.eclong );
|
||||
double bottom = std::cos( degtorad * m_body.eclong );
|
||||
m_body.rascen = clamp_circular( radtodeg * std::atan2( top, bottom ) );
|
||||
|
||||
// Greenwich mean sidereal time
|
||||
m_observer.gmst = 6.697375 + 0.0657098242 * daynumber + m_observer.utime;
|
||||
|
||||
m_observer.gmst -= 24.0 * (int)( m_observer.gmst / 24.0 );
|
||||
if( m_observer.gmst < 0.0 ) m_observer.gmst += 24.0;
|
||||
|
||||
// local mean sidereal time
|
||||
m_observer.lmst = m_observer.gmst * 15.0 + m_observer.longitude;
|
||||
|
||||
m_observer.lmst -= 360.0 * (int)( m_observer.lmst / 360.0 );
|
||||
if( m_observer.lmst < 0.0 ) m_observer.lmst += 360.0;
|
||||
|
||||
// hour angle
|
||||
m_body.hrang = m_observer.lmst - m_body.rascen;
|
||||
|
||||
if( m_body.hrang < -180.0 ) m_body.hrang += 360.0; // (force it between -180 and 180 degrees)
|
||||
else if( m_body.hrang > 180.0 ) m_body.hrang -= 360.0;
|
||||
|
||||
double cz; // cosine of the solar zenith angle
|
||||
|
||||
double tdatcd = std::cos( degtorad * m_body.declin );
|
||||
double tdatch = std::cos( degtorad * m_body.hrang );
|
||||
double tdatcl = std::cos( degtorad * m_observer.latitude );
|
||||
double tdatsd = std::sin( degtorad * m_body.declin );
|
||||
double tdatsl = std::sin( degtorad * m_observer.latitude );
|
||||
|
||||
cz = tdatsd * tdatsl + tdatcd * tdatcl * tdatch;
|
||||
|
||||
// (watch out for the roundoff errors)
|
||||
if( fabs (cz) > 1.0 ) { cz >= 0.0 ? cz = 1.0 : cz = -1.0; }
|
||||
|
||||
m_body.zenetr = std::acos( cz ) * radtodeg;
|
||||
m_body.elevetr = 90.0 - m_body.zenetr;
|
||||
refract();
|
||||
}
|
||||
|
||||
void cMoon::refract() {
|
||||
|
||||
static double degtorad = 0.0174532925; // converts from degrees to radians
|
||||
|
||||
double prestemp; // temporary pressure/temperature correction
|
||||
double refcor; // temporary refraction correction
|
||||
double tanelev; // tangent of the solar elevation angle
|
||||
|
||||
// if the sun is near zenith, the algorithm bombs; refraction near 0.
|
||||
if( m_body.elevetr > 85.0 )
|
||||
refcor = 0.0;
|
||||
else {
|
||||
|
||||
tanelev = tan( degtorad * m_body.elevetr );
|
||||
if( m_body.elevetr >= 5.0 )
|
||||
refcor = 58.1 / tanelev
|
||||
- 0.07 / pow( tanelev, 3 )
|
||||
+ 0.000086 / pow( tanelev, 5 );
|
||||
else if( m_body.elevetr >= -0.575 )
|
||||
refcor = 1735.0
|
||||
+ m_body.elevetr * ( -518.2 + m_body.elevetr *
|
||||
( 103.4 + m_body.elevetr * ( -12.79 + m_body.elevetr * 0.711 ) ) );
|
||||
else
|
||||
refcor = -20.774 / tanelev;
|
||||
|
||||
prestemp = ( m_observer.press * 283.0 ) / ( 1013.0 * ( 273.0 + m_observer.temp ) );
|
||||
refcor *= prestemp / 3600.0;
|
||||
}
|
||||
|
||||
// refracted solar elevation angle
|
||||
m_body.elevref = m_body.elevetr + refcor;
|
||||
|
||||
// refracted solar zenith angle
|
||||
m_body.zenref = 90.0 - m_body.elevref;
|
||||
}
|
||||
|
||||
void cMoon::irradiance() {
|
||||
|
||||
static double radtodeg = 57.295779513; // converts from radians to degrees
|
||||
static double degtorad = 0.0174532925; // converts from degrees to radians
|
||||
|
||||
m_body.dayang = ( Simulation::Time.year_day() - 1 ) * 360.0 / 365.0;
|
||||
double sd = sin( degtorad * m_body.dayang ); // sine of the day angle
|
||||
double cd = cos( degtorad * m_body.dayang ); // cosine of the day angle or delination
|
||||
m_body.erv = 1.000110 + 0.034221*cd + 0.001280*sd;
|
||||
double d2 = 2.0 * m_body.dayang;
|
||||
double c2 = cos( degtorad * d2 );
|
||||
double s2 = sin( degtorad * d2 );
|
||||
m_body.erv += 0.000719*c2 + 0.000077*s2;
|
||||
|
||||
double solcon = 1367.0; // Solar constant, 1367 W/sq m
|
||||
|
||||
m_body.coszen = cos( degtorad * m_body.zenref );
|
||||
if( m_body.coszen > 0.0 ) {
|
||||
m_body.etrn = solcon * m_body.erv;
|
||||
m_body.etr = m_body.etrn * m_body.coszen;
|
||||
}
|
||||
else {
|
||||
m_body.etrn = 0.0;
|
||||
m_body.etr = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
cMoon::phase() {
|
||||
|
||||
// calculate moon's age in days from new moon
|
||||
float ip = normalize( ( Simulation::Time.julian_day() - 2451550.1f ) / 29.530588853f );
|
||||
m_phase = ip * 29.53f;
|
||||
}
|
||||
|
||||
// normalize values to range 0...1
|
||||
float
|
||||
cMoon::normalize( const float Value ) const {
|
||||
|
||||
float value = Value - floor( Value );
|
||||
if( value < 0.f ) { ++value; }
|
||||
|
||||
return value;
|
||||
}
|
||||
106
moon.h
Normal file
106
moon.h
Normal file
@@ -0,0 +1,106 @@
|
||||
#pragma once
|
||||
|
||||
#include "windows.h"
|
||||
#include "GL/glew.h"
|
||||
#include "GL/wglew.h"
|
||||
#include "dumb3d.h"
|
||||
|
||||
|
||||
// TODO: sun and moon share code as celestial bodies, we could make a base class out of it
|
||||
|
||||
class cMoon {
|
||||
|
||||
public:
|
||||
// types:
|
||||
|
||||
// methods:
|
||||
void init();
|
||||
void update();
|
||||
void render();
|
||||
// returns location of the sun in the 3d scene
|
||||
Math3D::vector3 getPosition() { return m_position; }
|
||||
// returns vector pointing at the sun
|
||||
Math3D::vector3 getDirection();
|
||||
// returns current elevation above horizon
|
||||
float getAngle() const;
|
||||
// returns current intensity of the sun
|
||||
float getIntensity();
|
||||
// returns current phase of the moon
|
||||
float getPhase() const { return m_phase; }
|
||||
// sets current time, overriding one acquired from the system clock
|
||||
void setTime( int const Hour, int const Minute, int const Second );
|
||||
// sets current geographic location
|
||||
void setLocation( float const Longitude, float const Latitude );
|
||||
// sets ambient temperature in degrees C.
|
||||
void setTemperature( float const Temperature );
|
||||
// sets surface pressure in milibars
|
||||
void setPressure( float const Pressure );
|
||||
|
||||
// constructors:
|
||||
cMoon();
|
||||
|
||||
// deconstructor:
|
||||
~cMoon();
|
||||
|
||||
// members:
|
||||
|
||||
protected:
|
||||
// types:
|
||||
|
||||
// methods:
|
||||
// calculates sun position on the sky given specified time and location
|
||||
void move();
|
||||
// calculates position adjustment due to refraction
|
||||
void refract();
|
||||
// calculates light intensity at current moment
|
||||
void irradiance();
|
||||
void phase();
|
||||
// helper, normalize values to range 0...1
|
||||
float normalize( const float Value ) const;
|
||||
|
||||
// members:
|
||||
GLUquadricObj *moonsphere; // temporary handler for moon positioning test
|
||||
|
||||
struct celestialbody { // main planet parameters
|
||||
|
||||
double dayang; // day angle (daynum*360/year-length) degrees
|
||||
double phlong; // longitude of perihelion
|
||||
double mnlong; // mean longitude, degrees
|
||||
double mnanom; // mean anomaly, degrees
|
||||
double tranom; // true anomaly, degrees
|
||||
double eclong; // ecliptic longitude, degrees.
|
||||
double oblecl; // obliquity of ecliptic.
|
||||
double declin; // declination--zenith angle of solar noon at equator, degrees NORTH.
|
||||
double rascen; // right ascension, degrees
|
||||
double hrang; // hour angle--hour of sun from solar noon, degrees WEST
|
||||
double zenetr; // solar zenith angle, no atmospheric correction (= ETR)
|
||||
double zenref; // solar zenith angle, deg. from zenith, refracted
|
||||
double coszen; // cosine of refraction corrected solar zenith angle
|
||||
double elevetr; // solar elevation, no atmospheric correction (= ETR)
|
||||
double elevref; // solar elevation angle, deg. from horizon, refracted.
|
||||
double distance; // distance from earth in AUs
|
||||
double erv; // earth radius vector (multiplied to solar constant)
|
||||
double etr; // extraterrestrial (top-of-atmosphere) W/sq m global horizontal solar irradiance
|
||||
double etrn; // extraterrestrial (top-of-atmosphere) W/sq m direct normal solar irradiance
|
||||
};
|
||||
|
||||
struct observer { // weather, time and position data in observer's location
|
||||
|
||||
double latitude; // latitude, degrees north (south negative)
|
||||
double longitude; // longitude, degrees east (west negative)
|
||||
int hour{ -1 }; // current time, used for calculation of utime. if set to -1, time for
|
||||
int minute{ -1 };// calculation will be obtained from the local clock
|
||||
int second{ -1 };
|
||||
double utime; // universal (Greenwich) standard time
|
||||
double timezone; // time zone, east (west negative). USA: Mountain = -7, Central = -6, etc.
|
||||
double gmst; // Greenwich mean sidereal time, hours
|
||||
double lmst; // local mean sidereal time, degrees
|
||||
double temp; // ambient dry-bulb temperature, degrees C, used for refraction correction
|
||||
double press; // surface pressure, millibars, used for refraction correction and ampress
|
||||
};
|
||||
|
||||
celestialbody m_body;
|
||||
observer m_observer;
|
||||
Math3D::vector3 m_position;
|
||||
float m_phase;
|
||||
};
|
||||
156
renderer.cpp
156
renderer.cpp
@@ -75,11 +75,6 @@ opengl_renderer::Init( GLFWwindow *Window ) {
|
||||
glEnable( GL_COLOR_MATERIAL );
|
||||
glColorMaterial( GL_FRONT, GL_AMBIENT_AND_DIFFUSE );
|
||||
|
||||
|
||||
// ::glFogi( GL_FOG_COORD_SRC, GL_FOG_COORD );
|
||||
// ::glFogi( GL_FOG_COORD_SRC, GL_FRAGMENT_DEPTH );
|
||||
// ::glFogi( GL_FOG_MODE, GL_LINEAR );
|
||||
|
||||
// setup lighting
|
||||
GLfloat ambient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
::glLightModelfv( GL_LIGHT_MODEL_AMBIENT, ambient );
|
||||
@@ -113,6 +108,8 @@ opengl_renderer::Init( GLFWwindow *Window ) {
|
||||
// preload some common textures
|
||||
WriteLog( "Loading common gfx data..." );
|
||||
m_glaretextureid = GetTextureId( "fx\\lightglare", szTexturePath );
|
||||
m_suntextureid = GetTextureId( "fx\\sun", szTexturePath );
|
||||
m_moontextureid = GetTextureId( "fx\\moon", szTexturePath );
|
||||
WriteLog( "...gfx data pre-loading done" );
|
||||
|
||||
return true;
|
||||
@@ -132,32 +129,16 @@ opengl_renderer::Render() {
|
||||
std::max( 1.0f, (float)Global::ScreenWidth ) / std::max( 1.0f, (float)Global::ScreenHeight ),
|
||||
0.1f * Global::ZoomFactor,
|
||||
m_drawrange * Global::fDistanceFactor );
|
||||
/*
|
||||
glm::mat4 projection = glm::perspective(
|
||||
Global::FieldOfView / Global::ZoomFactor * 0.0174532925f,
|
||||
std::max( 1.0f, (float)Global::ScreenWidth ) / std::max( 1.0f, (float)Global::ScreenHeight ),
|
||||
0.1f * Global::ZoomFactor,
|
||||
m_drawrange * Global::fDistanceFactor );
|
||||
::glLoadMatrixf( &projection[0][0] );
|
||||
*/
|
||||
|
||||
::glMatrixMode( GL_MODELVIEW ); // Select The Modelview Matrix
|
||||
::glLoadIdentity();
|
||||
|
||||
if( World.InitPerformed() ) {
|
||||
/*
|
||||
glm::mat4 modelview( 1.0f );
|
||||
World.Camera.SetMatrix( modelview );
|
||||
::glLoadMatrixf( &modelview[ 0 ][ 0 ] );
|
||||
m_camera.update_frustum( projection, modelview );
|
||||
*/
|
||||
|
||||
World.Camera.SetMatrix();
|
||||
m_camera.update_frustum();
|
||||
|
||||
if( !Global::bWireFrame ) {
|
||||
// bez nieba w trybie rysowania linii
|
||||
World.Environment.render();
|
||||
}
|
||||
|
||||
Render( &World.Environment );
|
||||
World.Ground.Render( World.Camera.Pos );
|
||||
|
||||
World.Render_Cab();
|
||||
@@ -172,7 +153,131 @@ opengl_renderer::Render() {
|
||||
return true; // for now always succeed
|
||||
}
|
||||
|
||||
#ifndef EU07_USE_OLD_RENDERCODE
|
||||
bool
|
||||
opengl_renderer::Render( world_environment *Environment ) {
|
||||
|
||||
if( Global::bWireFrame ) {
|
||||
// bez nieba w trybie rysowania linii
|
||||
return false;
|
||||
}
|
||||
|
||||
Bind( 0 );
|
||||
|
||||
::glDisable( GL_LIGHTING );
|
||||
::glDisable( GL_DEPTH_TEST );
|
||||
::glDepthMask( GL_FALSE );
|
||||
::glPushMatrix();
|
||||
::glTranslatef( Global::pCameraPosition.x, Global::pCameraPosition.y, Global::pCameraPosition.z );
|
||||
|
||||
// setup fog
|
||||
if( Global::fFogEnd > 0 ) {
|
||||
// fog setup
|
||||
::glFogfv( GL_FOG_COLOR, Global::FogColor );
|
||||
::glFogf( GL_FOG_DENSITY, 1.0f / Global::fFogEnd );
|
||||
::glEnable( GL_FOG );
|
||||
}
|
||||
else { ::glDisable( GL_FOG ); }
|
||||
|
||||
Environment->m_skydome.Render();
|
||||
Environment->m_stars.render();
|
||||
|
||||
float const duskfactor = 1.0f - clamp( std::abs( Environment->m_sun.getAngle() ), 0.0f, 12.0f ) / 12.0f;
|
||||
float3 suncolor = interpolate(
|
||||
float3( 255.0f / 255.0f, 242.0f / 255.0f, 231.0f / 255.0f ),
|
||||
float3( 235.0f / 255.0f, 140.0f / 255.0f, 36.0f / 255.0f ),
|
||||
duskfactor );
|
||||
|
||||
if( DebugModeFlag == true ) {
|
||||
// mark sun position for easier debugging
|
||||
Environment->m_sun.render();
|
||||
Environment->m_moon.render();
|
||||
}
|
||||
// render actual sun and moon
|
||||
::glPushAttrib( GL_ENABLE_BIT | GL_CURRENT_BIT | GL_COLOR_BUFFER_BIT );
|
||||
|
||||
::glDisable( GL_LIGHTING );
|
||||
::glDisable( GL_ALPHA_TEST );
|
||||
::glEnable( GL_BLEND );
|
||||
::glBlendFunc( GL_SRC_ALPHA, GL_ONE );
|
||||
|
||||
auto const &modelview = OpenGLMatrices.data( GL_MODELVIEW );
|
||||
// sun
|
||||
{
|
||||
Bind( m_suntextureid );
|
||||
::glColor4f( suncolor.x, suncolor.y, suncolor.z, 1.0f );
|
||||
auto const sunvector = Environment->m_sun.getDirection();
|
||||
auto const sunposition = modelview * glm::vec4( sunvector.x, sunvector.y, sunvector.z, 1.0f );
|
||||
|
||||
::glPushMatrix();
|
||||
::glLoadIdentity(); // macierz jedynkowa
|
||||
::glTranslatef( sunposition.x, sunposition.y, sunposition.z ); // początek układu zostaje bez zmian
|
||||
|
||||
float const size = 0.045f;
|
||||
::glBegin( GL_TRIANGLE_STRIP );
|
||||
::glTexCoord2f( 1.0f, 1.0f ); ::glVertex3f( -size, size, 0.0f );
|
||||
::glTexCoord2f( 1.0f, 0.0f ); ::glVertex3f( -size, -size, 0.0f );
|
||||
::glTexCoord2f( 0.0f, 1.0f ); ::glVertex3f( size, size, 0.0f );
|
||||
::glTexCoord2f( 0.0f, 0.0f ); ::glVertex3f( size, -size, 0.0f );
|
||||
::glEnd();
|
||||
|
||||
::glPopMatrix();
|
||||
}
|
||||
// moon
|
||||
{
|
||||
Bind( m_moontextureid );
|
||||
float3 mooncolor( 255.0f / 255.0f, 242.0f / 255.0f, 231.0f / 255.0f );
|
||||
::glColor4f( mooncolor.x, mooncolor.y, mooncolor.z, 1.0f - Global::fLuminance * 0.5f );
|
||||
|
||||
auto const moonvector = Environment->m_moon.getDirection();
|
||||
auto const moonposition = modelview * glm::vec4( moonvector.x, moonvector.y, moonvector.z, 1.0f );
|
||||
::glPushMatrix();
|
||||
::glLoadIdentity(); // macierz jedynkowa
|
||||
::glTranslatef( moonposition.x, moonposition.y, moonposition.z );
|
||||
|
||||
float const size = 0.025f; // TODO: expose distance/scale factor from the moon object
|
||||
// choose the moon appearance variant, based on current moon phase
|
||||
// NOTE: implementation specific, 8 variants are laid out in 3x3 arrangement
|
||||
// from new moon onwards, top left to right bottom (last spot is left for future use, if any)
|
||||
auto const moonphase = Environment->m_moon.getPhase();
|
||||
float moonu, moonv;
|
||||
if( moonphase < 1.84566f ) { moonv = 1.0f - 0.0f; moonu = 0.0f; }
|
||||
else if( moonphase < 5.53699f ) { moonv = 1.0f - 0.0f; moonu = 0.333f; }
|
||||
else if( moonphase < 9.22831f ) { moonv = 1.0f - 0.0f; moonu = 0.667f; }
|
||||
else if( moonphase < 12.91963f ) { moonv = 1.0f - 0.333f; moonu = 0.0f; }
|
||||
else if( moonphase < 16.61096f ) { moonv = 1.0f - 0.333f; moonu = 0.333f; }
|
||||
else if( moonphase < 20.30228f ) { moonv = 1.0f - 0.333f; moonu = 0.667f; }
|
||||
else if( moonphase < 23.99361f ) { moonv = 1.0f - 0.667f; moonu = 0.0f; }
|
||||
else if( moonphase < 27.68493f ) { moonv = 1.0f - 0.667f; moonu = 0.333f; }
|
||||
else { moonv = 1.0f - 0.0f; moonu = 0.0f; }
|
||||
|
||||
::glBegin( GL_TRIANGLE_STRIP );
|
||||
::glTexCoord2f( moonu, moonv ); ::glVertex3f( -size, size, 0.0f );
|
||||
::glTexCoord2f( moonu, moonv - 0.333f ); ::glVertex3f( -size, -size, 0.0f );
|
||||
::glTexCoord2f( moonu + 0.333f, moonv ); ::glVertex3f( size, size, 0.0f );
|
||||
::glTexCoord2f( moonu + 0.333f, moonv - 0.333f ); ::glVertex3f( size, -size, 0.0f );
|
||||
::glEnd();
|
||||
|
||||
::glPopMatrix();
|
||||
}
|
||||
::glPopAttrib();
|
||||
|
||||
// clouds
|
||||
Environment->m_clouds.Render(
|
||||
interpolate( Environment->m_skydome.GetAverageColor(), suncolor, duskfactor * 0.25f )
|
||||
* ( 1.0f - Global::Overcast * 0.5f ) // overcast darkens the clouds
|
||||
* 2.5f ); // arbitrary adjustment factor
|
||||
|
||||
Global::DayLight.apply_angle();
|
||||
Global::DayLight.apply_intensity();
|
||||
|
||||
::glPopMatrix();
|
||||
::glDepthMask( GL_TRUE );
|
||||
::glEnable( GL_DEPTH_TEST );
|
||||
::glEnable( GL_LIGHTING );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
opengl_renderer::Render( TGround *Ground ) {
|
||||
|
||||
@@ -745,7 +850,6 @@ opengl_renderer::Render_Alpha( TSubModel *Submodel ) {
|
||||
if( Submodel->iAlpha & Submodel->iFlags & 0x2F000000 )
|
||||
Render_Alpha( Submodel->Next );
|
||||
};
|
||||
#endif
|
||||
|
||||
void
|
||||
opengl_renderer::Update ( double const Deltatime ) {
|
||||
|
||||
@@ -14,7 +14,7 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "lightarray.h"
|
||||
#include "dumb3d.h"
|
||||
#include "frustum.h"
|
||||
#include "ground.h"
|
||||
#include "world.h"
|
||||
|
||||
struct opengl_light {
|
||||
|
||||
@@ -116,7 +116,8 @@ public:
|
||||
// main draw call. returns false on error
|
||||
bool
|
||||
Render();
|
||||
#ifndef EU07_USE_OLD_RENDERCODE
|
||||
bool
|
||||
Render( world_environment *Environment );
|
||||
bool
|
||||
Render( TGround *Ground );
|
||||
bool
|
||||
@@ -135,7 +136,6 @@ public:
|
||||
Render_Alpha( TModel3d *Model, material_data const *Material, Math3D::vector3 const &Position, Math3D::vector3 const &Angle );
|
||||
void
|
||||
Render_Alpha( TSubModel *Submodel );
|
||||
#endif
|
||||
// maintenance jobs
|
||||
void
|
||||
Update( double const Deltatime);
|
||||
@@ -194,6 +194,8 @@ private:
|
||||
std::string m_debuginfo;
|
||||
GLFWwindow *m_window{ nullptr };
|
||||
texture_manager::size_type m_glaretextureid{ -1 };
|
||||
texture_manager::size_type m_suntextureid{ -1 };
|
||||
texture_manager::size_type m_moontextureid{ -1 };
|
||||
};
|
||||
|
||||
extern opengl_renderer GfxRenderer;
|
||||
|
||||
Reference in New Issue
Block a user