@gradio/model3d 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/Example.svelte +2 -2
- package/package.json +7 -6
- package/shared/Canvas3D.svelte +149 -0
- package/shared/Model3D.svelte +19 -65
- package/shared/Model3DUpload.svelte +14 -54
- package/shared/utils.ts +0 -85
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
# @gradio/model3d
|
2
2
|
|
3
|
+
## 0.6.0
|
4
|
+
|
5
|
+
### Features
|
6
|
+
|
7
|
+
- [#7315](https://github.com/gradio-app/gradio/pull/7315) [`b3a9c83`](https://github.com/gradio-app/gradio/commit/b3a9c830955a5ded8528d6118aaf1b6e019857a2) - Lite: Wasm-compatible Model3D. Thanks [@whitphx](https://github.com/whitphx)!
|
8
|
+
|
9
|
+
### Fixes
|
10
|
+
|
11
|
+
- [#7192](https://github.com/gradio-app/gradio/pull/7192) [`8dd6f4b`](https://github.com/gradio-app/gradio/commit/8dd6f4bc1901792f05cd59e86df7b1dbab692739) - Handle the case where examples is `null` for all components. Thanks [@abidlabs](https://github.com/abidlabs)!
|
12
|
+
|
3
13
|
## 0.5.0
|
4
14
|
|
5
15
|
### Features
|
package/Example.svelte
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
<script lang="ts">
|
2
|
-
export let value: string;
|
2
|
+
export let value: string | null;
|
3
3
|
export let type: "gallery" | "table";
|
4
4
|
export let selected = false;
|
5
5
|
</script>
|
@@ -9,7 +9,7 @@
|
|
9
9
|
class:gallery={type === "gallery"}
|
10
10
|
class:selected
|
11
11
|
>
|
12
|
-
{value}
|
12
|
+
{value ? value : ""}
|
13
13
|
</div>
|
14
14
|
|
15
15
|
<style>
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@gradio/model3d",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.6.0",
|
4
4
|
"description": "Gradio UI packages",
|
5
5
|
"type": "module",
|
6
6
|
"author": "",
|
@@ -11,12 +11,13 @@
|
|
11
11
|
"babylonjs": "^4.2.1",
|
12
12
|
"babylonjs-loaders": "^4.2.1",
|
13
13
|
"dequal": "^2.0.2",
|
14
|
-
"@gradio/atoms": "^0.5.
|
15
|
-
"@gradio/client": "^0.
|
14
|
+
"@gradio/atoms": "^0.5.1",
|
15
|
+
"@gradio/client": "^0.11.0",
|
16
16
|
"@gradio/icons": "^0.3.2",
|
17
|
-
"@gradio/statustracker": "^0.4.
|
18
|
-
"@gradio/
|
19
|
-
"@gradio/
|
17
|
+
"@gradio/statustracker": "^0.4.5",
|
18
|
+
"@gradio/upload": "^0.7.1",
|
19
|
+
"@gradio/utils": "^0.2.2",
|
20
|
+
"@gradio/wasm": "^0.6.0"
|
20
21
|
},
|
21
22
|
"main_changeset": true,
|
22
23
|
"main": "./Index.svelte",
|
@@ -0,0 +1,149 @@
|
|
1
|
+
<script lang="ts">
|
2
|
+
import { onMount } from "svelte";
|
3
|
+
import * as BABYLON from "babylonjs";
|
4
|
+
import * as BABYLON_LOADERS from "babylonjs-loaders";
|
5
|
+
import type { FileData } from "@gradio/client";
|
6
|
+
import { resolve_wasm_src } from "@gradio/wasm/svelte";
|
7
|
+
|
8
|
+
$: {
|
9
|
+
if (
|
10
|
+
BABYLON_LOADERS.OBJFileLoader != undefined &&
|
11
|
+
!BABYLON_LOADERS.OBJFileLoader.IMPORT_VERTEX_COLORS
|
12
|
+
) {
|
13
|
+
BABYLON_LOADERS.OBJFileLoader.IMPORT_VERTEX_COLORS = true;
|
14
|
+
}
|
15
|
+
}
|
16
|
+
|
17
|
+
export let value: FileData;
|
18
|
+
export let clear_color: [number, number, number, number];
|
19
|
+
export let camera_position: [number | null, number | null, number | null];
|
20
|
+
export let zoom_speed: number;
|
21
|
+
export let pan_speed: number;
|
22
|
+
|
23
|
+
$: url = value.url;
|
24
|
+
|
25
|
+
/* URL resolution for the Wasm mode. */
|
26
|
+
export let resolved_url: typeof url = undefined; // Exposed to be bound to the download link in the parent component.
|
27
|
+
// The prop can be updated before the Promise from `resolve_wasm_src` is resolved.
|
28
|
+
// In such a case, the resolved url for the old `url` has to be discarded,
|
29
|
+
// This variable `latest_url` is used to pick up only the value resolved for the latest `url`.
|
30
|
+
let latest_url: typeof url;
|
31
|
+
$: {
|
32
|
+
// In normal (non-Wasm) Gradio, the original `url` should be used immediately
|
33
|
+
// without waiting for `resolve_wasm_src()` to resolve.
|
34
|
+
// If it waits, a blank element is displayed until the async task finishes
|
35
|
+
// and it leads to undesirable flickering.
|
36
|
+
// So set `resolved_url` immediately above, and update it with the resolved values below later.
|
37
|
+
resolved_url = url;
|
38
|
+
|
39
|
+
if (url) {
|
40
|
+
latest_url = url;
|
41
|
+
const resolving_url = url;
|
42
|
+
resolve_wasm_src(url).then((resolved) => {
|
43
|
+
if (latest_url === resolving_url) {
|
44
|
+
resolved_url = resolved ?? undefined;
|
45
|
+
} else {
|
46
|
+
resolved && URL.revokeObjectURL(resolved);
|
47
|
+
}
|
48
|
+
});
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
/* BabylonJS engine and scene management */
|
53
|
+
let canvas: HTMLCanvasElement;
|
54
|
+
let scene: BABYLON.Scene;
|
55
|
+
let engine: BABYLON.Engine;
|
56
|
+
let mounted = false;
|
57
|
+
|
58
|
+
onMount(() => {
|
59
|
+
// Initialize BabylonJS engine and scene
|
60
|
+
engine = new BABYLON.Engine(canvas, true);
|
61
|
+
scene = new BABYLON.Scene(engine);
|
62
|
+
|
63
|
+
scene.createDefaultCameraOrLight();
|
64
|
+
scene.clearColor = scene.clearColor = new BABYLON.Color4(...clear_color);
|
65
|
+
|
66
|
+
engine.runRenderLoop(() => {
|
67
|
+
scene.render();
|
68
|
+
});
|
69
|
+
|
70
|
+
function onWindowResize(): void {
|
71
|
+
engine.resize();
|
72
|
+
}
|
73
|
+
window.addEventListener("resize", onWindowResize);
|
74
|
+
|
75
|
+
mounted = true;
|
76
|
+
|
77
|
+
return () => {
|
78
|
+
scene.dispose();
|
79
|
+
engine.dispose();
|
80
|
+
window.removeEventListener("resize", onWindowResize);
|
81
|
+
};
|
82
|
+
});
|
83
|
+
|
84
|
+
$: mounted && load_model(resolved_url);
|
85
|
+
|
86
|
+
function load_model(url: string | undefined): void {
|
87
|
+
if (scene) {
|
88
|
+
// Dispose of the previous model before loading a new one
|
89
|
+
scene.meshes.forEach((mesh) => {
|
90
|
+
mesh.dispose();
|
91
|
+
});
|
92
|
+
|
93
|
+
// Load the new model
|
94
|
+
if (url) {
|
95
|
+
BABYLON.SceneLoader.ShowLoadingScreen = false;
|
96
|
+
BABYLON.SceneLoader.Append(
|
97
|
+
url,
|
98
|
+
"",
|
99
|
+
scene,
|
100
|
+
() => create_camera(scene, camera_position, zoom_speed, pan_speed),
|
101
|
+
undefined,
|
102
|
+
undefined,
|
103
|
+
"." + value.path.split(".").pop()
|
104
|
+
);
|
105
|
+
}
|
106
|
+
}
|
107
|
+
}
|
108
|
+
|
109
|
+
function create_camera(
|
110
|
+
scene: BABYLON.Scene,
|
111
|
+
camera_position: [number | null, number | null, number | null],
|
112
|
+
zoom_speed: number,
|
113
|
+
pan_speed: number
|
114
|
+
): void {
|
115
|
+
scene.createDefaultCamera(true, true, true);
|
116
|
+
var helperCamera = scene.activeCamera! as BABYLON.ArcRotateCamera;
|
117
|
+
if (camera_position[0] !== null) {
|
118
|
+
helperCamera.alpha = BABYLON.Tools.ToRadians(camera_position[0]);
|
119
|
+
}
|
120
|
+
if (camera_position[1] !== null) {
|
121
|
+
helperCamera.beta = BABYLON.Tools.ToRadians(camera_position[1]);
|
122
|
+
}
|
123
|
+
if (camera_position[2] !== null) {
|
124
|
+
helperCamera.radius = camera_position[2];
|
125
|
+
}
|
126
|
+
helperCamera.lowerRadiusLimit = 0.1;
|
127
|
+
const updateCameraSensibility = (): void => {
|
128
|
+
helperCamera.wheelPrecision = 250 / (helperCamera.radius * zoom_speed);
|
129
|
+
helperCamera.panningSensibility =
|
130
|
+
(10000 * pan_speed) / helperCamera.radius;
|
131
|
+
};
|
132
|
+
updateCameraSensibility();
|
133
|
+
helperCamera.attachControl(true);
|
134
|
+
helperCamera.onAfterCheckInputsObservable.add(updateCameraSensibility);
|
135
|
+
}
|
136
|
+
|
137
|
+
export function reset_camera_position(
|
138
|
+
camera_position: [number | null, number | null, number | null],
|
139
|
+
zoom_speed: number,
|
140
|
+
pan_speed: number
|
141
|
+
): void {
|
142
|
+
if (scene) {
|
143
|
+
scene.removeCamera(scene.activeCamera!);
|
144
|
+
create_camera(scene, camera_position, zoom_speed, pan_speed);
|
145
|
+
}
|
146
|
+
}
|
147
|
+
</script>
|
148
|
+
|
149
|
+
<canvas bind:this={canvas}></canvas>
|
package/shared/Model3D.svelte
CHANGED
@@ -2,10 +2,7 @@
|
|
2
2
|
import type { FileData } from "@gradio/client";
|
3
3
|
import { BlockLabel, IconButton } from "@gradio/atoms";
|
4
4
|
import { File, Download, Undo } from "@gradio/icons";
|
5
|
-
import
|
6
|
-
import { onMount } from "svelte";
|
7
|
-
import * as BABYLON from "babylonjs";
|
8
|
-
import * as BABYLON_LOADERS from "babylonjs-loaders";
|
5
|
+
import Canvas3D from "./Canvas3D.svelte";
|
9
6
|
import type { I18nFormatter } from "@gradio/utils";
|
10
7
|
import { dequal } from "dequal";
|
11
8
|
|
@@ -25,71 +22,20 @@
|
|
25
22
|
|
26
23
|
let current_settings = { camera_position, zoom_speed, pan_speed };
|
27
24
|
|
28
|
-
|
29
|
-
|
30
|
-
BABYLON_LOADERS.OBJFileLoader != undefined &&
|
31
|
-
!BABYLON_LOADERS.OBJFileLoader.IMPORT_VERTEX_COLORS
|
32
|
-
) {
|
33
|
-
BABYLON_LOADERS.OBJFileLoader.IMPORT_VERTEX_COLORS = true;
|
34
|
-
}
|
35
|
-
}
|
36
|
-
|
37
|
-
let canvas: HTMLCanvasElement;
|
38
|
-
let scene: BABYLON.Scene;
|
39
|
-
let engine: BABYLON.Engine | null;
|
40
|
-
let mounted = false;
|
41
|
-
|
42
|
-
onMount(() => {
|
43
|
-
engine = new BABYLON.Engine(canvas, true);
|
44
|
-
window.addEventListener("resize", () => {
|
45
|
-
engine?.resize();
|
46
|
-
});
|
47
|
-
mounted = true;
|
48
|
-
});
|
49
|
-
|
50
|
-
$: ({ path } = value || {
|
51
|
-
path: undefined
|
52
|
-
});
|
53
|
-
|
54
|
-
$: canvas && mounted && path && dispose();
|
55
|
-
|
56
|
-
function dispose(): void {
|
57
|
-
if (scene && !scene.isDisposed) {
|
58
|
-
scene.dispose();
|
59
|
-
engine?.stopRenderLoop();
|
60
|
-
engine?.dispose();
|
61
|
-
engine = null;
|
62
|
-
engine = new BABYLON.Engine(canvas, true);
|
63
|
-
window.addEventListener("resize", () => {
|
64
|
-
engine?.resize();
|
65
|
-
});
|
66
|
-
}
|
67
|
-
if (engine !== null) {
|
68
|
-
scene = add_new_model(
|
69
|
-
canvas,
|
70
|
-
scene,
|
71
|
-
engine,
|
72
|
-
value,
|
73
|
-
clear_color,
|
74
|
-
camera_position,
|
75
|
-
zoom_speed,
|
76
|
-
pan_speed
|
77
|
-
);
|
78
|
-
}
|
79
|
-
}
|
25
|
+
let canvas3d: Canvas3D;
|
26
|
+
let resolved_url: string | undefined;
|
80
27
|
|
81
28
|
function handle_undo(): void {
|
82
|
-
reset_camera_position(
|
29
|
+
canvas3d.reset_camera_position(camera_position, zoom_speed, pan_speed);
|
83
30
|
}
|
84
31
|
|
85
32
|
$: {
|
86
33
|
if (
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
current_settings.pan_speed !== pan_speed)
|
34
|
+
!dequal(current_settings.camera_position, camera_position) ||
|
35
|
+
current_settings.zoom_speed !== zoom_speed ||
|
36
|
+
current_settings.pan_speed !== pan_speed
|
91
37
|
) {
|
92
|
-
reset_camera_position(
|
38
|
+
canvas3d.reset_camera_position(camera_position, zoom_speed, pan_speed);
|
93
39
|
current_settings = { camera_position, zoom_speed, pan_speed };
|
94
40
|
}
|
95
41
|
}
|
@@ -105,7 +51,7 @@
|
|
105
51
|
<div class="buttons">
|
106
52
|
<IconButton Icon={Undo} label="Undo" on:click={() => handle_undo()} />
|
107
53
|
<a
|
108
|
-
href={
|
54
|
+
href={resolved_url}
|
109
55
|
target={window.__is_colab__ ? "_blank" : null}
|
110
56
|
download={window.__is_colab__ ? null : value.orig_name || value.path}
|
111
57
|
>
|
@@ -113,7 +59,15 @@
|
|
113
59
|
</a>
|
114
60
|
</div>
|
115
61
|
|
116
|
-
<
|
62
|
+
<Canvas3D
|
63
|
+
bind:this={canvas3d}
|
64
|
+
bind:resolved_url
|
65
|
+
{value}
|
66
|
+
{clear_color}
|
67
|
+
{camera_position}
|
68
|
+
{zoom_speed}
|
69
|
+
{pan_speed}
|
70
|
+
/>
|
117
71
|
</div>
|
118
72
|
{/if}
|
119
73
|
|
@@ -124,7 +78,7 @@
|
|
124
78
|
width: var(--size-full);
|
125
79
|
height: var(--size-full);
|
126
80
|
}
|
127
|
-
canvas {
|
81
|
+
.model3D :global(canvas) {
|
128
82
|
width: var(--size-full);
|
129
83
|
height: var(--size-full);
|
130
84
|
object-fit: contain;
|
@@ -1,10 +1,11 @@
|
|
1
1
|
<script lang="ts">
|
2
|
-
import { createEventDispatcher, tick
|
2
|
+
import { createEventDispatcher, tick } from "svelte";
|
3
3
|
import { Upload, ModifyUpload } from "@gradio/upload";
|
4
4
|
import type { FileData } from "@gradio/client";
|
5
5
|
import { BlockLabel } from "@gradio/atoms";
|
6
6
|
import { File } from "@gradio/icons";
|
7
|
-
import {
|
7
|
+
import type { I18nFormatter } from "@gradio/utils";
|
8
|
+
import Canvas3D from "./Canvas3D.svelte";
|
8
9
|
|
9
10
|
export let value: null | FileData;
|
10
11
|
export let clear_color: [number, number, number, number] = [0, 0, 0, 0];
|
@@ -22,60 +23,25 @@
|
|
22
23
|
null
|
23
24
|
];
|
24
25
|
|
25
|
-
let mounted = false;
|
26
|
-
let canvas: HTMLCanvasElement;
|
27
|
-
let scene: BABYLON.Scene;
|
28
|
-
let engine: BABYLON.Engine;
|
29
|
-
|
30
|
-
function reset_scene(): void {
|
31
|
-
scene = add_new_model(
|
32
|
-
canvas,
|
33
|
-
scene,
|
34
|
-
engine,
|
35
|
-
value,
|
36
|
-
clear_color,
|
37
|
-
camera_position,
|
38
|
-
zoom_speed,
|
39
|
-
pan_speed
|
40
|
-
);
|
41
|
-
}
|
42
|
-
|
43
|
-
onMount(() => {
|
44
|
-
if (value != null) {
|
45
|
-
reset_scene();
|
46
|
-
}
|
47
|
-
mounted = true;
|
48
|
-
});
|
49
|
-
|
50
|
-
$: ({ path } = value || {
|
51
|
-
path: undefined
|
52
|
-
});
|
53
|
-
|
54
|
-
$: canvas && mounted && path != null && reset_scene();
|
55
|
-
|
56
26
|
async function handle_upload({
|
57
27
|
detail
|
58
28
|
}: CustomEvent<FileData>): Promise<void> {
|
59
29
|
value = detail;
|
60
30
|
await tick();
|
61
|
-
reset_scene();
|
62
31
|
dispatch("change", value);
|
63
32
|
dispatch("load", value);
|
64
33
|
}
|
65
34
|
|
66
35
|
async function handle_clear(): Promise<void> {
|
67
|
-
if (scene && engine) {
|
68
|
-
scene.dispose();
|
69
|
-
engine.dispose();
|
70
|
-
}
|
71
36
|
value = null;
|
72
37
|
await tick();
|
73
38
|
dispatch("clear");
|
74
39
|
dispatch("change");
|
75
40
|
}
|
76
41
|
|
42
|
+
let canvas3D: Canvas3D;
|
77
43
|
async function handle_undo(): Promise<void> {
|
78
|
-
reset_camera_position(
|
44
|
+
canvas3D.reset_camera_position(camera_position, zoom_speed, pan_speed);
|
79
45
|
}
|
80
46
|
|
81
47
|
const dispatch = createEventDispatcher<{
|
@@ -87,19 +53,6 @@
|
|
87
53
|
|
88
54
|
let dragging = false;
|
89
55
|
|
90
|
-
import * as BABYLON from "babylonjs";
|
91
|
-
import * as BABYLON_LOADERS from "babylonjs-loaders";
|
92
|
-
import type { I18nFormatter } from "@gradio/utils";
|
93
|
-
|
94
|
-
$: {
|
95
|
-
if (
|
96
|
-
BABYLON_LOADERS.OBJFileLoader != undefined &&
|
97
|
-
!BABYLON_LOADERS.OBJFileLoader.IMPORT_VERTEX_COLORS
|
98
|
-
) {
|
99
|
-
BABYLON_LOADERS.OBJFileLoader.IMPORT_VERTEX_COLORS = true;
|
100
|
-
}
|
101
|
-
}
|
102
|
-
|
103
56
|
$: dispatch("drag", dragging);
|
104
57
|
</script>
|
105
58
|
|
@@ -123,7 +76,14 @@
|
|
123
76
|
on:undo={handle_undo}
|
124
77
|
absolute
|
125
78
|
/>
|
126
|
-
<
|
79
|
+
<Canvas3D
|
80
|
+
bind:this={canvas3D}
|
81
|
+
{value}
|
82
|
+
{clear_color}
|
83
|
+
{camera_position}
|
84
|
+
{zoom_speed}
|
85
|
+
{pan_speed}
|
86
|
+
></Canvas3D>
|
127
87
|
</div>
|
128
88
|
{/if}
|
129
89
|
|
@@ -137,7 +97,7 @@
|
|
137
97
|
height: var(--size-full);
|
138
98
|
}
|
139
99
|
|
140
|
-
canvas {
|
100
|
+
.input-model :global(canvas) {
|
141
101
|
width: var(--size-full);
|
142
102
|
height: var(--size-full);
|
143
103
|
object-fit: contain;
|
package/shared/utils.ts
DELETED
@@ -1,85 +0,0 @@
|
|
1
|
-
import type { FileData } from "@gradio/client";
|
2
|
-
import * as BABYLON from "babylonjs";
|
3
|
-
|
4
|
-
const create_camera = (
|
5
|
-
scene: BABYLON.Scene,
|
6
|
-
camera_position: [number | null, number | null, number | null],
|
7
|
-
zoom_speed: number,
|
8
|
-
pan_speed: number
|
9
|
-
): void => {
|
10
|
-
scene.createDefaultCamera(true, true, true);
|
11
|
-
var helperCamera = scene.activeCamera! as BABYLON.ArcRotateCamera;
|
12
|
-
if (camera_position[0] !== null) {
|
13
|
-
helperCamera.alpha = BABYLON.Tools.ToRadians(camera_position[0]);
|
14
|
-
}
|
15
|
-
if (camera_position[1] !== null) {
|
16
|
-
helperCamera.beta = BABYLON.Tools.ToRadians(camera_position[1]);
|
17
|
-
}
|
18
|
-
if (camera_position[2] !== null) {
|
19
|
-
helperCamera.radius = camera_position[2];
|
20
|
-
}
|
21
|
-
helperCamera.lowerRadiusLimit = 0.1;
|
22
|
-
const updateCameraSensibility = (): void => {
|
23
|
-
helperCamera.wheelPrecision = 250 / (helperCamera.radius * zoom_speed);
|
24
|
-
helperCamera.panningSensibility = (10000 * pan_speed) / helperCamera.radius;
|
25
|
-
};
|
26
|
-
updateCameraSensibility();
|
27
|
-
helperCamera.attachControl(true);
|
28
|
-
helperCamera.onAfterCheckInputsObservable.add(updateCameraSensibility);
|
29
|
-
};
|
30
|
-
|
31
|
-
export const add_new_model = (
|
32
|
-
canvas: HTMLCanvasElement,
|
33
|
-
scene: BABYLON.Scene,
|
34
|
-
engine: BABYLON.Engine,
|
35
|
-
value: FileData | null,
|
36
|
-
clear_color: [number, number, number, number],
|
37
|
-
camera_position: [number | null, number | null, number | null],
|
38
|
-
zoom_speed: number,
|
39
|
-
pan_speed: number
|
40
|
-
): BABYLON.Scene => {
|
41
|
-
if (scene && !scene.isDisposed && engine) {
|
42
|
-
scene.dispose();
|
43
|
-
engine.dispose();
|
44
|
-
}
|
45
|
-
|
46
|
-
engine = new BABYLON.Engine(canvas, true);
|
47
|
-
scene = new BABYLON.Scene(engine);
|
48
|
-
scene.createDefaultCameraOrLight();
|
49
|
-
scene.clearColor = scene.clearColor = new BABYLON.Color4(...clear_color);
|
50
|
-
|
51
|
-
engine.runRenderLoop(() => {
|
52
|
-
scene.render();
|
53
|
-
});
|
54
|
-
|
55
|
-
window.addEventListener("resize", () => {
|
56
|
-
engine.resize();
|
57
|
-
});
|
58
|
-
|
59
|
-
if (!value) return scene;
|
60
|
-
let url: string;
|
61
|
-
|
62
|
-
url = value.url!;
|
63
|
-
|
64
|
-
BABYLON.SceneLoader.ShowLoadingScreen = false;
|
65
|
-
BABYLON.SceneLoader.Append(
|
66
|
-
url,
|
67
|
-
"",
|
68
|
-
scene,
|
69
|
-
() => create_camera(scene, camera_position, zoom_speed, pan_speed),
|
70
|
-
undefined,
|
71
|
-
undefined,
|
72
|
-
"." + value.path.split(".")[1]
|
73
|
-
);
|
74
|
-
return scene;
|
75
|
-
};
|
76
|
-
|
77
|
-
export const reset_camera_position = (
|
78
|
-
scene: BABYLON.Scene,
|
79
|
-
camera_position: [number | null, number | null, number | null],
|
80
|
-
zoom_speed: number,
|
81
|
-
pan_speed: number
|
82
|
-
): void => {
|
83
|
-
scene.removeCamera(scene.activeCamera!);
|
84
|
-
create_camera(scene, camera_position, zoom_speed, pan_speed);
|
85
|
-
};
|