Heavy UV Maps Handling
Version 3.1.0 of the packer introduced significant performance improvements for handling UV maps with a huge number of faces (a few millions and more). Benchmarks show that the packer is now able to process a UV map containing 15 millions of faces in a few minutes. There are still a few considerations the user should have in mind, when packing such a UV map.
Heuristic search considerations
In order to achieve the most dense packing possible, one should enable the Heuristic Search functionality. Heavy UV maps are no exception from this rule - you should only remember to set the Search Time parameter to a larger value so that the packer has enough time for iterating the algorithm.
One problem with using a heuristic search on a heavy UV map is the fact, that the packer always updates the UV map in the Blender UV editor immediately as soon as it finds a better result. While it is a desired behavior when dealing with a usual UV map, it may be problematic in case of heavy UV maps - triggering a position update for millions of UV faces in Blender always requires noticeable computational and memory resources what slows down the entire process.
Due to this issue, you can disable such immediate UV updates:
- expand the top-most panel in the packer UI in Blender (the panel showing the packer version in the header):
- press the Show Expert Options button. The expert options will be displayed,
- check the Disable Immediate UV Update option.
With this option enabled, the packer will only report the area, when a better result is found, but the UV map will stay intact in Blender during the entire search. The UV map will be updated with the best result only once, after the search is done.
Running an operation without GUI
When processing a heavy UV map consider running Blender in the background mode. In this mode Blender is run from command line (without GUI) and a Python script provided by you determines what should be done. This way you can save computer resources and speed up the entire operation.
In order to run Blender in the background mode issue the following command:
blender --python-exit-code 1 -b -P run_uvpm3.py
where run_uvpm3.py is the name of a script to execute. Below we share an exemplary script which performs the following steps:
- loads a mesh from an obj file,
- selects all UVs of the mesh,
- sets particular UVPackmaster options,
- performs packing,
- saves the resulting mesh with the packed UV map to a different obj file.
Of course the script requires a working UVPackmaster engine installation to run properly.
# MIT License
#
# Copyright (c) 2022 Lukasz Czyz
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
import bpy
import bmesh
source_file = 'test.obj'
target_file = 'test_packed.obj'
# Deselect all objects
bpy.ops.object.select_all(action='DESELECT')
bpy.ops.import_scene.obj(filepath=source_file)
obj_object = bpy.context.selected_objects[0]
# Make the object active
bpy.context.view_layer.objects.active = obj_object
bpy.ops.object.editmode_toggle()
# Select all UVs
bm = bmesh.from_edit_mesh(obj_object.data)
uv_layer = bm.loops.layers.uv.verify()
for face in bm.faces:
for loop in face.loops:
loop_uv = loop[uv_layer]
loop_uv.select = True
# === PACKING OPERATION BEGIN ===
# Reset all UVPM parameters to defaults
bpy.ops.uvpackmaster3.reset_to_defaults()
# Set values for all required UVPM parameters directly in the script.
uvpm3_prefs = bpy.context.preferences.addons['uvpackmaster3'].preferences
uvpm3_props = bpy.context.scene.uvpm3_props
# To get the python path for the given parameter, open Blender normally (with GUI),
# right mouse click over the parameter in the packer UI, then select 'Copy Data Path'
# from the menu. The path will be copied to clipboard.
uvpm3_props.precision = 500
# Select packing mode id - uncomment only one line below
mode_id = "pack.single_tile"
# mode_id = "pack.tiles"
# mode_id = "pack.groups_to_tiles"
# mode_id = "pack.groups_together"
# If you want to use the packing mode currently selected in the blend file (e.g. after loading a UVPM preset), uncomment the following line
# mode_id = uvpm3_props.active_main_mode_id
try:
bpy.ops.uvpackmaster3.pack(mode_id=mode_id, pack_to_others=False)
except Exception as ex:
print('Pack operation failed: ' + str(ex))
if uvpm3_prefs.engine_retcode != 0:
raise RuntimeError('UVPM 3 operation not succeeded (a warning or error occurred)! Return code: {}'.format(int(uvpm3_prefs.engine_retcode)))
# === PACKING OPERATION END ===
bpy.ops.object.editmode_toggle()
bpy.ops.export_scene.obj(filepath=target_file, use_selection=True)