Newer
Older
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# <pep8 compliant>
# Script copyright (C) Campbell Barton, Bastien Montagne
import math
Bastien Montagne
committed
import time
from collections import namedtuple
from collections.abc import Iterable
from itertools import zip_longest, chain
import bpy
import bpy_extras
from bpy.types import Object, Bone, PoseBone, DepsgraphObjectInstance
Bastien Montagne
committed
from mathutils import Vector, Matrix
from . import encode_bin, data_types
# "Constants"
FBX_VERSION = 7400
FBX_HEADER_VERSION = 1003
FBX_SCENEINFO_VERSION = 100
FBX_TEMPLATES_VERSION = 100
FBX_MODELS_VERSION = 232
FBX_GEOMETRY_VERSION = 124
# Revert back normals to 101 (simple 3D values) for now, 102 (4D + weights) seems not well supported by most apps
# currently, apart from some AD products.
FBX_GEOMETRY_NORMAL_VERSION = 101
FBX_GEOMETRY_BINORMAL_VERSION = 101
FBX_GEOMETRY_TANGENT_VERSION = 101
FBX_GEOMETRY_SMOOTHING_VERSION = 102
FBX_GEOMETRY_CREASE_VERSION = 101
FBX_GEOMETRY_VCOLOR_VERSION = 101
FBX_GEOMETRY_UV_VERSION = 101
FBX_GEOMETRY_MATERIAL_VERSION = 101
FBX_GEOMETRY_LAYER_VERSION = 100
FBX_GEOMETRY_SHAPE_VERSION = 100
FBX_DEFORMER_SHAPE_VERSION = 100
FBX_DEFORMER_SHAPECHANNEL_VERSION = 100
FBX_POSE_BIND_VERSION = 100
FBX_DEFORMER_SKIN_VERSION = 101
FBX_DEFORMER_CLUSTER_VERSION = 100
FBX_MATERIAL_VERSION = 102
FBX_TEXTURE_VERSION = 202
FBX_ANIM_KEY_VERSION = 4008
FBX_NAME_CLASS_SEP = b"\x00\x01"
FBX_ANIM_PROPSGROUP_NAME = "d"
FBX_KTIME = 46186158000 # This is the number of "ktimes" in one second (yep, precision over the nanosecond...)
MAT_CONVERT_LIGHT = Matrix.Rotation(math.pi / 2.0, 4, 'X') # Blender is -Z, FBX is -Y.
MAT_CONVERT_CAMERA = Matrix.Rotation(math.pi / 2.0, 4, 'Y') # Blender is -Z, FBX is +X.
# XXX I can't get this working :(
# MAT_CONVERT_BONE = Matrix.Rotation(math.pi / 2.0, 4, 'Z') # Blender is +Y, FBX is -X.
MAT_CONVERT_BONE = Matrix()
BLENDER_OTHER_OBJECT_TYPES = {'CURVE', 'SURFACE', 'FONT', 'META'}
BLENDER_OBJECT_TYPES_MESHLIKE = {'MESH'} | BLENDER_OTHER_OBJECT_TYPES
# Lamps.
FBX_LIGHT_TYPES = {
'POINT': 0, # Point.
'SUN': 1, # Directional.
'SPOT': 2, # Spot.
'HEMI': 1, # Directional.
'AREA': 3, # Area.
}
FBX_LIGHT_DECAY_TYPES = {
'CONSTANT': 0, # None.
'INVERSE_LINEAR': 1, # Linear.
'INVERSE_SQUARE': 2, # Quadratic.
'INVERSE_COEFFICIENTS': 2, # Quadratic...
'CUSTOM_CURVE': 2, # Quadratic.
'LINEAR_QUADRATIC_WEIGHTED': 2, # Quadratic.
}
RIGHT_HAND_AXES = {
Bastien Montagne
committed
# Up, Forward -> FBX values (tuples of (axis, sign), Up, Front, Coord).
( 'X', '-Y'): ((0, 1), (1, 1), (2, 1)),
( 'X', 'Y'): ((0, 1), (1, -1), (2, -1)),
( 'X', '-Z'): ((0, 1), (2, 1), (1, -1)),
( 'X', 'Z'): ((0, 1), (2, -1), (1, 1)),
('-X', '-Y'): ((0, -1), (1, 1), (2, -1)),
('-X', 'Y'): ((0, -1), (1, -1), (2, 1)),
('-X', '-Z'): ((0, -1), (2, 1), (1, 1)),
('-X', 'Z'): ((0, -1), (2, -1), (1, -1)),
( 'Y', '-X'): ((1, 1), (0, 1), (2, -1)),
( 'Y', 'X'): ((1, 1), (0, -1), (2, 1)),
( 'Y', '-Z'): ((1, 1), (2, 1), (0, 1)),
( 'Y', 'Z'): ((1, 1), (2, -1), (0, -1)),
('-Y', '-X'): ((1, -1), (0, 1), (2, 1)),
('-Y', 'X'): ((1, -1), (0, -1), (2, -1)),
('-Y', '-Z'): ((1, -1), (2, 1), (0, -1)),
('-Y', 'Z'): ((1, -1), (2, -1), (0, 1)),
( 'Z', '-X'): ((2, 1), (0, 1), (1, 1)),
( 'Z', 'X'): ((2, 1), (0, -1), (1, -1)),
( 'Z', '-Y'): ((2, 1), (1, 1), (0, -1)),
( 'Z', 'Y'): ((2, 1), (1, -1), (0, 1)), # Blender system!
('-Z', '-X'): ((2, -1), (0, 1), (1, -1)),
('-Z', 'X'): ((2, -1), (0, -1), (1, 1)),
('-Z', '-Y'): ((2, -1), (1, 1), (0, 1)),
('-Z', 'Y'): ((2, -1), (1, -1), (0, -1)),
}
FBX_FRAMERATES = (
(-1.0, 14), # Custom framerate.
(120.0, 1),
(100.0, 2),
(60.0, 3),
(50.0, 4),
(48.0, 5),
(30.0, 6), # BW NTSC.
(30.0 / 1.001, 9), # Color NTSC.
(25.0, 10),
(24.0, 11),
(24.0 / 1.001, 13),
(96.0, 15),
(72.0, 16),
(60.0 / 1.001, 17),
)
Bastien Montagne
committed
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
DO_PERFMON = True
if DO_PERFMON:
class PerfMon():
def __init__(self):
self.level = -1
self.ref_time = []
def level_up(self, message=""):
self.level += 1
self.ref_time.append(None)
if message:
print("\t" * self.level, message, sep="")
def level_down(self, message=""):
if not self.ref_time:
if message:
print(message)
return
ref_time = self.ref_time[self.level]
print("\t" * self.level,
"\tDone (%f sec)\n" % ((time.process_time() - ref_time) if ref_time is not None else 0.0),
sep="")
if message:
print("\t" * self.level, message, sep="")
del self.ref_time[self.level]
self.level -= 1
def step(self, message=""):
ref_time = self.ref_time[self.level]
curr_time = time.process_time()
if ref_time is not None:
print("\t" * self.level, "\tDone (%f sec)\n" % (curr_time - ref_time), sep="")
self.ref_time[self.level] = curr_time
print("\t" * self.level, message, sep="")
else:
class PerfMon():
def __init__(self):
pass
def level_up(self, message=""):
pass
def level_down(self, message=""):
pass
def step(self, message=""):
pass
Loading
Loading full blame...