skin-tokens

This commit is contained in:
Aggtaa
2026-09-30 07:38:21 +03:00
parent 8db94e5c31
commit 9cad7452bb
16 changed files with 1314 additions and 78 deletions
+74 -7
View File
@@ -31,10 +31,10 @@ export interface Text2ImgInput {
*/
export type BatchState = 'draft' | 'pending' | 'done' | 'error';
/** Картинка батча (Images): id и проект, если из неё создан проект. */
/** Картинка батча (Images): id и проекты, созданные из неё (из одной картинки — сколько угодно). */
export interface BatchImage extends FileRef {
id: number;
projectId: number | null;
projectIds: number[];
}
/** Проект — работа над одной картинкой из батча. */
@@ -72,12 +72,57 @@ export interface Project {
textureJobId: string | null;
textureError?: string;
textureLive?: LiveStatus;
/** риг SkinTokens: скелет и веса скиннинга на модели (текстурированной, если есть) */
rig: RigArtifacts | null;
/** идёт риггинг: 'skintokens:<мс начала>' (в ComfyUI не попадает — skin-tokens.cpp в WSL) */
rigJobId: string | null;
rigError?: string;
/** анимации, перенесённые на сгенерированный SkinTokens скелет рига (retarget-generated), по порядку создания */
anims: AnimArtifacts[];
animError?: string;
}
/** Чем сгенерирована 3D-модель. */
export type ModelGenerator = 'hunyuan' | 'trellis';
/** Анимация из app/data/motions на скелете рига: модель со скелетом рига и движением. */
export interface AnimArtifacts {
glb: FileRef;
/** файлы движений через запятую (пути в app/data/motions) — подпись */
motion: string;
/** файлы движений по порядку анимаций в GLB (у старых записей нет — тогда одна: motion) */
motions?: string[];
/** длительность ретаргета, с */
seconds: number;
updated: number;
}
export const GENERATOR_NAMES: Record<ModelGenerator, string> = { hunyuan: 'Hunyuan3D-2 mini', trellis: 'TRELLIS.2' };
/** Риг: rig — скелет сгенерирован SkinTokens, skin — только веса под скелет пользователя. */
export interface RigArtifacts {
mode: 'rig' | 'skin';
glb: FileRef;
/** скелет пользователя (GLB), если был */
skeleton: FileRef | null;
/** скелет из app/data/motions (относительный путь), если был — его анимация есть в GLB */
motion?: string;
/** на какой модели: текстурированной или без текстур */
basedOn: 'textured' | 'model';
faces: number | null;
joints: number;
/** время работы SkinTokens, с */
seconds: number;
updated: number;
}
/** Начало идущего риггинга (мс) из rigJobId. */
export const rigStarted = (jobId: string | null) => (jobId?.startsWith('skintokens:') ? Number(jobId.slice(11)) : null);
/** Чем сгенерирована 3D-модель. */
export type ModelGenerator = 'hunyuan' | 'hy3dwrapper' | 'trellis';
export const GENERATOR_NAMES: Record<ModelGenerator, string> = {
hunyuan: 'Hunyuan3D-2 mini', hy3dwrapper: 'Hunyuan3D-2 mini (Hy3D wrapper)', trellis: 'TRELLIS.2',
};
/** Модель без текстур — её можно текстурировать Hunyuan3D-2 Paint (TRELLIS.2 даёт текстуры сразу). */
export const isUntextured = (g: ModelGenerator) => g !== 'trellis';
/** Модель без текстур. */
export interface ModelArtifacts {
@@ -123,6 +168,9 @@ export interface ProjectModelRequest {
octree: number | string;
/** целевое число треугольников после упрощения */
faces: number | string;
/** Hy3D wrapper: перестроить сетку Instant Meshes (Hy3DIMRemesh) до remeshVertices вершин */
remesh: boolean;
remeshVertices: number | string;
/** TRELLIS.2: размер текстуры, px */
textureSize: number | string;
/** TRELLIS.2: металличность и шероховатость (карты metallic, roughness) в модели */
@@ -175,7 +223,7 @@ export type ImageBatch = TextBatch | UploadBatch;
/** В батче есть картинка, из которой создан проект. */
export function hasProject(b: ImageBatch): boolean {
return b.images.some(i => i.projectId != null);
return b.images.some(i => i.projectIds.length > 0);
}
export function isLocked(b: ImageBatch): boolean {
@@ -230,6 +278,8 @@ export interface ModelParams {
/** Hunyuan3D-2 mini */
steps?: number;
octree?: number;
/** Hy3D wrapper: Hy3DIMRemesh, 0 — выключен */
remeshVertices?: number;
/** TRELLIS.2 */
textureSize?: number;
pbr?: boolean;
@@ -292,6 +342,9 @@ export interface ModelSettings {
steps: string;
octree: string;
faces: string;
/** Hy3D wrapper */
remesh: boolean;
remeshVertices: string;
/** TRELLIS.2 */
trellisFaces: string;
textureSize: string;
@@ -304,8 +357,22 @@ export interface TextureSettings {
delight: boolean;
}
export interface RetargetSettings {
/** выбранные файлы движений в app/data/motions */
motions: string[];
}
export interface RigSettings {
/** скелет: '' — сгенерировать, 'file' — свой GLB, иначе путь GLB в app/data/motions */
skeleton: string;
/** как совместить скелет пользователя с мешем: none | global | articulated */
fit: string;
postprocess: boolean;
}
export type SettingsByPage = {
text2img: Text2ImgSettings; cleanup: CleanupSettings; model: ModelSettings; texture: TextureSettings;
text2img: Text2ImgSettings; cleanup: CleanupSettings; model: ModelSettings; texture: TextureSettings; rig: RigSettings;
retarget: RetargetSettings;
};
export type SettingsPage = keyof SettingsByPage;