-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathFbxReadWriter.py
172 lines (141 loc) · 6.49 KB
/
FbxReadWriter.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
import sys
from typing import Dict
from SmplObject import SmplObjects
import os
import cv2
from scipy.spatial.transform import Rotation as R
import numpy as np
try:
from FbxCommon import *
from fbx import *
except ImportError:
print("Error: module FbxCommon failed to import.\n")
print("Copy the files located in the compatible sub-folder lib/python<version> into your python interpreter site-packages folder.")
import platform
if platform.system() == 'Windows' or platform.system() == 'Microsoft':
print('For example: copy ..\\..\\lib\\Python27_x64\\* C:\\Python27\\Lib\\site-packages')
elif platform.system() == 'Linux':
print('For example: cp ../../lib/Python27_x64/* /usr/local/lib/python2.7/site-packages')
elif platform.system() == 'Darwin':
print('For example: cp ../../lib/Python27_x64/* /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages')
class FbxReadWrite(object):
def __init__(self, fbx_source_path):
# Prepare the FBX SDK.
lSdkManager, lScene = InitializeSdkObjects()
self.lSdkManager = lSdkManager
self.lScene = lScene
# Load the scene.
# The example can take a FBX file as an argument.
print("\nLoading File: {}".format(fbx_source_path))
lResult = LoadScene(self.lSdkManager, self.lScene, fbx_source_path)
if not lResult:
raise Exception("An error occured while loading the scene :(")
def _write_curve(self, lCurve, data):
"""
data: np.ndarray of (N, )
"""
lKeyIndex = 0
lTime = FbxTime()
lTime.SetGlobalTimeMode(FbxTime.eFrames30) # Set to fps=30
data = np.squeeze(data)
lCurve.KeyModifyBegin()
for i in range(data.shape[0]):
lTime.SetFrame(i, FbxTime.eFrames30)
lKeyIndex = lCurve.KeyAdd(lTime)[0]
lCurve.KeySetValue(lKeyIndex, data[i])
lCurve.KeySetInterpolation(lKeyIndex, FbxAnimCurveDef.eInterpolationCubic)
lCurve.KeyModifyEnd()
def addAnimation(self, pkl_filename, smpl_params,model_type, verbose = False):
lScene = self.lScene
# 0. Set fps to 30
lGlobalSettings = lScene.GetGlobalSettings()
if verbose==True:
print ("Before time mode:{}".format(lGlobalSettings.GetTimeMode()))
lGlobalSettings.SetTimeMode(FbxTime.eFrames30)
if verbose==True:
print ("After time mode:{}".format(lScene.GetGlobalSettings().GetTimeMode()))
self.destroyAllAnimation()
lAnimStackName = pkl_filename
lAnimStack = FbxAnimStack.Create(lScene, lAnimStackName)
lAnimLayer = FbxAnimLayer.Create(lScene, "Base Layer")
lAnimStack.AddMember(lAnimLayer)
lRootNode = lScene.GetRootNode()
# 1. Write smpl_poses
smpl_poses = np.array(smpl_params["smpl_poses"])
# tfj 翻转朝向
if 'smplh' in model_type: #TODO: smplh不做旋转
names = SmplObjects.smplh_joints
elif 'smpl' in model_type: # smpl旋转90,人物转正
names = SmplObjects.joints
for idx,pose in enumerate(smpl_poses):
R_mod = cv2.Rodrigues(np.array([np.pi, 0, 0]))[0]
R_root = cv2.Rodrigues(pose[:3])[0]
new_root = R_root.dot(R_mod)
tmp = cv2.Rodrigues(new_root)[0].reshape(3)
smpl_poses[idx,:3] = tmp
for idx, name in enumerate(names):
node = lRootNode.FindChild(name)
rotvec = smpl_poses[:, idx*3:idx*3+3]
_euler = []
for _f in range(rotvec.shape[0]):
r = R.from_rotvec([rotvec[_f, 0], rotvec[_f, 1], rotvec[_f, 2]])
euler = r.as_euler('xyz', degrees=True)
_euler.append([euler[0], euler[1], euler[2]])
euler = np.vstack(_euler)
lCurve = node.LclRotation.GetCurve(lAnimLayer, "X", True)
if lCurve:
self._write_curve(lCurve, euler[:, 0])
else:
print ("Failed to write {}, {}".format(name, "x"))
lCurve = node.LclRotation.GetCurve(lAnimLayer, "Y", True)
if lCurve:
self._write_curve(lCurve, euler[:, 1])
else:
print ("Failed to write {}, {}".format(name, "y"))
lCurve = node.LclRotation.GetCurve(lAnimLayer, "Z", True)
if lCurve:
self._write_curve(lCurve, euler[:, 2])
else:
print ("Failed to write {}, {}".format(name, "z"))
# 3. Write smpl_trans to f_avg_root
smpl_trans = np.array(smpl_params["smpl_trans"]) # *100
name = "m_avg_root"
node = lRootNode.FindChild(name)
lCurve = node.LclTranslation.GetCurve(lAnimLayer, "X", True)
if lCurve:
self._write_curve(lCurve, smpl_trans[:, 0])
else:
print ("Failed to write {}, {}".format(name, "x"))
lCurve = node.LclTranslation.GetCurve(lAnimLayer, "Y", True)
if lCurve:
self._write_curve(lCurve, smpl_trans[:, 1])
else:
print ("Failed to write {}, {}".format(name, "y"))
lCurve = node.LclTranslation.GetCurve(lAnimLayer, "Z", True)
if lCurve:
self._write_curve(lCurve, smpl_trans[:, 2])
else:
print ("Failed to write {}, {}".format(name, "z"))
# add by tfj, 修改节点名字
kll_names = SmplObjects.kll_joints
for idx, name in enumerate(names):
node = lRootNode.FindChild(name)
node.SetName(kll_names[idx])
node = lRootNode.FindChild('m_avg_Pelvis')
node.SetName('Hips')
def writeFbx(self, write_base:str, filename:str):
if os.path.isdir(write_base) == False:
os.makedirs(write_base, exist_ok=True)
write_path = os.path.join(write_base, filename.replace(".pkl", ""))
print ("Writing to {}".format(write_path))
lResult = SaveScene(self.lSdkManager, self.lScene, write_path)
if lResult == False:
raise Exception("Failed to write to {}".format(write_path))
def destroy(self):
self.lSdkManager.Destroy()
def destroyAllAnimation(self):
lScene = self.lScene
animStackCount = lScene.GetSrcObjectCount(FbxCriteria.ObjectType(FbxAnimStack.ClassId))
for i in range(animStackCount):
lAnimStack = lScene.GetSrcObject(FbxCriteria.ObjectType(FbxAnimStack.ClassId), i)
lAnimStack.Destroy()