class Gradient
{
ArrayList colors;
// Constructor
Gradient()
{
colors = new ArrayList();
}
void addColor(color c)
{
colors.add(c);
}
color getGradient(float value)
{
// make sure there are colors to use
if(colors.size() == 0)
return #000000;
// if its too low, use the lowest value
if(value <= 0.0)
return (color)(Integer) colors.get(0);
// if its too high, use the highest value
if(value >= colors.size() - 1)
return (color)(Integer) colors.get(colors.size() - 1);
// lerp between the two needed colors
int color_index = (int)value;
color c1 = (color)(Integer) colors.get(color_index);
color c2 = (color)(Integer) colors.get(color_index + 1);
return lerpColor(c1, c2, value - color_index);
}
}
// Screen size
int ssize = 300;
// Array to store the heat values for each pixel
float heatmap[][][] = new float[2][ssize][ssize];
// The index of the current heatmap
int index = 0;
// A color gradient to see pretty colors
Gradient g;
void setup()
{
size(300, 300);
g = new Gradient();
g.addColor(color(0, 0, 0));
g.addColor(color(102, 0, 102));
g.addColor(color(0, 144, 255));
g.addColor(color(0, 255, 207));
g.addColor(color(51, 204, 102));
g.addColor(color(111, 255, 0));
g.addColor(color(191, 255, 0));
g.addColor(color(255, 240, 0));
g.addColor(color(255, 153, 102));
g.addColor(color(204, 51, 0));
g.addColor(color(153, 0, 0));
// Initalize the heat map (make sure everything is 0.0)
for(int i = 0; i < ssize; ++i)
for(int j = 0; j < ssize; ++j)
heatmap[index][i][j] = 0.0;
}
void draw()
{
// See if heat (or cold) needs applied
if (mousePressed && (mouseButton == LEFT))
apply_heat(mouseX, mouseY, 15, .5);
if (mousePressed && (mouseButton == RIGHT))
apply_heat(mouseX, mouseY, 15, -.25);
// Calculate the next step of the heatmap
update_heatmap();
// For each pixel, translate its heat to the appropriate color
for(int i = 0; i < ssize; ++i)
for(int j = 0; j < ssize; ++j)
set(i, j, g.getGradient(heatmap[index][i][j]));
}
void update_heatmap()
{
// Calculate the new heat value for each pixel
for(int i = 0; i < ssize; ++i)
for(int j = 0; j < ssize; ++j)
heatmap[index ^ 1][i][j] = calc_pixel(i, j);
// flip the index to the next heatmap
index ^= 1;
}
float calc_pixel(int i, int j)
{
float total = 0.0;
int count = 0;
// This is were the magic happens...
// Average the heat around the current pixel to determin the new value
for(int ii = -1; ii < 2; ++ii)
{
for(int jj = -1; jj < 2; ++jj)
{
if(i + ii < 0 || i + ii >= width || j + jj < 0 || j + jj >= height)
continue;
++count;
total += heatmap[index][i + ii][j + jj];
}
}
// return the average
return total / count;
}
void apply_heat(int i, int j, int r, float delta)
{
// apply delta heat (or remove it) at location
// (i, j) with radius r
for(int ii = -(r / 2); ii < (r / 2); ++ii)
{
for(int jj = -(r / 2); jj < (r / 2); ++jj)
{
if(i + ii < 0 || i + ii >= width || j + jj < 0 || j + jj >= height)
continue;
// apply the heat
heatmap[index][i + ii][j + jj] += delta;
heatmap[index][i + ii][j + jj] = constrain(heatmap[index][i + ii][j + jj], 0.0, 20.0);
}
}
}
Simulation of the distribution of heat in a simple system.
Each pixel represents a single "heat" value. Each pixel is updated by averaging the amount of heat around it, thus the heat will flow to cooler areas. The value is then translated into a color from the color gradient (which makes it look ten times cooler). I broke out the gradient into its own separate class in case someone finds it useful.
Left Mouse: Apply heat
Right Mouse: Remove heat