MagicaVoxel File: Perl 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.

Perl source code to parse MagicaVoxel File

MagicavoxelVox.pm

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

use strict;
use warnings;
use IO::KaitaiStruct 0.009_000;

########################################################################
package MagicavoxelVox;

our @ISA = 'IO::KaitaiStruct::Struct';

sub from_file {
    my ($class, $filename) = @_;
    my $fd;

    open($fd, '<', $filename) or return undef;
    binmode($fd);
    return new($class, IO::KaitaiStruct::Stream->new($fd));
}

our $CHUNK_TYPE_MAIN = 1296124238;
our $CHUNK_TYPE_MATT = 1296127060;
our $CHUNK_TYPE_PACK = 1346454347;
our $CHUNK_TYPE_RGBA = 1380401729;
our $CHUNK_TYPE_SIZE = 1397316165;
our $CHUNK_TYPE_XYZI = 1482250825;

our $MATERIAL_TYPE_DIFFUSE = 0;
our $MATERIAL_TYPE_METAL = 1;
our $MATERIAL_TYPE_GLASS = 2;
our $MATERIAL_TYPE_EMISSIVE = 3;

our $PROPERTY_BITS_TYPE_PLASTIC = 1;
our $PROPERTY_BITS_TYPE_ROUGHNESS = 2;
our $PROPERTY_BITS_TYPE_SPECULAR = 4;
our $PROPERTY_BITS_TYPE_IOR = 8;
our $PROPERTY_BITS_TYPE_ATTENUATION = 16;
our $PROPERTY_BITS_TYPE_POWER = 32;
our $PROPERTY_BITS_TYPE_GLOW = 64;
our $PROPERTY_BITS_TYPE_IS_TOTAL_POWER = 128;

sub new {
    my ($class, $_io, $_parent, $_root) = @_;
    my $self = IO::KaitaiStruct::Struct->new($_io);

    bless $self, $class;
    $self->{_parent} = $_parent;
    $self->{_root} = $_root || $self;;

    $self->_read();

    return $self;
}

sub _read {
    my ($self) = @_;

    $self->{magic} = $self->{_io}->read_bytes(4);
    $self->{version} = $self->{_io}->read_u4le();
    $self->{main} = MagicavoxelVox::Chunk->new($self->{_io}, $self, $self->{_root});
}

sub magic {
    my ($self) = @_;
    return $self->{magic};
}

sub version {
    my ($self) = @_;
    return $self->{version};
}

sub main {
    my ($self) = @_;
    return $self->{main};
}

########################################################################
package MagicavoxelVox::Chunk;

our @ISA = 'IO::KaitaiStruct::Struct';

sub from_file {
    my ($class, $filename) = @_;
    my $fd;

    open($fd, '<', $filename) or return undef;
    binmode($fd);
    return new($class, IO::KaitaiStruct::Stream->new($fd));
}

sub new {
    my ($class, $_io, $_parent, $_root) = @_;
    my $self = IO::KaitaiStruct::Struct->new($_io);

    bless $self, $class;
    $self->{_parent} = $_parent;
    $self->{_root} = $_root || $self;;

    $self->_read();

    return $self;
}

sub _read {
    my ($self) = @_;

    $self->{chunk_id} = $self->{_io}->read_u4be();
    $self->{num_bytes_of_chunk_content} = $self->{_io}->read_u4le();
    $self->{num_bytes_of_children_chunks} = $self->{_io}->read_u4le();
    if ($self->num_bytes_of_chunk_content() != 0) {
        my $_on = $self->chunk_id();
        if ($_on == $MagicavoxelVox::CHUNK_TYPE_SIZE) {
            $self->{_raw_chunk_content} = $self->{_io}->read_bytes($self->num_bytes_of_chunk_content());
            my $io__raw_chunk_content = IO::KaitaiStruct::Stream->new($self->{_raw_chunk_content});
            $self->{chunk_content} = MagicavoxelVox::Size->new($io__raw_chunk_content, $self, $self->{_root});
        }
        elsif ($_on == $MagicavoxelVox::CHUNK_TYPE_MATT) {
            $self->{_raw_chunk_content} = $self->{_io}->read_bytes($self->num_bytes_of_chunk_content());
            my $io__raw_chunk_content = IO::KaitaiStruct::Stream->new($self->{_raw_chunk_content});
            $self->{chunk_content} = MagicavoxelVox::Matt->new($io__raw_chunk_content, $self, $self->{_root});
        }
        elsif ($_on == $MagicavoxelVox::CHUNK_TYPE_RGBA) {
            $self->{_raw_chunk_content} = $self->{_io}->read_bytes($self->num_bytes_of_chunk_content());
            my $io__raw_chunk_content = IO::KaitaiStruct::Stream->new($self->{_raw_chunk_content});
            $self->{chunk_content} = MagicavoxelVox::Rgba->new($io__raw_chunk_content, $self, $self->{_root});
        }
        elsif ($_on == $MagicavoxelVox::CHUNK_TYPE_XYZI) {
            $self->{_raw_chunk_content} = $self->{_io}->read_bytes($self->num_bytes_of_chunk_content());
            my $io__raw_chunk_content = IO::KaitaiStruct::Stream->new($self->{_raw_chunk_content});
            $self->{chunk_content} = MagicavoxelVox::Xyzi->new($io__raw_chunk_content, $self, $self->{_root});
        }
        elsif ($_on == $MagicavoxelVox::CHUNK_TYPE_PACK) {
            $self->{_raw_chunk_content} = $self->{_io}->read_bytes($self->num_bytes_of_chunk_content());
            my $io__raw_chunk_content = IO::KaitaiStruct::Stream->new($self->{_raw_chunk_content});
            $self->{chunk_content} = MagicavoxelVox::Pack->new($io__raw_chunk_content, $self, $self->{_root});
        }
        else {
            $self->{chunk_content} = $self->{_io}->read_bytes($self->num_bytes_of_chunk_content());
        }
    }
    if ($self->num_bytes_of_children_chunks() != 0) {
        $self->{children_chunks} = ();
        while (!$self->{_io}->is_eof()) {
            push @{$self->{children_chunks}}, MagicavoxelVox::Chunk->new($self->{_io}, $self, $self->{_root});
        }
    }
}

sub chunk_id {
    my ($self) = @_;
    return $self->{chunk_id};
}

sub num_bytes_of_chunk_content {
    my ($self) = @_;
    return $self->{num_bytes_of_chunk_content};
}

sub num_bytes_of_children_chunks {
    my ($self) = @_;
    return $self->{num_bytes_of_children_chunks};
}

sub chunk_content {
    my ($self) = @_;
    return $self->{chunk_content};
}

sub children_chunks {
    my ($self) = @_;
    return $self->{children_chunks};
}

sub _raw_chunk_content {
    my ($self) = @_;
    return $self->{_raw_chunk_content};
}

########################################################################
package MagicavoxelVox::Size;

our @ISA = 'IO::KaitaiStruct::Struct';

sub from_file {
    my ($class, $filename) = @_;
    my $fd;

    open($fd, '<', $filename) or return undef;
    binmode($fd);
    return new($class, IO::KaitaiStruct::Stream->new($fd));
}

sub new {
    my ($class, $_io, $_parent, $_root) = @_;
    my $self = IO::KaitaiStruct::Struct->new($_io);

    bless $self, $class;
    $self->{_parent} = $_parent;
    $self->{_root} = $_root || $self;;

    $self->_read();

    return $self;
}

sub _read {
    my ($self) = @_;

    $self->{size_x} = $self->{_io}->read_u4le();
    $self->{size_y} = $self->{_io}->read_u4le();
    $self->{size_z} = $self->{_io}->read_u4le();
}

sub size_x {
    my ($self) = @_;
    return $self->{size_x};
}

sub size_y {
    my ($self) = @_;
    return $self->{size_y};
}

sub size_z {
    my ($self) = @_;
    return $self->{size_z};
}

########################################################################
package MagicavoxelVox::Rgba;

our @ISA = 'IO::KaitaiStruct::Struct';

sub from_file {
    my ($class, $filename) = @_;
    my $fd;

    open($fd, '<', $filename) or return undef;
    binmode($fd);
    return new($class, IO::KaitaiStruct::Stream->new($fd));
}

sub new {
    my ($class, $_io, $_parent, $_root) = @_;
    my $self = IO::KaitaiStruct::Struct->new($_io);

    bless $self, $class;
    $self->{_parent} = $_parent;
    $self->{_root} = $_root || $self;;

    $self->_read();

    return $self;
}

sub _read {
    my ($self) = @_;

    $self->{colors} = ();
    my $n_colors = 256;
    for (my $i = 0; $i < $n_colors; $i++) {
        push @{$self->{colors}}, MagicavoxelVox::Color->new($self->{_io}, $self, $self->{_root});
    }
}

sub colors {
    my ($self) = @_;
    return $self->{colors};
}

########################################################################
package MagicavoxelVox::Pack;

our @ISA = 'IO::KaitaiStruct::Struct';

sub from_file {
    my ($class, $filename) = @_;
    my $fd;

    open($fd, '<', $filename) or return undef;
    binmode($fd);
    return new($class, IO::KaitaiStruct::Stream->new($fd));
}

sub new {
    my ($class, $_io, $_parent, $_root) = @_;
    my $self = IO::KaitaiStruct::Struct->new($_io);

    bless $self, $class;
    $self->{_parent} = $_parent;
    $self->{_root} = $_root || $self;;

    $self->_read();

    return $self;
}

sub _read {
    my ($self) = @_;

    $self->{num_models} = $self->{_io}->read_u4le();
}

sub num_models {
    my ($self) = @_;
    return $self->{num_models};
}

########################################################################
package MagicavoxelVox::Matt;

our @ISA = 'IO::KaitaiStruct::Struct';

sub from_file {
    my ($class, $filename) = @_;
    my $fd;

    open($fd, '<', $filename) or return undef;
    binmode($fd);
    return new($class, IO::KaitaiStruct::Stream->new($fd));
}

sub new {
    my ($class, $_io, $_parent, $_root) = @_;
    my $self = IO::KaitaiStruct::Struct->new($_io);

    bless $self, $class;
    $self->{_parent} = $_parent;
    $self->{_root} = $_root || $self;;

    $self->_read();

    return $self;
}

sub _read {
    my ($self) = @_;

    $self->{id} = $self->{_io}->read_u4le();
    $self->{material_type} = $self->{_io}->read_u4le();
    $self->{material_weight} = $self->{_io}->read_f4le();
    $self->{property_bits} = $self->{_io}->read_u4le();
    if ($self->has_plastic()) {
        $self->{plastic} = $self->{_io}->read_f4le();
    }
    if ($self->has_roughness()) {
        $self->{roughness} = $self->{_io}->read_f4le();
    }
    if ($self->has_specular()) {
        $self->{specular} = $self->{_io}->read_f4le();
    }
    if ($self->has_ior()) {
        $self->{ior} = $self->{_io}->read_f4le();
    }
    if ($self->has_attenuation()) {
        $self->{attenuation} = $self->{_io}->read_f4le();
    }
    if ($self->has_power()) {
        $self->{power} = $self->{_io}->read_f4le();
    }
    if ($self->has_glow()) {
        $self->{glow} = $self->{_io}->read_f4le();
    }
    if ($self->has_is_total_power()) {
        $self->{is_total_power} = $self->{_io}->read_f4le();
    }
}

sub has_is_total_power {
    my ($self) = @_;
    return $self->{has_is_total_power} if ($self->{has_is_total_power});
    $self->{has_is_total_power} = ($self->property_bits() & 128) != 0;
    return $self->{has_is_total_power};
}

sub has_plastic {
    my ($self) = @_;
    return $self->{has_plastic} if ($self->{has_plastic});
    $self->{has_plastic} = ($self->property_bits() & 1) != 0;
    return $self->{has_plastic};
}

sub has_attenuation {
    my ($self) = @_;
    return $self->{has_attenuation} if ($self->{has_attenuation});
    $self->{has_attenuation} = ($self->property_bits() & 16) != 0;
    return $self->{has_attenuation};
}

sub has_power {
    my ($self) = @_;
    return $self->{has_power} if ($self->{has_power});
    $self->{has_power} = ($self->property_bits() & 32) != 0;
    return $self->{has_power};
}

sub has_roughness {
    my ($self) = @_;
    return $self->{has_roughness} if ($self->{has_roughness});
    $self->{has_roughness} = ($self->property_bits() & 2) != 0;
    return $self->{has_roughness};
}

sub has_specular {
    my ($self) = @_;
    return $self->{has_specular} if ($self->{has_specular});
    $self->{has_specular} = ($self->property_bits() & 4) != 0;
    return $self->{has_specular};
}

sub has_ior {
    my ($self) = @_;
    return $self->{has_ior} if ($self->{has_ior});
    $self->{has_ior} = ($self->property_bits() & 8) != 0;
    return $self->{has_ior};
}

sub has_glow {
    my ($self) = @_;
    return $self->{has_glow} if ($self->{has_glow});
    $self->{has_glow} = ($self->property_bits() & 64) != 0;
    return $self->{has_glow};
}

sub id {
    my ($self) = @_;
    return $self->{id};
}

sub material_type {
    my ($self) = @_;
    return $self->{material_type};
}

sub material_weight {
    my ($self) = @_;
    return $self->{material_weight};
}

sub property_bits {
    my ($self) = @_;
    return $self->{property_bits};
}

sub plastic {
    my ($self) = @_;
    return $self->{plastic};
}

sub roughness {
    my ($self) = @_;
    return $self->{roughness};
}

sub specular {
    my ($self) = @_;
    return $self->{specular};
}

sub ior {
    my ($self) = @_;
    return $self->{ior};
}

sub attenuation {
    my ($self) = @_;
    return $self->{attenuation};
}

sub power {
    my ($self) = @_;
    return $self->{power};
}

sub glow {
    my ($self) = @_;
    return $self->{glow};
}

sub is_total_power {
    my ($self) = @_;
    return $self->{is_total_power};
}

########################################################################
package MagicavoxelVox::Xyzi;

our @ISA = 'IO::KaitaiStruct::Struct';

sub from_file {
    my ($class, $filename) = @_;
    my $fd;

    open($fd, '<', $filename) or return undef;
    binmode($fd);
    return new($class, IO::KaitaiStruct::Stream->new($fd));
}

sub new {
    my ($class, $_io, $_parent, $_root) = @_;
    my $self = IO::KaitaiStruct::Struct->new($_io);

    bless $self, $class;
    $self->{_parent} = $_parent;
    $self->{_root} = $_root || $self;;

    $self->_read();

    return $self;
}

sub _read {
    my ($self) = @_;

    $self->{num_voxels} = $self->{_io}->read_u4le();
    $self->{voxels} = ();
    my $n_voxels = $self->num_voxels();
    for (my $i = 0; $i < $n_voxels; $i++) {
        push @{$self->{voxels}}, MagicavoxelVox::Voxel->new($self->{_io}, $self, $self->{_root});
    }
}

sub num_voxels {
    my ($self) = @_;
    return $self->{num_voxels};
}

sub voxels {
    my ($self) = @_;
    return $self->{voxels};
}

########################################################################
package MagicavoxelVox::Color;

our @ISA = 'IO::KaitaiStruct::Struct';

sub from_file {
    my ($class, $filename) = @_;
    my $fd;

    open($fd, '<', $filename) or return undef;
    binmode($fd);
    return new($class, IO::KaitaiStruct::Stream->new($fd));
}

sub new {
    my ($class, $_io, $_parent, $_root) = @_;
    my $self = IO::KaitaiStruct::Struct->new($_io);

    bless $self, $class;
    $self->{_parent} = $_parent;
    $self->{_root} = $_root || $self;;

    $self->_read();

    return $self;
}

sub _read {
    my ($self) = @_;

    $self->{r} = $self->{_io}->read_u1();
    $self->{g} = $self->{_io}->read_u1();
    $self->{b} = $self->{_io}->read_u1();
    $self->{a} = $self->{_io}->read_u1();
}

sub r {
    my ($self) = @_;
    return $self->{r};
}

sub g {
    my ($self) = @_;
    return $self->{g};
}

sub b {
    my ($self) = @_;
    return $self->{b};
}

sub a {
    my ($self) = @_;
    return $self->{a};
}

########################################################################
package MagicavoxelVox::Voxel;

our @ISA = 'IO::KaitaiStruct::Struct';

sub from_file {
    my ($class, $filename) = @_;
    my $fd;

    open($fd, '<', $filename) or return undef;
    binmode($fd);
    return new($class, IO::KaitaiStruct::Stream->new($fd));
}

sub new {
    my ($class, $_io, $_parent, $_root) = @_;
    my $self = IO::KaitaiStruct::Struct->new($_io);

    bless $self, $class;
    $self->{_parent} = $_parent;
    $self->{_root} = $_root || $self;;

    $self->_read();

    return $self;
}

sub _read {
    my ($self) = @_;

    $self->{x} = $self->{_io}->read_u1();
    $self->{y} = $self->{_io}->read_u1();
    $self->{z} = $self->{_io}->read_u1();
    $self->{color_index} = $self->{_io}->read_u1();
}

sub x {
    my ($self) = @_;
    return $self->{x};
}

sub y {
    my ($self) = @_;
    return $self->{y};
}

sub z {
    my ($self) = @_;
    return $self->{z};
}

sub color_index {
    my ($self) = @_;
    return $self->{color_index};
}

1;