125 lines
3.8 KiB
Python
125 lines
3.8 KiB
Python
import bpy
|
|
|
|
from math import degrees, sin, asin, tan, atan
|
|
from mathutils import Vector, Matrix
|
|
|
|
from .util import escape_name, mat2str, ExportCancelled
|
|
|
|
class World:
|
|
def __init__(self, render_engine, depsgraph):
|
|
scene = depsgraph.scene
|
|
self.background_shader = BackgroundShader(render_engine, scene.world)
|
|
|
|
|
|
def take_sample(self, render_engine, depsgraph, time):
|
|
if render_engine.test_break():
|
|
raise ExportCancelled()
|
|
self.background_shader.take_sample(render_engine, depsgraph, time)
|
|
|
|
def cleanup(self):
|
|
pass
|
|
|
|
def export(self, render_engine, w):
|
|
w.write("World {\n")
|
|
w.indent()
|
|
|
|
self.background_shader.export(render_engine, w)
|
|
|
|
w.unindent()
|
|
w.write("}\n")
|
|
|
|
|
|
class Camera:
|
|
def __init__(self, render_engine, ob, aspect_ratio):
|
|
self.ob = ob
|
|
self.aspect_ratio = aspect_ratio
|
|
|
|
self.fovs = []
|
|
self.aperture_radii = []
|
|
self.focal_distances = []
|
|
self.xforms = []
|
|
|
|
def take_sample(self, render_engine, depsgraph, time):
|
|
render_engine.update_stats("", "Psychopath: Collecting '{}' at time {}".format(self.ob.name, time))
|
|
|
|
# Fov.
|
|
# TODO: account for the various ways sensor size can be specified.
|
|
x_extent = depsgraph.scene.render.resolution_x / depsgraph.scene.render.pixel_aspect_x
|
|
y_extent = depsgraph.scene.render.resolution_y / depsgraph.scene.render.pixel_aspect_y
|
|
aspect_ratio = x_extent / y_extent
|
|
if aspect_ratio >= 1.0:
|
|
self.fovs += [degrees(self.ob.data.angle_x)]
|
|
else:
|
|
self.fovs += [degrees(2.0 * atan(tan(self.ob.data.angle_x * 0.5) * aspect_ratio))]
|
|
|
|
if self.ob.data.dof.use_dof:
|
|
# Aperture radius.
|
|
radius = self.ob.data.lens / 2000.0 / self.ob.data.dof.aperture_fstop
|
|
self.aperture_radii += [radius]
|
|
|
|
# Dof distance
|
|
if self.ob.data.dof.focus_object == None:
|
|
self.focal_distances += [self.ob.data.dof.focus_distance]
|
|
else:
|
|
# TODO: implement DoF object tracking here
|
|
self.focal_distances += [0.0]
|
|
print("WARNING: DoF object tracking not yet implemented.")
|
|
else:
|
|
self.aperture_radii += [0.0]
|
|
self.focal_distances += [1.0]
|
|
|
|
# Transform
|
|
mat = self.ob.matrix_world.copy()
|
|
matz = Matrix()
|
|
matz[2][2] = -1
|
|
self.xforms += [(mat @ matz).inverted()]
|
|
|
|
def cleanup(self):
|
|
pass
|
|
|
|
def export(self, render_engine, w):
|
|
render_engine.update_stats("", "Psychopath: Exporting %s" % self.ob.name)
|
|
w.write("Camera {\n")
|
|
w.indent()
|
|
|
|
for fov in self.fovs:
|
|
w.write("Fov [%f]\n" % fov)
|
|
|
|
for rad in self.aperture_radii:
|
|
w.write("ApertureRadius [%f]\n" % rad)
|
|
|
|
for dist in self.focal_distances:
|
|
w.write("FocalDistance [%f]\n" % dist)
|
|
|
|
for mat in self.xforms:
|
|
w.write("Transform [%s]\n" % mat2str(mat))
|
|
|
|
w.unindent()
|
|
w.write("}\n")
|
|
|
|
|
|
class BackgroundShader:
|
|
def __init__(self, render_engine, world):
|
|
self.world = world
|
|
self.color = []
|
|
|
|
def take_sample(self, render_engine, depsgraph, time):
|
|
if self.world != None:
|
|
self.color += [(
|
|
self.world.psychopath.background_color[0],
|
|
self.world.psychopath.background_color[1],
|
|
self.world.psychopath.background_color[2],
|
|
)]
|
|
|
|
def export(self, render_engine, w):
|
|
if self.world != None:
|
|
w.write("BackgroundShader {\n")
|
|
w.indent();
|
|
w.write("Type [Color]\n")
|
|
for c in self.color:
|
|
w.write("Color [rec709, %f %f %f]\n" % c)
|
|
w.unindent()
|
|
w.write("}\n")
|
|
|
|
|