content/hifi-content/alan/dev/Scripts/DayNightReal/DayNightZoneReal.js
2022-02-13 20:41:08 +01:00

284 lines
13 KiB
JavaScript

// JavaScript source code
// Template by Antony Evans
// sunset API used with attribution to https://sunrise-sunset.org/api
(function () {
var sun;
var sunlight;
var latitude = 0; // will move to userdata
var longitude = 0;
var dayLength; // in seconds will move to userdata
var time = 0.9; // 0-1 for how far through day we are
var sunDistance = 2500; // radius for distance of sun
var updateFreq = 100; // how often we refresh sun position
var starMap = "";
const RADPERDEGREE = 0.0174533;
var useRealTime = true;
var nightLight;
var timer1;
var timer2;
var sunrise = 0.2484837962962963;
var sunset = 0.7506828703703704;
var sunData = {};
var civil_twilight_begin = 0.22568287037037038; // these defaults are based on London on spring equinox
var civil_twilight_end = 0.7790393518518518;
var nautical_twilight_begin = 0.19864583333333333;
var nautical_twilight_end = 0.8060763888888889;
var astronomical_twilight_begin = 0.1705324074074074;
var astronomical_twilight_end = 0.8341898148148148;
var startSunset = 0.4; //need to adjust for 0 being sunrise to 0 being midnight
var startTwilight = 0.12; //need to adjust
function MyObject() {
// Can be used a constructor
}
MyObject.prototype = {
preload: function (entityID) {
// When an entity instance has been loaded into the world, this is triggered.
Script.setTimeout(function () {
// this timeout is to ensure the sun and light loads before the script starts
var properties = Entities.getEntityProperties(entityID);
timer1 = Script.setInterval(function () {
// regularly check for updates to USerData
var tempLongitude = longitude;
var tempLatitude = latitude;
properties = Entities.getEntityProperties(entityID);
var userData = JSON.parse(properties.userData);
dayLength = userData.dayLength;
latitude = RADPERDEGREE * userData.latitude;
longitude = RADPERDEGREE * userData.longitude;
nightLight = userData.nightLight;
starMap = userData.nightSkyURL;
useRealTime = userData.useRealTime;
if ((longitude !== tempLongitude) || (latitude !== tempLatitude)) {
// update sunset/sunrise times because we changed userdata location
print("updating sunrise");
var request = new XMLHttpRequest();
var lat = latitude / RADPERDEGREE + 0.0001; //small addition fixes bug when supply integers not floats
var lng = longitude / RADPERDEGREE + 0.0001;
request.open('GET', 'https://api.sunrise-sunset.org/json?lat=' + lat.toString() + '&lng=' + lng.toString() + '&date=today', false);
request.onreadystatechange = function () {
var status = request.status;
if ((status >= 200) && (status < 400)) {
if (request.responseText) {
var sunData = JSON.parse(request.responseText);
print(JSON.stringify(request.responseText));
sunrise = convertDateToDayFraction(sunData.results.sunrise);
sunset = convertDateToDayFraction(sunData.results.sunset);
civil_twilight_begin = convertDateToDayFraction(sunData.results.civil_twilight_begin);
civil_twilight_end = convertDateToDayFraction(sunData.results.civil_twilight_end);
nautical_twilight_begin = convertDateToDayFraction(sunData.results.nautical_twilight_begin);
nautical_twilight_end = convertDateToDayFraction(sunData.results.nautical_twilight_end);
astronomical_twilight_begin = convertDateToDayFraction(sunData.results.astronomical_twilight_begin);
astronomical_twilight_end = convertDateToDayFraction(sunData.results.astronomical_twilight_end);
//print("sunrise: " + sunrise.toString());
//print("sunset: " + sunset.toString());
//print("nautical_twilight_end: " + nautical_twilight_begin.toString());
//print("time: " + time.toString());
startSunset = - Math.sin(calcAngleFromTime(nautical_twilight_begin)) * Math.cos(latitude);
//print("startSunset: " + startSunset.toString());
startTwilight = - Math.sin(calcAngleFromTime(civil_twilight_begin)) * Math.cos(latitude);
//print("startTwilight: " + startTwilight.toString());
}
}
};
// Send request
request.send();
}
}, 1000);
timer2 = Script.setInterval(function () {
// this is our main script loop that moves the sun etc
// time is a fraction between 0 and 1 for how far through the day we are
if (useRealTime) {
var d = new Date();
var n = d.getTimezoneOffset();
var h = d.getHours();
var m = d.getMinutes();
var s = d.getSeconds();
var ms = d.getMilliseconds();
time = (h*60 + m + n + (s / 60) + (ms / 60000)) / (24*60) // note this time is UTC fraction of day to match sunset/sunrise times which return in UTC
time = ((time < 0) ? 1 + time : time) ;
time = ((time >= 1) ? time - 1 : time) ;
//print("time: " + h.toString() + ":" + m.toString());
} else {
time += updateFreq/(1000 * dayLength);
time = ((time < 1) ? time : 0) ;
}
// print("time is: " + time.toString());
setSun(entityID, time, properties.position);
// print("Time: " + time);
}, updateFreq);
}, 1500);
},
unload: function (entityID) {
Script.clearInterval(timer1);
Script.clearInterval(timer2);
}
}
function convertDateToDayFraction(timeString) {
var seconds = 0;
var time = timeString.split(" ");
if (time[1] == "PM") {seconds += 12*60*60} ;
time = time[0].split(":");
seconds += ((time[0] > 11.5) ? 0 : parseInt(time[0])*60*60); //this catches 12 not being 0
seconds += parseInt(time[1])*60;
seconds += parseInt(time[2]);
var output = seconds / (24*60*60) ;
return output;
}
function calcAngleFromTime(timeInput) {
var angle = 0;
if (sunset > sunrise) {
if (timeInput < sunrise) {
// nighttime
angle = Math.PI * (timeInput - sunrise) / (1 - sunset + sunrise);
} else if (timeInput < sunset) {
// day time
angle = Math.PI * (timeInput - sunrise) / (sunset - sunrise);
} else {
// night time
angle = Math.PI * (1+((timeInput - sunset) / (1 - sunset + sunrise))); // at sunset angle is pi then increases from there, creating negative sin angle
}
} else {
// this is when longitude is high and we are on opposite side of world so sunrise is PM UTC
if (timeInput < sunset) {
// day time
angle = Math.PI * (1-((sunset - timeInput) / (1 - sunrise + sunset)));
} else if (timeInput < sunrise) {
// night time
angle = Math.PI * (1+((timeInput - sunset) / (sunrise - sunset))); // goes between pi and 2pi
} else {
// day time
angle = Math.PI * (timeInput - sunrise) / (1 - sunrise + sunset);
}
}
return angle;
}
function setSun(entityID, time, position) {
var angle = calcAngleFromTime(time);
var x = sunDistance * Math.sin(latitude);
var y = sunDistance * Math.sin(angle) * Math.cos(latitude);
var z = sunDistance * Math.cos(angle) * Math.cos(latitude);
var altitude = y / sunDistance;
var sunsetPercent;
var nightPercent;
var showdows;
var skyColor;
var sunColor;
var hazeColor;
var nightSky;
var lightDirection;
var normalize = Math.sqrt( Math.pow(x,2) + Math.pow(y,2) + Math.pow(z,2)); // this is wrong but is working anyway
if (altitude > startSunset) {
// midday sun
sunsetPercent = 0;
nightPercent = 0;
sunColor = { "r": 230, "g": 210, "b": 161 };
skyColor = { "r": 0, "g": 100, "b": 255};
hazeColor = { "r": 255, "g": 255, "b": 255};
nightSky = "";
shadows = true;
lightDirection = { "x": - x / normalize, "y": - y / normalize, "z": - z / normalize };
} else if (altitude > 0) {
//sunrise
sunsetPercent = Math.pow(1 - (altitude/startSunset),2);
nightPercent = 0;
sunColor = { "r": 255 - sunsetPercent*2, "g": 255 - sunsetPercent*183, "b": 255 - sunsetPercent*172};
skyColor = { "r": 0, "g": 100 - sunsetPercent*100, "b": 255 - sunsetPercent*255};
hazeColor = { "r": 255 - sunsetPercent*2, "g": 255 - sunsetPercent*183, "b": 255 - sunsetPercent*172};
nightSky = "";
shadows = true;
lightDirection = { "x": - x / normalize, "y": - y / normalize, "z": - z / normalize };
} else if (altitude > - startTwilight) {
// twilight
sunsetPercent = 1;
nightPercent = 1-Math.pow((((startTwilight)+altitude)/startTwilight),2);
sunColor = { "r": 255, "g": 255-(183*(1-nightPercent)), "b": 255 -(172*(1-nightPercent))};
skyColor = { "r": 0, "g": 0, "b": 0};
hazeColor = { "r": (255 - 2)*(1-nightPercent), "g": (255 - 183)*(1-nightPercent), "b": (255 - 172)*(1-nightPercent)};
nightSky = starMap;
shadows = false;
lightDirection = { "x": - x / normalize, "y": - y / normalize, "z": - z / normalize };
} else {
// night
sunsetPercent = 1;
nightPercent = 1;
sunColor = { "r": 255, "g": 255, "b": 255};
skyColor = { "r": 0, "g": 0, "b": 0};
nightSky = starMap;
shadows = false;
lightDirection = { "x": - x / normalize, "y": - y / normalize, "z": - z / normalize };
}
var sunID = Entities.findEntitiesByName("Sun", position, 1000, false)[0];
var sunlightID = Entities.findEntitiesByName("Sunlight", position, 1000, false)[0];
// print("sun: " + sunlight);
// print("sun: " + JSON.stringify(sunID));
//print("EntityID: " + entityID);
//print (JSON.stringify(Entities.getEntityProperties(sunID)));
var sunSize = 15 + (15 * Math.pow(sunsetPercent,3));
var result = Entities.editEntity(sunID, {
"localPosition": { "x": x, "y": y, "z": z },
"dimensions": {"x": sunSize, "y": sunSize, "z": sunSize},
"color": sunColor
});
Entities.editEntity(entityID, {
"skybox": {
"color": skyColor,
"url": nightSky
},
"keyLight": {
"color": sunColor,
"intensity": 1 - ((1-nightLight) * nightPercent),
"direction": lightDirection,
"castShadows": shadows
},
"haze": {
"hazeRange": 500,
"hazeColor": hazeColor,
"hazeEnableGlare": false,
"hazeGlareColor": "#ffffff",
"hazeGlareAngle": 20,
"hazeAltitudeEffect": true,
"hazeBaseRef": -100,
"hazeCeiling": (100+200*(sunsetPercent)+((sunsetPercent < 0.9) ? 0 : 300 * Math.pow((sunsetPercent - 0.9)/0.9,2)))*(1-nightPercent),
"hazeBackgroundBlend": 0.6 - (0.6 * sunsetPercent),
},
"bloom" : {
"bloomIntensity": 0.1 + (0.9 * Math.pow(sunsetPercent,3)),
"bloomThreshold": 1,
"bloomSize": -(0.05 + (9.95 * Math.pow(sunsetPercent,3)))
}
});
//print("result: " + result);
var distanceLight = 0.10;
Entities.editEntity(sunlightID, {
"localPosition": { "x": -(distanceLight * x), "y": -(distanceLight * y) , "z": -(distanceLight * z) },
"color": sunColor,
"intensity": 100000 // + (90000 * (1 - sunsetPercent))
});
// "#fd5e53"
}
// This is called every time a new object is created with this script
return new MyObject()
}) // Either use this or a return at the very end of the file.