e98493bcfb
- imagegen.EditRequest.Mask -> sd-server img2img inpainting (white=repaint) - imagegen.Upscaler + BackgroundRemover, videogen.Interpolator, audio.DiarizationModel: new optional provider-minted surfaces - NEW meshgen leaf package (image->3D, glb/stl/obj) - provider/llamaswap: all five via the /upstream/<model>/<path> passthrough (upstreamPath helper, shared one-file multipart builder); binary success bodies validated (non-image, non-video, JSON-mesh rejection); diarization pins output=json (vtt/srt drop speaker labels) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
153 lines
5.0 KiB
Go
153 lines
5.0 KiB
Go
// Package meshgen is majordomo's canonical image-to-3D surface. Like
|
|
// imagegen/audio/videogen, it is a deliberately separate leaf contract from
|
|
// the llm package: mesh generation shares none of the chat machinery, so it
|
|
// gets its own small Provider/Model interfaces (ADR-0020, following the
|
|
// ADR-0016→0019 lineage: functional options, zero values = backend default,
|
|
// bytes-only I/O, Raw escape hatch).
|
|
//
|
|
// The first implementation is provider/llamaswap, which targets a
|
|
// Hunyuan3D-2.1-style api_server reached through the /upstream passthrough.
|
|
// The surface is image-to-3D only: text-to-3D is the composition
|
|
// imagegen.Generate → meshgen.Generate, owned by the caller.
|
|
package meshgen
|
|
|
|
import (
|
|
"context"
|
|
|
|
"gitea.stevedudenhoeffer.com/steve/majordomo/llm"
|
|
)
|
|
|
|
// Image is the conditioning input (bytes + MIME), aliased to llm.ImagePart so
|
|
// chat- or imagegen-sourced images feed mesh generation without conversion.
|
|
type Image = llm.ImagePart
|
|
|
|
// Mesh is one generated 3D asset: raw encoded bytes plus its format.
|
|
type Mesh struct {
|
|
// Data is the encoded mesh (binary GLB/STL/OBJ container).
|
|
Data []byte
|
|
|
|
// Format is the lowercase container name ("glb", "stl", "obj").
|
|
Format string
|
|
|
|
// MIME is the corresponding MIME type, e.g. "model/gltf-binary",
|
|
// "model/stl".
|
|
MIME string
|
|
}
|
|
|
|
// Request is an image-to-3D generation request. Zero values mean "backend
|
|
// default".
|
|
type Request struct {
|
|
// Image is the source image the mesh is reconstructed from. Required.
|
|
Image Image
|
|
|
|
// Format is the requested output container ("glb", "stl", "obj");
|
|
// "" = backend default (glb).
|
|
Format string
|
|
|
|
// Texture asks the backend to also synthesize surface textures. Much
|
|
// slower and much more VRAM-hungry than shape-only on the reference
|
|
// backend; leave false for print-pipeline geometry.
|
|
Texture bool
|
|
|
|
// RemoveBackground lets the backend cut the subject out first; nil =
|
|
// backend default (true on Hunyuan3D). Set explicitly to false when the
|
|
// input is already a clean cutout.
|
|
RemoveBackground *bool
|
|
|
|
// OctreeResolution is the shape-decoder grid resolution; 0 = backend
|
|
// default.
|
|
OctreeResolution int
|
|
|
|
// Steps is the number of diffusion steps; nil = backend default.
|
|
Steps *int
|
|
|
|
// GuidanceScale is the guidance strength; nil = backend default.
|
|
GuidanceScale *float64
|
|
|
|
// Seed fixes the RNG seed for reproducible output; nil = backend default.
|
|
Seed *int64
|
|
|
|
// FaceCount caps the output mesh's face count; 0 = backend default.
|
|
FaceCount int
|
|
}
|
|
|
|
// Result is the canonical mesh-generation result.
|
|
type Result struct {
|
|
// Mesh is the generated asset.
|
|
Mesh Mesh
|
|
|
|
// Raw is the provider-native response object. May be nil.
|
|
Raw any
|
|
}
|
|
|
|
// Option mutates a Request before it is sent. Options passed to Generate are
|
|
// applied to a copy of the request, so a Request value can be reused.
|
|
type Option func(*Request)
|
|
|
|
// WithFormat sets the output container ("glb", "stl", "obj").
|
|
func WithFormat(f string) Option { return func(r *Request) { r.Format = f } }
|
|
|
|
// WithTexture enables texture synthesis.
|
|
func WithTexture() Option { return func(r *Request) { r.Texture = true } }
|
|
|
|
// WithRemoveBackground sets the backend's background-removal preprocessing.
|
|
func WithRemoveBackground(v bool) Option {
|
|
return func(r *Request) { r.RemoveBackground = &v }
|
|
}
|
|
|
|
// WithOctreeResolution sets the shape-decoder grid resolution.
|
|
func WithOctreeResolution(n int) Option { return func(r *Request) { r.OctreeResolution = n } }
|
|
|
|
// WithSteps overrides the number of diffusion steps.
|
|
func WithSteps(n int) Option { return func(r *Request) { r.Steps = &n } }
|
|
|
|
// WithGuidanceScale overrides the guidance strength.
|
|
func WithGuidanceScale(s float64) Option { return func(r *Request) { r.GuidanceScale = &s } }
|
|
|
|
// WithSeed fixes the RNG seed.
|
|
func WithSeed(seed int64) Option { return func(r *Request) { r.Seed = &seed } }
|
|
|
|
// WithFaceCount caps the output mesh's face count.
|
|
func WithFaceCount(n int) Option { return func(r *Request) { r.FaceCount = n } }
|
|
|
|
// Apply returns a copy of the request with all options applied. Providers
|
|
// call this once at the top of Generate.
|
|
func (r Request) Apply(opts ...Option) Request {
|
|
for _, opt := range opts {
|
|
opt(&r)
|
|
}
|
|
return r
|
|
}
|
|
|
|
// Model generates 3D meshes from images.
|
|
type Model interface {
|
|
// Generate reconstructs a mesh from the request's image.
|
|
Generate(ctx context.Context, req Request, opts ...Option) (*Result, error)
|
|
}
|
|
|
|
// ModelOption configures a Model at construction time. Reserved for future
|
|
// per-model settings.
|
|
type ModelOption func(*ModelConfig)
|
|
|
|
// ModelConfig carries per-model construction settings.
|
|
type ModelConfig struct{}
|
|
|
|
// ApplyModelOptions folds options into a config.
|
|
func ApplyModelOptions(opts []ModelOption) ModelConfig {
|
|
var cfg ModelConfig
|
|
for _, opt := range opts {
|
|
opt(&cfg)
|
|
}
|
|
return cfg
|
|
}
|
|
|
|
// Provider mints mesh models bound to one backend.
|
|
type Provider interface {
|
|
// Name is the registry identifier for the provider.
|
|
Name() string
|
|
|
|
// MeshModel returns a Model bound to the given id (passed through to the
|
|
// backend verbatim; no catalog validation).
|
|
MeshModel(id string, opts ...ModelOption) (Model, error)
|
|
}
|