2023-07-23 16:46:30 +02:00
|
|
|
// To compile on Windows
|
|
|
|
|
2023-07-24 23:15:49 +02:00
|
|
|
// Install GLFW 3.3.8
|
|
|
|
// https://www.glfw.org/download.html
|
2023-07-26 23:29:51 +02:00
|
|
|
// Install GLEW 2.2.0
|
|
|
|
// https://github.com/nigels-com/glew/releases/tag/glew-2.2.0
|
|
|
|
//
|
|
|
|
// extract the downloaded .zip files to "C:/libs"; this is currently expected
|
2023-07-24 23:15:49 +02:00
|
|
|
// by our CMakeLists.txt.
|
|
|
|
|
2023-07-23 16:46:30 +02:00
|
|
|
// Install CMake
|
|
|
|
// https://cmake.org/download
|
|
|
|
// Add to PATH for all users
|
|
|
|
// from project root:
|
|
|
|
// mkdir build
|
|
|
|
// cd build
|
|
|
|
// cmake ..
|
|
|
|
// cmake --build .
|
2023-07-23 17:46:53 +02:00
|
|
|
// The last step compiles the executable - this can also be done from Visual
|
|
|
|
// Studio
|
2023-07-23 16:46:30 +02:00
|
|
|
|
2023-07-23 17:46:53 +02:00
|
|
|
// To run in VS
|
|
|
|
// Set startup project in Solution Explorer
|
2023-07-24 23:15:49 +02:00
|
|
|
// Press F5 to run
|
2023-08-02 00:29:52 +02:00
|
|
|
|
|
|
|
// To run in VSCode
|
|
|
|
// https://code.visualstudio.com/docs/cpp/config-mingw
|
|
|
|
|
2023-07-24 23:15:49 +02:00
|
|
|
// To compile on Arch Linux
|
|
|
|
//
|
|
|
|
// Install dependencies
|
2023-07-24 23:31:58 +02:00
|
|
|
// sudo pacman -S glfw mesa glew
|
2023-07-24 23:15:49 +02:00
|
|
|
//
|
|
|
|
// Build
|
|
|
|
// cmake ..
|
|
|
|
// cmake --build .
|
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
|
|
|
|
2023-07-31 00:08:17 +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"
|
2023-10-06 00:25:37 +02:00
|
|
|
#include "widget.hpp"
|
2023-07-24 23:54:37 +02:00
|
|
|
|
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
|
|
|
|
{
|
|
|
|
bool cycleAnimation;
|
|
|
|
} input;
|
|
|
|
|
2024-03-04 00:52:34 +01:00
|
|
|
void keyCallback(GLFWwindow* window, int key, int scancode, int action, int mods)
|
|
|
|
{
|
|
|
|
if (key == GLFW_KEY_C && action == GLFW_PRESS)
|
|
|
|
{
|
2024-03-04 08:57:42 +01:00
|
|
|
input.cycleAnimation = true;
|
2024-03-04 00:52:34 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-04 08:57:42 +01:00
|
|
|
void clearInput()
|
|
|
|
{
|
|
|
|
input.cycleAnimation = false;
|
|
|
|
}
|
|
|
|
|
2024-08-21 15:53:33 +02:00
|
|
|
double getTime()
|
|
|
|
{
|
|
|
|
auto now = std::chrono::steady_clock::now().time_since_epoch();
|
|
|
|
return std::chrono::duration<double>(now).count();
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
Orbit orbit;
|
|
|
|
orbit.setSemiMajorAxis(1.0); // in km
|
|
|
|
// TODO: implement zoom
|
|
|
|
//orbit.setSemiMajorAxis(384748); // in km
|
|
|
|
orbit.setEccentricity(0.055);
|
2024-08-21 14:30:21 +02:00
|
|
|
orbit.setInclination(glm::radians(5.15)); // radians?
|
2024-08-20 01:35:43 +02:00
|
|
|
orbit.setArgumentOfPeriapsis(318.15); // in the case of the moon these last two values are
|
|
|
|
orbit.setLongitudeOfAscendingNode(60.0); // pretty much constantly changing so use whatever
|
|
|
|
|
|
|
|
// TODO: add something in a nice eccentric orbit around the moon
|
|
|
|
// make the earth-moon system
|
|
|
|
ParticleMap map;
|
|
|
|
map.setParticle({"earth", 5.9e24});
|
2024-08-20 21:21:44 +02:00
|
|
|
map.setParticle({"moon", 7.3e22});
|
|
|
|
map.setRelationship("earth", "moon", orbit);
|
2024-08-20 01:35:43 +02:00
|
|
|
ParticleVisualizer earthVis(map, "earth", 0.2, litProgram, unlitProgram);
|
2024-08-20 21:21:44 +02:00
|
|
|
ParticleVisualizer moonVis(map, "moon", 0.1, litProgram, unlitProgram);
|
2024-08-20 01:35:43 +02:00
|
|
|
OrbitVisualizer orbitVis(orbit, unlitProgram);
|
2023-10-06 00:25:37 +02:00
|
|
|
|
2024-03-04 00:52:34 +01:00
|
|
|
// register input
|
|
|
|
glfwSetKeyCallback(window, keyCallback);
|
|
|
|
|
2024-08-18 02:43:57 +02:00
|
|
|
// TODO: convert these to an enum
|
|
|
|
const int ANIM_ORBITING = 0;
|
|
|
|
const int ANIM_ECCENTRICITY = 1;
|
|
|
|
int animation = 0;
|
2024-08-21 15:53:33 +02:00
|
|
|
|
|
|
|
double time = getTime();
|
2024-08-18 02:43:57 +02:00
|
|
|
|
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-03-04 08:57:42 +01:00
|
|
|
// apply input
|
|
|
|
if (input.cycleAnimation)
|
|
|
|
{
|
2024-08-18 02:43:57 +02:00
|
|
|
animation++;
|
|
|
|
if (animation > ANIM_ECCENTRICITY)
|
|
|
|
{
|
|
|
|
animation = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// only update time if playing the orbiting animation
|
2024-08-21 15:53:33 +02:00
|
|
|
const double speed = 0.5;
|
2024-08-18 02:43:57 +02:00
|
|
|
if (animation == ANIM_ORBITING)
|
|
|
|
{
|
2024-08-21 15:53:33 +02:00
|
|
|
time = getTime() * speed;
|
2024-08-18 02:43:57 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2024-08-21 15:53:33 +02:00
|
|
|
double e = .25 + .2 * sin(getTime());
|
2024-08-18 02:43:57 +02:00
|
|
|
orbit.setEccentricity(e);
|
2024-03-04 08:57:42 +01:00
|
|
|
}
|
|
|
|
|
2024-03-04 00:52:34 +01:00
|
|
|
// rendering
|
2023-07-24 23:54:37 +02:00
|
|
|
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);
|
|
|
|
orbitVis.render(time);
|
2023-07-23 18:21:44 +02:00
|
|
|
|
2023-07-24 23:54:37 +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
|
|
|
}
|