Skip to content

Commit b531d34

Browse files
authored
[3d] performance improve (#3961)
1 parent 55ad207 commit b531d34

File tree

5 files changed

+183
-86
lines changed

5 files changed

+183
-86
lines changed

src/components/load3d/Load3DScene.vue

Lines changed: 71 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<script setup lang="ts">
88
import { LGraphNode } from '@comfyorg/litegraph'
9-
import { onMounted, onUnmounted, ref, toRaw, watch, watchEffect } from 'vue'
9+
import { onMounted, onUnmounted, ref, toRaw, watch } from 'vue'
1010
1111
import LoadingOverlay from '@/components/load3d/LoadingOverlay.vue'
1212
import Load3d from '@/extensions/core/load3d/Load3d'
@@ -76,18 +76,71 @@ const eventConfig = {
7676
emit('recordingStatusChange', value)
7777
} as const
7878
79-
watchEffect(() => {
80-
if (load3d.value) {
81-
const rawLoad3d = toRaw(load3d.value) as Load3d
79+
watch(
80+
() => props.showPreview,
81+
(newValue) => {
82+
if (load3d.value) {
83+
const rawLoad3d = toRaw(load3d.value) as Load3d
8284
83-
rawLoad3d.setBackgroundColor(props.backgroundColor)
84-
rawLoad3d.toggleGrid(props.showGrid)
85-
rawLoad3d.setLightIntensity(props.lightIntensity)
86-
rawLoad3d.setFOV(props.fov)
87-
rawLoad3d.toggleCamera(props.cameraType)
88-
rawLoad3d.togglePreview(props.showPreview)
85+
rawLoad3d.togglePreview(newValue)
86+
}
8987
}
90-
})
88+
)
89+
90+
watch(
91+
() => props.cameraType,
92+
(newValue) => {
93+
if (load3d.value) {
94+
const rawLoad3d = toRaw(load3d.value) as Load3d
95+
96+
rawLoad3d.toggleCamera(newValue)
97+
}
98+
}
99+
)
100+
101+
watch(
102+
() => props.fov,
103+
(newValue) => {
104+
if (load3d.value) {
105+
const rawLoad3d = toRaw(load3d.value) as Load3d
106+
107+
rawLoad3d.setFOV(newValue)
108+
}
109+
}
110+
)
111+
112+
watch(
113+
() => props.lightIntensity,
114+
(newValue) => {
115+
if (load3d.value) {
116+
const rawLoad3d = toRaw(load3d.value) as Load3d
117+
118+
rawLoad3d.setLightIntensity(newValue)
119+
}
120+
}
121+
)
122+
123+
watch(
124+
() => props.showGrid,
125+
(newValue) => {
126+
if (load3d.value) {
127+
const rawLoad3d = toRaw(load3d.value) as Load3d
128+
129+
rawLoad3d.toggleGrid(newValue)
130+
}
131+
}
132+
)
133+
134+
watch(
135+
() => props.backgroundColor,
136+
(newValue) => {
137+
if (load3d.value) {
138+
const rawLoad3d = toRaw(load3d.value) as Load3d
139+
140+
rawLoad3d.setBackgroundColor(newValue)
141+
}
142+
}
143+
)
91144
92145
watch(
93146
() => props.backgroundImage,
@@ -164,12 +217,13 @@ const handleEvents = (action: 'add' | 'remove') => {
164217
}
165218
166219
onMounted(() => {
167-
load3d.value = useLoad3dService().registerLoad3d(
168-
node.value as LGraphNode,
169-
// @ts-expect-error fixme ts strict error
170-
container.value,
171-
props.inputSpec
172-
)
220+
if (container.value) {
221+
load3d.value = useLoad3dService().registerLoad3d(
222+
node.value as LGraphNode,
223+
container.value,
224+
props.inputSpec
225+
)
226+
}
173227
handleEvents('add')
174228
})
175229

src/extensions/core/load3d.ts

Lines changed: 65 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ useExtensionService().registerExtension({
112112
LOAD_3D(node) {
113113
const fileInput = document.createElement('input')
114114
fileInput.type = 'file'
115-
fileInput.accept = '.gltf,.glb,.obj,.mtl,.fbx,.stl'
115+
fileInput.accept = '.gltf,.glb,.obj,.fbx,.stl'
116116
fileInput.style.display = 'none'
117117

118118
fileInput.onchange = async () => {
@@ -195,9 +195,7 @@ useExtensionService().registerExtension({
195195

196196
await nextTick()
197197

198-
const load3d = useLoad3dService().getLoad3d(node)
199-
200-
if (load3d) {
198+
useLoad3dService().waitForLoad3d(node, (load3d) => {
201199
let cameraState = node.properties['Camera Info']
202200

203201
const config = new Load3DConfiguration(load3d)
@@ -256,7 +254,7 @@ useExtensionService().registerExtension({
256254
return returnVal
257255
}
258256
}
259-
}
257+
})
260258
}
261259
})
262260

@@ -346,67 +344,65 @@ useExtensionService().registerExtension({
346344

347345
await nextTick()
348346

349-
const sceneWidget = node.widgets?.find((w) => w.name === 'image')
347+
useLoad3dService().waitForLoad3d(node, (load3d) => {
348+
const sceneWidget = node.widgets?.find((w) => w.name === 'image')
349+
const modelWidget = node.widgets?.find((w) => w.name === 'model_file')
350+
let cameraState = node.properties['Camera Info']
351+
const width = node.widgets?.find((w) => w.name === 'width')
352+
const height = node.widgets?.find((w) => w.name === 'height')
350353

351-
const load3d = useLoad3dService().getLoad3d(node) as Load3dAnimation
354+
if (modelWidget && width && height && sceneWidget && load3d) {
355+
const config = new Load3DConfiguration(load3d)
352356

353-
const modelWidget = node.widgets?.find((w) => w.name === 'model_file')
357+
config.configure('input', modelWidget, cameraState, width, height)
354358

355-
let cameraState = node.properties['Camera Info']
359+
sceneWidget.serializeValue = async () => {
360+
node.properties['Camera Info'] = load3d.getCameraState()
356361

357-
const width = node.widgets?.find((w) => w.name === 'width')
358-
const height = node.widgets?.find((w) => w.name === 'height')
362+
const load3dAnimation = load3d as Load3dAnimation
363+
load3dAnimation.toggleAnimation(false)
359364

360-
if (modelWidget && width && height && sceneWidget && load3d) {
361-
const config = new Load3DConfiguration(load3d)
365+
if (load3dAnimation.isRecording()) {
366+
load3dAnimation.stopRecording()
367+
}
362368

363-
config.configure('input', modelWidget, cameraState, width, height)
369+
const {
370+
scene: imageData,
371+
mask: maskData,
372+
normal: normalData
373+
} = await load3dAnimation.captureScene(
374+
width.value as number,
375+
height.value as number
376+
)
364377

365-
sceneWidget.serializeValue = async () => {
366-
node.properties['Camera Info'] = load3d.getCameraState()
378+
const [data, dataMask, dataNormal] = await Promise.all([
379+
Load3dUtils.uploadTempImage(imageData, 'scene'),
380+
Load3dUtils.uploadTempImage(maskData, 'scene_mask'),
381+
Load3dUtils.uploadTempImage(normalData, 'scene_normal')
382+
])
367383

368-
load3d.toggleAnimation(false)
384+
load3dAnimation.handleResize()
369385

370-
if (load3d.isRecording()) {
371-
load3d.stopRecording()
372-
}
386+
const returnVal = {
387+
image: `threed/${data.name} [temp]`,
388+
mask: `threed/${dataMask.name} [temp]`,
389+
normal: `threed/${dataNormal.name} [temp]`,
390+
camera_info: node.properties['Camera Info'],
391+
recording: ''
392+
}
373393

374-
const {
375-
scene: imageData,
376-
mask: maskData,
377-
normal: normalData
378-
} = await load3d.captureScene(
379-
width.value as number,
380-
height.value as number
381-
)
382-
383-
const [data, dataMask, dataNormal] = await Promise.all([
384-
Load3dUtils.uploadTempImage(imageData, 'scene'),
385-
Load3dUtils.uploadTempImage(maskData, 'scene_mask'),
386-
Load3dUtils.uploadTempImage(normalData, 'scene_normal')
387-
])
388-
389-
load3d.handleResize()
390-
391-
const returnVal = {
392-
image: `threed/${data.name} [temp]`,
393-
mask: `threed/${dataMask.name} [temp]`,
394-
normal: `threed/${dataNormal.name} [temp]`,
395-
camera_info: node.properties['Camera Info'],
396-
recording: ''
397-
}
394+
const recordingData = load3dAnimation.getRecordingData()
395+
if (recordingData) {
396+
const [recording] = await Promise.all([
397+
Load3dUtils.uploadTempImage(recordingData, 'recording', 'mp4')
398+
])
399+
returnVal['recording'] = `threed/${recording.name} [temp]`
400+
}
398401

399-
const recordingData = load3d.getRecordingData()
400-
if (recordingData) {
401-
const [recording] = await Promise.all([
402-
Load3dUtils.uploadTempImage(recordingData, 'recording', 'mp4')
403-
])
404-
returnVal['recording'] = `threed/${recording.name} [temp]`
402+
return returnVal
405403
}
406-
407-
return returnVal
408404
}
409-
}
405+
})
410406
}
411407
})
412408

@@ -467,19 +463,19 @@ useExtensionService().registerExtension({
467463
useToastStore().addAlert(msg)
468464
}
469465

470-
const load3d = useLoad3dService().getLoad3d(node)
471-
472466
let cameraState = message.result[1]
473467

474-
const modelWidget = node.widgets?.find((w) => w.name === 'model_file')
468+
useLoad3dService().waitForLoad3d(node, (load3d) => {
469+
const modelWidget = node.widgets?.find((w) => w.name === 'model_file')
475470

476-
if (load3d && modelWidget) {
477-
modelWidget.value = filePath.replaceAll('\\', '/')
471+
if (modelWidget) {
472+
modelWidget.value = filePath.replaceAll('\\', '/')
478473

479-
const config = new Load3DConfiguration(load3d)
474+
const config = new Load3DConfiguration(load3d)
480475

481-
config.configure('output', modelWidget, cameraState)
482-
}
476+
config.configure('output', modelWidget, cameraState)
477+
}
478+
})
483479
}
484480
}
485481
})
@@ -543,16 +539,16 @@ useExtensionService().registerExtension({
543539

544540
let cameraState = message.result[1]
545541

546-
const load3d = useLoad3dService().getLoad3d(node)
547-
548-
const modelWidget = node.widgets?.find((w) => w.name === 'model_file')
549-
if (load3d && modelWidget) {
550-
modelWidget.value = filePath.replaceAll('\\', '/')
542+
useLoad3dService().waitForLoad3d(node, (load3d) => {
543+
const modelWidget = node.widgets?.find((w) => w.name === 'model_file')
544+
if (modelWidget) {
545+
modelWidget.value = filePath.replaceAll('\\', '/')
551546

552-
const config = new Load3DConfiguration(load3d)
547+
const config = new Load3DConfiguration(load3d)
553548

554-
config.configure('output', modelWidget, cameraState)
555-
}
549+
config.configure('output', modelWidget, cameraState)
550+
}
551+
})
556552
}
557553
}
558554
})

src/extensions/core/load3d/Load3d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,14 @@ class Load3d {
486486
}
487487

488488
public remove(): void {
489+
this.renderer.forceContextLoss()
490+
const canvas = this.renderer.domElement
491+
const event = new Event('webglcontextlost', {
492+
bubbles: true,
493+
cancelable: true
494+
})
495+
canvas.dispatchEvent(event)
496+
489497
if (this.animationFrameId !== null) {
490498
cancelAnimationFrame(this.animationFrameId)
491499
}

src/extensions/core/load3d/PreviewManager.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,14 @@ export class PreviewManager implements PreviewManagerInterface {
6262

6363
dispose(): void {
6464
if (this.previewRenderer) {
65+
this.previewRenderer.forceContextLoss()
66+
const canvas = this.previewRenderer.domElement
67+
const event = new Event('webglcontextlost', {
68+
bubbles: true,
69+
cancelable: true
70+
})
71+
canvas.dispatchEvent(event)
72+
6573
this.previewRenderer.dispose()
6674
}
6775

0 commit comments

Comments
 (0)