Saturday, January 15, 2011

Camera control program

Well, what we have here is a class you can add to your programs to control your camera much like you would in a strategy game without a central actor. It's really good for experements and I hope you use it. In your main program you are going to want to add the line:
from cam import Cam as well as self.cam=Cam() to any program. You will want to remove the marker actor that shows where the center of the camera from your finished project or maybe put something like a colored lamp to make it look classy. In the meantime find some model to put in there, obviously it's not going to work out of the box for that reason.

from direct.showbase.DirectObject import DirectObject
import sys, time
from direct.gui.OnscreenText import OnscreenText
from pandac.PandaModules import *
from direct.actor.Actor import Actor
from math import sin, cos, radians

class Cam(DirectObject):

def __init__(self):
#camr Movement
self.vel = Vec3(0.0,0.0,0.0)
self.spin=Vec3(0, 0, 0)
self.forwardspeed = 19.0
self.backspeed = 17.0
self.risespeed=10.0
self.rotspeed=1
self.pitspeed=1
self.zoomrate=10
self.zoomlvl=10
#Hide mouse
props = WindowProperties()
props.setCursorHidden(False)
base.win.requestProperties(props)
base.disableMouse()


#create the camr
self.camr = NodePath(ActorNode("camr"))
self.camr.reparentTo(render)
base.camera.reparentTo(self.camr)
self.marker = Actor("/home/stephen/daes/marker.x" )
self.marker.reparentTo(self.camr)
self.camr.setPos(0,0,100)
base.camera.setPos(0, self.zoomlvl, 0)
base.camera.lookAt(self.camr)
self.marker.setColor(1, 0, 0)
self.camr.setP(self.camr, 35)
self.camr.setPos( 0, 0, 0 )
self.marker.setScale(0.2)
#Grab input and run task
self.accept("escape", sys.exit)
self.keyMap = {"forward":0,"backward":0,"strafeleft":0,"straferight":0,"riseup":0,"risedown":0, "lookdown":0, "lookup":0 }
self.accept("w",self.setKey, ["forward",1])
self.accept("s",self.setKey, ["backward",1])
self.accept("a",self.setKey, ["strafeleft",1])
self.accept("d",self.setKey, ["straferight",1])
self.accept("wheel_up", self.zoom, [1])
self.accept("wheel_down", self.zoom, [-1])
self.accept("z",self.setKey, ["riseup",1])
self.accept("x",self.setKey, ["risedown",1])
self.accept("w-up",self.setKey, ["forward",0])
self.accept("s-up",self.setKey, ["backward",0])
self.accept("a-up",self.setKey, ["strafeleft",0])
self.accept("d-up",self.setKey, ["straferight",0])
self.accept("z-up",self.setKey, ["riseup",0])
self.accept("x-up",self.setKey, ["risedown",0])
self.accept("q",self.setKey, ["lookdown", 1])
self.accept("q-up",self.setKey, ["lookdown", 0])
self.accept("e",self.setKey, ["lookup", 1])
self.accept("e-up",self.setKey, ["lookup", 0])


taskMgr.add(self.updatecamr, "updatecamr")
self.setupTxt()
def zoom(self, amt):
self.zoomlvl+=amt*self.zoomrate
base.camera.setPos(0, self.zoomlvl, 0)
def updateTxt(self):
self.poso.destroy()
self.oro.destroy()
self.setupTxt()
def setupTxt(self):
self.poso=OnscreenText(`self.camr.getPos()`, pos = (-1.3, .95-.05*0), fg=(1,1,1,1), align = TextNode.ALeft, scale = .05, mayChange = 0)
self.oro= OnscreenText(`self.camr.getHpr()`, pos = (-1.3, .95-.05*1), fg=(1,1,1,1), align = TextNode.ALeft, scale = .05, mayChange = 0)


def setKey(self, key, value):
self.keyMap[key] = value

def updatecamr(self, task):
"""Big task that updates the camrs position every tick"""
elapsed = globalClock.getDt()
# reset mouse coords for next iteration
x = 0.0
y = 0.0
z = 0.0
rot=0.0
pit=0.0
#Move the camr around
if (self.keyMap["strafeleft"]!=0):
rot = -self.rotspeed
self.camr.setH(self.camr.getH()%360)
if (self.keyMap["straferight"]!=0):
rot = self.rotspeed
self.camr.setH(self.camr.getH()%360)
if (self.keyMap["forward"]!=0):
x = self.forwardspeed *sin(radians(self.camr.getH()))
y = - self.forwardspeed *cos(radians(self.camr.getH()))
if (self.keyMap["backward"]!=0):
x = -self.forwardspeed *sin(radians(self.camr.getH()))
y = self.forwardspeed *cos(radians(self.camr.getH()))
if(self.keyMap["riseup"]!=0):
z= self.risespeed
if(self.keyMap["risedown"]!=0):
z= -self.risespeed
if(not(self.camr.getP()>=70) and (self.keyMap["lookup"]!=0)):
pit+= self.pitspeed
if(not(self.camr.getP()<=10) and (self.keyMap["lookdown"]!=0)):
pit-= self.pitspeed
# (x, y)=(sin(radians(self.camr.getH())), cos(radians(self.camr.getH())))
self.vel = Vec3(x,y,z)
self.vel *= elapsed
self.spin=Vec3(rot, pit, 0.0)
#self.spin *= elapsed
self.camr.setFluidPos(self.camr.getPos()+ self.vel)
self.camr.setHpr(self.camr.getHpr()+ self.spin)
#self.camr.setP(pit)
self.updateTxt()
return task.cont


Summery of Intent

I'm setting this up as a blog to document my attempts to learn Panda3d in python. I encourage you, the reader, to ask questions and make suggestions. I will post some of the code I've been working on and you are free to use it in your own projects but I hope you will let me know if you find it helpful and how you've improved it. I've been at the API for a week or two over break so I'm just getting started but I'd be glad to walk you through anything via Skype or a chat client.