// 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) }