Source code for plato.draw.fresnel.Scene

import fresnel
import numpy as np
import rowan

from ... import draw

[docs]class Scene(draw.Scene): __doc__ = (draw.Scene.__doc__ or '') + """ This Scene supports the following features: * *antialiasing*: Enable antialiasing, for the preview tracer only. This uses fresnel's aa_level=3 if set, 0 otherwise. * *pathtracer*: Enable the path tracer. Accepts parameter ``samples`` with default value 64. * *directional_light*: Add directional lights. The given vector(s) indicates the light direction. The length of the vector(s) determines the magnitude of the light(s). * *ambient_light*: Enable ambient lighting. The given value indicates the magnitude of the light. """ def __init__(self, *args, tracer_kwargs={}, **kwargs): super(Scene, self).__init__(*args, **kwargs) self._device = fresnel.Device() self._fresnel_scene = fresnel.Scene(device=self._device) default_size = self.size_pixels.astype(np.uint32) self._preview_tracer = fresnel.tracer.Preview( device=self._device, w=default_size[0], h=default_size[1]) self._path_tracer = fresnel.tracer.Path( device=self._device, w=default_size[0], h=default_size[1]) self._geometries = [] self._output = None
[docs] def show(self): """Render the scene to an image and display using IPython.""" import IPython if self._output is None: self.render() IPython.display.display(self._output, display_id=str(id(self)))
[docs] def save(self, filename): """Render and save an image of this Scene. :param filename: target filename to save the image into """ try: import PIL except ImportError: raise RuntimeError('Could not import PIL. PIL (pillow) is required to save fresnel images.') else: if self._output is None: self.render() image = PIL.Image.fromarray(self._output[:], mode='RGBA') image.save(filename)
[docs] def render(self): """Render this Scene object.""" # Remove existing fresnel geometries from the scene for geometry in self._geometries: geometry.remove() # Clear the list of fresnel geometries self._geometries = [] # Add fresnel scene geometries from plato scene primitives for prim in self._primitives: geometry = prim.render(self._fresnel_scene) self._geometries.append(geometry) # Set up the camera camera_up = rowan.rotate(rowan.conjugate(self.rotation), [0, 1, 0]) camera_position = rowan.rotate(rowan.conjugate(self.rotation), -self.translation) camera_look_at = camera_position + rowan.rotate(rowan.conjugate(self.rotation), [0, 0, -1]) camera_height = self.size[1]/self.zoom self._fresnel_scene.camera = fresnel.camera.orthographic( position=camera_position, look_at=camera_look_at, up=camera_up, height=camera_height) # Set up lights lights = [] if 'ambient_light' in self.enabled_features: config = self.get_feature_config('ambient_light') magnitude = config.get('value', 0.25) if magnitude > 0: lights.append(fresnel.light.Light(direction=(0, 0, 1), color=(magnitude, magnitude, magnitude), theta=np.pi)) if 'directional_light' in self.enabled_features: config = self.get_feature_config('directional_light') directions = config.get('value', (.25, .5, -1)) directions = np.atleast_2d(directions).astype(np.float32) for direction in directions: magnitude = np.linalg.norm(direction) if magnitude > 0: lights.append(fresnel.light.Light(direction=-direction, color=(magnitude, magnitude, magnitude), theta=0.7)) if len(lights) > 0: self._fresnel_scene.lights = lights # Set up tracer if 'pathtracer' in self.enabled_features: # Use path tracer if enabled config = self.get_feature_config('pathtracer') tracer = self._path_tracer samples = config.get('samples', 64) def render_function(scene, **kwargs): return tracer.sample(scene, samples, **kwargs) else: # Use preview tracer by default tracer = self._preview_tracer tracer.aa_level = 3 if 'antialiasing' in self.enabled_features else 0 render_function = tracer.render self._output = render_function(self._fresnel_scene)
def _ipython_display_(self): return self.show()