Compare commits
7 Commits
a270d3d601
...
2d69bb3c78
Author | SHA1 | Date |
---|---|---|
Jay Robson | 2d69bb3c78 | |
Jay Robson | e2b16e0591 | |
Jay Robson | c85984fc7f | |
Jay Robson | ddec7eeb9d | |
Jay Robson | 25861bbf16 | |
Jay Robson | e2f8eefe5b | |
Jay Robson | 1b317e9ff6 |
BIN
assets/scene.blend (Stored with Git LFS)
BIN
assets/scene.glb (Stored with Git LFS)
|
@ -1,26 +0,0 @@
|
|||
|
||||
#version 460 core
|
||||
|
||||
uniform int samples;
|
||||
uniform sampler2D tex;
|
||||
|
||||
in vec2 texPos;
|
||||
|
||||
out vec4 FragColour;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 texel_size = 1.f / vec2(textureSize(tex, 0));
|
||||
float samples_n = pow(samples * 2 + 1, 2);
|
||||
vec4 colour;
|
||||
|
||||
for(int x = -samples; x <= samples; x++)
|
||||
for(int y = -samples; y <= samples; y++)
|
||||
{
|
||||
vec2 off = texel_size * vec2(x, y);
|
||||
colour += texture2D(tex, texPos + off);
|
||||
}
|
||||
|
||||
FragColour = vec4((colour / samples_n).rgb, 1);
|
||||
}
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
|
||||
#version 460 core
|
||||
|
||||
layout (location = 1) in vec2 aTexPos;
|
||||
layout (location = 2) in vec4 aPos;
|
||||
|
||||
out vec2 texPos;
|
||||
|
||||
void main()
|
||||
{
|
||||
texPos = aTexPos;
|
||||
gl_Position = aPos;
|
||||
}
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
|
||||
#version 460 core
|
||||
|
||||
layout (location = 2) in vec4 aPos;
|
||||
layout (location = 4) in vec4 aColour;
|
||||
layout (location = 5) in vec3 aMaterial;
|
||||
layout (location = 6) in float aTransformIndex;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 camera;
|
||||
|
||||
out flat int should_ignore;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = camera * model * aPos;
|
||||
should_ignore = int(aTransformIndex >= 0.f || aMaterial[2] > 0.f || aColour.a < 1.f);
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
|
||||
#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 vec4 aPos;
|
||||
layout (location = 3) in vec3 aNormal;
|
||||
layout (location = 4) in vec4 aColour;
|
||||
layout (location = 5) in vec3 aMaterial;
|
||||
layout (location = 6) in float aTransformIndex;
|
||||
|
||||
uniform mat4 model;
|
||||
uniform mat4 camera;
|
||||
uniform mat4 projection;
|
||||
|
||||
layout (binding = 3) readonly buffer TransformBuffer
|
||||
{
|
||||
mat4 transforms[];
|
||||
};
|
||||
|
||||
out VS_OUT {
|
||||
vec3 normal;
|
||||
vec4 colour;
|
||||
vec3 pos;
|
||||
vec2 tex_pos;
|
||||
vec3 material;
|
||||
} vout;
|
||||
|
||||
out flat sampler2D frag_tex;
|
||||
|
||||
void main()
|
||||
{
|
||||
mat4 m = (aTransformIndex >= 0.f ? transforms[int(aTransformIndex)] : mat4(1.f)) * model;
|
||||
mat4 mvp = camera * m;
|
||||
vec4 pos = mvp * aPos;
|
||||
|
||||
vout.normal = mat3(m) * aNormal;
|
||||
vout.pos = (m * aPos).xyz;
|
||||
vout.colour = aColour;
|
||||
vout.tex_pos = aTexPos;
|
||||
vout.material = aMaterial;
|
||||
frag_tex = aTex;
|
||||
|
||||
gl_Position = projection * pos;
|
||||
}
|
||||
|
After Width: | Height: | Size: 59 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 103 KiB |
After Width: | Height: | Size: 270 KiB |
After Width: | Height: | Size: 560 KiB |
After Width: | Height: | Size: 14 KiB |
|
@ -14,18 +14,20 @@ constexpr static double calc_cylinder(double h, double d)
|
|||
return M_PI * r * r * h * 1000;
|
||||
}
|
||||
|
||||
Evaporator::Evaporator(Fluid type, double height, double diameter, double mass, double level) :
|
||||
height(height),
|
||||
diameter(diameter),
|
||||
FluidHolder(type, calc_cylinder(height, diameter), mass)
|
||||
Evaporator::Evaporator(Fluid type, double volume, double mass, double level)
|
||||
: FluidHolder(type, volume, mass)
|
||||
{
|
||||
this->level = level;
|
||||
}
|
||||
|
||||
Evaporator::Evaporator(const Json::Value& node) :
|
||||
height(node["height"].asDouble()),
|
||||
diameter(node["diameter"].asDouble()),
|
||||
FluidHolder(node)
|
||||
Evaporator::Evaporator(Fluid type, double height, double diameter, double mass, double level)
|
||||
: FluidHolder(type, calc_cylinder(height, diameter), mass)
|
||||
{
|
||||
this->level = level;
|
||||
}
|
||||
|
||||
Evaporator::Evaporator(const Json::Value& node)
|
||||
: FluidHolder(node)
|
||||
{
|
||||
steam_output = node["steam_output"].asDouble();
|
||||
}
|
||||
|
@ -70,8 +72,6 @@ Evaporator::operator Json::Value() const
|
|||
{
|
||||
Json::Value node(FluidHolder::operator::Json::Value());
|
||||
|
||||
node["height"] = height;
|
||||
node["diameter"] = diameter;
|
||||
node["steam_output"] = steam_output;
|
||||
|
||||
return node;
|
||||
|
|
|
@ -8,13 +8,11 @@ namespace Sim::Coolant
|
|||
|
||||
class Evaporator : public FluidHolder
|
||||
{
|
||||
const double height;
|
||||
const double diameter;
|
||||
|
||||
double steam_output = 0;
|
||||
|
||||
public:
|
||||
|
||||
Evaporator(Fluid type, double volume, double mass, double level);
|
||||
Evaporator(Fluid type, double height, double diameter, double mass, double level);
|
||||
Evaporator(const Json::Value& node);
|
||||
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
|
||||
#include "pool.hpp"
|
||||
|
||||
using namespace Sim::Coolant;
|
||||
|
||||
Pool::Pool(const Json::Value& node)
|
||||
: Evaporator(node)
|
||||
, dimensions(node["dimensions"]["x"].asDouble(), node["dimensions"]["y"].asDouble(), node["dimensions"]["z"].asDouble())
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Pool::Pool(Fluid fluid, const glm::vec3& dimensions, double heat, double mass, double level)
|
||||
: Evaporator(fluid, dimensions.x * dimensions.y * dimensions.z * 1000, mass, level)
|
||||
, dimensions(dimensions)
|
||||
{
|
||||
this->heat = heat;
|
||||
this->level = level;
|
||||
}
|
||||
|
||||
Pool::operator Json::Value() const
|
||||
{
|
||||
Json::Value node = Evaporator::operator Json::Value();
|
||||
node["dimensions"]["x"] = dimensions.x;
|
||||
node["dimensions"]["y"] = dimensions.y;
|
||||
node["dimensions"]["z"] = dimensions.z;
|
||||
return node;
|
||||
}
|
||||
|
||||
double Pool::get_level_height() const
|
||||
{
|
||||
double ratio = level / volume;
|
||||
return dimensions.z * ratio;
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
|
||||
#include "evaporator.hpp"
|
||||
|
||||
#include <glm/vec3.hpp>
|
||||
|
||||
namespace Sim::Coolant
|
||||
{
|
||||
|
||||
class Pool : public Evaporator
|
||||
{
|
||||
public:
|
||||
|
||||
const glm::vec3 dimensions;
|
||||
|
||||
Pool(Fluid fluid, const glm::vec3& dimensions, double temperature, double mass, double level);
|
||||
Pool(const Json::Value& node);
|
||||
|
||||
operator Json::Value() const;
|
||||
double get_level_height() const;
|
||||
};
|
||||
|
||||
};
|
||||
|
|
@ -33,7 +33,7 @@ void Generator::update(double dt)
|
|||
double energy_input = turbine->extract_energy();
|
||||
double energy_friction = get_rpm() / 60 * dt * friction;
|
||||
double work = Util::Math::j_to_ms2(energy_input - energy_friction, mass);
|
||||
phase = std::fmod(phase + Util::Math::map( get_rpm(), 0, 3600, 0, 120 * M_PI ) * dt, 2 * M_PI);
|
||||
phase = std::fmod(phase + Util::Math::map( get_rpm(), 0, 3600, 0, 120 * M_PI ) * dt, 4 * M_PI);
|
||||
|
||||
// do energy transfer stuff here
|
||||
if(breaker_closed)
|
||||
|
@ -121,6 +121,22 @@ double Generator::get_phase_diff() const
|
|||
return Util::Math::mod(phase - grid->get_phase() + M_PI, 2*M_PI) - M_PI;
|
||||
}
|
||||
|
||||
double Generator::get_frequency() const
|
||||
{
|
||||
return get_rpm() / 60;
|
||||
}
|
||||
|
||||
double Generator::get_power() const
|
||||
{
|
||||
return energy_generated;
|
||||
}
|
||||
|
||||
double Generator::get_voltage() const
|
||||
{
|
||||
// TODO: implement this
|
||||
return get_frequency() / 60 * 20e3;
|
||||
}
|
||||
|
||||
Generator::operator Json::Value() const
|
||||
{
|
||||
Json::Value node;
|
||||
|
|
|
@ -34,11 +34,13 @@ public:
|
|||
void update(double dt);
|
||||
|
||||
double get_rpm() const;
|
||||
double get_frequency() const;
|
||||
double get_power() const;
|
||||
double get_voltage() const;
|
||||
double get_phase_diff() const;
|
||||
|
||||
operator Json::Value() const;
|
||||
|
||||
constexpr double get_energy_generated() const { return energy_generated; }
|
||||
constexpr double get_phase() const { return phase; }
|
||||
};
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include "camera.hpp"
|
||||
#include "mesh/mesh.hpp"
|
||||
#include "data/mesh.hpp"
|
||||
#include "input/keyboard.hpp"
|
||||
#include "../util/math.hpp"
|
||||
|
||||
|
@ -19,7 +19,7 @@ static bool on_ground = false;
|
|||
static double yaw = 0, pitch = 0;
|
||||
static glm::vec<3, double> pos(0, 0, 2);
|
||||
static glm::vec<3, double> velocity(0);
|
||||
static Mesh collision_scene;
|
||||
static Data::Mesh collision_scene;
|
||||
static glm::mat4 camera_mat;
|
||||
|
||||
Json::Value Camera::serialize()
|
||||
|
@ -79,7 +79,12 @@ glm::vec<3, double> Camera::get_pos()
|
|||
return pos;
|
||||
}
|
||||
|
||||
void Camera::init(const Model& model)
|
||||
glm::vec<3, double> Camera::get_pos_base()
|
||||
{
|
||||
return pos - glm::vec<3, double>(0, 0, 1.5);
|
||||
}
|
||||
|
||||
void Camera::init(const Data::Model& model)
|
||||
{
|
||||
collision_scene = model.load("collision");
|
||||
}
|
||||
|
|
|
@ -5,13 +5,14 @@
|
|||
#include <json/json.h>
|
||||
|
||||
#include "../system.hpp"
|
||||
#include "mesh/model.hpp"
|
||||
#include "data/model.hpp"
|
||||
|
||||
namespace Sim::Graphics::Camera
|
||||
{
|
||||
|
||||
glm::vec<3, double> get_normal();
|
||||
glm::vec<3, double> get_pos();
|
||||
glm::vec<3, double> get_pos_base();
|
||||
glm::mat4 get_matrix();
|
||||
double get_pitch();
|
||||
double get_yaw();
|
||||
|
@ -19,7 +20,7 @@ double get_yaw();
|
|||
Json::Value serialize();
|
||||
void load(const Json::Value& node);
|
||||
|
||||
void init(const Model& model);
|
||||
void init(const Data::Model& model);
|
||||
void rotate(double pitch, double yaw);
|
||||
void move(double x, double y, double z);
|
||||
void update(double dt);
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <assimp/Importer.hpp>
|
||||
|
||||
#include "../shader.hpp"
|
||||
#include "../../util/streams.hpp"
|
||||
#include "arrays.hpp"
|
||||
#include "font.hpp"
|
||||
|
||||
using namespace Sim::Graphics::Data;
|
||||
|
||||
static void* ptr_diff(void* a, void* b)
|
||||
{
|
||||
return (void*)((size_t)a - (size_t)b);
|
||||
}
|
||||
|
||||
void Arrays::vertex_attrib_pointers()
|
||||
{
|
||||
Vertex v;
|
||||
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, false, sizeof(v), ptr_diff(&v.texpos, &v));
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, false, sizeof(v), ptr_diff(&v.pos, &v));
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
glVertexAttribPointer(2, 4, GL_FLOAT, false, sizeof(v), ptr_diff(&v.colour, &v));
|
||||
glEnableVertexAttribArray(2);
|
||||
|
||||
glVertexAttribPointer(3, 3, GL_FLOAT, true, sizeof(v), ptr_diff(&v.tbn[0], &v));
|
||||
glEnableVertexAttribArray(3);
|
||||
|
||||
glVertexAttribPointer(4, 3, GL_FLOAT, true, sizeof(v), ptr_diff(&v.tbn[1], &v));
|
||||
glEnableVertexAttribArray(4);
|
||||
|
||||
glVertexAttribPointer(5, 3, GL_FLOAT, true, sizeof(v), ptr_diff(&v.tbn[2], &v));
|
||||
glEnableVertexAttribArray(5);
|
||||
|
||||
glVertexAttribPointer(6, 3, GL_FLOAT, false, sizeof(v), ptr_diff(&v.material, &v));
|
||||
glEnableVertexAttribArray(6);
|
||||
|
||||
glVertexAttribIPointer(7, 1, GL_INT, sizeof(v), ptr_diff(&v.transform_id, &v));
|
||||
glEnableVertexAttribArray(7);
|
||||
|
||||
glVertexAttribIPointer(8, 1, GL_UNSIGNED_INT, sizeof(v), ptr_diff(&v.tex_diffuse, &v));
|
||||
glEnableVertexAttribArray(8);
|
||||
|
||||
glVertexAttribIPointer(9, 1, GL_UNSIGNED_INT, sizeof(v), ptr_diff(&v.tex_normal, &v));
|
||||
glEnableVertexAttribArray(9);
|
||||
|
||||
}
|
||||
|
||||
std::ostream& Arrays::operator<<(std::ostream& os, const Vertex& v)
|
||||
{
|
||||
os << "Vertex{";
|
||||
os << "texpos=" << v.texpos << ", ";
|
||||
os << "pos=" << v.pos << ", ";
|
||||
os << "colour=" << v.colour << ", ";
|
||||
os << "tbn=" << v.tbn << ", ";
|
||||
os << "transform_id=" << v.transform_id << ", ";
|
||||
os << "tex_diffuse=" << v.tex_diffuse << ", ";
|
||||
os << "tex_normal=" << v.tex_normal << ", ";
|
||||
os << "material=" << v.material;
|
||||
os << "}";
|
||||
return os;
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "texture.hpp"
|
||||
|
||||
#include <glm/matrix.hpp>
|
||||
#include <ostream>
|
||||
|
||||
namespace Sim::Graphics::Data::Arrays
|
||||
{
|
||||
|
||||
struct Vertex
|
||||
{
|
||||
glm::vec2 texpos = {0, 0};
|
||||
glm::vec3 pos = {0, 0, 0};
|
||||
glm::vec4 colour = {1, 1, 1, 1};
|
||||
glm::mat3 tbn = glm::mat3(1);
|
||||
int transform_id = -1;
|
||||
unsigned int tex_diffuse = Texture::handle_white;
|
||||
unsigned int tex_normal = Texture::handle_normal;
|
||||
glm::vec3 material = {0.5, 0, 0};
|
||||
|
||||
constexpr bool operator==(const Vertex&) const = default;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const Vertex& v);
|
||||
|
||||
};
|
||||
|
||||
void vertex_attrib_pointers();
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace Sim::Graphics::Data
|
||||
{
|
||||
|
||||
template <int N>
|
||||
struct Atlas
|
||||
{
|
||||
struct Pixel
|
||||
{
|
||||
uint8_t data[N] = {0};
|
||||
|
||||
constexpr Pixel() = default;
|
||||
|
||||
constexpr Pixel(const Pixel& p)
|
||||
{
|
||||
for(int i = 0; i < N; i++)
|
||||
{
|
||||
data[i] = p.data[i];
|
||||
}
|
||||
}
|
||||
|
||||
constexpr Pixel(const uint8_t* p)
|
||||
{
|
||||
for(int i = 0; i < N; i++)
|
||||
{
|
||||
data[i] = p[i];
|
||||
}
|
||||
}
|
||||
|
||||
constexpr bool operator == (const Pixel& p) const
|
||||
{
|
||||
for(int i = 0; i < N; i++)
|
||||
{
|
||||
if(data[i] != p.data[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
constexpr bool operator != (const Pixel& p) const
|
||||
{
|
||||
return !(*this == p);
|
||||
}
|
||||
|
||||
constexpr Pixel& operator = (const Pixel& p)
|
||||
{
|
||||
for(int i = 0; i < N; i++)
|
||||
{
|
||||
data[i] = p.data[i];
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr Pixel& operator = (const uint8_t* p)
|
||||
{
|
||||
for(int i = 0; i < N; i++)
|
||||
{
|
||||
data[i] = p[i];
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr uint8_t& operator [] (int i)
|
||||
{
|
||||
return data[i];
|
||||
}
|
||||
|
||||
constexpr const uint8_t& operator [] (int i) const
|
||||
{
|
||||
return data[i];
|
||||
}
|
||||
};
|
||||
|
||||
const int width;
|
||||
const int height;
|
||||
|
||||
std::vector<Pixel> data;
|
||||
|
||||
Atlas(int width, int height)
|
||||
: width(width)
|
||||
, height(height)
|
||||
, data(width * height)
|
||||
{
|
||||
}
|
||||
|
||||
Pixel& operator()(int x, int y)
|
||||
{
|
||||
return data[y * width + x];
|
||||
}
|
||||
|
||||
const Pixel& operator()(int x, int y) const
|
||||
{
|
||||
return data[y * width + x];
|
||||
}
|
||||
|
||||
void draw(const Atlas<N>& src, int x, int y, bool padding = false)
|
||||
{
|
||||
for(int i = 0; i < src.height; i++)
|
||||
{
|
||||
for(int j = 0; j < src.width; j++)
|
||||
{
|
||||
(*this)(x + j, y + i) = src(j, i);
|
||||
}
|
||||
}
|
||||
|
||||
if(padding)
|
||||
{
|
||||
for(int i = 0; i < src.height; i++)
|
||||
{
|
||||
(*this)(x - 1, y + i) = src(0, i);
|
||||
(*this)(x + src.width, y + i) = src(src.width - 1, i);
|
||||
}
|
||||
|
||||
for(int i = 0; i < src.width; i++)
|
||||
{
|
||||
(*this)(x + i, y - 1) = src(i, 0);
|
||||
(*this)(x + i, y + src.height) = src(i, src.height - 1);
|
||||
}
|
||||
|
||||
(*this)(x - 1, y - 1) = src(0, 0);
|
||||
(*this)(x + src.width, y - 1) = src(src.width - 1, 0);
|
||||
(*this)(x - 1, y + src.height) = src(0, src.height - 1);
|
||||
(*this)(x + src.width, y + src.height) = src(src.width - 1, src.height - 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <glm/matrix.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace Sim::Graphics::Data
|
||||
{
|
||||
|
||||
struct Camera
|
||||
{
|
||||
const std::string name;
|
||||
const glm::vec3 pos;
|
||||
const glm::vec3 look;
|
||||
const glm::vec3 up;
|
||||
const float fov;
|
||||
|
||||
float pitch = 0;
|
||||
float yaw = 0;
|
||||
float zoom = 1;
|
||||
};
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,181 @@
|
|||
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
#include <glm/vec2.hpp>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <format>
|
||||
|
||||
#include "../shader.hpp"
|
||||
#include "mesh.hpp"
|
||||
#include "arrays.hpp"
|
||||
#include "material.hpp"
|
||||
#include "texture.hpp"
|
||||
#include "font.hpp"
|
||||
|
||||
using namespace Sim::Graphics::Data;
|
||||
|
||||
Font Fonts::BASE;
|
||||
Font Fonts::MONO;
|
||||
|
||||
void Fonts::init()
|
||||
{
|
||||
BASE.init("DroidSans", 64);
|
||||
MONO.init("DroidSansMono", 64);
|
||||
}
|
||||
|
||||
void Font::init(const std::string& name, int size)
|
||||
{
|
||||
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, std::format("../assets/font/{}.ttf", name).c_str(), 0, &face))
|
||||
{
|
||||
std::cout << "Error: failed to load freetype font\n";
|
||||
return;
|
||||
}
|
||||
|
||||
texel_size = 1.0f / size;
|
||||
FT_Set_Pixel_Sizes(face, 0, size);
|
||||
|
||||
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";
|
||||
}
|
||||
|
||||
int width = face->glyph->bitmap.width;
|
||||
int height = face->glyph->bitmap.rows;
|
||||
int offx = face->glyph->bitmap_left;
|
||||
int offy = face->glyph->bitmap_top;
|
||||
|
||||
Character& c = characters[i];
|
||||
c.advance = face->glyph->advance.x * texel_size / 64.0;
|
||||
c.size = {width * texel_size, height * texel_size};
|
||||
c.bearing = {offx * texel_size, offy * texel_size};
|
||||
|
||||
if(c.size.x == 0 || c.size.y == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> buffer(width * height);
|
||||
|
||||
for(int i = 0; i < width * height; i++)
|
||||
{
|
||||
buffer[i] = face->glyph->bitmap.buffer[i];
|
||||
}
|
||||
|
||||
int swizzleMask[] = {GL_RED, GL_RED, GL_RED, GL_RED};
|
||||
c.handle = Texture::load_mem(buffer.data(), width, height, 1, swizzleMask);
|
||||
}
|
||||
|
||||
FT_Done_FreeType(ft);
|
||||
}
|
||||
|
||||
Font::Font()
|
||||
{
|
||||
}
|
||||
|
||||
Mesh Font::load_text(const std::string& text, float size) const
|
||||
{
|
||||
Mesh m;
|
||||
|
||||
if(text[0] == '\0')
|
||||
{
|
||||
return m;
|
||||
}
|
||||
|
||||
float x = 0, y = size;
|
||||
unsigned int at = 0;
|
||||
float t0 = 0;
|
||||
float t1 = 1;
|
||||
/*
|
||||
if(!Shader::USE_BINDLESS_TEXTURES)
|
||||
{
|
||||
t0 += texel_size / 2;
|
||||
t1 -= texel_size / 2;
|
||||
}*/
|
||||
|
||||
|
||||
for(unsigned int i = 0; i < text.size(); i++)
|
||||
{
|
||||
char c = text[i];
|
||||
const Character& ch = characters[c];
|
||||
|
||||
if(c == '\n')
|
||||
{
|
||||
x = 0;
|
||||
y += size;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(ch.handle == 0)
|
||||
{
|
||||
x += ch.advance * size;
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned int index[6] = {
|
||||
at, at + 1, at + 3,
|
||||
at, at + 3, at + 2
|
||||
};
|
||||
|
||||
float sx = x + ch.bearing.x * size;
|
||||
float sy = y - ch.bearing.y * size;
|
||||
float ex = sx + ch.size.x * size;
|
||||
float ey = sy + ch.size.y * size;
|
||||
|
||||
m.vertices.push_back(Arrays::Vertex{.texpos={t0, t0}, .pos={sx, sy, 0}, .tex_diffuse=ch.handle, .material={0, 0, 1}});
|
||||
m.vertices.push_back(Arrays::Vertex{.texpos={t0, t1}, .pos={sx, ey, 0}, .tex_diffuse=ch.handle, .material={0, 0, 1}});
|
||||
m.vertices.push_back(Arrays::Vertex{.texpos={t1, t0}, .pos={ex, sy, 0}, .tex_diffuse=ch.handle, .material={0, 0, 1}});
|
||||
m.vertices.push_back(Arrays::Vertex{.texpos={t1, t1}, .pos={ex, ey, 0}, .tex_diffuse=ch.handle, .material={0, 0, 1}});
|
||||
m.indices.insert(m.indices.end(), &index[0], &index[6]);
|
||||
|
||||
at += 4;
|
||||
x += ch.advance * size;
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
Mesh Font::load_text(const std::string& text, float size, glm::vec2 align) const
|
||||
{
|
||||
glm::vec2 max;
|
||||
Mesh m = load_text(text, size);
|
||||
|
||||
for(Arrays::Vertex& v : m.vertices)
|
||||
{
|
||||
if(v.pos.x > max.x)
|
||||
{
|
||||
max.x = v.pos.x;
|
||||
}
|
||||
|
||||
if(v.pos.y > max.y)
|
||||
{
|
||||
max.y = v.pos.y;
|
||||
}
|
||||
}
|
||||
|
||||
align *= max;
|
||||
|
||||
for(Arrays::Vertex& v : m.vertices)
|
||||
{
|
||||
v.pos.x -= align.x;
|
||||
v.pos.y -= align.y;
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "mesh.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include <glm/vec2.hpp>
|
||||
|
||||
namespace Sim::Graphics::Data
|
||||
{
|
||||
|
||||
class Font
|
||||
{
|
||||
struct Character
|
||||
{
|
||||
uint32_t handle;
|
||||
glm::vec2 size;
|
||||
glm::vec2 bearing;
|
||||
float advance;
|
||||
};
|
||||
|
||||
float texel_size;
|
||||
Character characters[128];
|
||||
|
||||
public:
|
||||
|
||||
Font();
|
||||
|
||||
void init(const std::string& name, int size);
|
||||
Mesh load_text(const std::string& text, float size, glm::vec2 align) const;
|
||||
Mesh load_text(const std::string& text, float size) const;
|
||||
|
||||
template <class T>
|
||||
void load_text(const char* header, T& item, double size)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << header << item;
|
||||
load_text(ss.str(), size);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void load_text(const char* header, T& item, double size, glm::vec2 align)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << header << item;
|
||||
load_text(ss.str(), size, align);
|
||||
}
|
||||
};
|
||||
|
||||
namespace Fonts
|
||||
{
|
||||
void init();
|
||||
|
||||
extern Font BASE;
|
||||
extern Font MONO;
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include "gllights.hpp"
|
||||
#include "../shader.hpp"
|
||||
#include "../window.hpp"
|
||||
#include "texture.hpp"
|
||||
|
||||
#include <glm/ext/matrix_transform.hpp>
|
||||
#include <glm/ext/matrix_clip_space.hpp>
|
||||
|
||||
using namespace Sim::Graphics::Data;
|
||||
|
||||
static glm::mat4 shadow_mats[6];
|
||||
|
||||
GLLights::GLLights(std::vector<Light>&& _lights) : lights(_lights), size(1024)
|
||||
{
|
||||
glGenTextures(1, &texid);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, texid);
|
||||
glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_DEPTH_COMPONENT, size, size, 6 * lights.size(), 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_COMPARE_FUNC, GL_LESS);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
glGenFramebuffers(1, &fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, texid, 0);
|
||||
glDrawBuffer(GL_NONE);
|
||||
glReadBuffer(GL_NONE);
|
||||
|
||||
glGenBuffers(1, &ssbo);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(Light) * lights.size(), lights.data(), GL_STATIC_COPY);
|
||||
}
|
||||
|
||||
GLLights::GLLights(GLLights&& o) : lights(o.lights), size(o.size)
|
||||
{
|
||||
texid = o.texid;
|
||||
fbo = o.fbo;
|
||||
|
||||
o.texid = 0;
|
||||
o.fbo = 0;
|
||||
}
|
||||
|
||||
GLLights::~GLLights()
|
||||
{
|
||||
if(fbo)
|
||||
glDeleteFramebuffers(1, &fbo);
|
||||
if(texid)
|
||||
glDeleteTextures(1, &texid);
|
||||
}
|
||||
|
||||
void GLLights::render()
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||
glViewport(0, 0, size, size);
|
||||
|
||||
Window::bind_scene_ssbo();
|
||||
|
||||
for(int i = 0; i < lights.size(); i++)
|
||||
{
|
||||
glUniform3fv(Shader::LIGHT["light_pos"], 1, &lights[i].pos[0]);
|
||||
glUniform1i(Shader::LIGHT["light_pass"], i);
|
||||
Window::render_scene();
|
||||
}
|
||||
}
|
||||
|
||||
void GLLights::init()
|
||||
{
|
||||
glm::mat4 shadow_proj = glm::perspective<float>(M_PI * 0.5f, 1.0f, 0.01f, 100.f);
|
||||
|
||||
shadow_mats[0] = shadow_proj * glm::lookAt(glm::vec3(0), { 1, 0, 0}, {0,-1, 0});
|
||||
shadow_mats[1] = shadow_proj * glm::lookAt(glm::vec3(0), {-1, 0, 0}, {0,-1, 0});
|
||||
shadow_mats[2] = shadow_proj * glm::lookAt(glm::vec3(0), { 0, 1, 0}, {0, 0, 1});
|
||||
shadow_mats[3] = shadow_proj * glm::lookAt(glm::vec3(0), { 0,-1, 0}, {0, 0,-1});
|
||||
shadow_mats[4] = shadow_proj * glm::lookAt(glm::vec3(0), { 0, 0, 1}, {0,-1, 0});
|
||||
shadow_mats[5] = shadow_proj * glm::lookAt(glm::vec3(0), { 0, 0,-1}, {0,-1, 0});
|
||||
|
||||
glUniformMatrix4fv(Shader::LIGHT["shadow_mats"], 6, false, &shadow_mats[0][0][0]);
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "light.hpp"
|
||||
|
||||
namespace Sim::Graphics::Data
|
||||
{
|
||||
|
||||
struct GLLights
|
||||
{
|
||||
const int size;
|
||||
|
||||
unsigned int texid, fbo, ssbo;
|
||||
|
||||
std::vector<Light> lights;
|
||||
|
||||
GLLights(std::vector<Light>&& lights);
|
||||
GLLights(GLLights&& o);
|
||||
GLLights(const GLLights& o) = delete;
|
||||
~GLLights();
|
||||
|
||||
static void init();
|
||||
|
||||
void render();
|
||||
};
|
||||
|
||||
};
|
||||
|
|
@ -6,8 +6,9 @@
|
|||
#include "arrays.hpp"
|
||||
#include "../shader.hpp"
|
||||
#include "../camera.hpp"
|
||||
#include "../../util/streams.hpp"
|
||||
|
||||
using namespace Sim::Graphics;
|
||||
using namespace Sim::Graphics::Data;
|
||||
|
||||
constexpr static void init(GLMesh* m)
|
||||
{
|
||||
|
@ -32,18 +33,22 @@ GLMesh::GLMesh(GLMesh&& o)
|
|||
vbo = o.vbo;
|
||||
ebo = o.ebo;
|
||||
vao = o.vao;
|
||||
size = o.size;
|
||||
model_matrix = o.model_matrix;
|
||||
ssbo = o.ssbo;
|
||||
|
||||
o.vbo = 0;
|
||||
o.ebo = 0;
|
||||
o.vao = 0;
|
||||
o.ssbo = 0;
|
||||
|
||||
size = o.size;
|
||||
ssbo_size = o.ssbo_size;
|
||||
}
|
||||
|
||||
GLMesh::~GLMesh()
|
||||
{
|
||||
if(vbo) glDeleteBuffers(1, &vbo);
|
||||
if(ebo) glDeleteBuffers(1, &ebo);
|
||||
if(ssbo) glDeleteBuffers(1, &ssbo);
|
||||
if(vao) glDeleteVertexArrays(1, &vao);
|
||||
}
|
||||
|
||||
|
@ -54,9 +59,15 @@ void GLMesh::bind()
|
|||
glBindVertexArray(vao);
|
||||
}
|
||||
|
||||
void GLMesh::uniform()
|
||||
void GLMesh::bind_ssbo()
|
||||
{
|
||||
glUniformMatrix4fv(Shader::ACTIVE->get("model"), 1, false, &model_matrix[0][0]);
|
||||
if(!ssbo)
|
||||
{
|
||||
glGenBuffers(1, &ssbo);
|
||||
}
|
||||
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, ssbo);
|
||||
}
|
||||
|
||||
void GLMesh::set(const Mesh& m, int mode)
|
||||
|
@ -65,7 +76,9 @@ void GLMesh::set(const Mesh& m, int mode)
|
|||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
|
||||
glBufferData(GL_ARRAY_BUFFER, m.vertices.size() * sizeof(m.vertices[0]), &m.vertices[0], mode);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, m.indices.size() * sizeof(m.indices[0]), &m.indices[0], mode);
|
||||
|
||||
this->size = m.indices.size();
|
||||
this->ssbo_size = m.transforms.size();
|
||||
}
|
||||
|
||||
void GLMesh::render()
|
|
@ -8,14 +8,14 @@
|
|||
|
||||
#include <glm/matrix.hpp>
|
||||
|
||||
namespace Sim::Graphics
|
||||
namespace Sim::Graphics::Data
|
||||
{
|
||||
|
||||
struct GLMesh
|
||||
{
|
||||
unsigned int vao = 0, vbo = 0, ebo = 0, size = 0;
|
||||
|
||||
glm::mat4 model_matrix {1.0f};
|
||||
unsigned int vao = 0, vbo = 0, ebo = 0, ssbo = 0;
|
||||
int ssbo_size = 0;
|
||||
int size = 0;
|
||||
|
||||
constexpr GLMesh() { }
|
||||
|
||||
|
@ -24,7 +24,7 @@ struct GLMesh
|
|||
~GLMesh();
|
||||
|
||||
void bind();
|
||||
void uniform();
|
||||
void bind_ssbo();
|
||||
void set(const Mesh& m, int mode);
|
||||
void render(int type);
|
||||
void render();
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#include <glm/matrix.hpp>
|
||||
|
||||
namespace Sim::Graphics
|
||||
namespace Sim::Graphics::Data
|
||||
{
|
||||
|
||||
struct Light
|
|
@ -0,0 +1,27 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <glm/vec4.hpp>
|
||||
|
||||
namespace Sim::Graphics::Data
|
||||
{
|
||||
|
||||
struct Material
|
||||
{
|
||||
uint32_t diffuse = Texture::handle_white;
|
||||
uint32_t normal = Texture::handle_normal;
|
||||
glm::vec4 colour = {1, 1, 1, 1};
|
||||
float roughness = 0.5;
|
||||
float metalness = 0;
|
||||
float luminance = 0;
|
||||
// float padding = 0;
|
||||
|
||||
/* static void init();
|
||||
static int create(Material m);
|
||||
static void destroy(int id);
|
||||
static Material get(int id);
|
||||
static void sync();*/
|
||||
};
|
||||
|
||||
};
|
||||
|
|
@ -5,81 +5,143 @@
|
|||
#include "../camera.hpp"
|
||||
#include "../input/focus.hpp"
|
||||
#include "../../util/math.hpp"
|
||||
#include "../../util/streams.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace Sim::Graphics;
|
||||
using namespace Sim::Graphics::Data;
|
||||
|
||||
Mesh::Mesh()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Mesh::set_transform_id()
|
||||
Mesh& Mesh::set_diffuse_id(unsigned int id)
|
||||
{
|
||||
for(unsigned int i = 0; i < vertices.size(); i++)
|
||||
{
|
||||
vertices[i].tex_diffuse = id;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Mesh& Mesh::set_normal_id(unsigned int id)
|
||||
{
|
||||
for(unsigned int i = 0; i < vertices.size(); i++)
|
||||
{
|
||||
vertices[i].tex_normal = id;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Mesh& Mesh::set_blank_transform()
|
||||
{
|
||||
transforms = {glm::mat4(1)};
|
||||
|
||||
for(unsigned int i = 0; i < vertices.size(); i++)
|
||||
{
|
||||
vertices[i].transform_id = 0;
|
||||
}
|
||||
|
||||
max_transform_id = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Mesh::add(const Mesh& o, glm::mat4 mat)
|
||||
Mesh& Mesh::add(const Mesh& o, glm::mat4 mat, bool bake)
|
||||
{
|
||||
unsigned int off = vertices.size();
|
||||
float t_off = max_transform_id + 1;
|
||||
int off = vertices.size();
|
||||
|
||||
indices.reserve(indices.size() + o.indices.size());
|
||||
vertices.reserve(vertices.size() + o.vertices.size());
|
||||
|
||||
if(bake)
|
||||
{
|
||||
for(int i = 0; i < o.vertices.size(); i++)
|
||||
{
|
||||
Arrays::Vertex v = o.vertices[i];
|
||||
int t_id = v.transform_id;
|
||||
glm::mat4 t_mat = t_id >= 0 ? transforms[t_id] : glm::mat4(1);
|
||||
t_mat = mat * t_mat;
|
||||
|
||||
v.pos = t_mat * glm::vec4(v.pos, 1);
|
||||
v.tbn = glm::mat3(t_mat) * v.tbn;
|
||||
v.transform_id = -1;
|
||||
vertices.push_back(v);
|
||||
}
|
||||
|
||||
for(int i = 0; i < o.indices.size(); i++)
|
||||
{
|
||||
indices.push_back(o.indices[i] + off);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
glm::mat3 mat3(mat);
|
||||
vertices.reserve(vertices.size() + o.vertices.size());
|
||||
indices.reserve(indices.size() + o.indices.size());
|
||||
int t_off = transforms.size();
|
||||
int t_new = -1;
|
||||
|
||||
for(unsigned int i = 0; i < o.vertices.size(); i++)
|
||||
if(mat != glm::mat4(1))
|
||||
{
|
||||
t_new = transforms.size() + o.transforms.size();
|
||||
}
|
||||
|
||||
transforms.reserve(transforms.size() + o.transforms.size() + (t_new >= 0 ? 1 : 0));
|
||||
|
||||
for(int i = 0; i < o.vertices.size(); i++)
|
||||
{
|
||||
Arrays::Vertex v = o.vertices[i];
|
||||
v.normal = mat3 * v.normal;
|
||||
v.pos = mat * v.pos;
|
||||
|
||||
|
||||
if(v.transform_id >= 0)
|
||||
{
|
||||
v.transform_id += t_off;
|
||||
max_transform_id = std::max(max_transform_id, v.transform_id);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
v.transform_id = t_new;
|
||||
}
|
||||
|
||||
vertices.push_back(v);
|
||||
}
|
||||
|
||||
for(unsigned int i = 0; i < o.indices.size(); i++)
|
||||
for(int i = 0; i < o.transforms.size(); i++)
|
||||
{
|
||||
transforms.push_back(o.transforms[i] * mat);
|
||||
}
|
||||
|
||||
for(int i = 0; i < o.indices.size(); i++)
|
||||
{
|
||||
indices.push_back(o.indices[i] + off);
|
||||
}
|
||||
}
|
||||
|
||||
void Mesh::add(const Mesh& o)
|
||||
{
|
||||
add(o, glm::mat4(1));
|
||||
}
|
||||
|
||||
void Mesh::set_vertices(const Arrays::Vertex* data, size_t size)
|
||||
{
|
||||
vertices.clear();
|
||||
vertices.reserve(size);
|
||||
|
||||
for(unsigned int i = 0; i < size; i++)
|
||||
if(t_new >= 0)
|
||||
{
|
||||
vertices.push_back(data[i]);
|
||||
transforms.push_back(mat);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Mesh::set_indices(const unsigned int* data, size_t size)
|
||||
Mesh& Mesh::bake_transforms()
|
||||
{
|
||||
indices.clear();
|
||||
indices.reserve(size);
|
||||
|
||||
for(unsigned int i = 0; i < size; i++)
|
||||
for(unsigned int i = 0; i < vertices.size(); i++)
|
||||
{
|
||||
indices.push_back(data[i]);
|
||||
int id = vertices[i].transform_id;
|
||||
|
||||
if(id >= 0)
|
||||
{
|
||||
glm::mat4 transform = transforms[id];
|
||||
vertices[i].pos = glm::vec3(transform * glm::vec4(vertices[i].pos, 1));
|
||||
vertices[i].tbn = glm::mat3(transform) * vertices[i].tbn;
|
||||
vertices[i].transform_id = -1;
|
||||
}
|
||||
}
|
||||
|
||||
transforms.clear();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
typedef glm::vec<3, double> vec3;
|
||||
|
@ -126,15 +188,28 @@ bool ray_intersects_triangle(vec3 ray_origin,
|
|||
|
||||
bool Mesh::check_focus(double len) const
|
||||
{
|
||||
if(!Focus::is_triggered())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto near = Focus::get_trigger_near();
|
||||
auto far = Focus::get_trigger_far();
|
||||
|
||||
return Focus::is_triggered() && check_intersect(near, glm::normalize(far - near) * len);
|
||||
return check_intersect(near, glm::normalize(far - near) * len);
|
||||
}
|
||||
|
||||
bool Mesh::check_focus() const
|
||||
bool Mesh::check_focus_hold(double len)
|
||||
{
|
||||
return check_focus(2.5);
|
||||
if(!Focus::is_triggered() && (!focus || Focus::is_triggered_release()))
|
||||
{
|
||||
return focus = false;
|
||||
}
|
||||
|
||||
auto near = Focus::get_trigger_near();
|
||||
auto far = Focus::get_trigger_far();
|
||||
|
||||
return focus = check_intersect(near, glm::normalize(far - near) * len);
|
||||
}
|
||||
|
||||
bool Mesh::check_intersect(vec3 pos, vec3 path) const
|
||||
|
@ -150,11 +225,21 @@ bool Mesh::check_intersect(vec3 pos, vec3 path) const
|
|||
|
||||
for(unsigned int i = 0; i < indices.size(); i += 3)
|
||||
{
|
||||
vec3 v[3] = {
|
||||
vec3(this->vertices[indices[i]].pos),
|
||||
vec3(this->vertices[indices[i + 1]].pos),
|
||||
vec3(this->vertices[indices[i + 2]].pos)
|
||||
Arrays::Vertex verts[3] = {
|
||||
vertices[indices[i]],
|
||||
vertices[indices[i + 1]],
|
||||
vertices[indices[i + 2]]
|
||||
};
|
||||
|
||||
vec3 v[3];
|
||||
|
||||
for(int j = 0; j < 3; j++)
|
||||
{
|
||||
int t_id = verts[j].transform_id;
|
||||
glm::mat4 t_mat = t_id >= 0 ? transforms[t_id] : glm::mat4(1);
|
||||
|
||||
v[j] = vec3(t_mat * glm::vec4(verts[j].pos, 1));
|
||||
}
|
||||
|
||||
vec3 ipoint;
|
||||
vec3 normal = glm::normalize(glm::cross(v[1] - v[0], v[2] - v[0]));
|
||||
|
@ -218,11 +303,21 @@ vec3 Mesh::calc_intersect(vec3 pos, vec3 path) const
|
|||
|
||||
for(unsigned int i = 0; i < indices.size(); i += 3)
|
||||
{
|
||||
vec3 v[3] = {
|
||||
vec3(this->vertices[indices[i]].pos),
|
||||
vec3(this->vertices[indices[i + 1]].pos),
|
||||
vec3(this->vertices[indices[i + 2]].pos)
|
||||
Arrays::Vertex verts[3] = {
|
||||
vertices[indices[i]],
|
||||
vertices[indices[i + 1]],
|
||||
vertices[indices[i + 2]]
|
||||
};
|
||||
|
||||
vec3 v[3];
|
||||
|
||||
for(int j = 0; j < 3; j++)
|
||||
{
|
||||
int t_id = verts[j].transform_id;
|
||||
glm::mat4 t_mat = t_id >= 0 ? transforms[t_id] : glm::mat4(1);
|
||||
|
||||
v[j] = vec3(t_mat * glm::vec4(verts[j].pos, 1));
|
||||
}
|
||||
|
||||
if(calc_intercept_vert(v, pos, path, path_n, l))
|
||||
{
|
||||
|
@ -257,4 +352,33 @@ Mesh Mesh::to_lines() const
|
|||
return m;
|
||||
}
|
||||
|
||||
std::ostream& Sim::Graphics::Data::operator<<(std::ostream& os, const Mesh& m)
|
||||
{
|
||||
os << "Mesh(\n";
|
||||
os << " Vertices(\n";
|
||||
|
||||
for(int i = 0; i < m.vertices.size(); i++)
|
||||
{
|
||||
os << " " << m.vertices[i] << "\n";
|
||||
}
|
||||
|
||||
os << " )\n";
|
||||
|
||||
for(int i = 0; i < m.indices.size(); i += 3)
|
||||
{
|
||||
os << " " << m.indices[i] << " " << m.indices[i + 1] << " " << m.indices[i + 2] << "\n";
|
||||
}
|
||||
|
||||
os << " Transforms(\n";
|
||||
|
||||
for(int i = 0; i < m.transforms.size(); i++)
|
||||
{
|
||||
os << " " << m.transforms[i] << "\n";
|
||||
}
|
||||
|
||||
os << " )\n";
|
||||
os << ")\n";
|
||||
|
||||
return os;
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <glm/matrix.hpp>
|
||||
|
||||
#include "arrays.hpp"
|
||||
#include "light.hpp"
|
||||
|
||||
namespace Sim::Graphics::Data
|
||||
{
|
||||
|
||||
struct Mesh
|
||||
{
|
||||
std::vector<Arrays::Vertex> vertices;
|
||||
std::vector<unsigned int> indices;
|
||||
std::vector<glm::mat4> transforms;
|
||||
bool focus = false;
|
||||
|
||||
Mesh();
|
||||
|
||||
Mesh& bake_transforms();
|
||||
Mesh& set_blank_transform();
|
||||
Mesh& set_normal_id(unsigned int id);
|
||||
Mesh& set_diffuse_id(unsigned int id);
|
||||
Mesh& add(const Mesh& o, glm::mat4 mat = glm::mat4(1), bool bake = false);
|
||||
|
||||
Mesh to_lines() const;
|
||||
bool check_focus(double len = 2.5) const;
|
||||
bool check_focus_hold(double len = 2.5);
|
||||
bool check_intersect(glm::vec<3, double> pos, glm::vec<3, double> path) const;
|
||||
glm::vec<3, double> calc_intersect(glm::vec<3, double> pos, glm::vec<3, double> path) const;
|
||||
|
||||
bool operator==(const Mesh&) const = default;
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const Mesh& m);
|
||||
};
|
||||
|
||||
};
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "../mesh/model.hpp"
|
||||
#include "model.hpp"
|
||||
|
||||
namespace Sim::Graphics
|
||||
namespace Sim::Graphics::Data
|
||||
{
|
||||
|
||||
class MeshGen
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <unordered_map>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
#include "mesh.hpp"
|
||||
|
@ -14,7 +15,7 @@
|
|||
#include "model.hpp"
|
||||
#include "../../util/streams.hpp"
|
||||
|
||||
using namespace Sim::Graphics;
|
||||
using namespace Sim::Graphics::Data;
|
||||
|
||||
struct ProcState
|
||||
{
|
||||
|
@ -23,107 +24,18 @@ struct ProcState
|
|||
std::string base;
|
||||
std::vector<Arrays::Vertex> vertices;
|
||||
std::vector<unsigned int> indices;
|
||||
std::unordered_map<const aiTexture*, unsigned int> handles;
|
||||
std::vector<glm::mat4> transforms;
|
||||
const std::vector<Material>& materials;
|
||||
};
|
||||
|
||||
static unsigned int proc_texture(const ProcState& state, aiMaterial* mat, const aiScene* scene, aiTextureType type, int index)
|
||||
static void proc_mesh(ProcState& state, aiMesh* mesh, const aiScene* scene)
|
||||
{
|
||||
aiString str;
|
||||
mat->GetTexture(type, index, &str);
|
||||
|
||||
if(str.C_Str()[0] == '\0')
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const aiTexture* tex = scene->GetEmbeddedTexture(str.C_Str());
|
||||
|
||||
if(tex != nullptr)
|
||||
{
|
||||
unsigned int handle = state.handles.find(tex)->second;
|
||||
std::cout << "Using preloaded texture: " << tex->mFilename.C_Str() << "\n";
|
||||
return handle;
|
||||
}
|
||||
|
||||
std::string filename(str.C_Str());
|
||||
std::replace(filename.begin(), filename.end(), '\\', '/');
|
||||
|
||||
return Texture::load(state.base + "/" + filename);
|
||||
}
|
||||
|
||||
static void proc_mesh(ProcState& state, glm::mat4 mat, aiMesh* mesh, const aiScene* scene)
|
||||
{
|
||||
aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
|
||||
aiString name;
|
||||
|
||||
material->Get(AI_MATKEY_NAME, name);
|
||||
/*
|
||||
std::cout << "Material " << name.C_Str() << " has " << material->mNumProperties << " properties\n";
|
||||
|
||||
for(int i = 0; i < material->mNumProperties; i++)
|
||||
{
|
||||
aiMaterialProperty* prop = material->mProperties[i];
|
||||
|
||||
std::cout << " " << prop->mKey.C_Str() << ": type=" << prop->mType << " index=" << prop->mIndex << " length=" << prop->mDataLength;
|
||||
|
||||
if(prop->mType == 1)
|
||||
{
|
||||
float* v = (float*)prop->mData;
|
||||
|
||||
std::cout << " value=";
|
||||
|
||||
switch(prop->mDataLength)
|
||||
{
|
||||
case 4:
|
||||
std::cout << v[0];
|
||||
break;
|
||||
case 8:
|
||||
std::cout << "{" << v[0] << ", " << v[1] << "}";
|
||||
break;
|
||||
case 12:
|
||||
std::cout << "{" << v[0] << ", " << v[1] << ", " << v[2] << "}";
|
||||
break;
|
||||
case 16:
|
||||
std::cout << "{" << v[0] << ", " << v[1] << ", " << v[2] << ", " << v[3] << "}";
|
||||
break;
|
||||
default:
|
||||
std::cout << "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "\n";
|
||||
}*/
|
||||
|
||||
glm::vec3 matv(0);
|
||||
aiColor4D ai_cb;
|
||||
aiColor4D ai_em;
|
||||
|
||||
material->Get(AI_MATKEY_ROUGHNESS_FACTOR, matv[0]);
|
||||
material->Get(AI_MATKEY_METALLIC_FACTOR, matv[1]);
|
||||
material->Get(AI_MATKEY_EMISSIVE_INTENSITY, matv[2]);
|
||||
material->Get(AI_MATKEY_COLOR_EMISSIVE, ai_em);
|
||||
material->Get(AI_MATKEY_BASE_COLOR, ai_cb);
|
||||
|
||||
glm::vec4 cb = {ai_cb[0], ai_cb[1], ai_cb[2], ai_cb[3]};
|
||||
glm::vec4 em = {ai_em[0], ai_em[1], ai_em[2], ai_em[3]};
|
||||
|
||||
if(em.x > 0 || em.y > 0 || em.z > 0)
|
||||
{
|
||||
cb = em;
|
||||
}
|
||||
|
||||
unsigned int handle = proc_texture(state, material, scene, aiTextureType_BASE_COLOR, 0);
|
||||
Material mat = state.materials[mesh->mMaterialIndex];
|
||||
unsigned int offset = state.offset;
|
||||
glm::mat3 mat3(mat);
|
||||
|
||||
if(!handle)
|
||||
|
||||
if(!mesh->HasNormals())
|
||||
{
|
||||
handle = proc_texture(state, material, scene, aiTextureType_DIFFUSE, 0);
|
||||
}
|
||||
|
||||
if(!handle)
|
||||
{
|
||||
handle = Texture::handle_white;
|
||||
throw std::runtime_error("Mesh has no normals");
|
||||
}
|
||||
|
||||
for(unsigned int i = 0; i < mesh->mNumVertices; i++)
|
||||
|
@ -131,30 +43,42 @@ static void proc_mesh(ProcState& state, glm::mat4 mat, aiMesh* mesh, const aiSce
|
|||
Arrays::Vertex vertex;
|
||||
|
||||
auto [x, y, z] = mesh->mVertices[i];
|
||||
vertex.pos = glm::vec4(x, y, z, 1) * mat;
|
||||
vertex.material = matv;
|
||||
vertex.texid = handle;
|
||||
vertex.colour = cb;
|
||||
|
||||
if(mesh->HasNormals())
|
||||
{
|
||||
auto [x, y, z] = mesh->mNormals[i];
|
||||
vertex.normal = glm::vec3(x, y, z) * mat3;
|
||||
}
|
||||
vertex.transform_id = state.transforms.size();
|
||||
vertex.pos = glm::vec3(x, y, z);
|
||||
vertex.colour = mat.colour;
|
||||
vertex.tex_diffuse = mat.diffuse;
|
||||
vertex.tex_normal = mat.normal;
|
||||
vertex.material = {mat.roughness, mat.metalness, mat.luminance};
|
||||
|
||||
/*if(mesh->HasTangentsAndBitangents())
|
||||
{
|
||||
auto [x1, y1, z1] = mesh->mTangents[i];
|
||||
auto [x2, y2, z2] = mesh->mBitangents[i];
|
||||
vertex.tangent = {x1, y1, z1};
|
||||
vertex.bitangent = {x2, y2, z2};
|
||||
}*/
|
||||
|
||||
if(mesh->mTextureCoords[0])
|
||||
{
|
||||
auto [x, y, z] = mesh->mTextureCoords[0][i];
|
||||
vertex.texpos = {x, y};
|
||||
}
|
||||
|
||||
if(mesh->HasTangentsAndBitangents())
|
||||
{
|
||||
auto [x1, y1, z1] = mesh->mTangents[i];
|
||||
auto [x2, y2, z2] = mesh->mBitangents[i];
|
||||
auto [x3, y3, z3] = mesh->mNormals[i];
|
||||
|
||||
vertex.tbn = {
|
||||
{x1, y1, z1},
|
||||
{x2, y2, z2},
|
||||
{x3, y3, z3},
|
||||
};
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
auto [x, y, z] = mesh->mNormals[i];
|
||||
|
||||
glm::vec3 normal = {x, y, z};
|
||||
glm::vec3 tangent = glm::normalize(glm::cross(normal, {-y, z, x}));
|
||||
glm::vec3 bitangent = glm::normalize(glm::cross(normal, tangent));
|
||||
|
||||
vertex.tbn = {tangent, bitangent, normal};
|
||||
}
|
||||
|
||||
state.vertices.push_back(vertex);
|
||||
}
|
||||
|
@ -175,10 +99,10 @@ static void proc_mesh(ProcState& state, glm::mat4 mat, aiMesh* mesh, const aiSce
|
|||
glm::mat4 convert_mat(aiMatrix4x4 m)
|
||||
{
|
||||
return {
|
||||
m.a1, m.a2, m.a3, m.a4,
|
||||
m.b1, m.b2, m.b3, m.b4,
|
||||
m.c1, m.c2, m.c3, m.c4,
|
||||
m.d1, m.d2, m.d3, m.d4
|
||||
m.a1, m.b1, m.c1, m.d1,
|
||||
m.a2, m.b2, m.c2, m.d2,
|
||||
m.a3, m.b3, m.c3, m.d3,
|
||||
m.a4, m.b4, m.c4, m.d4
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -207,7 +131,12 @@ static void proc_node(ProcState& state, glm::mat4 mat, aiNode* node, const aiSce
|
|||
for(size_t i = 0; i < node->mNumMeshes; i++)
|
||||
{
|
||||
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
|
||||
proc_mesh(state, mat, mesh, scene);
|
||||
proc_mesh(state, mesh, scene);
|
||||
}
|
||||
|
||||
if(node->mNumMeshes > 0)
|
||||
{
|
||||
state.transforms.push_back(mat);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -217,7 +146,7 @@ static void proc_node(ProcState& state, glm::mat4 mat, aiNode* node, const aiSce
|
|||
}
|
||||
}
|
||||
|
||||
static unsigned int proc_embedded_texture(aiTexture* tex)
|
||||
static uint64_t proc_embedded_texture(aiTexture* tex)
|
||||
{
|
||||
std::cout << "Loading embedded data: " << tex->mFilename.C_Str() << "\n";
|
||||
|
||||
|
@ -252,50 +181,138 @@ glm::mat4 get_transforms(const aiNode* node)
|
|||
return mat;
|
||||
}
|
||||
|
||||
glm::mat4 Model::get_matrix(const char* name) const
|
||||
glm::mat4 Model::load_matrix(const char* name) const
|
||||
{
|
||||
return get_transforms(scene->mRootNode->FindNode(name));
|
||||
}
|
||||
|
||||
static uint32_t proc_texture(
|
||||
const std::string& path_base,
|
||||
aiMaterial* mat,
|
||||
const aiScene* scene,
|
||||
aiTextureType type,
|
||||
int index,
|
||||
uint64_t handle_fail=0)
|
||||
{
|
||||
aiString str;
|
||||
mat->GetTexture(type, index, &str);
|
||||
|
||||
if(str.C_Str()[0] == '\0')
|
||||
{
|
||||
return handle_fail;
|
||||
}
|
||||
|
||||
std::string filename(str.C_Str());
|
||||
std::replace(filename.begin(), filename.end(), '\\', '/');
|
||||
|
||||
return Texture::load(path_base + "/" + filename);
|
||||
}
|
||||
|
||||
Model::Model(std::string base, std::string filename) : base(base)
|
||||
{
|
||||
std::string path = base + "/" + filename;
|
||||
scene = importer.ReadFile(path.c_str(), aiProcess_Triangulate | aiProcess_FlipUVs);
|
||||
scene = importer.ReadFile(path.c_str(), aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_CalcTangentSpace);
|
||||
|
||||
textures.reserve(scene->mNumTextures);
|
||||
materials.reserve(scene->mNumMaterials);
|
||||
|
||||
for(int i = 0; i < scene->mNumTextures; i++)
|
||||
{
|
||||
aiTexture* tex = scene->mTextures[i];
|
||||
unsigned int handle = proc_embedded_texture(tex);
|
||||
uint64_t handle = proc_embedded_texture(tex);
|
||||
textures.push_back(handle);
|
||||
}
|
||||
|
||||
for(int i = 0; i < scene->mNumLights; i++)
|
||||
{
|
||||
aiLight* light = scene->mLights[i];
|
||||
glm::mat4 mat = get_matrix(light->mName.C_Str());
|
||||
glm::mat4 mat = load_matrix(light->mName.C_Str());
|
||||
|
||||
auto [x, y, z] = light->mPosition;
|
||||
auto [r, g, b] = light->mColorDiffuse;
|
||||
|
||||
glm::vec4 pos = glm::vec4(x, y, z, 1) * mat;
|
||||
glm::vec4 pos = mat * glm::vec4(x, y, z, 1);
|
||||
|
||||
lights.push_back({
|
||||
glm::vec3(pos),
|
||||
{r, g, b},
|
||||
});
|
||||
}
|
||||
|
||||
for(int i = 0; i < scene->mNumCameras; i++)
|
||||
{
|
||||
aiCamera* camera = scene->mCameras[i];
|
||||
glm::mat4 mat = load_matrix(camera->mName.C_Str());
|
||||
|
||||
auto [x, y, z] = camera->mPosition;
|
||||
auto [dx, dy, dz] = camera->mLookAt;
|
||||
auto [ux, uy, uz] = camera->mUp;
|
||||
|
||||
glm::vec4 pos = mat * glm::vec4(x, y, z, 1);
|
||||
glm::vec3 look = glm::normalize(glm::mat3(mat) * glm::vec3(dx, dy, dz));
|
||||
glm::vec3 up = glm::normalize(glm::mat3(mat) * glm::vec3(ux, uy, uz));
|
||||
|
||||
cameras.push_back(Camera {
|
||||
.name={camera->mName.C_Str()},
|
||||
.pos=glm::vec3(pos),
|
||||
.look=look,
|
||||
.up=up,
|
||||
.fov=camera->mHorizontalFOV
|
||||
});
|
||||
}
|
||||
|
||||
for(int i = 0; i < scene->mNumMaterials; i++)
|
||||
{
|
||||
aiMaterial* ai_mat = scene->mMaterials[i];
|
||||
|
||||
glm::vec3 matv(0);
|
||||
aiColor4D ai_cb;
|
||||
aiColor4D ai_em;
|
||||
|
||||
ai_mat->Get(AI_MATKEY_COLOR_EMISSIVE, ai_em);
|
||||
ai_mat->Get(AI_MATKEY_BASE_COLOR, ai_cb);
|
||||
|
||||
glm::vec4 cb = {ai_cb[0], ai_cb[1], ai_cb[2], ai_cb[3]};
|
||||
glm::vec4 em = {ai_em[0], ai_em[1], ai_em[2], ai_em[3]};
|
||||
|
||||
if(em.x > 0 || em.y > 0 || em.z > 0)
|
||||
{
|
||||
cb = em;
|
||||
}
|
||||
|
||||
ai_mat->Get(AI_MATKEY_ROUGHNESS_FACTOR, matv[0]);
|
||||
ai_mat->Get(AI_MATKEY_METALLIC_FACTOR, matv[1]);
|
||||
ai_mat->Get(AI_MATKEY_EMISSIVE_INTENSITY, matv[2]);
|
||||
|
||||
uint32_t handle_diffuse = proc_texture(base, ai_mat, scene, aiTextureType_BASE_COLOR, 0, Texture::handle_white);
|
||||
uint32_t handle_normal = proc_texture(base, ai_mat, scene, aiTextureType_NORMALS, 0, Texture::handle_normal);
|
||||
|
||||
Material mat = {
|
||||
.diffuse = handle_diffuse,
|
||||
.normal = handle_normal,
|
||||
.colour = cb,
|
||||
.roughness = matv[0],
|
||||
.metalness = matv[1],
|
||||
.luminance = matv[2],
|
||||
};
|
||||
|
||||
materials.push_back(mat);
|
||||
}
|
||||
}
|
||||
|
||||
Mesh Model::load(const char* name, glm::mat4 mat) const
|
||||
{
|
||||
Mesh mesh;
|
||||
ProcState state {.base = base};
|
||||
ProcState state {
|
||||
.base = base,
|
||||
.materials = materials,
|
||||
};
|
||||
|
||||
proc_node(state, mat, scene->mRootNode, scene, name);
|
||||
|
||||
mesh.vertices = std::move(state.vertices);
|
||||
mesh.indices = std::move(state.indices);
|
||||
mesh.transforms = std::move(state.transforms);
|
||||
|
||||
return mesh;
|
||||
}
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include "mesh.hpp"
|
||||
#include "light.hpp"
|
||||
#include "camera.hpp"
|
||||
#include "material.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
@ -14,7 +16,7 @@
|
|||
#include <assimp/material.h>
|
||||
#include <assimp/postprocess.h>
|
||||
|
||||
namespace Sim::Graphics
|
||||
namespace Sim::Graphics::Data
|
||||
{
|
||||
|
||||
class Model
|
||||
|
@ -25,7 +27,9 @@ class Model
|
|||
|
||||
public:
|
||||
|
||||
std::vector<uint64_t> textures;
|
||||
std::vector<uint32_t> textures;
|
||||
std::vector<Material> materials;
|
||||
std::vector<Camera> cameras;
|
||||
std::vector<Light> lights;
|
||||
|
||||
Model(std::string base, std::string filename);
|
||||
|
@ -35,7 +39,7 @@ public:
|
|||
Mesh load_root(glm::mat4 mat) const;
|
||||
Mesh load(const char* name) const;
|
||||
Mesh load(const char* name, glm::mat4 mat) const;
|
||||
glm::mat4 get_matrix(const char* name) const;
|
||||
glm::mat4 load_matrix(const char* name) const;
|
||||
};
|
||||
|
||||
};
|
|
@ -0,0 +1,273 @@
|
|||
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <stb/stb_image.h>
|
||||
#include <stb/stb_rect_pack.h>
|
||||
|
||||
#include <glm/matrix.hpp>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
|
||||
#include "texture.hpp"
|
||||
#include "atlas.hpp"
|
||||
#include "../shader.hpp"
|
||||
|
||||
using namespace Sim::Graphics::Data;
|
||||
|
||||
static bool is_done = false;
|
||||
static uint32_t atlas_texid;
|
||||
static uint32_t atlas_uv_ssbo;
|
||||
static std::unordered_map<std::string, uint32_t> loaded;
|
||||
static std::vector<Atlas<4>> texture_atlas_queue;
|
||||
|
||||
uint32_t Texture::handle_white;
|
||||
uint32_t Texture::handle_normal;
|
||||
|
||||
void Texture::init()
|
||||
{
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
unsigned char pixels_white[] = {255};
|
||||
unsigned char pixels_normal[] = {128, 255};
|
||||
int swizzle_white[] = {GL_RED, GL_RED, GL_RED, GL_RED};
|
||||
int swizzle_normal[] = {GL_RED, GL_RED, GL_GREEN, GL_GREEN};
|
||||
handle_white = load_mem(pixels_white, 1, 1, 1, swizzle_white);
|
||||
handle_normal = load_mem(pixels_normal, 1, 1, 2, swizzle_normal);
|
||||
}
|
||||
|
||||
void Texture::generate_atlas()
|
||||
{
|
||||
// if we are using bindless textures, we don't need to generate an atlas
|
||||
if(Shader::USE_BINDLESS_TEXTURES)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int total_area = 0;
|
||||
int padding = 2;
|
||||
int offset = 1;
|
||||
|
||||
for(const Atlas<4>& atlas : texture_atlas_queue)
|
||||
{
|
||||
total_area += (atlas.width + padding) * (atlas.height + padding);
|
||||
}
|
||||
|
||||
int size = std::pow(2, std::ceil(std::log2(std::sqrt(total_area))));
|
||||
|
||||
std::vector<stbrp_rect> rects;
|
||||
std::vector<glm::mat2> uvs;
|
||||
|
||||
rects.reserve(texture_atlas_queue.size());
|
||||
uvs.reserve(texture_atlas_queue.size());
|
||||
|
||||
for(int i = 0; i < texture_atlas_queue.size(); i++)
|
||||
{
|
||||
const Atlas<4>& atlas = texture_atlas_queue[i];
|
||||
stbrp_rect rect;
|
||||
rect.id = i;
|
||||
rect.w = atlas.width + padding;
|
||||
rect.h = atlas.height + padding;
|
||||
rects.push_back(rect);
|
||||
}
|
||||
|
||||
stbrp_context context;
|
||||
std::vector<stbrp_node> nodes(size);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
stbrp_init_target(&context, size, size, nodes.data(), nodes.size());
|
||||
|
||||
if(stbrp_pack_rects(&context, rects.data(), rects.size()) == 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
size *= 2;
|
||||
nodes.resize(size);
|
||||
std::cout << "Error: failed to pack textures, trying again with size " << size << "\n";
|
||||
}
|
||||
|
||||
Atlas<4> atlas(size, size);
|
||||
|
||||
for(const stbrp_rect& rect : rects)
|
||||
{
|
||||
const Atlas<4>& src = texture_atlas_queue[rect.id];
|
||||
atlas.draw(src, rect.x + offset, rect.y + offset, true);
|
||||
|
||||
uvs.emplace_back(glm::mat2(
|
||||
(rect.x + offset + 0.5f) / size, (rect.y + offset + 0.5f) / size,
|
||||
(rect.x + offset + src.width - 0.5f) / size, (rect.y + offset + src.height - 0.5f) / size
|
||||
));
|
||||
}
|
||||
|
||||
std::cout << "Finished stitching " << size << "x" << size << " texture atlas\n";
|
||||
|
||||
glGenTextures(1, &atlas_texid);
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, atlas_texid);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, size, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, atlas.data.data());
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
glGenBuffers(1, &atlas_uv_ssbo);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, atlas_uv_ssbo);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, uvs.size() * sizeof(uvs[0]), uvs.data(), GL_STATIC_DRAW);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, atlas_uv_ssbo);
|
||||
|
||||
glUniform1i(Shader::MAIN["tex_atlas"], 1);
|
||||
|
||||
is_done = true;
|
||||
}
|
||||
|
||||
uint32_t Texture::load_mem(const uint8_t* data, int width, int height, int channels, int* swizzleMask)
|
||||
{
|
||||
if(is_done)
|
||||
{
|
||||
throw std::runtime_error("Texture loading is done");
|
||||
}
|
||||
|
||||
if(!data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int swizzleMaskDefault[] = {GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA};
|
||||
|
||||
if(!swizzleMask)
|
||||
{
|
||||
swizzleMask = swizzleMaskDefault;
|
||||
|
||||
switch(channels)
|
||||
{
|
||||
case 1:
|
||||
swizzleMask[1] = GL_ONE;
|
||||
case 2:
|
||||
swizzleMask[2] = GL_ONE;
|
||||
case 3:
|
||||
swizzleMask[3] = GL_ONE;
|
||||
}
|
||||
}
|
||||
|
||||
if(!Shader::USE_BINDLESS_TEXTURES)
|
||||
{
|
||||
Atlas<4> atlas(width, height);
|
||||
|
||||
for(int i = 0; i < width * height; i++)
|
||||
{
|
||||
int pixel_pos = i * channels;
|
||||
Atlas<4>::Pixel pixel;
|
||||
|
||||
for(int j = 0; j < 4; j++)
|
||||
{
|
||||
switch(swizzleMask[j])
|
||||
{
|
||||
case GL_RED:
|
||||
pixel[j] = data[pixel_pos];
|
||||
break;
|
||||
case GL_GREEN:
|
||||
pixel[j] = data[pixel_pos + 1];
|
||||
break;
|
||||
case GL_BLUE:
|
||||
pixel[j] = data[pixel_pos + 2];
|
||||
break;
|
||||
case GL_ALPHA:
|
||||
pixel[j] = data[pixel_pos + 3];
|
||||
break;
|
||||
case GL_ZERO:
|
||||
pixel[j] = 0;
|
||||
break;
|
||||
case GL_ONE:
|
||||
pixel[j] = 255;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
atlas.data[i] = pixel;
|
||||
}
|
||||
|
||||
texture_atlas_queue.push_back(std::move(atlas));
|
||||
return texture_atlas_queue.size() - 1;
|
||||
}
|
||||
|
||||
GLenum format;
|
||||
GLenum format_in;
|
||||
|
||||
switch(channels)
|
||||
{
|
||||
case 1:
|
||||
format = GL_RED;
|
||||
format_in = GL_R8;
|
||||
break;
|
||||
case 2:
|
||||
format = GL_RG;
|
||||
format_in = GL_RG8;
|
||||
break;
|
||||
case 3:
|
||||
format = GL_RGB;
|
||||
format_in = GL_RGB8;
|
||||
break;
|
||||
case 4:
|
||||
format = GL_RGBA;
|
||||
format_in = GL_RGBA8;
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Invalid number of channels: " + std::to_string(channels));
|
||||
}
|
||||
|
||||
unsigned int texid;
|
||||
|
||||
glGenTextures(1, &texid);
|
||||
glBindTexture(GL_TEXTURE_2D, texid);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, format_in, width, height, 0, format, GL_UNSIGNED_BYTE, data);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTextureParameteriv(texid, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
uint32_t handle = glGetTextureHandleARB(texid);
|
||||
glMakeTextureHandleResidentARB(handle);
|
||||
return handle;
|
||||
}
|
||||
|
||||
uint32_t Texture::load_mem(const uint8_t* filedata, size_t len)
|
||||
{
|
||||
int width, height, channels;
|
||||
unsigned char* data = stbi_load_from_memory(filedata, len, &width, &height, &channels, 0);
|
||||
uint64_t handle = load_mem(data, width, height, channels);
|
||||
stbi_image_free(data);
|
||||
return handle;
|
||||
}
|
||||
|
||||
uint32_t Texture::load(std::string path)
|
||||
{
|
||||
const auto it = loaded.find(path);
|
||||
|
||||
if(it != loaded.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
|
||||
int width, height, channels;
|
||||
unsigned char* data = stbi_load(path.c_str(), &width, &height, &channels, 0);
|
||||
uint64_t handle = load_mem(data, width, height, channels);
|
||||
stbi_image_free(data);
|
||||
|
||||
if(handle == 0)
|
||||
{
|
||||
throw std::runtime_error("Failed to load path: " + path);
|
||||
}
|
||||
|
||||
std::cout << "Loaded image: " << path << "\n";
|
||||
|
||||
loaded[path] = handle;
|
||||
return handle;
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include <string>
|
||||
#include <glm/vec2.hpp>
|
||||
|
||||
namespace Sim::Graphics::Data::Texture
|
||||
{
|
||||
|
||||
extern uint32_t handle_white;
|
||||
extern uint32_t handle_normal;
|
||||
|
||||
void init();
|
||||
void generate_atlas();
|
||||
uint32_t load(std::string path);
|
||||
uint32_t load_mem(const uint8_t* data, int width, int height, int channels, int* swizzleMask = nullptr);
|
||||
uint32_t load_mem(const uint8_t* data, size_t len);
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
|
||||
#include "generator.hpp"
|
||||
#include "../../system.hpp"
|
||||
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
using namespace Sim::Graphics::Equipment;
|
||||
using namespace Sim::Graphics::Data;
|
||||
|
||||
Generator::Generator(const Model& model)
|
||||
{
|
||||
g_rotor = model.load("visual_generator_rotor");
|
||||
}
|
||||
|
||||
void Generator::remesh_static(Mesh& rmesh)
|
||||
{
|
||||
rmesh.add(g_rotor);
|
||||
}
|
||||
|
||||
void Generator::get_static_transforms(std::vector<glm::mat4>& transforms)
|
||||
{
|
||||
Sim::System& sys = *Sim::System::active;
|
||||
glm::mat4 rot = glm::rotate(glm::mat4(1), (float)sys.loop.generator.get_phase() * 0.5f, glm::vec3(0, 0, 1));
|
||||
transforms.push_back(rot);
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "../data/meshgen.hpp"
|
||||
|
||||
namespace Sim::Graphics::Equipment
|
||||
{
|
||||
|
||||
class Generator : public Data::MeshGen
|
||||
{
|
||||
Data::Mesh g_rotor;
|
||||
|
||||
public:
|
||||
|
||||
Generator(const Data::Model& model);
|
||||
void get_static_transforms(std::vector<glm::mat4>& transforms) override;
|
||||
void remesh_static(Data::Mesh& rmesh) override;
|
||||
};
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
|
||||
#include "pool.hpp"
|
||||
#include "../../system.hpp"
|
||||
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
using namespace Sim::Graphics::Equipment;
|
||||
using namespace Sim::Graphics::Data;
|
||||
|
||||
Pool::Pool(const Model& model)
|
||||
{
|
||||
g_pool = model.load("visual_water");
|
||||
}
|
||||
|
||||
void Pool::remesh_static(Mesh& rmesh)
|
||||
{
|
||||
rmesh.add(g_pool);
|
||||
}
|
||||
|
||||
void Pool::get_static_transforms(std::vector<glm::mat4>& transforms)
|
||||
{
|
||||
Sim::System& sys = *Sim::System::active;
|
||||
double z = sys.pool.get_level_height();
|
||||
|
||||
if(z > 0.1)
|
||||
{
|
||||
transforms.push_back(glm::translate(glm::mat4(1), glm::vec3(0, 0, z - sys.pool.dimensions.z)));
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
// hacky solution to prevent z fighting with the bottom of the pool
|
||||
transforms.push_back(glm::mat4(0));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "../data/meshgen.hpp"
|
||||
|
||||
namespace Sim::Graphics::Equipment
|
||||
{
|
||||
|
||||
class Pool : public Data::MeshGen
|
||||
{
|
||||
Data::Mesh g_pool;
|
||||
|
||||
public:
|
||||
|
||||
Pool(const Data::Model& model);
|
||||
void get_static_transforms(std::vector<glm::mat4>& transforms) override;
|
||||
void remesh_static(Data::Mesh& rmesh) override;
|
||||
};
|
||||
|
||||
};
|
||||
|
|
@ -8,18 +8,30 @@
|
|||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
using namespace Sim::Graphics::Equipment;
|
||||
using namespace Sim::Graphics::Data;
|
||||
|
||||
Reactor::Reactor(const Model& model)
|
||||
{
|
||||
g_control_rod = model.load("visual_control_rod");
|
||||
g_control_rod_lift = model.load("visual_control_rod_lift");
|
||||
g_control_rod_base = model.load("visual_control_rod_base");
|
||||
}
|
||||
|
||||
void Reactor::remesh_static(Mesh& rmesh)
|
||||
{
|
||||
Sim::System& sys = *Sim::System::active;
|
||||
double t_step = sys.reactor.cell_width;
|
||||
double t_sx = -(sys.reactor.width - 1) * t_step / 2.0;
|
||||
double t_sy = -(sys.reactor.height - 1) * t_step / 2.0;
|
||||
|
||||
glm::mat4 mat_scale = glm::scale(glm::mat4(1), glm::vec3(t_step / 0.4));
|
||||
|
||||
for(int i = 0; i < sys.reactor.size; i++)
|
||||
{
|
||||
int x = i % sys.reactor.width;
|
||||
int y = i / sys.reactor.width;
|
||||
double ox = t_sx + x * t_step;
|
||||
double oy = t_sy + y * t_step;
|
||||
|
||||
Sim::Reactor::Rod* r = sys.reactor.rods[i].get();
|
||||
|
||||
if(!r->should_display())
|
||||
|
@ -29,9 +41,24 @@ void Reactor::remesh_static(Mesh& rmesh)
|
|||
|
||||
if(r->get_colour()[3] != 0)
|
||||
{
|
||||
Mesh m = g_control_rod;
|
||||
m.set_transform_id();
|
||||
rmesh.add(m);
|
||||
Mesh m1, m2;
|
||||
glm::mat4 m = glm::translate(glm::mat4(1), glm::vec3(ox, oy, 0)) * mat_scale;
|
||||
m1.add(g_control_rod_base, m);
|
||||
m2.add(g_control_rod_lift, m);
|
||||
m1.bake_transforms();
|
||||
m2.bake_transforms();
|
||||
m2.set_blank_transform();
|
||||
|
||||
for(int i = 0; i < m2.vertices.size(); i++)
|
||||
{
|
||||
if(g_control_rod_lift.vertices[i].pos.z == 0)
|
||||
{
|
||||
m2.vertices[i].transform_id = -1;
|
||||
}
|
||||
}
|
||||
|
||||
rmesh.add(m1);
|
||||
rmesh.add(m2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -40,17 +67,8 @@ void Reactor::get_static_transforms(std::vector<glm::mat4>& transforms)
|
|||
{
|
||||
Sim::System& sys = *Sim::System::active;
|
||||
|
||||
double t_step = sys.reactor.cell_width;
|
||||
double t_sx = -(sys.reactor.width - 1) * t_step / 2.0;
|
||||
double t_sy = -(sys.reactor.height - 1) * t_step / 2.0;
|
||||
|
||||
for(int i = 0; i < sys.reactor.size; i++)
|
||||
{
|
||||
int x = i % sys.reactor.width;
|
||||
int y = i / sys.reactor.width;
|
||||
double ox = t_sx + x * t_step;
|
||||
double oy = t_sy + y * t_step;
|
||||
|
||||
Sim::Reactor::Rod* r = sys.reactor.rods[i].get();
|
||||
|
||||
if(!r->should_display())
|
||||
|
@ -60,7 +78,7 @@ void Reactor::get_static_transforms(std::vector<glm::mat4>& transforms)
|
|||
|
||||
if(r->get_colour()[3] != 0)
|
||||
{
|
||||
transforms.push_back(glm::translate(glm::mat4(1), glm::vec3(ox, oy, (1 - r->get_colour().r) * sys.reactor.cell_height)));
|
||||
transforms.push_back(glm::translate(glm::mat4(1), glm::vec3(0, 0, (1 - r->get_colour().r) * sys.reactor.cell_height)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "../mesh/meshgen.hpp"
|
||||
#include "../data/meshgen.hpp"
|
||||
|
||||
namespace Sim::Graphics::Equipment
|
||||
{
|
||||
|
||||
class Reactor : public MeshGen
|
||||
class Reactor : public Data::MeshGen
|
||||
{
|
||||
Mesh g_control_rod;
|
||||
Data::Mesh g_control_rod_lift, g_control_rod_base;
|
||||
|
||||
public:
|
||||
|
||||
Reactor(const Model& model);
|
||||
virtual void get_static_transforms(std::vector<glm::mat4>& transforms);
|
||||
virtual void remesh_static(Mesh& rmesh);
|
||||
Reactor(const Data::Model& model);
|
||||
void get_static_transforms(std::vector<glm::mat4>& transforms) override;
|
||||
void remesh_static(Data::Mesh& rmesh) override;
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -24,6 +24,7 @@ static std::unique_ptr<Focus::FocusType> state = nullptr;
|
|||
static bool mouse_visible = false;
|
||||
static bool mouse_locked = false;
|
||||
static bool triggered = false;
|
||||
static bool triggered_release = false;
|
||||
|
||||
void Focus::on_keypress(int key, int sc, int action, int mods)
|
||||
{
|
||||
|
@ -53,8 +54,10 @@ void Focus::on_mouse_button(int button, int action, int mods)
|
|||
state->on_mouse_button(button, action, mods);
|
||||
}
|
||||
|
||||
if(button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS)
|
||||
if(button == GLFW_MOUSE_BUTTON_LEFT && (action == GLFW_RELEASE || action == GLFW_PRESS))
|
||||
{
|
||||
bool t = false;
|
||||
|
||||
if(is_mouse_locked() && mouse_visible)
|
||||
{
|
||||
double mx, my;
|
||||
|
@ -66,14 +69,21 @@ void Focus::on_mouse_button(int button, int action, int mods)
|
|||
|
||||
trigger_near = glm::unProject(glm::vec3(mouse, -1), Camera::get_matrix(), Window::projection_matrix, viewport);
|
||||
trigger_far = glm::unProject(glm::vec3(mouse, 1), Camera::get_matrix(), Window::projection_matrix, viewport);
|
||||
triggered = true;
|
||||
t = true;
|
||||
}
|
||||
|
||||
else if(!mouse_visible)
|
||||
{
|
||||
trigger_near = Camera::get_pos();
|
||||
trigger_far = trigger_near + Camera::get_normal();
|
||||
triggered = true;
|
||||
t = true;
|
||||
}
|
||||
|
||||
if(t)
|
||||
{
|
||||
t = (action == GLFW_PRESS);
|
||||
triggered_release = !t;
|
||||
triggered = t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -107,6 +117,7 @@ glm::vec<3, double> Focus::get_trigger_far()
|
|||
void Focus::update(double dt)
|
||||
{
|
||||
triggered = false;
|
||||
triggered_release = false;
|
||||
|
||||
bool c = is_mouse_locked();
|
||||
|
||||
|
@ -194,3 +205,8 @@ bool Focus::is_triggered()
|
|||
return triggered;
|
||||
}
|
||||
|
||||
bool Focus::is_triggered_release()
|
||||
{
|
||||
return triggered_release;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ struct FocusType
|
|||
bool is_focused();
|
||||
void clear_focus();
|
||||
bool is_triggered();
|
||||
bool is_triggered_release();
|
||||
bool is_mouse_locked();
|
||||
void clear_mouse_locked();
|
||||
glm::vec<3, double> get_trigger_near();
|
||||
|
|
|
@ -1,47 +0,0 @@
|
|||
|
||||
#include "locations.hpp"
|
||||
#include <glm/ext/matrix_transform.hpp>
|
||||
|
||||
using namespace Sim::Graphics;
|
||||
|
||||
const glm::mat4 Locations::monitors[7] = {
|
||||
(
|
||||
glm::translate(glm::mat4(1), glm::vec3(-2.9475, -1.7778 + 0.05, 3 - 0.05)) *
|
||||
glm::rotate(glm::mat4(1), glm::radians<float>(-90), glm::vec3(1, 0, 0)) *
|
||||
glm::rotate(glm::mat4(1), glm::radians<float>(-90), glm::vec3(0, 1, 0)) *
|
||||
glm::scale(glm::mat4(1), glm::vec3(1.9, 1.9, 1.9))
|
||||
),
|
||||
(
|
||||
glm::translate(glm::mat4(1), glm::vec3(-1.5 + 0.05, 3.9475, 3 - 0.05)) *
|
||||
glm::rotate(glm::mat4(1), glm::radians<float>(-90), glm::vec3(1, 0, 0)) *
|
||||
glm::scale(glm::mat4(1), glm::vec3(1.9, 1.9, 1.9))
|
||||
),
|
||||
(
|
||||
glm::translate(glm::mat4(1), glm::vec3(1 + 0.05, 3.9475, 3 - 0.05)) *
|
||||
glm::rotate(glm::mat4(1), glm::radians<float>(-90), glm::vec3(1, 0, 0)) *
|
||||
glm::scale(glm::mat4(1), glm::vec3(1.9, 1.9, 1.9))
|
||||
),
|
||||
(
|
||||
glm::translate(glm::mat4(1), glm::vec3(3.5 + 0.05, 3.9475, 3 - 0.05)) *
|
||||
glm::rotate(glm::mat4(1), glm::radians<float>(-90), glm::vec3(1, 0, 0)) *
|
||||
glm::scale(glm::mat4(1), glm::vec3(1.9, 1.9, 1.9))
|
||||
),
|
||||
(
|
||||
glm::translate(glm::mat4(1), glm::vec3(6 + 0.05, 3.9475, 3 - 0.05)) *
|
||||
glm::rotate(glm::mat4(1), glm::radians<float>(-90), glm::vec3(1, 0, 0)) *
|
||||
glm::scale(glm::mat4(1), glm::vec3(1.9, 1.9, 1.9))
|
||||
),
|
||||
(
|
||||
glm::translate(glm::mat4(1), glm::vec3(8.9475, 7.0/3.0 - 0.05, 3 - 0.05)) *
|
||||
glm::rotate(glm::mat4(1), glm::radians<float>(-90), glm::vec3(1, 0, 0)) *
|
||||
glm::rotate(glm::mat4(1), glm::radians<float>(90), glm::vec3(0, 1, 0)) *
|
||||
glm::scale(glm::mat4(1), glm::vec3(1.9, 1.9, 1.9))
|
||||
),
|
||||
(
|
||||
glm::translate(glm::mat4(1), glm::vec3(8.9475, -1.0/3.0 - 0.05, 3 - 0.05)) *
|
||||
glm::rotate(glm::mat4(1), glm::radians<float>(-90), glm::vec3(1, 0, 0)) *
|
||||
glm::rotate(glm::mat4(1), glm::radians<float>(90), glm::vec3(0, 1, 0)) *
|
||||
glm::scale(glm::mat4(1), glm::vec3(1.9, 1.9, 1.9))
|
||||
)
|
||||
};
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <glm/matrix.hpp>
|
||||
|
||||
namespace Sim::Graphics::Locations
|
||||
{
|
||||
|
||||
extern const glm::mat4 monitors[7];
|
||||
|
||||
};
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include <assimp/Importer.hpp>
|
||||
|
||||
#include "../shader.hpp"
|
||||
#include "arrays.hpp"
|
||||
#include "font.hpp"
|
||||
|
||||
using namespace Sim::Graphics;
|
||||
|
||||
static void* ptr_diff(void* a, void* b)
|
||||
{
|
||||
return (void*)((size_t)a - (size_t)b);
|
||||
}
|
||||
|
||||
void Arrays::vertex_attrib_pointers()
|
||||
{
|
||||
Vertex v;
|
||||
|
||||
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, 4, GL_FLOAT, false, sizeof(v), ptr_diff(&v.pos, &v));
|
||||
glEnableVertexAttribArray(2);
|
||||
|
||||
glVertexAttribPointer(3, 3, GL_FLOAT, false, sizeof(v), ptr_diff(&v.normal, &v));
|
||||
glEnableVertexAttribArray(3);
|
||||
|
||||
glVertexAttribPointer(4, 4, GL_FLOAT, false, sizeof(v), ptr_diff(&v.colour, &v));
|
||||
glEnableVertexAttribArray(4);
|
||||
|
||||
glVertexAttribPointer(5, 3, GL_FLOAT, false, sizeof(v), ptr_diff(&v.material, &v));
|
||||
glEnableVertexAttribArray(5);
|
||||
|
||||
glVertexAttribPointer(6, 1, GL_FLOAT, false, sizeof(v), ptr_diff(&v.transform_id, &v));
|
||||
glEnableVertexAttribArray(6);
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <glm/matrix.hpp>
|
||||
|
||||
namespace Sim::Graphics::Arrays
|
||||
{
|
||||
|
||||
struct Vertex
|
||||
{
|
||||
unsigned long texid = 0;
|
||||
glm::vec2 texpos = {0, 0};
|
||||
glm::vec4 pos = {0, 0, 0, 1};
|
||||
glm::vec3 normal = {0, 0, 0};
|
||||
glm::vec4 colour = {1, 1, 1, 1};
|
||||
glm::vec3 material = {0, 0, 0};
|
||||
float transform_id = -1;
|
||||
|
||||
constexpr bool operator==(const Vertex&) const = default;
|
||||
|
||||
} __attribute__((packed));
|
||||
|
||||
void vertex_attrib_pointers();
|
||||
|
||||
};
|
||||
|
|
@ -1,188 +0,0 @@
|
|||
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include <ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
|
||||
#include <glm/vec2.hpp>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "mesh.hpp"
|
||||
#include "arrays.hpp"
|
||||
#include "font.hpp"
|
||||
|
||||
using namespace Sim::Graphics;
|
||||
|
||||
struct Character
|
||||
{
|
||||
unsigned long handle;
|
||||
float advance;
|
||||
glm::vec2 size;
|
||||
glm::vec2 bearing;
|
||||
};
|
||||
|
||||
static Character 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, "../assets/font/DroidSans.ttf", 0, &face))
|
||||
{
|
||||
std::cout << "Error: failed to load freetype font\n";
|
||||
return;
|
||||
}
|
||||
|
||||
int size = 256;
|
||||
float m = 1.0f / size;
|
||||
|
||||
FT_Set_Pixel_Sizes(face, 0, size);
|
||||
|
||||
GLuint texids[128];
|
||||
std::vector<glm::vec<4, unsigned char>> pixels;
|
||||
|
||||
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";
|
||||
}
|
||||
|
||||
int width = face->glyph->bitmap.width;
|
||||
int height = face->glyph->bitmap.rows;
|
||||
int offx = face->glyph->bitmap_left;
|
||||
int offy = face->glyph->bitmap_top;
|
||||
|
||||
Character& c = chars[i];
|
||||
c.advance = face->glyph->advance.x * m / 64.0;
|
||||
c.size = {width * m, height * m};
|
||||
c.bearing = {offx * m, offy * m};
|
||||
|
||||
if(c.size.x == 0 || c.size.y == 0)
|
||||
{
|
||||
c.handle = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
pixels.resize(width * height);
|
||||
|
||||
for(int i = 0; i < width * height; i++)
|
||||
{
|
||||
pixels[i] = glm::vec<4, unsigned char>(face->glyph->bitmap.buffer[i]);
|
||||
}
|
||||
|
||||
glCreateTextures(GL_TEXTURE_2D, 1, &texids[i]);
|
||||
|
||||
glTextureStorage2D(texids[i], 1, GL_RGBA8, width, height);
|
||||
glTextureSubImage2D(texids[i], 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, &pixels[0]);
|
||||
|
||||
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_LINEAR);
|
||||
glTextureParameteri(texids[i], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
c.handle = glGetTextureHandleARB(texids[i]);
|
||||
glMakeTextureHandleResidentARB(c.handle);
|
||||
|
||||
chars[i] = c;
|
||||
}
|
||||
|
||||
FT_Done_FreeType(ft);
|
||||
}
|
||||
|
||||
void Mesh::load_text(const char* text, double size)
|
||||
{
|
||||
std::vector<Arrays::Vertex> vertices;
|
||||
std::vector<unsigned int> indices;
|
||||
|
||||
float x = 0, y = size;
|
||||
unsigned int at = 0;
|
||||
|
||||
if(text[0] == '\0')
|
||||
{
|
||||
this->vertices.clear();
|
||||
this->indices.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
for(unsigned int i = 0; text[i] != '\0'; i++)
|
||||
{
|
||||
char c = text[i];
|
||||
Character ch = chars[c];
|
||||
|
||||
if(c == '\n')
|
||||
{
|
||||
x = 0;
|
||||
y += size;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(ch.handle == 0)
|
||||
{
|
||||
x += ch.advance * size;
|
||||
continue;
|
||||
}
|
||||
|
||||
unsigned int index[6] = {
|
||||
at, at + 1, at + 3,
|
||||
at, at + 3, at + 2
|
||||
};
|
||||
|
||||
float sx = x + ch.bearing.x * size;
|
||||
float sy = y - ch.bearing.y * size;
|
||||
float ex = sx + ch.size.x * size;
|
||||
float ey = sy + ch.size.y * size;
|
||||
|
||||
vertices.push_back(Arrays::Vertex{.texid=ch.handle, .texpos={0, 0}, .pos={sx, sy, 0, 1}, .normal={0, 0, -1}, .material={0, 0, 1}});
|
||||
vertices.push_back(Arrays::Vertex{.texid=ch.handle, .texpos={0, 1}, .pos={sx, ey, 0, 1}, .normal={0, 0, -1}, .material={0, 0, 1}});
|
||||
vertices.push_back(Arrays::Vertex{.texid=ch.handle, .texpos={1, 0}, .pos={ex, sy, 0, 1}, .normal={0, 0, -1}, .material={0, 0, 1}});
|
||||
vertices.push_back(Arrays::Vertex{.texid=ch.handle, .texpos={1, 1}, .pos={ex, ey, 0, 1}, .normal={0, 0, -1}, .material={0, 0, 1}});
|
||||
indices.insert(indices.end(), &index[0], &index[6]);
|
||||
|
||||
at += 4;
|
||||
x += ch.advance * size;
|
||||
}
|
||||
|
||||
this->vertices = std::move(vertices);
|
||||
this->indices = std::move(indices);
|
||||
}
|
||||
|
||||
void Mesh::load_text(const char* text, double size, glm::vec2 align)
|
||||
{
|
||||
glm::vec2 max;
|
||||
|
||||
load_text(text, size);
|
||||
|
||||
for(Arrays::Vertex& v : vertices)
|
||||
{
|
||||
if(v.pos.x > max.x)
|
||||
{
|
||||
max.x = v.pos.x;
|
||||
}
|
||||
|
||||
if(v.pos.y > max.y)
|
||||
{
|
||||
max.y = v.pos.y;
|
||||
}
|
||||
}
|
||||
|
||||
align *= max;
|
||||
|
||||
for(Arrays::Vertex& v : vertices)
|
||||
{
|
||||
v.pos.x -= align.x;
|
||||
v.pos.y -= align.y;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "mesh.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
namespace Sim::Graphics::Font
|
||||
{
|
||||
|
||||
void init();
|
||||
|
||||
};
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include "gllight.hpp"
|
||||
#include "../shader.hpp"
|
||||
#include "../window.hpp"
|
||||
#include "texture.hpp"
|
||||
|
||||
#include <glm/ext/matrix_transform.hpp>
|
||||
#include <glm/ext/matrix_clip_space.hpp>
|
||||
|
||||
using namespace Sim::Graphics;
|
||||
|
||||
static glm::mat4 shadow_mats[6];
|
||||
|
||||
GLLight::GLLight(Light light) : light(light), size(1024)
|
||||
{
|
||||
glGenTextures(1, &id);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, id);
|
||||
|
||||
for(int i = 0; i < 6; i++)
|
||||
{
|
||||
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_DEPTH_COMPONENT, size, size, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);
|
||||
}
|
||||
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
glGenFramebuffers(1, &fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, id, 0);
|
||||
glDrawBuffer(GL_NONE);
|
||||
glReadBuffer(GL_NONE);
|
||||
|
||||
handle = glGetTextureHandleARB(id);
|
||||
glMakeTextureHandleResidentARB(handle);
|
||||
}
|
||||
|
||||
GLLight::GLLight(GLLight&& o) : light(o.light), size(o.size)
|
||||
{
|
||||
id = o.id;
|
||||
handle = o.handle;
|
||||
fbo = o.fbo;
|
||||
|
||||
o.id = 0;
|
||||
o.handle = 0;
|
||||
o.fbo = 0;
|
||||
}
|
||||
|
||||
GLLight::~GLLight()
|
||||
{
|
||||
if(fbo)
|
||||
glDeleteFramebuffers(1, &fbo);
|
||||
if(id)
|
||||
glDeleteTextures(1, &id);
|
||||
}
|
||||
|
||||
void GLLight::render()
|
||||
{
|
||||
glm::mat4 camera_mat = glm::translate(glm::mat4(1), -light.pos);
|
||||
glUniformMatrix4fv(Shader::LIGHT["camera"], 1, false, &camera_mat[0][0]);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||
glViewport(0, 0, size, size);
|
||||
Window::render_scene();
|
||||
}
|
||||
|
||||
void GLLight::init()
|
||||
{
|
||||
glm::mat4 shadow_proj = glm::perspective<float>(M_PI * 0.5f, 1.0f, 0.01f, 100.f);
|
||||
|
||||
shadow_mats[0] = shadow_proj * glm::lookAt(glm::vec3(0), { 1, 0, 0}, {0,-1, 0});
|
||||
shadow_mats[1] = shadow_proj * glm::lookAt(glm::vec3(0), {-1, 0, 0}, {0,-1, 0});
|
||||
shadow_mats[2] = shadow_proj * glm::lookAt(glm::vec3(0), { 0, 1, 0}, {0, 0, 1});
|
||||
shadow_mats[3] = shadow_proj * glm::lookAt(glm::vec3(0), { 0,-1, 0}, {0, 0,-1});
|
||||
shadow_mats[4] = shadow_proj * glm::lookAt(glm::vec3(0), { 0, 0, 1}, {0,-1, 0});
|
||||
shadow_mats[5] = shadow_proj * glm::lookAt(glm::vec3(0), { 0, 0,-1}, {0,-1, 0});
|
||||
|
||||
glUniformMatrix4fv(Shader::LIGHT["shadow_mats"], 6, false, &shadow_mats[0][0][0]);
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "light.hpp"
|
||||
|
||||
namespace Sim::Graphics
|
||||
{
|
||||
|
||||
struct GLLight
|
||||
{
|
||||
const int size;
|
||||
|
||||
unsigned int id, fbo;
|
||||
unsigned long handle;
|
||||
Light light;
|
||||
|
||||
GLLight(Light light);
|
||||
GLLight(GLLight&& o);
|
||||
GLLight(const GLLight& o) = delete;
|
||||
~GLLight();
|
||||
|
||||
static void init();
|
||||
|
||||
void render();
|
||||
};
|
||||
|
||||
};
|
||||
|
|
@ -1,52 +0,0 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <glm/matrix.hpp>
|
||||
|
||||
#include "arrays.hpp"
|
||||
#include "light.hpp"
|
||||
|
||||
namespace Sim::Graphics
|
||||
{
|
||||
|
||||
struct Mesh
|
||||
{
|
||||
std::vector<Arrays::Vertex> vertices;
|
||||
std::vector<unsigned int> indices;
|
||||
float max_transform_id = -1;
|
||||
|
||||
Mesh();
|
||||
|
||||
void set_transform_id();
|
||||
void set_vertices(const Arrays::Vertex* data, size_t size);
|
||||
void set_indices(const unsigned int* data, size_t size);
|
||||
void load_text(const char* text, double size);
|
||||
void load_text(const char* text, double size, glm::vec2 align);
|
||||
void add(const Mesh& o, glm::mat4 mat);
|
||||
void add(const Mesh& o);
|
||||
|
||||
Mesh to_lines() const;
|
||||
bool check_focus() const;
|
||||
bool check_focus(double len) const;
|
||||
bool check_intersect(glm::vec<3, double> pos, glm::vec<3, double> path) const;
|
||||
glm::vec<3, double> calc_intersect(glm::vec<3, double> pos, glm::vec<3, double> path) const;
|
||||
|
||||
bool operator==(const Mesh&) const = default;
|
||||
|
||||
template <class T>
|
||||
void load_text(const char* header, T& item, double size)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << header << item;
|
||||
load_text(ss.str().c_str(), size);
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <stb/stb_image.h>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <iostream>
|
||||
|
||||
#include "texture.hpp"
|
||||
|
||||
using namespace Sim::Graphics;
|
||||
|
||||
static std::unordered_map<std::string, unsigned int> loaded;
|
||||
unsigned int Texture::handle_white;
|
||||
|
||||
void Texture::init()
|
||||
{
|
||||
unsigned char pixels[] = {255, 255, 255, 255};
|
||||
handle_white = load_mem(pixels, 1, 1, 4);
|
||||
}
|
||||
|
||||
unsigned int Texture::load_mem(const unsigned char* data, int width, int height, int channels)
|
||||
{
|
||||
if(!data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
GLenum format, format_in;
|
||||
switch(channels)
|
||||
{
|
||||
case 1:
|
||||
format = GL_RED;
|
||||
format_in = GL_R8;
|
||||
break;
|
||||
case 2:
|
||||
format = GL_RG;
|
||||
format_in = GL_RG8;
|
||||
break;
|
||||
case 3:
|
||||
format = GL_RGB;
|
||||
format_in = GL_RGB8;
|
||||
break;
|
||||
case 4:
|
||||
format = GL_RGBA;
|
||||
format_in = GL_RGBA8;
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned int texid;
|
||||
|
||||
glCreateTextures(GL_TEXTURE_2D, 1, &texid);
|
||||
glTextureStorage2D(texid, 1, format_in, width, height);
|
||||
glTextureSubImage2D(texid, 0, 0, 0, width, height, format, GL_UNSIGNED_BYTE, data);
|
||||
|
||||
glTextureParameteri(texid, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTextureParameteri(texid, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTextureParameteri(texid, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTextureParameteri(texid, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glGenerateTextureMipmap(texid);
|
||||
|
||||
unsigned int handle = glGetTextureHandleARB(texid);
|
||||
glMakeTextureHandleResidentARB(handle);
|
||||
return handle;
|
||||
}
|
||||
|
||||
unsigned int Texture::load_mem(const unsigned char* filedata, size_t len)
|
||||
{
|
||||
int width, height, channels;
|
||||
unsigned char* data = stbi_load_from_memory(filedata, len, &width, &height, &channels, 0);
|
||||
unsigned int handle = load_mem(data, width, height, channels);
|
||||
stbi_image_free(data);
|
||||
return handle;
|
||||
}
|
||||
|
||||
unsigned int Texture::load(std::string path)
|
||||
{
|
||||
const auto it = loaded.find(path);
|
||||
|
||||
if(it != loaded.end())
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
|
||||
int width, height, channels;
|
||||
unsigned char* data = stbi_load(path.c_str(), &width, &height, &channels, 0);
|
||||
unsigned int handle = load_mem(data, width, height, channels);
|
||||
stbi_image_free(data);
|
||||
|
||||
if(handle == 0)
|
||||
{
|
||||
throw std::runtime_error("Failed to load path: " + path);
|
||||
}
|
||||
|
||||
std::cout << "Loaded image: " << path << "\n";
|
||||
|
||||
loaded[path] = handle;
|
||||
return handle;
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Sim::Graphics::Texture
|
||||
{
|
||||
|
||||
extern unsigned int handle_white;
|
||||
|
||||
void init();
|
||||
unsigned int load(std::string path);
|
||||
unsigned int load_mem(const unsigned char* data, int width, int height, int channels);
|
||||
unsigned int load_mem(const unsigned char* data, size_t len);
|
||||
|
||||
};
|
||||
|
|
@ -0,0 +1,313 @@
|
|||
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include <glm/ext/matrix_transform.hpp>
|
||||
#include <glm/ext/matrix_clip_space.hpp>
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include "cctv.hpp"
|
||||
#include "../shader.hpp"
|
||||
#include "../window.hpp"
|
||||
#include "../camera.hpp"
|
||||
#include "../input/focus.hpp"
|
||||
#include "../data/texture.hpp"
|
||||
#include "../data/font.hpp"
|
||||
#include "../../system.hpp"
|
||||
#include "../../util/math.hpp"
|
||||
#include "../../util/streams.hpp"
|
||||
|
||||
#define HEIGHT 512
|
||||
|
||||
using namespace Sim::Graphics::Monitor;
|
||||
using namespace Sim::Graphics::Data;
|
||||
using namespace Sim::Graphics;
|
||||
using namespace Sim;
|
||||
|
||||
class FocusCCTV : public Focus::FocusType
|
||||
{
|
||||
CCTV* parent;
|
||||
|
||||
int zoom = 0;
|
||||
int rot_pitch = 0;
|
||||
int rot_yaw = 0;
|
||||
|
||||
public:
|
||||
|
||||
FocusCCTV(CCTV* parent)
|
||||
{
|
||||
this->parent = parent;
|
||||
}
|
||||
|
||||
virtual void update(double dt)
|
||||
{
|
||||
if(rot_pitch || rot_yaw)
|
||||
{
|
||||
parent->rotate(dt, rot_pitch, -rot_yaw);
|
||||
}
|
||||
|
||||
if(zoom)
|
||||
{
|
||||
Data::Camera& active = parent->cameras[parent->camera_at];
|
||||
active.zoom = Util::Math::clamp(active.zoom - zoom * dt * 0.5f, 0.25, 1);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void on_keypress(int key, int sc, int action, int mods)
|
||||
{
|
||||
if(action == GLFW_PRESS)
|
||||
{
|
||||
switch(key)
|
||||
{
|
||||
case GLFW_KEY_KP_1:
|
||||
parent->camera_at = (parent->camera_at + parent->cameras.size() - 1) % parent->cameras.size();
|
||||
break;
|
||||
case GLFW_KEY_KP_2:
|
||||
parent->powered = !parent->powered;
|
||||
break;
|
||||
case GLFW_KEY_KP_3:
|
||||
parent->camera_at = (parent->camera_at + 1) % parent->cameras.size();
|
||||
break;
|
||||
case GLFW_KEY_KP_4:
|
||||
rot_yaw += 1;
|
||||
break;
|
||||
case GLFW_KEY_KP_5:
|
||||
rot_pitch -= 1;
|
||||
break;
|
||||
case GLFW_KEY_KP_6:
|
||||
rot_yaw -= 1;
|
||||
break;
|
||||
case GLFW_KEY_KP_7:
|
||||
zoom += 1;
|
||||
break;
|
||||
case GLFW_KEY_KP_8:
|
||||
rot_pitch += 1;
|
||||
break;
|
||||
case GLFW_KEY_KP_9:
|
||||
zoom -= 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
else if(action == GLFW_RELEASE)
|
||||
{
|
||||
switch(key)
|
||||
{
|
||||
case GLFW_KEY_KP_4:
|
||||
rot_yaw -= 1;
|
||||
break;
|
||||
case GLFW_KEY_KP_5:
|
||||
rot_pitch += 1;
|
||||
break;
|
||||
case GLFW_KEY_KP_6:
|
||||
rot_yaw += 1;
|
||||
break;
|
||||
case GLFW_KEY_KP_7:
|
||||
zoom -= 1;
|
||||
break;
|
||||
case GLFW_KEY_KP_8:
|
||||
rot_pitch -= 1;
|
||||
break;
|
||||
case GLFW_KEY_KP_9:
|
||||
zoom += 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CCTV::CCTV(Model& model)
|
||||
: height(HEIGHT)
|
||||
, width(HEIGHT * 16 / 9)
|
||||
, cameras(model.cameras)
|
||||
{
|
||||
m_buttons[0] = model.load("click_cctv_numpad_1");
|
||||
m_buttons[1] = model.load("click_cctv_numpad_2");
|
||||
m_buttons[2] = model.load("click_cctv_numpad_3");
|
||||
m_buttons[3] = model.load("click_cctv_numpad_4");
|
||||
m_buttons[4] = model.load("click_cctv_numpad_5");
|
||||
m_buttons[5] = model.load("click_cctv_numpad_6");
|
||||
m_buttons[6] = model.load("click_cctv_numpad_7");
|
||||
m_buttons[7] = model.load("click_cctv_numpad_8");
|
||||
m_buttons[8] = model.load("click_cctv_numpad_9");
|
||||
|
||||
glGenFramebuffers(1, &fbo);
|
||||
glGenTextures(1, &texture);
|
||||
glGenRenderbuffers(1, &rbo_depth);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, rbo_depth);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo_depth);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
|
||||
|
||||
handle = glGetTextureHandleARB(texture);
|
||||
glMakeTextureHandleResidentARB(handle);
|
||||
|
||||
mat = model.load_matrix("translation_monitor_1");
|
||||
m_screen.vertices = {
|
||||
{.texpos={0, 1}, .pos={0, 0, 0}, .transform_id=0, .tex_diffuse=handle, .material={0, 0, 1}},
|
||||
{.texpos={0, 0}, .pos={0, 1, 0}, .transform_id=0, .tex_diffuse=handle, .material={0, 0, 1}},
|
||||
{.texpos={1, 1}, .pos={1, 0, 0}, .transform_id=0, .tex_diffuse=handle, .material={0, 0, 1}},
|
||||
{.texpos={1, 0}, .pos={1, 1, 0}, .transform_id=0, .tex_diffuse=handle, .material={0, 0, 1}},
|
||||
};
|
||||
m_screen.indices = {0, 1, 3, 0, 3, 2};
|
||||
m_screen.transforms = {mat};
|
||||
m_screen.bake_transforms();
|
||||
|
||||
gm_screen.bind();
|
||||
gm_screen.set(m_screen, GL_STATIC_DRAW);
|
||||
}
|
||||
|
||||
CCTV::~CCTV()
|
||||
{
|
||||
if(fbo) glDeleteFramebuffers(1, &fbo);
|
||||
if(texture) glDeleteTextures(1, &texture);
|
||||
if(rbo_depth) glDeleteRenderbuffers(1, &rbo_depth);
|
||||
}
|
||||
|
||||
CCTV::CCTV(CCTV&& o)
|
||||
: width(o.width)
|
||||
, height(o.height)
|
||||
, cameras(std::move(o.cameras))
|
||||
, gm_screen(std::move(o.gm_screen))
|
||||
, m_screen(std::move(o.m_screen))
|
||||
, m_buttons(std::move(o.m_buttons))
|
||||
, powered(o.powered)
|
||||
{
|
||||
fbo = o.fbo;
|
||||
texture = o.texture;
|
||||
rbo_depth = o.rbo_depth;
|
||||
handle = o.handle;
|
||||
|
||||
o.fbo = 0;
|
||||
o.texture = 0;
|
||||
o.rbo_depth = 0;
|
||||
o.handle = 0;
|
||||
}
|
||||
|
||||
void CCTV::rotate(double dt, float pitch, float yaw)
|
||||
{
|
||||
Data::Camera& active = cameras[camera_at];
|
||||
float m = float(M_PI) * dt * 0.5f * active.zoom;
|
||||
|
||||
active.pitch = Util::Math::clamp(active.pitch + pitch * m, -M_PI / 4, M_PI / 4);
|
||||
active.yaw = Util::Math::clamp(active.yaw + yaw * m, -M_PI / 4, M_PI / 4);
|
||||
}
|
||||
|
||||
void CCTV::remesh_slow(Data::Mesh& rmesh)
|
||||
{
|
||||
if(!powered)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const Data::Camera& active = cameras[camera_at];
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "- ";
|
||||
|
||||
for(int i = 0; i < cameras.size(); i++)
|
||||
{
|
||||
if(i == camera_at)
|
||||
{
|
||||
ss << "[" << cameras[i].name << "] ";
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
ss << " " << cameras[i].name << " ";
|
||||
}
|
||||
}
|
||||
|
||||
ss << "-\n";
|
||||
|
||||
rmesh.add(Data::Fonts::MONO.load_text(ss.str(), 0.02, {0.5, 0}), glm::translate(mat, {0.5, 0.95, 0}), true);
|
||||
|
||||
char zoom_chars[] = " ";
|
||||
zoom_chars[(int)std::round(Util::Math::ramp(active.zoom, 1, 0.25, 0, 9))] = '#';
|
||||
|
||||
ss.str("");
|
||||
ss << "Zoom: [" << zoom_chars << "]";
|
||||
|
||||
rmesh.add(Data::Fonts::MONO.load_text(ss.str(), 0.02), glm::translate(mat, {0.0125, 0.0125, 0}), true);
|
||||
}
|
||||
|
||||
void CCTV::update(double dt)
|
||||
{
|
||||
Data::Camera& active = cameras[camera_at];
|
||||
|
||||
if(m_screen.check_focus())
|
||||
Focus::set(std::make_unique<FocusCCTV>(this));
|
||||
if(m_buttons[0].check_focus_hold())
|
||||
active.zoom = Util::Math::clamp(active.zoom - dt * 0.5f, 0.25, 1);
|
||||
if(m_buttons[1].check_focus_hold())
|
||||
rotate(dt, 1, 0);
|
||||
if(m_buttons[2].check_focus_hold())
|
||||
active.zoom = Util::Math::clamp(active.zoom + dt * 0.5f, 0.25, 1);
|
||||
if(m_buttons[3].check_focus_hold())
|
||||
rotate(dt, 0, -1);
|
||||
if(m_buttons[4].check_focus_hold())
|
||||
rotate(dt, -1, 0);
|
||||
if(m_buttons[5].check_focus_hold())
|
||||
rotate(dt, 0, 1);
|
||||
if(m_buttons[6].check_focus())
|
||||
camera_at = (camera_at + cameras.size() - 1) % cameras.size();
|
||||
if(m_buttons[7].check_focus())
|
||||
powered = !powered;
|
||||
if(m_buttons[8].check_focus())
|
||||
camera_at = (camera_at + 1) % cameras.size();
|
||||
}
|
||||
|
||||
void CCTV::render_view()
|
||||
{
|
||||
if(!powered)
|
||||
return;
|
||||
|
||||
Data::Camera& active = cameras[camera_at];
|
||||
|
||||
glm::mat4 rot = glm::mat4(1);
|
||||
glm::vec3 right = glm::normalize(glm::cross(active.look, active.up));
|
||||
rot = glm::rotate(rot, -active.yaw, active.up);
|
||||
rot = glm::rotate(rot, active.pitch, right);
|
||||
|
||||
glm::mat4 view = glm::lookAt(active.pos, active.pos + glm::mat3(rot) * active.look, active.up);
|
||||
glm::mat4 proj = glm::perspective(active.fov * active.zoom, (float)width / height, 0.1f, 100.0f);
|
||||
glm::vec3 brightness = glm::vec3(System::active->grid.get_light_intensity());
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
glViewport(0, 0, width, height);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glFrontFace(GL_CCW);
|
||||
|
||||
glUniformMatrix4fv(Shader::MAIN["projection"], 1, false, &proj[0][0]);
|
||||
glUniformMatrix4fv(Shader::MAIN["camera"], 1, false, &view[0][0]);
|
||||
glUniform3fv(Shader::MAIN["camera_pos"], 1, &active.pos[0]);
|
||||
|
||||
Window::bind_scene_ssbo();
|
||||
Window::render_scene();
|
||||
Window::render_dynamic();
|
||||
Window::render_player();
|
||||
}
|
||||
|
||||
void CCTV::render_screen()
|
||||
{
|
||||
if(!powered)
|
||||
return;
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glBlendFunc(GL_SRC_COLOR, GL_ONE);
|
||||
|
||||
gm_screen.bind();
|
||||
gm_screen.render();
|
||||
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <glm/matrix.hpp>
|
||||
|
||||
#include <vector>
|
||||
#include <array>
|
||||
|
||||
#include "../data/meshgen.hpp"
|
||||
#include "../data/camera.hpp"
|
||||
#include "../data/glmesh.hpp"
|
||||
|
||||
namespace Sim::Graphics::Monitor
|
||||
{
|
||||
|
||||
class CCTV : public Data::MeshGen
|
||||
{
|
||||
Data::GLMesh gm_screen;
|
||||
Data::Mesh m_screen;
|
||||
std::array<Data::Mesh, 9> m_buttons;
|
||||
|
||||
unsigned int fbo;
|
||||
unsigned int texture;
|
||||
unsigned int rbo_depth;
|
||||
unsigned int handle;
|
||||
|
||||
const int width;
|
||||
const int height;
|
||||
|
||||
public:
|
||||
|
||||
glm::mat4 mat;
|
||||
std::vector<Data::Camera> cameras;
|
||||
int camera_at = 0;
|
||||
bool powered = false;
|
||||
|
||||
CCTV(Data::Model& model);
|
||||
CCTV(const CCTV&) = delete;
|
||||
CCTV(CCTV&&);
|
||||
~CCTV();
|
||||
|
||||
void update(double dt) override;
|
||||
void remesh_slow(Data::Mesh& rmesh) override;
|
||||
void rotate(double dt, float pitch, float yaw);
|
||||
void render_view();
|
||||
void render_screen();
|
||||
};
|
||||
|
||||
};
|
||||
|
|
@ -3,12 +3,12 @@
|
|||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include "core.hpp"
|
||||
#include "../locations.hpp"
|
||||
#include "../input/focus.hpp"
|
||||
#include "../mesh/arrays.hpp"
|
||||
#include "../mesh/texture.hpp"
|
||||
#include "../data/arrays.hpp"
|
||||
#include "../data/texture.hpp"
|
||||
#include "../../system.hpp"
|
||||
#include "../../util/streams.hpp"
|
||||
#include "../data/font.hpp"
|
||||
|
||||
#include <glm/ext/matrix_transform.hpp>
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
|||
using namespace Sim;
|
||||
using namespace Sim::Graphics;
|
||||
using namespace Sim::Graphics::Monitor;
|
||||
using namespace Sim::Graphics::Data;
|
||||
using namespace Sim::Util::Streams;
|
||||
|
||||
static void set_all(bool state)
|
||||
|
@ -66,7 +67,7 @@ struct CoreMonitor : public Focus::FocusType
|
|||
sys.reactor.move_cursor(-1);
|
||||
break;
|
||||
case GLFW_KEY_KP_5:
|
||||
sys.reactor.toggle_selected();
|
||||
sys.reactor.move_cursor(sys.reactor.height);
|
||||
break;
|
||||
case GLFW_KEY_KP_6:
|
||||
sys.reactor.move_cursor(1);
|
||||
|
@ -75,7 +76,7 @@ struct CoreMonitor : public Focus::FocusType
|
|||
sys.reactor.reset_rod_speed();
|
||||
break;
|
||||
case GLFW_KEY_KP_2:
|
||||
sys.reactor.move_cursor(sys.reactor.height);
|
||||
sys.reactor.toggle_selected();
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
|
@ -118,16 +119,16 @@ struct CoreJoystick : public Focus::FocusType
|
|||
|
||||
Core::Core(const Model& model)
|
||||
{
|
||||
mat = Locations::monitors[2];
|
||||
m_buttons[0] = model.load("click_numpad_1");
|
||||
m_buttons[1] = model.load("click_numpad_2");
|
||||
m_buttons[2] = model.load("click_numpad_3");
|
||||
m_buttons[3] = model.load("click_numpad_4");
|
||||
m_buttons[4] = model.load("click_numpad_5");
|
||||
m_buttons[5] = model.load("click_numpad_6");
|
||||
m_buttons[6] = model.load("click_numpad_7");
|
||||
m_buttons[7] = model.load("click_numpad_8");
|
||||
m_buttons[8] = model.load("click_numpad_9");
|
||||
mat = model.load_matrix("translation_monitor_3");
|
||||
m_buttons[0] = model.load("click_reactor_numpad_1");
|
||||
m_buttons[1] = model.load("click_reactor_numpad_2");
|
||||
m_buttons[2] = model.load("click_reactor_numpad_3");
|
||||
m_buttons[3] = model.load("click_reactor_numpad_4");
|
||||
m_buttons[4] = model.load("click_reactor_numpad_5");
|
||||
m_buttons[5] = model.load("click_reactor_numpad_6");
|
||||
m_buttons[6] = model.load("click_reactor_numpad_7");
|
||||
m_buttons[7] = model.load("click_reactor_numpad_8");
|
||||
m_buttons[8] = model.load("click_reactor_numpad_9");
|
||||
m_joystick = model.load("click_reactor_joystick");
|
||||
m_monitor = model.load("translation_monitor_3");
|
||||
m_scram = model.load("click_scram");
|
||||
|
@ -135,24 +136,21 @@ Core::Core(const Model& model)
|
|||
|
||||
void Core::remesh_static(Mesh& rmesh)
|
||||
{
|
||||
Mesh mesh;
|
||||
mesh.load_text("Reactor Core", 0.04);
|
||||
rmesh.add(mesh, mat);
|
||||
rmesh.add(Data::Fonts::BASE.load_text("Reactor Core", 0.04), mat, true);
|
||||
}
|
||||
|
||||
static Mesh add_dot(glm::mat4 model_mat, glm::vec4 colour)
|
||||
static Data::Mesh add_dot(glm::mat4 model_mat, glm::vec4 colour)
|
||||
{
|
||||
unsigned int indices[] = {0, 1, 3, 0, 3, 2};
|
||||
Arrays::Vertex vertices[] = {
|
||||
{.texid=Texture::handle_white, .texpos={0, 0}, .pos=model_mat * glm::vec4(-0.75, -0.75, 0, 1), .normal={0, 0, -1}, .colour=colour, .material={0, 0, 1}},
|
||||
{.texid=Texture::handle_white, .texpos={0, 1}, .pos=model_mat * glm::vec4(-0.75, 0.75, 0, 1), .normal={0, 0, -1}, .colour=colour, .material={0, 0, 1}},
|
||||
{.texid=Texture::handle_white, .texpos={1, 0}, .pos=model_mat * glm::vec4( 0.75, -0.75, 0, 1), .normal={0, 0, -1}, .colour=colour, .material={0, 0, 1}},
|
||||
{.texid=Texture::handle_white, .texpos={1, 1}, .pos=model_mat * glm::vec4( 0.75, 0.75, 0, 1), .normal={0, 0, -1}, .colour=colour, .material={0, 0, 1}},
|
||||
Data::Mesh mesh;
|
||||
|
||||
mesh.indices = {0, 1, 3, 0, 3, 2};
|
||||
mesh.vertices = {
|
||||
{.texpos={0, 0}, .pos=glm::vec3(model_mat * glm::vec4(-0.75, -0.75, 0, 1)), .colour=colour, .material={0, 0, 1}},
|
||||
{.texpos={0, 1}, .pos=glm::vec3(model_mat * glm::vec4(-0.75, 0.75, 0, 1)), .colour=colour, .material={0, 0, 1}},
|
||||
{.texpos={1, 0}, .pos=glm::vec3(model_mat * glm::vec4( 0.75, -0.75, 0, 1)), .colour=colour, .material={0, 0, 1}},
|
||||
{.texpos={1, 1}, .pos=glm::vec3(model_mat * glm::vec4( 0.75, 0.75, 0, 1)), .colour=colour, .material={0, 0, 1}},
|
||||
};
|
||||
|
||||
Mesh mesh;
|
||||
mesh.set_indices(indices, 6);
|
||||
mesh.set_vertices(vertices, 4);
|
||||
return mesh;
|
||||
}
|
||||
|
||||
|
@ -175,21 +173,21 @@ void Core::update(double dt)
|
|||
if(m_buttons[3].check_focus())
|
||||
sys.reactor.move_cursor(-1);
|
||||
if(m_buttons[4].check_focus())
|
||||
sys.reactor.toggle_selected();
|
||||
sys.reactor.move_cursor(sys.reactor.height);
|
||||
if(m_buttons[5].check_focus())
|
||||
sys.reactor.move_cursor(1);
|
||||
if(m_buttons[6].check_focus())
|
||||
sys.reactor.reset_rod_speed();
|
||||
if(m_buttons[7].check_focus())
|
||||
sys.reactor.move_cursor(sys.reactor.height);
|
||||
sys.reactor.toggle_selected();
|
||||
}
|
||||
|
||||
void Core::remesh_slow(Mesh& rmesh)
|
||||
{
|
||||
Sim::System& sys = *System::active;
|
||||
Sim::Graphics::Mesh mesh;
|
||||
Sim::Graphics::Data::Mesh mesh;
|
||||
|
||||
double step = 1 / (sys.vessel.diameter / sys.reactor.cell_width * 0.8);
|
||||
double step = sys.reactor.cell_width / sys.vessel.diameter * 0.8;
|
||||
double sx = 0.5 - (sys.reactor.width - 1) * step / 2.0;
|
||||
double sy = 0.5 - (sys.reactor.height - 1) * step / 2.0;
|
||||
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "../mesh/model.hpp"
|
||||
#include "../mesh/meshgen.hpp"
|
||||
#include "../data/model.hpp"
|
||||
#include "../data/meshgen.hpp"
|
||||
|
||||
namespace Sim::Graphics::Monitor
|
||||
{
|
||||
|
||||
class Core : public MeshGen
|
||||
class Core : public Data::MeshGen
|
||||
{
|
||||
glm::mat4 mat;
|
||||
|
||||
Mesh m_monitor;
|
||||
Mesh m_buttons[9];
|
||||
Mesh m_joystick;
|
||||
Mesh m_scram;
|
||||
Data::Mesh m_monitor;
|
||||
Data::Mesh m_buttons[9];
|
||||
Data::Mesh m_joystick;
|
||||
Data::Mesh m_scram;
|
||||
|
||||
public:
|
||||
|
||||
Core(const Model& model);
|
||||
virtual void update(double dt);
|
||||
virtual void remesh_static(Mesh& rmesh);
|
||||
virtual void remesh_slow(Mesh& rmesh);
|
||||
Core(const Data::Model& model);
|
||||
void update(double dt) override;
|
||||
void remesh_static(Data::Mesh& rmesh) override;
|
||||
void remesh_slow(Data::Mesh& rmesh) override;
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -3,17 +3,18 @@
|
|||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include "primary_loop.hpp"
|
||||
#include "../locations.hpp"
|
||||
#include "../../system.hpp"
|
||||
#include "../../coolant/valve.hpp"
|
||||
#include "../input/focus.hpp"
|
||||
#include "../../util/streams.hpp"
|
||||
#include "../data/font.hpp"
|
||||
|
||||
#include <glm/ext/matrix_transform.hpp>
|
||||
#include <iostream>
|
||||
|
||||
using namespace Sim::Graphics;
|
||||
using namespace Sim::Graphics::Monitor;
|
||||
using namespace Sim::Graphics::Data;
|
||||
using namespace Sim::Util::Streams;
|
||||
|
||||
struct ValveJoystick : public Focus::FocusType
|
||||
|
@ -51,7 +52,7 @@ struct ValveJoystick : public Focus::FocusType
|
|||
|
||||
PrimaryLoop::PrimaryLoop(const Model& model)
|
||||
{
|
||||
mat = Locations::monitors[3];
|
||||
mat = model.load_matrix("translation_monitor_4");
|
||||
|
||||
g_switch_pump = model.load("visual_pump_switch_1");
|
||||
g_switch_bypass = model.load("visual_bypass_switch");
|
||||
|
@ -62,16 +63,11 @@ PrimaryLoop::PrimaryLoop(const Model& model)
|
|||
m_switch_pump = model.load("click_pump_switch_1");
|
||||
m_switch_bypass = model.load("click_bypass_switch");
|
||||
m_switch_inlet = model.load("click_inlet_switch");
|
||||
|
||||
g_switch_pump.set_transform_id();
|
||||
g_switch_bypass.set_transform_id();
|
||||
g_switch_inlet.set_transform_id();
|
||||
}
|
||||
|
||||
void PrimaryLoop::remesh_static(Mesh& rmesh)
|
||||
{
|
||||
std::stringstream ss;
|
||||
Mesh mesh;
|
||||
|
||||
ss << "Turbine Bypass Valve\n\n";
|
||||
ss << "Opened\nFlow\nSetpoint\n\n";
|
||||
|
@ -85,8 +81,7 @@ void PrimaryLoop::remesh_static(Mesh& rmesh)
|
|||
ss << "Pressure\n";
|
||||
ss << "Level\n";
|
||||
|
||||
mesh.load_text(ss.str().c_str(), 0.04);
|
||||
rmesh.add(mesh, mat);
|
||||
rmesh.add(Data::Fonts::BASE.load_text(ss.str(), 0.04), mat, true);
|
||||
|
||||
rmesh.add(g_switch_pump);
|
||||
rmesh.add(g_switch_bypass);
|
||||
|
@ -112,7 +107,6 @@ void PrimaryLoop::update(double dt)
|
|||
void PrimaryLoop::remesh_slow(Mesh& rmesh)
|
||||
{
|
||||
std::stringstream ss;
|
||||
Sim::Graphics::Mesh mesh;
|
||||
System& sys = *System::active;
|
||||
|
||||
ss << "\n\n";
|
||||
|
@ -153,7 +147,7 @@ void PrimaryLoop::remesh_slow(Mesh& rmesh)
|
|||
show_units( ss, sys.loop.condenser.get_pressure() ) << "Pa\n";
|
||||
ss << show( sys.loop.condenser.get_level() / 1000 ) << " / " << show( sys.loop.condenser.get_volume() / 1000 ) << " kL\n";
|
||||
|
||||
mesh.load_text(ss.str().c_str(), 0.04);
|
||||
Mesh mesh = Data::Fonts::BASE.load_text(ss.str(), 0.04);
|
||||
rmesh.add(mesh, glm::translate(mat, glm::vec3(0.5, 0, 0)));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,34 +1,34 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "../mesh/model.hpp"
|
||||
#include "../mesh/meshgen.hpp"
|
||||
#include "../data/model.hpp"
|
||||
#include "../data/meshgen.hpp"
|
||||
|
||||
namespace Sim::Graphics::Monitor
|
||||
{
|
||||
|
||||
class PrimaryLoop : public MeshGen
|
||||
class PrimaryLoop : public Data::MeshGen
|
||||
{
|
||||
glm::mat4 mat;
|
||||
|
||||
Mesh m_joystick_turbine_bypass;
|
||||
Mesh m_joystick_turbine_inlet;
|
||||
Data::Mesh m_joystick_turbine_bypass;
|
||||
Data::Mesh m_joystick_turbine_inlet;
|
||||
|
||||
Mesh g_switch_pump;
|
||||
Mesh g_switch_bypass;
|
||||
Mesh g_switch_inlet;
|
||||
Data::Mesh g_switch_pump;
|
||||
Data::Mesh g_switch_bypass;
|
||||
Data::Mesh g_switch_inlet;
|
||||
|
||||
Mesh m_switch_pump;
|
||||
Mesh m_switch_bypass;
|
||||
Mesh m_switch_inlet;
|
||||
Data::Mesh m_switch_pump;
|
||||
Data::Mesh m_switch_bypass;
|
||||
Data::Mesh m_switch_inlet;
|
||||
|
||||
public:
|
||||
|
||||
PrimaryLoop(const Model& model);
|
||||
virtual void update(double dt);
|
||||
virtual void get_static_transforms(std::vector<glm::mat4>& transforms);
|
||||
virtual void remesh_static(Mesh& rmesh);
|
||||
virtual void remesh_slow(Mesh& rmesh);
|
||||
PrimaryLoop(const Data::Model& model);
|
||||
void update(double dt) override;
|
||||
void get_static_transforms(std::vector<glm::mat4>& transforms) override;
|
||||
void remesh_static(Data::Mesh& rmesh) override;
|
||||
void remesh_slow(Data::Mesh& rmesh) override;
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -3,23 +3,23 @@
|
|||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include "secondary_loop.hpp"
|
||||
#include "../locations.hpp"
|
||||
#include "../../system.hpp"
|
||||
#include "../../coolant/valve.hpp"
|
||||
#include "../input/focus.hpp"
|
||||
#include "../../util/streams.hpp"
|
||||
#include "../data/font.hpp"
|
||||
|
||||
#include <glm/ext/matrix_transform.hpp>
|
||||
#include <iostream>
|
||||
|
||||
using namespace Sim::Graphics;
|
||||
using namespace Sim::Graphics::Monitor;
|
||||
using namespace Sim::Graphics::Data;
|
||||
using namespace Sim::Util::Streams;
|
||||
|
||||
|
||||
SecondaryLoop::SecondaryLoop(const Model& model)
|
||||
{
|
||||
mat = Locations::monitors[5];
|
||||
mat = model.load_matrix("translation_monitor_6");
|
||||
|
||||
g_switch_2 = model.load("visual_pump_switch_2");
|
||||
g_switch_3 = model.load("visual_pump_switch_3");
|
||||
|
@ -28,9 +28,6 @@ SecondaryLoop::SecondaryLoop(const Model& model)
|
|||
m_joystick_turbine_inlet = model.load("click_inlet_joystick");
|
||||
m_switch_2 = model.load("click_pump_switch_2");
|
||||
m_switch_3 = model.load("click_pump_switch_3");
|
||||
|
||||
g_switch_2.set_transform_id();
|
||||
g_switch_3.set_transform_id();
|
||||
}
|
||||
|
||||
void SecondaryLoop::update(double dt)
|
||||
|
@ -46,7 +43,6 @@ void SecondaryLoop::update(double dt)
|
|||
void SecondaryLoop::remesh_static(Mesh& rmesh)
|
||||
{
|
||||
std::stringstream ss;
|
||||
Mesh mesh;
|
||||
|
||||
ss << "Cooling Tower\n\n";
|
||||
ss << "Heat\nSteam\nPressure\nLevel\n\n";
|
||||
|
@ -55,8 +51,7 @@ void SecondaryLoop::remesh_static(Mesh& rmesh)
|
|||
ss << "Freight Pump\n\n";
|
||||
ss << "Power\nSpeed\nFlow\n\n";
|
||||
|
||||
mesh.load_text(ss.str().c_str(), 0.04);
|
||||
rmesh.add(mesh, mat);
|
||||
rmesh.add(Data::Fonts::BASE.load_text(ss.str(), 0.04), mat, true);
|
||||
rmesh.add(g_switch_2);
|
||||
rmesh.add(g_switch_3);
|
||||
}
|
||||
|
@ -64,7 +59,6 @@ void SecondaryLoop::remesh_static(Mesh& rmesh)
|
|||
void SecondaryLoop::remesh_slow(Mesh& rmesh)
|
||||
{
|
||||
std::stringstream ss;
|
||||
Sim::Graphics::Mesh mesh;
|
||||
System& sys = *System::active;
|
||||
|
||||
ss << "\n\n";
|
||||
|
@ -81,7 +75,7 @@ void SecondaryLoop::remesh_slow(Mesh& rmesh)
|
|||
ss << show( sys.freight_pump.get_rpm() ) << " r/min\n";
|
||||
show_units( ss, sys.freight_pump.get_flow_mass() ) << "g/s\n";
|
||||
|
||||
mesh.load_text(ss.str().c_str(), 0.04);
|
||||
Mesh mesh = Data::Fonts::BASE.load_text(ss.str().c_str(), 0.04);
|
||||
rmesh.add(mesh, glm::translate(mat, glm::vec3(0.5, 0, 0)));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,31 +1,31 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "../mesh/model.hpp"
|
||||
#include "../mesh/meshgen.hpp"
|
||||
#include "../data/model.hpp"
|
||||
#include "../data/meshgen.hpp"
|
||||
|
||||
namespace Sim::Graphics::Monitor
|
||||
{
|
||||
|
||||
class SecondaryLoop : public MeshGen
|
||||
class SecondaryLoop : public Data::MeshGen
|
||||
{
|
||||
glm::mat4 mat;
|
||||
|
||||
Mesh g_switch_2;
|
||||
Mesh g_switch_3;
|
||||
|
||||
Mesh m_joystick_turbine_bypass;
|
||||
Mesh m_joystick_turbine_inlet;
|
||||
Mesh m_switch_2;
|
||||
Mesh m_switch_3;
|
||||
Data::Mesh g_switch_2;
|
||||
Data::Mesh g_switch_3;
|
||||
|
||||
Data::Mesh m_joystick_turbine_bypass;
|
||||
Data::Mesh m_joystick_turbine_inlet;
|
||||
Data::Mesh m_switch_2;
|
||||
Data::Mesh m_switch_3;
|
||||
|
||||
public:
|
||||
|
||||
SecondaryLoop(const Model& model);
|
||||
virtual void update(double dt);
|
||||
virtual void get_static_transforms(std::vector<glm::mat4>& transforms);
|
||||
virtual void remesh_static(Mesh& rmesh);
|
||||
virtual void remesh_slow(Mesh& rmesh);
|
||||
SecondaryLoop(const Data::Model& model);
|
||||
void update(double dt) override;
|
||||
void get_static_transforms(std::vector<glm::mat4>& transforms) override;
|
||||
void remesh_static(Data::Mesh& rmesh) override;
|
||||
void remesh_slow(Data::Mesh& rmesh) override;
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -3,29 +3,32 @@
|
|||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include "turbine.hpp"
|
||||
#include "../locations.hpp"
|
||||
#include "../../system.hpp"
|
||||
#include "../../coolant/valve.hpp"
|
||||
#include "../input/focus.hpp"
|
||||
#include "../../util/streams.hpp"
|
||||
#include "../../util/math.hpp"
|
||||
#include "../data/font.hpp"
|
||||
|
||||
#include <glm/ext/matrix_transform.hpp>
|
||||
#include <iostream>
|
||||
|
||||
using namespace Sim::Graphics;
|
||||
using namespace Sim::Graphics::Monitor;
|
||||
using namespace Sim::Graphics::Data;
|
||||
using namespace Sim::Util::Streams;
|
||||
|
||||
Turbine::Turbine(const Model& model)
|
||||
{
|
||||
mat = Locations::monitors[4];
|
||||
mat = model.load_matrix("translation_monitor_5");
|
||||
|
||||
g_dial_phase = model.load("visual_dial_phase");
|
||||
g_dial_voltage = model.load("visual_dial_voltage");
|
||||
g_dial_power = model.load("visual_dial_power");
|
||||
g_dial_frequency = model.load("visual_dial_frequency");
|
||||
|
||||
g_synchroscope_dial = model.load("visual_synchroscope_dial");
|
||||
g_switch_breaker = model.load("visual_breaker_switch");
|
||||
m_switch_breaker = model.load("click_breaker_switch");
|
||||
|
||||
g_synchroscope_dial.set_transform_id();
|
||||
g_switch_breaker.set_transform_id();
|
||||
}
|
||||
|
||||
void Turbine::update(double dt)
|
||||
|
@ -40,40 +43,49 @@ void Turbine::get_static_transforms(std::vector<glm::mat4>& transforms)
|
|||
{
|
||||
System& sys = *System::active;
|
||||
double rpm = sys.loop.generator.get_rpm();
|
||||
glm::mat4 mat(1);
|
||||
glm::mat4 mat_phase(1);
|
||||
glm::mat4 mat_voltage(1);
|
||||
glm::mat4 mat_power(1);
|
||||
glm::mat4 mat_frequency(1);
|
||||
|
||||
if(rpm > 3570 && rpm < 3630)
|
||||
{
|
||||
mat = glm::translate(mat, glm::vec3(6.35, 3.949, 1.35));
|
||||
mat = glm::rotate(mat, float(sys.loop.generator.get_phase_diff()), glm::vec3(0, 1, 0));
|
||||
mat = glm::translate(mat, glm::vec3(-6.35, -3.949, -1.35));
|
||||
mat_phase = glm::rotate(mat_phase, float(sys.loop.generator.get_phase_diff()), glm::vec3(0, 1, 0));
|
||||
}
|
||||
|
||||
mat_voltage = glm::rotate(mat_voltage, float(Util::Math::map(sys.loop.generator.get_voltage(), 0, 24e3, 0, M_PI)), glm::vec3(0, 1, 0));
|
||||
mat_power = glm::rotate(mat_power, float(Util::Math::map(sys.loop.generator.get_power(), 0, 600e6, 0, M_PI)), glm::vec3(0, 1, 0));
|
||||
mat_frequency = glm::rotate(mat_frequency, float(Util::Math::map(sys.loop.generator.get_frequency(), 0, 120, 0, M_PI)), glm::vec3(0, 1, 0));
|
||||
|
||||
transforms.push_back(mat_phase);
|
||||
transforms.push_back(mat_voltage);
|
||||
transforms.push_back(mat_power);
|
||||
transforms.push_back(mat_frequency);
|
||||
|
||||
float off1 = sys.loop.generator.breaker_closed ? 0.07 : 0;
|
||||
|
||||
transforms.push_back(mat);
|
||||
transforms.push_back(glm::translate(glm::mat4(1), glm::vec3(0, off1, 0)));
|
||||
}
|
||||
|
||||
void Turbine::remesh_static(Mesh& rmesh)
|
||||
{
|
||||
std::stringstream ss;
|
||||
Sim::Graphics::Mesh mesh;
|
||||
|
||||
ss << "Turbine\n\n";
|
||||
ss << "Heat\nPressure\nSpeed\n\n";
|
||||
|
||||
mesh.load_text(ss.str().c_str(), 0.04);
|
||||
rmesh.add(mesh, mat);
|
||||
rmesh.add(Data::Fonts::BASE.load_text(ss.str(), 0.04), mat, true);
|
||||
|
||||
rmesh.add(g_synchroscope_dial);
|
||||
rmesh.add(g_dial_phase);
|
||||
rmesh.add(g_dial_voltage);
|
||||
rmesh.add(g_dial_power);
|
||||
rmesh.add(g_dial_frequency);
|
||||
rmesh.add(g_switch_breaker);
|
||||
}
|
||||
|
||||
void Turbine::remesh_slow(Mesh& rmesh)
|
||||
{
|
||||
std::stringstream ss;
|
||||
Sim::Graphics::Mesh mesh;
|
||||
System& sys = *System::active;
|
||||
|
||||
ss << "\n\n";
|
||||
|
@ -81,24 +93,7 @@ void Turbine::remesh_slow(Mesh& rmesh)
|
|||
ss << show( sys.loop.turbine.get_pressure() / 1000 ) << " kPa\n";
|
||||
ss << show( sys.loop.generator.get_rpm() ) << " r/min\n";
|
||||
|
||||
mesh.load_text(ss.str().c_str(), 0.04);
|
||||
Mesh mesh = Data::Fonts::BASE.load_text(ss.str(), 0.04);
|
||||
rmesh.add(mesh, glm::translate(mat, glm::vec3(0.5, 0, 0)));
|
||||
|
||||
ss = std::stringstream();
|
||||
|
||||
ss << "Local\n\n";
|
||||
ss << show( sys.loop.generator.get_rpm() / 60 ) << " Hz\n";
|
||||
Util::Streams::show_units( ss, sys.loop.generator.get_energy_generated() ) << "W\n";
|
||||
|
||||
mesh.load_text(ss.str().c_str(), 0.04);
|
||||
rmesh.add(mesh, glm::translate(mat, glm::vec3(0.4, 0.75, 0)));
|
||||
|
||||
ss = std::stringstream();
|
||||
|
||||
ss << "Grid\n\n";
|
||||
ss << show( sys.grid.frequency ) << " Hz\n";
|
||||
|
||||
mesh.load_text(ss.str().c_str(), 0.04);
|
||||
rmesh.add(mesh, glm::translate(mat, glm::vec3(0.7, 0.75, 0)));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,28 +1,31 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "../mesh/model.hpp"
|
||||
#include "../mesh/glmesh.hpp"
|
||||
#include "../mesh/meshgen.hpp"
|
||||
#include "../data/model.hpp"
|
||||
#include "../data/glmesh.hpp"
|
||||
#include "../data/meshgen.hpp"
|
||||
|
||||
namespace Sim::Graphics::Monitor
|
||||
{
|
||||
|
||||
class Turbine : public MeshGen
|
||||
class Turbine : public Data::MeshGen
|
||||
{
|
||||
glm::mat4 mat;
|
||||
|
||||
Mesh g_synchroscope_dial;
|
||||
Mesh g_switch_breaker;
|
||||
Mesh m_switch_breaker;
|
||||
Data::Mesh g_dial_phase;
|
||||
Data::Mesh g_dial_voltage;
|
||||
Data::Mesh g_dial_power;
|
||||
Data::Mesh g_dial_frequency;
|
||||
Data::Mesh g_switch_breaker;
|
||||
Data::Mesh m_switch_breaker;
|
||||
|
||||
public:
|
||||
|
||||
Turbine(const Model& model);
|
||||
virtual void update(double dt);
|
||||
virtual void get_static_transforms(std::vector<glm::mat4>& transforms);
|
||||
virtual void remesh_static(Mesh& rmesh);
|
||||
virtual void remesh_slow(Mesh& rmesh);
|
||||
Turbine(const Data::Model& model);
|
||||
void update(double dt) override;
|
||||
void get_static_transforms(std::vector<glm::mat4>& transforms) override;
|
||||
void remesh_static(Data::Mesh& rmesh) override;
|
||||
void remesh_slow(Data::Mesh& rmesh) override;
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -5,25 +5,25 @@
|
|||
#include "vessel.hpp"
|
||||
#include "../../reactor/rod.hpp"
|
||||
#include "../../reactor/control/boron_rod.hpp"
|
||||
#include "../locations.hpp"
|
||||
#include "../../system.hpp"
|
||||
#include "../../util/streams.hpp"
|
||||
#include "../data/font.hpp"
|
||||
|
||||
#include <glm/ext/matrix_transform.hpp>
|
||||
#include <sstream>
|
||||
|
||||
using namespace Sim::Graphics::Monitor;
|
||||
using namespace Sim::Graphics::Data;
|
||||
using namespace Sim::Util::Streams;
|
||||
|
||||
Vessel::Vessel(const Model& model)
|
||||
{
|
||||
mat = Locations::monitors[1];
|
||||
mat = model.load_matrix("translation_monitor_2");
|
||||
}
|
||||
|
||||
void Vessel::remesh_static(Mesh& rmesh)
|
||||
{
|
||||
std::stringstream ss;
|
||||
Sim::Graphics::Mesh mesh;
|
||||
|
||||
ss << "Reactor Vessel\n\n";
|
||||
ss << "Heat\n";
|
||||
|
@ -37,14 +37,12 @@ void Vessel::remesh_static(Mesh& rmesh)
|
|||
ss << "Temperature\nMin\nMax\n\n";
|
||||
ss << "Control Rods\nMin\nMax\nSpeed\n";
|
||||
|
||||
mesh.load_text(ss.str().c_str(), 0.04);
|
||||
rmesh.add(mesh, mat);
|
||||
rmesh.add(Data::Fonts::BASE.load_text(ss.str(), 0.04), mat, true);
|
||||
}
|
||||
|
||||
void Vessel::remesh_slow(Mesh& rmesh)
|
||||
{
|
||||
std::stringstream ss;
|
||||
Sim::Graphics::Mesh mesh;
|
||||
Sim::System& sys = *System::active;
|
||||
|
||||
double temp_min, temp_max;
|
||||
|
@ -92,7 +90,7 @@ void Vessel::remesh_slow(Mesh& rmesh)
|
|||
if(sys.reactor.rod_speed == 0) ss << " (Stopped)";
|
||||
ss << "\n";
|
||||
|
||||
mesh.load_text(ss.str().c_str(), 0.04);
|
||||
Mesh mesh = Data::Fonts::BASE.load_text(ss.str(), 0.04);
|
||||
rmesh.add(mesh, glm::translate(mat, glm::vec3(0.5, 0, 0)));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "../mesh/model.hpp"
|
||||
#include "../mesh/meshgen.hpp"
|
||||
#include "../data/model.hpp"
|
||||
#include "../data/meshgen.hpp"
|
||||
|
||||
namespace Sim::Graphics::Monitor
|
||||
{
|
||||
|
||||
class Vessel : public MeshGen
|
||||
class Vessel : public Data::MeshGen
|
||||
{
|
||||
glm::mat4 mat;
|
||||
|
||||
public:
|
||||
|
||||
Vessel(const Model& model);
|
||||
virtual void remesh_static(Mesh& rmesh);
|
||||
virtual void remesh_slow(Mesh& rmesh);
|
||||
Vessel(const Data::Model& model);
|
||||
void remesh_static(Data::Mesh& rmesh) override;
|
||||
void remesh_slow(Data::Mesh& rmesh) override;
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
using namespace Sim::Graphics;
|
||||
using namespace Sim::Graphics::Resize;
|
||||
using namespace Sim::Graphics::Window;
|
||||
|
||||
static bool is_fullscreen = false;
|
||||
|
||||
|
|
|
@ -5,46 +5,87 @@
|
|||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <format>
|
||||
|
||||
#include "shader.hpp"
|
||||
#include "shadersource.hpp"
|
||||
#include "window.hpp"
|
||||
|
||||
using namespace Sim::Graphics;
|
||||
|
||||
Shader Shader::MAIN;
|
||||
Shader Shader::BLUR;
|
||||
Shader Shader::LIGHT;
|
||||
Shader* Shader::ACTIVE;
|
||||
|
||||
static int load_shader(const char* src, int type)
|
||||
bool Shader::USE_BINDLESS_TEXTURES = false;
|
||||
|
||||
static std::vector<std::string> shader_compiler_flags;
|
||||
|
||||
void Shader::add_define(const std::string& flag)
|
||||
{
|
||||
int id = glCreateShader(type);
|
||||
|
||||
glShaderSource(id, 1, &src, nullptr);
|
||||
glCompileShader(id);
|
||||
|
||||
return id;
|
||||
shader_compiler_flags.push_back(flag);
|
||||
}
|
||||
|
||||
static std::string read_shader(const char* path)
|
||||
void Shader::init()
|
||||
{
|
||||
Shader::Source sources_main[] = {
|
||||
{ShaderSource::MAIN_VSH, "main.vsh", GL_VERTEX_SHADER},
|
||||
{ShaderSource::MAIN_FSH, "main.fsh", GL_FRAGMENT_SHADER}
|
||||
};
|
||||
|
||||
Shader::Source sources_light[] = {
|
||||
{ShaderSource::LIGHT_VSH, "light.vsh", GL_VERTEX_SHADER},
|
||||
{ShaderSource::LIGHT_GSH, "light.gsh", GL_GEOMETRY_SHADER},
|
||||
{ShaderSource::LIGHT_FSH, "light.fsh", GL_FRAGMENT_SHADER}
|
||||
};
|
||||
|
||||
Shader::MAIN.load(sources_main, "main", 2);
|
||||
Shader::LIGHT.load(sources_light, "light", 3);
|
||||
}
|
||||
|
||||
std::string apply_shader_compiler_flags(const char* source)
|
||||
{
|
||||
std::stringstream ss;
|
||||
std::ifstream file(path, std::ios::binary);
|
||||
char buff[1024];
|
||||
ss << "#version 430 core\n";
|
||||
|
||||
while(!file.eof())
|
||||
for(const auto& flag : shader_compiler_flags)
|
||||
{
|
||||
file.read(buff, 1024);
|
||||
ss.write(buff, file.gcount());
|
||||
ss << "#define " << flag << "\n";
|
||||
}
|
||||
|
||||
ss << source;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
static std::string read_shader(const char* base, const char* file)
|
||||
Shader::Source::Source(const char* data, const char* name, GLenum type)
|
||||
{
|
||||
std::string path = std::string(base) + "/" + std::string(file);
|
||||
return read_shader(path.c_str());
|
||||
int success;
|
||||
std::string source = apply_shader_compiler_flags(data);
|
||||
data = source.c_str();
|
||||
|
||||
id = glCreateShader(type);
|
||||
glShaderSource(id, 1, &data, nullptr);
|
||||
glCompileShader(id);
|
||||
glGetShaderiv(id, GL_COMPILE_STATUS, &success);
|
||||
|
||||
if(!success)
|
||||
{
|
||||
char infoLog[512];
|
||||
glGetShaderInfoLog(id, 512, NULL, infoLog);
|
||||
std::string entry = std::format("Shader Compile Error ({0}): {1}", name, infoLog);
|
||||
throw std::runtime_error(entry);
|
||||
}
|
||||
}
|
||||
|
||||
Shader::Source::Source(Source&& o)
|
||||
{
|
||||
id = o.id;
|
||||
o.id = 0;
|
||||
}
|
||||
|
||||
Shader::Source::~Source()
|
||||
{
|
||||
if(id) glDeleteShader(id);
|
||||
}
|
||||
|
||||
Shader::Shader()
|
||||
|
@ -66,30 +107,15 @@ Shader::~Shader()
|
|||
}
|
||||
}
|
||||
|
||||
void Shader::load(const char* path, const char* file_vsh, const char* file_fsh)
|
||||
void Shader::load(const Source* sources, const char* name, int count)
|
||||
{
|
||||
load(path, file_vsh, nullptr, file_fsh);
|
||||
}
|
||||
|
||||
void Shader::load(const char* path, const char* file_vsh, const char* file_gsh, const char* file_fsh)
|
||||
{
|
||||
std::string shader_vsh = file_vsh ? read_shader(path, file_vsh) : "";
|
||||
std::string shader_gsh = file_gsh ? read_shader(path, file_gsh) : "";
|
||||
std::string shader_fsh = file_fsh ? read_shader(path, file_fsh) : "";
|
||||
|
||||
int success;
|
||||
int vsh_id = file_vsh ? load_shader(shader_vsh.c_str(), GL_VERTEX_SHADER) : 0;
|
||||
int gsh_id = file_gsh ? load_shader(shader_gsh.c_str(), GL_GEOMETRY_SHADER) : 0;
|
||||
int fsh_id = file_fsh ? load_shader(shader_fsh.c_str(), GL_FRAGMENT_SHADER) : 0;
|
||||
|
||||
prog_id = glCreateProgram();
|
||||
|
||||
if(file_vsh)
|
||||
glAttachShader(prog_id, vsh_id);
|
||||
if(file_gsh)
|
||||
glAttachShader(prog_id, gsh_id);
|
||||
if(file_fsh)
|
||||
glAttachShader(prog_id, fsh_id);
|
||||
for(int i = 0; i < count; i++)
|
||||
{
|
||||
glAttachShader(prog_id, sources[i].id);
|
||||
}
|
||||
|
||||
glLinkProgram(prog_id);
|
||||
glGetProgramiv(prog_id, GL_LINK_STATUS, &success);
|
||||
|
@ -98,21 +124,9 @@ void Shader::load(const char* path, const char* file_vsh, const char* file_gsh,
|
|||
{
|
||||
char infoLog[512];
|
||||
glGetProgramInfoLog(prog_id, 512, NULL, infoLog);
|
||||
std::cout << "Shader Link Error (" << path << "," << file_vsh << "," << file_fsh << "): " << infoLog << std::endl;
|
||||
Window::close();
|
||||
return;
|
||||
std::string entry = std::format("Shader Link Error {0}: {1}", name, infoLog);
|
||||
throw std::runtime_error(entry);
|
||||
}
|
||||
|
||||
glUseProgram(prog_id);
|
||||
|
||||
if(file_vsh)
|
||||
glDeleteShader(vsh_id);
|
||||
if(file_gsh)
|
||||
glDeleteShader(gsh_id);
|
||||
if(file_fsh)
|
||||
glDeleteShader(fsh_id);
|
||||
|
||||
ACTIVE = this;
|
||||
}
|
||||
|
||||
void Shader::use()
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
|
||||
namespace Sim::Graphics
|
||||
{
|
||||
|
||||
|
||||
class Shader
|
||||
{
|
||||
unsigned int prog_id = 0;
|
||||
|
@ -14,20 +18,33 @@ class Shader
|
|||
std::unordered_map<const char*, unsigned int> uniform_block_indices;
|
||||
|
||||
public:
|
||||
|
||||
struct Source
|
||||
{
|
||||
unsigned int id;
|
||||
|
||||
Source(const char* data, const char* name, GLenum type);
|
||||
Source(const Source& o) = delete;
|
||||
Source(Source&& o);
|
||||
~Source();
|
||||
};
|
||||
|
||||
static Shader MAIN;
|
||||
static Shader BLUR;
|
||||
static Shader LIGHT;
|
||||
|
||||
static Shader* ACTIVE;
|
||||
|
||||
static bool USE_BINDLESS_TEXTURES;
|
||||
|
||||
Shader();
|
||||
Shader(const Shader& o) = delete;
|
||||
Shader(Shader&& o);
|
||||
~Shader();
|
||||
|
||||
void load(const char* path, const char* file_vsh, const char* file_gsh, const char* file_fsh);
|
||||
void load(const char* path, const char* file_vsh, const char* file_fsh);
|
||||
static void add_define(const std::string& flag);
|
||||
static void init();
|
||||
|
||||
void load(const Source* sources, const char* name, int count);
|
||||
void block_binding(const char* name, unsigned int index);
|
||||
void use();
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
|
||||
#version 460 core
|
||||
R"GLSL(
|
||||
|
||||
in vec3 frag_pos;
|
||||
|
||||
|
@ -11,3 +10,4 @@ void main()
|
|||
gl_FragDepth = distance / far_plane;
|
||||
}
|
||||
|
||||
)GLSL";
|
|
@ -1,10 +1,10 @@
|
|||
|
||||
#version 460 core
|
||||
R"GLSL(
|
||||
|
||||
layout (triangles) in;
|
||||
layout (triangle_strip, max_vertices=18) out;
|
||||
|
||||
uniform mat4 shadow_mats[6];
|
||||
uniform int light_pass;
|
||||
|
||||
in flat int should_ignore[];
|
||||
out vec3 frag_pos;
|
||||
|
@ -13,9 +13,11 @@ void main()
|
|||
{
|
||||
if(should_ignore[0] != 0) return;
|
||||
|
||||
int pass_offset = light_pass * 6;
|
||||
|
||||
for(int i = 0; i < 6; i++)
|
||||
{
|
||||
gl_Layer = i;
|
||||
gl_Layer = i + pass_offset;
|
||||
|
||||
for(int j = 0; j < 3; j++)
|
||||
{
|
||||
|
@ -30,3 +32,4 @@ void main()
|
|||
}
|
||||
}
|
||||
|
||||
)GLSL";
|
|
@ -0,0 +1,31 @@
|
|||
R"GLSL(
|
||||
|
||||
layout (location = 1) in vec3 aPos;
|
||||
layout (location = 2) in vec4 aColour;
|
||||
layout (location = 7) in int aTransformIndex;
|
||||
|
||||
layout (binding = 3) readonly buffer TransformBuffer
|
||||
{
|
||||
mat4 transforms[];
|
||||
};
|
||||
|
||||
out flat int should_ignore;
|
||||
|
||||
uniform vec3 light_pos;
|
||||
uniform int light_pass;
|
||||
|
||||
mat4 load_model_mat(int index)
|
||||
{
|
||||
return index < 0 ? mat4(1.f) : transforms[index];
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 pos = vec4(aPos, 1.f);
|
||||
mat4 model = load_model_mat(aTransformIndex);
|
||||
|
||||
gl_Position = model * pos - vec4(light_pos, 0.f);
|
||||
should_ignore = int(aColour.a < 1.f);
|
||||
}
|
||||
|
||||
)GLSL";
|
|
@ -1,15 +1,17 @@
|
|||
R"GLSL(
|
||||
|
||||
#version 460 core
|
||||
#ifdef USE_BINDLESS_TEXTURES
|
||||
#extension GL_ARB_bindless_texture : require
|
||||
#endif
|
||||
|
||||
const float PI = 3.141592f;
|
||||
|
||||
in VS_OUT {
|
||||
vec3 normal;
|
||||
vec4 colour;
|
||||
mat3 tbn;
|
||||
vec3 pos;
|
||||
vec2 tex_pos;
|
||||
vec3 material;
|
||||
flat vec4 colour;
|
||||
flat vec3 material;
|
||||
} vin;
|
||||
|
||||
struct Light
|
||||
|
@ -18,24 +20,65 @@ struct Light
|
|||
vec4 colour;
|
||||
};
|
||||
|
||||
layout(std140, binding = 1) readonly buffer LightBuffer
|
||||
layout(std140, binding = 2) readonly buffer LightBuffer
|
||||
{
|
||||
Light lights[];
|
||||
};
|
||||
|
||||
layout(std430, binding = 2) readonly buffer ShadowMapBuffer
|
||||
#ifdef USE_BINDLESS_TEXTURES
|
||||
|
||||
in flat sampler2D frag_tex_diffuse;
|
||||
in flat sampler2D frag_tex_normal;
|
||||
|
||||
#define ReadTexture(tex, uv) texture(tex, uv)
|
||||
|
||||
#else
|
||||
|
||||
in flat uint frag_tex_diffuse;
|
||||
in flat uint frag_tex_normal;
|
||||
|
||||
uniform sampler2D tex_atlas;
|
||||
|
||||
struct AtlasPart
|
||||
{
|
||||
samplerCube shadow_maps[];
|
||||
vec2 uv_min;
|
||||
vec2 uv_max;
|
||||
};
|
||||
|
||||
in flat sampler2D frag_tex;
|
||||
layout(std140, binding = 5) readonly buffer AtlasBuffer
|
||||
{
|
||||
AtlasPart atlas[];
|
||||
};
|
||||
|
||||
vec4 ReadTexture(uint tex, vec2 uv)
|
||||
{
|
||||
AtlasPart a = atlas[tex];
|
||||
uv = mod(uv, 1.f) * (a.uv_max - a.uv_min) + a.uv_min;
|
||||
return texture(tex_atlas, uv);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
out vec4 frag_colour;
|
||||
|
||||
uniform vec3 brightness;
|
||||
uniform vec3 camera_pos;
|
||||
uniform int lights_count;
|
||||
uniform float far_plane;
|
||||
uniform bool shadows_enabled;
|
||||
uniform int lights_count;
|
||||
|
||||
uniform samplerCubeArrayShadow shadow_maps;
|
||||
|
||||
float Map(float v, float i_min, float i_max, float o_min, float o_max)
|
||||
{
|
||||
return o_min + (o_max - o_min) * (v - i_min) / (i_max - i_min);
|
||||
}
|
||||
|
||||
float Ramp(float v, float i_min, float i_max, float o_min, float o_max)
|
||||
{
|
||||
float t = clamp(v, i_min, i_max);
|
||||
return Map(t, i_min, i_max, o_min, o_max);
|
||||
}
|
||||
|
||||
vec3 FresnelSchlick(float cosTheta, vec3 F0)
|
||||
{
|
||||
|
@ -97,31 +140,52 @@ vec3 sRGB_To_LinRGB(vec3 c)
|
|||
|
||||
void main()
|
||||
{
|
||||
vec4 albedo = texture2D(frag_tex, vin.tex_pos);
|
||||
vec4 albedo = ReadTexture(frag_tex_diffuse, vin.tex_pos);
|
||||
if(albedo.a == 0.f) discard;
|
||||
|
||||
vec3 tangent = ReadTexture(frag_tex_normal, vin.tex_pos).rgb * 2.f - 1.f;
|
||||
vec3 albedo_lin = sRGB_To_LinRGB(albedo.rgb) * vin.colour.rgb;
|
||||
albedo *= vin.colour;
|
||||
|
||||
|
||||
float roughness = vin.material[0];
|
||||
float metalness = vin.material[1];
|
||||
float luminance = min(vin.material[2], 1.f);
|
||||
|
||||
vec3 N = normalize(vin.normal);
|
||||
vec3 N = normalize(vin.tbn * tangent);
|
||||
vec3 V = normalize(camera_pos - vin.pos.xyz);
|
||||
|
||||
vec3 F0 = vec3(0.04f);
|
||||
F0 = mix(F0, albedo_lin, metalness);
|
||||
vec3 F0 = mix(vec3(0.04f), albedo_lin, metalness);
|
||||
vec3 ambient = vec3(Map(dot(N, vec3(0.f, 0.f, 1.f)), -1.f, 1.f, 0.2f, 0.25f)) * albedo_lin * brightness;
|
||||
vec3 Lo = vec3(0.f);
|
||||
|
||||
vec3 Lo = vec3(0.0f);
|
||||
for(int i = 0; i < lights_count; i++)
|
||||
{
|
||||
Light l = lights[i];
|
||||
|
||||
vec3 L = normalize(l.pos.xyz - vin.pos);
|
||||
vec3 H = normalize(V + L);
|
||||
|
||||
float d = length(vin.pos - l.pos.xyz);
|
||||
vec3 L = (l.pos.xyz - vin.pos) / d;
|
||||
float light_m;
|
||||
|
||||
if(shadows_enabled)
|
||||
{
|
||||
if(dot(vin.tbn[2], L) < 0.f)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
light_m = texture(shadow_maps, vec4(-L, i), d / far_plane);
|
||||
|
||||
if(light_m <= 0.f)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
light_m = 1.f;
|
||||
}
|
||||
|
||||
vec3 H = normalize(V + L);
|
||||
float atten = 1.f / (d*d);
|
||||
vec3 radiance = l.colour.rgb * atten;
|
||||
|
||||
|
@ -137,32 +201,16 @@ void main()
|
|||
vec3 numerator = NDF * G * F;
|
||||
float denominator = 4.f * max(dot(N, V), 0.f) * max(dot(N, L), 0.f) + 1e-4f;
|
||||
vec3 specular = numerator / denominator;
|
||||
|
||||
float light_m;
|
||||
float spec_m;
|
||||
|
||||
if(shadows_enabled)
|
||||
{
|
||||
float max_d = texture(shadow_maps[i], -L).r * far_plane + 1e-2f;
|
||||
spec_m = max_d > d ? 1.f : 0.f;
|
||||
light_m = spec_m * 0.25f + 0.75f;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
light_m = 1.f;
|
||||
spec_m = 1.f;
|
||||
}
|
||||
|
||||
// add to outgoing radiance Lo
|
||||
float NdotL = max(dot(N, L), 0.f);
|
||||
Lo += (kD * albedo_lin / PI + specular * spec_m) * radiance * NdotL * light_m;
|
||||
Lo += (kD * albedo_lin / PI + specular) * radiance * NdotL * light_m;
|
||||
}
|
||||
|
||||
vec3 ambient = vec3(0.03f) * albedo_lin * brightness;
|
||||
vec3 light = LinRGB_To_sRGB(ambient + Lo);
|
||||
|
||||
light = mix(light, albedo.rgb, luminance);
|
||||
frag_colour = vec4(light, albedo.a);
|
||||
}
|
||||
|
||||
)GLSL";
|
|
@ -0,0 +1,78 @@
|
|||
R"GLSL(
|
||||
|
||||
#ifdef USE_BINDLESS_TEXTURES
|
||||
#extension GL_ARB_bindless_texture : require
|
||||
#endif
|
||||
|
||||
layout (location = 0) in vec2 aTexPos;
|
||||
layout (location = 1) in vec3 aPos;
|
||||
layout (location = 2) in vec4 aColour;
|
||||
layout (location = 3) in vec3 aTangent;
|
||||
layout (location = 4) in vec3 aBitangent;
|
||||
layout (location = 5) in vec3 aNormal;
|
||||
layout (location = 6) in vec3 aMaterial;
|
||||
layout (location = 7) in int aTransformIndex;
|
||||
|
||||
#ifdef USE_BINDLESS_TEXTURES
|
||||
|
||||
layout (location = 8) in sampler2D aTexDiffuse;
|
||||
layout (location = 9) in sampler2D aTexNormal;
|
||||
|
||||
out flat sampler2D frag_tex_diffuse;
|
||||
out flat sampler2D frag_tex_normal;
|
||||
|
||||
#else
|
||||
|
||||
layout (location = 8) in uint aTexDiffuse;
|
||||
layout (location = 9) in uint aTexNormal;
|
||||
|
||||
out flat uint frag_tex_diffuse;
|
||||
out flat uint frag_tex_normal;
|
||||
|
||||
#endif
|
||||
|
||||
uniform mat4 camera;
|
||||
uniform mat4 projection;
|
||||
|
||||
layout (std430, binding = 3) readonly buffer TransformBuffer
|
||||
{
|
||||
mat4 transforms[];
|
||||
};
|
||||
|
||||
out VS_OUT {
|
||||
mat3 tbn;
|
||||
vec3 pos;
|
||||
vec2 tex_pos;
|
||||
flat vec4 colour;
|
||||
flat vec3 material;
|
||||
} vout;
|
||||
|
||||
mat4 load_model_mat(int index)
|
||||
{
|
||||
return index < 0 ? mat4(1.f) : transforms[index];
|
||||
}
|
||||
|
||||
float Map(float v, float i_min, float i_max, float o_min, float o_max)
|
||||
{
|
||||
return o_min + (o_max - o_min) * (v - i_min) / (i_max - i_min);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 pos = vec4(aPos, 1.f);
|
||||
mat4 model = load_model_mat(aTransformIndex);
|
||||
mat4 mv = camera * model;
|
||||
mat4 mvp = projection * mv;
|
||||
|
||||
vout.tbn = mat3(model) * mat3(aTangent, aBitangent, aNormal);
|
||||
vout.pos = (model * pos).xyz;
|
||||
vout.tex_pos = aTexPos;
|
||||
vout.colour = aColour;
|
||||
vout.material = aMaterial.xyz;
|
||||
frag_tex_diffuse = aTexDiffuse;
|
||||
frag_tex_normal = aTexNormal;
|
||||
|
||||
gl_Position = mvp * pos;
|
||||
}
|
||||
|
||||
)GLSL";
|
|
@ -0,0 +1,17 @@
|
|||
|
||||
#include "shadersource.hpp"
|
||||
|
||||
using namespace Sim::Graphics;
|
||||
|
||||
const char* ShaderSource::LIGHT_VSH =
|
||||
#include "shaders/light.vsh"
|
||||
const char* ShaderSource::LIGHT_GSH =
|
||||
#include "shaders/light.gsh"
|
||||
const char* ShaderSource::LIGHT_FSH =
|
||||
#include "shaders/light.fsh"
|
||||
|
||||
const char* ShaderSource::MAIN_VSH =
|
||||
#include "shaders/main.vsh"
|
||||
const char* ShaderSource::MAIN_FSH =
|
||||
#include "shaders/main.fsh"
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
namespace Sim::Graphics::ShaderSource
|
||||
{
|
||||
extern const char* LIGHT_VSH;
|
||||
extern const char* LIGHT_GSH;
|
||||
extern const char* LIGHT_FSH;
|
||||
extern const char* MAIN_VSH;
|
||||
extern const char* MAIN_FSH;
|
||||
};
|
||||
|
|
@ -6,11 +6,11 @@
|
|||
|
||||
#include <glm/ext/matrix_transform.hpp>
|
||||
|
||||
#include "mesh/mesh.hpp"
|
||||
#include "mesh/glmesh.hpp"
|
||||
#include "mesh/arrays.hpp"
|
||||
#include "mesh/font.hpp"
|
||||
#include "mesh/texture.hpp"
|
||||
#include "data/mesh.hpp"
|
||||
#include "data/glmesh.hpp"
|
||||
#include "data/arrays.hpp"
|
||||
#include "data/font.hpp"
|
||||
#include "data/texture.hpp"
|
||||
#include "resize.hpp"
|
||||
#include "shader.hpp"
|
||||
|
||||
|
@ -18,31 +18,22 @@
|
|||
|
||||
using namespace Sim::Graphics;
|
||||
|
||||
static GLMesh gm_ui;
|
||||
static GLMesh gm_dynamic_slow[2];
|
||||
|
||||
static Data::Mesh g_ui;
|
||||
static Data::GLMesh gm_dynamic_slow[2];
|
||||
static Widget::Clock w_clock;
|
||||
|
||||
static int gm_dynamic_slow_at = 0;
|
||||
|
||||
void UI::init()
|
||||
{
|
||||
Mesh m;
|
||||
|
||||
unsigned int handle = Texture::handle_white;
|
||||
const unsigned int indices[] = {0, 1, 3, 0, 3, 2};
|
||||
const Arrays::Vertex vertices[] = {
|
||||
{.texid=handle, .texpos={0, 0}, .pos={-1, -1, 0, 1}, .normal={0, 0, -1}, .colour={1, 1, 1, 1}, .material={0, 0, 1}},
|
||||
{.texid=handle, .texpos={0, 1}, .pos={-1, 1, 0, 1}, .normal={0, 0, -1}, .colour={1, 1, 1, 1}, .material={0, 0, 1}},
|
||||
{.texid=handle, .texpos={1, 0}, .pos={ 1, -1, 0, 1}, .normal={0, 0, -1}, .colour={1, 1, 1, 1}, .material={0, 0, 1}},
|
||||
{.texid=handle, .texpos={1, 1}, .pos={ 1, 1, 0, 1}, .normal={0, 0, -1}, .colour={1, 1, 1, 1}, .material={0, 0, 1}},
|
||||
g_ui.indices = {0, 1, 3, 0, 3, 2};
|
||||
g_ui.vertices = {
|
||||
{.texpos={0, 0}, .pos={-1, -1, 0}, .material={0, 0, 1}},
|
||||
{.texpos={0, 1}, .pos={-1, 1, 0}, .material={0, 0, 1}},
|
||||
{.texpos={1, 0}, .pos={ 1, -1, 0}, .material={0, 0, 1}},
|
||||
{.texpos={1, 1}, .pos={ 1, 1, 0}, .material={0, 0, 1}},
|
||||
};
|
||||
|
||||
m.set_indices(indices, 6);
|
||||
m.set_vertices(vertices, 4);
|
||||
|
||||
gm_ui.bind();
|
||||
gm_ui.set(m, GL_STATIC_DRAW);
|
||||
g_ui.bake_transforms();
|
||||
}
|
||||
|
||||
void UI::update(double dt)
|
||||
|
@ -52,12 +43,15 @@ void UI::update(double dt)
|
|||
|
||||
void UI::update_slow()
|
||||
{
|
||||
Mesh mesh;
|
||||
Data::Mesh mesh;
|
||||
|
||||
w_clock.remesh_slow(mesh);
|
||||
|
||||
mesh.add(g_ui);
|
||||
mesh.bake_transforms();
|
||||
|
||||
gm_dynamic_slow[gm_dynamic_slow_at].bind();
|
||||
gm_dynamic_slow[gm_dynamic_slow_at].set(mesh, GL_DYNAMIC_DRAW);
|
||||
gm_dynamic_slow[gm_dynamic_slow_at].set(mesh, GL_STREAM_DRAW);
|
||||
gm_dynamic_slow_at = (gm_dynamic_slow_at + 1) % 2;
|
||||
}
|
||||
|
||||
|
@ -71,15 +65,8 @@ void UI::render()
|
|||
glm::mat4 mat_camera = glm::scale(glm::mat4(1), glm::vec3(1.0f / wsize * glm::vec2(1, -1), -1));
|
||||
glUniformMatrix4fv(Shader::MAIN["projection"], 1, false, &mat_projection[0][0]);
|
||||
glUniformMatrix4fv(Shader::MAIN["camera"], 1, false, &mat_camera[0][0]);
|
||||
|
||||
gm_ui.bind();
|
||||
gm_ui.uniform();
|
||||
gm_ui.render();
|
||||
|
||||
gm_dynamic_slow[gm_dynamic_slow_at].bind();
|
||||
gm_dynamic_slow[gm_dynamic_slow_at].uniform();
|
||||
gm_dynamic_slow[gm_dynamic_slow_at].render();
|
||||
|
||||
w_clock.render();
|
||||
}
|
||||
|
||||
|
|
|
@ -10,13 +10,15 @@
|
|||
#include <sstream>
|
||||
#include <cmath>
|
||||
|
||||
#include "../mesh/arrays.hpp"
|
||||
#include "../mesh/font.hpp"
|
||||
#include "../mesh/arrays.hpp"
|
||||
#include "../data/arrays.hpp"
|
||||
#include "../data/font.hpp"
|
||||
#include "../data/arrays.hpp"
|
||||
#include "../resize.hpp"
|
||||
#include "../../system.hpp"
|
||||
#include "../../util/streams.hpp"
|
||||
|
||||
using namespace Sim::Graphics::Widget;
|
||||
using namespace Sim::Graphics::Data;
|
||||
|
||||
void Clock::update(double dt)
|
||||
{
|
||||
|
@ -25,7 +27,6 @@ void Clock::update(double dt)
|
|||
|
||||
void Clock::remesh_slow(Mesh& rmesh)
|
||||
{
|
||||
Mesh m;
|
||||
double at = System::active->clock;
|
||||
glm::vec2 wsize(Resize::get_size() / 2);
|
||||
std::stringstream ss;
|
||||
|
@ -40,11 +41,7 @@ void Clock::remesh_slow(Mesh& rmesh)
|
|||
ss << std::setfill('0') << std::setw(2) << t_s << "\n";
|
||||
ss << "Day: " << std::floor(at / (3600 * 24)) << "\n";
|
||||
|
||||
m.load_text(ss.str().c_str(), 20);
|
||||
Mesh m = Fonts::BASE.load_text(ss.str(), 20);
|
||||
rmesh.add(m, glm::translate(glm::mat4(1), glm::vec3(-wsize + glm::vec2(2, 2), 0)));
|
||||
}
|
||||
|
||||
void Clock::render()
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "../mesh/glmesh.hpp"
|
||||
#include "../data/glmesh.hpp"
|
||||
|
||||
namespace Sim::Graphics::Widget
|
||||
{
|
||||
|
@ -11,8 +11,7 @@ struct Clock
|
|||
double dt;
|
||||
|
||||
void update(double dt);
|
||||
void remesh_slow(Mesh& rmesh);
|
||||
void render();
|
||||
void remesh_slow(Data::Mesh& rmesh);
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
#include "mesh/mesh.hpp"
|
||||
#include "mesh/arrays.hpp"
|
||||
#include "data/mesh.hpp"
|
||||
#include "data/arrays.hpp"
|
||||
#include "input/keyboard.hpp"
|
||||
#include "input/mouse.hpp"
|
||||
#include "input/focus.hpp"
|
||||
|
@ -19,44 +19,51 @@
|
|||
#include "resize.hpp"
|
||||
#include "window.hpp"
|
||||
#include "shader.hpp"
|
||||
#include "mesh/font.hpp"
|
||||
#include "locations.hpp"
|
||||
#include "data/font.hpp"
|
||||
#include "monitor/vessel.hpp"
|
||||
#include "monitor/core.hpp"
|
||||
#include "monitor/primary_loop.hpp"
|
||||
#include "monitor/secondary_loop.hpp"
|
||||
#include "monitor/turbine.hpp"
|
||||
#include "mesh/texture.hpp"
|
||||
#include "mesh/model.hpp"
|
||||
#include "mesh/gllight.hpp"
|
||||
#include "mesh/meshgen.hpp"
|
||||
#include "monitor/cctv.hpp"
|
||||
#include "data/texture.hpp"
|
||||
#include "data/model.hpp"
|
||||
#include "data/gllights.hpp"
|
||||
#include "data/meshgen.hpp"
|
||||
#include "data/material.hpp"
|
||||
#include "equipment/reactor.hpp"
|
||||
#include "equipment/generator.hpp"
|
||||
#include "equipment/pool.hpp"
|
||||
#include "../system.hpp"
|
||||
#include "../util/streams.hpp"
|
||||
#include "ui.hpp"
|
||||
|
||||
using namespace Sim;
|
||||
using namespace Sim::Graphics;
|
||||
using namespace Sim::Graphics::Data;
|
||||
|
||||
constexpr int SSBO_TRANSFORMS_LEN = 2;
|
||||
|
||||
static GLFWwindow* win;
|
||||
static bool win_should_close = false;
|
||||
static unsigned int ssbo_lights;
|
||||
static unsigned int ssbo_shadow_maps;
|
||||
static unsigned int ssbo_transforms[SSBO_TRANSFORMS_LEN];
|
||||
static double secs_wait_at = 0;
|
||||
static double secs_wait_now = 0;
|
||||
static unsigned int wait_at = 0;
|
||||
|
||||
static int gm_dynamic_slow_at = 0;
|
||||
static int ssbo_transforms_at = 0;
|
||||
|
||||
static Mesh g_scene;
|
||||
static std::vector<glm::mat4> g_scene_transforms;
|
||||
|
||||
static GLMesh gm_scene;
|
||||
static GLMesh gm_transparent;
|
||||
static GLMesh gm_player;
|
||||
static GLMesh gm_dynamic_slow[2];
|
||||
|
||||
static std::vector<GLLight> lights;
|
||||
static std::vector<std::unique_ptr<MeshGen>> monitors;
|
||||
static std::vector<std::unique_ptr<MeshGen>> equipment;
|
||||
static std::unique_ptr<GLLights> lights;
|
||||
static std::vector<MeshGen*> monitors;
|
||||
static std::vector<MeshGen*> equipment;
|
||||
|
||||
static Monitor::CCTV* monitor_cctv;
|
||||
|
||||
glm::mat4 Window::projection_matrix;
|
||||
|
||||
|
@ -73,11 +80,32 @@ static void GLAPIENTRY cb_debug_message(GLenum source, GLenum type, GLuint id, G
|
|||
}
|
||||
}
|
||||
|
||||
void remesh_static()
|
||||
{
|
||||
Mesh mesh(g_scene);
|
||||
|
||||
for(auto& monitor : monitors)
|
||||
{
|
||||
monitor->remesh_static(mesh);
|
||||
}
|
||||
|
||||
for(auto& equipment : equipment)
|
||||
{
|
||||
equipment->remesh_static(mesh);
|
||||
}
|
||||
|
||||
gm_scene.bind();
|
||||
gm_scene.set(mesh, GL_STATIC_DRAW);
|
||||
g_scene_transforms = std::move(mesh.transforms);
|
||||
|
||||
std::cout << "Total triangle count: " << mesh.indices.size() / 3 << "\n";
|
||||
}
|
||||
|
||||
void Window::create()
|
||||
{
|
||||
glfwInit();
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, true);
|
||||
glfwWindowHint(GLFW_VISIBLE, false);
|
||||
|
@ -101,17 +129,15 @@ void Window::create()
|
|||
return;
|
||||
}
|
||||
|
||||
if(!glGetTextureHandleARB || !glMakeTextureHandleResidentARB)
|
||||
if(glGetTextureHandleARB && glMakeTextureHandleResidentARB)
|
||||
{
|
||||
std::cerr << "Fatal: Bindless textures not supported\n";
|
||||
Shader::add_define("USE_BINDLESS_TEXTURES");
|
||||
Shader::USE_BINDLESS_TEXTURES = true;
|
||||
}
|
||||
|
||||
if(!glGetTextureHandleARB)
|
||||
std::cerr << " Missing: glGetTextureHandleARB\n";
|
||||
if(!glMakeTextureHandleResidentARB)
|
||||
std::cerr << " Missing: glMakeTextureHandleResidentARB\n";
|
||||
|
||||
close();
|
||||
return;
|
||||
else
|
||||
{
|
||||
std::cout << "Warning: Bindless textures are not supported. Using texture atlas instead.\n";
|
||||
}
|
||||
|
||||
glEnable(GL_MULTISAMPLE);
|
||||
|
@ -128,79 +154,59 @@ void Window::create()
|
|||
Mouse::init();
|
||||
Resize::init();
|
||||
Texture::init();
|
||||
Font::init();
|
||||
Fonts::init();
|
||||
UI::init();
|
||||
Shader::init();
|
||||
|
||||
Shader::MAIN.load("../assets/shader", "main.vsh", "main.fsh");
|
||||
Shader::MAIN.use();
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
Sim::System& sys = *System::active;
|
||||
Mesh m_scene, m_transparent;
|
||||
|
||||
Model model("../assets", "scene.glb");
|
||||
m_transparent = model.load("visual_water");
|
||||
m_scene = model.load("scene");
|
||||
|
||||
Camera::init(model);
|
||||
Mesh m_player = model.load("visual_player");
|
||||
|
||||
// send all the light data
|
||||
glGenBuffers(1, &ssbo_lights);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo_lights);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, model.lights.size() * sizeof(model.lights[0]), &model.lights[0], GL_STATIC_DRAW);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, ssbo_lights);
|
||||
gm_player.bind();
|
||||
gm_player.bind_ssbo();
|
||||
gm_player.set(m_player, GL_STATIC_DRAW);
|
||||
|
||||
g_scene.add(model.load("cr"));
|
||||
g_scene.add(model.load("cb"));
|
||||
g_scene.add(model.load("hw"));
|
||||
g_scene.bake_transforms();
|
||||
|
||||
Camera::init(model);
|
||||
|
||||
glUniform1i(Shader::MAIN["lights_count"], model.lights.size());
|
||||
|
||||
monitors.push_back(std::make_unique<Monitor::Core>(model));
|
||||
monitors.push_back(std::make_unique<Monitor::Vessel>(model));
|
||||
monitors.push_back(std::make_unique<Monitor::PrimaryLoop>(model));
|
||||
monitors.push_back(std::make_unique<Monitor::SecondaryLoop>(model));
|
||||
monitors.push_back(std::make_unique<Monitor::Turbine>(model));
|
||||
equipment.push_back(std::make_unique<Equipment::Reactor>(model));
|
||||
monitors.push_back(new Monitor::Core(model));
|
||||
monitors.push_back(new Monitor::Vessel(model));
|
||||
monitors.push_back(new Monitor::PrimaryLoop(model));
|
||||
monitors.push_back(new Monitor::SecondaryLoop(model));
|
||||
monitors.push_back(new Monitor::Turbine(model));
|
||||
monitors.push_back(monitor_cctv = new Monitor::CCTV(model));
|
||||
|
||||
for(auto& monitor : monitors)
|
||||
{
|
||||
monitor->remesh_static(m_scene);
|
||||
}
|
||||
equipment.push_back(new Equipment::Reactor(model));
|
||||
equipment.push_back(new Equipment::Generator(model));
|
||||
equipment.push_back(new Equipment::Pool(model));
|
||||
|
||||
for(auto& equipment : equipment)
|
||||
{
|
||||
equipment->remesh_static(m_scene);
|
||||
}
|
||||
|
||||
gm_scene.bind();
|
||||
gm_scene.set(m_scene, GL_STATIC_DRAW);
|
||||
|
||||
gm_transparent.bind();
|
||||
gm_transparent.set(m_transparent, GL_STATIC_DRAW);
|
||||
Texture::generate_atlas();
|
||||
|
||||
remesh_static();
|
||||
|
||||
glfwShowWindow(win);
|
||||
|
||||
// setup lighting and prerender shadows
|
||||
Shader::LIGHT.load("../assets/shader", "light.vsh", "light.gsh", "light.fsh");
|
||||
Shader::LIGHT.use();
|
||||
glUniform1f(Shader::LIGHT["far_plane"], 100.0f);
|
||||
GLLight::init();
|
||||
GLLights::init();
|
||||
|
||||
std::vector<unsigned long> light_handles;
|
||||
|
||||
for(int i = 0; i < model.lights.size(); i++)
|
||||
{
|
||||
GLLight light(model.lights[i]);
|
||||
light.render();
|
||||
|
||||
light_handles.push_back(light.handle);
|
||||
lights.push_back(std::move(light));
|
||||
}
|
||||
lights = std::make_unique<GLLights>(std::move(model.lights));
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, lights->ssbo);
|
||||
|
||||
Shader::MAIN.use();
|
||||
glUniform1f(Shader::MAIN["far_plane"], 100.0f);
|
||||
glUniform1i(Shader::MAIN["shadows_enabled"], 1);
|
||||
|
||||
// send all the light shadow map handles
|
||||
glGenBuffers(1, &ssbo_shadow_maps);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo_shadow_maps);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, light_handles.size() * sizeof(light_handles[0]), &light_handles[0], GL_STATIC_DRAW);
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, ssbo_shadow_maps);
|
||||
|
||||
// setup the transforms ssbos and their initial values
|
||||
|
||||
|
@ -239,6 +245,8 @@ void update_slow()
|
|||
equipment->remesh_slow(mesh);
|
||||
}
|
||||
|
||||
mesh.bake_transforms();
|
||||
|
||||
gm_dynamic_slow[gm_dynamic_slow_at].bind();
|
||||
gm_dynamic_slow[gm_dynamic_slow_at].set(mesh, GL_DYNAMIC_DRAW);
|
||||
gm_dynamic_slow_at = (gm_dynamic_slow_at + 1) % 2;
|
||||
|
@ -246,6 +254,11 @@ void update_slow()
|
|||
UI::update_slow();
|
||||
}
|
||||
|
||||
void Window::reload()
|
||||
{
|
||||
remesh_static();
|
||||
}
|
||||
|
||||
void Window::update(double dt)
|
||||
{
|
||||
Mesh mesh;
|
||||
|
@ -264,70 +277,109 @@ void Window::update(double dt)
|
|||
equipment->update(dt);
|
||||
equipment->get_static_transforms(transforms);
|
||||
}
|
||||
|
||||
for(int i = 0; i < transforms.size(); i++)
|
||||
{
|
||||
transforms[i] = g_scene_transforms[i] * transforms[i];
|
||||
}
|
||||
|
||||
if(transforms.size() != g_scene_transforms.size())
|
||||
{
|
||||
std::cerr << "Transforms size mismatch! " << transforms.size() << " != " << g_scene_transforms.size() << "\n";
|
||||
close();
|
||||
}
|
||||
|
||||
UI::update(dt);
|
||||
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, ssbo_transforms[ssbo_transforms_at]);
|
||||
ssbo_transforms_at = (ssbo_transforms_at + 1) % SSBO_TRANSFORMS_LEN;
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo_transforms[ssbo_transforms_at]);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, transforms.size() * sizeof(transforms[0]), &transforms[0], GL_DYNAMIC_DRAW);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, transforms.size() * sizeof(transforms[0]), &transforms[0], GL_STREAM_DRAW);
|
||||
ssbo_transforms_at = (ssbo_transforms_at + 1) % SSBO_TRANSFORMS_LEN;
|
||||
|
||||
secs_wait_now += dt;
|
||||
if(secs_wait_now > secs_wait_at + 1.0/30.0)
|
||||
if(wait_at++ % 4 == 0)
|
||||
{
|
||||
secs_wait_at += 1.0/30.0;
|
||||
update_slow();
|
||||
}
|
||||
}
|
||||
|
||||
void Window::render_player()
|
||||
{
|
||||
gm_player.bind();
|
||||
gm_player.bind_ssbo();
|
||||
gm_player.render();
|
||||
}
|
||||
|
||||
void Window::bind_scene_ssbo()
|
||||
{
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, ssbo_transforms[ssbo_transforms_at]);
|
||||
}
|
||||
|
||||
void Window::render_scene()
|
||||
{
|
||||
gm_scene.bind();
|
||||
gm_scene.uniform();
|
||||
gm_scene.render();
|
||||
|
||||
gm_dynamic_slow[gm_dynamic_slow_at].bind();
|
||||
gm_dynamic_slow[gm_dynamic_slow_at].uniform();
|
||||
gm_dynamic_slow[gm_dynamic_slow_at].render();
|
||||
|
||||
gm_transparent.bind();
|
||||
gm_transparent.uniform();
|
||||
gm_transparent.render();
|
||||
|
||||
Focus::render();
|
||||
}
|
||||
|
||||
void Window::render_dynamic()
|
||||
{
|
||||
gm_dynamic_slow[gm_dynamic_slow_at].bind();
|
||||
gm_dynamic_slow[gm_dynamic_slow_at].render();
|
||||
}
|
||||
|
||||
void Window::render()
|
||||
{
|
||||
glFrontFace(GL_CCW);
|
||||
|
||||
glm::vec<2, int> size = Resize::get_size();
|
||||
glm::vec3 camera_pos = Camera::get_pos();
|
||||
glm::mat4 mat_camera = Camera::get_matrix();
|
||||
|
||||
Shader::MAIN.use();
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glViewport(0, 0, size.x, size.y);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, lights->texid);
|
||||
glUniform1i(Shader::MAIN["shadow_maps"], 0);
|
||||
|
||||
glm::vec3 brightness = glm::vec3(System::active->grid.get_light_intensity());
|
||||
glm::mat4 mat_projection = glm::perspective(glm::radians(90.0f), Resize::get_aspect(), 0.01f, 100.f);
|
||||
glUniformMatrix4fv(Shader::MAIN["projection"], 1, false, &mat_projection[0][0]);
|
||||
glUniform3fv(Shader::MAIN["brightness"], 1, &brightness[0]);
|
||||
|
||||
glm::mat4 mat_player = glm::mat4(1);
|
||||
mat_player = glm::translate(mat_player, glm::vec3(Camera::get_pos_base()));
|
||||
mat_player = glm::rotate(mat_player, (float)glm::radians(90 - Camera::get_yaw()), glm::vec3(0, 0, 1));
|
||||
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, gm_player.ssbo);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(glm::mat4), &mat_player, GL_STREAM_DRAW);
|
||||
|
||||
monitor_cctv->render_view();
|
||||
|
||||
glUniformMatrix4fv(Shader::MAIN["camera"], 1, false, &mat_camera[0][0]);
|
||||
glUniform3fv(Shader::MAIN["camera_pos"], 1, &camera_pos[0]);
|
||||
glUniform3fv(Shader::MAIN["brightness"], 1, &brightness[0]);
|
||||
glUniformMatrix4fv(Shader::MAIN["projection"], 1, false, &mat_projection[0][0]);
|
||||
projection_matrix = mat_projection;
|
||||
|
||||
glFrontFace(GL_CCW);
|
||||
glClearColor(0, 0, 0, 1.0f);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||
glViewport(0, 0, size.x, size.y);
|
||||
|
||||
bind_scene_ssbo();
|
||||
render_scene();
|
||||
render_dynamic();
|
||||
monitor_cctv->render_screen();
|
||||
|
||||
brightness = glm::vec3(1);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
glUniform3fv(Shader::MAIN["brightness"], 1, &brightness[0]);
|
||||
|
||||
UI::render();
|
||||
Focus::render_ui();
|
||||
|
||||
glfwSwapBuffers(win);
|
||||
|
||||
Shader::LIGHT.use();
|
||||
glFrontFace(GL_CW);
|
||||
lights->render();
|
||||
}
|
||||
|
||||
bool Window::should_close()
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <glm/matrix.hpp>
|
||||
|
||||
#include "../system.hpp"
|
||||
|
||||
struct GLFWwindow;
|
||||
|
||||
namespace Sim::Graphics::Window
|
||||
{
|
||||
|
||||
|
@ -13,10 +14,13 @@ extern glm::mat4 projection_matrix;
|
|||
|
||||
bool should_close();
|
||||
void create();
|
||||
void remesh();
|
||||
void reload();
|
||||
void update(double dt);
|
||||
void render();
|
||||
void bind_scene_ssbo();
|
||||
void render_scene();
|
||||
void render_dynamic();
|
||||
void render_player();
|
||||
void destroy();
|
||||
void close();
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include "coolant/valve.hpp"
|
||||
#include "coolant/pump.hpp"
|
||||
|
||||
#include "graphics/mesh/mesh.hpp"
|
||||
#include "graphics/input/focus.hpp"
|
||||
|
||||
#include "graphics/window.hpp"
|
||||
|
|
|
@ -10,12 +10,14 @@
|
|||
namespace Sim::Reactor
|
||||
{
|
||||
|
||||
struct Reactor;
|
||||
|
||||
class Rod
|
||||
{
|
||||
public:
|
||||
|
||||
bool selected = false;
|
||||
void* reactor = nullptr;
|
||||
Reactor* reactor = nullptr;
|
||||
static const int VAL_N = 3;
|
||||
|
||||
enum val_t
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
#define STB_RECT_PACK_IMPLEMENTATION
|
||||
#include <stb/stb_rect_pack.h>
|
||||
|
|
@ -9,6 +9,7 @@
|
|||
#include "reactor/coolant/pipe.hpp"
|
||||
#include "reactor/coolant/heater.hpp"
|
||||
#include "graphics/camera.hpp"
|
||||
#include "graphics/window.hpp"
|
||||
|
||||
using namespace Sim;
|
||||
|
||||
|
@ -38,8 +39,9 @@ const char* CORE_LAYOUT[] = {
|
|||
|
||||
System::System() :
|
||||
vessel(Coolant::WATER, 8, 10, 6e6, 5e5, 10),
|
||||
reactor(Reactor::Builder(19, 19, 1.0 / 4.0, 4, Reactor::Fuel::FuelRod(0.5), &vessel, CORE_LAYOUT)),
|
||||
reactor(Reactor::Builder(19, 19, 0.4, 4, Reactor::Fuel::FuelRod(0.5), &vessel, CORE_LAYOUT)),
|
||||
evaporator(Coolant::WATER, 2, 30, 0, 1000),
|
||||
pool(Coolant::WATER, {16, 32, 11.3}, 16, 1e5, 0),
|
||||
sink(Coolant::WATER, 11, 0, 0),
|
||||
grid(),
|
||||
freight_pump(&sink, &evaporator, 1e5, 1, 1e4, 0.1, 10, Coolant::Pump::mode_t::DST, 1e6),
|
||||
|
@ -54,6 +56,7 @@ System::System(const Json::Value& node) :
|
|||
reactor(node["reactor"], &vessel),
|
||||
grid(node["grid"]),
|
||||
evaporator(node["evaporator"]),
|
||||
pool(node["pool"]),
|
||||
sink(evaporator.fluid, 11, 0, 0),
|
||||
freight_pump(node["pump"]["freight"], &sink, &evaporator),
|
||||
loop(node, &vessel, &evaporator, &grid)
|
||||
|
@ -81,6 +84,7 @@ System::operator Json::Value() const
|
|||
node["grid"] = grid;
|
||||
node["vessel"] = vessel;
|
||||
node["evaporator"] = evaporator;
|
||||
node["pool"] = pool;
|
||||
node["pump"]["freight"] = freight_pump;
|
||||
node["reactor"] = reactor;
|
||||
node["clock"] = clock;
|
||||
|
@ -113,6 +117,8 @@ void System::load(const char* path)
|
|||
Graphics::Camera::load(root["camera"]);
|
||||
std::unique_ptr<System> sys = std::make_unique<System>(root);
|
||||
active = std::move(sys);
|
||||
|
||||
Graphics::Window::reload();
|
||||
}
|
||||
|
||||
void System::save()
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "reactor/reactor.hpp"
|
||||
#include "electric/grid.hpp"
|
||||
#include "coolant/loop.hpp"
|
||||
#include "coolant/pool.hpp"
|
||||
|
||||
namespace Sim
|
||||
{
|
||||
|
@ -20,6 +21,7 @@ struct System
|
|||
Reactor::Reactor reactor;
|
||||
Reactor::Coolant::Vessel vessel;
|
||||
Coolant::Evaporator evaporator;
|
||||
Coolant::Pool pool;
|
||||
Coolant::Pump freight_pump;
|
||||
Coolant::Sink sink;
|
||||
Coolant::Loop loop;
|
||||
|
|
|
@ -19,13 +19,24 @@ constexpr double j_to_ms2(double j, double mass)
|
|||
return m*std::sqrt(m * j / (mass * 0.001));
|
||||
}
|
||||
|
||||
constexpr float map(float v, float imin, float imax, float omin, float omax)
|
||||
template <typename A>
|
||||
constexpr A map(A v, auto imin, auto imax, auto omin, auto omax)
|
||||
{
|
||||
return (v - imin) * (omax - omin) / (imax - imin) + omin;
|
||||
}
|
||||
|
||||
template<typename A, typename B>
|
||||
constexpr A mod(A a, B b)
|
||||
template <typename A>
|
||||
constexpr A clamp(A v, auto min, auto max)
|
||||
{
|
||||
if(v < min)
|
||||
return min;
|
||||
if(v > max)
|
||||
return max;
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename A>
|
||||
constexpr A mod(A a, auto b)
|
||||
{
|
||||
A v = std::fmod(a, b);
|
||||
|
||||
|
@ -37,5 +48,11 @@ constexpr A mod(A a, B b)
|
|||
return v;
|
||||
}
|
||||
|
||||
template <typename A>
|
||||
constexpr A ramp(A v, auto imin, auto imax, auto omin, auto omax)
|
||||
{
|
||||
return clamp(map(v, imin, imax, omin, omax), omin, omax);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -5,6 +5,39 @@
|
|||
#include <ostream>
|
||||
#include <glm/matrix.hpp>
|
||||
|
||||
namespace glm
|
||||
{
|
||||
|
||||
template <int N, typename T, glm::qualifier Q>
|
||||
std::ostream& operator<<(std::ostream& o, const glm::vec<N, T, Q>& v)
|
||||
{
|
||||
o << "{";
|
||||
|
||||
for(int i = 0; i < N - 1; i++)
|
||||
{
|
||||
o << v[i] << ", ";
|
||||
}
|
||||
|
||||
o << v[N - 1] << "}";
|
||||
return o;
|
||||
}
|
||||
|
||||
template <int N, int M, typename T, glm::qualifier Q>
|
||||
std::ostream& operator<<(std::ostream& o, const glm::mat<N, M, T, Q>& m)
|
||||
{
|
||||
o << "{";
|
||||
|
||||
for(int i = 0; i < N - 1; i++)
|
||||
{
|
||||
o << " " << m[i] << ", ";
|
||||
}
|
||||
|
||||
o << " " << m[N - 1] << "}";
|
||||
return o;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
namespace Sim::Util::Streams
|
||||
{
|
||||
|
||||
|
@ -23,17 +56,3 @@ std::ostream& show_units(std::ostream& o, double v);
|
|||
|
||||
};
|
||||
|
||||
template <int N, typename T>
|
||||
std::ostream& operator<<(std::ostream& o, const glm::vec<N, T>& v)
|
||||
{
|
||||
o << "{";
|
||||
|
||||
for(int i = 0; i < N - 1; i++)
|
||||
{
|
||||
o << v[i] << ", ";
|
||||
}
|
||||
|
||||
o << v[N - 1] << "}";
|
||||
return o;
|
||||
}
|
||||
|
||||
|
|