KhronosGroup / glTF

glTF – Runtime 3D Asset Delivery
Other
7.16k stars 1.14k forks source link

Forward vector convention #1043

Closed bghgary closed 6 years ago

bghgary commented 7 years ago

The current text in the README.md says this:

glTF uses a right-handed coordinate system, that is, the cross product of X and Y yields Z. glTF defines the y axis as up.

Which way is forward? This is apparently a lot of discrepancies between viewers, tools, and even the samples in the sample repo.

My understanding of the state of viewers/tools

Maya/Max: right-handed, +Z is forward Toolbag: right-handed, +Z is forward Blender: right-handed, +Z is up, -Y is forward Unity: left-handed, +Z is forward Unreal: left-handed, +Z is up, +X is forward

glTF is right-handed. Should -Z be forward or +Z be forward? Without this definition, it is hard for authors to decide which way to place the content.

Edit: Blender is -Y forward

emackey commented 7 years ago

This is also mentioned in README.md for the TextureCoordinateTest model.

Looking at the POSITION attributes min/max, you can see that the left side is +X, the top is +Y, the back plane is +Z (facing away from the default camera), and the default camera sits on the -Z side looking toward the origin with +Y up. The "front" of the model faces -Z, and this is reflected in the NORMAL accessors of all except the back plane.

This model does not contain a camera. It correctly faces the default camera in BabylonJS, ThreeJS, and the glTF-WebGL-PBR reference.

I suggest we embrace this behavior as correct, as many sample models face this direction.

lexaknyazev commented 7 years ago

Just for convenience, from Cameras:

A camera defines the projection matrix that transforms from view to clip coordinates. The projection can be perspective or orthographic. Cameras are contained in nodes and thus can be transformed. Their world-space transformation matrix is used for calculating view-space transformation. The camera is defined such that the local +X axis is to the right, the lens looks towards the local -Z axis, and the top of the camera is aligned with the local +Y axis. If no transformation is specified, the location of the camera is at the origin.

emackey commented 7 years ago

the lens looks towards the local -Z axis

So, the spec says to look the opposite way from most of the WebGL-based implementations, unfortunately.

the location of the camera is at the origin.

This doesn't seem an ideal place for a camera. Most models naturally center themselves on the origin, or place their pivot point or center of gravity on the origin, etc.

bghgary commented 7 years ago

@emackey

the lens looks towards the local -Z axis

So, the spec says to look the opposite way from most of the WebGL-based implementations, unfortunately.

This statement only applies to the local space of the camera. I think this actually implies that it matches what most implementations are already doing. See last paragraph.

the location of the camera is at the origin.

This doesn't seem an ideal place for a camera. Most models naturally center themselves on the origin, or place their pivot point or center of gravity on the origin, etc.

Similarly, this only applies when a camera is defined but no transformation is specified. I don't think this implies where the default camera should be.

That said, I think the forward convention of the camera does indirectly determine what the forward convention of the asset should be. Suppose I attach a model of a camera to the node of a camera. I would expect that the forward vector of the model to match the forward vector of the node, without additional transformations. Given this, I would expect the forward vector of the asset to match the conventions of the camera. If this is correct, then -Z should be the forward vector for the asset.

emackey commented 7 years ago

@bghgary Great to hear.

For reference, on the TextureCoordinateTest model I mentioned above, the normal vectors across the front face of the model do indeed face -Z [0, 0, -1] (source). This means -Z is "forward" for the asset, and the camera is placed with a -Z offset, looking back toward the origin and beyond that toward the +Z axis.

javagl commented 7 years ago

It's good to occasionally see the own views (literally) questioned. For me, until now, there was no doubt that there was no such thing as a "forward vector". The coordinate system is defined to be right-handed. Without a transformation, the camera (eye point) is defined to be at the origin, and the view direction of the camera is along the negative z-axis.

So at the risk of embarassing myself: Could someone explain what "forward vector" should actually mean here?

(It sounds like you wanted to introduce some sort of "default transform" for the camera)

pjcozzi commented 7 years ago

Original forward vector discussion: #22

emackey commented 7 years ago

@javagl To me, the "forward vector" means which side is the "front" of a model: The headlights of a car, the nose of an aircraft, etc., should all face the forward vector.

javagl commented 7 years ago

@emackey I wonder in how far this is an issue of the spec. If someone wants to create a "top-down-view" game, the aircraft nose may point in -z-direction. For a sidescroller, it may point in +x-direction. But this is also just based on the default/conventions for the camera. Beyond that, these are just "arbitrary" coordinate systems.

Or to put it that way: Imagine, the "Forward Vector®" is officially defined to be +z. Who will be affected by that, in which way?

(Is the goal of this to have the model in a "nice" orientation when viewn with the default camera? This will hardly work, with the camera (eye point) being at the origin. However, I also noticed that, for example, the "Damaged Helmet" sample model was looking away from the default camera. (This might be a mistake on my side, but I'm afraid that some viewers do not use the default camera by default...))

emackey commented 7 years ago

If I'm not mistaken, Gary's comment above is that the "default camera" in most viewers should not be the same as a supplied camera node with zero transformations. Placing the actual default camera at the origin makes no sense for any viewer app. So when no camera node is supplied, the app places a camera automatically, wherever it's best for the app, typically looking at what it hopes might be the front of the model, and typically taking the total model size into account.

But you're right, this is all arbitrary, every app does this differently.

javagl commented 7 years ago

OK, this clarifies the goal of this issue. It would then, in hindsight, have made more sense to define the default camera differently (e.g. like "The default camera is looking along -z and placed like this-and-that, so that the unit cube is fully visible") - i.e. the main issue here is that the camera is at the origin, and most models will not be sensibly visible then. However, fixing this on spec-level now is difficult. Maybe someone has an idea. (Maybe one could give a recommendation, like "Viewers should/could move the camera along +z until the bounding box of the object is contained in the frustum", but this would only be sort of an implementation note...)

emackey commented 7 years ago

Ideally, if we find a bunch of glTF files of cars online, we won't find one car driving +Z and another one driving -X and another +X. We would like assets to know which way is front, for the same reason we like them to know which way is up. But of course, individual apps and individual assets are free to use any arbitrary coordinate frame they like.

The reference app, and most of the online viewers, use a convention like this:

sample_camera_car

Here, "App's camera" is not part of the glTF. The glTF contains one camera node, dash_cam, and this node has a translation from the origin, but no rotation. As such, the dash_cam node "faces front" like the rest of the asset.

The app's default camera, portrayed here, sits in the front (-Z) and looks toward the back (+Z). So by default, it's essentially looking the opposite direction from a typical camera node with no rotation.

McNopper commented 7 years ago

I recommend that -z as forward for any node element in glTF 2.0.

The rest is derivable.

javagl commented 7 years ago

@McNopper Is it right that this would mean that the default camera (which is at the origin, looking along -z) would always have to be

  1. rotated about 180° around the y-axis
  2. be moved ("backwards") along -z

in order to see the "front" of the model?

McNopper commented 7 years ago

With derivable, it is up to your application, where you want to place the default camera.

For a basic viewer, to see the front, yes, your approach is right.

pjcozzi commented 7 years ago

@cedricpinson @aurl we are planning to define +z as forward so the coordinate system is right handed. This is what the Blender exporter and many apps do, and we would like to make the entire glTF ecosystem consistent.

What do you think about this for Sketchfab?

AurL commented 7 years ago

@pjcozzi For info, Sketchfab is ZUp right-handed (+Y forward), and we convert to YUp during export. We probably need a 180° rotation around y to be compliant. We will update this on Sketchfab, thanks for the ping 👍

pjcozzi commented 7 years ago

@AurL very nice, thank you!!!

sbtron commented 6 years ago

Below is a list of tools/assets that need to be updated to use +z as forward. I have also identified some folks with each tool that could help update it. Please let me know if you can't help update the tool associated with you.

Sample Models

As far as I know all other tools including Blender, Substance Painter, 3DS Max exporter through Babylon, Sketchup, Paint 3D, Minecraft are already exporting +z.

I haven't been able to look into all the loaders beyond three, babylon and the Unity importer. Would appreciate any help on that :). Once we get the sample models updated it would be obvious which loaders are flipped and need updating.

@pjcozzi Do you also want to update the spec with this convention?

pjcozzi commented 6 years ago

@sbtron thanks for compiling this list! Yes, I think we should update the spec. Could be anything from a one liner to including a diagram. Do you want to make the change? :smile:

stevenvergenz commented 6 years ago

Also glTF-Blender-Exporter (@McNopper)

sbtron commented 6 years ago

I believe blender exporter is already +z

McNopper commented 6 years ago

The Blender exporter is swizzling the coordinates anyway: https://github.com/KhronosGroup/glTF-Blender-Exporter/blob/master/docs/developer.md Hope the naming does not confuse, as it is from the "viewers" perspective.

McNopper commented 6 years ago

It is also important to mention, that a default camera is facing to -z: Camera eye/position at (0,0,5) (with default look at direction (0,0,-1)) will see the front face of an object at (0,0,0). But this is already specified and this should not be changed.

pjcozzi commented 6 years ago

@sbtron is UnityGLTF updated? Is that all that is needed to close this issue?

pjcozzi commented 6 years ago

Bump:

@sbtron is UnityGLTF updated? Is that all that is needed to close this issue?

bghgary commented 6 years ago

UnityGLTF was updated a while back.