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 known key found for this signature in database
GPG Key ID: 5B472A12F6ECA9F2
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);
{
for (int i = 3; i < Size.X-7; i++)
{
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;