skein/src/main.cpp

197 lines
6.1 KiB
C++
Raw Normal View History

2023-07-23 17:46:53 +02:00
2023-07-24 23:31:58 +02:00
#include <GL/glew.h>
2023-07-23 17:46:53 +02:00
#include <GLFW/glfw3.h>
2024-03-04 00:52:34 +01:00
#include <iostream>
2023-07-23 16:45:15 +02:00
#include "gfx.hpp"
2023-08-02 01:52:04 +02:00
#include "icosphere.hpp"
2024-08-18 15:12:08 +02:00
#include "particlevisualizer.hpp"
2024-08-17 22:51:42 +02:00
#include "orbitvisualizer.hpp"
#include "widget.hpp"
2024-08-17 22:51:42 +02:00
#include <skein/orbit.h>
2024-08-18 15:12:08 +02:00
#include <skein/particle.h>
2024-08-20 01:35:43 +02:00
#include <skein/particlemap.h>
2024-08-17 22:51:42 +02:00
2024-08-21 15:53:33 +02:00
#include <chrono>
2024-03-04 08:57:42 +01:00
// INPUT!
//
// what input do we even want in the first place?
// * camera controls - this is a rendering only concern which needn't affect the orbital
// * model validation - we want to modify orbits over time to confirm that our model is
// working properly
//
// TODO: input can only be directly handled by static methods, so we need to find a way to collect
// input from object instances and handle it at a higher level. in the case of this class, we want
// to determine when a configurable key is pressed. alternatively, we can split the behaviour into
// multiple sub-classes and run different loops at the top level?
//
// another idea is to process all input into a well-defined Input struct in the main loop, then
// pass this struct into objects' render() method.
//
// it's possible the first idea makes the most sense if the plan is to ultimately extract the orbit
// stuff to a library, since it keeps input a separate concern from the physics model
struct Input
{
2024-09-23 23:57:57 +02:00
bool pauseTime;
bool printCartesian;
2024-03-04 08:57:42 +01:00
} input;
2024-09-23 23:57:57 +02:00
2024-03-04 00:52:34 +01:00
void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if (action == GLFW_PRESS)
2024-03-04 00:52:34 +01:00
{
input.pauseTime = key == GLFW_KEY_SPACE;
input.printCartesian = key == GLFW_KEY_W;
2024-03-04 00:52:34 +01:00
}
}
2024-03-04 08:57:42 +01:00
void clearInput()
{
2024-09-23 23:57:57 +02:00
input.pauseTime = false;
input.printCartesian = false;
2024-03-04 08:57:42 +01:00
}
2024-09-23 23:57:57 +02:00
// now should always increase linearly with real world time, this should not be modified by input
// for animations etc
struct Time
{
double now;
double dt;
} engineTime;
void updateTime()
2024-08-21 15:53:33 +02:00
{
2024-09-23 23:57:57 +02:00
std::chrono::duration timeSinceEpoch = std::chrono::steady_clock::now().time_since_epoch();
double now = std::chrono::duration<double>(timeSinceEpoch).count();
double dt = now - engineTime.now;
engineTime.dt = dt;
engineTime.now = now;
2024-08-21 15:53:33 +02:00
}
void printVector(const glm::dvec3& vector)
{
std::cout << "(" << vector.x << ", " << vector.y << ", " << vector.z << ")";
}
2023-07-30 23:02:20 +02:00
int main()
{
GLFWwindow* window = nullptr;
2024-08-18 01:10:20 +02:00
if (initGraphics(&window, "skeingl") != 0)
2023-07-30 23:02:20 +02:00
return -1;
2023-08-06 13:08:49 +02:00
GLuint litProgram = compileShaderProgram("./frag_lit.glsl");
GLuint unlitProgram = compileShaderProgram("./frag_unlit.glsl");
2024-08-20 01:35:43 +02:00
// set parameters of moon's orbit around earth
2024-08-24 14:18:08 +02:00
Orbit moonOrbit;
double moonOrbitSemiMajorAxis = 3.84748e8;
moonOrbit.setSemiMajorAxis(moonOrbitSemiMajorAxis); // metres
moonOrbit.setEccentricity(0.055);
moonOrbit.setInclination(glm::radians(5.15)); // radians
moonOrbit.setArgumentOfPeriapsis(318.15); // in the case of the moon these last two values are
moonOrbit.setLongitudeOfAscendingNode(60.0); // pretty much constantly changing so use whatever
// set parameters of satellite orbit around moon
Orbit stationOrbit;
stationOrbit.setSemiMajorAxis(5e7);
stationOrbit.setEccentricity(0.6);
stationOrbit.setInclination(glm::radians(89.0));
stationOrbit.setArgumentOfPeriapsis(43.2);
stationOrbit.setLongitudeOfAscendingNode(239.7);
2024-08-20 01:35:43 +02:00
ParticleMap map;
map.setParticle({"earth", 5.9e24});
2024-08-20 21:21:44 +02:00
map.setParticle({"moon", 7.3e22});
2024-08-24 14:18:08 +02:00
map.setParticle({"station", 1e6});
map.setRelationship("earth", "moon", moonOrbit);
map.setRelationship("moon", "station", stationOrbit);
float scale = moonOrbitSemiMajorAxis * 1.1;
ParticleVisualizer earthVis(map, "earth", 0.1, litProgram, unlitProgram, scale);
ParticleVisualizer moonVis(map, "moon", 0.02, litProgram, unlitProgram, scale);
ParticleVisualizer stationVis(map, "station", 0.01, litProgram, unlitProgram, scale);
OrbitVisualizer moonOrbitVis(map, "moon", unlitProgram, scale);
OrbitVisualizer stationOrbitVis(map, "station", unlitProgram, scale);
2024-03-04 00:52:34 +01:00
// register input
glfwSetKeyCallback(window, keyCallback);
// TODO: convert these to an enum
2024-09-23 23:57:57 +02:00
const int MODE_ORBIT = 0;
const int MODE_MANEOUVRE = 1;
int mode = 0;
2024-08-21 15:53:33 +02:00
2024-09-23 23:57:57 +02:00
// simulation time. this can be paused or whatever as animation demands.
double time = 0;
2023-07-27 21:54:06 +02:00
// Main loop
2023-07-23 17:46:53 +02:00
while (!glfwWindowShouldClose(window))
{
2024-03-04 08:57:42 +01:00
// receive input - key callback populates input struct defined further up,
// clearInput() needs to be called to clear input from previous frame
clearInput();
2024-03-04 00:52:34 +01:00
glfwPollEvents();
2024-09-23 23:57:57 +02:00
updateTime();
2024-03-04 00:52:34 +01:00
2024-03-04 08:57:42 +01:00
// apply input
2024-09-23 23:57:57 +02:00
if (input.pauseTime)
2024-03-04 08:57:42 +01:00
{
2024-09-23 23:57:57 +02:00
mode++;
if (mode > MODE_MANEOUVRE)
{
2024-09-23 23:57:57 +02:00
mode = 0;
}
}
// the moon takes like 27 days to orbit earth. to see this in motion, then, we need to
// increase the speed of time by 60 * 60 * 24 to see 1 day per second.
const double speed = 60 * 60 * 24;
2024-09-23 23:57:57 +02:00
// orbit modifications need to be instanteneous
if (mode == MODE_ORBIT)
{
2024-09-23 23:57:57 +02:00
time += engineTime.dt * speed;
}
else
{
if (input.printCartesian)
{
const glm::dvec3 p = map.getParticleLocalPosition("station", time);
printVector(p);
std::cout << std::endl;
// TODO: what unit is this in lol
const glm::dvec3 v = map.getParticleLocalVelocity("station", time);
const glm::dvec3 newVelocity = v * 0.9;
printVector(v);
std::cout << " -> ";
printVector(newVelocity);
std::cout << std::endl;
map.setParticleLocalVelocity("station", time, newVelocity);
}
2024-03-04 08:57:42 +01:00
}
2024-03-04 00:52:34 +01:00
// rendering
glClearColor(0.2, 0.3, 0.3, 1.0);
2023-08-03 10:28:14 +02:00
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2023-07-23 18:21:44 +02:00
2024-08-20 01:35:43 +02:00
earthVis.render(time);
moonVis.render(time);
2024-08-24 14:18:08 +02:00
stationVis.render(time);
moonOrbitVis.render(time);
stationOrbitVis.render(time);
2023-07-23 18:21:44 +02:00
glfwSwapBuffers(window);
2023-07-23 17:46:53 +02:00
}
glfwTerminate();
2023-07-23 16:45:15 +02:00
return 0;
2023-07-24 23:15:49 +02:00
}