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:
authorJulien Duroure <julien.duroure@gmail.com>2019-11-09 12:52:56 +0300
committerJulien Duroure <julien.duroure@gmail.com>2019-11-09 12:52:56 +0300
commiteb4085f1dc1522debb6bd490c3002fd0e22e6149 (patch)
tree5f5a367d77d850cd405b3648db6e94e261c7a076 /io_scene_gltf2/io/imp/gltf2_io_binary.py
parent5367ebad4813a41b245b242322d6c94f34254f54 (diff)
glTF importer: accessor decoding enhancements
Diffstat (limited to 'io_scene_gltf2/io/imp/gltf2_io_binary.py')
-rwxr-xr-xio_scene_gltf2/io/imp/gltf2_io_binary.py146
1 files changed, 74 insertions, 72 deletions
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