Esempio n. 1
0
    def ensure_uniform_scale(self):
        if self.is_bounding_box:
            return

        l, r, s = decompose(self.matrix_local)

        if not np.allclose(s[:1], s[1:], rtol=0, atol=0.001):
            print(f"[INFO] {self.name} has non-uniform scale")

            if self.source.type == "MESH":
                self.vertex_transform = s

            self.matrix_local = compose(l, r, 1)
            for child in self.children:
                child.matrix_local[:3, :3] *= s

        for child in self.children:
            child.ensure_uniform_scale()
Esempio n. 2
0
    def correct_rest_positions(self):
        """Correct the rest pose of the root bone.

        The rest pose of vanilla assets often feature inconvenient transforms.
        This is not an issue in-game since you would only ever see actors with
        their animations applied. When working in Blender however, a sane rest
        pose will make the lives of artists much easier.

        This function replaces the root bone's rest matrix with an edited copy
        of its posed matrix. This edited copy is identical to pose matrix with
        regards to location and scale, but has had its rotation about all axes
        aligned to the nearest 90 degree angle.
        """
        if not self.armatures:
            return

        root = self.get_armature_node()
        root_bone = next(self.iter_bones(root))

        # calculate corrected transformation matrix
        l, r, s = decompose(root_bone.matrix_posed)
        r = nif_utils.snap_rotation(r)
        corrected_matrix = compose(l, r, s)

        # only do corrections if they are necessary
        if np.allclose(root_bone.matrix_world,
                       corrected_matrix,
                       rtol=0,
                       atol=1e-6):
            return

        # correct the rest matrix of skinned meshes
        inverse = la.inv(root_bone.matrix_world)
        for node in self.get_skinned_meshes():
            if root_bone not in node.parents:
                node.matrix_world = corrected_matrix @ (
                    inverse @ node.matrix_world)

        # correct the rest matrix of the root bone
        root_bone.matrix_world = corrected_matrix
Esempio n. 3
0
    def correct_rest_positions(self):
        if not self.armatures:
            return

        root = self.get(*self.armatures)  # __history__
        root_bone = next(self.iter_bones(root))  # __history__

        # calculate corrected transformation matrix
        l, r, s = decompose(root_bone.matrix_posed)
        r = nif_utils.snap_rotation(r)
        corrected_matrix = compose(l, r, s)

        # correct the rest matrix of skinned meshes
        bone_inverse = la.inv(root_bone.matrix_world)
        for node in self.nodes:
            skin = getattr(node.source, "skin", None)
            if skin and (skin.root is root.source) and (root_bone
                                                        not in node.parents):
                node.matrix_world = corrected_matrix @ bone_inverse @ node.matrix_world

        # correct the rest matrix of the root bone
        root_bone.matrix_world = corrected_matrix
Esempio n. 4
0
 def matrix(self) -> ndarray:
     return compose(self.translation, self.rotation, self.scale)
Esempio n. 5
0
 def matrix(self):
     return compose(self.center, self.rotation, self.extents)
Esempio n. 6
0
 def matrix(self) -> ndarray:
     return compose(self.center, self.axes, self.extents)