Isometric Grid
No Frameworks, just basic Javascript
March 18, 2023 - Tommy Dräger
Today is Saturday so there is finally time to program for myself. Today I programmed something mesmerizing. I added a simple user interface so that you can play around with the values.
In order to put the WFC project to use I want to use an isometric grid that I can combine with the wfc and marching cube algorithm in order to procedually generate an isometric little cosmos. I plan to make a little project that has an "aquarium" feel to it.
References
Demonstration
https://apps.fenixfox-studios.com/isometric_grid/
Isometric Transformations with Matrices
In an isometric grid, the goal is to map 2D coordinates onto an isometric plane, creating the illusion of depth. This can be achieved using a combination of rotation and scaling matrices. Here’s a step-by-step explanation:
Rotation Matrix
We'll use gl-matrix for this example. "gl-matrix" is a highly optimized library for matrix operations like multiply, inverse etc.
import { vec2, mat2 } from 'gl-matrix';
const point = vec2.fromValues(x * w, y * h);
const angle = Math.PI / 4;
const rotationMatrix = mat2.create();
mat2.rotate(rotationMatrix, rotationMatrix, angle);
you obviously need to fill in w and h (width and height of your grid) yourself, as well as x and y (grid coordinates).
Here, scaleX and scaleY represent the scaling factors for the x and y dimensions, respectively. The y-axis is usually scaled down (often by a factor of 0.5
) to create the characteristic isometric look.
Transforming the Point
To apply both transformations, we use the transformMat2 method:
vec2.transformMat2(point, point, rotationMatrix);
vec2.transformMat2(point, point, scalingMatrix);
Full Example
import { vec2, mat2 } from 'gl-matrix';
function isometricTransform(x, y, w, h)
{
const point = vec2.fromValues(x * w, y * h);
const angle = Math.PI / 4;
const scaleX = 1;
const scaleY = 0.5;
const rotationMatrix = mat2.create();
const scalingMatrix = mat2.create();
mat2.rotate(rotationMatrix, rotationMatrix, angle);
mat2.scale(scalingMatrix, scalingMatrix, [scaleX, scaleY]);
vec2.transformMat2(point, point, rotationMatrix);
vec2.transformMat2(point, point, scalingMatrix);
return point;
}
Usage
const rows = 10;
const cols = 10;
const width = 20;
const height = 20;
const grid = [];
for (let y = 0; y < rows; y++)
{
for (let x = 0; x < cols; x++)
{
const tranform = isometricTransform(x, y, width, height);
grid.push(tranform);
}
}