[Bf-extensions-cvs] SVN commit: /data/svn/bf-extensions [2205] trunk/py/scripts/addons/ io_scene_fbx: patch [#28118] Add XNA requirements to the official FBX exporter
Campbell Barton
ideasman42 at gmail.com
Mon Aug 1 02:47:10 CEST 2011
Revision: 2205
http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-extensions&revision=2205
Author: campbellbarton
Date: 2011-08-01 00:47:09 +0000 (Mon, 01 Aug 2011)
Log Message:
-----------
patch [#28118] Add XNA requirements to the official FBX exporter
from John Brown (jcbdigger)
The patch has been modified, some of the changes I rather see applied as separate patches.
This commit adds/changes:
- Option to export XNA compatible armature rotations.
- Option not to export mesh edges.
- Always export armatures as 'Limb' type.
- dont write default cameras or camera switch when cameras are disabled.
- fix for (harmless) error where armature connections were written out twice.
Modified Paths:
--------------
trunk/py/scripts/addons/io_scene_fbx/__init__.py
trunk/py/scripts/addons/io_scene_fbx/export_fbx.py
Modified: trunk/py/scripts/addons/io_scene_fbx/__init__.py
===================================================================
--- trunk/py/scripts/addons/io_scene_fbx/__init__.py 2011-07-31 09:33:04 UTC (rev 2204)
+++ trunk/py/scripts/addons/io_scene_fbx/__init__.py 2011-08-01 00:47:09 UTC (rev 2205)
@@ -21,10 +21,10 @@
bl_info = {
"name": "Autodesk FBX format",
"author": "Campbell Barton",
- "blender": (2, 5, 7),
- "api": 35622,
+ "blender": (2, 5, 8),
+ "api": 38691,
"location": "File > Import-Export",
- "description": "Import-Export FBX meshes, UV's, vertex colors, materials, textures, cameras and lamps",
+ "description": "Export FBX meshes, UV's, vertex colors, materials, textures, cameras, lamps and actions",
"warning": "",
"wiki_url": "http://wiki.blender.org/index.php/Extensions:2.5/Py/"\
"Scripts/Import-Export/Autodesk_FBX",
@@ -62,8 +62,8 @@
# to the class instance from the operator settings before calling.
use_selection = BoolProperty(name="Selected Objects", description="Export selected objects on visible layers", default=False)
-# EXP_OBS_SCENE = BoolProperty(name="Scene Objects", description="Export all objects in this scene", default=True)
- global_scale = FloatProperty(name="Scale", description="Scale all data, (Note! some imports dont support scaled armatures)", min=0.01, max=1000.0, soft_min=0.01, soft_max=1000.0, default=1.0)
+ # XNA does not support scaled armatures (JCB)
+ global_scale = FloatProperty(name="Scale", description="Scale all data. Some importers do not support scaled armatures!", min=0.01, max=1000.0, soft_min=0.01, soft_max=1000.0, default=1.0)
axis_forward = EnumProperty(
name="Forward",
@@ -71,7 +71,7 @@
('Y', "Y Forward", ""),
('Z', "Z Forward", ""),
('-X', "-X Forward", ""),
- ('-Y', "-Y Forward", ""),
+ ('-Y', "-Y Forward (Blender)", ""),
('-Z', "-Z Forward", ""),
),
default='-Z',
@@ -81,7 +81,7 @@
name="Up",
items=(('X', "X Up", ""),
('Y', "Y Up", ""),
- ('Z', "Z Up", ""),
+ ('Z', "Z Up (Blender)", ""),
('-X', "-X Up", ""),
('-Y', "-Y Up", ""),
('-Z', "-Z Up", ""),
@@ -112,13 +112,21 @@
default='FACE',
)
+ # XNA does not use the edge information (JCB)
+ use_edges = BoolProperty(name="Include Edges", description="Edges may not be necessary and can cause errors with some importers!", default=False)
# EXP_MESH_HQ_NORMALS = BoolProperty(name="HQ Normals", description="Generate high quality normals", default=True)
# armature animation
- ANIM_ENABLE = BoolProperty(name="Enable Animation", description="Export keyframe animation", default=True)
+ ANIM_ENABLE = BoolProperty(name="Include Animation", description="Export keyframe animation", default=True)
+ ANIM_ACTION_ALL = BoolProperty(name="All Actions", description="Export all actions for armatures or just the currently selected action", default=True)
ANIM_OPTIMIZE = BoolProperty(name="Optimize Keyframes", description="Remove double keyframes", default=True)
ANIM_OPTIMIZE_PRECISSION = FloatProperty(name="Precision", description="Tolerence for comparing double keyframes (higher for greater accuracy)", min=1, max=16, soft_min=1, soft_max=16, default=6.0)
-# ANIM_ACTION_ALL = BoolProperty(name="Current Action", description="Use actions currently applied to the armatures (use scene start/end frame)", default=True)
- ANIM_ACTION_ALL = BoolProperty(name="All Actions", description="Use all actions for armatures, if false, use current action", default=False)
+ # XNA needs different names for each take having the first one always called Default_Take is unhelpful (JCB)
+ # XNA usually errors if the textures are not in the same folder as the FBX file (JCB)
+ # XNA - validation to avoid incompatible settings. I will understand if this is not kept in the generic version. (JCB)
+ # It would be nice to have this for XNA, UDK, Unity and Sunburn if others could provide the details. (JCB)
+ xna_validate = BoolProperty(name="XNA Strict Options", description="Make sure options are compatible with Microsoft XNA", default=False)
+ # The armature rotation does not work for XNA and setting the global matrix to identity is not sufficient on its own (JCB)
+ use_rotate_workaround = BoolProperty(name="XNA Rotate Fix", description="Disable global rotation, for XNA compatibility", default=False)
batch_mode = EnumProperty(
name="Batch Mode",
@@ -133,23 +141,51 @@
path_mode = path_reference_mode
+ # Validate that the options are compatible with XNA (JCB)
+ def _validate_xna_options(self):
+ if not self.xna_validate:
+ return False
+ changed = False
+ if not self.use_rotate_workaround:
+ changed = True
+ self.use_rotate_workaround = True
+ if self.global_scale != 1.0 or self.mesh_smooth_type != 'OFF':
+ changed = True
+ self.global_scale = 1.0
+ self.mesh_smooth_type = 'OFF'
+ if self.ANIM_OPTIMIZE or self.use_edges:
+ changed = True
+ self.ANIM_OPTIMIZE = False
+ self.use_edges = False
+ if self.object_types & {'CAMERA', 'LAMP', 'EMPTY'}:
+ changed = True
+ self.object_types -= {'CAMERA', 'LAMP', 'EMPTY'}
+ return changed
+
@property
def check_extension(self):
return self.batch_mode == 'OFF'
def check(self, context):
- return axis_conversion_ensure(self, "axis_forward", "axis_up")
+ is_xna_change = self._validate_xna_options()
+ is_axis_change = axis_conversion_ensure(self, "axis_forward", "axis_up")
+ if is_xna_change or is_axis_change:
+ return True
+ else:
+ return False
def execute(self, context):
from mathutils import Matrix
if not self.filepath:
raise Exception("filepath not set")
+ # Armature rotation causes a mess in XNA there are also other changes in the main script to avoid rotation (JCB)
global_matrix = Matrix()
global_matrix[0][0] = global_matrix[1][1] = global_matrix[2][2] = self.global_scale
- global_matrix = global_matrix * axis_conversion(to_forward=self.axis_forward, to_up=self.axis_up).to_4x4()
+ if not self.use_rotate_workaround:
+ global_matrix = global_matrix * axis_conversion(to_forward=self.axis_forward, to_up=self.axis_up).to_4x4()
- keywords = self.as_keywords(ignore=("axis_forward", "axis_up", "global_scale", "check_existing", "filter_glob"))
+ keywords = self.as_keywords(ignore=("axis_forward", "axis_up", "global_scale", "check_existing", "filter_glob", "xna_validate"))
keywords["global_matrix"] = global_matrix
from . import export_fbx
Modified: trunk/py/scripts/addons/io_scene_fbx/export_fbx.py
===================================================================
--- trunk/py/scripts/addons/io_scene_fbx/export_fbx.py 2011-07-31 09:33:04 UTC (rev 2204)
+++ trunk/py/scripts/addons/io_scene_fbx/export_fbx.py 2011-08-01 00:47:09 UTC (rev 2205)
@@ -202,12 +202,20 @@
ANIM_ACTION_ALL=False,
use_metadata=True,
path_mode='AUTO',
+ use_edges=True,
+ use_rotate_workaround=False,
):
import bpy_extras.io_utils
+ # Only used for camera and lamp rotations
mtx_x90 = Matrix.Rotation(math.pi / 2.0, 3, 'X')
+ # Used for mesh and armature rotations
mtx4_z90 = Matrix.Rotation(math.pi / 2.0, 4, 'Z')
+ # Rotation does not work for XNA animations. I do not know why but they end up a mess! (JCB)
+ if use_rotate_workaround:
+ # Set rotation to Matrix Identity for XNA (JCB)
+ mtx4_z90.identity()
if global_matrix is None:
global_matrix = Matrix()
@@ -449,6 +457,11 @@
loc = tuple(loc)
rot = tuple(rot.to_euler()) # quat -> euler
scale = tuple(scale)
+
+ # Essential for XNA to use the original matrix not rotated nor scaled (JCB)
+ if use_rotate_workaround:
+ matrix = ob.matrix_local
+
else:
# 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
@@ -1010,12 +1023,12 @@
)
# matrixOnly is not used at the moment
- def write_null(my_null=None, fbxName=None):
+ def write_null(my_null=None, fbxName=None, fbxType="Null", fbxTypeFlags="Null"):
# ob can be null
if not fbxName:
fbxName = my_null.fbxName
- file.write('\n\tModel: "Model::%s", "Null" {' % fbxName)
+ file.write('\n\tModel: "Model::%s", "%s" {' % (fbxName, fbxType))
file.write('\n\t\tVersion: 232')
if my_null:
@@ -1024,15 +1037,16 @@
poseMatrix = write_object_props()[3]
pose_items.append((fbxName, poseMatrix))
+
+ file.write('\n\t\t}'
+ '\n\t\tMultiLayer: 0'
+ '\n\t\tMultiTake: 1'
+ '\n\t\tShading: Y'
+ '\n\t\tCulling: "CullingOff"'
+ )
- file.write('''
- }
- MultiLayer: 0
- MultiTake: 1
- Shading: Y
- Culling: "CullingOff"
- TypeFlags: "Null"
- }''')
+ file.write('\n\t\tTypeFlags: "%s"' % fbxTypeFlags)
+ file.write('\n\t}')
# Material Settings
if world:
@@ -1312,7 +1326,7 @@
# convert into lists once.
me_vertices = me.vertices[:]
- me_edges = me.edges[:]
+ me_edges = me.edges[:] if use_edges else ()
me_faces = me.faces[:]
poseMatrix = write_object_props(my_mesh.blenObject, None, my_mesh.parRelMatrix())[3]
@@ -2059,13 +2073,31 @@
del tmp_obmapping
# Finished finding groups we use
+
+ # == WRITE OBJECTS TO THE FILE ==
+ # == From now on we are building the FBX file from the information collected above (JCB)
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-extensions-cvs
mailing list