WIP: IO: Add file unit type selector to stl importer and exporter #128337

Draft
Cedric Steiert wants to merge 3 commits from Bujus_Krachus/blender:main into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
First-time contributor

As STL is a unitless format, most other programs assume it to be millimeters. Blender on the other hand uses meters. This means, that whatever size the object has (e.g. 2m) it will always be assumed as millimeters in other apps (in case of 2m that would be 2mm, as no unit is saved, only the numeric value). Changing the unit system inside blender only changes the UI display values, not however the actual data and fiddling with the scene scale or export scale values can be quite tedious (time consuming for often users, confusing for sporadic users).

To allow for CAD modelling and exporting to STL in real life measures (which is desirable as STLs are commonly used for 3d printing), this PR supplies the user with a dropdown allowing to choose the target unit type (m, dm, cm, mm, in) used by the application he wishes to export for, whilst leaving a custom option for user defined scale (otherwise the scale factor input field is disabled); the chosen unit will modify the scale factor value. Additionally a new option got added to scale the mesh according to the used scene unit (e.g. scene unit cm, which then also assumes the stl scale values to be cm).
The default unit stays meter (factor 1) to not introduce any breaking changes to existing workflows, whilst still allowing anyone to quickly change units without having to think about conversion factors too much.

This change is inspired by the upcoming release of the x3d extension with a similar (but not identical) choosing option: 7e0b0e903a

The current feature proposal looks like this:
meter selected (default):
grafik
dropdown options:
grafik
millimeter selected (1m in blender is now 1m for most other apps as well):
grafik
when using millimeter as preset value, a user can model in real life measures and export/import in the correct scale. For example: model is 10x10cm (blender internally this equals to 0.1x0.1(m), thus in other apps as 0.1x0.1(mm)), a scale factor of 1000 will be applied, which results in a final scale of 100x100(mm)=10x10(cm).

The proposal got implemented for the stl importer and exporter.

As STL is a unitless format, most other programs assume it to be millimeters. Blender on the other hand uses meters. This means, that whatever size the object has (e.g. 2m) it will always be assumed as millimeters in other apps (in case of 2m that would be 2mm, as no unit is saved, only the numeric value). Changing the unit system inside blender only changes the UI display values, not however the actual data and fiddling with the scene scale or export scale values can be quite tedious (time consuming for often users, confusing for sporadic users). To allow for CAD modelling and exporting to STL in real life measures (which is desirable as STLs are commonly used for 3d printing), this PR supplies the user with a dropdown allowing to choose the target unit type (m, dm, cm, mm, in) used by the application he wishes to export for, whilst leaving a custom option for user defined scale (otherwise the scale factor input field is disabled); the chosen unit will modify the scale factor value. Additionally a new option got added to scale the mesh according to the used scene unit (e.g. scene unit cm, which then also assumes the stl scale values to be cm). The default unit stays meter (factor 1) to not introduce any breaking changes to existing workflows, whilst still allowing anyone to quickly change units without having to think about conversion factors too much. This change is inspired by the upcoming release of the x3d extension with a similar (but not identical) choosing option: https://projects.blender.org/extensions/io_scene_x3d/commit/7e0b0e903a2cc51706aeca1e9b3f394eaeee3ef1 The current feature proposal looks like this: meter selected (default): ![grafik](/attachments/ede1e389-dcec-4cf9-9514-f1494ec59dd8) dropdown options: ![grafik](/attachments/eec6b127-7637-4283-bc6d-d394d84556cf) millimeter selected (1m in blender is now 1m for most other apps as well): ![grafik](/attachments/ec702dfe-c3e0-4e32-81b1-e2a20718459d) when using millimeter as preset value, a user can model in real life measures and export/import in the correct scale. For example: model is 10x10cm (blender internally this equals to 0.1x0.1(m), thus in other apps as 0.1x0.1(mm)), a scale factor of 1000 will be applied, which results in a final scale of 100x100(mm)=10x10(cm). The proposal got implemented for the stl importer and exporter.
Cedric Steiert added 2 commits 2024-09-29 22:11:11 +02:00
As STL is a unitless format, most other programs assume it to be millimeters. Blender on the other hand uses meters. To allow for CAD modelling and exporting to STL in real life measures, this commit supplies the user with a dropdown allowing to choose the target unit type (m, dm, cm, mm, in), whilst leaving a custom option for user defined scale (otherwise scale factor input field is disabled); the chosen unit will modify the scale factor value.
The default unit stays meter (factor 1) to not introduce any breaking changes to existing workflows.
This commit adds a new option to the dropdown to set the scale factor accordingly to the used scene unit of the blend file (blender assumes meter, thus a conversion from meter to unit system is needed). This is useful if the user already decides to model in the target unit system used by the other application.
Also done some cleanup, removed some redundant code.
Iliya Katushenock added this to the Pipeline, Assets & IO project 2024-09-29 23:25:23 +02:00
Iliya Katushenock reviewed 2024-09-29 23:26:13 +02:00
@ -0,0 +1,35 @@
/* SPDX-FileCopyrightText: 2023 Blender Authors

Today is 2024/

Today is `2024`/
Bujus_Krachus marked this conversation as resolved
Cedric Steiert added 1 commit 2024-09-30 00:59:46 +02:00
Fix: copyright year, c styleguide
All checks were successful
buildbot/vexp-code-patch-lint Build done.
buildbot/vexp-code-patch-linux-x86_64 Build done.
buildbot/vexp-code-patch-windows-amd64 Build done.
buildbot/vexp-code-patch-darwin-arm64 Build done.
buildbot/vexp-code-patch-darwin-x86_64 Build done.
buildbot/vexp-code-patch-coordinator Build done.
9aab742e68
Cedric Steiert requested review from Aras Pranckevicius 2024-09-30 01:18:27 +02:00

That's an interesting idea, but it makes me wonder: should some other formats that are "unit-less" (e.g. OBJ, PLY) also get the same feature?

That's an interesting idea, but it makes me wonder: should some other formats that are "unit-less" (e.g. OBJ, PLY) also get the same feature?
Author
First-time contributor

should some other formats that are "unit-less" (e.g. OBJ, PLY) also get the same feature?

Should? Idk, that's for the blender team to decide.

Could? Yes, absolutely; most of the code is located in io common, only embedding to the individual UI's would be needed. Adding that feature to the other file types (If it gets accepted ofc), would create a more generalized standard UI, which i already outlined here (due to many differences in the IO core addons): https://blender.community/c/rightclickselect/DY5B/ (still a decision has to be made what options to consider as general, and whether to adjust the IO core addons individually or to create a one-size-fits-all-solution).

Recommended? Maybe. It for sure would be a nice feature, as it simplifies the unit conversion process if needed and is transparent in it's making (the scale factor is exposed to the user in the UI).
However the use cases fully depend on the users, their modelling preferences (large (200m(blender)=200mm(extern)=20cm(extern)) or little scaling (200mm(blender)=200mm(extern)) with grid scale adjustments needed), the external software used, etc.
I remember back in school when i did some CAD models for 3D-printing in blender on a sporadic basis it was always headscratches which factor to use and why, as somehow all attempts were different size in the slicer program than i'd expect it to be from blender (i foolishly assumed cm to be cm).

> should some other formats that are "unit-less" (e.g. OBJ, PLY) also get the same feature? Should? Idk, that's for the blender team to decide. Could? Yes, absolutely; most of the code is located in io common, only embedding to the individual UI's would be needed. Adding that feature to the other file types (If it gets accepted ofc), would create a more generalized standard UI, which i already outlined here (due to many differences in the IO core addons): https://blender.community/c/rightclickselect/DY5B/ (still a decision has to be made what options to consider as general, and whether to adjust the IO core addons individually or to create a one-size-fits-all-solution). Recommended? Maybe. It for sure would be a nice feature, as it simplifies the unit conversion process if needed and is transparent in it's making (the scale factor is exposed to the user in the UI). However the use cases fully depend on the users, their modelling preferences (large (200m(blender)=200mm(extern)=20cm(extern)) or little scaling (200mm(blender)=200mm(extern)) with grid scale adjustments needed), the external software used, etc. I remember back in school when i did some CAD models for 3D-printing in blender on a sporadic basis it was always headscratches which factor to use and why, as somehow all attempts were different size in the slicer program than i'd expect it to be from blender (i foolishly assumed cm to be cm).

@blender-bot build

@blender-bot build
Aras Pranckevicius reviewed 2024-10-03 10:09:08 +02:00
@ -0,0 +35,4 @@
char scene_unit = scene->unit.length_unit;
if (scene->unit.system == USER_UNIT_METRIC) {
switch (scene_unit) {
case '\0': // kilometer

Not quite like hardcoding unit system indices in that way. As far as I can tell, these would only work as long as no one reorders to alters the unit systems arrays inside unit.cc. Would it be better to use something like BKE_unit_base_scalar to get the scaling factors instead?

Not quite like hardcoding unit system indices in that way. As far as I can tell, these would only work as long as no one reorders to alters the unit systems arrays inside `unit.cc`. Would it be better to use something like `BKE_unit_base_scalar` to get the scaling factors instead?

btw I'm not too familiar with the whole units system, perhaps @ideasman42 would have better opinions

btw I'm not too familiar with the whole units system, perhaps @ideasman42 would have better opinions
Author
First-time contributor

Hi Aras, i didn't like the hardcoding either due to the reordering issue, usually try to avoid it.

In theory following code should work instead of hardcoding the bytes as type identifier and values as scalars

int base = BKE_unit_base_get((const void *)&scene->unit.system);
double base_scalar = BKE_unit_base_scalar(B_UNIT_LENGTH, base);

however base is always 1 and thus base_scalar always 1.0 no matter which scene unit is set for length in the blender scene properties. Even when changing the base here manually, only at int 5 there is another value despite 1.0.
I'll be honest, i have no idea how accessing the user defined scene unit works, thus the hardcoded approach.

The main issue is knowing which scene_unit is selected, only way i found until now is using scene->unit.length_unit and comparing it's byte values. I'd be glad to implement a proper idea over that if someone points me into the right direction.
The second thing is the scalars values, these could be refactored to using UN_SC_M from unit.cc, as they're already defined there.

little side note: only the dropdown entry Scene unit length of this PR is affected by this issue.

Hi Aras, i didn't like the hardcoding either due to the reordering issue, usually try to avoid it. In theory following code should work instead of hardcoding the bytes as type identifier and values as scalars ```cpp int base = BKE_unit_base_get((const void *)&scene->unit.system); double base_scalar = BKE_unit_base_scalar(B_UNIT_LENGTH, base); ``` however `base` is always `1` and thus `base_scalar` always `1.0` no matter which scene unit is set for length in the blender scene properties. Even when changing the `base` here manually, only at int `5` there is another value despite `1.0`. I'll be honest, i have no idea how accessing the user defined scene unit works, thus the hardcoded approach. The main issue is knowing which scene_unit is selected, only way i found until now is using `scene->unit.length_unit` and comparing it's byte values. I'd be glad to implement a proper idea over that if someone points me into the right direction. The second thing is the scalars values, these could be refactored to using `UN_SC_M` from `unit.cc`, as they're already defined there. _little side note: only the dropdown entry `Scene unit length` of this PR is affected by this issue._
Cedric Steiert changed title from IO: Add file unit type selector to stl importer and exporter to WIP: IO: Add file unit type selector to stl importer and exporter 2024-10-15 16:22:41 +02:00
All checks were successful
buildbot/vexp-code-patch-lint Build done.
buildbot/vexp-code-patch-linux-x86_64 Build done.
buildbot/vexp-code-patch-windows-amd64 Build done.
buildbot/vexp-code-patch-darwin-arm64 Build done.
buildbot/vexp-code-patch-darwin-x86_64 Build done.
buildbot/vexp-code-patch-coordinator Build done.
This pull request is marked as a work in progress.

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u main:Bujus_Krachus-main
git checkout Bujus_Krachus-main
Sign in to join this conversation.
No reviewers
No Label
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset System
Interest
Audio
Interest
Automated Testing
Interest
Blender Asset Bundle
Interest
BlendFile
Interest
Code Documentation
Interest
Collada
Interest
Compatibility
Interest
Compositing
Interest
Core
Interest
Cycles
Interest
Dependency Graph
Interest
Development Management
Interest
EEVEE
Interest
Freestyle
Interest
Geometry Nodes
Interest
Grease Pencil
Interest
ID Management
Interest
Images & Movies
Interest
Import Export
Interest
Line Art
Interest
Masking
Interest
Metal
Interest
Modeling
Interest
Modifiers
Interest
Motion Tracking
Interest
Nodes & Physics
Interest
OpenGL
Interest
Overlay
Interest
Overrides
Interest
Performance
Interest
Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds & Tests
Interest
Python API
Interest
Render & Cycles
Interest
Render Pipeline
Interest
Sculpt, Paint & Texture
Interest
Text Editor
Interest
Translations
Interest
Triaging
Interest
Undo
Interest
USD
Interest
User Interface
Interest
UV Editing
Interest
VFX & Video
Interest
Video Sequencer
Interest
Viewport & EEVEE
Interest
Virtual Reality
Interest
Vulkan
Interest
Wayland
Interest
Workbench
Interest: X11
Legacy
Asset Browser Project
Legacy
Blender 2.8 Project
Legacy
Milestone 1: Basic, Local Asset Browser
Legacy
OpenGL Error
Meta
Good First Issue
Meta
Papercut
Meta
Retrospective
Meta
Security
Module
Animation & Rigging
Module
Core
Module
Development Management
Module
Grease Pencil
Module
Modeling
Module
Nodes & Physics
Module
Pipeline, Assets & IO
Module
Platforms, Builds & Tests
Module
Python API
Module
Render & Cycles
Module
Sculpt, Paint & Texture
Module
Triaging
Module
User Interface
Module
VFX & Video
Module
Viewport & EEVEE
Platform
FreeBSD
Platform
Linux
Platform
macOS
Platform
Windows
Severity
High
Severity
Low
Severity
Normal
Severity
Unbreak Now!
Status
Archived
Status
Confirmed
Status
Duplicate
Status
Needs Info from Developers
Status
Needs Information from User
Status
Needs Triage
Status
Resolved
Type
Bug
Type
Design
Type
Known Issue
Type
Patch
Type
Report
Type
To Do
No Milestone
No Assignees
3 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: blender/blender#128337
No description provided.