def write_scene_file(): # write out nodes and transforms numjoints = len(joint_list) if numjoints == 0: return scene_data = [ struct.pack("i", (int(helpers.version_number))), struct.pack("i", (int(numjoints))) ] for j in range(numjoints): if joint_list[j] is None: joint_list[j] = "no_name" scene_data.append(struct.pack("i", (int(type_list[j])))) helpers.pack_parsable_string(scene_data, joint_list[j]) helpers.pack_parsable_string(scene_data, geom_attach_data_list[j]) scene_data.append( struct.pack("i", (int(len(material_attach_data_list[j]))))) for i in range(0, len(material_attach_data_list[j])): helpers.pack_parsable_string(scene_data, material_attach_data_list[j][i]) helpers.pack_parsable_string(scene_data, material_symbol_list[j][i]) parentindex = joint_list.index(parent_list[j]) scene_data.append(struct.pack("i", (int(parentindex)))) scene_data.append(struct.pack("i", (int(len(transform_list[j]))))) for t in transform_list[j]: splitted = t.split() transform_type_index = transform_types.index(splitted[0]) scene_data.append(struct.pack("i", (int(transform_type_index)))) for val in range(1, len(splitted)): scene_data.append(struct.pack("f", (float(splitted[val])))) helpers.output_file.scene.append(scene_data)
def write_geometry_file(geom_instance): # write out geometry num_meshes = len(geom_instance.meshes) if num_meshes == 0: return geometry_data = [ struct.pack("i", (int(helpers.version_number))), struct.pack("i", (int(num_meshes))) ] for mat in geom_instance.materials: if not mat: helpers.pack_parsable_string(geometry_data, "none") else: helpers.pack_parsable_string(geometry_data, mat) data_size = len(geometry_data) * 4 for mesh in geom_instance.meshes: mesh_data = [] # calulate index size num_floats = len(mesh.vertex_elements[0].float_values) num_vertices = num_floats / 4 index_type = "i" index_size = 4 if num_vertices < 65535: index_type = "H" index_size = 2 # write min / max extents for i in range(0, 3, 1): mesh_data.append(struct.pack("f", (float(mesh.min_extents[i])))) for i in range(0, 3, 1): mesh_data.append(struct.pack("f", (float(mesh.max_extents[i])))) # write info mesh_data.append(struct.pack( "i", int(0))) # handedness (left handed), for mesh opt mesh_data.append(struct.pack("i", int(num_vertices))) # num pos verts mesh_data.append(struct.pack("i", int(index_size))) # pos index size mesh_data.append(struct.pack( "i", (len(mesh.index_buffer)))) # pos buffer index count mesh_data.append(struct.pack("i", int(num_vertices))) # num vb verts mesh_data.append(struct.pack("i", int(index_size))) # vertex index size mesh_data.append(struct.pack( "i", (len(mesh.index_buffer)))) # vertex buffer index count # skinning is conditional, but write any fixed length data anyway skinned = 0 num_joint_floats = 0 bind_shape_matrix = [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] if geom_instance.controller: skinned = 1 num_joint_floats = len(geom_instance.controller.joint_bind_matrix) bind_shape_matrix = geom_instance.controller.bind_shape_matrix mesh_data.append(struct.pack("i", int(skinned))) mesh_data.append(struct.pack("i", int(num_joint_floats))) helpers.pack_corrected_4x4matrix(mesh_data, bind_shape_matrix) # now write data if num_joint_floats > 0: helpers.pack_corrected_4x4matrix( mesh_data, geom_instance.controller.joint_bind_matrix) # position only buffer for vertexfloat in mesh.vertex_elements[0].float_values: mesh_data.append(struct.pack("f", (float(vertexfloat)))) # vertex buffer for vertexfloat in mesh.vertex_buffer: mesh_data.append(struct.pack("f", (float(vertexfloat)))) data_size += len(mesh_data) * 4 # write index buffer twice, at this point they match, but after optimisation # the number of indices in position only vs vertex buffer may changes # position index buffer for index in mesh.index_buffer: mesh_data.append(struct.pack(index_type, (int(index)))) data_size += len(mesh.index_buffer) * 2 # vertex index buffer for index in mesh.index_buffer: mesh_data.append(struct.pack(index_type, (int(index)))) data_size += len(mesh.index_buffer) * 2 # top level pmm for m in mesh_data: geometry_data.append(m) helpers.output_file.geometry_names.append(geom_instance.name) helpers.output_file.geometry.append(geometry_data) helpers.output_file.geometry_sizes.append(data_size)
def write_geometry(file, root): basename = os.path.basename(file) full_path = os.path.join(root, file) obj_file = open(full_path) obj_data = obj_file.read().split('\n') vertex_info = [ ('v', 0, 3, [1.0]), ('vn', 1, 3, [1.0]), ('vt', 2, 2, [0.0, 0.0]), ] vertex_data = [[], [], []] min_extents = [sys.float_info.max, sys.float_info.max, sys.float_info.max] max_extents = [-sys.float_info.max, -sys.float_info.max, -sys.float_info.max] mat_name = 1 vb = 2 ib = 3 pb = 4 meshes = [] cur_mesh = None index = 0 flip_winding = False for line in obj_data: if line.find("pmtech_flip_winding") != -1: flip_winding = True element_raw = line.split(' ') element = [] # strip dead elems for e in element_raw: if e != '': element.append(e) if len(element) == 0: continue for vv in vertex_info: if element[0] == 'v': grow_extents(element[1:], min_extents, max_extents) if vv[0] == element[0]: vec = [] for i in range(0, vv[2]): vec.append(element[1+i]) for f in vv[3]: vec.append(f) vertex_data[vv[1]].append(vec) if element[0] == 'f': face_list = element[1:] if flip_winding: face_list.reverse() if not cur_mesh: cur_mesh = (basename, "obj_default", [], [], [], []) tri_list = [] if len(face_list) == 4: tri_list.append(face_list[0]) tri_list.append(face_list[1]) tri_list.append(face_list[2]) tri_list.append(face_list[2]) tri_list.append(face_list[3]) tri_list.append(face_list[0]) elif len(face_list) == 3: tri_list.append(face_list[0]) tri_list.append(face_list[1]) tri_list.append(face_list[2]) for trivert in tri_list: elem_indices = [0] if trivert.find("//") != -1: velems = trivert.split("//") elem_indices.append(1) else: velems = trivert.split("/") elem_indices.append(2) elem_indices.append(1) vertex = [[0.0, 0.0, 0.0, 1.0], # pos [0.0, 1.0, 0.0, 1.0], # normal [0.0, 0.0, 0.0, 1.0], # texcoord [1.0, 0.0, 0.0, 1.0], # tangent [0.0, 0.0, 1.0, 1.0]] # bitangent elem_index = 0 for vi in velems: ii = elem_indices[elem_index] li = int(vi)-1 if li < len(vertex_data[ii]): vertex[ii] = vertex_data[ii][li] for vf in vertex_data[ii][int(vi)-1]: if elem_index == 0: cur_mesh[pb].append(float(vf)) elem_index += 1 for v in vertex: for f in v: cur_mesh[vb].append(float(f)) cur_mesh[ib].append(index) index += 1 if element[0] == 'g': if cur_mesh: meshes.append(cur_mesh) cur_mesh = (element[1], "", [], [], [], []) index = 0 if element[0] == 'usemtl': if not cur_mesh: cur_mesh = (basename, element[0], [], [], [], []) if cur_mesh: meshes.append(cur_mesh) geometry_data = [struct.pack("i", (int(helpers.version_number))), struct.pack("i", (int(len(meshes))))] for m in meshes: helpers.pack_parsable_string(geometry_data, m[0]) data_size = len(geometry_data) * 4 for mesh in meshes: generated_vb = mesh[vb] if len(vertex_data[1]) == 0: generated_vb = calc_normals(generated_vb) generated_vb = calc_tangents(generated_vb) mesh_data = [] skinned = 0 num_joint_floats = 0 bind_shape_matrix = [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] num_verts = len(mesh[pb])/4 index_type = "i" index_size = 4 if num_verts < 65535: index_type = "H" index_size = 2 # write min / max extents for i in range(0, 3, 1): mesh_data.append(struct.pack("f", (float(min_extents[i])))) for i in range(0, 3, 1): mesh_data.append(struct.pack("f", (float(max_extents[i])))) # write vb and ib handedness = 0 if flip_winding: handedness = 1 mesh_data.append(struct.pack("i", int(handedness))) mesh_data.append(struct.pack("i", int(num_verts))) # num pos verts mesh_data.append(struct.pack("i", int(index_size))) # pos index size mesh_data.append(struct.pack("i", (len(mesh[ib])))) # pos buffer index count mesh_data.append(struct.pack("i", int(num_verts))) # num vb verts mesh_data.append(struct.pack("i", int(index_size))) # vertex index size mesh_data.append(struct.pack("i", (len(mesh[ib])))) # vertex buffer index count # skinning is not supported in obj, but write any fixed length data anyway mesh_data.append(struct.pack("i", int(skinned))) mesh_data.append(struct.pack("i", int(num_joint_floats))) mesh_data.append(struct.pack("i", int(0))) # bone offset helpers.pack_corrected_4x4matrix(mesh_data, bind_shape_matrix) for vf in mesh[pb]: # position only buffer mesh_data.append(struct.pack("f", (float(vf)))) for vf in generated_vb: mesh_data.append(struct.pack("f", (float(vf)))) data_size += len(mesh_data)*4 # write index buffer twice, at this point they match, but after optimisation # the number of indices in position only vs vertex buffer may changes for index in mesh[ib]: mesh_data.append(struct.pack(index_type, (int(index)))) data_size += len(mesh[ib]) * 2 for index in mesh[ib]: mesh_data.append(struct.pack(index_type, (int(index)))) data_size += len(mesh[ib]) * 2 for m in mesh_data: geometry_data.append(m) helpers.output_file.geometry_names.append(mesh[0]) helpers.output_file.geometry.append(geometry_data) helpers.output_file.geometry_sizes.append(data_size) scene_data = [struct.pack("i", int(helpers.version_number)), struct.pack("i", int(len(meshes))), struct.pack("i", int(0))] for m in meshes: scene_data.append(struct.pack("i", (int(0)))) # node type helpers.pack_parsable_string(scene_data, basename) helpers.pack_parsable_string(scene_data, m[0]) scene_data.append(struct.pack("i", int(1))) # num sub meshes # material name / symbol helpers.pack_parsable_string(scene_data, m[mat_name]) helpers.pack_parsable_string(scene_data, m[mat_name]) scene_data.append(struct.pack("i", (int(0)))) # parent scene_data.append(struct.pack("i", (int(1)))) # transform count scene_data.append(struct.pack("i", (int(3)))) # transform type helpers.output_file.scene.append(scene_data)
def write_geometry(file, root): basename = os.path.basename(file) full_path = os.path.join(root, file) obj_file = open(full_path) obj_data = obj_file.read().split('\n') vertex_info = [ ('v', 0, 3, [1.0]), ('vn', 1, 3, [1.0]), ('vt', 2, 2, [0.0, 0.0]), ] vertex_data = [[], [], []] min_extents = [sys.float_info.max, sys.float_info.max, sys.float_info.max] max_extents = [ -sys.float_info.max, -sys.float_info.max, -sys.float_info.max ] mat_name = 1 vb = 2 ib = 3 pb = 4 cb = 5 meshes = [] cur_mesh = None index = 0 flip_winding = False for line in obj_data: if line.find("pmtech_flip_winding") != -1: flip_winding = True element = line.split(' ') for vv in vertex_info: if element[0] == 'v': grow_extents(element[1:], min_extents, max_extents) if vv[0] == element[0]: vec = [] for i in range(0, vv[2]): vec.append(element[1 + i]) for f in vv[3]: vec.append(f) vertex_data[vv[1]].append(vec) if element[0] == 'f': face_list = element[1:] if flip_winding: face_list.reverse() if not cur_mesh: cur_mesh = (basename, "obj_default", [], [], [], []) tri_list = [] if len(face_list) == 4: tri_list.append(face_list[0]) tri_list.append(face_list[1]) tri_list.append(face_list[2]) tri_list.append(face_list[2]) tri_list.append(face_list[3]) tri_list.append(face_list[0]) elif len(face_list) == 3: tri_list.append(face_list[0]) tri_list.append(face_list[1]) tri_list.append(face_list[2]) for trivert in tri_list: elem_indices = [0] if trivert.find("//") != -1: velems = trivert.split("//") elem_indices.append(1) else: velems = trivert.split("/") elem_indices.append(2) elem_indices.append(1) vertex = [ [0.0, 0.0, 0.0, 1.0], # pos [0.0, 1.0, 0.0, 1.0], # normal [0.0, 0.0, 0.0, 1.0], # texcoord [1.0, 0.0, 0.0, 1.0], # tangent [0.0, 0.0, 1.0, 1.0] ] # bitangent elem_index = 0 for vi in velems: ii = elem_indices[elem_index] li = int(vi) - 1 if li < len(vertex_data[ii]): vertex[ii] = vertex_data[ii][li] for vf in vertex_data[ii][int(vi) - 1]: if elem_index == 0: cur_mesh[pb].append(float(vf)) cur_mesh[cb].append(float(vf)) elem_index += 1 for v in vertex: for f in v: cur_mesh[vb].append(float(f)) cur_mesh[ib].append(index) index += 1 if element[0] == 'g': if cur_mesh: meshes.append(cur_mesh) cur_mesh = (element[1], "", [], [], [], []) index = 0 if element[0] == 'usemtl': if not cur_mesh: cur_mesh = (basename, element[0], [], [], [], []) else: cur_mesh[mat_name] = element[0] if cur_mesh: meshes.append(cur_mesh) geometry_data = [ struct.pack("i", (int(helpers.version_number))), struct.pack("i", (int(len(meshes)))) ] for m in meshes: helpers.pack_parsable_string(geometry_data, m[0]) data_size = len(geometry_data) * 4 for mesh in meshes: generated_vb = mesh[vb] if len(vertex_data[1]) == 0: generated_vb = calc_normals(generated_vb) generated_vb = calc_tangents(generated_vb) mesh_data = [] # write min / max extents for i in range(0, 3, 1): mesh_data.append(struct.pack("f", (float(min_extents[i])))) for i in range(0, 3, 1): mesh_data.append(struct.pack("f", (float(max_extents[i])))) # write vb and ib mesh_data.append(struct.pack("i", (len(mesh[pb])))) mesh_data.append(struct.pack("i", (len(generated_vb)))) mesh_data.append(struct.pack("i", (len(mesh[ib])))) mesh_data.append(struct.pack("i", (len(mesh[cb])))) index_type = "i" if len(mesh[ib]) < 65535: index_type = "H" # obj always non-skinned mesh_data.append(struct.pack("i", int(0))) for vf in mesh[pb]: # position only buffer mesh_data.append(struct.pack("f", (float(vf)))) for vf in generated_vb: mesh_data.append(struct.pack("f", (float(vf)))) data_size += len(mesh_data) * 4 for index in mesh[ib]: mesh_data.append(struct.pack(index_type, (int(index)))) data_size += len(mesh[ib]) * 2 for vf in mesh[cb]: mesh_data.append(struct.pack("f", (float(vf)))) data_size += len(mesh[cb]) * 4 for m in mesh_data: geometry_data.append(m) helpers.output_file.geometry_names.append(mesh[0]) helpers.output_file.geometry.append(geometry_data) helpers.output_file.geometry_sizes.append(data_size) scene_data = [ struct.pack("i", (int(helpers.version_number))), struct.pack("i", (int(len(meshes)))) ] for m in meshes: scene_data.append(struct.pack("i", (int(0)))) # node type helpers.pack_parsable_string(scene_data, basename) helpers.pack_parsable_string(scene_data, m[0]) scene_data.append(struct.pack("i", int(1))) # num sub meshes # material name / symbol helpers.pack_parsable_string(scene_data, m[mat_name]) helpers.pack_parsable_string(scene_data, m[mat_name]) scene_data.append(struct.pack("i", (int(0)))) # parent scene_data.append(struct.pack("i", (int(1)))) # transform count scene_data.append(struct.pack("i", (int(3)))) # transform type helpers.output_file.scene.append(scene_data)
def pack_texture(output, tex): [fnoext, fext] = os.path.splitext(tex) tex = fnoext + ".dds" helpers.pack_parsable_string(output, tex)
def write_geometry_file(geom_instance): # write out geometry num_meshes = len(geom_instance.meshes) if num_meshes == 0: return geometry_data = [struct.pack("i", (int(helpers.version_number))), struct.pack("i", (int(num_meshes)))] for mat in geom_instance.materials: if not mat: helpers.pack_parsable_string(geometry_data, "none") else: helpers.pack_parsable_string(geometry_data, mat) data_size = len(geometry_data)*4 for mesh in geom_instance.meshes: # write collision info mesh_data = [] # write min / max extents for i in range(0, 3, 1): mesh_data.append(struct.pack("f", (float(mesh.min_extents[i])))) for i in range(0, 3, 1): mesh_data.append(struct.pack("f", (float(mesh.max_extents[i])))) # write vb and ib mesh_data.append(struct.pack("i", (len(mesh.vertex_elements[0].float_values)))) mesh_data.append(struct.pack("i", (len(mesh.vertex_buffer)))) mesh_data.append(struct.pack("i", (len(mesh.index_buffer)))) mesh_data.append(struct.pack("i", (len(mesh.collision_vertices)))) index_type = "i" if len(mesh.index_buffer) < 65535: index_type = "H" skinned = 0 if geom_instance.controller != None: skinned = 1 num_floats = len(mesh.vertex_elements[0].float_values) num_vertices = num_floats / 4 mesh_data.append(struct.pack("i", int(skinned))) if skinned: helpers.pack_corrected_4x4matrix(mesh_data, geom_instance.controller.bind_shape_matrix) mesh_data.append(struct.pack("i", len(geom_instance.controller.joint_bind_matrix))) helpers.pack_corrected_4x4matrix(mesh_data, geom_instance.controller.joint_bind_matrix) for vertexfloat in mesh.vertex_elements[0].float_values: # position only buffer mesh_data.append(struct.pack("f", (float(vertexfloat)))) for vertexfloat in mesh.vertex_buffer: mesh_data.append(struct.pack("f", (float(vertexfloat)))) data_size += len(mesh_data)*4 for index in mesh.index_buffer: mesh_data.append(struct.pack(index_type, (int(index)))) data_size += len(mesh.index_buffer) * 2 for vertexfloat in mesh.collision_vertices: mesh_data.append(struct.pack("f", (float(vertexfloat)))) data_size += len(mesh.collision_vertices) * 4 for m in mesh_data: geometry_data.append(m) helpers.output_file.geometry_names.append(geom_instance.name) helpers.output_file.geometry.append(geometry_data) helpers.output_file.geometry_sizes.append(data_size)