More with Two windows, but now same scene

Hi there,

I have been playing around with a second window, and right now I am trying to view the exact same aspect2d scene in two windows, but I am getting strange output. If I leave the cameras at their default positions, I see nothing in the second window. If I move the second camera, I can see the scene, but it the aspect ratio is not right. I loaded two models just to make sure it wasn’t something weird with the models. Also no idea why the smiley looks weird in both windows. Here is my code:

from direct.showbase.ShowBase import ShowBase
from direct.showbase.DirectObject import DirectObject
from panda3d.core import OrthographicLens

class World(DirectObject):
def init(self):
self.win = ShowBase()
window2 = self.win.openWindow()
lens = OrthographicLens()
camera = self.win.camList[0]
camera.node().setLens(lens)
camera.reparentTo( aspect2d )
#camera.setPos(0, 20, 0)

    camera2 = self.win.camList[1]
    camera2.node().setLens(lens)
    camera2.reparentTo( aspect2d )
    camera2.setPos(0, -100, 0)

    print 'cam1', camera.getPos()
    print 'cam2', camera2.getPos()

    self.win.disableMouse()

    self.smiley = self.win.loader.loadModel('smiley')
    self.smiley.setScale(0.2)
    self.smiley.setPos(-0.2, 0, -0.1)
    self.smiley.reparentTo( camera )

    square = self.win.loader.loadModel("Models/plane")
    square.reparentTo( aspect2d )
    square.setPos(0.2, 0, 0.1)

    square.setScale(0.3)
    square.setDepthTest(False)
    square.setTransparency(1)
    sq_texture = self.win.loader.loadTexture("textures/calibration_square.png")
    square.setTexture(sq_texture, 1)
    square.reparentTo( aspect2d )

if name == “main”:
W = World()
run()

Can anyone tell what I am doing wrong here? Thanks, Maria


So, I’ve been playing around with this some more, and it appears that if I set the second camera to render2d, instead of aspect2d, then the distortion is corrected, but the scene still looks magnified. If I have the second camera set to Orthographic, then I cannot alter this magnification. But, if I do not change the lens, set the camera to render2d, and set the second camera position to be at (0, -3.5, 0) then everything looks approximately the same (The first camera is at (0, 0, 0)). I can’t figure out anyway to verify that they are really the same, and -3.5 seems really arbitrary. I’d like them to be exactly the same, of course, and not just, yeah, that kind of looks right. Also, I’d really like to know why this is happening, and not just try to apply a lame patch to make it work. I tried playing around with setting up the second window from scratch (using base.graphicsEngine.makeOutput), and creating a display and camera from scratch, but this did not help. If I set the 2nd camera to render, then I get different outputs to each window, depending on whether I parent my models to render or aspect2d or camera or camera2, which makes sense, and is what I expect. If I set the parent of the second camera to be the first parent, I get the distortion, even if I am not changing the lens or anything else of the second camera. Help!

This is interesting.

If I change the lens of the second camera with OrthographicLens(), then the distortion goes away completely, but I am zoomed in on the image in the second window, and changing the position of the camera does nothing.

If I set smiley to be on a different plane than the y=0 plane, then it shows up twice in the first window, which was a bit unexpected. One of the smileys is in the same place and size as it was before, but more interesting is that the second smiley is warped in much the same way as smiley was being warped by the second camera. As if instead of moving the smiley, it made a second copy on the new plane, which was apparently too close to the camera lens. I used y = 5. Weirdly enough, if the second camera is set to an OrthographicLens, at position (0, 0, 0), and is parented to render2d, than it is the second smiley that shows up, not warped, but the same size and place as the second smiley in the first window. If it is parented to aspect2d instead, it still just shows the second smiley, but this time looks exactly the same as the warped one in the first window.

I have checked every setting I could for the lenses and the cameras, and they appear to be exactly the same. Somehow they seem to be a different distance from the scene, but it isn’t showing up as a camera parameter. I think by reparenting the second camera to aspect2d, I was somehow setting the aspect2d twice, although that seems pretty weird. Why my magnification is also changing, I still don’t understand. And I have no idea why something on y = 5 would show up twice in any window. I understand that it is abnormal to use y = 5 for render2d, so mostly this doesn’t matter, but I was curious, and it does seem somehow related to my second window problem.

I feel like I must be missing something terribly obvious. :frowning:

So, I gave up on pixel2d. Turns out using the OrthographicLens is sufficient. You just have to set the film size to the pixel size of your window, and you are pretty much done. Here is some code that opens two windows, puts smileys only on one window, frowney on both. Both windows are using pixels as coordinates (with zero in the center). For the curious, the reason I am using Panda3d in such an unusual way is that I am using it to create a calibration routine for an eye-tracker (my actual calibration task runs on two separate monitors, in which just one plots the eye movements). After the calibration routine, we will run a 3d VR game, in which we can track the players eye movement. As you can see, I can now tell exactly where I am plotting stuff and what size in pixels everything is. Woot!

from direct.showbase.ShowBase import ShowBase
from direct.showbase.DirectObject import DirectObject
from panda3d.core import WindowProperties
from panda3d.core import OrthographicLens
from panda3d.core import BitMask32

class World(DirectObject):
def init(self):
base = ShowBase()

    props = WindowProperties.getDefault()
    props.setOrigin(600, 200)
    window2 = base.openWindow(props)
    print base.win.getProperties().getXSize()
    print base.win.getProperties().getYSize()

    lens = OrthographicLens()
    lens.setFilmSize(800, 600)
    lens.setNearFar(-100,100)
    camera = base.camList[0]
    camera.node().setLens(lens)
    camera.reparentTo( render )

    camera2 = base.camList[1]
    camera2.node().setLens(lens)
    camera2.reparentTo( render )

    camera.node().setCameraMask(BitMask32.bit(0))
    camera2.node().setCameraMask(BitMask32.bit(1))
    base.disableMouse()

    smiley = base.loader.loadModel('smiley')
    smiley.setScale(30)
    smiley.setPos(0.5, 55, 0.5)
    smiley.reparentTo( render )
    min, max = smiley.getTightBounds()                                                             
    size = max - min                                                                                    
    print size[0], size[2]                                 
    print smiley.getPos()     
    
    smiley.hide(BitMask32.bit(0))
    smiley.show(BitMask32.bit(1))
    
    root = base.render.attachNewNode("Root")  
    smiley2 = smiley.copyTo(root)                                                        
    smiley2.setPos(-300, 0, -200) 
    smiley2.setScale(30)
    min, max = smiley2.getTightBounds()                                                             
    size = max - min                                                                                    
    print size[0], size[2]                                                                               
    print smiley2.getPos()     
    
    frowney = base.loader.loadModel('frowney')
    frowney.setScale(30)
    frowney.setPos(300, 55, 200)
    frowney.reparentTo( render )
    min, max = frowney.getTightBounds()                                                             
    size = max - min                                                                                    
    print size[0], size[2]                                                                               
    print frowney.getPos()     

if name == “main”:
W = World()
run()