lookAt() flipping looker object?

Hi guys,
This might be a stupid question as I’m new to panda…

I’ve been trying to do something with the NodePath.lookAt() method and it seems to flip the node in a strange way when I move the object looking around what it’s looking at (see screen grab).

Here’s the looker and looked at nodes in my scene graph:

PandaNode render S:(CullFaceAttrib RescaleNormalAttrib)

  ActorNode myActor T:(pos 20 200 -20)	# Node I’m moving.
    ModelRoot cones.egg T:(scale 6)	# Looker.
      Character cones
        GeomNode  (1 geoms)

  PandaNode empty T:(pos 5 200 0)	# Looked at.

Any idea why my looker object is flipping?

If I haven’t been clear enough please let me know.

I’ve also tried having the ‘cones’ model sitting directly in ‘render’ and it flips in the same way when I move it around…

NodePath.lookAt() will rotate your model about its own origin: the (0, 0, 0) point of your model. If your model is not centered about (0, 0, 0), then it will appear to move when you rotate it.

The easy way to fix this is to move the origin of your model within the modeling package that you used to create it.

The harder way to fix this is to create a dummy node that compensates for the origin of your model, and parent the model to this new dummy node, and then call lookAt() on the dummy node.

David

Hi,

Thanks for replying - I’m afraid I haven’t been clear enough about the issue :frowning:

The cones are rotating around the axis I expect them to be - it’s that the orientation flips when it passes the other object on the X-axis.

HPR print out:
VBase3(90, -78.6901, -1.74136e-005)
VBase3(0, -90, 0)
VBase3(-90, -78.6901, 1.74136e-005)

Initially I had a force attached to to the arrow to push the actor node along the red arrow (I’ve stripped this out of the example I’m showing).

Problem was the red arrow was flipping in the opposite direction when it passed the larger sphere on the x-axis and it started pushing the actor node back in the opposit direction…

I initially thought this was because they were on the same plane, however this doesn’t seem to be the only time this occurs…

Here is my code if it can help any… sorry it’s a messy but I’m just trying things out…

from direct.directbase.DirectStart import *
from direct.interval.IntervalGlobal import *
from pandac.PandaModules import *
from direct.showbase.DirectObject import DirectObject
from direct.task import Task

########## Setting up scene graph/geometry ###############
an = ActorNode('myActor')              
anp = render.attachNewNode(an)           

cs1 = CollisionSphere(0, 0, 0, 8)                      
cnp = anp.attachNewNode(CollisionNode('cnode'))         # Build collision node parented to actor.
cnp.node().addSolid(cs1)      
cnp.show()                      # Set collision node to show geometry.

# Gimbal attached to actor node.
arrow = loader.loadModel("cones")        # Load cone.
arrow.setScale(6)
arrow.reparentTo(anp)                       # Parent it under actor.

pn = PandaNode("empty")
pnp = render.attachNewNode(pn)
cs2 = CollisionSphere(0, 0, 0, 15)                
cnp = pnp.attachNewNode(CollisionNode('cnode'))        
cnp.node().addSolid(cs2)                                
cnp.show()  # Set collision node to show geometry.

anp.setPos(20,200,-20)    # Little sphere with arrow.
pnp.setPos(5,200,0)     # Big sphere.

######### setting user input ##############

class PmGameInput(DirectObject):
    def __init__(s):
        
        # Location stuff
        s.accept('w-repeat', s.moveZ, [5] )
        s.accept('s-repeat', s.moveZ, [-5] )
        s.accept('a-repeat', s.moveX, [-5] )
        s.accept('d-repeat', s.moveX, [5] )
        s.accept('r-repeat', s.moveY, [5] )
        s.accept('f-repeat', s.moveY, [-5] )
        s.accept('w', s.moveZ, [5] )
        s.accept('s', s.moveZ, [-5] )
        s.accept('a', s.moveX, [-5] )
        s.accept('d', s.moveX, [5] )
        s.accept('r', s.moveY, [5] )
        s.accept('f', s.moveY, [-5] )
        
        s.accept('z', s.testX )
        s.accept('x', s.testY )
        s.accept('c', s.testZ )


    def moveX(s, v):
        anp.setX( anp, v )
        s.onMove()
    def moveY(s, v):
        anp.setY( anp, v )
        s.onMove()
    def moveZ(s, v):
        anp.setZ( anp, v )
        s.onMove()

    
    def testX(s):
        anp.setPos(10, 200, 0)
    def testY(s):
        anp.setPos(5, 210, 0)
    def testZ(s):
        anp.setPos(5, 200, 5)
    
    def onMove(s):
        arrow.lookAt( pnp )
        print arrow.getHpr()

input = PmGameInput()

##### run game engine's main loop ######
run()

I’ve also put the egg file on my server - but as always it’s taking time to show it on there - will post a link when it will let me download it…

Hope this makes more sence now.
Thanks so much for the help :slight_smile:

Hmm, sorry, it’s still not clear what the problem is. If the object is flipping about when the look-at axis starts to coincide with the Z axis, that’s normal, and it’s called gimbal lock. It happens whenever you want to look nearly straight down the same axis that is being used to determine the rotation about the look axis (i.e. the up vector).

You can avoid this by choosing a different axis for the up vector. This is the implicit, last argument to lookAt(), and the default is the z axis. Try specifying the x axis, for instance: nodePath.lookAt(target, Point3(0, 0, 0), Point3(1, 0, 0))

David

Thanks so much David,

That clears things up a lot for me. After looking into gimbal lock it looks like I might need to do something a bit more complicated to achive what I want :slight_smile: