Model3D panning, improved UX (#6240)

* Model3D panning, improved UX

* add changeset

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
This commit is contained in:
Dylan Ebert 2023-11-01 19:00:55 -04:00 committed by GitHub
parent 3e31c1752e
commit dd901c1b0a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 34 additions and 14 deletions

View File

@ -0,0 +1,6 @@
---
"@gradio/model3d": minor
"gradio": minor
---
feat:Model3D panning, improved UX

View File

@ -42,6 +42,7 @@ class Model3D(Component):
None,
),
zoom_speed: float = 1,
pan_speed: float = 1,
height: int | None = None,
label: str | None = None,
show_label: bool | None = None,
@ -61,6 +62,7 @@ class Model3D(Component):
clear_color: background color of scene, should be a tuple of 4 floats between 0 and 1 representing RGBA values.
camera_position: initial camera position of scene, provided as a tuple of `(alpha, beta, radius)`. Each value is optional. If provided, `alpha` and `beta` should be in degrees reflecting the angular position along the longitudinal and latitudinal axes, respectively. Radius corresponds to the distance from the center of the object to the camera.
zoom_speed: the speed of zooming in and out of the scene when the cursor wheel is rotated or when screen is pinched on a mobile device. Should be a positive float, increase this value to make zooming faster, decrease to make it slower. Affects the wheelPrecision property of the camera.
pan_speed: the speed of panning the scene when the cursor is dragged or when the screen is dragged on a mobile device. Should be a positive float, increase this value to make panning faster, decrease to make it slower. Affects the panSensibility property of the camera.
height: height of the model3D component, in pixels.
interactive: if True, will allow users to upload a file; if False, can only be used to display files. If not provided, this is inferred based on whether the component is used as an input or output.
label: The label for this component. Appears above the component and is also used as the header if there are a table of examples for this component. If None and used in a `gr.Interface`, the label will be the name of the parameter this component is assigned to.
@ -78,6 +80,7 @@ class Model3D(Component):
self.camera_position = camera_position
self.height = height
self.zoom_speed = zoom_speed
self.pan_speed = pan_speed
super().__init__(
label=label,
every=every,

View File

@ -14,6 +14,7 @@
export let show_label: boolean;
export let i18n: I18nFormatter;
export let zoom_speed = 1;
export let pan_speed = 1;
// alpha, beta, radius
export let camera_position: [number | null, number | null, number | null] = [
@ -69,13 +70,14 @@
value,
clear_color,
camera_position,
zoom_speed
zoom_speed,
pan_speed
);
}
}
function handle_undo(): void {
reset_camera_position(scene, camera_position, zoom_speed);
reset_camera_position(scene, camera_position, zoom_speed, pan_speed);
}
</script>

View File

@ -13,6 +13,7 @@
export let root: string;
export let i18n: I18nFormatter;
export let zoom_speed = 1;
export let pan_speed = 1;
// alpha, beta, radius
export let camera_position: [number | null, number | null, number | null] = [
@ -34,7 +35,8 @@
value,
clear_color,
camera_position,
zoom_speed
zoom_speed,
pan_speed
);
}
@ -71,7 +73,7 @@
}
async function handle_undo(): Promise<void> {
reset_camera_position(scene, camera_position, zoom_speed);
reset_camera_position(scene, camera_position, zoom_speed, pan_speed);
}
const dispatch = createEventDispatcher<{

View File

@ -4,7 +4,8 @@ import * as BABYLON from "babylonjs";
const create_camera = (
scene: BABYLON.Scene,
camera_position: [number | null, number | null, number | null],
zoom_speed: number
zoom_speed: number,
pan_speed: number
): void => {
scene.createDefaultCamera(true, true, true);
var helperCamera = scene.activeCamera! as BABYLON.ArcRotateCamera;
@ -17,11 +18,14 @@ const create_camera = (
if (camera_position[2] !== null) {
helperCamera.radius = camera_position[2];
}
// Disable panning. Adapted from: https://playground.babylonjs.com/#4U6TVQ#3
helperCamera.panningSensibility = 0;
helperCamera.attachControl(false, false, -1);
helperCamera.pinchToPanMaxDistance = 0;
helperCamera.wheelPrecision = 2500 / zoom_speed;
helperCamera.lowerRadiusLimit = 0.1;
const updateCameraSensibility = (): void => {
helperCamera.wheelPrecision = 250 / (helperCamera.radius * zoom_speed);
helperCamera.panningSensibility = (10000 * pan_speed) / helperCamera.radius;
};
updateCameraSensibility();
helperCamera.attachControl(true);
helperCamera.onAfterCheckInputsObservable.add(updateCameraSensibility);
};
export const add_new_model = (
@ -31,7 +35,8 @@ export const add_new_model = (
value: FileData | null,
clear_color: [number, number, number, number],
camera_position: [number | null, number | null, number | null],
zoom_speed: number
zoom_speed: number,
pan_speed: number
): BABYLON.Scene => {
if (scene && !scene.isDisposed && engine) {
scene.dispose();
@ -61,7 +66,7 @@ export const add_new_model = (
url,
"",
scene,
() => create_camera(scene, camera_position, zoom_speed),
() => create_camera(scene, camera_position, zoom_speed, pan_speed),
undefined,
undefined,
"." + value.path.split(".")[1]
@ -72,8 +77,9 @@ export const add_new_model = (
export const reset_camera_position = (
scene: BABYLON.Scene,
camera_position: [number | null, number | null, number | null],
zoom_speed: number
zoom_speed: number,
pan_speed: number
): void => {
scene.removeCamera(scene.activeCamera!);
create_camera(scene, camera_position, zoom_speed);
create_camera(scene, camera_position, zoom_speed, pan_speed);
};

View File

@ -2016,6 +2016,7 @@ class TestModel3D:
"camera_position": (None, None, None),
"height": None,
"zoom_speed": 1,
"pan_speed": 1,
"_selectable": False,
}