Quake 1 (idtech2) model format (MDL version 6): PHP parsing library

Application

Quake 1 (idtech2)

File extension

mdl

KS implementation details

License: CC0-1.0
Minimal Kaitai Struct required: 0.7

This page hosts a formal specification of Quake 1 (idtech2) model format (MDL version 6) using Kaitai Struct. This specification can be automatically translated into a variety of programming languages to get a parsing library.

PHP source code to parse Quake 1 (idtech2) model format (MDL version 6)

QuakeMdl.php

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

class QuakeMdl extends \Kaitai\Struct\Struct {
    public function __construct(\Kaitai\Struct\Stream $_io, \Kaitai\Struct\Struct $_parent = null, \QuakeMdl $_root = null) {
        parent::__construct($_io, $_parent, $_root);
        $this->_read();
    }

    private function _read() {
        $this->_m_header = new \QuakeMdl\MdlHeader($this->_io, $this, $this->_root);
        $this->_m_skins = [];
        $n = $this->header()->numSkins();
        for ($i = 0; $i < $n; $i++) {
            $this->_m_skins[] = new \QuakeMdl\MdlSkin($this->_io, $this, $this->_root);
        }
        $this->_m_textureCoordinates = [];
        $n = $this->header()->numVerts();
        for ($i = 0; $i < $n; $i++) {
            $this->_m_textureCoordinates[] = new \QuakeMdl\MdlTexcoord($this->_io, $this, $this->_root);
        }
        $this->_m_triangles = [];
        $n = $this->header()->numTris();
        for ($i = 0; $i < $n; $i++) {
            $this->_m_triangles[] = new \QuakeMdl\MdlTriangle($this->_io, $this, $this->_root);
        }
        $this->_m_frames = [];
        $n = $this->header()->numFrames();
        for ($i = 0; $i < $n; $i++) {
            $this->_m_frames[] = new \QuakeMdl\MdlFrame($this->_io, $this, $this->_root);
        }
    }
    protected $_m_header;
    protected $_m_skins;
    protected $_m_textureCoordinates;
    protected $_m_triangles;
    protected $_m_frames;
    public function header() { return $this->_m_header; }
    public function skins() { return $this->_m_skins; }
    public function textureCoordinates() { return $this->_m_textureCoordinates; }
    public function triangles() { return $this->_m_triangles; }
    public function frames() { return $this->_m_frames; }
}

namespace \QuakeMdl;

class MdlVertex extends \Kaitai\Struct\Struct {
    public function __construct(\Kaitai\Struct\Stream $_io, \Kaitai\Struct\Struct $_parent = null, \QuakeMdl $_root = null) {
        parent::__construct($_io, $_parent, $_root);
        $this->_read();
    }

    private function _read() {
        $this->_m_values = [];
        $n = 3;
        for ($i = 0; $i < $n; $i++) {
            $this->_m_values[] = $this->_io->readU1();
        }
        $this->_m_normalIndex = $this->_io->readU1();
    }
    protected $_m_values;
    protected $_m_normalIndex;
    public function values() { return $this->_m_values; }
    public function normalIndex() { return $this->_m_normalIndex; }
}

namespace \QuakeMdl;

class MdlTexcoord extends \Kaitai\Struct\Struct {
    public function __construct(\Kaitai\Struct\Stream $_io, \QuakeMdl $_parent = null, \QuakeMdl $_root = null) {
        parent::__construct($_io, $_parent, $_root);
        $this->_read();
    }

    private function _read() {
        $this->_m_onSeam = $this->_io->readS4le();
        $this->_m_s = $this->_io->readS4le();
        $this->_m_t = $this->_io->readS4le();
    }
    protected $_m_onSeam;
    protected $_m_s;
    protected $_m_t;
    public function onSeam() { return $this->_m_onSeam; }
    public function s() { return $this->_m_s; }
    public function t() { return $this->_m_t; }
}

namespace \QuakeMdl;

class MdlHeader extends \Kaitai\Struct\Struct {
    public function __construct(\Kaitai\Struct\Stream $_io, \QuakeMdl $_parent = null, \QuakeMdl $_root = null) {
        parent::__construct($_io, $_parent, $_root);
        $this->_read();
    }

    private function _read() {
        $this->_m_ident = $this->_io->ensureFixedContents("\x49\x44\x50\x4F");
        $this->_m_versionMustBe6 = $this->_io->ensureFixedContents("\x06\x00\x00\x00");
        $this->_m_scale = new \QuakeMdl\Vec3($this->_io, $this, $this->_root);
        $this->_m_origin = new \QuakeMdl\Vec3($this->_io, $this, $this->_root);
        $this->_m_radius = $this->_io->readF4le();
        $this->_m_eyePosition = new \QuakeMdl\Vec3($this->_io, $this, $this->_root);
        $this->_m_numSkins = $this->_io->readS4le();
        $this->_m_skinWidth = $this->_io->readS4le();
        $this->_m_skinHeight = $this->_io->readS4le();
        $this->_m_numVerts = $this->_io->readS4le();
        $this->_m_numTris = $this->_io->readS4le();
        $this->_m_numFrames = $this->_io->readS4le();
        $this->_m_synctype = $this->_io->readS4le();
        $this->_m_flags = $this->_io->readS4le();
        $this->_m_size = $this->_io->readF4le();
    }
    protected $_m_version;
    public function version() {
        if ($this->_m_version !== null)
            return $this->_m_version;
        $this->_m_version = 6;
        return $this->_m_version;
    }
    protected $_m_skinSize;
    public function skinSize() {
        if ($this->_m_skinSize !== null)
            return $this->_m_skinSize;
        $this->_m_skinSize = ($this->skinWidth() * $this->skinHeight());
        return $this->_m_skinSize;
    }
    protected $_m_ident;
    protected $_m_versionMustBe6;
    protected $_m_scale;
    protected $_m_origin;
    protected $_m_radius;
    protected $_m_eyePosition;
    protected $_m_numSkins;
    protected $_m_skinWidth;
    protected $_m_skinHeight;
    protected $_m_numVerts;
    protected $_m_numTris;
    protected $_m_numFrames;
    protected $_m_synctype;
    protected $_m_flags;
    protected $_m_size;
    public function ident() { return $this->_m_ident; }
    public function versionMustBe6() { return $this->_m_versionMustBe6; }
    public function scale() { return $this->_m_scale; }
    public function origin() { return $this->_m_origin; }
    public function radius() { return $this->_m_radius; }
    public function eyePosition() { return $this->_m_eyePosition; }
    public function numSkins() { return $this->_m_numSkins; }
    public function skinWidth() { return $this->_m_skinWidth; }
    public function skinHeight() { return $this->_m_skinHeight; }
    public function numVerts() { return $this->_m_numVerts; }
    public function numTris() { return $this->_m_numTris; }
    public function numFrames() { return $this->_m_numFrames; }
    public function synctype() { return $this->_m_synctype; }
    public function flags() { return $this->_m_flags; }
    public function size() { return $this->_m_size; }
}

namespace \QuakeMdl;

class MdlSkin extends \Kaitai\Struct\Struct {
    public function __construct(\Kaitai\Struct\Stream $_io, \QuakeMdl $_parent = null, \QuakeMdl $_root = null) {
        parent::__construct($_io, $_parent, $_root);
        $this->_read();
    }

    private function _read() {
        $this->_m_group = $this->_io->readS4le();
        if ($this->group() == 0) {
            $this->_m_singleTextureData = $this->_io->readBytes($this->_root()->header()->skinSize());
        }
        if ($this->group() != 0) {
            $this->_m_numFrames = $this->_io->readU4le();
        }
        if ($this->group() != 0) {
            $this->_m_frameTimes = [];
            $n = $this->numFrames();
            for ($i = 0; $i < $n; $i++) {
                $this->_m_frameTimes[] = $this->_io->readF4le();
            }
        }
        if ($this->group() != 0) {
            $this->_m_groupTextureData = [];
            $n = $this->numFrames();
            for ($i = 0; $i < $n; $i++) {
                $this->_m_groupTextureData[] = $this->_io->readBytes($this->_root()->header()->skinSize());
            }
        }
    }
    protected $_m_group;
    protected $_m_singleTextureData;
    protected $_m_numFrames;
    protected $_m_frameTimes;
    protected $_m_groupTextureData;
    public function group() { return $this->_m_group; }
    public function singleTextureData() { return $this->_m_singleTextureData; }
    public function numFrames() { return $this->_m_numFrames; }
    public function frameTimes() { return $this->_m_frameTimes; }
    public function groupTextureData() { return $this->_m_groupTextureData; }
}

namespace \QuakeMdl;

class MdlFrame extends \Kaitai\Struct\Struct {
    public function __construct(\Kaitai\Struct\Stream $_io, \QuakeMdl $_parent = null, \QuakeMdl $_root = null) {
        parent::__construct($_io, $_parent, $_root);
        $this->_read();
    }

    private function _read() {
        $this->_m_type = $this->_io->readS4le();
        if ($this->type() != 0) {
            $this->_m_min = new \QuakeMdl\MdlVertex($this->_io, $this, $this->_root);
        }
        if ($this->type() != 0) {
            $this->_m_max = new \QuakeMdl\MdlVertex($this->_io, $this, $this->_root);
        }
        if ($this->type() != 0) {
            $this->_m_time = [];
            $n = $this->type();
            for ($i = 0; $i < $n; $i++) {
                $this->_m_time[] = $this->_io->readF4le();
            }
        }
        $this->_m_frames = [];
        $n = $this->numSimpleFrames();
        for ($i = 0; $i < $n; $i++) {
            $this->_m_frames[] = new \QuakeMdl\MdlSimpleFrame($this->_io, $this, $this->_root);
        }
    }
    protected $_m_numSimpleFrames;
    public function numSimpleFrames() {
        if ($this->_m_numSimpleFrames !== null)
            return $this->_m_numSimpleFrames;
        $this->_m_numSimpleFrames = ($this->type() == 0 ? 1 : $this->type());
        return $this->_m_numSimpleFrames;
    }
    protected $_m_type;
    protected $_m_min;
    protected $_m_max;
    protected $_m_time;
    protected $_m_frames;
    public function type() { return $this->_m_type; }
    public function min() { return $this->_m_min; }
    public function max() { return $this->_m_max; }
    public function time() { return $this->_m_time; }
    public function frames() { return $this->_m_frames; }
}

namespace \QuakeMdl;

class MdlSimpleFrame extends \Kaitai\Struct\Struct {
    public function __construct(\Kaitai\Struct\Stream $_io, \QuakeMdl\MdlFrame $_parent = null, \QuakeMdl $_root = null) {
        parent::__construct($_io, $_parent, $_root);
        $this->_read();
    }

    private function _read() {
        $this->_m_bboxMin = new \QuakeMdl\MdlVertex($this->_io, $this, $this->_root);
        $this->_m_bboxMax = new \QuakeMdl\MdlVertex($this->_io, $this, $this->_root);
        $this->_m_name = \Kaitai\Struct\Stream::bytesToStr(\Kaitai\Struct\Stream::bytesTerminate(\Kaitai\Struct\Stream::bytesStripRight($this->_io->readBytes(16), 0), 0, false), "ASCII");
        $this->_m_vertices = [];
        $n = $this->_root()->header()->numVerts();
        for ($i = 0; $i < $n; $i++) {
            $this->_m_vertices[] = new \QuakeMdl\MdlVertex($this->_io, $this, $this->_root);
        }
    }
    protected $_m_bboxMin;
    protected $_m_bboxMax;
    protected $_m_name;
    protected $_m_vertices;
    public function bboxMin() { return $this->_m_bboxMin; }
    public function bboxMax() { return $this->_m_bboxMax; }
    public function name() { return $this->_m_name; }
    public function vertices() { return $this->_m_vertices; }
}

namespace \QuakeMdl;

class MdlTriangle extends \Kaitai\Struct\Struct {
    public function __construct(\Kaitai\Struct\Stream $_io, \QuakeMdl $_parent = null, \QuakeMdl $_root = null) {
        parent::__construct($_io, $_parent, $_root);
        $this->_read();
    }

    private function _read() {
        $this->_m_facesFront = $this->_io->readS4le();
        $this->_m_vertices = [];
        $n = 3;
        for ($i = 0; $i < $n; $i++) {
            $this->_m_vertices[] = $this->_io->readS4le();
        }
    }
    protected $_m_facesFront;
    protected $_m_vertices;
    public function facesFront() { return $this->_m_facesFront; }
    public function vertices() { return $this->_m_vertices; }
}

namespace \QuakeMdl;

class Vec3 extends \Kaitai\Struct\Struct {
    public function __construct(\Kaitai\Struct\Stream $_io, \QuakeMdl\MdlHeader $_parent = null, \QuakeMdl $_root = null) {
        parent::__construct($_io, $_parent, $_root);
        $this->_read();
    }

    private function _read() {
        $this->_m_x = $this->_io->readF4le();
        $this->_m_y = $this->_io->readF4le();
        $this->_m_z = $this->_io->readF4le();
    }
    protected $_m_x;
    protected $_m_y;
    protected $_m_z;
    public function x() { return $this->_m_x; }
    public function y() { return $this->_m_y; }
    public function z() { return $this->_m_z; }
}