Cauldron3D.Formats reads the Quake family of game files into cauldron_3d structures. It reads archives, maps, models, sprites, picture collections, pictures and sounds.

Where it fits

The readers return Cauldron3D values: Cauldron3D.Bsp, Cauldron3D.Mesh and Cauldron3D.Texture. cauldron_3d draws and collides them in software. cauldron_gpu converts them and draws them on the graphics card. A quake_c host starts from a map's entity text and the game's progs.dat, both read through Cauldron3D.Formats.Files.

Installation

Add the dependency to mix.exs:

def deps do
  [
    {:cauldron_3d_formats, "~> 0.3"}
  ]
end

What is here

ModuleWhat it reads
Cauldron3D.Formats.FilesGathers a game's files from directories. It reads pak0.pak… archives, .pk3 zips (zips inside zips too) and loose files. Later sources override earlier ones. Call open/2, then read/2, read!/2, exists?/2 or list/2.
Cauldron3D.Formats.BspReads map files into a Cauldron3D.Bsp and the entity text. It reads BSP29, BSP2 and Half-Life's BSP30, with its own texture palettes and coloured lighting.
Cauldron3D.Formats.MdlReads Quake models into a Cauldron3D.Mesh, with frame groups, effect flags and a box. pose/3 picks the pose for a frame at a time.
Cauldron3D.Formats.StudioReads Half-Life studio models (.mdl version 10). It reads bones, controllers, hitboxes, sequences and events, attachments, textures, skin families and meshes. It decodes the compressed animation to bone poses.
Cauldron3D.Formats.SprReads Quake and Half-Life sprites.
Cauldron3D.Formats.Wad2, Cauldron3D.Formats.Wad3Read picture, texture and font collections.
Cauldron3D.Formats.Tga, Cauldron3D.Formats.BmpRead TGA and BMP pictures.
Cauldron3D.Formats.WavReads WAVE sounds to 16-bit PCM.
Cauldron3D.Formats.EntitiesReads a map's entity text into one map of keys and values per entity.
Cauldron3D.Formats.NormalsHolds the 162 vertex normals that Quake models index into.

Usage

alias Cauldron3D.Formats.{Bsp, Files, Mdl}

{:ok, files} = Files.open("/games/quake", within: "id1")

{:ok, %{bsp: bsp, entities: text}} =
  Bsp.parse(Files.read!(files, "maps/e1m1.bsp"),
    hulls: [{{-16.0, -16.0, -24.0}, {16.0, 16.0, 32.0}}, {{-32.0, -32.0, -24.0}, {32.0, 32.0, 64.0}}],
    texture: &MyGame.texture/2
  )

{:ok, player} = Mdl.parse(Files.read!(files, "progs/player.mdl"))
Cauldron3D.Mesh.polygons(player.mesh, frame: Mdl.pose(player, 0, 0.0))

Each game names its own conventions through Bsp.parse/2's options. :hulls gives the collision box sizes. :texture gives each texture its kind: sky, liquid, hidden or masked. So the same reader serves Quake and Half-Life.

License

MIT. No game data is included.