Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@farmboy0
Created July 23, 2016 12:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save farmboy0/cd6d87cdee77cd507eda0fc521a18aae to your computer and use it in GitHub Desktop.
Save farmboy0/cd6d87cdee77cd507eda0fc521a18aae to your computer and use it in GitHub Desktop.
//------------------------------------------------------
//--- 010 Editor v6.0.2 Binary Template
//
// File: KoTOR2MDL.bt
// Author: Enrico Horn (Farmboy0)
// Revision: 0.1
// Purpose: to map the model format of the kotor2 engine from bioware
//------------------------------------------------------
// Colors:
//------------------------------------------------------
// Dark Red : array of file pointers(not the array definition)
// Black : array of strings(node names)
// Red : controller keys
// Light Red : controller data
// Light Blue : file header
// Light Purple : geometry header
// Aqua : model header without geometry header
// Dark Aqua : animation header without geometry header incl. events array
// Light Green : node header
// Yellow : light node without node header
// Dark Yellow : emitter node without node header
// Orange : skin node without node header
// Gray : mesh node without node header
//------------------------------------------------------
//------------------------------------------------------
// generic structures
typedef struct {
string s <bgcolor=cBlack, fgcolor=cWhite>;
} strings <read=ReadStrings>;
typedef struct {
float w;
float x;
float y;
float z;
} quaternion;
typedef struct {
uint32 p_array_start <format=hex,read=ReadPointer>;
uint32 nr_used_entries;
uint32 nr_alloc_entries;
} array_definition;
typedef struct {
array_definition def;
if (def.nr_used_entries > 0) {
local int pos = FTell();
GoToPointer(def.p_array_start);
uint32 p_index[def.nr_used_entries] <format=hex,optimize=false,fgcolor=cWhite,bgcolor=cDkRed,read=ReadPointer>;
FSeek(pos);
}
} array;
typedef struct {
array array_info;
local int pos = FTell();
local int i;
for (i = 0; i < array_info.def.nr_used_entries; i++) {
GoToPointer(array_info.p_index[i]);
strings str;
}
FSeek(pos);
} string_array;
//------------------------------------------------------
// generic header structures
typedef struct {
uint32 bin_mdl_id <format=hex>;
uint32 mdl_length;
uint32 mdx_length;
} header_file <bgcolor=cLtBlue>;
void GoToPointer(uint32 p) {
FSeek(sizeof(header_file) + p);
}
typedef struct {
uint32 p_func1 <format=hex>;
uint32 p_func2 <format=hex>;
char model_name[32];
uint32 p_node_header <format=hex,read=ReadPointer>;
uint32 count_nodes;
array_definition unknown1;
array_definition unknown2;
uint32 ref_count;
ubyte type;
ubyte padding[3];
} header_geometry <bgcolor=cLtPurple,fgcolor=cBlack>;
typedef struct {
header_geometry geometry;
uint32 field_50 <format=hex>;
uint32 count_child_model;
array animations;
uint32 p_supermodel <format=hex>;
float boundingbox_min[3];
float boundingbox_max[3];
float model_radius;
float scale;
char supermodel_name[32];
uint32 p_node1 <format=hex,read=ReadPointer>;
uint32 field_B0;
uint32 mdx_length;
uint32 p_mdx <format=hex>;
string_array names;
} header_model <bgcolor=cAqua>;
//------------------------------------------------------
// specific node structures
// forward declaration of the node struct
struct node;
typedef struct {
ushort animated_uv : 1;
ushort light_mapped : 1;
ushort bgr_geometry : 1;
ushort beaming : 1;
ushort render : 1;
} node_flags;
enum mesh_type {
point_list=0,
line_list,
line_strip,
triangle_list,
triangle_strip,
triangle_fan,
unknown
};
typedef struct {
float normal[3];
float distance;
ushort adj_faces[3];
ushort index_vertex[3];
} face;
typedef struct {
array_definition faces;
float bounding_min[3];
float bounding_max[3];
float radius;
float points_average[3];
uint32 transparency;
node_flags flags;
ushort shadow;
char texture[32];
uint32 count_faces;
uint32 p_faces_mdl <format=hex, read=ReadPointer>;
int32 unknown4;
mesh_type type;
uint32 unknown5 <format=hex>;
uint32 unknown6;
uint32 unknown7 <format=hex>;
uint32 size_vertex_struct_mdx;
uint32 unknown8;
int32 unknown9;
int32 count_normals;
int32 unknown10;
int32 uv[4];
int32 unknown11;
int32 unknown12;
int32 unknown13;
int32 unknown14;
int32 unknown15;
ushort count_vertex;
ushort count_texture;
uint32 p_vertex_mdx <format=hex>;
uint32 unknown16 <format=hex>;
int32 material_id;
uint32 material_groupid;
float illumination[3];
float alpha;
float texture_coords_w;
uint32 unknown17 <format=hex>;
uint32 p_faces_mdx <format=hex>;
uint32 unknown18;
} header_mesh <bgcolor=cSilver>;
typedef struct(node &n) {
local int pos = FTell();
if (n.mesh.faces.nr_used_entries > 0) {
GoToPointer(n.mesh.faces.p_array_start);
face faces[n.mesh.faces.nr_used_entries] <fgcolor=cYellow>;
}
if (n.mesh.p_faces_mdl > 0) {
GoToPointer(n.mesh.p_faces_mdl);
ushort faces_mdl[n.mesh.count_faces] <fgcolor=cWhite>;
}
FSeek(pos);
} data_mesh <bgcolor=cDkGray>;
typedef struct {
uint32 unknown1;
uint32 unknown2;
uint32 unknown3;
uint32 count1;
uint32 count2;
uint32 p_bone_mapping <format=hex, read=ReadPointer>;
uint32 count_bone_mapping;
array_definition qbone;
array_definition tbone;
array_definition bone_constants;
short bone_parts[47];
short spare;
} header_skin <bgcolor=0x0080FF>;
typedef struct(node &n) {
local int pos = FTell();
if (n.skin.count_bone_mapping > 0) {
GoToPointer(n.skin.p_bone_mapping);
short bone_mapping[n.skin.count_bone_mapping] <fgcolor=cWhite>;
}
if (n.skin.qbone.nr_used_entries > 0) {
GoToPointer(n.skin.qbone.p_array_start);
quaternion q[n.skin.qbone.nr_used_entries] <fgcolor=cDkGreen>;
}
if (n.skin.tbone.nr_used_entries > 0) {
GoToPointer(n.skin.tbone.p_array_start);
float t[3*n.skin.tbone.nr_used_entries] <fgcolor=cBlack>;
}
FSeek(pos);
} data_skin <bgcolor=0x0090FF>;
typedef struct {
uint32 u1[23];
float u2[16];
} header_light <bgcolor=cYellow>;
typedef struct {
uint32 flag_p2p : 1; // 1
uint32 flag_p2p_sel : 1; // 2
uint32 flag_affected_wind : 1; // 4
uint32 flag_tinted : 1; // 8
uint32 flag_bounce : 1; // 10
uint32 flag_random : 1; // 20
uint32 flag_inherit : 1; // 40
uint32 flag_inherit_vel : 1; // 80
uint32 flag_inherit_local : 1; // 100
uint32 flag_splat : 1; // 200
uint32 flag_inherit_part : 1; // 400
uint32 flag_unknown800 : 1; // 800
uint32 flag_unknown1000 : 1; // 1000
uint32 flag_unknown2000 : 1; // 2000
uint32 flag_unknown4000 : 1; // 4000
uint32 flag_unknown8000 : 1; // 8000
} emitter_flags;
typedef struct {
float dead_space;
float blast_radius;
float blast_length;
uint32 grid_x;
uint32 grid_y;
uint32 space;
uint32 space2;
uint32 space3;
char update[32];
char render[32];
char blend[32];
char texture[32];
char chunk[32];
float unknown[55];
uint32 p_next_emitter <format=hex,read=ReadPointer>;
uint32 unknown2;
uint32 unknown3;
emitter_flags flags;
} header_emitter <bgcolor=cDkYellow>;
//------------------------------------------------------
// general node structures
enum controller_type_all {
position=8,
orientation=20,
scale=36
};
enum controller_type_light {
light_position=8,
light_orientation=20,
light_scale=36,
light_color=76,
light_radius=88,
light_radius_shadow=96,
light_vert_displacement=100,
light_multiplier=140
};
enum controller_type_mesh {
mesh_position=8,
mesh_orientation=20,
mesh_scale=36,
mesh_self_illum_color=100,
mesh_unknown=132
};
typedef struct {
short has_header : 1; // 1
short has_light : 1; // 2
short has_emitter : 1; // 4
short has_camera: 1; // 8
short has_reference : 1; // 10
short has_mesh : 1; // 20
short has_skin : 1; // 40
short has_anim : 1; // 80
short has_dangly : 1; // 100
short has_aabb : 1; // 200
short has_unknown400: 1; // 400
short has_unknown800: 1; // 800
short has_gob: 1; // 1000
short has_collision: 1; // 2000
short has_sphere: 1; // 4000
short has_capsule: 1; // 8000
} content_node;
typedef struct(content_node &c) {
if (c.has_light) {
controller_type_light type;
} else if (c.has_mesh) {
controller_type_mesh type;
} else {
controller_type_all type;
}
short unknown1 <format=hex>;
ushort value_count;
ushort timekey_start;
ushort data_start;
byte column_count;
byte padding[3];
} controller <bgcolor=cRed,read=ReadController>;
typedef struct {
content_node content;
short node_number1;
short node_number2;
short unknown;
uint32 p_root_node <format=hex,read=ReadPointer>;
uint32 p_parent_node <format=hex,read=ReadPointer>;
float position[3];
float orientation[4];
array children;
array_definition controllers_keys;
array_definition controllers_data;
} header_node <bgcolor=cLtGreen,fgcolor=cBlack>;
typedef struct {
header_node header;
local int n;
if (header.controllers_keys.nr_used_entries > 0) {
GoToPointer(header.controllers_keys.p_array_start);
for (n = 0; n < header.controllers_keys.nr_used_entries; n++) {
controller key(header.content);
}
}
if (header.controllers_data.nr_used_entries > 0) {
GoToPointer(header.controllers_data.p_array_start);
float controller_data[header.controllers_data.nr_used_entries] <bgcolor=cLtRed>;
}
for (n = 0; n < header.children.def.nr_used_entries; n++) {
GoToPointer(header.children.p_index[n]);
node children;
}
} node <read=ReadNode>;
//------------------------------------------------------
// animation structures
typedef struct {
float length;
char name[32];
} event <read=ReadEvent>;
typedef struct(int nr_of_events) {
local int e;
for (e = 0; e < nr_of_events; e++) {
event ev;
}
} event_array;
typedef struct {
header_geometry geometry;
float length;
float transistion;
char name[32];
array_definition array_events;
uint32 unknown3;
} header_animation;
typedef struct {
header_animation header;
if (header.array_events.nr_used_entries > 0) {
GoToPointer(header.array_events.p_array_start);
event_array events(header.array_events.nr_used_entries);
}
GoToPointer(header.geometry.p_node_header);
node animation_node;
} animation <read=ReadAnim, bgcolor=cDkAqua,fgcolor=cWhite>;
//------------------------------------------------------
// main definition
LittleEndian();
header_file hf;
header_model hm;
GoToPointer(hm.geometry.p_node_header);
node root;
local int a;
for (a = 0; a < hm.animations.def.nr_used_entries; a++) {
GoToPointer(hm.animations.p_index[a]);
animation anim;
}
//------------------------------------------------------
// read Methods
string ReadStrings( strings &str ) {
return str.s;
}
string ReadPointer(uint32 &p) {
uint32 v = 0;
if (p > 0) {
v = sizeof(header_file) + p;
}
string s;
SPrintf(s, "%Xh", v);
return s;
}
string ReadController( controller &key ) {
string s;
SPrintf(s, "%i", key.type);
return s;
}
string ReadNode( node &n ) {
string s = hm.names.str[n.header.node_number2].s;
if (n.header.content.has_light) {
s+="+Ligh";
}
if (n.header.content.has_emitter) {
s+="+Emit";
}
if (n.header.content.has_camera) {
s+="+Came";
}
if (n.header.content.has_reference) {
s+="+Refs";
}
if (n.header.content.has_mesh) {
s+="+Mesh";
}
if (n.header.content.has_skin) {
s+="+Skin";
}
if (n.header.content.has_anim) {
s+="+Anim";
}
if (n.header.content.has_dangly) {
s+="+Dang";
}
if (n.header.content.has_aabb) {
s+="+AABB";
}
if (n.header.content.has_unknown400) {
s+="+U400";
}
if (n.header.content.has_unknown800) {
s+="+U800";
}
if (n.header.content.has_gob) {
s+="+Gob";
}
if (n.header.content.has_collision) {
s+="+Coll";
}
if (n.header.content.has_sphere) {
s+="+Sphr";
}
if (n.header.content.has_capsule) {
s+="+Caps";
}
if (n.header.children.def.nr_used_entries > 0) {
local string child_count;
SPrintf(child_count, "(%d)", n.header.children.def.nr_used_entries);
s+=child_count;
}
return s;
}
string ReadEvent(event &e) {
local string s;
SPrintf(s, "%s(%f)", e.name, e.length);
return s;
}
string ReadAnim(animation &anim) {
return anim.header.geometry.model_name;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment