forked from bartvdbraak/blender
FBX Export, small changes made while looking into reported bug. (no functional changes)
- Warn for armature deformed meshes which are scaled, these don't work quite the same as in blender, reported as [#24663]. - Use matrix.decompose() to convert a matrix to loc/rot/scale. - get vert/edge/face lists for each mesh only once. - faster euler rad -> deg conversion function.
This commit is contained in:
parent
efcf1ac357
commit
f48f8d3bbc
@ -63,15 +63,9 @@ def copy_images(dest_dir, textures):
|
|||||||
|
|
||||||
# I guess FBX uses degrees instead of radians (Arystan).
|
# I guess FBX uses degrees instead of radians (Arystan).
|
||||||
# Call this function just before writing to FBX.
|
# Call this function just before writing to FBX.
|
||||||
def eulerRadToDeg(eul):
|
# 180 / math.pi == 57.295779513
|
||||||
ret = Euler()
|
def tuple_rad_to_deg(eul):
|
||||||
|
return eul[0] * 57.295779513, eul[1] * 57.295779513, eul[2] * 57.295779513
|
||||||
ret.x = 180 / math.pi * eul[0]
|
|
||||||
ret.y = 180 / math.pi * eul[1]
|
|
||||||
ret.z = 180 / math.pi * eul[2]
|
|
||||||
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
# def strip_path(p):
|
# def strip_path(p):
|
||||||
# return p.split('\\')[-1].split('/')[-1]
|
# return p.split('\\')[-1].split('/')[-1]
|
||||||
@ -609,12 +603,12 @@ def save(operator, context, filepath="",
|
|||||||
# par_matrix = mtx4_z90 * parent.matrix['ARMATURESPACE'] # dont apply armature matrix anymore
|
# par_matrix = mtx4_z90 * parent.matrix['ARMATURESPACE'] # dont apply armature matrix anymore
|
||||||
matrix = par_matrix.copy().invert() * matrix
|
matrix = par_matrix.copy().invert() * matrix
|
||||||
|
|
||||||
matrix_rot = matrix.rotation_part()
|
loc, rot, scale = matrix.decompose()
|
||||||
|
matrix_rot = rot.to_matrix()
|
||||||
loc = tuple(matrix.translation_part())
|
|
||||||
scale = tuple(matrix.scale_part())
|
|
||||||
rot = tuple(matrix_rot.to_euler())
|
|
||||||
|
|
||||||
|
loc = tuple(loc)
|
||||||
|
rot = tuple(rot.to_euler()) # quat -> euler
|
||||||
|
scale = tuple(scale)
|
||||||
else:
|
else:
|
||||||
# This is bad because we need the parent relative matrix from the fbx parent (if we have one), dont use anymore
|
# This is bad because we need the parent relative matrix from the fbx parent (if we have one), dont use anymore
|
||||||
#if ob and not matrix: matrix = ob.matrix_world * GLOBAL_MATRIX
|
#if ob and not matrix: matrix = ob.matrix_world * GLOBAL_MATRIX
|
||||||
@ -625,20 +619,20 @@ def save(operator, context, filepath="",
|
|||||||
# matrix = matrix_scale * matrix
|
# matrix = matrix_scale * matrix
|
||||||
|
|
||||||
if matrix:
|
if matrix:
|
||||||
loc = tuple(matrix.translation_part())
|
loc, rot, scale = matrix.decompose()
|
||||||
scale = tuple(matrix.scale_part())
|
matrix_rot = rot.to_matrix()
|
||||||
|
|
||||||
matrix_rot = matrix.rotation_part()
|
|
||||||
# Lamps need to be rotated
|
# Lamps need to be rotated
|
||||||
if ob and ob.type =='LAMP':
|
if ob and ob.type =='LAMP':
|
||||||
matrix_rot = matrix_rot * mtx_x90
|
matrix_rot = matrix_rot * mtx_x90
|
||||||
rot = tuple(matrix_rot.to_euler())
|
|
||||||
elif ob and ob.type =='CAMERA':
|
elif ob and ob.type =='CAMERA':
|
||||||
y = Vector((0.0, 1.0, 0.0)) * matrix_rot
|
y = Vector((0.0, 1.0, 0.0)) * matrix_rot
|
||||||
matrix_rot = Matrix.Rotation(math.pi/2, 3, y) * matrix_rot
|
matrix_rot = Matrix.Rotation(math.pi/2, 3, y) * matrix_rot
|
||||||
|
# else do nothing.
|
||||||
|
|
||||||
|
loc = tuple(loc)
|
||||||
rot = tuple(matrix_rot.to_euler())
|
rot = tuple(matrix_rot.to_euler())
|
||||||
else:
|
scale = tuple(scale)
|
||||||
rot = tuple(matrix_rot.to_euler())
|
|
||||||
else:
|
else:
|
||||||
if not loc:
|
if not loc:
|
||||||
loc = 0,0,0
|
loc = 0,0,0
|
||||||
@ -656,7 +650,7 @@ def save(operator, context, filepath="",
|
|||||||
loc, rot, scale, matrix, matrix_rot = object_tx(ob, loc, matrix, matrix_mod)
|
loc, rot, scale, matrix, matrix_rot = object_tx(ob, loc, matrix, matrix_mod)
|
||||||
|
|
||||||
file.write('\n\t\t\tProperty: "Lcl Translation", "Lcl Translation", "A+",%.15f,%.15f,%.15f' % loc)
|
file.write('\n\t\t\tProperty: "Lcl Translation", "Lcl Translation", "A+",%.15f,%.15f,%.15f' % loc)
|
||||||
file.write('\n\t\t\tProperty: "Lcl Rotation", "Lcl Rotation", "A+",%.15f,%.15f,%.15f' % tuple(eulerRadToDeg(rot)))
|
file.write('\n\t\t\tProperty: "Lcl Rotation", "Lcl Rotation", "A+",%.15f,%.15f,%.15f' % tuple_rad_to_deg(rot))
|
||||||
# file.write('\n\t\t\tProperty: "Lcl Rotation", "Lcl Rotation", "A+",%.15f,%.15f,%.15f' % rot)
|
# file.write('\n\t\t\tProperty: "Lcl Rotation", "Lcl Rotation", "A+",%.15f,%.15f,%.15f' % rot)
|
||||||
file.write('\n\t\t\tProperty: "Lcl Scaling", "Lcl Scaling", "A+",%.15f,%.15f,%.15f' % scale)
|
file.write('\n\t\t\tProperty: "Lcl Scaling", "Lcl Scaling", "A+",%.15f,%.15f,%.15f' % scale)
|
||||||
return loc, rot, scale, matrix, matrix_rot
|
return loc, rot, scale, matrix, matrix_rot
|
||||||
@ -1413,18 +1407,18 @@ def save(operator, context, filepath="",
|
|||||||
me = my_mesh.blenData
|
me = my_mesh.blenData
|
||||||
|
|
||||||
# if there are non NULL materials on this mesh
|
# if there are non NULL materials on this mesh
|
||||||
if my_mesh.blenMaterials: do_materials = True
|
do_materials = bool(my_mesh.blenMaterials)
|
||||||
else: do_materials = False
|
do_textures = bool(my_mesh.blenTextures)
|
||||||
|
|
||||||
if my_mesh.blenTextures: do_textures = True
|
|
||||||
else: do_textures = False
|
|
||||||
|
|
||||||
do_uvs = bool(me.uv_textures)
|
do_uvs = bool(me.uv_textures)
|
||||||
|
|
||||||
|
|
||||||
file.write('\n\tModel: "Model::%s", "Mesh" {' % my_mesh.fbxName)
|
file.write('\n\tModel: "Model::%s", "Mesh" {' % my_mesh.fbxName)
|
||||||
file.write('\n\t\tVersion: 232') # newline is added in write_object_props
|
file.write('\n\t\tVersion: 232') # newline is added in write_object_props
|
||||||
|
|
||||||
|
# convert into lists once.
|
||||||
|
me_vertices = me.vertices[:]
|
||||||
|
me_edges = me.edges[:]
|
||||||
|
me_faces = me.faces[:]
|
||||||
|
|
||||||
poseMatrix = write_object_props(my_mesh.blenObject, None, my_mesh.parRelMatrix())[3]
|
poseMatrix = write_object_props(my_mesh.blenObject, None, my_mesh.parRelMatrix())[3]
|
||||||
pose_items.append((my_mesh.fbxName, poseMatrix))
|
pose_items.append((my_mesh.fbxName, poseMatrix))
|
||||||
|
|
||||||
@ -1439,7 +1433,7 @@ def save(operator, context, filepath="",
|
|||||||
file.write('\n\t\tVertices: ')
|
file.write('\n\t\tVertices: ')
|
||||||
i=-1
|
i=-1
|
||||||
|
|
||||||
for v in me.vertices:
|
for v in me_vertices:
|
||||||
if i==-1:
|
if i==-1:
|
||||||
file.write('%.6f,%.6f,%.6f' % tuple(v.co)); i=0
|
file.write('%.6f,%.6f,%.6f' % tuple(v.co)); i=0
|
||||||
else:
|
else:
|
||||||
@ -1450,7 +1444,7 @@ def save(operator, context, filepath="",
|
|||||||
|
|
||||||
file.write('\n\t\tPolygonVertexIndex: ')
|
file.write('\n\t\tPolygonVertexIndex: ')
|
||||||
i=-1
|
i=-1
|
||||||
for f in me.faces:
|
for f in me_faces:
|
||||||
fi = f.vertices[:]
|
fi = f.vertices[:]
|
||||||
|
|
||||||
# last index XORd w. -1 indicates end of face
|
# last index XORd w. -1 indicates end of face
|
||||||
@ -1470,7 +1464,7 @@ def save(operator, context, filepath="",
|
|||||||
i+=1
|
i+=1
|
||||||
|
|
||||||
# write loose edges as faces.
|
# write loose edges as faces.
|
||||||
for ed in me.edges:
|
for ed in me_edges:
|
||||||
if ed.is_loose:
|
if ed.is_loose:
|
||||||
ed_val = ed.vertices[:]
|
ed_val = ed.vertices[:]
|
||||||
ed_val = ed_val[0], ed_val[-1] ^ -1
|
ed_val = ed_val[0], ed_val[-1] ^ -1
|
||||||
@ -1488,7 +1482,7 @@ def save(operator, context, filepath="",
|
|||||||
|
|
||||||
file.write('\n\t\tEdges: ')
|
file.write('\n\t\tEdges: ')
|
||||||
i=-1
|
i=-1
|
||||||
for ed in me.edges:
|
for ed in me_edges:
|
||||||
if i==-1:
|
if i==-1:
|
||||||
file.write('%i,%i' % (ed.vertices[0], ed.vertices[1]))
|
file.write('%i,%i' % (ed.vertices[0], ed.vertices[1]))
|
||||||
i=0
|
i=0
|
||||||
@ -1510,7 +1504,7 @@ def save(operator, context, filepath="",
|
|||||||
Normals: ''')
|
Normals: ''')
|
||||||
|
|
||||||
i=-1
|
i=-1
|
||||||
for v in me.vertices:
|
for v in me_vertices:
|
||||||
if i==-1:
|
if i==-1:
|
||||||
file.write('%.15f,%.15f,%.15f' % tuple(v.normal)); i=0
|
file.write('%.15f,%.15f,%.15f' % tuple(v.normal)); i=0
|
||||||
else:
|
else:
|
||||||
@ -1530,7 +1524,7 @@ def save(operator, context, filepath="",
|
|||||||
Smoothing: ''')
|
Smoothing: ''')
|
||||||
|
|
||||||
i=-1
|
i=-1
|
||||||
for f in me.faces:
|
for f in me_faces:
|
||||||
if i==-1:
|
if i==-1:
|
||||||
file.write('%i' % f.use_smooth); i=0
|
file.write('%i' % f.use_smooth); i=0
|
||||||
else:
|
else:
|
||||||
@ -1551,7 +1545,7 @@ def save(operator, context, filepath="",
|
|||||||
Smoothing: ''')
|
Smoothing: ''')
|
||||||
|
|
||||||
i=-1
|
i=-1
|
||||||
for ed in me.edges:
|
for ed in me_edges:
|
||||||
if i==-1:
|
if i==-1:
|
||||||
file.write('%i' % (ed.use_edge_sharp)); i=0
|
file.write('%i' % (ed.use_edge_sharp)); i=0
|
||||||
else:
|
else:
|
||||||
@ -1589,7 +1583,7 @@ def save(operator, context, filepath="",
|
|||||||
i = -1
|
i = -1
|
||||||
ii = 0 # Count how many Colors we write
|
ii = 0 # Count how many Colors we write
|
||||||
|
|
||||||
for f, cf in zip(me.faces, collayer.data):
|
for f, cf in zip(me_faces, collayer.data):
|
||||||
colors = [cf.color1, cf.color2, cf.color3, cf.color4]
|
colors = [cf.color1, cf.color2, cf.color3, cf.color4]
|
||||||
|
|
||||||
# determine number of verts
|
# determine number of verts
|
||||||
@ -1756,11 +1750,11 @@ def save(operator, context, filepath="",
|
|||||||
if me.uv_textures.active:
|
if me.uv_textures.active:
|
||||||
uv_faces = me.uv_textures.active.data
|
uv_faces = me.uv_textures.active.data
|
||||||
else:
|
else:
|
||||||
uv_faces = [None] * len(me.faces)
|
uv_faces = [None] * len(me_faces)
|
||||||
|
|
||||||
i=-1
|
i=-1
|
||||||
for f, uf in zip(me.faces, uv_faces):
|
for f, uf in zip(me_faces, uv_faces):
|
||||||
# for f in me.faces:
|
# for f in me_faces:
|
||||||
try: mat = mats[f.material_index]
|
try: mat = mats[f.material_index]
|
||||||
except:mat = None
|
except:mat = None
|
||||||
|
|
||||||
@ -2029,6 +2023,10 @@ def save(operator, context, filepath="",
|
|||||||
if armob and armob not in ob_arms:
|
if armob and armob not in ob_arms:
|
||||||
ob_arms.append(armob)
|
ob_arms.append(armob)
|
||||||
|
|
||||||
|
# Warning for scaled, mesh objects with armatures
|
||||||
|
if abs(ob.scale[0] - 1.0) > 0.05 or abs(ob.scale[1] - 1.0) > 0.05 or abs(ob.scale[1] - 1.0) > 0.05:
|
||||||
|
operator.report('WARNING', "Object '%s' has a scale of (%.3f, %.3f, %.3f), Armature deformation will not work as expected!, Apply Scale to fix." % ((ob.name,) + tuple(ob.scale)))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
blenParentBoneName = armob = None
|
blenParentBoneName = armob = None
|
||||||
|
|
||||||
@ -2708,7 +2706,7 @@ Takes: {''')
|
|||||||
for mtx in context_bone_anim_mats:
|
for mtx in context_bone_anim_mats:
|
||||||
if prev_eul: prev_eul = mtx[1].to_euler('XYZ', prev_eul)
|
if prev_eul: prev_eul = mtx[1].to_euler('XYZ', prev_eul)
|
||||||
else: prev_eul = mtx[1].to_euler()
|
else: prev_eul = mtx[1].to_euler()
|
||||||
context_bone_anim_vecs.append(eulerRadToDeg(prev_eul))
|
context_bone_anim_vecs.append(tuple_rad_to_deg(prev_eul))
|
||||||
|
|
||||||
file.write('\n\t\t\t\tChannel: "%s" {' % TX_CHAN) # translation
|
file.write('\n\t\t\t\tChannel: "%s" {' % TX_CHAN) # translation
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user