diff --git a/tools/sim_people/nurse_oshiro/README.md b/tools/sim_people/nurse_oshiro/README.md index cd6298f..98c894e 100644 --- a/tools/sim_people/nurse_oshiro/README.md +++ b/tools/sim_people/nurse_oshiro/README.md @@ -46,7 +46,9 @@ ## 動かした時に気をつけたこと -- 袖は胴とつなげず、別の部品にしてある。つなげると、腕を前に出した時に袖と胴の継ぎ目が裂けて、すき間から肌が見えた。袖は付け根の4cmだけ肩の骨と分け合い、そこから先は上腕の骨だけで動く +- 袖は胴とつなげず、別の部品にしてある。つなげると、腕を前に出した時に袖と胴の継ぎ目が裂けて、すき間から肌が見えた。袖はまるごと上腕の骨だけで動く(付け根を肩の骨と分け合うと、腕を上げた時に袖の山がゆがんだ・2026-11-13) +- 面の向きは marching_cubes のまま(外向き)。前の版は逆にしていて、Unity で全部の部品の面が裏返っていた(依頼162 の報告・2026-11-13 に直した) +- パンツは腰と太ももの重みの境目を広めにしてある(しゃがむと付け根の面が細かく折れたため)。深くしゃがむと、ひざと付け根に面の少なさから来るしわが少し残る - 袖の中に隠れる腕の付け根の肌は作っていない(服がのびた時に肌が服から突き出ないように) - 指の骨の z 軸は手のひらに向けてある。骨の x 軸まわりに回すと、指が手のひらのほうへ曲がる(握る・つかむ) - 胴の服の重みは高さで Hips・Spine・Chest に分け、境目はなめらかにつないである(おじぎで胴を曲げても段にならない) diff --git a/tools/sim_people/nurse_oshiro/nurse_build.py b/tools/sim_people/nurse_oshiro/nurse_build.py index b1ada99..0565dfe 100644 --- a/tools/sim_people/nurse_oshiro/nurse_build.py +++ b/tools/sim_people/nurse_oshiro/nurse_build.py @@ -364,7 +364,7 @@ def mesh_of(fn, lo, hi, vox): def to_blender(name, v, f, col, rough=0.6, sss=0.0, ratio=None): me = bpy.data.meshes.new(name) - me.from_pydata(v.tolist(), [], f[:, ::-1].tolist()) + me.from_pydata(v.tolist(), [], f.tolist()) # marching_cubes の向きのままで外向き(逆にすると Unity で全部の面が裏返った・依頼162) me.update() ob = bpy.data.objects.new(name, me) bpy.context.scene.collection.objects.link(ob) @@ -513,7 +513,9 @@ def weight_mesh(ob, kind): names = list(R) D = np.stack([R[k] for k in names]) dmin = D.min(axis=0) - W = np.stack([np.exp(-np.maximum(D[i] - dmin, 0) / tau_of(k)) for i, k in enumerate(names)]) + # パンツは腰と太ももの境目を広くなだらかにする(しゃがむと付け根の面が細かく折れた・依頼162) + tau = (lambda k: 0.045 if k == "Hips" or "UpperLeg" in k else tau_of(k)) if kind == "pants" else tau_of + W = np.stack([np.exp(-np.maximum(D[i] - dmin, 0) / tau(k)) for i, k in enumerate(names)]) W = W / W.sum(axis=0) top4 = np.argsort(-W, axis=0)[:4] groups = {k: ob.vertex_groups.new(name=k) for k in names} @@ -527,22 +529,11 @@ def weight_mesh(ob, kind): def weight_sleeves(ob): - """袖:付け根(腕の骨の根元から 4cm)だけ肩の骨と分け合い、そこから先は腕の骨だけ""" - gs = {} + """袖はまるごと上腕の骨に付ける(付け根を肩の骨と分け合うと、腕を上げた時に袖の山がゆがんだ)。 + 袖の山は肩の関節のすぐ外にあるので、腕と一緒に回しても肩から離れない""" for side, L in ((1, "Left"), (-1, "Right")): - sh, _, _, d1, _ = arm_points(side) - ga = ob.vertex_groups.new(name=L + "UpperArm") - gsh = ob.vertex_groups.new(name=L + "Shoulder") - for v in ob.data.vertices: - if v.co.x * side <= 0: - continue - proj = float(np.dot(np.array(v.co) - sh, d1)) - w = min(max((proj + 0.01) / 0.04, 0.0), 1.0) - if w > 0: - ga.add([v.index], w, "REPLACE") - if w < 1: - gsh.add([v.index], 1 - w, "REPLACE") - return gs + g = ob.vertex_groups.new(name=L + "UpperArm") + g.add([v.index for v in ob.data.vertices if v.co.x * side > 0], 1.0, "REPLACE") def weight_whole(ob, bone):