Skip to content

Commit

Permalink
[AmbientLight] light direction based on long and lat and time
Browse files Browse the repository at this point in the history
  • Loading branch information
sarthou committed Aug 23, 2024
1 parent 560598d commit 525b199
Show file tree
Hide file tree
Showing 6 changed files with 213 additions and 3 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ owds_add_ros_library(overworld_utility_lib
src/Utils/YamlReader.cpp
src/Utils/Ontology.cpp
src/Utils/XmlTokenize.cpp
src/Utils/SolarAzEl.cpp

# src/Utils/RosFiles.cpp
src/Utils/Wavefront.cpp)
Expand Down
55 changes: 55 additions & 0 deletions include/overworld/Engine/Common/Lights/AmbientLight.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
#ifndef OWDS_COMMON_AMBIENT_LIGHT_H
#define OWDS_COMMON_AMBIENT_LIGHT_H

#include <array>
#include <cmath>
#include <ctime>
#include <glm/gtc/type_ptr.hpp>
#include <glm/vec3.hpp>
#include <glm/vec4.hpp>
#include <iostream>
#include <time.h>

#include "overworld/Utils/SolarAzEl.h"

namespace owds {

Expand All @@ -24,11 +32,54 @@ namespace owds {
computeSpecular();
}

AmbientLight(const std::array<float, 3>& lat_long_alt,
const glm::vec3& color = glm::vec3(1.0),
float ambient_strength = 1.0f,
float diffuse_strength = 1.0f,
float specular_strength = 1.0f) : color_(glm::vec4(color, 1.0f)),
ambient_strength_(ambient_strength),
diffuse_strength_(diffuse_strength),
specular_strength_(specular_strength),
latitude_(lat_long_alt[0]),
longitude_(lat_long_alt[1]),
altitude_(lat_long_alt[2])

{
double el = 0., az = 0.;
solarAzEl(time(0), latitude_, longitude_, altitude_, &az, &el);
setElevationAndAzimuth(glm::radians(el), glm::radians(az));
computeAmbient();
computeDiffuse();
computeSpecular();
}

void setDirection(const glm::vec3& direction)
{
direction_ = glm::vec4(direction, 1.0f);
}

void setElevationAndAzimuth(float elevation, float azimuth)
{
float x = std::cos(elevation) * std::sin(azimuth);
float y = std::cos(elevation) * std::cos(azimuth);
float z = std::sin(elevation);
setDirection(glm::vec3(y, -x, -z));

if(z < 0)
{
diffuse_strength_ = 0.;
specular_strength_ = 0.;
color_ = glm::vec4(0.31, 0.435f, 0.78f, 1.f);
}
else if(z < 1.)
{
auto night_color = glm::vec4(0.31, 0.435f, 0.78f, 1.f);
color_ = z * color_ + night_color * (1.f - z);
diffuse_strength_ = z;
specular_strength_ = z;
}
}

void setColor(const glm::vec3& color)
{
color_ = glm::vec4(color, 1.0f);
Expand Down Expand Up @@ -68,6 +119,10 @@ namespace owds {
float diffuse_strength_;
float specular_strength_;

float latitude_;
float longitude_;
float altitude_;

glm::vec4 ambient_;
glm::vec4 diffuse_;
glm::vec4 specular_;
Expand Down
8 changes: 8 additions & 0 deletions include/overworld/Utils/SolarAzEl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef OWDS_SOLARAZEL_H
#define OWDS_SOLARAZEL_H

#include <ctime>

void solarAzEl(time_t utc_time_point, double Lat, double Lon, double Alt, double* Az, double* El);

#endif // OWDS_SOLARAZEL_H
2 changes: 1 addition & 1 deletion src/Engine/Common/World.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ namespace owds {
float diffuse_strength,
float specular_strength)
{
ambient_light_ = AmbientLight(glm::vec3(direction[0], direction[1], direction[2]),
ambient_light_ = AmbientLight(direction,
glm::vec3(color[0], color[1], color[2]),
ambient_strength, diffuse_strength, specular_strength);
}
Expand Down
4 changes: 2 additions & 2 deletions src/Nodes/TestOpengl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ void worldThread(const std::string& world_name, owds::Window* window)
{
std::cout << world_name << std::endl;
auto& cam = window->getCamera();
cam.setFieldOfView(80.f);
cam.setFieldOfView(60.f);
cam.setOutputAA(owds::ViewAntiAliasing_e::msaa_x4);
cam.setOutputResolution({640, 480});
cam.setPositionAndLookAt({6, 6, 1.7}, {0, 0, 0});
Expand All @@ -74,7 +74,7 @@ void worldThread(const std::string& world_name, owds::Window* window)

std::cout << "================== WORLD " << world_name << " CREATED ! ================" << std::endl;

world.setAmbientLight({0.5f, 0.2f, -0.3f},
world.setAmbientLight({48.f, -2.f, 0.f},
{1.0f, 0.976f, 0.898f},
0.25, 0.4, 0.8);

Expand Down
146 changes: 146 additions & 0 deletions src/Utils/SolarAzEl.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/*
Copyright(c) 2010, Darin Koblick
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met :
*Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "overworld/Utils/SolarAzEl.h"

#include <math.h>
#include <stdio.h>
#include <time.h>

#ifndef M_PI
#define M_PI (3.14159265358979323846264338327950288)
#endif /* M_PI */

double julian_day(time_t utc_time_point);

void solarAzEl(time_t utc_time_point, double Lat, double Lon, double Alt, double* Az, double* El)
{
double jd = julian_day(utc_time_point);

double d = jd - 2451543.5;

// Keplerian Elements for the Sun(geocentric)
double w = 282.9404 + 4.70935e-5 * d; // (longitude of perihelion degrees)
// a = 1.000000; % (mean distance, a.u.)
double e = 0.016709 - 1.151e-9 * d; // (eccentricity)
double M = fmod(356.0470 + 0.9856002585 * d, 360.0); // (mean anomaly degrees)

double L = w + M; // (Sun's mean longitude degrees)

double oblecl = 23.4393 - 3.563e-7 * d; // (Sun's obliquity of the ecliptic)

// auxiliary angle
double E = M + (180 / M_PI) * e * sin(M * (M_PI / 180)) * (1 + e * cos(M * (M_PI / 180)));

// rectangular coordinates in the plane of the ecliptic(x axis toward perhilion)
double x = cos(E * (M_PI / 180)) - e;
double y = sin(E * (M_PI / 180)) * sqrt(1 - pow(e, 2));

// find the distance and true anomaly
double r = sqrt(pow(x, 2) + pow(y, 2));
double v = atan2(y, x) * (180 / M_PI);

// find the longitude of the sun
double lon = v + w;

// compute the ecliptic rectangular coordinates
double xeclip = r * cos(lon * (M_PI / 180));
double yeclip = r * sin(lon * (M_PI / 180));
double zeclip = 0.0;
// rotate these coordinates to equitorial rectangular coordinates
double xequat = xeclip;

double yequat = yeclip * cos(oblecl * (M_PI / 180)) + zeclip * sin(oblecl * (M_PI / 180));

double zequat = yeclip * sin(23.4406 * (M_PI / 180)) + zeclip * cos(oblecl * (M_PI / 180));
// convert equatorial rectangular coordinates to RA and Decl:
r = sqrt(pow(xequat, 2) + pow(yequat, 2) + pow(zequat, 2)) - (Alt / 149598000); // roll up the altitude correction
double RA = atan2(yequat, xequat) * (180 / M_PI);

double delta = asin(zequat / r) * (180 / M_PI);

// Following the RA DEC to Az Alt conversion sequence explained here :
// http ://www.stargazing.net/kepler/altaz.html
// Find the J2000 value
// J2000 = jd - 2451545.0;
// hourvec = datevec(UTC);
// UTH = hourvec(:, 4) + hourvec(:, 5) / 60 + hourvec(:, 6) / 3600;

// Get UTC representation of time / C++ Specific
tm* ptm;
ptm = gmtime(&utc_time_point);
double UTH = (double)ptm->tm_hour + (double)ptm->tm_min / 60 + (double)ptm->tm_sec / 3600;

// Calculate local siderial time
double GMST0 = fmod(L + 180, 360.0) / 15;

double SIDTIME = GMST0 + UTH + Lon / 15;

// Replace RA with hour angle HA
double HA = (SIDTIME * 15 - RA);

// convert to rectangular coordinate system
x = cos(HA * (M_PI / 180)) * cos(delta * (M_PI / 180));

y = sin(HA * (M_PI / 180)) * cos(delta * (M_PI / 180));
double z = sin(delta * (M_PI / 180));

// rotate this along an axis going east - west.
double xhor = x * cos((90 - Lat) * (M_PI / 180)) - z * sin((90 - Lat) * (M_PI / 180));

double yhor = y;
double zhor = x * sin((90 - Lat) * (M_PI / 180)) + z * cos((90 - Lat) * (M_PI / 180));

// Find the h and AZ
*Az = atan2(yhor, xhor) * (180 / M_PI) + 180;
*El = asin(zhor) * (180 / M_PI);
}

double julian_day(time_t utc_time_point)
{
// Extract UTC Time
struct tm* tm = gmtime(&utc_time_point);

double year = tm->tm_year + 1900;
double month = tm->tm_mon + 1;
double day = tm->tm_mday;
double hour = tm->tm_hour;
double min = tm->tm_min;
double sec = tm->tm_sec;

if(month <= 2)
{
year -= 1;
month += 12;
}

double jd = floor(365.25 * (year + 4716.0)) + floor(30.6001 * (month + 1.0)) + 2.0 -
floor(year / 100.0) + floor(floor(year / 100.0) / 4.0) + day - 1524.5 +
(hour + min / 60 + sec / 3600) / 24;

return jd;
}

0 comments on commit 525b199

Please sign in to comment.