C Other
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.



Build Status Documentation

This is a tiny MIT-licensed C library of image utilities for dealing with height maps, normal maps, distance fields, and the like. It has a very low-level API, where an "image" is simply a flat array of floats. It's pretty fast too, since it's parallelized with OpenMP.

Heman can do stuff like this:

  • Create a random height field using simplex noise and FBM.
  • Generate a normal map from a height map.
  • Compute ambient occlusion from a height map.
  • Generate a signed distance field (SDF).
  • Export a 3D mesh in PLY format.
  • Apply a color gradient to a heightmap.
  • Generate a color gradient, given a list of control points.
  • Compute diffuse lighting with an infinite light source.
  • Generate a nicely-distributed list of points according to a density field.

Heman implements some really nice 21st-century algorithms:

  • Ambient occlusion is generated using Sean Barrett's efficient method that makes 16 sweeps over the height field.
  • Distance field computation uses the beautiful algorithm from Distance Transforms of Sampled Functions (Felzenszwalb and Huttenlocher).
  • Density field samples are generated using Robert Bridson's Fast Poisson Disk Sampling in Arbitrary Dimensions.

Python and JavaScript too!

Unit tests are performed using the Python bindings, which live in prideout/heman-python.

Heman also provides emscripten bindings for its API. The JavaScript demo is here.


The above images were generated from code that looks like this:

// Generate an island shape using simplex noise and a distance field.
heman_image* elevation = heman_generate_island_heightmap(1024, 1024, rand());

// Compute ambient occlusion from the height map.
heman_image* occ = heman_lighting_compute_occlusion(elevation);

// Visualize the normal vectors.
heman_image* normals = heman_lighting_compute_normals(elevation);

// Apply a color gradient.
heman_image* gradient = heman_color_create_gradient(...);
heman_image* albedo = heman_color_apply_gradient(elevation, -0.5, 0.5, grad);

// Apply diffuse lighting.
heman_image* final = heman_lighting_apply(elevation, albedo, ...);

For the unabridged version, see test_lighting in test/test_heman.c.


The latest Sphinx-generated docs are hosted here. You can also take a look at heman's one and only header file.


Heman has no dependencies, so it should be easy just to incorporate the code directly into your project.

For building a shared library in OS X, you can do this:

brew install scons
scons lib

Note that this will not use OpenMP or build any tests.

Linux is required for OpenMP and tests. If you are not using a Linux machine but you want OpenMP support, take a look at the provided Dockerfile.

There's a script in the repo, env.sh, that makes using Docker easy. It calls docker-machine and builds a container. Here's how to use it:

brew install docker-machine
. env.sh
# Lots of stuff spews out as it builds the container...
# You're now inside the VM -- press enter twice for the prompt.
scons && build/test_heman
# You can now look at the generated images:
ls build/*.png


Here are some to-be-done items:

  • Provide "Exponentially Distributed Noise", in addition to Simplex.
  • Flesh out the Python Bindings and provide docstrings.
  • Implement a contour extractor:
    • heman_ops_extract_contour(image, threshold, thickness)
    • this just does a Sobel operator, that's all
  • More distance field stuff.
    • Allow non-monochrome source images.
    • Allow computation of unsigned, squared distance.
    • Spherical distance.
  • Smarter Mesh Output
    • Create a hull from poisson samples
    • Sobel + (Step => Sobel) => Density Field => Poisson Samples
    • Do not use marching squares!
    • Two meshes: overwater and underwater
  • Provide gamma decode and encode functions.
  • More noise routines!
    • Bridson's Curl noise (and a routine that performs advection?)
    • Worley noise (useful for billows as seen in Real-time Volumetric Cloudscapes of Horizon)
    • Analytic noise normals
    • Wavelet Noise
  • heman_image_sample doesn't do any interpolation. Maybe it should at least do a 2x2 box filter.
  • Provide functionality from Scalable Height-Field Self-Shadowing
  • If we need more string handling, we can integrate SDS.
  • Integrate aaOcean, or some other implementation of Tessendorf waves.
  • If we need to read JSON, we might use this or this.
  • There are cool data structures in http://concurrencykit.org/