[Bf-extensions-cvs] [eb4085f1] master: glTF importer: accessor decoding enhancements

Julien Duroure noreply at git.blender.org
Sat Nov 9 10:56:57 CET 2019


Commit: eb4085f1dc1522debb6bd490c3002fd0e22e6149
Author: Julien Duroure
Date:   Sat Nov 9 10:52:56 2019 +0100
Branches: master
https://developer.blender.org/rBAeb4085f1dc1522debb6bd490c3002fd0e22e6149

glTF importer: accessor decoding enhancements

===================================================================

M	io_scene_gltf2/__init__.py
M	io_scene_gltf2/io/imp/gltf2_io_binary.py

===================================================================

diff --git a/io_scene_gltf2/__init__.py b/io_scene_gltf2/__init__.py
index 8fcb46b4..6155a811 100755
--- a/io_scene_gltf2/__init__.py
+++ b/io_scene_gltf2/__init__.py
@@ -15,7 +15,7 @@
 bl_info = {
     'name': 'glTF 2.0 format',
     'author': 'Julien Duroure, Norbert Nopper, Urs Hanselmann, Moritz Becher, Benjamin Schmithüsen, Jim Eckerlein, and many external contributors',
-    "version": (1, 1, 1),
+    "version": (1, 1, 2),
     'blender': (2, 81, 6),
     'location': 'File > Import-Export',
     'description': 'Import-Export as glTF 2.0',
diff --git a/io_scene_gltf2/io/imp/gltf2_io_binary.py b/io_scene_gltf2/io/imp/gltf2_io_binary.py
index c72a893a..6969465f 100755
--- a/io_scene_gltf2/io/imp/gltf2_io_binary.py
+++ b/io_scene_gltf2/io/imp/gltf2_io_binary.py
@@ -15,17 +15,24 @@
 import struct
 import base64
 
+from ..com.gltf2_io import Accessor
+
 
 class BinaryData():
     """Binary reader."""
     def __new__(cls, *args, **kwargs):
         raise RuntimeError("%s should not be instantiated" % cls)
 
+# Note that this function is not used in Blender importer, but is kept in
+# Source code to be used in any pipeline that want to manage gltf/glb file in python
     @staticmethod
     def get_binary_from_accessor(gltf, accessor_idx):
         """Get binary from accessor."""
         accessor = gltf.data.accessors[accessor_idx]
-        data = BinaryData.get_buffer_view(gltf, accessor.buffer_view) # TODO initialize with 0 when not present!
+        if accessor.buffer_view is None:
+            return None
+
+        data = BinaryData.get_buffer_view(gltf, accessor.buffer_view)
 
         accessor_offset = accessor.byte_offset
         if accessor_offset is None:
@@ -58,40 +65,78 @@ class BinaryData():
             return gltf.accessor_cache[accessor_idx]
 
         accessor = gltf.data.accessors[accessor_idx]
+        data = BinaryData.get_data_from_accessor_obj(gltf, accessor)
 
-        bufferView = gltf.data.buffer_views[accessor.buffer_view]  # TODO initialize with 0 when not present!
-        buffer_data = BinaryData.get_binary_from_accessor(gltf, accessor_idx)
+        if cache:
+            gltf.accessor_cache[accessor_idx] = data
 
-        fmt_char = gltf.fmt_char_dict[accessor.component_type]
-        component_nb = gltf.component_nb_dict[accessor.type]
-        fmt = '<' + (fmt_char * component_nb)
-        stride_ = struct.calcsize(fmt)
-        # TODO data alignment stuff
+        return data
 
-        if bufferView.byte_stride:
-            stride = bufferView.byte_stride
-        else:
-            stride = stride_
+    @staticmethod
+    def get_data_from_accessor_obj(gltf, accessor):
+        if accessor.buffer_view is not None:
+            bufferView = gltf.data.buffer_views[accessor.buffer_view]
+            buffer_data = BinaryData.get_buffer_view(gltf, accessor.buffer_view)
+
+            accessor_offset = accessor.byte_offset or 0
+            buffer_data = buffer_data[accessor_offset:]
+
+            fmt_char = gltf.fmt_char_dict[accessor.component_type]
+            component_nb = gltf.component_nb_dict[accessor.type]
+            fmt = '<' + (fmt_char * component_nb)
+            default_stride = struct.calcsize(fmt)
+
+            # Special layouts for certain formats; see the section about
+            # data alignment in the glTF 2.0 spec.
+            component_size = struct.calcsize('<' + fmt_char)
+            if accessor.type == 'MAT2' and component_size == 1:
+                fmt = '<FFxxFF'.replace('F', fmt_char)
+                default_stride = 8
+            elif accessor.type == 'MAT3' and component_size == 1:
+                fmt = '<FFFxFFFxFFF'.replace('F', fmt_char)
+                default_stride = 12
+            elif accessor.type == 'MAT3' and component_size == 2:
+                fmt = '<FFFxxFFFxxFFF'.replace('F', fmt_char)
+                default_stride = 24
+
+            stride = bufferView.byte_stride or default_stride
+
+            # Decode
+            unpack_from = struct.Struct(fmt).unpack_from
+            data = [
+                unpack_from(buffer_data, offset)
+                for offset in range(0, accessor.count*stride, stride)
+            ]
 
-        unpack_from = struct.Struct(fmt).unpack_from
-        data = [
-            unpack_from(buffer_data, offset)
-            for offset in range(0, accessor.count*stride, stride)
-        ]
+        else:
+            # No buffer view; initialize to zeros
+            component_nb = gltf.component_nb_dict[accessor.type]
+            data = [
+                (0,) * component_nb
+                for i in range(accessor.count)
+            ]
 
         if accessor.sparse:
-            sparse_indices_data = BinaryData.get_data_from_sparse(gltf, accessor.sparse, "indices")
-            sparse_values_values = BinaryData.get_data_from_sparse(
-                gltf,
-                accessor.sparse,
-                "values",
-                accessor.type,
-                accessor.component_type
-            )
-
-            # apply sparse
-            for cpt_idx, idx in enumerate(sparse_indices_data):
-                data[idx[0]] = sparse_values_values[cpt_idx]
+            sparse_indices_obj = Accessor.from_dict({
+                'count': accessor.sparse.count,
+                'bufferView': accessor.sparse.indices.buffer_view,
+                'byteOffset': accessor.sparse.indices.byte_offset or 0,
+                'componentType': accessor.sparse.indices.component_type,
+                'type': 'SCALAR',
+            })
+            sparse_values_obj = Accessor.from_dict({
+                'count': accessor.sparse.count,
+                'bufferView': accessor.sparse.values.buffer_view,
+                'byteOffset': accessor.sparse.values.byte_offset or 0,
+                'componentType': accessor.component_type,
+                'type': accessor.type,
+            })
+            sparse_indices = BinaryData.get_data_from_accessor_obj(gltf, sparse_indices_obj)
+            sparse_values = BinaryData.get_data_from_accessor_obj(gltf, sparse_values_obj)
+
+            # Apply sparse
+            for i in range(accessor.sparse.count):
+                data[sparse_indices[i][0]] = sparse_values[i]
 
         # Normalization
         if accessor.normalized:
@@ -110,49 +155,6 @@ class BinaryData():
                         new_tuple += (float(i),)
                 data[idx] = new_tuple
 
-        if cache:
-            gltf.accessor_cache[accessor_idx] = data
-
-        return data
-
-    @staticmethod
-    def get_data_from_sparse(gltf, sparse, type_, type_val=None, comp_type=None):
-        """Get data from sparse."""
-        if type_ == "indices":
-            bufferView = gltf.data.buffer_views[sparse.indices.buffer_view]
-            offset = sparse.indices.byte_offset
-            component_nb = gltf.component_nb_dict['SCALAR']
-            fmt_char = gltf.fmt_char_dict[sparse.indices.component_type]
-        elif type_ == "values":
-            bufferView = gltf.data.buffer_views[sparse.values.buffer_view]
-            offset = sparse.values.byte_offset
-            component_nb = gltf.component_nb_dict[type_val]
-            fmt_char = gltf.fmt_char_dict[comp_type]
-
-        if bufferView.buffer in gltf.buffers.keys():
-            buffer = gltf.buffers[bufferView.buffer]
-        else:
-            # load buffer
-            gltf.load_buffer(bufferView.buffer)
-            buffer = gltf.buffers[bufferView.buffer]
-
-        bin_data = buffer[bufferView.byte_offset + offset:bufferView.byte_offset + offset + bufferView.byte_length]
-
-        fmt = '<' + (fmt_char * component_nb)
-        stride_ = struct.calcsize(fmt)
-        # TODO data alignment stuff ?
-
-        if bufferView.byte_stride:
-            stride = bufferView.byte_stride
-        else:
-            stride = stride_
-
-        unpack_from = struct.Struct(fmt).unpack_from
-        data = [
-            unpack_from(bin_data, offset)
-            for offset in range(0, sparse.count*stride, stride)
-        ]
-
         return data
 
     @staticmethod



More information about the Bf-extensions-cvs mailing list