io_scene_3ds: Moved specular color texture to specular tint #104918

Merged
Sebastian Sille merged 89 commits from :main into main 2023-09-27 00:42:09 +02:00
9 changed files with 39 additions and 13 deletions
Showing only changes of commit 81869233ef - Show all commits

View File

@ -5,7 +5,7 @@
bl_info = { bl_info = {
'name': 'glTF 2.0 format', 'name': 'glTF 2.0 format',
'author': 'Julien Duroure, Scurest, Norbert Nopper, Urs Hanselmann, Moritz Becher, Benjamin Schmithüsen, Jim Eckerlein, and many external contributors', 'author': 'Julien Duroure, Scurest, Norbert Nopper, Urs Hanselmann, Moritz Becher, Benjamin Schmithüsen, Jim Eckerlein, and many external contributors',
"version": (4, 0, 30), "version": (4, 0, 31),
'blender': (4, 0, 0), 'blender': (4, 0, 0),
'location': 'File > Import-Export', 'location': 'File > Import-Export',
'description': 'Import-Export as glTF 2.0', 'description': 'Import-Export as glTF 2.0',

View File

@ -93,6 +93,8 @@ def export_specular(blender_material, export_settings):
specular = specular_socket.default_value if specular_not_linked else None specular = specular_socket.default_value if specular_not_linked else None
specular_tint = specular_tint_socket.default_value if specular_tint_not_linked else None specular_tint = specular_tint_socket.default_value if specular_tint_not_linked else None
if specular_tint is not None:
specular_tint = (specular_tint[0] + specular_tint[1] + specular_tint[2]) / 3 # TODO tmp fix to avoid crash
transmission = transmission_socket.default_value if transmission_not_linked else None transmission = transmission_socket.default_value if transmission_not_linked else None
ior = ior_socket.default_value if ior_not_linked else GLTF_IOR # textures not supported #TODOExt add warning? ior = ior_socket.default_value if ior_not_linked else GLTF_IOR # textures not supported #TODOExt add warning?
base_color = base_color_socket.default_value[0:3] base_color = base_color_socket.default_value[0:3]

View File

@ -44,14 +44,14 @@ def specular_calculation(stored):
# keep only needed channels # keep only needed channels
## scalar ## scalar
for i in ['specular', 'specular_tint', 'transmission']: for i in ['specular', 'transmission']:
if i in buffers.keys(): if i in buffers.keys():
buffers[i] = buffers[i][:,:,stored[i + "_channel"].data] buffers[i] = buffers[i][:,:,stored[i + "_channel"].data]
else: else:
buffers[i] = np.full((width, height, 1), stored[i].data) buffers[i] = np.full((width, height, 1), stored[i].data)
# Vector 3 # Vector 3
for i in ['base_color']: for i in ['base_color', 'specular_tint']:
if i in buffers.keys(): if i in buffers.keys():
if i + "_channel" not in stored.keys(): if i + "_channel" not in stored.keys():
buffers[i] = buffers[i][:,:,:3] buffers[i] = buffers[i][:,:,:3]
@ -64,6 +64,9 @@ def specular_calculation(stored):
else: else:
buffers[i] = np.full((width, height, 3), stored[i].data[0:3]) buffers[i] = np.full((width, height, 3), stored[i].data[0:3])
# TODO tmp Merge last dimension to avoid crash
buffers['specular_tint'] = np.average(buffers['specular_tint'], axis=2)
ior = stored['ior'].data ior = stored['ior'].data
# calculation # calculation

View File

@ -194,7 +194,7 @@ def __get_image_data(sockets, default_sockets, export_settings) -> ExportImage:
results = [get_tex_from_socket(socket) for socket in sockets] results = [get_tex_from_socket(socket) for socket in sockets]
# Check if we need a simple mapping or more complex calculation # Check if we need a simple mapping or more complex calculation
if any([socket.name == "Specular" and socket.node.type == "BSDF_PRINCIPLED" for socket in sockets]): if any([socket.name == "Specular IOR Level" and socket.node.type == "BSDF_PRINCIPLED" for socket in sockets]):
return __get_image_data_specular(sockets, results, export_settings) return __get_image_data_specular(sockets, results, export_settings)
else: else:
return __get_image_data_mapping(sockets, default_sockets, results, export_settings) return __get_image_data_mapping(sockets, default_sockets, results, export_settings)
@ -252,7 +252,7 @@ def __get_image_data_mapping(sockets, default_sockets, results, export_settings)
dst_chan = Channel.G dst_chan = Channel.G
elif socket.name == 'Thickness': # For KHR_materials_volume elif socket.name == 'Thickness': # For KHR_materials_volume
dst_chan = Channel.G dst_chan = Channel.G
elif socket.name == "Specular IOR Level": # For original KHR_material_specular elif socket.name == "Specular": # For original KHR_material_specular
dst_chan = Channel.A dst_chan = Channel.A
elif socket.name == "Roughness" and socket.node.type == "BSDF_SHEEN": # For KHR_materials_sheen elif socket.name == "Roughness" and socket.node.type == "BSDF_SHEEN": # For KHR_materials_sheen
dst_chan = Channel.A dst_chan = Channel.A

View File

@ -139,7 +139,7 @@ def specular(mh, location_specular,
blender_specular_tint = 1.0 blender_specular_tint = 1.0
specular_socket.default_value = blender_specular specular_socket.default_value = blender_specular
specular_tint_socket.default_value = blender_specular_tint specular_tint_socket.default_value = [blender_specular_tint]*3 + [1.0] #TODO tmp fix to avoid crash
# Note: blender_specular can be greater 1. The Blender documentation permits this. # Note: blender_specular can be greater 1. The Blender documentation permits this.
return return
@ -297,7 +297,7 @@ def specular(mh, location_specular,
if blender_specular_tint_tex_not_needed == True: if blender_specular_tint_tex_not_needed == True:
lum = lambda c: 0.3 * c[0] + 0.6 * c[1] + 0.1 * c[2] lum = lambda c: 0.3 * c[0] + 0.6 * c[1] + 0.1 * c[2]
specular_tint_socket.default_value = lum(blender_specular_tint[0][0]) specular_tint_socket.default_value = [lum(blender_specular_tint[0][0])]*3 + [1.0] #TODO tmp fix to avoid crash
else: else:
blender_specular_tint = np.reshape(blender_specular_tint, width * height * 4) blender_specular_tint = np.reshape(blender_specular_tint, width * height * 4)
# Create images in Blender, width and height are dummy values, then set packed file data # Create images in Blender, width and height are dummy values, then set packed file data

View File

@ -96,7 +96,7 @@ def pbr_metallic_roughness(mh: MaterialHelper):
emission( emission(
mh, mh,
location=locs['emission'], location=locs['emission'],
color_socket=pbr_node.inputs['Emission'], color_socket=pbr_node.inputs['Emission Color'],
strength_socket=pbr_node.inputs['Emission Strength'], strength_socket=pbr_node.inputs['Emission Strength'],
) )

View File

@ -32,11 +32,11 @@ def process_all(process, name_map):
process('lip.T.L', parent='jaw_master', layer=1, rig='skin.stretchy_chain', sharpen=(0, 90), process('lip.T.L', parent='jaw_master', layer=1, rig='skin.stretchy_chain', sharpen=(0, 90),
falloff=(0.7, 1, 0.1), spherical=(True, False, True), scale=True) falloff=(0.7, 1, 0.1), spherical=(True, False, True), scale=True)
process('lip.T.L.001') process('lip.T.L.001', bbone_mapping_mode='CURVED')
process('lip.B.L', parent='jaw_master', layer=1, rig='skin.stretchy_chain', sharpen=(0, 90), process('lip.B.L', parent='jaw_master', layer=1, rig='skin.stretchy_chain', sharpen=(0, 90),
falloff=(0.7, 1, 0.1), spherical=(True, False, True), scale=True) falloff=(0.7, 1, 0.1), spherical=(True, False, True), scale=True)
process('lip.B.L.001') process('lip.B.L.001', bbone_mapping_mode='CURVED')
process('jaw', parent='jaw_master', layer=1, rig='skin.basic_chain', connect_ends='next') process('jaw', parent='jaw_master', layer=1, rig='skin.basic_chain', connect_ends='next')
process('chin', parent='jaw_master', rig='skin.stretchy_chain', connect_ends='prev') process('chin', parent='jaw_master', rig='skin.stretchy_chain', connect_ends='prev')
@ -58,11 +58,11 @@ def process_all(process, name_map):
process('lip.T.R', parent='jaw_master', layer=1, rig='skin.stretchy_chain', sharpen=(0, 90), process('lip.T.R', parent='jaw_master', layer=1, rig='skin.stretchy_chain', sharpen=(0, 90),
falloff=(0.7, 1, 0.1), spherical=(True, False, True), scale=True) falloff=(0.7, 1, 0.1), spherical=(True, False, True), scale=True)
process('lip.T.R.001') process('lip.T.R.001', bbone_mapping_mode='CURVED')
process('lip.B.R', parent='jaw_master', layer=1, rig='skin.stretchy_chain', sharpen=(0, 90), process('lip.B.R', parent='jaw_master', layer=1, rig='skin.stretchy_chain', sharpen=(0, 90),
falloff=(0.7, 1, 0.1), spherical=(True, False, True), scale=True) falloff=(0.7, 1, 0.1), spherical=(True, False, True), scale=True)
process('lip.B.R.001') process('lip.B.R.001', bbone_mapping_mode='CURVED')
process('brow.B.L', rig='skin.stretchy_chain', middle=2, connect_ends='next') process('brow.B.L', rig='skin.stretchy_chain', middle=2, connect_ends='next')
process('brow.B.L.001') process('brow.B.L.001')
@ -320,6 +320,7 @@ def set_rig(
connect_ends=None, priority=0, middle=0, sharpen=None, connect_ends=None, priority=0, middle=0, sharpen=None,
falloff=None, spherical=None, falloff_length=False, scale=False, falloff=None, spherical=None, falloff_length=False, scale=False,
glue_copy=None, glue_reparent=False, glue_copy=None, glue_reparent=False,
bbone_mapping_mode=None,
params=None, **_kwargs params=None, **_kwargs
): ):
bone = name_map.get(bone, bone) bone = name_map.get(bone, bone)
@ -367,6 +368,9 @@ def set_rig(
for k, v in params.items(): for k, v in params.items():
setattr(pbone.rigify_parameters, k, v) setattr(pbone.rigify_parameters, k, v)
if bbone_mapping_mode is not None:
obj.pose.bones[bone].bone.bbone_mapping_mode = bbone_mapping_mode
def update_face_rig(obj): def update_face_rig(obj):
assert obj.type == 'ARMATURE' assert obj.type == 'ARMATURE'

View File

@ -160,7 +160,7 @@ def copy_bone(obj: ArmatureObject, bone_name: str, assign_name='', *,
if bbone: if bbone:
# noinspection SpellCheckingInspection # noinspection SpellCheckingInspection
for name in ['bbone_segments', for name in ['bbone_segments', 'bbone_mapping_mode',
'bbone_easein', 'bbone_easeout', 'bbone_easein', 'bbone_easeout',
'bbone_rollin', 'bbone_rollout', 'bbone_rollin', 'bbone_rollout',
'bbone_curveinx', 'bbone_curveinz', 'bbone_curveoutx', 'bbone_curveoutz', 'bbone_curveinx', 'bbone_curveinz', 'bbone_curveoutx', 'bbone_curveoutz',

View File

@ -14,6 +14,7 @@ from bpy.types import bpy_struct, Constraint, Object, PoseBone, Bone, Armature
from bpy.types import bpy_prop_array, bpy_prop_collection # noqa from bpy.types import bpy_prop_array, bpy_prop_collection # noqa
from idprop.types import IDPropertyArray from idprop.types import IDPropertyArray
from mathutils import Vector
from .misc import ArmatureObject, wrap_list_to_lines, IdPropSequence, find_index from .misc import ArmatureObject, wrap_list_to_lines, IdPropSequence, find_index
@ -573,6 +574,18 @@ def write_metarig(obj: ArmatureObject, layers=False, func_name="create",
code.append("\n bones = {}\n") code.append("\n bones = {}\n")
# noinspection SpellCheckingInspection
extra_props = {
'bbone_segments': 1,
'bbone_mapping_mode': 'STRAIGHT',
'bbone_easein': 1, 'bbone_easeout': 1,
'bbone_rollin': 0, 'bbone_rollout': 0,
'bbone_curveinx': 0, 'bbone_curveinz': 0,
'bbone_curveoutx': 0, 'bbone_curveoutz': 0,
'bbone_scalein': Vector((1, 1, 1)),
'bbone_scaleout': Vector((1, 1, 1)),
}
for bone_name in bones: for bone_name in bones:
bone = arm.edit_bones[bone_name] bone = arm.edit_bones[bone_name]
code.append(" bone = arm.edit_bones.new(%r)" % bone.name) code.append(" bone = arm.edit_bones.new(%r)" % bone.name)
@ -584,6 +597,10 @@ def write_metarig(obj: ArmatureObject, layers=False, func_name="create",
code.append(" bone.inherit_scale = %r" % str(bone.inherit_scale)) code.append(" bone.inherit_scale = %r" % str(bone.inherit_scale))
if bone.parent: if bone.parent:
code.append(" bone.parent = arm.edit_bones[bones[%r]]" % bone.parent.name) code.append(" bone.parent = arm.edit_bones[bones[%r]]" % bone.parent.name)
for prop, default in extra_props.items():
value = getattr(bone, prop)
if value != default:
code.append(f" bone.{prop} = {value!r}")
code.append(" bones[%r] = bone.name" % bone.name) code.append(" bones[%r] = bone.name" % bone.name)
bpy.ops.object.mode_set(mode='OBJECT') bpy.ops.object.mode_set(mode='OBJECT')