I’m trying to implement a way to move the camera view around in my program and I’ve used the functionality provided in the Roaming Ralph sample program.
It’s pretty much exactly what I need for now, however, it doesn’t quite work the same in my program.
The camera view can move around fine, but the model to which the camera is attached vibrates weirdly on the spot and I can’t seem to figure out why.
Here is my code:
from direct.showbase.ShowBase import ShowBase
from direct.interval.IntervalGlobal import *
from panda3d.core import WindowProperties
from panda3d.core import Vec3, Vec4, VBase4
from panda3d.core import GeoMipTerrain
from panda3d.core import AmbientLight, PointLight, DirectionalLight, Spotlight, PerspectiveLens
from panda3d.core import NodePath, PandaNode, Camera, TextNode
import sys
import os
print("Imports successful!")
# Measuring units in Panda3D are arbitrary, so I've set 1 unit to equal 1m
MARS_RADIUS = 3389500 # m
LANDER_RADIUS = 1 # m
MARS_DAY = 88620 # s
class MarsLander(ShowBase):
def __init__(self):
ShowBase.__init__(self)
# The default mouse controls take precedence over base.camera (or self.camera in this case, since MarsLander inherits from ShowBase)
# Disabling default mouse controls allows base.camera to be manipulated
self.disableMouse()
self.load_mars()
self.load_lander()
# Create a floater object, which floats 2 units above the lander
# We use this as a target for the camera to look at
self.floater = NodePath(PandaNode("floater"))
self.floater.reparentTo(self.lander)
self.floater.setZ(0.0)
# Create a keymap to store which keys are currently pressed
self.keyMap = {
"cam_left": 0,
"cam_right": 0,
"cam_up": 0,
"cam_down": 0
}
# Accept the control keys for the program
self.accept("escape", sys.exit)
self.accept("a", self.setKey, ["cam_left", True])
self.accept("a-up", self.setKey, ["cam_left", False])
self.accept("d", self.setKey, ["cam_right", True])
self.accept("d-up", self.setKey, ["cam_right", False])
self.accept("w", self.setKey, ["cam_up", True])
self.accept("w-up", self.setKey, ["cam_up", False])
self.accept("s", self.setKey, ["cam_down", True])
self.accept("s-up", self.setKey, ["cam_down", False])
taskMgr.add(self.move_camera, "move_camera_task")
self.configure_camera()
self.lander_light()
def move_camera(self, task):
dt = globalClock.getDt()
if (self.keyMap["cam_left"]):
self.camera.setX(self.camera, +100 * dt)
if (self.keyMap["cam_right"]):
self.camera.setX(self.camera, -100 * dt)
if (self.keyMap["cam_up"]):
self.camera.setZ(self.camera, -100 * dt)
if (self.keyMap["cam_down"]):
self.camera.setZ(self.camera, +100 * dt)
self.camera.lookAt(self.floater)
#print(self.camera.getPos())
return task.cont
def setKey(self, key, value):
'''Records the state of the arrow keys'''
self.keyMap[key] = value
def load_mars(self):
'''Load Mars model into the program, attach it to the scene graph (root node in this case) so it can render, set its position and its scale'''
self.mars = self.loader.loadModel("models_and_textures/mars/mars.obj")
self.mars.reparentTo(self.render)
self.mars.setPos(0, 0, 0)
self.mars_model_size = float(str(self.mars.getBounds()).split()[-1])
self.mars_scale_factor = MARS_RADIUS / self.mars_model_size
self.mars.setScale(self.mars_scale_factor)
def load_lander(self):
'''Load lander model into the program, render it, set position and scale'''
self.lander = self.loader.loadModel("models_and_textures/lander/lander.obj")
self.lander.reparentTo(self.render)
self.lander_model_size = float(str(self.lander.getBounds()).split()[-1])
self.lander_scale_factor = LANDER_RADIUS / self.lander_model_size
self.lander.setScale(self.lander_scale_factor)
self.lander.setPos(0, -1.2 * MARS_RADIUS, 0)
#print(self.lander.getBounds())
print("Lander position relative to origin is: ", tuple(self.lander.getPos()))
def configure_camera(self):
'''Set up the camera to always be 'connected' to and looking at the lander'''
self.camera.reparentTo(self.lander)
self.camera.setPos(0, -100, 0)
#self.camera.lookAt(0, 0, 0)
print("Camera position relative to lander is: ", tuple(self.camera.getPos()), "\n")
#self.cameraNode = self.render.attachNewNode('cameraNode')
#self.camera.wrtReparentTo(self.cameraNode)
# The default field of view angle is 40 degrees, increasing it to 50 widens the view field
self.camLens.setFov(50)
# The default far distance of the lens frustum is set at 1000.0 units, so Mars is too far away to be rendered
# Increasing it to 10 million puts Mars in the lens frustum so it can be rendered
self.camLens.setFar(10000000)
def lander_light(self):
'''Materials on models don't show up without a light specifically aimed at the model'''
frontLight = PointLight("front light")
frontLight.setColor(VBase4(1, 1, 1, 1))
self.frontLightNodePath = self.render.attachNewNode(frontLight)
self.frontLightNodePath.setPos(self.lander.getPos() + (10, 10, 2))
self.lander.setLight(self.frontLightNodePath)
backLight = PointLight("back light")
backLight.setColor(VBase4(1, 1, 1, 1))
self.backLightNodePath = self.render.attachNewNode(backLight)
self.backLightNodePath.setPos(self.lander.getPos() + (10, -10, 2))
self.lander.setLight(self.backLightNodePath)
mars_lander = MarsLander()
mars_lander.run()
This video shows the issue: