예제 #1
0
 def create_motion_by_following(self, nodes):
     motion = velocity.MotionWithVelocity(skel=self.skel, fps=self.fps)
     for i in range(len(nodes) - 1):
         n1 = nodes[i]
         n2 = nodes[i + 1]
         nodes_inbetween = nx.shortest_path(self.graph, n1, n2)
         range_nodes = (
             range(len(nodes_inbetween))
             if i == len(nodes) - 2
             else range(len(nodes_inbetween) - 1)
         )
         for j in range_nodes:
             n = nodes_inbetween[j]
             motion_idx = self.graph.nodes[n]["motion_idx"]
             frame_start = self.graph.nodes[n]["frame_start"]
             frame_end = self.graph.nodes[n]["frame_end"]
             if self.motions[motion_idx] is None:
                 self.load_motion_at_idx(
                     motion_idx, self.motion_files[motion_idx]
                 )
             m = self.motions[motion_idx].detach(
                 frame_start, frame_end + self.frames_blend
             )
             motion = motion_ops.append_and_blend(
                 motion, m, blend_length=self.blend_length,
             )
     return motion
예제 #2
0
    def create_random_motion(self, length, start_node=None):
        """
        This funtion generate a motion from the given motion graph by randomly
        traversing the graph.

        length - length of the generated motion
        start_node - we can specify a start node if necessary
        """
        motion = velocity.MotionWithVelocity(skel=self.skel)
        t_processed = 0.0
        nodes = list(self.graph.nodes)
        if start_node is None or start_node not in self.graph.nodes:
            cur_node = random.choice(nodes)
        else:
            cur_node = start_node
        visited_nodes = []
        while t_processed < length:
            # Record currently visiting node
            visited_nodes.append(cur_node)

            # Append the selected motion to the current motion
            motion_idx = self.graph.nodes[cur_node]["motion_idx"]
            frame_start = self.graph.nodes[cur_node]["frame_start"]
            frame_end = self.graph.nodes[cur_node]["frame_end"]

            # Load the motion if it is not loaded in advance
            if self.motions[motion_idx] is None:
                self.load_motion_at_idx(motion_idx,
                                        self.motion_files[motion_idx])
            """
            We should detach with the extra (frames_blend)
            because motion.append affects the end of current motion
            """
            m = motion_ops.cut(
                self.motions[motion_idx],
                frame_start,
                frame_end + self.frames_blend,
            )

            if self.verbose:
                logging.info(f"[{cur_node}] {self.graph.nodes[cur_node]}")

            motion = motion_ops.append_and_blend(
                motion,
                m,
                blend_length=self.blend_length,
            )

            t_processed = motion.length()
            # Jump to adjacent node (motion) randomly
            if self.graph.out_degree(cur_node) == 0:
                if self.verbose:
                    logging.info("Dead-end exists in the graph!")
                break
            cur_node = random.choice(list(self.graph.successors(cur_node)))
        return motion, visited_nodes
예제 #3
0
    def motionify(self, nodes):
        """
        Turn a list of nodes into motion.
        """
        motion = velocity.MotionWithVelocity(skel=self.skel, fps=self.fps)
        t_processed = 0.0
        cur_node = nodes[0]
        for motion_idx in nodes[1:]:
            # Append the selected motion to the current motion
            motion_idx = self.graph.nodes[cur_node]["motion_idx"]
            frame_start = self.graph.nodes[cur_node]["frame_start"]
            frame_end = self.graph.nodes[cur_node]["frame_end"]

            # Load the motion if it is not loaded in advance
            if self.motions[motion_idx] is None:
                self.load_motion_at_idx(motion_idx,
                                        self.motion_files[motion_idx])
            """
            We should detach with the extra (frames_blend)
            because motion.append affects the end of current motion
            """
            m = motion_ops.cut(
                self.motions[motion_idx],
                frame_start,
                frame_end + self.frames_blend,
            )

            if self.verbose:
                logging.info(f"[{cur_node}] {self.graph.nodes[cur_node]}")
            # motion = motion_ops.append(
            #     motion, m
            # )

            motion = motion_ops.append_and_blend(
                motion,
                m,
                blend_length=self.blend_length,
            )

        return motion
예제 #4
0
    def test_append_motion(self):
        motion1 = bvh.load(file="tests/data/sinusoidal.bvh")
        motion2 = bvh.load(file="tests/data/sinusoidal.bvh")
        num_frames = motion1.num_frames()

        # Append motion 1 and motion 2, and check total combined frames
        combined_motion1 = motion_ops.append(motion1, motion2)
        self.assertEqual(
            combined_motion1.num_frames(),
            motion1.num_frames() + motion2.num_frames(),
        )

        # Append motion 1 and motion 3, and check total combined frames
        motion3 = bvh.load(file="tests/data/sinusoidal.bvh")
        combined_motion2 = motion_ops.append(motion1, motion3)
        self.assertEqual(
            combined_motion2.num_frames(),
            motion1.num_frames() + motion3.num_frames(),
        )
        # Ensure operation has not been done in place
        self.assertEqual(
            motion1.num_frames(),
            num_frames,
        )

        # Test blending
        blend_length = 0.1
        combined_motion3 = motion_ops.append_and_blend(
            motion1,
            motion2,
            blend_length=blend_length,
        )
        self.assertEqual(
            combined_motion3.num_frames(),
            (motion1.num_frames() + motion2.num_frames() -
             blend_length * motion1.fps),
        )