mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-03-09 07:00:06 +00:00
[3d] support output normal and lineart at once (#3122)
This commit is contained in:
@@ -124,21 +124,30 @@ app.registerExtension({
|
||||
sceneWidget.serializeValue = async () => {
|
||||
node.properties['Camera Info'] = load3d.getCameraState()
|
||||
|
||||
const { scene: imageData, mask: maskData } = await load3d.captureScene(
|
||||
const {
|
||||
scene: imageData,
|
||||
mask: maskData,
|
||||
normal: normalData,
|
||||
lineart: lineartData
|
||||
} = await load3d.captureScene(
|
||||
width.value as number,
|
||||
height.value as number
|
||||
)
|
||||
|
||||
const [data, dataMask] = await Promise.all([
|
||||
const [data, dataMask, dataNormal, dataLineart] = await Promise.all([
|
||||
Load3dUtils.uploadTempImage(imageData, 'scene'),
|
||||
Load3dUtils.uploadTempImage(maskData, 'scene_mask')
|
||||
Load3dUtils.uploadTempImage(maskData, 'scene_mask'),
|
||||
Load3dUtils.uploadTempImage(normalData, 'scene_normal'),
|
||||
Load3dUtils.uploadTempImage(lineartData, 'scene_lineart')
|
||||
])
|
||||
|
||||
load3d.handleResize()
|
||||
|
||||
return {
|
||||
image: `threed/${data.name} [temp]`,
|
||||
mask: `threed/${dataMask.name} [temp]`
|
||||
mask: `threed/${dataMask.name} [temp]`,
|
||||
normal: `threed/${dataNormal.name} [temp]`,
|
||||
lineart: `threed/${dataLineart.name} [temp]`
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -252,21 +261,27 @@ app.registerExtension({
|
||||
|
||||
load3d.toggleAnimation(false)
|
||||
|
||||
const { scene: imageData, mask: maskData } = await load3d.captureScene(
|
||||
const {
|
||||
scene: imageData,
|
||||
mask: maskData,
|
||||
normal: normalData
|
||||
} = await load3d.captureScene(
|
||||
width.value as number,
|
||||
height.value as number
|
||||
)
|
||||
|
||||
const [data, dataMask] = await Promise.all([
|
||||
const [data, dataMask, dataNormal] = await Promise.all([
|
||||
Load3dUtils.uploadTempImage(imageData, 'scene'),
|
||||
Load3dUtils.uploadTempImage(maskData, 'scene_mask')
|
||||
Load3dUtils.uploadTempImage(maskData, 'scene_mask'),
|
||||
Load3dUtils.uploadTempImage(normalData, 'scene_normal')
|
||||
])
|
||||
|
||||
load3d.handleResize()
|
||||
|
||||
return {
|
||||
image: `threed/${data.name} [temp]`,
|
||||
mask: `threed/${dataMask.name} [temp]`
|
||||
mask: `threed/${dataMask.name} [temp]`,
|
||||
normal: `threed/${dataNormal.name} [temp]`
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,9 @@ class Load3d {
|
||||
protected loaderManager: LoaderManager
|
||||
protected modelManager: ModelManager
|
||||
|
||||
STATUS_MOUSE_ON_NODE: boolean
|
||||
STATUS_MOUSE_ON_SCENE: boolean
|
||||
|
||||
constructor(
|
||||
container: Element | HTMLElement,
|
||||
options: Load3DOptions = {
|
||||
@@ -124,6 +127,9 @@ class Load3d {
|
||||
this.previewManager.init()
|
||||
}
|
||||
|
||||
this.STATUS_MOUSE_ON_NODE = false
|
||||
this.STATUS_MOUSE_ON_SCENE = false
|
||||
|
||||
this.handleResize()
|
||||
this.startAnimation()
|
||||
}
|
||||
@@ -167,6 +173,18 @@ class Load3d {
|
||||
animate()
|
||||
}
|
||||
|
||||
updateStatusMouseOnNode(onNode: boolean): void {
|
||||
this.STATUS_MOUSE_ON_NODE = onNode
|
||||
}
|
||||
|
||||
updateStatusMouseOnScene(onScene: boolean): void {
|
||||
this.STATUS_MOUSE_ON_SCENE = onScene
|
||||
}
|
||||
|
||||
isActive(): boolean {
|
||||
return this.STATUS_MOUSE_ON_NODE || this.STATUS_MOUSE_ON_SCENE
|
||||
}
|
||||
|
||||
setBackgroundColor(color: string): void {
|
||||
this.sceneManager.setBackgroundColor(color)
|
||||
this.renderer.render(
|
||||
|
||||
@@ -196,7 +196,7 @@ export class SceneManager implements SceneManagerInterface {
|
||||
captureScene(
|
||||
width: number,
|
||||
height: number
|
||||
): Promise<{ scene: string; mask: string }> {
|
||||
): Promise<{ scene: string; mask: string; normal: string; lineart: string }> {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
const originalWidth = this.renderer.domElement.width
|
||||
@@ -207,6 +207,7 @@ export class SceneManager implements SceneManagerInterface {
|
||||
const originalClearAlpha = this.renderer.getClearAlpha()
|
||||
const originalToneMapping = this.renderer.toneMapping
|
||||
const originalExposure = this.renderer.toneMappingExposure
|
||||
const originalOutputColorSpace = this.renderer.outputColorSpace
|
||||
|
||||
this.renderer.setSize(width, height)
|
||||
|
||||
@@ -240,6 +241,11 @@ export class SceneManager implements SceneManagerInterface {
|
||||
)
|
||||
}
|
||||
|
||||
const originalMaterials = new Map<
|
||||
THREE.Mesh,
|
||||
THREE.Material | THREE.Material[]
|
||||
>()
|
||||
|
||||
this.renderer.clear()
|
||||
|
||||
if (this.backgroundMesh && this.backgroundTexture) {
|
||||
@@ -262,12 +268,103 @@ export class SceneManager implements SceneManagerInterface {
|
||||
this.renderer.render(this.scene, this.getActiveCamera())
|
||||
const maskData = this.renderer.domElement.toDataURL('image/png')
|
||||
|
||||
this.scene.traverse((child) => {
|
||||
if (child instanceof THREE.Mesh) {
|
||||
originalMaterials.set(child, child.material)
|
||||
|
||||
child.material = new THREE.MeshNormalMaterial({
|
||||
flatShading: false,
|
||||
side: THREE.DoubleSide,
|
||||
normalScale: new THREE.Vector2(1, 1)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
const gridVisible = this.gridHelper.visible
|
||||
this.gridHelper.visible = false
|
||||
|
||||
this.renderer.setClearColor(0x000000, 1)
|
||||
this.renderer.clear()
|
||||
this.renderer.render(this.scene, this.getActiveCamera())
|
||||
const normalData = this.renderer.domElement.toDataURL('image/png')
|
||||
|
||||
this.scene.traverse((child) => {
|
||||
if (child instanceof THREE.Mesh) {
|
||||
const originalMaterial = originalMaterials.get(child)
|
||||
if (originalMaterial) {
|
||||
child.material = originalMaterial
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
let lineartModel: THREE.Group | null = null
|
||||
|
||||
const originalSceneVisible: Map<THREE.Object3D, boolean> = new Map()
|
||||
|
||||
this.scene.traverse((child) => {
|
||||
if (child instanceof THREE.Group && child.name === 'lineartModel') {
|
||||
lineartModel = child as THREE.Group
|
||||
}
|
||||
|
||||
if (
|
||||
child instanceof THREE.Mesh &&
|
||||
!(child.parent?.name === 'lineartModel')
|
||||
) {
|
||||
originalSceneVisible.set(child, child.visible)
|
||||
|
||||
child.visible = false
|
||||
}
|
||||
})
|
||||
|
||||
this.renderer.setClearColor(0xffffff, 1)
|
||||
this.renderer.clear()
|
||||
|
||||
if (lineartModel !== null) {
|
||||
lineartModel = lineartModel as THREE.Group
|
||||
|
||||
const originalLineartVisibleMap: Map<THREE.Object3D, boolean> =
|
||||
new Map()
|
||||
|
||||
lineartModel.traverse((child: THREE.Object3D) => {
|
||||
if (child instanceof THREE.Mesh) {
|
||||
originalLineartVisibleMap.set(child, child.visible)
|
||||
|
||||
child.visible = true
|
||||
}
|
||||
})
|
||||
|
||||
const originalLineartVisible = lineartModel.visible
|
||||
lineartModel.visible = true
|
||||
|
||||
this.renderer.render(this.scene, this.getActiveCamera())
|
||||
|
||||
lineartModel.visible = originalLineartVisible
|
||||
|
||||
originalLineartVisibleMap.forEach((visible, object) => {
|
||||
object.visible = visible
|
||||
})
|
||||
}
|
||||
|
||||
const lineartData = this.renderer.domElement.toDataURL('image/png')
|
||||
|
||||
originalSceneVisible.forEach((visible, object) => {
|
||||
object.visible = visible
|
||||
})
|
||||
|
||||
this.gridHelper.visible = gridVisible
|
||||
|
||||
this.renderer.setClearColor(originalClearColor, originalClearAlpha)
|
||||
this.renderer.setSize(originalWidth, originalHeight)
|
||||
this.renderer.outputColorSpace = originalOutputColorSpace
|
||||
|
||||
this.handleResize(width, height)
|
||||
this.handleResize(originalWidth, originalHeight)
|
||||
|
||||
resolve({ scene: sceneData, mask: maskData })
|
||||
resolve({
|
||||
scene: sceneData,
|
||||
mask: maskData,
|
||||
normal: normalData,
|
||||
lineart: lineartData
|
||||
})
|
||||
} catch (error) {
|
||||
reject(error)
|
||||
}
|
||||
|
||||
@@ -40,6 +40,8 @@ export interface Load3DOptions {
|
||||
export interface CaptureResult {
|
||||
scene: string
|
||||
mask: string
|
||||
normal: string
|
||||
lineart: string
|
||||
}
|
||||
|
||||
export interface BaseManager {
|
||||
|
||||
Reference in New Issue
Block a user