Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBastien Montagne <montagne29@wanadoo.fr>2014-09-08 16:58:26 +0400
committerBastien Montagne <montagne29@wanadoo.fr>2014-09-08 16:58:26 +0400
commit075a6a591630733c5e53c24d8d2c53d6ef0ce493 (patch)
tree81dac8e35c8e52b142bef885c64d2b190cc5f628
parent866397a8ffb8c1bc994b29de9f78059215bcd57d (diff)
FBX Importer: Bake space transform on import
Revision: D739 Patch by jrestemeier (Jens Restemeier).
-rw-r--r--io_scene_fbx_experimental/__init__.py8
-rw-r--r--io_scene_fbx_experimental/fbx_utils.py1
-rw-r--r--io_scene_fbx_experimental/import_fbx.py71
3 files changed, 68 insertions, 12 deletions
diff --git a/io_scene_fbx_experimental/__init__.py b/io_scene_fbx_experimental/__init__.py
index b1e0777d..a273e21c 100644
--- a/io_scene_fbx_experimental/__init__.py
+++ b/io_scene_fbx_experimental/__init__.py
@@ -101,6 +101,13 @@ class ImportFBX_experimental(bpy.types.Operator, ImportHelper):
min=0.001, max=1000.0,
default=1.0,
)
+ bake_space_transform = BoolProperty(
+ name="Apply Transform",
+ description=("Bake space transform into object data, avoids getting unwanted rotations to objects when "
+ "target space is not aligned with Blender's space "
+ "(WARNING! experimental option, might give odd/wrong results)"),
+ default=False,
+ )
use_image_search = BoolProperty(
name="Image Search",
@@ -180,6 +187,7 @@ class ImportFBX_experimental(bpy.types.Operator, ImportHelper):
sub.prop(self, "axis_forward")
sub.prop(self, "axis_up")
sub.prop(self, "global_scale")
+ layout.prop(self, "bake_space_transform")
layout.prop(self, "use_image_search")
# layout.prop(self, "use_alpha_decals")
diff --git a/io_scene_fbx_experimental/fbx_utils.py b/io_scene_fbx_experimental/fbx_utils.py
index e0651656..f0eeca03 100644
--- a/io_scene_fbx_experimental/fbx_utils.py
+++ b/io_scene_fbx_experimental/fbx_utils.py
@@ -1102,6 +1102,7 @@ FBXExportData = namedtuple("FBXExportData", (
# Helper container gathering all importer settings.
FBXImportSettings = namedtuple("FBXImportSettings", (
"report", "to_axes", "global_matrix", "global_scale",
+ "bake_space_transform", "global_matrix_inv", "global_matrix_inv_transposed",
"use_cycles", "use_image_search",
"use_alpha_decals", "decal_offset",
"use_custom_props", "use_custom_props_enum_as_string",
diff --git a/io_scene_fbx_experimental/import_fbx.py b/io_scene_fbx_experimental/import_fbx.py
index 4bb64436..98edf0c2 100644
--- a/io_scene_fbx_experimental/import_fbx.py
+++ b/io_scene_fbx_experimental/import_fbx.py
@@ -624,15 +624,21 @@ def blen_read_geom_array_mapped_vert(
fbx_layer_data, fbx_layer_index,
fbx_layer_mapping, fbx_layer_ref,
stride, item_size, descr,
+ xform=None
):
# TODO, generic mapping apply function
if fbx_layer_mapping == b'ByVertice':
if fbx_layer_ref == b'Direct':
assert(fbx_layer_index is None)
# TODO, more generic support for mapping types
- for i, blen_data_item in enumerate(blen_data):
- setattr(blen_data_item, blend_attr,
- fbx_layer_data[(i * stride): (i * stride) + item_size])
+ if xform is None:
+ for i, blen_data_item in enumerate(blen_data):
+ setattr(blen_data_item, blend_attr,
+ fbx_layer_data[(i * stride): (i * stride) + item_size])
+ else:
+ for i, blen_data_item in enumerate(blen_data):
+ setattr(blen_data_item, blend_attr,
+ xform(fbx_layer_data[(i * stride): (i * stride) + item_size]))
return True
else:
print("warning layer %r ref type unsupported: %r" % (descr, fbx_layer_ref))
@@ -881,7 +887,7 @@ def blen_read_geom_layer_smooth(fbx_obj, mesh):
return False
-def blen_read_geom_layer_normal(fbx_obj, mesh):
+def blen_read_geom_layer_normal(fbx_obj, mesh, xform=None):
fbx_layer = elem_find_first(fbx_obj, b'LayerElementNormal')
if fbx_layer is None:
@@ -902,10 +908,25 @@ def blen_read_geom_layer_normal(fbx_obj, mesh):
fbx_layer_data, None,
fbx_layer_mapping, fbx_layer_ref,
3, 3, layer_id,
+ xform
)
def blen_read_geom(fbx_tmpl, fbx_obj, settings):
+ from mathutils import Matrix, Vector
+ from itertools import chain
+ import array
+
+ # Vertices are in object space, but we are post-multiplying all transforms with the inverse of the
+ # global matrix, so we need to apply the global matrix to the vertices to get the correct result.
+ geom_mat_co = settings.global_matrix if settings.bake_space_transform else None
+ # We need to apply the inverse transpose of the global matrix when transforming normals.
+ geom_mat_no = Matrix(settings.global_matrix_inv_transposed) if settings.bake_space_transform else None
+ if geom_mat_no is not None:
+ # Remove translation & scaling!
+ geom_mat_no.translation = Vector()
+ geom_mat_no.normalize()
+
# TODO, use 'fbx_tmpl'
elem_name_utf8 = elem_name_ensure_class(fbx_obj, b'Geometry')
@@ -913,6 +934,12 @@ def blen_read_geom(fbx_tmpl, fbx_obj, settings):
fbx_polys = elem_prop_first(elem_find_first(fbx_obj, b'PolygonVertexIndex'))
fbx_edges = elem_prop_first(elem_find_first(fbx_obj, b'Edges'))
+ if geom_mat_co is not None:
+ def _vcos_transformed_gen(raw_cos, m=None):
+ # Note: we could most likely get much better performances with numpy, but will leave this as TODO for now.
+ return chain(*(m * Vector(v) for v in zip(*(iter(raw_cos),) * 3)))
+ fbx_verts = array.array(fbx_verts.typecode, _vcos_transformed_gen(fbx_verts, geom_mat_co))
+
if fbx_verts is None:
fbx_verts = ()
if fbx_polys is None:
@@ -978,7 +1005,12 @@ def blen_read_geom(fbx_tmpl, fbx_obj, settings):
# must be after edge, face loading.
ok_smooth = blen_read_geom_layer_smooth(fbx_obj, mesh)
- ok_normals = blen_read_geom_layer_normal(fbx_obj, mesh)
+ if geom_mat_no is None:
+ ok_normals = blen_read_geom_layer_normal(fbx_obj, mesh)
+ else:
+ def nortrans(v):
+ return geom_mat_no * Vector(v)
+ ok_normals = blen_read_geom_layer_normal(fbx_obj, mesh, nortrans)
mesh.validate()
@@ -1274,16 +1306,21 @@ class FbxImportHelperNode:
child.ignore = True # Ignore leaf bone at end of chain
for child in self.children:
child.mark_leaf_bones()
-
- def find_correction_matrix(self, settings, parent_correction_inv = None):
+
+ def do_bake_transform(self, settings):
+ return (settings.bake_space_transform and self.fbx_type in (b'Mesh', b'Null') and
+ not self.is_armature and not self.is_bone)
+
+ def find_correction_matrix(self, settings, parent_correction_inv=None):
from bpy_extras.io_utils import axis_conversion
from mathutils import Matrix, Vector
- if self.parent and self.parent.is_root:
+ if self.parent and (self.parent.is_root or self.parent.do_bake_transform(settings)):
self.pre_matrix = settings.global_matrix
- else:
- self.pre_matrix = parent_correction_inv # if the parent has a correction we need the inverse applied here
-
+
+ if parent_correction_inv:
+ self.pre_matrix = parent_correction_inv * (self.pre_matrix if self.pre_matrix else Matrix())
+
correction_matrix = None
if self.is_bone:
@@ -1372,7 +1409,10 @@ class FbxImportHelperNode:
correction_matrix = MAT_CONVERT_LAMP
self.post_matrix = correction_matrix
-
+
+ if self.do_bake_transform(settings):
+ self.post_matrix = settings.global_matrix_inv * (self.post_matrix if self.post_matrix else Matrix())
+
# process children
correction_matrix_inv = correction_matrix.inverted() if correction_matrix else None
for child in self.children:
@@ -1805,6 +1845,7 @@ def load(operator, context, filepath="",
axis_forward='-Z',
axis_up='Y',
global_scale=1.0,
+ bake_space_transform=False,
use_cycles=True,
use_image_search=False,
use_alpha_decals=False,
@@ -1894,6 +1935,11 @@ def load(operator, context, filepath="",
global_matrix = (Matrix.Scale(global_scale, 4) *
axis_conversion(from_forward=axis_forward, from_up=axis_up).to_4x4())
+ # To cancel out unwanted rotation/scale on nodes.
+ global_matrix_inv = global_matrix.inverted()
+ # For transforming mesh normals.
+ global_matrix_inv_transposed = global_matrix_inv.transposed()
+
# Compute bone correction matrix
bone_correction_matrix = None # None means no correction/identity
if not automatic_bone_orientation:
@@ -1916,6 +1962,7 @@ def load(operator, context, filepath="",
# store global settings that need to be accessed during conversion
settings = FBXImportSettings(
operator.report, (axis_up, axis_forward), global_matrix, global_scale,
+ bake_space_transform, global_matrix_inv, global_matrix_inv_transposed,
use_cycles, use_image_search,
use_alpha_decals, decal_offset,
use_custom_props, use_custom_props_enum_as_string,