2025年10月11日土曜日

シェイプキーとアーマチュアを関連付けて筋肉を表現してみたい2

退職を伝えた日は仏滅だったのですが、吉日だったそうです。ひと粒万倍日とかだそうで…生涯初めて1年で2回退職しましたが、これは3回目もあるんでしょうか?
その会社の事務の方から電話がかかってきましたがひたすら謝られてしまいました。いや、今どきこんな昭和みたいな会社あるんやなあとは思いましたが、特に謝られるような事は…私と同日に入社1週間で辞めた方とは揉めたんでしょうか?
定期的に人事がえらいことになっているのかもしれません。
又、丁度国税調査をやっていましたが…確かに調査対象の日程は就業してましたが回答する時点では退職しているんですよね…これ、情勢と合わないのでは?

さておき、今日も元気にプログラムです
とりあえず、ボーン名決め打ち(test_bone)で伸縮割合を出すプログラムを書いていきます。最初に考えるべきは、このプラグインの主体ですが、アーマチュアとシェイプキーを割り当てられたメッシュオブジェクトが主体になります。なので、プラグインはオブジェクトモードで起動する事にします。

コード開始

import bpy
import math

while bpy.context.mode == 'OBJECT':

    scene = bpy.context.scene
    
    frame_backup = scene.frame_current
    frame_start  = scene.frame_start
    frame_end    = scene.frame_end
    frame_step   = scene.frame_step

    for obj in bpy.context.selected_objects:
        if obj.type != 'MESH':
            continue

        # find allocation bone
        arm = obj.find_armature()
        if not arm:
            continue
        
        # find allocation shape
        shape_keys = bpy.data.meshes[obj.name].shape_keys
        if not shape_keys:
            continue

        bone = arm.pose.bones["test_bone"
        length = arm.data.bones["test_bone"].length
        
        # frame loop
        for frame in range(frame_start,frame_end+frame_step,frame_step):
            scene.frame_set(frame)
            
            vec = bone.head - bone.tail
            scalar = math.sqrt(vec.x*vec.x + vec.y+vec.y + vec.z*vec.z)
            print("frame/",frame,":length/",scalar / length)
            
        scene.frame_set(frame_backup)
    break

コードここまで

順を追って解説していきます。
最初は現フレームと開始/終了フレーム等を拾っています。

次に選択されたオブジェクトを拾うループに入ります。
拾ったオブジェクトに対して、メッシュオブジェクトか?アーマチュアが割り当てられているか?シェイプキーが割り当てられているか?
を調べ、該当しなければ処理から除外します。

次にオブジェクトに割り当てられたアーマチュアの中から名前決め打ち(test_bone)でボーンを抜いてきますが…
arm.pose.bones と arm.data.bones の2系統からデータを引いてきています。
pose の方はフレーム変化に伴うボーンの移動等により値が変化しますが、data の方は変化しません。どちらにもボーンの先頭と末尾を示す head tail のメンバーがあるのですが data の方は値が変化せず、結構ハマりました。

# frame loop 以降は各フレームでのボーンの長さを求めて、元々のボーンの長さで割り比率を求めています
ココで解説すべきは…

scalar = math.sqrt(vec.x*vec.x + vec.y+vec.y + vec.z*vec.z)

二乗の和の平方根=スカラ量≒ベクトルの長さ≒ボーンの現在の長さ
いやあ、スカラ量を求める計算なんてゲーム業界辞めてから20年近くやってなかったですね。まあ法線を必要とするプラグイン開発をしょっちゅうやっていたので流石にすぐに出ましたけど、覚えているもんなんですねえ。

で、結果がこんな感じに。
順調に値が変わっているのが見て取れます。次はこれらを使ってシェイプキーを打つプログラムですかね。

0 件のコメント:

コメントを投稿