Browse Source

Blender: export hierarchy

rkusa 10 years ago
parent
commit
02a08075e8

+ 13 - 0
utils/exporters/blender/addons/io_three/__init__.py

@@ -303,6 +303,7 @@ def save_settings_export(properties):
         constants.EMBED_ANIMATION: properties.option_embed_animation,
         constants.EMBED_ANIMATION: properties.option_embed_animation,
         constants.LIGHTS: properties.option_lights,
         constants.LIGHTS: properties.option_lights,
         constants.CAMERAS: properties.option_cameras,
         constants.CAMERAS: properties.option_cameras,
+        constants.HIERARCHY: properties.option_hierarchy,
 
 
         constants.MORPH_TARGETS: properties.option_animation_morph,
         constants.MORPH_TARGETS: properties.option_animation_morph,
         constants.ANIMATION: properties.option_animation_skeletal,
         constants.ANIMATION: properties.option_animation_skeletal,
@@ -447,6 +448,10 @@ def restore_settings_export(properties):
     properties.option_cameras = settings.get(
     properties.option_cameras = settings.get(
         constants.CAMERAS,
         constants.CAMERAS,
         constants.EXPORT_OPTIONS[constants.CAMERAS])
         constants.EXPORT_OPTIONS[constants.CAMERAS])
+
+    properties.option_hierarchy = settings.get(
+        constants.HIERARCHY,
+        constants.EXPORT_OPTIONS[constants.HIERARCHY])
     ## }
     ## }
 
 
     ## Animation {
     ## Animation {
@@ -638,6 +643,11 @@ class ExportThree(bpy.types.Operator, ExportHelper):
         description="Export default scene cameras",
         description="Export default scene cameras",
         default=False)
         default=False)
 
 
+    option_hierarchy = BoolProperty(
+        name="Hierarchy",
+        description="Export object hierarchy",
+        default=False)
+
     option_animation_morph = BoolProperty(
     option_animation_morph = BoolProperty(
         name="Morph animation",
         name="Morph animation",
         description="Export animation (morphs)",
         description="Export animation (morphs)",
@@ -811,6 +821,9 @@ class ExportThree(bpy.types.Operator, ExportHelper):
         row.prop(self.properties, 'option_cameras')
         row.prop(self.properties, 'option_cameras')
         ## }
         ## }
 
 
+        row = layout.row()
+        row.prop(self.properties, 'option_hierarchy')
+
         layout.separator()
         layout.separator()
 
 
         ## Settings {
         ## Settings {

+ 3 - 0
utils/exporters/blender/addons/io_three/constants.py

@@ -60,6 +60,7 @@ SKIN_WEIGHTS = 'skinWeights'
 LOGGING = 'logging'
 LOGGING = 'logging'
 CAMERAS = 'cameras'
 CAMERAS = 'cameras'
 LIGHTS = 'lights'
 LIGHTS = 'lights'
+HIERARCHY = 'hierarchy'
 FACE_MATERIALS = 'faceMaterials'
 FACE_MATERIALS = 'faceMaterials'
 SKINNING = 'skinning'
 SKINNING = 'skinning'
 COPY_TEXTURES = 'copyTextures'
 COPY_TEXTURES = 'copyTextures'
@@ -110,6 +111,7 @@ EXPORT_OPTIONS = {
     MORPH_TARGETS: False,
     MORPH_TARGETS: False,
     CAMERAS: False,
     CAMERAS: False,
     LIGHTS: False,
     LIGHTS: False,
+    HIERARCHY: False,
     COPY_TEXTURES: True,
     COPY_TEXTURES: True,
     TEXTURE_FOLDER: '',
     TEXTURE_FOLDER: '',
     LOGGING: DEBUG,
     LOGGING: DEBUG,
@@ -160,6 +162,7 @@ POINT_LIGHT = 'PointLight'
 SPOT_LIGHT = 'SpotLight'
 SPOT_LIGHT = 'SpotLight'
 HEMISPHERE_LIGHT = 'HemisphereLight'
 HEMISPHERE_LIGHT = 'HemisphereLight'
 MESH = 'Mesh'
 MESH = 'Mesh'
+EMPTY = 'Empty'
 SPRITE = 'Sprite'
 SPRITE = 'Sprite'
 
 
 DEFAULT_METADATA = {
 DEFAULT_METADATA = {

+ 25 - 42
utils/exporters/blender/addons/io_three/exporter/api/object.py

@@ -2,6 +2,7 @@ import math
 import mathutils
 import mathutils
 import bpy
 import bpy
 from bpy import data, context, types
 from bpy import data, context, types
+from bpy_extras.io_utils import axis_conversion
 from .. import constants, logger, utilities, exceptions
 from .. import constants, logger, utilities, exceptions
 from .constants import (
 from .constants import (
     MESH,
     MESH,
@@ -225,14 +226,8 @@ def position(obj, options):
 
 
     """
     """
     logger.debug('object.position(%s)', obj)
     logger.debug('object.position(%s)', obj)
-    vector = _decompose_matrix(obj)[0]
-    vector = (vector.x, vector.y, vector.z)
-
-    round_off, round_val = utilities.rounding(options)
-    if round_off:
-        vector = utilities.round_off(vector, round_val)
-
-    return vector
+    vector = matrix(obj, options).to_translation()
+    return (vector.x, vector.y, vector.z)
 
 
 
 
 @_object
 @_object
@@ -250,23 +245,35 @@ def receive_shadow(obj):
             return False
             return False
 
 
 
 
+AXIS_CONVERSION = axis_conversion(to_forward='Z', to_up='Y').to_4x4()
+
 @_object
 @_object
-def rotation(obj, options):
+def matrix(obj, options):
     """
     """
 
 
     :param obj:
     :param obj:
     :param options:
     :param options:
 
 
     """
     """
-    logger.debug('object.rotation(%s)', obj)
-    vector = _decompose_matrix(obj)[1].to_euler(ZYX)
-    vector = (vector.x, vector.y, vector.z)
+    logger.debug('object.matrix(%s)', obj)
+    if options.get(constants.HIERARCHY, False) and obj.parent:
+        parent_inverted = obj.parent.matrix_world.inverted(mathutils.Matrix())
+        return parent_inverted * obj.matrix_world
+    else:
+        return AXIS_CONVERSION * obj.matrix_world
+
 
 
-    round_off, round_val = utilities.rounding(options)
-    if round_off:
-        vector = utilities.round_off(vector, round_val)
+@_object
+def rotation(obj, options):
+    """
+
+    :param obj:
+    :param options:
 
 
-    return vector
+    """
+    logger.debug('object.rotation(%s)', obj)
+    vector = matrix(obj, options).to_euler(ZYX)
+    return (vector.x, vector.y, vector.z)
 
 
 
 
 @_object
 @_object
@@ -278,14 +285,8 @@ def scale(obj, options):
 
 
     """
     """
     logger.debug('object.scale(%s)', obj)
     logger.debug('object.scale(%s)', obj)
-    vector = _decompose_matrix(obj)[2]
-    vector = (vector.x, vector.y, vector.z)
-
-    round_off, round_val = utilities.rounding(options)
-    if round_off:
-        vector = utilities.round_off(vector, round_val)
-
-    return vector
+    vector = matrix(obj, options).to_scale()
+    return (vector.x, vector.y, vector.z)
 
 
 
 
 @_object
 @_object
@@ -477,24 +478,6 @@ def extracted_meshes():
     return [key for key in _MESH_MAP.keys()]
     return [key for key in _MESH_MAP.keys()]
 
 
 
 
-def _decompose_matrix(obj, local=False):
-    """
-
-    :param obj:
-    :param local:  (Default value = False)
-
-    """
-    rotate_x_pi2 = mathutils.Quaternion((1.0, 0.0, 0.0),
-                                        math.radians(-90.0))
-    rotate_x_pi2 = rotate_x_pi2.to_matrix().to_4x4()
-
-    if local:
-        matrix = rotate_x_pi2 * obj.matrix_local
-    else:
-        matrix = rotate_x_pi2 * obj.matrix_world
-    return matrix.decompose()
-
-
 def _on_visible_layer(obj, visible_layers):
 def _on_visible_layer(obj, visible_layers):
     """
     """
 
 

+ 12 - 12
utils/exporters/blender/addons/io_three/exporter/object.py

@@ -68,14 +68,13 @@ class Object(base_classes.BaseNode):
         logger.debug("Object()._node_setup()")
         logger.debug("Object()._node_setup()")
         self[constants.NAME] = api.object.name(self.node)
         self[constants.NAME] = api.object.name(self.node)
 
 
-        self[constants.POSITION] = api.object.position(
-            self.node, self.options)
+        transform = api.object.matrix(self.node, self.options)
+        matrix = []
+        for col in range(0, 4):
+            for row in range(0, 4):
+                matrix.append(transform[row][col])
 
 
-        self[constants.ROTATION] = api.object.rotation(
-            self.node, self.options)
-
-        self[constants.SCALE] = api.object.scale(
-            self.node, self.options)
+        self[constants.MATRIX] = matrix
 
 
         self[constants.VISIBLE] = api.object.visible(self.node)
         self[constants.VISIBLE] = api.object.visible(self.node)
 
 
@@ -120,11 +119,12 @@ class Object(base_classes.BaseNode):
         elif self[constants.TYPE] in lights:
         elif self[constants.TYPE] in lights:
             self._init_light()
             self._init_light()
 
 
-        #for child in api.object.children(self.node, self.scene.valid_types):
-        #    if not self.get(constants.CHILDREN):
-        #        self[constants.CHILDREN] = [Object(child, parent=self)]
-        #    else:
-        #        self[constants.CHILDREN].append(Object(child, parent=self))
+        if self.options.get(constants.HIERARCHY, False):
+            for child in api.object.children(self.node, self.scene.valid_types):
+                if not self.get(constants.CHILDREN):
+                    self[constants.CHILDREN] = [Object(child, parent=self)]
+                else:
+                    self[constants.CHILDREN].append(Object(child, parent=self))
 
 
     def _root_setup(self):
     def _root_setup(self):
         """Applies to a root/scene object"""
         """Applies to a root/scene object"""

+ 9 - 1
utils/exporters/blender/addons/io_three/exporter/scene.py

@@ -39,6 +39,9 @@ class Scene(base_classes.BaseScene):
         """
         """
         valid_types = [api.constants.MESH]
         valid_types = [api.constants.MESH]
 
 
+        if self.options.get(constants.HIERARCHY, False):
+            valid_types.append(api.constants.EMPTY)
+
         if self.options.get(constants.CAMERAS):
         if self.options.get(constants.CAMERAS):
             logger.info("Adding cameras to valid object types")
             logger.info("Adding cameras to valid object types")
             valid_types.append(api.constants.CAMERA)
             valid_types.append(api.constants.CAMERA)
@@ -207,7 +210,12 @@ class Scene(base_classes.BaseScene):
         self[constants.UUID] = utilities.id_from_name(scene_name)
         self[constants.UUID] = utilities.id_from_name(scene_name)
 
 
         objects = []
         objects = []
-        for node in api.object.nodes(self.valid_types, self.options):
+        if self.options.get(constants.HIERARCHY, False):
+            nodes = api.object.assemblies(self.valid_types, self.options)
+        else:
+            nodes = api.object.nodes(self.valid_types, self.options)
+
+        for node in nodes:
             logger.info("Parsing object %s", node)
             logger.info("Parsing object %s", node)
             obj = object_.Object(node, parent=self[constants.OBJECT])
             obj = object_.Object(node, parent=self[constants.OBJECT])
             objects.append(obj)
             objects.append(obj)