Fix #104684: json2fbx.py script creates invalid FBX v7500+ files #104913
@ -5,7 +5,7 @@
|
|||||||
bl_info = {
|
bl_info = {
|
||||||
"name": "FBX format",
|
"name": "FBX format",
|
||||||
"author": "Campbell Barton, Bastien Montagne, Jens Restemeier, @Mysteryem",
|
"author": "Campbell Barton, Bastien Montagne, Jens Restemeier, @Mysteryem",
|
||||||
"version": (5, 8, 2),
|
"version": (5, 8, 3),
|
||||||
"blender": (3, 6, 0),
|
"blender": (3, 6, 0),
|
||||||
"location": "File > Import-Export",
|
"location": "File > Import-Export",
|
||||||
"description": "FBX IO meshes, UVs, vertex colors, materials, textures, cameras, lamps and actions",
|
"description": "FBX IO meshes, UVs, vertex colors, materials, textures, cameras, lamps and actions",
|
||||||
|
@ -12,8 +12,10 @@ import array
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import zlib
|
import zlib
|
||||||
|
|
||||||
_BLOCK_SENTINEL_LENGTH = 13
|
_BLOCK_SENTINEL_LENGTH = ...
|
||||||
_BLOCK_SENTINEL_DATA = (b'\0' * _BLOCK_SENTINEL_LENGTH)
|
_BLOCK_SENTINEL_DATA = ...
|
||||||
|
_ELEM_META_FORMAT = ...
|
||||||
|
_ELEM_META_SIZE = ...
|
||||||
_IS_BIG_ENDIAN = (__import__("sys").byteorder != 'little')
|
_IS_BIG_ENDIAN = (__import__("sys").byteorder != 'little')
|
||||||
_HEAD_MAGIC = b'Kaydara FBX Binary\x20\x20\x00\x1a\x00'
|
_HEAD_MAGIC = b'Kaydara FBX Binary\x20\x20\x00\x1a\x00'
|
||||||
|
|
||||||
@ -227,7 +229,7 @@ class FBXElem:
|
|||||||
assert(self._end_offset == -1)
|
assert(self._end_offset == -1)
|
||||||
assert(self._props_length == -1)
|
assert(self._props_length == -1)
|
||||||
|
|
||||||
offset += 12 # 3 uints
|
offset += _ELEM_META_SIZE # 3 uints (or 3 ulonglongs for FBX 7500 and later)
|
||||||
offset += 1 + len(self.id) # len + idname
|
offset += 1 + len(self.id) # len + idname
|
||||||
|
|
||||||
props_length = 0
|
props_length = 0
|
||||||
@ -258,7 +260,7 @@ class FBXElem:
|
|||||||
assert(self._end_offset != -1)
|
assert(self._end_offset != -1)
|
||||||
assert(self._props_length != -1)
|
assert(self._props_length != -1)
|
||||||
|
|
||||||
write(pack('<3I', self._end_offset, len(self.props), self._props_length))
|
write(pack(_ELEM_META_FORMAT, self._end_offset, len(self.props), self._props_length))
|
||||||
|
|
||||||
write(bytes((len(self.id),)))
|
write(bytes((len(self.id),)))
|
||||||
write(self.id)
|
write(self.id)
|
||||||
@ -271,7 +273,7 @@ class FBXElem:
|
|||||||
|
|
||||||
if tell() != self._end_offset:
|
if tell() != self._end_offset:
|
||||||
raise IOError("scope length not reached, "
|
raise IOError("scope length not reached, "
|
||||||
"something is wrong (%d)" % (end_offset - tell()))
|
"something is wrong (%d)" % (self._end_offset - tell()))
|
||||||
|
|
||||||
def _write_children(self, write, tell, is_last):
|
def _write_children(self, write, tell, is_last):
|
||||||
if self.elems:
|
if self.elems:
|
||||||
@ -316,6 +318,27 @@ def _write_timedate_hack(elem_root):
|
|||||||
print("Missing fields!")
|
print("Missing fields!")
|
||||||
|
|
||||||
|
|
||||||
|
# FBX 7500 (aka FBX2016) introduces incompatible changes at binary level:
|
||||||
|
# * The NULL block marking end of nested stuff switches from 13 bytes long to 25 bytes long.
|
||||||
|
# * The FBX element metadata (end_offset, prop_count and prop_length) switch from uint32 to uint64.
|
||||||
|
def init_version(fbx_version):
|
||||||
|
global _BLOCK_SENTINEL_LENGTH, _BLOCK_SENTINEL_DATA, _ELEM_META_FORMAT, _ELEM_META_SIZE
|
||||||
|
|
||||||
|
_BLOCK_SENTINEL_LENGTH = ...
|
||||||
|
_BLOCK_SENTINEL_DATA = ...
|
||||||
|
_ELEM_META_FORMAT = ...
|
||||||
|
_ELEM_META_SIZE = ...
|
||||||
|
|
||||||
|
if fbx_version < 7500:
|
||||||
|
_ELEM_META_FORMAT = '<3I'
|
||||||
|
_ELEM_META_SIZE = 12
|
||||||
|
else:
|
||||||
|
_ELEM_META_FORMAT = '<3Q'
|
||||||
|
_ELEM_META_SIZE = 24
|
||||||
|
_BLOCK_SENTINEL_LENGTH = _ELEM_META_SIZE + 1
|
||||||
|
_BLOCK_SENTINEL_DATA = (b'\0' * _BLOCK_SENTINEL_LENGTH)
|
||||||
|
|
||||||
|
|
||||||
def write(fn, elem_root, version):
|
def write(fn, elem_root, version):
|
||||||
assert(elem_root.id == b'')
|
assert(elem_root.id == b'')
|
||||||
|
|
||||||
@ -323,6 +346,8 @@ def write(fn, elem_root, version):
|
|||||||
write = f.write
|
write = f.write
|
||||||
tell = f.tell
|
tell = f.tell
|
||||||
|
|
||||||
|
init_version(version)
|
||||||
|
|
||||||
write(_HEAD_MAGIC)
|
write(_HEAD_MAGIC)
|
||||||
write(pack('<I', version))
|
write(pack('<I', version))
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user