got something rendering
This commit is contained in:
parent
714300930f
commit
480852ff76
|
@ -3,10 +3,10 @@ cmake_minimum_required(VERSION 3.25)
|
||||||
project(FastNuclearSim VERSION 1.0)
|
project(FastNuclearSim VERSION 1.0)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
set(CMAKE_CXX_FLAGS "-g -lncurses")
|
set(CMAKE_CXX_FLAGS "-g -lncurses -I/usr/include/freetype2")
|
||||||
|
|
||||||
file(GLOB_RECURSE SOURCES src/*.cpp)
|
file(GLOB_RECURSE SOURCES src/*.cpp)
|
||||||
|
|
||||||
add_executable(FastNuclearSim ${SOURCES})
|
add_executable(FastNuclearSim ${SOURCES})
|
||||||
target_link_libraries(FastNuclearSim PUBLIC stdc++ m)
|
target_link_libraries(FastNuclearSim PUBLIC stdc++ m GLEW glfw GL freetype)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
#include "arrays.hpp"
|
||||||
|
#include "font.hpp"
|
||||||
|
|
||||||
|
using namespace sim::graphics;
|
||||||
|
|
||||||
|
static unsigned int vao, vbo, ebo;
|
||||||
|
|
||||||
|
static void* ptr_diff(void* a, void* b)
|
||||||
|
{
|
||||||
|
return (void*)((size_t)a - (size_t)b);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int arrays::init()
|
||||||
|
{
|
||||||
|
vertex v;
|
||||||
|
unsigned long handle = font::chars['*'].handle;
|
||||||
|
|
||||||
|
arrays::vertex vertices[4] = {
|
||||||
|
{handle, {0.0f, 1.0f}, {-0.5f, -0.5f, 0.0f}},
|
||||||
|
{handle, {0.0f, 0.0f}, {-0.5f, 0.5f, 0.0f}},
|
||||||
|
{handle, {1.0f, 1.0f}, { 0.5f, -0.5f, 0.0f}},
|
||||||
|
{handle, {1.0f, 0.0f}, { 0.5f, 0.5f, 0.0f}}
|
||||||
|
};
|
||||||
|
|
||||||
|
int indices[6] = {
|
||||||
|
0, 1, 3, 0, 2, 3
|
||||||
|
};
|
||||||
|
|
||||||
|
glGenVertexArrays(1, &vao);
|
||||||
|
glBindVertexArray(vao);
|
||||||
|
|
||||||
|
glGenBuffers(1, &vbo);
|
||||||
|
glGenBuffers(1, &ebo);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glVertexAttribLPointer(0, 1, GL_UNSIGNED_INT64_ARB, sizeof(v), ptr_diff(&v.texid, &v));
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
|
||||||
|
glVertexAttribPointer(1, 2, GL_FLOAT, false, sizeof(v), ptr_diff(&v.texpos, &v));
|
||||||
|
glEnableVertexAttribArray(1);
|
||||||
|
|
||||||
|
glVertexAttribPointer(2, 3, GL_FLOAT, false, sizeof(v), ptr_diff(&v.pos, &v));
|
||||||
|
glEnableVertexAttribArray(2);
|
||||||
|
|
||||||
|
return vao;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <glm/vec2.hpp>
|
||||||
|
#include <glm/vec3.hpp>
|
||||||
|
|
||||||
|
namespace sim::graphics::arrays
|
||||||
|
{
|
||||||
|
|
||||||
|
struct vertex
|
||||||
|
{
|
||||||
|
unsigned long texid;
|
||||||
|
glm::vec2 texpos;
|
||||||
|
glm::vec3 pos;
|
||||||
|
};
|
||||||
|
|
||||||
|
unsigned int init();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
#include <ft2build.h>
|
||||||
|
#include FT_FREETYPE_H
|
||||||
|
|
||||||
|
#include <glm/vec2.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "font.hpp"
|
||||||
|
|
||||||
|
using namespace sim::graphics;
|
||||||
|
|
||||||
|
font::character font::chars[128];
|
||||||
|
|
||||||
|
void font::init()
|
||||||
|
{
|
||||||
|
FT_Library ft;
|
||||||
|
FT_Face face;
|
||||||
|
|
||||||
|
if(FT_Init_FreeType(&ft))
|
||||||
|
{
|
||||||
|
std::cout << "Error: failed to init freetype\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(FT_New_Face(ft, "/usr/share/fonts/noto/NotoSans-Regular.ttf", 0, &face))
|
||||||
|
{
|
||||||
|
std::cout << "Error: failed to load freetype font\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FT_Set_Pixel_Sizes(face, 0, 1024);
|
||||||
|
|
||||||
|
GLuint texids[128];
|
||||||
|
|
||||||
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
|
|
||||||
|
for(int i = 0; i < 128; i++)
|
||||||
|
{
|
||||||
|
if(FT_Load_Char(face, (char)i, FT_LOAD_RENDER))
|
||||||
|
{
|
||||||
|
std::cout << "Error: failed to load glyph " << i << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
character& c = chars[i];
|
||||||
|
c.advance = face->glyph->advance.x;
|
||||||
|
c.size = {face->glyph->bitmap.width, face->glyph->bitmap.rows};
|
||||||
|
c.bearing = {face->glyph->bitmap_left, face->glyph->bitmap_top};
|
||||||
|
|
||||||
|
if(c.size.x == 0 || c.size.y == 0)
|
||||||
|
{
|
||||||
|
c.handle = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
glCreateTextures(GL_TEXTURE_2D, 1, &texids[i]);
|
||||||
|
glTextureStorage2D(texids[i], 1, GL_R8, c.size.x, c.size.y);
|
||||||
|
glTextureSubImage2D(texids[i], 0, 0, 0, c.size.x, c.size.y, GL_RED, GL_UNSIGNED_BYTE, face->glyph->bitmap.buffer);
|
||||||
|
|
||||||
|
glTextureParameteri(texids[i], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
|
glTextureParameteri(texids[i], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
glTextureParameteri(texids[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTextureParameteri(texids[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
|
||||||
|
c.handle = glGetTextureHandleARB(texids[i]);
|
||||||
|
glMakeTextureHandleResidentARB(c.handle);
|
||||||
|
|
||||||
|
chars[i] = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace sim::graphics::font
|
||||||
|
{
|
||||||
|
|
||||||
|
struct character
|
||||||
|
{
|
||||||
|
unsigned long handle;
|
||||||
|
long advance;
|
||||||
|
glm::ivec2 size;
|
||||||
|
glm::ivec2 bearing;
|
||||||
|
};
|
||||||
|
|
||||||
|
void init();
|
||||||
|
|
||||||
|
extern character chars[128];
|
||||||
|
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
#include "keyboard.hpp"
|
||||||
|
#include "window.hpp"
|
||||||
|
#include "resize.hpp"
|
||||||
|
|
||||||
|
using namespace sim::graphics;
|
||||||
|
|
||||||
|
static void cb_keypress(GLFWwindow* win, int key, int sc, int action, int mods)
|
||||||
|
{
|
||||||
|
if(key == GLFW_KEY_F11 && action == GLFW_RELEASE)
|
||||||
|
{
|
||||||
|
resize::toggle_fullscreen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void keyboard::init()
|
||||||
|
{
|
||||||
|
GLFWwindow* win = window::get_window();
|
||||||
|
glfwSetKeyCallback(win, cb_keypress);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace sim::graphics::keyboard
|
||||||
|
{
|
||||||
|
|
||||||
|
void init();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
#include "resize.hpp"
|
||||||
|
#include "window.hpp"
|
||||||
|
|
||||||
|
using namespace sim::graphics;
|
||||||
|
|
||||||
|
static bool is_fullscreen = false;
|
||||||
|
|
||||||
|
static int win_w = 800;
|
||||||
|
static int win_h = 600;
|
||||||
|
|
||||||
|
static int win_restore_w;
|
||||||
|
static int win_restore_h;
|
||||||
|
static int win_restore_x;
|
||||||
|
static int win_restore_y;
|
||||||
|
|
||||||
|
void resize::toggle_fullscreen()
|
||||||
|
{
|
||||||
|
GLFWwindow* win = window::get_window();
|
||||||
|
is_fullscreen = !is_fullscreen;
|
||||||
|
|
||||||
|
if(is_fullscreen)
|
||||||
|
{
|
||||||
|
win_restore_w = win_w;
|
||||||
|
win_restore_h = win_h;
|
||||||
|
|
||||||
|
glfwGetWindowPos(win, &win_restore_x, &win_restore_y);
|
||||||
|
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
|
||||||
|
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
|
||||||
|
glfwSetWindowMonitor(win, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
{
|
||||||
|
glfwSetWindowMonitor(win, nullptr, win_restore_x, win_restore_y, win_restore_w, win_restore_h, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cb_framebuffer_size(GLFWwindow* win, int w, int h)
|
||||||
|
{
|
||||||
|
win_w = w;
|
||||||
|
win_h = h;
|
||||||
|
glViewport(0, 0, w, h);
|
||||||
|
}
|
||||||
|
|
||||||
|
void resize::init()
|
||||||
|
{
|
||||||
|
GLFWwindow* win = window::get_window();
|
||||||
|
glfwSetFramebufferSizeCallback(win, cb_framebuffer_size);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace sim::graphics::resize
|
||||||
|
{
|
||||||
|
|
||||||
|
void init();
|
||||||
|
void toggle_fullscreen();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "shader.hpp"
|
||||||
|
#include "window.hpp"
|
||||||
|
|
||||||
|
using namespace sim::graphics;
|
||||||
|
|
||||||
|
static const char* VERTEX_SHADER = R"(
|
||||||
|
#version 460 core
|
||||||
|
#extension GL_ARB_bindless_texture : require
|
||||||
|
|
||||||
|
layout (location = 0) in sampler2D aTex;
|
||||||
|
layout (location = 1) in vec2 aTexPos;
|
||||||
|
layout (location = 2) in vec3 aPos;
|
||||||
|
|
||||||
|
out flat sampler2D tex;
|
||||||
|
out vec2 texPos;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
gl_Position = vec4(aPos, 1.0);
|
||||||
|
texPos = aTexPos;
|
||||||
|
tex = aTex;
|
||||||
|
}
|
||||||
|
|
||||||
|
)";
|
||||||
|
|
||||||
|
static const char* FRAGMENT_SHADER = R"(
|
||||||
|
#version 460 core
|
||||||
|
#extension GL_ARB_bindless_texture : require
|
||||||
|
|
||||||
|
in flat sampler2D tex;
|
||||||
|
in vec2 texPos;
|
||||||
|
|
||||||
|
out vec4 FragColour;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
FragColour = vec4(1) * texture2D(tex, texPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
)";
|
||||||
|
|
||||||
|
static unsigned int prog_id;
|
||||||
|
|
||||||
|
static int load_shader(const char** src, int type)
|
||||||
|
{
|
||||||
|
int id = glCreateShader(type);
|
||||||
|
|
||||||
|
glShaderSource(id, 1, src, nullptr);
|
||||||
|
glCompileShader(id);
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int shader::init_program()
|
||||||
|
{
|
||||||
|
int success;
|
||||||
|
int vsh_id = load_shader(&VERTEX_SHADER, GL_VERTEX_SHADER);
|
||||||
|
int fsh_id = load_shader(&FRAGMENT_SHADER, GL_FRAGMENT_SHADER);
|
||||||
|
prog_id = glCreateProgram();
|
||||||
|
|
||||||
|
glAttachShader(prog_id, vsh_id);
|
||||||
|
glAttachShader(prog_id, fsh_id);
|
||||||
|
glLinkProgram(prog_id);
|
||||||
|
glGetProgramiv(prog_id, GL_LINK_STATUS, &success);
|
||||||
|
|
||||||
|
if(!success)
|
||||||
|
{
|
||||||
|
char infoLog[512];
|
||||||
|
glGetProgramInfoLog(prog_id, 512, NULL, infoLog);
|
||||||
|
std::cout << "Shader Link Error: " << infoLog << std::endl;
|
||||||
|
window::close();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
glUseProgram(prog_id);
|
||||||
|
glDeleteShader(vsh_id);
|
||||||
|
glDeleteShader(fsh_id);
|
||||||
|
|
||||||
|
return prog_id;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace sim::graphics::shader
|
||||||
|
{
|
||||||
|
|
||||||
|
unsigned int init_program();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "arrays.hpp"
|
||||||
|
#include "keyboard.hpp"
|
||||||
|
#include "resize.hpp"
|
||||||
|
#include "window.hpp"
|
||||||
|
#include "shader.hpp"
|
||||||
|
#include "font.hpp"
|
||||||
|
|
||||||
|
using namespace sim::graphics;
|
||||||
|
|
||||||
|
static GLFWwindow* win;
|
||||||
|
static bool win_should_close = false;
|
||||||
|
|
||||||
|
void GLAPIENTRY cb_debug_message(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam)
|
||||||
|
{
|
||||||
|
std::cout << "GL CALLBACK: " << message << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
void window::create()
|
||||||
|
{
|
||||||
|
glfwInit();
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
|
||||||
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
|
||||||
|
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||||
|
// glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, true);
|
||||||
|
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, true);
|
||||||
|
|
||||||
|
win = glfwCreateWindow(800, 600, "FastNuclearSim", nullptr, nullptr);
|
||||||
|
|
||||||
|
glfwMakeContextCurrent(win);
|
||||||
|
|
||||||
|
GLenum err = glewInit();
|
||||||
|
|
||||||
|
if(err != GLEW_OK)
|
||||||
|
{
|
||||||
|
std::cout << "GLEW Init Failed: " << glewGetErrorString(err) << "\n";
|
||||||
|
close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
glEnable(GL_DEBUG_OUTPUT);
|
||||||
|
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
|
||||||
|
glDebugMessageCallback(cb_debug_message, nullptr);
|
||||||
|
|
||||||
|
keyboard::init();
|
||||||
|
resize::init();
|
||||||
|
font::init();
|
||||||
|
|
||||||
|
shader::init_program();
|
||||||
|
arrays::init();
|
||||||
|
|
||||||
|
glViewport(0, 0, 800, 600);
|
||||||
|
}
|
||||||
|
|
||||||
|
void window::loop()
|
||||||
|
{
|
||||||
|
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
|
||||||
|
|
||||||
|
glfwSwapBuffers(win);
|
||||||
|
glfwPollEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool window::should_close()
|
||||||
|
{
|
||||||
|
return win_should_close || glfwWindowShouldClose(win);
|
||||||
|
}
|
||||||
|
|
||||||
|
void window::close()
|
||||||
|
{
|
||||||
|
win_should_close = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void window::destroy()
|
||||||
|
{
|
||||||
|
glfwTerminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWwindow* window::get_window()
|
||||||
|
{
|
||||||
|
return win;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <GLFW/glfw3.h>
|
||||||
|
|
||||||
|
namespace sim::graphics::window
|
||||||
|
{
|
||||||
|
|
||||||
|
void create();
|
||||||
|
bool should_close();
|
||||||
|
void loop();
|
||||||
|
void destroy();
|
||||||
|
void close();
|
||||||
|
|
||||||
|
GLFWwindow* get_window();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
213
src/main.cpp
213
src/main.cpp
|
@ -1,216 +1,17 @@
|
||||||
|
|
||||||
#include "reactor/builder.hpp"
|
#include "graphics/window.hpp"
|
||||||
#include "reactor/control/control_rod.hpp"
|
|
||||||
#include "reactor/fuel/fuel_rod.hpp"
|
|
||||||
#include "reactor/coolant/pipe.hpp"
|
|
||||||
#include "reactor/coolant/heater.hpp"
|
|
||||||
#include "reactor/coolant/vessel.hpp"
|
|
||||||
#include "coolant/fluid_t.hpp"
|
|
||||||
#include "coolant/valve.hpp"
|
|
||||||
#include "coolant/pump.hpp"
|
|
||||||
#include "display.hpp"
|
|
||||||
|
|
||||||
#include <cmath>
|
using namespace sim;
|
||||||
#include <sstream>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <curses.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
|
|
||||||
const bool do_graphics = true;
|
|
||||||
const bool do_clock = true;
|
|
||||||
|
|
||||||
unsigned long get_now()
|
|
||||||
{
|
|
||||||
struct timeval tv;
|
|
||||||
gettimeofday(&tv, nullptr);
|
|
||||||
return (unsigned long)tv.tv_sec * 1000000 + tv.tv_usec;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
std::random_device rd;
|
graphics::window::create();
|
||||||
std::mt19937 rand(rd());
|
|
||||||
|
while(!graphics::window::should_close())
|
||||||
if(do_graphics)
|
|
||||||
{
|
{
|
||||||
initscr();
|
graphics::window::loop();
|
||||||
cbreak();
|
|
||||||
noecho();
|
|
||||||
keypad(stdscr, TRUE);
|
|
||||||
nodelay(stdscr, TRUE);
|
|
||||||
curs_set(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
sim::reactor::coolant::vessel vessel(200, 400, sim::coolant::WATER);
|
|
||||||
sim::reactor::reactor<5, 5> reactor = sim::reactor::builder<5, 5>(
|
|
||||||
sim::reactor::fuel::fuel_rod(2000, 4000),
|
|
||||||
sim::reactor::control::control_rod(vessel, 10000, 1),
|
|
||||||
sim::reactor::coolant::pipe(vessel), {
|
|
||||||
"#C#C#",
|
|
||||||
"CFCFC",
|
|
||||||
"#C#C#",
|
|
||||||
"CFCFC",
|
|
||||||
"#C#C#"
|
|
||||||
});
|
|
||||||
|
|
||||||
sim::coolant::valve<sim::reactor::coolant::vessel> valve(vessel, 1, 500);
|
|
||||||
sim::coolant::pump<sim::reactor::coolant::vessel> pump(vessel, 1e4, 15);
|
|
||||||
|
|
||||||
double secs = 0;
|
|
||||||
long clock = get_now();
|
|
||||||
double speed = 1;
|
|
||||||
int framerate = 100;
|
|
||||||
int steps_extra = 1;
|
|
||||||
|
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << "Reactor Core\n\n";
|
|
||||||
|
|
||||||
{
|
|
||||||
long mins = secs / 60;
|
|
||||||
long hours = mins / 60;
|
|
||||||
long days = hours / 24;
|
|
||||||
long years = days / 365;
|
|
||||||
double s = fmod(secs, 60);
|
|
||||||
|
|
||||||
mins %= 60;
|
|
||||||
hours %= 24;
|
|
||||||
days %= 365;
|
|
||||||
|
|
||||||
ss << "Time:\n";
|
|
||||||
|
|
||||||
if(years > 0) goto years;
|
|
||||||
if(days > 0) goto days;
|
|
||||||
if(hours > 0) goto hours;
|
|
||||||
if(mins > 0) goto mins;
|
|
||||||
goto secs;
|
|
||||||
|
|
||||||
years: ss << years << "y ";
|
|
||||||
days: ss << days << "d ";
|
|
||||||
hours: ss << hours << "h ";
|
|
||||||
mins: ss << mins << "m ";
|
|
||||||
secs: ss << s << "s\n";
|
|
||||||
|
|
||||||
ss << "Speed: " << speed << "x\n\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i = 0; i < steps_extra; i++)
|
|
||||||
{
|
|
||||||
double dt = speed / framerate / steps_extra;
|
|
||||||
reactor.update(rand, dt);
|
|
||||||
pump.update(dt);
|
|
||||||
valve.update(dt);
|
|
||||||
vessel.update();
|
|
||||||
secs += dt;
|
|
||||||
}
|
|
||||||
|
|
||||||
ss << "Vessel\n" << vessel << "\n";
|
|
||||||
ss << "Steam Valve\n" << valve << "\n";
|
|
||||||
ss << "Coolant Pump\n" << pump << "\n";
|
|
||||||
|
|
||||||
if(do_graphics)
|
|
||||||
{
|
|
||||||
erase();
|
|
||||||
display::draw_text(1, 0, ss.str().c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
const int X = 1, Y = 30;
|
|
||||||
const int W = 36, H = 11;
|
|
||||||
|
|
||||||
for(int x = 0; x < reactor.width; x++)
|
|
||||||
for(int y = 0; y < reactor.height; y++)
|
|
||||||
{
|
|
||||||
int id = y * reactor.width + x;
|
|
||||||
sim::reactor::rod* r = reactor.rods[id];
|
|
||||||
|
|
||||||
if(!r->should_display())
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << *r;
|
|
||||||
|
|
||||||
int px = X + (H - 1) * y;
|
|
||||||
int py = Y + (W - 1) * x;
|
|
||||||
|
|
||||||
if(do_graphics)
|
|
||||||
{
|
|
||||||
display::draw_text(px + 1, py + 2, ss.str().c_str());
|
|
||||||
display::draw_box(px, py, H, W);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(do_graphics && r->should_select() && id == reactor.cursor)
|
|
||||||
{
|
|
||||||
display::draw_text(px + 1, py + W - 5, "[ ]");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(do_graphics && r->is_selected())
|
|
||||||
{
|
|
||||||
display::draw_text(px + 1, py + W - 4, "#");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int c = 0;
|
|
||||||
|
|
||||||
if(do_graphics)
|
|
||||||
{
|
|
||||||
refresh();
|
|
||||||
c = getch();
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(c)
|
|
||||||
{
|
|
||||||
case KEY_LEFT:
|
|
||||||
reactor.move_cursor(-1);
|
|
||||||
break;
|
|
||||||
case KEY_RIGHT:
|
|
||||||
reactor.move_cursor(1);
|
|
||||||
break;
|
|
||||||
case KEY_UP:
|
|
||||||
reactor.update_selected(1);
|
|
||||||
break;
|
|
||||||
case KEY_DOWN:
|
|
||||||
reactor.update_selected(-1);
|
|
||||||
break;
|
|
||||||
case ' ':
|
|
||||||
reactor.toggle_selected();
|
|
||||||
break;
|
|
||||||
case 't':
|
|
||||||
speed *= 10;
|
|
||||||
break;
|
|
||||||
case 'g':
|
|
||||||
speed /= 10;
|
|
||||||
break;
|
|
||||||
case 'r':
|
|
||||||
valve.open(0.001);
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
valve.open(-0.001);
|
|
||||||
break;
|
|
||||||
case 'e':
|
|
||||||
pump.change_speed(0.01);
|
|
||||||
break;
|
|
||||||
case 'd':
|
|
||||||
pump.change_speed(-0.01);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(do_clock)
|
|
||||||
{
|
|
||||||
long now = get_now();
|
|
||||||
|
|
||||||
while(clock + 1e6 / framerate > now)
|
|
||||||
{
|
|
||||||
usleep(clock + 1e6 / framerate - now);
|
|
||||||
now = get_now();
|
|
||||||
}
|
|
||||||
|
|
||||||
clock += 1e6 / framerate;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
graphics::window::destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,216 @@
|
||||||
|
|
||||||
|
#include "reactor/builder.hpp"
|
||||||
|
#include "reactor/control/control_rod.hpp"
|
||||||
|
#include "reactor/fuel/fuel_rod.hpp"
|
||||||
|
#include "reactor/coolant/pipe.hpp"
|
||||||
|
#include "reactor/coolant/heater.hpp"
|
||||||
|
#include "reactor/coolant/vessel.hpp"
|
||||||
|
#include "coolant/fluid_t.hpp"
|
||||||
|
#include "coolant/valve.hpp"
|
||||||
|
#include "coolant/pump.hpp"
|
||||||
|
#include "display.hpp"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
#include <sstream>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <curses.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
const bool do_graphics = true;
|
||||||
|
const bool do_clock = true;
|
||||||
|
|
||||||
|
unsigned long get_now()
|
||||||
|
{
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv, nullptr);
|
||||||
|
return (unsigned long)tv.tv_sec * 1000000 + tv.tv_usec;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::random_device rd;
|
||||||
|
std::mt19937 rand(rd());
|
||||||
|
|
||||||
|
if(do_graphics)
|
||||||
|
{
|
||||||
|
initscr();
|
||||||
|
cbreak();
|
||||||
|
noecho();
|
||||||
|
keypad(stdscr, TRUE);
|
||||||
|
nodelay(stdscr, TRUE);
|
||||||
|
curs_set(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
sim::reactor::coolant::vessel vessel(200, 400, sim::coolant::WATER);
|
||||||
|
sim::reactor::reactor<5, 5> reactor = sim::reactor::builder<5, 5>(
|
||||||
|
sim::reactor::fuel::fuel_rod(2000, 4000),
|
||||||
|
sim::reactor::control::control_rod(vessel, 10000, 1),
|
||||||
|
sim::reactor::coolant::pipe(vessel), {
|
||||||
|
"#C#C#",
|
||||||
|
"CFCFC",
|
||||||
|
"#C#C#",
|
||||||
|
"CFCFC",
|
||||||
|
"#C#C#"
|
||||||
|
});
|
||||||
|
|
||||||
|
sim::coolant::valve<sim::reactor::coolant::vessel> valve(vessel, 1, 500);
|
||||||
|
sim::coolant::pump<sim::reactor::coolant::vessel> pump(vessel, 1e4, 15);
|
||||||
|
|
||||||
|
double secs = 0;
|
||||||
|
long clock = get_now();
|
||||||
|
double speed = 1;
|
||||||
|
int framerate = 100;
|
||||||
|
int steps_extra = 1;
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "Reactor Core\n\n";
|
||||||
|
|
||||||
|
{
|
||||||
|
long mins = secs / 60;
|
||||||
|
long hours = mins / 60;
|
||||||
|
long days = hours / 24;
|
||||||
|
long years = days / 365;
|
||||||
|
double s = fmod(secs, 60);
|
||||||
|
|
||||||
|
mins %= 60;
|
||||||
|
hours %= 24;
|
||||||
|
days %= 365;
|
||||||
|
|
||||||
|
ss << "Time:\n";
|
||||||
|
|
||||||
|
if(years > 0) goto years;
|
||||||
|
if(days > 0) goto days;
|
||||||
|
if(hours > 0) goto hours;
|
||||||
|
if(mins > 0) goto mins;
|
||||||
|
goto secs;
|
||||||
|
|
||||||
|
years: ss << years << "y ";
|
||||||
|
days: ss << days << "d ";
|
||||||
|
hours: ss << hours << "h ";
|
||||||
|
mins: ss << mins << "m ";
|
||||||
|
secs: ss << s << "s\n";
|
||||||
|
|
||||||
|
ss << "Speed: " << speed << "x\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < steps_extra; i++)
|
||||||
|
{
|
||||||
|
double dt = speed / framerate / steps_extra;
|
||||||
|
reactor.update(rand, dt);
|
||||||
|
pump.update(dt);
|
||||||
|
valve.update(dt);
|
||||||
|
vessel.update();
|
||||||
|
secs += dt;
|
||||||
|
}
|
||||||
|
|
||||||
|
ss << "Vessel\n" << vessel << "\n";
|
||||||
|
ss << "Steam Valve\n" << valve << "\n";
|
||||||
|
ss << "Coolant Pump\n" << pump << "\n";
|
||||||
|
|
||||||
|
if(do_graphics)
|
||||||
|
{
|
||||||
|
erase();
|
||||||
|
display::draw_text(1, 0, ss.str().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
const int X = 1, Y = 30;
|
||||||
|
const int W = 36, H = 11;
|
||||||
|
|
||||||
|
for(int x = 0; x < reactor.width; x++)
|
||||||
|
for(int y = 0; y < reactor.height; y++)
|
||||||
|
{
|
||||||
|
int id = y * reactor.width + x;
|
||||||
|
sim::reactor::rod* r = reactor.rods[id];
|
||||||
|
|
||||||
|
if(!r->should_display())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << *r;
|
||||||
|
|
||||||
|
int px = X + (H - 1) * y;
|
||||||
|
int py = Y + (W - 1) * x;
|
||||||
|
|
||||||
|
if(do_graphics)
|
||||||
|
{
|
||||||
|
display::draw_text(px + 1, py + 2, ss.str().c_str());
|
||||||
|
display::draw_box(px, py, H, W);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(do_graphics && r->should_select() && id == reactor.cursor)
|
||||||
|
{
|
||||||
|
display::draw_text(px + 1, py + W - 5, "[ ]");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(do_graphics && r->is_selected())
|
||||||
|
{
|
||||||
|
display::draw_text(px + 1, py + W - 4, "#");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int c = 0;
|
||||||
|
|
||||||
|
if(do_graphics)
|
||||||
|
{
|
||||||
|
refresh();
|
||||||
|
c = getch();
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(c)
|
||||||
|
{
|
||||||
|
case KEY_LEFT:
|
||||||
|
reactor.move_cursor(-1);
|
||||||
|
break;
|
||||||
|
case KEY_RIGHT:
|
||||||
|
reactor.move_cursor(1);
|
||||||
|
break;
|
||||||
|
case KEY_UP:
|
||||||
|
reactor.update_selected(1);
|
||||||
|
break;
|
||||||
|
case KEY_DOWN:
|
||||||
|
reactor.update_selected(-1);
|
||||||
|
break;
|
||||||
|
case ' ':
|
||||||
|
reactor.toggle_selected();
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
speed *= 10;
|
||||||
|
break;
|
||||||
|
case 'g':
|
||||||
|
speed /= 10;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
valve.open(0.001);
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
valve.open(-0.001);
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
pump.change_speed(0.01);
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
pump.change_speed(-0.01);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(do_clock)
|
||||||
|
{
|
||||||
|
long now = get_now();
|
||||||
|
|
||||||
|
while(clock + 1e6 / framerate > now)
|
||||||
|
{
|
||||||
|
usleep(clock + 1e6 / framerate - now);
|
||||||
|
now = get_now();
|
||||||
|
}
|
||||||
|
|
||||||
|
clock += 1e6 / framerate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue