From 6af1a40072668e38e8e36bc663b301cfa7b63bd2 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Tue, 3 Aug 2021 16:29:07 -0400 Subject: [PATCH] Don't touch my UV maps! It's better to trust the artist to know what they are doing if they provide a uv map for the lightmap modifier to use. Closes #265. --- korman/exporter/etlight.py | 36 +++++++++++++++++---------- korman/exporter/mesh.py | 3 +++ korman/properties/modifiers/render.py | 2 +- korman/ui/modifiers/render.py | 2 ++ 4 files changed, 29 insertions(+), 14 deletions(-) diff --git a/korman/exporter/etlight.py b/korman/exporter/etlight.py index 94d90c9..c25b2d2 100644 --- a/korman/exporter/etlight.py +++ b/korman/exporter/etlight.py @@ -15,7 +15,7 @@ import bpy -from contextlib import ExitStack +from contextlib import contextmanager import itertools from .explosions import * @@ -375,6 +375,8 @@ class LightBaker(_MeshManager): # this tended to create sharp edges. There was already a discussion about this on the # Guild of Writers forum, so I'm implementing a code version of dendwaler's process, # as detailed here: https://forum.guildofwriters.org/viewtopic.php?p=62572#p62572 + # This has been amended with Sirius's observations in GH-265 about forced uv map + # packing. Namely, don't do it unless modifiers make us. uv_base = self._get_lightmap_uvtex(mesh, modifier) if uv_base is not None: uv_textures.active = uv_base @@ -384,25 +386,25 @@ class LightBaker(_MeshManager): uv_textures.active = uvtex # if the artist hid any UVs, they will not be baked to... fix this now - bpy.ops.object.mode_set(mode="EDIT") - bpy.ops.uv.reveal() - bpy.ops.object.mode_set(mode="OBJECT") + with self._set_mode("EDIT"): + bpy.ops.uv.reveal() self._associate_image_with_uvtex(uv_textures.active, im) - bpy.ops.object.mode_set(mode="EDIT") - # prep the uvtex for lightmapping - bpy.ops.mesh.select_all(action="SELECT") - bpy.ops.uv.average_islands_scale() - bpy.ops.uv.pack_islands() + # Meshes with modifiers need to have islands packed to prevent generated vertices + # from sharing UVs. Sigh. + if self.is_collapsed(bo): + self._report.warn("'{}': packing islands in UV Texture '{}' due to modifier collapse", bo.name, uv_base.name) + with self._set_mode("EDIT"): + bpy.ops.mesh.select_all(action="SELECT") + bpy.ops.uv.pack_islands() else: # same thread, see Sirius's suggestion RE smart unwrap. this seems to yield good # results in my tests. it will be good enough for quick exports. uvtex = uv_textures.new(self.lightmap_uvtex_name) self._associate_image_with_uvtex(uvtex, im) - bpy.ops.object.mode_set(mode="EDIT") - bpy.ops.mesh.select_all(action="SELECT") - bpy.ops.uv.smart_project() - bpy.ops.object.mode_set(mode="OBJECT") + with self._set_mode("EDIT"): + bpy.ops.mesh.select_all(action="SELECT") + bpy.ops.uv.smart_project(island_margin=0.05) # Now, set the new LIGHTMAPGEN uv layer as what we want to render to... # NOTE that this will need to be reset by us to what the user had previously @@ -490,3 +492,11 @@ class LightBaker(_MeshManager): elif isinstance(i.data, bpy.types.Mesh) and not self._has_valid_material(i): toggle.track(i, "hide_render", True) i.select = value + + @contextmanager + def _set_mode(self, mode): + bpy.ops.object.mode_set(mode=mode) + try: + yield + finally: + bpy.ops.object.mode_set(mode="OBJECT") diff --git a/korman/exporter/mesh.py b/korman/exporter/mesh.py index fef6d9a..caeea81 100644 --- a/korman/exporter/mesh.py +++ b/korman/exporter/mesh.py @@ -232,6 +232,9 @@ class _MeshManager: continue setattr(mod, key, value) + def is_collapsed(self, bo) -> bool: + return bo.name in self._overrides + class MeshConverter(_MeshManager): def __init__(self, exporter): diff --git a/korman/properties/modifiers/render.py b/korman/properties/modifiers/render.py index 07d0621..6b39dfe 100644 --- a/korman/properties/modifiers/render.py +++ b/korman/properties/modifiers/render.py @@ -472,7 +472,7 @@ class PlasmaLightMapGen(idprops.IDPropMixin, PlasmaModifierProperties, PlasmaMod materials = mat_mgr.get_materials(bo) # Find the stupid UVTex - uvtex_name = "LIGHTMAPGEN" + uvtex_name = exporter.oven.lightmap_uvtex_name uvw_src = next((i for i, uvtex in enumerate(bo.data.uv_textures) if uvtex.name == uvtex_name), None) if uvw_src is None: raise ExportError("'{}': Lightmap UV Texture '{}' seems to be missing. Did you delete it?", bo.name, uvtex_name) diff --git a/korman/ui/modifiers/render.py b/korman/ui/modifiers/render.py index 1205105..24c202e 100644 --- a/korman/ui/modifiers/render.py +++ b/korman/ui/modifiers/render.py @@ -196,6 +196,8 @@ def lightmap(modifier, layout, context): col = layout.column() col.active = is_texture col.prop_search(modifier, "uv_map", context.active_object.data, "uv_textures") + if bool(modifier.id_data.modifiers): + col.label("UV Map islands will be packed on export.", icon="ERROR") col = layout.column() col.active = is_texture col.prop(modifier, "image", icon="IMAGE_RGB")