/tiny3d

N64 3D ucode for libdragon

Primary LanguageC++MIT LicenseMIT

Tiny3D

3D ucode/library for the N64 using libdragon.
The motivation of this project is to provide a fast and minimal API while having all the features needed for 3D applications.

Features

Tiny3D comes with both RSP microcode and an easy to use C-API around it.
Features include:

  • Full 3D Pipeline for loading and rendering meshes
  • Matrix stack and functions
  • Lighting with ambient and directional lighting
  • Normals & Color at the same time with 16bytes per vertex
  • Skinned Meshes & Animation support
    • fake-blending with 1 bone per vertex / up to 3 bones per triangle
    • animation blending
    • (compressed) animation streaming from ROM
    • attachment of non-skeletal targets (e.g. camera)
  • GLTF importer with Fast64 support (supported settings)
    • Vertex cache optimization
    • Automatic texture loading
    • Applies CC and related settings set in Fast64
  • Direct interop. with the RDPQ API.

Usage

Checkout this repository and build it first (see the Build section), no prebuilts are provided.
To use Tiny3D in your project, add the following line in your Makefile:

include $(T3D_INST)/t3d.mk

Where T3D_INST points to the path of this repository.
Internally this will handle adding the correct include path and linking Tiny3D itself into you project.

In general, it's easier to simply take one of the included example projects as a starting point.
These can be found in the examples directory, where each of them goes into details about different features.

To start out, take a look at examples/01_quad which is the most basic setup drawing a single 3D quad.

API Reference

(@TODO: generate docs from comments, add github page for it)

GLTF Model import

Tiny3D comes with a build-in model format and an importer for GLTF files.
In order to best use the N64 hardware, it is recommended to use Fast64.

Note: Due to internal changes in the GLTF exporter, only blender up to version 4.0 is supported at the moment.
Exporting embedded texture may also cause issues, so it's recommended to use files.

At the moment only fast64 materials are supported.
For this to work, custom properties export must be enabled.
This can be set during export:

For a full list of supported settings, see docs/fast64Settings.md.

Build

Tiny3D requires libdragon, specifically the preview branch.
Make sure you have that project setup first.

To build Tiny3D, simply run the build.sh script in the root directory of the project.

./build.sh

This will build the library itself, tools related to it, and all examples.
If you need to build specific parts, run the Makefile present in each directory.
After building, you can use the project as described in the Usage section.

If you want to perform a clean build for everything, run:

./build.sh clean

Customization

You will notice that Tiny3D does not install itself in any system-wide location.
This is done on purpose, as it allows you to easily modify the library.
Use-cases can be wanting to specialize the API for your project, or to modify the ucode.

RSP ucode

The ucode of Tiny3D is written in RSPL, a high level language that has been worked on in parallel with this project.
By default, the generated ASM is included to avoid any additional dependencies.
If you plan on modifying the ucode, you will need to either install the RSPL transpiler or use the WebUI.
Keep in mind to enable reordering within RSPL to get maximum performance.

Differences to OpenGL

If you are already familiar with OpenGL in libdragon, you will notice some key differences in Tiny3D.
With an existing codebase, this may require changes to the way models are handled and drawn.
Here are the most important ones:

Matrices and Vertices are DMA'd in

Even when recorded into a display-list, matrices and vertices are DMA'd into the RSP each time.
Meaning you have keep both around in RDRAM the entire time you want to render them.
However, this also means you can easily modify them at any time without having to re-record the display-list.
Same is true for matrices: you can record a matrix load without losing the ability to modify it later.

No Abstract Materials

Beside being able to enable/disable textures & lighting, there are no abstract materials in Tiny3D.
Everything needs to be set either manually via the RSPQ API or by using the builtin model format which can do it for you.
In other words, Tiny3D is the equivalent of always running in GL_RDPQ_MATERIAL_N64 mode.

No Texture abstraction

Tiny3D does not know about textures, for loads and related settings the RDPQ API & sprite_load must be used.
This also removes the need for special functions like glSpriteTextureN64 & glTexParameteri like in OpenGL.
Due to all of this, UVs must be set in pixel-coordinates (10.5 fixed point), not normalized ones.
Multi-Textures are therefore also directly supported.

Fixed Layout

Tiny3D uses a fixed and interleaved layout for its vertices.
This is done to maximize performance and to simplify the API.
A matching C struct T3DVertPacked can be found in t3d.h.

If you plan on using your own custom model format, take a look at the GLTF importer on how to normalize data properly.
A full description of the builtin model-format layout can be found in docs/modelFormat.md too.

Support

If you need any help, feel free to ask me (@HailToDodongo) in the N64brew Discord.

Contributing

Contributions via PRs or any feedback is welcome.
Same as above, feel free to talk about changes on Discord.

Credits & License

© 2023-2024 - Max Bebök (HailToDodongo)

Tiny3D is licensed under the MIT License, see the LICENSE file for more information.

External Libraries