Hey!
I’m a bit stuck and in need of some help.
I work on a script that aims to display a 3d scene on a curved screen to cover a larger FOV.
So far I managed to generate a dynamic cube map, to apply the texture on a screen model of my actual screen and to view it with a camera to validate that it looks realistic when you look around.
Now to display the cube map on the actual screen, I thought that I can either somehow project the applied texture back onto a flat screen which I’ll the display on the curved screen, but since all projections seem to use cameras I’m again limited in the FOV.
I also found the nonlinearimager and its lenses, but it’s unclear to me how to customize the lenses to my needs, as I’m not sure if the fisheye or cylindrical lens will help me.
Any ideas?
Thanks:)
#------------------------------------------------------------------------------
#load configuration .prc file
from panda3d.core import loadPrcFile
loadPrcFile("Config/VR_screen_model_config.prc")
# #load config manager and print config vars
from panda3d.core import ConfigVariableManager
ConfigVariableManager.getGlobalPtr().listVariables()
# import gltf support
import simplepbr
#import panda3d.core stuff
from panda3d.core import *
#import ShowBase
from direct.showbase.ShowBase import ShowBase
# import task, a task is a procedure that is called every frame
from direct.task import Task
#------------------------------------------------------------------------------
#make dictionary to map keys press events to true/false
keyMap = {
"up": False,
"down": False,
"left": False,
"right": False,
"rcon": False,
"zero": False,
"w": False,
"s": False,
"a": False,
"d": False,
"e": False,
"q": False,
"2": False,
"1": False
}
#callback update function
def updateKeyMap(key,state):
keyMap[key] = state
#------------------------------------------------------------------------------
class VR(ShowBase):
def __init__(self, cube_size = 2048):
super().__init__()
simplepbr.init(use_normal_maps=True)
#load scene
self.scene = self.loader.loadModel('world.glb')
self.scene.setScale(10)
self.scene.reparentTo(self.render)
#adjust camera
self.camera.setPos(0,-10,0)
self.camera.setHpr(0,0,0)
#set speed
self.camera_speed = 0.5
self.turning_speed = 1.5
#create new window, camera, avatar and renderer for screen display
win2 = self.openWindow(makeCamera=True)
render2 = NodePath('render2')
self.cam2 = self.camList[1]
self.cam2.reparentTo(render2)
self.cam2.node().getLens().setNearFar(1/10,1000)
self.cam2.node().getLens().setFov(70)
self.cam2.node().showFrustum()
avatar = self.loader.loadModel('ZF_fov.glb')
avatar.setHpr(0,-90,0)
avatar.setScale(0.02)
avatar.setPos(0,0,0)
avatar.setColor(0.7,0.3,0.3)
avatar.reparentTo(self.cam2)
#create new window with overview camera
win_ov = self.openWindow(makeCamera=True)
cam_ov = self.camList[2]
cam_ov.reparentTo(render2)
cam_ov.setPos(0,0,50)
cam_ov.lookAt(avatar)
# activate keyboard control
self.keyboard_control()
#make cube map from win and attach to win2
self.cube_cams = self.scene.attachNewNode('cube_cams')
self.cube_cams.setHpr(180,0,0) #rotate cube cams
self.cube_cams.setPos(0,0,0)
cube_map_buffer = win2.makeCubeMap('cube_map', cube_size, self.cube_cams)
[icam.node().getLens().setNearFar(1/10,1000) for icam in self.cube_cams.getChildren()] #adjust near and far clipping distance
[icam.node().showFrustum() for icam in self.cube_cams.getChildren()]
#load display screen
self.screen = self.loader.loadModel("curved_screen_model.glb")
self.screen.setScale(1)
self.screen.reparentTo(render2) #attach screen to cam2 to render it with render2
self.screen.setPos(0,5.5,0) #move screen relative to render2
self.screen.setHpr(-90,0,90)
# display cube_map_buffer.getTexture() on screen
ts = TextureStage('ts')
self.screen.setTexGen(ts, TexGenAttrib.MWorldCubeMap)
self.screen.setTexture(ts,cube_map_buffer.getTexture())
#self.cam2.lookAt(self.screen)
# Add the move tasks procedure to the task manager.
self.taskMgr.add(self.move_cam2, "move_cam2")
self.taskMgr.add(self.move_cube_cams, "move_cc")
def keyboard_control(self):
#create camera control for cam2
#use build-in keyboard support: self.accept. see doc for key (event) names
self.accept("arrow_left",updateKeyMap,["left", True])
self.accept("arrow_right",updateKeyMap,["right", True])
self.accept("arrow_up",updateKeyMap,["up", True])
self.accept("arrow_down",updateKeyMap,["down", True])
self.accept("rcontrol",updateKeyMap,["rcon", True])
self.accept("0",updateKeyMap,["zero", True])
#key release events
self.accept("arrow_left-up",updateKeyMap,["left", False])
self.accept("arrow_right-up",updateKeyMap,["right", False])
self.accept("arrow_up-up",updateKeyMap,["up", False])
self.accept("arrow_down-up",updateKeyMap,["down", False])
self.accept("rcontrol-up",updateKeyMap,["rcon", False])
self.accept("0-up",updateKeyMap,["zero", False])
#create camera control for cube cams
#use build-in keyboard support: self.accept. see doc for key (event) names
self.accept("a",updateKeyMap,["a", True])
self.accept("d",updateKeyMap,["d", True])
self.accept("w",updateKeyMap,["w", True])
self.accept("s",updateKeyMap,["s", True])
self.accept("e",updateKeyMap,["e", True])
self.accept("q",updateKeyMap,["q", True])
self.accept("2",updateKeyMap,["2", True])
self.accept("1",updateKeyMap,["1", True])
#key release events
self.accept("a-up",updateKeyMap,["a", False])
self.accept("d-up",updateKeyMap,["d", False])
self.accept("w-up",updateKeyMap,["w", False])
self.accept("s-up",updateKeyMap,["s", False])
self.accept("e-up",updateKeyMap,["e", False])
self.accept("q-up",updateKeyMap,["q", False])
self.accept("2-up",updateKeyMap,["2", False])
self.accept("1-up",updateKeyMap,["1", False])
def move_cam2(self, task):
#get camera position and Hpr
cam2_pos = self.cam2.getPos()
cam2_hpr = self.cam2.getHpr()
#update camera based on key pressing
if keyMap["left"]:
cam2_pos.x -= self.camera_speed
if keyMap["right"]:
cam2_pos.x += self.camera_speed
if keyMap["up"]:
cam2_pos.y += self.camera_speed
if keyMap["down"]:
cam2_pos.y -= self.camera_speed
if keyMap["rcon"]:
cam2_hpr.x += self.turning_speed
print(cam2_hpr)
if keyMap["zero"]:
cam2_hpr.x -= self.turning_speed
print(cam2_hpr)
#update camera position and Hpr
self.cam2.setPos(cam2_pos)
self.cam2.setHpr(cam2_hpr)
return Task.cont
def move_cube_cams(self,task):
#get cube cams position and Hpr
cc_pos = self.cube_cams.getPos()
cc_hpr = self.cube_cams.getHpr()
#update camera based on key pressing
if keyMap["a"]:
cc_pos.x -= self.camera_speed
if keyMap["d"]:
cc_pos.x += self.camera_speed
if keyMap["w"]:
cc_pos.y += self.camera_speed
if keyMap["s"]:
cc_pos.y -= self.camera_speed
if keyMap["2"]:
cc_pos.z += self.camera_speed
if keyMap["1"]:
cc_pos.z -= self.camera_speed
#-----------------------------------
if keyMap["e"]:
cc_hpr.x += self.turning_speed
if keyMap["q"]:
cc_hpr.x -= self.turning_speed
#-----------------------------------
#update subjct position and Hpr
self.cube_cams.setPos(cc_pos)
self.cube_cams.setHpr(cc_hpr)
return Task.cont
#------------------------------------------------------------------------------
VR_instance = VR() #read out variables with test_instance.variable
VR_instance.run()