适用于非分层变换,以分层骨架? [英] apply non-hierarchial transforms to hierarchial skeleton?
问题描述
我用Blender3D,但答案可能并不API独占。
I use Blender3D, but the answer might not API-exclusive.
我有一些矩阵我需要分配到PoseBones。由此产生的姿势看起来不错时,有没有骨骼层次(养育)和搞砸了的时候有。
I have some matrices I need to assign to PoseBones. The resulting pose looks fine when there is no bone hierarchy (parenting) and messed up when there is.
我已经上传样本混合的被操纵模型,文字动画进口商这里测试动画文件存档:
http://www.2shared.com/file/5qUjmnIs/sample_files.html
通过选择电枢和运行SBA文件中的进口商导入动画。
执行此操作为电枢。
I've uploaded an archive with sample blend of the rigged models, text animation importer and a test animation file here:
http://www.2shared.com/file/5qUjmnIs/sample_files.html
Import the animation by selecting an Armature and running the importer on "sba" file.
Do this for both Armatures.
这是我在现实(复)进口商指定的姿势:
This is how I assign the poses in the real (complex) importer:
matrix_bases = ... # matrix from file
animation_matrix = matrix_basis * pose.bones['mybone'].matrix.copy()
pose.bones[bonename].matrix = animation_matrix
如果我去到编辑模式,选择所有的骨骼和preSS Alt键+ P撤消育儿,姿势又看起来很好。
If I go to edit mode, select all bones and press Alt+P to undo parenting, the Pose looks fine again.
API文档说,PoseBone.matrix在对象空间,但它似乎很清楚,我从这些测试,它们是相对于父骨骼。
The API documentation says the PoseBone.matrix is in "object space", but it seems clear to me from these tests that they are relative to parent bones.
最后4x4矩阵约束和驱动程序应用后(对象 空间)
Final 4x4 matrix after constraints and drivers are applied (object space)
我试图做这样的事情:
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
但它看起来更糟。尝试了操作顺序,没有运气了所有。
But it looks worse. Experimented with order of operations, no luck with all.
有关的记录,在旧的2.4 API这个工作就像一个魅力:
For the record, in the old 2.4 API this worked like a charm:
matrix_basis = ... # matrix from file
animation_matrix = armature.bones['mybone'].matrix['ARMATURESPACE'].copy() * matrix_basis
pose.bones[bonename].poseMatrix = animation_matrix
pose.update()
链接到搅拌机API参考:
Link to Blender API ref:
<一个href="http://www.blender.org/documentation/blender_python_api_2_63_17/bpy.types.BlendData.html#bpy.types.BlendData" rel="nofollow">http://www.blender.org/documentation/blender_python_api_2_63_17/bpy.types.BlendData.html#bpy.types.BlendData
<一个href="http://www.blender.org/documentation/blender_python_api_2_63_17/bpy.types.PoseBone.html#bpy.types.PoseBone" rel="nofollow">http://www.blender.org/documentation/blender_python_api_2_63_17/bpy.types.PoseBone.html#bpy.types.PoseBone
推荐答案
对象空间可能并不意味着相对于父骨骼。你可以乘倍母公司的倒数全球转换为本地变换的矩阵。您还可能会发现,你会希望所有家长逆的串联繁殖转变:乘B1 *逆(B0)和B2 *(逆(B1)*逆(B0))
'object space' probably does mean relative to the parent bone. You can convert from global to local by multiplying times the inverse of the parent transform's matrix. You may also find that you'll want to multiply by the concatenation of all parent inverse transforms: multiply B1 * inverse(B0), and B2 * (inverse(B1) * inverse(B0)).
下面是一些例子code,做类似的东西(在Panda3D中,没有搅拌机,但同样的总体思路)。我们有3个骨头全球位置和旋转值,父他们开始在一起,并将其转换全球坐标到正确的地方的矩阵。
Here's some example code that does something similar (in Panda3D, not Blender, but same general idea). We start off with 3 bones with global position and rotation values, parent them together, and convert the global coordinates into the correct local matrices.
# 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)
这篇关于适用于非分层变换,以分层骨架?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!