garment proxy
A garment of your own, bound to a body, with no engine. A garment file
(from the tailor or Blender, see garment-file) is a mesh
and a note of the body it was made on. garmentProxy binds it to that body
and hands back the same HumanProxy MakeHuman's own clothes are (a binding,
triangles, uvs, a name, a slot, category clothes), so it goes through the
same path: fitProxy onto any shape of the body, coverSkin, weights,
morphs. A character in the builder wears it this way, and an exporter
writes it this way.
import { readGarment } from 'tosijs-3d/garment-file'
import { garmentProxy, garmentMadeOn } from 'tosijs-3d/garment-proxy'
import { morphHuman, macroWeights } from 'tosijs-3d/human-morph'
const content = readGarment(bytes)
// MakeHuman's body in the shape it was made on (its sliders are in the file).
const on = morphHuman(pack, macroWeights(garmentMadeOn(content.meta), (n) => pack.has(n)))
const proxy = garmentProxy(content, { positions: on, triangles: pack.triangles })
proxy.material.baseColorTexture // { bytes, mimeType }, or null
proxy.material.gltf // the look as glTF factors, where it has a plain reading
The material is DATA, not URLs: the file's pictures as bytes, its factors,
twoSided (a skirt or a draped garment is seen from inside), and look, the
material recipe it was worn with when saved. gltf reads that look as glTF
metallic-roughness factors (and sheen, for cloth) where it has a plain
reading: a flat colour on a garment with no picture of its own, a flat
roughness and metalness. A look that recolours the garment's own picture has
no factor reading; recolourCloth (cloth-bake) bakes it into the picture.
A garment made on a mesh's body (its meta.source names the mesh) binds to
that body the same way: pass the rigged body's positions and indices.
MAKEHUMAN'S OWN CLOTHES go out the same way. They are bound to the pack's
every vertex, helpers included, and the skin a MakeHuman body draws is a part
of them (or a lighter body proxy over them), so onSkin binds the piece as
worn to that skin instead, carrying the skin it deletes across; and
packGarmentMaterial is a pack proxy's material as data, its pictures as
bytes the caller fetched.
const drawn = drawnPositions(proxy, fitProxy(proxy, body.full))
const garment = {
...onSkin(proxy, drawn, { positions: body.positions, triangles: body.indices, vertices: body.skin.vertices }),
material: packGarmentMaterial(proxy, { diffuse }, look),
}
riggedBodyGlb(body, { garments: [garment] })
Pure: no DOM, no Babylon.