Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Request to add a "Unit" variable to GLTF #2425

Closed
kitaedesigns opened this issue Jul 17, 2024 · 10 comments
Closed

Feature Request to add a "Unit" variable to GLTF #2425

kitaedesigns opened this issue Jul 17, 2024 · 10 comments

Comments

@kitaedesigns
Copy link

Currently, glTF's have a scale variable that describes the XYZ scale of the scene as a float. The problem is that every 3D app has a different default Unit, with Architecture and Engineering apps having different units per project, i.e. Feet, Inches, mm, meters, cm, etc. and different 3D Modeling and Animation apps having their own default units, Houdini and C4D are cm, Blender is m, etc. This would say users the hassle of having to always scale a model upon import, or go back to their creation app and reexport their glTF. For built environment workflows and products, this is crucial.

Having a Unit variable would allow any app receiving a glTF to know how to correctly scale that model to match its own unit system. Here is an example of how a glTF's incoming units could be read and then converted into an environment based on meters. All the receiving environment would have to do is read the Unit variable and multiply it by the correct float to resolve to meters.

1: { name: "Microns",factor: 0.000001 },
2: { name: "Millimeters",factor: 0.001 },
3: { name: "Centimeters",factor: 0.01 },
4: { name: "Meters",factor: 1 },
5: { name: "Kilometers",factor: 1000.00 },
6: { name: "Microinches",factor: 0.0000000254 },
7: { name: "Mils",factor: 0.0000254 },
8: { name: "Inches",factor: 0.0254 },
9: { name: "Feet",factor: 0.3048 },
10: { name: "Miles",factor: 1609.344 },
11: { name: "CustomUnits",factor: 1 },
12: { name: "Angstroms",factor: 0.0000000001 },
13: { name: "Nanometers",factor: 0.000000001 },
14: { name: "Decimeters",factor: 0.1 },
15: { name: "Dekameters",factor: 10 },
16: { name: "Hectometers",factor: 100 },
17: { name: "Megameters",factor: 1000000 },
18: { name: "Gigameters",factor: 1000000000 },
19: { name: "Yards",factor: 0.3048 },
@bhouston
Copy link
Contributor

bhouston commented Jul 17, 2024

Why?

Instead we should just always assume that it is in meters.

The matrices are already stored in JSON format so you can store very high precision number values. JavaScript for example already defaults to doubles for floating point precision. Doubles already handle the range give from Microns to Gigameters with great accuracy given that doubles have a 53 mantissa.

log10( 2^53 ) =15.955 base-10 digits of precision.

If you want to achieve the above you can just have a matrix at the top level that is a scale matrix that has doubles in it.

@lexaknyazev
Copy link
Member

Not just assume - the glTF 2.0 spec explicitly defines all linear distances as meters.

@kitaedesigns
Copy link
Author

kitaedesigns commented Jul 17, 2024

I know glTF assumes meters, but it doesn't take into account the units of the exporting app. If you export a glTF from Rhino and the scene was set to inches, and your model is 30 inches wide, that will be read as 30 meters wide in the glTF because it's just a float that is written. glTF might have meters internally, but that doesn't take into account the units of the working environment. Here is an image of a glTF created in C4D (cm) and the same exact model exported as glTF from Rhino (meters), both appearing in Three.js (meters). As you can see, the C4D model is way too small. What I'm describing could either be a scalar factor applied on export by each app, or be written into the file as a Unit variable and then the ingesting app applies the correct scalar factor. I suggested the latter since you can't change the Units of most 3D Modeling and Animation apps like you can with AEC apps.

image

@lexaknyazev
Copy link
Member

If you export a glTF from Rhino and the scene was set to inches, and your model is 30 inches wide, that will be read as 30 meters wide in the glTF because it's just a float that is written.

Exporters must handle that properly, i.e., convert source values or add extra node transforms so that final object dimensions are correct.

@kitaedesigns
Copy link
Author

kitaedesigns commented Jul 17, 2024

I agree that they should, but none of them apply the conversion to meters since you can't change units in their software and many of them are "scaleless". Having a Unit par written into the glTF could be an easy solution since we know that C4D is cm, Blender is meters, Houdini is cm, etc. This could potentially even be done retroactively if we know the source app that was used to create a series of files.

This could be called "Source Units" and denote an app like "Cinema4D" and we know that means Centimeters if they're too lazy to add Units to their exporter.

@javagl
Copy link
Contributor

javagl commented Jul 17, 2024

I agree that this is the responsbility of the exporter. It was a concious decision to always use meters in glTF. Many early 3D model formats did not have units at all (OBJ and stuff like that). And it was exactly the different conventions of different tools that required each importer and exporter to handle each source- and target unit. Some formats did include units, but they often have not been handled (converted) properly.

(Somewhat related: KhronosGroup/glTF-Sample-Assets#63 (comment) . The ReciprocatingSaw model was too small... or too large... whatever a scale factor of 0.01 means ... even though the original Collada file contained <unit meter="1.000000" name="meters"/> - so that didn't really work...)

(An aside: Some tools (at least in their UI) also use 'degrees' for angles. But for glTF, it's radians...)

@aaronfranke
Copy link
Contributor

@kitaedesigns I explicitly want this to NOT be a thing. The fact that glTF has one coordinate system is a blessing. It makes everything much simpler to only have to deal with meters. Supporting multiple units has multiple downsides with few upsides. The formats that do have this feature are a pain to work with.

If you export a glTF from Rhino and the scene was set to inches, and your model is 30 inches wide, that will be read as 30 meters wide in the glTF

I agree that they should, but none of them apply the conversion to meters since you can't change units in their software

This is a bug in Rhino. It should not be exporting a 30 inch model as 30 meters, it needs to scale on export.

What I'm describing could either be a scalar factor applied on export by each app

That's already what is supposed to happen. Apps that don't use meters need to bake the scale on export. It is the job of those apps that choose non-meter scales to conform, it is not the job of glTF or any app that uses meters.

@emackey
Copy link
Member

emackey commented Aug 2, 2024

Agreed. glTF specifies meters. All exporters and importers are required to either use meters or convert meters to/from their local units of choice. Please file a bug with Rhino and any other exporters not following the specification, thanks!

@emackey emackey closed this as not planned Won't fix, can't repro, duplicate, stale Aug 2, 2024
@npolys
Copy link

npolys commented Aug 2, 2024 via email

@emackey
Copy link
Member

emackey commented Aug 2, 2024

To be clear, this is not a missing feature of glTF, this was a deliberate choice when glTF was first published. At the time a lot of folks were concerned about other formats (COLLADA, FBX, and others) where exporters could configure all kinds of different things in different ways, and importers couldn't keep pace with all the configuration options found in the files. So the design of glTF was set: Always use meters, and demand that exporters convert their units to meters. Always use +Y up, +Z front, always use right-handed coordinates, and demand that exporters convert on export.

I heard a term for this just recently: "Convention over configuration." That's what's happened here, and I think in general it's helped the ecosystem more than it's hurt. Certainly the global collection of glTF assets is more coherent and more standardized as a result, and generally importers are better expected to properly import files. This choice places a heavier burden on exporters, and we encourage folks to file bugs and get those exporters fixed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants