Is it possible to construct a coordinate system which gets "pulled in"

158 Views Asked by At

I really hope i can explain our issue adequately and keep this purely math bound, even if it is technically a graphics programming related question. But over on their exchange ill never get an answer. I do think this is still the right exchange because the core question is about coordinate systems and transformations. What we use it for is secondary.

What is the problem ?

enter image description here

In essence this. Me and a friend have been working on a render engine for Kerr black holes for a while now. A core part of that is the accretion disk. Because we are cheap, we decided to use a procedurally generated disk instead of simulating one. So we use some noise functions to create a density field.

And here, the issues start. enter image description here

Irl, these disks kind of swirl inwards. Which we realize by rotating the coordinate system by an angle over radii dependency. The basic formula we use is $\theta = \frac{1}{\sqrt{r}}$. Here you can see what this looks like;

enter image description here

On the left you see how the noise looks after rotating the coordinate system, compared to the undistorted one on the right. The issue with this approach is two fold. For one, as time advances the distortion is going to get worse and worse. To the point where all features are lost. (Just so we are clear, by distortion i mean the loss of clear features in the noise duo to streaching) Right at some point it is just a bunch of lines. For instance here;

enter image description here

The second issue is with this setup, the noise does not actually get pulled inwards. As the angle increases, the radius stays constant. So depending on the exact pattern it just sort of looks like the noise flies away.

The core issue is atm, the way we transform the coordinate system by rotating it around a central axis using a varying angle only works visually when there is either no time dependency or the time is close to 0. This time dependency thing is a big problem because we have time dilation. So different parts of the disk may be several seconds apart from each other.

What do we want ?

Ideally we would want a way to "pull" the coordinates in so it actually looks like the noise is falling towards the Horizon, while maintaining a constant distortion level. To illustrate the first part, a very simple way to pull coordinates in is to convert the cartesian space into spherical coordinates, decrease the $r$ component and convert back into cartesian. Which yields something like this; enter image description here

However you might notice an issue. As the coordinates are pulled in, they are distorted in the radial direction. Which intuitively makes sense, as $r$ decreases we push coordinate points which used to be far away into a small and smaller radius. So this is no bueno.

In spirit, this cartesian -> spherical -> decrease $r$ -> cartesian thing does the trick if it was not for the distortion. And obviously if we try and compensate for the radial distortion by scaling theta we undo the pulling in part.

So, ideally we want this sort of pulling in behaivor, minus the radial distortion. In essence, we want this; enter image description here

We want to have the coordinates pulled in, but the features either stay the same size, or uniformly scale down. We are fine if the feature size decreases, as long as it does so on all axis so we don't get weird streaching.

Is this even possible ?

I am not a big math guy. But something tells me this whole question is similar to "Can you map a sphere to a plane". You can, but not without some distortion somewhere. Just thinking about this particular problem, i don't think there is a perfect solution which has no distortion at all.

But there are maybe a few saving graves. For instance, the disk stops at $r = 5$, so if for instance a solution is more or less distortion free till this lower bound, it does not really matter what happens at lower radii because the disk isnt there anymore.

Even then, i have a feeling it is not really possible for any arbitrarily high value of time. Or at least i cant really see a way of doing it, maybe i am wrong and through some 4th dimensional "pull the coords in along the W axis" voodoo it is possible.

Closing words, pls don't nuke this

Sorry for not including a lot of hard math. The truth of the matter is i have a lot of examples of how not to achieve this goal. But basically nothing which even sort of works. I hope i explained our problem in an understandable way. I have read through this decertation to double check. I know yall like when some more substantial math is presented and not a blind cry for help. Sorry for that.

Thanks for reading, mods or at whom´s ever mercy i am... common bro D:

EDIT; So to give some closure to this. The solution turned out to be a 2 in one.

First of all, big thanks to Jeffrey Kumley and Duncan Ramage, who have suggested and and presented the usage of a logistics spiral.

This works great for pulling features in without distortion. However one issue remained, the fact with a logistics spiral the entire thing had to rotate at the same angular speed throughout. Which a real disk does not do.

The solution to this was to, oversimplified, simulate a couple of points at increasing radii from the Black Hole and use the position of these points to construct a coordinate system. This coordinate system would rotate at differing speeds depending on the Radii but not distort. Then i applied the logistics spiral to this new wanky coordinate system, which took some questionable math, and tada, we have a disk that can spin forever, with no distortion and differing orbital velocities depending on the radii.

This has been quiet a journey, and without the suggestions from this post i couldnt have done it. So big thanks !

1

There are 1 best solutions below

3
On BEST ANSWER

As Duncan mentioned in a comment, a logarithmic spiral should do the trick. Its radius can be made to grow at a convenient rate proportional to the arc length, which should keep your UV segmentation from stretching too much.

Here's a Desmos interactive graph comparing a pair of equations scaled to grow by number of revolutions rather than by radians (Polar: Logarithmic Spiral vs Squared Spiral; screenshot).

By comparison, the logarithmic spiral is much more stable in that each point on the spiral is $a$ times farther from the origin than the previous point at the same angle. With $a = 2$, that means the length of an arc and the distance between that arc and the previous arc at the same angles are both doubling with each revolution around the spiral.

One snag in using a logarithmic spiral is that the center of the spiral does not infinitely reduce in size without adjustment. The beginning point of the spiral starts at $(1, 0)$ rather than the origin, $(0, 0)$. However, if you subtract $1$ from the radius and thus use $r = (\frac{\theta}{2\pi})^b-1$, then the spiral will go to the origin.

The shader code below can be used to render UVs for such a spiral to the screen in the Shader Editor app for Android.

#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif

uniform float time;
uniform vec2 resolution;

void main(void) {
    const float pi = 3.14159265;
    const float pi2 = pi * 2.0;

    float mn = min(resolution.x, resolution.y);
    vec2 center_uv = gl_FragCoord.xy / mn;

    vec2 xy = center_uv - 0.5;
    float x = xy.x;
    float y = xy.y;
    float a = (y >= 0.0 ? 0.25 : 0.75) - atan(x / y) / pi2;
    float dd = x*x+y*y;
    float d = sqrt(dd);
    vec2 ad = vec2(a,d);

    const float speed = 0.1;
    float spin = a + time * speed;
    float spiral_u = spin * 8.0;
    float spiral_v = (log2(d) - pow(2.0, a)) - 1.0;
    vec2 spiral_uv = vec2(spiral_u, spiral_v);
    vec3 color = vec3(mod(spiral_uv, 1.0), 0.0);
    gl_FragColor = vec4(color, 1.0);
}

The result looks like this screenshot.