mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-18 12:39:18 +02:00
Merge branch 'master' into feat/uart-2.0
This commit is contained in:
@@ -31,6 +31,7 @@ http://mozilla.org/MPL/2.0/.
|
||||
#include "utilities/dictionary.h"
|
||||
#include "version_info.h"
|
||||
#include <chrono>
|
||||
#include <format>
|
||||
#include "utilities/translation.h"
|
||||
|
||||
#if WITH_DISCORD_RPC
|
||||
@@ -320,9 +321,13 @@ int eu07_application::init(int Argc, char *Argv[])
|
||||
return result;
|
||||
}
|
||||
|
||||
// the run's seed, settled once and kept in Globals: the engines come out of it.
|
||||
// narrowed on purpose - mt19937 and seed_of() both work on 32 bits, and that is
|
||||
// the seed somebody can write down and pass on
|
||||
if (!Global.random_seed)
|
||||
Global.random_seed = std::random_device{}();
|
||||
Global.random_seed = static_cast<std::uint32_t>(true_random_seed());
|
||||
Global.random_engine.seed(Global.random_seed);
|
||||
Global.local_random_engine.seed(Global.random_seed);
|
||||
|
||||
// configure the OS console according to Globals.ShowSystemConsole.
|
||||
// must run AFTER init_settings (so the ini-loaded value is honoured) and
|
||||
@@ -1140,10 +1145,21 @@ int eu07_application::init_settings(int Argc, char *Argv[])
|
||||
Global.local_start_vehicle = ToLower(Argv[++i]);
|
||||
}
|
||||
}
|
||||
else if (token == "-seed")
|
||||
{
|
||||
// a number is the seed; anything else is a word that stands for one. said in the
|
||||
// log as it was given, because that is what gets passed on to somebody else
|
||||
if (i + 1 < Argc)
|
||||
{
|
||||
Global.random_seed = seed_of(Argv[++i]);
|
||||
WriteLog(std::format("seed given on the command line: {} -> {}", Argv[i], Global.random_seed));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "usage: " << std::string(Argv[0]) << " [-s sceneryfilepath]"
|
||||
<< " [-v vehiclename]" << std::endl;
|
||||
<< " [-v vehiclename]"
|
||||
<< " [-seed number|word]" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -1421,7 +1437,7 @@ int eu07_application::init_data()
|
||||
|
||||
int eu07_application::init_modes()
|
||||
{
|
||||
Global.local_random_engine.seed(std::random_device{}());
|
||||
Global.local_random_engine.seed(static_cast<std::mt19937::result_type>(true_random_seed()));
|
||||
|
||||
if ((!Global.network_servers.empty() || Global.network_client) && Global.SceneryFile.empty())
|
||||
{
|
||||
|
||||
@@ -403,10 +403,9 @@ std::string *brush_object_list::GetRandomObject()
|
||||
if (Objects.empty())
|
||||
return ∅
|
||||
|
||||
static std::mt19937 rng{std::random_device{}()};
|
||||
std::uniform_int_distribution<size_t> dist(0, Objects.size() - 1);
|
||||
|
||||
return &Objects[dist(rng)];
|
||||
return &Objects[dist(Global.local_random_engine)];
|
||||
}
|
||||
|
||||
void brush_object_list::render()
|
||||
|
||||
@@ -218,7 +218,10 @@ void CSkyDome::RebuildColors() {
|
||||
vertex = glm::normalize( m_vertices[ i ] );
|
||||
|
||||
// angle between sun and vertex
|
||||
const float gamma = std::acos( glm::dot( vertex, m_sundirection ) );
|
||||
// NOTE: the dot product can exceed the [ -1, 1 ] range by a rounding error,
|
||||
// which would turn the vertex - and, through the averages, the fog and ambient
|
||||
// light - into a NaN, so it gets clamped before feeding it to acos()
|
||||
const float gamma = std::acos( std::clamp( glm::dot( vertex, m_sundirection ), -1.0f, 1.0f ) );
|
||||
|
||||
// warning : major hack!!! .. i had to do something with values under horizon
|
||||
//vertex.y = Clamp<float>( vertex.y, 0.05f, 1.0f );
|
||||
|
||||
@@ -10,9 +10,26 @@ layout(location = 0) out vec4 out_color;
|
||||
layout(location = 1) out vec4 out_motion;
|
||||
#endif
|
||||
|
||||
// the skydome vertex colours carry Perez luminance scaled by a fixed exposure
|
||||
// (see CSkyDome::SetExposure), so the circumsolar region and the horizon band
|
||||
// routinely land well above 1.0. hard-clipping them, as this shader used to do,
|
||||
// flattened everything within ~20 degrees of the sun - and most of the lower sky -
|
||||
// into one solid white patch. compress the top end instead: below the knee the
|
||||
// response is unchanged, above it it rolls off towards SKY_SHOULDER_WHITE, so the
|
||||
// brightness gradient around the sun survives and the patch keeps a soft edge.
|
||||
const float SKY_SHOULDER_KNEE = 0.25;
|
||||
const float SKY_SHOULDER_WHITE = 0.95;
|
||||
|
||||
vec3 sky_shoulder(vec3 color)
|
||||
{
|
||||
const float range = SKY_SHOULDER_WHITE - SKY_SHOULDER_KNEE;
|
||||
vec3 excess = max(color - vec3(SKY_SHOULDER_KNEE), vec3(0.0));
|
||||
return min(color, vec3(SKY_SHOULDER_KNEE)) + range * (vec3(1.0) - exp(-excess / range));
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 col = clamp(pow(f_color.rgb, vec3(2.2)),0, 1);
|
||||
vec3 col = sky_shoulder(pow(max(f_color.rgb, vec3(0.0)), vec3(2.2)));
|
||||
#if POSTFX_ENABLED
|
||||
out_color = vec4(apply_fog(col), 1.0f);
|
||||
#else
|
||||
|
||||
@@ -45,7 +45,20 @@ float calc_shadow()
|
||||
if (distance <= cascade_end[cascade])
|
||||
break;
|
||||
float dist_casc = distance / cascade_end[cascade];
|
||||
vec3 coords = f_light_pos[cascade].xyz / f_light_pos[cascade].w;
|
||||
// Normal offset: sample the shadow map from a point pushed along the surface normal
|
||||
// by a fraction of the cascade's texel footprint. A constant depth bias can't keep up
|
||||
// with large texels (far cascades, small shadow maps) on surfaces at a grazing angle
|
||||
// to the sun, which then show shadow acne stripes. lightview maps view space metres
|
||||
// to [0,1] shadow map coordinates, so its x/y row lengths give texels per metre.
|
||||
vec3 shadownormal = normalize(f_normal);
|
||||
float shadowNdotL = clamp(dot(shadownormal, normalize(-lights[0].dir)), 0.0, 1.0);
|
||||
mat4 shadowview = lightview[cascade];
|
||||
float texelspermetre = min(length(vec3(shadowview[0][0], shadowview[1][0], shadowview[2][0])),
|
||||
length(vec3(shadowview[0][1], shadowview[1][1], shadowview[2][1]))) * float(textureSize(shadowmap, 0).x);
|
||||
float texelsize = 1.0 / texelspermetre;
|
||||
vec3 shadowpos = f_pos.xyz + shadownormal * (texelsize * 1.5 * (1.0 - shadowNdotL));
|
||||
vec4 lightpos = shadowview * vec4(shadowpos, 1.0);
|
||||
vec3 coords = lightpos.xyz / lightpos.w;
|
||||
if (coords.z < 0.0)
|
||||
return 0.0f;
|
||||
|
||||
@@ -64,29 +77,28 @@ float calc_shadow()
|
||||
radius = 0.5;
|
||||
|
||||
#if defined(GL_ARB_gpu_shader5) || defined(GL_EXT_gpu_shader5) || __VERSION__ >= 400
|
||||
// Fast path -- replace the original 4x4 grid of individual hardware-PCF
|
||||
// lookups with 4 textureGather() calls. Each gather returns the 4 raw
|
||||
// shadow comparisons of a 2x2 texel footprint, so 4 gathers laid out at
|
||||
// (+-1, +-1) * radius * texel from the sample center cover the same 4x4
|
||||
// sample area as the original kernel; summing all 16 comparisons and
|
||||
// dividing by 16 reproduces the original loop's averaging. The cost on
|
||||
// the TMUs drops from 16 hardware-PCF samples to 4 gathers (the gather
|
||||
// path returns 4 values per fetch where the original needed 4 fetches),
|
||||
// roughly a 4x reduction in shadow-sample work. The only thing dropped
|
||||
// vs. the hardware-PCF path is the implicit bilinear blending inside
|
||||
// each 2x2 footprint -- effectively turning a tent-weighted kernel into
|
||||
// a box-weighted one of the same extent, which is imperceptible in
|
||||
// motion. calc_shadow() is by far the heaviest piece of the lighting
|
||||
// shader, so this is a measurable GPU saving on every shaded fragment.
|
||||
// Fast path: 4 textureGather() calls cover a 4x4 texel block. Raw gathered
|
||||
// comparisons must be weighted by the sub-texel position (bilinear weights),
|
||||
// otherwise the result is constant across each shadow map texel and shadow
|
||||
// edges turn into texel-sized stair steps. With per-axis weights
|
||||
// (1-f, 1, 1, f) this equals a 3x3 grid of hardware bilinear PCF taps.
|
||||
vec2 size = vec2(textureSize(shadowmap, 0).xy);
|
||||
vec2 uv = coords.xy * size - 0.5;
|
||||
vec2 base = floor(uv);
|
||||
vec2 f = uv - base;
|
||||
float refz = coords.z + bias;
|
||||
float layer = float(cascade);
|
||||
vec2 off = radius * texel;
|
||||
vec4 g0 = textureGather(shadowmap, vec3(coords.xy + vec2(-off.x, -off.y), layer), refz);
|
||||
vec4 g1 = textureGather(shadowmap, vec3(coords.xy + vec2( off.x, -off.y), layer), refz);
|
||||
vec4 g2 = textureGather(shadowmap, vec3(coords.xy + vec2(-off.x, off.y), layer), refz);
|
||||
vec4 g3 = textureGather(shadowmap, vec3(coords.xy + vec2( off.x, off.y), layer), refz);
|
||||
float shadow = dot(g0 + g1 + g2 + g3, vec4(1.0 / 16.0));
|
||||
return shadow;
|
||||
// sampling at texel corners selects blocks with lower-left texel base-1 and base+1
|
||||
vec4 g00 = textureGather(shadowmap, vec3((base + vec2(0.0, 0.0)) / size, layer), refz);
|
||||
vec4 g10 = textureGather(shadowmap, vec3((base + vec2(2.0, 0.0)) / size, layer), refz);
|
||||
vec4 g01 = textureGather(shadowmap, vec3((base + vec2(0.0, 2.0)) / size, layer), refz);
|
||||
vec4 g11 = textureGather(shadowmap, vec3((base + vec2(2.0, 2.0)) / size, layer), refz);
|
||||
// gather component order: x=(0,1) y=(1,1) z=(1,0) w=(0,0)
|
||||
float shadow = dot(g00, vec4(1.0 - f.x, 1.0, 1.0 - f.y, (1.0 - f.x) * (1.0 - f.y)))
|
||||
+ dot(g10, vec4(1.0, f.x, f.x * (1.0 - f.y), 1.0 - f.y))
|
||||
+ dot(g01, vec4((1.0 - f.x) * f.y, f.y, 1.0, 1.0 - f.x))
|
||||
+ dot(g11, vec4(f.y, f.x * f.y, f.x, 1.0));
|
||||
return shadow / 9.0;
|
||||
#else
|
||||
// Fallback for drivers without textureGather on shadow samplers
|
||||
// (notably GLES 3.0 and any 3.3 desktop driver that doesn't expose
|
||||
@@ -256,17 +268,29 @@ vec3 EnvBRDFApprox(vec3 F0, float roughness, float NoV)
|
||||
return F0 * AB.x + AB.y;
|
||||
}
|
||||
|
||||
// Diffuse colour of the submodel (t3d/e3d) or shape, used as the albedo multiplier:
|
||||
// untextured materials take it as their colour, textured ones multiply the base texture by it
|
||||
// (same as the legacy renderer's GL_MODULATE). param[0].rgb holds the authored sRGB colour,
|
||||
// param[1].x its intensity (HSV value unless a material overrides it).
|
||||
vec3 material_diffuse()
|
||||
{
|
||||
vec3 diffusecolor = pow(max(param[0].rgb, vec3(0.0)), vec3(2.2));
|
||||
float value = max(param[0].r, max(param[0].g, param[0].b));
|
||||
return (value > 0.0 ? diffusecolor * (param[1].x / value) : vec3(0.0));
|
||||
}
|
||||
|
||||
// [0] - diffuse, [1] - specular
|
||||
// do magic here
|
||||
vec3 apply_lights(vec3 fragcolor, vec3 fragnormal, vec3 texturecolor, float reflectivity, float specularity, float shadowtone)
|
||||
{
|
||||
vec3 basecolor = param[0].rgb;
|
||||
// Scale ambient before it gets tinted by basecolor / texture.
|
||||
// Diffuse colour is applied once, to the albedo; the light terms below are not scaled by it again
|
||||
texturecolor *= material_diffuse();
|
||||
// Scale ambient before it gets tinted by the texture.
|
||||
// Sun, headlights and emission are added afterwards so they are NOT
|
||||
// attenuated by AMBIENT_SCALE - this only dims the indirect term.
|
||||
fragcolor *= basecolor * AMBIENT_SCALE;
|
||||
fragcolor *= AMBIENT_SCALE;
|
||||
|
||||
vec3 emissioncolor = basecolor * emission;
|
||||
vec3 emissioncolor = vec3(emission);
|
||||
|
||||
vec3 view_dir = normalize(-f_pos.xyz);
|
||||
float NdotV = max(dot(fragnormal, view_dir), 0.0);
|
||||
@@ -302,7 +326,7 @@ vec3 apply_lights(vec3 fragcolor, vec3 fragnormal, vec3 texturecolor, float refl
|
||||
// panels, vehicle bodies and terrain reads as a clear edge rather
|
||||
// than a soft Lambertian ramp. Tunable via SUN_NDOTL_SHARPNESS.
|
||||
float sun_NdotL = pow(sunlight.x, SUN_NDOTL_SHARPNESS);
|
||||
float diffuseamount = sun_NdotL * param[1].x * lights[0].intensity;
|
||||
float diffuseamount = sun_NdotL * lights[0].intensity;
|
||||
|
||||
float shadow1 = 0.0;
|
||||
if (shadowtone < 1.0)
|
||||
@@ -317,7 +341,7 @@ vec3 apply_lights(vec3 fragcolor, vec3 fragnormal, vec3 texturecolor, float refl
|
||||
{
|
||||
light_s light = lights[i];
|
||||
vec2 part = calc_headlights(light, fragnormal);
|
||||
fragcolor += light.color * (part.x * param[1].x + part.y * param[1].y) * light.intensity;
|
||||
fragcolor += light.color * (part.x + part.y * param[1].y) * light.intensity;
|
||||
}
|
||||
|
||||
float specularamount = sunlight.y * param[1].y * specularity * lights[0].intensity
|
||||
|
||||
@@ -9,9 +9,9 @@ in vec4 f_clip_future_pos;
|
||||
|
||||
#param (color, 0, 0, 4, diffuse)
|
||||
#param (diffuse, 1, 0, 1, diffuse)
|
||||
#param (specular, 0.2, 0.2, 0.2, specular)
|
||||
#param (reflection, 0.5, 0.5, 0.5, zero)
|
||||
#param (glossiness, 0.5, 0.5, 0.5, glossiness)
|
||||
#param (specular, 1, 1, 1, specular)
|
||||
#param (reflection, 1, 2, 1, zero)
|
||||
#param (glossiness, 1, 3, 1, glossiness)
|
||||
|
||||
layout(location = 0) out vec4 out_color;
|
||||
#if MOTIONBLUR_ENABLED
|
||||
@@ -24,7 +24,8 @@ layout(location = 1) out vec4 out_motion;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 tex_color = vec4(pow(param[0].rgb, vec3(2.2)), param[0].a);
|
||||
// no texture: the diffuse colour alone makes the albedo, apply_lights() applies it to the white base
|
||||
vec4 tex_color = vec4(1.0, 1.0, 1.0, param[0].a);
|
||||
|
||||
// if (tex_color.a < opacity)
|
||||
// discard;
|
||||
@@ -32,7 +33,7 @@ void main()
|
||||
vec3 fragcolor = ambient;
|
||||
vec3 fragnormal = normalize(f_normal);
|
||||
float reflectivity = param[1].z;
|
||||
float specularity = (tex_color.r + tex_color.g + tex_color.b) * 0.5;
|
||||
float specularity = dot(pow(param[0].rgb, vec3(2.2)), vec3(0.5));
|
||||
glossiness = abs(param[1].w);
|
||||
|
||||
fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, specularity, shadow_tone);
|
||||
|
||||
@@ -41,7 +41,7 @@ void main()
|
||||
//float specularity = (tex_color.r + tex_color.g + tex_color.b) * 0.5;
|
||||
glossiness = abs(param[1].w);
|
||||
|
||||
fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, 0, shadow_tone);
|
||||
fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, 0.0, shadow_tone);
|
||||
vec4 color = vec4(apply_fog(fragcolor), tex_color.a * alpha_mult);
|
||||
/*
|
||||
float distance = dot(f_pos.xyz, f_pos.xyz);
|
||||
|
||||
@@ -44,7 +44,7 @@ void main()
|
||||
float specularity = (tex_color.r + tex_color.g + tex_color.b) * 0.5;
|
||||
glossiness = abs(param[1].w);
|
||||
|
||||
fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, 0, shadow_tone);
|
||||
fragcolor = apply_lights(fragcolor, fragnormal, tex_color.rgb, reflectivity, 0.0, shadow_tone);
|
||||
|
||||
if(alphatestfail)
|
||||
fragcolor.r = 1.0;
|
||||
|
||||
@@ -32,14 +32,15 @@ uniform sampler2D normalmap;
|
||||
|
||||
vec3 apply_lights_sunless(vec3 fragcolor, vec3 fragnormal, vec3 texturecolor, float reflectivity, float specularity, float shadowtone)
|
||||
{
|
||||
vec3 basecolor = param[0].rgb;
|
||||
// diffuse colour applied once, to the albedo (see material_diffuse() in light_common.glsl)
|
||||
texturecolor *= material_diffuse();
|
||||
|
||||
// Cab interior: dim ambient less than the exterior path because
|
||||
// ambient is the dominant indoor illumination. 0.80 trims the
|
||||
// brightest faces without making the cab feel under-lit.
|
||||
fragcolor *= basecolor * 0.80;
|
||||
fragcolor *= 0.80;
|
||||
|
||||
vec3 emissioncolor = basecolor * emission;
|
||||
vec3 emissioncolor = vec3(emission);
|
||||
vec3 envcolor = envmap_color(fragnormal);
|
||||
|
||||
// yuv path
|
||||
@@ -60,7 +61,7 @@ vec3 apply_lights_sunless(vec3 fragcolor, vec3 fragnormal, vec3 texturecolor, fl
|
||||
// Sharpen N.L for stronger contrast between lit and shaded cab
|
||||
// surfaces (uses SUN_NDOTL_SHARPNESS from light_common.glsl).
|
||||
float sun_NdotL = pow(sunlight.x, SUN_NDOTL_SHARPNESS);
|
||||
float diffuseamount = (sun_NdotL * param[1].x) * lights[0].intensity;
|
||||
float diffuseamount = sun_NdotL * lights[0].intensity;
|
||||
fragcolor += envcolor * reflectivity;
|
||||
float specularamount = (sunlight.y * param[1].y * specularity) * lights[0].intensity;
|
||||
glossiness = abs(param[1].w);
|
||||
@@ -79,7 +80,7 @@ vec3 apply_lights_sunless(vec3 fragcolor, vec3 fragnormal, vec3 texturecolor, fl
|
||||
// else if (light.type == LIGHT_HEADLIGHTS)
|
||||
part = calc_headlights(light, fragnormal);
|
||||
|
||||
fragcolor += light.color * (part.x * param[1].x + part.y * param[1].y) * light.intensity;
|
||||
fragcolor += light.color * (part.x + part.y * param[1].y) * light.intensity;
|
||||
}
|
||||
|
||||
if (shadowtone < 1.0)
|
||||
|
||||
@@ -36,12 +36,13 @@ uniform sampler2D specgloss;
|
||||
|
||||
vec3 apply_lights_sunless(vec3 fragcolor, vec3 fragnormal, vec3 texturecolor, float reflectivity, float specularity, float shadowtone)
|
||||
{
|
||||
vec3 basecolor = param[0].rgb;
|
||||
// diffuse colour applied once, to the albedo (see material_diffuse() in light_common.glsl)
|
||||
texturecolor *= material_diffuse();
|
||||
// Cab interior: dim ambient less than the exterior path - ambient
|
||||
// is the dominant indoor illumination, but it was still too bright.
|
||||
fragcolor *= basecolor * 0.80;
|
||||
fragcolor *= 0.80;
|
||||
|
||||
vec3 emissioncolor = basecolor * emission;
|
||||
vec3 emissioncolor = vec3(emission);
|
||||
|
||||
vec3 view_dir = normalize(-f_pos.xyz);
|
||||
float NdotV = max(dot(fragnormal, view_dir), 0.0);
|
||||
@@ -71,7 +72,7 @@ vec3 apply_lights_sunless(vec3 fragcolor, vec3 fragnormal, vec3 texturecolor, fl
|
||||
// Sharpen N.L for stronger contrast between lit and shaded cab
|
||||
// surfaces (uses SUN_NDOTL_SHARPNESS from light_common.glsl).
|
||||
float sun_NdotL = pow(sunlight.x, SUN_NDOTL_SHARPNESS);
|
||||
float diffuseamount = sun_NdotL * param[1].x * lights[0].intensity;
|
||||
float diffuseamount = sun_NdotL * lights[0].intensity;
|
||||
|
||||
float specularamount = sunlight.y * param[1].y * specularity * lights[0].intensity;
|
||||
|
||||
@@ -79,7 +80,7 @@ vec3 apply_lights_sunless(vec3 fragcolor, vec3 fragnormal, vec3 texturecolor, fl
|
||||
{
|
||||
light_s light = lights[i];
|
||||
vec2 part = calc_headlights(light, fragnormal);
|
||||
fragcolor += light.color * (part.x * param[1].x + part.y * param[1].y) * light.intensity;
|
||||
fragcolor += light.color * (part.x + part.y * param[1].y) * light.intensity;
|
||||
}
|
||||
|
||||
if (shadowtone < 1.0)
|
||||
|
||||
@@ -7,3 +7,7 @@ sonar.sourceEncoding=UTF-8
|
||||
|
||||
# Exclusions
|
||||
sonar.exclusions=betterRenderer/**,ref/**,imgui/**,stb/**,build/**,bw-output/**
|
||||
|
||||
# Excluding all files from coverage making the gate skip that
|
||||
# instead of failing it.
|
||||
sonar.coverage.exclusions=**/*
|
||||
|
||||
@@ -726,7 +726,9 @@ bool global_settings::ConfigParseSimulation(cParser& Parser, const std::string&
|
||||
|
||||
if (token == "randomseed")
|
||||
{
|
||||
ParseOne(Parser, Global.random_seed, 1);
|
||||
std::string text;
|
||||
ParseOne(Parser, text);
|
||||
Global.random_seed = seed_of(text);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ Copyright (C) 2007-2014 Maciej Cierniak
|
||||
//
|
||||
//#include <sys/types.h>
|
||||
//#include <sys/stat.h>
|
||||
#include <charconv>
|
||||
#include <ranges>
|
||||
//#ifndef WIN32
|
||||
//#include <unistd.h>
|
||||
@@ -28,9 +29,9 @@ Copyright (C) 2007-2014 Maciej Cierniak
|
||||
#include "utilities/Globals.h"
|
||||
#include "utilities/parser.h"
|
||||
#include "utilities/U8.h"
|
||||
#include "utilities/Logs.h"
|
||||
|
||||
|
||||
//#include "utilities/Logs.h"
|
||||
|
||||
// TODO: This shouldn't be in Globals?
|
||||
bool DebugModeFlag = false;
|
||||
@@ -137,15 +138,51 @@ int Random(int min, int max)
|
||||
return dist(Global.random_engine);
|
||||
}
|
||||
|
||||
std::uint64_t true_random_seed()
|
||||
{
|
||||
try
|
||||
{
|
||||
std::random_device rd;
|
||||
if (rd.entropy() > 0.0)
|
||||
{
|
||||
// NOTE: both halves have to be 64 bit wide before the shift - shifting a std::uint32_t
|
||||
// by 32 is undefined behaviour, and drops the high half of the seed
|
||||
std::uint64_t const high{rd()};
|
||||
std::uint64_t const low{rd()};
|
||||
return (high << 32) | low;
|
||||
}
|
||||
}
|
||||
catch (std::exception const &Error)
|
||||
{
|
||||
// std::random_device throws when the machine has no usable hardware entropy source;
|
||||
// the clock below stands in for it, which is worth saying out loud since it is a
|
||||
// weaker seed than the caller asked for
|
||||
WriteLog(std::format("random: no hardware entropy source ({}), seeding from the clock instead", Error.what()));
|
||||
}
|
||||
return static_cast<std::uint64_t>(std::chrono::high_resolution_clock::now().time_since_epoch().count());
|
||||
}
|
||||
|
||||
std::uint32_t seed_of(std::string const &Text)
|
||||
{
|
||||
if (std::uint32_t number{}; std::from_chars(Text.data(), Text.data() + Text.size(), number).ec == std::errc{})
|
||||
{
|
||||
return number;
|
||||
}
|
||||
std::uint32_t hash{};
|
||||
for (auto const character : Text)
|
||||
{
|
||||
hash = hash * 31u + static_cast<std::uint32_t>(static_cast<unsigned char>(character));
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
std::string generate_uuid_v4()
|
||||
{
|
||||
std::random_device rd;
|
||||
std::mt19937 gen(rd());
|
||||
std::uniform_int_distribution<int> dist(0, 255);
|
||||
|
||||
std::array<uint8_t, 16> bytes;
|
||||
for (auto &b : bytes)
|
||||
b = static_cast<uint8_t>(dist(gen));
|
||||
b = static_cast<uint8_t>(dist(Global.random_engine));
|
||||
|
||||
// UUID v4 (RFC 4122)
|
||||
bytes[6] = bytes[6] & 0x0F | 0x40;
|
||||
|
||||
@@ -62,6 +62,18 @@ inline long Round(double const f)
|
||||
|
||||
double Random(double a, double b);
|
||||
int Random(int min, int max);
|
||||
|
||||
/// @author lxvia
|
||||
/// @brief Returns a random seed from the system's entropy source, if available. Otherwise, falls back to a clock-based seed.
|
||||
/// @return A random seed as 64 bit unsigned integer
|
||||
std::uint64_t true_random_seed();
|
||||
|
||||
// The seed a word stands for. A number is taken as it is written; anything else is
|
||||
// hashed the way Java's String.hashCode does it, so the same word gives the same
|
||||
// world on every platform and every build - which is the whole point of telling
|
||||
// somebody a seed.
|
||||
std::uint32_t seed_of(std::string const &Text);
|
||||
|
||||
std::string generate_uuid_v4();
|
||||
double LocalRandom(double a, double b);
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include "utilities/utilities.h"
|
||||
#include "utilities/Globals.h"
|
||||
|
||||
class UID {
|
||||
public:
|
||||
@@ -13,10 +15,9 @@ public:
|
||||
|
||||
|
||||
static UID random() {
|
||||
static thread_local std::mt19937_64 gen(std::random_device{}());
|
||||
UID u;
|
||||
uint64_t a = gen();
|
||||
uint64_t b = gen();
|
||||
uint64_t a = Global.random_engine();
|
||||
uint64_t b = Global.random_engine();
|
||||
for (int i = 0; i < 8; ++i) u.bytes[i] = uint8_t(a >> (i * 8) & 0xFF);
|
||||
for (int i = 0; i < 8; ++i) u.bytes[8 + i] = uint8_t(b >> (i * 8) & 0xFF);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user