Skip to content

Instantly share code, notes, and snippets.

@HarukaKajita
Last active September 20, 2020 08:33
Show Gist options
  • Save HarukaKajita/5d57c9c2c01b9c93ae57421068888b8e to your computer and use it in GitHub Desktop.
Save HarukaKajita/5d57c9c2c01b9c93ae57421068888b8e to your computer and use it in GitHub Desktop.
import hou
class Transform(object):
translation = []
rotation = []
scale = []
def __init__(self, t, r, s):
self.translation = t
self.rotation = r
self.scale = s
def get_matrix(self):
scale_mat = hou.hmath.buildScale(self.scale[0], self.scale[1], self.scale[2])
rot_mat = hou.hmath.buildRotate(self.rotation[0], self.rotation[1], self.rotation[2], "xyz")
trans_mat = hou.hmath.buildTranslate(self.translation[0], self.translation[1], self.translation[2])
matrix = scale_mat * rot_mat
matrix = matrix * trans_mat
return matrix
class Exporter(object):
attributes = {}
namePathDic = {}
pathToParentInvertedMaterix = {}
pathToParentMatrixScale = {}
pathToHierarchyPath = {}
def __init__(self):
self.hda_node = hou.pwd().parent()
self.export_node = self.hda_node.node('sopnet1')
self.geo = self.export_node.displayNode().geometry()
def float_to_vector(self, floats):
return [floats[i:i + 3] for i in range(0, len(floats), 3)]
def vec3_mul_vec3(self, vec0, vec1):
vec2 = hou.Vector3(1,1,1)
vec2[0] = vec0[0] * vec1[0]
vec2[1] = vec0[1] * vec1[1]
vec2[2] = vec0[2] * vec1[2]
return vec2
def vec3_div_vec3(self, vec0, vec1):
vec2 = hou.Vector3(1,1,1)
vec2[0] = vec0[0] / vec1[0]
vec2[1] = vec0[1] / vec1[1]
vec2[2] = vec0[2] / vec1[2]
return vec2
def get_transform_components(self):
#アトリビュート名取得
trans_attrib = self.hda_node.evalParm("translationattrib")
rot_attrib = self.hda_node.evalParm("rotationattrib")
scale_attrib = self.hda_node.evalParm("scaleattrib")
#なんかこれがfullpathの数と一致するっぽい
point_num = len(self.geo.points())
translations = self.geo.pointFloatAttribValues(trans_attrib)
rotations = self.geo.pointFloatAttribValues(rot_attrib)
scales = self.geo.pointFloatAttribValues(scale_attrib)
if translations:
translations = self.float_to_vector(translations)
else:
translations = [[0,0,0] for i in range(point_num)]
if rotations:
rotations = self.float_to_vector(rotations)
else:
rotations = [[0,0,0] for i in range(point_num)]
if scales:
scales = self.float_to_vector(scales)
else:
scales = scales = [[1,1,1] for i in range(point_num)]
transforms = [Transform([0,0,0], [0,0,0], [1,1,1])] * point_num
for i in range(point_num):
transforms[i] = Transform(translations[i], rotations[i], scales[i])
return transforms
def set_transform(self, geo_node, trans, rot, scale):
geo_node.parmTuple('s').set(scale)
geo_node.parmTuple('r').set(rot)
geo_node.parmTuple('t').set(trans)
def create_fbx_parm(self, node, path):
# パスから名前を取得
name = path.split('/')[-1]
# ノードのパラメータテンプレートを取得
group = node.parmTemplateGroup()
# FBXの階層用パラメータを追加
path_parm = hou.StringParmTemplate('fbx_node_path', 'fbx_node_path', 1)
path_parm.setDefaultValue((path,))
name_parm = hou.StringParmTemplate('fbx_node_name', 'fbx_node_name', 1)
name_parm.setDefaultValue((name,))
# パラメータテンプレートに追加
group.append(path_parm)
group.append(name_parm)
# パラメータテンプレートを設定
node.setParmTemplateGroup(group)
def create_obj_nodes(self, objnet_node, path, exist_paths):
# 階層ごとに分ける
node_paths = path.split('/')
print(str(len(node_paths)) + " : " + path)
# 階層が一つしかない場合
# if len(node_paths) == 1:
# name = node_paths[0]
# geo_node = objnet_node.createNode('geo', node_name=name)
# geo_node.moveToGoodPosition()
# # node_path = '/'.join(node_paths[0])
# # exist_paths[node_path] = geo_node
# return geo_node
# 階層が複数ある場合
parent_nodes = []
matrix = hou.Matrix4(1)
#親のTransfotmをMatrixで積んでく
for i, current_name in enumerate(node_paths):
# 作ったノードを記録するためにノードパスを取得
node_path = '/'.join(node_paths[:i+1])
# すでに作ったノードの場合
if node_path in exist_paths:
parent_node = exist_paths[node_path]
parent_nodes.append(parent_node)
continue
# 名前がLODGroupだったらヌル、それ以外だったらGeometryノードを作る
if current_name == 'LODGroup':
node = objnet_node.createNode('null', node_name=current_name)
node.moveToGoodPosition()
else:
node = objnet_node.createNode(
'geo', node_name=current_name, run_init_scripts=False
)
node.moveToGoodPosition()
node_correctname = node.name()
self.namePathDic[node_correctname] = node_path
# ルートノード以外はインプットを繋げる
if i != 0:
parent_node = parent_nodes[-1]
node.setInput(0, parent_node)
# FBXの階層を作るためのパラメータを追加
self.create_fbx_parm(node, node_path)
# ノードを親ノードとして追加
parent_nodes.append(node)
# ノードをすでに作ったノードとして記録
exist_paths[node_path] = node
matrix *= node.localTransform().inverted()
# アトリビュートで指定したTransform値を入力する
# 親の逆変換をしたのちにアトリビュートで指定したTransform値を入力する
geo_node = parent_nodes[-1]
parent_matrix_scale = geo_node.worldTransform().extractScales('srt')
print("world Transformのスケール")
print(parent_matrix_scale)
inverted_parent = geo_node.worldTransform().inverted()
self.pathToParentInvertedMaterix[geo_node.path()] = inverted_parent
matrix = self.attributes[path].get_matrix()
trans = matrix.extractTranslates('srt')
trans = self.vec3_div_vec3(trans, parent_matrix_scale)
rot = matrix.extractRotates('srt', 'xyz')
scale = matrix.extractScales('srt')
self.set_transform(geo_node, trans, rot, scale)
self.pathToParentMatrixScale[geo_node.path()] = self.vec3_mul_vec3(parent_matrix_scale, scale)
print("Attributeで指定したTransformはこれ!")
print(trans)
print(rot)
print(scale)
return geo_node
def create_nodes_in_geo(self, geo_node, group, parent_Scale):
obj_merge = geo_node.createNode('object_merge')
obj_merge.parm('objpath1').set(self.export_node.path())
obj_merge.parm('group1').set(group)
#Transformもつけとく
currentParent_node = obj_merge
transform_sop = geo_node.createNode('xform')
transform_sop.setInput(0, currentParent_node)
transform_sop.setDisplayFlag(True)
transform_sop.setRenderFlag(True)
obj_merge.setDisplayFlag(False)
obj_merge.setRenderFlag(False)
transform_sop.moveToGoodPosition()
#ここ以降は後でやるべき
parent = transform_sop.parent()
matrix = hou.Matrix4(1)
# if parent_inputs_num == 1 :
obj_node = parent#parent_inputs[0]
matrix = obj_node.worldTransform().inverted()
trans = matrix.extractTranslates('srt')
rot = matrix.extractRotates('srt', 'xyz')
scale = matrix.extractScales('srt')
print("world Transform")
print(trans)
print(rot)
print(scale)
self.set_transform(transform_sop, trans, rot, scale)
def export(self):
self.attributes = {}
self.namePathDic = {}
self.pathToParentInvertedMaterix = {}
self.pathToParentMatrixScale = {}
self.pathToHierarchyPath = {}
print("START EXPORT\n")
print("objnet 取得")
objneet_node = self.hda_node.node("objnet1")
print("pathattribute を値列を取得")
path_attrib = self.hda_node.evalParm("pathattrib")
full_path_list = self.geo.primStringAttribValues(path_attrib)
print("full_path_list")
for full_path in full_path_list:
print(full_path)
#なんかこれがfullpathの数と一致するっぽい
#pointのattributeとprimのpathnameの数はsopnetでそろってる
#transformの配列を取得
point_num = len(self.geo.points())
transforms = [Transform((0,0,0), (0,0,0), (1,1,1))] * point_num
transforms = self.get_transform_components()
#transformをグローバルに。
for num, full_path in enumerate(full_path_list):
self.attributes[full_path] = transforms[num]
#親階層側から並ぶようにソート
pathDepthDic = {}
for key in self.attributes.keys():
pathDepthDic[key] = key.count("/")
pathDepthDic = sorted(pathDepthDic.items(), key=lambda x:x[1])
for v in pathDepthDic:
print(v)
#objのネットワークを作ってAttributeで指定したTransform値を入れるだけ
print("一回目のfor文だよ!")
exist_paths = {}
for pathDepthPair in pathDepthDic:
# 階層の作成
hierarchy_path = pathDepthPair[0]
pathDepth = pathDepthPair[1]
#geometryノードツリーを作って、attributeで指定されたTransformを書き込む
#(この変換に)
geo_node = self.create_obj_nodes(objneet_node, hierarchy_path, exist_paths)
self.pathToHierarchyPath[geo_node.path()] = hierarchy_path
print("")
print("二回目のfor文だよ!")
for path in self.pathToParentInvertedMaterix:
hierarchy_path = self.pathToHierarchyPath[path]
parent_Scale = self.pathToParentMatrixScale[path]
node = hou.node(path)
# 一番子供のGeometryノードにObject Mergeを作成
print("@" + path_attrib + "=" + hierarchy_path)
self.create_nodes_in_geo(node, "@" + path_attrib + "=" + hierarchy_path, parent_Scale)
print("export fin.")
def cleanup(self):
objneet_node = self.hda_node.node('objnet1')
objneet_node.deleteItems(objneet_node.children())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment