Note, this was written Novemeber 17th 2024. It's been rotting in google docs ever since. As I've mentioned before I don't really like making YouTube videos, and I wanted to wait until the module was out to make the video. So here's a webpage version! Just keep in mind everything is relative to November 17th 2024.
Hello denizens of hyperspace! For the past 40 days, I've been working on this 4D multiplayer game. Well, I suppose it's not a game, as it doesn't have any gameplay, but it's still a program designed for entertainment, so I'll call it a game for simplicity's sake. In the game, you can walk around and talk with your friends in a 4D environment, and there's tons of cool little things to check out, it's kind of like a 4D museum. It's up on my itch.io page for you to play! If you were to donate a singular penny that would be really cool of you.
But before you go do that, I want to talk about how I made the renderer. The renderer started as a voxel screen that I would draw 3D lines to, but this was very laggy at any decent resolution so I switched to just drawing 2D lines on the screen. The way it worked is that it would project all the vertices from the scene onto the 4D camera, and then that 3D wireframe image would get projected to the 3D camera's 2D screen. In 4D, cameras show 3D images instead of 2D ones. You would then orbit around this 3D image to see how the 4D camera looked at the world. This was cool, but was very uninutive and clunky. This was where the project was when I uploaded that video about prisms, I was using this very renderer!
Up until this point, I was using euler angles for rotation, and desperately wanted to upgrade as they were a pain in the ass. Euler angles are when you rotate on each plane one by one, so order matters a lot which fucks up interpolation among other things. It's also confusing trying to rotate globally, or sometimes locally. Let's clear something up: when you rotate around an axis, you're really rotating inside the plane perpendicular to that axis. We describe the axis since it's one less character. This is fine in 3D, but doesn't work in any other dimension. I mean, how would you describe a 2D axial rotation? The Z axis? It makes more sense to say the XY plane. Or really, just say rotation. Also, in 4D a 3D volume is perpendicular to an axis, and you can't rotate 3 dimensionally, so there's vagueness. Look at this tesseract. If I rotate it around the Y axis, I can make it spin inside the XZ (blue) plane like you may expect, but I could also make it spin inside the XW (yellow) or ZW plane, or any of the infinite planes perpendicular to Y. So yeah, planes are how rotations really work under the hood.
You can also rotate around planes in 4D by specifying the plane perpendicular to the rotation, but this is unnecessary in most cases as it introduces confusion. In 5D, rotation still happens in planes, but you can also rotate around 3D volumes. I think you can see the problem beginning to form- in the 36th dimension, you could specify the two vectors making up the rotation you're performing, or you could specify the 34 axes perpendicular to said rotation. Up to you :P
I wanted to use something else, and I didn't know of any other options so I tried to use two quaternions to describe a 4D rotation. The first quaternion is the unit vector to point towards, and the second quaternion is a 3D rotation to describe all the rolly elements. But this was really hard, and I couldn't ever get it to work. But then I remembered my friend Aaron Franke! Aaron made this 4D addon for godot that just makes a Node4D, with all the transform related variables and stuff. I asked him about it and he explained them to me and how to download the project. Perfect! I got the new rotation system working quickly and it's awesome! Now rotation is simple. What is the rotation system? Well his project (like godot 3D) uses transform matrices for rotation, among other things.
The basis matrix is a 4x4 matrix that describes the rotation, scale, and skew of an object. Basis transforms work like this: You've got n n dimensional vectors, so for this 2D example, you have two vectors that point to the right and up. When you want to rotate on a plane, you rotate every vector by that plane and angle. Then using matrix multiplication magic that I don't understand, you can transform a point by that rotation. So in 4D, it's the same thing, but with 4 4D vectors.
Currently the way this engine worked is that a GDscript file would render the scene using an array of a class called “Model”. My Model class just had a position, rotation, and mesh data on it. This was very clunky as most stuff was in one file, and I couldn't put code on objects. I split “Model” into two classes, a mesh class called Model and an object class called Entity. I actually shouldn't have done this. I had been using Aaron Franke's 4D addon for godot, which added some 4D transform utilities, but had also added a Node4D, which handled parent child transformations, and a bunch of other stuff. I had literally forgotten that Node4D existed and did exactly what I wanted. Whoops. Like literally, I programmed my own parent child transform inheritance system and everything. I was trying to build a hexagon for my cart while sitting on a wheel. Anyway I continued making my crappy Entity class and it was very nice to have, I could now attach scripts to 4D objects.
I then changed it to render the 3D projected image orthographically, so now it feels more like a 2D image of a 4D scene, rather than looking at the 3D image of a 4D scene. This makes it a lot easier to understand, but loses the double perspective projection. This does help things be less cluttered though. Before, I would project the scene with perspective to a 3D image, and then render that with perspective again to 2D. There's a problem with this though, several actually. Imagine a flatlander looking at a 2D image of a 3D virtual scene. If it's on the right side, the right side of the image looks bigger than the left side, even though they're both the same distance from the camera. This is confusing and bad. Also, now on top of having to manage the 4D camera, the player also has to manage the 3D camera. This made it hard to code and even harder to play. Switching to an orthographic projection, the X and Y axis of the screen look normal, the Z axis going "into" the screen looks normal too, and the W axis becomes flat. It looks great!
There is a problem with this though. Which is that the W axis is completely flat. To fix this, well, I don't remember when exactly I did this or if it was Aaron (I'm writing this paragraph 6/11/2025), but semi transparent edges were added to the engine. Now when something was far away in 4D, it would be semi transparent, and even colored orange/blue depending on if it was ana or kata of you. Something I remember I did do for sure was come up with the idea to make this range narrower when things are close, and wider when they're far. This mimics the fact that you can't see very far left and right with the near elements of the scene (without turning your head of course) but far away you can easily see 36's of meters left and right. I also got the idea to make a button you can hold to narrow your 4D vision to less than a meter, I called this focusing. It's very helpful for aiming and removing clutter from the wireframe scenes.
I decided to message Aaron about what I had been making, and he got inspired to work on his module again! He hadn't touched it in over 6 months at that point. We added each other to our git repos, and he ported my engine to C++. It went from 30 FPS on our test scene to well over 300. Very nice! He continued to work on the engine side of the project, making more nodes like Camera4D and MeshInstance4D. Instead of Model and Entity, there's ArrayWireMesh4D and Node4D. This is great as the engine is super simple to use, I don't have to explain things to people or do any project setup. Before this point, if I wanted to make a project that used my renderer, I had to copy and paste all the scene files over. And then things wouldn't stay in sync, so I never did that. But now creating a new 4D project is as simple as creating a new project and adding Node4Ds to it.
Now I just needed to test the engine, to see if it was capable of making a fully fledged game. And as I would work on it full time, I would find issues for us to solve. And I did find a lot of them. Aaron just finished adding an editor by this point, so now you can look at your scenes in 4D instead of having to run them. Even without being able to click on the objects and move them in editor, this made it so much easier to use and I wouldn't have been able to make Lobby4D without it. Also, I had had a lot of fun making mesh utility functions, like extrude, scale, inset, revolve, etc. I used these functions a lot, like to make this klein bottle, and this torisphere. Making that klein bottle was really hard, I had to model it by hand with extrude and rotate functions by typing in the 4D values. I'm still baffled I was able to make that curve as well as I did.
I had been wanting to play around with multiplayer, so I decided to make a multiplayer game. When I had made the basics, there was no gameplay and it could become anything, but I liked the idea of a social hangout space type of thing, so I kept it that way until release. It feels really nice to finally finish a project. We plan to add some more features, like hopefully VR, and then we'll release our module.
The module has been released for 3 months. Not many more features were added since the writing of this script, mostly just bug fixes and what not. Anyway if you plan to use this module, it is absolutely crucial that you download these two scripts and drag them into your project. Then by typing Model and Math you have access to helpful utilities. The Math class isn't very helpful but the Model class is and uses Math as a dependency. I update the Model class fairly frequently, so you might want to check into that google drive every once in a while. If you have any problems using the module, dm me or Aaron on discord. My username is tessimal, his is aaronfranke.
I've been working on a new game called Arena4D, it's an actual game, aka it has gameplay. No release date yet, but it'll probably release 2025, maybe 2026. I hope to keep the scope small and make money from it. Maybe I'll make some devlogs. Thanks for reading.