Skip to content

Make models with Nfty.Model

Nfty.Model turns finished pixel art into a voxel mesh and writes glTF, with no glTF library. It references Nfty.Core; nothing references it back. The code below comes from samples/Nfty.Embedding.Sample and rises the first asset cooked on the previous page.

// Rise the first cooked asset into a 3D model, the way a Set written with --models does.
GeneratedAsset first = set.Assets[0];
var options = new RiseOptions { Format = ModelFormat.Glb, Pivot = Pivot.BottomCenter, VoxelSize = 1f };

using StackRise? rise = StackDepth.ForAsset(book.Recipe(first.RecipeId), first, "asset #1");
Mesh? mesh = Riser.TryBuild(first.Image, rise?.Depth, options, "asset #1", rise?.Faces);

if (mesh is null)
    Console.WriteLine("Nothing fully opaque: no model.");   // not an error; a batch skips and names it
else
    foreach (ModelFile file in ModelWriter.Write(mesh, first.Image, options, "0001", rise?.Faces))
    {
        File.WriteAllBytes(Path.Combine(outDir, file.FileName), file.Bytes);
        Console.WriteLine($"model {file.FileName} {file.Bytes.Length:N0} bytes");
    }
  • Riser.TryBuild makes the mesh from finished art plus an optional DepthMap. It returns null when nothing is fully opaque, and throws PartialAlphaException naming the picture when a pixel is partly transparent: a voxel is there or it is not.
  • StackDepth.ForAsset is the rule for a layered asset: per pixel, the front is the largest front over the layers and the back the largest back. Pass the Faces it returns so each face and side takes the right layer's color. For one flat picture, leave both null.
  • ModelWriter.Write returns ModelFiles (name and bytes) and writes nothing; you choose where they go. glTF with a .bin returns two files. RiseOptions sets format, pivot and voxel size.
  • To model a whole Set as it is written, give SetWriter.Write a Nfty.Model.SetModeler.
  • GltfReader reads back nfty's own glTF subset only and reports anything else as UnsupportedModelException.

For what front, back and paper mean, see Depth: paper, front and back. Every type is in the Nfty.Model API pages.