Trying to map a 2d array into a disk

No Mechaenetia make me sad, so i decided to figure out. How hard can it be to map a 2d array into a Disk. Answer: Very hard

Anyways so to to make this i had to rewatch a video on making minetest into a torus some times and mix some values and figure out some constants over and over again. but i think i have a ok method now.
Dont mind that its circles(i am too lazy to connect squares)

you can find this project at this github url, though i dont recommend using any of this code as it sucks and the math is barely right

4 Likes

some more progress later and ive made this


the weird chunks is because i just rotate a square texture without moving the vertexes to go into each other

i have 3 things that i can do next.

  1. fix the math(its duct tape together, and i dont know math)
  2. fix the vertexes together(dont wanna, and never done shaders before)
  3. make a donut(oh hell naw)

basically im to lazy to improve this anymore

2 Likes

Mechaenetia is probably having Donut worlds.

Donut worlds? How hard can it be to make donut worlds? know what, ill make a donut world thingy, and as a matter of fact ill do the 2D version which should be much easier, this shouldnt take more than a couple of hours. ¯_(ツ)_/¯

So yeah, im back. and ive slightly made my algoritm a little better. While i still dont know why it works, it doesnt feel duct tape together anymore, very few constant numbers and if it is, it is in places where it makes sense. For example

x:(x as f32 *2.0 /ARRX as f32 -1.0) * std::f32::consts::PI

the (x as f32 *2.0 /ARRX as f32 -1.0) is there to reduce the lenght down to -1 to 1 no matter the size BUT. Why do i multiply by pi, I dont know, but i have a theory, you see the X is the circumfourense of the world, so maybe it just works that way since then ill map from -PI to PI, and would you look at that computers calculate Rotations from 0 to 2PI, which is the same length as what i multiply, i suspect why this works.

Suddenly this

Became this

now, my height mapping algorythm looks like this

y: (y as f32 - ARRY as f32)/12.0

the twelve is there just simply because my boxes wont connect if i dont. like this


the fix is simple, just force them close enough together. This should be made automatic with some algorithm, but i dont know of it and 12 works wonderously for now,

you might wonder, why dont i force this between -1 to 1.

simple reason actually, i want it to go on infinity deep in. if i try to do it in a more proper way by normalising it beetwen -1 and 1, i get this.


while this keeps the correct aspect ratio when i go in, which is the most importan property.
Id also have to unhardcode that number 12, because when i increase the amount of boxes it gets more dense. as can be seen here

now if you ask me what is easiest, make an algorythm that makes a more correct algorithm work, or just allow the boxes to naturally shrink in the void with some hardcoded number.

Note that both ways look excatly the same.

Obviusly im just gonna hardcode.

Now to the most important piece of this code. The above just prepares it for this step.

    			let mut worlds_complex = Complex{re:box_world[x][y].y, im:box_world[x][y].x};
    			worlds_complex = Complex::exp(worlds_complex);
				let node_x = worlds_complex.re;
				let node_y = worlds_complex.im;

i dont expect you do get this, honestly i still dont. but ill try explain it to you.

So basically

let mut worlds_complex = Complex{re:box_world[x][y].y, im:box_world[x][y].x};
this just turns the X and Y position into their imaginary counterpart, prework for the next part.

worlds_complex = Complex::exp(worlds_complex);
This is the heart of my algorithm and also the part i understand least of. basically since complex math is done on a 2d grid, math just works differently there. Nah but for real, the limit of what i know is that i transform it with EXP, which is taking e^x, which i didnt know for a long time btw. The reason i know that this is important is that EXP maintains correct aspect ratio no matter what.
all my math is taken from this video btw, go watch it its great.

now

let node_x = worlds_complex.re;
let node_y = worlds_complex.im;

isnt really that importan since it just takes the imaginary and real part into X and Y, unnecacary but i do it for clarity.

good, you have done this, but oh no, why is it just a tiny dot in the middle of the screen?
image
well you see, everything has been normalised. so everything ranges from -1 to 1. to fix this you have to options, either scale the Y with something like this

re:box_world[x][y].y + world_offset_height

which can work, but remember this goes right into an exponential function, so things shrink and grow pretty fast. value of 7 you might see the entire world, but at 10 you see nothing as youre inside the hole within. or the other way, by scaling the blocks directly.

let node_x = worlds_complex.re * radius;
let node_y = worlds_complex.im * radius;

the benefit of doing it this way is that if the radius = 100, the world will be 200 pixels big. quite simple.
though the downside is that when you zoom into the world you will eventually stop, even if the world is much deeper. this is because of something known as floating point inacurasy. the EXP function grows extremely fast big, which is bad for us since floating numbers though can be immense have a limit. But the

re:box_world[x][y].y + world_offset_height

method bypasses this since its doing the tranformation before the EXP function. Which means, that we avoid reaching insane values for what we see, and is interested in. NICE

This is basically the gist of it and i hope this has been useful to any idiot with similar ideas to me

and yes the source code can be found at: GitHub - Fyrstikkeske/disktest: insanium

i have some ideas about collisions and stuff, this shouldnt be too hard since i can do the collisions in the 2d grid before i turn it into a torus and things should behave similar. which is great since then the edges while looking ugly doesnt affect the program at all

3 Likes

trust me, this is important to my program

1 Like