ボーン/ボールジョイントのワールド座標での中心位置を計算 (スクリプト)

ボーン/ボールジョイントのワールド座標での中心位置をスクリプトで計算します。

共通部分


import numpy
import math

# --------------------------------------.
# クォータニオンから4x4回転行列を計算.
# --------------------------------------.
def quaternion_matrix4x4 (q):
    m = numpy.matrix(numpy.identity(4))

    # q(w,x,y,z)から(x,y,z,w)に並べ替え.
    q2 = range(4)
    q2[0] = q[1]
    q2[1] = q[2]
    q2[2] = q[3]
    q2[3] = q[0]

    m[0,0] = q2[3]*q2[3] + q2[0]*q2[0] - q2[1]*q2[1] - q2[2]*q2[2]
    m[0,1] = 2.0 * q2[0] * q2[1] - 2.0 * q2[3] * q2[2]
    m[0,2] = 2.0 * q2[0] * q2[2] + 2.0 * q2[3] * q2[1]
    m[0,3] = 0.0

    m[1,0] = 2.0 * q2[0] * q2[1] + 2.0 * q2[3] * q2[2]
    m[1,1] = q2[3] * q2[3] - q2[0] * q2[0] + q2[1] * q2[1] - q2[2] * q2[2]
    m[1,2] = 2.0 * q2[1] * q2[2] - 2.0 * q2[3] * q2[0]
    m[1,3] = 0.0

    m[2,0] = 2.0 * q2[0] * q2[2] - 2.0 * q2[3] * q2[1]
    m[2,1] = 2.0 * q2[1] * q2[2] + 2.0 * q2[3] * q2[0]
    m[2,2] = q2[3] * q2[3] - q2[0] * q2[0] - q2[1] * q2[1] + q2[2] * q2[2]
    m[2,3] = 0.0

    m[3,0] = 0.0
    m[3,1] = 0.0
    m[3,2] = 0.0
    m[3,3] = q2[3] * q2[3] + q2[0] * q2[0] + q2[1] * q2[1] + q2[2] * q2[2]

    k = m[3,3]
    for i in range(3):
        for j in range(3):
            m[i,j] /= k

    m[3,3] = 1.0

    return m

# --------------------------------------.
# translateを4x4行列に変換.
# --------------------------------------.
def translate_matrix4x4 (pos):
    m = numpy.matrix(numpy.identity(4))
    m[3,0] = pos[0]
    m[3,1] = pos[1]
    m[3,2] = pos[2]
    return m

ボールジョイントのワールド座標での中心位置を計算


def calcBallJointWorldCenter(shape):
    cPos = numpy.array([0.0, 0.0, 0.0, 1.0])
    lwMat = numpy.matrix(shape.local_to_world_matrix)
    pos = shape.ball_joint.position
    joint_offset = shape.ball_joint.offset
    joint_rotate = quaternion_matrix4x4(shape.ball_joint.rotation)

    cPos2 = numpy.dot(cPos, joint_rotate)
    cPos2 = numpy.dot(cPos2, translate_matrix4x4(numpy.array(joint_offset) + numpy.array(pos)))
    cPos2 = numpy.dot(cPos2, lwMat)
    return numpy.array([cPos2[0,0], cPos2[0,1], cPos2[0,2]])

この計算は、以下も同じ結果になります。


def calcBallJointWorldCenter(shape):
    lwMat = numpy.matrix(shape.local_to_world_matrix)
    pos = shape.ball_joint.position
    m = numpy.matrix(shape.transformation_matrix).I
    m = numpy.dot(m, shape.transformation)
    cPos2 = numpy.array([pos[0], pos[1], pos[2], 1.0])
    cPos2 = numpy.dot(cPos2, m)
    cPos2 = numpy.dot(cPos2, lwMat)
    return numpy.array([cPos2[0,0], cPos2[0,1], cPos2[0,2]])

ボーンのワールド座標での中心位置を計算


def calcBoneWorldCenter(shape):
    cPos = numpy.array([0.0, 0.0, 0.0, 1.0])
    lwMat = numpy.matrix(shape.local_to_world_matrix)
    m = numpy.matrix(shape.bone_joint.matrix)
    joint_offset = shape.bone_joint.offset
    joint_rotate = quaternion_matrix4x4(shape.bone_joint.rotation)

    cPos2 = numpy.dot(cPos, joint_rotate)
    cPos2 = numpy.dot(cPos2, m)
    cPos2 = numpy.dot(cPos2, translate_matrix4x4(joint_offset))
    cPos2 = numpy.dot(cPos2, lwMat)
    return numpy.array([cPos2[0,0], cPos2[0,1], cPos2[0,2]])

この計算は、以下も同じ結果になります。


def calcBoneWorldCenter(shape):
    cPos = numpy.array([0.0, 0.0, 0.0, 1.0])
    lwMat = numpy.matrix(shape.local_to_world_matrix)
    m = numpy.matrix(shape.transformation)

    cPos2 = numpy.dot(cPos, m)
    cPos2 = numpy.dot(cPos2, lwMat)
    return numpy.array([cPos2[0,0], cPos2[0,1], cPos2[0,2]])

使用方法

上記の関数を使用して、選択形状がボールジョイントまたはボーンの場合、
ワールド座標での中心位置をメッセージウィンドウに表示します。


scene = xshade.scene()

shape = scene.active_shape()
cPos = [0.0, 0.0, 0.0]
if shape.is_ball_joint:     # ボールジョイントの場合.
    cPos = calcBallJointWorldCenter(shape)

if shape.is_bone_joint:     # ボーンの場合.
    cPos = calcBoneWorldCenter(shape)

print "center : " + str(cPos[0]) + ",  " + str(cPos[1]) + ", " + str(cPos[2])
この記事のタイトルとURLをコピーする
Translate »