【问题标题】:apply non-hierarchial transforms to hierarchial skeleton?将非分层变换应用于分层骨架?
【发布时间】:2012-07-28 04:10:02
【问题描述】:

我使用 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 矩阵(object 空间)

我试着做这样的事情:

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

【问题讨论】:

    标签: animation 3d matrix blender blender-2.61


    【解决方案1】:

    'object space' 可能确实意味着相对于父骨骼。您可以通过乘以父变换矩阵的逆矩阵从全局转换为局部。您可能还会发现您需要乘以所有父逆变换的串联:乘 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)
    

    【讨论】:

    • 经过一些测试,这里的“对象空间”实际上是“相对于骨架原点的位置”,而是“相对于父骨骼的旋转”。我尝试相应地更改我的代码,但没有运气。 blender.org/forum/viewtopic.php?p=98632#98632
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-09
    • 2015-12-23
    • 2019-01-27
    • 1970-01-01
    • 1970-01-01
    • 2011-11-30
    • 1970-01-01
    相关资源
    最近更新 更多