GeomDrawCallbackData - the getObject () method is not available

API documentation declares method getObject() for the GeomDrawCallbackData class. However, when trying to use:

  File "main.py", line 6, in init
    d = cbdata.getObject ()
AttributeError: 'panda3d.core.GeomDrawCallbackData' object has no attribute 'get
Object '

Apparently CullableObject is not exposed to Python, so getObject cannot be implemented.

However, what do you intend to gain from this? I do not believe that CullableObject has any public APIs at the moment. We would need to expose some APIs from this class depending on what you would like to do with it.

Actually get a link to the CallbackNode node that called. I know that the render tree does not store much information. However, it is somehow connected.

For example, need to reproduce the calculations with the object if it is in the frame and so on.

Panda3D doesn’t store the original node object in the CullableObject. We could however add methods to return the RenderState or the modelview transformation of the node.

When assigning the callback to the node, we could probably make it possible to pass along some extra data, so that you could pass in the node object or something.

I think that would be helpful. Create a scene manager in a lazy way. For example, animation playback should be disabled if the object is outside the camera area and, therefore, unload the CPU. Although, perhaps, the panda is already doing this, but I do not know. Other ways are possible, for example, to realize the game. If the player does not see a particular scene, then make changes on the fly. This technique is used in horror, for example, the ball changes its position when it is not seen. In fact, many ways.

I think you should consider using a cull callback instead of a draw callback for things like that. With a cull callback, you do still have access to the original node object, and it’s still only called if the parent object is in view. And, you can use it to do custom culling checks.

In a cull callback, you can call getData() on the callback data, which returns a CullTraverserData object. This has a node() method to get the underlying PandaNode, and ways to obtain the accumulated transformation.

For the record, Panda3D’s animation system does not animate models that are out of view.

1 Like

This works, but the panda model node becomes invisible. I also tried the reverse order, I attached CallbackNode to the panda model node and it also became invisible (debug geometry) with this all working as expected.

from panda3d.core import CallbackNode, BoundingBox
import direct.directbase.DirectStart

def init(cbdata):
    print (cbdata.getData().node().getName())
    pass

cbnode = CallbackNode("cbnode")
cbnode.setBounds(BoundingBox())
cbnode.setCullCallback(init)
cbnp = render.attachNewNode(cbnode)
cbnp.showBounds()

mpanda = loader.loadModel("panda")
mpanda.reparentTo(cbnp)

base.run()

I wonder why created a separate callback node instead of adding the required method to the Node class?

I think you specifically need to call cbdata.upcall() to ensure that the node is still culled properly, and Panda continues to traverse the scene graph. You would avoid calling it if you don’t want the node to be rendered.

As for why we need a special CallbackNode, that’s a good point; for a draw callback we do need a node, but for a cull callback, we could make something like a CullCallbackEffect that you assign to a node using setEffect. Feel free to make a feature request for this if you need this.

1 Like

I seem to have forgotten that Panda3D has a lot of nodes for different purposes. I think it will be better if everything remains as before.

Решение: setDrawCallback заменить setCullCallback

from panda3d.core import CallbackNode, BoundingBox
import direct.directbase.DirectStart

def init(cbdata):
    print (cbdata.getData().node().getName())
    cbdata.upcall()

cbnode = CallbackNode("cbnode")
cbnode.setBounds(BoundingBox())
cbnode.setCullCallback(init)
cbnp = render.attachNewNode(cbnode)
cbnp.showBounds()

mpanda = loader.loadModel("panda")
mpanda.reparentTo(cbnp)

base.run()