psychopath/psychoblend/objects.py

207 lines
8.3 KiB
Python

import bpy
from .util import escape_name, mat2str, needs_def_mb, needs_xform_mb, ExportCancelled
from mathutils import Vector, Matrix
def make_object_data_cache(render_engine, depsgraph, ob, name):
if ob.type == 'MESH':
return Mesh(render_engine, depsgraph, ob, name)
elif ob.type == 'LIGHT':
if ob.data.type == 'POINT':
return SphereLamp(render_engine, depsgraph, ob, name)
elif ob.data.type == 'AREA':
return RectLamp(render_engine, depsgraph, ob, name)
elif ob.data.type == 'AREA':
return RectLamp(render_engine, depsgraph, ob, name)
class Mesh:
""" Holds data for a mesh to be exported.
"""
def __init__(self, render_engine, depsgraph, ob, name):
self.name = name
self.material_name = None
if len(ob.material_slots) >= 1 and ob.material_slots[0].material != None:
self.material_name = ob.material_slots[0].material.name
self.is_subdiv = ob.data.psychopath.is_subdivision_surface
self.needs_mb = needs_def_mb(ob)
self.time_meshes = []
def take_sample(self, render_engine, depsgraph, ob, time):
if len(self.time_meshes) == 0 or self.needs_mb:
render_engine.update_stats("", "Psychopath: Collecting '{}' at time {}".format(self.name, time))
self.time_meshes += [ob.to_mesh(depsgraph=depsgraph).copy()]
def cleanup(self):
for mesh in self.time_meshes:
bpy.data.meshes.remove(mesh)
def export(self, render_engine, w):
render_engine.update_stats("", "Psychopath: Exporting %s" % self.name)
if self.is_subdiv == False:
# Exporting normal mesh
w.write("MeshSurface $%s {\n" % escape_name(self.name))
w.indent()
else:
# Exporting subdivision surface cage
w.write("SubdivisionSurface $%s {\n" % escape_name(self.name))
w.indent()
# Material bindings.
if self.material_name != None:
w.write("SurfaceShaderBind [${}]\n".format(escape_name(self.material_name)))
# Write vertices and (if it's smooth shaded) normals
for ti in range(len(self.time_meshes)):
w.write("Vertices [")
w.write(" ".join([("%f" % i) for vert in self.time_meshes[ti].vertices for i in vert.co]), False)
w.write("]\n", False)
if self.time_meshes[0].polygons[0].use_smooth and self.is_subdiv == False:
w.write("Normals [")
w.write(" ".join([("%f" % i) for vert in self.time_meshes[ti].vertices for i in vert.normal]), False)
w.write("]\n", False)
# Write face vertex counts
w.write("FaceVertCounts [")
w.write(" ".join([("%d" % len(p.vertices)) for p in self.time_meshes[0].polygons]), False)
w.write("]\n", False)
# Write face vertex indices
w.write("FaceVertIndices [")
w.write(" ".join([("%d"%v) for p in self.time_meshes[0].polygons for v in p.vertices]), False)
w.write("]\n", False)
# MeshSurface/SubdivisionSurface section end
w.unindent()
w.write("}\n")
class SphereLamp:
""" Holds data for a sphere light to be exported.
"""
def __init__(self, render_engine, depsgraph, ob, name):
self.name = name
self.time_col = []
self.time_rad = []
def take_sample(self, render_engine, depsgraph, ob, time):
render_engine.update_stats("", "Psychopath: Collecting '{}' at time {}".format(ob.name, time))
if ob.data.psychopath.color_type == 'Rec709':
self.time_col += [('Rec709', ob.data.color * ob.data.energy)]
elif ob.data.psychopath.color_type == 'Blackbody':
self.time_col += [('Blackbody', ob.data.psychopath.color_blackbody_temp, ob.data.energy)]
elif ob.data.psychopath.color_type == 'ColorTemperature':
self.time_col += [('ColorTemperature', ob.data.psychopath.color_blackbody_temp, ob.data.energy)]
self.time_rad += [ob.data.shadow_soft_size]
def cleanup(self):
pass
def export(self, render_engine, w):
render_engine.update_stats("", "Psychopath: Exporting %s" % self.name)
w.write("SphereLight $%s {\n" % escape_name(self.name))
w.indent()
for col in self.time_col:
if col[0] == 'Rec709':
w.write("Color [rec709, %f %f %f]\n" % (col[1][0], col[1][1], col[1][2]))
elif col[0] == 'Blackbody':
w.write("Color [blackbody, %f %f]\n" % (col[1], col[2]))
elif col[0] == 'ColorTemperature':
w.write("Color [color_temperature, %f %f]\n" % (col[1], col[2]))
for rad in self.time_rad:
w.write("Radius [%f]\n" % rad)
w.unindent()
w.write("}\n")
class RectLamp:
""" Holds data for a rectangular light to be exported.
"""
def __init__(self, render_engine, depsgraph, ob, name):
self.name = name
self.time_col = []
self.time_dim = []
def take_sample(self, render_engine, depsgraph, ob, time):
render_engine.update_stats("", "Psychopath: Collecting '{}' at time {}".format(self.name, time))
if ob.data.psychopath.color_type == 'Rec709':
self.time_col += [('Rec709', ob.data.color * ob.data.energy)]
elif ob.data.psychopath.color_type == 'Blackbody':
self.time_col += [('Blackbody', ob.data.psychopath.color_blackbody_temp, ob.data.energy)]
elif ob.data.psychopath.color_type == 'ColorTemperature':
self.time_col += [('ColorTemperature', ob.data.psychopath.color_blackbody_temp, ob.data.energy)]
if ob.data.shape == 'RECTANGLE':
self.time_dim += [(ob.data.size, ob.data.size_y)]
else:
self.time_dim += [(ob.data.size, ob.data.size)]
def cleanup(self):
pass
def export(self, render_engine, w):
render_engine.update_stats("", "Psychopath: Exporting %s" % self.name)
w.write("RectangleLight $%s {\n" % escape_name(self.name))
w.indent()
for col in self.time_col:
if col[0] == 'Rec709':
w.write("Color [rec709, %f %f %f]\n" % (col[1][0], col[1][1], col[1][2]))
elif col[0] == 'Blackbody':
w.write("Color [blackbody, %f %f]\n" % (col[1], col[2]))
elif col[0] == 'ColorTemperature':
w.write("Color [color_temperature, %f %f]\n" % (col[1], col[2]))
for dim in self.time_dim:
w.write("Dimensions [%f %f]\n" % dim)
w.unindent()
w.write("}\n")
class DistantDiskLamp:
def __init__(self, render_engine, depsgraph, ob, name):
self.name = name
self.time_col = []
self.time_dir = []
self.time_rad = []
def take_sample(self, render_engine, depsgraph, ob, time):
render_engine.update_stats("", "Psychopath: Collecting '{}' at time {}".format(self.name, time))
self.time_dir += [tuple(ob.matrix_world.to_3x3() @ Vector((0, 0, -1)))]
if ob.data.psychopath.color_type == 'Rec709':
self.time_col += [('Rec709', ob.data.color * ob.data.energy)]
elif ob.data.psychopath.color_type == 'Blackbody':
self.time_col += [('Blackbody', ob.data.psychopath.color_blackbody_temp, ob.data.energy)]
elif ob.data.psychopath.color_type == 'ColorTemperature':
self.time_col += [('ColorTemperature', ob.data.psychopath.color_blackbody_temp, ob.data.energy)]
self.time_rad += [ob.data.shadow_soft_size]
def cleanup(self):
pass
def export(self, render_engine, w):
render_engine.update_stats("", "Psychopath: Exporting %s" % escape_name(self.name))
w.write("DistantDiskLight $%s {\n" % self.name)
w.indent()
for direc in self.time_dir:
w.write("Direction [%f %f %f]\n" % (direc[0], direc[1], direc[2]))
for col in self.time_col:
if col[0] == 'Rec709':
w.write("Color [rec709, %f %f %f]\n" % (col[1][0], col[1][1], col[1][2]))
elif col[0] == 'Blackbody':
w.write("Color [blackbody, %f %f]\n" % (col[1], col[2]))
elif col[0] == 'ColorTemperature':
w.write("Color [color_temperature, %f %f]\n" % (col[1], col[2]))
for rad in self.time_rad:
w.write("Radius [%f]\n" % rad)
w.unindent()
w.write("}\n")