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.
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.
Using Kaitai Struct in C++/STL usually consists of 3 steps.
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.mdl", std::ifstream::binary);
#include <sstream>
std::istringstream is(str);
#include <sstream>
const char buf[] = { ... };
std::string str(buf, sizeof buf);
std::istringstream is(str);
#include "kaitai/kaitaistream.h"
kaitai::kstream ks(&is);
quake_mdl_t data(&ks);
After that, one can get various attributes from the structure by invoking getter methods like:
data.header() // => get header
#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
class quake_mdl_t : public kaitai::kstruct {
public:
class mdl_vertex_t;
class mdl_texcoord_t;
class mdl_header_t;
class mdl_skin_t;
class mdl_frame_t;
class mdl_simple_frame_t;
class mdl_triangle_t;
class vec3_t;
quake_mdl_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = nullptr, quake_mdl_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~quake_mdl_t();
class mdl_vertex_t : public kaitai::kstruct {
public:
mdl_vertex_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent = nullptr, quake_mdl_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~mdl_vertex_t();
private:
std::unique_ptr<std::vector<uint8_t>> m_values;
uint8_t m_normal_index;
quake_mdl_t* m__root;
kaitai::kstruct* m__parent;
public:
std::vector<uint8_t>* values() const { return m_values.get(); }
uint8_t normal_index() const { return m_normal_index; }
quake_mdl_t* _root() const { return m__root; }
kaitai::kstruct* _parent() const { return m__parent; }
};
class mdl_texcoord_t : public kaitai::kstruct {
public:
mdl_texcoord_t(kaitai::kstream* p__io, quake_mdl_t* p__parent = nullptr, quake_mdl_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~mdl_texcoord_t();
private:
int32_t m_on_seam;
int32_t m_s;
int32_t m_t;
quake_mdl_t* m__root;
quake_mdl_t* m__parent;
public:
int32_t on_seam() const { return m_on_seam; }
int32_t s() const { return m_s; }
int32_t t() const { return m_t; }
quake_mdl_t* _root() const { return m__root; }
quake_mdl_t* _parent() const { return m__parent; }
};
class mdl_header_t : public kaitai::kstruct {
public:
mdl_header_t(kaitai::kstream* p__io, quake_mdl_t* p__parent = nullptr, quake_mdl_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~mdl_header_t();
private:
bool f_version;
int8_t m_version;
public:
int8_t version();
private:
bool f_skin_size;
int32_t m_skin_size;
public:
int32_t skin_size();
private:
std::string m_ident;
std::string m_version_must_be_6;
std::unique_ptr<vec3_t> m_scale;
std::unique_ptr<vec3_t> m_origin;
float m_radius;
std::unique_ptr<vec3_t> m_eye_position;
int32_t m_num_skins;
int32_t m_skin_width;
int32_t m_skin_height;
int32_t m_num_verts;
int32_t m_num_tris;
int32_t m_num_frames;
int32_t m_synctype;
int32_t m_flags;
float m_size;
quake_mdl_t* m__root;
quake_mdl_t* m__parent;
public:
std::string ident() const { return m_ident; }
std::string version_must_be_6() const { return m_version_must_be_6; }
vec3_t* scale() const { return m_scale.get(); }
vec3_t* origin() const { return m_origin.get(); }
float radius() const { return m_radius; }
vec3_t* eye_position() const { return m_eye_position.get(); }
int32_t num_skins() const { return m_num_skins; }
int32_t skin_width() const { return m_skin_width; }
int32_t skin_height() const { return m_skin_height; }
int32_t num_verts() const { return m_num_verts; }
int32_t num_tris() const { return m_num_tris; }
int32_t num_frames() const { return m_num_frames; }
int32_t synctype() const { return m_synctype; }
int32_t flags() const { return m_flags; }
float size() const { return m_size; }
quake_mdl_t* _root() const { return m__root; }
quake_mdl_t* _parent() const { return m__parent; }
};
class mdl_skin_t : public kaitai::kstruct {
public:
mdl_skin_t(kaitai::kstream* p__io, quake_mdl_t* p__parent = nullptr, quake_mdl_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~mdl_skin_t();
private:
int32_t m_group;
std::string m_single_texture_data;
bool n_single_texture_data;
public:
bool _is_null_single_texture_data() { single_texture_data(); return n_single_texture_data; };
private:
uint32_t m_num_frames;
bool n_num_frames;
public:
bool _is_null_num_frames() { num_frames(); return n_num_frames; };
private:
std::unique_ptr<std::vector<float>> m_frame_times;
bool n_frame_times;
public:
bool _is_null_frame_times() { frame_times(); return n_frame_times; };
private:
std::unique_ptr<std::vector<std::string>> m_group_texture_data;
bool n_group_texture_data;
public:
bool _is_null_group_texture_data() { group_texture_data(); return n_group_texture_data; };
private:
quake_mdl_t* m__root;
quake_mdl_t* m__parent;
public:
int32_t group() const { return m_group; }
std::string single_texture_data() const { return m_single_texture_data; }
uint32_t num_frames() const { return m_num_frames; }
std::vector<float>* frame_times() const { return m_frame_times.get(); }
std::vector<std::string>* group_texture_data() const { return m_group_texture_data.get(); }
quake_mdl_t* _root() const { return m__root; }
quake_mdl_t* _parent() const { return m__parent; }
};
class mdl_frame_t : public kaitai::kstruct {
public:
mdl_frame_t(kaitai::kstream* p__io, quake_mdl_t* p__parent = nullptr, quake_mdl_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~mdl_frame_t();
private:
bool f_num_simple_frames;
int32_t m_num_simple_frames;
public:
int32_t num_simple_frames();
private:
int32_t m_type;
std::unique_ptr<mdl_vertex_t> m_min;
bool n_min;
public:
bool _is_null_min() { min(); return n_min; };
private:
std::unique_ptr<mdl_vertex_t> m_max;
bool n_max;
public:
bool _is_null_max() { max(); return n_max; };
private:
std::unique_ptr<std::vector<float>> m_time;
bool n_time;
public:
bool _is_null_time() { time(); return n_time; };
private:
std::unique_ptr<std::vector<std::unique_ptr<mdl_simple_frame_t>>> m_frames;
quake_mdl_t* m__root;
quake_mdl_t* m__parent;
public:
int32_t type() const { return m_type; }
mdl_vertex_t* min() const { return m_min.get(); }
mdl_vertex_t* max() const { return m_max.get(); }
std::vector<float>* time() const { return m_time.get(); }
std::vector<std::unique_ptr<mdl_simple_frame_t>>* frames() const { return m_frames.get(); }
quake_mdl_t* _root() const { return m__root; }
quake_mdl_t* _parent() const { return m__parent; }
};
class mdl_simple_frame_t : public kaitai::kstruct {
public:
mdl_simple_frame_t(kaitai::kstream* p__io, quake_mdl_t::mdl_frame_t* p__parent = nullptr, quake_mdl_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~mdl_simple_frame_t();
private:
std::unique_ptr<mdl_vertex_t> m_bbox_min;
std::unique_ptr<mdl_vertex_t> m_bbox_max;
std::string m_name;
std::unique_ptr<std::vector<std::unique_ptr<mdl_vertex_t>>> m_vertices;
quake_mdl_t* m__root;
quake_mdl_t::mdl_frame_t* m__parent;
public:
mdl_vertex_t* bbox_min() const { return m_bbox_min.get(); }
mdl_vertex_t* bbox_max() const { return m_bbox_max.get(); }
std::string name() const { return m_name; }
std::vector<std::unique_ptr<mdl_vertex_t>>* vertices() const { return m_vertices.get(); }
quake_mdl_t* _root() const { return m__root; }
quake_mdl_t::mdl_frame_t* _parent() const { return m__parent; }
};
class mdl_triangle_t : public kaitai::kstruct {
public:
mdl_triangle_t(kaitai::kstream* p__io, quake_mdl_t* p__parent = nullptr, quake_mdl_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~mdl_triangle_t();
private:
int32_t m_faces_front;
std::unique_ptr<std::vector<int32_t>> m_vertices;
quake_mdl_t* m__root;
quake_mdl_t* m__parent;
public:
int32_t faces_front() const { return m_faces_front; }
std::vector<int32_t>* vertices() const { return m_vertices.get(); }
quake_mdl_t* _root() const { return m__root; }
quake_mdl_t* _parent() const { return m__parent; }
};
class vec3_t : public kaitai::kstruct {
public:
vec3_t(kaitai::kstream* p__io, quake_mdl_t::mdl_header_t* p__parent = nullptr, quake_mdl_t* p__root = nullptr);
private:
void _read();
void _clean_up();
public:
~vec3_t();
private:
float m_x;
float m_y;
float m_z;
quake_mdl_t* m__root;
quake_mdl_t::mdl_header_t* m__parent;
public:
float x() const { return m_x; }
float y() const { return m_y; }
float z() const { return m_z; }
quake_mdl_t* _root() const { return m__root; }
quake_mdl_t::mdl_header_t* _parent() const { return m__parent; }
};
private:
std::unique_ptr<mdl_header_t> m_header;
std::unique_ptr<std::vector<std::unique_ptr<mdl_skin_t>>> m_skins;
std::unique_ptr<std::vector<std::unique_ptr<mdl_texcoord_t>>> m_texture_coordinates;
std::unique_ptr<std::vector<std::unique_ptr<mdl_triangle_t>>> m_triangles;
std::unique_ptr<std::vector<std::unique_ptr<mdl_frame_t>>> m_frames;
quake_mdl_t* m__root;
kaitai::kstruct* m__parent;
public:
mdl_header_t* header() const { return m_header.get(); }
std::vector<std::unique_ptr<mdl_skin_t>>* skins() const { return m_skins.get(); }
std::vector<std::unique_ptr<mdl_texcoord_t>>* texture_coordinates() const { return m_texture_coordinates.get(); }
std::vector<std::unique_ptr<mdl_triangle_t>>* triangles() const { return m_triangles.get(); }
std::vector<std::unique_ptr<mdl_frame_t>>* frames() const { return m_frames.get(); }
quake_mdl_t* _root() const { return m__root; }
kaitai::kstruct* _parent() const { return m__parent; }
};
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
#include "quake_mdl.h"
#include "kaitai/exceptions.h"
quake_mdl_t::quake_mdl_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, quake_mdl_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = this;
m_header = nullptr;
m_skins = nullptr;
m_texture_coordinates = nullptr;
m_triangles = nullptr;
m_frames = nullptr;
_read();
}
void quake_mdl_t::_read() {
m_header = std::unique_ptr<mdl_header_t>(new mdl_header_t(m__io, this, m__root));
int l_skins = header()->num_skins();
m_skins = std::unique_ptr<std::vector<std::unique_ptr<mdl_skin_t>>>(new std::vector<std::unique_ptr<mdl_skin_t>>());
m_skins->reserve(l_skins);
for (int i = 0; i < l_skins; i++) {
m_skins->push_back(std::move(std::unique_ptr<mdl_skin_t>(new mdl_skin_t(m__io, this, m__root))));
}
int l_texture_coordinates = header()->num_verts();
m_texture_coordinates = std::unique_ptr<std::vector<std::unique_ptr<mdl_texcoord_t>>>(new std::vector<std::unique_ptr<mdl_texcoord_t>>());
m_texture_coordinates->reserve(l_texture_coordinates);
for (int i = 0; i < l_texture_coordinates; i++) {
m_texture_coordinates->push_back(std::move(std::unique_ptr<mdl_texcoord_t>(new mdl_texcoord_t(m__io, this, m__root))));
}
int l_triangles = header()->num_tris();
m_triangles = std::unique_ptr<std::vector<std::unique_ptr<mdl_triangle_t>>>(new std::vector<std::unique_ptr<mdl_triangle_t>>());
m_triangles->reserve(l_triangles);
for (int i = 0; i < l_triangles; i++) {
m_triangles->push_back(std::move(std::unique_ptr<mdl_triangle_t>(new mdl_triangle_t(m__io, this, m__root))));
}
int l_frames = header()->num_frames();
m_frames = std::unique_ptr<std::vector<std::unique_ptr<mdl_frame_t>>>(new std::vector<std::unique_ptr<mdl_frame_t>>());
m_frames->reserve(l_frames);
for (int i = 0; i < l_frames; i++) {
m_frames->push_back(std::move(std::unique_ptr<mdl_frame_t>(new mdl_frame_t(m__io, this, m__root))));
}
}
quake_mdl_t::~quake_mdl_t() {
_clean_up();
}
void quake_mdl_t::_clean_up() {
}
quake_mdl_t::mdl_vertex_t::mdl_vertex_t(kaitai::kstream* p__io, kaitai::kstruct* p__parent, quake_mdl_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_values = nullptr;
_read();
}
void quake_mdl_t::mdl_vertex_t::_read() {
int l_values = 3;
m_values = std::unique_ptr<std::vector<uint8_t>>(new std::vector<uint8_t>());
m_values->reserve(l_values);
for (int i = 0; i < l_values; i++) {
m_values->push_back(std::move(m__io->read_u1()));
}
m_normal_index = m__io->read_u1();
}
quake_mdl_t::mdl_vertex_t::~mdl_vertex_t() {
_clean_up();
}
void quake_mdl_t::mdl_vertex_t::_clean_up() {
}
quake_mdl_t::mdl_texcoord_t::mdl_texcoord_t(kaitai::kstream* p__io, quake_mdl_t* p__parent, quake_mdl_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
_read();
}
void quake_mdl_t::mdl_texcoord_t::_read() {
m_on_seam = m__io->read_s4le();
m_s = m__io->read_s4le();
m_t = m__io->read_s4le();
}
quake_mdl_t::mdl_texcoord_t::~mdl_texcoord_t() {
_clean_up();
}
void quake_mdl_t::mdl_texcoord_t::_clean_up() {
}
quake_mdl_t::mdl_header_t::mdl_header_t(kaitai::kstream* p__io, quake_mdl_t* p__parent, quake_mdl_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_scale = nullptr;
m_origin = nullptr;
m_eye_position = nullptr;
f_version = false;
f_skin_size = false;
_read();
}
void quake_mdl_t::mdl_header_t::_read() {
m_ident = m__io->read_bytes(4);
if (!(ident() == std::string("\x49\x44\x50\x4F", 4))) {
throw kaitai::validation_not_equal_error<std::string>(std::string("\x49\x44\x50\x4F", 4), ident(), _io(), std::string("/types/mdl_header/seq/0"));
}
m_version_must_be_6 = m__io->read_bytes(4);
if (!(version_must_be_6() == std::string("\x06\x00\x00\x00", 4))) {
throw kaitai::validation_not_equal_error<std::string>(std::string("\x06\x00\x00\x00", 4), version_must_be_6(), _io(), std::string("/types/mdl_header/seq/1"));
}
m_scale = std::unique_ptr<vec3_t>(new vec3_t(m__io, this, m__root));
m_origin = std::unique_ptr<vec3_t>(new vec3_t(m__io, this, m__root));
m_radius = m__io->read_f4le();
m_eye_position = std::unique_ptr<vec3_t>(new vec3_t(m__io, this, m__root));
m_num_skins = m__io->read_s4le();
m_skin_width = m__io->read_s4le();
m_skin_height = m__io->read_s4le();
m_num_verts = m__io->read_s4le();
m_num_tris = m__io->read_s4le();
m_num_frames = m__io->read_s4le();
m_synctype = m__io->read_s4le();
m_flags = m__io->read_s4le();
m_size = m__io->read_f4le();
}
quake_mdl_t::mdl_header_t::~mdl_header_t() {
_clean_up();
}
void quake_mdl_t::mdl_header_t::_clean_up() {
}
int8_t quake_mdl_t::mdl_header_t::version() {
if (f_version)
return m_version;
m_version = 6;
f_version = true;
return m_version;
}
int32_t quake_mdl_t::mdl_header_t::skin_size() {
if (f_skin_size)
return m_skin_size;
m_skin_size = (skin_width() * skin_height());
f_skin_size = true;
return m_skin_size;
}
quake_mdl_t::mdl_skin_t::mdl_skin_t(kaitai::kstream* p__io, quake_mdl_t* p__parent, quake_mdl_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_frame_times = nullptr;
m_group_texture_data = nullptr;
_read();
}
void quake_mdl_t::mdl_skin_t::_read() {
m_group = m__io->read_s4le();
n_single_texture_data = true;
if (group() == 0) {
n_single_texture_data = false;
m_single_texture_data = m__io->read_bytes(_root()->header()->skin_size());
}
n_num_frames = true;
if (group() != 0) {
n_num_frames = false;
m_num_frames = m__io->read_u4le();
}
n_frame_times = true;
if (group() != 0) {
n_frame_times = false;
int l_frame_times = num_frames();
m_frame_times = std::unique_ptr<std::vector<float>>(new std::vector<float>());
m_frame_times->reserve(l_frame_times);
for (int i = 0; i < l_frame_times; i++) {
m_frame_times->push_back(std::move(m__io->read_f4le()));
}
}
n_group_texture_data = true;
if (group() != 0) {
n_group_texture_data = false;
int l_group_texture_data = num_frames();
m_group_texture_data = std::unique_ptr<std::vector<std::string>>(new std::vector<std::string>());
m_group_texture_data->reserve(l_group_texture_data);
for (int i = 0; i < l_group_texture_data; i++) {
m_group_texture_data->push_back(std::move(m__io->read_bytes(_root()->header()->skin_size())));
}
}
}
quake_mdl_t::mdl_skin_t::~mdl_skin_t() {
_clean_up();
}
void quake_mdl_t::mdl_skin_t::_clean_up() {
if (!n_single_texture_data) {
}
if (!n_num_frames) {
}
if (!n_frame_times) {
}
if (!n_group_texture_data) {
}
}
quake_mdl_t::mdl_frame_t::mdl_frame_t(kaitai::kstream* p__io, quake_mdl_t* p__parent, quake_mdl_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_min = nullptr;
m_max = nullptr;
m_time = nullptr;
m_frames = nullptr;
f_num_simple_frames = false;
_read();
}
void quake_mdl_t::mdl_frame_t::_read() {
m_type = m__io->read_s4le();
n_min = true;
if (type() != 0) {
n_min = false;
m_min = std::unique_ptr<mdl_vertex_t>(new mdl_vertex_t(m__io, this, m__root));
}
n_max = true;
if (type() != 0) {
n_max = false;
m_max = std::unique_ptr<mdl_vertex_t>(new mdl_vertex_t(m__io, this, m__root));
}
n_time = true;
if (type() != 0) {
n_time = false;
int l_time = type();
m_time = std::unique_ptr<std::vector<float>>(new std::vector<float>());
m_time->reserve(l_time);
for (int i = 0; i < l_time; i++) {
m_time->push_back(std::move(m__io->read_f4le()));
}
}
int l_frames = num_simple_frames();
m_frames = std::unique_ptr<std::vector<std::unique_ptr<mdl_simple_frame_t>>>(new std::vector<std::unique_ptr<mdl_simple_frame_t>>());
m_frames->reserve(l_frames);
for (int i = 0; i < l_frames; i++) {
m_frames->push_back(std::move(std::unique_ptr<mdl_simple_frame_t>(new mdl_simple_frame_t(m__io, this, m__root))));
}
}
quake_mdl_t::mdl_frame_t::~mdl_frame_t() {
_clean_up();
}
void quake_mdl_t::mdl_frame_t::_clean_up() {
if (!n_min) {
}
if (!n_max) {
}
if (!n_time) {
}
}
int32_t quake_mdl_t::mdl_frame_t::num_simple_frames() {
if (f_num_simple_frames)
return m_num_simple_frames;
m_num_simple_frames = ((type() == 0) ? (1) : (type()));
f_num_simple_frames = true;
return m_num_simple_frames;
}
quake_mdl_t::mdl_simple_frame_t::mdl_simple_frame_t(kaitai::kstream* p__io, quake_mdl_t::mdl_frame_t* p__parent, quake_mdl_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_bbox_min = nullptr;
m_bbox_max = nullptr;
m_vertices = nullptr;
_read();
}
void quake_mdl_t::mdl_simple_frame_t::_read() {
m_bbox_min = std::unique_ptr<mdl_vertex_t>(new mdl_vertex_t(m__io, this, m__root));
m_bbox_max = std::unique_ptr<mdl_vertex_t>(new mdl_vertex_t(m__io, this, m__root));
m_name = kaitai::kstream::bytes_to_str(kaitai::kstream::bytes_terminate(kaitai::kstream::bytes_strip_right(m__io->read_bytes(16), 0), 0, false), std::string("ASCII"));
int l_vertices = _root()->header()->num_verts();
m_vertices = std::unique_ptr<std::vector<std::unique_ptr<mdl_vertex_t>>>(new std::vector<std::unique_ptr<mdl_vertex_t>>());
m_vertices->reserve(l_vertices);
for (int i = 0; i < l_vertices; i++) {
m_vertices->push_back(std::move(std::unique_ptr<mdl_vertex_t>(new mdl_vertex_t(m__io, this, m__root))));
}
}
quake_mdl_t::mdl_simple_frame_t::~mdl_simple_frame_t() {
_clean_up();
}
void quake_mdl_t::mdl_simple_frame_t::_clean_up() {
}
quake_mdl_t::mdl_triangle_t::mdl_triangle_t(kaitai::kstream* p__io, quake_mdl_t* p__parent, quake_mdl_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
m_vertices = nullptr;
_read();
}
void quake_mdl_t::mdl_triangle_t::_read() {
m_faces_front = m__io->read_s4le();
int l_vertices = 3;
m_vertices = std::unique_ptr<std::vector<int32_t>>(new std::vector<int32_t>());
m_vertices->reserve(l_vertices);
for (int i = 0; i < l_vertices; i++) {
m_vertices->push_back(std::move(m__io->read_s4le()));
}
}
quake_mdl_t::mdl_triangle_t::~mdl_triangle_t() {
_clean_up();
}
void quake_mdl_t::mdl_triangle_t::_clean_up() {
}
quake_mdl_t::vec3_t::vec3_t(kaitai::kstream* p__io, quake_mdl_t::mdl_header_t* p__parent, quake_mdl_t* p__root) : kaitai::kstruct(p__io) {
m__parent = p__parent;
m__root = p__root;
_read();
}
void quake_mdl_t::vec3_t::_read() {
m_x = m__io->read_f4le();
m_y = m__io->read_f4le();
m_z = m__io->read_f4le();
}
quake_mdl_t::vec3_t::~vec3_t() {
_clean_up();
}
void quake_mdl_t::vec3_t::_clean_up() {
}