@gradio/model3d 0.14.5 → 0.14.7
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 +22 -0
- package/dist/shared/Canvas3D.svelte +52 -121
- package/package.json +8 -9
- package/shared/Canvas3D.svelte +53 -138
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,27 @@
|
|
1
1
|
# @gradio/model3d
|
2
2
|
|
3
|
+
## 0.14.7
|
4
|
+
|
5
|
+
### Features
|
6
|
+
|
7
|
+
- [#10847](https://github.com/gradio-app/gradio/pull/10847) [`d5fde7c`](https://github.com/gradio-app/gradio/commit/d5fde7c390004ce5394072100b059f545d2d4eae) - Babylon update for model3D. Thanks @CedricGuillemet!
|
8
|
+
|
9
|
+
### Dependency updates
|
10
|
+
|
11
|
+
- @gradio/wasm@0.18.1
|
12
|
+
- @gradio/client@1.14.1
|
13
|
+
- @gradio/upload@0.15.7
|
14
|
+
|
15
|
+
## 0.14.6
|
16
|
+
|
17
|
+
### Dependency updates
|
18
|
+
|
19
|
+
- @gradio/atoms@0.14.1
|
20
|
+
- @gradio/statustracker@0.10.6
|
21
|
+
- @gradio/client@1.14.0
|
22
|
+
- @gradio/wasm@0.18.0
|
23
|
+
- @gradio/upload@0.15.6
|
24
|
+
|
3
25
|
## 0.14.5
|
4
26
|
|
5
27
|
### Dependency updates
|
@@ -1,12 +1,6 @@
|
|
1
1
|
<script>import { onMount } from "svelte";
|
2
|
-
import * as BABYLON from "babylonjs";
|
3
|
-
import * as BABYLON_LOADERS from "babylonjs-loaders";
|
4
2
|
import { resolve_wasm_src } from "@gradio/wasm/svelte";
|
5
|
-
|
6
|
-
if (BABYLON_LOADERS.OBJFileLoader != void 0 && !BABYLON_LOADERS.OBJFileLoader.IMPORT_VERTEX_COLORS) {
|
7
|
-
BABYLON_LOADERS.OBJFileLoader.IMPORT_VERTEX_COLORS = true;
|
8
|
-
}
|
9
|
-
}
|
3
|
+
let BABYLON_VIEWER;
|
10
4
|
export let value;
|
11
5
|
export let display_mode;
|
12
6
|
export let clear_color;
|
@@ -32,146 +26,83 @@ $: {
|
|
32
26
|
}
|
33
27
|
}
|
34
28
|
let canvas;
|
35
|
-
let
|
36
|
-
let
|
37
|
-
let point_cloud_system = null;
|
29
|
+
let viewer;
|
30
|
+
let viewerDetails;
|
38
31
|
let mounted = false;
|
39
32
|
onMount(() => {
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
33
|
+
const initViewer = async () => {
|
34
|
+
BABYLON_VIEWER = await import("@babylonjs/viewer");
|
35
|
+
BABYLON_VIEWER.createViewerForCanvas(canvas, {
|
36
|
+
clearColor: clear_color,
|
37
|
+
useRightHandedSystem: true,
|
38
|
+
cameraAutoOrbit: { enabled: false },
|
39
|
+
onInitialized: (details) => {
|
40
|
+
viewerDetails = details;
|
41
|
+
}
|
42
|
+
}).then((promiseViewer) => {
|
43
|
+
viewer = promiseViewer;
|
44
|
+
mounted = true;
|
45
|
+
});
|
46
|
+
};
|
47
|
+
initViewer();
|
53
48
|
return () => {
|
54
|
-
|
55
|
-
engine.dispose();
|
56
|
-
window.removeEventListener("resize", onWindowResize);
|
49
|
+
viewer?.dispose();
|
57
50
|
};
|
58
51
|
});
|
59
52
|
$:
|
60
53
|
mounted && load_model(resolved_url);
|
54
|
+
function setRenderingMode(pointsCloud, wireframe) {
|
55
|
+
viewerDetails.scene.forcePointsCloud = pointsCloud;
|
56
|
+
viewerDetails.scene.forceWireframe = wireframe;
|
57
|
+
}
|
61
58
|
function load_model(url2) {
|
62
|
-
if (
|
63
|
-
scene.meshes.forEach((mesh) => {
|
64
|
-
mesh.dispose();
|
65
|
-
});
|
66
|
-
if (point_cloud_system) {
|
67
|
-
point_cloud_system.dispose();
|
68
|
-
point_cloud_system = null;
|
69
|
-
}
|
59
|
+
if (viewer) {
|
70
60
|
if (url2) {
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
scene,
|
76
|
-
() => {
|
77
|
-
if (display_mode === "point_cloud") {
|
78
|
-
create_point_cloud(scene);
|
79
|
-
} else if (display_mode === "wireframe") {
|
80
|
-
create_wireframe(scene);
|
81
|
-
} else {
|
82
|
-
create_camera(scene, camera_position, zoom_speed, pan_speed);
|
61
|
+
viewer.loadModel(url2, {
|
62
|
+
pluginOptions: {
|
63
|
+
obj: {
|
64
|
+
importVertexColors: true
|
83
65
|
}
|
84
|
-
}
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
66
|
+
}
|
67
|
+
}).then(() => {
|
68
|
+
if (display_mode === "point_cloud") {
|
69
|
+
setRenderingMode(true, false);
|
70
|
+
} else if (display_mode === "wireframe") {
|
71
|
+
setRenderingMode(false, true);
|
72
|
+
} else {
|
73
|
+
update_camera(camera_position, zoom_speed, pan_speed);
|
74
|
+
}
|
75
|
+
});
|
76
|
+
} else {
|
77
|
+
viewer.resetModel();
|
89
78
|
}
|
90
79
|
}
|
91
80
|
}
|
92
|
-
function
|
93
|
-
|
94
|
-
|
81
|
+
function update_camera(camera_position2, zoom_speed2, pan_speed2) {
|
82
|
+
viewer.resetCamera();
|
83
|
+
const camera = viewerDetails.camera;
|
95
84
|
if (camera_position2[0] !== null) {
|
96
|
-
|
85
|
+
camera.alpha = camera_position2[0] * Math.PI / 180;
|
97
86
|
}
|
98
87
|
if (camera_position2[1] !== null) {
|
99
|
-
|
88
|
+
camera.beta = camera_position2[1] * Math.PI / 180;
|
100
89
|
}
|
101
90
|
if (camera_position2[2] !== null) {
|
102
|
-
|
91
|
+
camera.radius = camera_position2[2];
|
103
92
|
}
|
104
|
-
|
93
|
+
camera.lowerRadiusLimit = 0.1;
|
105
94
|
const updateCameraSensibility = () => {
|
106
|
-
|
107
|
-
|
95
|
+
camera.wheelPrecision = 250 / (camera.radius * zoom_speed2);
|
96
|
+
camera.panningSensibility = 1e4 * pan_speed2 / camera.radius;
|
108
97
|
};
|
109
98
|
updateCameraSensibility();
|
110
|
-
|
111
|
-
helperCamera.onAfterCheckInputsObservable.add(updateCameraSensibility);
|
99
|
+
camera.onAfterCheckInputsObservable.add(updateCameraSensibility);
|
112
100
|
}
|
113
101
|
export function reset_camera_position(camera_position2, zoom_speed2, pan_speed2) {
|
114
|
-
if (
|
115
|
-
|
116
|
-
create_camera(scene, camera_position2, zoom_speed2, pan_speed2);
|
102
|
+
if (viewerDetails) {
|
103
|
+
update_camera(camera_position2, zoom_speed2, pan_speed2);
|
117
104
|
}
|
118
105
|
}
|
119
|
-
function create_point_cloud(scene2) {
|
120
|
-
const meshes = scene2.meshes;
|
121
|
-
const pointPositions = [];
|
122
|
-
meshes.forEach((mesh) => {
|
123
|
-
if (mesh instanceof BABYLON.Mesh) {
|
124
|
-
const positions = mesh.getVerticesData(
|
125
|
-
BABYLON.VertexBuffer.PositionKind
|
126
|
-
);
|
127
|
-
if (positions) {
|
128
|
-
for (let i = 0; i < positions.length; i += 3) {
|
129
|
-
pointPositions.push(
|
130
|
-
new BABYLON.Vector3(
|
131
|
-
positions[i],
|
132
|
-
positions[i + 1],
|
133
|
-
positions[i + 2]
|
134
|
-
)
|
135
|
-
);
|
136
|
-
}
|
137
|
-
}
|
138
|
-
mesh.setEnabled(false);
|
139
|
-
}
|
140
|
-
});
|
141
|
-
point_cloud_system = new BABYLON.PointsCloudSystem(
|
142
|
-
"point_cloud_system",
|
143
|
-
1,
|
144
|
-
scene2
|
145
|
-
);
|
146
|
-
point_cloud_system.addPoints(
|
147
|
-
pointPositions.length,
|
148
|
-
(particle, i) => {
|
149
|
-
particle.position = pointPositions[i];
|
150
|
-
particle.color = new BABYLON.Color4(
|
151
|
-
Math.random(),
|
152
|
-
Math.random(),
|
153
|
-
Math.random(),
|
154
|
-
1
|
155
|
-
);
|
156
|
-
}
|
157
|
-
);
|
158
|
-
point_cloud_system.buildMeshAsync().then((mesh) => {
|
159
|
-
mesh.alwaysSelectAsActiveMesh = true;
|
160
|
-
create_camera(scene2, camera_position, zoom_speed, pan_speed);
|
161
|
-
});
|
162
|
-
}
|
163
|
-
function create_wireframe(scene2) {
|
164
|
-
scene2.meshes.forEach((mesh) => {
|
165
|
-
if (mesh instanceof BABYLON.Mesh) {
|
166
|
-
mesh.material = new BABYLON.StandardMaterial(
|
167
|
-
"wireframeMaterial",
|
168
|
-
scene2
|
169
|
-
);
|
170
|
-
mesh.material.wireframe = true;
|
171
|
-
}
|
172
|
-
create_camera(scene2, camera_position, zoom_speed, pan_speed);
|
173
|
-
});
|
174
|
-
}
|
175
106
|
</script>
|
176
107
|
|
177
108
|
<canvas bind:this={canvas}></canvas>
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@gradio/model3d",
|
3
|
-
"version": "0.14.
|
3
|
+
"version": "0.14.7",
|
4
4
|
"description": "Gradio UI packages",
|
5
5
|
"type": "module",
|
6
6
|
"author": "",
|
@@ -8,17 +8,16 @@
|
|
8
8
|
"private": false,
|
9
9
|
"dependencies": {
|
10
10
|
"@types/babylon": "^6.16.6",
|
11
|
-
"babylonjs": "^7.
|
12
|
-
"babylonjs-loaders": "^7.25.1",
|
11
|
+
"@babylonjs/viewer": "^7.54.0",
|
13
12
|
"dequal": "^2.0.2",
|
14
13
|
"gsplat": "^1.0.5",
|
15
|
-
"@gradio/
|
16
|
-
"@gradio/client": "^1.13.1",
|
17
|
-
"@gradio/upload": "^0.15.5",
|
14
|
+
"@gradio/client": "^1.14.1",
|
18
15
|
"@gradio/icons": "^0.10.0",
|
19
|
-
"@gradio/
|
20
|
-
"@gradio/
|
21
|
-
"@gradio/
|
16
|
+
"@gradio/statustracker": "^0.10.6",
|
17
|
+
"@gradio/atoms": "^0.14.1",
|
18
|
+
"@gradio/upload": "^0.15.7",
|
19
|
+
"@gradio/utils": "^0.10.1",
|
20
|
+
"@gradio/wasm": "^0.18.1"
|
22
21
|
},
|
23
22
|
"devDependencies": {
|
24
23
|
"@gradio/preview": "^0.13.0"
|
package/shared/Canvas3D.svelte
CHANGED
@@ -1,18 +1,10 @@
|
|
1
1
|
<script lang="ts">
|
2
2
|
import { onMount } from "svelte";
|
3
|
-
import * as BABYLON from "babylonjs";
|
4
|
-
import * as BABYLON_LOADERS from "babylonjs-loaders";
|
5
3
|
import type { FileData } from "@gradio/client";
|
6
4
|
import { resolve_wasm_src } from "@gradio/wasm/svelte";
|
5
|
+
import type { Viewer, ViewerDetails } from "@babylonjs/viewer";
|
7
6
|
|
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
|
-
}
|
7
|
+
let BABYLON_VIEWER: typeof import("@babylonjs/viewer");
|
16
8
|
|
17
9
|
export let value: FileData;
|
18
10
|
export let display_mode: "solid" | "point_cloud" | "wireframe";
|
@@ -50,104 +42,90 @@
|
|
50
42
|
}
|
51
43
|
}
|
52
44
|
|
53
|
-
/* BabylonJS engine and scene management */
|
54
45
|
let canvas: HTMLCanvasElement;
|
55
|
-
let
|
56
|
-
let
|
57
|
-
let point_cloud_system: BABYLON.PointsCloudSystem | null = null;
|
46
|
+
let viewer: Viewer;
|
47
|
+
let viewerDetails: Readonly<ViewerDetails>;
|
58
48
|
let mounted = false;
|
59
49
|
|
60
50
|
onMount(() => {
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
}
|
76
|
-
window.addEventListener("resize", onWindowResize);
|
51
|
+
const initViewer = async (): Promise<void> => {
|
52
|
+
BABYLON_VIEWER = await import("@babylonjs/viewer");
|
53
|
+
BABYLON_VIEWER.createViewerForCanvas(canvas, {
|
54
|
+
clearColor: clear_color,
|
55
|
+
useRightHandedSystem: true,
|
56
|
+
cameraAutoOrbit: { enabled: false },
|
57
|
+
onInitialized: (details: any) => {
|
58
|
+
viewerDetails = details;
|
59
|
+
}
|
60
|
+
}).then((promiseViewer: any) => {
|
61
|
+
viewer = promiseViewer;
|
62
|
+
mounted = true;
|
63
|
+
});
|
64
|
+
};
|
77
65
|
|
78
|
-
|
66
|
+
initViewer();
|
79
67
|
|
80
68
|
return () => {
|
81
|
-
|
82
|
-
engine.dispose();
|
83
|
-
window.removeEventListener("resize", onWindowResize);
|
69
|
+
viewer?.dispose();
|
84
70
|
};
|
85
71
|
});
|
86
72
|
|
87
73
|
$: mounted && load_model(resolved_url);
|
88
74
|
|
89
|
-
function
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
mesh.dispose();
|
94
|
-
});
|
95
|
-
|
96
|
-
if (point_cloud_system) {
|
97
|
-
point_cloud_system.dispose();
|
98
|
-
point_cloud_system = null;
|
99
|
-
}
|
75
|
+
function setRenderingMode(pointsCloud: boolean, wireframe: boolean): void {
|
76
|
+
viewerDetails.scene.forcePointsCloud = pointsCloud;
|
77
|
+
viewerDetails.scene.forceWireframe = wireframe;
|
78
|
+
}
|
100
79
|
|
101
|
-
|
80
|
+
function load_model(url: string | undefined): void {
|
81
|
+
if (viewer) {
|
102
82
|
if (url) {
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
83
|
+
viewer
|
84
|
+
.loadModel(url, {
|
85
|
+
pluginOptions: {
|
86
|
+
obj: {
|
87
|
+
importVertexColors: true
|
88
|
+
}
|
89
|
+
}
|
90
|
+
})
|
91
|
+
.then(() => {
|
109
92
|
if (display_mode === "point_cloud") {
|
110
|
-
|
93
|
+
setRenderingMode(true, false);
|
111
94
|
} else if (display_mode === "wireframe") {
|
112
|
-
|
95
|
+
setRenderingMode(false, true);
|
113
96
|
} else {
|
114
|
-
|
97
|
+
update_camera(camera_position, zoom_speed, pan_speed);
|
115
98
|
}
|
116
|
-
}
|
117
|
-
|
118
|
-
|
119
|
-
"." + value.path.split(".").pop()
|
120
|
-
);
|
99
|
+
});
|
100
|
+
} else {
|
101
|
+
viewer.resetModel();
|
121
102
|
}
|
122
103
|
}
|
123
104
|
}
|
124
105
|
|
125
|
-
function
|
126
|
-
scene: BABYLON.Scene,
|
106
|
+
function update_camera(
|
127
107
|
camera_position: [number | null, number | null, number | null],
|
128
108
|
zoom_speed: number,
|
129
109
|
pan_speed: number
|
130
110
|
): void {
|
131
|
-
|
132
|
-
|
111
|
+
viewer.resetCamera();
|
112
|
+
const camera = viewerDetails.camera;
|
133
113
|
if (camera_position[0] !== null) {
|
134
|
-
|
114
|
+
camera.alpha = (camera_position[0] * Math.PI) / 180;
|
135
115
|
}
|
136
116
|
if (camera_position[1] !== null) {
|
137
|
-
|
117
|
+
camera.beta = (camera_position[1] * Math.PI) / 180;
|
138
118
|
}
|
139
119
|
if (camera_position[2] !== null) {
|
140
|
-
|
120
|
+
camera.radius = camera_position[2];
|
141
121
|
}
|
142
|
-
|
122
|
+
camera.lowerRadiusLimit = 0.1;
|
143
123
|
const updateCameraSensibility = (): void => {
|
144
|
-
|
145
|
-
|
146
|
-
(10000 * pan_speed) / helperCamera.radius;
|
124
|
+
camera.wheelPrecision = 250 / (camera.radius * zoom_speed);
|
125
|
+
camera.panningSensibility = (10000 * pan_speed) / camera.radius;
|
147
126
|
};
|
148
127
|
updateCameraSensibility();
|
149
|
-
|
150
|
-
helperCamera.onAfterCheckInputsObservable.add(updateCameraSensibility);
|
128
|
+
camera.onAfterCheckInputsObservable.add(updateCameraSensibility);
|
151
129
|
}
|
152
130
|
|
153
131
|
export function reset_camera_position(
|
@@ -155,73 +133,10 @@
|
|
155
133
|
zoom_speed: number,
|
156
134
|
pan_speed: number
|
157
135
|
): void {
|
158
|
-
if (
|
159
|
-
|
160
|
-
create_camera(scene, camera_position, zoom_speed, pan_speed);
|
136
|
+
if (viewerDetails) {
|
137
|
+
update_camera(camera_position, zoom_speed, pan_speed);
|
161
138
|
}
|
162
139
|
}
|
163
|
-
|
164
|
-
function create_point_cloud(scene: BABYLON.Scene): void {
|
165
|
-
const meshes = scene.meshes;
|
166
|
-
const pointPositions: BABYLON.Vector3[] = [];
|
167
|
-
|
168
|
-
meshes.forEach((mesh) => {
|
169
|
-
if (mesh instanceof BABYLON.Mesh) {
|
170
|
-
const positions = mesh.getVerticesData(
|
171
|
-
BABYLON.VertexBuffer.PositionKind
|
172
|
-
);
|
173
|
-
if (positions) {
|
174
|
-
for (let i = 0; i < positions.length; i += 3) {
|
175
|
-
pointPositions.push(
|
176
|
-
new BABYLON.Vector3(
|
177
|
-
positions[i],
|
178
|
-
positions[i + 1],
|
179
|
-
positions[i + 2]
|
180
|
-
)
|
181
|
-
);
|
182
|
-
}
|
183
|
-
}
|
184
|
-
mesh.setEnabled(false);
|
185
|
-
}
|
186
|
-
});
|
187
|
-
|
188
|
-
point_cloud_system = new BABYLON.PointsCloudSystem(
|
189
|
-
"point_cloud_system",
|
190
|
-
1,
|
191
|
-
scene
|
192
|
-
);
|
193
|
-
|
194
|
-
point_cloud_system.addPoints(
|
195
|
-
pointPositions.length,
|
196
|
-
(particle: BABYLON.CloudPoint, i: number) => {
|
197
|
-
particle.position = pointPositions[i];
|
198
|
-
particle.color = new BABYLON.Color4(
|
199
|
-
Math.random(),
|
200
|
-
Math.random(),
|
201
|
-
Math.random(),
|
202
|
-
1.0
|
203
|
-
);
|
204
|
-
}
|
205
|
-
);
|
206
|
-
|
207
|
-
point_cloud_system.buildMeshAsync().then((mesh) => {
|
208
|
-
mesh.alwaysSelectAsActiveMesh = true;
|
209
|
-
create_camera(scene, camera_position, zoom_speed, pan_speed);
|
210
|
-
});
|
211
|
-
}
|
212
|
-
|
213
|
-
function create_wireframe(scene: BABYLON.Scene): void {
|
214
|
-
scene.meshes.forEach((mesh) => {
|
215
|
-
if (mesh instanceof BABYLON.Mesh) {
|
216
|
-
mesh.material = new BABYLON.StandardMaterial(
|
217
|
-
"wireframeMaterial",
|
218
|
-
scene
|
219
|
-
);
|
220
|
-
mesh.material.wireframe = true;
|
221
|
-
}
|
222
|
-
create_camera(scene, camera_position, zoom_speed, pan_speed);
|
223
|
-
});
|
224
|
-
}
|
225
140
|
</script>
|
226
141
|
|
227
142
|
<canvas bind:this={canvas}></canvas>
|