Browse Source

More lighting improvements...

Added the Render > Lighting modifier that lets one specify whether or not
we should forcibly use RT lights. This allows us to change the light
baking rules to allow the baking of nonanimated Plasma lights when this
setting is disabled. The modifier also has text explaining what the
lighting results should look like.
pull/43/head
Adam Johnson 9 years ago
parent
commit
5a9cd719f2
  1. 20
      korman/exporter/animation.py
  2. 2
      korman/exporter/convert.py
  3. 20
      korman/exporter/etlight.py
  4. 7
      korman/exporter/mesh.py
  5. 2
      korman/exporter/rtlight.py
  6. 2
      korman/nodes/node_messages.py
  7. 2
      korman/properties/modifiers/anim.py
  8. 2
      korman/properties/modifiers/physics.py
  9. 61
      korman/properties/modifiers/render.py
  10. 22
      korman/properties/prop_object.py
  11. 36
      korman/ui/modifiers/render.py

20
korman/exporter/animation.py

@ -31,7 +31,7 @@ class AnimationConverter:
return frame_num / self._bl_fps
def convert_object_animations(self, bo, so):
if not self.is_animated(bo):
if not bo.plasma_object.has_animation_data:
return
def fetch_animation_data(id_data):
@ -308,24 +308,6 @@ class AnimationConverter:
master = self._mgr.find_create_object(plAGMasterMod, so=so, bl=bo)
return mod, master
def has_transform_animation(self, bo):
if bo.animation_data is not None:
if bo.animation_data.action is not None:
data_paths = frozenset((i.data_path for i in bo.animation_data.action.fcurves))
return {"location", "rotation_euler", "scale"} & data_paths
return False
def is_animated(self, bo):
if bo.animation_data is not None:
if bo.animation_data.action is not None:
return True
data = getattr(bo, "data", None)
if data is not None:
if data.animation_data is not None:
if data.animation_data.action is not None:
return True
return False
def make_matrix44_controller(self, fcurves, pos_path, scale_path, pos_default, scale_default):
def convert_matrix_keyframe(**kwargs):
pos = kwargs.get(pos_path)

2
korman/exporter/convert.py

@ -259,7 +259,7 @@ class Exporter:
return True
if bo.name in self.actors:
return True
if self.animation.has_transform_animation(bo):
if bo.plasma_object.has_transform_animation:
return True
for mod in bo.plasma_modifiers.modifiers:

20
korman/exporter/etlight.py

@ -118,13 +118,14 @@ class LightBaker:
# Return how many thingos we baked
return sum(map(len, bake.values()))
def _generate_lightgroup(self, mesh, user_lg=None):
def _generate_lightgroup(self, bo, user_lg=None):
"""Makes a new light group for the baking process that excludes all Plasma RT lamps"""
if user_lg is not None:
user_lg = bpy.data.groups.get(user_lg)
shouldibake = (user_lg is not None and bool(user_lg.objects))
mesh = bo.data
for material in mesh.materials:
if material is None:
# material is not assigned to this material... (why is this even a thing?)
@ -143,13 +144,20 @@ class LightBaker:
source = lg.objects
dest = bpy.data.groups.new("_LIGHTMAPGEN_{}".format(name))
# Only use non-RT lights
# Rules:
# 1) No animated lights, period.
# 2) If we accept runtime lighting, no Plasma Objects
rtl_mod = bo.plasma_modifiers.lighting
for obj in source:
if obj.plasma_object.enabled:
if obj.plasma_object.has_animation_data:
continue
if rtl_mod.rt_lights and obj.plasma_object.enabled:
continue
dest.objects.link(obj)
shouldibake = True
else:
# The aforementioned rules do not apply. You better hope you know WTF you are
# doing. I'm not going to help!
dest = user_lg
material.light_group = dest
return shouldibake
@ -185,7 +193,7 @@ class LightBaker:
bake[key].append(i)
else:
bake[key] = [i,]
elif not mods.water_basic.enabled:
elif mods.lighting.preshade:
vcols = i.data.vertex_colors
for j in _VERTEX_COLOR_LAYERS:
if j in vcols:
@ -212,7 +220,7 @@ class LightBaker:
uv_textures = mesh.uv_textures
# Create a special light group for baking
if not self._generate_lightgroup(mesh, modifier.light_group):
if not self._generate_lightgroup(bo, modifier.light_group):
return False
# We need to ensure that we bake onto the "BlahObject_LIGHTMAPGEN" image
@ -285,7 +293,7 @@ class LightBaker:
vcols = mesh.vertex_colors
# Create a special light group for baking
if not self._generate_lightgroup(mesh):
if not self._generate_lightgroup(bo):
return False
# I have heard tale of some moar "No valid image to bake to" boogs if there is a really

7
korman/exporter/mesh.py

@ -130,6 +130,13 @@ class MeshConverter:
raise explosions.TooManyUVChannelsError(bo, bm)
geospan.format = numUVWchans
# Begin total guesswork WRT flags
mods = bo.plasma_modifiers
if mods.lightmap.enabled:
geospan.props |= plGeometrySpan.kLiteVtxNonPreshaded
if mods.lighting.rt_lights:
geospan.props |= plGeometrySpan.kPropRunTimeLight
# Harvest lights
permaLights, permaProjs = self._exporter().light.find_material_light_keys(bo, bm)
for i in permaLights:

2
korman/exporter/rtlight.py

@ -188,7 +188,7 @@ class LightConverter:
# If the lamp has any sort of animation attached, then it needs to be marked movable.
# Otherwise, Plasma may not use it for lighting.
if projectors or self._exporter().animation.is_animated(bo):
if projectors or bo.plasma_object.has_animation_data:
pl_light.setProperty(plLightInfo.kLPMovable, True)
# *Sigh*

2
korman/nodes/node_messages.py

@ -174,7 +174,7 @@ class PlasmaAnimCmdMsgNode(PlasmaMessageNode, bpy.types.Node):
if obj is None:
self.raise_error("invalid object: '{}'".format(self.object_name))
if self.anim_type == "OBJECT":
if not exporter.animation.is_animated(obj):
if not obj.plasma_object.has_animation_data:
self.raise_error("invalid animation")
group = obj.plasma_modifiers.animation_group
if group.enabled:

2
korman/properties/modifiers/anim.py

@ -112,7 +112,7 @@ class PlasmaAnimationGroupModifier(ActionModifier, PlasmaModifierProperties):
active_child_index = IntProperty(options={"HIDDEN"})
def export(self, exporter, bo, so):
if not exporter.animation.is_animated(bo):
if not bo.plasma_object.has_animation_data:
raise ExportError("'{}': Object is not animated".format(bo.name))
# The message forwarder is the guy that makes sure that everybody knows WTF is going on

2
korman/properties/modifiers/physics.py

@ -105,7 +105,7 @@ class PlasmaCollider(PlasmaModifierProperties):
def post_export(self, exporter, bo, so):
test_bo = bo
while test_bo is not None:
if exporter.animation.has_transform_animation(test_bo):
if test_bo.plasma_object.has_transform_animation:
self._make_physical_movable(so)
break
test_bo = test_bo.parent

61
korman/properties/modifiers/render.py

@ -216,6 +216,67 @@ class PlasmaLightMapGen(PlasmaModifierProperties):
def resolution(self):
return int(self.quality)
class PlasmaLightingMod(PlasmaModifierProperties):
pl_id = "lighting"
bl_category = "Render"
bl_label = "Lighting"
bl_description = "Fine tune Plasma lighting settings"
force_rt_lights = BoolProperty(name="Force RT Lighting",
description="Unleashes satan by forcing the engine to dynamically light this object",
default=True,
options=set())
force_preshade = BoolProperty(name="Force Vertex Shading",
description="Ensures vertex lights are baked, even if illogical",
default=False,
options=set())
@property
def allow_preshade(self):
bo = self.id_data
if bo.plasma_modifiers.water_basic.enabled:
return False
if bo.plasma_modifiers.lightmap.enabled:
return False
return True
def export(self, exporter, bo, so):
# Exposes no new keyed objects, mostly a hint to the ET light code
pass
@property
def preshade(self):
bo = self.id_data
if self.allow_preshade:
if self.force_preshade:
return True
# RT lights means no preshading unless requested
if self.rt_lights:
return False
if not bo.plasma_object.has_transform_animation:
return True
return False
@property
def rt_lights(self):
"""Are RT lights forcibly enabled or do we otherwise want them?"""
return (self.enabled and self.force_rt_lights) or self.want_rt_lights
@property
def want_rt_lights(self):
"""Gets whether or not this object ought to be lit dynamically"""
bo = self.id_data
if bo.plasma_modifiers.lightmap.enabled:
return False
if bo.plasma_modifiers.water_basic.enabled:
return True
if bo.plasma_object.has_transform_animation:
return True
return False
class PlasmaViewFaceMod(PlasmaModifierProperties):
pl_id = "viewfacemod"

22
korman/properties/prop_object.py

@ -52,6 +52,28 @@ class PlasmaObject(bpy.types.PropertyGroup):
default=False,
options={"HIDDEN"})
@property
def has_animation_data(self):
bo = self.id_data
if bo.animation_data is not None:
if bo.animation_data.action is not None:
return True
data = getattr(bo, "data", None)
if data is not None:
if data.animation_data is not None:
if data.animation_data.action is not None:
return True
return False
@property
def has_transform_animation(self):
bo = self.id_data
if bo.animation_data is not None:
if bo.animation_data.action is not None:
data_paths = frozenset((i.data_path for i in bo.animation_data.action.fcurves))
return {"location", "rotation_euler", "scale"} & data_paths
return False
class PlasmaNet(bpy.types.PropertyGroup):
manual_sdl = BoolProperty(name="Override SDL",

36
korman/ui/modifiers/render.py

@ -45,6 +45,42 @@ def followmod(modifier, layout, context):
if modifier.leader_type == "kFollowObject":
layout.prop_search(modifier, "leader_object", bpy.data, "objects", icon="OUTLINER_OB_MESH")
def lighting(modifier, layout, context):
split = layout.split()
col = split.column()
col.prop(modifier, "force_rt_lights")
col = split.column()
col.active = modifier.allow_preshade
col.prop(modifier, "force_preshade")
layout.separator()
lightmap = modifier.id_data.plasma_modifiers.lightmap
have_static_lights = lightmap.enabled or modifier.preshade
def yes_no(val):
return "Yes" if val else "No"
col = layout.column(align=True)
col.label("Plasma Lighting Summary:")
if modifier.rt_lights and have_static_lights:
col.label(" You have unleashed Satan!", icon="GHOST_ENABLED")
else:
col.label(" Satan remains ensconced deep in the abyss...", icon="GHOST_ENABLED")
col.label("Animated lights will be cast at runtime.", icon="LAYER_USED")
col.label("Projection lights will be cast at runtime.", icon="LAYER_USED")
col.label("Specular lights will be cast to specular materials at runtime.", icon="LAYER_USED")
col.label("Other Plasma lights {} be cast at runtime.".format("will" if modifier.rt_lights else "will NOT"),
icon="LAYER_USED")
if lightmap.enabled and lightmap.light_group:
col.label(" All '{}' lights will be baked to a lightmap".format(lightmap.light_group),
icon="LAYER_USED")
elif have_static_lights:
light_type = "Blender-only" if modifier.rt_lights else "unanimated"
map_type = "a lightmap" if lightmap.enabled else "vertex colors"
col.label("Other {} lights will be baked to {}.".format(light_type, map_type), icon="LAYER_USED")
else:
col.label("No static lights will be baked.", icon="LAYER_USED")
def lightmap(modifier, layout, context):
layout.row(align=True).prop(modifier, "quality", expand=True)
layout.prop(modifier, "render_layers", text="Active Render Layers")

Loading…
Cancel
Save