osb/source/game/StarSkyRenderData.cpp
Niffe 4b4013e5c8 Dynamic sun image
Also adds access to sun scale, ray color, and fixes sun rendering in front of satellites
2024-03-01 18:28:13 +02:00

181 lines
6.3 KiB
C++

#include "StarSkyRenderData.hpp"
#include "StarJsonExtra.hpp"
#include "StarDataStreamExtra.hpp"
#include "StarRandomPoint.hpp"
#include "StarDrawable.hpp"
namespace Star {
StringList SkyRenderData::starTypes() const {
if (type == SkyType::Warp)
return hyperStarList;
else
return starList;
}
List<SkyOrbiter> SkyRenderData::backOrbiters(Vec2F const& viewSize) const {
if (!settings)
return {};
float planetScale = settings.queryFloat("satellite.planetScale");
float moonScale = settings.queryFloat("satellite.moonScale");
List<tuple<List<pair<String, float>>, Vec2F, float>> orbitingCelestialObjects;
// Gather up all the CelestialParameters and scales for all the celestial
// objects to draw in the sky, we should draw the parent planet if we are a
// satellite, as well as all the other satellites.
if (skyParameters.nearbyPlanet)
orbitingCelestialObjects.append(tuple_cat(*skyParameters.nearbyPlanet, tie(planetScale)));
for (auto moon : skyParameters.nearbyMoons)
orbitingCelestialObjects.append(tuple_cat(moon, tie(moonScale)));
Vec2F satelliteArea = jsonToVec2F(settings.query("satellite.area"));
auto planetCenter = Vec2F(viewSize[0] / 2, 0) - worldOffset;
auto rotMatrix = Mat3F::rotation(worldRotation, planetCenter);
List<SkyOrbiter> orbiters;
for (auto const& object : orbitingCelestialObjects) {
auto const& layers = get<0>(object);
Vec2F pos = get<1>(object);
pos = pos.piecewiseMultiply(satelliteArea);
pos -= worldOffset;
pos = rotMatrix.transformVec2(pos);
for (auto const& l : layers)
orbiters.append(SkyOrbiter{SkyOrbiterType::Moon, get<2>(object) * l.second, 0.0f, l.first, pos});
}
return orbiters;
}
SkyWorldHorizon SkyRenderData::worldHorizon(Vec2F const& viewSize) const {
if (!settings)
return {};
SkyWorldHorizon worldHorizon;
if (type == SkyType::Orbital) {
worldHorizon.center = Vec2F(viewSize[0] / 2, 0) - worldOffset;
worldHorizon.scale = settings.queryFloat("planetHorizon.scale");
worldHorizon.rotation = worldRotation;
worldHorizon.layers = skyParameters.horizonImages;
}
return worldHorizon;
}
List<SkyOrbiter> SkyRenderData::frontOrbiters(Vec2F const& viewSize) const {
if (!settings)
return {};
struct HorizonCloud {
float startAngle;
String image;
float speed;
float radius;
};
List<HorizonCloud> horizonClouds;
if (skyParameters.horizonClouds) {
Vec2I cloudCountRange = jsonToVec2I(settings.query("planetHorizon.cloudCount"));
Vec2F cloudRadiusRange = jsonToVec2F(settings.query("planetHorizon.cloudRadius"));
Vec2F cloudSpeedRange = jsonToVec2F(settings.query("planetHorizon.cloudSpeed"));
StringList cloudList = jsonToStringList(settings.query("planetHorizon.clouds"));
int numClouds = staticRandomI32Range(cloudCountRange[0], cloudCountRange[1], "HorizonCloudCount");
for (int i = 0; i < numClouds; ++i) {
horizonClouds.append({staticRandomFloatRange(0, 2 * Constants::pi, i, "CloudStartAngle"),
staticRandomFrom(cloudList, i, "Cloud"),
staticRandomFloatRange(cloudSpeedRange[0], cloudSpeedRange[1], i, "CloudSpeed"),
staticRandomFloatRange(cloudRadiusRange[0], cloudRadiusRange[1], i, "CloudRadius")});
}
}
List<SkyOrbiter> orbiters;
if (type == SkyType::Atmospheric || type == SkyType::Atmosphereless) {
String image;
if (settings.queryBool("sun.dynamicImage.enabled", false) && !skyParameters.sunType.empty())
image = settings.queryString("sun.dynamicImage.images." + skyParameters.sunType, settings.queryString("sun.image"));
else
image = settings.queryString("sun.image");
orbiters.append({SkyOrbiterType::Sun,
settings.queryFloat("sun.scale", 1.0f),
0.0f,
image,
Vec2F::withAngle(orbitAngle, settings.queryFloat("sun.radius")) + viewSize / 2});
} else if (type == SkyType::Orbital) {
auto planetCenter = Vec2F(viewSize[0] / 2, 0)
- Vec2F::withAngle(worldRotation - Constants::pi / 2, settings.queryFloat("planetHorizon.yCenter")) - worldOffset;
float scale = settings.queryFloat("planetHorizon.scale");
auto rotMatrix = Mat3F::rotation(worldRotation, planetCenter);
if (skyParameters.horizonClouds) {
for (auto const& horizonCloud : horizonClouds) {
Vec2F position = Vec2F::withAngle(horizonCloud.startAngle + orbitAngle * horizonCloud.speed, horizonCloud.radius) + planetCenter;
position = rotMatrix.transformVec2(position);
orbiters.append({SkyOrbiterType::HorizonCloud, scale, worldRotation, horizonCloud.image, position});
}
}
}
return orbiters;
}
DataStream& operator>>(DataStream& ds, SkyRenderData& skyRenderData) {
ds.read(skyRenderData.settings);
ds.read(skyRenderData.skyParameters);
ds.read(skyRenderData.type);
ds.read(skyRenderData.dayLevel);
ds.read(skyRenderData.skyAlpha);
ds.read(skyRenderData.dayLength);
ds.read(skyRenderData.timeOfDay);
ds.read(skyRenderData.epochTime);
ds.read(skyRenderData.starOffset);
ds.read(skyRenderData.starRotation);
ds.read(skyRenderData.worldOffset);
ds.read(skyRenderData.worldRotation);
ds.read(skyRenderData.orbitAngle);
ds.readVlqS(skyRenderData.starFrames);
ds.read(skyRenderData.starList);
ds.read(skyRenderData.hyperStarList);
ds.read(skyRenderData.environmentLight);
ds.read(skyRenderData.mainSkyColor);
ds.read(skyRenderData.topRectColor);
ds.read(skyRenderData.bottomRectColor);
ds.read(skyRenderData.flashColor);
return ds;
}
DataStream& operator<<(DataStream& ds, SkyRenderData const& skyRenderData) {
ds.write(skyRenderData.settings);
ds.write(skyRenderData.skyParameters);
ds.write(skyRenderData.type);
ds.write(skyRenderData.dayLevel);
ds.write(skyRenderData.skyAlpha);
ds.write(skyRenderData.dayLength);
ds.write(skyRenderData.timeOfDay);
ds.write(skyRenderData.epochTime);
ds.write(skyRenderData.starOffset);
ds.write(skyRenderData.starRotation);
ds.write(skyRenderData.worldOffset);
ds.write(skyRenderData.worldRotation);
ds.write(skyRenderData.orbitAngle);
ds.writeVlqS(skyRenderData.starFrames);
ds.write(skyRenderData.starList);
ds.write(skyRenderData.hyperStarList);
ds.write(skyRenderData.environmentLight);
ds.write(skyRenderData.mainSkyColor);
ds.write(skyRenderData.topRectColor);
ds.write(skyRenderData.bottomRectColor);
ds.write(skyRenderData.flashColor);
return ds;
}
}