//------------------------------------------------ //--- 010 Editor v11.0.1 Binary Template // // File: vt2_unit.bt // Authors: Lucas Schwiderski // Version: // Purpose: // Category: Vermintide 2 // File Mask: *.unit // ID Bytes: BA 00 00 00 // History: //------------------------------------------------ // See // Type Definitions // 16 byte typedef struct { float row_1[4]; float row_2[4]; float row_3[4]; float row_4[4]; } Matrix4x4; // 3 byte typedef struct { float x; float y; float z; } Vector3; // 7 byte typedef struct { float lx; float ly; float lz; float ux; float uy; float uz; byte unknown[4]; } Bounds; // 21 byte typedef struct { uint32 data_size; byte data[data_size]; uint32 unknown_1; uint32 unknown_2; uint32 num_elements; uint32 element_size; } MeshSection; typedef struct { uint32 name; uint32 type; uint32 unknown_1; uint32 index; byte unknown_2; } MeshChannelDefinition; // 4 + (x * 21) byte typedef struct { uint32 num_streams; struct Stream { uint32 data_size; hfloat data[data_size / 2]; uint32 unknown_1; uint32 unknown_2; uint32 num_elements; uint32 element_size; } streams[num_streams] ; uint32 num_streams_2 ; struct StreamMeta { uint32 name; uint32 type; uint32 unknown_1; uint32 index; byte unknown_2; } stream_meta[num_streams] ; uint32 unknown_1; uint32 unknown_2; // Apparently the number of vertices with position values // that don't fit in a single short/uint16 // When > 0, indicates that following data should be read as uint32 // instead uint32 unknown_3; uint32 num_index_stream_data; uint32 size_index_stream_data; // this means each entrie's size is `size_stream_data / num_stream_data` if (size_index_stream_data / num_index_stream_data == 2) { uint16 index_stream_data[num_index_stream_data]; } else { byte index_stream_data[size_index_stream_data]; } uint32 num_materials; struct Material { uint32 id; uint32 tri_array_start; uint32 tri_count; uint32 unknown; } materials[num_materials]; Bounds bounds; uint32 num_materials_2 ; uint32 material_names[num_materials_2]; } Geometry; // 4 + (x * 16) + (x * 4) byte typedef struct { uint32 num_bones; Matrix4x4 matrix[num_bones]; uint32 bone_ids[num_bones]; } Skin; // 15 byte typedef struct { Vector3 localXAxis; Vector3 localYAxis; Vector3 localZAxis; Vector3 localPosition; Vector3 localScale; } NodeLocal; // 4 byte typedef struct { uint16 unknown; // Index into `num_nodes` uint16 parent_id; } NodeExtra; enum NodeFlags { // Rarely set, since renderables with this value aren't included // for compilation by default VIEWPORT_VISIBLE=1, SHADOW_CASTER=2, CULLING_DISABLED=4, }; // 27 byte typedef struct { uint32 parent; uint32 name; uint32 num_geometries; uint32 geometry_name[num_geometries]; uint32 unknown_1; uint32 unknown_2; uint32 unknown_3; // Flags set in the .unit file // Usually set to `1`, since hidden renderables are skipped // during compilation by default uint32 viewport_visible : 1; uint32 shadow_caster : 1; // Need to check if this is really defined as a negative, as implied by the name // Usually, you should name booleans after the positive value to minimize confusion. uint32 culling_disabled : 1; uint32 occluder : 1; uint32 surface_queries : 1; uint32 always_keep : 1; Bounds bounds; } Node; // 12 byte //typedef struct { // uint32 name; // uint64 resource; //} Material; enum ActorShapeType { Sphere, Box, Capsule, MESH, Convex, }; // 32 + x + (1, 2, 3, ?) byte typedef struct { ActorShapeType type; uint32 material; uint32 template; Matrix4x4 pose; uint32 physx_data_size; byte physx_data[physx_data_size]; switch (type) { case 0: byte shape_shpere_radius; break; case 1: byte shape_box_half_size_x; byte shape_box_half_size_y; byte shape_box_half_size_z; break; case 2: byte shape_capsule_radius; byte shape_capsule_length; break; case 3: return "ActorShapeType.MESH not implemented"; break; case 4: return "ActorShapeType.Convex not implemented"; break; } } Shape; // 17 + (x * (32 + y + (1, 2, 3, ?))) byte typedef struct { uint32 name; uint32 template; uint32 node; byte mass; uint32 num_shapes; Shape shapes[num_shapes] ; } Actor; // 15 byte typedef struct { uint32 name; uint32 unknown_1; byte near_range; byte far_range; byte vertical_fov; uint32 unknown_2; } Camera; enum LightType { Omni, Spot, BOX, Directional, }; typedef byte boolean; // 35 + (6, 8) byte typedef struct { uint32 name; uint32 node_id; byte color_r; byte color_g; byte color_b; // Should both be 1 byte check_1; byte check_2; LightType type; switch (type) { case 0: // Fallthrough case 1: byte falloff_start; byte falloff_end; byte unknown_1; byte spot_angle_start; byte spot_angle_end; byte unknown_2; break; case 2: byte box_min_x; byte box_min_y; byte box_min_z; byte box_max_x; byte box_max_y; byte box_max_z; break; case 3: uint unknown_1; } boolean cast_shadows; byte bs[17]; } Light; // 21 byte typedef struct { byte step_end; byte step_start; uint32 num_renderables; uint32 renderable_id[num_renderables]; Bounds bounding_volume; uint32 unknown_flags; } LODSteps; // 12 + (x * 21) byte typedef struct { uint32 name; uint32 orientation; uint32 num_steps; LODSteps steps[num_steps]; } LOD; // 19 byte typedef struct { uint32 name; byte height; byte radius; uint32 collision_filter; byte slope_limit; byte ffx8[8]; } Mover; // 8 + (x * 4) typedef struct { uint32 name; uint32 num_members; uint32 renderable_ids[num_members]; } VisibilityGroup; // File Parsing uint32 version; // =================== // Meshes // =================== uint32 num_geometries; Geometry geometries[num_geometries] ; // =================== // Skins // =================== uint32 num_skins; Skin skins[num_skins] ; uint32 size_unknown_1; byte unknown_1[size_unknown_1]; uint32 num_unknown_2; uint32 unknown_2[num_unknown_2]; // =================== // Nodes // =================== uint32 num_nodes; NodeLocal node_locals[num_nodes]; Matrix4x4 node_world_poses[num_nodes]; // Should be 0 uint32 unknown_3; // =================== // Renderables // =================== uint32 num_nodes; Node nodes[num_nodes] ; // =================== // Physics // =================== uint32 num_actors; Actor actors[num_actors] ; // =================== // Cameras // =================== uint32 num_cameras; Camera cameras[num_cameras]; // =================== // Lights // =================== uint32 num_lights; Light lights[num_lights]; // =================== // LOD // =================== uint32 num_lods; LOD lods[num_lods]; // Should both be 0. Sections I don't know yet? uint32 unknown_4; uint32 unknown_5; // =================== // Movers // =================== uint32 num_movers; Mover movers[num_movers]; // Should be 0. Section I don't know yet? uint32 unknown_6; boolean unknown_has_animation_blender_bones; uint32 str_length; char str[str_length]; // =================== // Script Data // =================== uint32 script_data_size; byte script_data[script_data_size]; // =================== // Visibility Group // =================== uint32 num_visibility_groups; VisibilityGroup visibility_groups[num_visibility_groups]; // =================== // Unknown // =================== // Probably related to scripting/Flow // When there is data, it contains strings that look like function calls uint32 size_flow_data_1; byte flow_data_1[size_flow_data_1]; uint32 size_flow_data_2; byte flow_data_2[size_flow_data_2]; // =================== // Materials // =================== uint32 size_material_definition; uint32 num_materials; struct MaterialDefinition { // Probably the index into the other material section uint32 unknown_1; uint32 num_primitives; uint32 unknown_2; uint32 num_primitives_2; uint32 unknown_3; // Fits for the 6 vectors, but not for the last `unknown`. Bounds bounds; uint32 num_primitives_3; uint32 primitives[num_primitives_3]; } material_definitions[num_materials] ; // Should be 0. Sections I don't know yet? uint32 unknown_7; uint32 unknown_8; uint32 unknown_9; uint32 unknown_10; // Apparently doesn't have to match the previous `num_materials` uint32 num_materials_2; struct MaterialResources { uint32 name; uint64 resource; } material_resources[num_materials_2]; // Should be 0. Sections I don't know yet? uint32 unknown_11; uint32 unknown_12; uint32 unknown_13; uint32 unknown_14;