glTF exporter: fix various animation & texture export
This commit is contained in:
parent
73df2edf63
commit
b93459de4b
|
@ -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": (0, 9, 6),
|
||||
"version": (0, 9, 7),
|
||||
'blender': (2, 80, 0),
|
||||
'location': 'File > Import-Export',
|
||||
'description': 'Import-Export as glTF 2.0',
|
||||
|
|
|
@ -105,9 +105,6 @@ def convert_swizzle_scale(scale, export_settings):
|
|||
def decompose_transition(matrix, export_settings):
|
||||
translation, rotation, scale = matrix.decompose()
|
||||
|
||||
# Put w at the end.
|
||||
rotation = Quaternion((rotation[1], rotation[2], rotation[3], rotation[0]))
|
||||
|
||||
return translation, rotation, scale
|
||||
|
||||
def extract_primitive_floor(a, indices, use_tangents):
|
||||
|
|
|
@ -116,8 +116,6 @@ def __gather_output(channels: typing.Tuple[bpy.types.FCurve],
|
|||
|
||||
target_datapath = channels[0].data_path
|
||||
|
||||
transform = mathutils.Matrix.Identity(4)
|
||||
|
||||
is_yup = export_settings[gltf2_blender_export_keys.YUP]
|
||||
|
||||
# bone animations need to be handled differently as they are in a different coordinate system
|
||||
|
@ -141,6 +139,10 @@ def __gather_output(channels: typing.Tuple[bpy.types.FCurve],
|
|||
bone.parent.bone.matrix_local.inverted(), bone.bone.matrix_local)
|
||||
|
||||
transform = correction_matrix_local
|
||||
else:
|
||||
transform = mathutils.Matrix.Identity(4)
|
||||
else:
|
||||
transform = parent_inverse
|
||||
|
||||
values = []
|
||||
for keyframe in keyframes:
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
from . import gltf2_blender_export_keys
|
||||
from io_scene_gltf2.blender.exp.gltf2_blender_gather_cache import cached
|
||||
from io_scene_gltf2.blender.exp import gltf2_blender_generate_extras
|
||||
from io_scene_gltf2.io.com import gltf2_io
|
||||
|
||||
import bpy
|
||||
|
@ -44,6 +45,8 @@ def __gather_extensions(blender_camera, export_settings):
|
|||
|
||||
|
||||
def __gather_extras(blender_camera, export_settings):
|
||||
if export_settings['gltf_extras']:
|
||||
return gltf2_blender_generate_extras.generate_extras(blender_camera)
|
||||
return None
|
||||
|
||||
|
||||
|
|
|
@ -36,21 +36,37 @@ def gather_image(
|
|||
if not __filter_image(blender_shader_sockets_or_texture_slots, export_settings):
|
||||
return None
|
||||
|
||||
uri = __gather_uri(blender_shader_sockets_or_texture_slots, export_settings)
|
||||
buffer_view = __gather_buffer_view(blender_shader_sockets_or_texture_slots, export_settings)
|
||||
if not (uri is not None or buffer_view is not None):
|
||||
image_data = __get_image_data(blender_shader_sockets_or_texture_slots, export_settings)
|
||||
if image_data is None:
|
||||
# The blender image has no data
|
||||
return None
|
||||
|
||||
image = gltf2_io.Image(
|
||||
mime_type = __gather_mime_type(blender_shader_sockets_or_texture_slots, export_settings)
|
||||
name = __gather_name(blender_shader_sockets_or_texture_slots, export_settings)
|
||||
|
||||
uri = __gather_uri(image_data, mime_type, name, export_settings)
|
||||
buffer_view = __gather_buffer_view(image_data, mime_type, name, export_settings)
|
||||
|
||||
return __make_image(
|
||||
buffer_view,
|
||||
__gather_extensions(blender_shader_sockets_or_texture_slots, export_settings),
|
||||
__gather_extras(blender_shader_sockets_or_texture_slots, export_settings),
|
||||
mime_type,
|
||||
name,
|
||||
uri,
|
||||
export_settings
|
||||
)
|
||||
|
||||
@cached
|
||||
def __make_image(buffer_view, extensions, extras, mime_type, name, uri, export_settings):
|
||||
return gltf2_io.Image(
|
||||
buffer_view=buffer_view,
|
||||
extensions=__gather_extensions(blender_shader_sockets_or_texture_slots, export_settings),
|
||||
extras=__gather_extras(blender_shader_sockets_or_texture_slots, export_settings),
|
||||
mime_type=__gather_mime_type(blender_shader_sockets_or_texture_slots, export_settings),
|
||||
name=__gather_name(blender_shader_sockets_or_texture_slots, export_settings),
|
||||
extensions=extensions,
|
||||
extras=extras,
|
||||
mime_type=mime_type,
|
||||
name=name,
|
||||
uri=uri
|
||||
)
|
||||
return image
|
||||
|
||||
|
||||
def __filter_image(sockets_or_slots, export_settings):
|
||||
|
@ -59,13 +75,10 @@ def __filter_image(sockets_or_slots, export_settings):
|
|||
return True
|
||||
|
||||
|
||||
def __gather_buffer_view(sockets_or_slots, export_settings):
|
||||
@cached
|
||||
def __gather_buffer_view(image_data, mime_type, name, export_settings):
|
||||
if export_settings[gltf2_blender_export_keys.FORMAT] != 'GLTF_SEPARATE':
|
||||
image = __get_image_data(sockets_or_slots, export_settings)
|
||||
if image is None:
|
||||
return None
|
||||
return gltf2_io_binary_data.BinaryData(
|
||||
data=image.encode(__gather_mime_type(sockets_or_slots, export_settings)))
|
||||
return gltf2_io_binary_data.BinaryData(data=image_data.encode(mime_type))
|
||||
return None
|
||||
|
||||
|
||||
|
@ -100,14 +113,14 @@ def __gather_name(sockets_or_slots, export_settings):
|
|||
return image_name
|
||||
|
||||
|
||||
def __gather_uri(sockets_or_slots, export_settings):
|
||||
@cached
|
||||
def __gather_uri(image_data, mime_type, name, export_settings):
|
||||
if export_settings[gltf2_blender_export_keys.FORMAT] == 'GLTF_SEPARATE':
|
||||
# as usual we just store the data in place instead of already resolving the references
|
||||
mime_type = __gather_mime_type(sockets_or_slots, export_settings)
|
||||
return gltf2_io_image_data.ImageData(
|
||||
data=__get_image_data(sockets_or_slots, export_settings).encode(mime_type=mime_type),
|
||||
data=image_data.encode(mime_type=mime_type),
|
||||
mime_type=mime_type,
|
||||
name=__gather_name(sockets_or_slots, export_settings)
|
||||
name=name
|
||||
)
|
||||
|
||||
return None
|
||||
|
@ -122,9 +135,9 @@ def __is_slot(sockets_or_slots):
|
|||
|
||||
|
||||
def __get_image_data(sockets_or_slots, export_settings) -> gltf2_blender_image.ExportImage:
|
||||
# For shared ressources, such as images, we just store the portion of data that is needed in the glTF property
|
||||
# For shared resources, such as images, we just store the portion of data that is needed in the glTF property
|
||||
# in a helper class. During generation of the glTF in the exporter these will then be combined to actual binary
|
||||
# ressources.
|
||||
# resources.
|
||||
def split_pixels_by_channels(image: bpy.types.Image, export_settings) -> typing.Optional[typing.List[typing.List[float]]]:
|
||||
channelcache = export_settings['gltf_channelcache']
|
||||
if image.name in channelcache:
|
||||
|
|
|
@ -52,8 +52,8 @@ def gather_joint(blender_bone, export_settings):
|
|||
translation, rotation, scale = (None, None, None)
|
||||
if trans[0] != 0.0 or trans[1] != 0.0 or trans[2] != 0.0:
|
||||
translation = [trans[0], trans[1], trans[2]]
|
||||
if rot[0] != 0.0 or rot[1] != 0.0 or rot[2] != 0.0 or rot[3] != 1.0:
|
||||
rotation = [rot[0], rot[1], rot[2], rot[3]]
|
||||
if rot[0] != 1.0 or rot[1] != 0.0 or rot[2] != 0.0 or rot[3] != 0.0:
|
||||
rotation = [rot[1], rot[2], rot[3], rot[0]]
|
||||
if sca[0] != 1.0 or sca[1] != 1.0 or sca[2] != 1.0:
|
||||
scale = [sca[0], sca[1], sca[2]]
|
||||
|
||||
|
|
|
@ -258,19 +258,23 @@ def __gather_name(blender_object, export_settings):
|
|||
|
||||
|
||||
def __gather_trans_rot_scale(blender_object, export_settings):
|
||||
trans = gltf2_blender_extract.convert_swizzle_location(blender_object.location, export_settings)
|
||||
if blender_object.matrix_parent_inverse == Matrix.Identity(4):
|
||||
trans = blender_object.location
|
||||
|
||||
if blender_object.rotation_mode in ['QUATERNION', 'AXIS_ANGLE']:
|
||||
rotation = blender_object.rotation_quaternion
|
||||
if blender_object.rotation_mode in ['QUATERNION', 'AXIS_ANGLE']:
|
||||
rot = blender_object.rotation_quaternion
|
||||
else:
|
||||
rot = blender_object.rotation_euler.to_quaternion()
|
||||
|
||||
sca = blender_object.scale
|
||||
else:
|
||||
rotation = blender_object.rotation_euler.to_quaternion()
|
||||
# matrix_local = matrix_parent_inverse*location*rotation*scale
|
||||
# Decomposing matrix_local gives less accuracy, but is needed if matrix_parent_inverse is not the identity.
|
||||
trans, rot, sca = gltf2_blender_extract.decompose_transition(blender_object.matrix_local, export_settings)
|
||||
|
||||
rotation = gltf2_blender_extract.convert_swizzle_rotation(rotation, export_settings)
|
||||
|
||||
# Put w at the end.
|
||||
rot = Quaternion((rotation[1], rotation[2], rotation[3], rotation[0]))
|
||||
|
||||
sca = gltf2_blender_extract.convert_swizzle_scale(blender_object.scale, export_settings)
|
||||
trans = gltf2_blender_extract.convert_swizzle_location(trans, export_settings)
|
||||
rot = gltf2_blender_extract.convert_swizzle_rotation(rot, export_settings)
|
||||
sca = gltf2_blender_extract.convert_swizzle_scale(sca, export_settings)
|
||||
|
||||
if blender_object.instance_type == 'COLLECTION' and blender_object.instance_collection:
|
||||
trans = -gltf2_blender_extract.convert_swizzle_location(
|
||||
|
@ -278,14 +282,14 @@ def __gather_trans_rot_scale(blender_object, export_settings):
|
|||
translation, rotation, scale = (None, None, None)
|
||||
trans[0], trans[1], trans[2] = gltf2_blender_math.round_if_near(trans[0], 0.0), gltf2_blender_math.round_if_near(trans[1], 0.0), \
|
||||
gltf2_blender_math.round_if_near(trans[2], 0.0)
|
||||
rot[0], rot[1], rot[2], rot[3] = gltf2_blender_math.round_if_near(rot[0], 0.0), gltf2_blender_math.round_if_near(rot[1], 0.0), \
|
||||
gltf2_blender_math.round_if_near(rot[2], 0.0), gltf2_blender_math.round_if_near(rot[3], 1.0)
|
||||
rot[0], rot[1], rot[2], rot[3] = gltf2_blender_math.round_if_near(rot[0], 1.0), gltf2_blender_math.round_if_near(rot[1], 0.0), \
|
||||
gltf2_blender_math.round_if_near(rot[2], 0.0), gltf2_blender_math.round_if_near(rot[3], 0.0)
|
||||
sca[0], sca[1], sca[2] = gltf2_blender_math.round_if_near(sca[0], 1.0), gltf2_blender_math.round_if_near(sca[1], 1.0), \
|
||||
gltf2_blender_math.round_if_near(sca[2], 1.0)
|
||||
if trans[0] != 0.0 or trans[1] != 0.0 or trans[2] != 0.0:
|
||||
translation = [trans[0], trans[1], trans[2]]
|
||||
if rot[0] != 0.0 or rot[1] != 0.0 or rot[2] != 0.0 or rot[3] != 1.0:
|
||||
rotation = [rot[0], rot[1], rot[2], rot[3]]
|
||||
if rot[0] != 1.0 or rot[1] != 0.0 or rot[2] != 0.0 or rot[3] != 0.0:
|
||||
rotation = [rot[1], rot[2], rot[3], rot[0]]
|
||||
if sca[0] != 1.0 or sca[1] != 1.0 or sca[2] != 1.0:
|
||||
scale = [sca[0], sca[1], sca[2]]
|
||||
return translation, rotation, scale
|
||||
|
|
|
@ -29,7 +29,7 @@ def gather_texture(
|
|||
typing.Tuple[bpy.types.NodeSocket], typing.Tuple[typing.Any]],
|
||||
export_settings):
|
||||
"""
|
||||
Gather texture sampling information and image channels from a blender shader textu re attached to a shader socket.
|
||||
Gather texture sampling information and image channels from a blender shader texture attached to a shader socket.
|
||||
|
||||
:param blender_shader_sockets: The sockets of the material which should contribute to the texture
|
||||
:param export_settings: configuration of the export
|
||||
|
@ -47,7 +47,7 @@ def gather_texture(
|
|||
source=__gather_source(blender_shader_sockets_or_texture_slots, export_settings)
|
||||
)
|
||||
|
||||
# although valid, most viewers cant handle missing source properties
|
||||
# although valid, most viewers can't handle missing source properties
|
||||
if texture.source is None:
|
||||
return None
|
||||
|
||||
|
|
|
@ -212,13 +212,13 @@ class GlTF2Exporter:
|
|||
def __add_image(self, image: gltf2_io_image_data.ImageData):
|
||||
name = image.adjusted_name()
|
||||
count = 1
|
||||
regex = re.compile(r"\d+$")
|
||||
regex_found = re.findall(regex, name)
|
||||
regex = re.compile(r"-\d+$")
|
||||
while name in self.__images.keys():
|
||||
regex_found = re.findall(regex, name)
|
||||
if regex_found:
|
||||
name = re.sub(regex, str(count), name)
|
||||
name = re.sub(regex, "-" + str(count), name)
|
||||
else:
|
||||
name += " " + str(count)
|
||||
name += "-" + str(count)
|
||||
|
||||
count += 1
|
||||
# TODO: we need to know the image url at this point already --> maybe add all options to the constructor of the
|
||||
|
|
Loading…
Reference in New Issue