-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add gsplat dependency add gsplat implementation run formatting move example .splat and .ply to url add changeset dispose of renderer on unmount notebook * dynamically load canvas components
- Loading branch information
1 parent
4ab399f
commit 3e886d8
Showing
9 changed files
with
241 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
"@gradio/model3d": minor | ||
"gradio": minor | ||
--- | ||
|
||
feat:Model3D Gaussian Splatting |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: model3D"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('files')\n", "!wget -q -O files/Bunny.obj https://github.com/gradio-app/gradio/raw/main/demo/model3D/files/Bunny.obj\n", "!wget -q -O files/Duck.glb https://github.com/gradio-app/gradio/raw/main/demo/model3D/files/Duck.glb\n", "!wget -q -O files/Fox.gltf https://github.com/gradio-app/gradio/raw/main/demo/model3D/files/Fox.gltf\n", "!wget -q -O files/face.obj https://github.com/gradio-app/gradio/raw/main/demo/model3D/files/face.obj\n", "!wget -q -O files/sofia.stl https://github.com/gradio-app/gradio/raw/main/demo/model3D/files/sofia.stl\n", "!wget -q -O files/source.txt https://github.com/gradio-app/gradio/raw/main/demo/model3D/files/source.txt"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import os\n", "\n", "\n", "def load_mesh(mesh_file_name):\n", " return mesh_file_name\n", "\n", "\n", "demo = gr.Interface(\n", " fn=load_mesh,\n", " inputs=gr.Model3D(),\n", " outputs=gr.Model3D(\n", " clear_color=[0.0, 0.0, 0.0, 0.0], label=\"3D Model\"),\n", " examples=[\n", " [os.path.join(os.path.abspath(''), \"files/Bunny.obj\")],\n", " [os.path.join(os.path.abspath(''), \"files/Duck.glb\")],\n", " [os.path.join(os.path.abspath(''), \"files/Fox.gltf\")],\n", " [os.path.join(os.path.abspath(''), \"files/face.obj\")],\n", " [os.path.join(os.path.abspath(''), \"files/sofia.stl\")],\n", " ],\n", " cache_examples=True\n", ")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} | ||
{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: model3D"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["# Downloading files from the demo repo\n", "import os\n", "os.mkdir('files')\n", "!wget -q -O files/Bunny.obj https://github.com/gradio-app/gradio/raw/main/demo/model3D/files/Bunny.obj\n", "!wget -q -O files/Duck.glb https://github.com/gradio-app/gradio/raw/main/demo/model3D/files/Duck.glb\n", "!wget -q -O files/Fox.gltf https://github.com/gradio-app/gradio/raw/main/demo/model3D/files/Fox.gltf\n", "!wget -q -O files/face.obj https://github.com/gradio-app/gradio/raw/main/demo/model3D/files/face.obj\n", "!wget -q -O files/sofia.stl https://github.com/gradio-app/gradio/raw/main/demo/model3D/files/sofia.stl\n", "!wget -q -O files/source.txt https://github.com/gradio-app/gradio/raw/main/demo/model3D/files/source.txt"]}, {"cell_type": "code", "execution_count": null, "id": "44380577570523278879349135829904343037", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "import os\n", "\n", "\n", "def load_mesh(mesh_file_name):\n", " return mesh_file_name\n", "\n", "\n", "demo = gr.Interface(\n", " fn=load_mesh,\n", " inputs=gr.Model3D(),\n", " outputs=gr.Model3D(\n", " clear_color=[0.0, 0.0, 0.0, 0.0], label=\"3D Model\"),\n", " examples=[\n", " [os.path.join(os.path.abspath(''), \"files/Bunny.obj\")],\n", " [os.path.join(os.path.abspath(''), \"files/Duck.glb\")],\n", " [os.path.join(os.path.abspath(''), \"files/Fox.gltf\")],\n", " [os.path.join(os.path.abspath(''), \"files/face.obj\")],\n", " [os.path.join(os.path.abspath(''), \"files/sofia.stl\")],\n", " [\"https://huggingface.co/datasets/dylanebert/3dgs/resolve/main/bonsai/bonsai-7k-mini.splat\"],\n", " [\"https://huggingface.co/datasets/dylanebert/3dgs/resolve/main/luigi/luigi.ply\"],\n", " ],\n", " cache_examples=True\n", ")\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
<script lang="ts"> | ||
import { onMount } from "svelte"; | ||
import * as SPLAT from "gsplat"; | ||
import type { FileData } from "@gradio/client"; | ||
import { resolve_wasm_src } from "@gradio/wasm/svelte"; | ||
export let value: FileData; | ||
export let zoom_speed: number; | ||
export let pan_speed: number; | ||
$: url = value.url; | ||
/* URL resolution for the Wasm mode. */ | ||
export let resolved_url: typeof url = undefined; // Exposed to be bound to the download link in the parent component. | ||
// The prop can be updated before the Promise from `resolve_wasm_src` is resolved. | ||
// In such a case, the resolved url for the old `url` has to be discarded, | ||
// This variable `latest_url` is used to pick up only the value resolved for the latest `url`. | ||
let latest_url: typeof url; | ||
$: { | ||
// In normal (non-Wasm) Gradio, the original `url` should be used immediately | ||
// without waiting for `resolve_wasm_src()` to resolve. | ||
// If it waits, a blank element is displayed until the async task finishes | ||
// and it leads to undesirable flickering. | ||
// So set `resolved_url` immediately above, and update it with the resolved values below later. | ||
resolved_url = url; | ||
if (url) { | ||
latest_url = url; | ||
const resolving_url = url; | ||
resolve_wasm_src(url).then((resolved) => { | ||
if (latest_url === resolving_url) { | ||
resolved_url = resolved ?? undefined; | ||
} else { | ||
resolved && URL.revokeObjectURL(resolved); | ||
} | ||
}); | ||
} | ||
} | ||
let canvas: HTMLCanvasElement; | ||
let scene: SPLAT.Scene; | ||
let camera: SPLAT.Camera; | ||
let renderer: SPLAT.WebGLRenderer | null = null; | ||
let controls: SPLAT.OrbitControls; | ||
let mounted = false; | ||
let frameId: number | null = null; | ||
function reset_scene(): void { | ||
if (frameId !== null) { | ||
cancelAnimationFrame(frameId); | ||
frameId = null; | ||
} | ||
if (renderer !== null) { | ||
renderer.dispose(); | ||
renderer = null; | ||
} | ||
scene = new SPLAT.Scene(); | ||
camera = new SPLAT.Camera(); | ||
renderer = new SPLAT.WebGLRenderer(canvas); | ||
controls = new SPLAT.OrbitControls(camera, canvas); | ||
controls.zoomSpeed = zoom_speed; | ||
controls.panSpeed = pan_speed; | ||
if (!value) { | ||
return; | ||
} | ||
let loading = false; | ||
const load = async (): Promise<void> => { | ||
if (loading) { | ||
console.error("Already loading"); | ||
return; | ||
} | ||
if (!resolved_url) { | ||
throw new Error("No resolved URL"); | ||
} | ||
loading = true; | ||
if (resolved_url.endsWith(".ply")) { | ||
await SPLAT.PLYLoader.LoadAsync(resolved_url, scene, undefined); | ||
} else if (resolved_url.endsWith(".splat")) { | ||
await SPLAT.Loader.LoadAsync(resolved_url, scene, undefined); | ||
} else { | ||
throw new Error("Unsupported file type"); | ||
} | ||
loading = false; | ||
}; | ||
const frame = (): void => { | ||
if (!renderer) { | ||
return; | ||
} | ||
if (loading) { | ||
frameId = requestAnimationFrame(frame); | ||
return; | ||
} | ||
controls.update(); | ||
renderer.render(scene, camera); | ||
frameId = requestAnimationFrame(frame); | ||
}; | ||
load(); | ||
frameId = requestAnimationFrame(frame); | ||
} | ||
onMount(() => { | ||
if (value != null) { | ||
reset_scene(); | ||
} | ||
mounted = true; | ||
return () => { | ||
if (renderer) { | ||
renderer.dispose(); | ||
} | ||
}; | ||
}); | ||
$: ({ path } = value || { | ||
path: undefined | ||
}); | ||
$: canvas && mounted && path && reset_scene(); | ||
</script> | ||
|
||
<canvas bind:this={canvas}></canvas> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.