godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.11k stars 69 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.

geowarin commented 1 year ago

At least, the documentation about importing from blender should acknowledge the problem and give users a viable solution.

TheDuriel commented 1 year ago

Uhm...

In Blender, your character is looking towards -Y.

In Godot, your character is looking towards -Z.

This is consistent across both and the GLTF spec you quoted. We only swapped letters, not directions.

The difference here is not that the character is rotated in an unexpected direction, but that the camera is on the other side. The editor camera is placed at a positive Z coordinate, while in Blender it is placed at a negative Y coordinate. There is nothing functionally wrong here.

And to me this makes sense, since for the purposes of gameplay we want to consider viewing a character from their back side. Not just player controlled models.

image


We could add an option to automatically rotate imported models 180°... but then you'd have to flip them back around the moment you want to make them move "forwards".

TheDuriel commented 1 year ago

Maybe the real "issue" here, is that the camera defaults to the wrong location.

geowarin commented 1 year ago

Nope. Character is looking towards +Z in Godot. That's the problem.

image

EDIT: I've added captions to the proposal for more clarity

TheDuriel commented 1 year ago

Huh, can confirm.

I was under the expression from my past uses of Godot 3D that this was not the case.

In that case though, no need for a proposal. That's a straight up bug. The importer is actively rotating the model, already.

geowarin commented 1 year ago

@TheDuriel Are you sure this is a bug? I've looked quickly at the importer code and I see no extra rotations being applied other than the one described in the GLTF file.

This seems to be the core of the issue: conflicting conventions between gtlf and Godot

Flavelius commented 1 year ago

-redacted- (my previous text was partially incorrect) I also think this should be an import option as both ways could potentially be desired

fire commented 1 year ago

Historically as the group who proposed adding this to Blender we think the fortune algorithm and the temperance algorithms are a bad idea because it breaks bones. https://github.com/KhronosGroup/glTF-Blender-IO/issues/1662 @lyuma Also I think we’ve implemented this 3-6 times in Godot Engine.

jtnicholl commented 1 year ago

I think it'd be better if Godot followed convention and treated +Z as forward. Fixing the editor camera would be simple, though changing methods like look_at would break compatibility.

TheDuriel commented 1 year ago

I do not understand Z+ as forwards to be a common convention at all.

Calinou commented 1 year ago

I think it'd be better if Godot followed convention and treated +Z as forward. Fixing the editor camera would be simple, though changing methods like look_at would break compatibility.

There is no set convention for 3D software: https://docs.godotengine.org/en/latest/tutorials/3d/introduction_to_3d.html#coordinate-system

Flavelius commented 1 year ago

I do not understand Z+ as forwards to be a common convention at all.

It's easier to visualize and more practical to use because when you look top down x & y(then z as up-direction) will still be positive (just like you expect the original y up as being positive) and projections and math you do in this view don't have to be value-flipped on one axis to map to memory indices. It also practically aligns with how humans also tend to associate negative with backwards and positive with forwards, as in time and speed which maps perfectly to motion and thus vectors.

TheDuriel commented 1 year ago

A camera inherently views into a space. That space is negative, since it is inside your monitor.

There is an equivalent amount of analogies that can be made to explain either direction as the default.

From a technical standpoint, Z- is correct for cameras. And since cameras look "forwards", that axis should translate to your character models.

In any case This issue is about the fact that: Y- in GLTF becomes Z+ in Godot, when it should be Z-.

Simple as that.

jtnicholl commented 1 year ago

There is no set convention for 3D software: https://docs.godotengine.org/en/latest/tutorials/3d/introduction_to_3d.html#coordinate-system

Maybe "convention" is not the best term, but it's the most common. (At least, right-handed Y-up is, not as sure about +Z being forward.) And the fact that it's not completely standardized is very annoying, I get tripped up often going between Blender and Godot.

Besides, Godot is not even consistent about Z+ being forward, for example the advanced scene import window opens showing the Z+ side of the scene facing the camera. If Z- is forward that means it's opening backwards.

In any case This issue is about the fact that: Y- in GLTF becomes Z+ in Godot, when it should be Z-.

Simple as that.

No? The GLTF specification states that Z+ is forward, not Y-. This is directly quoted in the proposal. If you mean Blender is converting Y- to Z+, that's what it's supposed to do.

The fix is to either rotate imported GLTF files 180 degrees around the Y axis, or treat Z+ as "forward". I was just saying that I would prefer the latter.

TheDuriel commented 1 year ago

The fix is to indeed, to offer an option to rotate the axis upon import, and to enable it by default. So that the model does not flip from blender to godot.

No change to godots forward axis needs to be made at any point. It's completely irrelevant that it is Z-. Literally, you will never interact with that fact while you are modelling, animating, or programming your game. In the former cases, the perceived difference should be handled by the export/import steps. And in the latter case you are working with the FORWARDS constant provided by Godots various types.

Lets not make this proposal about something it's not.

An alternative Fix would be to advise Blender users to configure their axies before export, something blender is fully capable off. And which is a standard step in asset production targeting specific formats. But Godot should be nice enough not to ask of you.

jtnicholl commented 1 year ago

It's completely irrelevant that it is Z-.

If it didn't matter, we wouldn't be discussing it.

Lets not make this proposal about something it's not.

The purpose of proposals is to make a suggestion, and have a discussion on whether it should be implemented and how. Mentioning an alternative is not off-topic.

An alternative Fix would be to advise Blender users to configure their axies before export, something blender is fully capable off. And which is a standard step in asset production targeting specific formats. But Godot should be nice enough not to ask of you.

I just said that Blender's GLTF exporter behaves as it should. Nothing about that part of the pipeline should change, if it did it wouldn't be complying with the GLTF standard.

TheDuriel commented 1 year ago

It doesn't matter that it's Z- or Y+. It matters that the model is facing BACKWARD.

QbieShay commented 1 year ago

It seems to me that there are enough points of agreement here to converge this conversation:

  1. The models are currently facing backwards. This is an issue.
  2. Godot uses -Z forward and we do not want to change that (it's a really gigantic change to do and it 100% not happening)
  3. The likely simplest fix for this would be to offer an optional checkbox upon import, off by default, which would keep compatibility and still offer the feature proposed here

If there's any other point, feel free to add, but otherwise I think that discussing adding Z+ as a forward to Godot is completely out of scope.

Also, it seems like some of you got a bit heated during this discussion. I encourage you to take a pause if that's the case.

QbieShay commented 1 year ago

Also please note that this behaviour has been the case for very long. Comments including "Godot should just do X" downplay the complexities involved when dealing with different space coordinates and skinned meshes. Please be kind and patient.

geowarin commented 1 year ago

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.

For instance, see this and the multiple issues it relates to:

To quote reduz:

This should be closed and any further requests to change how axis work should point to this issue

I've edited the proposal to make this clear


Comments including "Godot should just do X" downplay the complexities involved when dealing with different space coordinates and skinned meshes. Please be kind and patient.

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?

YuriSizov 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?

I don't think it was in reference to the importer. Adding a flag to the importer should be pretty straightforward (though don't quote me on that, file formats for 3D models are a special kind of hell). Qbie's request was more general to the discussion about what should be the correct way, as if this is not a cornerstone of entire rendering, animation, importing, etc systems. Saying that this should be changed to another coordinate system is downplaying the profound effect of such a change on the entire engine.

geowarin commented 1 year ago

Yes sorry, I misread.

So real question: if we decide to implement this feature, should it be the default? It will break all the games that manually flipped imported GLTF or worked around look_at facing backwards.

So if we want to make this the default, it should probably happen before 4.0 is released?

jtnicholl commented 1 year ago

The already rejected proposals that were linked are suggesting a change away from a right-handed Y-up coordinate system, which is not what I was suggesting. I was only suggesting to change the names of the directions. That is a much smaller change.

If even that is too big especially in time for 4.0 that's understandable, and it is perhaps getting a bit off-topic, but I wanted to make it clear what I said.

ghost commented 1 year ago

What about replacing the Root Scale importer setting with a Root Transform? It would solve all of the issues like this without adding settings for compatibility with specific formats.

Flavelius commented 1 year ago

What about replacing the Root Scale importer setting with a Root Transform? It would solve all of the issues like this without adding settings for compatibility with specific formats.

With Transforms you only have rotation and scale available for adjustments where scale introduces other issues (with colliders, mesh normals and probably more), and using rotation results in the x axis being flipped too, so this likely won't be enough.

jtnicholl commented 1 year ago

With Transforms you only have rotation and scale available for adjustments where scale introduces other issues (with colliders, mesh normals and probably more), and using rotation results in the x axis being flipped too, so this likely won't be enough.

Just rotating would be enough for GLTF, it doesn't just treat Z+ as forward, but also X+ as left. Although, there's other formats which don't have their coordinate systems 100% standardized, so having transform options may be useful for those. We can flip the normals again after scaling, and apply colliders afterwards, so I don't think that's an issue. I can't think of anything else that would be a problem.

Flavelius commented 1 year ago

Just rotating would be enough for GLTF, it doesn't just treat Z+ as forward, but also X+ as left.

Interesting, i didn't know and expect that it defined +x as left; Coordinate space conventions truly are a wild west.

I can't think of anything else that would be a problem.

I also remember animations as something that breaks when negative scale is applied (even sometimes does in unity these days, when exported from blender)

TokageItLab commented 1 year ago

It is a glTF specification that the asset must be oriented in the +Z direction.

https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#coordinate-system-and-units

So I assure that importing the -Z axis as forward in Godot's importer will never be supported in the core.

If you absolutely need it, you just write it as an import plugin.

TheDuriel commented 1 year ago

A forward facing model in GLTF, should arrive forward facing in Godot. Without an additional rotation being applied by the user.

To be clear, models are not arriving flipped. They are arriving facing 180° from where they are expected to be.

The cleanest way to ensure that models arrive facing the same direction they were exported in, is to allow the user to specify the forward direction in the importer. Since the importer will need to rotate the entire stored scene around the origin.

A post import script via editor plugin can't handle that.

The ugly way, would be to apply a 180° rotation to the root node of the imported scene and leave it that way.

TokageItLab commented 1 year ago

PathFollow3D also treats +Z as forward. What are you actually saying about the thing in Godot that treats -Z as forward? If it exists, we should fix that method.

TheDuriel commented 1 year ago

https://docs.godotengine.org/en/stable/classes/class_vector3.html#:~:text=Down%20unit%20vector.-,FORWARD,-%3D%20Vector3(%200

Vectors, Transforms, Cameras, and Spatial Rotations, all treat Z- as forwards.

This would imply that PathFollow3D is inverted.

image

^Above: The default camera view direction in the 3D editor.

image

jtnicholl commented 1 year ago

The editor camera should default to looking backwards, that means it's looking at the front of the scene.

TokageItLab commented 1 year ago

Indeed... Personally, I think Vector3.FORWARD should be +Z, but I don't know how much of an impact that would cause. But, as long as we keep the right hand coordinate system, I don't think that many modifications will be necessary.

However, most importantly, we are now just before 4.0 RC. To change it now is quite horrible.

As for the camera facing backward by default, I don't see a problem. It is affordance viewing the asset from the front by default. If the asset is to be imported with -Z as forward, then the default camera placement would need to be reversed as well.

TheDuriel commented 1 year ago

SO ANYWAYS.

Now that all the newcomers to the thread are up to speed on Godots forward direction, and the unchangeable nature of it. (Scroll up.)

The GLTF Importer is applying a 180° rotation to imported models. This is wrong. It needs changing. And doing so before this gets locked in for the entire lifetime of 4.x is probably a good idea.

Because if not now. Then when? Certainly we don't want to break everyone's 4.0 projects with 4.1.

geowarin commented 1 year ago

A little off topic but PathFollow3D is indeed inverted: https://github.com/godotengine/godot/issues/53837

jtnicholl commented 1 year ago

People misinterpreted/misread what I wrote. What can't be changed is the right-handed Y-up system. Switching forwards with backwards and left with right hasn't been proposed before (AFAIK). While I still agree it's probably too big to do right before the RC, it doesn't require changes to the underlying math, just some renaming. And Godot is already inconsistent with these labels anyways.

Though for now, we should do something that doesn't break compatibility. Making Z+ forward can be discussed in a separate proposal for 5.0.

Also, please stop shouting at people in all-caps and bold text.

TokageItLab commented 1 year ago

it doesn't require changes to the underlying math, just some renaming.

I agree.

I have most worked for animation with glTF assets. But to be honest, I never noticed that -Z is labeled Forward until now. Since the asset needs to go forward, I had no idea that the PathFollow3D direction was the other way around.

Yes, I think it is possible to just rename it.

    _VariantCall::add_variant_constant(Variant::VECTOR3, "LEFT", Vector3(-1, 0, 0));
    _VariantCall::add_variant_constant(Variant::VECTOR3, "RIGHT", Vector3(1, 0, 0));
    _VariantCall::add_variant_constant(Variant::VECTOR3, "FORWARD", Vector3(0, 0, -1));
    _VariantCall::add_variant_constant(Variant::VECTOR3, "BACK", Vector3(0, 0, 1));

    _VariantCall::add_variant_constant(Variant::VECTOR3, "LEFT", Vector3(1, 0, 0));
    _VariantCall::add_variant_constant(Variant::VECTOR3, "RIGHT", Vector3(-1, 0, 0));
    _VariantCall::add_variant_constant(Variant::VECTOR3, "FORWARD", Vector3(0, 0, 1));
    _VariantCall::add_variant_constant(Variant::VECTOR3, "BACK", Vector3(0, 0, -1));

Whether good or bad, core uses vector with direct numerical values inside core instead of using constants such as Forward, so the renaming will not affect core's behavior. (However, it may destroy the user's project)

If do that, I feel it is strange that the camera and lights irradiate backwards, but that can be fixed in 4.1 or 5.0 in the future. Probably the only things that actually need to define forward as a Node are Camera3D, SpotLight3D, and PathFollow3D.

In most other cases, users can assign any vector as Forward, and there, Forward is just a label.

geowarin commented 1 year ago

Ok so in this case, we should make the front view to be Z+, which was changed on Feb 2021 and fix look_at, which considers Z- to be forward.

Funnily enough, on the topic of look_at, people were having a very similar conversation to the one we are having right now.

TheDuriel commented 1 year ago

I don't know why we are having this conversation whatsoever. It does not relate to the problem at hand.

geowarin commented 1 year ago

I don't know why we are having this conversation whatsoever. It does not relate to the problem at hand.

Well, we assumed that changing the forward direction would be a massive undertaking but if it is only:

Then we can have the same convention as GLTF and thus we are solving the issue in a much more elegant way.

TheDuriel commented 1 year ago

Then we can have the same convention as GLTF

Which was never the question.

And does that mean that when, after this change, Godot does not follow the forwards standard for FBX, DAE, USD, or other potential formats, The we then go and change Godots forwards direction again?

When in fact. The problem at hand is the lack of an applied rotation in one specific asset import script?

TokageItLab commented 1 year ago

If the forward vector can be set by the user in the import or project settings, the forward vectors of some Nodes and method must also be changed at the same time, as mentioned above.

So, systemically, "only one vector is forward" is straightforward.

Surely, the problem is that Godot currently defines -Z as forward, but loads the forward of the glTF asset as +Z. This can be solved by loading the forward of the glTF asset as -Z.

But in this case, loading the forward of the glTF asset as +Z should not be an option, for the reasons stated above.


However, in the opinion of myself, @jtnicholl and my modeler friends, it is minority that -Z is forward in the right handed Y-UP coordinate system. Walking animations are usually created so that it approaches the default camera.

The default camera shots the asset's face. And it is common to use the side with the asset's face as the Forward. However unfortunately, Godot uses the asset's hips as the forward vector.

In summary, the confusion is caused by the fact that the Godot's default camera direction, glTF importer and PathFollower3D use +Z as the Forward, but Godot's Vector3, Camera3D, SpotLight3D Forward is labeled as -Z.


And does that mean that when, after this change, Godot does not follow the forwards standard for FBX, DAE, USD, or other potential formats, The we then go and change Godots forwards direction again?

It might happen if a right-hand coordinate format emerges that Godot supports in preference to glTF, but I guess that the chance is almost zero.

I don't know of any format that defines forward as clearly than glTF. Also, since Godot is the most supporting glTF, so I suggest that +Z should be forward to be consistent with the glTF specification.

TheDuriel commented 1 year ago

the problem is

That assets imported by the GLTF scene importer, face the wrong direction.

It's not about convention. If this one singular fact were to be changed. Then it would literally not matter where forwards is.

TokageItLab commented 1 year ago

That assets imported by the GLTF scene importer, face the wrong direction.

That cannot be said without presuming that Godot assumes -Z to be Forward. In fact, Godot is trying to make +Z a Forward in some places (default camera direction, glTF importer and PathFollower3D), as noted above, so it's not just about the glTF importer.

TheDuriel commented 1 year ago

Godot has made it unquestionably clear as to which direction it considers forwards. The fact that, a node or two, get it wrong, does not invalidate this. It instead means that someone needs to write an issue to correct this mistake.

Assets imported by the GLTF importer, face Vector3.BACKWARDS as per the Vector3, transform, basis, and other constants. Necessitating user intervention if the user wishes to move the asset Vector3.FORWARDS.

Other importers make an assumption about what axial system the format uses, and by extension of the original problem that this thread is about, may require additional import settings to be added. That is not in the scope of this proposal however. This proposal is about the fact that the GLTF importer needs to rotate assets 180°. Which is not controversial. And is not a breaking change requiring someone to rename and swap out every direction constant in the engine, from nodes to importers to the renderer.

Flavelius commented 1 year ago

That assets imported by the GLTF scene importer, face the wrong direction.

That cannot be said without presuming that Godot assumes -Z to be Forward. In fact, Godot is trying to make +Z a Forward in some places (default camera direction, glTF importer and PathFollower3D), as noted above, so it's not just about the glTF importer.

Even the documentation states that +z is 'Front' and forwards and only that cameras 'Look Back': https://docs.godotengine.org/en/stable/tutorials/3d/using_transforms.html#introducing-transforms which even coincides with the basis identity (which would be expected to have forward semantics)

TheDuriel commented 1 year ago

Tutorials should be taken with a grain of salt. This one is simply wrong. If you orient your characters to face -Z, then they will walk backwards if you use any of the built in methods without an additional rotation.

Taking the quote "the camera looks back" as being indicative of the entire engine treating Z- as backwards is not a good argument either.

Especially when the tutorial later points out the correct direction. https://docs.godotengine.org/en/stable/tutorials/3d/using_transforms.html#introducing-transforms:~:text=Imagine%20you%20need%20to%20shoot%20a%20bullet%20in%20the%20direction%20your%20player%20is%20facing.%20Just%20use%20the%20forward%20axis%20(commonly%20Z%20or%20%2DZ).

Godots mathematics tutorial written by reduz also points out Z- as being forwards https://docs.godotengine.org/en/stable/tutorials/math/matrices_and_transforms.html#moving-an-object-relative-to-itself

Flavelius commented 1 year ago

Then again if you take the z component from Basis.Identity as in the shoot example, the bullet will fly towards +z, which is expected as the identity basis should have forward semantics. Negating that value just to change forward semantics seems really arbitrary and doesn't make much sense in a user facing context (only maybe for core engine-internals-developers that need to adhere to other constraints of graphic libraries etc.)

The last tutorial in that case also needs to negate (active instruction to change semantics) the basis forward vector.

And from a users perspective, the negation part then spills to user code where it's needed to actively invert values to conform to an overlaid design decision, where it could have been more direct in the first place (which i believed to be one of godot's accessibility goals)

aaronfranke commented 1 year ago

The standard rotation for Y-is-up right-handed coordinate systems is that +X is right and +Z is back (-Z is forward).
The standard rotation for Z-is-up right-handed coordinate systems is that +X is right and +Y is forward (-Y is back).
-Z being forward is implied if we accept these two truths first:

If we spun 180 degrees around Y to keep +Y up to make +Z be forward, then that would also imply that +X becomes left and -X becomes right. That's silly, it is directly contrary to 2D and most expectations (and yeah Godot's 2D has +Y down but uh let's ignore that...). Users expect +X to be right.


Now, let's talk about how this relates to Blender -> GLTF -> Godot:

Godot and Blender both use the same handedness, right-handed. The difference is that they are rotated 90 degrees around X relative to each other. This is why +Y in Blender is -Z in Godot, and -Y in Blender is +Z in Godot. This is the correct mapping.

GLTF itself uses Y-is-up right-handed, the same as Godot. The program doing the conversion is Blender. Blender is (correctly) mapping its +Y to GLTF -Z and its -Y to GLTF +Z. @TheDuriel Godot is NOT "applying a 180° rotation to imported models". Neither is Blender.

If we want to add an option to the GLTF importer to spin the model 180 degrees, that's fine, but that's an extra feature we are adding. It's not a bug. The models are being imported exactly as-is. Godot is not doing any conversions whatsoever right now. We can just add a bool/checkbox to the importer that does this (anyone want to bikeshed on the name? something like "rotate 180 degrees around Y"), which will default to false, just like the OP proposes.

Even the documentation states that +z is 'Front' and forwards and only that cameras 'Look Back': https://docs.godotengine.org/en/stable/tutorials/3d/using_transforms.html#introducing-transforms

Sorry that this has caused you confusion. This article is really bad, it needs to be rewritten from scratch. I've known about it for years, but I keep forgetting about it...

Flavelius commented 1 year ago

I did a few more tests in godot and blender and i stand corrected that the forward semantics atleast are consistent between both, (which then applies to gltf aswell), through models and shader logic:

grafik

BlendImportAxis.zip

This makes it a little less of an issue for my case. It's still some (mental/performance) overhead for flipping z in code for the rest of the worldspace logic, though not ideal, i can live with that; it's the better alternative for me, than flipping things in blender and in shader

Edit: The difference in blender is how they seem to treat 'front' for the camera perspective (menu option), blender puts it on the opposite axis as godot, so one treats it like a look-at and the other as a look-with)