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);
    }
}