[Bf-extensions-cvs] [b54d306] master: FBX io: better handling for orientation and scale.
Bastien Montagne
noreply at git.blender.org
Sun May 11 12:45:49 CEST 2014
Commit: b54d30693cc4f297c9940d6626d30a9ea497cee0
Author: Bastien Montagne
Date: Sun May 11 12:32:16 2014 +0200
https://developer.blender.org/rBAb54d30693cc4f297c9940d6626d30a9ea497cee0
FBX io: better handling for orientation and scale.
Export: generate a valid scale value from Blender scene's Scale setting (if valid, else 1.0),
assuming 1BU = 1m and 1FBX unit = 1cm.
Import:
* Use by default axes and scale data in FBX file instead of manually specified ones (using same
conventions as in exporter).
* Also import FPS data from FBX file (crucial for future animations import!).
And a few fixes for issues found in those areas as well...
===================================================================
M io_scene_fbx/__init__.py
M io_scene_fbx/export_fbx_bin.py
M io_scene_fbx/import_fbx.py
===================================================================
diff --git a/io_scene_fbx/__init__.py b/io_scene_fbx/__init__.py
index 284005e..226508e 100644
--- a/io_scene_fbx/__init__.py
+++ b/io_scene_fbx/__init__.py
@@ -21,7 +21,7 @@
bl_info = {
"name": "Autodesk FBX format",
"author": "Campbell Barton, Bastien Montagne",
- "version": (3, 0, 0),
+ "version": (3, 1, 0),
"blender": (2, 70, 0),
"location": "File > Import-Export",
"description": "Export FBX meshes, UV's, vertex colors, materials, "
@@ -69,26 +69,11 @@ class ImportFBX(bpy.types.Operator, ImportHelper):
filename_ext = ".fbx"
filter_glob = StringProperty(default="*.fbx", options={'HIDDEN'})
- use_image_search = BoolProperty(
- name="Image Search",
- description="Search subdirs for any associated images (Warning, may be slow)",
- default=True,
- )
-
- use_alpha_decals = BoolProperty(
- name="Alpha Decals",
- description="Treat materials with alpha as decals (no shadow casting)",
+ use_manual_orientation = BoolProperty(
+ name="Manual Orientation",
+ description="Specify orientation and scale, instead of using embeded data in FBX file",
default=False,
- options={'HIDDEN'}
)
- decal_offset = FloatProperty(
- name="Decal Offset",
- description="Displace geometry of alpha meshes",
- min=0.0, max=1.0,
- default=0.0,
- options={'HIDDEN'}
- )
-
axis_forward = EnumProperty(
name="Forward",
items=(('X', "X Forward", ""),
@@ -117,21 +102,42 @@ class ImportFBX(bpy.types.Operator, ImportHelper):
default=1.0,
)
- def execute(self, context):
- from mathutils import Matrix
+ use_image_search = BoolProperty(
+ name="Image Search",
+ description="Search subdirs for any associated images (Warning, may be slow)",
+ default=True,
+ )
- keywords = self.as_keywords(ignore=("axis_forward",
- "axis_up",
- "global_scale",
- "filter_glob",
- "directory",
- ))
+ use_alpha_decals = BoolProperty(
+ name="Alpha Decals",
+ description="Treat materials with alpha as decals (no shadow casting)",
+ default=False,
+ options={'HIDDEN'}
+ )
+ decal_offset = FloatProperty(
+ name="Decal Offset",
+ description="Displace geometry of alpha meshes",
+ min=0.0, max=1.0,
+ default=0.0,
+ options={'HIDDEN'}
+ )
- global_matrix = (Matrix.Scale(self.global_scale, 4) *
- axis_conversion(from_forward=self.axis_forward,
- from_up=self.axis_up,
- ).to_4x4())
- keywords["global_matrix"] = global_matrix
+ def draw(self, context):
+ layout = self.layout
+
+ layout.prop(self, "use_manual_orientation"),
+ sub = layout.column()
+ sub.enabled = self.use_manual_orientation
+ sub.prop(self, "axis_forward")
+ sub.prop(self, "axis_up")
+ sub.prop(self, "global_scale")
+
+ layout.prop(self, "use_image_search")
+ #layout.prop(self, "use_alpha_decals")
+ layout.prop(self, "decal_offset")
+
+ def execute(self, context):
+ keywords = self.as_keywords(ignore=("filter_glob", "directory"))
keywords["use_cycles"] = (context.scene.render.engine == 'CYCLES')
from . import import_fbx
diff --git a/io_scene_fbx/export_fbx_bin.py b/io_scene_fbx/export_fbx_bin.py
index ff43d56..481eded 100644
--- a/io_scene_fbx/export_fbx_bin.py
+++ b/io_scene_fbx/export_fbx_bin.py
@@ -2240,11 +2240,14 @@ def fbx_header_elements(root, scene_data, time=None):
##### Start of GlobalSettings element.
global_settings = elem_empty(root, b"GlobalSettings")
+ scene = scene_data.scene
elem_data_single_int32(global_settings, b"Version", 1000)
props = elem_properties(global_settings)
up_axis, front_axis, coord_axis = RIGHT_HAND_AXES[scene_data.settings.to_axes]
+ # Currently not sure about that, but looks like default unit of FBX is cm...
+ scale_factor = (1.0 if scene.unit_settings.system == 'NONE' else scene.unit_settings.scale_length) * 100
elem_props_set(props, "p_integer", b"UpAxis", up_axis[0])
elem_props_set(props, "p_integer", b"UpAxisSign", up_axis[1])
elem_props_set(props, "p_integer", b"FrontAxis", front_axis[0])
@@ -2253,15 +2256,15 @@ def fbx_header_elements(root, scene_data, time=None):
elem_props_set(props, "p_integer", b"CoordAxisSign", coord_axis[1])
elem_props_set(props, "p_integer", b"OriginalUpAxis", -1)
elem_props_set(props, "p_integer", b"OriginalUpAxisSign", 1)
- elem_props_set(props, "p_double", b"UnitScaleFactor", 1.0)
- elem_props_set(props, "p_double", b"OriginalUnitScaleFactor", 1.0)
+ elem_props_set(props, "p_double", b"UnitScaleFactor", scale_factor)
+ elem_props_set(props, "p_double", b"OriginalUnitScaleFactor", scale_factor)
elem_props_set(props, "p_color_rgb", b"AmbientColor", (0.0, 0.0, 0.0))
elem_props_set(props, "p_string", b"DefaultCamera", "Producer Perspective")
# Global timing data.
- r = scene_data.scene.render
- fps = r.fps / r.fps_base
- fbx_fps, fbx_fps_mode = FBX_FRAMERATES[0] # Custom framerate.
+ r = scene.render
+ _, fbx_fps_mode = FBX_FRAMERATES[0] # Custom framerate.
+ fbx_fps = fps = r.fps / r.fps_base
for ref_fps, fps_mode in FBX_FRAMERATES:
if similar_values(fps, ref_fps):
fbx_fps = ref_fps
diff --git a/io_scene_fbx/import_fbx.py b/io_scene_fbx/import_fbx.py
index ecb152f..199a165 100644
--- a/io_scene_fbx/import_fbx.py
+++ b/io_scene_fbx/import_fbx.py
@@ -178,6 +178,24 @@ def elem_props_get_number(elem, elem_prop_id, default=None):
return default
+def elem_props_get_integer(elem, elem_prop_id, default=None):
+ elem_prop = elem_props_find_first(elem, elem_prop_id)
+ if elem_prop is not None:
+ assert(elem_prop.props[0] == elem_prop_id)
+ if elem_prop.props[1] == b'int':
+ assert(elem_prop.props[1] == b'int')
+ assert(elem_prop.props[2] == b'Integer')
+ elif elem_prop.props[1] == b'ULongLong':
+ assert(elem_prop.props[1] == b'ULongLong')
+ assert(elem_prop.props[2] == b'')
+
+ # we could allow other number types
+ assert(elem_prop.props_type[4] in {data_types.INT32, data_types.INT64})
+
+ return elem_prop.props[4]
+ return default
+
+
def elem_props_get_bool(elem, elem_prop_id, default=None):
elem_prop = elem_props_find_first(elem, elem_prop_id)
if elem_prop is not None:
@@ -873,7 +891,10 @@ def is_ascii(filepath, size):
def load(operator, context, filepath="",
- global_matrix=None,
+ use_manual_orientation=False,
+ axis_forward='-Z',
+ axis_up='Y',
+ global_scale=1.0,
use_cycles=True,
use_image_search=False,
use_alpha_decals=False,
@@ -882,10 +903,12 @@ def load(operator, context, filepath="",
global fbx_elem_nil
fbx_elem_nil = FBXElem('', (), (), ())
- global_scale = (sum(global_matrix.to_scale()) / 3.0) if global_matrix else 1.0
-
import os
+ from bpy_extras.io_utils import axis_conversion
+ from mathutils import Matrix
+
from . import parse_fbx
+ from .fbx_utils import RIGHT_HAND_AXES, FBX_FRAMERATES
# detect ascii files
if is_ascii(filepath, 24):
@@ -929,6 +952,43 @@ def load(operator, context, filepath="",
scene = context.scene
+
+ #### Get some info from GlobalSettings.
+
+ fbx_settings = elem_find_first(elem_root, b'GlobalSettings')
+ fbx_settings_props = elem_find_first(fbx_settings, b'Properties70')
+ if fbx_settings is None or fbx_settings_props is None:
+ operator.report({'ERROR'}, "No 'GlobalSettings' found in file %r" % filepath)
+ return {'CANCELLED'}
+
+ # Compute global matrix and scale.
+ if not use_manual_orientation:
+ axis_forward = (elem_props_get_integer(fbx_settings_props, b'FrontAxis', 1),
+ elem_props_get_integer(fbx_settings_props, b'FrontAxisSign', 1))
+ axis_up = (elem_props_get_integer(fbx_settings_props, b'UpAxis', 2),
+ elem_props_get_integer(fbx_settings_props, b'UpAxisSign', 1))
+ axis_coord = (elem_props_get_integer(fbx_settings_props, b'CoordAxis', 0),
+ elem_props_get_integer(fbx_settings_props, b'CoordAxisSign', 1))
+ print(axis_up, axis_forward, axis_coord)
+ axis_up, axis_forward = {v: k for k, v in RIGHT_HAND_AXES.items()}.get((axis_up, axis_forward, axis_coord), ('Z', 'Y'))
+ print(axis_up, axis_forward)
+ # FBX base unit seems to be the centimeter, while raw Blender Unit is equivalent to the meter...
+ global_scale = elem_props_get_number(fbx_settings_props, b'UnitScaleFactor', 100.0) / 100.0
+ global_matrix = (Matrix.Scale(global_scale, 4) *
+ axis_conversion(from_forward=axis_forward, from_up=axis_up).to_4x4())
+
+ # Compute framerate settings.
+ custom_fps = elem_props_get_number(fbx_settings_props, b'CustomFrameRate', 25.0)
+ time_mode = elem_props_get_enum(fbx_settings_props, b'TimeMode')
+ real_fps = {eid: val for val, eid in FBX_FRAMERATES[1:]}.get(time_mode, custom_fps)
+ if real_fps < 0.0:
+ real_fps = 25.0
+ scene.render.fps = round(real_fps)
+ scene.render.fps_base = scene.render.fps / real_fps
+
+
+ #### And now, the "real" data.
+
fbx_defs = elem_find_first(elem_root, b'Definitions') # can be None
fbx_nodes = elem_find_first(elem_root, b'Objects')
fbx_connections = elem_find_first(elem_root, b'Connections')
More information about the Bf-extensions-cvs
mailing list