Wednesday, June 25, 2008

Panda3D in a Global Immersion Dome

To the outside world (at least the four or five people that have visited my blog), the topics covered must appear seemingly random from week to week. Well, this week is no exception! I really like what I'm doing, because I never know what's around the next corner. Really, my experience is probably not all that new. It seems like deep knowledge of a narrow area has its place (e.g. the hot-shot Oracle DB administrator), but that doesn't seem to be the game anymore. Rather, the ultra-adaptable, multi-lingual (C, C++, Java, Python, Ruby, etc.) developer who can work in any environment or platform, multi-task, and turn on a dime, and work in multiple teams at once seems to be the profile. I'm not saying that I am the best example, but it's what I'm striving to be.

That said, I thought I'd pass along this tidbit from my latest adventure...

Serious gaming is a hot topic on campus. How can we utilize game engine platforms to create new tools for simulation, interactive visual applications, training, and learning? Marry this with unique assets such as an interactive dome, an ultra-high (4K) resolution stereo environment, and a cool 360-degree 'viz wall', and it gets even more interesting. Over the summer, my group is exploring this intersection of game engines, and unique environments, and reaching out to folks on campus to find like-minded 'explorers'.

The true topic of this post is getting Panda to work in our dome, which turned out to be fairly straight forward. The example I'm using is a bit 'hackey', because it reflects a lot of trial-and-error. Python is great for this fortunately. I'll try and annotate what did the trick, using the baked in Panda and scene you get with the download...


# our dome has a 2800x2100 display, create a window at the 0,0 origin with no borders like so...

from pandac.PandaModules import loadPrcFileData
loadPrcFileData("", """win-size 2800 2100
win-origin 0 0
undecorated 1""")

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

# create a function that sets up a camera to a display region, pointing a given direction
# note that we're essentially creating one borderless window divided into four equal regions.
# each region depicts a camera with a precise eye-point and aspect ratio.
#
# NOTE this geometry is particular to our dome

def createCamera(dispRegion, x, y, z):
camera=base.makeCamera(base.win,displayRegion=dispRegion)
camera.node().getLens().setViewHpr(x, y, z)
camera.node().getLens().setFov(112,86)
return camera

# set the default display region to inactive so we can remake it

dr = base.camNode.getDisplayRegion(0)
dr.setActive(0)


#settings for main cam, which we will not really be displaying. Actually, this code might be
# unnecessary!

base.camLens.setViewHpr(45.0, 52.5, 0)
base.camLens.setFov(112)


# set up my dome-friendly display regions to reflect the dome geometry

window = dr.getWindow()
dr1 = window.makeDisplayRegion(0, 0.5, 0, 0.5)
dr1.setSort(dr.getSort())
dr2 = window.makeDisplayRegion(0.5, 1, 0, 0.5)
dr2.setSort(dr2.getSort())
dr3 = window.makeDisplayRegion(0, 0.5, 0.5, 1)
dr3.setSort(dr3.getSort())
dr4 = window.makeDisplayRegion(0.5, 1, 0.5, 1)
dr4.setSort(dr4.getSort())


# create four cameras, one per region, with the dome geometry. Note that we're not using the
# base cam. I tried this at first, pointing the base cam at region 1. It worked, but it threw the
# geometry off for some reason. The fix was to create four cameras, parent them to the base
# cam, and off we go.

cam1 = createCamera((0, 0.5, 0, 0.5), 45.0, 52.5, 0)
dr1.setCamera(cam1)
cam2 = createCamera((0.5, 1, 0, 0.5), -45.0, 52.5, 0)
dr2.setCamera(cam2)
cam3 = createCamera((0, 0.5, 0.5, 1), 135.0, 52.5, 0)
dr3.setCamera(cam3)
cam4 = createCamera((0.5, 1, 0.5, 1), -135, 52.5, 0)
dr4.setCamera(cam4)

# loading some baked-in model

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

cam1.reparentTo(base.cam)
cam2.reparentTo(base.cam)
cam3.reparentTo(base.cam)
cam4.reparentTo(base.cam)

# rest of code follows...this works!

No comments: