AMereBagatelle / fabricskyboxes

Custom skyboxes mod for Fabric
MIT License
76 stars 22 forks source link

Trying to improve rotation #86

Open UsernameGeri opened 1 year ago

UsernameGeri commented 1 year ago

In this report, I'll try to propose an idea to try to improve rotation system.

The main idea would be that in order to specify the desired rotation axis, users would need to specify a vector coordinate, rather than a set of degrees. I will explain in a bit why I think this is necessary. Let's take this as our coordinate system:

axis

This sphere represents all the possible points our rotation axis vector can point to. Let's take a random point on its surface, and see how we can reach it from our default stating position:

https://user-images.githubusercontent.com/96586974/234076597-1d45381c-c6a3-4a67-b225-3f5fb575564a.mp4

As you can see, the number of ways we can reach it is basically infinite. We can specify an infinite number of 3 sets of degrees to reach this point. Which can be an issue. However, this point has its own coordinates.

Desktop Screenshot 2023 04 24 - 19 28 27 31

And I believe users should specify this vector instead, and the Euler rotation should happen hidden in the background in whatever way the code would most efficiently allow it. This way, I believe the axis would be much more clearly defined, and people would get a much more solid grasp over their chosen axis.

I would also propose to do away with rotation speed X and Z, and only keep rotation speed Y (the default up/down coordinate in Minecraft). Using the Y coordinate as the default rotation axis, and a full 360° range of vectors, you can map out any rotation. And while a combination of X Y Z rotation can get some really wonky and interesting results, let's be honest here- nobody would ever use it, much less understand what it does exactly.

One obvious question would be, how would people know the coordinates of an arbitrary point on this sphere? Well, most people would simply not want to do such a rotation at all, and the 6 cardinal directions would suffice, as seen in the first image. But in case they would want to do more custom rotations, there is of course the Blender tool I made, which can generate those coordinates for you extremely easily.

vector

Pack makers who are more serious about their skies, can look at the docs, and use the blend file for free. Of course it still takes effort, but it's the easiest solution I think. Or of course they can do the math pen and paper style :D

So that's pretty much it. Of course, this proposal is basically asking to replicate the format of Optifine's rotation, at least on the pack maker's side. This would have the obvious advantage of making conversion and interoperability basically trivial when it comes to rotation, since the values could simply be reused. But moreover, I think Optifne doesn't do rotation this way for no reason, using vectors is probably the most straight forward and most well defined way to achieve custom axes.

Edit: Couple more thoughts

This method would of course also work for static, as you can reach any point on the sphere, so you can naturally remap a point of the texture to any other.

And hopefully this could also be applied to decorations, if we apply them as like a part of a regular skybox

This should also in theory solve the issue of what I call "impotent rotation", which can occur if you rotate on all 3 axis. Though I'm not exactly sure how it works, but it can definitely lead to unwanted behavior. Here you can see that if I rotate axis on its local "axis", nothing really changes, which, while correct, is definitely unintuitive. And static in this case simply makes the texture go further along the rotation path, so to speak. (you can see when I rotate static counter to the animation, it seems to slow down)

https://user-images.githubusercontent.com/96586974/234087861-8de73360-3721-4f69-be89-812777e2fdfa.mp4

Edit 2

Been thinking more about this implementation, and one thing that came to mind, is that using a simple vector would not actually allow static to be fully customized and defined.

For axis a vector is perfectly enough, however, for static you may also would want to rotate the texture along the axis of rotation, meaning its local up/down axis. Basically like this:

https://user-images.githubusercontent.com/96586974/235347646-9800aa65-15f8-403e-9f5c-ea9a02d5a810.mp4

People would have to specify a vector for both static and axis, and there would be an additional object, something like "staticOffset" which would be specified in degrees. So I would propose a rotation object that would look something like this:

"rotation": {
    "rotationSpeed": 1.0,
    "axis": [0.428, 0.598, -0.677],
    "static": [0.428, 0.598, -0.677],
    "staticOffset": 45.0
    }
supsm commented 1 year ago

I don't think the proposed axis changes are necessary or beneficial. There is always a single unique set (between -180 and 180 degrees) of coordinates to reach a certain axis, and the order of applying these do not matter (as shown in your video). However, this is an internal implementation detail and the user will not be concerned with it. On the contrary, the proposed system of specifying a vector would need to allow an infinite number of combinations as the magnitude is not defined; if we only allow unit vectors, not only would pack creation be far more difficult, floating point inaccuracies could have an effect on the magnitude and disallow some axes entirely. Additionally, utilizing degrees to specify an axis (a ray having theoretically infinite length) makes more logical sense than a vector, which has a fixed length. The only real issue with the current system is that the default axis from which the rotations take place is slightly counterintuitive (south instead of north) and not apparent (which can be fixed through documentation).
If this is really the system used by optifine, I believe both my own implementation of conversion in MCPPPP and @FlashyReese's implementation in fsb-interop are incorrect. This is due to the lack of explanation in the documentation, as well as the relative rarity of packs which utilize "nonstandard" rotations (anything not aligned with a standard axis) and the difficulty of confirming that two rotation axes are identical.
In short, I believe the current system to be superior to the proposed system which matches (?) optifine's system, but this post nonetheless is incredibly valuable for developers of interop tools (such as myself and Reese) if it outlines the optifine rotation system.

P.S. Reese if you are reading this I will submit a pr once I implement and convert the "correct" method, hopefully in a few days

UsernameGeri commented 1 year ago

floating point inaccuracies could have an effect on the magnitude and disallow some axes entirely

yeah that's true and it's an issue of Optifine as well. If you input a vector that is not a unit lenght (or very close to it), you will get very glitchy results (skybox will stretch like crazy, rotation speed will slow down and speed up periodically, very weird) Their docs say normalization is not required, but that's bs I think.

Maybe it would be possible to normalize this vector? Since due to floating point coordinates, it will never be exactly one unit lenght. The coordinates while may not be exctly a unit length, it does define a direction clearly.

Also, the reason I think vector would be better, is coz if you look at one on a cardinal direction, you can clearly tell its direction. eg. (0;1;0) clearly points upwards. But where does (0;90;0) point to? It's not clear at all. You would need to know the initial direction, and then you can figure out where does the rotation take it. In this concrete example, (0;90;0) does nothing at all, if the initial direction is upwards. (it's that impotent rotation I described)

FlashyReese commented 1 year ago

(skybox will stretch like crazy, rotation speed will slow down and speed up periodically, very weird)

They are probably using the sun/moon trajectory for skybox rotation. It speeds up and slows down

UsernameGeri commented 1 year ago

No I don't think so, it's entirely up to the vector you specify. If it's just a little smaller or larger than a unit length, the effect will be less noticeable, but if it's off by a lot, the effect gets amplified. I will show examples when I get home.

FlashyReese commented 1 year ago

Trajectory wise it is(in terms of speeding up and slowing down like sun/moon trajectory), the speed they use a different formula.

UsernameGeri commented 1 year ago

This is what I mean by slowing down and speeding up:

https://user-images.githubusercontent.com/96586974/234335069-a9df3879-2794-4744-a210-949ea450f519.mp4

using these specs:

axis=0.0 -2.0 0.0
speed=50.0

It's clearly breaking something in its logic, so a one unit length vector must be used. Normalization could easily solve it.

UsernameGeri commented 1 year ago

added one more point to the post about static

AMereBagatelle commented 1 month ago

This will be resolved with the keyframes system and using quaternions internally.