yfdeng's picture
init
744eb4e
#-------------------------------------------------------------------------------
# Name: rig_parser.py
# Purpose: classes for skeleton and rig
# RigNet Copyright 2020 University of Massachusetts
# RigNet is made available under General Public License Version 3 (GPLv3), or under a Commercial License.
# Please see the LICENSE README.txt file in the main directory for more information and instruction on using and licensing RigNet.
#-------------------------------------------------------------------------------
import numpy as np
try:
import Queue as Q # ver. < 3.0
except ImportError:
import queue as Q
class Node(object):
def __init__(self, name, pos):
self.name = name
self.pos = pos
class TreeNode(Node):
def __init__(self, name, pos):
super(TreeNode, self).__init__(name, pos)
self.children = []
self.parent = None
class Info:
"""
Wrap class for rig information
"""
def __init__(self, filename=None):
self.joint_pos = {}
self.joint_skin = []
self.root = None
if filename is not None:
self.load(filename)
def load(self, filename):
with open(filename, 'r') as f_txt:
lines = f_txt.readlines()
for line in lines:
word = line.split()
if word[0] == 'joints':
self.joint_pos[word[1]] = [float(word[2]), float(word[3]), float(word[4])]
elif word[0] == 'root':
root_pos = self.joint_pos[word[1]]
self.root = TreeNode(word[1], (root_pos[0], root_pos[1], root_pos[2]))
elif word[0] == 'skin':
skin_item = word[1:]
self.joint_skin.append(skin_item)
self.loadHierarchy_recur(self.root, lines, self.joint_pos)
def loadHierarchy_recur(self, node, lines, joint_pos):
for li in lines:
if li.split()[0] == 'hier' and li.split()[1] == node.name:
pos = joint_pos[li.split()[2]]
ch_node = TreeNode(li.split()[2], tuple(pos))
node.children.append(ch_node)
ch_node.parent = node
self.loadHierarchy_recur(ch_node, lines, joint_pos)
def save(self, filename):
with open(filename, 'w') as file_info:
for key, val in self.joint_pos.items():
file_info.write(
'joints {0} {1:.8f} {2:.8f} {3:.8f}\n'.format(key, val[0], val[1], val[2]))
file_info.write('root {}\n'.format(self.root.name))
for skw in self.joint_skin:
cur_line = 'skin {0} '.format(skw[0])
for cur_j in range(1, len(skw), 2):
cur_line += '{0} {1:.4f} '.format(skw[cur_j], float(skw[cur_j+1]))
cur_line += '\n'
file_info.write(cur_line)
this_level = self.root.children
while this_level:
next_level = []
for p_node in this_level:
file_info.write('hier {0} {1}\n'.format(p_node.parent.name, p_node.name))
next_level += p_node.children
this_level = next_level
# return a numpy array skin_relation, where skin_relation[i, j] = 1 if joint i is skinned to joint j
def get_skin_dict(self, filename):
skinning_dict = {}
with open (filename, 'r') as f:
lines = f.readlines()
skin_lines = [line for line in lines if line.startswith('skin')]
vertex_num = len(skin_lines)
for line in skin_lines:
word = line.split()
word = word[1:]
skin_vertex = {}
for i in range(1,len(word),2):
skin_vertex[word[i]] = float(word[i+1])
skinning_dict[word[0]] = skin_vertex
return skinning_dict,vertex_num
def save_as_skel_format(self, filename):
fout = open(filename, 'w')
this_level = [self.root]
hier_level = 1
while this_level:
next_level = []
for p_node in this_level:
pos = p_node.pos
parent = p_node.parent.name if p_node.parent is not None else 'None'
line = '{0} {1} {2:8f} {3:8f} {4:8f} {5}\n'.format(hier_level, p_node.name, pos[0], pos[1], pos[2],
parent)
fout.write(line)
for c_node in p_node.children:
next_level.append(c_node)
this_level = next_level
hier_level += 1
fout.close()
def normalize(self, scale, trans):
for k, v in self.joint_pos.items():
self.joint_pos[k] /= scale
self.joint_pos[k] -= trans
this_level = [self.root]
while this_level:
next_level = []
for node in this_level:
node.pos /= scale
node.pos = (node.pos[0] - trans[0], node.pos[1] - trans[1], node.pos[2] - trans[2])
for ch in node.children:
next_level.append(ch)
this_level = next_level
def get_joint_dict(self):
joint_dict = {}
this_level = [self.root]
while this_level:
next_level = []
for node in this_level:
joint_dict[node.name] = node.pos
next_level += node.children
this_level = next_level
return joint_dict
def adjacent_matrix(self):
joint_pos = self.get_joint_dict()
joint_name_list = list(joint_pos.keys())
num_joint = len(joint_pos)
adj_matrix = np.zeros((num_joint, num_joint))
this_level = [self.root]
while this_level:
next_level = []
for p_node in this_level:
for c_node in p_node.children:
index_parent = joint_name_list.index(p_node.name)
index_children = joint_name_list.index(c_node.name)
adj_matrix[index_parent, index_children] = 1.
next_level += p_node.children
this_level = next_level
adj_matrix = adj_matrix + adj_matrix.transpose()
return adj_matrix
class Skel:
"""
Wrap class for skeleton topology
"""
def __init__(self, filename=None):
self.root = None
if filename is not None:
self.load(filename)
def load(self, filename):
with open(filename, 'r') as fin:
lines = fin.readlines()
for li in lines:
words = li.split()
if words[5] == "None":
self.root = TreeNode(words[1], (float(words[2]), float(words[3]), float(words[4])))
if len(words) == 7:
has_order = True
self.root.order = int(words[6])
else:
has_order = False
break
self.loadSkel_recur(self.root, lines, has_order)
def loadSkel_recur(self, node, lines, has_order):
if has_order:
ch_queue = Q.PriorityQueue()
for li in lines:
words = li.split()
if words[5] == node.name:
ch_queue.put((int(li.split()[6]), li))
while not ch_queue.empty():
item = ch_queue.get()
li = item[1]
ch_node = TreeNode(li.split()[1], (float(li.split()[2]), float(li.split()[3]), float(li.split()[4])))
ch_node.order = int(li.split()[6])
node.children.append(ch_node)
ch_node.parent = node
self.loadSkel_recur(ch_node, lines, has_order)
else:
for li in lines:
words = li.split()
if words[5] == node.name:
ch_node = TreeNode(words[1], (float(words[2]), float(words[3]), float(words[4])))
node.children.append(ch_node)
ch_node.parent = node
self.loadSkel_recur(ch_node, lines, has_order)
def save(self, filename):
fout = open(filename, 'w')
this_level = [self.root]
hier_level = 1
while this_level:
next_level = []
for p_node in this_level:
pos = p_node.pos
parent = p_node.parent.name if p_node.parent is not None else 'None'
line = '{0} {1} {2:8f} {3:8f} {4:8f} {5}\n'.format(hier_level, p_node.name, pos[0], pos[1], pos[2], parent)
fout.write(line)
for c_node in p_node.children:
next_level.append(c_node)
this_level = next_level
hier_level += 1
fout.close()
def normalize(self, scale, trans):
this_level = [self.root]
while this_level:
next_level = []
for node in this_level:
node.pos /= scale
node.pos = (node.pos[0] - trans[0], node.pos[1] - trans[1], node.pos[2] - trans[2])
for ch in node.children:
next_level.append(ch)
this_level = next_level
def get_joint_pos(self):
joint_pos = {}
this_level = [self.root]
while this_level:
next_level = []
for node in this_level:
joint_pos[node.name] = node.pos
next_level += node.children
this_level = next_level
return joint_pos
def adjacent_matrix(self):
joint_pos = self.get_joint_pos()
joint_name_list = list(joint_pos.keys())
num_joint = len(joint_pos)
adj_matrix = np.zeros((num_joint, num_joint))
this_level = [self.root]
while this_level:
next_level = []
for p_node in this_level:
for c_node in p_node.children:
index_parent = joint_name_list.index(p_node.name)
index_children = joint_name_list.index(c_node.name)
adj_matrix[index_parent, index_children] = 1.
next_level += p_node.children
this_level = next_level
adj_matrix = adj_matrix + adj_matrix.transpose()
return adj_matrix