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 *.glb filter=lfs diff=lfs merge=lfs -text
*.blend 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 #version 460 core
#extension GL_ARB_bindless_texture : require #extension GL_ARB_bindless_texture : require
const float PI = 3.141592; const float PI = 3.141592f;
const float Epsilon = 0.00001;
// Constant normal incidence Fresnel factor for all dielectrics.
const vec3 Fdielectric = vec3(0.04);
in VS_OUT { in VS_OUT {
vec3 normal; vec3 normal;
@ -27,29 +23,34 @@ layout(std140, binding = 1) buffer ssbo_lights
Light lights[]; Light lights[];
}; };
layout(std430, binding = 2) buffer ssbo_shadow_maps
{
samplerCube shadow_maps[];
};
in flat sampler2D frag_tex; in flat sampler2D frag_tex;
out vec4 frag_colour; out vec4 frag_colour;
uniform mat4 tex_mat;
uniform vec3 brightness; uniform vec3 brightness;
uniform vec3 camera_pos; uniform vec3 camera_pos;
uniform int lights_count; 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 DistributionGGX(vec3 N, vec3 H, float roughness)
{ {
float a = roughness*roughness; float a = roughness*roughness;
float a2 = a*a; 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 NdotH2 = NdotH*NdotH;
float num = a2; float num = a2;
float denom = (NdotH2 * (a2 - 1.0) + 1.0); float denom = (NdotH2 * (a2 - 1.f) + 1.f);
denom = PI * denom * denom; denom = PI * denom * denom;
return num / denom; return num / denom;
@ -57,27 +58,49 @@ float DistributionGGX(vec3 N, vec3 H, float roughness)
float GeometrySchlickGGX(float NdotV, float roughness) float GeometrySchlickGGX(float NdotV, float roughness)
{ {
float r = (roughness + 1.0); float r = (roughness + 1.f);
float k = (r*r) / 8.0; float k = (r*r) / 8.f;
float num = NdotV; float num = NdotV;
float denom = NdotV * (1.0 - k) + k; float denom = NdotV * (1.f - k) + k;
return num / denom; return num / denom;
} }
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
{ {
float NdotV = max(dot(N, V), 0.0); float NdotV = max(dot(N, V), 0.f);
float NdotL = max(dot(N, L), 0.0); float NdotL = max(dot(N, L), 0.f);
float ggx2 = GeometrySchlickGGX(NdotV, roughness); float ggx2 = GeometrySchlickGGX(NdotV, roughness);
float ggx1 = GeometrySchlickGGX(NdotL, roughness); float ggx1 = GeometrySchlickGGX(NdotL, roughness);
return ggx1 * ggx2; 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() 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 roughness = vin.material[0];
float metalness = vin.material[1]; float metalness = vin.material[1];
@ -86,10 +109,10 @@ void main()
vec3 N = normalize(vin.normal); vec3 N = normalize(vin.normal);
vec3 V = normalize(camera_pos - vin.pos.xyz); vec3 V = normalize(camera_pos - vin.pos.xyz);
vec3 F0 = vec3(0.04); vec3 F0 = vec3(0.04f);
F0 = mix(F0, albedo.rgb, metalness); F0 = mix(F0, albedo_lin, metalness);
vec3 Lo = vec3(0.0); vec3 Lo = vec3(0.0f);
for(int i = 0; i < lights_count; i++) for(int i = 0; i < lights_count; i++)
{ {
Light l = lights[i]; Light l = lights[i];
@ -104,29 +127,42 @@ void main()
// cook-torrance brdf // cook-torrance brdf
float NDF = DistributionGGX(N, H, roughness); float NDF = DistributionGGX(N, H, roughness);
float G = GeometrySmith(N, V, L, 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 kS = F;
vec3 kD = vec3(1.0) - kS; vec3 kD = vec3(1.f) - kS;
kD *= 1.0 - metalness; kD *= 1.f - metalness;
vec3 numerator = NDF * G * F; 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; vec3 specular = numerator / denominator;
// add to outgoing radiance Lo float light_m;
float NdotL = max(dot(N, L), 0.0); float spec_m;
Lo += (kD * albedo.rgb / PI + specular) * radiance * NdotL;
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; else
vec3 light = ambient + Lo; {
light_m = 1.f;
spec_m = 1.f;
}
light = light / (light + vec3(1.f)); // add to outgoing radiance Lo
light = pow(light, vec3(1.f/2.2f)); float NdotL = max(dot(N, L), 0.f);
light = light * (1 - luminance) + albedo.rgb * luminance; 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); 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; 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) void Camera::update(double dt)
@ -123,11 +123,10 @@ void Camera::update(double dt)
velocity.z += 3.5; velocity.z += 3.5;
} }
glm::vec<3, double> normal_last(0);
glm::vec<3, double> velocity2; glm::vec<3, double> velocity2;
velocity2 = collision_scene.calc_intersect(pos, velocity * dt, normal_last); velocity2 = collision_scene.calc_intersect(pos, velocity * dt);
velocity2 = collision_scene.calc_intersect(pos + glm::vec<3, double>(0, 0, -1.5), velocity2, normal_last) / dt; velocity2 = collision_scene.calc_intersect(pos + glm::vec<3, double>(0, 0, -1.5), velocity2) / dt;
pos += velocity2 * dt; pos += velocity2 * dt;
on_ground = ((velocity * dt / dt).z != velocity2.z); on_ground = ((velocity * dt / dt).z != velocity2.z);

View File

@ -5,6 +5,7 @@
#include <json/json.h> #include <json/json.h>
#include "../system.hpp" #include "../system.hpp"
#include "mesh/model.hpp"
namespace Sim::Graphics::Camera namespace Sim::Graphics::Camera
{ {
@ -18,7 +19,7 @@ double get_yaw();
Json::Value serialize(); Json::Value serialize();
void load(const Json::Value& node); void load(const Json::Value& node);
void init(); void init(const Model& model);
void rotate(double pitch, double yaw); void rotate(double pitch, double yaw);
void move(double x, double y, double z); void move(double x, double y, double z);
void update(double dt); 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] = { 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(1, 0, 0)) *
glm::rotate(glm::mat4(1), glm::radians<float>(-90), glm::vec3(0, 1, 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::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::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::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::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::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::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::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::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::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(1, 0, 0)) *
glm::rotate(glm::mat4(1), glm::radians<float>(90), glm::vec3(0, 1, 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::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(1, 0, 0)) *
glm::rotate(glm::mat4(1), glm::radians<float>(90), glm::vec3(0, 1, 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::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); 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::vec3 normal = {0, 0, 0};
glm::vec4 colour = {1, 1, 1, 1}; glm::vec4 colour = {1, 1, 1, 1};
glm::vec3 material = {0, 0, 0}; glm::vec3 material = {0, 0, 0};
constexpr bool operator==(const Vertex&) const = default;
} __attribute__((packed)); } __attribute__((packed));
void vertex_attrib_pointers(); 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); FT_Set_Pixel_Sizes(face, 0, size);
GLuint texids[128]; GLuint texids[128];
std::vector<glm::vec<4, unsigned char>> pixels;
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
@ -74,10 +75,17 @@ void Font::init()
continue; 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]); glCreateTextures(GL_TEXTURE_2D, 1, &texids[i]);
glTextureStorage2D(texids[i], 1, GL_R8, width, height); glTextureStorage2D(texids[i], 1, GL_RGBA8, width, height);
glTextureSubImage2D(texids[i], 0, 0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE, face->glyph->bitmap.buffer); 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_S, GL_CLAMP_TO_EDGE);
glTextureParameteri(texids[i], GL_TEXTURE_WRAP_T, 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); 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; ebo = o.ebo;
vao = o.vao; vao = o.vao;
size = o.size; size = o.size;
colour_matrix = o.colour_matrix;
model_matrix = o.model_matrix; model_matrix = o.model_matrix;
o.vbo = 0; o.vbo = 0;
@ -53,18 +52,17 @@ void GLMesh::bind()
init(this); init(this);
glBindVertexArray(vao); glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
} }
void GLMesh::uniform() void GLMesh::uniform()
{ {
glUniformMatrix4fv(Shader::MAIN["model"], 1, false, &model_matrix[0][0]); glUniformMatrix4fv(Shader::ACTIVE->get("model"), 1, false, &model_matrix[0][0]);
glUniformMatrix4fv(Shader::MAIN["tex_mat"], 1, false, &colour_matrix[0][0]);
} }
void GLMesh::set(const Mesh& m, int mode) 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_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); glBufferData(GL_ELEMENT_ARRAY_BUFFER, m.indices.size() * sizeof(m.indices[0]), &m.indices[0], mode);
this->size = m.indices.size(); this->size = m.indices.size();

View File

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

View File

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

View File

@ -155,17 +155,11 @@ bool Mesh::check_intersect(vec3 pos, vec3 path) const
return false; return false;
} }
vec3 Mesh::calc_intersect(vec3 pos, vec3 path) const static bool calc_intercept_vert(vec3 v[3], vec3 pos, vec3& path, vec3& path_n, double& l)
{
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)
{ {
vec3 ipoint; vec3 ipoint;
vec3 normal = glm::normalize(glm::cross(v[1] - v[0], v[2] - v[0])); 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) if(d >= 0)
return false; 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)) if(l < glm::length(ipoint - pos))
return false; 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; path -= normal * d;
normal_last = normal;
l = glm::length(path); l = glm::length(path);
}
if(l > 0) 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; 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); 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) 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; 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) 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) if(l == 0)
{ {
@ -265,3 +250,4 @@ Mesh Mesh::to_lines() const
return m; return m;
} }

View File

@ -17,18 +17,15 @@ namespace Sim::Graphics
struct Mesh struct Mesh
{ {
std::unordered_map<std::string, glm::mat4> mat_nodes;
std::vector<Arrays::Vertex> vertices; std::vector<Arrays::Vertex> vertices;
std::vector<unsigned int> indices; std::vector<unsigned int> indices;
std::vector<Light> lights;
Mesh(); Mesh();
void set_vertices(const Arrays::Vertex* data, size_t size); void set_vertices(const Arrays::Vertex* data, size_t size);
void set_indices(const unsigned int* 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);
void load_text(const char* text, double size, glm::vec2 align);
void add(const Mesh& o, glm::mat4 mat); void add(const Mesh& o, glm::mat4 mat);
void add(const Mesh& o); void add(const Mesh& o);
@ -37,7 +34,8 @@ struct Mesh
bool check_focus(double len) const; bool check_focus(double len) const;
bool check_intersect(glm::vec<3, double> pos, glm::vec<3, double> path) 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) 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> template <class T>
void load_text(const char* header, T& item, double size) 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 <GL/glew.h>
#include <GLFW/glfw3.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 <glm/matrix.hpp>
#include <unordered_map> #include <unordered_map>
@ -15,6 +11,7 @@
#include "mesh.hpp" #include "mesh.hpp"
#include "arrays.hpp" #include "arrays.hpp"
#include "texture.hpp" #include "texture.hpp"
#include "model.hpp"
#include "../../util/streams.hpp" #include "../../util/streams.hpp"
using namespace Sim::Graphics; using namespace Sim::Graphics;
@ -24,11 +21,9 @@ struct ProcState
unsigned int offset = 0; unsigned int offset = 0;
std::string base; std::string base;
std::vector<Light> lights;
std::vector<Arrays::Vertex> vertices; std::vector<Arrays::Vertex> vertices;
std::vector<unsigned int> indices; std::vector<unsigned int> indices;
std::unordered_map<const aiTexture*, unsigned int> handles; 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) 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; aiString name;
material->Get(AI_MATKEY_NAME, name); material->Get(AI_MATKEY_NAME, name);
/*
std::cout << "Material " << name.C_Str() << " has " << material->mNumProperties << " properties\n"; std::cout << "Material " << name.C_Str() << " has " << material->mNumProperties << " properties\n";
for(int i = 0; i < material->mNumProperties; i++) 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"; std::cout << "\n";
} }*/
glm::vec3 matv(0); glm::vec3 matv(0);
aiColor4D ai_cb; aiColor4D ai_cb;
@ -117,8 +112,6 @@ static void proc_mesh(ProcState& state, glm::mat4 mat, aiMesh* mesh, const aiSce
cb = em; cb = em;
} }
std::cout << "Material: " << matv << "\n";
unsigned int handle = proc_texture(state, material, scene, aiTextureType_BASE_COLOR, 0); unsigned int handle = proc_texture(state, material, scene, aiTextureType_BASE_COLOR, 0);
unsigned int offset = state.offset; unsigned int offset = state.offset;
glm::mat3 mat3(mat); 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; state.offset += mesh->mNumVertices;
} }
glm::mat4 get_mat(aiMatrix4x4 m) glm::mat4 convert_mat(aiMatrix4x4 m)
{ {
return { return {
m.a1, m.a2, m.a3, m.a4, 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; while(base[0] != '\0' && check[0] != '\0')
std::string name(node->mName.C_Str()); {
state.mat_nodes[name] = mat; 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++) for(size_t i = 0; i < node->mNumMeshes; i++)
{ {
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]]; aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
proc_mesh(state, mat, mesh, scene); proc_mesh(state, mat, mesh, scene);
} }
}
for(size_t i = 0; i < node->mNumChildren; i++) 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); 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++) for(int i = 0; i < tex->mWidth * tex->mHeight; i++)
{ {
aiTexel t = tex->pcData[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); glm::mat4 mat(1);
while(node->mParent != nullptr) while(node->mParent != nullptr)
{ {
mat *= get_mat(node->mTransformation); mat = mat * convert_mat(node->mTransformation);
node = node->mParent; node = node->mParent;
} }
return mat; 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; 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); textures.reserve(scene->mNumTextures);
if(scene == nullptr)
{
std::cerr << "AssImp: Error loading model\n";
return;
}
for(int i = 0; i < scene->mNumTextures; i++) for(int i = 0; i < scene->mNumTextures; i++)
{ {
aiTexture* tex = scene->mTextures[i]; aiTexture* tex = scene->mTextures[i];
unsigned int handle = proc_embedded_texture(tex); unsigned int handle = proc_embedded_texture(tex);
state.handles[tex] = handle; textures.push_back(handle);
} }
for(int i = 0; i < scene->mNumLights; i++) for(int i = 0; i < scene->mNumLights; i++)
{ {
aiLight* light = scene->mLights[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 [x, y, z] = light->mPosition;
auto [r, g, b] = light->mColorDiffuse; auto [r, g, b] = light->mColorDiffuse;
glm::vec4 pos = glm::vec4(x, y, z, 1) * mat; glm::vec4 pos = glm::vec4(x, y, z, 1) * mat;
state.lights.push_back({ lights.push_back({
glm::vec3(pos), glm::vec3(pos),
{r, g, b}, {r, g, b},
}); });
} }
}
proc_node(state, glm::mat4(1), scene->mRootNode, scene);
Mesh Model::load(const char* name, glm::mat4 mat) const
mat_nodes = std::move(state.mat_nodes); {
vertices = std::move(state.vertices); Mesh mesh;
indices = std::move(state.indices); ProcState state {.base = base};
lights = std::move(state.lights); 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); throw std::runtime_error("Failed to load path: " + path);
} }
std::cout << "Loaded Image: " << path << "\n"; std::cout << "Loaded image: " << path << "\n";
loaded[path] = handle; loaded[path] = handle;
return handle; return handle;

View File

@ -80,8 +80,6 @@ struct CoreMonitor : public Focus::FocusType
default: default:
return; return;
} }
parent->is_dirty = true;
} }
}; };
@ -97,7 +95,6 @@ struct CoreJoystick : public Focus::FocusType
virtual void on_cursor_pos(double x, double y) virtual void on_cursor_pos(double x, double y)
{ {
System::active->reactor.add_rod_speed(y * 1e-6); System::active->reactor.add_rod_speed(y * 1e-6);
parent->is_dirty = true;
} }
virtual ~CoreJoystick() 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() mesh.load_text("Reactor Core", 0.04);
{ rmesh.add(mesh, mat);
mesh1.model_matrix = mesh2.model_matrix = Locations::monitors[2];
mesh1.colour_matrix = mesh2.colour_matrix = Arrays::colour({1, 1, 1, 1});
Sim::Graphics::Mesh rmesh; m_buttons[0] = model.load("click_numpad_1");
m_buttons[1] = model.load("click_numpad_2");
rmesh.load_text("Reactor Core", 0.04); m_buttons[2] = model.load("click_numpad_3");
mesh1.bind(); m_buttons[3] = model.load("click_numpad_4");
mesh1.set(rmesh, GL_STATIC_DRAW); m_buttons[4] = model.load("click_numpad_5");
m_buttons[5] = model.load("click_numpad_6");
m_buttons[0].load_model("../assets/model/", "reactor_core_button1.stl"); m_buttons[6] = model.load("click_numpad_7");
m_buttons[1].load_model("../assets/model/", "reactor_core_button2.stl"); m_buttons[7] = model.load("click_numpad_8");
m_buttons[2].load_model("../assets/model/", "reactor_core_button3.stl"); m_buttons[8] = model.load("click_numpad_9");
m_buttons[3].load_model("../assets/model/", "reactor_core_button4.stl"); m_joystick = model.load("click_reactor_joystick");
m_buttons[4].load_model("../assets/model/", "reactor_core_button5.stl"); m_monitor = model.load("translation_monitor_3");
m_buttons[5].load_model("../assets/model/", "reactor_core_button6.stl"); m_scram = model.load("click_scram");
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");
} }
static Mesh add_dot(glm::mat4 model_mat, glm::vec4 colour) 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; Sim::System& sys = *System::active;
if(m_monitor.check_focus()) { if(m_monitor.check_focus())
Focus::set(std::make_unique<CoreMonitor>(this)); Focus::set(std::make_unique<CoreMonitor>(this));
} if(m_joystick.check_focus())
if(m_joystick.check_focus()) {
Focus::set(std::make_unique<CoreJoystick>(this)); Focus::set(std::make_unique<CoreJoystick>(this));
} if(m_scram.check_focus())
if(m_scram.check_focus()) {
sys.reactor.scram(); sys.reactor.scram();
is_dirty = true; if(m_buttons[0].check_focus())
}
if(m_buttons[0].check_focus()) {
set_all(true); 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); 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); set_all(false);
is_dirty = true; if(m_buttons[3].check_focus())
}
if(m_buttons[3].check_focus()) {
sys.reactor.move_cursor(-1); sys.reactor.move_cursor(-1);
is_dirty = true; if(m_buttons[4].check_focus())
}
if(m_buttons[4].check_focus()) {
sys.reactor.toggle_selected(); sys.reactor.toggle_selected();
is_dirty = true; if(m_buttons[5].check_focus())
}
if(m_buttons[5].check_focus()) {
sys.reactor.move_cursor(1); 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(); 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); sys.reactor.move_cursor(sys.reactor.height);
is_dirty = true;
} }
clock_now += dt; void Core::remesh_slow(Mesh& rmesh)
if(clock_at + 1.0/30.0 > clock_now)
{ {
if(!is_dirty) remesh(rmesh, false);
{
return;
}
} }
else void Core::remesh_fast(Mesh& rmesh)
{ {
clock_at += 1.0/30.0; remesh(rmesh, true);
} }
Sim::Graphics::Mesh rmesh; void Core::remesh(Mesh& rmesh, bool fast)
is_dirty = false; {
Sim::System& sys = *System::active;
Sim::Graphics::Mesh mesh;
double step = 1 / (sys.vessel.diameter / sys.reactor.cell_width * 0.8); double step = 1 / (sys.vessel.diameter / sys.reactor.cell_width * 0.8);
double sx = 0.5 - (sys.reactor.width - 1) * step / 2.0; double sx = 0.5 - (sys.reactor.width - 1) * step / 2.0;
@ -252,6 +220,10 @@ void Core::update(double dt)
continue; 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_heat = r->get_heat_colour() * glm::vec4(glm::vec3(1), 1);
glm::vec4 colour_spec = r->get_colour(); glm::vec4 colour_spec = r->get_colour();
@ -260,38 +232,32 @@ void Core::update(double dt)
continue; 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) 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) 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(); rmesh.add(mesh, mat);
mesh2.set(rmesh, GL_DYNAMIC_DRAW);
} }
void Core::render() void Core::render()
{ {
mesh1.bind();
mesh1.uniform();
mesh1.render();
mesh2.bind();
mesh2.uniform();
mesh2.render();
} }

View File

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

View File

@ -49,26 +49,12 @@ struct ValveJoystick : public Focus::FocusType
} }
}; };
PrimaryLoop::PrimaryLoop(const Model& model, Mesh& rmesh)
PrimaryLoop::PrimaryLoop()
{ {
mat = Locations::monitors[3];
}
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
};
std::stringstream ss; std::stringstream ss;
Sim::Graphics::Mesh rmesh; Sim::Graphics::Mesh mesh;
ss << "Turbine Bypass Valve\n\n"; ss << "Turbine Bypass Valve\n\n";
ss << "Opened\nFlow\nSetpoint\n\n"; ss << "Opened\nFlow\nSetpoint\n\n";
@ -82,39 +68,41 @@ void PrimaryLoop::init()
ss << "Pressure\n"; ss << "Pressure\n";
ss << "Level\n"; ss << "Level\n";
rmesh.load_text(ss.str().c_str(), 0.04); mesh.load_text(ss.str().c_str(), 0.04);
mesh1.bind(); rmesh.add(mesh, mat);
mesh1.set(rmesh, GL_STATIC_DRAW);
rmesh.load_model("../assets/model", "pump_switch_1.glb"); g_switch_pump = model.load("visual_pump_switch_1");
gm_switch_pump.bind(); g_switch_bypass = model.load("visual_bypass_switch");
gm_switch_pump.set(rmesh, GL_STATIC_DRAW); g_switch_inlet = model.load("visual_inlet_switch");
rmesh.load_model("../assets/model", "turbine_valve_bypass_switch.glb"); m_joystick_turbine_bypass = model.load("click_bypass_joystick");
gm_switch_bypass.bind(); m_joystick_turbine_inlet = model.load("click_inlet_joystick");
gm_switch_bypass.set(rmesh, GL_STATIC_DRAW); m_switch_pump = model.load("click_pump_switch_1");
m_switch_bypass = model.load("click_bypass_switch");
rmesh.load_model("../assets/model", "turbine_valve_inlet_switch.glb"); m_switch_inlet = model.load("click_inlet_switch");
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");
} }
void PrimaryLoop::update(double dt) void PrimaryLoop::update(double dt)
{ {
System& sys = *System::active; 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; std::stringstream ss;
Sim::Graphics::Mesh rmesh; Sim::Graphics::Mesh mesh;
clock_at += 1.0/30.0; System& sys = *System::active;
ss << "\n\n"; ss << "\n\n";
ss << show( sys.loop.turbine_bypass_valve.get_state() * 100 ) << " %\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"; 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"; 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); mesh.load_text(ss.str().c_str(), 0.04);
mesh2.bind(); rmesh.add(mesh, glm::translate(mat, glm::vec3(0.5, 0, 0)));
mesh2.set(rmesh, GL_DYNAMIC_DRAW);
} }
if(m_joystick_turbine_bypass.check_focus()) void PrimaryLoop::remesh_fast(Mesh& rmesh)
Focus::set(std::make_unique<ValveJoystick>(&sys.loop.turbine_bypass_valve)); {
if(m_joystick_turbine_inlet.check_focus()) System& sys = *System::active;
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();
gm_switch_inlet.model_matrix = glm::translate(glm::mat4(1), glm::vec3(0, sys.loop.turbine_inlet_valve.get_auto() ? 0.07 : 0, 0)); float off1 = sys.loop.primary_pump.powered ? 0.07 : 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)); float off2 = sys.loop.turbine_bypass_valve.get_auto() ? 0.07 : 0;
gm_switch_pump.model_matrix = glm::translate(glm::mat4(1), glm::vec3(0, sys.loop.primary_pump.powered ? 0.07 : 0, 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() 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 #pragma once
#include "../mesh/glmesh.hpp" #include "../mesh/model.hpp"
#include "../mesh/meshgen.hpp"
namespace Sim::Graphics::Monitor namespace Sim::Graphics::Monitor
{ {
class PrimaryLoop class PrimaryLoop : public MeshGen
{ {
GLMesh mesh1, mesh2; glm::mat4 mat;
double clock_at = 0, clock_now = 0;
GLMesh gm_switch_pump;
GLMesh gm_switch_bypass;
GLMesh gm_switch_inlet;
Mesh m_joystick_turbine_bypass; Mesh m_joystick_turbine_bypass;
Mesh m_joystick_turbine_inlet; Mesh m_joystick_turbine_inlet;
Mesh g_switch_pump;
Mesh g_switch_bypass;
Mesh g_switch_inlet;
Mesh m_switch_pump; Mesh m_switch_pump;
Mesh m_switch_bypass; Mesh m_switch_bypass;
Mesh m_switch_inlet; Mesh m_switch_inlet;
public: public:
PrimaryLoop(); PrimaryLoop(const Model& model, Mesh& rmesh);
void init(); virtual void update(double dt);
void update(double dt); virtual void remesh_slow(Mesh& rmesh);
void render(); 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::Graphics::Monitor;
using namespace Sim::Util::Streams; using namespace Sim::Util::Streams;
SecondaryLoop::SecondaryLoop()
SecondaryLoop::SecondaryLoop(const Model& model, Mesh& rmesh)
{ {
mat = Locations::monitors[5];
}
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
};
std::stringstream ss; std::stringstream ss;
Sim::Graphics::Mesh rmesh; Sim::Graphics::Mesh mesh;
ss << "Cooling Tower\n\n"; ss << "Cooling Tower\n\n";
ss << "Heat\nSteam\nPressure\nLevel\n\n"; ss << "Heat\nSteam\nPressure\nLevel\n\n";
@ -43,34 +31,33 @@ void SecondaryLoop::init()
ss << "Freight Pump\n\n"; ss << "Freight Pump\n\n";
ss << "Power\nSpeed\nFlow\n\n"; ss << "Power\nSpeed\nFlow\n\n";
rmesh.load_text(ss.str().c_str(), 0.04); mesh.load_text(ss.str().c_str(), 0.04);
mesh1.bind(); rmesh.add(mesh, mat);
mesh1.set(rmesh, GL_STATIC_DRAW);
rmesh.load_model("../assets/model", "pump_switch_2.glb"); g_switch_2 = model.load("visual_pump_switch_2");
gm_switch_2.bind(); g_switch_3 = model.load("visual_pump_switch_3");
gm_switch_2.set(rmesh, GL_STATIC_DRAW);
rmesh.load_model("../assets/model", "pump_switch_3.glb"); m_joystick_turbine_bypass = model.load("click_bypass_joystick");
gm_switch_3.bind(); m_joystick_turbine_inlet = model.load("click_inlet_joystick");
gm_switch_3.set(rmesh, GL_STATIC_DRAW); m_switch_2 = model.load("click_pump_switch_2");
m_switch_3 = model.load("click_pump_switch_3");
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");
} }
void SecondaryLoop::update(double dt) void SecondaryLoop::update(double dt)
{ {
System& sys = *System::active; 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; std::stringstream ss;
Sim::Graphics::Mesh rmesh; Sim::Graphics::Mesh mesh;
clock_at += 1.0/30.0; System& sys = *System::active;
ss << "\n\n"; ss << "\n\n";
ss << show( sys.evaporator.get_heat() ) << " C\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"; ss << show( sys.freight_pump.get_rpm() ) << " r/min\n";
show_units( ss, sys.freight_pump.get_flow_mass() ) << "g/s\n"; show_units( ss, sys.freight_pump.get_flow_mass() ) << "g/s\n";
rmesh.load_text(ss.str().c_str(), 0.04); mesh.load_text(ss.str().c_str(), 0.04);
mesh2.bind(); rmesh.add(mesh, glm::translate(mat, glm::vec3(0.5, 0, 0)));
mesh2.set(rmesh, GL_DYNAMIC_DRAW);
} }
if(m_switch_2.check_focus()) void SecondaryLoop::remesh_fast(Mesh& rmesh)
sys.loop.secondary_pump.powered = !sys.loop.secondary_pump.powered; {
if(m_switch_3.check_focus()) System& sys = *System::active;
sys.freight_pump.powered = !sys.freight_pump.powered;
gm_switch_2.model_matrix = glm::translate(glm::mat4(1), glm::vec3(0, sys.loop.secondary_pump.powered ? 0.07 : 0, 0)); float off2 = sys.loop.secondary_pump.powered ? 0.07 : 0;
gm_switch_3.model_matrix = glm::translate(glm::mat4(1), glm::vec3(0, sys.freight_pump.powered ? 0.07 : 0, 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() 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 #pragma once
#include "../mesh/glmesh.hpp" #include "../mesh/model.hpp"
#include "../mesh/meshgen.hpp"
namespace Sim::Graphics::Monitor namespace Sim::Graphics::Monitor
{ {
class SecondaryLoop class SecondaryLoop : public MeshGen
{ {
Sim::Graphics::GLMesh mesh1, mesh2; glm::mat4 mat;
double clock_at = 0, clock_now = 0;
Sim::Graphics::GLMesh gm_switch_2; Mesh g_switch_2;
Sim::Graphics::GLMesh gm_switch_3; Mesh g_switch_3;
Sim::Graphics::Mesh m_joystick_turbine_bypass; Mesh m_joystick_turbine_bypass;
Sim::Graphics::Mesh m_joystick_turbine_inlet; Mesh m_joystick_turbine_inlet;
Sim::Graphics::Mesh m_switch_2; Mesh m_switch_2;
Sim::Graphics::Mesh m_switch_3; Mesh m_switch_3;
public: public:
SecondaryLoop(); SecondaryLoop(const Model& model, Mesh& rmesh);
void init(); virtual void update(double dt);
void update(double dt); virtual void remesh_slow(Mesh& rmesh);
void render(); 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::Graphics::Monitor;
using namespace Sim::Util::Streams; using namespace Sim::Util::Streams;
Turbine::Turbine() Turbine::Turbine(const Model& model, Mesh& rmesh)
{ {
mat = Locations::monitors[4];
}
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
};
std::stringstream ss; std::stringstream ss;
Sim::Graphics::Mesh rmesh, rmesh2; Sim::Graphics::Mesh mesh;
ss << "Turbine\n\n"; ss << "Turbine\n\n";
ss << "Heat\nPressure\nSpeed\n\n"; ss << "Heat\nPressure\nSpeed\n\n";
rmesh.load_text(ss.str().c_str(), 0.04); mesh.load_text(ss.str().c_str(), 0.04);
rmesh2.load_text("Synchroscope", 0.04); rmesh.add(mesh, mat);
rmesh.add(rmesh2, glm::translate(glm::mat4(1), glm::vec3(0, 0.6, 0)));
mesh1.bind(); mesh.load_text("Synchroscope", 0.04);
mesh1.set(rmesh, GL_STATIC_DRAW); 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.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"); g_switch_breaker = model.load("visual_breaker_switch");
gm_switch_breaker.bind(); m_switch_breaker = model.load("click_breaker_switch");
gm_switch_breaker.set(rmesh, GL_STATIC_DRAW);
m_switch_breaker.load_model("../assets/model", "turbine_breaker_switch_click.stl");
} }
void Turbine::update(double dt) void Turbine::update(double dt)
{ {
System& sys = *System::active; 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(); double rpm = sys.loop.generator.get_rpm();
if(rpm > 3570 && rpm < 3630) if(rpm > 3570 && rpm < 3630)
@ -108,20 +56,49 @@ void Turbine::update(double dt)
if(m_switch_breaker.check_focus()) if(m_switch_breaker.check_focus())
sys.loop.generator.breaker_closed = !sys.loop.generator.breaker_closed; 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() void Turbine::render()
{ {
mesh1.bind();
mesh1.uniform();
mesh1.render();
mesh2.bind();
mesh2.uniform();
mesh2.render();
double rpm = System::active->loop.generator.get_rpm(); double rpm = System::active->loop.generator.get_rpm();
if(rpm > 3570 && rpm < 3630) if(rpm > 3570 && rpm < 3630)
@ -130,9 +107,5 @@ void Turbine::render()
gm_synchroscope_dial.uniform(); gm_synchroscope_dial.uniform();
gm_synchroscope_dial.render(); gm_synchroscope_dial.render();
} }
gm_switch_breaker.bind();
gm_switch_breaker.uniform();
gm_switch_breaker.render();
} }

View File

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

View File

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

View File

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

View File

@ -13,6 +13,8 @@ using namespace Sim::Graphics;
Shader Shader::MAIN; Shader Shader::MAIN;
Shader Shader::BLUR; Shader Shader::BLUR;
Shader Shader::LIGHT;
Shader* Shader::ACTIVE;
static int load_shader(const char* src, int type) static int load_shader(const char* src, int type)
{ {
@ -39,6 +41,12 @@ static std::string read_shader(const char* path)
return ss.str(); 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() Shader::Shader()
{ {
@ -60,18 +68,29 @@ Shader::~Shader()
void Shader::load(const char* path, const char* file_vsh, const char* file_fsh) 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); load(path, file_vsh, nullptr, file_fsh);
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()); 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 success;
int vsh_id = load_shader(shader_vsh.c_str(), GL_VERTEX_SHADER); int vsh_id = file_vsh ? load_shader(shader_vsh.c_str(), GL_VERTEX_SHADER) : 0;
int fsh_id = load_shader(shader_fsh.c_str(), GL_FRAGMENT_SHADER); 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(); prog_id = glCreateProgram();
if(file_vsh)
glAttachShader(prog_id, vsh_id); glAttachShader(prog_id, vsh_id);
if(file_gsh)
glAttachShader(prog_id, gsh_id);
if(file_fsh)
glAttachShader(prog_id, fsh_id); glAttachShader(prog_id, fsh_id);
glLinkProgram(prog_id); glLinkProgram(prog_id);
glGetProgramiv(prog_id, GL_LINK_STATUS, &success); 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); glUseProgram(prog_id);
if(file_vsh)
glDeleteShader(vsh_id); glDeleteShader(vsh_id);
if(file_gsh)
glDeleteShader(gsh_id);
if(file_fsh)
glDeleteShader(fsh_id); glDeleteShader(fsh_id);
ACTIVE = this;
} }
void Shader::use() void Shader::use()
{ {
glUseProgram(prog_id); glUseProgram(prog_id);
ACTIVE = this;
} }
unsigned int Shader::operator [](const char* pos) 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); 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 MAIN;
static Shader BLUR; static Shader BLUR;
static Shader LIGHT;
static Shader* ACTIVE;
Shader(); Shader();
Shader(const Shader& o) = delete; Shader(const Shader& o) = delete;
Shader(Shader&& o); Shader(Shader&& o);
~Shader(); ~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 load(const char* path, const char* file_vsh, const char* file_fsh);
void use(); void use();
unsigned int operator[](const char* pos); unsigned int operator[](const char* pos);
unsigned int get(const char* pos);
}; };
}; };

View File

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

View File

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

View File

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

View File

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

View File

@ -7,6 +7,8 @@
#include <glm/ext/matrix_clip_space.hpp> // glm::perspective #include <glm/ext/matrix_clip_space.hpp> // glm::perspective
#include <iostream> #include <iostream>
#include <vector>
#include <memory>
#include "mesh/mesh.hpp" #include "mesh/mesh.hpp"
#include "mesh/arrays.hpp" #include "mesh/arrays.hpp"
@ -25,6 +27,10 @@
#include "monitor/secondary_loop.hpp" #include "monitor/secondary_loop.hpp"
#include "monitor/turbine.hpp" #include "monitor/turbine.hpp"
#include "mesh/texture.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 "../system.hpp"
#include "../util/streams.hpp" #include "../util/streams.hpp"
#include "ui.hpp" #include "ui.hpp"
@ -34,20 +40,32 @@ using namespace Sim::Graphics;
static GLFWwindow* win; static GLFWwindow* win;
static bool win_should_close = false; static bool win_should_close = false;
static unsigned int ssbo_lights; 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 GLMesh gm_scene;
static Monitor::Core monitor_core; static GLMesh gm_transparent;
static Monitor::PrimaryLoop monitor_primary_loop; static GLMesh gm_dynamic_slow[2];
static Monitor::SecondaryLoop monitor_secondary_loop; static GLMesh gm_dynamic_fast;
static Monitor::Turbine monitor_turbine; 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; 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) 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"; std::cout << "GL CALLBACK: " << message << "\n";
} }
@ -108,7 +126,6 @@ void Window::create()
Mouse::init(); Mouse::init();
Resize::init(); Resize::init();
Texture::init(); Texture::init();
Camera::init();
Font::init(); Font::init();
UI::init(); UI::init();
@ -116,109 +133,180 @@ void Window::create()
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
Sim::System& sys = *System::active; 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 Camera::init(model);
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";
// send all the light data // send all the light data
glGenBuffers(1, &ssbo_lights); glGenBuffers(1, &ssbo_lights);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 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); 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(); monitors.push_back(std::make_unique<Monitor::Core>(model, m_scene));
mesh_scene.set(m, GL_STATIC_DRAW); 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(); equipment.push_back(std::make_unique<Equipment::Reactor>(model, m_scene));
monitor_vessel.init();
monitor_primary_loop.init(); gm_scene.bind();
monitor_secondary_loop.init(); gm_scene.set(m_scene, GL_STATIC_DRAW);
monitor_turbine.init();
gm_transparent.bind();
gm_transparent.set(m_transparent, GL_STATIC_DRAW);
glfwShowWindow(win); 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) void Window::update(double dt)
{ {
Mesh mesh;
glfwPollEvents(); glfwPollEvents();
monitor_core.update(dt); for(auto& monitor : monitors)
monitor_vessel.update(dt); {
monitor_primary_loop.update(dt); monitor->update(dt);
monitor_secondary_loop.update(dt);
monitor_turbine.update(dt);
UI::update(dt);
} }
void render_scene() for(auto& equipment : equipment)
{ {
mesh_scene.bind(); equipment->update(dt);
mesh_scene.uniform(); }
mesh_scene.render();
monitor_core.render(); UI::update(dt);
monitor_vessel.render();
monitor_primary_loop.render(); for(auto& monitor : monitors)
monitor_secondary_loop.render(); {
monitor_turbine.render(); 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 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_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(); Focus::render();
} }
void Window::render() void Window::render()
{ {
glm::vec<2, int> size = Resize::get_size();
glm::vec3 camera_pos = Camera::get_pos(); glm::vec3 camera_pos = Camera::get_pos();
glm::mat4 mat_camera = Camera::get_matrix(); 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::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["projection"], 1, false, &mat_projection[0][0]);
glUniformMatrix4fv(Shader::MAIN["camera"], 1, false, &mat_camera[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["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); glFrontFace(GL_CCW);
glClearColor(0, 0, 0, 1.0f);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
render_scene(); render_scene();

View File

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