• they/them

ancient multidimensional shrimp


idk video games or something
sometimes level designer
i rechost a lot


( \ / )

>(@~@)<

~🦐~



[O_o]
d____b

tomforsyth
@tomforsyth

There's a graphics trick that used to be widely known that has now probably almost vanished from the graphics consciousness - you can do rotations by applying three shears in a row. This should surprise you! It surprised me. And it re-surprises me every time I remember it.


polymath
@polymath

So I thought this was cool, so I did a little talk about it at the big MathsJam last year, and Matt Parker was there so now it's made it into one of his videos

This chost has very much escaped containment


You must log in to comment.

in reply to @tomforsyth's post:

But why go to all this trouble though? Why not get your GPU to do it?

I've seen people use this trick in MS Paint which has (had?) shears but no rotations. Probably an unconventional place to be using it, but a very fun one.

Even less widely known: it generalizes to higher dimensions and to any volume preserving linear transformation A, not just rotations. So you could use this to linearly transform voxel data or go even higher dimensional. To do that you decompose A (permuting/flipping axes as required) into 3 unitriangular matrices and those are each just a bunch of axis aligned shears (exactly one shear each in the 2d case).

This is the algorithm I came up with a while ago: https://gist.github.com/jix/3df036fba9d1f1a4ae78a40bf6c67aac

(hope you don't mind me duplicating this comment here and on your mastodon post)

i put this in my rebug in tags-as-marginalia fashion but in absence of a feature showing tags in rebug notifications: this rules, i figured out i could sort of rotate stuff in mspaint this way but i only did the first two and not another x so it didn't work well except at relatively gentle angles. i had no idea a sequence of shears could actually map to a true rotation

Fun fact: The Sega Genesis/Mega Drive can shear background layers horizontally on a scanline-by-scanline basis, are vertically in 2-tile-wide blocks, and several games used this to simulate limited rotation (because at shallow angles, the visual elongation caused by not doing the third shear isn't as noticeable), notably Streets of Rage 2 and Castlevania: Bloodline.

The SNES had similar capabilities (vertical shearing was on a tile-by-tile basis but could only be done in three of the system's eight graphics modes) but they weren't generally used to simulate background rotation, owing the existence of mode 7.

#!/usr/bin/env python3
import cv2
import numpy as np
import math

def sheer(img, ratio, y=False, origin=None):
    result = img.copy()
    if y:
        result = np.transpose(result, (1, 0, 2))
    if origin is None:
        origin = result.shape[0] / 2
    for i in range(result.shape[0]):
        shift = round((i - origin) * ratio)
        if shift > 0:
            result[i,shift:] = result[i,:-shift]
        elif shift < 0:
            result[i,:shift] = result[i,-shift:]
    if y:
        result = np.transpose(result, (1, 0, 2))
    return result

def rotate(img, angle):
    img = sheer(img, -math.tan(angle / 2))
    img = sheer(img, math.sin(angle), y=True)
    img = sheer(img, -math.tan(angle / 2))
    return img

if __name__ == '__main__':
    a = cv2.imread('fox.png')
    # Photo by Jeremy Hynes https://unsplash.com/photos/UeCG6uMSKdE
    b = a.copy()
    for i in range(120):
        b = rotate(b, math.pi / 6)
    cv2.imshow('result', b)
    cv2.waitKey()

Look at what I got with this code https://i.imgur.com/BhrRrJG.png The code was slightly modified (+0.5 to origin, otherwise it looked bad) This extremely naive implementation of mine survives 12000 rotations by 30 degrees!