I want to create a stereo camera

A stereo camera is really just two different cameras, a left and a right eye, parented to the same node and slightly offset from each other.

The bigger question is, how do you intend render the stereo output? There are lots of options, from rendering two side-by-side images, to combining both images into a red-blue stereo image, to rendering both images into a single stereo window (if your hardware supports this).

David

I want two windows showing different things, or any type of stereo camera is good for me too.

Cristiano
from Brazil

You can call base.openWindow() to create additional windows. When you do this, the camera for each window will be listed in base.camList: base.camList[0] is the original camera, base.camList[1] is the camera for the first additional window you create, and so on.

All of the nodes in base.camList are parented to the same parent node, which is the “camera” node that you manipulate normally as the camera. So you can just offset base.camList[0] and base.camList[1] from each other a bit, and still move them both together as a unit by moving camera.

David

thanks for the help, but I don´t understand how to put this in my script. can you show me an example please?

Cristiano
from Brazil

hey man, the tip for the cameras is very good, and I did it. but I saw that it´s was not what I really want. the thing I´m trying to do is show two images in the same window, like a right eye and a left eye. if one eye is closed, the full image wil change the position, like in the real life (alternately close an eye and open the other to see the difference). this is possible? where I can find tutorials for the cameras?
sorry for my english
thanks.
Cristiano
from Brazil

from direct.directbase.DirectStart import *
from pandac.PandaModules import *

# Retitle the main window as the "left" eye
wp = WindowProperties()
wp.setTitle('left')
base.win.requestProperties(wp)

# Open a new window and title it as the "right" eye
w2 = base.openWindow()
wp.setTitle('right')
w2.requestProperties(wp)

# Move the eyes apart a little bit, and converge them both on a point
# 20 feet ahead.
base.camList[0].setPos(-0.5, 0, 0)
base.camList[0].lookAt(0, 20, 0)
base.camList[1].setPos(0.5, 0, 0)
base.camList[1].lookAt(0, 20, 0)

David

thank you again, we are almost there. do you played Commandos? there´s an option to see multiple images in the same window. this is one camera I´m trying to create. The other thing I want is overlap two cameras, showing different things, like a mirage or a illusion. this is possible?
thanks

Cristiano

I see I´m making the wrong question. sorry. What I really want is multiple cameras in the same window, not multiple windows.

thanks for the help

Cristiano

I did have to re-read your question as I was going to post some of my old multiple windows code. But I now see what your after.

You want to display multiple camera regions on the same window. Ive not tried this myself yet, but I believe the sceneEditor ( located in the panda intall directory ) does something along these lines.

Have fun!

To put two cameras side-by-side in a window, you simply need to create two DisplayRegions. One easy way is via base.makeCamera(), like this:

    # Turn off the default camera and replace it with two new cameras, with
    # side-by-side DisplayRegions.
    base.camNode.setActive(0)
    base.makeCamera(base.win, displayRegion = (0, 0.5, 0, 1))
    base.makeCamera(base.win, displayRegion = (0.5, 1, 0, 1))

    # Move the eyes apart a little bit, and converge them both on a point
    # 20 feet ahead.
    base.camList[1].setPos(-0.5, 0, 0)
    base.camList[1].lookAt(0, 20, 0)
    base.camList[2].setPos(0.5, 0, 0)
    base.camList[2].lookAt(0, 20, 0)

To overlay two different scenes in the same window, it’s a bit more complicated. You’ll need to render one of them offscreen using base.makeTextureBuffer(), then apply that texture to a transparent card layered over the main screen. I think there are a few examples of rendering offscreen like this in the manual and in the Panda examples.

David

Two different scenes overlayed in the same window:

# Create a pair of offscreen buffers in which to view the "left"
# and "right" eyes.
leftBuffer = base.win.makeTextureBuffer('left', 512, 512)
leftBuffer.setClearColor(VBase4(0, 0, 0, 0))
base.makeCamera(leftBuffer)
rightBuffer = base.win.makeTextureBuffer('right', 512, 512)
rightBuffer.setClearColor(VBase4(0, 0, 0, 0))
base.makeCamera(rightBuffer)

# Create a pair of cards to display the contents of these buffer
# overlayed with the main window.
leftCard = CardMaker('left')
leftCard.setFrame(-1, 1, -1, 1)
leftCard.setColor(1, 1, 1, 0.5)
leftCardNP = render2d.attachNewNode(leftCard.generate())
leftCardNP.setTransparency(1)
leftCardNP.setTexture(leftBuffer.getTexture())
rightCard = CardMaker('right')
rightCard.setFrame(-1, 1, -1, 1)
rightCard.setColor(1, 1, 1, 0.5)
rightCardNP = render2d.attachNewNode(rightCard.generate())
rightCardNP.setTransparency(1)
rightCardNP.setTexture(rightBuffer.getTexture())

# Turn off the main camera, so we don't get them in triplicate.
base.camNode.setActive(0)

# Move the eyes apart a little bit, and converge them both on a point
# 20 feet ahead.
base.camList[1].setPos(-0.5, 0, 0)
base.camList[1].lookAt(0, 20, 0)
base.camList[2].setPos(0.5, 0, 0)
base.camList[2].lookAt(0, 20, 0)

David

I have tried your code … and made some extensions

from direct.directbase.DirectStart import *
from pandac.PandaModules import *
from direct.task import Task
from direct.actor import Actor 
import math 

# Create a pair of offscreen buffers in which to view the "left"
# and "right" eyes.
leftBuffer = base.win.makeTextureBuffer('left', 512, 512)
leftBuffer.setClearColor(VBase4(0, 0, 0, 0))
base.makeCamera(leftBuffer)
rightBuffer = base.win.makeTextureBuffer('right', 512, 512)
rightBuffer.setClearColor(VBase4(0, 0, 0, 0))
base.makeCamera(rightBuffer)

# Create a pair of cards to display the contents of these buffer
# overlayed with the main window.
leftCard = CardMaker('left')
leftCard.setFrame(-1, 1, -1, 1)
leftCard.setColor(1, 1, 1, 0.5)
leftCardNP = render2d.attachNewNode(leftCard.generate())
leftCardNP.setTransparency(1)
leftCardNP.setTexture(leftBuffer.getTexture())
rightCard = CardMaker('right')
rightCard.setFrame(-1, 1, -1, 1)
rightCard.setColor(1, 1, 1, 0.5)
rightCardNP = render2d.attachNewNode(rightCard.generate())
rightCardNP.setTransparency(1)
rightCardNP.setTexture(rightBuffer.getTexture())

# Turn off the main camera, so we don't get them in triplicate.
base.camNode.setActive(0)


base.makeCamera(base.win, displayRegion = (0, 0.5, 0, 1))
base.makeCamera(base.win, displayRegion = (0.5, 1, 0, 1)) 

# Move the eyes apart a little bit, and converge them both on a point
# 20 feet ahead.
base.camList[1].setPos(-0.5, 0, 0)
base.camList[1].lookAt(0, 20, 0)
base.camList[2].setPos(0.5, 0, 0)
base.camList[2].lookAt(0, 20, 0)



#load an environment model
environ= loader.loadModel("models/environment")
environ.reparentTo(render)
environ.setScale(0.25,0.25,0.25)
environ.setPos(-8,42,0)

def SpinCamera1Task(task):
	angledegrees = task.time * 6.0 
	angleradians = angledegrees * (math.pi / 180.0) 
	base.camList[1].setPos(-20*math.sin(angleradians),-20.0*math.cos(angleradians),3) 
	base.camList[1].setHpr(angledegrees, 0, 0) 
	return Task.cont
	
def SpinCamera2Task(task):
	angledegrees = task.time * 6.0 
	angleradians = angledegrees * (math.pi / 180.0)
	base.camList[2].setPos(20*math.sin(angleradians),-20.0*math.cos(angleradians),3) 
	base.camList[2].setHpr(angledegrees, 0, 0) 
	return Task.cont

taskMgr.add(SpinCamera1Task, "SpinCamera1Task")
taskMgr.add(SpinCamera2Task, "SpinCamera2Task")

#Load the panda actor, and loop its animation 
pandaActor = Actor.Actor("models/panda-model",{"walk":"models/panda-walk4"}) 
pandaActor.setScale(0.005,0.005,0.005) 
pandaActor.reparentTo(render) 
pandaActor.loop("walk") 

run()

whats the matter why it looks so stupid what I have done

hey, red-blue stereo output is to see the image with 3d glasses, isn´t? how can I create one? this is cool.

It looks like you have combined code from both of my examples. One of the two above examples creates a pair of side-by-side cameras in the same window; the other overlays them both into the same window. Choose one or the other; you don’t want to run both of them.

Here’s a simple variant for making red-blue stereo pairs. The biggest difference from the above is that I am coloring the two polygons red and blue. I also use ColorBlendAttrib.MAdd for blending the polygons into the frame buffer, which seems to work better.

# Create a pair of offscreen buffers in which to view the "left"
# and "right" eyes.
leftBuffer = base.win.makeTextureBuffer('left', 512, 512)
leftBuffer.setClearColor(VBase4(0, 0, 0, 0))
base.makeCamera(leftBuffer)
rightBuffer = base.win.makeTextureBuffer('right', 512, 512)
rightBuffer.setClearColor(VBase4(0, 0, 0, 0))
base.makeCamera(rightBuffer)
base.win.setClearColor(VBase4(0, 0, 0, 0))

# Create a pair of cards to display the contents of these buffers
# overlayed together in the main window.
leftCard = CardMaker('left')
leftCard.setFrame(-1, 1, -1, 1)
leftCard.setColor(1, 0, 0, 1)
leftCardNP = render2d.attachNewNode(leftCard.generate())
leftCardNP.node().setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MAdd))
leftCardNP.setTexture(leftBuffer.getTexture())
rightCard = CardMaker('right')
rightCard.setFrame(-1, 1, -1, 1)
rightCard.setColor(0, 0, 1, 1)
rightCardNP = render2d.attachNewNode(rightCard.generate())
rightCardNP.node().setAttrib(ColorBlendAttrib.make(ColorBlendAttrib.MAdd))
rightCardNP.setTexture(rightBuffer.getTexture())

# Turn off the main camera, so we don't get them in triplicate.
base.camNode.setActive(0)

# Make sure the new cameras use the same lens as the main camera.
base.camList[1].node().setLens(base.camLens)
base.camList[2].node().setLens(base.camLens)

# Move the eyes apart a little bit.
base.camList[1].setPos(-0.1, 0, 0)
base.camList[2].setPos(0.1, 0, 0)

David

I’m doing a similar scene. I would like to overlay 2 camera frames in the same window. Basically, you click on a card, and the card scales up to almost full screen size. Then I want a scene to play in a frame that takes up the upper half of the card.

My question is this: Can I create a frame and parent it to render instead of render2d, so I can place it in front of the card, so it looks like it’s playing on the card?

edit: and if I can, do I have to destroy the default camera (and create 2 extra ones), or can I just create an additional one for the frame?

more detail: the smaller frame that comes up can be on render2d, since it will always be on top of the card. But the other frame i want to take up the whole camera space (like the regular camera does). I want to be able to move the camera around within a scene off screen and have the scene play out in the small frame on top of the card.

Any suggestions?

Ok, I don’t clearly understand everything you would like to do, but the simple answer is, “yes, it’s all possible.”

There are two approaches. One is to render directly into a rectangular sub-region of the window; I think this may be what you mean when you say “frame”. Panda3D calls this concept a DisplayRegion. Everything Panda3D draws is drawn in a DisplayRegion somewhere; usually, you are rendering into a default DisplayRegion that covers the whole window, but you could have a smaller one that covers just the top portion of the window or a smaller rectangle anywhere within the window. And you can create and destroy as many DisplayRegions as you like, and move them around on the screen, wherever you want them to be, as you are rendering into them. Once you have a DisplayRegion, you can use displayRegion.setDimensions() to move it around on the screen, and displayRegion.setSort() to change its stacking order relative to the other DisplayRegions.

There are two DisplayRegions created by default: one for render, and another one, layered on top of it, for render2d. You can create as many additional DisplayRegions as you want. Each one requires its own camera, and each one can either render the same scene as one of the other DisplayRegions, or a completely different scene of your choosing.

But there are some restrictions on DisplayRegions. A DisplayRegion is always perfectly rectangular, and it always appears completely on top of all the DisplayRegions with a lower sort value.

So it’s possible to have two side-by-side DisplayRegions in a window, and it’s possible to bring one of those to the foreground and have it completely obscure the other one, but you can’t really make a filmy DisplayRegion that you can partially see through to another one (unless your scene is so simple that you don’t require a depth buffer).

On the other hand, you could just forget about this whole DisplayRegion stuff and just render offscreen to a texture, and then slap the texture on a polygon. That’s what I did in the red/blue example and in the overlayed cameras example above. When you do it this way, you can do pretty much anything you darn well please with your different camera views–you can overlay them together, you can color one red and one blue, you could wrap them around a sphere and bounce them up and down if you want. Only downside is that it chews up a little more of your framebuffer memory this way, especially if you have a big window (like 1280x1024).

David

[size=75][color=green]Is there a base.closeWindow() to close the window that you create by making a base.openWindow()? I’m trying to make it to where when you walk up to an enemy another screen will pop up and you fight the enemy/s. Then when the fight is over the screen dissappears.[/size]

Yes, there is a base.closeWindow().

David

[size=75][color=green]Okay thanks. I’ll try it out in my program. ^,^[/size]

[size=75][color=green]I added it in, but it closes both windows. Is there a way to make it so that it calls a certain window?[/size]