Load FBX characters directly: in-app conversion to GLB
The model button now accepts .fbx too: a new model:convert IPC runs Blender with scripts/fbx2modelglb.py (mesh + skin kept, animations dropped, embedded diffuse recovered even when the FBX references missing external textures) into userData/models3d, then the resulting GLB loads as usual. anim/model conversion share one convertFbx helper. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a5c0a8b297
commit
d329759961
6 files changed
+93
-19
No files matched your search
@@ -117,24 +117,27 @@ function blenderPath() {
|
||||
for (const c of cands) if (fs.existsSync(c)) return c;
|
||||
return null;
|
||||
}
|
||||
ipcMain.handle('anim:convert', async (_e, fbxPath) => {
|
||||
function convertFbx(fbxPath, scriptName, outSub) {
|
||||
const blender = blenderPath();
|
||||
if (!blender) return { ok: false, error: 'Blender non trovato: serve per convertire gli FBX (oppure carica un .glb)' };
|
||||
const outDir = path.join(app.getPath('userData'), 'anims');
|
||||
if (!blender) return Promise.resolve({ ok: false,
|
||||
error: 'Blender non trovato: serve per convertire gli FBX (oppure carica un .glb)' });
|
||||
const outDir = path.join(app.getPath('userData'), outSub);
|
||||
fs.mkdirSync(outDir, { recursive: true });
|
||||
const out = path.join(outDir, path.basename(fbxPath).replace(/\.fbx$/i, '') + '.glb');
|
||||
// packaged app: the .py must live outside the asar for Blender to read it
|
||||
const script = path.join(__dirname, 'scripts', 'fbx2animglb.py')
|
||||
const script = path.join(__dirname, 'scripts', scriptName)
|
||||
.replace('app.asar' + path.sep, 'app.asar.unpacked' + path.sep);
|
||||
return new Promise((resolve) => {
|
||||
execFile(blender, ['-b', '-P', script, '--', fbxPath, out],
|
||||
{ maxBuffer: 1 << 24, timeout: 180000 }, (err, _so, se) => {
|
||||
{ maxBuffer: 1 << 24, timeout: 300000 }, (err, _so, se) => {
|
||||
if (err || !fs.existsSync(out))
|
||||
resolve({ ok: false, error: 'conversione fallita: ' + String(se || (err && err.message) || '').slice(-300) });
|
||||
else resolve({ ok: true, path: out });
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
ipcMain.handle('anim:convert', (_e, p) => convertFbx(p, 'fbx2animglb.py', 'anims'));
|
||||
ipcMain.handle('model:convert', (_e, p) => convertFbx(p, 'fbx2modelglb.py', 'models3d'));
|
||||
|
||||
// Camera permission is requested lazily (only when an interactive preset is
|
||||
// activated), not at startup: no camera prompt for users who never use it.
|
||||
|
||||
Reference in new issue
Block a user