Skip to content

Commit

Permalink
Merge branch 'main' into node_tree_refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
julienduroure committed Sep 6, 2023
2 parents 86bb1bb + 77801af commit 939dfa2
Show file tree
Hide file tree
Showing 29 changed files with 155 additions and 72 deletions.
2 changes: 1 addition & 1 deletion addons/io_scene_gltf2/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
bl_info = {
'name': 'glTF 2.0 format',
'author': 'Julien Duroure, Scurest, Norbert Nopper, Urs Hanselmann, Moritz Becher, Benjamin Schmithüsen, Jim Eckerlein, and many external contributors',
"version": (4, 0, 7),
"version": (4, 0, 15),
'blender': (4, 0, 0),
'location': 'File > Import-Export',
'description': 'Import-Export as glTF 2.0',
Expand Down
6 changes: 4 additions & 2 deletions addons/io_scene_gltf2/blender/com/gltf2_blender_conversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,8 @@ def get_numpy_type(attribute_component_type):
def get_attribute_type(component_type, data_type):
if gltf2_io_constants.DataType.num_elements(data_type) == 1:
return {
gltf2_io_constants.ComponentType.Float: "FLOAT"
gltf2_io_constants.ComponentType.Float: "FLOAT",
gltf2_io_constants.ComponentType.UnsignedByte: "INT" # What is the best for compatibility?
}[component_type]
elif gltf2_io_constants.DataType.num_elements(data_type) == 2:
return {
Expand All @@ -142,7 +143,8 @@ def get_attribute_type(component_type, data_type):
elif gltf2_io_constants.DataType.num_elements(data_type) == 4:
return {
gltf2_io_constants.ComponentType.Float: "FLOAT_COLOR",
gltf2_io_constants.ComponentType.UnsignedShort: "BYTE_COLOR"
gltf2_io_constants.ComponentType.UnsignedShort: "BYTE_COLOR",
gltf2_io_constants.ComponentType.UnsignedByte: "BYTE_COLOR" # What is the best for compatibility?
}[component_type]
else:
pass
Expand Down
19 changes: 14 additions & 5 deletions addons/io_scene_gltf2/blender/com/gltf2_blender_data_path.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,19 @@ def is_bone_anim_channel(data_path: str) -> bool:

def get_sk_exported(key_blocks):
return [
key_block
for key_block in key_blocks
if not skip_sk(key_block)
k
for k in key_blocks
if not skip_sk(key_blocks, k)
]

def skip_sk(k):
return k == k.relative_key or k.mute
def skip_sk(key_blocks, k):
# Do not export:
# - if muted
# - if relative key is SK itself (this avoid exporting Basis too if user didn't change order)
# - the Basis (the first SK of the list)
return k == k.relative_key \
or k.mute \
or is_first_index(key_blocks, k) is True

def is_first_index(key_blocks, k):
return key_blocks[0].name == k.name
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def gather_animation_fcurves_channels(
custom_range = (blender_action.frame_start, blender_action.frame_end)

channels = []
for chan in [chan for chan in channels_to_perform.values() if len(chan['properties']) != 0]:
for chan in [chan for chan in channels_to_perform.values() if len(chan['properties']) != 0 and chan['type'] != "EXTRA"]:
for channel_group in chan['properties'].values():
channel = __gather_animation_fcurve_channel(chan['obj_uuid'], channel_group, chan['bone'], custom_range, export_settings)
if channel is not None:
Expand Down Expand Up @@ -83,10 +83,13 @@ def get_channel_groups(obj_uuid: str, blender_action: bpy.types.Action, export_s
else:
try:
target = get_object_from_datapath(blender_object, object_path)
type_ = "BONE"
if blender_object.type == "ARMATURE" and fcurve.data_path.startswith("pose.bones["):
type_ = "BONE"
else:
type_ = "EXTRA"
if blender_object.type == "MESH" and object_path.startswith("key_blocks"):
shape_key = blender_object.data.shape_keys.path_resolve(object_path)
if skip_sk(shape_key):
if skip_sk(blender_object.data.shape_keys.key_blocks, shape_key):
continue
target = blender_object.data.shape_keys
type_ = "SK"
Expand All @@ -96,7 +99,7 @@ def get_channel_groups(obj_uuid: str, blender_action: bpy.types.Action, export_s
if blender_object.type == "MESH":
try:
shape_key = blender_object.data.shape_keys.path_resolve(object_path)
if skip_sk(shape_key):
if skip_sk(blender_object.data.shape_keys.key_blocks, shape_key):
continue
target = blender_object.data.shape_keys
type_ = "SK"
Expand Down Expand Up @@ -191,7 +194,7 @@ def __get_channel_group_sorted(channels: typing.Tuple[bpy.types.FCurve], blender
shapekeys_idx = {}
cpt_sk = 0
for sk in blender_object.data.shape_keys.key_blocks:
if skip_sk(sk):
if skip_sk(blender_object.data.shape_keys.key_blocks, sk):
continue
shapekeys_idx[sk.name] = cpt_sk
cpt_sk += 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

import bpy
import typing
from .....blender.com.gltf2_blender_data_path import skip_sk
from .....blender.com.gltf2_blender_data_path import get_sk_exported
from ....com.gltf2_blender_data_path import get_target_object_path
from ...gltf2_blender_gather_cache import cached
from ..gltf2_blender_gather_keyframes import Keyframe
Expand Down Expand Up @@ -175,9 +175,7 @@ def __gather_non_keyed_values(
if object_path:
shapekeys_idx = {}
cpt_sk = 0
for sk in blender_object.data.shape_keys.key_blocks:
if skip_sk(sk):
continue
for sk in get_sk_exported(blender_object.data.shape_keys.key_blocks):
shapekeys_idx[cpt_sk] = sk.name
cpt_sk += 1

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,8 @@ def gather_action_animations( obj_uuid: int,
channel = gather_sampled_object_channel(obj_uuid, prop, blender_action.name, True, get_gltf_interpolation("LINEAR"), export_settings)
elif type_ == "SK":
channel = gather_sampled_sk_channel(obj_uuid, blender_action.name, export_settings)
elif type_ == "EXTRA":
channel = None
else:
print("Type unknown. Should not happen")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def get_sk_drivers(blender_armature_uuid, export_settings):
sk_name = child.data.shape_keys.path_resolve(get_target_object_path(sk_c.data_path)).name
except:
continue
if skip_sk(child.data.shape_keys.key_blocks[sk_name]):
if skip_sk(child.data.shape_keys.key_blocks, child.data.shape_keys.key_blocks[sk_name]):
continue
idx_channel_mapping.append((shapekeys_idx[sk_name], sk_c))
existing_idx = dict(idx_channel_mapping)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import bpy
from mathutils import Matrix, Quaternion, Vector

from ...io.com.gltf2_io_debug import print_console
from ...io.com import gltf2_io
from ...io.com import gltf2_io_extensions
from ...io.exp.gltf2_io_user_extensions import export_user_extensions
Expand Down Expand Up @@ -191,7 +192,9 @@ def __gather_mesh(vnode, blender_object, export_settings):
return None

# Be sure that object is valid (no NaN for example)
blender_object.data.validate()
res = blender_object.data.validate()
if res is True:
print_console("WARNING", "Mesh " + blender_object.data.name + " is not valid, and may be exported wrongly")

modifiers = blender_object.modifiers
if len(modifiers) == 0:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def gather_primitive_attributes(blender_primitive, export_settings):
return attributes


def array_to_accessor(array, component_type, data_type, include_max_and_min=False):
def array_to_accessor(array, component_type, data_type, include_max_and_min=False, normalized=None):

amax = None
amin = None
Expand All @@ -63,7 +63,7 @@ def array_to_accessor(array, component_type, data_type, include_max_and_min=Fals
max=amax,
min=amin,
name=None,
normalized=None,
normalized=normalized,
sparse=None,
type=data_type,
)
Expand Down Expand Up @@ -193,6 +193,7 @@ def __gather_attribute(blender_primitive, attribute, export_settings):
data['data'],
component_type=data['component_type'],
data_type=data['data_type'],
include_max_and_min=include_max_and_mins.get(attribute, False)
include_max_and_min=include_max_and_mins.get(attribute, False),
normalized=data.get('normalized')
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from mathutils import Vector
from ...blender.com.gltf2_blender_data_path import get_sk_exported
from ...io.com.gltf2_io_debug import print_console
from ...io.com.gltf2_io_constants import NORMALS_ROUNDING_DIGIT
from ...io.com.gltf2_io_constants import ROUNDING_DIGIT
from ...io.exp.gltf2_io_user_extensions import export_user_extensions
from ...io.com import gltf2_io_constants
from ..com import gltf2_blender_conversion
Expand Down Expand Up @@ -367,9 +367,16 @@ def populate_dots_data(self):
def primitive_split(self):
# Calculate triangles and sort them into primitives.

self.blender_mesh.calc_loop_triangles()
loop_indices = np.empty(len(self.blender_mesh.loop_triangles) * 3, dtype=np.uint32)
self.blender_mesh.loop_triangles.foreach_get('loops', loop_indices)
try:
self.blender_mesh.calc_loop_triangles()
loop_indices = np.empty(len(self.blender_mesh.loop_triangles) * 3, dtype=np.uint32)
self.blender_mesh.loop_triangles.foreach_get('loops', loop_indices)
except:
# For some not valid meshes, we can't get loops without errors
# We already displayed a Warning message after validate() check, so here
# we can return without a new one
self.prim_indices = {}
return

self.prim_indices = {} # maps material index to TRIANGLES-style indices into dots

Expand Down Expand Up @@ -725,15 +732,15 @@ def __get_normals(self):

self.normals = self.normals.reshape(len(self.blender_mesh.loops), 3)

self.normals = np.round(self.normals, NORMALS_ROUNDING_DIGIT)
self.normals = np.round(self.normals, ROUNDING_DIGIT)
# Force normalization of normals in case some normals are not (why ?)
PrimitiveCreator.normalize_vecs(self.normals)

self.morph_normals = []
for key_block in key_blocks:
ns = np.array(key_block.normals_split_get(), dtype=np.float32)
ns = ns.reshape(len(self.blender_mesh.loops), 3)
ns = np.round(ns, NORMALS_ROUNDING_DIGIT)
ns = np.round(ns, ROUNDING_DIGIT)
self.morph_normals.append(ns)

# Transform for skinning
Expand Down Expand Up @@ -792,13 +799,15 @@ def __get_tangents(self):
self.tangents = np.empty(len(self.blender_mesh.loops) * 3, dtype=np.float32)
self.blender_mesh.loops.foreach_get('tangent', self.tangents)
self.tangents = self.tangents.reshape(len(self.blender_mesh.loops), 3)
self.tangents = np.round(self.tangents, ROUNDING_DIGIT)

# Transform for skinning
if self.armature and self.blender_object:
apply_matrix = self.armature.matrix_world.inverted_safe() @ self.blender_object.matrix_world
tangent_transform = apply_matrix.to_quaternion().to_matrix()
self.tangents = PrimitiveCreator.apply_mat_to_all(tangent_transform, self.tangents)
PrimitiveCreator.normalize_vecs(self.tangents)
self.tangents = np.round(self.tangents, ROUNDING_DIGIT)

if self.export_settings['gltf_yup']:
PrimitiveCreator.zup2yup(self.tangents)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ def export_clearcoat(blender_material, export_settings):
clearcoat_texture, clearcoat_texture_use_active_uvmap, _ = gltf2_blender_gather_texture_info.gather_texture_info(
clearcoat_socket,
clearcoat_roughness_slots,
(),
export_settings,
)
clearcoat_extension['clearcoatTexture'] = clearcoat_texture
Expand All @@ -74,6 +75,7 @@ def export_clearcoat(blender_material, export_settings):
clearcoat_roughness_texture, clearcoat_roughness_texture_use_active_uvmap, _ = gltf2_blender_gather_texture_info.gather_texture_info(
clearcoat_roughness_socket,
clearcoat_roughness_slots,
(),
export_settings,
)
clearcoat_extension['clearcoatRoughnessTexture'] = clearcoat_roughness_texture
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def export_emission_texture(blender_material, export_settings):
emissive = get_socket(blender_material, "Emissive")
if emissive.socket is None:
emissive = get_socket_from_gltf_material_node(blender_material, "Emissive")
emissive_texture, use_actives_uvmap_emissive, _ = gltf2_blender_gather_texture_info.gather_texture_info(emissive, (emissive,), export_settings)
emissive_texture, use_actives_uvmap_emissive, _ = gltf2_blender_gather_texture_info.gather_texture_info(emissive, (emissive,), (), export_settings)
return emissive_texture, ["emissiveTexture"] if use_actives_uvmap_emissive else None

def export_emission_strength_extension(emissive_factor, export_settings):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ def export_sheen(blender_material, export_settings):
original_sheenColor_texture, original_sheenColor_use_active_uvmap, _ = gltf2_blender_gather_texture_info.gather_texture_info(
sheenColor_socket,
(sheenColor_socket,),
(),
export_settings,
)
sheen_extension['sheenColorTexture'] = original_sheenColor_texture
Expand All @@ -77,6 +78,7 @@ def export_sheen(blender_material, export_settings):
original_sheenRoughness_texture, original_sheenRoughness_use_active_uvmap, _ = gltf2_blender_gather_texture_info.gather_texture_info(
sheenRoughness_socket,
(sheenRoughness_socket,),
(),
export_settings,
)
sheen_extension['sheenRoughnessTexture'] = original_sheenRoughness_texture
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from .....io.com.gltf2_io_extensions import Extension
from .....io.com.gltf2_io_constants import GLTF_IOR
from ....com.gltf2_blender_default import BLENDER_SPECULAR, BLENDER_SPECULAR_TINT
from ...material import gltf2_blender_gather_texture_info
from ...material.gltf2_blender_gather_texture_info import gather_texture_info
from ..gltf2_blender_search_node_tree import \
has_image_node_from_socket, \
get_socket_from_gltf_material_node, \
Expand Down Expand Up @@ -51,9 +51,10 @@ def export_original_specular(blender_material, export_settings):

# Texture
if has_image_node_from_socket(original_specular_socket, export_settings):
original_specular_texture, original_specular_use_active_uvmap, _ = gltf2_blender_gather_texture_info.gather_texture_info(
original_specular_texture, original_specular_use_active_uvmap, _ = gather_texture_info(
original_specular_socket,
(original_specular_socket,),
(),
export_settings,
)
specular_extension['specularTexture'] = original_specular_texture
Expand All @@ -73,9 +74,10 @@ def export_original_specular(blender_material, export_settings):

# Texture
if has_image_node_from_socket(original_specularcolor_socket, export_settings):
original_specularcolor_texture, original_specularcolor_use_active_uvmap, _ = gltf2_blender_gather_texture_info.gather_texture_info(
original_specularcolor_texture, original_specularcolor_use_active_uvmap, _ = gather_texture_info(
original_specularcolor_socket,
(original_specularcolor_socket,),
(),
export_settings,
)
specular_extension['specularColorTexture'] = original_specularcolor_texture
Expand Down Expand Up @@ -163,9 +165,10 @@ def normalize(c):
if base_color_not_linked:
primary_socket = transmission_socket

specularColorTexture, use_active_uvmap, specularColorFactor = gltf2_blender_gather_texture_info.gather_texture_info(
specularColorTexture, use_active_uvmap, specularColorFactor = gather_texture_info(
primary_socket,
sockets,
(),
export_settings,
filter_type='ANY')
if specularColorTexture is None:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ def export_transmission(blender_material, export_settings):
combined_texture, use_active_uvmap, _ = gltf2_blender_gather_texture_info.gather_texture_info(
transmission_socket,
transmission_slots,
(),
export_settings,
)
if has_transmission_texture:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ def export_volume(blender_material, export_settings):
combined_texture, use_active_uvmap, _ = gltf2_blender_gather_texture_info.gather_texture_info(
thickness_socket,
thickness_slots,
(),
export_settings,
)
if has_thickness_texture:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ class FillWhite:
"""Fills a channel with all ones (1.0)."""
pass

class FillWith:
"""Fills a channel with all same values"""
def __init__(self, value):
self.value = value

class StoreData:
def __init__(self, data):
"""Store numeric data (not an image channel"""
Expand Down Expand Up @@ -109,6 +114,9 @@ def store_data(self, identifier, data, type='Image'):
def fill_white(self, dst_chan: Channel):
self.fills[dst_chan] = FillWhite()

def fill_with(self, dst_chan, value):
self.fills[dst_chan] = FillWith(value)

def is_filled(self, chan: Channel) -> bool:
return chan in self.fills

Expand Down Expand Up @@ -193,6 +201,8 @@ def __encode_unhappy(self, export_settings) -> bytes:
for dst_chan, fill in self.fills.items():
if isinstance(fill, FillImage) and fill.image == image:
out_buf[int(dst_chan)::4] = tmp_buf[int(fill.src_chan)::4]
elif isinstance(fill, FillWith):
out_buf[int(dst_chan)::4] = fill.value

tmp_buf = None # GC this

Expand Down
Loading

0 comments on commit 939dfa2

Please sign in to comment.