Browse Source

Merge pull request #75 from Hoikas/proc-mods

Fix #63
pull/82/head
Adam Johnson 7 years ago committed by GitHub
parent
commit
1b45152734
  1. 5
      korman/exporter/convert.py
  2. 11
      korman/exporter/etlight.py
  3. 78
      korman/exporter/mesh.py
  4. 2
      korman/operators/op_lightmap.py

5
korman/exporter/convert.py

@ -53,7 +53,8 @@ class Exporter:
self.animation = animation.AnimationConverter(self)
self.sumfile = sumfile.SumFile()
# Step 0.9: Init the progress mgr
# Step 0.8: Init the progress mgr
self.mesh.add_progress_presteps(self.report)
self.report.progress_add_step("Collecting Objects")
self.report.progress_add_step("Harvesting Actors")
if self._op.bake_lighting:
@ -65,6 +66,8 @@ class Exporter:
self.report.progress_add_step("Composing Geometry")
self.report.progress_start("EXPORTING AGE")
# Step 0.9: Apply modifiers to all meshes temporarily.
with self.mesh:
# Step 1: Create the age info and the pages
self._export_age_info()

11
korman/exporter/etlight.py

@ -17,24 +17,25 @@ import bpy
from bpy.app.handlers import persistent
from .logger import ExportProgressLogger
from .mesh import _VERTEX_COLOR_LAYERS
from .mesh import _MeshManager, _VERTEX_COLOR_LAYERS
from ..helpers import *
_NUM_RENDER_LAYERS = 20
class LightBaker:
class LightBaker(_MeshManager):
"""ExportTime Lighting"""
def __init__(self, report=None):
self._lightgroups = {}
if report is None:
self._report = ExportProgressLogger()
self.add_progress_steps(self._report)
self.add_progress_steps(self._report, True)
self._report.progress_start("PREVIEWING LIGHTING")
self._own_report = True
else:
self._report = report
self._own_report = False
super().__init__(self._report)
self._uvtexs = {}
def __del__(self):
@ -42,7 +43,9 @@ class LightBaker:
self._report.progress_end()
@staticmethod
def add_progress_steps(report):
def add_progress_steps(report, add_base=False):
if add_base:
_MeshManager.add_progress_presteps(report)
report.progress_add_step("Searching for Bahro")
report.progress_add_step("Baking Static Lighting")

78
korman/exporter/mesh.py

@ -18,6 +18,7 @@ from PyHSPlasma import *
from math import fabs
import weakref
from ..exporter.logger import ExportProgressLogger
from . import explosions
from .. import helpers
from . import material
@ -111,7 +112,71 @@ class _GeoData:
self.vertices = []
class MeshConverter:
class _MeshManager:
def __init__(self, report=None):
if report is not None:
self._report = report
self._overrides = {}
@staticmethod
def add_progress_presteps(report):
report.progress_add_step("Applying Blender Mods")
def _build_prop_dict(self, bstruct):
props = {}
for i in bstruct.bl_rna.properties:
ident = i.identifier
if ident == "rna_type":
continue
props[ident] = getattr(bstruct, ident) if getattr(i, "array_length", 0) == 0 else tuple(getattr(bstruct, ident))
return props
def __enter__(self):
self._report.progress_advance()
self._report.progress_range = len(bpy.data.objects)
# Some modifiers like "Array" will procedurally generate new geometry that will impact
# lightmap generation. The Blender Internal renderer does not seem to be smart enough to
# take this into account. Thus, we temporarily apply modifiers to ALL meshes (even ones that
# are not exported) such that we can generate proper lighting.
scene = bpy.context.scene
for i in bpy.data.objects:
if i.type == "MESH" and i.is_modified(scene, "RENDER"):
# Remember, storing actual pointers to the Blender objects can cause bad things to
# happen because Blender's memory management SUCKS!
self._overrides[i.name] = { "mesh": i.data.name, "modifiers": [] }
i.data = i.to_mesh(scene, True, "RENDER", calc_tessface=False)
# If the modifiers are left on the object, the lightmap bake can break under some
# situations. Therefore, we now cache the modifiers and clear them away...
if i.plasma_object.enabled:
cache_mods = self._overrides[i.name]["modifiers"]
for mod in i.modifiers:
cache_mods.append(self._build_prop_dict(mod))
i.modifiers.clear()
self._report.progress_increment()
return self
def __exit__(self, type, value, traceback):
data_bos, data_meshes = bpy.data.objects, bpy.data.meshes
for obj_name, override in self._overrides.items():
bo = data_bos.get(obj_name)
# Reapply the old mesh
trash_mesh, bo.data = bo.data, data_meshes.get(override["mesh"])
data_meshes.remove(trash_mesh)
# If modifiers were removed, reapply them now.
for cached_mod in override["modifiers"]:
mod = bo.modifiers.new(cached_mod["name"], cached_mod["type"])
for key, value in cached_mod.items():
if key in {"name", "type"}:
continue
setattr(mod, key, value)
class MeshConverter(_MeshManager):
def __init__(self, exporter):
self._exporter = weakref.ref(exporter)
self.material = material.MaterialConverter(exporter)
@ -119,6 +184,9 @@ class MeshConverter:
self._dspans = {}
self._mesh_geospans = {}
# _report is a property on this subclass
super().__init__()
def _calc_num_uvchans(self, bo, mesh):
max_user_texs = plGeometrySpan.kUVCountMask
num_user_texs = len(mesh.tessface_uv_textures)
@ -403,8 +471,11 @@ class MeshConverter:
diface.addDrawable(dspan_key, idx)
def _export_mesh(self, bo):
# Step 0.7: Update the mesh such that we can do things and schtuff...
mesh = bo.to_mesh(bpy.context.scene, True, "RENDER", calc_tessface=True)
# Previously, this called bo.to_mesh to apply modifiers. However, due to limitations in the
# lightmap generation, this is now done for all modified mesh objects before any Plasma data
# is exported.
mesh = bo.data
mesh.calc_tessface()
# Step 0.8: Figure out which materials are attached to this object. Because Blender is backwards,
# we can actually have materials that are None. gotdawgit!!!
@ -412,7 +483,6 @@ class MeshConverter:
if not materials:
return None
with helpers.TemporaryObject(mesh, bpy.data.meshes.remove):
# Step 1: Export all of the doggone materials.
geospans = self._export_material_spans(bo, mesh, materials)

2
korman/operators/op_lightmap.py

@ -41,7 +41,7 @@ class LightmapAutobakePreviewOperator(_LightingOperator, bpy.types.Operator):
with GoodNeighbor() as toggle:
toggle.track(context.scene, "layers", tuple(context.scene.layers))
bake = LightBaker()
with LightBaker() as bake:
if not bake.bake_static_lighting([context.active_object,]):
self.report({"INFO"}, "No valid lights found to bake.")
return {"FINISHED"}

Loading…
Cancel
Save