Skip to content

Commit e474a6c

Browse files
Init repo
0 parents  commit e474a6c

File tree

4 files changed

+291
-0
lines changed

4 files changed

+291
-0
lines changed

.gitmodules

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "Cinder"]
2+
path = Cinder
3+
url = https://github.com/cinder/Cinder.git

CMakeLists.txt

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
cmake_minimum_required(VERSION 3.20)
2+
3+
project(orbitsim LANGUAGES CXX)
4+
5+
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/Cinder)
6+
7+
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src coresrc)
8+
add_executable(${PROJECT_NAME} WIN32 ${coresrc})
9+
10+
set_target_properties(${PROJECT_NAME}
11+
PROPERTIES CXX_STANDARD 17
12+
CXX_STANDARD_REQUIRED ON
13+
# BUILD_TYPE Debug
14+
EXPORT_COMPILE_COMMANDS ON)
15+
16+
target_link_libraries(${PROJECT_NAME} cinder)

Cinder

Submodule Cinder added at 093ea5f

src/main.cpp

+271
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
#include <cinder/app/App.h>
2+
#include <cinder/app/RendererGl.h>
3+
#include <cinder/gl/gl.h>
4+
#include <cinder/Json.h>
5+
6+
#include <random>
7+
8+
// Forces the use of Nvidia display card
9+
#include <windows.h>
10+
extern "C" {
11+
_declspec(dllexport) DWORD NvOptimusEnablement = 1;
12+
_declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
13+
}
14+
15+
using namespace ci;
16+
using namespace ci::app;
17+
using namespace std::this_thread;
18+
using namespace std::chrono_literals;
19+
20+
// constexpr float G = 6.67430;
21+
constexpr float G = 6.67430e-11f;
22+
23+
std::random_device rd;
24+
std::mt19937 gen(rd());
25+
26+
float random_float(float floor, float ceiling) {
27+
std::uniform_real_distribution<float> dis(floor, ceiling);
28+
return dis(gen);
29+
}
30+
31+
float random_float(float ceiling) {
32+
std::uniform_real_distribution<float> dis(0, ceiling);
33+
return dis(gen);
34+
}
35+
36+
class Planet {
37+
public:
38+
vec3 position, speed;
39+
float mass /* kg */, radius /* m */;
40+
41+
Planet() = default;
42+
Planet(float mass, float radius, vec3 position, vec3 speed)
43+
: position{ position }, speed{ speed }, mass{ mass }, radius{ radius }
44+
{}
45+
46+
void draw();
47+
void init_render(gl::GlslProgRef& shader);
48+
void update_speed(std::vector<Planet>&);
49+
50+
vec3 eval_next_pos(float timestep);
51+
void set_pos(vec3);
52+
53+
NLOHMANN_DEFINE_TYPE_INTRUSIVE(Planet, position, speed, mass, radius)
54+
private:
55+
gl::BatchRef m_shape;
56+
};
57+
58+
void Planet::init_render(gl::GlslProgRef& shader) {
59+
auto sphere = geom::Sphere()
60+
.radius(this->radius)
61+
.subdivisions(100);
62+
m_shape = gl::Batch::create(sphere, shader);
63+
}
64+
65+
void Planet::update_speed(std::vector<Planet>& planets) {
66+
// vec3 acceleration = vec3(0, 0, 0); // m/s^2
67+
// for (auto& planet : planets) {
68+
// if (&planet == this)
69+
// continue;
70+
// float x_diff = (this->position.x - planet.position.x);
71+
// float y_diff = (this->position.y - planet.position.y);
72+
// float z_diff = (this->position.z - planet.position.z);
73+
// float denominator = pow(pow(x_diff, 2) + pow(y_diff, 2) + pow(z_diff, 2), 3 / 2);
74+
// float numerator = G * (planet.mass);
75+
// acceleration.x += ((numerator * x_diff) / denominator);
76+
// acceleration.y += ((numerator * y_diff) / denominator);
77+
// acceleration.z += ((numerator * z_diff) / denominator);
78+
// }
79+
// this->speed += acceleration;
80+
vec3 acceleration = vec3(0, 0, 0); // m/s^2
81+
for (const auto& planet : planets) {
82+
if (&planet == this)
83+
continue;
84+
vec3 direction = planet.position - this->position;
85+
float distance = glm::length(direction);
86+
if (distance > 0) {
87+
direction = glm::normalize(direction);
88+
float force = G * (this->mass * planet.mass) / (distance * distance);
89+
acceleration += direction * (force / this->mass);
90+
}
91+
}
92+
this->speed += acceleration;
93+
}
94+
95+
vec3 Planet::eval_next_pos(float timestep) {
96+
float new_x = this->position.x + ((this->speed.x) * timestep);
97+
float new_y = this->position.y + ((this->speed.y) * timestep);
98+
float new_z = this->position.z + ((this->speed.z) * timestep);
99+
return vec3(new_x, new_y, new_z);
100+
}
101+
102+
103+
void Planet::draw() {
104+
gl::pushModelMatrix();
105+
vec3 translation = this->position;
106+
gl::translate(translation);
107+
m_shape->draw();
108+
gl::popModelMatrix();
109+
}
110+
111+
void Planet::set_pos(vec3 target) {
112+
this->position = target;
113+
}
114+
115+
class BasicApp : public App {
116+
public:
117+
void draw() override;
118+
void setup() override;
119+
120+
void mouseDrag(MouseEvent event) override;
121+
void mouseDown(MouseEvent event) override;
122+
void mouseWheel(MouseEvent event) override;
123+
124+
void initialize_from_file(std::string filename);
125+
void dump_to_file(std::string filename);
126+
127+
std::vector<Planet> m_planets;
128+
private:
129+
// Settings
130+
const float ANGLE_SCALAR = 0.01, SCROLL_SCALAR = 100;
131+
const float CAM_DIST = 400;
132+
const float TIMESTEP = 0.00001;
133+
134+
void update_camera();
135+
int half_rounds = 0;
136+
int next_half_rounds = 0;
137+
138+
ivec2 m_mouse_pos;
139+
float m_phi = 0, m_theta = 0;
140+
float m_cam_dist = CAM_DIST;
141+
CameraPersp m_cam;
142+
};
143+
144+
void BasicApp::setup() {
145+
// setWindowSize(1080, 1080);
146+
console() << __argc << std::endl;
147+
if (__argc > 1) {
148+
console() << "Loading previous saved state " << __argv[1] << std::endl;
149+
this->initialize_from_file(__argv[1]);
150+
}
151+
else {
152+
getWindow()->getSignalClose().connect([this]() {
153+
auto t = time(nullptr);
154+
std::ostringstream oss;
155+
oss << std::put_time(localtime(&t), "%Y-%m-%d %H-%M-%S");
156+
oss << ".json";
157+
this->dump_to_file(oss.str());
158+
});
159+
}
160+
setFrameRate(144.0f);
161+
162+
gl::enableDepth();
163+
auto lambert = gl::ShaderDef().lambert().color();
164+
gl::GlslProgRef shader = gl::getStockShader(lambert);
165+
166+
for (int i = 0; i < 100; ++i) {
167+
m_planets.emplace_back(random_float(1000000000000000), random_float(5, 7),
168+
vec3(random_float(-25, 25), random_float(-25, 25), random_float(-25, 25)),
169+
vec3(random_float(-20, 20), random_float(-20, 20), random_float(-20, 20)));
170+
}
171+
for (auto& planet : m_planets)
172+
planet.init_render(shader);
173+
174+
this->update_camera();
175+
}
176+
177+
void BasicApp::draw() {
178+
gl::clear();
179+
this->update_camera();
180+
gl::setMatrices(m_cam);
181+
std::vector<vec3> new_positions(m_planets.size());
182+
for (size_t it = 0; it < m_planets.size(); ++it) {
183+
m_planets.at(it).draw();
184+
m_planets.at(it).update_speed(m_planets);
185+
new_positions.at(it) = m_planets.at(it).eval_next_pos(TIMESTEP);
186+
}
187+
for (size_t it = 0; it < m_planets.size(); ++it)
188+
m_planets.at(it).set_pos(new_positions.at(it));
189+
190+
191+
gl::setMatricesWindow(getWindowSize());
192+
TextBox m_tbox = TextBox()
193+
.alignment(TextBox::LEFT)
194+
.font(Font("Arial", 30))
195+
.size(vec2(300, 30))
196+
.text("INIT")
197+
.backgroundColor(ColorA(0.5f, 0.5f, 0.5f, 0.5f));
198+
std::ostringstream ss;
199+
ss << "phi: ";
200+
ss << roundf(m_phi * 100) / 100;
201+
ss << " theta: ";
202+
ss << roundf(m_theta * 100) / 100;
203+
m_tbox.setText(ss.str());
204+
gl::TextureRef m_tbox_texture = gl::Texture::create(m_tbox.render());
205+
206+
gl::draw(m_tbox_texture, vec2(0, 0));
207+
208+
}
209+
210+
211+
void BasicApp::update_camera() {
212+
if (bool((next_half_rounds - half_rounds) % 2))
213+
m_cam.setWorldUp(m_cam.getWorldUp() * vec3(1, -1, 1));
214+
m_cam.lookAt(vec3(
215+
m_cam_dist * sinf(m_phi) * cosf(m_theta),
216+
m_cam_dist * cosf(m_phi),
217+
m_cam_dist * sinf(m_phi) * sinf(m_theta)
218+
), vec3(0));
219+
half_rounds = next_half_rounds;
220+
}
221+
222+
void BasicApp::mouseDrag(MouseEvent event) {
223+
ivec2 diff = event.getPos() - m_mouse_pos;
224+
// float theta = -atan2(diff.x, diff.y) + M_PI;
225+
// float phi = acosf(clamp(float(diff.y) / getWindowSize().y, -1.0f, 1.0f));
226+
// m_theta += (diff.x * ANGLE_SCALAR * (m_cam_dist / CAM_DIST));
227+
m_theta += (diff.x * ANGLE_SCALAR);
228+
// m_phi += (diff.y * ANGLE_SCALAR * (m_cam_dist / CAM_DIST));
229+
m_phi += (diff.y * ANGLE_SCALAR);
230+
231+
next_half_rounds = int(m_phi / M_PI);
232+
m_mouse_pos = event.getPos();
233+
}
234+
235+
void BasicApp::mouseDown(MouseEvent event) {
236+
m_mouse_pos = event.getPos();
237+
}
238+
239+
void BasicApp::mouseWheel(MouseEvent event) {
240+
float diff = event.getWheelIncrement() * SCROLL_SCALAR;
241+
if (m_cam_dist - diff > 0)
242+
m_cam_dist -= diff;
243+
}
244+
245+
void BasicApp::dump_to_file(std::string filename) {
246+
std::ofstream file(filename);
247+
Json planets_array = m_planets;
248+
file << std::setw(4) << planets_array;
249+
}
250+
251+
void BasicApp::initialize_from_file(std::string filename) {
252+
std::ifstream file(filename);
253+
Json planets_array = Json::parse(file);
254+
m_planets = planets_array.template get<decltype(m_planets)>();
255+
}
256+
257+
CINDER_APP(BasicApp, RendererGl)
258+
259+
void to_json(Json& target, const vec3& source) {
260+
target = Json{
261+
{ "x", source.x },
262+
{ "y", source.y },
263+
{ "z", source.z },
264+
};
265+
}
266+
267+
void from_json(const Json& source, vec3& target) {
268+
source.at("x").get_to(target.x);
269+
source.at("y").get_to(target.y);
270+
source.at("z").get_to(target.z);
271+
}

0 commit comments

Comments
 (0)