Created
July 23, 2016 12:16
-
-
Save farmboy0/cd6d87cdee77cd507eda0fc521a18aae to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//------------------------------------------------------ | |
//--- 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