forked from softcat477/SMPL-to-FBX
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFbxReadWriter.py
145 lines (123 loc) · 5.63 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
import sys
from typing import Dict
from SmplObject import SmplObjects
import os
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:FbxAnimCurve, data:np.ndarray):
"""
data: np.ndarray of (N, )
"""
lKeyIndex = 0
lTime = FbxTime()
lTime.SetGlobalTimeMode(FbxTime.eFrames60) # Set to fps=60
data = np.squeeze(data)
lCurve.KeyModifyBegin()
for i in range(data.shape[0]):
lTime.SetFrame(i, FbxTime.eFrames60)
lKeyIndex = lCurve.KeyAdd(lTime)[0]
lCurve.KeySetValue(lKeyIndex, data[i])
lCurve.KeySetInterpolation(lKeyIndex, FbxAnimCurveDef.eInterpolationCubic)
lCurve.KeyModifyEnd()
def addAnimation(self, pkl_filename:str, smpl_params:Dict, verbose:bool = False):
lScene = self.lScene
# 0. Set fps to 60
lGlobalSettings = lScene.GetGlobalSettings()
if verbose==True:
print ("Before time mode:{}".format(lGlobalSettings.GetTimeMode()))
lGlobalSettings.SetTimeMode(FbxTime.eFrames60)
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()
names = SmplObjects.joints
# 1. Write smpl_poses
smpl_poses = smpl_params["smpl_poses"]
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 = smpl_params["smpl_trans"]
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"))
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()