Hi @DrOldies,
You mention the thread, but I wanted to be sure to point out this framework for arranging arbitrary matrixes with various offsets and rotations:
Yes, the pixel map is rendered in your browser using real JavaScript, and a 2D or 3D normalized map of the pixel coordinates is stored. While you can live code that part too in order to get the mapping right, the ideas is as @Scruffynerf mentions, the map itself is usually static once set.
The mapper text should resolve to either a json array of arrays, or a javascript function that when executed will return one. You can define helper functions inside this function as demonstrated in the examples.
These coordinates are then fed in to render2D or render3D depending on how many dimensions are defined in the map. Generally the idea is that your pixel map has the Cartesian coordinates of each pixel, and most patterns are written for that. It is not limited to that, you can use it for any arbitrary 2 or 3 dimensions of data. If you do store coordinates, you can use the built in math functions to calculate other things such as the radius from a center and angle, if you prefer to work in polar space.
For example, “firework nova” calculates radius from the center in 3D space:
export function render3D(index, x, y, z) {
//center coordinates
x -= 0.5
y -= 0.5
z -= 0.5
//get pixel distance from center
r = sqrt(x*x + y*y + z*z) * scale
//...
}
Likewise angle can get obtained from atan2.
Note that atan2 is broken in v2.23 and will be fixed, use this until then:
var HALF_PI = PI/2
function arctan2(y, x) {
if (x > 0) return atan(y/x)
if (y > 0) return HALF_PI - atan(x/y)
if (y < 0) return -HALF_PI - atan(x/y)
if (x < 0) return PI + atan(y/x)
return 1.0
}
Here’s a pattern with these as utility functions, displaying a rotating gradient based on angle, with colors shifting outward based on the radius. On 3D pieces, it shifts rotation from z, causing a helix:
var HALF_PI = PI/2
//NOTE: atan2 has a bug in V2.23, when fixed this can be replaces with atan2 directly
function arctan2(y, x) {
if (x > 0) return atan(y/x)
if (y > 0) return HALF_PI - atan(x/y)
if (y < 0) return -HALF_PI - atan(x/y)
if (x < 0) return PI + atan(y/x)
return 1.0
}
//return the angle in radians, can be negative
function getAngleInRads(x, y) {
//center the coordinate, then get the angle
return arctan2(x - .5, y - .5)
}
//return the angle as a value between 0 and 1.0
//most of Pixelblaze's animation language uses this range
//it also happens to rotate the angle so that 0 is north
function getUnitAngle(x, y) {
return (PI + arctan2(x - .5, y - .5))/PI2
}
function getRadius2D(x, y) {
//center coordinates
x -= 0.5
y -= 0.5
return sqrt(x*x + y*y)
}
function getRadius3D(x, y, z) {
//center coordinates
x -= 0.5
y -= 0.5
z -= 0.5
return sqrt(x*x + y*y + z*z)
}
export function beforeRender(delta) {
t1 = time(.1)
}
export var t, x1, y1, z1
export function render3D(index, x, y, z) {
if (index == 0) {
t = getRadius3D(x, y, z)
x1 = x
y1 = y
z1 = z
}
//get the angle of the pixel, and move it clockwize over time
//pass that into triangle() to turn into a gradient
v = triangle(getUnitAngle(x, y) + z + t1)
v = pow(v, 10) //for contrast
h = getRadius3D(x, y, z)
s = 1
hsv(h, s, v)
}
//for broad compatibility, support 2D maps as well
export function render2D(index, x, y) {
render3D(index, x, y, .5)
}
angle and radius from coordinates.epe (5.5 KB)
GlowFlow by Roger uses matrix transformations to rotate the mapped 3D coordinates and create the effect of a bucket of glowing liquid that follows gravity. It’s super cool!