I’ve created a simple program that let’s you take a panda3d render and blit it to a Pygame Window. This could be helpful if you need pixel perfect graphics and drawing which Pygame provides while also wanting to use all of Panda3D’s wonderful features.
I’ve used pygame-ce for this.
This code is in the public domain.
import pygame
from direct.showbase.ShowBase import ShowBase
from panda3d.core import Texture, GraphicsOutput
class Window(ShowBase):
def __init__(self):
super().__init__(windowType='offscreen')
self.window = pygame.Window(size=(640, 480))
self.display_surface = self.window.get_surface()
self.screen_texture_3d = Texture()
self.screen_texture_3d.setMinfilter(Texture.FTLinear)
self.win.addRenderTexture(self.screen_texture_3d, GraphicsOutput.RTMCopyRam)
self.add_task(self.process_events)
self.add_task(self.blit_3d, sort=-10)
self.add_task(self.show_render, sort=30)
self.accept('w', self.move_cam)
self.accept('s', self.move_cam)
self.accept('d', self.move_cam)
self.accept('a', self.move_cam)
self.loader.load_model('panda').reparent_to(self.render)
def move_cam(self, event):
k = event.get('key') or event.get('text')
print(k, 'key')
if k == 'w':
self.cam.set_y(self.cam, 1)
elif k == 's':
self.cam.set_y(self.cam, -1)
elif k == 'a':
self.cam.set_x(self.cam, -1)
elif k == 'd':
self.cam.set_x(self.cam, 1)
def blit_3d(self, task):
if self.screen_texture_3d.hasRamImage():
i = pygame.image.frombuffer(self.screen_texture_3d.get_ram_image().getData(),
(self.screen_texture_3d.get_x_size(), self.screen_texture_3d.get_y_size()),
"BGRA")
self.display_surface.blit(pygame.transform.flip(i, False, True).convert())
pygame.draw.rect(self.display_surface, (255,255,255), (0,0,100,100))
return task.cont
def show_render(self, task):
self.window.flip()
return task.cont
def process_events(self, task):
for event in pygame.event.get():
print(event.dict)
if 'pos' in event.dict:
self.messenger.send('pos', sentArgs=[event.dict])
elif 'unicode' in event.dict:
self.messenger.send(event.dict['unicode'], sentArgs=[event.dict])
elif 'text' in event.dict:
self.messenger.send(event.dict['text'], sentArgs=[event.dict])
if event.type == pygame.QUIT:
quit()
return task.cont
if __name__ == '__main__':
example = Window()
example.run()
