def _process_node(self, node): mat = self._calc_mat(node) self._matrixes_local.append(mat) if node is self._bone.root: mat_g = mat4.translation(node.offset) * mat self.__last_matrix = mat_g self._matrixes_global.append(mat_g) self._positions.append(mat_g * (0, 0, 0)) else: self._positions.append(self.__last_matrix * node.offset) mat_g = self.__last_matrix * mat4.translation(node.offset) * mat self._matrixes_global.append(mat_g) for child in node.children: self.__last_matrix = mat_g self._process_node(child)
def test_calc_matrix(self): n1 = Node() n1.channels = ["Xposition", "Yposition", "Zposition"] n2 = Node() n2.channels = [] n3 = Node() n3.channels = ["Xrotation", "Yrotation", "Zrotation"] n1.children.append(n2) n2.children.append(n3) bone = BVHToolkit.Bone(n1) pose = BVHToolkit.Pose(bone, [10, 20, 30, 90, 90, 90]) m1 = mat4.translation((10, 20, 30)) m2 = mat4.rotation(math.pi / 2, (1, 0, 0)) * \ mat4.rotation(math.pi / 2, (0, 1, 0)) * \ mat4.rotation(math.pi / 2, (0, 0, 1)) self.assertMat4Equal(pose._calc_mat(n1), m1) self.assertMat4Equal(pose._calc_mat(n2), mat4.identity()) self.assertMat4Equal(pose._calc_mat(n3), m2)
def test_calc_matrix(self): n1 = Node() n1.channels = ["Xposition", "Yposition", "Zposition"] n2 = Node() n2.channels = [] n3 = Node() n3.channels = ["Xrotation", "Yrotation", "Zrotation"] n1.children.append(n2) n2.children.append(n3) bone = BVHToolkit.Bone(n1) pose = BVHToolkit.Pose(bone, [10, 20, 30, 90, 90, 90]) m1 = mat4.translation((10, 20, 30)) m2 = ( mat4.rotation(math.pi / 2, (1, 0, 0)) * mat4.rotation(math.pi / 2, (0, 1, 0)) * mat4.rotation(math.pi / 2, (0, 0, 1)) ) self.assertMat4Equal(pose._calc_mat(n1), m1) self.assertMat4Equal(pose._calc_mat(n2), mat4.identity()) self.assertMat4Equal(pose._calc_mat(n3), m2)
class Pose(object): """ Represent the pose of the bone in the specific frame. >>> from cgkit.bvh import Node >>> n0 = Node() >>> n0.channels = ["Xposition", "Yposition"] >>> n1 = Node() >>> n1.offset = (10, 0, 0) >>> n0.children.append(n1) >>> pose = Pose(Bone(n0), [0, 0]) >>> pose.get_position(n1) (10, 0, 0) >>> pose = Pose(Bone(n0), [10, 10]) >>> pose.get_position(n1) (20, 10, 0) """ @property def matrixes_global(self): return self._matrixes_global @property def matrixes_local(self): return self._matrixes_local @property def positions(self): return self._positions @property def bone(self): return self._bone @property def frame(self): return self._frame _mat_funcs = { "Xrotation": lambda rot: mat4.rotation(rot * math.pi / 180, [1, 0, 0]), "Yrotation": lambda rot: mat4.rotation(rot * math.pi / 180, [0, 1, 0]), "Zrotation": lambda rot: mat4.rotation(rot * math.pi / 180, [0, 0, 1]), "Xposition": lambda pos: mat4.translation((pos, 0, 0)), "Yposition": lambda pos: mat4.translation((0, pos, 0)), "Zposition": lambda pos: mat4.translation((0, 0, pos)), } def __init__(self, bone, frame): self._matrixes_global = [] self._matrixes_local = [] self._positions = [] self.__last_matrix = mat4.identity() self._bone = bone self._frame = frame self._process_node(bone.root) def _calc_mat(self, node): mat = mat4.identity() channels = node.channels param_offset = self._bone.get_param_offset(node) for i, channel in enumerate(channels): mat *= self._mat_funcs[channel](self._frame[param_offset + i]) return mat def _process_node(self, node): mat = self._calc_mat(node) self._matrixes_local.append(mat) if node is self._bone.root: mat_g = mat4.translation(node.offset) * mat self.__last_matrix = mat_g self._matrixes_global.append(mat_g) self._positions.append(mat_g * (0, 0, 0)) else: self._positions.append(self.__last_matrix * node.offset) mat_g = self.__last_matrix * mat4.translation(node.offset) * mat self._matrixes_global.append(mat_g) for child in node.children: self.__last_matrix = mat_g self._process_node(child) def get_position(self, index_or_node): """ Returns a global position of given node in the frame """ if type(index_or_node) is int: index = index_or_node else: index = self._bone.node_list.index(index_or_node) return self._positions[index]