mrdoob / three.js

JavaScript 3D Library.
https://threejs.org/
MIT License
103.04k stars 35.41k forks source link

Bounding box transform controls #25619

Open FluorescentHallucinogen opened 1 year ago

FluorescentHallucinogen commented 1 year ago

Description

Three.js has TransformControls (similar to Blender), which has 3 modes: translate, rotate and scale. And the problems are that:

Live demo: https://threejs.org/examples/#misc_controls_transform.

Solution

Bounding box transform controls provide manipulation affordances for translate, rotation and scale, all at once, without the need to switch between modes.

babylonjs

Here's the video how it works:

https://user-images.githubusercontent.com/7892779/222917713-316209eb-7489-4b7d-bd7d-8ecccce41601.mp4

Alternatives

Babylon.js provides bounding box gizmo "out-of-the-box".

Live demo: https://playground.babylonjs.com/#8GY6J8#211

Mixed Reality Toolkit (MRTK) for Unity has bounding box gizmo. Unity projects can be exported for WebXR.

Live demo: https://rufus31415.github.io/sandbox/simple-webxr-mrtk/

Additional context

This feature is really needed for the new WebXR mode for Meta Quest devices in the Google's <model-viewer> web component, that is based on Three.js.

Mugen87 commented 1 year ago

it's not comfortable and intuitive for end users

I'm afraid this is a subjective opinion. If you have all transformation options enabled at once, I could imagine frequent mistakes in the handling since users accidentally select the wrong gizmo. Or maybe just don't remember what gizmo controls which transformation. All of this does not happen with separate transformation modes.

Besides, different modes allows you to visualize the gizmos in more specialized ways. I personally prefer the circle gizmos in the rotation mode than what the bounding box offers.

That said, I understand that in an XR environment the presented bounding box approach can be advantage. Especially since you don't have to think about how the user toggles different modes which seems less of an issue with classic UIs and mouse/keyboard.

An ideal solution would be to make a new class that derives from TransformControls. That might require some refactoring in the base class though.

FluorescentHallucinogen commented 1 year ago

To be clear, I'm not suggesting to replace the existing `TransformControls'.

I completely agree that there are cases where switching between translate, rotate and scale modes fits better.

If you have all transformation options enabled at once, I could imagine frequent mistakes in the handling since users accidentally select the wrong gizmo.

That's why I wrote that it's not comfortable and intuitive for end users. I meant turning on all modes at once in the existing TransformControls.

This is exactly what the bounding box solves.

See how it's implemented in Babylon.js: https://doc.babylonjs.com/features/featuresDeepDive/mesh/gizmo

The position, scale, rotation and bounding box gizmos coexist together.

Moreover, it's possible to enable more than one (even all four) gizmo at once. I can imagine cases where this (e.g. enabling translate and rotate at the same time) might be useful.

An ideal solution would be to make a new class that derives from TransformControls. That might require some refactoring in the base class though.

Another solution might be to add the new possible value bounding-box to existing translate, rotate and scale.

Allowing arrays for properties and methods related to modes will also be helpful.

FluorescentHallucinogen commented 1 year ago

in an XR environment the presented bounding box approach can be advantage

The bounding box approach works like a charm in regular 3D environments too.

You can try interacting with the object yourself using the mouse in the following demo: https://playground.babylonjs.com/#8GY6J8#211. :wink: The only thing is that the bounding box in this demo has a legacy HoloLens 1 design.

elalish commented 1 year ago

This looks great, and I agree that implementing it as a class that derives from TransformControls would probably be good. One question though: when dragging a face, I would expect that to be translation mode, but it seems to also incorporate some strange rotations? Can that be removed so the modes are more clearly separated?

On the other hand, if you're using a 6-DoF controller instead of a mouse, I imagine you might want another mode where you can "attach" the model to the controller and have full 6-DoF placement control until you let go.