X-Git-Url: https://git.localhorst.tv/?a=blobdiff_plain;f=src%2Fworld%2Fworld.cpp;h=a939b3e586e129e748984e0c55ef9386701ea95d;hb=02d5571eef7630c38968af264a441aa43e802d0f;hp=c9a7a326f3d94a2f4bc496e4100da541df82e794;hpb=98770f59a02c76f02de0a46ed36d9cfd52f5071b;p=blobs.git diff --git a/src/world/world.cpp b/src/world/world.cpp index c9a7a32..a939b3e 100644 --- a/src/world/world.cpp +++ b/src/world/world.cpp @@ -4,15 +4,21 @@ #include "Simulation.hpp" #include "Sun.hpp" #include "Tile.hpp" +#include "TileSet.hpp" +#include "TileType.hpp" #include "../const.hpp" #include "../app/Assets.hpp" #include "../graphics/Viewport.hpp" +#include "../rand/OctaveNoise.hpp" +#include "../rand/SimplexNoise.hpp" #include #include +#include #include #include +#include #include using blobs::G; @@ -235,7 +241,7 @@ glm::dmat4 Orbit::Matrix(double t) const noexcept { double P = sma * (cos(E) - ecc); double Q = sma * sin(E) * sqrt(1 - (ecc * ecc)); - return glm::translate(glm::yawPitchRoll(asc, inc, arg), glm::dvec3(P, 0.0, -Q)); + return glm::yawPitchRoll(asc, inc, arg) * glm::translate(glm::dvec3(P, 0.0, -Q)); } glm::dmat4 Orbit::InverseMatrix(double t) const noexcept { @@ -243,7 +249,7 @@ glm::dmat4 Orbit::InverseMatrix(double t) const noexcept { double E = mean2eccentric(M, ecc); double P = sma * (cos(E) - ecc); double Q = sma * sin(E) * sqrt(1 - (ecc * ecc)); - return glm::transpose(glm::yawPitchRoll(asc, inc, arg)) * glm::translate(glm::dvec3(-P, 0.0, Q)); + return glm::translate(glm::dvec3(-P, 0.0, Q)) * glm::transpose(glm::yawPitchRoll(asc, inc, arg)); } @@ -258,7 +264,15 @@ Planet::Planet(int sidelength) Planet::~Planet() { } -void Planet::BuildVAOs() { +glm::dvec3 Planet::TileCenter(int surface, int x, int y) const noexcept { + glm::dvec3 center(0.0f); + center[(surface + 0) % 3] = x + 0.5 - Radius(); + center[(surface + 1) % 3] = y + 0.5 - Radius(); + center[(surface + 2) % 3] = surface < 3 ? Radius() : -Radius(); + return center; +} + +void Planet::BuildVAOs(const TileSet &ts) { vao.Bind(); vao.BindAttributes(); vao.EnableAttribute(0); @@ -268,7 +282,7 @@ void Planet::BuildVAOs() { vao.ReserveAttributes(TilesTotal() * 4, GL_STATIC_DRAW); { auto attrib = vao.MapAttributes(GL_WRITE_ONLY); - float offset = sidelength * 0.5f; + float offset = Radius(); // srf 0 1 2 3 4 5 // up +Z +X +Y -Z -X -Y @@ -276,33 +290,35 @@ void Planet::BuildVAOs() { for (int index = 0, surface = 0; surface < 6; ++surface) { for (int y = 0; y < sidelength; ++y) { for (int x = 0; x < sidelength; ++x, ++index) { - float tex = TileAt(surface, x, y).type; + float tex = ts[TileAt(surface, x, y).type].texture; + const float tex_u_begin = surface < 3 ? 1.0f : 0.0f; + const float tex_u_end = surface < 3 ? 0.0f : 1.0f; attrib[4 * index + 0].position[(surface + 0) % 3] = x + 0 - offset; attrib[4 * index + 0].position[(surface + 1) % 3] = y + 0 - offset; attrib[4 * index + 0].position[(surface + 2) % 3] = surface < 3 ? offset : -offset; - attrib[4 * index + 0].tex_coord[0] = 0.0f; - attrib[4 * index + 0].tex_coord[1] = 0.0f; + attrib[4 * index + 0].tex_coord[0] = tex_u_begin; + attrib[4 * index + 0].tex_coord[1] = 1.0f; attrib[4 * index + 0].tex_coord[2] = tex; attrib[4 * index + 1].position[(surface + 0) % 3] = x + 0 - offset; attrib[4 * index + 1].position[(surface + 1) % 3] = y + 1 - offset; attrib[4 * index + 1].position[(surface + 2) % 3] = surface < 3 ? offset : -offset; - attrib[4 * index + 1].tex_coord[0] = 0.0f; + attrib[4 * index + 1].tex_coord[0] = tex_u_end; attrib[4 * index + 1].tex_coord[1] = 1.0f; attrib[4 * index + 1].tex_coord[2] = tex; attrib[4 * index + 2].position[(surface + 0) % 3] = x + 1 - offset; attrib[4 * index + 2].position[(surface + 1) % 3] = y + 0 - offset; attrib[4 * index + 2].position[(surface + 2) % 3] = surface < 3 ? offset : -offset; - attrib[4 * index + 2].tex_coord[0] = 1.0f; + attrib[4 * index + 2].tex_coord[0] = tex_u_begin; attrib[4 * index + 2].tex_coord[1] = 0.0f; attrib[4 * index + 2].tex_coord[2] = tex; attrib[4 * index + 3].position[(surface + 0) % 3] = x + 1 - offset; attrib[4 * index + 3].position[(surface + 1) % 3] = y + 1 - offset; attrib[4 * index + 3].position[(surface + 2) % 3] = surface < 3 ? offset : -offset; - attrib[4 * index + 3].tex_coord[0] = 1.0f; - attrib[4 * index + 3].tex_coord[1] = 1.0f; + attrib[4 * index + 3].tex_coord[0] = tex_u_end; + attrib[4 * index + 3].tex_coord[1] = 0.0f; attrib[4 * index + 3].tex_coord[2] = tex; } } @@ -359,15 +375,68 @@ void Planet::Draw(app::Assets &assets, graphics::Viewport &viewport) { } -void GenerateTest(Planet &p) { +void GenerateEarthlike(const TileSet &tiles, Planet &p) noexcept { + rand::SimplexNoise elevation_gen(0); + + const int ice = tiles["ice"].id; + const int grass = tiles["grass"].id; + const int water = tiles["water"].id; + const int sand = tiles["sand"].id; + const int rock = tiles["rock"].id; + + constexpr double water_thresh = 0.0; + constexpr double beach_thresh = 0.1; + constexpr double mountain_thresh = 0.5; + + const glm::dvec3 axis(glm::dvec4(0.0, 1.0, 0.0, 0.0) * glm::eulerAngleXY(p.SurfaceTilt().x, p.SurfaceTilt().y)); + const double cap_thresh = std::cos(p.AxialTilt().x); + + for (int surface = 0; surface <= 5; ++surface) { + for (int y = 0; y < p.SideLength(); ++y) { + for (int x = 0; x < p.SideLength(); ++x) { + glm::dvec3 to_tile = p.TileCenter(surface, x, y); + double near_axis = std::abs(glm::dot(glm::normalize(to_tile), axis)); + if (near_axis > cap_thresh) { + p.TileAt(surface, x, y).type = ice; + continue; + } + float elevation = rand::OctaveNoise( + elevation_gen, + to_tile / p.Radius(), + 3, // octaves + 0.5, // persistence + 2 / p.Radius(), // frequency + 2, // amplitude + 2 // growth + ); + if (elevation < water_thresh) { + p.TileAt(surface, x, y).type = water; + } else if (elevation < beach_thresh) { + p.TileAt(surface, x, y).type = sand; + } else if (elevation < mountain_thresh) { + p.TileAt(surface, x, y).type = grass; + } else { + p.TileAt(surface, x, y).type = rock; + } + } + } + } + p.BuildVAOs(tiles); +} + +void GenerateTest(const TileSet &tiles, Planet &p) noexcept { for (int surface = 0; surface <= 5; ++surface) { for (int y = 0; y < p.SideLength(); ++y) { for (int x = 0; x < p.SideLength(); ++x) { - p.TileAt(surface, x, y).type = (x == p.SideLength()/2) + (y == p.SideLength()/2); + if (x == p.SideLength() / 2 && y == p.SideLength() / 2) { + p.TileAt(surface, x, y).type = surface; + } else { + p.TileAt(surface, x, y).type = (x == p.SideLength()/2) + (y == p.SideLength()/2) + 6; + } } } } - p.BuildVAOs(); + p.BuildVAOs(tiles); } @@ -378,5 +447,41 @@ Sun::Sun() Sun::~Sun() { } +TileSet::TileSet() +: types() +, names() { +} + +TileSet::~TileSet() { +} + +int TileSet::Add(const TileType &t) { + int id = types.size(); + if (!names.emplace(t.name, id).second) { + throw std::runtime_error("duplicate tile type name " + t.name); + } + types.emplace_back(t); + types.back().id = id; + return id; +} + +TileType &TileSet::operator [](const std::string &name) { + auto entry = names.find(name); + if (entry != names.end()) { + return types[entry->second]; + } else { + throw std::runtime_error("unknown tile type " + name); + } +} + +const TileType &TileSet::operator [](const std::string &name) const { + auto entry = names.find(name); + if (entry != names.end()) { + return types[entry->second]; + } else { + throw std::runtime_error("unknown tile type " + name); + } +} + } }