GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Define the coordinate system · Issue #460 · pygfx/pygfx

Define the coordinate system #460

New issue
Copy link
New issue
Copy link
Open
Open
Define the coordinate system#460
Copy link

Description

@almarklein
almarklein
opened on Feb 17, 2023
Issue body actions

Todo

  • Decide on a coordinate system
  • Document it
  • Document that our coordinates are unit-free, see this comment in this issue for some example explanations for threejs.
  • Modify the look_at functions (cameras and lights should work as they do now, but all other objects should consider +Z the default forward).

What do others use?

pygfx currently we seem to have a right-handed system with right +X, up +Y and forward -Z.

glTF uses a right-handed coordinate system. glTF defines +Y as up, +Z as forward, and -X as right; the front of a glTF asset faces +Z. The units for all linear distances are meters. All angles are in radians. Positive rotation is counterclockwise.

OpenGL by convention uses a right-handed system. What this basically says is that the positive x-axis is to your right, the positive y-axis is up and the positive z-axis is backwards.

Blender uses the right hand coordinate system with the Z axis pointing upwards. This is common with the coordinate systems used by most common 3D CAD packages.

From my understanding, CAD software like 3D studio max and blender historically have Z point upwards, whereas game and gfx related software has Y point upwards. Not sure why glTF swaps directions for X and Z ...

Decision

We've decided to adopt glTF (threeJS did too):

  • glTF uses a right-handed coordinate system. glTF defines +Y as up, +Z as forward, and -X as right; the front of a glTF asset faces +Z.
  • 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.
    The view matrix is derived from the global transform of the node containing the camera with the scaling ignored. If the node’s global transform is identity, the location of the camera is at the origin.
  • For light types that have a direction (directional and spot lights), the light's direction is defined as the 3-vector (0.0, 0.0, -1.0) and the rotation of the node orients the light accordingly. That is, an untransformed light points down the -Z axis. The light's transform is affected by the node's world scale, but all properties of the light (such as range and intensity) are unaffected.

Activity

  1. Korijn commented on Feb 17, 2023

    @Korijn
    Korijn
    on Feb 17, 2023
    Collaborator
    More actions

    Can you clarify in each instance whether or not the coordinate system you describe applies to model/view/clip space? Because the conventions are different between those spaces usually as well.

    Reacted by Almar Klein
  2. almarklein commented on Feb 17, 2023

    @almarklein
    almarklein
    on Feb 17, 2023
    MemberAuthor
    More actions

    Isn't it only the model space that matters? The clip space is an implementation detail (if an application has backends for both OpenGL and wgpu, the conventions for their clip planes would be different in these cases).

  3. FirefoxMetzger commented on Feb 17, 2023

    @FirefoxMetzger
    FirefoxMetzger
    on Feb 17, 2023
    Contributor
    More actions

    pygfx currently we seem to have a right-handed system with right +X, up +Y and forward -Z.

    😆 sigh, so which is it now, does forward mean positive Z or negative Z? 😅

  4. Korijn commented on Feb 17, 2023

    @Korijn
    Korijn
    on Feb 17, 2023
    Collaborator
    More actions

    I found this nice picture: :)

    image

    I would like to add that Three.js is Y-up, and right-handed.

    Also, you can actually change the coordinate system in three like this:

    THREE.Object3D.DefaultUp = new THREE.Vector3(0,0,1);

    But that's all besides the point. We just need to pick something and document it. What do we want?

    Personally, I would prefer to stay right-handed, and Y-up. The Z negative/positive thing seems to be our only real uncertainty here. Let's pick positive Z?

  5. almarklein commented on Feb 17, 2023

    @almarklein
    almarklein
    on Feb 17, 2023
    MemberAuthor
    More actions

    😆 sigh, so which is it now, does forward mean positive Z or negative Z? 😅

    Sorry, I know! I was confused between NDC and model coords! 😆

    To quote Linkin Park: In the end, it doesn't even matter (what we choose). Users can always set the camera's up value, and/or flip the camera's scale to move from a left-handed to right-handed system. The main issue (as I understand it) is that when a user loads left-handed models into a right-handed system (or vise versa) the models will be inside-out. And that only is really a problem when people set the material.side = 'front'.

    The Z negative/positive thing seems to be our only real uncertainty here. Let's pick positive Z?

    From what I understand, given +X is right, and +Y is up, if we'd pick forward to mean +Z it'd be left-handed, and -Z would be right-handed.

  6. almarklein
    changed the title [-]Define on the coordinate system[/-] [+]Define the coordinate system[/+] on Feb 17, 2023
  7. almarklein commented on Feb 17, 2023

    @almarklein
    almarklein
    on Feb 17, 2023
    MemberAuthor
    More actions

    Addition: we're not actually deciding on the coordinate system, but only on the default.

  8. Korijn commented on Feb 20, 2023

    @Korijn
    Korijn
    on Feb 20, 2023
    Collaborator
    More actions

    From what I understand, given +X is right, and +Y is up, if we'd pick forward to mean +Z it'd be left-handed, and -Z would be right-handed.

    You are right. And since we want to be right-handed, let's pick -Z as forward.

    image

    That aligns with three.js defaults.

    • +X is right
    • +Y is up
    • -Z is forward

    Can we close this?

    Reacted by Pan Xinmiao
  9. almarklein commented on Feb 20, 2023

    @almarklein
    almarklein
    on Feb 20, 2023
    MemberAuthor
    More actions

    👍

  10. almarklein
    closed this as completedon Feb 20, 2023
  11. Korijn commented on Feb 22, 2023

    @Korijn
    Korijn
    on Feb 22, 2023
    Collaborator
    More actions

    I'm reopening this because I discovered some new information. Three.js seems to follow the glTF conventions.

    I summarized them here: pygfx/pylinalg#43 (comment)

    I propose that we align with those conventions as well, both in pygfx and pylinalg.

    Reacted by Almar Klein
  12. Korijn
    reopened this on Feb 23, 2023
  13. Korijn commented on Feb 25, 2023

    @Korijn
    Korijn
    on Feb 25, 2023
    Collaborator
    More actions

    So to summarize from the glTF spec:

    • glTF uses a right-handed coordinate system. glTF defines +Y as up, +Z as forward, and -X as right; the front of a glTF asset faces +Z.
    • 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.
      The view matrix is derived from the global transform of the node containing the camera with the scaling ignored. If the node’s global transform is identity, the location of the camera is at the origin.
    • For light types that have a direction (directional and spot lights), the light's direction is defined as the 3-vector (0.0, 0.0, -1.0) and the rotation of the node orients the light accordingly. That is, an untransformed light points down the -Z axis. The light's transform is affected by the node's world scale, but all properties of the light (such as range and intensity) are unaffected.
  14. almarklein commented on Feb 27, 2023

    @almarklein
    almarklein
    on Feb 27, 2023
    MemberAuthor
    More actions

    I've copied this to the top post and also started a todo list. Feel free to add items.

  15. Korijn commented on Jul 12, 2023

    @Korijn
    Korijn
    on Jul 12, 2023
    Collaborator
    More actions

    @almarklein can you comment on the status of this item? I think we've completed all the implementation changes, and just need to document the conventions now, right?

  16. almarklein commented on Jul 12, 2023

    @almarklein
    almarklein
    on Jul 12, 2023
    MemberAuthor
    More actions

    I thought we already documented it too, but searching for "handed" in the docs shows nothing, so I guess we should add it. My suggestion would be to explain in in the guide, as well as a brief technical summary on the base camera.

  17. DennyLindberg commented on Jul 18, 2023

    @DennyLindberg
    DennyLindberg
    on Jul 18, 2023
    More actions

    Could I request documentation on linear distance units as well? I tried figuring out the default units and could not find any information on it. glTF is defined in meters (see 3.4). The helmet in the PBR example is 1.5-2.0 meter sized when opened in Blender and that size is reflected in pygfx when using the trimesh python package. If I create a reference mesh in Blender and export to various formats using the default scene settings the size is consistent in pygfx to the meter standard. I get the impression that many of the pygfx examples are either using cm or unitless which can sometimes make it confusing when the camera setup is automatic for framing the object. I see values in the 20, 50, 100, 600 ranges just skimming through the examples now. Seeing that you are already documenting the coordinate system standards it would be nice if all units were clearly defined. I like pygfx so far so I would love for it to become a "standard" python package.

    Reacted by Ivo Flipse
  18. almarklein commented on Jul 19, 2023

    @almarklein
    almarklein
    on Jul 19, 2023
    MemberAuthor
    More actions

    @DennyLindberg I agree that documenting this in the docs is a good idea.

    The short answer is that pygfx does not impose any units. It's the responsibility of the user to ensure that all objects are represented in the same units. In Blender-like use-case, and loading stuff using trimesh this would indeed often be meters. But for scientific applications it might be different. E.g. microscopy vs GIS vs astronomy.

    Reacted by Denny Lindberg
  19. DennyLindberg commented on Jul 19, 2023

    @DennyLindberg
    DennyLindberg
    on Jul 19, 2023
    More actions

    @almarklein Fair enough.

  20. Korijn commented on Jul 19, 2023

    @Korijn
    Korijn
    on Jul 19, 2023
    Collaborator
    More actions

    It's a matter of application vs library, I think. For applications it's expected that everything is defined, but for a library, well, it's used to build applications. So to give application developers the freedom to pick their own unit convention, we should be agnostic here.

  21. DennyLindberg commented on Jul 19, 2023

    @DennyLindberg
    DennyLindberg
    on Jul 19, 2023
    More actions

    Yes, that seems to be the same notion over at ThreeJS. It would not hurt to mention it is unitless right, if other details are being documented anyway?

    https://discourse.threejs.org/t/what-unit-of-distance-in-threejs/20782/2
    https://discourse.threejs.org/t/units-in-three-js/1174
    mrdoob/three.js#6259

    Reacted by Korijn van Golen and Almar Klein
  22. almarklein commented on Jul 19, 2023

    @almarklein
    almarklein
    on Jul 19, 2023
    MemberAuthor
    More actions

    I added a checkbox in the top post.

    Reacted by Denny Lindberg
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      You are visitor 01402520 — GeezerVison does not store the pages you look up.
      Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.