3

私は Blender3D を使用していますが、答えは API 専用ではないかもしれません。

PoseBones に割り当てる必要のあるマトリックスがいくつかあります。結果として得られるポーズは、ボーン階層 (親子関係) がない場合はきれいに見えますが、ある場合は台無しになります。 ここに画像の説明を入力

リグ モデルのサンプル ブレンド、テキスト アニメーション インポーター、およびテスト アニメーション ファイルを含むアーカイブをここにアップロードしました : http://www.2shared.com/file/5qUjmnIs/sample_files.html
「sba」ファイルのインポーター。両方のアーマチュアに対してこれを行います。

これは、実際の (複雑な) インポーターでポーズを割り当てる方法です。

matrix_bases = ... # matrix from file
animation_matrix = matrix_basis * pose.bones['mybone'].matrix.copy()
pose.bones[bonename].matrix = animation_matrix

編集モードに移動し、すべてのボーンを選択して Alt+P を押してペアレント化を元に戻すと、ポーズが再び正常に表示されます。

API ドキュメントには、PoseBone.matrix は「オブジェクト スペース」にあると書かれていますが、これらのテストから、それらが親ボーンに相対的であることは明らかです。

制約とドライバーが適用された後の最終的な 4x4 マトリックス (オブジェクト 空間)

私はこのようなことをしてみました:

matrix_basis = ... # matrix from file
animation_matrix = matrix_basis * (pose.bones['mybone'].matrix.copy()  * pose.bones[bonename].bone.parent.matrix_local.copy().inverted())
pose.bones[bonename].matrix = animation_matrix

しかし、それは悪く見えます。操作の順序を実験しましたが、すべてうまくいきませんでした。

記録として、古い 2.4 API では、これは魅力的に機能しました。

matrix_basis = ... # matrix from file
animation_matrix = armature.bones['mybone'].matrix['ARMATURESPACE'].copy() * matrix_basis
pose.bones[bonename].poseMatrix = animation_matrix

pose.update()

Blender API リファレンスへのリンク:

http://www.blender.org/documentation/blender_python_api_2_63_17/bpy.types.BlendData.html#bpy.types.BlendData

http://www.blender.org/documentation/blender_python_api_2_63_17/bpy.types.PoseBone.html#bpy.types.PoseBone

4

1 に答える 1

0

「オブジェクト スペース」は、おそらく親ボーンに対する相対的な意味です。親変換の行列の逆数を掛けることで、グローバルからローカルに変換できます。また、すべての親逆変換の連結を掛けたいと思うかもしれません: B1 * inverse(B0) と B2 * (inverse(B1) * inverse(B0)) を掛けます。

これは、似たようなことを行うサンプルコードです (Panda3D では、Blender ではなく、同じ一般的な考え方です)。グローバルな位置と回転の値を持つ 3 つのボーンから始めて、それらを一緒にペアレント化し、グローバル座標を正しいローカル マトリックスに変換します。

    # Load three boxes ('bones'), give them global position and rotation
    # each is 3 units long, at a 30 degree angle.  

    self.bone1=loader.loadModel("box.egg")
    self.bone1.reparentTo(render)

    self.bone2=loader.loadModel("box.egg")
    self.bone2.reparentTo(self.bone1)

    self.bone3=loader.loadModel("box.egg")
    self.bone3.reparentTo(self.bone2)

    ''' 
    equivalent code, in local coordinates
    self.bone1.setPos(0,0,0)
    self.bone1.setHpr(0,0,30)

    self.bone2.setPos(0,0,3)
    self.bone2.setHpr(0,0,30)

    self.bone3.setPos(0,0,3)
    self.bone3.setHpr(0,0,30)
    '''

    # give each a global rotation value

    R1=Mat4()
    R1.setRotateMat(30,Vec3(0,1,0))

    R2=Mat4()
    R2.setRotateMat(60,Vec3(0,1,0))

    R3=Mat4()
    R3.setRotateMat(90,Vec3(0,1,0))

    # set global translation values

    T1=Mat4()

    # position of bone 2 in global coords
    T2 = Mat4.translateMat(1.271,0,2.606) 

    # position of bone 3 in global coords
    T3 = Mat4.translateMat(3.782,0,4.036) 

    # set the matrix for bone 1
    M1 = R1 * T1
    self.bone1.setMat(M1)

    # get inverse of matrix of parent
    I1 = Mat4()
    I1.invertFrom (M1)

    # multiply bone2 matrix times inverse of parent

    M2 = R2 * T2
    M2 = M2 * I1

    self.bone2.setMat(M2)

    # get inverse of parent for next bone 

    I2 = Mat4()
    I2.invertFrom(M2)

    M3 = R3 * T3
    # notice that M3 * I2 isn't enough - needs to be M3 * (I1 * I2)
    M3 =  M3 * (I1 * I2)

    self.bone3.setMat(M3)
于 2012-08-22T06:23:02.163 に答える