As started above does anyone knows how to
extract .mcl files...???
extract .mcl files...???
Credits: Phantom*Quote:
A Saturday evening programming with Yamachi weeks ago.
Still outstanding/missing is the terrain texture splatting (Google: Blender+"Texture Splatting") and object placement.
* The source is of value as it explains the MCL file format, importing into Blender not so much.
Copy/Paste/Save source below as "import_scene_cabal_mcl.py" and move into ".blender/scripts/io"
Code:# Copyright (c) 2010 Peter S. Stevens # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # # Version 0.0.1 # * Initial release __author__ = 'Peter S. Stevens' __email__ = 'pstevens:cryptomail*org' __url__ = ('blender', 'elysiun', 'Project homepage, http://www.********.com/') __version__ = '0.0.1' __bpydoc__ = ''' \ Import CABAL mcl files ''' import bpy import io import Mathutils import os import struct u = 0.0 v = 0.0 def create_cabal_map_file_mesh_object(cabal_map_file_object_vertices_co, cabal_map_file_object_vertices_uv, cabal_map_file_object_indices): cabal_map_file_mesh = bpy.data.meshes.new('tile') cabal_map_file_mesh.add_geometry(int(len(cabal_map_file_object_vertices_co) / 3), 0, int(len(cabal_map_file_object_indices) / 4)) cabal_map_file_mesh.verts.foreach_set('co', cabal_map_file_object_vertices_co) cabal_map_file_mesh.faces.foreach_set('verts_raw', cabal_map_file_object_indices) cabal_map_file_mesh.add_uv_texture() for i, cabal_map_file_mesh_face in enumerate(cabal_map_file_mesh.faces): cabal_map_file_mesh_texture_data = cabal_map_file_mesh.uv_textures[0].data[i] cabal_map_file_mesh_texture_data_uvs = [cabal_map_file_object_vertices_uv[j] for j in cabal_map_file_mesh_face.verts] cabal_map_file_mesh_texture_data.uv1 = cabal_map_file_mesh_texture_data_uvs[0] cabal_map_file_mesh_texture_data.uv2 = cabal_map_file_mesh_texture_data_uvs[1] cabal_map_file_mesh_texture_data.uv3 = cabal_map_file_mesh_texture_data_uvs[2] cabal_map_file_mesh.update() cabal_map_file_mesh_object = bpy.data.objects.new('Mesh', cabal_map_file_mesh) cabal_map_file_mesh_object.data = cabal_map_file_mesh return cabal_map_file_mesh_object def parse_cabal_map_file_tile_object(cabal_map_file, cabal_map_file_tile_object_index): global u, v print("parse tile object at {0:x}".format(cabal_map_file.tell())) cabal_map_file_tile_object_unknown0, \ cabal_map_file_tile_object_face_count, \ cabal_map_file_tile_object_vertex_count = struct.unpack('<3I', cabal_map_file.read(12)) cabal_map_file_tile_object_vertices_co = [] cabal_map_file_tile_object_vertices_uv = [] print("parse tile object vertices at {0:x} count {1:x}".format(cabal_map_file.tell(), cabal_map_file_tile_object_vertex_count)) for i in range(cabal_map_file_tile_object_vertex_count): cabal_map_file_tile_object_vertex_co = list(struct.unpack('3f', cabal_map_file.read(12))) cabal_map_file_tile_object_vertex_co[0] *= 0.001 cabal_map_file_tile_object_vertex_co[1] *= 0.001 cabal_map_file_tile_object_vertex_co[2] *= 0.001 cabal_map_file_tile_object_vertices_co.extend(cabal_map_file_tile_object_vertex_co) if cabal_map_file_tile_object_index % 2 == 0: cabal_map_file.seek(4, os.SEEK_CUR) cabal_map_file_tile_object_vertex_uv = list(struct.unpack('2f', cabal_map_file.read(8))) cabal_map_file_tile_object_vertex_uv[0] = cabal_map_file_tile_object_vertex_uv[0] / 32.5 cabal_map_file_tile_object_vertex_uv[1] = cabal_map_file_tile_object_vertex_uv[1] / 32.5 if cabal_map_file_tile_object_vertex_uv[0] > u: u = cabal_map_file_tile_object_vertex_uv[0] if cabal_map_file_tile_object_vertex_uv[1] > v: v = cabal_map_file_tile_object_vertex_uv[1] cabal_map_file_tile_object_vertices_uv.append(cabal_map_file_tile_object_vertex_uv) cabal_map_file_tile_object_indices = [] print("parse tile object faces at {0:x} count {1:x}".format(cabal_map_file.tell(), cabal_map_file_tile_object_face_count)) for i in range(cabal_map_file_tile_object_face_count): cabal_map_file_tile_object_face = list(struct.unpack('<3H', cabal_map_file.read(6))) cabal_map_file_tile_object_face.append(0) cabal_map_file_tile_object_indices.extend(cabal_map_file_tile_object_face) print("parse tile object unknowns at {0:x}".format(cabal_map_file.tell())) # texture index per face for i in range(cabal_map_file_tile_object_face_count): struct.unpack('<I', cabal_map_file.read(4))[0] # texture count cabal_map_file_tile_object_unknowns_unique_count = struct.unpack('<I', cabal_map_file.read(4))[0] # texture indices used on this tile for i in range(cabal_map_file_tile_object_unknowns_unique_count): struct.unpack('<I', cabal_map_file.read(4))[0] cabal_map_file_mesh_object = None if cabal_map_file_tile_object_index % 2 != 0: cabal_map_file_mesh_object = create_cabal_map_file_mesh_object(cabal_map_file_tile_object_vertices_co, cabal_map_file_tile_object_vertices_uv, cabal_map_file_tile_object_indices) return cabal_map_file_mesh_object def parse_cabal_map_file_tile_objects(cabal_map_file): global u, v cabal_map_file_tile_objects = [] for i in range(2): if i % 2 == 0: # tile boundry cabal_map_file_tile_object_aa = Mathutils.Vector(struct.unpack('3f', cabal_map_file.read(12))) cabal_map_file_tile_object_bb = Mathutils.Vector(struct.unpack('3f', cabal_map_file.read(12))) cabal_map_file_tile_object = parse_cabal_map_file_tile_object(cabal_map_file, i) if cabal_map_file_tile_object is not None: cabal_map_file_tile_objects.append(cabal_map_file_tile_object) if i == 1: print(u) print(v) return cabal_map_file_tile_objects def parse_cabal_map_file_tile_texture(cabal_map_file, cabal_map_file_tile_texture_index): print("parse tile texture at {0:x}".format(cabal_map_file.tell())) cabal_map_file_tile_textures_file_path = os.path.splitext(cabal_map_file.name)[0] cabal_map_file_tile_texture = None cabal_map_file_tile_texture_size = struct.unpack('<I', cabal_map_file.read(4))[0] if cabal_map_file_tile_texture_size > 0: cabal_map_file_tile_texture_data = cabal_map_file.read(cabal_map_file_tile_texture_size) cabal_map_file_tile_texture_file_path = os.path.normpath(os.path.join(cabal_map_file_tile_textures_file_path, "tile{0}.dds".format(cabal_map_file_tile_texture_index))) if os.path.isfile(cabal_map_file_tile_texture_file_path) == False: with open(cabal_map_file_tile_texture_file_path, 'w+b') as cabal_map_file_tile_texture_file: cabal_map_file_tile_texture_file.write(cabal_map_file_tile_texture_data) return cabal_map_file_tile_texture def parse_cabal_map_file_tile_textures(cabal_map_file): cabal_map_file_tile_textures_file_path = os.path.splitext(cabal_map_file.name)[0] if os.path.isdir(cabal_map_file_tile_textures_file_path) == False: os.mkdir(cabal_map_file_tile_textures_file_path) cabal_map_file_tile_textures = [] for i in range(64): cabal_map_file_tile_texture = parse_cabal_map_file_tile_texture(cabal_map_file, i) cabal_map_file_tile_textures.append(cabal_map_file_tile_texture) return cabal_map_file_tile_textures def parse_cabal_map_file_terrain_texture(cabal_map_file, cabal_map_file_terrain_texture_index): print("parse terrain texture at {0:x}".format(cabal_map_file.tell())) cabal_map_file_terrain_textures_file_path = os.path.splitext(cabal_map_file.name)[0] cabal_map_file_terrain_texture = None cabal_map_file_terrain_texture_size = struct.unpack('<I', cabal_map_file.read(4))[0] if cabal_map_file_terrain_texture_size > 0: cabal_map_file_terrain_texture_data = cabal_map_file.read(cabal_map_file_terrain_texture_size) cabal_map_file_terrain_texture_file_path = os.path.normpath(os.path.join(cabal_map_file_terrain_textures_file_path, "terrain{0}.dds".format(cabal_map_file_terrain_texture_index))) if os.path.isfile(cabal_map_file_terrain_texture_file_path) == False: with open(cabal_map_file_terrain_texture_file_path, 'w+b') as cabal_map_file_terrain_texture_file: cabal_map_file_terrain_texture_file.write(cabal_map_file_terrain_texture_data) return cabal_map_file_terrain_texture def parse_cabal_map_file_terrain_textures(cabal_map_file): cabal_map_file_terrain_textures_file_path = os.path.splitext(cabal_map_file.name)[0] if os.path.isdir(cabal_map_file_terrain_textures_file_path) == False: os.mkdir(cabal_map_file_terrain_textures_file_path) cabal_map_file_terrain_texture_count, \ cabal_map_file_terrain_texture_unknown1 = struct.unpack('<2I', cabal_map_file.read(8)) cabal_map_file_terrain_textures = [] for i in range(cabal_map_file_terrain_texture_count - 1): cabal_map_file_terrain_texture = parse_cabal_map_file_terrain_texture(cabal_map_file, i) cabal_map_file_terrain_textures.append(cabal_map_file_terrain_texture) return cabal_map_file_terrain_textures def parse_cabal_map_file_external_objects(cabal_map_file): cabal_map_file_external_object_count = struct.unpack('<I', cabal_map_file.read(4))[0] cabal_map_file_external_objects = [] for i in range(cabal_map_file_external_object_count): print("parse external object at {0:x}".format(cabal_map_file.tell())) cabal_map_file_external_object_file_path_length = struct.unpack('<H', cabal_map_file.read(2))[0] cabal_map_file_external_object_file_path = '' if cabal_map_file_external_object_file_path_length > 0: cabal_map_file_external_object_file_path = cabal_map_file.read(cabal_map_file_external_object_file_path_length) cabal_map_file.seek(16, os.SEEK_CUR) # todo: load external object return cabal_map_file_external_objects def parse_cabal_map_file(cabal_map_file): cabal_map_file_magic = struct.unpack('<I', cabal_map_file.read(4))[0] if cabal_map_file_magic != 0x3ED: return cabal_map_file.seek(128, os.SEEK_CUR) cabal_map_file_external_objects = parse_cabal_map_file_external_objects(cabal_map_file) cabal_map_file_terrain_textures = parse_cabal_map_file_terrain_textures(cabal_map_file) cabal_map_file.seek(526352, os.SEEK_CUR) cabal_map_file_tile_tile_textures = parse_cabal_map_file_tile_textures(cabal_map_file) cabal_map_file_tile_objects = parse_cabal_map_file_tile_objects(cabal_map_file) return cabal_map_file_tile_objects def import_cabal_map_file_from_path(cabal_map_file_path, context): with io.open(cabal_map_file_path, mode='r+b') as cabal_map_file: cabal_map_file_tile_objects = parse_cabal_map_file(cabal_map_file) for cabal_map_file_tile_object in cabal_map_file_tile_objects: context.scene.objects.link(cabal_map_file_tile_object) class IMPORT_OT_cabal_mcl(bpy.types.Operator): '''Import CABAL mcl''' bl_idname = "import_scene.cabal_mcl" bl_label = 'Import CABAL mcl' path = bpy.props.StringProperty(name="File Path", description="CABAL mcl file path", maxlen= 1024, default= "") def execute(self, context): import_cabal_map_file_from_path(self.properties.path, context) return ('FINISHED',) def invoke(self, context, event): window_manager = context.manager window_manager.add_fileselect(self) return ('RUNNING_MODAL',) menu_function = lambda self, context: self.layout.operator(IMPORT_OT_cabal_mcl.bl_idname, text="CABAL Map (.mcl)...") def register(): bpy.types.register(IMPORT_OT_cabal_mcl) bpy.types.INFO_MT_file_import.append(menu_function) def unregister(): bpy.types.unregister(IMPORT_OT_cabal_mcl) bpy.types.INFO_MT_file_import.remove(menu_function) if __name__ == "__main__": register()