Retrieve current transform values from lerped NodePath

Hi,

As I never used Intervals before, I might be missing something obvious, but it seems impossible to retrieve the current transform of a NodePath while it is being lerped.
For example, when I use a LerpQuatInterval on the camera to smoothly change the view, I need to update the position of another object depending on the transform of the camera. When I try to do this in a task, the object’s movement lags behind that of the camera, so it seems that the transform values I retrieve from the camera NodePath are not yet updated to correspond to the actual transform set on its node by the LerpInterval. No matter what value I set for the sort parameter of the task (to make it run after the LerpInterval has set the new transform on the node, but before the scene is rendered), it makes no difference. Also setting bakeInStart to 0 for the LerpInterval doesn’t change anything.

The following code sample should show what I mean; it tries to copy the roll of the big green needle to the small red one, so they would stay together during the lerp, but the red needle is always a step behind the green one.

from panda3d.core import *
from direct.showbase.ShowBase import ShowBase
from direct.interval.IntervalGlobal import LerpHprInterval, Sequence


class Panda3DApp(ShowBase):

    def __init__(self):

        ShowBase.__init__(self)

        self.disable_mouse()
        self.camera.set_y(-10.)

        self.needle1 = needle1 = self.render.attach_new_node(create_needle(1.))
        needle1.set_render_mode_thickness(6)
        needle1.set_color(1., 0., 0.)
        self.needle2 = needle2 = self.render.attach_new_node(create_needle(2.))
        needle2.set_render_mode_thickness(6)
        needle2.set_color(0., 1., 0.)
        needle2.set_y(1.)
        needle2.set_r(85.)

        hpr = VBase3(0., 0., -85.)
        lerp_interval1 = LerpHprInterval(needle2, 1., hpr, bakeInStart=0)
        hpr = VBase3(0., 0., 85.)
        lerp_interval2 = LerpHprInterval(needle2, 1., hpr, bakeInStart=0)
        self.sequence = Sequence(lerp_interval1, lerp_interval2)
        self.sequence.loop()

        self.task_mgr.add(self.__update_needle1, "update_needle1", sort=1000000)

    def __update_needle1(self, task):

        r = self.needle2.get_r()
        self.needle1.set_r(r)

        return task.cont


def create_needle(length):

    vertex_format = GeomVertexFormat.get_v3()
    vertex_data = GeomVertexData("line_data", vertex_format, Geom.UH_static)
    lines = GeomLines(Geom.UH_static)

    pos_writer = GeomVertexWriter(vertex_data, "vertex")
    pos_writer.add_data3f(0., 0., 0.)
    pos_writer.add_data3f(0., 0., length)

    lines.add_next_vertices(2)

    geom = Geom(vertex_data)
    geom.add_primitive(lines)
    node = GeomNode("needle_geom_node")
    node.add_geom(geom)

    return node

My current workaround is to lerp a dummy node and just copy its transform to the object that is supposed to be lerped.

I think it may have to do with the sort value on your task. ivalLoop (which updates intervals) has a sort of 20, whereas igLoop (the render loop) has a sort of 50, so you probably want a sort value in between 20 and 50 if you want to get the transform as reported by the interval but before the frame is rendered.

Ah, you’re right, I was completely oblivious to the sort value of the render loop, so I immediately used too high a sort for my own task.

Thank you, it works now.