Convert hmap data to gradients

This commit is contained in:
Tamás Bálint Misius 2022-12-25 10:33:14 +01:00
parent bb6c371aa8
commit 3e3ee8a722
No account linked to committer's email address
14 changed files with 166 additions and 164 deletions

File diff suppressed because one or more lines are too long

View File

@ -1,24 +0,0 @@
/**
* Powder Toy - Heatmap Data
*
* Copyright (c) 2010 Simon Robertshaw
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
#pragma once
extern const unsigned char color_data[];
//extern const char plasma_data[];
extern const unsigned char hflm_data[];
extern const unsigned char firw_data[];

View File

@ -1,4 +1 @@
data_files += files(
'hmap.cpp',
)
data_files += to_array.process('font.bz2', extra_args: 'compressed_font_data')

View File

@ -10,7 +10,6 @@
#include "bzip2/bz2wrap.h"
#include "Config.h"
#include "Format.h"
#include "hmap.h"
#include "simulation/Simulation.h"
#include "simulation/ElementClasses.h"
@ -18,6 +17,7 @@
#include "common/tpt-minmax.h"
#include "common/tpt-compat.h"
#include "bson/BSON.h"
#include "graphics/Renderer.h"
static void ConvertJsonToBson(bson *b, Json::Value j, int depth = 0);
static void ConvertBsonToJson(bson_iterator *b, Json::Value *j, int depth = 0);
@ -404,6 +404,7 @@ static void CheckBsonFieldFloat(bson_iterator iter, const char *field, float *se
void GameSave::readOPS(const std::vector<char> &data)
{
Renderer::PopulateTables();
unsigned char *inputData = (unsigned char*)&data[0], *partsData = NULL, *partsPosData = NULL, *fanData = NULL, *wallData = NULL, *soapLinkData = NULL;
unsigned char *pressData = NULL, *vxData = NULL, *vyData = NULL, *ambientData = NULL;
@ -1078,10 +1079,9 @@ void GameSave::readOPS(const std::vector<char> &data)
case PT_FIRW:
if (particles[newIndex].tmp>=2 && savedVersion < 81)
{
auto caddress = int(restrict_flt(float(particles[newIndex].tmp-4), 0.0f, 199.0f)) * 3;
particles[newIndex].type = PT_EMBR;
particles[newIndex].ctype = Renderer::firwTableAt(particles[newIndex].tmp - 4);
particles[newIndex].tmp = 1;
particles[newIndex].ctype = (((firw_data[caddress]))<<16) | (((firw_data[caddress+1]))<<8) | ((firw_data[caddress+2]));
}
break;
case PT_PSTN:
@ -1243,6 +1243,8 @@ void GameSave::readOPS(const std::vector<char> &data)
void GameSave::readPSv(const std::vector<char> &dataVec)
{
Renderer::PopulateTables();
unsigned char * saveData = (unsigned char *)&dataVec[0];
auto dataLength = int(dataVec.size());
int q,j,k,x,y,p=0, ver, pty, ty, legacy_beta=0;
@ -1800,10 +1802,9 @@ void GameSave::readPSv(const std::vector<char> &dataVec)
}
if (particles[i-1].type==PT_FIRW && particles[i-1].tmp>=2)
{
auto caddress = int(restrict_flt(float(particles[i-1].tmp-4), 0.0f, 199.0f))*3;
particles[i-1].type = PT_EMBR;
particles[i-1].ctype = Renderer::firwTableAt(particles[i-1].tmp-4);
particles[i-1].tmp = 1;
particles[i-1].ctype = (((firw_data[caddress]))<<16) | (((firw_data[caddress+1]))<<8) | ((firw_data[caddress+2]));
}
}
if (ver < 89)

View File

@ -137,58 +137,6 @@ VideoBuffer::~VideoBuffer()
delete[] Buffer;
}
/**
* Common graphics functions, mostly static methods that provide
* encoding/decoding of different formats and font metrics
*/
char * Graphics::GenerateGradient(pixel * colours, float * points, int pointcount, int size)
{
int cp, i, j;
pixel ptemp;
char * newdata = (char*)malloc(size * 3);
float poss, pose, temp;
memset(newdata, 0, size*3);
//Sort the Colours and Points
for (i = (pointcount - 1); i > 0; i--)
{
for (j = 1; j <= i; j++)
{
if (points[j-1] > points[j])
{
temp = points[j-1];
points[j-1] = points[j];
points[j] = temp;
ptemp = colours[j-1];
colours[j-1] = colours[j];
colours[j] = ptemp;
}
}
}
i = 0;
j = 1;
poss = points[i];
pose = points[j];
for (cp = 0; cp < size; cp++)
{
float cpos = (float)cp / (float)size, ccpos, cccpos;
if(cpos > pose && j+1 < pointcount)
{
poss = points[++i];
pose = points[++j];
}
ccpos = cpos - poss;
cccpos = ccpos / (pose - poss);
if(cccpos > 1.0f)
cccpos = 1.0f;
newdata[(cp*3) ] = char(PIXR(colours[i])*(1.0f-cccpos) + PIXR(colours[j])*(cccpos));
newdata[(cp*3)+1] = char(PIXG(colours[i])*(1.0f-cccpos) + PIXG(colours[j])*(cccpos));
newdata[(cp*3)+2] = char(PIXB(colours[i])*(1.0f-cccpos) + PIXB(colours[j])*(cccpos));
}
return newdata;
}
pixel *Graphics::resample_img_nn(pixel * src, int sw, int sh, int rw, int rh)
{
int y, x;
@ -965,3 +913,39 @@ bool PngDataToPixels(std::vector<pixel> &imageData, int &imgw, int &imgh, const
png_destroy_read_struct(&png, &info, (png_infopp)NULL);
return true;
}
bool Graphics::GradientStop::operator <(const GradientStop &other) const
{
return point < other.point;
}
std::vector<pixel> Graphics::Gradient(std::vector<GradientStop> stops, int resolution)
{
std::vector<pixel> table(resolution, 0);
if (stops.size() >= 2)
{
std::sort(stops.begin(), stops.end());
auto stop = -1;
for (auto i = 0; i < resolution; ++i)
{
auto point = i / (float)resolution;
while (stop < (int)stops.size() - 1 && stops[stop + 1].point <= point)
{
++stop;
}
if (stop < 0 || stop >= (int)stops.size() - 1)
{
continue;
}
auto &left = stops[stop];
auto &right = stops[stop + 1];
auto f = (point - left.point) / (right.point - left.point);
table[i] = PIXRGB(
int(PIXR(left.color) + (PIXR(right.color) - PIXR(left.color)) * f),
int(PIXG(left.color) + (PIXG(right.color) - PIXG(left.color)) * f),
int(PIXB(left.color) + (PIXB(right.color) - PIXB(left.color)) * f)
);
}
}
return table;
}

View File

@ -80,8 +80,14 @@ public:
pixel *vid;
int sdl_scale;
//Common graphics methods in Graphics.cpp
static char * GenerateGradient(pixel * colours, float * points, int pointcount, int size);
struct GradientStop
{
pixel color;
float point;
bool operator <(const GradientStop &other) const;
};
static std::vector<pixel> Gradient(std::vector<GradientStop> stops, int resolution);
//PTIF methods
static pixel *resample_img_nn(pixel *src, int sw, int sh, int rw, int rh);

View File

@ -25,7 +25,6 @@
#include "lua/LuaScriptHelper.h"
#include "lua/LuaSmartRef.h"
#endif
#include "hmap.h"
#define VIDXRES WINDOWW
#define VIDYRES WINDOWH
@ -701,7 +700,7 @@ void Renderer::prepare_alpha(int size, float intensity)
#ifndef FONTEDITOR
void Renderer::render_parts()
{
int deca, decr, decg, decb, cola, colr, colg, colb, firea, firer, fireg, fireb, pixel_mode, q, i, t, nx, ny, x, y, caddress;
int deca, decr, decg, decb, cola, colr, colg, colb, firea, firer, fireg, fireb, pixel_mode, q, i, t, nx, ny, x, y;
int orbd[4] = {0, 0, 0, 0}, orbl[4] = {0, 0, 0, 0};
float gradv, flicker;
Particle * parts;
@ -790,7 +789,7 @@ void Renderer::render_parts()
if((elements[t].Properties & PROP_HOT_GLOW) && sim->parts[i].temp>(elements[t].HighTemperature-800.0f))
{
gradv = 3.1415/(2*elements[t].HighTemperature-(elements[t].HighTemperature-800.0f));
caddress = int((sim->parts[i].temp>elements[t].HighTemperature)?elements[t].HighTemperature-(elements[t].HighTemperature-800.0f):sim->parts[i].temp-(elements[t].HighTemperature-800.0f));
auto caddress = int((sim->parts[i].temp>elements[t].HighTemperature)?elements[t].HighTemperature-(elements[t].HighTemperature-800.0f):sim->parts[i].temp-(elements[t].HighTemperature-800.0f));
colr += int(sin(gradv*caddress) * 226);
colg += int(sin(gradv*caddress*4.55 +3.14) * 34);
colb += int(sin(gradv*caddress*2.22 +3.14) * 64);
@ -814,11 +813,11 @@ void Renderer::render_parts()
{
constexpr float min_temp = MIN_TEMP;
constexpr float max_temp = MAX_TEMP;
caddress = int(restrict_flt((sim->parts[i].temp - min_temp) / (max_temp - min_temp) * 1024, 0, 1023)) * 3;
firea = 255;
firer = colr = color_data[caddress];
fireg = colg = color_data[caddress+1];
fireb = colb = color_data[caddress+2];
auto color = heatTableAt(int((sim->parts[i].temp - min_temp) / (max_temp - min_temp) * 1024));
firer = colr = PIXR(color);
fireg = colg = PIXG(color);
fireb = colb = PIXB(color);
cola = 255;
if(pixel_mode & (FIREMODE | PMODE_GLOW))
pixel_mode = (pixel_mode & ~(FIREMODE|PMODE_GLOW)) | PMODE_BLUR;
@ -1322,8 +1321,8 @@ int HeatToColour(float temp)
{
constexpr float min_temp = MIN_TEMP;
constexpr float max_temp = MAX_TEMP;
int caddress = int(restrict_flt((temp - min_temp) / (max_temp - min_temp) * 1024, 0, 1023)) * 3;
return PIXRGB((int)(color_data[caddress]*0.7f), (int)(color_data[caddress+1]*0.7f), (int)(color_data[caddress+2]*0.7f));
auto color = Renderer::heatTableAt(int((temp - min_temp) / (max_temp - min_temp) * 1024));
return PIXRGB((int)(PIXR(color)*0.7f), (int)(PIXG(color)*0.7f), (int)(PIXB(color)*0.7f));
}
void Renderer::draw_air()
@ -1444,6 +1443,65 @@ pixel Renderer::GetPixel(int x, int y)
return vid[(y*VIDXRES)+x];
}
std::vector<pixel> Renderer::flameTable;
std::vector<pixel> Renderer::plasmaTable;
std::vector<pixel> Renderer::heatTable;
std::vector<pixel> Renderer::clfmTable;
std::vector<pixel> Renderer::firwTable;
static bool tablesPopulated = false;
static std::mutex tablesPopulatedMx;
void Renderer::PopulateTables()
{
std::lock_guard g(tablesPopulatedMx);
if (!tablesPopulated)
{
tablesPopulated = true;
flameTable = Graphics::Gradient({
{ 0x000000, 0.00f },
{ 0x60300F, 0.50f },
{ 0xDFBF6F, 0.90f },
{ 0xAF9F0F, 1.00f },
}, 200);
plasmaTable = Graphics::Gradient({
{ 0x000000, 0.00f },
{ 0x301040, 0.25f },
{ 0x301060, 0.50f },
{ 0xAFFFFF, 0.90f },
{ 0xAFFFFF, 1.00f },
}, 200);
heatTable = Graphics::Gradient({
{ 0x2B00FF, 0.00f },
{ 0x003CFF, 0.01f },
{ 0x00C0FF, 0.05f },
{ 0x00FFEB, 0.08f },
{ 0x00FF14, 0.19f },
{ 0x4BFF00, 0.25f },
{ 0xC8FF00, 0.37f },
{ 0xFFDC00, 0.45f },
{ 0xFF0000, 0.71f },
{ 0xFF00DC, 1.00f },
}, 1024);
clfmTable = Graphics::Gradient({
{ 0x000000, 0.00f },
{ 0x0A0917, 0.10f },
{ 0x19163C, 0.20f },
{ 0x28285E, 0.30f },
{ 0x343E77, 0.40f },
{ 0x49769A, 0.60f },
{ 0x57A0B4, 0.80f },
{ 0x5EC4C6, 1.00f },
}, 200);
firwTable = Graphics::Gradient({
{ 0xFF00FF, 0.00f },
{ 0x0000FF, 0.20f },
{ 0x00FFFF, 0.40f },
{ 0x00FF00, 0.60f },
{ 0xFFFF00, 0.80f },
{ 0xFF0000, 1.00f },
}, 200);
}
}
Renderer::Renderer(Graphics * g, Simulation * sim):
sim(NULL),
g(NULL),
@ -1466,6 +1524,8 @@ Renderer::Renderer(Graphics * g, Simulation * sim):
ZFACTOR(8),
gridSize(0)
{
PopulateTables();
this->g = g;
this->sim = sim;
vid = g->vid;
@ -1551,17 +1611,6 @@ Renderer::Renderer(Graphics * g, Simulation * sim):
graphicscache = new gcache_item[PT_NUM];
std::fill(&graphicscache[0], &graphicscache[PT_NUM], gcache_item());
int fireColoursCount = 4;
pixel fireColours[] = {PIXPACK(0xAF9F0F), PIXPACK(0xDFBF6F), PIXPACK(0x60300F), PIXPACK(0x000000)};
float fireColoursPoints[] = {1.0f, 0.9f, 0.5f, 0.0f};
int plasmaColoursCount = 5;
pixel plasmaColours[] = {PIXPACK(0xAFFFFF), PIXPACK(0xAFFFFF), PIXPACK(0x301060), PIXPACK(0x301040), PIXPACK(0x000000)};
float plasmaColoursPoints[] = {1.0f, 0.9f, 0.5f, 0.25, 0.0f};
flm_data = Graphics::GenerateGradient(fireColours, fireColoursPoints, fireColoursCount, 200);
plasma_data = Graphics::GenerateGradient(plasmaColours, plasmaColoursPoints, plasmaColoursCount, 200);
prepare_alpha(CELL, 1.0f);
}
@ -1709,8 +1758,6 @@ Renderer::~Renderer()
delete[] persistentVid;
delete[] warpVid;
delete[] graphicscache;
free(flm_data);
free(plasma_data);
}
#define PIXELMETHODS_CLASS Renderer

View File

@ -50,8 +50,6 @@ public:
unsigned char fire_g[YRES/CELL][XRES/CELL];
unsigned char fire_b[YRES/CELL][XRES/CELL];
unsigned int fire_alpha[CELL*3][CELL*3];
char * flm_data;
char * plasma_data;
//
bool gravityZonesEnabled;
bool gravityFieldEnabled;
@ -153,6 +151,23 @@ public:
Renderer(Graphics * g, Simulation * sim);
~Renderer();
#define RENDERER_TABLE(name) \
static std::vector<pixel> name; \
static inline pixel name ## At(int index) \
{ \
auto size = int(name.size()); \
if (index < 0) index = 0; \
if (index > size - 1) index = size - 1; \
return name[index]; \
}
RENDERER_TABLE(flameTable)
RENDERER_TABLE(plasmaTable)
RENDERER_TABLE(heatTable)
RENDERER_TABLE(clfmTable)
RENDERER_TABLE(firwTable)
#undef RENDERER_TABLE
static void PopulateTables();
private:
int gridSize;
};

View File

@ -9,7 +9,6 @@ Slider::Slider(Point position, Point size, int steps):
sliderSteps(steps),
sliderPosition(0),
isMouseDown(false),
bgGradient(NULL),
col1(0, 0, 0, 0),
col2(0, 0, 0, 0)
{
@ -66,12 +65,12 @@ void Slider::OnMouseUp(int x, int y, unsigned button)
void Slider::SetColour(Colour col1, Colour col2)
{
pixel pix[2] = {(pixel)PIXRGB(col1.Red, col1.Green, col1.Blue), (pixel)PIXRGB(col2.Red, col2.Green, col2.Blue)};
float fl[2] = {0.0f, 1.0f};
free(bgGradient);
this->col1 = col1;
this->col2 = col2;
bgGradient = (unsigned char*)Graphics::GenerateGradient(pix, fl, 2, Size.X-7);
bgGradient = Graphics::Gradient({
{ pixel(PIXRGB(col1.Red, col1.Green, col1.Blue)), 0.f },
{ pixel(PIXRGB(col2.Red, col2.Green, col2.Blue)), 1.f },
}, Size.X-7);
}
int Slider::GetValue()
@ -107,11 +106,16 @@ void Slider::Draw(const Point& screenPos)
Graphics * g = GetGraphics();
//g->drawrect(screenPos.X, screenPos.Y, Size.X, Size.Y, 255, 255, 255, 255);
if(bgGradient)
if (bgGradient.size())
{
for (int j = 3; j < Size.Y-7; j++)
{
for (int i = 3; i < Size.X-7; i++)
g->blendpixel(screenPos.X+i+2, screenPos.Y+j+2, bgGradient[(i-3)*3], bgGradient[(i-3)*3+1], bgGradient[(i-3)*3+2], 255);
{
auto color = bgGradient[i - 3];
g->blendpixel(screenPos.X+i+2, screenPos.Y+j+2, PIXR(color), PIXG(color), PIXB(color), 255);
}
}
}
g->drawrect(screenPos.X+3, screenPos.Y+3, Size.X-6, Size.Y-6, 255, 255, 255, 255);

View File

@ -3,6 +3,7 @@
#include "Component.h"
#include "Colour.h"
#include "graphics/Pixel.h"
#include <functional>
@ -12,7 +13,7 @@ class Slider : public ui::Component
int sliderSteps;
int sliderPosition;
bool isMouseDown;
unsigned char * bgGradient;
std::vector<pixel> bgGradient;
struct SliderAction
{

View File

@ -1,5 +1,4 @@
#include "simulation/ElementCommon.h"
#include "hmap.h"
static int graphics(GRAPHICS_FUNC_ARGS);
static void create(ELEMENT_CREATE_FUNC_ARGS);
@ -51,10 +50,10 @@ void Element::Element_CFLM()
static int graphics(GRAPHICS_FUNC_ARGS)
{
int caddress = int(restrict_flt(float(cpart->life / 2), 0, 199)) * 3;
*colr = hflm_data[caddress];
*colg = hflm_data[caddress+1];
*colb = hflm_data[caddress+2];
auto color = Renderer::clfmTableAt(cpart->life / 2);
*colr = PIXR(color);
*colg = PIXG(color);
*colb = PIXB(color);
*firea = 255;
*firer = *colr;

View File

@ -353,10 +353,10 @@ static int updateLegacy(UPDATE_FUNC_ARGS)
static int graphics(GRAPHICS_FUNC_ARGS)
{
int caddress = int(restrict_flt(float(cpart->life), 0, 199)) * 3;
*colr = (unsigned char)ren->flm_data[caddress];
*colg = (unsigned char)ren->flm_data[caddress+1];
*colb = (unsigned char)ren->flm_data[caddress+2];
auto color = Renderer::flameTableAt(cpart->life);
*colr = PIXR(color);
*colg = PIXG(color);
*colb = PIXB(color);
*firea = 255;
*firer = *colr;

View File

@ -1,5 +1,4 @@
#include "simulation/ElementCommon.h"
#include "hmap.h"
static int update(UPDATE_FUNC_ARGS);
static int graphics(GRAPHICS_FUNC_ARGS);
@ -88,17 +87,14 @@ static int update(UPDATE_FUNC_ARGS)
}
else //if (parts[i].tmp>=2)
{
float angle, magnitude;
int caddress = RNG::Ref().between(0, 199) * 3;
int n;
unsigned col = (((firw_data[caddress]))<<16) | (((firw_data[caddress+1]))<<8) | ((firw_data[caddress+2]));
for (n=0; n<40; n++)
unsigned col = Renderer::firwTableAt(RNG::Ref().between(0, 199));
for (int n=0; n<40; n++)
{
np = sim->create_part(-3, x, y, PT_EMBR);
if (np>-1)
{
magnitude = RNG::Ref().between(40, 99) * 0.05f;
angle = RNG::Ref().between(0, 6283) * 0.001f;//(in radians, between 0 and 2*pi)
auto magnitude = RNG::Ref().between(40, 99) * 0.05f;
auto angle = RNG::Ref().between(0, 6283) * 0.001f;//(in radians, between 0 and 2*pi)
parts[np].vx = parts[i].vx*0.5f + cosf(angle)*magnitude;
parts[np].vy = parts[i].vy*0.5f + sinf(angle)*magnitude;
parts[np].ctype = col;

View File

@ -52,10 +52,10 @@ void Element::Element_PLSM()
static int graphics(GRAPHICS_FUNC_ARGS)
{
int caddress = int(restrict_flt(float(cpart->life), 0, 199)) * 3;
*colr = (unsigned char)ren->plasma_data[caddress];
*colg = (unsigned char)ren->plasma_data[caddress+1];
*colb = (unsigned char)ren->plasma_data[caddress+2];
auto color = Renderer::plasmaTableAt(cpart->life);
*colr = PIXR(color);
*colg = PIXG(color);
*colb = PIXB(color);
*firea = 255;
*firer = *colr;