# ufbx: A Single-Source FBX Loader for C and C++

> ufbx parses binary and ASCII FBX files through two copied source files and exposes the loaded scene as plain C data. It suits applications that need broad FBX coverage without adopting a full SDK dependency, but its pre-1.0 compatibility policy and copy-based setup require attention.

**ufbx/ufbx** — Single source file FBX loader

- Repository: https://github.com/ufbx/ufbx
- Stars: 1,432 · Forks: 107
- Language: C
- License: NOASSERTION
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/ufbx-ufbx

## Why ufbx Exists Outside the Official SDK

ufbx addresses a specific integration problem: loading FBX content from a C or C++ application without adding a separate SDK package to the build. Its distribution model is unusually direct. The README tells developers to copy `ufbx.h` and `ufbx.c` into the project, rather than install a library through a package manager. This makes the loader suitable for engines, tools, renderers, and native applications whose build systems already manage portable C sources.

The stated scope extends beyond basic geometry loading. The README documents support for binary and ASCII FBX files from version 3000, along with meshes, skinning, blend shapes, cameras, lights, embedded textures, NURBS curves and surfaces, geometry caches, LOD groups, rigging constraints, and display or selection sets. It also supports Wavefront `.obj` files. These are project claims from the README, not an independent assessment of every exporter or scene construction.

The target audience is therefore narrower than the file format itself suggests. ufbx is for developers who want an embeddable parser and direct access to scene data. It is a poor fit for a team whose main requirement is a vendor-supported SDK integration, managed binary distribution, or tooling around a larger FBX application suite. The README says feature parity with the official FBX SDK is the goal, not that ufbx duplicates the SDK's packaging, editor, or proprietary ecosystem.

## The Plain Data Scene Returned by ufbx

The central mechanism is a load call that returns a `ufbx_scene *`. Applications pass an input path, an optional `ufbx_load_opts` structure, and an optional `ufbx_error`. A successful result contains plain data structures that the caller can inspect directly. The scene includes arrays of nodes, while each `ufbx_node` can provide a name, root status, and an associated mesh. The README describes no required scene graph object or opaque callback layer for basic use.

This first-use example lists non-root objects and reports the face count for nodes that contain a mesh:

```cpp
ufbx_load_opts opts = { 0 };
ufbx_error error;
ufbx_scene *scene = ufbx_load_file("thing.fbx", &opts, &error);
if (!scene) {
    fprintf(stderr, "Failed to load: %s\n", error.description.data);
    exit(1);
}

for (size_t i = 0; i < scene->nodes.count; i++) {
    ufbx_node *node = scene->nodes.data[i];
    if (node->is_root) continue;

    printf("Object: %s\n", node->name.data);
    if (node->mesh) {
        printf("-> mesh with %zu faces\n", node->mesh->faces.count);
    }
}

ufbx_free_scene(scene);
```

The result is expected to be null on failure, with the error description available through `error.description.data`. A successful scene remains caller-owned and must be released with `ufbx_free_scene`. The example combines loading, inspection, and cleanup in one function, which makes the ownership model easy to understand. Real applications should also decide where cleanup occurs when scene loading is one stage of a larger pipeline.

The README also documents optional scene utilities, including polygon triangulation, index generation, animation curve evaluation and layer blending, CPU skinning evaluation, subdivision surface evaluation, and NURBS tessellation. It says these utilities can be compiled out when they are not needed. That makes feature scope and compilation size explicit choices, but the README does not document the macros or build switches used to remove each utility.

## Copying ufbx.c and ufbx.h for a First Native Build

The documented installation is a source-copy operation. There is no `git clone`, package-manager install, or platform-specific setup command in the README. Obtain `ufbx.c` and `ufbx.h` from the repository, place both in the project, and compile `ufbx.c` as C99 or newer. The code can also compile as C++11 or newer. The optional `misc/ufbx.natvis` file supplies debug formatting for ufbx types in supported debugger environments.

For a first check, add the header to the application source and compile the loader as a second C or C++ translation unit. The exact compiler invocation depends on the project's build system and compiler, which the README does not prescribe. The following illustrative call demonstrates the load and cleanup path rather than a portable build command:

```cpp
#include "ufbx.h"

ufbx_load_opts opts = { 0 };
ufbx_error error;
ufbx_scene *scene = ufbx_load_file("thing.fbx", &opts, &error);
if (!scene) {
    exit(1);
}
ufbx_free_scene(scene);
```

Passing `NULL` for both optional output parameters requests defaults and discards error details. A first real use should instead provide a `ufbx_error`, as in the fuller README example, because a loader for user-supplied assets needs a way to report why a file failed.

The stated compiler floor also has a platform-specific consequence. On an unknown compiler targeting a version older than C11 or C++11, some functions are not thread-safe because C99 does not provide atomic support. MSVC, Clang, GCC, and TCC are specifically excluded from that unknown-compiler condition in the portability note. Teams deploying to a less common toolchain should therefore verify concurrency behavior rather than assuming that portability includes equivalent thread-safety guarantees.

## Malformed FBX Handling and Sanitization Defaults

ufbx places particular emphasis on treating hostile or damaged input as a loader problem. The README states that invalid files and out-of-memory conditions are handled gracefully. It also says loaded scenes are sanitized by default, preventing out-of-bounds indices and non-UTF-8 strings. Those are meaningful guarantees for applications that accept FBX files from users or external pipelines, because malformed input is not limited to a clean parse error.

The documented verification approach is broad but cannot be treated as proof for every workload. The README reports internal cases across listed platforms, parser and structured fuzzing with AFL, built-in tests for byte modifications, truncation, and out-of-memory conditions, semantic fuzzing for binary FBX and OBJ files, a public dataset, and a larger private dataset. It also reports static stack-depth analysis and coverage figures. Those figures describe the project's stated test program. They do not establish behavior for every FBX exporter, deeply nested scene, or platform outside the documented CI matrix.

CI reportedly produces bit-exact results on Windows, macOS, Linux, and WASI across the listed compiler and architecture combinations. That is useful evidence for cross-platform consistency, although the README does not define exactly which parsed outputs are compared. Applications should still test their own loading path because they may compile different utility features, use different language standards, or exercise files unlike the listed datasets.

A related failure boundary is version support. The README explicitly says binary and ASCII FBX files from version 3000 are supported. It does not describe support for FBX versions earlier than 3000. Projects that receive legacy FBX exports need to confirm their producer versions before switching a production import path to ufbx.

## Source Compatibility Before ufbx Reaches Version 1.0

ufbx has no GitHub releases, so there is no release entry to inspect for packaged artifacts or upgrade notes. The README instead states that the latest commit in the `master` branch contains the latest stable version. Older releases are tagged as `vX.Y.Z`. Although the repository metadata identifies `main` as the default branch, the versioning text refers to `master`; the README does not explain whether both branches exist, whether one mirrors the other, or whether the documentation is out of date. That discrepancy should be checked before building a dependency automation policy around a particular branch.

The compatibility policy is more important than the release-channel mechanics. Patch releases, identified by the `Z` component, are documented as ABI compatible and compatible with older headers from the same `Y` minor version. Versions within a major release are expected to remain source compatible after `1.0.0`. Before then, the README says every `0.Y.Z` minor release can break compatibility. In other words, a minor-version upgrade may require source changes while ufbx remains in its `0.Y.Z` series.

The last push was on 2026-10-01, which is recent relative to the repository state, but there are no GitHub releases from which to establish a release cadence. Maintenance activity and release stability are different facts. A recent commit can contain fixes without providing a tagged upgrade path, while a new tag can require review of compatibility policy and asset compatibility.

The license also requires a deliberate choice. The README presents two alternatives: the MIT License or a Public Domain dedication under the Unlicense wording. The repository metadata categorizes the license as custom because GitHub cannot classify this dual-option text. Distribution files should preserve the selected option's required notices. This is a licensing selection to review, not legal advice.

## Comparing ufbx with the Official FBX SDK

The clearest alternative named by the project is the official FBX SDK. The mechanism differs at the distribution boundary. ufbx is delivered as `ufbx.c` and `ufbx.h`, which the application copies and compiles as part of its own source tree. That approach exposes the complete loader source in the build and gives the application direct control over compilation options. It also means that source updates, compiler compatibility, static analysis, and integration work fall on the integrating project.

The README names the official FBX SDK but does not describe its distribution model. The README does not document its installation method, API shape, platform coverage, or licensing terms, so this review cannot make claims about those areas. What can be said is that ufbx targets feature parity with it while exposing loaded scenes as plain C data and also accepting OBJ files. That makes ufbx the more natural candidate for a small native build, based on its documented setup, not necessarily the better choice for every FBX workflow.

ufbx may also be a poor tool when an application depends on behaviors outside parsing. The README does not document a scene editor, GUI, rendering pipeline, or vendor service integration. Conversely, the two-file model may be inconvenient for organizations that ban vendored source or require centrally versioned binary dependencies. The choice should therefore center on build policy and required format coverage, not on a claim that either loader is universally superior.

## Conclusion

Application developers should consider ufbx when they want direct control over a C FBX loader and can copy ufbx.c and ufbx.h into the build. Teams that require a stable 1.x compatibility promise or prefer the official FBX SDK should account for ufbx's pre-1.0 release policy. Before adoption, verify that your compiler meets the C99 or C++11 requirement, inspect the custom dual-license terms in LICENSE, and test the exact FBX features and malformed-file cases your pipeline sends.

## FAQ

### How do I install and use ufbx?

Copy `ufbx.c` and `ufbx.h` into the project, compile `ufbx.c` as C99 or C++11 or newer, then call `ufbx_load_file()`. Release a successful `ufbx_scene` with `ufbx_free_scene()`.

### Which FBX and OBJ file formats does ufbx support?

The README documents binary and ASCII FBX support starting with version 3000. It also documents support for Wavefront `.obj` files.

### Can I use ufbx in a commercial application?

The project offers two license alternatives: the MIT License and a Public Domain dedication under the Unlicense wording. The integrating project must preserve the requirements associated with its selected option.

### Is ufbx safe for malformed and untrusted FBX files?

The README says invalid files and out-of-memory conditions are handled gracefully, with sanitized scenes by default. It also documents fuzzing, semantic fuzzing, modification tests, truncation tests, and static stack-depth analysis, though those claims do not replace testing an application's own threat model.

## Sources

- [Issues](https://github.com/ufbx/ufbx/issues)
- [README](https://github.com/ufbx/ufbx/blob/main/README.md)
- [ufbx/ufbx on GitHub](https://github.com/ufbx/ufbx)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/ufbx-ufbx
