import math import os from pathlib import Path import sys from direct.showbase.ShowBase import ShowBase import panda3d.core as p3d import simplepbr p3d.load_prc_file_data( '', 'window-size 1024 768\n' 'texture-minfilter mipmap\n' 'texture-anisotropic-degree 16\n' 'notify-level-simplepbr info\n' 'show-frame-rate-meter true\n' 'frame-rate-meter-milliseconds true\n' 'gl-version 3 2\n' 'gl-debug t\n' ) class App(ShowBase): def __init__(self): if len(sys.argv) < 2: print("Missing input file") sys.exit(1) super().__init__() cubemap_path = Path(__file__).parent / 'hdri' / '512_cg_#.hdr' # cubemap_path = p3d.Filename.from_os_specific( # os.path.join(os.path.dirname(__file__), '..', 'cubemap.env') # ) self.env_map = simplepbr.EnvPool.ptr().load( cubemap_path, # prefiltered_size=256, # prefiltered_samples=16 ) # self.env_map = simplepbr.EnvMap.from_file_path(cubemap_path) self.pipeline = simplepbr.init( # env_map=self.env_map, use_normal_maps=True, ) self.set_background_color(0, 0, 0, 1) infile = p3d.Filename.from_os_specific(os.path.abspath(sys.argv[1])) p3d.get_model_path().prepend_directory(infile.get_dirname()) # self.skybox = simplepbr.utils.make_skybox(self.env_map.filtered_env_map) # self.skybox.reparent_to(self.render) self.model_root = self.loader.load_model(infile, noCache=True) self.accept('escape', sys.exit) self.accept('q', sys.exit) self.accept('w', self.toggle_wireframe) self.accept('t', self.toggle_texture) self.accept('n', self.toggle_normal_maps) self.accept('e', self.toggle_emission_maps) self.accept('o', self.toggle_occlusion_maps) self.accept('a', self.toggle_ambient_light) self.accept('i', self.toggle_ibl) # self.accept('b', self.toggle_calc_binormals) self.accept('shift-l', self.model_root.ls) self.accept('shift-a', self.model_root.analyze) self.model_root.reparent_to(self.render) bounds = self.model_root.getBounds() center = bounds.get_center() if bounds.is_empty(): radius = 1 else: radius = bounds.get_radius() fov = self.camLens.get_fov() distance = radius / math.tan(math.radians(min(fov[0], fov[1]) / 2.0)) self.camLens.set_near(min(self.camLens.get_default_near(), radius / 2)) self.camLens.set_far(max(self.camLens.get_default_far(), distance + radius * 2)) trackball = self.trackball.node() trackball.set_origin(center) trackball.set_pos(0, distance, 0) trackball.setForwardScale(distance * 0.006) # Create a light if the model does not have one if not self.model_root.find('**/+Light'): self.light = self.render.attach_new_node(p3d.PointLight('light')) self.light.set_pos(0, -distance, distance) self.render.set_light(self.light) # Move lights to render self.model_root.clear_light() for light in self.model_root.find_all_matches('**/+Light'): light.parent.wrt_reparent_to(self.render) self.render.set_light(light) # Add some ambient light self.ambient = self.render.attach_new_node(p3d.AmbientLight('ambient')) self.ambient.node().set_color((.1, .1, .1, 1)) self.render.set_light(self.ambient) if self.model_root.find('**/+Character'): self.anims = p3d.AnimControlCollection() p3d.autoBind(self.model_root.node(), self.anims, ~0) if self.anims.get_num_anims() > 0: self.anims.get_anim(0).loop(True) def toggle_normal_maps(self): self.pipeline.use_normal_maps = not self.pipeline.use_normal_maps def toggle_emission_maps(self): self.pipeline.use_emission_maps = not self.pipeline.use_emission_maps def toggle_occlusion_maps(self): self.pipeline.use_occlusion_maps = not self.pipeline.use_occlusion_maps def toggle_ambient_light(self): if self.render.has_light(self.ambient): self.render.clear_light(self.ambient) else: self.render.set_light(self.ambient) def toggle_ibl(self): if self.pipeline.env_map: self.pipeline.env_map = None else: self.pipeline.env_map = self.env_map def toggle_calc_binormals(self): self.pipeline.calculate_binormals = not self.pipeline.calculate_binormals def main(): App().run() if __name__ == '__main__': main()