mirror of
https://github.com/gradio-app/gradio.git
synced 2025-01-12 10:34:32 +08:00
add model3d output
This commit is contained in:
parent
07b2a4992f
commit
d137654e46
@ -1,10 +1,9 @@
|
||||
import os.path
|
||||
|
||||
import gradio as gr
|
||||
|
||||
|
||||
def load_mesh(mesh_file_name):
|
||||
file_dir = "files"
|
||||
file_dir = "demo/model3d/files"
|
||||
mesh_path = os.path.join(file_dir, mesh_file_name)
|
||||
return mesh_path
|
||||
|
||||
@ -15,7 +14,7 @@ iface = gr.Interface(
|
||||
gr.inputs.Dropdown(["Duck.glb", "Bunny.obj", "Fox.gltf"], type="value", default="Duck.glb", label="Mesh File")
|
||||
],
|
||||
outputs=[
|
||||
"model"
|
||||
"model3d"
|
||||
|
||||
# to specify options use the object initializer
|
||||
# gr.outputs.Model(clear_color=[1.0, 1.0, 1.0], label="3D Model")
|
@ -852,17 +852,17 @@ class State(OutputComponent):
|
||||
"state": {},
|
||||
}
|
||||
|
||||
|
||||
class Model(OutputComponent):
|
||||
class Model3D(OutputComponent):
|
||||
'''
|
||||
Used for 3d model output.
|
||||
Output type: filepath
|
||||
Demos: hello_model
|
||||
Demos: model3d
|
||||
'''
|
||||
|
||||
def __init__(self, clear_color=None, label=None):
|
||||
'''
|
||||
Parameters:
|
||||
clear_color (List[r, g, b, a]): background color of scene
|
||||
label (str): component name in interface.
|
||||
'''
|
||||
super().__init__(label)
|
||||
@ -871,7 +871,7 @@ class Model(OutputComponent):
|
||||
@classmethod
|
||||
def get_shortcut_implementations(cls):
|
||||
return {
|
||||
"model": {},
|
||||
"model3d": {},
|
||||
}
|
||||
|
||||
def postprocess(self, y):
|
||||
@ -884,14 +884,16 @@ class Model(OutputComponent):
|
||||
(str): base64 url data
|
||||
"""
|
||||
|
||||
# return processing_utils.encode_file_to_base64(y)
|
||||
|
||||
if self.clear_color is None:
|
||||
self.clear_color = [0.2, 0.2, 0.2]
|
||||
self.clear_color = [0.2, 0.2, 0.2, 1.0]
|
||||
|
||||
return {
|
||||
"name": os.path.basename(y),
|
||||
"extension": os.path.splitext(y)[1],
|
||||
"clearColor": self.clear_color,
|
||||
"data": processing_utils.encode_file_to_base64(y, type="model"),
|
||||
"data": processing_utils.encode_file_to_base64(y),
|
||||
}
|
||||
|
||||
def deserialize(self, x):
|
||||
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"dependencies": {
|
||||
"three": "^0.138.2",
|
||||
"vitest": "^0.5.9"
|
||||
}
|
||||
}
|
@ -20,7 +20,11 @@
|
||||
"svelte": "^3.46.3",
|
||||
"svelte-check": "^2.4.1",
|
||||
"svelte-i18n": "^3.3.13",
|
||||
"vitest": "^0.3.2",
|
||||
"three": "^0.138.2"
|
||||
"babylonjs": "^4.2.1",
|
||||
"babylonjs-loaders": "^4.2.1",
|
||||
"vitest": "^0.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/three": "^0.138.0"
|
||||
}
|
||||
}
|
||||
|
7474
ui/packages/app/public/static/img/Bunny.obj
Normal file
7474
ui/packages/app/public/static/img/Bunny.obj
Normal file
File diff suppressed because it is too large
Load Diff
BIN
ui/packages/app/public/static/img/Duck.glb
Normal file
BIN
ui/packages/app/public/static/img/Duck.glb
Normal file
Binary file not shown.
@ -25,7 +25,7 @@ import OutputTextbox from "./output/Textbox/config.js";
|
||||
import OutputVideo from "./output/Video/config.js";
|
||||
import OutputTimeSeries from "./output/TimeSeries/config.js";
|
||||
import OutputChatbot from "./output/Chatbot/config.js";
|
||||
import OutputModel from "./output/Model/config.js";
|
||||
import OutputModel3D from "./output/Model3D/config.js";
|
||||
|
||||
import StaticButton from "./static/Button/config.js";
|
||||
import StaticMarkdown from "./static/Markdown/config.js";
|
||||
@ -60,7 +60,7 @@ export const output_component_map = {
|
||||
timeseries: OutputTimeSeries,
|
||||
video: OutputVideo,
|
||||
chatbot: OutputChatbot,
|
||||
model: OutputModel
|
||||
model3d: OutputModel3D
|
||||
};
|
||||
|
||||
export const static_component_map = {
|
||||
|
@ -1,85 +0,0 @@
|
||||
<script lang="ts">
|
||||
export let value: string;
|
||||
export let theme: string;
|
||||
|
||||
componentDidMount() {
|
||||
const canvas = document.getElementById("renderCanvas");
|
||||
const engine = new BABYLON.Engine(canvas, true);
|
||||
|
||||
this.scene = new BABYLON.Scene(engine);
|
||||
this.scene.createDefaultCameraOrLight();
|
||||
|
||||
const clearColor = this.props.value["clearColor"]
|
||||
this.scene.clearColor = new BABYLON.Color3(clearColor[0], clearColor[1], clearColor[2]);
|
||||
|
||||
this.addNewModel();
|
||||
|
||||
engine.runRenderLoop(() => {
|
||||
this.scene.render();
|
||||
});
|
||||
|
||||
window.addEventListener("resize", () => {
|
||||
engine.resize();
|
||||
});
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps, prevState, snapshot) {
|
||||
this.addNewModel();
|
||||
}
|
||||
|
||||
addNewModel() {
|
||||
// remove all existing models
|
||||
for (let mesh of this.scene.meshes) {
|
||||
mesh.dispose();
|
||||
}
|
||||
|
||||
// add new model
|
||||
let base64_model_content = this.props.value["data"];
|
||||
let raw_content = BABYLON.Tools.DecodeBase64(base64_model_content);
|
||||
let blob = new Blob([raw_content]);
|
||||
let url = URL.createObjectURL(blob);
|
||||
BABYLON.SceneLoader.Append("", url, this.scene, () => {
|
||||
this.scene.createDefaultCamera(true, true, true);
|
||||
}, undefined, undefined, this.props.value["extension"]);
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.props.value) {
|
||||
return (
|
||||
<div className="output_model">
|
||||
<canvas id="renderCanvas"></canvas>
|
||||
<a href={this.props.value["data"]} download={this.props.value["name"]} className="download_link">Download {this.props.value["name"]}</a>
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="output-image w-full h-60 flex justify-center items-center bg-gray-200 dark:bg-gray-600 relative"
|
||||
{theme}
|
||||
>
|
||||
<div className="output_model_example">{value}</div>;
|
||||
|
||||
<div className="output_model">
|
||||
<canvas id="renderCanvas"></canvas>
|
||||
<a href={this.props.value["data"]} download={value} className="download_link">Download {value}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="postcss">
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// class ModelOutputExample extends ComponentExample {
|
||||
// render() {
|
||||
// return <div className="output_model_example">{this.props.value}</div>;
|
||||
// }
|
||||
// }
|
||||
|
||||
// export {ModelOutput, ModelOutputExample};
|
55
ui/packages/app/src/components/output/Model3D/Model3D.svelte
Normal file
55
ui/packages/app/src/components/output/Model3D/Model3D.svelte
Normal file
@ -0,0 +1,55 @@
|
||||
<script lang="ts">
|
||||
export let value: string;
|
||||
export let theme: string;
|
||||
|
||||
import { onMount, afterUpdate} from 'svelte';
|
||||
import * as BABYLON from 'babylonjs';
|
||||
import 'babylonjs-loaders'
|
||||
|
||||
let canvas: HTMLCanvasElement;
|
||||
let scene: BABYLON.Scene;
|
||||
|
||||
onMount(() => {
|
||||
const engine = new BABYLON.Engine(canvas, true);
|
||||
scene = new BABYLON.Scene(engine);
|
||||
scene.createDefaultCameraOrLight();
|
||||
const clearColor = value["clearColor"]
|
||||
scene.clearColor = new BABYLON.Color4(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
|
||||
engine.runRenderLoop(() => {
|
||||
scene.render();
|
||||
});
|
||||
|
||||
window.addEventListener('resize', () => {
|
||||
engine.resize();
|
||||
});
|
||||
});
|
||||
|
||||
afterUpdate(() => {
|
||||
addNewModel();
|
||||
});
|
||||
|
||||
function addNewModel() {
|
||||
for (let mesh of scene.meshes) {
|
||||
mesh.dispose();
|
||||
}
|
||||
|
||||
let base64_model_content = value["data"];
|
||||
let raw_content = BABYLON.Tools.DecodeBase64(base64_model_content);
|
||||
let blob = new Blob([raw_content]);
|
||||
let url = URL.createObjectURL(blob);
|
||||
BABYLON.SceneLoader.Append("", url, scene, () => {
|
||||
scene.createDefaultCamera(true, true, true);
|
||||
}, undefined, undefined, value["extension"]);
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<div
|
||||
class="output-model w-full h-60 flex justify-center items-center bg-gray-200 dark:bg-gray-600 relative"
|
||||
{theme}
|
||||
>
|
||||
<canvas class="w-full h-full object-fit" bind:this={canvas}></canvas>
|
||||
</div>
|
||||
|
||||
<style lang="postcss">
|
||||
</style>
|
@ -1,4 +1,4 @@
|
||||
import Component from "./Model.svelte";
|
||||
import Component from "./Model3D.svelte";
|
||||
|
||||
export default {
|
||||
component: Component
|
@ -4,6 +4,9 @@ importers:
|
||||
|
||||
.:
|
||||
specifiers:
|
||||
'@types/three': ^0.138.0
|
||||
babylonjs: ^4.2.1
|
||||
babylonjs-loaders: ^4.2.1
|
||||
prettier: ^2.5.1
|
||||
prettier-plugin-svelte: ^2.6.0
|
||||
svelte: ^3.46.3
|
||||
@ -11,12 +14,16 @@ importers:
|
||||
svelte-i18n: ^3.3.13
|
||||
vitest: ^0.3.2
|
||||
dependencies:
|
||||
babylonjs: 4.2.1
|
||||
babylonjs-loaders: 4.2.1
|
||||
prettier: 2.5.1
|
||||
prettier-plugin-svelte: 2.6.0_prettier@2.5.1+svelte@3.46.3
|
||||
svelte: 3.46.3
|
||||
svelte-check: 2.4.1_svelte@3.46.3
|
||||
svelte-i18n: 3.3.13_svelte@3.46.3
|
||||
vitest: 0.3.5
|
||||
devDependencies:
|
||||
'@types/three': 0.138.0
|
||||
|
||||
packages/app:
|
||||
specifiers:
|
||||
@ -248,6 +255,10 @@ packages:
|
||||
resolution: {integrity: sha512-3BKgtrXdr+E/lsz79Hbkb8X3kjlbsgw1m0x/ewhff+cqN059GpFWHtYuLJd2ToDTeWZa3OE2V4KIo//PnOrKlQ==}
|
||||
dev: true
|
||||
|
||||
/@types/three/0.138.0:
|
||||
resolution: {integrity: sha512-D8AoV7h2kbCfrv/DcebHOFh1WDwyus3HdooBkAwcBikXArdqnsQ38PQ85JCunnvun160oA9jz53GszF3zch3tg==}
|
||||
dev: true
|
||||
|
||||
/abab/2.0.5:
|
||||
resolution: {integrity: sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==}
|
||||
dev: false
|
||||
@ -412,6 +423,21 @@ packages:
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/babylonjs-gltf2interface/4.2.1:
|
||||
resolution: {integrity: sha512-ZBfKgIoztO1x1nyf9aPQJ+WXmB6Kw0VlyxvcKchIixbICqeeExiN8nmjvypwXC4hl+5ZDMnUKQNrIhh7uzulnA==}
|
||||
dev: false
|
||||
|
||||
/babylonjs-loaders/4.2.1:
|
||||
resolution: {integrity: sha512-WLpbadXDyxbBQogU0SOrpwgAWN/DJ1xn5kCRD31NVoCbBIpvkdDIvzpRvze2esxrlv/KM8wbDu62ShJd6rQnVQ==}
|
||||
dependencies:
|
||||
babylonjs: 4.2.1
|
||||
babylonjs-gltf2interface: 4.2.1
|
||||
dev: false
|
||||
|
||||
/babylonjs/4.2.1:
|
||||
resolution: {integrity: sha512-FQdJ2VTENUpUJQ30ddihwTjV6K94kglET0P7jV8OQzjA4eez3sotmG22Fn9+8yb069SA26KnrAGOI2sKMQ7BCw==}
|
||||
dev: false
|
||||
|
||||
/balanced-match/1.0.2:
|
||||
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
|
||||
dev: false
|
||||
|
Loading…
Reference in New Issue
Block a user