home n64

introduction

this document explains the system i developed for handling collision detection between the player and the 3d mesh representing the game environment. without such a system, the player would not interact with the environment and would walk through walls, or, if gravity is implemented, would fall through floors. early in development i used an AABB system similar to the one in example 5 (splitscreen) in HailToDodongo's tiny3d library. this system works well for small, simple environments consisting of rectangular obstacles aligned with the coordinate system, and is fairly simple and straightforward to set up. but for more complicated environments with diagonal surfaces, a more robust system is needed. additionally, in a project with many different complex environments the player could navigate between, i needed a system which would be able to automatically extract collision data from the environment mesh so that no manual intervention would be required every time i add a new area to the game.



world collision system overview

this diagram shows all of the components of the collision system starting from creating the model in blender to calling the collision resolution function while the game is running. the flow of the system is tightly correlated with the system for displaying the environment (since the collision must happen where the visual boundaries are), so on the right side of the diagram i have included the components of the tiny3d system for rendering the environment.


here is a high level description of each step in the world collision system:
  1. asset creation
    1. in blender, create the 3d model for the environment that the player will walk around in.
    2. export the model as a .glb file. (this is the same file used for the tiny3d system, indicated by the branching arrow in the diagram)
  2. compile time (pc)
    1. save_triangles is a script i wrote to extract the coordinates of all the triangles in the .glb file. it is called by the makefile when compiling the n64 rom.
    2. the result of save_triangles is a .bin file containing a vector of all the triangles and their coordinates. it is loaded into the filesystem for the rom.
  3. run time (n64)
    1. while the game is running, any time a new environment is loaded, the loadCollTriangles() function is called. this reads from the .bin file corresponding to the current environment.
    2. the result of loadCollTriangles() is a vector of triangles in memory, reconstructed from the .bin file.
    3. the coordinates of the triangles must be scaled and transformed the same way as the coordinates of the triangles in the rendered T3DModel. otherwise, the collision boundaries will not be aligned with the visually rendered environment.
    4. finally, the collision function, resolveWallCollision(), is called every frame.


save_triangles.cpp -> loadCollTriangles()

save_triangles is a standalone script i wrote to extract triangle information (3d coordinates of vertices grouped by triangles) from a .glb file exported from blender. it uses the tinygltf library.


it can be run from the command line with the following syntax:

save_triangles <path/to/input.glb> <path/to/output.bin>

i modified the makefile for my game to automatically execute save_triangles if a new .glb file is added to the game assets or an existing one has been updated:

filesystem/%.bin: assets/models/%.glb
@mkdir -p $(dir $@)
@echo " [COLL] $@"
tools/save_triangles/save_triangles $< $@


resolveWallCollision()