JSFiddle - React, Tailwind, and code Playground
HTML
<script src="http://www.numericjs.com/lib/numeric-1.2.3.min.js"></script>
<canvas id="c" width="128" height="128"></canvas>
CSS
#c {
width: 300px;
height: 300px;
}
JavaScript
"use strict";
//FFT based smooth life
var INNER_RADIUS = 7.0;
var OUTER_RADIUS = 3 * INNER_RADIUS;
var B1 = 0.278;
var B2 = 0.365;
var D1 = 0.267;
var D2 = 0.445;
var ALPHA_N = 0.028;
var ALPHA_M = 0.147;
var LOG_RES = 7;
//Coloring stuff
var color_shift = [0, 0, 0];
var color_scale = [256, 256, 256];
//Canvas elements
var canvas = document.getElementById("c");
var ctx = canvas.getContext("2d");
canvas.width = (1<<LOG_RES);
canvas.height = (1<<LOG_RES);
//Buffers
var field_dims = [ (1<<LOG_RES), (1<<LOG_RES) ];
var fields = new Array(2);
for(var i=0; i<fields.length; ++i) {
fields[i] = numeric.rep(field_dims, 0.0);
}
var imaginary_field = numeric.rep(field_dims, 0.0);
var current_field = 0;
var M_re_buffer = numeric.rep(field_dims, 0.0);
var M_im_buffer = numeric.rep(field_dims, 0.0);
var N_re_buffer = numeric.rep(field_dims, 0,0);
var N_im_buffer = numeric.rep(field_dims, 0.0);
//Initialize kernel
function BesselJ(radius) {
//Do this in a somewhat stupid way
var field = numeric.rep(field_dims, 0.0);
var weight = 0.0;
for(var i=0; i<field.length; ++i) {
for(var j=0; j<field.length; ++j) {
var ii = ((i + field.length/2) % field.length) - field.length/2;
var jj = ((j + field.length/2) % field.length) - field.length/2;
var r = Math.sqrt(ii*ii + jj*jj) - radius;
var v = 1.0 / (1.0 + Math.exp(LOG_RES * r));
weight += v;
field[i][j] = v;
}
}
var imag_field = numeric.rep(field_dims, 0.0);
fft2(1, LOG_RES, field, imag_field);
return { re: field, im: imag_field, w: weight };
}
//Precalculate multipliers for m,n
var M_re, M_im, N_re, N_im;
(function() {
var inner_bessel = BesselJ(INNER_RADIUS);
var outer_bessel = BesselJ(OUTER_RADIUS);
var inner_w = 1.0 / inner_bessel.w;
var outer_w = 1.0 / (outer_bessel.w - inner_bessel.w);
M_re = inner_bessel.re;
M_im = inner_bessel.im;
...