From e557fd4eafb170f9e2f58b732e8ae0d0914af8a4 Mon Sep 17 00:00:00 2001 From: lisyarus Date: Tue, 22 Feb 2022 22:17:58 +0300 Subject: [PATCH] Rewrite convert-mesh: support both flat & non-flat shading in one model, support specifying model name --- tools/convert-mesh/CMakeLists.txt | 13 +-- tools/convert-mesh/bin/convert-mesh.py | 121 ++++++++++--------------- 2 files changed, 56 insertions(+), 78 deletions(-) diff --git a/tools/convert-mesh/CMakeLists.txt b/tools/convert-mesh/CMakeLists.txt index 60253cd1..35da03c4 100644 --- a/tools/convert-mesh/CMakeLists.txt +++ b/tools/convert-mesh/CMakeLists.txt @@ -11,23 +11,24 @@ function(psemek_add_model TARGET) while(ARGN) list(GET ARGN 0 _FILE) - list(GET ARGN 1 _NAME) - list(REMOVE_AT ARGN 0 1) + list(GET ARGN 1 _MODEL_NAME) + list(GET ARGN 2 _RESOURCE_NAME) + list(REMOVE_AT ARGN 0 1 2) - get_filename_component(_NAME_PREFIX ${_NAME} DIRECTORY) + get_filename_component(_NAME_PREFIX ${_RESOURCE_NAME} DIRECTORY) file(MAKE_DIRECTORY "${_OUT_DIR}/meshes/${_NAME_PREFIX}") - set(_OUT_FILE "${_OUT_DIR}/meshes/${_NAME}") + set(_OUT_FILE "${_OUT_DIR}/meshes/${_RESOURCE_NAME}") set(_SCRIPT "${PSEMEK_CONVERT_MESH_DIR}/bin/convert-mesh.py") add_custom_command(OUTPUT "${_OUT_FILE}" - COMMAND blender --background "${_FILE}" --python "${_SCRIPT}" --python-exit-code 1 -- "${_OUT_FILE}" + COMMAND blender --background "${_FILE}" --python "${_SCRIPT}" --python-exit-code 1 -- "${_MODEL_NAME}" "${_OUT_FILE}" DEPENDS "${_FILE}" "${_SCRIPT}" WORKING_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}" ) - psemek_add_resources(${TARGET} "${_OUT_FILE}" ${_NAME}) + psemek_add_resources(${TARGET} "${_OUT_FILE}" ${_RESOURCE_NAME}) endwhile() endfunction() diff --git a/tools/convert-mesh/bin/convert-mesh.py b/tools/convert-mesh/bin/convert-mesh.py index d93664d6..bd7d5e55 100644 --- a/tools/convert-mesh/bin/convert-mesh.py +++ b/tools/convert-mesh/bin/convert-mesh.py @@ -3,18 +3,18 @@ import math import sys import struct +model_name = sys.argv[sys.argv.index('--') + 1] +filename = sys.argv[sys.argv.index('--') + 2] + bpy.ops.object.mode_set(mode = 'OBJECT') obj = None mesh = None -flat = False -if 'mesh' in bpy.data.objects: - obj = bpy.data.objects['mesh'] - print('Using smooth normals') -if 'mesh_flat' in bpy.data.objects: - obj = bpy.data.objects['mesh_flat'] - print('Using flat normals') - flat = True +if model_name in bpy.data.objects: + obj = bpy.data.objects[model_name] +else: + raise RuntimeError("Model " + model_name + " not found in file") + mesh = obj.data colors = None @@ -27,6 +27,7 @@ if len(mesh.uv_layers) > 0: texcoords = mesh.uv_layers.active.data print('Found texture coordinates') +# TODO: proper armature support armature = None bone_names = None if 'armature' in bpy.data.objects: @@ -59,73 +60,51 @@ indices = [] mesh.calc_loop_triangles() -if flat: - for p in mesh.loop_triangles: - for li in p.loops: - i = len(vertex_coords) - v = mesh.vertices[mesh.loops[li].vertex_index] - vertex_coords.append((v.co.x, v.co.y, v.co.z)) - vertex_normals.append((p.normal.x, p.normal.y, p.normal.z)) - if colors: - vertex_colors.append(tuple(colors[li].color)) - if texcoords: - vertex_texcoords.append(tuple(texcoords[li].uv)) - if armature: - weights = [] - for g in v.groups: - name = obj.vertex_groups[g.group].name - if name in bone_names: - weights.append((bone_names.index(name), g.weight)) - for g, w in weights: - if g >= len(armature.data.bones): - print("Invalid vertex group index {} for armature weights".format(g), file=sys.stderr) - sys.exit(1) - weights = list(sorted(weights, key=lambda p: -p[1]))[:2] - while len(weights) < 2: - weights.append((0,0.0)) - weights = list(sorted(weights, key=lambda p: -p[1]))[:2] - W = sum(p[1] for p in weights) - weights = [(i,w/W) for i,w in weights] - vertex_weights[vi] = weights - indices.append(i) - -else: - for v in mesh.vertices: - vertex_coords.append((v.co.x, v.co.y, v.co.z)) - vertex_normals.append((v.normal.x, v.normal.y, v.normal.z)) +smooth_index = {} +def append_vertex(v, n): + vertex_coords.append((v.co.x, v.co.y, v.co.z)) + vertex_normals.append((n.x, n.y, n.z)) if colors: - vertex_colors = [None] * len(vertex_coords) + vertex_colors.append(tuple(colors[li].color)) if texcoords: - vertex_texcoords = [None] * len(vertex_coords) + vertex_texcoords.append(tuple(texcoords[li].uv)) if armature: - vertex_weights = [None] * len(vertex_coords) + weights = [] + for g in v.groups: + name = obj.vertex_groups[g.group].name + if name in bone_names: + weights.append((bone_names.index(name), g.weight)) + for g, w in weights: + if g >= len(armature.data.bones): + print("Invalid vertex group index {} for armature weights".format(g), file=sys.stderr) + sys.exit(1) + while len(weights) < 2: + weights.append((0,0.0)) + weights = list(sorted(weights, key=lambda p: -p[1]))[:2] + W = sum(p[1] for p in weights) + weights = [(i,w/W) for i,w in weights] + vertex_weights.append(weights) - for p in mesh.loop_triangles: - for li in p.loops: - vi = mesh.loops[li].vertex_index - indices.append(vi) - v = mesh.vertices[vi] - if colors: - vertex_colors[vi] = tuple(colors[li].color) - if texcoords: - vertex_texcoords[vi] = tuple(texcoords[li].uv) - if armature: - weights = [] - for g in v.groups: - name = obj.vertex_groups[g.group].name - if name in bone_names: - weights.append((bone_names.index(name), g.weight)) - for g, w in weights: - if g >= len(armature.data.bones): - print("Invalid vertex group index {} for armature weights".format(g), file=sys.stderr) - sys.exit(1) - weights = list(sorted(weights, key=lambda p: -p[1]))[:2] - while len(weights) < 2: - weights.append((0,0.0)) - W = sum(p[1] for p in weights) - weights = [(i,w/W) for i,w in weights] - vertex_weights[vi] = weights +for p in mesh.loop_triangles: + for li in p.loops: + vi = mesh.loops[li].vertex_index + v = mesh.vertices[vi] + n = p.normal + if p.use_smooth: + i = None + if vi not in smooth_index: + i = len(vertex_coords) + smooth_index[vi] = i + append_vertex(v, n) + else: + i = smooth_index[vi] + + indices.append(i) + else: + i = len(vertex_coords) + append_vertex(v, n) + indices.append(i) assert (len(indices) % 3) == 0 @@ -267,7 +246,5 @@ if armature: for name, pdata in poses: data += to_bytes((SECTION_POSE, name, pdata)) -filename = sys.argv[sys.argv.index('--') + 1] - with open(filename, 'wb') as f: f.write(data)