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++98/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
#ifndef QUAKE_MDL_H_
#define QUAKE_MDL_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 < 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 = 0, quake_mdl_t* p__root = 0);
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 = 0, quake_mdl_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~mdl_vertex_t();
private:
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; }
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 = 0, quake_mdl_t* p__root = 0);
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 = 0, quake_mdl_t* p__root = 0);
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;
vec3_t* m_scale;
vec3_t* m_origin;
float m_radius;
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; }
vec3_t* origin() const { return m_origin; }
float radius() const { return m_radius; }
vec3_t* eye_position() const { return m_eye_position; }
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 = 0, quake_mdl_t* p__root = 0);
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::vector<float>* m_frame_times;
bool n_frame_times;
public:
bool _is_null_frame_times() { frame_times(); return n_frame_times; };
private:
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; }
std::vector<std::string>* group_texture_data() const { return m_group_texture_data; }
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 = 0, quake_mdl_t* p__root = 0);
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;
mdl_vertex_t* m_min;
bool n_min;
public:
bool _is_null_min() { min(); return n_min; };
private:
mdl_vertex_t* m_max;
bool n_max;
public:
bool _is_null_max() { max(); return n_max; };
private:
std::vector<float>* m_time;
bool n_time;
public:
bool _is_null_time() { time(); return n_time; };
private:
std::vector<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; }
mdl_vertex_t* max() const { return m_max; }
std::vector<float>* time() const { return m_time; }
std::vector<mdl_simple_frame_t*>* frames() const { return m_frames; }
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 = 0, quake_mdl_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~mdl_simple_frame_t();
private:
mdl_vertex_t* m_bbox_min;
mdl_vertex_t* m_bbox_max;
std::string m_name;
std::vector<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; }
mdl_vertex_t* bbox_max() const { return m_bbox_max; }
std::string name() const { return m_name; }
std::vector<mdl_vertex_t*>* vertices() const { return m_vertices; }
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 = 0, quake_mdl_t* p__root = 0);
private:
void _read();
void _clean_up();
public:
~mdl_triangle_t();
private:
int32_t m_faces_front;
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; }
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 = 0, quake_mdl_t* p__root = 0);
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:
mdl_header_t* m_header;
std::vector<mdl_skin_t*>* m_skins;
std::vector<mdl_texcoord_t*>* m_texture_coordinates;
std::vector<mdl_triangle_t*>* m_triangles;
std::vector<mdl_frame_t*>* m_frames;
quake_mdl_t* m__root;
kaitai::kstruct* m__parent;
public:
mdl_header_t* header() const { return m_header; }
std::vector<mdl_skin_t*>* skins() const { return m_skins; }
std::vector<mdl_texcoord_t*>* texture_coordinates() const { return m_texture_coordinates; }
std::vector<mdl_triangle_t*>* triangles() const { return m_triangles; }
std::vector<mdl_frame_t*>* frames() const { return m_frames; }
quake_mdl_t* _root() const { return m__root; }
kaitai::kstruct* _parent() const { return m__parent; }
};
#endif // QUAKE_MDL_H_
// 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 = 0;
m_skins = 0;
m_texture_coordinates = 0;
m_triangles = 0;
m_frames = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void quake_mdl_t::_read() {
m_header = new mdl_header_t(m__io, this, m__root);
int l_skins = header()->num_skins();
m_skins = new std::vector<mdl_skin_t*>();
m_skins->reserve(l_skins);
for (int i = 0; i < l_skins; i++) {
m_skins->push_back(new mdl_skin_t(m__io, this, m__root));
}
int l_texture_coordinates = header()->num_verts();
m_texture_coordinates = new std::vector<mdl_texcoord_t*>();
m_texture_coordinates->reserve(l_texture_coordinates);
for (int i = 0; i < l_texture_coordinates; i++) {
m_texture_coordinates->push_back(new mdl_texcoord_t(m__io, this, m__root));
}
int l_triangles = header()->num_tris();
m_triangles = new std::vector<mdl_triangle_t*>();
m_triangles->reserve(l_triangles);
for (int i = 0; i < l_triangles; i++) {
m_triangles->push_back(new mdl_triangle_t(m__io, this, m__root));
}
int l_frames = header()->num_frames();
m_frames = new std::vector<mdl_frame_t*>();
m_frames->reserve(l_frames);
for (int i = 0; i < l_frames; i++) {
m_frames->push_back(new mdl_frame_t(m__io, this, m__root));
}
}
quake_mdl_t::~quake_mdl_t() {
_clean_up();
}
void quake_mdl_t::_clean_up() {
if (m_header) {
delete m_header; m_header = 0;
}
if (m_skins) {
for (std::vector<mdl_skin_t*>::iterator it = m_skins->begin(); it != m_skins->end(); ++it) {
delete *it;
}
delete m_skins; m_skins = 0;
}
if (m_texture_coordinates) {
for (std::vector<mdl_texcoord_t*>::iterator it = m_texture_coordinates->begin(); it != m_texture_coordinates->end(); ++it) {
delete *it;
}
delete m_texture_coordinates; m_texture_coordinates = 0;
}
if (m_triangles) {
for (std::vector<mdl_triangle_t*>::iterator it = m_triangles->begin(); it != m_triangles->end(); ++it) {
delete *it;
}
delete m_triangles; m_triangles = 0;
}
if (m_frames) {
for (std::vector<mdl_frame_t*>::iterator it = m_frames->begin(); it != m_frames->end(); ++it) {
delete *it;
}
delete m_frames; m_frames = 0;
}
}
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 = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void quake_mdl_t::mdl_vertex_t::_read() {
int l_values = 3;
m_values = new std::vector<uint8_t>();
m_values->reserve(l_values);
for (int i = 0; i < l_values; i++) {
m_values->push_back(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() {
if (m_values) {
delete m_values; m_values = 0;
}
}
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;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
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 = 0;
m_origin = 0;
m_eye_position = 0;
f_version = false;
f_skin_size = false;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
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 = new vec3_t(m__io, this, m__root);
m_origin = new vec3_t(m__io, this, m__root);
m_radius = m__io->read_f4le();
m_eye_position = 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() {
if (m_scale) {
delete m_scale; m_scale = 0;
}
if (m_origin) {
delete m_origin; m_origin = 0;
}
if (m_eye_position) {
delete m_eye_position; m_eye_position = 0;
}
}
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 = 0;
m_group_texture_data = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
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 = 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(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 = 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(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 (m_frame_times) {
delete m_frame_times; m_frame_times = 0;
}
}
if (!n_group_texture_data) {
if (m_group_texture_data) {
delete m_group_texture_data; m_group_texture_data = 0;
}
}
}
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 = 0;
m_max = 0;
m_time = 0;
m_frames = 0;
f_num_simple_frames = false;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
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 = new mdl_vertex_t(m__io, this, m__root);
}
n_max = true;
if (type() != 0) {
n_max = false;
m_max = new mdl_vertex_t(m__io, this, m__root);
}
n_time = true;
if (type() != 0) {
n_time = false;
int l_time = type();
m_time = new std::vector<float>();
m_time->reserve(l_time);
for (int i = 0; i < l_time; i++) {
m_time->push_back(m__io->read_f4le());
}
}
int l_frames = num_simple_frames();
m_frames = new std::vector<mdl_simple_frame_t*>();
m_frames->reserve(l_frames);
for (int i = 0; i < l_frames; i++) {
m_frames->push_back(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 (m_min) {
delete m_min; m_min = 0;
}
}
if (!n_max) {
if (m_max) {
delete m_max; m_max = 0;
}
}
if (!n_time) {
if (m_time) {
delete m_time; m_time = 0;
}
}
if (m_frames) {
for (std::vector<mdl_simple_frame_t*>::iterator it = m_frames->begin(); it != m_frames->end(); ++it) {
delete *it;
}
delete m_frames; m_frames = 0;
}
}
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 = 0;
m_bbox_max = 0;
m_vertices = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void quake_mdl_t::mdl_simple_frame_t::_read() {
m_bbox_min = new mdl_vertex_t(m__io, this, m__root);
m_bbox_max = 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 = new std::vector<mdl_vertex_t*>();
m_vertices->reserve(l_vertices);
for (int i = 0; i < l_vertices; i++) {
m_vertices->push_back(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() {
if (m_bbox_min) {
delete m_bbox_min; m_bbox_min = 0;
}
if (m_bbox_max) {
delete m_bbox_max; m_bbox_max = 0;
}
if (m_vertices) {
for (std::vector<mdl_vertex_t*>::iterator it = m_vertices->begin(); it != m_vertices->end(); ++it) {
delete *it;
}
delete m_vertices; m_vertices = 0;
}
}
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 = 0;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
void quake_mdl_t::mdl_triangle_t::_read() {
m_faces_front = m__io->read_s4le();
int l_vertices = 3;
m_vertices = new std::vector<int32_t>();
m_vertices->reserve(l_vertices);
for (int i = 0; i < l_vertices; i++) {
m_vertices->push_back(m__io->read_s4le());
}
}
quake_mdl_t::mdl_triangle_t::~mdl_triangle_t() {
_clean_up();
}
void quake_mdl_t::mdl_triangle_t::_clean_up() {
if (m_vertices) {
delete m_vertices; m_vertices = 0;
}
}
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;
try {
_read();
} catch(...) {
_clean_up();
throw;
}
}
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() {
}