Question

I have an object (say fromObj) stored in NodePath at a 3D point location (say fromPoint). Its heading-pitch-roll (HPR) is (0,0,0). I want to rotate it such that its X-axis points to another point toPoint in space. I just want to compute the HPR that achieves this rotation and use it for some other purpose.

I tried fromObj.lookAt(toPoint), but this points its Y-axis at toPoint. I want its X-axis to point at toPoint.

How do I compute the HPR that will rotate an object such that its X-axis points to a given location in space?

Note: I am aware of this question on StackOverflow: Calculate rotations to look at a 3D point? However, I am looking for a solution that uses existing Panda3D APIs and I want the result in the Panda3D HPR format.

Was it helpful?

Solution

Thanks to the helpful folks on Panda3D forums, I got an easier solution:

def getHprFromTo( fromNP, toNP ):
    # Rotate Y-axis of *from* to point to *to*
    fromNP.lookAt( toNP ) 

    # Rotate *from* so X-axis points at *to*
    fromNP.setHpr( fromNP, Vec3( 90, 0, 0 ) )

    # Extract HPR of *from* 
    return fromNP.getHpr()

If you only have point locations, create dummy nodePaths for the two points to do this calculation.

OTHER TIPS

I do not know how to do this using Panda3D APIs. But it can be done by raw calculations as follows:

def getHprFromTo( fromPt, toPt ):
    """
    HPR to rotate *from* point to look at *to* point
    """

    # Translate points so that fromPt is origin
    pos2 = toPt - fromPt

    # Find which XY-plane quadrant toPt lies in
    #    +Y
    #    ^
    #  2 | 1
    # ---o---> +X
    #  3 | 4

    quad = 0

    if pos2.x < 0:
        if pos2.y < 0:
            quad = 3
        else:
            quad = 2
    else:
        if pos2.y < 0:
            quad = 4

    # Get heading angle

    ax   = abs( pos2.x )
    ay   = abs( pos2.y )
    head = math.degrees( math.atan2( ay, ax ) )

    # Adjust heading angle based on quadrant

    if 2 == quad:
        head = 180 - head
    elif 3 == quad:
        head = 180 + head
    elif 4 == quad:
        head = 360 - head

    # Compute roll angle 

    v    = Vec3( pos2.x, pos2.y, 0 )
    vd   = abs( v.length() )
    az   = abs( pos2.z )
    roll = math.degrees( math.atan2( az, vd ) )

    # Adjust if toPt lies below XY-plane

    if pos2.z < 0:
        roll = - roll

    # Make HPR
    return Vec3( head, 0, -roll )

The basic idea is imagine your head stationary at fromPoint in space. Your head (or eyes) is facing along +ve X axis, +ve Y axis comes out of your left ear and your up vector is +ve Z axis. Somewhere in the space around you is the toPoint.

To look at it, you first rotate your head (like in horror movies) in the global XY plane until toPoint is above or below you. This is the heading angle.

Now you lift your head up or down to finally to get the toPoint in your sight. This is the roll angle. Note that this is roll and not pitch, though it seems like that. This is because it is roll in the coordinate system of your head. And this gives you the HPR!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top