Hi there, I have a problem with a camera I’m trying to set on a fixed point that looks down a vertical tunnel, the camera’s Pitch being -90. Since we’re looking down to a tunnel with the correct pitch, it gives way bottom and top limits, so when I want to look up or down in the tunnel, I’m actually changing the the pitch to -70 and -110 with this:
camera.setHpr(0, -90+mpos.getY()*20, 0)
Now here is the problem: I can’t get the view to change from the left to the right, when the pitch is “up” or “down”! Do I have to mess with Rotation or Yaw? I have tried with Rotation, like this:
camera.setHpr(0, -90+mpos.getY()*20, mpos.getX()*30)
but when the cursor goes from the bottom left to the upper left corner, instead of the camera following it, it crosses the middle to the opposite corner!
I based the camera tilting on “Ball in Maze” and “Looking and Gripping” samples that came with Panda3D.
import direct.directbase.DirectStart
from panda3d.core import Filename,AmbientLight,DirectionalLight
from panda3d.core import PandaNode,NodePath,Camera,TextNode
from panda3d.core import Fog
from direct.task.Task import Task
from direct.gui.OnscreenText import OnscreenText
from direct.showbase.DirectObject import DirectObject
from direct.interval.MetaInterval import Sequence
from direct.interval.LerpInterval import LerpFunc
from direct.interval.FunctionInterval import Func
from math import pi, sin, cos
import sys
#Global variables for the tunnel dimensions and speed of travel
TUNNEL_SEGMENT_LENGTH = 50
TUNNEL_TIME = 2
# Function to put instructions on the screen
def addInstructions(pos, msg):
return OnscreenText(text=msg, style=1, fg=(1,1,1,1),
pos=(-1.3, pos), align=TextNode.ALeft, scale = .05)
# Function to put title on the screen
def addTitle(text):
return OnscreenText(text=text, style=1, fg=(1,1,1,1),
pos=(1.3,-0.95), align=TextNode.ARight, scale = .07)
class World(DirectObject):
def __init__(self):
# Post the instructions
self.title = addTitle("Marco Oliveira first experiment with Panda3D")
self.inst1 = addInstructions(0.95, "Se no Passado nao houve registo")
self.inst2 = addInstructions(0.90, "Da pessoa que eu serei,")
self.inst3 = addInstructions(0.85, "Quando deixar de ser visto")
self.inst4 = addInstructions(0.80, "Foi para o Futuro que viajei!")
base.disableMouse() # disable mouse control in order to place camera
camera.setPosHpr(0, 0, 10, 0, -90, 0) # define coordinates to make the camera face a direction
base.setBackgroundColor(0, 0, 0) # define end of the tunnel with the color black
### Define world map
# define fog
self.fog = Fog('distanceFog')
self.fog.setColor(0, 0, 0)
#Set the density/falloff of the fog. The range is 0-1.
self.fog.setExpDensity(.08)
render.setFog(self.fog)
#Load the tunel and start the tunnel
self.initTunnel()
self.contTunnel()
# Add task to the task manager
taskMgr.add(self.spinCameraTask, "spinCameraTask")
# Code to initialize the tunnel
def initTunnel(self):
#Creates the list [None, None, None, None]
self.tunnel = [None for i in range(4)]
for x in range(4):
#Load a copy of the tunnel
self.tunnel[x] = loader.loadModel('/c/Panda3D-1.8.1/samples/Infinite-Tunnel/models/tunnel')
#The front segment needs to be attached to render
if x == 0:
self.tunnel[x].reparentTo(render)
#The rest of the segments parent to the previous one, so that by moving
#the front segement, the entire tunnel is moved
else:
self.tunnel[x].reparentTo(self.tunnel[x-1])
#We have to offset each segment by its length so that they stack onto
#each other. Otherwise, they would all occupy the same space.
self.tunnel[x].setPos(0, 0, -TUNNEL_SEGMENT_LENGTH)
#Now we have a tunnel consisting of 4 repeating segments with a
#hierarchy like this:
#render<-tunnel[0]<-tunnel[1]<-tunnel[2]<-tunnel[3]
# This function is called to snap the front of the tunnel to the back
# to simulate travelling through it
def contTunnel(self):
# Use slices to put the front of the list in the back
self.tunnel = self.tunnel[1:] + self.tunnel[0:1]
# Set the front segment to 0, which was TUNNEL_LENGTH when
# the segments started
self.tunnel[0].setZ(0)
# Reparent the segment to follow the previous hierarchy
self.tunnel[0].reparentTo(render)
self.tunnel[0].setScale(.155, .155, .305)
self.tunnel[3].reparentTo(self.tunnel[2])
self.tunnel[3].setZ(-TUNNEL_SEGMENT_LENGTH)
self.tunnel[3].setScale(1)
self.tunnelMove = Sequence(
LerpFunc(self.tunnel[0].setZ,
duration = TUNNEL_TIME,
fromData = 0,
toData = TUNNEL_SEGMENT_LENGTH * .305),
Func(self.contTunnel)
)
self.tunnelMove.start()
def spinCameraTask(self, task):
if base.mouseWatcherNode.hasMouse():
mpos = base.mouseWatcherNode.getMouse()
camera.setHpr(0, -90+mpos.getY()*20, 0)
return Task.cont
tunnel = World()
run()