Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

45 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

gnm-houdini

A personal research and development project that brings GNM Head — Google's high-fidelity statistical 3D model of the human head — into SideFX Houdini as a digital asset (HDA), generating parametric head meshes directly inside a SOP network.

Scope: This project is built and tested for personal use. It is shared openly in case others find it useful, but it comes with no guarantees of stability or completeness. Contributions and issues are welcome.


What is GNM?

GNM (Generative aNthropometric Model, pronounced like genome) is a family of parametric statistical human models developed by Google. Its first open-source release, GNM Head, is a 3D morphable model of the human head offering fine-grained, disentangled control over identity, expression, and head pose, including internal anatomy such as eyeballs, teeth, and tongue. It ships with NumPy, JAX, PyTorch, and TensorFlow backends; this project uses the NumPy backend only.


What this project does

  • gnm::gnm_head::1.0 HDA — a SOP node that generates a head mesh (17,821 points / 35,324 triangles) from the GNM Head model, with full parameter control over identity, expression, and pose (see Usage), and seam-correct per-corner UVs (a uv vertex attribute) ready for texturing.
  • houdini/python/gnm_hda.py — core logic: cached model load, seed-to-identity mapping, mesh generation, geometry write. Uses Houdini's bundled numpy; no TensorFlow on the generation path. A single cook takes on the order of tens of milliseconds.
  • houdini/packages/GNM.json — a Houdini package that sets PYTHONPATH and auto-discovers the HDA.
  • scripts/build_hda.py — reproducible HDA build script.
  • tests/test_gnm_hda.py — unit tests runnable under hython.
  • semantic_server/ — a separate, uv-managed FastAPI server (plain Python, not hython) wrapping GNM's TensorFlow-based semantic sampler. Lets the HDA generate an identity from gender/ethnicity, or an expression from a named label, via HTTP; see semantic_server/README.md.

GNM itself is an external, read-only dependency: this repository contains no model code or data, and imports GNM from a separate clone via PYTHONPATH.


Possible use cases

  • Procedural head generation — scatter seeds to produce varied background or crowd heads
  • Base mesh supply — generate a clean, consistent-topology head as a starting point for sculpting or lookdev
  • Research and pipeline testing — evaluate GNM Head output inside a real DCC environment

Current limitations

  • Numbered sliders only — identity/expression components are statistical basis coefficients with no semantic labels (this is inherent to the model data); sliders are numbered per group, with low numbers making the biggest changes.
  • No textures or materials — the mesh carries UVs, but no material or texture is wired in (GNM ships one modeling reference image, not a skin texture)
  • Semantic sampling needs a separate running server — GNM's semantic sampler requires TensorFlow, which is not bundled into Houdini's Python; semantic_server/ runs it separately and the HDA calls it over HTTP only when you click a "Sample" button (never during a normal cook). Single-label only — no weighted blending of multiple labels yet.
  • External GNM clone required — model data is not bundled; you need your own GNM checkout and two environment variables (see below)

Requirements

  • Houdini — tested with 22.0.368 (bundled Python 3.13, numpy 2.3); also verified with 21.0.729 (Python 3.11, numpy 1.26)
  • A clone of GNM: https://github.com/google/GNM
  • Optional, for semantic sampling only — uv (Python 3.13, fetched automatically by uv); see semantic_server/README.md

The commands below call hython, Houdini's bundled Python interpreter. It lives in Houdini's bin/ directory — either add that directory to your PATH or replace hython with its full path.

Installation

  1. Clone this repository and make sure you have a GNM clone.

  2. Use Houdini's hython to install the pure-Python dependencies into a local deps/ directory (run from the repository root):

    hython -m pip install --target=./deps etils absl-py immutabledict typing_extensions
    

    (numpy is provided by Houdini, so it is not installed. The core generation path does not require TensorFlow.)

  3. Set two environment variables (pointing at your actual paths):

    • GNM_HOUDINI = the root of this repository
    • GNM_REPO = your GNM clone
  4. Let Houdini load this repository's package by making houdini/packages/GNM.json discoverable. The simplest way is to set HOUDINI_PACKAGE_DIR to $GNM_HOUDINI/houdini/packages, or copy that JSON into the packages/ folder of your Houdini user preferences directory (e.g. $HOME/houdiniX.Y/packages/).

Usage

Launch Houdini and create a GNM Head node in a SOP context. Parameters are grouped in three tabs:

  • IdentitySeed/Strength pick a random base face (0 = the average face). The Head and Teeth component lists plus three Eyeball sliders add per-component offsets on top of the base: set a list's count to expose that many components (entry N always controls component N; low-numbered components make the biggest changes). Each entry's toggle mutes that component without losing its value or animation keys. Gender/Ethnicity plus Sample Identity fetch a semantic identity from semantic_server/ (see below); Semantic Strength blends it in on top of the seed base, same as Strength does for the random base — both sources and the slider offsets sum together.
  • Expression — same pattern: Exp Seed/Exp Strength (default 0 = neutral) plus per-region component lists (Left/Right Eye, Lower Face, Tongue) and an Iris slider. Expression Label plus Sample Expression fetch a named expression (e.g. Happy, Surprise) the same way, blended in via Semantic Strength.
  • Pose — axis-angle rotations in degrees for the neck, head, and each eyeball, plus a global translation.

Getting started with semantic sampling

  1. Start the server (see semantic_server/README.md for setup): from semantic_server/, uv run uvicorn server:app --host 0.0.0.0 --port 8000 (or your own port via GNM_SEMANTIC_PORT).
  2. On the HDA, set Server URL (shared by both tabs) to match, e.g. http://localhost:8000.
  3. Pick a Gender/Ethnicity (Identity tab) or Expression Label (Expression tab), then press the Sample Identity/Sample Expression button. This is the only point that talks to the server — it fetches once and bakes the result into the node, so the server doesn't need to stay running afterward for the node to keep cooking.
  4. Raise Semantic Strength from 0 to blend the sampled result in; it sums with the random Seed/Strength base and the slider offsets, it doesn't replace them.

If you update houdini/otls/gnm.gnm_head.1.0.hda (e.g. after pulling a newer version of this repo), existing GNM Head nodes already placed in a scene keep using the old parameter definition until you right-click the node → Match Current Definition (or delete and recreate it) — the new tabs/parms won't appear otherwise.

Development

Rebuild the HDA (run from the repository root; needs the same environment as Installation, since the build reads group sizes from the model):

hython scripts/build_hda.py houdini/otls/gnm.gnm_head.1.0.hda

Verify the built HDA end-to-end (needs the package env from Installation):

hython scripts/verify_hda.py

Run the tests:

hython -m unittest discover -s tests -v

For semantic_server/'s own dev/test commands (managed separately with uv), see semantic_server/README.md.


License

This project (HDA, Python module, scripts) is released for personal and research use with no restrictions.

GNM is subject to its own license — Apache License 2.0, permissive for both non-commercial and commercial use; see the GNM repository for details. This repository does not redistribute any GNM code, model data, or weights.

About

Houdini digital asset (HDA) that generates parametric 3D human head meshes using Google's GNM model.

Topics

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages