MasterState &operator =(MasterState &&) = delete;
public:
- void SetReference(world::Body &r) { reference = &r; }
+ graphics::Camera &GetCamera() noexcept { return cam; }
+ const graphics::Camera &GetCamera() const noexcept { return cam; }
private:
void OnResize(int w, int h) override;
private:
Assets &assets;
world::Simulation ∼
- world::Body *reference;
graphics::Camera cam;
#include "MasterState.hpp"
#include "../world/Body.hpp"
+#include "../world/Planet.hpp"
#include "../world/Simulation.hpp"
+#include "../world/Sun.hpp"
#include <glm/gtx/transform.hpp>
: State()
, assets(assets)
, sim(sim)
-, reference(&sim.Root())
-, cam()
+, cam(sim.Root())
, remain(0)
, thirds(0)
, paused(false) {
- // sunset view: standing in the center of surface 0 (+Z), looking west (-X)
- //cam.View(glm::lookAt(glm::vec3(0.0f, 0.0f, 5.6f), glm::vec3(-1.0f, 0.0f, 5.6f), glm::vec3(0.0f, 0.0f, 1.0f)));
- // sunrise view: standing in the center of surface 0 (+Z), looking east (+X)
- cam.View(glm::lookAt(glm::vec3(0.0f, 0.0f, 5.6f), glm::vec3(1.0f, 0.0f, 5.6f), glm::vec3(0.0f, 0.0f, 1.0f)));
- // far out, looking at planet
- //cam.View(glm::lookAt(glm::vec3(10.0f, 10.0f, 50.0f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f)));
}
MasterState::~MasterState() noexcept {
}
void MasterState::OnRender(graphics::Viewport &viewport) {
- glm::dmat4 ppos = reference->InverseTransform() * reference->ToParent();
+ glm::dmat4 ppos = cam.Model(**sim.Suns().begin());
assets.shaders.planet_surface.Activate();
assets.shaders.planet_surface.SetTexture(assets.textures.tiles);
+ assets.shaders.planet_surface.SetLight(glm::vec3(cam.View() * ppos[3]), glm::vec3(1.0f, 1.0f, 1.0f), 1.0e6f);
- assets.shaders.planet_surface.SetMVP(glm::mat4(1.0f), cam.View(), cam.Projection());
- assets.shaders.planet_surface.SetLight(glm::vec3(cam.View() * ppos[3]), glm::vec3(1.0f, 1.0f, 1.0f), 2.0e4f);
- reference->Draw(assets, viewport);
-
- world::Body *child = reference->Children()[0];
- assets.shaders.planet_surface.SetMVP(reference->InverseTransform() * child->FromParent() * child->LocalTransform(), cam.View(), cam.Projection());
- child->Draw(assets, viewport);
+ for (auto planet : sim.Planets()) {
+ assets.shaders.planet_surface.SetMVP(cam.Model(*planet), cam.View(), cam.Projection());
+ planet->Draw(assets, viewport);
+ }
assets.shaders.sun_surface.Activate();
- assets.shaders.sun_surface.SetMVP(ppos * reference->Parent().LocalTransform(), cam.View(), cam.Projection());
- assets.shaders.sun_surface.SetLight(glm::vec3(1.0f, 1.0f, 1.0f), 2.0e4f);
- assets.shaders.sun_surface.Draw();
+ for (auto sun : sim.Suns()) {
+ double sun_radius = sun->Radius();
+ assets.shaders.sun_surface.SetMVP(
+ cam.Model(*sun) * glm::scale(glm::vec3(sun_radius, sun_radius, sun_radius)),
+ cam.View(), cam.Projection());
+ assets.shaders.sun_surface.SetLight(glm::vec3(1.0f, 1.0f, 1.0f), 1.0e6f);
+ assets.shaders.sun_surface.Draw();
+ }
}
}
using namespace blobs;
int main(int argc, char *argv[]) {
- app::Init init;
+ app::Init init(true, 8);
app::Assets assets;
world::Sun sun;
sun.Mass(1.0e12);
- sun.Radius(1.0);
+ sun.Radius(10.0);
sun.SurfaceTilt(glm::dvec2(PI * 0.25, PI * 0.25));
sun.AngularMomentum(1.0e9);
world::GenerateTest(planet);
planet.SetParent(sun);
planet.Mass(1.0e9);
- planet.GetOrbit().SemiMajorAxis(100.0);
+ planet.GetOrbit().SemiMajorAxis(941.7);
planet.SurfaceTilt(glm::dvec2(PI * 0.25, PI * 0.25));
planet.AxialTilt(glm::dvec2(PI * 0.127, 0.0));
- planet.AngularMomentum(3.0e9);
+ planet.AngularMomentum(1.25e9);
world::Planet moon(3);
world::GenerateTest(moon);
moon.SetParent(planet);
moon.Mass(1.0e6);
moon.GetOrbit().SemiMajorAxis(25.0);
- moon.AngularMomentum(1.0e5);
+ moon.Rotation(PI * 0.25);
+ moon.AngularMomentum(1.0e4);
world::Simulation sim(sun);
- sim.AddBody(planet);
- sim.AddBody(moon);
+ sim.AddSun(sun);
+ sim.AddPlanet(planet);
+ sim.AddPlanet(moon);
std::cout << "length of year: " << planet.OrbitalPeriod() << "s" << std::endl;
std::cout << "length of moon cycle: " << moon.OrbitalPeriod() << "s" << std::endl;
std::cout << "length of day: " << planet.RotationalPeriod() << "s" << std::endl;
+ std::cout << "days per year: " << (planet.OrbitalPeriod() / planet.RotationalPeriod()) << std::endl;
+ std::cout << "moon cycle in days: " << (moon.OrbitalPeriod() / planet.RotationalPeriod()) << std::endl;
+ std::cout << "moon cycles per year: " << (planet.OrbitalPeriod() / moon.OrbitalPeriod()) << std::endl;
app::MasterState state(assets, sim);
- state.SetReference(planet);
+ state.GetCamera()
+ .Reference(planet)
+ // sunrise
+ .FirstPerson(0, glm::vec3(0.0f, 0.0f, 0.1f), glm::vec3(1.0f, -0.75f, 0.1f))
+ // sunset
+ //.FirstPerson(3, glm::vec3(0.0f, 0.0f, 0.1f), glm::vec3(1.0f, -0.75f, 0.1f))
+ // from afar
+ //.MapView(0, glm::vec3(0.0f, 0.0f, 25.0f), 0.0f)
+ // system view
+ //.Orbital(glm::vec3(50.0f, 2500.0f, 50.0f));
+ ;
planet.BuildVAOs();
app::Application app(init.window, init.viewport);
namespace blobs {
+namespace world {
+ class Body;
+}
namespace graphics {
class Camera {
public:
- Camera() noexcept;
+ explicit Camera(const world::Body &) noexcept;
~Camera() noexcept;
Camera(const Camera &) = delete;
Camera &operator =(Camera &&) = delete;
public:
- void FOV(float f) noexcept;
- void Aspect(float r) noexcept;
- void Aspect(float w, float h) noexcept;
- void Clip(float near, float far) noexcept;
+ Camera &FOV(float f) noexcept;
+ Camera &Aspect(float r) noexcept;
+ Camera &Aspect(float w, float h) noexcept;
+ Camera &Clip(float near, float far) noexcept;
+
+ const world::Body &Reference() const noexcept { return *ref; }
+ Camera &Reference(const world::Body &) noexcept;
+
+ /// standing on given surface, with pos.z being elevation over NN
+ /// looking at given coordinates
+ Camera &FirstPerson(int surface, const glm::vec3 &pos, const glm::vec3 &at) noexcept;
+ /// looking straight down at surface from above
+ Camera &MapView(int surface, const glm::vec3 &pos, float roll = 0.0f) noexcept;
+ /// look at center, position relative to orbital reference plane for children
+ Camera &Orbital(const glm::vec3 &pos) noexcept;
const glm::mat4 &Projection() const noexcept { return projection; }
const glm::mat4 &View() const noexcept { return view; }
- void View(const glm::mat4 &v) noexcept;
+ glm::mat4 Model(const world::Body &) const noexcept;
private:
void UpdateProjection() noexcept;
glm::mat4 projection;
glm::mat4 view;
+ // reference frame
+ const world::Body *ref;
+ // track reference body's orientation
+ bool track_orient;
+
};
}
#include "Viewport.hpp"
#include "../const.hpp"
+#include "../world/Body.hpp"
+#include <cmath>
#include <GL/glew.h>
#include <glm/gtx/transform.hpp>
namespace blobs {
namespace graphics {
-Camera::Camera() noexcept
+Camera::Camera(const world::Body &r) noexcept
: fov(PI_0p25)
, aspect(1.0f)
, near(0.1f)
-, far(256.0f)
+, far(12560.0f)
, projection(glm::perspective(fov, aspect, near, far))
-, view(1.0f) {
+, view(1.0f)
+, ref(&r)
+, track_orient(false) {
}
Camera::~Camera() noexcept {
}
-void Camera::FOV(float f) noexcept {
+Camera &Camera::FOV(float f) noexcept {
fov = f;
UpdateProjection();
+ return *this;
}
-void Camera::Aspect(float r) noexcept {
+Camera &Camera::Aspect(float r) noexcept {
aspect = r;
UpdateProjection();
+ return *this;
}
-void Camera::Aspect(float w, float h) noexcept {
+Camera &Camera::Aspect(float w, float h) noexcept {
Aspect(w / h);
+ return *this;
}
-void Camera::Clip(float n, float f) noexcept {
+Camera &Camera::Clip(float n, float f) noexcept {
near = n;
far = f;
UpdateProjection();
+ return *this;
}
-void Camera::View(const glm::mat4 &v) noexcept {
- view = v;
+Camera &Camera::Reference(const world::Body &r) noexcept {
+ ref = &r;
+ return *this;
+}
+
+Camera &Camera::FirstPerson(int srf, const glm::vec3 &pos, const glm::vec3 &at) noexcept {
+ track_orient = true;
+
+ float dir = srf < 3 ? 1.0f : -1.0f;
+
+ glm::vec3 position;
+ position[(srf + 0) % 3] = pos.x;
+ position[(srf + 1) % 3] = pos.y;
+ position[(srf + 2) % 3] = dir * (pos.z + Reference().Radius());
+
+ glm::vec3 up(0.0f);
+ up[(srf + 2) % 3] = dir;
+
+ glm::vec3 target;
+ target[(srf + 0) % 3] = at.x;
+ target[(srf + 1) % 3] = at.y;
+ target[(srf + 2) % 3] = dir * (at.z + Reference().Radius());
+
+ view = glm::lookAt(position, target, up);
+
+ return *this;
+}
+
+Camera &Camera::MapView(int srf, const glm::vec3 &pos, float roll) noexcept {
+ track_orient = true;
+
+ float dir = srf < 3 ? 1.0f : -1.0f;
+
+ glm::vec3 position;
+ position[(srf + 0) % 3] = pos.x;
+ position[(srf + 1) % 3] = pos.y;
+ position[(srf + 2) % 3] = dir * (pos.z + Reference().Radius());
+
+ glm::vec3 up(0.0f);
+ up[(srf + 0) % 3] = std::cos(roll);
+ up[(srf + 1) % 3] = std::sin(roll);
+ up[(srf + 2) % 3] = 0.0f;
+
+ glm::vec3 target = position;
+ target[(srf + 2) % 3] -= dir;
+
+ view = glm::lookAt(position, target, up);
+
+ return *this;
+}
+
+Camera &Camera::Orbital(const glm::vec3 &pos) noexcept {
+ track_orient = false;
+ view = glm::lookAt(pos, glm::vec3(0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
+ return *this;
+}
+
+glm::mat4 Camera::Model(const world::Body &b) const noexcept {
+ if (&b == ref) {
+ return track_orient ? glm::mat4(1.0f) : glm::mat4(ref->LocalTransform());
+ } else if (b.HasParent() && &b.Parent() == ref) {
+ return track_orient
+ ? ref->InverseTransform() * b.FromParent() * b.LocalTransform()
+ : b.FromParent() * b.LocalTransform();
+ } else if (ref->HasParent() && &ref->Parent() == &b) {
+ return track_orient
+ ? ref->InverseTransform() * ref->ToParent() * b.LocalTransform()
+ : ref->ToParent() * b.LocalTransform();
+ } else {
+ // TODO: model matrices for path distances > 1
+ return track_orient ? glm::mat4(1.0f) : glm::mat4(ref->LocalTransform());
+ }
}
void Camera::UpdateProjection() noexcept {
#ifndef BLOBS_WORLD_SIMULATION_HPP_
#define BLOBS_WORLD_SIMULATION_HPP_
-#include <vector>
+#include <set>
namespace blobs {
namespace world {
class Body;
+class Planet;
+class Sun;
class Simulation {
void Tick();
void AddBody(Body &);
+ void AddPlanet(Planet &);
+ void AddSun(Sun &);
- Body &Root() { return root; }
- const Body &Root() const { return root; }
+ Body &Root() noexcept { return root; }
+ const Body &Root() const noexcept { return root; }
+
+ const std::set<Body *> &Bodies() const noexcept { return bodies; }
+ const std::set<Planet *> &Planets() const noexcept { return planets; }
+ const std::set<Sun *> &Suns() const noexcept { return suns; }
double Time() const noexcept { return time; }
private:
Body &root;
- std::vector<Body *> all_bodies;
+ std::set<Body *> bodies;
+ std::set<Planet *> planets;
+ std::set<Sun *> suns;
double time;
};
#include "Simulation.hpp"
#include "Body.hpp"
+#include "Planet.hpp"
+#include "Sun.hpp"
namespace blobs {
Simulation::Simulation(Body &r)
: root(r)
-, all_bodies()
+, bodies()
+, planets()
+, suns()
, time(0.0) {
AddBody(r);
}
void Simulation::AddBody(Body &b) {
b.SetSimulation(*this);
- all_bodies.push_back(&b);
+ bodies.insert(&b);
+}
+
+void Simulation::AddPlanet(Planet &p) {
+ AddBody(p);
+ planets.insert(&p);
+}
+
+void Simulation::AddSun(Sun &s) {
+ AddBody(s);
+ suns.insert(&s);
}
void Simulation::Tick() {
constexpr double dt = 0.01666666666666666666666666666666;
time += dt;
- for (auto body : all_bodies) {
+ for (auto body : bodies) {
body->Rotation(body->Rotation() + dt * body->AngularMomentum() / body->Inertia());
}
}
auto attrib = vao.MapAttributes(GL_WRITE_ONLY);
float offset = sidelength * 0.5f;
+ // srf 0 1 2 3 4 5
+ // up +Z +X +Y -Z -X -Y
+
for (int index = 0, surface = 0; surface < 6; ++surface) {
for (int y = 0; y < sidelength; ++y) {
for (int x = 0; x < sidelength; ++x, ++index) {