GroomLab

Developer overview

Build your own bridges, tools and exporters on GroomLab's open API.

GroomLab's core is closed source, but its API is open. Anyone can build a bridge to another host (Houdini, Blender, a game engine, a render farm tool) or a pipeline tool on top of it, without GroomLab's source code.

What you get

PieceWhat it isUse it for
C API (groomlab_c.h)Plain C99 functions over opaque handles, in one library (groomlab.dll).Host plugins and any language with a C FFI.
C++ wrapper (groomlab.hpp)Header-only C++17 over the C API: RAII, views, exceptions.C++ hosts. It adds no binary of its own.
The .groom formatA JSON file holding a groom: graph, guides, scalp, maps.Moving grooms between hosts, and reading them without the library.
PythonMaya's groomlab package, and the core's groomlab_core module.Scripting inside Maya and Maya's Python. See Python API.
Samplesgroom_to_obj (C++) and groom_counts (C), MIT licensed.A starting point for your own bridge.

The C API, its headers and the samples come in the GroomLab SDK (a GroomLabSDK folder). See C and C++ API to build against it, and Writing a host bridge for the steps a bridge takes.

Licensing

The API and the samples are open to build on. The library itself is part of GroomLab: using it commercially needs a GroomLab licence. The samples are MIT licensed, so you may copy them into your own code.

What is stable

Three things carry a version. Each has its own rule.

The C API: semantic versioning

GROOMLAB_C_API_VERSION_MAJOR and _MINOR in groomlab_c.h name the API the header declares. gl_api_version() gives the library's.

  • Same major: binary compatible. A minor release only adds functions, and fields at the end of option structs (which carry their own struct_size). A program built against 1.0 runs on 1.3.
  • A new major may change or remove functions. Check it when you load the library: GROOMLAB_C_API_COMPATIBLE(gl_api_version()). The C++ wrapper does this for you when it makes a Session.
  • The CMake package GroomLabSDK has the same version, so find_package(GroomLabSDK 1.0) takes any 1.x.

Only groomlab_c.h and groomlab.hpp are the API. Nothing else in GroomLab is, including the core's C++ classes and the Python modules' internals.

The .groom file: a format version

A .groom file has "format": "groomlab.groom" and a whole-number "version" (1 today).

  • A file from a newer GroomLab is refused with a clear error ("update GroomLab to open it"). It is never half-read.
  • GroomLab does not migrate files. The version only goes up when an old file would no longer read back, and then files of the old version are refused too. Additions that have defaults (a new optional field) keep the version.
  • GroomLab ignores fields it does not know when it reads a file, and does not keep them when it writes one.

The full layout is in The .groom format.

Nodes: a version per node

Each operator (Scatter, Clump, Noise...) has a behaviour version. A saved graph stores, per node, the version it was made with, and every param's value, set or not.

  • A newer GroomLab keeps evaluating an old node the old way, so a saved groom keeps its look. A later change of a default never changes a saved file either.
  • When a node has a newer behaviour, its panel shows Upgrade. Upgrading is a choice: the look may change.
  • A graph holding a node newer than the library knows is refused, as files are.

From the API, gl_session_node_spec_json gives a node's "nodeVersion" and "outdated" (true when an upgrade exists), and gl_session_upgrade_node upgrades it (API 1.1). See Node versions.

What is not stable yet

  • Up axis. Points come out in the groom's up axis ("upAxis", Y by default). A Z-up host turns them on its side for now.
  • Inner documents of a groom file. The guide hierarchy, parts, flow and correctives are stored as GroomLab writes them. Their inner layout may change within a format version. Keep them as they are; don't edit them by hand.
  • Operator specs. Node and param names change rarely, and old ones keep loading. Read them from gl_operator_specs_json rather than hard-coding a list.

Next

On this page