MagicaVoxel File: C++/STL parsing library

Application

MagicaVoxel

File extension

vox

KS implementation details

License: MIT

This page hosts a formal specification of MagicaVoxel File using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.

Usage

Using Kaitai Struct in C++/STL usually consists of 3 steps.

  1. We need to create an STL input stream (std::istream).
    • One can open a stream for reading from a local file:
      #include <fstream>
      
      std::ifstream is("path/to/local/file.vox", std::ifstream::binary);
    • Or one can prepare a stream for reading from existing std::string str:
      #include <sstream>
      
      std::istringstream is(str);
    • Or one can parse arbitrary char* buffer in memory, given that we know its size:
      #include <sstream>
      
      const char buf[] = { ... };
      std::string str(buf, sizeof buf);
      std::istringstream is(str);
  2. We need to wrap our input stream into Kaitai stream:
    #include <kaitai/kaitaistream.h>
    
    kaitai::kstream ks(&is);
  3. And finally, we can invoke the parsing:
    vox_t data(&ks);

After that, one can get various attributes from the structure by invoking getter methods like:

data.version() // => 150 expected

C++/STL source code to parse MagicaVoxel File

vox.h

#ifndef VOX_H_
#define VOX_H_

// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild

#include "kaitai/kaitaistruct.h"

#include <stdint.h>
#include <vector>

#if KAITAI_STRUCT_VERSION < 7000L
#error "Incompatible Kaitai Struct C++/STL API: version 0.7 or later is required"
#endif

/**
 * \sa Format Description
 */

class vox_t : public kaitai::kstruct {

public:
    class chunk_t;
    class size_t;
    class rgba_t;
    class pack_t;
    class matt_t;
    class xyzi_t;
    class color_t;
    class voxel_t;

    enum chunk_type_t {
        CHUNK_TYPE_MAIN = 1296124238,
        CHUNK_TYPE_MATT = 1296127060,
        CHUNK_TYPE_PACK = 1346454347,
        CHUNK_TYPE_RGBA = 1380401729,
        CHUNK_TYPE_SIZE = 1397316165,
        CHUNK_TYPE_XYZI = 1482250825
    };

    enum material_type_t {
        MATERIAL_TYPE_DIFFUSE = 0,
        MATERIAL_TYPE_METAL = 1,
        MATERIAL_TYPE_GLASS = 2,
        MATERIAL_TYPE_EMISSIVE = 3
    };

    enum property_bits_type_t {
        PROPERTY_BITS_TYPE_PLASTIC = 1,
        PROPERTY_BITS_TYPE_ROUGHNESS = 2,
        PROPERTY_BITS_TYPE_SPECULAR = 4,
        PROPERTY_BITS_TYPE_IOR = 8,
        PROPERTY_BITS_TYPE_ATTENUATION = 16,
        PROPERTY_BITS_TYPE_POWER = 32,
        PROPERTY_BITS_TYPE_GLOW = 64,
        PROPERTY_BITS_TYPE_IS_TOTAL_POWER = 128
    };

    vox_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = 0, vox_t* p__root = 0);

private:
    void _read();

public:
    ~vox_t();

    class chunk_t : public kaitai::kstruct {

    public:

        chunk_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = 0, vox_t* p__root = 0);

    private:
        void _read();

    public:
        ~chunk_t();

    private:
        chunk_type_t m_chunk_id;
        uint32_t m_num_bytes_of_chunk_content;
        uint32_t m_num_bytes_of_children_chunks;
        kaitai::kstruct* m_chunk_content;
        bool n_chunk_content;

    public:
        bool _is_null_chunk_content() { chunk_content(); return n_chunk_content; };

    private:
        std::vector<chunk_t*>* m_children_chunks;
        bool n_children_chunks;

    public:
        bool _is_null_children_chunks() { children_chunks(); return n_children_chunks; };

    private:
        vox_t* m__root;
        kaitai::kstruct* m__parent;
        std::string m__raw_chunk_content;
        kaitai::kstream* m__io__raw_chunk_content;

    public:
        chunk_type_t chunk_id() const { return m_chunk_id; }
        uint32_t num_bytes_of_chunk_content() const { return m_num_bytes_of_chunk_content; }
        uint32_t num_bytes_of_children_chunks() const { return m_num_bytes_of_children_chunks; }
        kaitai::kstruct* chunk_content() const { return m_chunk_content; }
        std::vector<chunk_t*>* children_chunks() const { return m_children_chunks; }
        vox_t* _root() const { return m__root; }
        kaitai::kstruct* _parent() const { return m__parent; }
        std::string _raw_chunk_content() const { return m__raw_chunk_content; }
        kaitai::kstream* _io__raw_chunk_content() const { return m__io__raw_chunk_content; }
    };

    class size_t : public kaitai::kstruct {

    public:

        size_t(kaitai::kstream* p__io, vox_t::chunk_t* p__parent = 0, vox_t* p__root = 0);

    private:
        void _read();

    public:
        ~size_t();

    private:
        uint32_t m_size_x;
        uint32_t m_size_y;
        uint32_t m_size_z;
        vox_t* m__root;
        vox_t::chunk_t* m__parent;

    public:
        uint32_t size_x() const { return m_size_x; }
        uint32_t size_y() const { return m_size_y; }
        uint32_t size_z() const { return m_size_z; }
        vox_t* _root() const { return m__root; }
        vox_t::chunk_t* _parent() const { return m__parent; }
    };

    class rgba_t : public kaitai::kstruct {

    public:

        rgba_t(kaitai::kstream* p__io, vox_t::chunk_t* p__parent = 0, vox_t* p__root = 0);

    private:
        void _read();

    public:
        ~rgba_t();

    private:
        std::vector<color_t*>* m_colors;
        vox_t* m__root;
        vox_t::chunk_t* m__parent;

    public:
        std::vector<color_t*>* colors() const { return m_colors; }
        vox_t* _root() const { return m__root; }
        vox_t::chunk_t* _parent() const { return m__parent; }
    };

    class pack_t : public kaitai::kstruct {

    public:

        pack_t(kaitai::kstream* p__io, vox_t::chunk_t* p__parent = 0, vox_t* p__root = 0);

    private:
        void _read();

    public:
        ~pack_t();

    private:
        uint32_t m_num_models;
        vox_t* m__root;
        vox_t::chunk_t* m__parent;

    public:
        uint32_t num_models() const { return m_num_models; }
        vox_t* _root() const { return m__root; }
        vox_t::chunk_t* _parent() const { return m__parent; }
    };

    class matt_t : public kaitai::kstruct {

    public:

        matt_t(kaitai::kstream* p__io, vox_t::chunk_t* p__parent = 0, vox_t* p__root = 0);

    private:
        void _read();

    public:
        ~matt_t();

    private:
        bool f_has_is_total_power;
        bool m_has_is_total_power;

    public:
        bool has_is_total_power();

    private:
        bool f_has_plastic;
        bool m_has_plastic;

    public:
        bool has_plastic();

    private:
        bool f_has_attenuation;
        bool m_has_attenuation;

    public:
        bool has_attenuation();

    private:
        bool f_has_power;
        bool m_has_power;

    public:
        bool has_power();

    private:
        bool f_has_roughness;
        bool m_has_roughness;

    public:
        bool has_roughness();

    private:
        bool f_has_specular;
        bool m_has_specular;

    public:
        bool has_specular();

    private:
        bool f_has_ior;
        bool m_has_ior;

    public:
        bool has_ior();

    private:
        bool f_has_glow;
        bool m_has_glow;

    public:
        bool has_glow();

    private:
        uint32_t m_id;
        material_type_t m_material_type;
        float m_material_weight;
        uint32_t m_property_bits;
        float m_plastic;
        bool n_plastic;

    public:
        bool _is_null_plastic() { plastic(); return n_plastic; };

    private:
        float m_roughness;
        bool n_roughness;

    public:
        bool _is_null_roughness() { roughness(); return n_roughness; };

    private:
        float m_specular;
        bool n_specular;

    public:
        bool _is_null_specular() { specular(); return n_specular; };

    private:
        float m_ior;
        bool n_ior;

    public:
        bool _is_null_ior() { ior(); return n_ior; };

    private:
        float m_attenuation;
        bool n_attenuation;

    public:
        bool _is_null_attenuation() { attenuation(); return n_attenuation; };

    private:
        float m_power;
        bool n_power;

    public:
        bool _is_null_power() { power(); return n_power; };

    private:
        float m_glow;
        bool n_glow;

    public:
        bool _is_null_glow() { glow(); return n_glow; };

    private:
        float m_is_total_power;
        bool n_is_total_power;

    public:
        bool _is_null_is_total_power() { is_total_power(); return n_is_total_power; };

    private:
        vox_t* m__root;
        vox_t::chunk_t* m__parent;

    public:
        uint32_t id() const { return m_id; }
        material_type_t material_type() const { return m_material_type; }
        float material_weight() const { return m_material_weight; }
        uint32_t property_bits() const { return m_property_bits; }
        float plastic() const { return m_plastic; }
        float roughness() const { return m_roughness; }
        float specular() const { return m_specular; }
        float ior() const { return m_ior; }
        float attenuation() const { return m_attenuation; }
        float power() const { return m_power; }
        float glow() const { return m_glow; }
        float is_total_power() const { return m_is_total_power; }
        vox_t* _root() const { return m__root; }
        vox_t::chunk_t* _parent() const { return m__parent; }
    };

    class xyzi_t : public kaitai::kstruct {

    public:

        xyzi_t(kaitai::kstream* p__io, vox_t::chunk_t* p__parent = 0, vox_t* p__root = 0);

    private:
        void _read();

    public:
        ~xyzi_t();

    private:
        uint32_t m_num_voxels;
        std::vector<voxel_t*>* m_voxels;
        vox_t* m__root;
        vox_t::chunk_t* m__parent;

    public:
        uint32_t num_voxels() const { return m_num_voxels; }
        std::vector<voxel_t*>* voxels() const { return m_voxels; }
        vox_t* _root() const { return m__root; }
        vox_t::chunk_t* _parent() const { return m__parent; }
    };

    class color_t : public kaitai::kstruct {

    public:

        color_t(kaitai::kstream* p__io, vox_t::rgba_t* p__parent = 0, vox_t* p__root = 0);

    private:
        void _read();

    public:
        ~color_t();

    private:
        uint8_t m_r;
        uint8_t m_g;
        uint8_t m_b;
        uint8_t m_a;
        vox_t* m__root;
        vox_t::rgba_t* m__parent;

    public:
        uint8_t r() const { return m_r; }
        uint8_t g() const { return m_g; }
        uint8_t b() const { return m_b; }
        uint8_t a() const { return m_a; }
        vox_t* _root() const { return m__root; }
        vox_t::rgba_t* _parent() const { return m__parent; }
    };

    class voxel_t : public kaitai::kstruct {

    public:

        voxel_t(kaitai::kstream* p__io, vox_t::xyzi_t* p__parent = 0, vox_t* p__root = 0);

    private:
        void _read();

    public:
        ~voxel_t();

    private:
        uint8_t m_x;
        uint8_t m_y;
        uint8_t m_z;
        uint8_t m_color_index;
        vox_t* m__root;
        vox_t::xyzi_t* m__parent;

    public:
        uint8_t x() const { return m_x; }
        uint8_t y() const { return m_y; }
        uint8_t z() const { return m_z; }
        uint8_t color_index() const { return m_color_index; }
        vox_t* _root() const { return m__root; }
        vox_t::xyzi_t* _parent() const { return m__parent; }
    };

private:
    std::string m_magic;
    uint32_t m_version;
    chunk_t* m_main;
    vox_t* m__root;
    kaitai::kstruct* m__parent;

public:
    std::string magic() const { return m_magic; }

    /**
     * 150 expected
     */
    uint32_t version() const { return m_version; }
    chunk_t* main() const { return m_main; }
    vox_t* _root() const { return m__root; }
    kaitai::kstruct* _parent() const { return m__parent; }
};

#endif  // VOX_H_

vox.cpp

// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild

#include "vox.h"



vox_t::vox_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, vox_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = this;
    _read();
}

void vox_t::_read() {
    m_magic = m__io->ensure_fixed_contents(std::string("\x56\x4F\x58\x20", 4));
    m_version = m__io->read_u4le();
    m_main = new chunk_t(m__io, this, m__root);
}

vox_t::~vox_t() {
    delete m_main;
}

vox_t::chunk_t::chunk_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, vox_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    _read();
}

void vox_t::chunk_t::_read() {
    m_chunk_id = static_cast<vox_t::chunk_type_t>(m__io->read_u4be());
    m_num_bytes_of_chunk_content = m__io->read_u4le();
    m_num_bytes_of_children_chunks = m__io->read_u4le();
    n_chunk_content = true;
    if (num_bytes_of_chunk_content() != 0) {
        n_chunk_content = false;
        n_chunk_content = true;
        switch (chunk_id()) {
        case CHUNK_TYPE_SIZE: {
            n_chunk_content = false;
            m__raw_chunk_content = m__io->read_bytes(num_bytes_of_chunk_content());
            m__io__raw_chunk_content = new kaitai::kstream(m__raw_chunk_content);
            m_chunk_content = new size_t(m__io__raw_chunk_content, this, m__root);
            break;
        }
        case CHUNK_TYPE_MATT: {
            n_chunk_content = false;
            m__raw_chunk_content = m__io->read_bytes(num_bytes_of_chunk_content());
            m__io__raw_chunk_content = new kaitai::kstream(m__raw_chunk_content);
            m_chunk_content = new matt_t(m__io__raw_chunk_content, this, m__root);
            break;
        }
        case CHUNK_TYPE_XYZI: {
            n_chunk_content = false;
            m__raw_chunk_content = m__io->read_bytes(num_bytes_of_chunk_content());
            m__io__raw_chunk_content = new kaitai::kstream(m__raw_chunk_content);
            m_chunk_content = new xyzi_t(m__io__raw_chunk_content, this, m__root);
            break;
        }
        case CHUNK_TYPE_PACK: {
            n_chunk_content = false;
            m__raw_chunk_content = m__io->read_bytes(num_bytes_of_chunk_content());
            m__io__raw_chunk_content = new kaitai::kstream(m__raw_chunk_content);
            m_chunk_content = new pack_t(m__io__raw_chunk_content, this, m__root);
            break;
        }
        case CHUNK_TYPE_RGBA: {
            n_chunk_content = false;
            m__raw_chunk_content = m__io->read_bytes(num_bytes_of_chunk_content());
            m__io__raw_chunk_content = new kaitai::kstream(m__raw_chunk_content);
            m_chunk_content = new rgba_t(m__io__raw_chunk_content, this, m__root);
            break;
        }
        default: {
            m__raw_chunk_content = m__io->read_bytes(num_bytes_of_chunk_content());
            break;
        }
        }
    }
    n_children_chunks = true;
    if (num_bytes_of_children_chunks() != 0) {
        n_children_chunks = false;
        m_children_chunks = new std::vector<chunk_t*>();
        {
            int i = 0;
            while (!m__io->is_eof()) {
                m_children_chunks->push_back(new chunk_t(m__io, this, m__root));
                i++;
            }
        }
    }
}

vox_t::chunk_t::~chunk_t() {
    if (!n_chunk_content) {
        delete m__io__raw_chunk_content;
        delete m_chunk_content;
    }
    if (!n_children_chunks) {
        for (std::vector<chunk_t*>::iterator it = m_children_chunks->begin(); it != m_children_chunks->end(); ++it) {
            delete *it;
        }
        delete m_children_chunks;
    }
}

vox_t::size_t::size_t(kaitai::kstream* p__io, vox_t::chunk_t* p__parent, vox_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    _read();
}

void vox_t::size_t::_read() {
    m_size_x = m__io->read_u4le();
    m_size_y = m__io->read_u4le();
    m_size_z = m__io->read_u4le();
}

vox_t::size_t::~size_t() {
}

vox_t::rgba_t::rgba_t(kaitai::kstream* p__io, vox_t::chunk_t* p__parent, vox_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    _read();
}

void vox_t::rgba_t::_read() {
    int l_colors = 256;
    m_colors = new std::vector<color_t*>();
    m_colors->reserve(l_colors);
    for (int i = 0; i < l_colors; i++) {
        m_colors->push_back(new color_t(m__io, this, m__root));
    }
}

vox_t::rgba_t::~rgba_t() {
    for (std::vector<color_t*>::iterator it = m_colors->begin(); it != m_colors->end(); ++it) {
        delete *it;
    }
    delete m_colors;
}

vox_t::pack_t::pack_t(kaitai::kstream* p__io, vox_t::chunk_t* p__parent, vox_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    _read();
}

void vox_t::pack_t::_read() {
    m_num_models = m__io->read_u4le();
}

vox_t::pack_t::~pack_t() {
}

vox_t::matt_t::matt_t(kaitai::kstream* p__io, vox_t::chunk_t* p__parent, vox_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    f_has_is_total_power = false;
    f_has_plastic = false;
    f_has_attenuation = false;
    f_has_power = false;
    f_has_roughness = false;
    f_has_specular = false;
    f_has_ior = false;
    f_has_glow = false;
    _read();
}

void vox_t::matt_t::_read() {
    m_id = m__io->read_u4le();
    m_material_type = static_cast<vox_t::material_type_t>(m__io->read_u4le());
    m_material_weight = m__io->read_f4le();
    m_property_bits = m__io->read_u4le();
    n_plastic = true;
    if (has_plastic()) {
        n_plastic = false;
        m_plastic = m__io->read_f4le();
    }
    n_roughness = true;
    if (has_roughness()) {
        n_roughness = false;
        m_roughness = m__io->read_f4le();
    }
    n_specular = true;
    if (has_specular()) {
        n_specular = false;
        m_specular = m__io->read_f4le();
    }
    n_ior = true;
    if (has_ior()) {
        n_ior = false;
        m_ior = m__io->read_f4le();
    }
    n_attenuation = true;
    if (has_attenuation()) {
        n_attenuation = false;
        m_attenuation = m__io->read_f4le();
    }
    n_power = true;
    if (has_power()) {
        n_power = false;
        m_power = m__io->read_f4le();
    }
    n_glow = true;
    if (has_glow()) {
        n_glow = false;
        m_glow = m__io->read_f4le();
    }
    n_is_total_power = true;
    if (has_is_total_power()) {
        n_is_total_power = false;
        m_is_total_power = m__io->read_f4le();
    }
}

vox_t::matt_t::~matt_t() {
    if (!n_plastic) {
    }
    if (!n_roughness) {
    }
    if (!n_specular) {
    }
    if (!n_ior) {
    }
    if (!n_attenuation) {
    }
    if (!n_power) {
    }
    if (!n_glow) {
    }
    if (!n_is_total_power) {
    }
}

bool vox_t::matt_t::has_is_total_power() {
    if (f_has_is_total_power)
        return m_has_is_total_power;
    m_has_is_total_power = (property_bits() & 128) != 0;
    f_has_is_total_power = true;
    return m_has_is_total_power;
}

bool vox_t::matt_t::has_plastic() {
    if (f_has_plastic)
        return m_has_plastic;
    m_has_plastic = (property_bits() & 1) != 0;
    f_has_plastic = true;
    return m_has_plastic;
}

bool vox_t::matt_t::has_attenuation() {
    if (f_has_attenuation)
        return m_has_attenuation;
    m_has_attenuation = (property_bits() & 16) != 0;
    f_has_attenuation = true;
    return m_has_attenuation;
}

bool vox_t::matt_t::has_power() {
    if (f_has_power)
        return m_has_power;
    m_has_power = (property_bits() & 32) != 0;
    f_has_power = true;
    return m_has_power;
}

bool vox_t::matt_t::has_roughness() {
    if (f_has_roughness)
        return m_has_roughness;
    m_has_roughness = (property_bits() & 2) != 0;
    f_has_roughness = true;
    return m_has_roughness;
}

bool vox_t::matt_t::has_specular() {
    if (f_has_specular)
        return m_has_specular;
    m_has_specular = (property_bits() & 4) != 0;
    f_has_specular = true;
    return m_has_specular;
}

bool vox_t::matt_t::has_ior() {
    if (f_has_ior)
        return m_has_ior;
    m_has_ior = (property_bits() & 8) != 0;
    f_has_ior = true;
    return m_has_ior;
}

bool vox_t::matt_t::has_glow() {
    if (f_has_glow)
        return m_has_glow;
    m_has_glow = (property_bits() & 64) != 0;
    f_has_glow = true;
    return m_has_glow;
}

vox_t::xyzi_t::xyzi_t(kaitai::kstream* p__io, vox_t::chunk_t* p__parent, vox_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    _read();
}

void vox_t::xyzi_t::_read() {
    m_num_voxels = m__io->read_u4le();
    int l_voxels = num_voxels();
    m_voxels = new std::vector<voxel_t*>();
    m_voxels->reserve(l_voxels);
    for (int i = 0; i < l_voxels; i++) {
        m_voxels->push_back(new voxel_t(m__io, this, m__root));
    }
}

vox_t::xyzi_t::~xyzi_t() {
    for (std::vector<voxel_t*>::iterator it = m_voxels->begin(); it != m_voxels->end(); ++it) {
        delete *it;
    }
    delete m_voxels;
}

vox_t::color_t::color_t(kaitai::kstream* p__io, vox_t::rgba_t* p__parent, vox_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    _read();
}

void vox_t::color_t::_read() {
    m_r = m__io->read_u1();
    m_g = m__io->read_u1();
    m_b = m__io->read_u1();
    m_a = m__io->read_u1();
}

vox_t::color_t::~color_t() {
}

vox_t::voxel_t::voxel_t(kaitai::kstream* p__io, vox_t::xyzi_t* p__parent, vox_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    _read();
}

void vox_t::voxel_t::_read() {
    m_x = m__io->read_u1();
    m_y = m__io->read_u1();
    m_z = m__io->read_u1();
    m_color_index = m__io->read_u1();
}

vox_t::voxel_t::~voxel_t() {
}