Make heat display scale variable

No UI for it yet though.
This commit is contained in:
Tamás Bálint Misius
2025-04-16 08:36:56 +02:00
parent b1290d2803
commit 29e4e68041
8 changed files with 167 additions and 19 deletions

View File

@@ -13,6 +13,7 @@
#include "simulation/gravity/Gravity.h" #include "simulation/gravity/Gravity.h"
#include "simulation/orbitalparts.h" #include "simulation/orbitalparts.h"
#include <cmath> #include <cmath>
#include <algorithm>
void Renderer::RenderBackground() void Renderer::RenderBackground()
{ {
@@ -264,7 +265,7 @@ void Renderer::render_parts()
BlendPixel({ nx, ny }, 0x646464_rgb .WithAlpha(80)); BlendPixel({ nx, ny }, 0x646464_rgb .WithAlpha(80));
} }
} }
foundParticles = 0; stats.foundParticles = 0;
for(i = 0; i<=sim->parts.lastActiveIndex; i++) { for(i = 0; i<=sim->parts.lastActiveIndex; i++) {
if (sim->parts[i].type && sim->parts[i].type >= 0 && sim->parts[i].type < PT_NUM) { if (sim->parts[i].type && sim->parts[i].type >= 0 && sim->parts[i].type < PT_NUM) {
t = sim->parts[i].type; t = sim->parts[i].type;
@@ -360,10 +361,8 @@ void Renderer::render_parts()
//Alter colour based on display mode //Alter colour based on display mode
if(colorMode & COLOUR_HEAT) if(colorMode & COLOUR_HEAT)
{ {
constexpr float min_temp = MIN_TEMP;
constexpr float max_temp = MAX_TEMP;
firea = 255; firea = 255;
RGB color = heatTableAt(int((sim->parts[i].temp - min_temp) / (max_temp - min_temp) * 1024)); RGB color = heatTableAt(int((sim->parts[i].temp - stats.hdispLimitMin) / (stats.hdispLimitMax - stats.hdispLimitMin) * 1024));
firer = colr = color.Red; firer = colr = color.Red;
fireg = colg = color.Green; fireg = colg = color.Green;
fireb = colb = color.Blue; fireb = colb = color.Blue;
@@ -485,7 +484,7 @@ void Renderer::render_parts()
{ {
colr = firer = 255; colr = firer = 255;
colg = fireg = colb = fireb = 0; colg = fireg = colb = fireb = 0;
foundParticles++; stats.foundParticles++;
} }
else else
{ {
@@ -952,7 +951,7 @@ void Renderer::draw_air()
} }
else if (displayMode & DISPLAY_AIRH) else if (displayMode & DISPLAY_AIRH)
{ {
c = RGB::Unpack(HeatToColour(hv[y][x])); c = RGB::Unpack(HeatToColour(hv[y][x], stats.hdispLimitMin, stats.hdispLimitMax));
//c = RGB(clamp_flt(fabsf(vx[y][x]), 0.0f, 8.0f),//vx adds red //c = RGB(clamp_flt(fabsf(vx[y][x]), 0.0f, 8.0f),//vx adds red
// clamp_flt(hv[y][x], 0.0f, 1600.0f),//heat adds green // clamp_flt(hv[y][x], 0.0f, 1600.0f),//heat adds green
// clamp_flt(fabsf(vy[y][x]), 0.0f, 8.0f)).Pack();//vy adds blue // clamp_flt(fabsf(vy[y][x]), 0.0f, 8.0f)).Pack();//vy adds blue
@@ -1296,11 +1295,9 @@ void Renderer::render_fire()
} }
} }
int HeatToColour(float temp) int HeatToColour(float temp, float hdispLimitMin, float hdispLimitMax)
{ {
constexpr float min_temp = MIN_TEMP; RGB color = Renderer::heatTableAt(int((temp - hdispLimitMin) / (hdispLimitMax - hdispLimitMin) * 1024));
constexpr float max_temp = MAX_TEMP;
RGB color = Renderer::heatTableAt(int((temp - min_temp) / (max_temp - min_temp) * 1024));
color.Red = uint8_t(color.Red * 0.7f); color.Red = uint8_t(color.Red * 0.7f);
color.Green = uint8_t(color.Green * 0.7f); color.Green = uint8_t(color.Green * 0.7f);
color.Blue = uint8_t(color.Blue * 0.7f); color.Blue = uint8_t(color.Blue * 0.7f);
@@ -1376,6 +1373,62 @@ const std::vector<RenderPreset> Renderer::renderModePresets = {
}, },
}; };
void Renderer::AdjustHdispLimit()
{
stats.hdispLimitValid = false;
float autoHdispLimitMin = MAX_TEMP;
float autoHdispLimitMax = MIN_TEMP;
auto visit = [this, &autoHdispLimitMin, &autoHdispLimitMax](Vec2<int> point, float value) {
if (autoHdispLimitArea.Contains(point))
{
autoHdispLimitMin = std::min(autoHdispLimitMin, value);
autoHdispLimitMax = std::max(autoHdispLimitMax, value);
stats.hdispLimitValid = true;
}
};
if (std::holds_alternative<HdispLimitAuto>(wantHdispLimitMin) ||
std::holds_alternative<HdispLimitAuto>(wantHdispLimitMax))
{
auto &sd = SimulationData::CRef();
for (int i = 0; i <= sim->parts.lastActiveIndex; ++i)
{
auto t = sim->parts[i].type;
if (t > 0 && t < PT_NUM)
{
if (!sd.elements[t].HeatConduct)
{
continue;
}
auto nx = int(sim->parts[i].x + 0.5f);
auto ny = int(sim->parts[i].y + 0.5f);
visit({ nx, ny }, sim->parts[i].temp);
}
}
if (sim->aheat_enable && (displayMode & DISPLAY_AIR) && (displayMode & DISPLAY_AIRH))
{
auto *hv = sim->hv;
for (auto p : CELLS.OriginRect())
{
visit(p * CELL, hv[p.Y][p.X]);
}
}
}
stats.hdispLimitMin = autoHdispLimitMin;
stats.hdispLimitMax = autoHdispLimitMax;
if (auto *hdispLimitExplicit = std::get_if<HdispLimitExplicit>(&wantHdispLimitMin))
{
stats.hdispLimitMin = hdispLimitExplicit->value;
}
if (auto *hdispLimitExplicit = std::get_if<HdispLimitExplicit>(&wantHdispLimitMax))
{
stats.hdispLimitMax = hdispLimitExplicit->value;
}
if (std::isnan(stats.hdispLimitMin)) stats.hdispLimitMin = MIN_TEMP;
if (std::isnan(stats.hdispLimitMax)) stats.hdispLimitMax = MAX_TEMP;
stats.hdispLimitMax = std::clamp(stats.hdispLimitMax, MIN_TEMP, MAX_TEMP);
stats.hdispLimitMin = std::clamp(stats.hdispLimitMin, MIN_TEMP, stats.hdispLimitMax);
}
void Renderer::Clear() void Renderer::Clear()
{ {
if(displayMode & DISPLAY_PERS) if(displayMode & DISPLAY_PERS)
@@ -1386,6 +1439,7 @@ void Renderer::Clear()
{ {
std::fill_n(video.data(), WINDOWW * YRES, 0); std::fill_n(video.data(), WINDOWW * YRES, 0);
} }
AdjustHdispLimit();
} }
void Renderer::DrawBlob(Vec2<int> pos, RGB colour) void Renderer::DrawBlob(Vec2<int> pos, RGB colour)

View File

@@ -25,14 +25,14 @@ struct GraphicsFuncContext
Particle *pipeSubcallTpart; Particle *pipeSubcallTpart;
}; };
int HeatToColour(float temp); int HeatToColour(float temp, float hdispLimitMin, float hdispLimitMax);
class Renderer : private RendererSettings, public RasterDrawMethods<Renderer> class Renderer : private RendererSettings, public RasterDrawMethods<Renderer>
{ {
RendererFrame video; RendererFrame video;
std::array<pixel, WINDOW.X * RES.Y> persistentVideo; std::array<pixel, WINDOW.X * RES.Y> persistentVideo;
RendererFrame warpVideo; RendererFrame warpVideo;
int foundParticles = 0; RendererStats stats;
Rect<int> GetClipRect() const Rect<int> GetClipRect() const
{ {
@@ -59,6 +59,8 @@ class Renderer : private RendererSettings, public RasterDrawMethods<Renderer>
void draw_grav(); void draw_grav();
void draw_other(); void draw_other();
void AdjustHdispLimit();
public: public:
Renderer(); Renderer();
void ApplySettings(const RendererSettings &newSettings); void ApplySettings(const RendererSettings &newSettings);
@@ -73,9 +75,9 @@ public:
return video; return video;
} }
int GetFoundParticles() const RendererStats GetStats() const
{ {
return foundParticles; return stats;
} }
const RenderableSimulation *sim = nullptr; const RenderableSimulation *sim = nullptr;

View File

@@ -6,3 +6,11 @@
constexpr auto RendererFrameSize = Vec2<int>{ WINDOW.X, RES.Y }; constexpr auto RendererFrameSize = Vec2<int>{ WINDOW.X, RES.Y };
using RendererFrame = PlaneAdapter<std::array<pixel, WINDOW.X * RES.Y>, RendererFrameSize.X, RendererFrameSize.Y>; using RendererFrame = PlaneAdapter<std::array<pixel, WINDOW.X * RES.Y>, RendererFrameSize.X, RendererFrameSize.Y>;
struct RendererStats
{
int foundParticles = 0;
float hdispLimitMin = 0;
float hdispLimitMax = 0;
bool hdispLimitValid = false;
};

View File

@@ -1,9 +1,23 @@
#pragma once #pragma once
#include "gui/interface/Point.h" #include "gui/interface/Point.h"
#include "simulation/ElementGraphics.h" #include "simulation/ElementGraphics.h"
#include "simulation/ElementDefs.h"
#include "FindingElement.h" #include "FindingElement.h"
#include <cstdint> #include <cstdint>
#include <optional> #include <optional>
#include <variant>
struct HdispLimitExplicit
{
float value;
};
struct HdispLimitAuto
{
};
using HdispLimit = std::variant<
HdispLimitExplicit,
HdispLimitAuto
>;
struct RendererSettings struct RendererSettings
{ {
@@ -24,4 +38,7 @@ struct RendererSettings
ui::Point mousePos = { 0, 0 }; ui::Point mousePos = { 0, 0 };
int gridSize = 0; int gridSize = 0;
float fireIntensity = 1; float fireIntensity = 1;
HdispLimit wantHdispLimitMin = HdispLimitExplicit{ MIN_TEMP };
HdispLimit wantHdispLimitMax = HdispLimitExplicit{ MAX_TEMP };
Rect<int> autoHdispLimitArea = RES.OriginRect();
}; };

View File

@@ -2166,7 +2166,7 @@ void GameView::OnDraw()
StartRendererThread(); StartRendererThread();
WaitForRendererThread(); WaitForRendererThread();
AfterSimDraw(*sim); AfterSimDraw(*sim);
foundParticles = ren->GetFoundParticles(); rendererStats = ren->GetStats();
*rendererThreadResult = ren->GetVideo(); *rendererThreadResult = ren->GetVideo();
rendererFrame = rendererThreadResult.get(); rendererFrame = rendererThreadResult.get();
DispatchRendererThread(); DispatchRendererThread();
@@ -2177,7 +2177,7 @@ void GameView::OnDraw()
ren->ApplySettings(*rendererSettings); ren->ApplySettings(*rendererSettings);
RenderSimulation(*sim, true); RenderSimulation(*sim, true);
AfterSimDraw(*sim); AfterSimDraw(*sim);
foundParticles = ren->GetFoundParticles(); rendererStats = ren->GetStats();
rendererFrame = &ren->GetVideo(); rendererFrame = &ren->GetVideo();
} }
} }
@@ -2525,10 +2525,19 @@ void GameView::OnDraw()
if (showDebug) if (showDebug)
{ {
if (rendererSettings->findingElement) if (rendererSettings->findingElement)
fpsInfo << " Parts: " << foundParticles << "/" << sample.NumParts; fpsInfo << " Parts: " << rendererStats.foundParticles << "/" << sample.NumParts;
else else
fpsInfo << " Parts: " << sample.NumParts; fpsInfo << " Parts: " << sample.NumParts;
} }
if ((std::holds_alternative<HdispLimitAuto>(rendererSettings->wantHdispLimitMin) ||
std::holds_alternative<HdispLimitAuto>(rendererSettings->wantHdispLimitMax)) && rendererStats.hdispLimitValid)
{
fpsInfo << " [TEMP L:";
format::RenderTemperature(fpsInfo, rendererStats.hdispLimitMin, c->GetTemperatureScale());
fpsInfo << " H:";
format::RenderTemperature(fpsInfo, rendererStats.hdispLimitMax, c->GetTemperatureScale());
fpsInfo << "]";
}
if (c->GetReplaceModeFlags()&REPLACE_MODE) if (c->GetReplaceModeFlags()&REPLACE_MODE)
fpsInfo << " [REPLACE MODE]"; fpsInfo << " [REPLACE MODE]";
if (c->GetReplaceModeFlags()&SPECIFIC_DELETE) if (c->GetReplaceModeFlags()&SPECIFIC_DELETE)

View File

@@ -174,7 +174,7 @@ private:
void DispatchRendererThread(); void DispatchRendererThread();
std::unique_ptr<RenderableSimulation> rendererThreadSim; std::unique_ptr<RenderableSimulation> rendererThreadSim;
std::unique_ptr<RendererFrame> rendererThreadResult; std::unique_ptr<RendererFrame> rendererThreadResult;
int foundParticles = 0; RendererStats rendererStats;
const RendererFrame *rendererFrame = nullptr; const RendererFrame *rendererFrame = nullptr;
SimFpsLimit simFpsLimit = FpsLimitExplicit{ 60.f }; SimFpsLimit simFpsLimit = FpsLimitExplicit{ 60.f };

View File

@@ -411,7 +411,7 @@ void OptionsView::UpdateAmbientAirTempPreview(float airTemp, bool isValid)
{ {
if (isValid) if (isValid)
{ {
ambientAirTempPreview->Appearance.BackgroundInactive = RGB::Unpack(HeatToColour(airTemp)).WithAlpha(0xFF); ambientAirTempPreview->Appearance.BackgroundInactive = RGB::Unpack(HeatToColour(airTemp, MIN_TEMP, MAX_TEMP)).WithAlpha(0xFF);
ambientAirTempPreview->SetText(""); ambientAirTempPreview->SetText("");
} }
else else

View File

@@ -243,6 +243,62 @@ static int separateThread(lua_State *L)
return 1; return 1;
} }
static int heatDisplayLimits(lua_State *L)
{
auto *lsi = GetLSI();
lsi->AssertInterfaceEvent();
auto &rendererSettings = lsi->gameModel->GetRendererSettings();
if (lua_gettop(L))
{
auto write = [L](auto &setting, int index) {
if (lua_isstring(L, index) && byteStringEqualsLiteral(tpt_lua_toByteString(L, index), "auto"))
{
setting = HdispLimitAuto{};
}
else
{
setting = HdispLimitExplicit{ float(luaL_checknumber(L, index)) };
}
};
write(rendererSettings.wantHdispLimitMin, 1);
write(rendererSettings.wantHdispLimitMax, 2);
return 0;
}
auto read = [L](auto &setting) {
if (auto *hdispLimitExplicit = std::get_if<HdispLimitExplicit>(&setting))
{
lua_pushnumber(L, hdispLimitExplicit->value);
}
else
{
lua_pushliteral(L, "auto");
}
};
read(rendererSettings.wantHdispLimitMin);
read(rendererSettings.wantHdispLimitMax);
return 2;
}
static int heatDisplayAutoArea(lua_State *L)
{
auto *lsi = GetLSI();
lsi->AssertInterfaceEvent();
auto &rendererSettings = lsi->gameModel->GetRendererSettings();
if (lua_gettop(L))
{
rendererSettings.autoHdispLimitArea.pos .X = luaL_checkinteger(L, 1);
rendererSettings.autoHdispLimitArea.pos .Y = luaL_checkinteger(L, 2);
rendererSettings.autoHdispLimitArea.size.X = luaL_checkinteger(L, 3);
rendererSettings.autoHdispLimitArea.size.Y = luaL_checkinteger(L, 4);
return 0;
}
lua_pushinteger(L, rendererSettings.autoHdispLimitArea.pos .X);
lua_pushinteger(L, rendererSettings.autoHdispLimitArea.pos .Y);
lua_pushinteger(L, rendererSettings.autoHdispLimitArea.size.X);
lua_pushinteger(L, rendererSettings.autoHdispLimitArea.size.Y);
return 4;
}
void LuaRenderer::Open(lua_State *L) void LuaRenderer::Open(lua_State *L)
{ {
static const luaL_Reg reg[] = { static const luaL_Reg reg[] = {
@@ -262,6 +318,8 @@ void LuaRenderer::Open(lua_State *L)
LFUNC(fireSize), LFUNC(fireSize),
LFUNC(useDisplayPreset), LFUNC(useDisplayPreset),
LFUNC(separateThread), LFUNC(separateThread),
LFUNC(heatDisplayLimits),
LFUNC(heatDisplayAutoArea),
#undef LFUNC #undef LFUNC
{ nullptr, nullptr } { nullptr, nullptr }
}; };