[3d] improve mtl support logic (#3965)

This commit is contained in:
Terry Jia
2025-05-23 21:22:13 -04:00
committed by GitHub
parent 9d48638464
commit 8209765eec
3 changed files with 94 additions and 41 deletions

View File

@@ -266,7 +266,7 @@ useExtensionService().registerExtension({
LOAD_3D_ANIMATION(node) {
const fileInput = document.createElement('input')
fileInput.type = 'file'
fileInput.accept = '.fbx,glb,gltf'
fileInput.accept = '.gltf,.glb,.fbx'
fileInput.style.display = 'none'
fileInput.onchange = async () => {
if (fileInput.files?.length) {
@@ -452,31 +452,43 @@ useExtensionService().registerExtension({
const onExecuted = node.onExecuted
node.onExecuted = function (message: any) {
onExecuted?.apply(this, arguments as any)
useLoad3dService().waitForLoad3d(node, (load3d) => {
const config = new Load3DConfiguration(load3d)
let filePath = message.result[0]
const modelWidget = node.widgets?.find((w) => w.name === 'model_file')
if (!filePath) {
const msg = t('toastMessages.unableToGetModelFilePath')
console.error(msg)
useToastStore().addAlert(msg)
}
if (modelWidget) {
const lastTimeModelFile = node.properties['Last Time Model File']
let cameraState = message.result[1]
if (lastTimeModelFile) {
modelWidget.value = lastTimeModelFile
useLoad3dService().waitForLoad3d(node, (load3d) => {
const modelWidget = node.widgets?.find((w) => w.name === 'model_file')
if (modelWidget) {
modelWidget.value = filePath.replaceAll('\\', '/')
const config = new Load3DConfiguration(load3d)
const cameraState = node.properties['Camera Info']
config.configure('output', modelWidget, cameraState)
}
})
}
node.onExecuted = function (message: any) {
onExecuted?.apply(this, arguments as any)
let filePath = message.result[0]
if (!filePath) {
const msg = t('toastMessages.unableToGetModelFilePath')
console.error(msg)
useToastStore().addAlert(msg)
}
let cameraState = message.result[1]
modelWidget.value = filePath.replaceAll('\\', '/')
node.properties['Last Time Model File'] = modelWidget.value
config.configure('output', modelWidget, cameraState)
}
}
})
}
})
@@ -526,29 +538,42 @@ useExtensionService().registerExtension({
const onExecuted = node.onExecuted
node.onExecuted = function (message: any) {
onExecuted?.apply(this, arguments as any)
useLoad3dService().waitForLoad3d(node, (load3d) => {
const config = new Load3DConfiguration(load3d)
let filePath = message.result[0]
const modelWidget = node.widgets?.find((w) => w.name === 'model_file')
if (!filePath) {
const msg = t('toastMessages.unableToGetModelFilePath')
console.error(msg)
useToastStore().addAlert(msg)
}
if (modelWidget) {
const lastTimeModelFile = node.properties['Last Time Model File']
let cameraState = message.result[1]
if (lastTimeModelFile) {
modelWidget.value = lastTimeModelFile
useLoad3dService().waitForLoad3d(node, (load3d) => {
const modelWidget = node.widgets?.find((w) => w.name === 'model_file')
if (modelWidget) {
modelWidget.value = filePath.replaceAll('\\', '/')
const config = new Load3DConfiguration(load3d)
const cameraState = node.properties['Camera Info']
config.configure('output', modelWidget, cameraState)
}
})
}
node.onExecuted = function (message: any) {
onExecuted?.apply(this, arguments as any)
let filePath = message.result[0]
if (!filePath) {
const msg = t('toastMessages.unableToGetModelFilePath')
console.error(msg)
useToastStore().addAlert(msg)
}
let cameraState = message.result[1]
modelWidget.value = filePath.replaceAll('\\', '/')
node.properties['Last Time Model File'] = modelWidget.value
config.configure('output', modelWidget, cameraState)
}
}
})
}
})

View File

@@ -132,6 +132,14 @@ export class LoaderManager implements LoaderManagerInterface {
if (this.modelManager.materialMode === 'original') {
const mtlUrl = url.replace(/(filename=.*?)\.obj/, '$1.mtl')
const subfolderMatch = url.match(/[?&]subfolder=([^&]*)/)
const subfolder = subfolderMatch
? decodeURIComponent(subfolderMatch[1])
: '3d'
this.mtlLoader.setSubfolder(subfolder)
try {
const materials = await this.mtlLoader.loadAsync(mtlUrl)
materials.preload()

View File

@@ -38,6 +38,10 @@ class OverrideMTLLoader extends Loader {
this.loadRootFolder = loadRootFolder
}
setSubfolder(subfolder) {
this.subfolder = subfolder
}
/**
* Starts loading from the given URL and passes the loaded MTL asset
* to the `onLoad()` callback.
@@ -135,7 +139,8 @@ class OverrideMTLLoader extends Loader {
const materialCreator = new OverrideMaterialCreator(
this.resourcePath || path,
this.materialOptions,
this.loadRootFolder
this.loadRootFolder,
this.subfolder
)
materialCreator.setCrossOrigin(this.crossOrigin)
materialCreator.setManager(this.manager)
@@ -155,7 +160,7 @@ class OverrideMTLLoader extends Loader {
*/
class OverrideMaterialCreator {
constructor(baseUrl = '', options = {}, loadRootFolder) {
constructor(baseUrl = '', options = {}, loadRootFolder, subfolder) {
this.baseUrl = baseUrl
this.options = options
this.materialsInfo = {}
@@ -164,6 +169,7 @@ class OverrideMaterialCreator {
this.nameLookup = {}
this.loadRootFolder = loadRootFolder
this.subfolder = subfolder
this.crossOrigin = 'anonymous'
@@ -283,16 +289,25 @@ class OverrideMaterialCreator {
/**
* Override for ComfyUI api url
*/
function resolveURL(baseUrl, url, loadRootFolder) {
function resolveURL(baseUrl, url, loadRootFolder, subfolder) {
if (typeof url !== 'string' || url === '') return ''
if (baseUrl.endsWith('/')) {
baseUrl = baseUrl.slice(0, -1)
}
if (!baseUrl.endsWith('api')) {
baseUrl = '/api'
}
baseUrl =
baseUrl +
'/view?filename=' +
url +
'&type=' +
loadRootFolder +
'&subfolder=3d'
'&subfolder=' +
subfolder
return baseUrl
}
@@ -302,7 +317,12 @@ class OverrideMaterialCreator {
const texParams = scope.getTextureParams(value, params)
const map = scope.loadTexture(
resolveURL(scope.baseUrl, texParams.url, scope.loadRootFolder)
resolveURL(
scope.baseUrl,
texParams.url,
scope.loadRootFolder,
scope.subfolder
)
)
map.repeat.copy(texParams.scale)