adding proper turbine syncing

This commit is contained in:
Jay Robson 2024-02-16 15:07:33 +11:00
parent ebde378e10
commit 4753489a2b
53 changed files with 398 additions and 165 deletions

View File

@ -3,20 +3,25 @@ cmake_minimum_required(VERSION 3.25)
project(FastNuclearSim VERSION 1.0) project(FastNuclearSim VERSION 1.0)
set(CMAKE_CXX_STANDARD 26) set(CMAKE_CXX_STANDARD 26)
set(CMAKE_CXX_FLAGS "-g")
if(WIN32) if(NOT DEBUG_SET)
set(CMAKE_CXX_FLAGS "-g -O3") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
else() endif()
set(CMAKE_CXX_FLAGS "-g -O3 -I/usr/include/freetype2") if(NOT WIN32)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I/usr/include/freetype2")
endif() endif()
message("Using cmake flags: ${CMAKE_CXX_FLAGS}")
file(GLOB_RECURSE SOURCES src/*.cpp) file(GLOB_RECURSE SOURCES src/*.cpp)
add_executable(FastNuclearSim ${SOURCES}) add_executable(FastNuclearSim ${SOURCES})
if(WIN32) if(WIN32)
target_link_libraries(FastNuclearSim PUBLIC stdc++ m brotlidec assimp-5 glew32 opengl32 glfw3 freetype jsoncpp zlibstatic) set(libs stdc++ m brotlidec assimp-5 glew32 opengl32 glfw3 freetype jsoncpp zlibstatic)
else() else()
target_link_libraries(FastNuclearSim PUBLIC stdc++ m GLEW glfw GL freetype assimp jsoncpp) set(libs stdc++ m GLEW glfw GL freetype assimp jsoncpp)
endif() endif()
message("Using libs ${libs}")
target_link_libraries(FastNuclearSim PUBLIC ${libs})

BIN
assets/model/monitor_graphics.stl (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/model/monitor_turbine.stl (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
assets/model/pump_switch_1.glb (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

BIN
assets/model/pump_switch_2.glb (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

BIN
assets/model/pump_switch_3.glb (Stored with Git LFS)

Binary file not shown.

BIN
assets/model/pump_switch_click_1.stl (Stored with Git LFS)

Binary file not shown.

BIN
assets/model/pump_switch_click_3.stl (Stored with Git LFS)

Binary file not shown.

BIN
assets/model/reactor_core_joystick.stl (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
assets/model/switch.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/model/synchroscope_dial.stl (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

BIN
assets/model/turbine_breaker_switch_click.stl (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
assets/model/turbine_valve_bypass_switch_click.stl (Stored with Git LFS) Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
assets/model/turbine_valve_inlet_switch_click.stl (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/scene-baked.glb (Stored with Git LFS)

Binary file not shown.

BIN
assets/unbaked/scene.blend (Stored with Git LFS)

Binary file not shown.

BIN
assets/unbaked/scene/labels.png (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

BIN
assets/unbaked/scene/labels_1.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/unbaked/scene/labels_2.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -23,9 +23,39 @@ void valve::clear_open_speed()
speed = 0; speed = 0;
} }
void valve::toggle_auto()
{
set_auto(!auto_on);
}
void valve::set_auto(bool state)
{
if(state)
{
auto_th = src->get_heat();
}
else
{
auto_th = 0;
}
auto_on = state;
speed = 0;
}
void valve::update(double dt) void valve::update(double dt)
{
if(auto_on)
{
state -= pid.calculate(dt, auto_th, src->get_heat()) * dt;
auto_th += speed * dt * 100;
}
else
{ {
state += speed * dt; state += speed * dt;
}
if(state > 1) state = 1; if(state > 1) state = 1;
if(state < 0) state = 0; if(state < 0) state = 0;
@ -81,11 +111,12 @@ void valve::update(double dt)
this->flow = (mass_s + mass_a) / dt; this->flow = (mass_s + mass_a) / dt;
} }
valve::valve(const Json::Value& node, fluid_holder* src, fluid_holder* dst) : src(src), dst(dst), max(node["max"].asDouble()) valve::valve(const Json::Value& node, fluid_holder* src, fluid_holder* dst) : src(src), dst(dst), max(node["max"].asDouble()), pid(node["pid"])
{ {
speed = node["speed"].asDouble();
state = node["state"].asDouble(); state = node["state"].asDouble();
flow = node["flow"].asDouble(); flow = node["flow"].asDouble();
auto_th = node["auto_th"].asDouble();
auto_on = node["auto_on"].asBool();
} }
valve::operator Json::Value() const valve::operator Json::Value() const
@ -93,9 +124,11 @@ valve::operator Json::Value() const
Json::Value node; Json::Value node;
node["max"] = max; node["max"] = max;
node["speed"] = speed;
node["state"] = state; node["state"] = state;
node["flow"] = flow; node["flow"] = flow;
node["auto_th"] = auto_th;
node["auto_on"] = auto_on;
node["pid"] = pid;
return node; return node;
} }

View File

@ -2,6 +2,7 @@
#pragma once #pragma once
#include "fluid_holder.hpp" #include "fluid_holder.hpp"
#include "../util/pid.hpp"
namespace sim::coolant namespace sim::coolant
{ {
@ -17,6 +18,11 @@ class valve
double state = 0; double state = 0;
double flow = 0; // L/s double flow = 0; // L/s
bool auto_on = false;
double auto_th = 0; // C
util::PID pid {1e-3, -1e-3, 100, 0, 0};
public: public:
valve(fluid_holder* src, fluid_holder* dst, double state, double max); valve(fluid_holder* src, fluid_holder* dst, double state, double max);
@ -25,11 +31,15 @@ public:
void update(double secs); void update(double secs);
void add_open_speed(double v); void add_open_speed(double v);
void clear_open_speed(); void clear_open_speed();
void set_auto(bool state);
void toggle_auto();
operator Json::Value() const; operator Json::Value() const;
constexpr double get_state() const { return state; } constexpr double get_state() const { return state; }
constexpr double get_flow() const { return flow; } constexpr double get_flow() const { return flow; }
constexpr double get_setpoint() const { return auto_th; }
constexpr bool get_auto() const { return auto_on; }
}; };
}; };

View File

@ -30,12 +30,35 @@ turbine::turbine(const Json::Value& node, coolant::condenser* condenser) :
sim::coolant::fluid_holder(node) sim::coolant::fluid_holder(node)
{ {
velocity = node["velocity"].asDouble(); velocity = node["velocity"].asDouble();
phase = node["phase"].asDouble();
breaker_closed = node["breaker_closed"].asBool();
} }
void turbine::update(double dt) void turbine::update(double dt)
{ {
double work = get_rpm() / 60 * dt * friction; double work = get_rpm() / 60 * dt * friction;
phase = std::fmod(phase + util::map( get_rpm(), 0, 60, 0, 2 * M_PI ) * dt, 2 * M_PI);
// do energy transfer stuff here
if(breaker_closed)
{
double r_diff = util::map(get_phase_diff(), -M_PI, M_PI, -30, 30);
double w = r_diff * 1e6;
double v2 = util::mod((velocity - 3600) / 60 + 30, 60) - 30;
double w2 = w * w * v2;
energy_generated = w2 * extra_mass;
work += w * dt;
}
else
{
energy_generated = 0;
}
velocity = std::max(velocity - work, 0.0); velocity = std::max(velocity - work, 0.0);
} }
double turbine::get_rpm() const double turbine::get_rpm() const
@ -43,6 +66,12 @@ double turbine::get_rpm() const
return velocity / (M_PI * extra_mass * 0.001 * diameter * diameter * 0.25); return velocity / (M_PI * extra_mass * 0.001 * diameter * diameter * 0.25);
} }
double turbine::get_phase_diff() const
{
double phase_g = std::fmod(system::active.clock * 60, 1) * 2 * M_PI;
return util::mod(phase - phase_g + M_PI, 2*M_PI) - M_PI;
}
void turbine::add_gas(double steam, double air, double t) void turbine::add_gas(double steam, double air, double t)
{ {
double joules = (steam + air) * fluid.jPg; double joules = (steam + air) * fluid.jPg;
@ -58,6 +87,8 @@ turbine::operator Json::Value() const
node["diameter"] = diameter; node["diameter"] = diameter;
node["velocity"] = velocity; node["velocity"] = velocity;
node["friction"] = friction; node["friction"] = friction;
node["breaker_closed"] = breaker_closed;
node["phase"] = phase;
return node; return node;
} }

View File

@ -15,10 +15,14 @@ class turbine : public sim::coolant::fluid_holder
const double diameter; const double diameter;
const double friction = 1; const double friction = 1;
double energy_generated = 0; // W
double velocity = 0; // m/s double velocity = 0; // m/s
double phase = 0;
public: public:
bool breaker_closed = false;
turbine(coolant::fluid_t type, coolant::condenser* condenser, double length, double diameter, double mass); turbine(coolant::fluid_t type, coolant::condenser* condenser, double length, double diameter, double mass);
turbine(const Json::Value& node, coolant::condenser* condenser); turbine(const Json::Value& node, coolant::condenser* condenser);
@ -44,6 +48,10 @@ public:
virtual double get_pressure() const { return condenser->get_pressure(); } // pascals virtual double get_pressure() const { return condenser->get_pressure(); } // pascals
virtual double get_gas_density() const { return condenser->get_gas_density(); } // g/L virtual double get_gas_density() const { return condenser->get_gas_density(); } // g/L
constexpr double get_energy_generated() const { return energy_generated; }
constexpr double get_phase() const { return phase; }
double get_phase_diff() const;
operator Json::Value() const; operator Json::Value() const;
}; };

View File

@ -21,8 +21,8 @@ void mesh::add(const mesh& o, glm::mat4 mat)
for(unsigned int i = 0; i < o.vertices.size(); i++) for(unsigned int i = 0; i < o.vertices.size(); i++)
{ {
arrays::vertex v = o.vertices[i]; arrays::vertex v = o.vertices[i];
v.normal = v.normal * mat3; v.normal = mat3 * v.normal;
v.pos = v.pos * mat; v.pos = mat * v.pos;
vertices.push_back(v); vertices.push_back(v);
} }

View File

@ -7,6 +7,7 @@
#include "../locations.hpp" #include "../locations.hpp"
#include "../input/focus.hpp" #include "../input/focus.hpp"
#include "../mesh/arrays.hpp" #include "../mesh/arrays.hpp"
#include "../mesh/texture.hpp"
#include "../../system.hpp" #include "../../system.hpp"
#include <glm/ext/matrix_transform.hpp> #include <glm/ext/matrix_transform.hpp>
@ -106,17 +107,24 @@ void core::init()
mesh1.model_matrix = locations::monitors[2]; mesh1.model_matrix = locations::monitors[2];
mesh1.colour_matrix = arrays::colour({1, 1, 1, 1}); mesh1.colour_matrix = arrays::colour({1, 1, 1, 1});
sim::graphics::mesh rmesh1, rmesh2; sim::graphics::mesh rmesh;
rmesh1.load_text("Reactor Core", 0.04);
rmesh2.load_model("../assets/model/", "reactor_core_interface_circle.stl");
rmesh1.add(rmesh2, glm::mat4(1));
rmesh.load_text("Reactor Core", 0.04);
mesh1.bind(); mesh1.bind();
mesh1.set(rmesh1, GL_STATIC_DRAW); mesh1.set(rmesh, GL_STATIC_DRAW);
rmesh2.load_model("../assets/model/", "reactor_core_interface_cell.stl");
unsigned int indices[] = {0, 1, 3, 0, 3, 2};
arrays::vertex vertices[] = {
{texture::handle_white, {0, 0}, {-0.75, -0.75, 0, 1}, {0, 0, -1}},
{texture::handle_white, {0, 1}, {-0.75, 0.75, 0, 1}, {0, 0, -1}},
{texture::handle_white, {1, 0}, { 0.75, -0.75, 0, 1}, {0, 0, -1}},
{texture::handle_white, {1, 1}, { 0.75, 0.75, 0, 1}, {0, 0, -1}},
};
rmesh.set_indices(indices, 6);
rmesh.set_vertices(vertices, 4);
mesh2.bind(); mesh2.bind();
mesh2.set(rmesh2, GL_STATIC_DRAW); mesh2.set(rmesh, GL_STATIC_DRAW);
m_buttons[0].load_model("../assets/model/", "reactor_core_button1.stl"); m_buttons[0].load_model("../assets/model/", "reactor_core_button1.stl");
m_buttons[1].load_model("../assets/model/", "reactor_core_button2.stl"); m_buttons[1].load_model("../assets/model/", "reactor_core_button2.stl");
@ -169,14 +177,17 @@ void core::render()
double sy = 0.5 - (sys.reactor->height - 1) * step / 2.0; double sy = 0.5 - (sys.reactor->height - 1) * step / 2.0;
glm::mat4 mat_scale = glm::scale(glm::mat4(1), glm::vec3(step * 0.4, step * 0.4, 1)); glm::mat4 mat_scale = glm::scale(glm::mat4(1), glm::vec3(step * 0.4, step * 0.4, 1));
glm::mat4 mat_select = glm::translate(glm::mat4(1), glm::vec3(-0.8, -0.8, -0.001)) * glm::scale(glm::mat4(1), glm::vec3(0.5, 0.5, 1)); glm::mat4 mat_select = glm::translate(glm::mat4(1), glm::vec3(-0.8, -0.8, -0.001)) * glm::scale(glm::mat4(1), glm::vec3(0.25, 0.25, 1));
glm::mat4 mat_cursor = glm::translate(glm::mat4(1), glm::vec3(-0.8, 0.8, -0.001)) * glm::scale(glm::mat4(1), glm::vec3(0.5, 0.5, 1)); glm::mat4 mat_cursor = glm::translate(glm::mat4(1), glm::vec3(-0.8, 0.8, -0.001)) * glm::scale(glm::mat4(1), glm::vec3(0.25, 0.25, 1));
glm::mat4 mat_spec = glm::translate(glm::mat4(1), glm::vec3(0.8, -0.8, -0.001)) * glm::scale(glm::mat4(1), glm::vec3(0.25, 0.25, 1));
mesh1.bind(); mesh1.bind();
mesh1.uniform(); mesh1.uniform();
mesh1.render(); mesh1.render();
mesh2.bind(); mesh2.bind();
// this renderer is disgusting
for(int i = 0; i < sys.reactor->size; i++) for(int i = 0; i < sys.reactor->size; i++)
{ {
int x = i % sys.reactor->width; int x = i % sys.reactor->width;
@ -185,9 +196,16 @@ void core::render()
double oy = sy + y * step; double oy = sy + y * step;
reactor::rod* r = sys.reactor->rods[i].get(); reactor::rod* r = sys.reactor->rods[i].get();
glm::vec4 colour = r->get_colour();
if(colour[3] == 0) if(!r->should_display())
{
continue;
}
glm::vec4 colour_heat = r->get_heat_colour() * glm::vec4(glm::vec3(1), 1);
glm::vec4 colour_spec = r->get_colour();
if(colour_heat[3] == 0)
{ {
continue; continue;
} }
@ -195,7 +213,7 @@ void core::render()
glm::mat4 mat = mesh1.model_matrix * glm::translate(glm::mat4(1), glm::vec3(ox, oy, 0)) * mat_scale; glm::mat4 mat = mesh1.model_matrix * glm::translate(glm::mat4(1), glm::vec3(ox, oy, 0)) * mat_scale;
mesh2.model_matrix = mat; mesh2.model_matrix = mat;
mesh2.colour_matrix = arrays::colour(colour); mesh2.colour_matrix = arrays::colour(colour_heat);
mesh2.uniform(); mesh2.uniform();
mesh2.render(); mesh2.render();
@ -214,6 +232,14 @@ void core::render()
mesh2.uniform(); mesh2.uniform();
mesh2.render(); mesh2.render();
} }
if(colour_spec[3] != 0)
{
mesh2.model_matrix = mat * mat_spec;
mesh2.colour_matrix = arrays::colour(colour_spec);
mesh2.uniform();
mesh2.render();
}
} }
} }

View File

@ -54,15 +54,6 @@ primary_loop::primary_loop()
} }
void primary_loop::toggle_primary_pump()
{
system& sys = sim::system::active;
bool state;
sys.primary_pump->powered = state = !sys.primary_pump->powered;
gm_switch_1.model_matrix = glm::translate(glm::mat4(1), glm::vec3(0, state ? 0.07 : 0, 0));
}
void primary_loop::init() void primary_loop::init()
{ {
mesh1.model_matrix = locations::monitors[3]; mesh1.model_matrix = locations::monitors[3];
@ -79,9 +70,9 @@ void primary_loop::init()
sim::graphics::mesh rmesh; sim::graphics::mesh rmesh;
ss << "Turbine Bypass Valve\n\n"; ss << "Turbine Bypass Valve\n\n";
ss << "Opened\nFlow\n\n"; ss << "Opened\nFlow\nSetpoint\n\n";
ss << "Turbine Inlet Valve\n\n"; ss << "Turbine Inlet Valve\n\n";
ss << "Opened\nFlow\n\n"; ss << "Opened\nFlow\nSetpoint\n\n";
ss << "Primary Pump\n\n"; ss << "Primary Pump\n\n";
ss << "Power\nSpeed\nFlow\n\n"; ss << "Power\nSpeed\nFlow\n\n";
ss << "Condenser\n\n"; ss << "Condenser\n\n";
@ -94,13 +85,23 @@ void primary_loop::init()
mesh1.bind(); mesh1.bind();
mesh1.set(rmesh, GL_STATIC_DRAW); mesh1.set(rmesh, GL_STATIC_DRAW);
rmesh.load_model("../assets/model", "pump_switch_1.glb"); rmesh.load_model("../assets/model", "pump_switch_1.fbx");
gm_switch_1.bind(); gm_switch_pump.bind();
gm_switch_1.set(rmesh, GL_STATIC_DRAW); gm_switch_pump.set(rmesh, GL_STATIC_DRAW);
rmesh.load_model("../assets/model", "turbine_valve_bypass_switch.fbx");
gm_switch_bypass.bind();
gm_switch_bypass.set(rmesh, GL_STATIC_DRAW);
rmesh.load_model("../assets/model", "turbine_valve_inlet_switch.fbx");
gm_switch_inlet.bind();
gm_switch_inlet.set(rmesh, GL_STATIC_DRAW);
m_joystick_turbine_bypass.load_model("../assets/model", "turbine_valve_bypass_joystick.stl"); m_joystick_turbine_bypass.load_model("../assets/model", "turbine_valve_bypass_joystick.stl");
m_joystick_turbine_inlet.load_model("../assets/model", "turbine_valve_inlet_joystick.stl"); m_joystick_turbine_inlet.load_model("../assets/model", "turbine_valve_inlet_joystick.stl");
m_switch_1.load_model("../assets/model", "pump_switch_click_1.stl"); m_switch_pump.load_model("../assets/model", "pump_switch_click_1.stl");
m_switch_bypass.load_model("../assets/model", "turbine_valve_bypass_switch_click.stl");
m_switch_inlet.load_model("../assets/model", "turbine_valve_inlet_switch_click.stl");
} }
void primary_loop::update(double dt) void primary_loop::update(double dt)
@ -117,9 +118,31 @@ void primary_loop::update(double dt)
ss << "\n\n"; ss << "\n\n";
ss << show( sys.turbine_bypass_valve->get_state() * 100 ) << " %\n"; ss << show( sys.turbine_bypass_valve->get_state() * 100 ) << " %\n";
ss << show( sys.turbine_bypass_valve->get_flow() / 1000 ) << " kg/s\n"; ss << show( sys.turbine_bypass_valve->get_flow() / 1000 ) << " kg/s\n";
if(sys.turbine_bypass_valve->get_auto())
{
ss << show( sys.turbine_bypass_valve->get_setpoint() ) << " C\n";
}
else
{
ss << "-\n";
}
ss << "\n\n\n"; ss << "\n\n\n";
ss << show( sys.turbine_inlet_valve->get_state() * 100 ) << " %\n"; ss << show( sys.turbine_inlet_valve->get_state() * 100 ) << " %\n";
ss << show( sys.turbine_inlet_valve->get_flow() / 1000 ) << " kg/s\n"; ss << show( sys.turbine_inlet_valve->get_flow() / 1000 ) << " kg/s\n";
if(sys.turbine_inlet_valve->get_auto())
{
ss << show( sys.turbine_inlet_valve->get_setpoint() ) << " C\n";
}
else
{
ss << "-\n";
}
ss << "\n\n\n"; ss << "\n\n\n";
ss << show( sys.primary_pump->get_power() * 100 ) << " %\n"; ss << show( sys.primary_pump->get_power() * 100 ) << " %\n";
ss << show( sys.primary_pump->get_rpm() ) << " r/min\n"; ss << show( sys.primary_pump->get_rpm() ) << " r/min\n";
@ -139,8 +162,16 @@ void primary_loop::update(double dt)
focus::set(std::make_unique<valve_joystick>(sys.turbine_bypass_valve.get())); focus::set(std::make_unique<valve_joystick>(sys.turbine_bypass_valve.get()));
if(m_joystick_turbine_inlet.check_focus()) if(m_joystick_turbine_inlet.check_focus())
focus::set(std::make_unique<valve_joystick>(sys.turbine_inlet_valve.get())); focus::set(std::make_unique<valve_joystick>(sys.turbine_inlet_valve.get()));
if(m_switch_1.check_focus()) if(m_switch_pump.check_focus())
toggle_primary_pump(); sys.primary_pump->powered = !sys.primary_pump->powered;
if(m_switch_inlet.check_focus())
sys.turbine_inlet_valve->toggle_auto();
if(m_switch_bypass.check_focus())
sys.turbine_bypass_valve->toggle_auto();
gm_switch_inlet.model_matrix = glm::translate(glm::mat4(1), glm::vec3(0, sys.turbine_inlet_valve->get_auto() ? 0.07 : 0, 0));
gm_switch_bypass.model_matrix = glm::translate(glm::mat4(1), glm::vec3(0, sys.turbine_bypass_valve->get_auto() ? 0.07 : 0, 0));
gm_switch_pump.model_matrix = glm::translate(glm::mat4(1), glm::vec3(0, sys.primary_pump->powered ? 0.07 : 0, 0));
} }
void primary_loop::render() void primary_loop::render()
@ -153,8 +184,16 @@ void primary_loop::render()
mesh2.uniform(); mesh2.uniform();
mesh2.render(); mesh2.render();
gm_switch_1.bind(); gm_switch_pump.bind();
gm_switch_1.uniform(); gm_switch_pump.uniform();
gm_switch_1.render(); gm_switch_pump.render();
gm_switch_inlet.bind();
gm_switch_inlet.uniform();
gm_switch_inlet.render();
gm_switch_bypass.bind();
gm_switch_bypass.uniform();
gm_switch_bypass.render();
} }

View File

@ -8,16 +8,19 @@ namespace sim::graphics::monitor
class primary_loop class primary_loop
{ {
sim::graphics::glmesh mesh1, mesh2; glmesh mesh1, mesh2;
double clock_at = 0, clock_now = 0; double clock_at = 0, clock_now = 0;
sim::graphics::glmesh gm_switch_1; glmesh gm_switch_pump;
glmesh gm_switch_bypass;
glmesh gm_switch_inlet;
sim::graphics::mesh m_joystick_turbine_bypass; mesh m_joystick_turbine_bypass;
sim::graphics::mesh m_joystick_turbine_inlet; mesh m_joystick_turbine_inlet;
sim::graphics::mesh m_switch_1;
void toggle_primary_pump(); mesh m_switch_pump;
mesh m_switch_bypass;
mesh m_switch_inlet;
public: public:

View File

@ -20,22 +20,6 @@ secondary_loop::secondary_loop()
} }
void secondary_loop::toggle_secondary_pump()
{
system& sys = sim::system::active;
bool state = false;
sys.secondary_pump->powered = state = !sys.secondary_pump->powered;
gm_switch_2.model_matrix = glm::translate(glm::mat4(1), glm::vec3(0, state ? 0.07 : 0, 0));
}
void secondary_loop::toggle_freight_pump()
{
system& sys = sim::system::active;
bool state = false;
sys.freight_pump->powered = state = !sys.freight_pump->powered;
gm_switch_3.model_matrix = glm::translate(glm::mat4(1), glm::vec3(0, state ? 0.07 : 0, 0));
}
void secondary_loop::init() void secondary_loop::init()
{ {
mesh1.model_matrix = locations::monitors[5]; mesh1.model_matrix = locations::monitors[5];
@ -62,11 +46,11 @@ void secondary_loop::init()
mesh1.bind(); mesh1.bind();
mesh1.set(rmesh, GL_STATIC_DRAW); mesh1.set(rmesh, GL_STATIC_DRAW);
rmesh.load_model("../assets/model", "pump_switch_2.glb"); rmesh.load_model("../assets/model", "pump_switch_2.fbx");
gm_switch_2.bind(); gm_switch_2.bind();
gm_switch_2.set(rmesh, GL_STATIC_DRAW); gm_switch_2.set(rmesh, GL_STATIC_DRAW);
rmesh.load_model("../assets/model", "pump_switch_3.glb"); rmesh.load_model("../assets/model", "pump_switch_3.fbx");
gm_switch_3.bind(); gm_switch_3.bind();
gm_switch_3.set(rmesh, GL_STATIC_DRAW); gm_switch_3.set(rmesh, GL_STATIC_DRAW);
@ -106,11 +90,13 @@ void secondary_loop::update(double dt)
mesh2.set(rmesh, GL_DYNAMIC_DRAW); mesh2.set(rmesh, GL_DYNAMIC_DRAW);
} }
if(m_switch_2.check_focus()) if(m_switch_2.check_focus())
toggle_secondary_pump(); sys.secondary_pump->powered = !sys.secondary_pump->powered;
if(m_switch_3.check_focus()) if(m_switch_3.check_focus())
toggle_freight_pump(); sys.freight_pump->powered = !sys.freight_pump->powered;
gm_switch_2.model_matrix = glm::translate(glm::mat4(1), glm::vec3(0, sys.secondary_pump->powered ? 0.07 : 0, 0));
gm_switch_3.model_matrix = glm::translate(glm::mat4(1), glm::vec3(0, sys.freight_pump->powered ? 0.07 : 0, 0));
} }
void secondary_loop::render() void secondary_loop::render()

View File

@ -19,9 +19,6 @@ class secondary_loop
sim::graphics::mesh m_switch_2; sim::graphics::mesh m_switch_2;
sim::graphics::mesh m_switch_3; sim::graphics::mesh m_switch_3;
void toggle_secondary_pump();
void toggle_freight_pump();
public: public:
secondary_loop(); secondary_loop();

View File

@ -22,9 +22,7 @@ turbine::turbine()
void turbine::init() void turbine::init()
{ {
mesh1.model_matrix = locations::monitors[4]; mesh1.model_matrix = mesh2.model_matrix = locations::monitors[4];
mesh2.model_matrix = glm::translate(mesh1.model_matrix, glm::vec3(0.5, 0, 0));
mesh1.colour_matrix = mesh2.colour_matrix = { mesh1.colour_matrix = mesh2.colour_matrix = {
1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0,
@ -33,14 +31,27 @@ void turbine::init()
}; };
std::stringstream ss; std::stringstream ss;
sim::graphics::mesh rmesh; sim::graphics::mesh rmesh, rmesh2;
ss << "Turbine\n\n"; ss << "Turbine\n\n";
ss << "Heat\nPressure\nSpeed\n\n"; ss << "Heat\nPressure\nSpeed\n\n";
rmesh.load_text(ss.str().c_str(), 0.04); rmesh.load_text(ss.str().c_str(), 0.04);
rmesh2.load_text("Synchroscope", 0.04);
rmesh.add(rmesh2, glm::translate(glm::mat4(1), glm::vec3(0, 0.6, 0)));
mesh1.bind(); mesh1.bind();
mesh1.set(rmesh, GL_STATIC_DRAW); mesh1.set(rmesh, GL_STATIC_DRAW);
rmesh.load_model("../assets/model", "synchroscope_dial.stl");
gm_synchroscope_dial.bind();
gm_synchroscope_dial.set(rmesh, GL_STATIC_DRAW);
rmesh.load_model("../assets/model", "turbine_breaker_switch.fbx");
gm_switch_breaker.bind();
gm_switch_breaker.set(rmesh, GL_STATIC_DRAW);
m_switch_breaker.load_model("../assets/model", "turbine_breaker_switch_click.stl");
} }
void turbine::update(double dt) void turbine::update(double dt)
@ -51,7 +62,7 @@ void turbine::update(double dt)
if(clock_at + 1.0/30.0 < clock_now) if(clock_at + 1.0/30.0 < clock_now)
{ {
std::stringstream ss; std::stringstream ss;
sim::graphics::mesh rmesh; sim::graphics::mesh rmesh, rmesh2;
clock_at += 1.0/30.0; clock_at += 1.0/30.0;
ss << "\n\n"; ss << "\n\n";
@ -59,10 +70,45 @@ void turbine::update(double dt)
ss << show( sys.turbine->get_pressure() / 1000 ) << " kPa\n"; ss << show( sys.turbine->get_pressure() / 1000 ) << " kPa\n";
ss << show( sys.turbine->get_rpm() ) << " r/min\n"; ss << show( sys.turbine->get_rpm() ) << " r/min\n";
rmesh.load_text(ss.str().c_str(), 0.04); rmesh2.load_text(ss.str().c_str(), 0.04);
rmesh.add(rmesh2, glm::translate(glm::mat4(1), glm::vec3(0.5, 0, 0)));
ss = std::stringstream();
ss << "Local\n\n";
ss << show( sys.turbine->get_rpm() / 60 ) << " Hz\n";
ss << show( sys.turbine->get_energy_generated() ) << " W\n";
rmesh2.load_text(ss.str().c_str(), 0.04);
rmesh.add(rmesh2, glm::translate(glm::mat4(1), glm::vec3(0.4, 0.7, 0)));
ss = std::stringstream();
ss << "Grid\n\n";
ss << show( 60 ) << " Hz\n";
rmesh2.load_text(ss.str().c_str(), 0.04);
rmesh.add(rmesh2, glm::translate(glm::mat4(1), glm::vec3(0.7, 0.7, 0)));
mesh2.bind(); mesh2.bind();
mesh2.set(rmesh, GL_DYNAMIC_DRAW); mesh2.set(rmesh, GL_DYNAMIC_DRAW);
} }
double rpm = sys.turbine->get_rpm();
if(rpm > 3570 && rpm < 3630)
{
glm::mat4 mat = glm::mat4(1);
mat = glm::translate(mat, glm::vec3(6.35, 3.949, 1.35));
mat = glm::rotate(mat, float(sys.turbine->get_phase_diff()), glm::vec3(0, 1, 0));
mat = glm::translate(mat, glm::vec3(-6.35, -3.949, -1.35));
gm_synchroscope_dial.model_matrix = mat;
}
if(m_switch_breaker.check_focus())
sys.turbine->breaker_closed = !sys.turbine->breaker_closed;
gm_switch_breaker.model_matrix = glm::translate(glm::mat4(1), glm::vec3(0, sys.turbine->breaker_closed ? 0.07 : 0, 0));
} }
void turbine::render() void turbine::render()
@ -74,5 +120,18 @@ void turbine::render()
mesh2.bind(); mesh2.bind();
mesh2.uniform(); mesh2.uniform();
mesh2.render(); mesh2.render();
double rpm = system::active.turbine->get_rpm();
if(rpm > 3570 && rpm < 3630)
{
gm_synchroscope_dial.bind();
gm_synchroscope_dial.uniform();
gm_synchroscope_dial.render();
}
gm_switch_breaker.bind();
gm_switch_breaker.uniform();
gm_switch_breaker.render();
} }

View File

@ -11,6 +11,10 @@ class turbine
sim::graphics::glmesh mesh1, mesh2; sim::graphics::glmesh mesh1, mesh2;
double clock_at = 0, clock_now = 0; double clock_at = 0, clock_now = 0;
sim::graphics::glmesh gm_synchroscope_dial;
sim::graphics::glmesh gm_switch_breaker;
sim::graphics::mesh m_switch_breaker;
public: public:
turbine(); turbine();

View File

@ -41,8 +41,8 @@ void vessel::init()
ss << "Level\n"; ss << "Level\n";
ss << "Void Ratio\n\n"; ss << "Void Ratio\n\n";
ss << "Reactor Core\n\n"; ss << "Reactor Core\n\n";
ss << "Energy Output\n";
ss << "Neutron Flux\n\n"; ss << "Neutron Flux\n\n";
// ss << "Increase Rate\n\n";
ss << "Temperature\nMin\nMax\n\n"; ss << "Temperature\nMin\nMax\n\n";
ss << "Control Rods\nMin\nMax\nSpeed\n"; ss << "Control Rods\nMin\nMax\nSpeed\n";
@ -98,8 +98,8 @@ void vessel::update(double dt)
ss << show( sys.vessel->get_pressure() * 0.001 ) << " kPa\n"; ss << show( sys.vessel->get_pressure() * 0.001 ) << " kPa\n";
ss << show( sys.vessel->get_level() / 1000 ) << " / " << show( sys.vessel->get_volume() / 1000 ) << " kL\n"; ss << show( sys.vessel->get_level() / 1000 ) << " / " << show( sys.vessel->get_volume() / 1000 ) << " kL\n";
ss << show( sys.vessel->get_void_ratio() * 100 ) << " %\n\n\n\n"; ss << show( sys.vessel->get_void_ratio() * 100 ) << " %\n\n\n\n";
ss << show( sys.reactor->get_energy_output() * 0.001 ) << " kW\n";
ss << show( sys.reactor->get_flux() ) << " n/cm2/s\n\n\n"; ss << show( sys.reactor->get_flux() ) << " n/cm2/s\n\n\n";
// ss << show( sys.reactor->flux_rate * 100 ) << " %/s\n\n\n";
ss << show( temp_min ) << " C\n"; ss << show( temp_min ) << " C\n";
ss << show( temp_max ) << " C\n\n\n"; ss << show( temp_max ) << " C\n\n\n";
ss << show( 100 - crod_max * 100 ) << " %\n"; ss << show( 100 - crod_max * 100 ) << " %\n";

View File

@ -109,9 +109,12 @@ void window::create()
shader::init_program(); shader::init_program();
sim::system& sys = sim::system::active; sim::system& sys = sim::system::active;
mesh m; mesh m, m2;
m.load_model("../assets", "scene-baked.glb"); m.load_model("../assets", "scene-baked.glb");
m2.load_model("../assets/model", "monitor_graphics.stl");
m.add(m2, glm::mat4(1));
mesh_scene.bind(); mesh_scene.bind();
mesh_scene.set(m, GL_STATIC_DRAW); mesh_scene.set(m, GL_STATIC_DRAW);

View File

@ -45,49 +45,6 @@ double fuel_rod::get_energy_output() const
return s.get_energy() * mol * energy_density; return s.get_energy() * mol * energy_density;
} }
static float map(float v, float imin, float imax, float omin, float omax)
{
return (v - imin) * (omax - omin) / (imax - imin) + omin;
}
glm::vec4 fuel_rod::get_colour() const
{
double temp = vals[val_t::HEAT];
if(temp < 0)
{
temp = 0;
}
// this should not happen
if(std::isnan(temp))
{
return {1, 0, 1, 1};
}
if(temp < 120)
{
return {0, map(temp, 0, 120, 0, 1), 1, 1};
}
if(temp < 240)
{
return {0, 1, map(temp, 120, 240, 1, 0), 1};
}
if(temp < 280)
{
return {map(temp, 240, 280, 0, 1), 1, 0, 1};
}
if(temp < 320)
{
return {1, map(temp, 280, 320, 1, 0), 0, 1};
}
return {1, 0, 0, 1};
}
void fuel_rod::update(double secs) void fuel_rod::update(double secs)
{ {
update_rod(secs); update_rod(secs);

View File

@ -18,7 +18,6 @@ class fuel_rod : public sim::reactor::rod
virtual const char* get_name() const { return "Fuel"; } virtual const char* get_name() const { return "Fuel"; }
virtual int get_id() const { return 1; } virtual int get_id() const { return 1; }
virtual double get_energy_output() const; virtual double get_energy_output() const;
virtual glm::vec4 get_colour() const;
public: public:

View File

@ -74,6 +74,7 @@ void reactor::update(double secs)
{ {
int rods_lookup[size]; int rods_lookup[size];
double temp_min, temp_max; double temp_min, temp_max;
double flux_initial = get_flux();
get_stats(rod::val_t::HEAT, temp_min, temp_max); get_stats(rod::val_t::HEAT, temp_min, temp_max);
@ -103,6 +104,11 @@ void reactor::update(double secs)
{ {
update_selected(secs); update_selected(secs);
} }
if(flux_initial > 0)
{
flux_rate = (get_flux() - flux_initial) / flux_initial / secs;
}
} }
void reactor::update_selected(double dt) void reactor::update_selected(double dt)
@ -243,9 +249,9 @@ void reactor::get_stats(rod::val_t type, double& min, double& max)
reactor::reactor(const Json::Value& node, coolant::vessel* v) : reactor::reactor(const Json::Value& node, coolant::vessel* v) :
cell_width(node["cell_width"].asDouble()), cell_width(node["cell_width"].asDouble()),
cell_height(node["cell_height"].asDouble()), cell_height(node["cell_height"].asDouble()),
width(node["width"].asDouble()), width(node["width"].asInt()),
height(node["height"].asDouble()), height(node["height"].asInt()),
size(node["size"].asDouble()) size(node["size"].asInt())
{ {
const Json::Value& j_rods = node["rods"]; const Json::Value& j_rods = node["rods"];

View File

@ -21,6 +21,8 @@ struct reactor
const int size; const int size;
std::vector<std::unique_ptr<rod>> rods; std::vector<std::unique_ptr<rod>> rods;
double flux_rate = 0;
double rod_speed = 0; double rod_speed = 0;
int cursor; int cursor;

View File

@ -1,6 +1,7 @@
#include "rod.hpp" #include "rod.hpp"
#include "reactor.hpp" #include "reactor.hpp"
#include "../util/math.hpp"
#include <cmath> #include <cmath>
@ -51,6 +52,44 @@ void rod::interact(rod* o, double secs)
} }
} }
glm::vec4 rod::get_heat_colour() const
{
double temp = vals[val_t::HEAT];
if(temp < 0)
{
temp = 0;
}
// this should not happen
if(std::isnan(temp))
{
return {1, 0, 1, 1};
}
if(temp < 120)
{
return {0, util::map(temp, 0, 120, 0, 1), 1, 1};
}
if(temp < 240)
{
return {0, 1, util::map(temp, 120, 240, 1, 0), 1};
}
if(temp < 280)
{
return {util::map(temp, 240, 280, 0, 1), 1, 0, 1};
}
if(temp < 320)
{
return {1, util::map(temp, 280, 320, 1, 0), 0, 1};
}
return {1, 0, 0, 1};
}
double rod::get_flux() const double rod::get_flux() const
{ {
return (vals_n[val_t::N_FAST] + vals_n[val_t::N_SLOW]) * N_a / (get_side_area() * 10000) / 4; return (vals_n[val_t::N_FAST] + vals_n[val_t::N_SLOW]) * N_a / (get_side_area() * 10000) / 4;

View File

@ -35,10 +35,12 @@ public:
virtual double extract(val_t type, double s, double k, double o); virtual double extract(val_t type, double s, double k, double o);
virtual double get(val_t type) const; virtual double get(val_t type) const;
virtual std::unique_ptr<rod> clone() const { return std::make_unique<rod>(*this); } virtual std::unique_ptr<rod> clone() const { return std::make_unique<rod>(*this); }
virtual glm::vec4 get_colour() const { return {0, 0, 0, 0}; }
virtual double get_energy_output() const { return 0; } virtual double get_energy_output() const { return 0; }
virtual int get_id() const { return 0; } virtual int get_id() const { return 0; }
virtual glm::vec4 get_colour() const { return {0, 0, 0, 0}; }
glm::vec4 get_heat_colour() const;
virtual bool has_sensors(val_t t) const { return false; } virtual bool has_sensors(val_t t) const { return false; }
virtual bool should_display() const { return false; } virtual bool should_display() const { return false; }
virtual bool should_select() const { return false; } virtual bool should_select() const { return false; }

View File

@ -34,5 +34,23 @@ constexpr double calc_work(double j, double mass)
return m * std::sqrt(m * j / (mass * 0.001)); return m * std::sqrt(m * j / (mass * 0.001));
} }
constexpr float map(float v, float imin, float imax, float omin, float omax)
{
return (v - imin) * (omax - omin) / (imax - imin) + omin;
}
template<typename A, typename B>
constexpr A mod(A a, B b)
{
A v = std::fmod(a, b);
if(v < 0)
{
v += b;
}
return v;
}
}; };