MagicaVoxel File: C++11/STL parsing library

Application

MagicaVoxel

File extension

vox

KS implementation details

License: MIT
Minimal Kaitai Struct required: 0.9

References

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

Runtime library

All parsing code for C++11/STL generated by Kaitai Struct depends on the C++/STL runtime library. You have to install it before you can parse data.

For C++, the easiest way is to clone the runtime library sources and build them along with your project.

Code

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 local file for that, or use existing std::string or char* buffer.
    #include <fstream>
    
    std::ifstream is("path/to/local/file.vox", std::ifstream::binary);
    
    #include <sstream>
    
    std::istringstream is(str);
    
    #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:
    magicavoxel_vox_t data(&ks);
    

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

data.version() // => 150 expected

C++11/STL source code to parse MagicaVoxel File

magicavoxel_vox.h

#pragma once

// 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 <memory>
#include <vector>

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

/**
 * \sa https://ephtracy.github.io/ MagicaVoxel Homepage
 * \sa https://github.com/ephtracy/voxel-model/blob/master/MagicaVoxel-file-format-vox.txt Format Description
 */

class magicavoxel_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
    };

    magicavoxel_vox_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = nullptr, magicavoxel_vox_t* p__root = nullptr);

private:
    void _read();
    void _clean_up();

public:
    ~magicavoxel_vox_t();

    class chunk_t : public kaitai::kstruct {

    public:

        chunk_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = nullptr, magicavoxel_vox_t* p__root = nullptr);

    private:
        void _read();
        void _clean_up();

    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;
        std::unique_ptr<kaitai::kstruct> m_chunk_content;
        bool n_chunk_content;

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

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

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

    private:
        magicavoxel_vox_t* m__root;
        kaitai::kstruct* m__parent;
        std::string m__raw_chunk_content;
        bool n__raw_chunk_content;

    public:
        bool _is_null__raw_chunk_content() { _raw_chunk_content(); return n__raw_chunk_content; };

    private:
        std::unique_ptr<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.get(); }
        std::vector<std::unique_ptr<chunk_t>>* children_chunks() const { return m_children_chunks.get(); }
        magicavoxel_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.get(); }
    };

    class size_t : public kaitai::kstruct {

    public:

        size_t(kaitai::kstream* p__io, magicavoxel_vox_t::chunk_t* p__parent = nullptr, magicavoxel_vox_t* p__root = nullptr);

    private:
        void _read();
        void _clean_up();

    public:
        ~size_t();

    private:
        uint32_t m_size_x;
        uint32_t m_size_y;
        uint32_t m_size_z;
        magicavoxel_vox_t* m__root;
        magicavoxel_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; }
        magicavoxel_vox_t* _root() const { return m__root; }
        magicavoxel_vox_t::chunk_t* _parent() const { return m__parent; }
    };

    class rgba_t : public kaitai::kstruct {

    public:

        rgba_t(kaitai::kstream* p__io, magicavoxel_vox_t::chunk_t* p__parent = nullptr, magicavoxel_vox_t* p__root = nullptr);

    private:
        void _read();
        void _clean_up();

    public:
        ~rgba_t();

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

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

    class pack_t : public kaitai::kstruct {

    public:

        pack_t(kaitai::kstream* p__io, magicavoxel_vox_t::chunk_t* p__parent = nullptr, magicavoxel_vox_t* p__root = nullptr);

    private:
        void _read();
        void _clean_up();

    public:
        ~pack_t();

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

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

    class matt_t : public kaitai::kstruct {

    public:

        matt_t(kaitai::kstream* p__io, magicavoxel_vox_t::chunk_t* p__parent = nullptr, magicavoxel_vox_t* p__root = nullptr);

    private:
        void _read();
        void _clean_up();

    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:
        magicavoxel_vox_t* m__root;
        magicavoxel_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; }
        magicavoxel_vox_t* _root() const { return m__root; }
        magicavoxel_vox_t::chunk_t* _parent() const { return m__parent; }
    };

    class xyzi_t : public kaitai::kstruct {

    public:

        xyzi_t(kaitai::kstream* p__io, magicavoxel_vox_t::chunk_t* p__parent = nullptr, magicavoxel_vox_t* p__root = nullptr);

    private:
        void _read();
        void _clean_up();

    public:
        ~xyzi_t();

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

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

    class color_t : public kaitai::kstruct {

    public:

        color_t(kaitai::kstream* p__io, magicavoxel_vox_t::rgba_t* p__parent = nullptr, magicavoxel_vox_t* p__root = nullptr);

    private:
        void _read();
        void _clean_up();

    public:
        ~color_t();

    private:
        uint8_t m_r;
        uint8_t m_g;
        uint8_t m_b;
        uint8_t m_a;
        magicavoxel_vox_t* m__root;
        magicavoxel_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; }
        magicavoxel_vox_t* _root() const { return m__root; }
        magicavoxel_vox_t::rgba_t* _parent() const { return m__parent; }
    };

    class voxel_t : public kaitai::kstruct {

    public:

        voxel_t(kaitai::kstream* p__io, magicavoxel_vox_t::xyzi_t* p__parent = nullptr, magicavoxel_vox_t* p__root = nullptr);

    private:
        void _read();
        void _clean_up();

    public:
        ~voxel_t();

    private:
        uint8_t m_x;
        uint8_t m_y;
        uint8_t m_z;
        uint8_t m_color_index;
        magicavoxel_vox_t* m__root;
        magicavoxel_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; }
        magicavoxel_vox_t* _root() const { return m__root; }
        magicavoxel_vox_t::xyzi_t* _parent() const { return m__parent; }
    };

private:
    std::string m_magic;
    uint32_t m_version;
    std::unique_ptr<chunk_t> m_main;
    magicavoxel_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.get(); }
    magicavoxel_vox_t* _root() const { return m__root; }
    kaitai::kstruct* _parent() const { return m__parent; }
};

magicavoxel_vox.cpp

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

#include "magicavoxel_vox.h"
#include "kaitai/exceptions.h"

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

void magicavoxel_vox_t::_read() {
    m_magic = m__io->read_bytes(4);
    if (!(magic() == std::string("\x56\x4F\x58\x20", 4))) {
        throw kaitai::validation_not_equal_error<std::string>(std::string("\x56\x4F\x58\x20", 4), magic(), _io(), std::string("/seq/0"));
    }
    m_version = m__io->read_u4le();
    m_main = std::unique_ptr<chunk_t>(new chunk_t(m__io, this, m__root));
}

magicavoxel_vox_t::~magicavoxel_vox_t() {
    _clean_up();
}

void magicavoxel_vox_t::_clean_up() {
}

magicavoxel_vox_t::chunk_t::chunk_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, magicavoxel_vox_t* p__root) : kaitai::kstruct(p__io) {
    m__parent = p__parent;
    m__root = p__root;
    m__io__raw_chunk_content = nullptr;
    m_children_chunks = nullptr;
    _read();
}

void magicavoxel_vox_t::chunk_t::_read() {
    m_chunk_id = static_cast<magicavoxel_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 magicavoxel_vox_t::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 = std::unique_ptr<kaitai::kstream>(new kaitai::kstream(m__raw_chunk_content));
            m_chunk_content = std::unique_ptr<size_t>(new size_t(m__io__raw_chunk_content.get(), this, m__root));
            break;
        }
        case magicavoxel_vox_t::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 = std::unique_ptr<kaitai::kstream>(new kaitai::kstream(m__raw_chunk_content));
            m_chunk_content = std::unique_ptr<matt_t>(new matt_t(m__io__raw_chunk_content.get(), this, m__root));
            break;
        }
        case magicavoxel_vox_t::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 = std::unique_ptr<kaitai::kstream>(new kaitai::kstream(m__raw_chunk_content));
            m_chunk_content = std::unique_ptr<rgba_t>(new rgba_t(m__io__raw_chunk_content.get(), this, m__root));
            break;
        }
        case magicavoxel_vox_t::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 = std::unique_ptr<kaitai::kstream>(new kaitai::kstream(m__raw_chunk_content));
            m_chunk_content = std::unique_ptr<xyzi_t>(new xyzi_t(m__io__raw_chunk_content.get(), this, m__root));
            break;
        }
        case magicavoxel_vox_t::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 = std::unique_ptr<kaitai::kstream>(new kaitai::kstream(m__raw_chunk_content));
            m_chunk_content = std::unique_ptr<pack_t>(new pack_t(m__io__raw_chunk_content.get(), 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 = std::unique_ptr<std::vector<std::unique_ptr<chunk_t>>>(new std::vector<std::unique_ptr<chunk_t>>());
        {
            int i = 0;
            while (!m__io->is_eof()) {
                m_children_chunks->push_back(std::move(std::unique_ptr<chunk_t>(new chunk_t(m__io, this, m__root))));
                i++;
            }
        }
    }
}

magicavoxel_vox_t::chunk_t::~chunk_t() {
    _clean_up();
}

void magicavoxel_vox_t::chunk_t::_clean_up() {
    if (!n_chunk_content) {
    }
    if (!n_children_chunks) {
    }
}

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

void magicavoxel_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();
}

magicavoxel_vox_t::size_t::~size_t() {
    _clean_up();
}

void magicavoxel_vox_t::size_t::_clean_up() {
}

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

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

magicavoxel_vox_t::rgba_t::~rgba_t() {
    _clean_up();
}

void magicavoxel_vox_t::rgba_t::_clean_up() {
}

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

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

magicavoxel_vox_t::pack_t::~pack_t() {
    _clean_up();
}

void magicavoxel_vox_t::pack_t::_clean_up() {
}

magicavoxel_vox_t::matt_t::matt_t(kaitai::kstream* p__io, magicavoxel_vox_t::chunk_t* p__parent, magicavoxel_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 magicavoxel_vox_t::matt_t::_read() {
    m_id = m__io->read_u4le();
    m_material_type = static_cast<magicavoxel_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();
    }
}

magicavoxel_vox_t::matt_t::~matt_t() {
    _clean_up();
}

void magicavoxel_vox_t::matt_t::_clean_up() {
    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 magicavoxel_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 magicavoxel_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 magicavoxel_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 magicavoxel_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 magicavoxel_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 magicavoxel_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 magicavoxel_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 magicavoxel_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;
}

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

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

magicavoxel_vox_t::xyzi_t::~xyzi_t() {
    _clean_up();
}

void magicavoxel_vox_t::xyzi_t::_clean_up() {
}

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

void magicavoxel_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();
}

magicavoxel_vox_t::color_t::~color_t() {
    _clean_up();
}

void magicavoxel_vox_t::color_t::_clean_up() {
}

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

void magicavoxel_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();
}

magicavoxel_vox_t::voxel_t::~voxel_t() {
    _clean_up();
}

void magicavoxel_vox_t::voxel_t::_clean_up() {
}