FBX Export: Add Smoothgroups option.

Add 'Smoothing Groups' option for exporting polygon smoothing groups.

Generates 'bitflags' smoothgroups values, ensuring no faces from different
groups sharing a same boundary edge or vertex have the same bitflag value.

NOTE: This type of smoothgroups will run out of group values (aka bitflags) with
some specific topologies, e.g. a fan of over 31 flat faces sharing a same vertex
(like the sides of a cone). In such cases, once all available values have been used,
the remaining faces will get  `0` (aka 'no group') value assigned.

Original issue https://projects.blender.org/blender/blender-addons/issues/104434

Pull Request: https://projects.blender.org/blender/blender/pulls/135646
This commit is contained in:
Yury
2025-03-14 17:13:41 +01:00
committed by Bastien Montagne
parent e5d9b7a43f
commit 5b3952d11a
2 changed files with 9 additions and 4 deletions

View File

@@ -5,8 +5,8 @@
bl_info = {
"name": "FBX format",
"author": "Campbell Barton, Bastien Montagne, Jens Restemeier, @Mysteryem",
"version": (5, 12, 7),
"blender": (4, 2, 0),
"version": (5, 13, 0),
"blender": (4, 5, 0),
"location": "File > Import-Export",
"description": "FBX IO meshes, UVs, vertex colors, materials, textures, cameras, lamps and actions",
"warning": "",
@@ -391,6 +391,7 @@ class ExportFBX(bpy.types.Operator, ExportHelper):
items=(('OFF', "Normals Only", "Export only normals instead of writing edge or face smoothing data"),
('FACE', "Face", "Write face smoothing"),
('EDGE', "Edge", "Write edge smoothing"),
('SMOOTH_GROUP', "Smoothing Groups", "Write face smoothing groups"),
),
description="Export smoothing information "
"(prefer 'Normals Only' option if your target importer understand split normals)",

View File

@@ -1032,7 +1032,7 @@ def fbx_data_mesh_elements(root, me_obj, scene_data, done_meshes):
# And now, layers!
# Smoothing.
if smooth_type in {'FACE', 'EDGE'}:
if smooth_type in {'FACE', 'EDGE', 'SMOOTH_GROUP'}:
ps_fbx_dtype = np.int32
_map = b""
if smooth_type == 'FACE':
@@ -1047,6 +1047,10 @@ def fbx_data_mesh_elements(root, me_obj, scene_data, done_meshes):
# The mesh has no "sharp_face" attribute, so every face is smooth.
t_ps = np.ones(len(me.polygons), dtype=ps_fbx_dtype)
_map = b"ByPolygon"
elif smooth_type == 'SMOOTH_GROUP':
smoothing_groups = me.calc_smooth_groups(use_bitflags=True, use_boundary_vertices_for_bitflags=True)[0]
t_ps = np.asarray(smoothing_groups, dtype=ps_fbx_dtype)
_map = b"ByPolygon"
else: # EDGE
_map = b"ByEdge"
if t_pvi_edge_indices.size:
@@ -1503,7 +1507,7 @@ def fbx_data_mesh_elements(root, me_obj, scene_data, done_meshes):
lay_tan = elem_empty(layer, b"LayerElement")
elem_data_single_string(lay_tan, b"Type", b"LayerElementTangent")
elem_data_single_int32(lay_tan, b"TypedIndex", 0)
if smooth_type in {'FACE', 'EDGE'}:
if smooth_type in {'FACE', 'EDGE', 'SMOOTH_GROUP'}:
lay_smooth = elem_empty(layer, b"LayerElement")
elem_data_single_string(lay_smooth, b"Type", b"LayerElementSmoothing")
elem_data_single_int32(lay_smooth, b"TypedIndex", 0)