Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed incorrect mapping of meshes to blend shape bind mesh indices. #117

Merged
merged 1 commit into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 2 additions & 12 deletions addons/vrm/vrm_extension.gd
Original file line number Diff line number Diff line change
Expand Up @@ -480,22 +480,13 @@ func _create_animation_player(animplayer: AnimationPlayer, vrm_extension: Dictio
var nodes = gstate.get_nodes()
var blend_shape_groups = vrm_extension["blendShapeMaster"]["blendShapeGroups"]
# FIXME: Do we need to handle multiple references to the same mesh???
var mesh_idx_to_meshinstance: Dictionary = {}
var mesh_idx_to_meshinstance: Dictionary = vrm_utils.generate_mesh_index_to_meshinstance_mapping(gstate)
var material_name_to_mesh_and_surface_idx: Dictionary = {}
for i in range(meshes.size()):
var gltfmesh: GLTFMesh = meshes[i]
for j in range(gltfmesh.mesh.get_surface_count()):
material_name_to_mesh_and_surface_idx[gltfmesh.mesh.get_surface_material(j).resource_name] = [i, j]

for i in range(nodes.size()):
var gltfnode: GLTFNode = nodes[i]
var mesh_idx: int = gltfnode.mesh
#print("node idx " + str(i) + " node name " + gltfnode.resource_name + " mesh idx " + str(mesh_idx))
if mesh_idx != -1:
var scenenode: ImporterMeshInstance3D = gstate.get_scene_node(i)
mesh_idx_to_meshinstance[mesh_idx] = scenenode
#print("insert " + str(mesh_idx) + " node name " + scenenode.name)

var firstperson = vrm_extension["firstPerson"]

var reset_anim = Animation.new()
Expand All @@ -504,7 +495,6 @@ func _create_animation_player(animplayer: AnimationPlayer, vrm_extension: Dictio
for shape in blend_shape_groups:
#print("Blend shape group: " + shape["name"])
var anim = Animation.new()

for matbind in shape["materialValues"]:
var mesh_and_surface_idx = material_name_to_mesh_and_surface_idx[matbind["materialName"]]
var node: ImporterMeshInstance3D = mesh_idx_to_meshinstance[mesh_and_surface_idx[0]]
Expand Down Expand Up @@ -936,7 +926,7 @@ func _import_post(gstate: GLTFState, node: Node) -> Error:
if is_vrm_0:
# VRM 0.0 has models facing backwards due to a spec error (flipped z instead of x)
var blend_shape_names: Dictionary = vrm_utils._extract_blendshape_names(gltf_json)
vrm_utils.rotate_scene_180(root_node, blend_shape_names)
vrm_utils.rotate_scene_180(root_node, blend_shape_names, gstate)

var do_retarget = true

Expand Down
28 changes: 21 additions & 7 deletions addons/vrm/vrm_utils.gd
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ static func adjust_mesh_zforward(mesh: ImporterMesh, blendshapes: Array):
var mat: Material = surf_data_by_mesh[surf_idx].get("mat")
mesh.add_surface(prim, arr, bsarr, lods, mat, name, fmt_compress_flags)


static func rotate_scene_180_inner(p_node: Node3D, mesh_set: Dictionary, skin_set: Dictionary):
if p_node is Skeleton3D:
for bone_idx in range(p_node.get_bone_count()):
Expand All @@ -85,18 +84,34 @@ static func rotate_scene_180_inner(p_node: Node3D, mesh_set: Dictionary, skin_se
if child is Node3D:
rotate_scene_180_inner(child, mesh_set, skin_set)


static func rotate_scene_180(p_scene: Node3D, blend_shape_names: Dictionary):
static func generate_mesh_index_to_meshinstance_mapping(gstate : GLTFState) -> Dictionary:
var nodes = gstate.get_nodes()
var mesh_idx_to_meshinstance : Dictionary = {}
for i in range(nodes.size()):
var gltfnode: GLTFNode = nodes[i]
var mesh_idx: int = gltfnode.mesh
#print("node idx " + str(i) + " node name " + gltfnode.resource_name + " mesh idx " + str(mesh_idx))
if mesh_idx != -1:
var scenenode: ImporterMeshInstance3D = gstate.get_scene_node(i)
mesh_idx_to_meshinstance[mesh_idx] = scenenode
#print("insert " + str(mesh_idx) + " node name " + scenenode.name)
return mesh_idx_to_meshinstance

static func rotate_scene_180(p_scene: Node3D, blend_shape_names: Dictionary, gstate : GLTFState):
var mesh_set: Dictionary = {}
var skin_set: Dictionary = {}
rotate_scene_180_inner(p_scene, mesh_set, skin_set)
var mesh_index: int = 0
for mesh in mesh_set:

var mesh_idx_to_meshinstance : Dictionary = generate_mesh_index_to_meshinstance_mapping(gstate)

for mesh_index in mesh_idx_to_meshinstance.keys():
var mesh_node = mesh_idx_to_meshinstance[mesh_index]
var mesh = mesh_node.mesh
if mesh_index in blend_shape_names.keys():
adjust_mesh_zforward(mesh, blend_shape_names[mesh_index])
else:
adjust_mesh_zforward(mesh, [])
mesh_index += 1

for skin in skin_set:
for b in range(skin.get_bind_count()):
skin.set_bind_pose(b, ROTATE_180_TRANSFORM * skin.get_bind_pose(b) * ROTATE_180_TRANSFORM)
Expand Down Expand Up @@ -434,7 +449,6 @@ static func _generate_hide_bone_mesh(mesh: ImporterMesh, skin: Skin, bone_names_
new_mesh.add_surface(prim, arr, bsarr, lods, mat, name, fmt_compress_flags)
return new_mesh


static func perform_head_hiding(gstate: GLTFState, mesh_annotations_by_node: Dictionary, head_relative_bones: Dictionary, node_to_head_hidden_node: Dictionary):
var meshes = gstate.get_meshes()
var nodes = gstate.get_nodes()
Expand Down