Browse Source

Implement Omni Light animations

pull/40/head
Adam Johnson 9 years ago
parent
commit
5f8e57ef6b
  1. 57
      korman/exporter/animation.py
  2. 28
      korman/exporter/rtlight.py

57
korman/exporter/animation.py

@ -59,6 +59,8 @@ class AnimationConverter:
applicators.extend(self._convert_lamp_color_animation(bo.name, data_fcurves, lamp)) applicators.extend(self._convert_lamp_color_animation(bo.name, data_fcurves, lamp))
if isinstance(lamp, bpy.types.SpotLamp): if isinstance(lamp, bpy.types.SpotLamp):
applicators.extend(self._convert_spot_lamp_animation(bo.name, data_fcurves, lamp)) applicators.extend(self._convert_spot_lamp_animation(bo.name, data_fcurves, lamp))
if isinstance(lamp, bpy.types.PointLamp):
applicators.extend(self._convert_omni_lamp_animation(bo.name, data_fcurves, lamp))
# Check to make sure we have some valid animation applicators before proceeding. # Check to make sure we have some valid animation applicators before proceeding.
if not any(applicators): if not any(applicators):
@ -145,6 +147,61 @@ class AnimationConverter:
applicator.channel = channel applicator.channel = channel
yield applicator yield applicator
def _convert_omni_lamp_animation(self, name, fcurves, lamp):
energy_fcurve = next((i for i in fcurves if i.data_path == "energy"), None)
distance_fcurve = next((i for i in fcurves if i.data_path == "distance"), None)
if energy_fcurve is None and distance_fcurve is None:
return None
light_converter = self._exporter().light
intensity, atten_end = light_converter.convert_attenuation(lamp)
# All types allow animating cutoff
if distance_fcurve is not None:
channel = plScalarControllerChannel()
channel.controller = self.make_scalar_leaf_controller(distance_fcurve,
lambda x: x * 2 if lamp.use_sphere else x)
applicator = plOmniCutoffApplicator()
applicator.channelName = name
applicator.channel = channel
yield applicator
falloff = lamp.falloff_type
if falloff == "CONSTANT":
if energy_fcurve is not None:
self._exporter().report.warn("Constant attenuation cannot be animated in Plasma", ident=3)
elif falloff == "INVERSE_LINEAR":
def convert_linear_atten(distance, energy):
intens = abs(energy[0])
atten_end = distance[0] * 2 if lamp.use_sphere else distance[0]
return light_converter.convert_attenuation_linear(intens, atten_end)
keyframes = self._process_fcurves([distance_fcurve, energy_fcurve], convert_linear_atten,
{"distance": lamp.distance, "energy": lamp.energy})
if keyframes:
channel = plScalarControllerChannel()
channel.controller = self._make_scalar_leaf_controller(keyframes, False)
applicator = plOmniApplicator()
applicator.channelName = name
applicator.channel = channel
yield applicator
elif falloff == "INVERSE_SQUARE":
def convert_quadratic_atten(distance, energy):
intens = abs(energy[0])
atten_end = distance[0] * 2 if lamp.use_sphere else distance[0]
return light_converter.convert_attenuation_quadratic(intens, atten_end)
keyframes = self._process_fcurves([distance_fcurve, energy_fcurve], convert_quadratic_atten,
{"distance": lamp.distance, "energy": lamp.energy})
if keyframes:
channel = plScalarControllerChannel()
channel.controller = self._make_scalar_leaf_controller(keyframes, False)
applicator = plOmniSqApplicator()
applicator.channelName = name
applicator.channel = channel
yield applicator
else:
self._exporter().report.warn("Lamp Falloff '{}' animations are not supported".format(falloff), ident=3)
def _convert_sound_volume_animation(self, name, fcurves, soundemit): def _convert_sound_volume_animation(self, name, fcurves, soundemit):
if not fcurves: if not fcurves:
return None return None

28
korman/exporter/rtlight.py

@ -40,11 +40,8 @@ class LightConverter:
} }
def _convert_attenuation(self, bl, pl): def _convert_attenuation(self, bl, pl):
intens = bl.energy # If you change these calculations, be sure to update the AnimationConverter!
if intens < 0: intens, attenEnd = self.convert_attenuation(bl)
intens = -intens
attenEnd = bl.distance * 2 if bl.use_sphere else bl.distance
if bl.falloff_type == "CONSTANT": if bl.falloff_type == "CONSTANT":
print(" Attenuation: No Falloff") print(" Attenuation: No Falloff")
pl.attenConst = intens pl.attenConst = intens
@ -54,18 +51,29 @@ class LightConverter:
elif bl.falloff_type == "INVERSE_LINEAR": elif bl.falloff_type == "INVERSE_LINEAR":
print(" Attenuation: Inverse Linear") print(" Attenuation: Inverse Linear")
pl.attenConst = 1.0 pl.attenConst = 1.0
pl.attenLinear = max(0.0, (intens * _FAR_POWER - 1.0) / attenEnd) pl.attenLinear = self.convert_attenuation_linear(intens, attenEnd)
pl.attenQuadratic = 0.0 pl.attenQuadratic = 0.0
pl.attenCutoff = attenEnd pl.attenCutoff = attenEnd
elif bl.falloff_type == "INVERSE_SQUARE": elif bl.falloff_type == "INVERSE_SQUARE":
print(" Attenuation: Inverse Square") print(" Attenuation: Inverse Square")
pl.attenConst = 1.0 pl.attenConst = 1.0
pl.attenLinear = 0.0 pl.attenLinear = 0.0
pl.attenQuadratic = max(0.0, (intens * _FAR_POWER - 1.0) / (attenEnd * attenEnd)) pl.attenQuadratic = self.convert_attenuation_quadratic(intens, attenEnd)
pl.attenCutoff = attenEnd pl.attenCutoff = attenEnd
else: else:
raise BlenderOptionNotSupportedError(bl.falloff_type) raise BlenderOptionNotSupportedError(bl.falloff_type)
def convert_attenuation(self, lamp):
intens = abs(lamp.energy)
attenEnd = lamp.distance * 2 if lamp.use_sphere else lamp.distance
return (intens, attenEnd)
def convert_attenuation_linear(self, intensity, end):
return max(0.0, (intensity * _FAR_POWER - 1.0) / end)
def convert_attenuation_quadratic(self, intensity, end):
return max(0.0, (intensity * _FAR_POWER - 1.0) / pow(end, 2))
def _convert_area_lamp(self, bl, pl): def _convert_area_lamp(self, bl, pl):
print(" [LimitedDirLightInfo '{}']".format(bl.name)) print(" [LimitedDirLightInfo '{}']".format(bl.name))
@ -176,6 +184,11 @@ class LightConverter:
if projectors: if projectors:
self._export_rt_projector(bo, pl_light, projectors) self._export_rt_projector(bo, pl_light, projectors)
# 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):
pl_light.setProperty(plLightInfo.kLPMovable, True)
# *Sigh* # *Sigh*
pl_light.sceneNode = self.mgr.get_scene_node(location=so.key.location) pl_light.sceneNode = self.mgr.get_scene_node(location=so.key.location)
@ -203,7 +216,6 @@ class LightConverter:
else: else:
state.miscFlags |= hsGMatState.kMiscOrthoProjection state.miscFlags |= hsGMatState.kMiscOrthoProjection
state.ZFlags |= hsGMatState.kZNoZWrite state.ZFlags |= hsGMatState.kZNoZWrite
pl_light.setProperty(plLightInfo.kLPMovable, True)
pl_light.setProperty(plLightInfo.kLPCastShadows, False) pl_light.setProperty(plLightInfo.kLPCastShadows, False)
if slot.blend_type == "ADD": if slot.blend_type == "ADD":

Loading…
Cancel
Save