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