Rotating camera incorrect

I wrote a simple code to rotate the camera but it only works with yaw. When I use the exact same code to rotate the pitch, it gets wrong (it seems to run from -90 to 90).

Here is the code:

from panda3d.core import GeomVertexFormat,
GeomVertexData, GeomVertexWriter, Geom, GeomNode, GeomLines

from direct.showbase.ShowBase import ShowBase
from direct.task import Task
import numpy as np
import math
from pdb import set_trace as bp

def make_axes():
vformat = GeomVertexFormat.get_v3c4()
vdata = GeomVertexData(‘vdata’, vformat, Geom.UHStatic)
vdata.uncleanSetNumRows(6)

vertex = GeomVertexWriter(vdata, 'vertex')
color = GeomVertexWriter(vdata, 'color')

for x, y, z in np.eye(3):
    vertex.addData3(0, 0, 0)
    color.addData4(x, y, z, 1)
    vertex.addData3(x, y, z)
    color.addData4(x, y, z, 1)

prim = GeomLines(Geom.UHStatic)
prim.addNextVertices(6)

geom = Geom(vdata)
geom.addPrimitive(prim)
return geom

def euler_to_xyz(roll, pitch, yaw, distance):

roll_rad = math.radians(roll)
pitch_rad = math.radians(pitch)
yaw_rad = math.radians(yaw)

x = distance * math.cos(yaw_rad) * math.cos(pitch_rad)
y = distance * math.sin(yaw_rad) * math.cos(pitch_rad)
z = distance * math.sin(pitch_rad)

return x, y, z

class MyApp(ShowBase):

def __init__(self):

    ShowBase.__init__(self)

    geom_axis = make_axes()
    
    geom_axis_node = GeomNode('axis')
    geom_axis_node.addGeom(geom_axis)
    self.render.attachNewNode(geom_axis_node)

    self.taskMgr.add(self.spinYawCameraTask, "spinYawCameraTask")
    self.taskMgr.add(self.spinPitchCameraTask, "spinPitchCameraTask")

def spinYawCameraTask(self, task):

    angleDegrees = task.time * 40.0
    # roll, pitch, yaw
    x,y,z = euler_to_xyz(0, angleDegrees, 20, 30)
    self.camera.setPos(x,y,z)
    self.camera.lookAt(0, 0, 0)
    x,y,z = self.camera.getPos()

    return Task.cont

def spinPitchCameraTask(self, task):

    angleDegrees = task.time * 40.0
    # roll, pitch, yaw
    x,y,z = euler_to_xyz(0, angleDegrees, 10, 30)
    self.camera.setPos(x,y,z)
    self.camera.lookAt(0, 0, 0)
    x,y,z = self.camera.getPos()

    return Task.cont

app = MyApp()
app.run()

If I output the pitch- and z- values that appear in your “euler_to_xyz” function, it looks to me like they’re as expected.

And looking more closely at the rotation that results, it seems to me that the problem isn’t that the pitch is limited to the range (-90, 90), but rather that the camera’s orientation flips around its forward axis when passing the world’s vertical axis.

As such, I think that the problem is likely in the effect of the “lookAt” method: it’s getting confused about its expected orientation when it passes the world’s vertical axis.

(Perhaps as a result of gimbal lock? I’m not sure.)

This might be a situation in which the use of quaternions would be more reliable.

yeah I got it. It seem like the the effect of the “lookAt”. I tried to used setHpr and it seem fine.

1 Like

Perhaps this is due to the lookAt constraint, it is workable until you rotate the object along the axis of the vector that sets the top.

1 Like