175 lines
5.5 KiB
Python
175 lines
5.5 KiB
Python
"""
|
|
|
|
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()
|