def __init__(self, modelpath=None): super().__init__() self.synchronize = True self._modelpath = modelpath if modelpath else '' if modelpath is not None: self.nodepath = base.loader.loadModel(modelpath) else: self.nodepath = p3d.NodePath(p3d.PandaNode('node'))
def init_components(self, components): for comp in components[pcomps.NodePathComponent]: comp.nodepath = p3d.NodePath(p3d.PandaNode(comp.name)) if comp.parent is not None: comp.nodepath.reparent_to(comp.parent) for comp in components[pcomps.StaticMeshComponent]: nodepath = self.get_nodepath(comp) comp.model = p3d.NodePath(p3d.Loader().get_global_ptr().load_sync( comp.modelpath)) comp.model.reparent_to(nodepath)
def addFirefly(self): pos1 = p3dc.LPoint3(random.uniform(-50, 50), random.uniform(-100, 150), random.uniform(-10, 80)) dir = p3dc.LVector3(random.uniform(-1, 1), random.uniform(-1, 1), random.uniform(-1, 1)) dir.normalize() pos2 = pos1 + (dir * 20) fly = self.lightroot.attachNewNode(p3dc.PandaNode("fly")) glow = fly.attachNewNode(p3dc.PandaNode("glow")) dot = fly.attachNewNode(p3dc.PandaNode("dot")) color_r = 1.0 color_g = random.uniform(0.8, 1.0) color_b = min(color_g, random.uniform(0.5, 1.0)) fly.setColor(color_r, color_g, color_b, 1.0) fly.setShaderInput("lightcolor", (color_r, color_g, color_b, 1.0)) int1 = fly.posInterval(random.uniform(7, 12), pos1, pos2) int2 = fly.posInterval(random.uniform(7, 12), pos2, pos1) si1 = fly.scaleInterval(random.uniform(0.8, 1.5), p3dc.LPoint3(0.2, 0.2, 0.2), p3dc.LPoint3(0.2, 0.2, 0.2)) si2 = fly.scaleInterval(random.uniform(1.5, 0.8), p3dc.LPoint3(1.0, 1.0, 1.0), p3dc.LPoint3(0.2, 0.2, 0.2)) si3 = fly.scaleInterval(random.uniform(1.0, 2.0), p3dc.LPoint3(0.2, 0.2, 0.2), p3dc.LPoint3(1.0, 1.0, 1.0)) siseq = Sequence(si1, si2, si3) siseq.loop() siseq.setT(random.uniform(0, 1000)) seq = Sequence(int1, int2) seq.loop() self.spheremodel.instanceTo(glow) self.firefly.instanceTo(dot) glow.setScale(self.fireflysize * 1.1) glow.hide(p3dc.BitMask32(self.modelMask | self.plainMask)) dot.hide(p3dc.BitMask32(self.modelMask | self.lightMask)) dot.setColor(color_r, color_g, color_b, 1.0) self.fireflies.append(fly) self.sequences.append(seq) self.glowspheres.append(glow) self.scaleseqs.append(siseq)
def makeForrest(self): self.forest = p3dc.NodePath(p3dc.PandaNode("Forest Root")) self.forest.reparentTo(render()) #self.forest.hide(p3dc.BitMask32(self.lightMask | self.plainMask)) loader().loadModel([ "fireflies_models/background", "fireflies_models/foliage01", "fireflies_models/foliage02", "fireflies_models/foliage03", "fireflies_models/foliage04", "fireflies_models/foliage05", "fireflies_models/foliage06", "fireflies_models/foliage07", "fireflies_models/foliage08", "fireflies_models/foliage09" ], callback=self.finishLoadingForrest)
def __init__(self, modelpath=None, parent=None, filter=None): super().__init__() self._modelpath = modelpath if modelpath else '' if modelpath is not None: np = base.loader.loadModel(modelpath) if filter is not None: np = np.find(filter) #TODO error handling self.nodepath = np else: self.nodepath = p3d.NodePath(p3d.PandaNode('node')) if parent is not None: self.nodepath.reparent_to(parent)
def test_property(): # This is a property defined by MAKE_PROPERTY. np = core.PandaNode("") # Getter transform = np.get_transform() assert transform == np.transform # Setter new_transform = transform.set_pos((1, 0, 0)) np.transform = new_transform assert np.transform == new_transform # Invalid assignments with pytest.raises(TypeError): np.transform = None with pytest.raises(TypeError): np.transform = "nonsense" with pytest.raises(TypeError): del np.transform
def __init__( self, camera_collection: cameras.Cameras, tile_manager: manager.Manager, start_tile: int, sky_offsets: typing.List[int], ): camera = camera_collection.make_gui_camera("sky") camera.display_region.set_sort(constants.BACK_MOST) camera.display_region.set_active(True) display_node = core.PandaNode("sky") self._display: core.NodePath = core.NodePath(display_node) camera.camera_node.set_scene(self._display) textures = [ tile_manager.get_tile(start_tile + offset, 0) for offset in sky_offsets ] width = 2 / len(textures) card_maker = core.CardMaker("sky_part") card_maker.set_frame(-1, -1 + width, 1, -1) card_node = card_maker.generate() card: core.NodePath = self._display.attach_new_node(card_node) card.set_bin("fixed", constants.BACK_MOST) card.set_depth_write(False) card.set_two_sided(True) left = 0.0 for texture_index, texture in enumerate(textures): sky_part = self._display.attach_new_node(f"sky_{texture_index}") card.copy_to(sky_part) card.set_texture(texture, 1) sky_part.set_x(left) left += width card.remove_node()
def __init__(self): # Preliminary capabilities check. if not ape.base().win.getGsg().getSupportsBasicShaders(): self.t = addTitle( "Shadow Demo: Video driver reports that shaders are not supported." ) return if not ape.base().win.getGsg().getSupportsDepthTexture(): self.t = addTitle( "Shadow Demo: Video driver reports that depth textures are not supported." ) return self.inst_p = addInstructions(0.06, 'P : stop/start the Panda Rotation') self.inst_w = addInstructions(0.12, 'W : stop/start the Walk Cycle') self.inst_t = addInstructions(0.18, 'T : stop/start the Teapot') self.inst_l = addInstructions(0.24, 'L : move light source far or close') self.inst_v = addInstructions(0.30, 'V : View the Depth-Texture results') self.inst_u = addInstructions(0.36, 'U : toggle updating the shadow map') self.inst_x = addInstructions( 0.42, 'Left/Right Arrow : switch camera angles') ape.base().setBackgroundColor(0, 0, 0.2, 1) ape.base().camLens.setNearFar(1.0, 10000) ape.base().camLens.setFov(75) ape.base().disableMouse() # Load the scene. floorTex = ape.loader().loadTexture('maps/envir-ground.jpg') cm = p3dc.CardMaker('') cm.setFrame(-2, 2, -2, 2) floor = ape.render().attachNewNode(p3dc.PandaNode("floor")) for y in range(12): for x in range(12): nn = floor.attachNewNode(cm.generate()) nn.setP(-90) nn.setPos((x - 6) * 4, (y - 6) * 4, 0) floor.setTexture(floorTex) floor.flattenStrong() self.pandaAxis = ape.render().attachNewNode('panda axis') self.pandaModel = Actor('panda-model', {'walk': 'panda-walk4'}) self.pandaModel.reparentTo(self.pandaAxis) self.pandaModel.setPos(9, 0, 0) self.pandaModel.setScale(0.01) self.pandaWalk = self.pandaModel.actorInterval('walk', playRate=1.8) self.pandaWalk.loop() self.pandaMovement = self.pandaAxis.hprInterval( 20.0, p3dc.LPoint3(-360, 0, 0), startHpr=p3dc.LPoint3(0, 0, 0)) self.pandaMovement.loop() self.teapot = ape.loader().loadModel('teapot') self.teapot.reparentTo(ape.render()) self.teapot.setPos(0, -20, 10) self.teapotMovement = self.teapot.hprInterval( 50, p3dc.LPoint3(0, 360, 360)) self.teapotMovement.loop() self.accept('escape', sys.exit) self.accept("arrow_left", self.incrementCameraPosition, [-1]) self.accept("arrow_right", self.incrementCameraPosition, [1]) self.accept("p", self.toggleInterval, [self.pandaMovement]) self.accept("t", self.toggleInterval, [self.teapotMovement]) self.accept("w", self.toggleInterval, [self.pandaWalk]) self.accept("v", ape.base().bufferViewer.toggleEnable) self.accept("u", self.toggleUpdateShadowMap) self.accept("l", self.incrementLightPosition, [1]) self.accept("o", ape.base().oobe) self.light = ape.render().attachNewNode(p3dc.Spotlight("Spot")) self.light.node().setScene(ape.render()) self.light.node().setShadowCaster(True) self.light.node().showFrustum() self.light.node().getLens().setFov(40) self.light.node().getLens().setNearFar(10, 100) ape.render().setLight(self.light) self.alight = ape.render().attachNewNode(p3dc.AmbientLight("Ambient")) self.alight.node().setColor(p3dc.LVector4(0.2, 0.2, 0.2, 1)) ape.render().setLight(self.alight) # Important! Enable the shader generator. ape.render().setShaderAuto() # default values self.cameraSelection = 0 self.lightSelection = 0 self.incrementCameraPosition(0) self.incrementLightPosition(0)
def setup_fafnir(self): self.fafnir_np = p3d.NodePath(p3d.PandaNode("Fafnir")) global_shader = p3d.Shader.load( p3d.Shader.SL_GLSL, vertex="shaders/build_mesh_cache.vs", geometry="shaders/build_mesh_cache.gs", fragment="shaders/generate_primary_intersections.fs", ) self.fafnir_np.set_shader(global_shader) self.mesh_cache = MeshCache(1, 1) self.material_cache = MaterialCache() self.draw_manager = DrawManager(self.fafnir_np) win_width = self.win.get_x_size() win_height = self.win.get_y_size() rtt_fb_prop = p3d.FrameBufferProperties() rtt_fb_prop.set_rgba_bits(32, 32, 32, 32) rtt_fb_prop.set_float_color(True) rtt_fb_prop.set_depth_bits(32) rtt_win_prop = p3d.WindowProperties().size(win_width, win_height) rtt_buffer = base.graphics_engine.make_output( base.pipe, 'Fafnir RTT Buffer', -100, rtt_fb_prop, rtt_win_prop, p3d.GraphicsPipe.BF_refuse_window, base.win.get_gsg(), base.win) intersection_texture = p3d.Texture() rtt_buffer.add_render_texture(intersection_texture, p3d.GraphicsOutput.RTM_bind_or_copy, p3d.GraphicsOutput.RTP_color) rtt_cam = base.make_camera(rtt_buffer) rtt_cam.reparent_to(self.fafnir_np) vdata = p3d.GeomVertexData('empty', p3d.GeomVertexFormat.get_empty(), p3d.GeomEnums.UH_static) resolve_shader = p3d.Shader.load( p3d.Shader.SL_GLSL, vertex='shaders/resolve_intersections.vs', fragment='shaders/resolve_intersections.fs') self.int_texture = intersection_texture self.draw_manager.set_inputs(self.int_texture, self.material_cache.count_texture) self.temp_nps = [] def cb_update_draw_calls(cbdata): for np in self.temp_nps: np.remove_node() self.temp_nps = [] tex = self.draw_manager._indirect_buffer gsg = self.win.get_gsg() if self.graphics_engine.extract_texture_data(tex, gsg): tex_view = memoryview(tex.get_ram_image()).cast('i') for call_idx in range(tex.get_x_size()): i = call_idx * 4 primcount = tex_view[i + 1] first = tex_view[i + 2] prims = p3d.GeomPoints(p3d.GeomEnums.UH_dynamic) prims.add_next_vertices(primcount) geom = p3d.Geom(vdata) geom.add_primitive(prims) geom.set_bounds(p3d.OmniBoundingVolume()) node = p3d.GeomNode('Draw Call {}'.format(call_idx)) node.add_geom(geom) path = p3d.NodePath(node) path.set_bin('fixed', 50) path.set_depth_test(False) path.set_depth_write(False) path.set_shader(resolve_shader) path.set_shader_input('first', first) window_size = p3d.LVector2i(win_width, win_height) path.set_shader_input('window_size', window_size) path.set_shader_input('vertex_cache', self.mesh_cache.vert_texture) path.set_shader_input('index_cache', self.mesh_cache.index_texture) path.set_shader_input('intersections', self.int_texture) self.material_cache.bind(path) path.reparent_to(self.render) self.temp_nps.append(path) cbdata.upcall() cbnode = p3d.CallbackNode('UpdateDrawCalls') cbnode.set_draw_callback( p3d.PythonCallbackObject(cb_update_draw_calls)) cb_np = self.render.attach_new_node(cbnode) cb_np.set_bin('fixed', 45) # taskMgr.add(task_update_draw_calls, 'Update Draw Calls', sort=55) def task_fafnir(task): # node_paths = self.fafnir_np.find_all_matches('**/+GeomNode') # self.material_list = self.fafnir_np.find_all_materials() # self.mesh_cache.update(self.node_paths) # self.mesh_cache.bind(self.fafnir_np) self.material_cache.update(self.material_list, self.node_paths) win_width = self.win.get_x_size() win_height = self.win.get_y_size() self.draw_manager.update(len(self.material_list), win_width, win_height) return task.cont taskMgr.add(task_fafnir, 'Gather mesh data') def read_texture(): tex = self.draw_manager._indirect_buffer gsg = self.win.get_gsg() if self.graphics_engine.extract_texture_data( tex, self.win.get_gsg()): view = memoryview(tex.get_ram_image()).cast('i') for i in range(16): if i % 4 == 0: print() print(view[i]) # success = tex.write(p3d.Filename('vertex_cache.png')) # print('Texture write: ', success) else: print('texture has no RAM image') self.accept('f1', read_texture)
def __init__(self, workingdir, conn_addr): ShowBase.__init__(self) self.view_lens = p3d.MatrixLens() self.cam = p3d.NodePath(p3d.Camera('view')) self.cam.node().set_lens(self.view_lens) self.cam.node().set_active(True) self.cam.reparent_to(self.render) self.pipe = p3d.GraphicsPipeSelection.get_global_ptr().make_module_pipe('pandagl') self.bg_color = p3d.LVecBase4(0.0, 0.0, 0.0, 1.0) p3d.get_model_path().prepend_directory(workingdir) self.workingdir = workingdir self.texture = p3d.Texture() self.win = None self.renderer = None self.make_offscreen(1, 1) self.disableMouse() self.setFrameRateMeter(True) self.image_width = 1 self.image_height = 1 self.image_data = struct.pack('=BBB', 0, 0, 0) self.scene = self.render.attach_new_node(p3d.PandaNode("Empty Scene")) self.connection = BlenderConnection(conn_addr) def set_bg_clear_color(task): # Keep bg color working even if DisplayRegions get switched around # (e.g., from FilterManager) for win in self.graphicsEngine.windows: for dispregion in win.display_regions: if dispregion.get_camera() == self.cam: dispregion.set_clear_color_active(True) dispregion.set_clear_color(self.bg_color) return task.cont self.taskMgr.add(set_bg_clear_color, 'Set BG Clear Color') def do_updates(task): if not self.connection.running: sys.exit() latest_scene_update = None for update in self.connection.get_updates(): # print('update: {}'.format(update)) update_type = update['type'] if update_type == 'view': self.update_view( update['width'], update['height'], self.load_matrix(update['projection_matrix']), self.load_matrix(update['view_matrix']), ) elif update_type == 'scene': latest_scene_update = update elif update_type == 'background_color': self.bg_color = p3d.LVector4(*update['color']) else: raise RuntimeError('Unknown update type: {}'.format(update_type)) if latest_scene_update is not None: self.update_scene(latest_scene_update['path']) return task.cont self.taskMgr.add(do_updates, 'Updates') def image_updates(task): if self.texture.has_ram_image(): #start = time.perf_counter() self.connection.send_image( self.texture.get_x_size(), self.texture.get_y_size(), memoryview(self.texture.get_ram_image_as('BGR')) ) #print('Extern: Updated image data in {}ms'.format((time.perf_counter() - start) * 1000)) return task.cont self.taskMgr.add(image_updates, 'Upload Images')
def __init__(self): # Preliminary capabilities check. if not ape.base().win.getGsg().getSupportsBasicShaders(): self.t = addTitle( "Shadow Demo: Video driver reports that shaders are not supported." ) return if not ape.base().win.getGsg().getSupportsDepthTexture(): self.t = addTitle( "Shadow Demo: Video driver reports that depth textures are not supported." ) return # creating the offscreen buffer. winprops = p3dc.WindowProperties(size=(512, 512)) props = p3dc.FrameBufferProperties() props.setRgbColor(1) props.setAlphaBits(1) props.setDepthBits(1) LBuffer = ape.base().graphicsEngine.makeOutput( ape.base().pipe, "offscreen buffer", -2, props, winprops, p3dc.GraphicsPipe.BFRefuseWindow, ape.base().win.getGsg(), ape.base().win) self.buffer = LBuffer if not LBuffer: self.t = addTitle( "Shadow Demo: Video driver cannot create an offscreen buffer.") return Ldepthmap = p3dc.Texture() LBuffer.addRenderTexture(Ldepthmap, p3dc.GraphicsOutput.RTMBindOrCopy, p3dc.GraphicsOutput.RTPDepthStencil) if ape.base().win.getGsg().getSupportsShadowFilter(): Ldepthmap.setMinfilter(p3dc.Texture.FTShadow) Ldepthmap.setMagfilter(p3dc.Texture.FTShadow) # Adding a color texture is totally unnecessary, but it helps with # debugging. Lcolormap = p3dc.Texture() LBuffer.addRenderTexture(Lcolormap, p3dc.GraphicsOutput.RTMBindOrCopy, p3dc.GraphicsOutput.RTPColor) self.inst_p = addInstructions(0.06, 'P : stop/start the Panda Rotation') self.inst_w = addInstructions(0.12, 'W : stop/start the Walk Cycle') self.inst_t = addInstructions(0.18, 'T : stop/start the Teapot') self.inst_l = addInstructions(0.24, 'L : move light source far or close') self.inst_v = addInstructions(0.30, 'V : View the Depth-Texture results') self.inst_u = addInstructions(0.36, 'U : toggle updating the shadow map') self.inst_x = addInstructions( 0.42, 'Left/Right Arrow : switch camera angles') self.inst_a = addInstructions(0.48, 'Something about A/Z and push bias') ape.base().setBackgroundColor(0, 0, 0.2, 1) ape.base().camLens.setNearFar(1.0, 10000) ape.base().camLens.setFov(75) ape.base().disableMouse() # Load the scene. floorTex = ape.loader().loadTexture('maps/envir-ground.jpg') cm = p3dc.CardMaker('') cm.setFrame(-2, 2, -2, 2) floor = ape.render().attachNewNode(p3dc.PandaNode("floor")) for y in range(12): for x in range(12): nn = floor.attachNewNode(cm.generate()) nn.setP(-90) nn.setPos((x - 6) * 4, (y - 6) * 4, 0) floor.setTexture(floorTex) floor.flattenStrong() self.pandaAxis = ape.render().attachNewNode('panda axis') self.pandaModel = Actor('panda-model', {'walk': 'panda-walk4'}) self.pandaModel.reparentTo(self.pandaAxis) self.pandaModel.setPos(9, 0, 0) self.pandaModel.setShaderInput("scale", (0.01, 0.01, 0.01, 1.0)) self.pandaWalk = self.pandaModel.actorInterval('walk', playRate=1.8) self.pandaWalk.loop() self.pandaMovement = self.pandaAxis.hprInterval( 20.0, p3dc.LPoint3(-360, 0, 0), startHpr=p3dc.LPoint3(0, 0, 0)) self.pandaMovement.loop() self.teapot = ape.loader().loadModel('teapot') self.teapot.reparentTo(ape.render()) self.teapot.setPos(0, -20, 10) self.teapot.setShaderInput("texDisable", (1, 1, 1, 1)) self.teapotMovement = self.teapot.hprInterval( 50, p3dc.LPoint3(0, 360, 360)) self.teapotMovement.loop() self.accept('escape', sys.exit) self.accept("arrow_left", self.incrementCameraPosition, [-1]) self.accept("arrow_right", self.incrementCameraPosition, [1]) self.accept("p", self.toggleInterval, [self.pandaMovement]) self.accept("t", self.toggleInterval, [self.teapotMovement]) self.accept("w", self.toggleInterval, [self.pandaWalk]) self.accept("v", ape.base().bufferViewer.toggleEnable) self.accept("u", self.toggleUpdateShadowMap) self.accept("l", self.incrementLightPosition, [1]) self.accept("o", ape.base().oobe) self.accept('a', self.adjustPushBias, [1.1]) self.accept('z', self.adjustPushBias, [0.9]) self.LCam = ape.base().makeCamera(LBuffer) self.LCam.node().setScene(ape.render()) self.LCam.node().getLens().setFov(40) self.LCam.node().getLens().setNearFar(10, 100) # default values self.pushBias = 0.04 self.ambient = 0.2 self.cameraSelection = 0 self.lightSelection = 0 # setting up shader ape.render().setShaderInput('light', self.LCam) ape.render().setShaderInput('Ldepthmap', Ldepthmap) ape.render().setShaderInput('ambient', (self.ambient, 0, 0, 1.0)) ape.render().setShaderInput('texDisable', (0, 0, 0, 0)) ape.render().setShaderInput('scale', (1, 1, 1, 1)) # Put a shader on the Light camera. lci = p3dc.NodePath(p3dc.PandaNode("Light Camera Initializer")) lci.setShader(ape.loader().loadShader('shadows_caster.sha')) self.LCam.node().setInitialState(lci.getState()) # Put a shader on the Main camera. # Some video cards have special hardware for shadow maps. # If the card has that, use it. If not, use a different # shader that does not require hardware support. mci = p3dc.NodePath(p3dc.PandaNode("Main Camera Initializer")) if ape.base().win.getGsg().getSupportsShadowFilter(): mci.setShader(ape.loader().loadShader('shadows_shadow.sha')) else: mci.setShader( ape.loader().loadShader('shadows_shadow-nosupport.sha')) ape.base().cam.node().setInitialState(mci.getState()) self.incrementCameraPosition(0) self.incrementLightPosition(0) self.adjustPushBias(1.0)
def start(self): self.setBackgroundColor((0, 0, 0, 0)) # Preliminary capabilities check. if not self.win.getGsg().getSupportsBasicShaders(): NC( 1, "Firefly Demo: Video driver reports that Cg shaders are not supported." ) return if not self.win.getGsg().getSupportsDepthTexture(): NC( 1, "Firefly Demo: Video driver reports that depth textures are not supported." ) return # This algorithm uses two offscreen buffers, one of which has # an auxiliary bitplane, and the offscreen buffers share a single # depth buffer. This is a heck of a complicated buffer setup. self.modelbuffer = self.makeFBO("model buffer", 1) self.lightbuffer = self.makeFBO("light buffer", 0) # Creation of a high-powered buffer can fail, if the graphics card # doesn't support the necessary OpenGL extensions. if self.modelbuffer is None or self.lightbuffer is None: NC( 1, "Firefly Demo: Video driver does not support multiple render targets" ) return # Create four render textures: depth, normal, albedo, and final. # attach them to the various bitplanes of the offscreen buffers. self.texDepth = p3dc.Texture() self.texDepth.setFormat(p3dc.Texture.FDepthStencil) self.texAlbedo = p3dc.Texture() self.texNormal = p3dc.Texture() self.texFinal = p3dc.Texture() self.modelbuffer.addRenderTexture(self.texDepth, p3dc.GraphicsOutput.RTMBindOrCopy, p3dc.GraphicsOutput.RTPDepthStencil) self.modelbuffer.addRenderTexture(self.texAlbedo, p3dc.GraphicsOutput.RTMBindOrCopy, p3dc.GraphicsOutput.RTPColor) self.modelbuffer.addRenderTexture(self.texNormal, p3dc.GraphicsOutput.RTMBindOrCopy, p3dc.GraphicsOutput.RTPAuxRgba0) self.lightbuffer.addRenderTexture(self.texFinal, p3dc.GraphicsOutput.RTMBindOrCopy, p3dc.GraphicsOutput.RTPColor) # Set the near and far clipping planes. self.cam.node().getLens().setNear(50.0) self.cam.node().getLens().setFar(500.0) lens = self.cam.node().getLens() # This algorithm uses three cameras: one to render the models into the # model buffer, one to render the lights into the light buffer, and # one to render "plain" stuff (non-deferred shaded) stuff into the # light buffer. Each camera has a bitmask to identify it. self.modelMask = 1 self.lightMask = 2 self.plainMask = 4 self.modelcam = self.makeCamera(self.modelbuffer, lens=lens, scene=self.render, mask=self.modelMask) self.lightcam = self.makeCamera(self.lightbuffer, lens=lens, scene=self.render, mask=self.lightMask) self.plaincam = self.makeCamera(self.lightbuffer, lens=lens, scene=self.render, mask=self.plainMask) # Panda's main camera is not used. self.cam.node().setActive(0) # Take explicit control over the order in which the three # buffers are rendered. self.modelbuffer.setSort(1) self.lightbuffer.setSort(2) self.win.setSort(3) # Within the light buffer, control the order of the two cams. self.lightcam.node().getDisplayRegion(0).setSort(1) self.plaincam.node().getDisplayRegion(0).setSort(2) # By default, panda usually clears the screen before every # camera and before every window. Tell it not to do that. # Then, tell it specifically when to clear and what to clear. self.modelcam.node().getDisplayRegion(0).disableClears() self.lightcam.node().getDisplayRegion(0).disableClears() self.plaincam.node().getDisplayRegion(0).disableClears() self.cam.node().getDisplayRegion(0).disableClears() self.cam2d.node().getDisplayRegion(0).disableClears() self.modelbuffer.disableClears() self.win.disableClears() self.modelbuffer.setClearColorActive(1) self.modelbuffer.setClearDepthActive(1) self.lightbuffer.setClearColorActive(1) self.lightbuffer.setClearColor((0, 0, 0, 1)) # Miscellaneous stuff. self.disableMouse() self.camera.setPos(-9.112, -211.077, 46.951) self.camera.setHpr(0, -7.5, 2.4) random.seed() # Calculate the projection parameters for the final shader. # The math here is too complex to explain in an inline comment, # I've put in a full explanation into the HTML intro. proj = self.cam.node().getLens().getProjectionMat() proj_x = 0.5 * proj.getCell(3, 2) / proj.getCell(0, 0) proj_y = 0.5 * proj.getCell(3, 2) proj_z = 0.5 * proj.getCell(3, 2) / proj.getCell(2, 1) proj_w = -0.5 - 0.5 * proj.getCell(1, 2) # Configure the render state of the model camera. tempnode = p3dc.NodePath(p3dc.PandaNode("temp node")) tempnode.setAttrib( p3dc.AlphaTestAttrib.make(p3dc.RenderAttrib.MGreaterEqual, 0.5)) tempnode.setShader(self.loader.loadShader("fireflies_model.sha")) tempnode.setAttrib( p3dc.DepthTestAttrib.make(p3dc.RenderAttrib.MLessEqual)) self.modelcam.node().setInitialState(tempnode.getState()) # Configure the render state of the light camera. tempnode = p3dc.NodePath(p3dc.PandaNode("temp node")) tempnode.setShader(self.loader.loadShader("fireflies_light.sha")) tempnode.setShaderInput("texnormal", self.texNormal) tempnode.setShaderInput("texalbedo", self.texAlbedo) tempnode.setShaderInput("texdepth", self.texDepth) tempnode.setShaderInput("proj", (proj_x, proj_y, proj_z, proj_w)) tempnode.setAttrib( p3dc.ColorBlendAttrib.make(p3dc.ColorBlendAttrib.MAdd, p3dc.ColorBlendAttrib.OOne, p3dc.ColorBlendAttrib.OOne)) tempnode.setAttrib( p3dc.CullFaceAttrib.make( p3dc.CullFaceAttrib.MCullCounterClockwise)) # The next line causes problems on Linux. # tempnode.setAttrib(p3dc.DepthTestAttrib.make(p3dc.RenderAttrib.MGreaterEqual)) tempnode.setAttrib( p3dc.DepthWriteAttrib.make(p3dc.DepthWriteAttrib.MOff)) self.lightcam.node().setInitialState(tempnode.getState()) # Configure the render state of the plain camera. rs = p3dc.RenderState.makeEmpty() self.plaincam.node().setInitialState(rs) # Clear any render attribs on the root node. This is necessary # because by default, panda assigns some attribs to the root # node. These default attribs will override the # carefully-configured render attribs that we just attached # to the cameras. The simplest solution is to just clear # them all out. self.render.setState(p3dc.RenderState.makeEmpty()) # My artist created a model in which some of the polygons # don't have textures. This confuses the shader I wrote. # This little hack guarantees that everything has a texture. white = self.loader.loadTexture("fireflies_models/white.jpg") self.render.setTexture(white, 0) # Create two subroots, to help speed cull traversal. self.lightroot = p3dc.NodePath(p3dc.PandaNode("lightroot")) self.lightroot.reparentTo(self.render) self.modelroot = p3dc.NodePath(p3dc.PandaNode("modelroot")) self.modelroot.reparentTo(self.render) self.lightroot.hide(p3dc.BitMask32(self.modelMask)) self.modelroot.hide(p3dc.BitMask32(self.lightMask)) self.modelroot.hide(p3dc.BitMask32(self.plainMask)) # Load the model of a forest. Make it visible to the model camera. # This is a big model, so we load it asynchronously while showing a # load text. We do this by passing in a callback function. self.loading = addTitle("Loading models...") self.forest = p3dc.NodePath(p3dc.PandaNode("Forest Root")) self.forest.reparentTo(self.render) self.forest.hide(p3dc.BitMask32(self.lightMask | self.plainMask)) self.loader.loadModel([ "fireflies_models/background", "fireflies_models/foliage01", "fireflies_models/foliage02", "fireflies_models/foliage03", "fireflies_models/foliage04", "fireflies_models/foliage05", "fireflies_models/foliage06", "fireflies_models/foliage07", "fireflies_models/foliage08", "fireflies_models/foliage09" ], callback=self.finishLoading) # Cause the final results to be rendered into the main window on a card. self.card = self.lightbuffer.getTextureCard() self.card.setTexture(self.texFinal) self.card.reparentTo(self.render2d) # Panda contains a built-in viewer that lets you view the results of # your render-to-texture operations. This code configures the viewer. self.bufferViewer.setPosition("llcorner") self.bufferViewer.setCardSize(0, 0.40) self.bufferViewer.setLayout("vline") self.toggleCards() self.toggleCards() # Firefly parameters self.fireflies = [] self.sequences = [] self.scaleseqs = [] self.glowspheres = [] self.fireflysize = 1.0 self.spheremodel = self.loader.loadModel("misc/sphere") # Create the firefly model, a fuzzy dot dotSize = 1.0 cm = p3dc.CardMaker("firefly") cm.setFrame(-dotSize, dotSize, -dotSize, dotSize) self.firefly = p3dc.NodePath(cm.generate()) self.firefly.setTexture( self.loader.loadTexture("fireflies_models/firefly.png")) self.firefly.setAttrib( p3dc.ColorBlendAttrib.make(p3dc.ColorBlendAttrib.M_add, p3dc.ColorBlendAttrib.O_incoming_alpha, p3dc.ColorBlendAttrib.O_one)) # these allow you to change parameters in realtime self.accept("arrow_up", self.incFireflyCount, [1.1111111]) self.accept("arrow_down", self.decFireflyCount, [0.9000000]) self.accept("arrow_right", self.setFireflySize, [1.1111111]) self.accept("arrow_left", self.setFireflySize, [0.9000000]) self.accept("v", self.toggleCards) self.accept("V", self.toggleCards)
def start(self): # Set the background color to black self.win.setClearColor((0, 0, 0, 1)) # This is used to store which keys are currently pressed. self.keyMap = { "left": 0, "right": 0, "forward": 0, "cam-left": 0, "cam-right": 0} # Post the instructions self.title = addTitle( "Panda3D Tutorial: Roaming Ralph (Walking on Uneven Terrain)") self.inst1 = addInstructions(0.06, "[ESC]: Quit") self.inst2 = addInstructions(0.12, "[Left Arrow]: Rotate Ralph Left") self.inst3 = addInstructions(0.18, "[Right Arrow]: Rotate Ralph Right") self.inst4 = addInstructions(0.24, "[Up Arrow]: Run Ralph Forward") self.inst6 = addInstructions(0.30, "[A]: Rotate p3dc.Camera Left") self.inst7 = addInstructions(0.36, "[S]: Rotate p3dc.Camera Right") # Set up the environment # # This environment model contains collision meshes. If you look # in the egg file, you will see the following: # # <Collide> { Polyset keep descend } # # This tag causes the following mesh to be converted to a collision # mesh -- a mesh which is optimized for collision, not rendering. # It also keeps the original mesh, so there are now two copies --- # one optimized for rendering, one for collisions. self.environ = self.loader.loadModel("roaming_ralph_models/world") self.environ.reparentTo(self.render) # Create the main character, Ralph ralphStartPos = self.environ.find("**/start_point").getPos() self.ralph = Actor("roaming_ralph_models/ralph", {"run": "roaming_ralph_models/ralph-run", "walk": "roaming_ralph_models/ralph-walk"}) self.ralph.reparentTo(self.render) self.ralph.setScale(.2) self.ralph.setPos(ralphStartPos + (0, 0, 0.5)) # Create a floater object, which floats 2 units above ralph. We # use this as a target for the camera to look at. self.floater = p3dc.NodePath(p3dc.PandaNode("floater")) self.floater.reparentTo(self.ralph) self.floater.setZ(2.0) # Accept the control keys for movement and rotation self.accept("escape", sys.exit) self.accept("arrow_left", self.setKey, ["left", True]) self.accept("arrow_right", self.setKey, ["right", True]) self.accept("arrow_up", self.setKey, ["forward", True]) self.accept("a", self.setKey, ["cam-left", True]) self.accept("s", self.setKey, ["cam-right", True]) self.accept("arrow_left-up", self.setKey, ["left", False]) self.accept("arrow_right-up", self.setKey, ["right", False]) self.accept("arrow_up-up", self.setKey, ["forward", False]) self.accept("a-up", self.setKey, ["cam-left", False]) self.accept("s-up", self.setKey, ["cam-right", False]) self.taskMgr.add(self.move, "moveTask") # Game state variables self.isMoving = False # Set up the camera self.disableMouse() self.camera.setPos(self.ralph.getX(), self.ralph.getY() + 10, 2) # We will detect the height of the terrain by creating a collision # ray and casting it downward toward the terrain. One ray will # start above ralph's head, and the other will start above the camera. # A ray may hit the terrain, or it may hit a rock or a tree. If it # hits the terrain, we can detect the height. If it hits anything # else, we rule that the move is illegal. self.cTrav = p3dc.CollisionTraverser() self.ralphGroundRay = p3dc.CollisionRay() self.ralphGroundRay.setOrigin(0, 0, 9) self.ralphGroundRay.setDirection(0, 0, -1) self.ralphGroundCol = p3dc.CollisionNode('ralphRay') self.ralphGroundCol.addSolid(self.ralphGroundRay) self.ralphGroundCol.setFromCollideMask(p3dc.CollideMask.bit(0)) self.ralphGroundCol.setIntoCollideMask(p3dc.CollideMask.allOff()) self.ralphGroundColNp = self.ralph.attachNewNode(self.ralphGroundCol) self.ralphGroundHandler = p3dc.CollisionHandlerQueue() self.cTrav.addCollider(self.ralphGroundColNp, self.ralphGroundHandler) self.camGroundRay = p3dc.CollisionRay() self.camGroundRay.setOrigin(0, 0, 9) self.camGroundRay.setDirection(0, 0, -1) self.camGroundCol = p3dc.CollisionNode('camRay') self.camGroundCol.addSolid(self.camGroundRay) self.camGroundCol.setFromCollideMask(p3dc.CollideMask.bit(0)) self.camGroundCol.setIntoCollideMask(p3dc.CollideMask.allOff()) self.camGroundColNp = self.camera.attachNewNode(self.camGroundCol) self.camGroundHandler = p3dc.CollisionHandlerQueue() self.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler) # Uncomment this line to see the collision rays #self.ralphGroundColNp.show() #self.camGroundColNp.show() # Uncomment this line to show a visual representation of the # collisions occuring #self.cTrav.showCollisions(render) # Create some lighting ambientLight = p3dc.AmbientLight("ambientLight") ambientLight.setColor((.3, .3, .3, 1)) directionalLight = p3dc.DirectionalLight("directionalLight") directionalLight.setDirection((-5, -5, -5)) directionalLight.setColor((1, 1, 1, 1)) directionalLight.setSpecularColor((1, 1, 1, 1)) self.render.setLight(self.render.attachNewNode(ambientLight)) self.render.setLight(self.render.attachNewNode(directionalLight))
def start(self): # Set time of day if self.render_pipeline: self.render_pipeline.daytime_mgr.time = "7:40" # Use a special effect for rendering the scene, this is because the # roaming ralph model has no normals or valid materials if self.render_pipeline: self.render_pipeline.set_effect( ape.render(), "roaming_ralph_pipeline_scene-effect.yaml", {}, sort=250) self.keyMap = { "left": 0, "right": 0, "forward": 0, "backward": 0, "cam-left": 0, "cam-right": 0 } self.speed = 1.0 ape.base().win.setClearColor(p3dc.Vec4(0, 0, 0, 1)) # Post the instructions self.inst4 = addInstructions(0.90, "[W] Run Ralph Forward") self.inst4 = addInstructions(0.85, "[S] Run Ralph Backward") self.inst2 = addInstructions(0.80, "[A] Rotate Ralph Left") self.inst3 = addInstructions(0.75, "[D] Rotate Ralph Right") self.inst6 = addInstructions(0.70, "[Left Arrow] Rotate Camera Left") self.inst7 = addInstructions(0.65, "[Right Arrow] Rotate Camera Right") # Set up the environment # # This environment model contains collision meshes. If you look # in the egg file, you will see the following: # # <Collide> { Polyset keep descend } # # This tag causes the following mesh to be converted to a collision # mesh -- a mesh which is optimized for collision, not rendering. # It also keeps the original mesh, so there are now two copies --- # one optimized for rendering, one for collisions. self.environ = ape.loader().loadModel( "roaming_ralph_pipeline_resources/world") self.environ.reparentTo(ape.render()) self.environ.setPos(0, 0, 0) # Remove wall nodes self.environ.find("**/wall").remove_node() # Create the main character, Ralph self.ralph = Actor( "roaming_ralph_pipeline_resources/ralph", { "run": "roaming_ralph_pipeline_resources/ralph-run", "walk": "roaming_ralph_pipeline_resources/ralph-walk", "stand": "roaming_ralph_pipeline_resources/ralph" }) self.ralph.reparentTo(ape.render()) self.ralph.setScale(.2) self.ralph.setPos(p3dc.Vec3(-110.9, 29.4, 1.8)) # Create a floater object. We use the "floater" as a temporary # variable in a variety of calculations. self.floater = p3dc.NodePath(p3dc.PandaNode("floater")) self.floater.reparentTo(ape.render()) # Accept the control keys for movement and rotation self.accept("a", self.setKey, ["left", 1]) self.accept("d", self.setKey, ["right", 1]) self.accept("w", self.setKey, ["forward", 1]) self.accept("s", self.setKey, ["backward", 1]) self.accept("arrow_left", self.setKey, ["cam-left", 1]) self.accept("arrow_right", self.setKey, ["cam-right", 1]) self.accept("a-up", self.setKey, ["left", 0]) self.accept("d-up", self.setKey, ["right", 0]) self.accept("w-up", self.setKey, ["forward", 0]) self.accept("s-up", self.setKey, ["backward", 0]) self.accept("arrow_left-up", self.setKey, ["cam-left", 0]) self.accept("arrow_right-up", self.setKey, ["cam-right", 0]) self.accept("=", self.adjustSpeed, [0.25]) self.accept("+", self.adjustSpeed, [0.25]) self.accept("-", self.adjustSpeed, [-0.25]) ape.base().taskMgr.add(self.move, "moveTask") # Game state variables self.isMoving = False # Set up the camera ape.base().disableMouse() ape.base().camera.setPos(self.ralph.getX() + 10, self.ralph.getY() + 10, 2) ape.base().camLens.setFov(80) # We will detect the height of the terrain by creating a collision # ray and casting it downward toward the terrain. One ray will # start above ralph's head, and the other will start above the camera. # A ray may hit the terrain, or it may hit a rock or a tree. If it # hits the terrain, we can detect the height. If it hits anything # else, we rule that the move is illegal. self.cTrav = p3dc.CollisionTraverser() self.ralphGroundRay = p3dc.CollisionRay() self.ralphGroundRay.setOrigin(0, 0, 1000) self.ralphGroundRay.setDirection(0, 0, -1) self.ralphGroundCol = p3dc.CollisionNode('ralphRay') self.ralphGroundCol.addSolid(self.ralphGroundRay) self.ralphGroundCol.setFromCollideMask(p3dc.BitMask32.bit(0)) self.ralphGroundCol.setIntoCollideMask(p3dc.BitMask32.allOff()) self.ralphGroundColNp = self.ralph.attachNewNode(self.ralphGroundCol) self.ralphGroundHandler = p3dc.CollisionHandlerQueue() self.cTrav.addCollider(self.ralphGroundColNp, self.ralphGroundHandler) self.camGroundRay = p3dc.CollisionRay() self.camGroundRay.setOrigin(0, 0, 1000) self.camGroundRay.setDirection(0, 0, -1) self.camGroundCol = p3dc.CollisionNode('camRay') self.camGroundCol.addSolid(self.camGroundRay) self.camGroundCol.setFromCollideMask(p3dc.BitMask32.bit(0)) self.camGroundCol.setIntoCollideMask(p3dc.BitMask32.allOff()) self.camGroundColNp = ape.base().camera.attachNewNode( self.camGroundCol) self.camGroundHandler = p3dc.CollisionHandlerQueue() self.cTrav.addCollider(self.camGroundColNp, self.camGroundHandler) # Uncomment this line to see the collision rays #self.ralphGroundColNp.show() #self.camGroundColNp.show() # Uncomment this line to show a visual representation of the # collisions occuring #self.cTrav.showCollisions(ape.render()) # Create some lighting ambientLight = p3dc.AmbientLight("ambientLight") ambientLight.setColor(p3dc.Vec4(.3, .3, .3, 1)) directionalLight = p3dc.DirectionalLight("directionalLight") directionalLight.setDirection(p3dc.Vec3(-5, -5, -5)) directionalLight.setColor(p3dc.Vec4(1, 1, 1, 1)) directionalLight.setSpecularColor(p3dc.Vec4(1, 1, 1, 1)) ape.render().setLight(ape.render().attachNewNode(ambientLight)) ape.render().setLight(ape.render().attachNewNode(directionalLight))