trellis.2. unified 3d workflows
This commit is contained in:
+50
-6
@@ -1,10 +1,14 @@
|
||||
// Фоновое отслеживание незавершённых задач: результаты из ComfyUI записываются в базу,
|
||||
// даже если ни одна страница не открыта.
|
||||
import type { FileRef, Job, LiveStatus } from '../shared/api.ts';
|
||||
import type {
|
||||
FileRef, Job, LiveStatus, ModelArtifacts, ModelGenerator, TextureArtifacts, TextureSource,
|
||||
} from '../shared/api.ts';
|
||||
import { comfyJson } from './comfy.ts';
|
||||
import { glbTriangles } from './glb.ts';
|
||||
import { TEXTURE_VIEWS } from './workflows.ts';
|
||||
import {
|
||||
batchByJob, deleteJob, finishBatch, finishJob, finishProjectClean, finishProjectModel, pendingJobs, projectByCleanJob,
|
||||
projectByModelJob, transaction,
|
||||
batchByJob, deleteJob, finishBatch, finishJob, finishProjectClean, finishProjectModel, finishProjectTexture, pendingJobs,
|
||||
projectByCleanJob, projectByModelJob, projectByTextureJob, transaction,
|
||||
} from './db.ts';
|
||||
|
||||
/** Сколько ждать задачу, которой нет ни в очереди, ни в истории ComfyUI (ComfyUI перезапускался). */
|
||||
@@ -40,6 +44,36 @@ function outputFiles(h: HistoryEntry) {
|
||||
return { images, models };
|
||||
}
|
||||
|
||||
type Files = { images?: FileRef[]; models?: FileRef[] };
|
||||
/** Файл по метке префикса (см. workflows.ts): <prefix><tag>_NNNNN_.png. */
|
||||
const tagged = (files: FileRef[] | undefined, tag: string) => files?.find(i => i.filename.includes(tag + '_')) ?? null;
|
||||
|
||||
/**
|
||||
* Модель без текстур: у Hunyuan3D-2 mini — единственный GLB, у TRELLIS.2 — <prefix>_mesh_…glb; плюс превью.
|
||||
*/
|
||||
function modelArtifacts(generator: ModelGenerator, r: Files): ModelArtifacts | null {
|
||||
const glb = generator === 'trellis' ? tagged(r.models, '_mesh') : r.models?.[0];
|
||||
if (!glb) return null;
|
||||
return { generator, glb, preview: tagged(r.images, '_preview'), faces: glbTriangles(glb), updated: Date.now() };
|
||||
}
|
||||
|
||||
/**
|
||||
* Текстурная группа: текстурированный GLB (не _mesh), base color, metallic, roughness, развёртка и виды —
|
||||
* рендеры _view<угол> у TRELLIS.2 или 6 нарисованных видов _mv у Paint.
|
||||
*/
|
||||
function textureArtifacts(source: TextureSource, r: Files): TextureArtifacts | null {
|
||||
const glb = r.models?.find(m => !m.filename.includes('_mesh_')) ?? null;
|
||||
if (!glb) return null;
|
||||
const images = r.images ?? [];
|
||||
const views = source === 'trellis'
|
||||
? TEXTURE_VIEWS.map(a => tagged(images, '_view' + a)).filter((i): i is FileRef => i != null)
|
||||
: images.filter(i => i.filename.includes('_mv_')).sort((x, y) => x.filename.localeCompare(y.filename));
|
||||
return {
|
||||
source, glb, faces: glbTriangles(glb), baseColor: tagged(images, '_basecolor'), metallic: tagged(images, '_metallic'),
|
||||
roughness: tagged(images, '_roughness'), uv: tagged(images, '_uv'), views, updated: Date.now(),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Завершение задачи. Картинки text2img прикрепляются к её батчу (Images.batchId);
|
||||
* результат очистки и модель проекта заменяют прежние в проекте, а сама задача удаляется — история не хранится.
|
||||
@@ -52,11 +86,21 @@ function finish(job: Job, state: 'done' | 'error', result: { error?: string; ima
|
||||
deleteJob(job.id);
|
||||
return;
|
||||
}
|
||||
// модель проекта: GLB и превью — в проект, задача удаляется (история не хранится)
|
||||
// модель проекта (у TRELLIS.2 — сразу с текстурами) — в проект, задача удаляется (история не хранится)
|
||||
const modelProject = job.type === 'model' ? job.params.projectId ?? projectByModelJob(job.id) : null;
|
||||
if (modelProject != null) {
|
||||
if (job.type === 'model' && modelProject != null) {
|
||||
const generator = job.params.generator ?? 'hunyuan';
|
||||
const done = state === 'done';
|
||||
finishProjectModel(modelProject, done ? result.models?.[0] ?? null : null, done ? result.images?.[0] ?? null : null, result.error);
|
||||
const model = done ? modelArtifacts(generator, result) : null;
|
||||
const texture = done && generator === 'trellis' ? textureArtifacts('trellis', result) : null;
|
||||
finishProjectModel(modelProject, model, texture, result.error ?? (done && !model ? 'нет GLB в результате' : undefined));
|
||||
deleteJob(job.id);
|
||||
return;
|
||||
}
|
||||
// текстура Hunyuan3D-2 Paint — в проект, задача удаляется
|
||||
const textureProject = job.type === 'texture' ? job.params.projectId ?? projectByTextureJob(job.id) : null;
|
||||
if (textureProject != null) {
|
||||
finishProjectTexture(textureProject, state === 'done' ? textureArtifacts('paint', result) : null, result.error);
|
||||
deleteJob(job.id);
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user