Compare commits

...

10 Commits

97 changed files with 1123 additions and 1228 deletions

2
.gitattributes vendored
View File

@ -1,4 +1,2 @@
*.png filter=lfs diff=lfs merge=lfs -text
*.stl filter=lfs diff=lfs merge=lfs -text
*.glb filter=lfs diff=lfs merge=lfs -text
*.blend filter=lfs diff=lfs merge=lfs -text

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

Binary file not shown.

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

Binary file not shown.

Binary file not shown.

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

Binary file not shown.

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

View File

@ -1,3 +0,0 @@
linear_extrude(0.0001)
square([1, 1], center = true);

Binary file not shown.

View File

@ -1,10 +0,0 @@
$fn = 256;
linear_extrude(0.0001)
translate([0.5, 0.5])
difference()
{
circle(d = 0.81);
circle(d = 0.8);
}

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

Binary file not shown.

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

Binary file not shown.

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

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

Binary file not shown.

Binary file not shown.

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

Binary file not shown.

13
assets/shader/light.fsh Normal file
View File

@ -0,0 +1,13 @@
#version 460 core
in vec3 frag_pos;
uniform float far_plane;
void main()
{
float distance = length(frag_pos);
gl_FragDepth = distance / far_plane;
}

33
assets/shader/light.gsh Normal file
View File

@ -0,0 +1,33 @@
#version 460 core
layout (triangles) in;
layout (triangle_strip, max_vertices=18) out;
uniform mat4 shadow_mats[6];
in float emissive[];
in float base_transparency[];
out vec3 frag_pos;
void main()
{
if(emissive[0] > 0 || base_transparency[0] > 0) return;
for(int i = 0; i < 6; i++)
{
gl_Layer = i;
for(int j = 0; j < 3; j++)
{
vec4 fp = gl_in[j].gl_Position;
gl_Position = shadow_mats[i] * fp;
frag_pos = fp.xyz;
EmitVertex();
}
EndPrimitive();
}
}

20
assets/shader/light.vsh Normal file
View File

@ -0,0 +1,20 @@
#version 460 core
layout (location = 2) in vec4 aPos;
layout (location = 4) in vec4 aColour;
layout (location = 5) in vec3 aMaterial;
uniform mat4 model;
uniform mat4 camera;
out float emissive;
out float base_transparency;
void main()
{
gl_Position = camera * model * aPos;
base_transparency = 1.f - aColour.a;
emissive = aMaterial[2];
}

View File

@ -2,11 +2,7 @@
#version 460 core
#extension GL_ARB_bindless_texture : require
const float PI = 3.141592;
const float Epsilon = 0.00001;
// Constant normal incidence Fresnel factor for all dielectrics.
const vec3 Fdielectric = vec3(0.04);
const float PI = 3.141592f;
in VS_OUT {
vec3 normal;
@ -27,29 +23,34 @@ layout(std140, binding = 1) buffer ssbo_lights
Light lights[];
};
layout(std430, binding = 2) buffer ssbo_shadow_maps
{
samplerCube shadow_maps[];
};
in flat sampler2D frag_tex;
out vec4 frag_colour;
uniform mat4 tex_mat;
uniform vec3 brightness;
uniform vec3 camera_pos;
uniform int lights_count;
uniform float far_plane;
uniform bool shadows_enabled;
vec3 fresnelSchlick(float cosTheta, vec3 F0)
vec3 FresnelSchlick(float cosTheta, vec3 F0)
{
return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0);
return F0 + (1.f - F0) * pow(clamp(1.f - cosTheta, 0.f, 1.f), 5.f);
}
float DistributionGGX(vec3 N, vec3 H, float roughness)
{
float a = roughness*roughness;
float a2 = a*a;
float NdotH = max(dot(N, H), 0.0);
float NdotH = max(dot(N, H), 0.f);
float NdotH2 = NdotH*NdotH;
float num = a2;
float denom = (NdotH2 * (a2 - 1.0) + 1.0);
float denom = (NdotH2 * (a2 - 1.f) + 1.f);
denom = PI * denom * denom;
return num / denom;
@ -57,27 +58,49 @@ float DistributionGGX(vec3 N, vec3 H, float roughness)
float GeometrySchlickGGX(float NdotV, float roughness)
{
float r = (roughness + 1.0);
float k = (r*r) / 8.0;
float r = (roughness + 1.f);
float k = (r*r) / 8.f;
float num = NdotV;
float denom = NdotV * (1.0 - k) + k;
float denom = NdotV * (1.f - k) + k;
return num / denom;
}
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
{
float NdotV = max(dot(N, V), 0.0);
float NdotL = max(dot(N, L), 0.0);
float NdotV = max(dot(N, V), 0.f);
float NdotL = max(dot(N, L), 0.f);
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
return ggx1 * ggx2;
}
vec3 LinRGB_To_sRGB(vec3 c)
{
bvec3 th = lessThan(c, vec3(0.0031308f));
vec3 high = pow(c, vec3(1.0f / 2.4f)) * vec3(1.055f) - vec3(0.055f);
vec3 low = c * vec3(12.92f);
return mix(high, low, th);
}
vec3 sRGB_To_LinRGB(vec3 c)
{
bvec3 th = lessThan(c, vec3(0.04045f));
vec3 high = pow((c + vec3(0.055f)) * vec3(1.0f / 1.055f), vec3(2.4f));
vec3 low = c * vec3(1.0f / 12.92f);
return mix(high, low, th);
}
void main()
{
vec4 albedo = (tex_mat * texture2D(frag_tex, vin.tex_pos)) * vin.colour;
vec4 albedo = texture2D(frag_tex, vin.tex_pos) * vin.colour;
if(albedo.a == 0.f) discard;
vec3 albedo_lin = sRGB_To_LinRGB(albedo.rgb);
float roughness = vin.material[0];
float metalness = vin.material[1];
@ -86,10 +109,10 @@ void main()
vec3 N = normalize(vin.normal);
vec3 V = normalize(camera_pos - vin.pos.xyz);
vec3 F0 = vec3(0.04);
F0 = mix(F0, albedo.rgb, metalness);
vec3 F0 = vec3(0.04f);
F0 = mix(F0, albedo_lin, metalness);
vec3 Lo = vec3(0.0);
vec3 Lo = vec3(0.0f);
for(int i = 0; i < lights_count; i++)
{
Light l = lights[i];
@ -104,29 +127,42 @@ void main()
// cook-torrance brdf
float NDF = DistributionGGX(N, H, roughness);
float G = GeometrySmith(N, V, L, roughness);
vec3 F = fresnelSchlick(max(dot(H, V), 0.0), F0);
vec3 F = FresnelSchlick(max(dot(H, V), 0.f), F0);
vec3 kS = F;
vec3 kD = vec3(1.0) - kS;
kD *= 1.0 - metalness;
vec3 kD = vec3(1.f) - kS;
kD *= 1.f - metalness;
vec3 numerator = NDF * G * F;
float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001;
float denominator = 4.f * max(dot(N, V), 0.f) * max(dot(N, L), 0.f) + 1e-4f;
vec3 specular = numerator / denominator;
// add to outgoing radiance Lo
float NdotL = max(dot(N, L), 0.0);
Lo += (kD * albedo.rgb / PI + specular) * radiance * NdotL;
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;
}
vec3 ambient = vec3(0.03f) * albedo.rgb * brightness;
vec3 light = ambient + Lo;
else
{
light_m = 1.f;
spec_m = 1.f;
}
light = light / (light + vec3(1.f));
light = pow(light, vec3(1.f/2.2f));
light = light * (1 - luminance) + albedo.rgb * luminance;
// 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;
}
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);
if(frag_colour.a == 0.f) discard;
}

Binary file not shown.

Binary file not shown.

BIN
assets/test.glb (Stored with Git LFS)

Binary file not shown.

View File

@ -1,382 +0,0 @@
{
"asset":{
"generator":"Khronos glTF Blender I/O v4.0.44",
"version":"2.0"
},
"scene":0,
"scenes":[
{
"extras":{
"SimpleBake_Props":{},
"bake_to_vertex_color_props":{}
},
"name":"Scene",
"nodes":[
0,
1,
2,
3
]
}
],
"nodes":[
{
"mesh":0,
"name":"Cylinder",
"translation":[
0,
0,
0.5
]
},
{
"mesh":1,
"name":"Cylinder.001",
"translation":[
1,
0,
0.5
]
},
{
"mesh":2,
"name":"Cylinder.002",
"translation":[
3,
0,
0.5
]
},
{
"mesh":3,
"name":"Cylinder.003",
"translation":[
2,
0,
0.5
]
}
],
"materials":[
{
"doubleSided":true,
"name":"Material.006",
"pbrMetallicRoughness":{
"baseColorFactor":[
0.800000011920929,
0.800000011920929,
0.800000011920929,
1
],
"metallicFactor":0,
"roughnessFactor":0.75
}
},
{
"doubleSided":true,
"name":"Material.005",
"pbrMetallicRoughness":{
"baseColorFactor":[
0.800000011920929,
0.800000011920929,
0.800000011920929,
1
],
"metallicFactor":0,
"roughnessFactor":0.5
}
},
{
"doubleSided":true,
"name":"Material.003",
"pbrMetallicRoughness":{
"baseColorFactor":[
0.800000011920929,
0.800000011920929,
0.800000011920929,
1
],
"metallicFactor":0,
"roughnessFactor":0.125
}
},
{
"doubleSided":true,
"name":"Material.004",
"pbrMetallicRoughness":{
"baseColorFactor":[
0.800000011920929,
0.800000011920929,
0.800000011920929,
1
],
"metallicFactor":0,
"roughnessFactor":0.25
}
}
],
"meshes":[
{
"name":"Cylinder",
"primitives":[
{
"attributes":{
"POSITION":0,
"NORMAL":1,
"TEXCOORD_0":2
},
"indices":3,
"material":0
}
]
},
{
"name":"Cylinder.001",
"primitives":[
{
"attributes":{
"POSITION":4,
"NORMAL":5,
"TEXCOORD_0":6
},
"indices":3,
"material":1
}
]
},
{
"name":"Cylinder.002",
"primitives":[
{
"attributes":{
"POSITION":7,
"NORMAL":8,
"TEXCOORD_0":9
},
"indices":3,
"material":2
}
]
},
{
"name":"Cylinder.003",
"primitives":[
{
"attributes":{
"POSITION":10,
"NORMAL":11,
"TEXCOORD_0":12
},
"indices":3,
"material":3
}
]
}
],
"accessors":[
{
"bufferView":0,
"componentType":5126,
"count":192,
"max":[
0.20000000298023224,
0.20000000298023224,
0.5
],
"min":[
-0.20000000298023224,
-0.20000000298023224,
-0.5
],
"type":"VEC3"
},
{
"bufferView":1,
"componentType":5126,
"count":192,
"type":"VEC3"
},
{
"bufferView":2,
"componentType":5126,
"count":192,
"type":"VEC2"
},
{
"bufferView":3,
"componentType":5123,
"count":372,
"type":"SCALAR"
},
{
"bufferView":4,
"componentType":5126,
"count":192,
"max":[
0.20000000298023224,
0.20000000298023224,
0.5
],
"min":[
-0.20000000298023224,
-0.20000000298023224,
-0.5
],
"type":"VEC3"
},
{
"bufferView":5,
"componentType":5126,
"count":192,
"type":"VEC3"
},
{
"bufferView":6,
"componentType":5126,
"count":192,
"type":"VEC2"
},
{
"bufferView":7,
"componentType":5126,
"count":192,
"max":[
0.20000000298023224,
0.20000000298023224,
0.5
],
"min":[
-0.20000000298023224,
-0.20000000298023224,
-0.5
],
"type":"VEC3"
},
{
"bufferView":8,
"componentType":5126,
"count":192,
"type":"VEC3"
},
{
"bufferView":9,
"componentType":5126,
"count":192,
"type":"VEC2"
},
{
"bufferView":10,
"componentType":5126,
"count":192,
"max":[
0.20000000298023224,
0.20000000298023224,
0.5
],
"min":[
-0.20000000298023224,
-0.20000000298023224,
-0.5
],
"type":"VEC3"
},
{
"bufferView":11,
"componentType":5126,
"count":192,
"type":"VEC3"
},
{
"bufferView":12,
"componentType":5126,
"count":192,
"type":"VEC2"
}
],
"bufferViews":[
{
"buffer":0,
"byteLength":2304,
"byteOffset":0,
"target":34962
},
{
"buffer":0,
"byteLength":2304,
"byteOffset":2304,
"target":34962
},
{
"buffer":0,
"byteLength":1536,
"byteOffset":4608,
"target":34962
},
{
"buffer":0,
"byteLength":744,
"byteOffset":6144,
"target":34963
},
{
"buffer":0,
"byteLength":2304,
"byteOffset":6888,
"target":34962
},
{
"buffer":0,
"byteLength":2304,
"byteOffset":9192,
"target":34962
},
{
"buffer":0,
"byteLength":1536,
"byteOffset":11496,
"target":34962
},
{
"buffer":0,
"byteLength":2304,
"byteOffset":13032,
"target":34962
},
{
"buffer":0,
"byteLength":2304,
"byteOffset":15336,
"target":34962
},
{
"buffer":0,
"byteLength":1536,
"byteOffset":17640,
"target":34962
},
{
"buffer":0,
"byteLength":2304,
"byteOffset":19176,
"target":34962
},
{
"buffer":0,
"byteLength":2304,
"byteOffset":21480,
"target":34962
},
{
"buffer":0,
"byteLength":1536,
"byteOffset":23784,
"target":34962
}
],
"buffers":[
{
"byteLength":25320,
"uri":"test.bin"
}
]
}

View File

@ -79,9 +79,9 @@ glm::vec<3, double> Camera::get_pos()
return pos;
}
void Camera::init()
void Camera::init(const Model& model)
{
collision_scene.load_model("../assets/model", "scene_collisions.stl");
collision_scene = model.load("collision");
}
void Camera::update(double dt)
@ -123,11 +123,10 @@ void Camera::update(double dt)
velocity.z += 3.5;
}
glm::vec<3, double> normal_last(0);
glm::vec<3, double> velocity2;
velocity2 = collision_scene.calc_intersect(pos, velocity * dt, normal_last);
velocity2 = collision_scene.calc_intersect(pos + glm::vec<3, double>(0, 0, -1.5), velocity2, normal_last) / dt;
velocity2 = collision_scene.calc_intersect(pos, velocity * dt);
velocity2 = collision_scene.calc_intersect(pos + glm::vec<3, double>(0, 0, -1.5), velocity2) / dt;
pos += velocity2 * dt;
on_ground = ((velocity * dt / dt).z != velocity2.z);

View File

@ -5,6 +5,7 @@
#include <json/json.h>
#include "../system.hpp"
#include "mesh/model.hpp"
namespace Sim::Graphics::Camera
{
@ -18,7 +19,7 @@ double get_yaw();
Json::Value serialize();
void load(const Json::Value& node);
void init();
void init(const Model& model);
void rotate(double pitch, double yaw);
void move(double x, double y, double z);
void update(double dt);

View File

@ -0,0 +1,58 @@
#include "reactor.hpp"
#include "../../system.hpp"
#include "../../reactor/rod.hpp"
#include "../../reactor/coolant/vessel.hpp"
#include <glm/matrix.hpp>
#include <glm/gtc/matrix_transform.hpp>
using namespace Sim::Graphics::Equipment;
Reactor::Reactor(const Model& model, Mesh& rmesh)
{
g_control_rod = model.load("visual_control_rod");
}
void Reactor::update(double dt)
{
}
void Reactor::remesh_slow(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;
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())
{
continue;
}
if(r->get_colour()[3] != 0)
{
rmesh.add(g_control_rod, glm::translate(glm::mat4(1), glm::vec3(ox, oy, (1 - r->get_colour().r) * sys.reactor.cell_height)));
}
}
}
void Reactor::remesh_fast(Mesh& rmesh)
{
}
void Reactor::render()
{
}

View File

@ -0,0 +1,23 @@
#pragma once
#include "../mesh/meshgen.hpp"
namespace Sim::Graphics::Equipment
{
class Reactor : public MeshGen
{
Mesh g_control_rod;
public:
Reactor(const Model& model, Mesh& rmesh);
virtual void update(double dt);
virtual void remesh_slow(Mesh& rmesh);
virtual void remesh_fast(Mesh& rmesh);
virtual void render();
};
};

View File

@ -6,39 +6,39 @@ using namespace Sim::Graphics;
const glm::mat4 Locations::monitors[7] = {
(
glm::translate(glm::mat4(1), glm::vec3(-2.949, -1.7778 + 0.05, 3 - 0.05)) *
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.949, 3 - 0.05)) *
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.949, 3 - 0.05)) *
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.949, 3 - 0.05)) *
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.949, 3 - 0.05)) *
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.949, 7.0/3.0 - 0.05, 3 - 0.05)) *
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.949, -1.0/3.0 - 0.05, 3 - 0.05)) *
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))

View File

@ -38,13 +38,3 @@ void Arrays::vertex_attrib_pointers()
glEnableVertexAttribArray(5);
}
glm::mat4 Arrays::colour(glm::vec4 c)
{
return glm::mat4({
c.r, c.g, c.b, c.a,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0
});
}

View File

@ -14,10 +14,12 @@ struct Vertex
glm::vec3 normal = {0, 0, 0};
glm::vec4 colour = {1, 1, 1, 1};
glm::vec3 material = {0, 0, 0};
constexpr bool operator==(const Vertex&) const = default;
} __attribute__((packed));
void vertex_attrib_pointers();
glm::mat4 colour(glm::vec4 code);
};

View File

@ -48,6 +48,7 @@ void Font::init()
FT_Set_Pixel_Sizes(face, 0, size);
GLuint texids[128];
std::vector<glm::vec<4, unsigned char>> pixels;
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
@ -74,10 +75,17 @@ void Font::init()
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_R8, width, height);
glTextureSubImage2D(texids[i], 0, 0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE, face->glyph->bitmap.buffer);
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);
@ -150,3 +158,31 @@ void Mesh::load_text(const char* text, double size)
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;
}
}

View File

@ -0,0 +1,86 @@
#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]);
}

View File

@ -0,0 +1,28 @@
#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();
};
};

View File

@ -33,7 +33,6 @@ GLMesh::GLMesh(GLMesh&& o)
ebo = o.ebo;
vao = o.vao;
size = o.size;
colour_matrix = o.colour_matrix;
model_matrix = o.model_matrix;
o.vbo = 0;
@ -53,18 +52,17 @@ void GLMesh::bind()
init(this);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
}
void GLMesh::uniform()
{
glUniformMatrix4fv(Shader::MAIN["model"], 1, false, &model_matrix[0][0]);
glUniformMatrix4fv(Shader::MAIN["tex_mat"], 1, false, &colour_matrix[0][0]);
glUniformMatrix4fv(Shader::ACTIVE->get("model"), 1, false, &model_matrix[0][0]);
}
void GLMesh::set(const Mesh& m, int mode)
{
glBindBuffer(GL_ARRAY_BUFFER, vbo);
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();

View File

@ -16,7 +16,6 @@ struct GLMesh
unsigned int vao = 0, vbo = 0, ebo = 0, size = 0;
glm::mat4 model_matrix {1.0f};
glm::mat4 colour_matrix {1.0f};
constexpr GLMesh() { }

View File

@ -19,6 +19,8 @@ struct Light
glm::vec3 colour;
float padding2;
constexpr bool operator==(const Light&) const = default;
} __attribute__((packed));
};

View File

@ -155,17 +155,11 @@ bool Mesh::check_intersect(vec3 pos, vec3 path) const
return false;
}
vec3 Mesh::calc_intersect(vec3 pos, vec3 path) const
{
vec3 normal_last(0);
return calc_intersect(pos, path, normal_last);
}
static bool calc_intercept_vert(vec3 v[3], vec3 pos, vec3& path, vec3& path_n, vec3& normal_last, double& l)
static bool calc_intercept_vert(vec3 v[3], vec3 pos, vec3& path, vec3& path_n, double& l)
{
vec3 ipoint;
vec3 normal = glm::normalize(glm::cross(v[1] - v[0], v[2] - v[0]));
double d = glm::dot(normal, path);
double d = glm::dot(path, normal);
if(d >= 0)
return false;
@ -174,20 +168,11 @@ static bool calc_intercept_vert(vec3 v[3], vec3 pos, vec3& path, vec3& path_n, v
if(l < glm::length(ipoint - pos))
return false;
if(normal_last != vec3(0))
if(d < 0)
{
vec3 n = glm::cross(normal_last, normal);
if(glm::length(n) > 0)
{
normal = glm::normalize(glm::cross(glm::cross(normal_last, normal), normal_last));
d = glm::dot(normal, path);
}
}
path -= normal * d;
normal_last = normal;
l = glm::length(path);
}
if(l > 0)
{
@ -197,7 +182,7 @@ static bool calc_intercept_vert(vec3 v[3], vec3 pos, vec3& path, vec3& path_n, v
return true;
}
vec3 Mesh::calc_intersect(vec3 pos, vec3 path, vec3& normal_last) const
vec3 Mesh::calc_intersect(vec3 pos, vec3 path) const
{
double l = glm::length(path);
@ -217,7 +202,7 @@ vec3 Mesh::calc_intersect(vec3 pos, vec3 path, vec3& normal_last) const
vec3(this->vertices[indices[i + 2]].pos)
};
if(calc_intercept_vert(v, pos, path, path_n, normal_last, l))
if(calc_intercept_vert(v, pos, path, path_n, l))
{
i_found = i;
}
@ -236,7 +221,7 @@ vec3 Mesh::calc_intersect(vec3 pos, vec3 path, vec3& normal_last) const
vec3(this->vertices[indices[i + 2]].pos)
};
calc_intercept_vert(v, pos, path, path_n, normal_last, l);
calc_intercept_vert(v, pos, path, path_n, l);
if(l == 0)
{
@ -265,3 +250,4 @@ Mesh Mesh::to_lines() const
return m;
}

View File

@ -17,18 +17,15 @@ namespace Sim::Graphics
struct Mesh
{
std::unordered_map<std::string, glm::mat4> mat_nodes;
std::vector<Arrays::Vertex> vertices;
std::vector<unsigned int> indices;
std::vector<Light> lights;
Mesh();
void set_vertices(const Arrays::Vertex* data, size_t size);
void set_indices(const unsigned int* data, size_t size);
void load_model(std::string base, std::string path);
void load_model(std::string path);
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);
@ -37,7 +34,8 @@ struct Mesh
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;
glm::vec<3, double> calc_intersect(glm::vec<3, double> pos, glm::vec<3, double> path, glm::vec<3, double>& normal_last) const;
bool operator==(const Mesh&) const = default;
template <class T>
void load_text(const char* header, T& item, double size)

View File

@ -0,0 +1,20 @@
#pragma once
#include "../mesh/model.hpp"
namespace Sim::Graphics
{
class MeshGen
{
public:
virtual ~MeshGen() {}
virtual void update(double dt) = 0;
virtual void remesh_slow(Mesh& rmesh) = 0;
virtual void remesh_fast(Mesh& rmesh) = 0;
virtual void render() = 0;
};
};

View File

@ -2,10 +2,6 @@
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/postprocess.h>
#include <assimp/material.h>
#include <glm/matrix.hpp>
#include <unordered_map>
@ -15,6 +11,7 @@
#include "mesh.hpp"
#include "arrays.hpp"
#include "texture.hpp"
#include "model.hpp"
#include "../../util/streams.hpp"
using namespace Sim::Graphics;
@ -24,11 +21,9 @@ struct ProcState
unsigned int offset = 0;
std::string base;
std::vector<Light> lights;
std::vector<Arrays::Vertex> vertices;
std::vector<unsigned int> indices;
std::unordered_map<const aiTexture*, unsigned int> handles;
std::unordered_map<std::string, glm::mat4> mat_nodes;
};
static unsigned int proc_texture(const ProcState& state, aiMaterial* mat, const aiScene* scene, aiTextureType type, int index)
@ -62,7 +57,7 @@ static void proc_mesh(ProcState& state, glm::mat4 mat, aiMesh* mesh, const aiSce
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++)
@ -97,7 +92,7 @@ static void proc_mesh(ProcState& state, glm::mat4 mat, aiMesh* mesh, const aiSce
}
std::cout << "\n";
}
}*/
glm::vec3 matv(0);
aiColor4D ai_cb;
@ -117,8 +112,6 @@ static void proc_mesh(ProcState& state, glm::mat4 mat, aiMesh* mesh, const aiSce
cb = em;
}
std::cout << "Material: " << matv << "\n";
unsigned int handle = proc_texture(state, material, scene, aiTextureType_BASE_COLOR, 0);
unsigned int offset = state.offset;
glm::mat3 mat3(mat);
@ -179,7 +172,7 @@ static void proc_mesh(ProcState& state, glm::mat4 mat, aiMesh* mesh, const aiSce
state.offset += mesh->mNumVertices;
}
glm::mat4 get_mat(aiMatrix4x4 m)
glm::mat4 convert_mat(aiMatrix4x4 m)
{
return {
m.a1, m.a2, m.a3, m.a4,
@ -189,21 +182,38 @@ glm::mat4 get_mat(aiMatrix4x4 m)
};
}
static void proc_node(ProcState& state, glm::mat4 mat, aiNode* node, const aiScene* scene)
bool starts_with(const char* base, const char* check)
{
mat = get_mat(node->mTransformation) * mat;
std::string name(node->mName.C_Str());
state.mat_nodes[name] = mat;
while(base[0] != '\0' && check[0] != '\0')
{
if(base[0] != check[0])
{
return false;
}
base++;
check++;
}
return (check[0] == '\0');
}
static void proc_node(ProcState& state, glm::mat4 mat, aiNode* node, const aiScene* scene, const char* search)
{
mat = convert_mat(node->mTransformation) * mat;
if(starts_with(node->mName.C_Str(), search))
{
for(size_t i = 0; i < node->mNumMeshes; i++)
{
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
proc_mesh(state, mat, mesh, scene);
}
}
for(size_t i = 0; i < node->mNumChildren; i++)
{
proc_node(state, mat, node->mChildren[i], scene);
proc_node(state, mat, node->mChildren[i], scene, search);
}
}
@ -216,76 +226,92 @@ static unsigned int proc_embedded_texture(aiTexture* tex)
return Texture::load_mem((unsigned char*)tex->pcData, tex->mWidth);
}
// swizzle each pixel to get RGBA
std::vector<glm::vec<4, unsigned char>> pixels;
pixels.reserve(tex->mWidth * tex->mHeight);
// convert image to get RGBA
for(int i = 0; i < tex->mWidth * tex->mHeight; i++)
{
aiTexel t = tex->pcData[i];
tex->pcData[i] = {t.r, t.g, t.b, t.a};
pixels.push_back({t.r, t.g, t.b, t.a});
}
return Texture::load_mem((unsigned char*)tex->pcData, tex->mWidth, tex->mHeight, 4);
return Texture::load_mem(&pixels[0][0], tex->mWidth, tex->mHeight, 4);
}
glm::mat4 get_transforms(aiNode* node)
glm::mat4 get_transforms(const aiNode* node)
{
glm::mat4 mat(1);
while(node->mParent != nullptr)
{
mat *= get_mat(node->mTransformation);
mat = mat * convert_mat(node->mTransformation);
node = node->mParent;
}
return mat;
}
void Mesh::load_model(std::string path)
glm::mat4 Model::get_matrix(const char* name) const
{
load_model(".", path);
return get_transforms(scene->mRootNode->FindNode(name));
}
void Mesh::load_model(std::string base, std::string filename)
Model::Model(std::string base, std::string filename) : base(base)
{
ProcState state {.base = base};
std::string path = base + "/" + filename;
Assimp::Importer importer;
scene = importer.ReadFile(path.c_str(), aiProcess_Triangulate | aiProcess_FlipUVs);
const aiScene *scene = importer.ReadFile(path.c_str(), aiProcess_Triangulate | aiProcess_FlipUVs);
if(scene == nullptr)
{
std::cerr << "AssImp: Error loading model\n";
return;
}
textures.reserve(scene->mNumTextures);
for(int i = 0; i < scene->mNumTextures; i++)
{
aiTexture* tex = scene->mTextures[i];
unsigned int handle = proc_embedded_texture(tex);
state.handles[tex] = handle;
textures.push_back(handle);
}
for(int i = 0; i < scene->mNumLights; i++)
{
aiLight* light = scene->mLights[i];
glm::mat4 mat = get_transforms(scene->mRootNode->FindNode(light->mName));
glm::mat4 mat = get_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;
state.lights.push_back({
lights.push_back({
glm::vec3(pos),
{r, g, b},
});
}
proc_node(state, glm::mat4(1), scene->mRootNode, scene);
mat_nodes = std::move(state.mat_nodes);
vertices = std::move(state.vertices);
indices = std::move(state.indices);
lights = std::move(state.lights);
}
Mesh Model::load(const char* name, glm::mat4 mat) const
{
Mesh mesh;
ProcState state {.base = base};
proc_node(state, mat, scene->mRootNode, scene, name);
mesh.vertices = std::move(state.vertices);
mesh.indices = std::move(state.indices);
return mesh;
}
Mesh Model::load_root(glm::mat4 mat) const
{
return load("", mat);
}
Mesh Model::load(const char* name) const
{
return load(name, glm::mat4(1));
}
Mesh Model::load_root() const
{
return load("", glm::mat4(1));
}

View File

@ -0,0 +1,42 @@
#pragma once
#include "mesh.hpp"
#include "light.hpp"
#include <string>
#include <vector>
#include <glm/matrix.hpp>
#include <assimp/Importer.hpp>
#include <assimp/scene.h>
#include <assimp/material.h>
#include <assimp/postprocess.h>
namespace Sim::Graphics
{
class Model
{
std::string base;
Assimp::Importer importer;
const aiScene* scene;
public:
std::vector<uint64_t> textures;
std::vector<Light> lights;
Model(std::string base, std::string filename);
Model(const Model&) = delete;
Mesh load_root() const;
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;
};
};

View File

@ -92,7 +92,7 @@ unsigned int Texture::load(std::string path)
throw std::runtime_error("Failed to load path: " + path);
}
std::cout << "Loaded Image: " << path << "\n";
std::cout << "Loaded image: " << path << "\n";
loaded[path] = handle;
return handle;

View File

@ -80,8 +80,6 @@ struct CoreMonitor : public Focus::FocusType
default:
return;
}
parent->is_dirty = true;
}
};
@ -97,7 +95,6 @@ struct CoreJoystick : public Focus::FocusType
virtual void on_cursor_pos(double x, double y)
{
System::active->reactor.add_rod_speed(y * 1e-6);
parent->is_dirty = true;
}
virtual ~CoreJoystick()
@ -119,33 +116,26 @@ struct CoreJoystick : public Focus::FocusType
}
};
Core::Core()
Core::Core(const Model& model, Mesh& rmesh)
{
}
Mesh mesh = model.load("translation_monitor_3");
mat = Locations::monitors[2];
void Core::init()
{
mesh1.model_matrix = mesh2.model_matrix = Locations::monitors[2];
mesh1.colour_matrix = mesh2.colour_matrix = Arrays::colour({1, 1, 1, 1});
mesh.load_text("Reactor Core", 0.04);
rmesh.add(mesh, mat);
Sim::Graphics::Mesh rmesh;
rmesh.load_text("Reactor Core", 0.04);
mesh1.bind();
mesh1.set(rmesh, GL_STATIC_DRAW);
m_buttons[0].load_model("../assets/model/", "reactor_core_button1.stl");
m_buttons[1].load_model("../assets/model/", "reactor_core_button2.stl");
m_buttons[2].load_model("../assets/model/", "reactor_core_button3.stl");
m_buttons[3].load_model("../assets/model/", "reactor_core_button4.stl");
m_buttons[4].load_model("../assets/model/", "reactor_core_button5.stl");
m_buttons[5].load_model("../assets/model/", "reactor_core_button6.stl");
m_buttons[6].load_model("../assets/model/", "reactor_core_button7.stl");
m_buttons[7].load_model("../assets/model/", "reactor_core_button8.stl");
m_buttons[8].load_model("../assets/model/", "reactor_core_button9.stl");
m_joystick.load_model("../assets/model/", "reactor_core_joystick.stl");
m_monitor.load_model("../assets/model/", "reactor_core_input.stl");
m_scram.load_model("../assets/model/", "reactor_core_scram.stl");
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");
m_joystick = model.load("click_reactor_joystick");
m_monitor = model.load("translation_monitor_3");
m_scram = model.load("click_scram");
}
static Mesh add_dot(glm::mat4 model_mat, glm::vec4 colour)
@ -168,66 +158,44 @@ void Core::update(double dt)
{
Sim::System& sys = *System::active;
if(m_monitor.check_focus()) {
if(m_monitor.check_focus())
Focus::set(std::make_unique<CoreMonitor>(this));
}
if(m_joystick.check_focus()) {
if(m_joystick.check_focus())
Focus::set(std::make_unique<CoreJoystick>(this));
}
if(m_scram.check_focus()) {
if(m_scram.check_focus())
sys.reactor.scram();
is_dirty = true;
}
if(m_buttons[0].check_focus()) {
if(m_buttons[0].check_focus())
set_all(true);
is_dirty = true;
}
if(m_buttons[1].check_focus()) {
if(m_buttons[1].check_focus())
sys.reactor.move_cursor(-sys.reactor.height);
is_dirty = true;
}
if(m_buttons[2].check_focus()) {
if(m_buttons[2].check_focus())
set_all(false);
is_dirty = true;
}
if(m_buttons[3].check_focus()) {
if(m_buttons[3].check_focus())
sys.reactor.move_cursor(-1);
is_dirty = true;
}
if(m_buttons[4].check_focus()) {
if(m_buttons[4].check_focus())
sys.reactor.toggle_selected();
is_dirty = true;
}
if(m_buttons[5].check_focus()) {
if(m_buttons[5].check_focus())
sys.reactor.move_cursor(1);
is_dirty = true;
}
if(m_buttons[6].check_focus()) {
if(m_buttons[6].check_focus())
sys.reactor.reset_rod_speed();
is_dirty = true;
}
if(m_buttons[7].check_focus()) {
if(m_buttons[7].check_focus())
sys.reactor.move_cursor(sys.reactor.height);
is_dirty = true;
}
}
clock_now += dt;
void Core::remesh_slow(Mesh& rmesh)
{
remesh(rmesh, false);
}
if(clock_at + 1.0/30.0 > clock_now)
{
if(!is_dirty)
{
return;
}
}
void Core::remesh_fast(Mesh& rmesh)
{
remesh(rmesh, true);
}
else
{
clock_at += 1.0/30.0;
}
Sim::Graphics::Mesh rmesh;
is_dirty = false;
void Core::remesh(Mesh& rmesh, bool fast)
{
Sim::System& sys = *System::active;
Sim::Graphics::Mesh mesh;
double step = 1 / (sys.vessel.diameter / sys.reactor.cell_width * 0.8);
double sx = 0.5 - (sys.reactor.width - 1) * step / 2.0;
@ -252,6 +220,10 @@ void Core::update(double dt)
continue;
}
glm::mat4 mat = glm::translate(glm::mat4(1), glm::vec3(ox, oy, 0)) * mat_scale;
if(!fast)
{
glm::vec4 colour_heat = r->get_heat_colour() * glm::vec4(glm::vec3(1), 1);
glm::vec4 colour_spec = r->get_colour();
@ -260,38 +232,32 @@ void Core::update(double dt)
continue;
}
glm::mat4 mat = glm::translate(glm::mat4(1), glm::vec3(ox, oy, 0)) * mat_scale;
mesh.add(add_dot(mat, colour_heat));
rmesh.add(add_dot(mat, colour_heat));
if(colour_spec[3] != 0)
{
mesh.add(add_dot(mat * mat_spec, colour_spec));
}
}
else
{
if(sys.reactor.cursor == i)
{
rmesh.add(add_dot(mat * mat_cursor, {1, 0, 0, 1}));
mesh.add(add_dot(mat * mat_cursor, {1, 0, 0, 1}));
}
if(r->selected)
{
rmesh.add(add_dot(mat * mat_select, {1, 1, 0, 1}));
mesh.add(add_dot(mat * mat_select, {1, 1, 0, 1}));
}
if(colour_spec[3] != 0)
{
rmesh.add(add_dot(mat * mat_spec, colour_spec));
}
}
mesh2.bind();
mesh2.set(rmesh, GL_DYNAMIC_DRAW);
rmesh.add(mesh, mat);
}
void Core::render()
{
mesh1.bind();
mesh1.uniform();
mesh1.render();
mesh2.bind();
mesh2.uniform();
mesh2.render();
}

View File

@ -1,29 +1,29 @@
#pragma once
#include "../mesh/glmesh.hpp"
#include "../mesh/model.hpp"
#include "../mesh/meshgen.hpp"
namespace Sim::Graphics::Monitor
{
class Core
class Core : public MeshGen
{
Sim::Graphics::GLMesh mesh1, mesh2;
double clock_at = 0, clock_now = 0;
glm::mat4 mat;
Sim::Graphics::Mesh m_monitor;
Sim::Graphics::Mesh m_buttons[9];
Sim::Graphics::Mesh m_joystick;
Sim::Graphics::Mesh m_scram;
Mesh m_monitor;
Mesh m_buttons[9];
Mesh m_joystick;
Mesh m_scram;
public:
bool is_dirty = false;
Core();
void init();
void update(double dt);
void render();
Core(const Model& model, Mesh& rmesh);
void remesh(Mesh& rmesh, bool fast);
virtual void update(double dt);
virtual void remesh_slow(Mesh& rmesh);
virtual void remesh_fast(Mesh& rmesh);
virtual void render();
};
};

View File

@ -49,26 +49,12 @@ struct ValveJoystick : public Focus::FocusType
}
};
PrimaryLoop::PrimaryLoop()
PrimaryLoop::PrimaryLoop(const Model& model, Mesh& rmesh)
{
}
void PrimaryLoop::init()
{
mesh1.model_matrix = Locations::monitors[3];
mesh2.model_matrix = glm::translate(mesh1.model_matrix, glm::vec3(0.5, 0, 0));
mesh1.colour_matrix = mesh2.colour_matrix = {
1, 1, 1, 1,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0
};
mat = Locations::monitors[3];
std::stringstream ss;
Sim::Graphics::Mesh rmesh;
Sim::Graphics::Mesh mesh;
ss << "Turbine Bypass Valve\n\n";
ss << "Opened\nFlow\nSetpoint\n\n";
@ -82,39 +68,41 @@ void PrimaryLoop::init()
ss << "Pressure\n";
ss << "Level\n";
rmesh.load_text(ss.str().c_str(), 0.04);
mesh1.bind();
mesh1.set(rmesh, GL_STATIC_DRAW);
mesh.load_text(ss.str().c_str(), 0.04);
rmesh.add(mesh, mat);
rmesh.load_model("../assets/model", "pump_switch_1.glb");
gm_switch_pump.bind();
gm_switch_pump.set(rmesh, GL_STATIC_DRAW);
g_switch_pump = model.load("visual_pump_switch_1");
g_switch_bypass = model.load("visual_bypass_switch");
g_switch_inlet = model.load("visual_inlet_switch");
rmesh.load_model("../assets/model", "turbine_valve_bypass_switch.glb");
gm_switch_bypass.bind();
gm_switch_bypass.set(rmesh, GL_STATIC_DRAW);
rmesh.load_model("../assets/model", "turbine_valve_inlet_switch.glb");
gm_switch_inlet.bind();
gm_switch_inlet.set(rmesh, GL_STATIC_DRAW);
m_joystick_turbine_bypass.load_model("../assets/model", "turbine_valve_bypass_joystick.stl");
m_joystick_turbine_inlet.load_model("../assets/model", "turbine_valve_inlet_joystick.stl");
m_switch_pump.load_model("../assets/model", "pump_switch_click_1.stl");
m_switch_bypass.load_model("../assets/model", "turbine_valve_bypass_switch_click.stl");
m_switch_inlet.load_model("../assets/model", "turbine_valve_inlet_switch_click.stl");
m_joystick_turbine_bypass = model.load("click_bypass_joystick");
m_joystick_turbine_inlet = model.load("click_inlet_joystick");
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");
}
void PrimaryLoop::update(double dt)
{
System& sys = *System::active;
clock_now += dt;
if(clock_at + 1.0/30.0 < clock_now)
{
if(m_joystick_turbine_bypass.check_focus())
Focus::set(std::make_unique<ValveJoystick>(&sys.loop.turbine_bypass_valve));
if(m_joystick_turbine_inlet.check_focus())
Focus::set(std::make_unique<ValveJoystick>(&sys.loop.turbine_inlet_valve));
if(m_switch_pump.check_focus())
sys.loop.primary_pump.powered = !sys.loop.primary_pump.powered;
if(m_switch_inlet.check_focus())
sys.loop.turbine_inlet_valve.toggle_auto();
if(m_switch_bypass.check_focus())
sys.loop.turbine_bypass_valve.toggle_auto();
}
void PrimaryLoop::remesh_slow(Mesh& rmesh)
{
std::stringstream ss;
Sim::Graphics::Mesh rmesh;
clock_at += 1.0/30.0;
Sim::Graphics::Mesh mesh;
System& sys = *System::active;
ss << "\n\n";
ss << show( sys.loop.turbine_bypass_valve.get_state() * 100 ) << " %\n";
@ -154,47 +142,24 @@ void PrimaryLoop::update(double dt)
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";
rmesh.load_text(ss.str().c_str(), 0.04);
mesh2.bind();
mesh2.set(rmesh, GL_DYNAMIC_DRAW);
}
mesh.load_text(ss.str().c_str(), 0.04);
rmesh.add(mesh, glm::translate(mat, glm::vec3(0.5, 0, 0)));
}
if(m_joystick_turbine_bypass.check_focus())
Focus::set(std::make_unique<ValveJoystick>(&sys.loop.turbine_bypass_valve));
if(m_joystick_turbine_inlet.check_focus())
Focus::set(std::make_unique<ValveJoystick>(&sys.loop.turbine_inlet_valve));
if(m_switch_pump.check_focus())
sys.loop.primary_pump.powered = !sys.loop.primary_pump.powered;
if(m_switch_inlet.check_focus())
sys.loop.turbine_inlet_valve.toggle_auto();
if(m_switch_bypass.check_focus())
sys.loop.turbine_bypass_valve.toggle_auto();
void PrimaryLoop::remesh_fast(Mesh& rmesh)
{
System& sys = *System::active;
gm_switch_inlet.model_matrix = glm::translate(glm::mat4(1), glm::vec3(0, sys.loop.turbine_inlet_valve.get_auto() ? 0.07 : 0, 0));
gm_switch_bypass.model_matrix = glm::translate(glm::mat4(1), glm::vec3(0, sys.loop.turbine_bypass_valve.get_auto() ? 0.07 : 0, 0));
gm_switch_pump.model_matrix = glm::translate(glm::mat4(1), glm::vec3(0, sys.loop.primary_pump.powered ? 0.07 : 0, 0));
float off1 = sys.loop.primary_pump.powered ? 0.07 : 0;
float off2 = sys.loop.turbine_bypass_valve.get_auto() ? 0.07 : 0;
float off3 = sys.loop.turbine_inlet_valve.get_auto() ? 0.07 : 0;
rmesh.add(g_switch_pump, glm::translate(glm::mat4(1), glm::vec3(0, off1, 0)));
rmesh.add(g_switch_bypass, glm::translate(glm::mat4(1), glm::vec3(0, off2, 0)));
rmesh.add(g_switch_inlet, glm::translate(glm::mat4(1), glm::vec3(0, off3, 0)));
}
void PrimaryLoop::render()
{
mesh1.bind();
mesh1.uniform();
mesh1.render();
mesh2.bind();
mesh2.uniform();
mesh2.render();
gm_switch_pump.bind();
gm_switch_pump.uniform();
gm_switch_pump.render();
gm_switch_inlet.bind();
gm_switch_inlet.uniform();
gm_switch_inlet.render();
gm_switch_bypass.bind();
gm_switch_bypass.uniform();
gm_switch_bypass.render();
}

View File

@ -1,33 +1,34 @@
#pragma once
#include "../mesh/glmesh.hpp"
#include "../mesh/model.hpp"
#include "../mesh/meshgen.hpp"
namespace Sim::Graphics::Monitor
{
class PrimaryLoop
class PrimaryLoop : public MeshGen
{
GLMesh mesh1, mesh2;
double clock_at = 0, clock_now = 0;
GLMesh gm_switch_pump;
GLMesh gm_switch_bypass;
GLMesh gm_switch_inlet;
glm::mat4 mat;
Mesh m_joystick_turbine_bypass;
Mesh m_joystick_turbine_inlet;
Mesh g_switch_pump;
Mesh g_switch_bypass;
Mesh g_switch_inlet;
Mesh m_switch_pump;
Mesh m_switch_bypass;
Mesh m_switch_inlet;
public:
PrimaryLoop();
void init();
void update(double dt);
void render();
PrimaryLoop(const Model& model, Mesh& rmesh);
virtual void update(double dt);
virtual void remesh_slow(Mesh& rmesh);
virtual void remesh_fast(Mesh& rmesh);
virtual void render();
};
};

View File

@ -16,25 +16,13 @@ using namespace Sim::Graphics;
using namespace Sim::Graphics::Monitor;
using namespace Sim::Util::Streams;
SecondaryLoop::SecondaryLoop()
SecondaryLoop::SecondaryLoop(const Model& model, Mesh& rmesh)
{
}
void SecondaryLoop::init()
{
mesh1.model_matrix = Locations::monitors[5];
mesh2.model_matrix = glm::translate(mesh1.model_matrix, glm::vec3(0.5, 0, 0));
mesh1.colour_matrix = mesh2.colour_matrix = {
1, 1, 1, 1,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0
};
mat = Locations::monitors[5];
std::stringstream ss;
Sim::Graphics::Mesh rmesh;
Sim::Graphics::Mesh mesh;
ss << "Cooling Tower\n\n";
ss << "Heat\nSteam\nPressure\nLevel\n\n";
@ -43,34 +31,33 @@ void SecondaryLoop::init()
ss << "Freight Pump\n\n";
ss << "Power\nSpeed\nFlow\n\n";
rmesh.load_text(ss.str().c_str(), 0.04);
mesh1.bind();
mesh1.set(rmesh, GL_STATIC_DRAW);
mesh.load_text(ss.str().c_str(), 0.04);
rmesh.add(mesh, mat);
rmesh.load_model("../assets/model", "pump_switch_2.glb");
gm_switch_2.bind();
gm_switch_2.set(rmesh, GL_STATIC_DRAW);
g_switch_2 = model.load("visual_pump_switch_2");
g_switch_3 = model.load("visual_pump_switch_3");
rmesh.load_model("../assets/model", "pump_switch_3.glb");
gm_switch_3.bind();
gm_switch_3.set(rmesh, GL_STATIC_DRAW);
m_joystick_turbine_bypass.load_model("../assets/model", "turbine_valve_bypass_joystick.stl");
m_joystick_turbine_inlet.load_model("../assets/model", "turbine_valve_inlet_joystick.stl");
m_switch_2.load_model("../assets/model", "pump_switch_click_2.stl");
m_switch_3.load_model("../assets/model", "pump_switch_click_3.stl");
m_joystick_turbine_bypass = model.load("click_bypass_joystick");
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");
}
void SecondaryLoop::update(double dt)
{
System& sys = *System::active;
clock_now += dt;
if(clock_at + 1.0/30.0 < clock_now)
{
if(m_switch_2.check_focus())
sys.loop.secondary_pump.powered = !sys.loop.secondary_pump.powered;
if(m_switch_3.check_focus())
sys.freight_pump.powered = !sys.freight_pump.powered;
}
void SecondaryLoop::remesh_slow(Mesh& rmesh)
{
std::stringstream ss;
Sim::Graphics::Mesh rmesh;
clock_at += 1.0/30.0;
Sim::Graphics::Mesh mesh;
System& sys = *System::active;
ss << "\n\n";
ss << show( sys.evaporator.get_heat() ) << " C\n";
@ -86,37 +73,23 @@ void SecondaryLoop::update(double dt)
ss << show( sys.freight_pump.get_rpm() ) << " r/min\n";
show_units( ss, sys.freight_pump.get_flow_mass() ) << "g/s\n";
rmesh.load_text(ss.str().c_str(), 0.04);
mesh2.bind();
mesh2.set(rmesh, GL_DYNAMIC_DRAW);
}
mesh.load_text(ss.str().c_str(), 0.04);
rmesh.add(mesh, glm::translate(mat, glm::vec3(0.5, 0, 0)));
}
if(m_switch_2.check_focus())
sys.loop.secondary_pump.powered = !sys.loop.secondary_pump.powered;
if(m_switch_3.check_focus())
sys.freight_pump.powered = !sys.freight_pump.powered;
void SecondaryLoop::remesh_fast(Mesh& rmesh)
{
System& sys = *System::active;
gm_switch_2.model_matrix = glm::translate(glm::mat4(1), glm::vec3(0, sys.loop.secondary_pump.powered ? 0.07 : 0, 0));
gm_switch_3.model_matrix = glm::translate(glm::mat4(1), glm::vec3(0, sys.freight_pump.powered ? 0.07 : 0, 0));
float off2 = sys.loop.secondary_pump.powered ? 0.07 : 0;
float off3 = sys.freight_pump.powered ? 0.07 : 0;
rmesh.add(g_switch_2, glm::translate(glm::mat4(1), glm::vec3(0, off2, 0)));
rmesh.add(g_switch_3, glm::translate(glm::mat4(1), glm::vec3(0, off3, 0)));
}
void SecondaryLoop::render()
{
mesh1.bind();
mesh1.uniform();
mesh1.render();
mesh2.bind();
mesh2.uniform();
mesh2.render();
gm_switch_2.bind();
gm_switch_2.uniform();
gm_switch_2.render();
gm_switch_3.bind();
gm_switch_3.uniform();
gm_switch_3.render();
}

View File

@ -1,30 +1,31 @@
#pragma once
#include "../mesh/glmesh.hpp"
#include "../mesh/model.hpp"
#include "../mesh/meshgen.hpp"
namespace Sim::Graphics::Monitor
{
class SecondaryLoop
class SecondaryLoop : public MeshGen
{
Sim::Graphics::GLMesh mesh1, mesh2;
double clock_at = 0, clock_now = 0;
glm::mat4 mat;
Sim::Graphics::GLMesh gm_switch_2;
Sim::Graphics::GLMesh gm_switch_3;
Mesh g_switch_2;
Mesh g_switch_3;
Sim::Graphics::Mesh m_joystick_turbine_bypass;
Sim::Graphics::Mesh m_joystick_turbine_inlet;
Sim::Graphics::Mesh m_switch_2;
Sim::Graphics::Mesh m_switch_3;
Mesh m_joystick_turbine_bypass;
Mesh m_joystick_turbine_inlet;
Mesh m_switch_2;
Mesh m_switch_3;
public:
SecondaryLoop();
void init();
void update(double dt);
void render();
SecondaryLoop(const Model& model, Mesh& rmesh);
virtual void update(double dt);
virtual void remesh_slow(Mesh& rmesh);
virtual void remesh_fast(Mesh& rmesh);
virtual void render();
};
};

View File

@ -16,85 +16,33 @@ using namespace Sim::Graphics;
using namespace Sim::Graphics::Monitor;
using namespace Sim::Util::Streams;
Turbine::Turbine()
Turbine::Turbine(const Model& model, Mesh& rmesh)
{
}
void Turbine::init()
{
mesh1.model_matrix = mesh2.model_matrix = Locations::monitors[4];
mesh1.colour_matrix = mesh2.colour_matrix = {
1, 1, 1, 1,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0
};
mat = Locations::monitors[4];
std::stringstream ss;
Sim::Graphics::Mesh rmesh, rmesh2;
Sim::Graphics::Mesh mesh;
ss << "Turbine\n\n";
ss << "Heat\nPressure\nSpeed\n\n";
rmesh.load_text(ss.str().c_str(), 0.04);
rmesh2.load_text("Synchroscope", 0.04);
rmesh.add(rmesh2, glm::translate(glm::mat4(1), glm::vec3(0, 0.6, 0)));
mesh.load_text(ss.str().c_str(), 0.04);
rmesh.add(mesh, mat);
mesh1.bind();
mesh1.set(rmesh, GL_STATIC_DRAW);
mesh.load_text("Synchroscope", 0.04);
rmesh.add(mesh, glm::translate(mat, glm::vec3(0, 0.6, 0)));
rmesh.load_model("../assets/model", "synchroscope_dial.stl");
mesh = model.load("visual_synchroscope_dial");
gm_synchroscope_dial.bind();
gm_synchroscope_dial.set(rmesh, GL_STATIC_DRAW);
gm_synchroscope_dial.set(mesh, GL_STATIC_DRAW);
rmesh.load_model("../assets/model", "turbine_breaker_switch.glb");
gm_switch_breaker.bind();
gm_switch_breaker.set(rmesh, GL_STATIC_DRAW);
m_switch_breaker.load_model("../assets/model", "turbine_breaker_switch_click.stl");
g_switch_breaker = model.load("visual_breaker_switch");
m_switch_breaker = model.load("click_breaker_switch");
}
void Turbine::update(double dt)
{
System& sys = *System::active;
clock_now += dt;
if(clock_at + 1.0/30.0 < clock_now)
{
std::stringstream ss;
Sim::Graphics::Mesh rmesh, rmesh2;
clock_at += 1.0/30.0;
ss << "\n\n";
ss << show( sys.loop.turbine.get_heat() ) << " C\n";
ss << show( sys.loop.turbine.get_pressure() / 1000 ) << " kPa\n";
ss << show( sys.loop.generator.get_rpm() ) << " r/min\n";
rmesh2.load_text(ss.str().c_str(), 0.04);
rmesh.add(rmesh2, glm::translate(glm::mat4(1), glm::vec3(0.5, 0, 0)));
ss = std::stringstream();
ss << "Local\n\n";
ss << show( sys.loop.generator.get_rpm() / 60 ) << " Hz\n";
Util::Streams::show_units( ss, sys.loop.generator.get_energy_generated() ) << "W\n";
rmesh2.load_text(ss.str().c_str(), 0.04);
rmesh.add(rmesh2, glm::translate(glm::mat4(1), glm::vec3(0.4, 0.7, 0)));
ss = std::stringstream();
ss << "Grid\n\n";
ss << show( sys.grid.frequency ) << " Hz\n";
rmesh2.load_text(ss.str().c_str(), 0.04);
rmesh.add(rmesh2, glm::translate(glm::mat4(1), glm::vec3(0.7, 0.7, 0)));
mesh2.bind();
mesh2.set(rmesh, GL_DYNAMIC_DRAW);
}
double rpm = sys.loop.generator.get_rpm();
if(rpm > 3570 && rpm < 3630)
@ -108,20 +56,49 @@ void Turbine::update(double dt)
if(m_switch_breaker.check_focus())
sys.loop.generator.breaker_closed = !sys.loop.generator.breaker_closed;
}
gm_switch_breaker.model_matrix = glm::translate(glm::mat4(1), glm::vec3(0, sys.loop.generator.breaker_closed ? 0.07 : 0, 0));
void Turbine::remesh_slow(Mesh& rmesh)
{
std::stringstream ss;
Sim::Graphics::Mesh mesh;
System& sys = *System::active;
ss << "\n\n";
ss << show( sys.loop.turbine.get_heat() ) << " C\n";
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);
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.7, 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.7, 0)));
}
void Turbine::remesh_fast(Mesh& rmesh)
{
System& sys = *System::active;
float off1 = sys.loop.generator.breaker_closed ? 0.07 : 0;
rmesh.add(g_switch_breaker, glm::translate(glm::mat4(1), glm::vec3(0, off1, 0)));
}
void Turbine::render()
{
mesh1.bind();
mesh1.uniform();
mesh1.render();
mesh2.bind();
mesh2.uniform();
mesh2.render();
double rpm = System::active->loop.generator.get_rpm();
if(rpm > 3570 && rpm < 3630)
@ -130,9 +107,5 @@ void Turbine::render()
gm_synchroscope_dial.uniform();
gm_synchroscope_dial.render();
}
gm_switch_breaker.bind();
gm_switch_breaker.uniform();
gm_switch_breaker.render();
}

View File

@ -1,26 +1,28 @@
#pragma once
#include "../mesh/model.hpp"
#include "../mesh/glmesh.hpp"
#include "../mesh/meshgen.hpp"
namespace Sim::Graphics::Monitor
{
class Turbine
class Turbine : public MeshGen
{
Sim::Graphics::GLMesh mesh1, mesh2;
double clock_at = 0, clock_now = 0;
glm::mat4 mat;
Sim::Graphics::GLMesh gm_synchroscope_dial;
Sim::Graphics::GLMesh gm_switch_breaker;
Sim::Graphics::Mesh m_switch_breaker;
GLMesh gm_synchroscope_dial;
Mesh g_switch_breaker;
Mesh m_switch_breaker;
public:
Turbine();
void init();
void update(double dt);
void render();
Turbine(const Model& model, Mesh& rmesh);
virtual void update(double dt);
virtual void remesh_slow(Mesh& rmesh);
virtual void remesh_fast(Mesh& rmesh);
virtual void render();
};
};

View File

@ -15,25 +15,12 @@
using namespace Sim::Graphics::Monitor;
using namespace Sim::Util::Streams;
Vessel::Vessel()
Vessel::Vessel(const Model& model, Mesh& rmesh)
{
}
void Vessel::init()
{
mesh1.model_matrix = Locations::monitors[1];
mesh2.model_matrix = glm::translate(mesh1.model_matrix, glm::vec3(0.5, 0, 0));
mesh1.colour_matrix = mesh2.colour_matrix = {
1, 1, 1, 1,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0
};
mat = Locations::monitors[1];
std::stringstream ss;
Sim::Graphics::Mesh rmesh;
Sim::Graphics::Mesh mesh;
ss << "Reactor Vessel\n\n";
ss << "Heat\n";
@ -47,27 +34,23 @@ void Vessel::init()
ss << "Temperature\nMin\nMax\n\n";
ss << "Control Rods\nMin\nMax\nSpeed\n";
rmesh.load_text(ss.str().c_str(), 0.04);
mesh1.bind();
mesh1.set(rmesh, GL_STATIC_DRAW);
mesh.load_text(ss.str().c_str(), 0.04);
rmesh.add(mesh, mat);
}
void Vessel::update(double dt)
{
std::stringstream ss;
Sim::Graphics::Mesh rmesh;
Sim::System& sys = *System::active;
clock_now += dt;
}
if(clock_at + 1.0/30.0 > clock_now)
{
return;
}
void Vessel::remesh_slow(Mesh& rmesh)
{
std::stringstream ss;
Sim::Graphics::Mesh mesh;
Sim::System& sys = *System::active;
double temp_min, temp_max;
double crod_min = INFINITY, crod_max = -INFINITY;
clock_at += 1.0/30.0;
sys.reactor.get_stats(Sim::Reactor::Rod::val_t::HEAT, temp_min, temp_max);
for(int i = 0; i < sys.reactor.size; i++)
@ -110,19 +93,15 @@ void Vessel::update(double dt)
if(sys.reactor.rod_speed == 0) ss << " (Stopped)";
ss << "\n";
rmesh.load_text(ss.str().c_str(), 0.04);
mesh2.bind();
mesh2.set(rmesh, GL_DYNAMIC_DRAW);
mesh.load_text(ss.str().c_str(), 0.04);
rmesh.add(mesh, glm::translate(mat, glm::vec3(0.5, 0, 0)));
}
void Vessel::remesh_fast(Mesh& rmesh)
{
}
void Vessel::render()
{
mesh1.bind();
mesh1.uniform();
mesh1.render();
mesh2.bind();
mesh2.uniform();
mesh2.render();
}

View File

@ -1,22 +1,23 @@
#pragma once
#include "../mesh/glmesh.hpp"
#include "../mesh/model.hpp"
#include "../mesh/meshgen.hpp"
namespace Sim::Graphics::Monitor
{
class Vessel
class Vessel : public MeshGen
{
Sim::Graphics::GLMesh mesh1, mesh2;
double clock_at = 0, clock_now = 0;
glm::mat4 mat;
public:
Vessel();
void init();
void update(double dt);
void render();
Vessel(const Model& model, Mesh& rmesh);
virtual void update(double dt);
virtual void remesh_slow(Mesh& rmesh);
virtual void remesh_fast(Mesh& rmesh);
virtual void render();
};
};

View File

@ -13,6 +13,8 @@ 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)
{
@ -39,6 +41,12 @@ static std::string read_shader(const char* path)
return ss.str();
}
static std::string read_shader(const char* base, const char* file)
{
std::string path = std::string(base) + "/" + std::string(file);
return read_shader(path.c_str());
}
Shader::Shader()
{
@ -60,18 +68,29 @@ Shader::~Shader()
void Shader::load(const char* path, const char* file_vsh, const char* file_fsh)
{
std::string path_vsh = std::string(path) + "/" + std::string(file_vsh);
std::string path_fsh = std::string(path) + "/" + std::string(file_fsh);
std::string shader_vsh = read_shader(path_vsh.c_str());
std::string shader_fsh = read_shader(path_fsh.c_str());
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 = load_shader(shader_vsh.c_str(), GL_VERTEX_SHADER);
int fsh_id = load_shader(shader_fsh.c_str(), GL_FRAGMENT_SHADER);
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);
glLinkProgram(prog_id);
glGetProgramiv(prog_id, GL_LINK_STATUS, &success);
@ -85,13 +104,21 @@ void Shader::load(const char* path, const char* file_vsh, const char* file_fsh)
}
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()
{
glUseProgram(prog_id);
ACTIVE = this;
}
unsigned int Shader::operator [](const char* pos)
@ -106,3 +133,8 @@ unsigned int Shader::operator [](const char* pos)
return uniform_locations[pos] = glGetUniformLocation(prog_id, pos);
}
unsigned int Shader::get(const char* pos)
{
return operator[](pos);
}

View File

@ -16,16 +16,21 @@ public:
static Shader MAIN;
static Shader BLUR;
static Shader LIGHT;
static Shader* ACTIVE;
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);
void use();
unsigned int operator[](const char* pos);
unsigned int get(const char* pos);
};
};

View File

@ -18,9 +18,13 @@
using namespace Sim::Graphics;
static GLMesh s_mesh;
static GLMesh gm_ui;
static GLMesh gm_dynamic_slow[2];
static Widget::Clock w_clock;
static int gm_dynamic_slow_at = 0;
void UI::init()
{
Mesh m;
@ -37,8 +41,8 @@ void UI::init()
m.set_indices(indices, 6);
m.set_vertices(vertices, 4);
s_mesh.bind();
s_mesh.set(m, GL_STATIC_DRAW);
gm_ui.bind();
gm_ui.set(m, GL_STATIC_DRAW);
}
void UI::update(double dt)
@ -46,6 +50,17 @@ void UI::update(double dt)
w_clock.update(dt);
}
void UI::update_slow()
{
Mesh mesh;
w_clock.remesh_slow(mesh);
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;
}
void UI::render()
{
glClear(GL_DEPTH_BUFFER_BIT);
@ -57,9 +72,13 @@ void UI::render()
glUniformMatrix4fv(Shader::MAIN["projection"], 1, false, &mat_projection[0][0]);
glUniformMatrix4fv(Shader::MAIN["camera"], 1, false, &mat_camera[0][0]);
s_mesh.bind();
s_mesh.uniform();
s_mesh.render();
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();
}

View File

@ -6,6 +6,7 @@ namespace Sim::Graphics::UI
void init();
void update(double dt);
void update_slow();
void render();
};

View File

@ -19,6 +19,11 @@
using namespace Sim::Graphics::Widget;
void Clock::update(double dt)
{
this->dt = dt;
}
void Clock::remesh_slow(Mesh& rmesh)
{
Mesh m;
double at = System::active->clock;
@ -29,23 +34,17 @@ void Clock::update(double dt)
int t_m = std::fmod(at / 60, 60);
int t_h = std::fmod(at / 3600, 24);
// ss << "FPS: " << (1.0 / dt) << "\n";
ss << "Time: " << std::setfill('0') << std::setw(2) << t_h << ":";
ss << std::setfill('0') << std::setw(2) << t_m << ":";
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);
data.bind();
data.model_matrix = glm::translate(glm::mat4(1), glm::vec3(-wsize + glm::vec2(2, 2), 0));
data.colour_matrix = Arrays::colour({1, 1, 1, 1});
data.set(m, GL_DYNAMIC_DRAW);
rmesh.add(m, glm::translate(glm::mat4(1), glm::vec3(-wsize + glm::vec2(2, 2), 0)));
}
void Clock::render()
{
data.bind();
data.uniform();
data.render();
}

View File

@ -8,9 +8,10 @@ namespace Sim::Graphics::Widget
struct Clock
{
GLMesh data;
double dt;
void update(double dt);
void remesh_slow(Mesh& rmesh);
void render();
};

View File

@ -7,6 +7,8 @@
#include <glm/ext/matrix_clip_space.hpp> // glm::perspective
#include <iostream>
#include <vector>
#include <memory>
#include "mesh/mesh.hpp"
#include "mesh/arrays.hpp"
@ -25,6 +27,10 @@
#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 "equipment/reactor.hpp"
#include "../system.hpp"
#include "../util/streams.hpp"
#include "ui.hpp"
@ -34,20 +40,32 @@ using namespace Sim::Graphics;
static GLFWwindow* win;
static bool win_should_close = false;
static unsigned int ssbo_lights;
static unsigned int ssbo_shadow_maps;
static double secs_wait_at = 0;
static double secs_wait_now = 0;
static GLMesh mesh_scene;
static int gm_dynamic_slow_at = 0;
static Monitor::Vessel monitor_vessel;
static Monitor::Core monitor_core;
static Monitor::PrimaryLoop monitor_primary_loop;
static Monitor::SecondaryLoop monitor_secondary_loop;
static Monitor::Turbine monitor_turbine;
static GLMesh gm_scene;
static GLMesh gm_transparent;
static GLMesh gm_dynamic_slow[2];
static GLMesh gm_dynamic_fast;
static Mesh m_dynamic_fast;
static std::vector<GLLight> lights;
static std::vector<std::unique_ptr<MeshGen>> monitors;
static std::vector<std::unique_ptr<MeshGen>> equipment;
glm::mat4 Window::projection_matrix;
static void GLAPIENTRY cb_debug_message(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam)
{
if(severity != GL_DEBUG_SEVERITY_NOTIFICATION)
if(severity == GL_DEBUG_SEVERITY_HIGH)
{
throw std::runtime_error(message);
}
else if(severity != GL_DEBUG_SEVERITY_NOTIFICATION)
{
std::cout << "GL CALLBACK: " << message << "\n";
}
@ -108,7 +126,6 @@ void Window::create()
Mouse::init();
Resize::init();
Texture::init();
Camera::init();
Font::init();
UI::init();
@ -116,109 +133,180 @@ void Window::create()
glBindFramebuffer(GL_FRAMEBUFFER, 0);
Sim::System& sys = *System::active;
Mesh m, m2;
Mesh m_scene, m_transparent;
m.load_model("../assets", "scene.glb");
Model model("../assets", "scene.glb");
m_transparent = model.load("visual_water");
m_scene = model.load("scene");
// find the floor parts of the model and set them slightly transparent
for(int i = 0; i < m.indices.size(); i += 3)
{
Arrays::Vertex& v1 = m.vertices[m.indices[i]];
Arrays::Vertex& v2 = m.vertices[m.indices[i + 1]];
Arrays::Vertex& v3 = m.vertices[m.indices[i + 2]];
if(v1.pos.z <= 0 && v2.pos.z <= 0 && v3.pos.z <= 0)
{
v1.colour.w = 0.95;
v2.colour.w = 0.95;
v3.colour.w = 0.95;
}
}
for(Light& light : m.lights)
{
std::cout << "Sent light: " << light.pos << " with " << light.colour << "\n";
}
std::cout << "Light struct is " << sizeof(m.lights[0]) << " bytes\n";
Camera::init(model);
// send all the light data
glGenBuffers(1, &ssbo_lights);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo_lights);
glBufferData(GL_SHADER_STORAGE_BUFFER, m.lights.size() * sizeof(m.lights[0]), &m.lights[0], GL_STATIC_DRAW);
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);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
glUniform1i(Shader::MAIN["lights_count"], m.lights.size());
glUniform1i(Shader::MAIN["lights_count"], model.lights.size());
mesh_scene.bind();
mesh_scene.set(m, GL_STATIC_DRAW);
monitors.push_back(std::make_unique<Monitor::Core>(model, m_scene));
monitors.push_back(std::make_unique<Monitor::Vessel>(model, m_scene));
monitors.push_back(std::make_unique<Monitor::PrimaryLoop>(model, m_scene));
monitors.push_back(std::make_unique<Monitor::SecondaryLoop>(model, m_scene));
monitors.push_back(std::make_unique<Monitor::Turbine>(model, m_scene));
monitor_core.init();
monitor_vessel.init();
monitor_primary_loop.init();
monitor_secondary_loop.init();
monitor_turbine.init();
equipment.push_back(std::make_unique<Equipment::Reactor>(model, m_scene));
gm_scene.bind();
gm_scene.set(m_scene, GL_STATIC_DRAW);
gm_transparent.bind();
gm_transparent.set(m_transparent, GL_STATIC_DRAW);
glfwShowWindow(win);
glViewport(0, 0, 800, 600);
// setup lighting and prerender shadows
Shader::LIGHT.load("../assets/shader", "light.vsh", "light.gsh", "light.fsh");
glUniform1f(Shader::LIGHT["far_plane"], 100.0f);
GLLight::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));
}
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);
}
void update_slow()
{
Mesh mesh;
for(auto& monitor : monitors)
{
monitor->remesh_slow(mesh);
}
for(auto& equipment : equipment)
{
equipment->remesh_slow(mesh);
}
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;
UI::update_slow();
}
void Window::update(double dt)
{
Mesh mesh;
glfwPollEvents();
monitor_core.update(dt);
monitor_vessel.update(dt);
monitor_primary_loop.update(dt);
monitor_secondary_loop.update(dt);
monitor_turbine.update(dt);
for(auto& monitor : monitors)
{
monitor->update(dt);
}
for(auto& equipment : equipment)
{
equipment->update(dt);
}
UI::update(dt);
for(auto& monitor : monitors)
{
monitor->remesh_fast(mesh);
}
for(auto& equipment : equipment)
{
equipment->remesh_fast(mesh);
}
if(mesh != m_dynamic_fast)
{
gm_dynamic_fast.bind();
gm_dynamic_fast.set(mesh, GL_DYNAMIC_DRAW);
m_dynamic_fast = std::move(mesh);
}
secs_wait_now += dt;
if(secs_wait_now > secs_wait_at + 1.0/30.0)
{
secs_wait_at += 1.0/30.0;
update_slow();
}
}
void render_scene()
void Window::render_scene()
{
mesh_scene.bind();
mesh_scene.uniform();
mesh_scene.render();
gm_scene.bind();
gm_scene.uniform();
gm_scene.render();
monitor_core.render();
monitor_vessel.render();
monitor_primary_loop.render();
monitor_secondary_loop.render();
monitor_turbine.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_dynamic_fast.bind();
gm_dynamic_fast.uniform();
gm_dynamic_fast.render();
for(auto& monitor : monitors)
{
monitor->render();
}
for(auto& equipment : equipment)
{
equipment->render();
}
gm_transparent.bind();
gm_transparent.uniform();
gm_transparent.render();
Focus::render();
}
void Window::render()
{
glm::vec<2, int> size = Resize::get_size();
glm::vec3 camera_pos = Camera::get_pos();
glm::mat4 mat_camera = Camera::get_matrix();
mat_camera = glm::scale(mat_camera, {1, 1, -1});
camera_pos.z *= -1;
Shader::MAIN.use();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, size.x, size.y);
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, 20.f);
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]);
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]);
glUniform3fv(Shader::MAIN["camera_pos"], 1, &camera_pos[0]);
projection_matrix = mat_projection;
glClearColor(0, 0, 0, 1.0f);
glClear(GL_DEPTH_BUFFER_BIT);
glFrontFace(GL_CW);
render_scene();
camera_pos.z *= -1;
mat_camera = Camera::get_matrix();
glUniformMatrix4fv(Shader::MAIN["camera"], 1, false, &mat_camera[0][0]);
glUniform3fv(Shader::MAIN["camera_pos"], 1, &camera_pos[0]);
glClear(GL_DEPTH_BUFFER_BIT);
glFrontFace(GL_CCW);
glClearColor(0, 0, 0, 1.0f);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
render_scene();

View File

@ -15,6 +15,7 @@ bool should_close();
void create();
void update(double dt);
void render();
void render_scene();
void destroy();
void close();