mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-22 19:49:19 +02:00
semaphores controllable on minimap
This commit is contained in:
@@ -591,6 +591,24 @@ void TAnimModel::LightSet(int const n, float const v)
|
|||||||
lsLights[ n ] = v;
|
lsLights[ n ] = v;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::optional<std::tuple<float, float, std::optional<glm::vec3>> > TAnimModel::LightGet(const int n)
|
||||||
|
{
|
||||||
|
if (n >= iMaxNumLights)
|
||||||
|
return std::nullopt;
|
||||||
|
if (!LightsOn[n] && !LightsOff[n])
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
|
std::optional<glm::vec3> color;
|
||||||
|
|
||||||
|
if (m_lightcolors[n].r >= 0.0f)
|
||||||
|
color.emplace(m_lightcolors[n]);
|
||||||
|
|
||||||
|
if (!color && LightsOn[n])
|
||||||
|
color = LightsOn[n]->GetDiffuse();
|
||||||
|
|
||||||
|
return std::make_tuple(lsLights[n], m_lightopacities[n], color);
|
||||||
|
}
|
||||||
|
|
||||||
void TAnimModel::AnimUpdate(double dt)
|
void TAnimModel::AnimUpdate(double dt)
|
||||||
{ // wykonanie zakolejkowanych animacji, nawet gdy modele nie są aktualnie wyświetlane
|
{ // wykonanie zakolejkowanych animacji, nawet gdy modele nie są aktualnie wyświetlane
|
||||||
TAnimContainer *p = TAnimModel::acAnimList;
|
TAnimContainer *p = TAnimModel::acAnimList;
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ public:
|
|||||||
TAnimContainer * AddContainer(std::string const &Name);
|
TAnimContainer * AddContainer(std::string const &Name);
|
||||||
TAnimContainer * GetContainer(std::string const &Name = "");
|
TAnimContainer * GetContainer(std::string const &Name = "");
|
||||||
void LightSet( int const n, float const v );
|
void LightSet( int const n, float const v );
|
||||||
|
std::optional<std::tuple<float, float, std::optional<glm::vec3> > > LightGet( int const n );
|
||||||
int TerrainCount();
|
int TerrainCount();
|
||||||
TSubModel * TerrainSquare(int n);
|
TSubModel * TerrainSquare(int n);
|
||||||
int Flags();
|
int Flags();
|
||||||
|
|||||||
@@ -126,6 +126,7 @@ set(SOURCES
|
|||||||
"widgets/vehiclelist.cpp"
|
"widgets/vehiclelist.cpp"
|
||||||
"widgets/map.cpp"
|
"widgets/map.cpp"
|
||||||
"widgets/map_objects.cpp"
|
"widgets/map_objects.cpp"
|
||||||
|
"widgets/popup.cpp"
|
||||||
|
|
||||||
"ref/glad/src/glad.c"
|
"ref/glad/src/glad.c"
|
||||||
|
|
||||||
|
|||||||
24
Model3d.cpp
24
Model3d.cpp
@@ -91,6 +91,30 @@ TSubModel::SetDiffuseOverride( glm::vec3 const &Color, bool const Includechildre
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<glm::vec3>
|
||||||
|
TSubModel::GetDiffuse(float Includesiblings) {
|
||||||
|
if (eType == TP_FREESPOTLIGHT) {
|
||||||
|
if (DiffuseOverride.x >= 0.0f)
|
||||||
|
return DiffuseOverride;
|
||||||
|
else
|
||||||
|
return glm::vec3(f4Diffuse);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Includesiblings) {
|
||||||
|
auto sibling = this;
|
||||||
|
while ((sibling = sibling->Next)) {
|
||||||
|
auto result = sibling->GetDiffuse(true);
|
||||||
|
if (result)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Child)
|
||||||
|
return Child->GetDiffuse(true);
|
||||||
|
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
// sets visibility level (alpha component) to specified value
|
// sets visibility level (alpha component) to specified value
|
||||||
void
|
void
|
||||||
TSubModel::SetVisibilityLevel( float const Level, bool const Includechildren, bool const Includesiblings ) {
|
TSubModel::SetVisibilityLevel( float const Level, bool const Includechildren, bool const Includesiblings ) {
|
||||||
|
|||||||
@@ -196,6 +196,8 @@ public:
|
|||||||
void ColorsSet( glm::vec3 const &Ambient, glm::vec3 const &Diffuse, glm::vec3 const &Specular );
|
void ColorsSet( glm::vec3 const &Ambient, glm::vec3 const &Diffuse, glm::vec3 const &Specular );
|
||||||
// sets rgb components of diffuse color override to specified value
|
// sets rgb components of diffuse color override to specified value
|
||||||
void SetDiffuseOverride( glm::vec3 const &Color, bool const Includechildren = false, bool const Includesiblings = false );
|
void SetDiffuseOverride( glm::vec3 const &Color, bool const Includechildren = false, bool const Includesiblings = false );
|
||||||
|
// gets rgb components of any freespot diffuse color (searches also in children)
|
||||||
|
std::optional<glm::vec3> GetDiffuse(float Includesiblings = false);
|
||||||
// sets visibility level (alpha component) to specified value
|
// sets visibility level (alpha component) to specified value
|
||||||
void SetVisibilityLevel( float const Level, bool const Includechildren = false, bool const Includesiblings = false );
|
void SetVisibilityLevel( float const Level, bool const Includechildren = false, bool const Includesiblings = false );
|
||||||
// sets light level (alpha component of illumination color) to specified value
|
// sets light level (alpha component of illumination color) to specified value
|
||||||
|
|||||||
7
Names.h
7
Names.h
@@ -62,6 +62,13 @@ public:
|
|||||||
|
|
||||||
m_itemmap.erase(lookup);
|
m_itemmap.erase(lookup);
|
||||||
}
|
}
|
||||||
|
uint32_t find_id( std::string const &Name) const {
|
||||||
|
auto lookup = m_itemmap.find( Name );
|
||||||
|
return (
|
||||||
|
lookup != m_itemmap.end() ?
|
||||||
|
lookup->second :
|
||||||
|
-1 );
|
||||||
|
}
|
||||||
// locates item with specified name. returns pointer to the item, or nullptr
|
// locates item with specified name. returns pointer to the item, or nullptr
|
||||||
Type_ *
|
Type_ *
|
||||||
find( std::string const &Name ) const {
|
find( std::string const &Name ) const {
|
||||||
|
|||||||
@@ -236,6 +236,7 @@ commanddescription_sequence Commands_descriptions = {
|
|||||||
{ "pausetoggle", command_target::simulation, command_mode::oneoff },
|
{ "pausetoggle", command_target::simulation, command_mode::oneoff },
|
||||||
{ "entervehicle", command_target::simulation, command_mode::oneoff },
|
{ "entervehicle", command_target::simulation, command_mode::oneoff },
|
||||||
{ "queueevent", command_target::simulation, command_mode::oneoff },
|
{ "queueevent", command_target::simulation, command_mode::oneoff },
|
||||||
|
{ "setlight", command_target::simulation, command_mode::oneoff },
|
||||||
};
|
};
|
||||||
|
|
||||||
} // simulation
|
} // simulation
|
||||||
|
|||||||
@@ -230,6 +230,7 @@ enum class user_command {
|
|||||||
pausetoggle,
|
pausetoggle,
|
||||||
entervehicle,
|
entervehicle,
|
||||||
queueevent,
|
queueevent,
|
||||||
|
setlight,
|
||||||
|
|
||||||
none = -1
|
none = -1
|
||||||
};
|
};
|
||||||
|
|||||||
352
renderer.cpp
352
renderer.cpp
@@ -189,78 +189,16 @@ bool opengl_renderer::Init(GLFWwindow *Window)
|
|||||||
if (!Global.gfx_usegles && samples > 1)
|
if (!Global.gfx_usegles && samples > 1)
|
||||||
glEnable(GL_MULTISAMPLE);
|
glEnable(GL_MULTISAMPLE);
|
||||||
|
|
||||||
if (!Global.gfx_skippipeline)
|
|
||||||
{
|
|
||||||
m_msaa_rbc = std::make_unique<gl::renderbuffer>();
|
|
||||||
m_msaa_rbc->alloc(Global.gfx_format_color, Global.gfx_framebuffer_width, Global.gfx_framebuffer_height, samples);
|
|
||||||
|
|
||||||
m_msaa_rbd = std::make_unique<gl::renderbuffer>();
|
|
||||||
m_msaa_rbd->alloc(Global.gfx_format_depth, Global.gfx_framebuffer_width, Global.gfx_framebuffer_height, samples);
|
|
||||||
|
|
||||||
m_msaa_fb = std::make_unique<gl::framebuffer>();
|
|
||||||
m_msaa_fb->attach(*m_msaa_rbc, GL_COLOR_ATTACHMENT0);
|
|
||||||
m_msaa_fb->attach(*m_msaa_rbd, GL_DEPTH_ATTACHMENT);
|
|
||||||
|
|
||||||
if (Global.gfx_postfx_motionblur_enabled)
|
|
||||||
{
|
|
||||||
m_msaa_rbv = std::make_unique<gl::renderbuffer>();
|
|
||||||
m_msaa_rbv->alloc(Global.gfx_postfx_motionblur_format, Global.gfx_framebuffer_width, Global.gfx_framebuffer_height, samples);
|
|
||||||
m_msaa_fb->attach(*m_msaa_rbv, GL_COLOR_ATTACHMENT1);
|
|
||||||
|
|
||||||
m_main_tex = std::make_unique<opengl_texture>();
|
|
||||||
m_main_tex->alloc_rendertarget(Global.gfx_format_color, GL_RGB, Global.gfx_framebuffer_width, Global.gfx_framebuffer_height, 1, GL_CLAMP_TO_EDGE);
|
|
||||||
|
|
||||||
m_main_fb = std::make_unique<gl::framebuffer>();
|
|
||||||
m_main_fb->attach(*m_main_tex, GL_COLOR_ATTACHMENT0);
|
|
||||||
|
|
||||||
m_main_texv = std::make_unique<opengl_texture>();
|
|
||||||
m_main_texv->alloc_rendertarget(Global.gfx_postfx_motionblur_format, GL_RG, Global.gfx_framebuffer_width, Global.gfx_framebuffer_height);
|
|
||||||
m_main_fb->attach(*m_main_texv, GL_COLOR_ATTACHMENT1);
|
|
||||||
m_main_fb->setup_drawing(2);
|
|
||||||
|
|
||||||
if (!m_main_fb->is_complete())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
m_pfx_motionblur = std::make_unique<gl::postfx>("motionblur");
|
m_pfx_motionblur = std::make_unique<gl::postfx>("motionblur");
|
||||||
|
|
||||||
WriteLog("motion blur enabled");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!m_msaa_fb->is_complete())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
m_main2_tex = std::make_unique<opengl_texture>();
|
|
||||||
m_main2_tex->alloc_rendertarget(Global.gfx_format_color, GL_RGB, Global.gfx_framebuffer_width, Global.gfx_framebuffer_height);
|
|
||||||
|
|
||||||
m_main2_fb = std::make_unique<gl::framebuffer>();
|
|
||||||
m_main2_fb->attach(*m_main2_tex, GL_COLOR_ATTACHMENT0);
|
|
||||||
if (!m_main2_fb->is_complete())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
m_pfx_tonemapping = std::make_unique<gl::postfx>("tonemapping");
|
m_pfx_tonemapping = std::make_unique<gl::postfx>("tonemapping");
|
||||||
}
|
|
||||||
|
|
||||||
if (Global.gfx_shadowmap_enabled)
|
m_empty_cubemap = std::make_unique<gl::cubemap>();
|
||||||
{
|
m_empty_cubemap->alloc(Global.gfx_format_color, 16, 16, GL_RGB, GL_FLOAT);
|
||||||
m_shadow_fb = std::make_unique<gl::framebuffer>();
|
|
||||||
m_shadow_tex = std::make_unique<opengl_texture>();
|
|
||||||
m_shadow_tex->alloc_rendertarget(Global.gfx_format_depth, GL_DEPTH_COMPONENT, m_shadowbuffersize, m_shadowbuffersize);
|
|
||||||
m_shadow_fb->attach(*m_shadow_tex, GL_DEPTH_ATTACHMENT);
|
|
||||||
|
|
||||||
if (!m_shadow_fb->is_complete())
|
m_current_viewport = &default_viewport;
|
||||||
|
if (!init_viewport(default_viewport))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_cabshadows_fb = std::make_unique<gl::framebuffer>();
|
|
||||||
m_cabshadows_tex = std::make_unique<opengl_texture>();
|
|
||||||
m_cabshadows_tex->alloc_rendertarget(Global.gfx_format_depth, GL_DEPTH_COMPONENT, m_shadowbuffersize, m_shadowbuffersize);
|
|
||||||
m_cabshadows_fb->attach(*m_cabshadows_tex, GL_DEPTH_ATTACHMENT);
|
|
||||||
|
|
||||||
if (!m_cabshadows_fb->is_complete())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
WriteLog("shadows enabled");
|
|
||||||
}
|
|
||||||
|
|
||||||
m_pick_tex = std::make_unique<opengl_texture>();
|
m_pick_tex = std::make_unique<opengl_texture>();
|
||||||
m_pick_tex->alloc_rendertarget(GL_RGB8, GL_RGB, EU07_PICKBUFFERSIZE, EU07_PICKBUFFERSIZE);
|
m_pick_tex->alloc_rendertarget(GL_RGB8, GL_RGB, EU07_PICKBUFFERSIZE, EU07_PICKBUFFERSIZE);
|
||||||
m_pick_rb = std::make_unique<gl::renderbuffer>();
|
m_pick_rb = std::make_unique<gl::renderbuffer>();
|
||||||
@@ -272,30 +210,6 @@ bool opengl_renderer::Init(GLFWwindow *Window)
|
|||||||
if (!m_pick_fb->is_complete())
|
if (!m_pick_fb->is_complete())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (Global.gfx_envmap_enabled)
|
|
||||||
{
|
|
||||||
m_env_rb = std::make_unique<gl::renderbuffer>();
|
|
||||||
m_env_rb->alloc(Global.gfx_format_depth, gl::ENVMAP_SIZE, gl::ENVMAP_SIZE);
|
|
||||||
m_env_tex = std::make_unique<gl::cubemap>();
|
|
||||||
m_env_tex->alloc(Global.gfx_format_color, gl::ENVMAP_SIZE, gl::ENVMAP_SIZE, GL_RGB, GL_FLOAT);
|
|
||||||
m_empty_cubemap = std::make_unique<gl::cubemap>();
|
|
||||||
m_empty_cubemap->alloc(Global.gfx_format_color, 16, 16, GL_RGB, GL_FLOAT);
|
|
||||||
|
|
||||||
m_env_fb = std::make_unique<gl::framebuffer>();
|
|
||||||
|
|
||||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
|
||||||
for (int i = 0; i < 6; i++)
|
|
||||||
{
|
|
||||||
m_env_fb->attach(*m_empty_cubemap, i, GL_COLOR_ATTACHMENT0);
|
|
||||||
m_env_fb->clear(GL_COLOR_BUFFER_BIT);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_env_fb->detach(GL_COLOR_ATTACHMENT0);
|
|
||||||
m_env_fb->attach(*m_env_rb, GL_DEPTH_ATTACHMENT);
|
|
||||||
|
|
||||||
WriteLog("envmap enabled");
|
|
||||||
}
|
|
||||||
|
|
||||||
m_picking_pbo = std::make_unique<gl::pbo>();
|
m_picking_pbo = std::make_unique<gl::pbo>();
|
||||||
m_picking_node_pbo = std::make_unique<gl::pbo>();
|
m_picking_node_pbo = std::make_unique<gl::pbo>();
|
||||||
|
|
||||||
@@ -357,6 +271,103 @@ bool opengl_renderer::Init(GLFWwindow *Window)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool opengl_renderer::init_viewport(viewport_data &vp)
|
||||||
|
{
|
||||||
|
int samples = 1 << Global.iMultisampling;
|
||||||
|
|
||||||
|
if (!Global.gfx_skippipeline)
|
||||||
|
{
|
||||||
|
vp.msaa_rbc = std::make_unique<gl::renderbuffer>();
|
||||||
|
vp.msaa_rbc->alloc(Global.gfx_format_color, Global.gfx_framebuffer_width, Global.gfx_framebuffer_height, samples);
|
||||||
|
|
||||||
|
vp.msaa_rbd = std::make_unique<gl::renderbuffer>();
|
||||||
|
vp.msaa_rbd->alloc(Global.gfx_format_depth, Global.gfx_framebuffer_width, Global.gfx_framebuffer_height, samples);
|
||||||
|
|
||||||
|
vp.msaa_fb = std::make_unique<gl::framebuffer>();
|
||||||
|
vp.msaa_fb->attach(*vp.msaa_rbc, GL_COLOR_ATTACHMENT0);
|
||||||
|
vp.msaa_fb->attach(*vp.msaa_rbd, GL_DEPTH_ATTACHMENT);
|
||||||
|
|
||||||
|
if (Global.gfx_postfx_motionblur_enabled)
|
||||||
|
{
|
||||||
|
vp.msaa_rbv = std::make_unique<gl::renderbuffer>();
|
||||||
|
vp.msaa_rbv->alloc(Global.gfx_postfx_motionblur_format, Global.gfx_framebuffer_width, Global.gfx_framebuffer_height, samples);
|
||||||
|
vp.msaa_fb->attach(*vp.msaa_rbv, GL_COLOR_ATTACHMENT1);
|
||||||
|
|
||||||
|
vp.main_tex = std::make_unique<opengl_texture>();
|
||||||
|
vp.main_tex->alloc_rendertarget(Global.gfx_format_color, GL_RGB, Global.gfx_framebuffer_width, Global.gfx_framebuffer_height, 1, GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
vp.main_fb = std::make_unique<gl::framebuffer>();
|
||||||
|
vp.main_fb->attach(*vp.main_tex, GL_COLOR_ATTACHMENT0);
|
||||||
|
|
||||||
|
vp.main_texv = std::make_unique<opengl_texture>();
|
||||||
|
vp.main_texv->alloc_rendertarget(Global.gfx_postfx_motionblur_format, GL_RG, Global.gfx_framebuffer_width, Global.gfx_framebuffer_height);
|
||||||
|
vp.main_fb->attach(*vp.main_texv, GL_COLOR_ATTACHMENT1);
|
||||||
|
vp.main_fb->setup_drawing(2);
|
||||||
|
|
||||||
|
if (!vp.main_fb->is_complete())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
WriteLog("motion blur enabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!vp.msaa_fb->is_complete())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
vp.main2_tex = std::make_unique<opengl_texture>();
|
||||||
|
vp.main2_tex->alloc_rendertarget(Global.gfx_format_color, GL_RGB, Global.gfx_framebuffer_width, Global.gfx_framebuffer_height);
|
||||||
|
|
||||||
|
vp.main2_fb = std::make_unique<gl::framebuffer>();
|
||||||
|
vp.main2_fb->attach(*vp.main2_tex, GL_COLOR_ATTACHMENT0);
|
||||||
|
if (!vp.main2_fb->is_complete())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Global.gfx_shadowmap_enabled)
|
||||||
|
{
|
||||||
|
vp.shadow_fb = std::make_unique<gl::framebuffer>();
|
||||||
|
vp.shadow_tex = std::make_unique<opengl_texture>();
|
||||||
|
vp.shadow_tex->alloc_rendertarget(Global.gfx_format_depth, GL_DEPTH_COMPONENT, m_shadowbuffersize, m_shadowbuffersize);
|
||||||
|
vp.shadow_fb->attach(*vp.shadow_tex, GL_DEPTH_ATTACHMENT);
|
||||||
|
|
||||||
|
if (!vp.shadow_fb->is_complete())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
vp.cabshadows_fb = std::make_unique<gl::framebuffer>();
|
||||||
|
vp.cabshadows_tex = std::make_unique<opengl_texture>();
|
||||||
|
vp.cabshadows_tex->alloc_rendertarget(Global.gfx_format_depth, GL_DEPTH_COMPONENT, m_shadowbuffersize, m_shadowbuffersize);
|
||||||
|
vp.cabshadows_fb->attach(*vp.cabshadows_tex, GL_DEPTH_ATTACHMENT);
|
||||||
|
|
||||||
|
if (!vp.cabshadows_fb->is_complete())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
WriteLog("shadows enabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Global.gfx_envmap_enabled)
|
||||||
|
{
|
||||||
|
vp.env_rb = std::make_unique<gl::renderbuffer>();
|
||||||
|
vp.env_rb->alloc(Global.gfx_format_depth, gl::ENVMAP_SIZE, gl::ENVMAP_SIZE);
|
||||||
|
vp.env_tex = std::make_unique<gl::cubemap>();
|
||||||
|
vp.env_tex->alloc(Global.gfx_format_color, gl::ENVMAP_SIZE, gl::ENVMAP_SIZE, GL_RGB, GL_FLOAT);
|
||||||
|
|
||||||
|
vp.env_fb = std::make_unique<gl::framebuffer>();
|
||||||
|
|
||||||
|
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
|
for (int i = 0; i < 6; i++)
|
||||||
|
{
|
||||||
|
vp.env_fb->attach(*m_empty_cubemap, i, GL_COLOR_ATTACHMENT0);
|
||||||
|
vp.env_fb->clear(GL_COLOR_BUFFER_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
vp.env_fb->detach(GL_COLOR_ATTACHMENT0);
|
||||||
|
vp.env_fb->attach(*vp.env_rb, GL_DEPTH_ATTACHMENT);
|
||||||
|
|
||||||
|
WriteLog("envmap enabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<gl::program> opengl_renderer::make_shader(std::string v, std::string f)
|
std::unique_ptr<gl::program> opengl_renderer::make_shader(std::string v, std::string f)
|
||||||
{
|
{
|
||||||
gl::shader vert(v);
|
gl::shader vert(v);
|
||||||
@@ -401,7 +412,7 @@ bool opengl_renderer::Render()
|
|||||||
m_renderpass.draw_mode = rendermode::none; // force setup anew
|
m_renderpass.draw_mode = rendermode::none; // force setup anew
|
||||||
m_debugstats = debug_stats();
|
m_debugstats = debug_stats();
|
||||||
|
|
||||||
Render_pass(rendermode::color);
|
Render_pass(default_viewport, rendermode::color);
|
||||||
|
|
||||||
m_drawcount = m_cellqueue.size();
|
m_drawcount = m_cellqueue.size();
|
||||||
m_debugtimestext.clear();
|
m_debugtimestext.clear();
|
||||||
@@ -464,7 +475,7 @@ void opengl_renderer::draw_debug_ui()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// runs jobs needed to generate graphics for specified render pass
|
// runs jobs needed to generate graphics for specified render pass
|
||||||
void opengl_renderer::Render_pass(rendermode const Mode)
|
void opengl_renderer::Render_pass(viewport_data &vp, rendermode const Mode)
|
||||||
{
|
{
|
||||||
setup_pass(m_renderpass, Mode);
|
setup_pass(m_renderpass, Mode);
|
||||||
switch (m_renderpass.draw_mode)
|
switch (m_renderpass.draw_mode)
|
||||||
@@ -506,9 +517,9 @@ void opengl_renderer::Render_pass(rendermode const Mode)
|
|||||||
glDebug("render shadowmap start");
|
glDebug("render shadowmap start");
|
||||||
Timer::subsystem.gfx_shadows.start();
|
Timer::subsystem.gfx_shadows.start();
|
||||||
|
|
||||||
Render_pass(rendermode::shadows);
|
Render_pass(vp, rendermode::shadows);
|
||||||
if (!FreeFlyModeFlag)
|
if (!FreeFlyModeFlag)
|
||||||
Render_pass(rendermode::cabshadows);
|
Render_pass(vp, rendermode::cabshadows);
|
||||||
setup_pass(m_renderpass, Mode); // restore draw mode. TBD, TODO: render mode stack
|
setup_pass(m_renderpass, Mode); // restore draw mode. TBD, TODO: render mode stack
|
||||||
|
|
||||||
Timer::subsystem.gfx_shadows.stop();
|
Timer::subsystem.gfx_shadows.stop();
|
||||||
@@ -518,9 +529,9 @@ void opengl_renderer::Render_pass(rendermode const Mode)
|
|||||||
if (Global.gfx_envmap_enabled)
|
if (Global.gfx_envmap_enabled)
|
||||||
{
|
{
|
||||||
// potentially update environmental cube map
|
// potentially update environmental cube map
|
||||||
if (Render_reflections())
|
if (Render_reflections(vp))
|
||||||
setup_pass(m_renderpass, Mode); // restore color pass settings
|
setup_pass(m_renderpass, Mode); // restore color pass settings
|
||||||
setup_env_map(m_env_tex.get());
|
setup_env_map(vp.env_tex.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
@@ -528,16 +539,16 @@ void opengl_renderer::Render_pass(rendermode const Mode)
|
|||||||
setup_drawing(false);
|
setup_drawing(false);
|
||||||
if (!Global.gfx_skippipeline)
|
if (!Global.gfx_skippipeline)
|
||||||
{
|
{
|
||||||
m_msaa_fb->bind();
|
vp.msaa_fb->bind();
|
||||||
|
|
||||||
if (Global.gfx_postfx_motionblur_enabled)
|
if (Global.gfx_postfx_motionblur_enabled)
|
||||||
m_msaa_fb->setup_drawing(2);
|
vp.msaa_fb->setup_drawing(2);
|
||||||
else
|
else
|
||||||
m_msaa_fb->setup_drawing(1);
|
vp.msaa_fb->setup_drawing(1);
|
||||||
|
|
||||||
glViewport(0, 0, Global.gfx_framebuffer_width, Global.gfx_framebuffer_height);
|
glViewport(0, 0, Global.gfx_framebuffer_width, Global.gfx_framebuffer_height);
|
||||||
|
|
||||||
m_msaa_fb->clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
vp.msaa_fb->clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -579,7 +590,7 @@ void opengl_renderer::Render_pass(rendermode const Mode)
|
|||||||
{
|
{
|
||||||
glDebug("render cab opaque");
|
glDebug("render cab opaque");
|
||||||
if (Global.gfx_shadowmap_enabled)
|
if (Global.gfx_shadowmap_enabled)
|
||||||
setup_shadow_map(m_cabshadows_tex.get(), m_cabshadowpass);
|
setup_shadow_map(vp.cabshadows_tex.get(), m_cabshadowpass);
|
||||||
|
|
||||||
auto const *vehicle = simulation::Train->Dynamic();
|
auto const *vehicle = simulation::Train->Dynamic();
|
||||||
Render_cab(vehicle, vehicle->InteriorLightLevel, false);
|
Render_cab(vehicle, vehicle->InteriorLightLevel, false);
|
||||||
@@ -590,7 +601,7 @@ void opengl_renderer::Render_pass(rendermode const Mode)
|
|||||||
model_ubs.future = future;
|
model_ubs.future = future;
|
||||||
|
|
||||||
if (Global.gfx_shadowmap_enabled)
|
if (Global.gfx_shadowmap_enabled)
|
||||||
setup_shadow_map(m_shadow_tex.get(), m_shadowpass);
|
setup_shadow_map(vp.shadow_tex.get(), m_shadowpass);
|
||||||
|
|
||||||
Render(simulation::Region);
|
Render(simulation::Region);
|
||||||
|
|
||||||
@@ -608,7 +619,7 @@ void opengl_renderer::Render_pass(rendermode const Mode)
|
|||||||
glDebug("render translucent cab");
|
glDebug("render translucent cab");
|
||||||
model_ubs.future = glm::mat4();
|
model_ubs.future = glm::mat4();
|
||||||
if (Global.gfx_shadowmap_enabled)
|
if (Global.gfx_shadowmap_enabled)
|
||||||
setup_shadow_map(m_cabshadows_tex.get(), m_cabshadowpass);
|
setup_shadow_map(vp.cabshadows_tex.get(), m_cabshadowpass);
|
||||||
// cache shadow colour in case we need to account for cab light
|
// cache shadow colour in case we need to account for cab light
|
||||||
auto const *vehicle{simulation::Train->Dynamic()};
|
auto const *vehicle{simulation::Train->Dynamic()};
|
||||||
if (Global.Overcast > 1.0f)
|
if (Global.Overcast > 1.0f)
|
||||||
@@ -633,24 +644,24 @@ void opengl_renderer::Render_pass(rendermode const Mode)
|
|||||||
{
|
{
|
||||||
if (Global.gfx_postfx_motionblur_enabled)
|
if (Global.gfx_postfx_motionblur_enabled)
|
||||||
{
|
{
|
||||||
m_main_fb->clear(GL_COLOR_BUFFER_BIT);
|
vp.main_fb->clear(GL_COLOR_BUFFER_BIT);
|
||||||
m_msaa_fb->blit_to(m_main_fb.get(), Global.gfx_framebuffer_width, Global.gfx_framebuffer_height, GL_COLOR_BUFFER_BIT, GL_COLOR_ATTACHMENT0);
|
vp.msaa_fb->blit_to(vp.main_fb.get(), Global.gfx_framebuffer_width, Global.gfx_framebuffer_height, GL_COLOR_BUFFER_BIT, GL_COLOR_ATTACHMENT0);
|
||||||
m_msaa_fb->blit_to(m_main_fb.get(), Global.gfx_framebuffer_width, Global.gfx_framebuffer_height, GL_COLOR_BUFFER_BIT, GL_COLOR_ATTACHMENT1);
|
vp.msaa_fb->blit_to(vp.main_fb.get(), Global.gfx_framebuffer_width, Global.gfx_framebuffer_height, GL_COLOR_BUFFER_BIT, GL_COLOR_ATTACHMENT1);
|
||||||
|
|
||||||
model_ubs.param[0].x = m_framerate / (1.0 / Global.gfx_postfx_motionblur_shutter);
|
model_ubs.param[0].x = m_framerate / (1.0 / Global.gfx_postfx_motionblur_shutter);
|
||||||
model_ubo->update(model_ubs);
|
model_ubo->update(model_ubs);
|
||||||
m_pfx_motionblur->apply({m_main_tex.get(), m_main_texv.get()}, m_main2_fb.get());
|
m_pfx_motionblur->apply({vp.main_tex.get(), vp.main_texv.get()}, vp.main2_fb.get());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_main2_fb->clear(GL_COLOR_BUFFER_BIT);
|
vp.main2_fb->clear(GL_COLOR_BUFFER_BIT);
|
||||||
m_msaa_fb->blit_to(m_main2_fb.get(), Global.gfx_framebuffer_width, Global.gfx_framebuffer_height, GL_COLOR_BUFFER_BIT, GL_COLOR_ATTACHMENT0);
|
vp.msaa_fb->blit_to(vp.main2_fb.get(), Global.gfx_framebuffer_width, Global.gfx_framebuffer_height, GL_COLOR_BUFFER_BIT, GL_COLOR_ATTACHMENT0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Global.gfx_usegles && !Global.gfx_shadergamma)
|
if (!Global.gfx_usegles && !Global.gfx_shadergamma)
|
||||||
glEnable(GL_FRAMEBUFFER_SRGB);
|
glEnable(GL_FRAMEBUFFER_SRGB);
|
||||||
glViewport(0, 0, Global.iWindowWidth, Global.iWindowHeight);
|
glViewport(0, 0, Global.iWindowWidth, Global.iWindowHeight);
|
||||||
m_pfx_tonemapping->apply(*m_main2_tex, nullptr);
|
m_pfx_tonemapping->apply(*vp.main2_tex, nullptr);
|
||||||
opengl_texture::reset_unit_cache();
|
opengl_texture::reset_unit_cache();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -685,8 +696,8 @@ void opengl_renderer::Render_pass(rendermode const Mode)
|
|||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
glViewport(0, 0, m_shadowbuffersize, m_shadowbuffersize);
|
glViewport(0, 0, m_shadowbuffersize, m_shadowbuffersize);
|
||||||
m_shadow_fb->bind();
|
vp.shadow_fb->bind();
|
||||||
m_shadow_fb->clear(GL_DEPTH_BUFFER_BIT);
|
vp.shadow_fb->clear(GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
setup_matrices();
|
setup_matrices();
|
||||||
setup_drawing(false);
|
setup_drawing(false);
|
||||||
@@ -703,7 +714,7 @@ void opengl_renderer::Render_pass(rendermode const Mode)
|
|||||||
|
|
||||||
glDisable(GL_POLYGON_OFFSET_FILL);
|
glDisable(GL_POLYGON_OFFSET_FILL);
|
||||||
|
|
||||||
m_shadow_fb->unbind();
|
vp.shadow_fb->unbind();
|
||||||
|
|
||||||
glDebug("rendermodeshadows ::end");
|
glDebug("rendermodeshadows ::end");
|
||||||
|
|
||||||
@@ -720,8 +731,8 @@ void opengl_renderer::Render_pass(rendermode const Mode)
|
|||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
glViewport(0, 0, m_shadowbuffersize, m_shadowbuffersize);
|
glViewport(0, 0, m_shadowbuffersize, m_shadowbuffersize);
|
||||||
m_cabshadows_fb->bind();
|
vp.cabshadows_fb->bind();
|
||||||
m_cabshadows_fb->clear(GL_DEPTH_BUFFER_BIT);
|
vp.cabshadows_fb->clear(GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
setup_matrices();
|
setup_matrices();
|
||||||
setup_drawing(false);
|
setup_drawing(false);
|
||||||
@@ -735,7 +746,7 @@ void opengl_renderer::Render_pass(rendermode const Mode)
|
|||||||
|
|
||||||
glDisable(GL_POLYGON_OFFSET_FILL);
|
glDisable(GL_POLYGON_OFFSET_FILL);
|
||||||
|
|
||||||
m_cabshadows_fb->unbind();
|
vp.cabshadows_fb->unbind();
|
||||||
|
|
||||||
glDebug("rendermode::cabshadows end");
|
glDebug("rendermode::cabshadows end");
|
||||||
|
|
||||||
@@ -752,8 +763,8 @@ void opengl_renderer::Render_pass(rendermode const Mode)
|
|||||||
// NOTE: buffer attachment and viewport setup in this mode is handled by the wrapper method
|
// NOTE: buffer attachment and viewport setup in this mode is handled by the wrapper method
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||||
m_env_fb->clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
vp.env_fb->clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
m_env_fb->bind();
|
vp.env_fb->bind();
|
||||||
|
|
||||||
setup_env_map(m_empty_cubemap.get());
|
setup_env_map(m_empty_cubemap.get());
|
||||||
|
|
||||||
@@ -769,13 +780,13 @@ void opengl_renderer::Render_pass(rendermode const Mode)
|
|||||||
|
|
||||||
// opaque parts...
|
// opaque parts...
|
||||||
setup_drawing(false);
|
setup_drawing(false);
|
||||||
setup_shadow_map(m_shadow_tex.get(), m_shadowpass);
|
setup_shadow_map(vp.shadow_tex.get(), m_shadowpass);
|
||||||
|
|
||||||
scene_ubs.projection = OpenGLMatrices.data(GL_PROJECTION);
|
scene_ubs.projection = OpenGLMatrices.data(GL_PROJECTION);
|
||||||
scene_ubo->update(scene_ubs);
|
scene_ubo->update(scene_ubs);
|
||||||
Render(simulation::Region);
|
Render(simulation::Region);
|
||||||
|
|
||||||
m_env_fb->unbind();
|
vp.env_fb->unbind();
|
||||||
|
|
||||||
glDebug("rendermode::reflections end");
|
glDebug("rendermode::reflections end");
|
||||||
|
|
||||||
@@ -840,7 +851,7 @@ void opengl_renderer::Render_pass(rendermode const Mode)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// creates dynamic environment cubemap
|
// creates dynamic environment cubemap
|
||||||
bool opengl_renderer::Render_reflections()
|
bool opengl_renderer::Render_reflections(viewport_data &vp)
|
||||||
{
|
{
|
||||||
if (Global.ReflectionUpdatesPerSecond == 0)
|
if (Global.ReflectionUpdatesPerSecond == 0)
|
||||||
return false;
|
return false;
|
||||||
@@ -849,23 +860,23 @@ bool opengl_renderer::Render_reflections()
|
|||||||
auto const timestamp = time.wMilliseconds + time.wSecond * 1000 + time.wMinute * 1000 * 60 + time.wHour * 1000 * 60 * 60;
|
auto const timestamp = time.wMilliseconds + time.wSecond * 1000 + time.wMinute * 1000 * 60 + time.wHour * 1000 * 60 * 60;
|
||||||
|
|
||||||
if ((timestamp - m_environmentupdatetime < Global.ReflectionUpdatesPerSecond)
|
if ((timestamp - m_environmentupdatetime < Global.ReflectionUpdatesPerSecond)
|
||||||
&& (glm::length(m_renderpass.camera.position() - m_environmentupdatelocation) < 1000.0))
|
&& (glm::length(m_renderpass.pass_camera.position() - m_environmentupdatelocation) < 1000.0))
|
||||||
{
|
{
|
||||||
// run update every 5+ mins of simulation time, or at least 1km from the last location
|
// run update every 5+ mins of simulation time, or at least 1km from the last location
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
m_environmentupdatetime = timestamp;
|
m_environmentupdatetime = timestamp;
|
||||||
m_environmentupdatelocation = m_renderpass.camera.position();
|
m_environmentupdatelocation = m_renderpass.pass_camera.position();
|
||||||
|
|
||||||
glViewport(0, 0, gl::ENVMAP_SIZE, gl::ENVMAP_SIZE);
|
glViewport(0, 0, gl::ENVMAP_SIZE, gl::ENVMAP_SIZE);
|
||||||
for (m_environmentcubetextureface = 0; m_environmentcubetextureface < 6; ++m_environmentcubetextureface)
|
for (m_environmentcubetextureface = 0; m_environmentcubetextureface < 6; ++m_environmentcubetextureface)
|
||||||
{
|
{
|
||||||
m_env_fb->attach(*m_env_tex, m_environmentcubetextureface, GL_COLOR_ATTACHMENT0);
|
vp.env_fb->attach(*vp.env_tex, m_environmentcubetextureface, GL_COLOR_ATTACHMENT0);
|
||||||
if (m_env_fb->is_complete())
|
if (vp.env_fb->is_complete())
|
||||||
Render_pass(rendermode::reflections);
|
Render_pass(vp, rendermode::reflections);
|
||||||
}
|
}
|
||||||
m_env_tex->generate_mipmaps();
|
vp.env_tex->generate_mipmaps();
|
||||||
m_env_fb->detach(GL_COLOR_ATTACHMENT0);
|
vp.env_fb->detach(GL_COLOR_ATTACHMENT0);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -981,7 +992,7 @@ void opengl_renderer::setup_pass(renderpass_config &Config, rendermode const Mod
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// setup camera
|
// setup camera
|
||||||
auto &camera = Config.camera;
|
auto &camera = Config.pass_camera;
|
||||||
|
|
||||||
glm::dmat4 viewmatrix(1.0);
|
glm::dmat4 viewmatrix(1.0);
|
||||||
|
|
||||||
@@ -1020,7 +1031,7 @@ void opengl_renderer::setup_pass(renderpass_config &Config, rendermode const Mod
|
|||||||
auto const zfar = std::min(1.f, Global.shadowtune.depth / (Global.BaseDrawRange * Global.fDistanceFactor) * std::max(1.f, Global.ZoomFactor * 0.5f));
|
auto const zfar = std::min(1.f, Global.shadowtune.depth / (Global.BaseDrawRange * Global.fDistanceFactor) * std::max(1.f, Global.ZoomFactor * 0.5f));
|
||||||
renderpass_config worldview;
|
renderpass_config worldview;
|
||||||
setup_pass(worldview, rendermode::color, 0.f, zfar, true);
|
setup_pass(worldview, rendermode::color, 0.f, zfar, true);
|
||||||
auto &frustumchunkshapepoints = worldview.camera.frustum_points();
|
auto &frustumchunkshapepoints = worldview.pass_camera.frustum_points();
|
||||||
// ...modelview matrix: determine the centre of frustum chunk in world space...
|
// ...modelview matrix: determine the centre of frustum chunk in world space...
|
||||||
glm::vec3 frustumchunkmin, frustumchunkmax;
|
glm::vec3 frustumchunkmin, frustumchunkmax;
|
||||||
bounding_box(frustumchunkmin, frustumchunkmax, std::begin(frustumchunkshapepoints), std::end(frustumchunkshapepoints));
|
bounding_box(frustumchunkmin, frustumchunkmax, std::begin(frustumchunkshapepoints), std::end(frustumchunkshapepoints));
|
||||||
@@ -1028,7 +1039,7 @@ void opengl_renderer::setup_pass(renderpass_config &Config, rendermode const Mod
|
|||||||
// ...cap the vertical angle to keep shadows from getting too long...
|
// ...cap the vertical angle to keep shadows from getting too long...
|
||||||
auto const lightvector = glm::normalize(glm::vec3{m_sunlight.direction.x, std::min(m_sunlight.direction.y, -0.2f), m_sunlight.direction.z});
|
auto const lightvector = glm::normalize(glm::vec3{m_sunlight.direction.x, std::min(m_sunlight.direction.y, -0.2f), m_sunlight.direction.z});
|
||||||
// ...place the light source at the calculated centre and setup world space light view matrix...
|
// ...place the light source at the calculated centre and setup world space light view matrix...
|
||||||
camera.position() = worldview.camera.position() + glm::dvec3{frustumchunkcentre};
|
camera.position() = worldview.pass_camera.position() + glm::dvec3{frustumchunkcentre};
|
||||||
viewmatrix *= glm::lookAt(camera.position(), camera.position() + glm::dvec3{lightvector}, glm::dvec3{0.f, 1.f, 0.f});
|
viewmatrix *= glm::lookAt(camera.position(), camera.position() + glm::dvec3{lightvector}, glm::dvec3{0.f, 1.f, 0.f});
|
||||||
// ...projection matrix: calculate boundaries of the frustum chunk in light space...
|
// ...projection matrix: calculate boundaries of the frustum chunk in light space...
|
||||||
auto const lightviewmatrix = glm::translate(glm::mat4{glm::mat3{viewmatrix}}, -frustumchunkcentre);
|
auto const lightviewmatrix = glm::translate(glm::mat4{glm::mat3{viewmatrix}}, -frustumchunkcentre);
|
||||||
@@ -1136,11 +1147,11 @@ void opengl_renderer::setup_pass(renderpass_config &Config, rendermode const Mod
|
|||||||
void opengl_renderer::setup_matrices()
|
void opengl_renderer::setup_matrices()
|
||||||
{
|
{
|
||||||
::glMatrixMode(GL_PROJECTION);
|
::glMatrixMode(GL_PROJECTION);
|
||||||
OpenGLMatrices.load_matrix(m_renderpass.camera.projection());
|
OpenGLMatrices.load_matrix(m_renderpass.pass_camera.projection());
|
||||||
|
|
||||||
// trim modelview matrix just to rotation, since rendering is done in camera-centric world space
|
// trim modelview matrix just to rotation, since rendering is done in camera-centric world space
|
||||||
::glMatrixMode(GL_MODELVIEW);
|
::glMatrixMode(GL_MODELVIEW);
|
||||||
OpenGLMatrices.load_matrix(glm::mat4(glm::mat3(m_renderpass.camera.modelview())));
|
OpenGLMatrices.load_matrix(glm::mat4(glm::mat3(m_renderpass.pass_camera.modelview())));
|
||||||
}
|
}
|
||||||
|
|
||||||
void opengl_renderer::setup_drawing(bool const Alpha)
|
void opengl_renderer::setup_drawing(bool const Alpha)
|
||||||
@@ -1213,9 +1224,9 @@ void opengl_renderer::setup_shadow_map(opengl_texture *tex, renderpass_config co
|
|||||||
0.0, 0.0, 0.5, 0.0, //
|
0.0, 0.0, 0.5, 0.0, //
|
||||||
0.5, 0.5, 0.5, 1.0 //
|
0.5, 0.5, 0.5, 1.0 //
|
||||||
);
|
);
|
||||||
glm::mat4 depthproj = conf.camera.projection();
|
glm::mat4 depthproj = conf.pass_camera.projection();
|
||||||
glm::mat4 depthcam = conf.camera.modelview();
|
glm::mat4 depthcam = conf.pass_camera.modelview();
|
||||||
glm::mat4 worldcam = m_renderpass.camera.modelview();
|
glm::mat4 worldcam = m_renderpass.pass_camera.modelview();
|
||||||
|
|
||||||
scene_ubs.lightview = coordmove * depthproj * depthcam * glm::inverse(worldcam);
|
scene_ubs.lightview = coordmove * depthproj * depthcam * glm::inverse(worldcam);
|
||||||
scene_ubo->update(scene_ubs);
|
scene_ubo->update(scene_ubs);
|
||||||
@@ -1626,13 +1637,18 @@ opengl_texture &opengl_renderer::Texture(texture_handle const Texture) const
|
|||||||
return m_textures.texture(Texture);
|
return m_textures.texture(Texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void opengl_renderer::Update_AnimModel(TAnimModel *model)
|
||||||
|
{
|
||||||
|
model->RaAnimate(m_framestamp);
|
||||||
|
}
|
||||||
|
|
||||||
void opengl_renderer::Render(scene::basic_region *Region)
|
void opengl_renderer::Render(scene::basic_region *Region)
|
||||||
{
|
{
|
||||||
|
|
||||||
m_sectionqueue.clear();
|
m_sectionqueue.clear();
|
||||||
m_cellqueue.clear();
|
m_cellqueue.clear();
|
||||||
// build a list of region sections to render
|
// build a list of region sections to render
|
||||||
glm::vec3 const cameraposition{m_renderpass.camera.position()};
|
glm::vec3 const cameraposition{m_renderpass.pass_camera.position()};
|
||||||
auto const camerax = static_cast<int>(std::floor(cameraposition.x / scene::EU07_SECTIONSIZE + scene::EU07_REGIONSIDESECTIONCOUNT / 2));
|
auto const camerax = static_cast<int>(std::floor(cameraposition.x / scene::EU07_SECTIONSIZE + scene::EU07_REGIONSIDESECTIONCOUNT / 2));
|
||||||
auto const cameraz = static_cast<int>(std::floor(cameraposition.z / scene::EU07_SECTIONSIZE + scene::EU07_REGIONSIDESECTIONCOUNT / 2));
|
auto const cameraz = static_cast<int>(std::floor(cameraposition.z / scene::EU07_SECTIONSIZE + scene::EU07_REGIONSIDESECTIONCOUNT / 2));
|
||||||
int const segmentcount = 2 * static_cast<int>(std::ceil(m_renderpass.draw_range * Global.fDistanceFactor / scene::EU07_SECTIONSIZE));
|
int const segmentcount = 2 * static_cast<int>(std::ceil(m_renderpass.draw_range * Global.fDistanceFactor / scene::EU07_SECTIONSIZE));
|
||||||
@@ -1660,7 +1676,7 @@ void opengl_renderer::Render(scene::basic_region *Region)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
auto *section{Region->m_sections[row * scene::EU07_REGIONSIDESECTIONCOUNT + column]};
|
auto *section{Region->m_sections[row * scene::EU07_REGIONSIDESECTIONCOUNT + column]};
|
||||||
if ((section != nullptr) && (m_renderpass.camera.visible(section->m_area)))
|
if ((section != nullptr) && (m_renderpass.pass_camera.visible(section->m_area)))
|
||||||
{
|
{
|
||||||
m_sectionqueue.emplace_back(section);
|
m_sectionqueue.emplace_back(section);
|
||||||
}
|
}
|
||||||
@@ -1746,7 +1762,7 @@ void opengl_renderer::Render(section_sequence::iterator First, section_sequence:
|
|||||||
{
|
{
|
||||||
// since all shapes of the section share center point we can optimize out a few calls here
|
// since all shapes of the section share center point we can optimize out a few calls here
|
||||||
::glPushMatrix();
|
::glPushMatrix();
|
||||||
auto const originoffset{section->m_area.center - m_renderpass.camera.position()};
|
auto const originoffset{section->m_area.center - m_renderpass.pass_camera.position()};
|
||||||
::glTranslated(originoffset.x, originoffset.y, originoffset.z);
|
::glTranslated(originoffset.x, originoffset.y, originoffset.z);
|
||||||
// render
|
// render
|
||||||
for (auto const &shape : section->m_shapes)
|
for (auto const &shape : section->m_shapes)
|
||||||
@@ -1774,10 +1790,10 @@ void opengl_renderer::Render(section_sequence::iterator First, section_sequence:
|
|||||||
{
|
{
|
||||||
for (auto &cell : section->m_cells)
|
for (auto &cell : section->m_cells)
|
||||||
{
|
{
|
||||||
if ((true == cell.m_active) && (m_renderpass.camera.visible(cell.m_area)))
|
if ((true == cell.m_active) && (m_renderpass.pass_camera.visible(cell.m_area)))
|
||||||
{
|
{
|
||||||
// store visible cells with content as well as their current distance, for sorting later
|
// store visible cells with content as well as their current distance, for sorting later
|
||||||
m_cellqueue.emplace_back(glm::length2(m_renderpass.camera.position() - cell.m_area.center), &cell);
|
m_cellqueue.emplace_back(glm::length2(m_renderpass.pass_camera.position() - cell.m_area.center), &cell);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1825,7 +1841,7 @@ void opengl_renderer::Render(cell_sequence::iterator First, cell_sequence::itera
|
|||||||
{
|
{
|
||||||
// since all shapes of the section share center point we can optimize out a few calls here
|
// since all shapes of the section share center point we can optimize out a few calls here
|
||||||
::glPushMatrix();
|
::glPushMatrix();
|
||||||
auto const originoffset{cell->m_area.center - m_renderpass.camera.position()};
|
auto const originoffset{cell->m_area.center - m_renderpass.pass_camera.position()};
|
||||||
::glTranslated(originoffset.x, originoffset.y, originoffset.z);
|
::glTranslated(originoffset.x, originoffset.y, originoffset.z);
|
||||||
|
|
||||||
// render
|
// render
|
||||||
@@ -1846,7 +1862,7 @@ void opengl_renderer::Render(cell_sequence::iterator First, cell_sequence::itera
|
|||||||
{
|
{
|
||||||
// since all shapes of the section share center point we can optimize out a few calls here
|
// since all shapes of the section share center point we can optimize out a few calls here
|
||||||
::glPushMatrix();
|
::glPushMatrix();
|
||||||
auto const originoffset{cell->m_area.center - m_renderpass.camera.position()};
|
auto const originoffset{cell->m_area.center - m_renderpass.pass_camera.position()};
|
||||||
::glTranslated(originoffset.x, originoffset.y, originoffset.z);
|
::glTranslated(originoffset.x, originoffset.y, originoffset.z);
|
||||||
|
|
||||||
// render
|
// render
|
||||||
@@ -1866,7 +1882,7 @@ void opengl_renderer::Render(cell_sequence::iterator First, cell_sequence::itera
|
|||||||
// same procedure like with regular render, but editor-enabled nodes receive custom colour used for picking
|
// same procedure like with regular render, but editor-enabled nodes receive custom colour used for picking
|
||||||
// since all shapes of the section share center point we can optimize out a few calls here
|
// since all shapes of the section share center point we can optimize out a few calls here
|
||||||
::glPushMatrix();
|
::glPushMatrix();
|
||||||
auto const originoffset{cell->m_area.center - m_renderpass.camera.position()};
|
auto const originoffset{cell->m_area.center - m_renderpass.pass_camera.position()};
|
||||||
::glTranslated(originoffset.x, originoffset.y, originoffset.z);
|
::glTranslated(originoffset.x, originoffset.y, originoffset.z);
|
||||||
// render
|
// render
|
||||||
// opaque non-instanced shapes
|
// opaque non-instanced shapes
|
||||||
@@ -1987,7 +2003,7 @@ void opengl_renderer::Render(scene::shape_node const &Shape, bool const Ignorera
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
distancesquared = glm::length2((data.area.center - m_renderpass.camera.position()) / (double)Global.ZoomFactor) / Global.fDistanceFactor;
|
distancesquared = glm::length2((data.area.center - m_renderpass.pass_camera.position()) / (double)Global.ZoomFactor) / Global.fDistanceFactor;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2041,7 +2057,7 @@ void opengl_renderer::Render(TAnimModel *Instance)
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
distancesquared = Math3D::SquareMagnitude((Instance->location() - m_renderpass.camera.position()) / (double)Global.ZoomFactor) / Global.fDistanceFactor;
|
distancesquared = Math3D::SquareMagnitude((Instance->location() - m_renderpass.pass_camera.position()) / (double)Global.ZoomFactor) / Global.fDistanceFactor;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2069,7 +2085,7 @@ void opengl_renderer::Render(TAnimModel *Instance)
|
|||||||
if (Instance->pModel)
|
if (Instance->pModel)
|
||||||
{
|
{
|
||||||
// renderowanie rekurencyjne submodeli
|
// renderowanie rekurencyjne submodeli
|
||||||
Render(Instance->pModel, Instance->Material(), distancesquared, Instance->location() - m_renderpass.camera.position(), Instance->vAngle);
|
Render(Instance->pModel, Instance->Material(), distancesquared, Instance->location() - m_renderpass.pass_camera.position(), Instance->vAngle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2077,7 +2093,7 @@ bool opengl_renderer::Render(TDynamicObject *Dynamic)
|
|||||||
{
|
{
|
||||||
glDebug("Render TDynamicObject");
|
glDebug("Render TDynamicObject");
|
||||||
|
|
||||||
Dynamic->renderme = m_renderpass.camera.visible(Dynamic);
|
Dynamic->renderme = m_renderpass.pass_camera.visible(Dynamic);
|
||||||
if (false == Dynamic->renderme)
|
if (false == Dynamic->renderme)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -2087,7 +2103,7 @@ bool opengl_renderer::Render(TDynamicObject *Dynamic)
|
|||||||
|
|
||||||
// setup
|
// setup
|
||||||
TSubModel::iInstance = reinterpret_cast<std::uintptr_t>(Dynamic); //żeby nie robić cudzych animacji
|
TSubModel::iInstance = reinterpret_cast<std::uintptr_t>(Dynamic); //żeby nie robić cudzych animacji
|
||||||
glm::dvec3 const originoffset = Dynamic->vPosition - m_renderpass.camera.position();
|
glm::dvec3 const originoffset = Dynamic->vPosition - m_renderpass.pass_camera.position();
|
||||||
// lod visibility ranges are defined for base (x 1.0) viewing distance. for render we adjust them for actual range multiplier and zoom
|
// lod visibility ranges are defined for base (x 1.0) viewing distance. for render we adjust them for actual range multiplier and zoom
|
||||||
float squaredistance;
|
float squaredistance;
|
||||||
switch (m_renderpass.draw_mode)
|
switch (m_renderpass.draw_mode)
|
||||||
@@ -2208,7 +2224,7 @@ bool opengl_renderer::Render_cab(TDynamicObject const *Dynamic, float const Ligh
|
|||||||
// setup shared by all render paths
|
// setup shared by all render paths
|
||||||
::glPushMatrix();
|
::glPushMatrix();
|
||||||
|
|
||||||
auto const originoffset = Dynamic->GetPosition() - m_renderpass.camera.position();
|
auto const originoffset = Dynamic->GetPosition() - m_renderpass.pass_camera.position();
|
||||||
::glTranslated(originoffset.x, originoffset.y, originoffset.z);
|
::glTranslated(originoffset.x, originoffset.y, originoffset.z);
|
||||||
::glMultMatrixd(Dynamic->mMatrix.readArray());
|
::glMultMatrixd(Dynamic->mMatrix.readArray());
|
||||||
|
|
||||||
@@ -2805,7 +2821,7 @@ void opengl_renderer::Render(TMemCell *Memcell)
|
|||||||
{
|
{
|
||||||
|
|
||||||
::glPushMatrix();
|
::glPushMatrix();
|
||||||
auto const position = Memcell->location() - m_renderpass.camera.position();
|
auto const position = Memcell->location() - m_renderpass.pass_camera.position();
|
||||||
::glTranslated(position.x, position.y + 0.5, position.z);
|
::glTranslated(position.x, position.y + 0.5, position.z);
|
||||||
|
|
||||||
switch (m_renderpass.draw_mode)
|
switch (m_renderpass.draw_mode)
|
||||||
@@ -2912,7 +2928,7 @@ void opengl_renderer::Render_Alpha(cell_sequence::reverse_iterator First, cell_s
|
|||||||
{
|
{
|
||||||
// since all shapes of the cell share center point we can optimize out a few calls here
|
// since all shapes of the cell share center point we can optimize out a few calls here
|
||||||
::glPushMatrix();
|
::glPushMatrix();
|
||||||
auto const originoffset{cell->m_area.center - m_renderpass.camera.position()};
|
auto const originoffset{cell->m_area.center - m_renderpass.pass_camera.position()};
|
||||||
::glTranslated(originoffset.x, originoffset.y, originoffset.z);
|
::glTranslated(originoffset.x, originoffset.y, originoffset.z);
|
||||||
// render
|
// render
|
||||||
// NOTE: we can reuse the method used to draw opaque geometry
|
// NOTE: we can reuse the method used to draw opaque geometry
|
||||||
@@ -2965,7 +2981,7 @@ void opengl_renderer::Render_Alpha(cell_sequence::reverse_iterator First, cell_s
|
|||||||
{
|
{
|
||||||
// since all shapes of the cell share center point we can optimize out a few calls here
|
// since all shapes of the cell share center point we can optimize out a few calls here
|
||||||
::glPushMatrix();
|
::glPushMatrix();
|
||||||
auto const originoffset{cell->m_area.center - m_renderpass.camera.position()};
|
auto const originoffset{cell->m_area.center - m_renderpass.pass_camera.position()};
|
||||||
::glTranslated(originoffset.x, originoffset.y, originoffset.z);
|
::glTranslated(originoffset.x, originoffset.y, originoffset.z);
|
||||||
Bind_Material(null_handle);
|
Bind_Material(null_handle);
|
||||||
// render
|
// render
|
||||||
@@ -3000,7 +3016,7 @@ void opengl_renderer::Render_Alpha(TAnimModel *Instance)
|
|||||||
case rendermode::shadows:
|
case rendermode::shadows:
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
distancesquared = glm::length2((Instance->location() - m_renderpass.camera.position()) / (double)Global.ZoomFactor) / Global.fDistanceFactor;
|
distancesquared = glm::length2((Instance->location() - m_renderpass.pass_camera.position()) / (double)Global.ZoomFactor) / Global.fDistanceFactor;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3013,7 +3029,7 @@ void opengl_renderer::Render_Alpha(TAnimModel *Instance)
|
|||||||
if (Instance->pModel)
|
if (Instance->pModel)
|
||||||
{
|
{
|
||||||
// renderowanie rekurencyjne submodeli
|
// renderowanie rekurencyjne submodeli
|
||||||
Render_Alpha(Instance->pModel, Instance->Material(), distancesquared, Instance->location() - m_renderpass.camera.position(), Instance->vAngle);
|
Render_Alpha(Instance->pModel, Instance->Material(), distancesquared, Instance->location() - m_renderpass.pass_camera.position(), Instance->vAngle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3021,7 +3037,7 @@ void opengl_renderer::Render_Alpha(TTraction *Traction)
|
|||||||
{
|
{
|
||||||
glDebug("Render_Alpha TTraction");
|
glDebug("Render_Alpha TTraction");
|
||||||
|
|
||||||
auto const distancesquared { glm::length2( ( Traction->location() - m_renderpass.camera.position() ) / (double)Global.ZoomFactor ) / Global.fDistanceFactor };
|
auto const distancesquared { glm::length2( ( Traction->location() - m_renderpass.pass_camera.position() ) / (double)Global.ZoomFactor ) / Global.fDistanceFactor };
|
||||||
if ((distancesquared < Traction->m_rangesquaredmin) || (distancesquared >= Traction->m_rangesquaredmax))
|
if ((distancesquared < Traction->m_rangesquaredmin) || (distancesquared >= Traction->m_rangesquaredmax))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -3065,7 +3081,7 @@ void opengl_renderer::Render_Alpha(scene::lines_node const &Lines)
|
|||||||
|
|
||||||
auto const &data{Lines.data()};
|
auto const &data{Lines.data()};
|
||||||
|
|
||||||
auto const distancesquared { glm::length2( ( data.area.center - m_renderpass.camera.position() ) / (double)Global.ZoomFactor ) / Global.fDistanceFactor };
|
auto const distancesquared { glm::length2( ( data.area.center - m_renderpass.pass_camera.position() ) / (double)Global.ZoomFactor ) / Global.fDistanceFactor };
|
||||||
if ((distancesquared < data.rangesquared_min) || (distancesquared >= data.rangesquared_max))
|
if ((distancesquared < data.rangesquared_min) || (distancesquared >= data.rangesquared_max))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -3099,7 +3115,7 @@ bool opengl_renderer::Render_Alpha(TDynamicObject *Dynamic)
|
|||||||
|
|
||||||
// setup
|
// setup
|
||||||
TSubModel::iInstance = (size_t)Dynamic; //żeby nie robić cudzych animacji
|
TSubModel::iInstance = (size_t)Dynamic; //żeby nie robić cudzych animacji
|
||||||
glm::dvec3 const originoffset = Dynamic->vPosition - m_renderpass.camera.position();
|
glm::dvec3 const originoffset = Dynamic->vPosition - m_renderpass.pass_camera.position();
|
||||||
// lod visibility ranges are defined for base (x 1.0) viewing distance. for render we adjust them for actual range multiplier and zoom
|
// lod visibility ranges are defined for base (x 1.0) viewing distance. for render we adjust them for actual range multiplier and zoom
|
||||||
float squaredistance;
|
float squaredistance;
|
||||||
switch (m_renderpass.draw_mode)
|
switch (m_renderpass.draw_mode)
|
||||||
@@ -3414,7 +3430,7 @@ void opengl_renderer::Update_Pick_Control()
|
|||||||
pickbufferpos = glm::ivec2{mousepos.x * EU07_PICKBUFFERSIZE / std::max(1, Global.iWindowWidth), mousepos.y * EU07_PICKBUFFERSIZE / std::max(1, Global.iWindowHeight)};
|
pickbufferpos = glm::ivec2{mousepos.x * EU07_PICKBUFFERSIZE / std::max(1, Global.iWindowWidth), mousepos.y * EU07_PICKBUFFERSIZE / std::max(1, Global.iWindowHeight)};
|
||||||
pickbufferpos = glm::clamp(pickbufferpos, glm::ivec2(0, 0), glm::ivec2(EU07_PICKBUFFERSIZE - 1, EU07_PICKBUFFERSIZE - 1));
|
pickbufferpos = glm::clamp(pickbufferpos, glm::ivec2(0, 0), glm::ivec2(EU07_PICKBUFFERSIZE - 1, EU07_PICKBUFFERSIZE - 1));
|
||||||
|
|
||||||
Render_pass(rendermode::pickcontrols);
|
Render_pass(default_viewport, rendermode::pickcontrols);
|
||||||
m_pick_fb->bind();
|
m_pick_fb->bind();
|
||||||
m_picking_pbo->request_read(pickbufferpos.x, pickbufferpos.y, 1, 1);
|
m_picking_pbo->request_read(pickbufferpos.x, pickbufferpos.y, 1, 1);
|
||||||
m_pick_fb->unbind();
|
m_pick_fb->unbind();
|
||||||
@@ -3453,7 +3469,7 @@ void opengl_renderer::Update_Pick_Node()
|
|||||||
pickbufferpos = glm::ivec2{mousepos.x * EU07_PICKBUFFERSIZE / std::max(1, Global.iWindowWidth), mousepos.y * EU07_PICKBUFFERSIZE / std::max(1, Global.iWindowHeight)};
|
pickbufferpos = glm::ivec2{mousepos.x * EU07_PICKBUFFERSIZE / std::max(1, Global.iWindowWidth), mousepos.y * EU07_PICKBUFFERSIZE / std::max(1, Global.iWindowHeight)};
|
||||||
pickbufferpos = glm::clamp(pickbufferpos, glm::ivec2(0, 0), glm::ivec2(EU07_PICKBUFFERSIZE - 1, EU07_PICKBUFFERSIZE - 1));
|
pickbufferpos = glm::clamp(pickbufferpos, glm::ivec2(0, 0), glm::ivec2(EU07_PICKBUFFERSIZE - 1, EU07_PICKBUFFERSIZE - 1));
|
||||||
|
|
||||||
Render_pass(rendermode::pickscenery);
|
Render_pass(default_viewport, rendermode::pickscenery);
|
||||||
m_pick_fb->bind();
|
m_pick_fb->bind();
|
||||||
m_picking_node_pbo->request_read(pickbufferpos.x, pickbufferpos.y, 1, 1);
|
m_picking_node_pbo->request_read(pickbufferpos.x, pickbufferpos.y, 1, 1);
|
||||||
m_pick_fb->unbind();
|
m_pick_fb->unbind();
|
||||||
@@ -3503,11 +3519,11 @@ glm::dvec3 opengl_renderer::get_mouse_depth()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gl::framebuffer::blit(m_msaa_fb.get(), m_depth_pointer_fb.get(), bufferpos.x, bufferpos.y, 1, 1, GL_DEPTH_BUFFER_BIT, 0);
|
gl::framebuffer::blit(m_current_viewport->msaa_fb.get(), m_depth_pointer_fb.get(), bufferpos.x, bufferpos.y, 1, 1, GL_DEPTH_BUFFER_BIT, 0);
|
||||||
|
|
||||||
m_depth_pointer_fb->bind();
|
m_depth_pointer_fb->bind();
|
||||||
m_depth_pointer_pbo->request_read(0, 0, 1, 1, 4, GL_DEPTH_COMPONENT, GL_FLOAT);
|
m_depth_pointer_pbo->request_read(0, 0, 1, 1, 4, GL_DEPTH_COMPONENT, GL_FLOAT);
|
||||||
m_msaa_fb->bind();
|
m_current_viewport->msaa_fb->bind();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -3532,7 +3548,7 @@ glm::dvec3 opengl_renderer::get_mouse_depth()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gl::framebuffer::blit(m_msaa_fb.get(), m_depth_pointer_fb.get(), 0, 0, Global.gfx_framebuffer_width, Global.gfx_framebuffer_height, GL_DEPTH_BUFFER_BIT, 0);
|
gl::framebuffer::blit(m_current_viewport->msaa_fb.get(), m_depth_pointer_fb.get(), 0, 0, Global.gfx_framebuffer_width, Global.gfx_framebuffer_height, GL_DEPTH_BUFFER_BIT, 0);
|
||||||
|
|
||||||
m_empty_vao->bind();
|
m_empty_vao->bind();
|
||||||
m_depth_pointer_tex->bind(0);
|
m_depth_pointer_tex->bind(0);
|
||||||
@@ -3542,7 +3558,7 @@ glm::dvec3 opengl_renderer::get_mouse_depth()
|
|||||||
m_depth_pointer_pbo->request_read(bufferpos.x, bufferpos.y, 1, 1, 16, GL_RGBA_INTEGER, GL_UNSIGNED_INT);
|
m_depth_pointer_pbo->request_read(bufferpos.x, bufferpos.y, 1, 1, 16, GL_RGBA_INTEGER, GL_UNSIGNED_INT);
|
||||||
m_depth_pointer_shader->unbind();
|
m_depth_pointer_shader->unbind();
|
||||||
m_empty_vao->unbind();
|
m_empty_vao->unbind();
|
||||||
m_msaa_fb->bind();
|
m_current_viewport->msaa_fb->bind();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3550,15 +3566,15 @@ glm::dvec3 opengl_renderer::get_mouse_depth()
|
|||||||
{
|
{
|
||||||
if (GLAD_GL_ARB_clip_control || GLAD_GL_EXT_clip_control) {
|
if (GLAD_GL_ARB_clip_control || GLAD_GL_EXT_clip_control) {
|
||||||
if (pointdepth > 0.0f)
|
if (pointdepth > 0.0f)
|
||||||
m_worldmousecoordinates = glm::unProjectZO(glm::vec3(bufferpos, pointdepth), glm::mat4(glm::mat3(m_colorpass.camera.modelview())), m_colorpass.camera.projection(),
|
m_worldmousecoordinates = glm::unProjectZO(glm::vec3(bufferpos, pointdepth), glm::mat4(glm::mat3(m_colorpass.pass_camera.modelview())), m_colorpass.pass_camera.projection(),
|
||||||
glm::vec4(0, 0, Global.gfx_framebuffer_width, Global.gfx_framebuffer_height));
|
glm::vec4(0, 0, Global.gfx_framebuffer_width, Global.gfx_framebuffer_height));
|
||||||
} else if (pointdepth < 1.0f)
|
} else if (pointdepth < 1.0f)
|
||||||
m_worldmousecoordinates = glm::unProjectNO(glm::vec3(bufferpos, pointdepth), glm::mat4(glm::mat3(m_colorpass.camera.modelview())), m_colorpass.camera.projection(),
|
m_worldmousecoordinates = glm::unProjectNO(glm::vec3(bufferpos, pointdepth), glm::mat4(glm::mat3(m_colorpass.pass_camera.modelview())), m_colorpass.pass_camera.projection(),
|
||||||
glm::vec4(0, 0, Global.gfx_framebuffer_width, Global.gfx_framebuffer_height));
|
glm::vec4(0, 0, Global.gfx_framebuffer_width, Global.gfx_framebuffer_height));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return m_colorpass.camera.position() + glm::dvec3{m_worldmousecoordinates};
|
return m_colorpass.pass_camera.position() + glm::dvec3{m_worldmousecoordinates};
|
||||||
}
|
}
|
||||||
|
|
||||||
void opengl_renderer::Update(double const Deltatime)
|
void opengl_renderer::Update(double const Deltatime)
|
||||||
@@ -3659,7 +3675,7 @@ void opengl_renderer::Update_Lights(light_array &Lights)
|
|||||||
glDebug("Update_Lights");
|
glDebug("Update_Lights");
|
||||||
|
|
||||||
// arrange the light array from closest to farthest from current position of the camera
|
// arrange the light array from closest to farthest from current position of the camera
|
||||||
auto const camera = m_renderpass.camera.position();
|
auto const camera = m_renderpass.pass_camera.position();
|
||||||
std::sort(std::begin(Lights.data), std::end(Lights.data), [&camera](light_array::light_record const &Left, light_array::light_record const &Right) {
|
std::sort(std::begin(Lights.data), std::end(Lights.data), [&camera](light_array::light_record const &Left, light_array::light_record const &Right) {
|
||||||
// move lights which are off at the end...
|
// move lights which are off at the end...
|
||||||
if (Left.intensity == 0.f)
|
if (Left.intensity == 0.f)
|
||||||
|
|||||||
57
renderer.h
57
renderer.h
@@ -179,6 +179,7 @@ class opengl_renderer
|
|||||||
{
|
{
|
||||||
return m_worldmousecoordinates;
|
return m_worldmousecoordinates;
|
||||||
}
|
}
|
||||||
|
void Update_AnimModel(TAnimModel *model);
|
||||||
// maintenance methods
|
// maintenance methods
|
||||||
void Update(double const Deltatime);
|
void Update(double const Deltatime);
|
||||||
void Update_Pick_Control();
|
void Update_Pick_Control();
|
||||||
@@ -228,12 +229,36 @@ class opengl_renderer
|
|||||||
|
|
||||||
struct renderpass_config
|
struct renderpass_config
|
||||||
{
|
{
|
||||||
|
opengl_camera pass_camera;
|
||||||
opengl_camera camera;
|
opengl_camera viewport_camera;
|
||||||
rendermode draw_mode{rendermode::none};
|
rendermode draw_mode{rendermode::none};
|
||||||
float draw_range{0.0f};
|
float draw_range{0.0f};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct viewport_data {
|
||||||
|
std::unique_ptr<gl::framebuffer> msaa_fb;
|
||||||
|
std::unique_ptr<gl::renderbuffer> msaa_rbc;
|
||||||
|
std::unique_ptr<gl::renderbuffer> msaa_rbv;
|
||||||
|
std::unique_ptr<gl::renderbuffer> msaa_rbd;
|
||||||
|
|
||||||
|
std::unique_ptr<gl::framebuffer> main_fb;
|
||||||
|
std::unique_ptr<opengl_texture> main_texv;
|
||||||
|
std::unique_ptr<opengl_texture> main_tex;
|
||||||
|
|
||||||
|
std::unique_ptr<gl::framebuffer> main2_fb;
|
||||||
|
std::unique_ptr<opengl_texture> main2_tex;
|
||||||
|
|
||||||
|
std::unique_ptr<gl::framebuffer> shadow_fb;
|
||||||
|
std::unique_ptr<opengl_texture> shadow_tex;
|
||||||
|
|
||||||
|
std::unique_ptr<gl::framebuffer> cabshadows_fb;
|
||||||
|
std::unique_ptr<opengl_texture> cabshadows_tex;
|
||||||
|
|
||||||
|
std::unique_ptr<gl::framebuffer> env_fb;
|
||||||
|
std::unique_ptr<gl::renderbuffer> env_rb;
|
||||||
|
std::unique_ptr<gl::cubemap> env_tex;
|
||||||
|
};
|
||||||
|
|
||||||
typedef std::vector<opengl_light> opengllight_array;
|
typedef std::vector<opengl_light> opengllight_array;
|
||||||
|
|
||||||
// methods
|
// methods
|
||||||
@@ -246,9 +271,9 @@ class opengl_renderer
|
|||||||
void setup_env_map(gl::cubemap *tex);
|
void setup_env_map(gl::cubemap *tex);
|
||||||
void setup_environment_light(TEnvironmentType const Environment = e_flat);
|
void setup_environment_light(TEnvironmentType const Environment = e_flat);
|
||||||
// runs jobs needed to generate graphics for specified render pass
|
// runs jobs needed to generate graphics for specified render pass
|
||||||
void Render_pass(rendermode const Mode);
|
void Render_pass(viewport_data &vp, rendermode const Mode);
|
||||||
// creates dynamic environment cubemap
|
// creates dynamic environment cubemap
|
||||||
bool Render_reflections();
|
bool Render_reflections(viewport_data &vp);
|
||||||
bool Render(world_environment *Environment);
|
bool Render(world_environment *Environment);
|
||||||
void Render(scene::basic_region *Region);
|
void Render(scene::basic_region *Region);
|
||||||
void Render(section_sequence::iterator First, section_sequence::iterator Last);
|
void Render(section_sequence::iterator First, section_sequence::iterator Last);
|
||||||
@@ -277,6 +302,8 @@ class opengl_renderer
|
|||||||
glm::vec3 pick_color(std::size_t const Index);
|
glm::vec3 pick_color(std::size_t const Index);
|
||||||
std::size_t pick_index(glm::ivec3 const &Color);
|
std::size_t pick_index(glm::ivec3 const &Color);
|
||||||
|
|
||||||
|
bool init_viewport(viewport_data &vp);
|
||||||
|
|
||||||
void draw(const gfx::geometry_handle &handle);
|
void draw(const gfx::geometry_handle &handle);
|
||||||
void draw(std::vector<gfx::geometrybank_handle>::iterator begin, std::vector<gfx::geometrybank_handle>::iterator end);
|
void draw(std::vector<gfx::geometrybank_handle>::iterator begin, std::vector<gfx::geometrybank_handle>::iterator end);
|
||||||
|
|
||||||
@@ -323,6 +350,7 @@ class opengl_renderer
|
|||||||
float m_fogrange = 2000.0f;
|
float m_fogrange = 2000.0f;
|
||||||
|
|
||||||
renderpass_config m_renderpass; // parameters for current render pass
|
renderpass_config m_renderpass; // parameters for current render pass
|
||||||
|
viewport_data *m_current_viewport; // active viewport
|
||||||
section_sequence m_sectionqueue; // list of sections in current render pass
|
section_sequence m_sectionqueue; // list of sections in current render pass
|
||||||
cell_sequence m_cellqueue;
|
cell_sequence m_cellqueue;
|
||||||
renderpass_config m_colorpass; // parametrs of most recent color pass
|
renderpass_config m_colorpass; // parametrs of most recent color pass
|
||||||
@@ -367,23 +395,11 @@ class opengl_renderer
|
|||||||
|
|
||||||
std::unique_ptr<gl::vao> m_empty_vao;
|
std::unique_ptr<gl::vao> m_empty_vao;
|
||||||
|
|
||||||
std::unique_ptr<gl::framebuffer> m_msaa_fb;
|
viewport_data default_viewport;
|
||||||
std::unique_ptr<gl::renderbuffer> m_msaa_rbc;
|
|
||||||
std::unique_ptr<gl::renderbuffer> m_msaa_rbv;
|
|
||||||
std::unique_ptr<gl::renderbuffer> m_msaa_rbd;
|
|
||||||
|
|
||||||
std::unique_ptr<gl::framebuffer> m_main_fb;
|
|
||||||
std::unique_ptr<opengl_texture> m_main_texv;
|
|
||||||
std::unique_ptr<opengl_texture> m_main_tex;
|
|
||||||
|
|
||||||
std::unique_ptr<gl::framebuffer> m_main2_fb;
|
|
||||||
std::unique_ptr<opengl_texture> m_main2_tex;
|
|
||||||
|
|
||||||
std::unique_ptr<gl::postfx> m_pfx_motionblur;
|
std::unique_ptr<gl::postfx> m_pfx_motionblur;
|
||||||
std::unique_ptr<gl::postfx> m_pfx_tonemapping;
|
std::unique_ptr<gl::postfx> m_pfx_tonemapping;
|
||||||
|
|
||||||
std::unique_ptr<gl::framebuffer> m_shadow_fb;
|
|
||||||
std::unique_ptr<opengl_texture> m_shadow_tex;
|
|
||||||
std::unique_ptr<gl::program> m_shadow_shader;
|
std::unique_ptr<gl::program> m_shadow_shader;
|
||||||
std::unique_ptr<gl::program> m_alpha_shadow_shader;
|
std::unique_ptr<gl::program> m_alpha_shadow_shader;
|
||||||
|
|
||||||
@@ -392,13 +408,6 @@ class opengl_renderer
|
|||||||
std::unique_ptr<gl::renderbuffer> m_pick_rb;
|
std::unique_ptr<gl::renderbuffer> m_pick_rb;
|
||||||
std::unique_ptr<gl::program> m_pick_shader;
|
std::unique_ptr<gl::program> m_pick_shader;
|
||||||
|
|
||||||
std::unique_ptr<gl::framebuffer> m_cabshadows_fb;
|
|
||||||
std::unique_ptr<opengl_texture> m_cabshadows_tex;
|
|
||||||
|
|
||||||
std::unique_ptr<gl::framebuffer> m_env_fb;
|
|
||||||
std::unique_ptr<gl::renderbuffer> m_env_rb;
|
|
||||||
std::unique_ptr<gl::cubemap> m_env_tex;
|
|
||||||
|
|
||||||
std::unique_ptr<gl::cubemap> m_empty_cubemap;
|
std::unique_ptr<gl::cubemap> m_empty_cubemap;
|
||||||
|
|
||||||
std::unique_ptr<gl::pbo> m_picking_pbo;
|
std::unique_ptr<gl::pbo> m_picking_pbo;
|
||||||
|
|||||||
27
scene.cpp
27
scene.cpp
@@ -624,6 +624,24 @@ void basic_cell::get_map_active_switches(std::vector<gfx::geometrybank_handle> &
|
|||||||
path->get_map_active_switches(handles);
|
path->get_map_active_switches(handles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TTrack* basic_cell::find_nearest_track_point(const glm::dvec3 &pos)
|
||||||
|
{
|
||||||
|
float min = std::numeric_limits<float>::max();
|
||||||
|
TTrack *nearest = nullptr;
|
||||||
|
|
||||||
|
for (auto *path : m_paths) {
|
||||||
|
for (auto &ep : path->endpoints()) {
|
||||||
|
float dist2 = glm::distance2(ep, pos);
|
||||||
|
if (dist2 < min) {
|
||||||
|
min = dist2;
|
||||||
|
nearest = path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nearest;
|
||||||
|
}
|
||||||
|
|
||||||
// executes event assigned to specified launcher
|
// executes event assigned to specified launcher
|
||||||
void
|
void
|
||||||
basic_cell::launch_event( TEventLauncher *Launcher, bool local_only ) {
|
basic_cell::launch_event( TEventLauncher *Launcher, bool local_only ) {
|
||||||
@@ -1671,12 +1689,13 @@ void basic_region::create_map_geometry()
|
|||||||
s->create_map_geometry(m_map_geometrybank);
|
s->create_map_geometry(m_map_geometrybank);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<gfx::basic_vertex> vertices;
|
std::vector<gfx::basic_vertex> poi_vertices;
|
||||||
for (const auto sem : map::Semaphores) {
|
for (const auto sem : map::Objects.entries) {
|
||||||
vertices.push_back(gfx::basic_vertex(sem->location, glm::vec3(), glm::vec3()));
|
poi_vertices.push_back(gfx::basic_vertex(sem->location, glm::vec3(), glm::vec3()));
|
||||||
}
|
}
|
||||||
|
|
||||||
gfx::geometrybank_handle poibank = GfxRenderer.Create_Bank();
|
gfx::geometrybank_handle poibank = GfxRenderer.Create_Bank();
|
||||||
m_map_poipoints = GfxRenderer.Insert(vertices, poibank, GL_POINTS);
|
m_map_poipoints = GfxRenderer.Insert(poi_vertices, poibank, GL_POINTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // scene
|
} // scene
|
||||||
|
|||||||
13
scene.h
13
scene.h
@@ -157,6 +157,7 @@ public:
|
|||||||
create_map_geometry(std::vector<gfx::basic_vertex> &Bank, const gfx::geometrybank_handle Extra);
|
create_map_geometry(std::vector<gfx::basic_vertex> &Bank, const gfx::geometrybank_handle Extra);
|
||||||
void
|
void
|
||||||
get_map_active_switches(std::vector<gfx::geometrybank_handle> &handles);
|
get_map_active_switches(std::vector<gfx::geometrybank_handle> &handles);
|
||||||
|
TTrack *find_nearest_track_point(const glm::dvec3 &pos);
|
||||||
// provides access to bounding area data
|
// provides access to bounding area data
|
||||||
bounding_area const &
|
bounding_area const &
|
||||||
area() const {
|
area() const {
|
||||||
@@ -289,9 +290,9 @@ public:
|
|||||||
area() const {
|
area() const {
|
||||||
return m_area; }
|
return m_area; }
|
||||||
const gfx::geometrybank_handle get_map_geometry()
|
const gfx::geometrybank_handle get_map_geometry()
|
||||||
{
|
{ return m_map_geometryhandle;}
|
||||||
return m_map_geometryhandle;
|
TTrack* find_nearest_track_point(const glm::dvec3 &pos)
|
||||||
}
|
{ return cell(pos).find_nearest_track_point(pos); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// types
|
// types
|
||||||
@@ -406,11 +407,11 @@ public:
|
|||||||
void
|
void
|
||||||
create_map_geometry();
|
create_map_geometry();
|
||||||
basic_section* get_section(size_t section)
|
basic_section* get_section(size_t section)
|
||||||
{
|
{ return m_sections[section]; }
|
||||||
return m_sections[section];
|
|
||||||
}
|
|
||||||
gfx::geometrybank_handle
|
gfx::geometrybank_handle
|
||||||
get_map_poi_geometry() { return m_map_poipoints; }
|
get_map_poi_geometry() { return m_map_poipoints; }
|
||||||
|
TTrack* find_nearest_track_point(const glm::dvec3 &pos)
|
||||||
|
{ return section(pos).find_nearest_track_point(pos); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// types
|
// types
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include "Event.h"
|
#include "Event.h"
|
||||||
#include "MemCell.h"
|
#include "MemCell.h"
|
||||||
|
|
||||||
|
#include "AnimModel.h"
|
||||||
#include "widgets/map_objects.h"
|
#include "widgets/map_objects.h"
|
||||||
|
|
||||||
namespace scene {
|
namespace scene {
|
||||||
@@ -32,29 +33,6 @@ node_groups::create() {
|
|||||||
scene::group_handle
|
scene::group_handle
|
||||||
node_groups::close()
|
node_groups::close()
|
||||||
{
|
{
|
||||||
if (!m_activegroup.empty()) {
|
|
||||||
for (basic_node *node : m_groupmap[m_activegroup.top()].nodes) {
|
|
||||||
std::string postfix { "sem_mem" };
|
|
||||||
|
|
||||||
if (typeid(TMemCell) == typeid(*node) && string_ends_with(node->name(), postfix)) {
|
|
||||||
std::string sem_name = node->name().substr(0, node->name().length() - postfix.length());
|
|
||||||
|
|
||||||
map::Semaphores.push_back(std::make_shared<map::semaphore>());
|
|
||||||
auto sem_info = map::Semaphores.back();
|
|
||||||
|
|
||||||
sem_info->location = node->location();
|
|
||||||
sem_info->name = sem_name;
|
|
||||||
|
|
||||||
for (basic_event *event : m_groupmap[m_activegroup.top()].events) {
|
|
||||||
if (string_starts_with(event->name(), sem_name)
|
|
||||||
&& event->name().substr(sem_name.length()).find("sem") == std::string::npos) {
|
|
||||||
sem_info->events.push_back(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if( false == m_activegroup.empty() ) {
|
if( false == m_activegroup.empty() ) {
|
||||||
|
|
||||||
auto const closinggroup { m_activegroup.top() };
|
auto const closinggroup { m_activegroup.top() };
|
||||||
@@ -75,6 +53,54 @@ node_groups::close()
|
|||||||
return handle();
|
return handle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
node_groups::update_map()
|
||||||
|
{
|
||||||
|
map::Objects.entries.clear();
|
||||||
|
|
||||||
|
for (auto const &pair : m_groupmap) {
|
||||||
|
auto const &group = pair.second;
|
||||||
|
|
||||||
|
for (basic_node *node : group.nodes) {
|
||||||
|
std::string postfix { "_sem_mem" };
|
||||||
|
|
||||||
|
if (typeid(*node) == typeid(TMemCell) && string_ends_with(node->name(), postfix)) {
|
||||||
|
std::string sem_name = node->name().substr(0, node->name().length() - postfix.length());
|
||||||
|
|
||||||
|
auto sem_info = std::make_shared<map::semaphore>();
|
||||||
|
map::Objects.entries.push_back(sem_info);
|
||||||
|
|
||||||
|
sem_info->location = node->location();
|
||||||
|
sem_info->name = sem_name;
|
||||||
|
|
||||||
|
for (basic_event *event : group.events) {
|
||||||
|
if (string_starts_with(event->name(), sem_name)
|
||||||
|
&& event->name().substr(sem_name.length()).find("sem") == std::string::npos) {
|
||||||
|
sem_info->events.push_back(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (basic_node *node : group.nodes)
|
||||||
|
if (auto *model = dynamic_cast<TAnimModel*>(node))
|
||||||
|
if (string_starts_with(model->name(), sem_name))
|
||||||
|
sem_info->models.push_back(model);
|
||||||
|
}
|
||||||
|
if (TEventLauncher *launcher = dynamic_cast<TEventLauncher*>(node)) {
|
||||||
|
if (!launcher || !launcher->Event1 || !launcher->Event2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto track_switch = std::make_shared<map::track_switch>();
|
||||||
|
map::Objects.entries.push_back(track_switch);
|
||||||
|
|
||||||
|
track_switch->location = node->location();
|
||||||
|
track_switch->name = node->name();
|
||||||
|
track_switch->straight_event = launcher->Event1;
|
||||||
|
track_switch->divert_event = launcher->Event2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// returns current active group, or null_handle if group stack is empty
|
// returns current active group, or null_handle if group stack is empty
|
||||||
group_handle
|
group_handle
|
||||||
node_groups::handle() const {
|
node_groups::handle() const {
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ public:
|
|||||||
// indicates creation of current group ended. returns: handle to the parent group or null_handle if group stack is empty
|
// indicates creation of current group ended. returns: handle to the parent group or null_handle if group stack is empty
|
||||||
group_handle
|
group_handle
|
||||||
close();
|
close();
|
||||||
|
// update minimap objects
|
||||||
|
void
|
||||||
|
update_map();
|
||||||
// returns current active group, or null_handle if group stack is empty
|
// returns current active group, or null_handle if group stack is empty
|
||||||
group_handle
|
group_handle
|
||||||
handle() const;
|
handle() const;
|
||||||
|
|||||||
@@ -134,6 +134,14 @@ void state_manager::process_commands() {
|
|||||||
Events.AddToQuery(ev, nullptr);
|
Events.AddToQuery(ev, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (commanddata.command == user_command::setlight) {
|
||||||
|
uint32_t id = commanddata.action;
|
||||||
|
int light = std::round(commanddata.param1);
|
||||||
|
float state = commanddata.param2;
|
||||||
|
if (id < simulation::Instances.sequence().size())
|
||||||
|
simulation::Instances.sequence()[id]->LightSet(light, state);
|
||||||
|
}
|
||||||
|
|
||||||
if (DebugModeFlag) {
|
if (DebugModeFlag) {
|
||||||
if (commanddata.command == user_command::timejump) {
|
if (commanddata.command == user_command::timejump) {
|
||||||
Time.update(commanddata.param1);
|
Time.update(commanddata.param1);
|
||||||
|
|||||||
@@ -116,6 +116,7 @@ state_serializer::deserialize_continue(std::shared_ptr<deserializer_state> state
|
|||||||
deserialize_firstinit( Input, Scratchpad );
|
deserialize_firstinit( Input, Scratchpad );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scene::Groups.update_map();
|
||||||
Region->create_map_geometry();
|
Region->create_map_geometry();
|
||||||
|
|
||||||
if( ( false == state->scratchpad.binary.terrain )
|
if( ( false == state->scratchpad.binary.terrain )
|
||||||
|
|||||||
@@ -79,6 +79,9 @@ init() {
|
|||||||
"Map",
|
"Map",
|
||||||
"Mode windows",
|
"Mode windows",
|
||||||
|
|
||||||
|
"Straight |",
|
||||||
|
"Divert /",
|
||||||
|
|
||||||
"master controller",
|
"master controller",
|
||||||
"second controller",
|
"second controller",
|
||||||
"shunt mode power",
|
"shunt mode power",
|
||||||
@@ -239,6 +242,9 @@ init() {
|
|||||||
u8"Mapa",
|
u8"Mapa",
|
||||||
u8"Okna trybu",
|
u8"Okna trybu",
|
||||||
|
|
||||||
|
u8"Prosto |",
|
||||||
|
u8"W bok /",
|
||||||
|
|
||||||
u8"nastawnik jazdy",
|
u8"nastawnik jazdy",
|
||||||
u8"nastawnik dodatkowy",
|
u8"nastawnik dodatkowy",
|
||||||
u8"sterowanie analogowe",
|
u8"sterowanie analogowe",
|
||||||
|
|||||||
@@ -68,6 +68,9 @@ enum string {
|
|||||||
ui_map,
|
ui_map,
|
||||||
ui_mode_windows,
|
ui_mode_windows,
|
||||||
|
|
||||||
|
map_straight,
|
||||||
|
map_divert,
|
||||||
|
|
||||||
cab_mainctrl,
|
cab_mainctrl,
|
||||||
cab_scndctrl,
|
cab_scndctrl,
|
||||||
cab_shuntmodepower,
|
cab_shuntmodepower,
|
||||||
|
|||||||
16
uilayer.cpp
16
uilayer.cpp
@@ -50,8 +50,15 @@ void ui_panel::render()
|
|||||||
ImGui::SetNextWindowSizeConstraints(ImVec2(size_min.x, size_min.y), ImVec2(size_max.x, size_max.y));
|
ImGui::SetNextWindowSizeConstraints(ImVec2(size_min.x, size_min.y), ImVec2(size_max.x, size_max.y));
|
||||||
|
|
||||||
auto const panelname{(title.empty() ? name : title) + "###" + name};
|
auto const panelname{(title.empty() ? name : title) + "###" + name};
|
||||||
if (true == ImGui::Begin(panelname.c_str(), &is_open, flags))
|
if (ImGui::Begin(panelname.c_str(), &is_open, flags)) {
|
||||||
render_contents();
|
render_contents();
|
||||||
|
|
||||||
|
popups.remove_if([](std::unique_ptr<ui::popup> &popup)
|
||||||
|
{
|
||||||
|
return popup->render();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,6 +70,11 @@ void ui_panel::render_contents()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ui_panel::register_popup(std::unique_ptr<ui::popup> &&popup)
|
||||||
|
{
|
||||||
|
popups.push_back(std::move(popup));
|
||||||
|
}
|
||||||
|
|
||||||
void ui_expandable_panel::render_contents()
|
void ui_expandable_panel::render_contents()
|
||||||
{
|
{
|
||||||
ImGui::Checkbox(LOC_STR(ui_expand), &is_expanded);
|
ImGui::Checkbox(LOC_STR(ui_expand), &is_expanded);
|
||||||
@@ -317,7 +329,7 @@ void ui_layer::render_panels()
|
|||||||
|
|
||||||
void ui_layer::render_tooltip()
|
void ui_layer::render_tooltip()
|
||||||
{
|
{
|
||||||
if (!m_cursorvisible || m_tooltip.empty())
|
if (!m_cursorvisible || m_imguiio->WantCaptureMouse || m_tooltip.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ImGui::BeginTooltip();
|
ImGui::BeginTooltip();
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ http://mozilla.org/MPL/2.0/.
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include "Texture.h"
|
#include "Texture.h"
|
||||||
#include "translation.h"
|
#include "translation.h"
|
||||||
|
#include "widgets/popup.h"
|
||||||
|
|
||||||
// GuiLayer -- basic user interface class. draws requested information on top of openGL screen
|
// GuiLayer -- basic user interface class. draws requested information on top of openGL screen
|
||||||
|
|
||||||
@@ -48,10 +49,12 @@ public:
|
|||||||
int window_flags = -1;
|
int window_flags = -1;
|
||||||
|
|
||||||
const std::string& get_name() { return name; }
|
const std::string& get_name() { return name; }
|
||||||
|
void register_popup(std::unique_ptr<ui::popup> &&popup);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// members
|
// members
|
||||||
std::string name;
|
std::string name;
|
||||||
|
std::list<std::unique_ptr<ui::popup>> popups;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ui_expandable_panel : public ui_panel {
|
class ui_expandable_panel : public ui_panel {
|
||||||
|
|||||||
218
widgets/map.cpp
218
widgets/map.cpp
@@ -7,6 +7,7 @@
|
|||||||
#include "Camera.h"
|
#include "Camera.h"
|
||||||
#include "simulation.h"
|
#include "simulation.h"
|
||||||
#include "Driver.h"
|
#include "Driver.h"
|
||||||
|
#include "AnimModel.h"
|
||||||
|
|
||||||
ui::map_panel::map_panel() : ui_panel(LOC_STR(ui_map), false)
|
ui::map_panel::map_panel() : ui_panel(LOC_STR(ui_map), false)
|
||||||
{
|
{
|
||||||
@@ -115,8 +116,8 @@ void ui::map_panel::render_map_texture(glm::mat4 transform, glm::vec2 surface_si
|
|||||||
scene_ubo->update(scene_ubs);
|
scene_ubo->update(scene_ubs);
|
||||||
GfxRenderer.Draw_Geometry(m_switch_handles.begin(), m_switch_handles.end());
|
GfxRenderer.Draw_Geometry(m_switch_handles.begin(), m_switch_handles.end());
|
||||||
|
|
||||||
glPointSize(3.0f);
|
glPointSize(5.0f);
|
||||||
scene_ubs.time = 0.0f;
|
scene_ubs.time = 1.0f;
|
||||||
scene_ubo->update(scene_ubs);
|
scene_ubo->update(scene_ubs);
|
||||||
GfxRenderer.Draw_Geometry(simulation::Region->get_map_poi_geometry());
|
GfxRenderer.Draw_Geometry(simulation::Region->get_map_poi_geometry());
|
||||||
|
|
||||||
@@ -153,21 +154,7 @@ void ui::map_panel::render_labels(glm::mat4 transform, ImVec2 origin, glm::vec2
|
|||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
|
|
||||||
if (zoom > 0.005f) {
|
if (zoom > 0.005f) {
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.7f, 1.0f, 1.0f, 0.7f));
|
|
||||||
for (auto sem : map::Semaphores) {
|
|
||||||
glm::vec4 ndc_pos = transform * glm::vec4(sem->location, 1.0f);
|
|
||||||
if (glm::abs(ndc_pos.x) > 1.0f || glm::abs(ndc_pos.z) > 1.0f)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
glm::vec2 gui_pos = (glm::vec2(ndc_pos.x, -ndc_pos.z) / 2.0f + 0.5f) * glm::vec2(surface_size.x, surface_size.y);
|
|
||||||
|
|
||||||
const char *desc = sem->name.c_str();
|
|
||||||
ImVec2 textsize = ImGui::CalcTextSize(desc);
|
|
||||||
ImGui::SetCursorPos(ImVec2(origin.x + gui_pos.x - textsize.x / 2.0f,
|
|
||||||
origin.y + gui_pos.y - textsize.y / 2.0f));
|
|
||||||
ImGui::TextUnformatted(desc);
|
|
||||||
}
|
|
||||||
ImGui::PopStyleColor();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,19 +163,6 @@ void ui::map_panel::render_contents()
|
|||||||
if (!init_done)
|
if (!init_done)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (active) {
|
|
||||||
if (ImGui::BeginPopup("Sem")) {
|
|
||||||
for (auto ev : active->events)
|
|
||||||
if (ImGui::Button(ev->name().c_str())) {
|
|
||||||
active.reset();
|
|
||||||
command_relay relay;
|
|
||||||
relay.post(user_command::queueevent, (double)simulation::Events.GetEventId(ev), 0.0, GLFW_PRESS, 0);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ImGui::EndPopup();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float prev_zoom = zoom;
|
float prev_zoom = zoom;
|
||||||
|
|
||||||
if (ImGui::Button("-"))
|
if (ImGui::Button("-"))
|
||||||
@@ -271,53 +245,169 @@ void ui::map_panel::render_contents()
|
|||||||
|
|
||||||
translate -= delta * 2.0f;
|
translate -= delta * 2.0f;
|
||||||
}
|
}
|
||||||
if (ImGui::IsMouseClicked(1)) {
|
else {
|
||||||
ImVec2 screen_pos = ImGui::GetMousePos();
|
ImVec2 screen_pos = ImGui::GetMousePos();
|
||||||
glm::vec2 surface_pos(screen_pos.x - screen_origin.x, screen_pos.y - screen_origin.y);
|
glm::vec2 surface_pos(screen_pos.x - screen_origin.x, screen_pos.y - screen_origin.y);
|
||||||
glm::vec2 ndc_pos = surface_pos / surface_size * 2.0f - 1.0f;
|
glm::vec2 ndc_pos = surface_pos / surface_size * 2.0f - 1.0f;
|
||||||
glm::vec3 world_pos = glm::inverse(transform) * glm::vec4(ndc_pos.x, 0.0f, -ndc_pos.y, 1.0f);
|
glm::vec3 world_pos = glm::inverse(transform) * glm::vec4(ndc_pos.x, 0.0f, -ndc_pos.y, 1.0f);
|
||||||
|
|
||||||
std::vector<TEventLauncher *> launchers = simulation::Events.find_eventlaunchers(glm::vec2(world_pos.x, world_pos.z), 10.0f);
|
map::sorted_object_list objects =
|
||||||
|
map::Objects.find_in_range(glm::vec3(world_pos.x, NAN, world_pos.z), 0.03f / zoom);
|
||||||
|
|
||||||
float distx = 1000000.0f;
|
if (ImGui::IsMouseClicked(1)) {
|
||||||
|
if (objects.size() > 1)
|
||||||
|
register_popup(std::make_unique<ui::disambiguation_popup>(*this, std::move(objects)));
|
||||||
|
else if (objects.size() == 1)
|
||||||
|
handle_map_object_click(*this, objects.begin()->second);
|
||||||
|
|
||||||
TEventLauncher *lau = nullptr;
|
TTrack *nearest = simulation::Region->find_nearest_track_point(world_pos);
|
||||||
for (auto launcher : launchers) {
|
if (nearest) {
|
||||||
float distance = glm::distance2(glm::vec2(launcher->location().x, launcher->location().z),
|
WriteLog(nearest->name());
|
||||||
glm::vec2(world_pos.x, world_pos.z));
|
|
||||||
if (distance < distx) {
|
|
||||||
lau = launcher;
|
|
||||||
distx = distance;
|
|
||||||
}
|
}
|
||||||
|
//scene::basic_section &clicked_section = simulation::Region->section(world_pos);
|
||||||
|
//clicked_section.
|
||||||
}
|
}
|
||||||
|
else if (!objects.empty()) {
|
||||||
if (lau) {
|
handle_map_object_hover(objects.begin()->second);
|
||||||
command_relay relay;
|
|
||||||
if (!Global.shiftState && lau->Event1)
|
|
||||||
relay.post(user_command::queueevent, (double)simulation::Events.GetEventId(lau->Event1), 0.0, GLFW_PRESS, 0);
|
|
||||||
else if (lau->Event2)
|
|
||||||
relay.post(user_command::queueevent, (double)simulation::Events.GetEventId(lau->Event2), 0.0, GLFW_PRESS, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::shared_ptr<map::semaphore>> list;
|
|
||||||
|
|
||||||
for (auto entry : map::Semaphores) {
|
|
||||||
float distance = glm::distance2(glm::vec2(entry->location.x, entry->location.z),
|
|
||||||
glm::vec2(world_pos.x, world_pos.z));
|
|
||||||
if (distance < 100.0f) {
|
|
||||||
if (distance < distx) {
|
|
||||||
list.clear();
|
|
||||||
list.push_back(entry);
|
|
||||||
distx = distance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!list.empty()) {
|
|
||||||
ImGui::OpenPopup("Sem");
|
|
||||||
active.emplace(*list[0].get());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
render_labels(transform, window_origin, surface_size);
|
render_labels(transform, window_origin, surface_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ui::handle_map_object_click(ui_panel &parent, std::shared_ptr<map::map_object> &obj)
|
||||||
|
{
|
||||||
|
if (auto sem = std::dynamic_pointer_cast<map::semaphore>(obj)) {
|
||||||
|
parent.register_popup(std::make_unique<semaphore_window>(parent, std::move(sem)));
|
||||||
|
}
|
||||||
|
else if (auto track = std::dynamic_pointer_cast<map::track_switch>(obj)) {
|
||||||
|
parent.register_popup(std::make_unique<switch_window>(parent, std::move(track)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ui::handle_map_object_hover(std::shared_ptr<map::map_object> &obj)
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
|
||||||
|
if (auto sem = std::dynamic_pointer_cast<map::semaphore>(obj)) {
|
||||||
|
for (auto &model : sem->models) {
|
||||||
|
ImGui::PushID(model);
|
||||||
|
ImGui::TextUnformatted(model->name().c_str());
|
||||||
|
|
||||||
|
for (int i = 0; i < iMaxNumLights; i++) {
|
||||||
|
GfxRenderer.Update_AnimModel(model); // update lamp opacities
|
||||||
|
auto state = model->LightGet(i);
|
||||||
|
if (!state)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
glm::vec3 current_color = std::get<2>(*state).value_or(glm::vec3(0.5f)) * std::get<1>(*state);
|
||||||
|
if (std::get<0>(*state) < 0.0f)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(current_color.x, current_color.y, current_color.z, 1.0f));
|
||||||
|
|
||||||
|
std::string res = " ##" + std::to_string(i);
|
||||||
|
ImGui::Button(res.c_str());
|
||||||
|
|
||||||
|
ImGui::PopStyleColor();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::PopID();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (auto sw = std::dynamic_pointer_cast<map::track_switch>(obj)) {
|
||||||
|
ImGui::TextUnformatted(sw->name.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
|
||||||
|
ui::disambiguation_popup::disambiguation_popup(ui_panel &panel, map::sorted_object_list &&list)
|
||||||
|
: popup(panel), m_list(list) { }
|
||||||
|
|
||||||
|
void ui::disambiguation_popup::render_content()
|
||||||
|
{
|
||||||
|
for (auto &item : m_list) {
|
||||||
|
if (ImGui::Button(item.second->name.c_str())) {
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
|
||||||
|
handle_map_object_click(m_parent, item.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ui::semaphore_window::semaphore_window(ui_panel &panel, std::shared_ptr<map::semaphore> &&sem)
|
||||||
|
: popup(panel), m_sem(sem) { }
|
||||||
|
|
||||||
|
void ui::semaphore_window::render_content()
|
||||||
|
{
|
||||||
|
for (auto &model : m_sem->models) {
|
||||||
|
ImGui::PushID(model);
|
||||||
|
ImGui::TextUnformatted(model->name().c_str());
|
||||||
|
|
||||||
|
for (int i = 0; i < iMaxNumLights; i++) {
|
||||||
|
GfxRenderer.Update_AnimModel(model); // update lamp opacities
|
||||||
|
auto state = model->LightGet(i);
|
||||||
|
if (!state)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
glm::vec3 lamp_color = std::get<2>(*state).value_or(glm::vec3(0.5f));
|
||||||
|
glm::vec3 current_color = lamp_color * std::get<1>(*state);
|
||||||
|
float level = std::get<0>(*state);
|
||||||
|
|
||||||
|
if (level < 0.0f)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(lamp_color.x, lamp_color.y, lamp_color.z, 1.0f));
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(current_color.x, current_color.y, current_color.z, 1.0f));
|
||||||
|
|
||||||
|
std::string res = " ##" + std::to_string(i);
|
||||||
|
if (ImGui::Button(res.c_str())) {
|
||||||
|
level += 1.0f;
|
||||||
|
if (level >= 3.0f)
|
||||||
|
level = 0.0f;
|
||||||
|
|
||||||
|
int id = simulation::Instances.find_id(model->name());
|
||||||
|
m_relay.post(user_command::setlight, (double)i, level, id, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::PopStyleColor(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::PopID();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Separator();
|
||||||
|
|
||||||
|
for (auto &item : m_sem->events) {
|
||||||
|
std::string displayname = item->name().substr(m_sem->name.size());
|
||||||
|
|
||||||
|
if (displayname.size() < 2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
displayname[1] = std::toupper(displayname[1]);
|
||||||
|
|
||||||
|
if (ImGui::Button(displayname.c_str())) {
|
||||||
|
m_relay.post(user_command::queueevent, (double)simulation::Events.GetEventId(item), 0.0, GLFW_PRESS, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ui::switch_window::switch_window(ui_panel &panel, std::shared_ptr<map::track_switch> &&sw)
|
||||||
|
: popup(panel), m_switch(sw) { }
|
||||||
|
|
||||||
|
void ui::switch_window::render_content()
|
||||||
|
{
|
||||||
|
ImGui::TextUnformatted(m_switch->name.c_str());
|
||||||
|
|
||||||
|
if (ImGui::Button(LOC_STR(map_straight))) {
|
||||||
|
m_relay.post(user_command::queueevent, (double)simulation::Events.GetEventId(m_switch->straight_event), 0.0, GLFW_PRESS, 0);
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::Button(LOC_STR(map_divert))) {
|
||||||
|
m_relay.post(user_command::queueevent, (double)simulation::Events.GetEventId(m_switch->divert_event), 0.0, GLFW_PRESS, 0);
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,18 +5,37 @@
|
|||||||
#include "Texture.h"
|
#include "Texture.h"
|
||||||
#include "uilayer.h"
|
#include "uilayer.h"
|
||||||
#include "widgets/map_objects.h"
|
#include "widgets/map_objects.h"
|
||||||
|
#include "widgets/popup.h"
|
||||||
|
|
||||||
namespace ui {
|
namespace ui {
|
||||||
|
|
||||||
class disambiguation_popup {
|
class disambiguation_popup : public popup {
|
||||||
std::string m_id;
|
map::sorted_object_list m_list;
|
||||||
std::vector<map::semaphore> m_list;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
disambiguation_popup(std::string &&id, std::vector<map::semaphore> &&list)
|
disambiguation_popup(ui_panel &panel, map::sorted_object_list &&list);
|
||||||
: m_id(id), m_list(list) {}
|
|
||||||
|
|
||||||
void render();
|
virtual void render_content() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class semaphore_window : public popup {
|
||||||
|
std::shared_ptr<map::semaphore> m_sem;
|
||||||
|
command_relay m_relay;
|
||||||
|
|
||||||
|
public:
|
||||||
|
semaphore_window(ui_panel &panel, std::shared_ptr<map::semaphore> &&sem);
|
||||||
|
|
||||||
|
virtual void render_content() override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class switch_window : public popup {
|
||||||
|
std::shared_ptr<map::track_switch> m_switch;
|
||||||
|
command_relay m_relay;
|
||||||
|
|
||||||
|
public:
|
||||||
|
switch_window(ui_panel &panel, std::shared_ptr<map::track_switch> &&sw);
|
||||||
|
|
||||||
|
virtual void render_content() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class map_panel : public ui_panel {
|
class map_panel : public ui_panel {
|
||||||
@@ -50,4 +69,6 @@ public:
|
|||||||
void render_contents() override;
|
void render_contents() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void handle_map_object_click(ui_panel &parent, std::shared_ptr<map::map_object> &obj);
|
||||||
|
void handle_map_object_hover(std::shared_ptr<map::map_object> &obj);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,27 @@
|
|||||||
#include "widgets/map_objects.h"
|
#include "widgets/map_objects.h"
|
||||||
|
|
||||||
std::vector<std::shared_ptr<map::semaphore>> map::Semaphores;
|
map::objects map::Objects;
|
||||||
std::vector<std::shared_ptr<map::track_switch>> map::Switches;
|
|
||||||
|
map::sorted_object_list map::objects::find_in_range(glm::vec3 from, float distance)
|
||||||
|
{
|
||||||
|
sorted_object_list items;
|
||||||
|
|
||||||
|
float max_distance2 = distance * distance;
|
||||||
|
|
||||||
|
for (auto const entry : entries) {
|
||||||
|
glm::vec3 entry_location = entry->location;
|
||||||
|
glm::vec3 search_point = from;
|
||||||
|
|
||||||
|
if (glm::isnan(from.y)) {
|
||||||
|
entry_location.y = 0.0f;
|
||||||
|
search_point.y = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
float dist = glm::distance2(entry_location, search_point);
|
||||||
|
if (dist < max_distance2) {
|
||||||
|
items.emplace(dist, std::move(entry));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,19 +6,35 @@
|
|||||||
|
|
||||||
namespace map {
|
namespace map {
|
||||||
|
|
||||||
// semaphore description (only for minimap purposes)
|
struct map_object {
|
||||||
struct semaphore {
|
|
||||||
std::string name;
|
std::string name;
|
||||||
glm::vec3 location;
|
glm::vec3 location;
|
||||||
|
|
||||||
|
virtual ~map_object() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
using object_list = std::vector<std::shared_ptr<map::map_object>>;
|
||||||
|
using sorted_object_list = std::map<float, std::shared_ptr<map::map_object>>;
|
||||||
|
|
||||||
|
// semaphore description (only for minimap purposes)
|
||||||
|
struct semaphore : public map_object {
|
||||||
|
std::vector<TAnimModel *> models;
|
||||||
|
|
||||||
std::vector<basic_event *> events;
|
std::vector<basic_event *> events;
|
||||||
};
|
};
|
||||||
|
|
||||||
// switch description (only for minimap purposes)
|
// switch description (only for minimap purposes)
|
||||||
struct track_switch {
|
struct track_switch : public map_object {
|
||||||
glm::vec3 location;
|
basic_event *straight_event = nullptr;
|
||||||
|
basic_event *divert_event = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern std::vector<std::shared_ptr<semaphore>> Semaphores;
|
struct objects {
|
||||||
extern std::vector<std::shared_ptr<track_switch>> Switches;
|
std::vector<std::shared_ptr<map_object>> entries;
|
||||||
|
|
||||||
|
// returns objects in range from vec3, NaN in Y ignores it
|
||||||
|
sorted_object_list find_in_range(glm::vec3 from, float distance);
|
||||||
|
};
|
||||||
|
|
||||||
|
extern objects Objects;
|
||||||
}
|
}
|
||||||
|
|||||||
29
widgets/popup.cpp
Normal file
29
widgets/popup.cpp
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#include "widgets/popup.h"
|
||||||
|
|
||||||
|
ui::popup::popup(ui_panel &panel)
|
||||||
|
: m_parent(panel)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ui::popup::~popup()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ui::popup::render()
|
||||||
|
{
|
||||||
|
if (!m_id.size()) {
|
||||||
|
m_id = "popup:" + std::to_string(id++);
|
||||||
|
ImGui::OpenPopup(m_id.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ImGui::BeginPopup(m_id.c_str()))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
render_content();
|
||||||
|
|
||||||
|
ImGui::EndPopup();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ui::popup::id = 0;
|
||||||
22
widgets/popup.h
Normal file
22
widgets/popup.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
class ui_panel;
|
||||||
|
|
||||||
|
namespace ui {
|
||||||
|
|
||||||
|
class popup {
|
||||||
|
std::string m_id;
|
||||||
|
static int id;
|
||||||
|
|
||||||
|
public:
|
||||||
|
popup(ui_panel &panel);
|
||||||
|
~popup();
|
||||||
|
|
||||||
|
bool render();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ui_panel &m_parent;
|
||||||
|
virtual void render_content() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user