toolkit/render_service/service.py
"""
Render service to render previews of materials
"""
from __future__ import print_function
import sys
import socket
import time
import pickle
from threading import Thread
from panda3d.core import load_prc_file_data, Filename, Mat4
from panda3d.core import CS_zup_right, CS_yup_right, BamCache
from direct.showbase.ShowBase import ShowBase
sys.path.insert(0, "../../")
from rpcore import RenderPipeline, PointLight # noqa
class Application(ShowBase):
ICOMING_PORT = 62360
def __init__(self):
load_prc_file_data("", "win-size 512 512")
load_prc_file_data("", "window-type offscreen")
load_prc_file_data("", "model-cache-dir")
load_prc_file_data("", "model-cache-textures #f")
load_prc_file_data("", "textures-power-2 none")
load_prc_file_data("", "alpha-bits 0")
load_prc_file_data("", "print-pipe-types #f")
# Construct render pipeline
self.render_pipeline = RenderPipeline()
self.render_pipeline.mount_mgr.config_dir = "config/"
self.render_pipeline.create(self)
self.setup_scene()
# Disable model caching
BamCache.get_global_ptr().cache_models = False
self.update_queue = []
self.start_listen()
# Render initial frames
for i in range(10):
self.taskMgr.step()
last_update = 0.0
self.scene_node = None
# Wait for updates
while True:
# Update once in a while
curr_time = time.time()
if curr_time > last_update + 1.0:
last_update = curr_time
self.taskMgr.step()
if self.update_queue:
if self.scene_node:
self.scene_node.remove_node()
# Only take the latest packet
payload = self.update_queue.pop(0)
print("RENDERING:", payload)
scene = self.loader.loadModel(Filename.from_os_specific(payload["scene"]))
for light in scene.find_all_matches("**/+PointLight"):
light.remove_node()
for light in scene.find_all_matches("**/+Spotlight"):
light.remove_node()
# Find camera
main_cam = scene.find("**/Camera")
if main_cam:
transform_mat = main_cam.get_transform(self.render).get_mat()
transform_mat = Mat4.convert_mat(CS_zup_right, CS_yup_right) * transform_mat
self.camera.set_mat(transform_mat)
else:
print("WARNING: No camera found")
self.camera.set_pos(0, -3.5, 0)
self.camera.look_at(0, -2.5, 0)
self.camLens.set_fov(64.0)
self.scene_node = scene
scene.reparent_to(self.render)
# Render scene
for i in range(8):
self.taskMgr.step()
dest_path = Filename.from_os_specific(payload["dest"])
print("Saving screenshot to", dest_path)
self.win.save_screenshot(dest_path)
self.notify_about_finish(int(payload["pingback_port"]))
def start_listen(self):
""" Starts the listener thread """
thread = Thread(target=self.listener_thread, args=(), name="ListenerThread")
thread.setDaemon(True)
thread.start()
return thread
def listener_thread(self):
""" Thread which listens to incoming updates """
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
print("Listening on 127.0.0.1:" + str(self.ICOMING_PORT))
try:
sock.bind(("127.0.0.1", self.ICOMING_PORT))
while True:
data, addr = sock.recvfrom(8192)
self.handle_data(data)
except Exception as msg:
print("Failed to bind to address! Reason:", msg)
finally:
sock.close()
def handle_data(self, data):
""" Handles a new update """
# print("Got:", data)
unpacked_data = pickle.loads(data)
# print("Data = ", unpacked_data)
self.update_queue.append(unpacked_data)
def notify_about_finish(self, port):
""" Notifies the caller that the result finished """
print("Sending finish result to localhost:" + str(port))
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
try:
sock.connect(("localhost", port))
except Exception as msg:
print("Could not send finish result: ", msg)
return
sock.sendall(b"done")
print("Sent done flag.")
sock.close()
def setup_scene(self):
""" Setups the basic scene geometry """
self.disableMouse()
self.render2d.hide()
self.aspect2d.hide()
light = PointLight()
light.pos = 20.0, -0.85, -1.31
light.radius = 100.0
light.energy = 2500
light.set_color_from_temperature(8000)
# self.render_pipeline.add_light(light)
light = PointLight()
light.pos = -11.2, -13.84, -9.24
light.radius = 1e20
light.set_color_from_temperature(8000)
light.energy = 2500
# self.render_pipeline.add_light(light)
# envprobe = self.render_pipeline.add_environment_probe()
# envprobe.set_pos(0, -16.2, 4.4)
# envprobe.set_scale(40, 40, 40)
# envprobe.parallax_correction = False
Application()