Browse Source

Implement crappy vertex color light baking...

This should make the average age look a little bit better. I hope... If
you want to get rid of this crappy lighting, create a vertex color layer.
Or, better yet, add a stupid lightmap modifier!
pull/6/head
Adam Johnson 10 years ago
parent
commit
8bb8683f7c
  1. 69
      korman/exporter/mesh.py
  2. 51
      korman/operators/op_lightmap.py

69
korman/exporter/mesh.py

@ -24,6 +24,8 @@ from . import utils
_MAX_VERTS_PER_SPAN = 0xFFFF _MAX_VERTS_PER_SPAN = 0xFFFF
_WARN_VERTS_PER_SPAN = 0x8000 _WARN_VERTS_PER_SPAN = 0x8000
_VERTEX_COLOR_LAYERS = {"col", "color", "colour"}
class _RenderLevel: class _RenderLevel:
MAJOR_OPAQUE = 0 MAJOR_OPAQUE = 0
MAJOR_FRAMEBUF = 1 MAJOR_FRAMEBUF = 1
@ -148,6 +150,17 @@ class MeshConverter:
}) })
geodata = [_geodatacls() for i in mesh.materials] geodata = [_geodatacls() for i in mesh.materials]
# Locate relevant vertex color layers now...
color, alpha = None, None
for vcol_layer in mesh.tessface_vertex_colors:
name = vcol_layer.name.lower()
if name in _VERTEX_COLOR_LAYERS:
color = vcol_layer.data
elif name == "autocolor" and color is None:
color = vcol_layer.data
elif name == "alpha":
alpha = vcol_layer.data
# Convert Blender faces into things we can stuff into libHSPlasma # Convert Blender faces into things we can stuff into libHSPlasma
for i, tessface in enumerate(mesh.tessfaces): for i, tessface in enumerate(mesh.tessfaces):
data = geodata[tessface.material_index] data = geodata[tessface.material_index]
@ -157,24 +170,42 @@ class MeshConverter:
# NOTE: Blender has no third (W) coordinate # NOTE: Blender has no third (W) coordinate
tessface_uvws = [uvtex.data[i].uv for uvtex in mesh.tessface_uv_textures] tessface_uvws = [uvtex.data[i].uv for uvtex in mesh.tessface_uv_textures]
# Unpack colors
if color is None:
tessface_colors = ((1.0, 1.0, 1.0), (1.0, 1.0, 1.0), (1.0, 1.0, 1.0), (1.0, 1.0, 1.0))
else:
src = color[i]
tessface_colors = (src.color1, src.color2, src.color3, src.color4)
# Unpack alpha values
if alpha is None:
tessface_alphas = (1.0, 1.0, 1.0, 1.0)
else:
src = alpha[i]
# average color becomes the alpha value
tessface_alphas = (((src.color1[0] + src.color1[1] + src.color1[2]) / 3),
((src.color2[0] + src.color2[1] + src.color2[2]) / 3),
((src.color3[0] + src.color3[1] + src.color3[2]) / 3),
((src.color4[0] + src.color4[1] + src.color4[2]) / 3))
# Convert to per-material indices # Convert to per-material indices
for j, vertex in enumerate(tessface.vertices): for j, vertex in enumerate(tessface.vertices):
uvws = tuple([uvw[j] for uvw in tessface_uvws]) uvws = tuple([uvw[j] for uvw in tessface_uvws])
# Grab VCols (TODO--defaulting to white for now) # Grab VCols
# This will be finalized once the vertex color light code baking is in vertex_color = (int(tessface_colors[j][0] * 255), int(tessface_colors[j][1] * 255),
color = (255, 255, 255, 255) int(tessface_colors[j][2] * 255), int(tessface_alphas[j] * 255))
# Now, we'll index into the vertex dict using the per-face elements :( # Now, we'll index into the vertex dict using the per-face elements :(
# We're using tuples because lists are not hashable. The many mathutils and PyHSPlasma # We're using tuples because lists are not hashable. The many mathutils and PyHSPlasma
# types are not either, and it's entirely too much work to fool with all that. # types are not either, and it's entirely too much work to fool with all that.
coluv = (color, uvws) coluv = (vertex_color, uvws)
if coluv not in data.blender2gs[vertex]: if coluv not in data.blender2gs[vertex]:
source = mesh.vertices[vertex] source = mesh.vertices[vertex]
geoVertex = plGeometrySpan.TempVertex() geoVertex = plGeometrySpan.TempVertex()
geoVertex.position = utils.vector3(source.co) geoVertex.position = utils.vector3(source.co)
geoVertex.normal = utils.vector3(source.normal) geoVertex.normal = utils.vector3(source.normal)
geoVertex.color = hsColor32(*color) geoVertex.color = hsColor32(*vertex_color)
geoVertex.uvs = [hsVector3(uv[0], uv[1], 0.0) for uv in uvws] geoVertex.uvs = [hsVector3(uv[0], uv[1], 0.0) for uv in uvws]
data.blender2gs[vertex][coluv] = len(data.vertices) data.blender2gs[vertex][coluv] = len(data.vertices)
data.vertices.append(geoVertex) data.vertices.append(geoVertex)
@ -217,15 +248,10 @@ class MeshConverter:
return diface.key return diface.key
def _export_mesh(self, bo): def _export_mesh(self, bo):
# Step 0.8: If this mesh wants to be light mapped, we need to go ahead and generate it. # Step 0.8: If this mesh wants to be lit, we need to go ahead and generate it.
if bo.plasma_modifiers.lightmap.enabled: self._export_static_lighting(bo)
print(" Baking lightmap...")
print("====")
bpy.context.scene.objects.active = bo
bpy.ops.object.plasma_lightmap_autobake()
print("====")
# Step 0.9: Update the mesh # Step 0.9: Update the mesh such that we can do things and schtuff...
mesh = bo.data mesh = bo.data
mesh.update(calc_tessface=True) mesh.update(calc_tessface=True)
@ -263,6 +289,23 @@ class MeshConverter:
geospans[i] = (self._create_geospan(bo, mesh, blmat, hsgmat), blmat.pass_index) geospans[i] = (self._create_geospan(bo, mesh, blmat, hsgmat), blmat.pass_index)
return geospans return geospans
def _export_static_lighting(self, bo):
if bo.plasma_modifiers.lightmap.enabled:
print(" Baking lightmap...")
print("====")
bpy.context.scene.objects.active = bo
bpy.ops.object.plasma_lightmap_autobake()
print("====")
else:
for vcol_layer in bo.data.vertex_colors:
name = vcol_layer.name.lower()
if name in _VERTEX_COLOR_LAYERS:
break
else:
print(" Baking crappy vertex color lighting...")
bpy.ops.object.plasma_vertexlight_autobake()
def _find_create_dspan(self, bo, hsgmat, pass_index): def _find_create_dspan(self, bo, hsgmat, pass_index):
location = self._mgr.get_location(bo) location = self._mgr.get_location(bo)
if location not in self._dspans: if location not in self._dspans:

51
korman/operators/op_lightmap.py

@ -16,14 +16,20 @@
import bpy import bpy
from ..helpers import GoodNeighbor from ..helpers import GoodNeighbor
class _LightmapOperator: class _LightingOperator:
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
if context.object is not None: if context.object is not None:
return context.scene.render.engine == "PLASMA_GAME" return context.scene.render.engine == "PLASMA_GAME"
def _hide_textures(self, mesh, toggle):
for mat in mesh.materials:
for tex in mat.texture_slots:
if tex is not None and tex.use:
toggle.track(tex, "use", False)
class LightmapAutobakeOperator(_LightmapOperator, bpy.types.Operator): class LightmapAutobakeOperator(_LightingOperator, bpy.types.Operator):
bl_idname = "object.plasma_lightmap_autobake" bl_idname = "object.plasma_lightmap_autobake"
bl_label = "Bake Lightmap" bl_label = "Bake Lightmap"
bl_options = {"INTERNAL"} bl_options = {"INTERNAL"}
@ -76,10 +82,9 @@ class LightmapAutobakeOperator(_LightmapOperator, bpy.types.Operator):
toggle.track(render, "bake_type", "FULL") toggle.track(render, "bake_type", "FULL")
toggle.track(render, "use_bake_to_vertex_color", False) toggle.track(render, "use_bake_to_vertex_color", False)
for mat in obj.data.materials: # If we run a full render with our textures enabled, guess what we will get in our LM?
for tex in mat.texture_slots: # Yeah, textures. Mutter mutter mutter.
if tex is not None and tex.use: self._hide_textures(obj.data, toggle)
toggle.track(tex, "use", False)
# Now, we *finally* bake the lightmap... # Now, we *finally* bake the lightmap...
# FIXME: Don't bake Plasma RT lights # FIXME: Don't bake Plasma RT lights
@ -89,7 +94,7 @@ class LightmapAutobakeOperator(_LightmapOperator, bpy.types.Operator):
return {"FINISHED"} return {"FINISHED"}
class LightmapAutobakePreviewOperator(_LightmapOperator, bpy.types.Operator): class LightmapAutobakePreviewOperator(_LightingOperator, bpy.types.Operator):
bl_idname = "object.plasma_lightmap_preview" bl_idname = "object.plasma_lightmap_preview"
bl_label = "Preview Lightmap" bl_label = "Preview Lightmap"
bl_options = {"INTERNAL"} bl_options = {"INTERNAL"}
@ -104,3 +109,35 @@ class LightmapAutobakePreviewOperator(_LightmapOperator, bpy.types.Operator):
tex.image = bpy.data.images["{}_LIGHTMAPGEN".format(context.active_object.name)] tex.image = bpy.data.images["{}_LIGHTMAPGEN".format(context.active_object.name)]
return {"FINISHED"} return {"FINISHED"}
class VertexColorLightingOperator(_LightingOperator, bpy.types.Operator):
bl_idname = "object.plasma_vertexlight_autobake"
bl_label = "Bake Vertex Color Lighting"
bl_options = {"INTERNAL"}
def execute(self, context):
with GoodNeighbor() as toggle:
mesh = context.active_object.data
mesh.update()
# Find the "autocolor" vertex color layer
autocolor = mesh.vertex_colors.get("autocolor")
if autocolor is None:
mesh.vertex_colors.new("autocolor")
toggle.track(mesh.vertex_colors, "active", autocolor)
# Prepare to bake...
self._hide_textures(mesh, toggle)
# TODO: don't bake runtime lights
# Bake settings
render = context.scene.render
toggle.track(render, "bake_type", "FULL")
toggle.track(render, "use_bake_to_vertex_color", True)
# Bake
bpy.ops.object.bake_image()
# And done!
return {"FINISHED"}

Loading…
Cancel
Save