godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.16k stars 97 forks source link

Add an option to fix the Z-forward vector when importing a GLTF file #6198

Closed geowarin closed 1 year ago

geowarin commented 1 year ago

Describe the project you are working on

A 3D Game.

Describe the problem or limitation you are having in your project

The GLTF specification says:

glTF uses a right-handed coordinate system, that is, the cross product of +X and +Y yields +Z. glTF defines +Y as up. The front of a glTF asset faces +Z.

Which, for some reasons, contradicts Godot, which recommends that -Z be the forward direction.

In blender, if I have a character set up the conventional way:

Front view with -Y forward Front view with -Y forward

I export it as gltf and import it into godot, my character is facing the wrong way.

Front camera is showing the back of my character. Front camera is showing the back of my character (he is looking towards +Z)

image

This is what I found about GLTF decision:


This is not a discussion about which convention is the "right one".

Changing the Z direction (or any other axis) in the editor has already been discussed multiple times and rejected. This is a core design decision of Godot.


I don't want to manually flip all my characters so that they are facing the right way in Godot. The vast majority of 3D tools with GLTF export will consider +Z as the forward direction.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

I suggest adding an import option for GLTF, FBX and blend files (they are all essentially importing GLTF) that allows users to flip the meshes and skeletons by 180° around the Y axis.

It should be convenient for users to use this as the default for all 3D imports.

Maybe this should even be the default behavior, otherwise meshes will be facing backwards most of the time.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

A checkbox in the importer labelled "-Z is forward (godot convention)" or something like that.

If this enhancement will not be used often, can it be worked around with a few lines of script?

One could write a custom import script that flips the root node. But I think it is a question of having good defaults: using any model generated by 3D tools that export to GLTF will face backwards in the editor.

Is there a reason why this should be core and not an add-on in the asset library?

This reduces confusion when people use default methods like look_at and copy code from official tutorials, while using the vast majority of available 3D assets.

QbieShay commented 1 year ago

This is interesting, I am not really familiar with the importer, can you explain what kind of problems you anticipate for this feature to be implemented?

@geowarin 3d coordinate spaces are a bit messy. Say for example, in the importer we just flip every z coordinate. Cool right? it should be just what we want and what we've been discussing ..?

Not quite. To understand this you have to understand convention for cross products and coordinate spaces. @aaronfranke gave an in-depth explanation, but I'll illustrate the bases (pun intended)

Freya holmer has a nice diagram about different coordinate systems: https://twitter.com/FreyaHolmer/status/1325556229410861056?lang=en

You could deduce a 3D basis ( imagine it as a point of reference of a 3D space ) just by two vectors, instead of three, because the third vector can be inferred by making a cross product of of the first two, in the right order. Which way the third vector points, depends on the convention that you choose. Left hand or right hand (you put first vector on the thumb, second on the index, and then you point your middle finger away from your palm: you'll see that if you contort a bit and align both your thumbs and your indexes, your middle fingers will point in opposite direction for your two hands).

Flipping the Z axis, as-is, means changing the entire coordinate system convention for that model. Because Godot uses another coordinate systems, then interpreting rotations of the bones and the way they skin to the mesh will become really problematic. You'd end up with bones rotating in funny ways around axis you don't expect and your character being most definitely in pain :D

Like aaronfranke pointed out, simply rotating the model does still create some inconsistencies on what's right and left in the model. Likely, it can be still worked with, but i hope this comment sheds at least a bit of light of why it's not something that can be fixed just by snapping fingers.

will it be default

I don't think it should not be on by default, otherwise everyone that has imported models now will have them flipped around. It can however be a project setting to be set as a default, so it needs to be changed only once per project, which to me seems ilke a reasonable compromise.

EDIT: using bold to highlight parts of the text that imo are crucial to understand the big blorb i wrote. I mean in no way to "shout" with it.

TheDuriel commented 1 year ago

Godot 4 is not out yet. If this were to make it in, it could be one by default. And disabled by the 3.x to 4.x project converter.

Realistically it's not going to make it in.

Flipping the Z axis, as-is,

Would result in the model ending up mirrored as well. So it needs to be rotated.

QbieShay commented 1 year ago

Godot 4 is not out yet. If this were to make it in, it could be one by default. And disabled by the 3.x to 4.x project converter.

Godot4 is in beta stage, no more compat breaking changes.

Would result in the model ending up mirrored as well. So it needs to be rotated.

Yup! That as well. I was trying to start from the easiest hypothetical ( "why don't we "just" move forward to +z") as a base to talk about coordinate systems and why they are nontrivial to work with.

aaronfranke commented 1 year ago

I opened a PR to add an import option for this: https://github.com/godotengine/godot/pull/72753

Also worth noting is how GLTF is not self-consistent with how it defines forward. The camera spec defines forward as -Z (as a behavior of the camera's orientation), while the coordinate spec defines forward as +Z (as a convention).

Screenshot 2023-02-05 at 5 48 35 AM

At a glance, this may seem fine, and it works for placing a camera in silly little scenes with a single prop. However, when you think about it more, if you want two objects to face each other - doesn't that mean that one of them should have a transform rotated the other way? Going further, it completely breaks down for the cases you actually use cameras for, where you expect cameras to face the same direction as the assets, like for player characters (I rotated mannequiny):

Screenshot 2023-02-05 at 5 56 09 AM

Also worth noting is how GLTF is not self-consistent with how it defines scale. GLTF defines the unit of distance as meters, but boom box sample asset used in the spec is 0.02 units in diameter, which would make it 2cm. That's way too tiny for a boom box. The inconsistent conventions leads me to believe that the person who wrote section 3.4 of the GLTF spec, and made the boom box, was not communicating correctly with the writers of the other parts of the spec. Or maybe it was ruined by a committee settling on an inconsistent compromise.

Out of curiosity, I also checked how Blender defines cameras. They... point down by default. Interesting choice.

Godot is self-consistent, the rest of the world is not. So now we have to add compatibility options. ¯\_(ツ)_/¯

QbieShay commented 1 year ago

Godot is self-consistent, the rest of the world is not. So now we have to add compatibility options. ¯_(ツ)_/¯

I think what's important for Godot is to add ease of use, and rotating all your models 180degrees and adding a pivot is something that (imo) Godot could take care of, since it's something that's consistently a hassle across 3D projects.

QbieShay commented 1 year ago

After a lengthy discussion with other maintainers, it is clear that this issue is not as simple as it appear. Thanks to @aaronfranke 's attempt at a rotation, i think it's obvious why just rotating the object doesn't work. Importer maintainers have voiced their concern over adding complexity to the importer by adding extra rotations, and other maintainers have voiced concern over possibly adding extra convetions or look_at methods and so on.

It's clear to us that this is an involved discussion that needs to happen in a moment that does not have a massive release coming which is already in feature freeze.

To the people experiencing this as an issue: please be patient. You can write your own post-import script that adds an extra node on top of the hierarchy to rotate the model. Once we settle on a solution for this, we'll update this thread.

For now, there's no point in continuing the discussion. We need to take our time and gather our ideas on how to best address this in the best way possible and with the lowest impact possible on the various areas.

To Godot users pitching in this thread, thanks for your feedback. It has sparked a lot of discussion and allowed us to look deeper into things that turned out to be more complex than we thought.

To maintainers participating, thanks for putting your energy into this. Your input has been very valuable and allows people reading to understand the complexity of the topic at hand.

fracteed commented 1 year ago

Sigh, I really wish this was never changed in the first place, since it worked fine in early 3.x versions. People can argue semantics about the which way front is based on the axis, but having a front view should adhere to the way it works in every other 3d package out there.

I have used most 3d packages over the years and regardless of their worldspace up axis, they all have the front view based on what you see in the top view. If a character in the top view is looking down (in screen space), then this is the direction that the front camera should be looking towards. As can be seen from this screenshot in blender. I have put the arrow in to indicate this direction. This is what artists expect and is the way that most people would model and rig a character. It doesn't matter if it is a y-up or z-up package or negative/positive in the view direction.

front_down2

I currently have my front hotkey mapped to rear in godot, so I have learned to just ignore what the godot viewport label says. The best way of solving this issue is to make an option in the preferences so that front view can be set to either positive or negative z direction. Surely, this would keep everyone happy?

Having an option to rotate 180 degrees on import is just going to cause more confusion and is an attempt to correct a bad default. Most Godot users are going to model their assets in Blender, Maya or Zbrush and they all adhere to what I describe above.

QbieShay commented 1 year ago

Sigh, I really wish this was never changed in the first place, since it worked fine in early 3.x versions.

Was it different in 3.0? I think models have always been facing +z

fracteed commented 1 year ago

@QbieShay not sure as I was using dae back then. What I am referring to is the way that the front ortho camera works in Godot which has changed since then. It used to be consistent with the way Blender or Maya, etc worked.

As far as i can tell, the OP is having issues with what front ortho looks like in Godot, as it is the reverse of the conventional way (as used by blender). The model has been imported (presumably) correctly into Godot, but the Godot front camera is what a rear camera is doing in Blender. This is why I was suggesting having a settings option to orientate the front ortho camera in Godot to be the same as Blender. This way the front camera is consistent between Blender and Godot and is what most artists would expect.

aaronfranke commented 1 year ago

A short summary of PRs working on fixing this problem in different ways:

From @aaronfranke:

From @TokageItLab:

From @reduz:

des1redState commented 1 year ago

Just confirming that I'm another user experiencing this issue (sorry for any spam). Is there a workaround for now?

Zireael07 commented 1 year ago

@des1redState A workaround is to parent your model to an empty Spatial and rotate said empty spatial to however you want

aaronfranke commented 1 year ago

All PRs addressing this issue have been either merged or closed, and as far as I know all engine developers are satisfied with the current state. Therefore, I am closing this PR as resolved. 🎉

In addition to the list of engine PRs I made above, the 3D asset direction conventions have been documented on the Importing 3D scenes page. This page describes briefly, but dense with detail, how local and global directions work in Godot, Blender, and GLTF.

I have some closing notes to hopefully help clarify things. Much of this is focused on terminology and is redundant with the documentation. Pay attention to the terminology: "forward" vs "front".

r3a1d3a1 commented 4 months ago

New to Godot (4.2.2) and totally confused about axes.

Which one does "Front View" translate to? "Looking from the back towards front" or "Looking from the front towards the back"?

I'd normally think it's the latter, but people saying front is -Z makes me think the former definition is true. Up is down, left is right I suppose.

TokageItLab commented 4 months ago

"Forward" is an azimuth and "Front" is a side of the surface.

Forward indicates the direction in the global space and is -Z. In this case, Camera forward and Light forward are -Z because the direction of the camera and lights conform to space.

On the other hand, in OpenGL's right-hand coordinate system, the model is defined as facing the camera, so Model front is +Z. See also https://docs.godotengine.org/ja/4.x/classes/class_vector3.html#class-vector3-constant-forward.

Then, "Front View" can be expressed as "a view that allows the user to see the front side of the model".

Edit from aaronfranke: Fix front/forward mixup, it can be confusing even for experienced devs.

r3a1d3a1 commented 4 months ago

I selected a few different nodes and I always got the same view from "Front View", so it's model-independent aka a global thing. On that basis, it should've been named "Forward view" albeit, still weird, since it looks from the front to the back by default, contrary to what a normal human would consider "Forward".

TokageItLab commented 4 months ago

It is certainly model-independent, and one that can look front side of the model when the model is placed at global origin with initial basis.

This allows the user to notice when the user has imported the model in the wrong orientation. Front View is also a convention, and Blender and others have adopted the name Front View. Well, BTW, I think it would be fine to make a proposal to implement something like Model Front View in Godot.

r3a1d3a1 commented 4 months ago

I noticed this and I think @romlok has a good point. On that note, I believe if current views are to remain to global/model-indepedent, they should adhere to the naming used here. Therefore, and to polish @romlok's idea, if "Front view" is to become "Look Forward", then "Top view" has to become "Look Down", "Bottom view" -> "Look Up", "Rear view" -> "Look Back", "Left" -> "Look Right", and "Right view" -> "Look Left". Essentially, naming based on the vector of the view. The simple change of labels from the noun "view" to a verb "Look" helps a ton in avoiding any confusion, especially for the cases of right, left and back.

Of course changing the views to be model-dependent is also an option.

P.S. Would be great to change "Back" to "Backward" in here to align it better with "Forward" and avoid any possible confusion with its interpretation as "rear" in colloquial English.

TokageItLab commented 4 months ago

There should be no chance to rename the View, as it would be inconsistent with other DCC software and more confusing; Do you make suggestions that for other DCC software too? It is also unnatural as a word. "View forward" is understandable (although that is not a noun), but "Forward view" is strange. Well, I have not seen any software that adopts it. It might be appropriate as a function name, but not as an enum. Given the colloquial explanation in any tutorial or document, it should be a noun.

Changing BACK to BACKWARD might be a good point (then, LEFT and RIGHT should also be LEFTWARD and RIGHTWARD), but that is all.

r3a1d3a1 commented 4 months ago

My last edit was before your reply, so I wonder if you replied from an email. Anyhow, I suggest you re-read my comment.

As for other softwares, I won't comment if they have such discrepancies in their usage of terminology as in Godot that needs to be fixed.

aaronfranke commented 4 months ago

Changing BACK to BACKWARD might be a good point (then, LEFT and RIGHT should also be LEFTWARD and RIGHTWARD), but that is all.

That would also imply UP becomes UPWARD and DOWN becomes DOWNWARD.

I'm in favor of using simpler names when possible. We only use "Forward" because "Fore" isn't a common English word.

r3a1d3a1 commented 4 months ago

I mentioned that as P.S. because it wasn't that important, though certainly an improvement. I hope it doesn't distract from the main issue.