mirror of
https://github.com/EatTheFuture/compify.git
synced 2025-01-22 00:09:11 -05:00
Add UV margin setting.
It's a little hacky, but mostly works.
This commit is contained in:
parent
e65525da82
commit
d7aa7cc8ca
36
__init__.py
36
__init__.py
@ -36,6 +36,7 @@ from .node_groups import \
|
|||||||
ensure_footage_group, \
|
ensure_footage_group, \
|
||||||
ensure_camera_project_group, \
|
ensure_camera_project_group, \
|
||||||
ensure_feathered_square_group
|
ensure_feathered_square_group
|
||||||
|
from .uv_utils import leftmost_u
|
||||||
|
|
||||||
MAIN_NODE_NAME = "Compify Footage"
|
MAIN_NODE_NAME = "Compify Footage"
|
||||||
BAKE_IMAGE_NODE_NAME = "Baked Lighting"
|
BAKE_IMAGE_NODE_NAME = "Baked Lighting"
|
||||||
@ -99,6 +100,7 @@ class CompifyPanel(bpy.types.Panel):
|
|||||||
layout.separator(factor=1.0)
|
layout.separator(factor=1.0)
|
||||||
|
|
||||||
layout.use_property_split = True
|
layout.use_property_split = True
|
||||||
|
layout.prop(context.scene.compify_config, "bake_uv_margin")
|
||||||
layout.prop(context.scene.compify_config, "bake_image_res")
|
layout.prop(context.scene.compify_config, "bake_image_res")
|
||||||
|
|
||||||
layout.separator(factor=1.0)
|
layout.separator(factor=1.0)
|
||||||
@ -301,13 +303,29 @@ class CompifyPrepScene(bpy.types.Operator):
|
|||||||
bpy.ops.mesh.select_all(action='SELECT')
|
bpy.ops.mesh.select_all(action='SELECT')
|
||||||
bpy.ops.uv.smart_project(
|
bpy.ops.uv.smart_project(
|
||||||
angle_limit=(math.pi/180)*60, # 60 degrees
|
angle_limit=(math.pi/180)*60, # 60 degrees
|
||||||
island_margin=0.005,
|
island_margin=0.001,
|
||||||
area_weight=0.0,
|
area_weight=0.0,
|
||||||
correct_aspect=False,
|
correct_aspect=False,
|
||||||
scale_to_bounds=True,
|
scale_to_bounds=False,
|
||||||
)
|
)
|
||||||
bpy.ops.object.mode_set(mode='OBJECT')
|
bpy.ops.object.mode_set(mode='OBJECT')
|
||||||
|
|
||||||
|
# We have to do the UV island margins twice, because Blender's
|
||||||
|
# `island_margin` is stupid beyond belief and corresponds to
|
||||||
|
# nothing absolute that we can depend on. So what we're doing
|
||||||
|
# here is saying, "Hey, what was the actual margin achieved
|
||||||
|
# with `island_margin=0.001`? Okay, now let's redo it based on
|
||||||
|
# that result." It's still not 100% precise even with this,
|
||||||
|
# but with a bit of buffer it's close enough.
|
||||||
|
actual_margin = leftmost_u(context.selected_objects, UV_LAYER_NAME)
|
||||||
|
actual_margin_pixels = actual_margin * context.scene.compify_config.bake_image_res
|
||||||
|
target_margin_with_buffer = context.scene.compify_config.bake_uv_margin * (5.0 / 4.0)
|
||||||
|
correction_factor = target_margin_with_buffer / actual_margin_pixels
|
||||||
|
bpy.ops.object.mode_set(mode='EDIT')
|
||||||
|
bpy.ops.uv.select_all(action='SELECT')
|
||||||
|
bpy.ops.uv.pack_islands(rotate=False, margin = 0.001 * correction_factor)
|
||||||
|
bpy.ops.object.mode_set(mode='OBJECT')
|
||||||
|
|
||||||
return {'FINISHED'}
|
return {'FINISHED'}
|
||||||
|
|
||||||
|
|
||||||
@ -333,7 +351,8 @@ class CompifyBake(bpy.types.Operator):
|
|||||||
and context.scene.compify_config.footage != None \
|
and context.scene.compify_config.footage != None \
|
||||||
and context.scene.compify_config.camera != None \
|
and context.scene.compify_config.camera != None \
|
||||||
and context.scene.compify_config.geo_collection != None \
|
and context.scene.compify_config.geo_collection != None \
|
||||||
and len(context.scene.compify_config.geo_collection.all_objects) > 0
|
and len(context.scene.compify_config.geo_collection.all_objects) > 0 \
|
||||||
|
and compify_mat_name(context) in bpy.data.materials
|
||||||
|
|
||||||
def execute(self, context):
|
def execute(self, context):
|
||||||
# Clear operator fields. Not strictly necessary, since they
|
# Clear operator fields. Not strictly necessary, since they
|
||||||
@ -421,7 +440,7 @@ class CompifyBake(bpy.types.Operator):
|
|||||||
# filepath='',
|
# filepath='',
|
||||||
# width=512,
|
# width=512,
|
||||||
# height=512,
|
# height=512,
|
||||||
margin=4,
|
margin=context.scene.compify_config.bake_uv_margin,
|
||||||
margin_type='EXTEND',
|
margin_type='EXTEND',
|
||||||
use_selected_to_active=False,
|
use_selected_to_active=False,
|
||||||
max_ray_distance=0.0,
|
max_ray_distance=0.0,
|
||||||
@ -534,6 +553,15 @@ class CompifyFootageConfig(bpy.types.PropertyGroup):
|
|||||||
type=bpy.types.Collection,
|
type=bpy.types.Collection,
|
||||||
name="Footage Lights Collection",
|
name="Footage Lights Collection",
|
||||||
)
|
)
|
||||||
|
bake_uv_margin: bpy.props.IntProperty(
|
||||||
|
name="Bake UV Margin",
|
||||||
|
subtype='PIXEL',
|
||||||
|
options=set(), # Not animatable.
|
||||||
|
default=4,
|
||||||
|
min=0,
|
||||||
|
max=2**16,
|
||||||
|
soft_max=32,
|
||||||
|
)
|
||||||
bake_image_res: bpy.props.IntProperty(
|
bake_image_res: bpy.props.IntProperty(
|
||||||
name="Bake Resolution",
|
name="Bake Resolution",
|
||||||
subtype='PIXEL',
|
subtype='PIXEL',
|
||||||
|
@ -1,37 +0,0 @@
|
|||||||
from math import inf
|
|
||||||
from bpy_extras.mesh_utils import mesh_linked_uv_islands
|
|
||||||
|
|
||||||
|
|
||||||
def uv_island_bbox_area_sum_multi_object(mesh_objects, uv_layer_name):
|
|
||||||
area_sum = 0.0
|
|
||||||
for obj in mesh_objects:
|
|
||||||
area_sum += uv_island_bbox_area_sum(obj.data, uv_layer_name)
|
|
||||||
return area_sum
|
|
||||||
|
|
||||||
|
|
||||||
def uv_island_bbox_area_sum(mesh, uv_layer_name):
|
|
||||||
""" Returns the sum of the area of the bounding boxes of all the UV
|
|
||||||
islands in the given mesh for the given uv layer.
|
|
||||||
"""
|
|
||||||
uvs = mesh.uv_layers[uv_layer_name].data
|
|
||||||
islands = mesh_linked_uv_islands(mesh)
|
|
||||||
|
|
||||||
bbox_area_sum = 0.0
|
|
||||||
for island in islands:
|
|
||||||
# Calculate the island's bounding box.
|
|
||||||
min_u = inf
|
|
||||||
max_u = -inf
|
|
||||||
min_v = inf
|
|
||||||
max_v = -inf
|
|
||||||
for face_idx in island:
|
|
||||||
for loop_idx in mesh.polygons[face_idx].loop_indices:
|
|
||||||
uv = uvs[mesh.loops[loop_idx].vertex_index].uv
|
|
||||||
min_u = min(min_u, uv[0])
|
|
||||||
max_u = max(max_u, uv[0])
|
|
||||||
min_v = min(min_v, uv[1])
|
|
||||||
max_v = max(max_v, uv[1])
|
|
||||||
|
|
||||||
# Add it's area to the sum.
|
|
||||||
bbox_area_sum += ((max_u - min_u) * (max_v - min_v))**0.5
|
|
||||||
|
|
||||||
return bbox_area_sum
|
|
10
uv_utils.py
Normal file
10
uv_utils.py
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
from math import inf
|
||||||
|
|
||||||
|
|
||||||
|
def leftmost_u(mesh_objects, uv_layer_name):
|
||||||
|
leftmost = inf
|
||||||
|
for obj in mesh_objects:
|
||||||
|
uvs = obj.data.uv_layers[uv_layer_name].data
|
||||||
|
for uv in uvs:
|
||||||
|
leftmost = min(leftmost, uv.uv[0])
|
||||||
|
return leftmost
|
Loading…
Reference in New Issue
Block a user