Referencing models

When I use the demo from the manual: panda3d.org/manual/index.php … anda_Model
everything works fine.

But the problem is I don’t want to reference the panda in the class field to get the animation working. When I change the pandaActor to be a local variable, animation disappears.

This is stupid.

I wont say why, because any sober-minded, or at least thinking programmer wouldn’t come to the idea that one has to reference a model in class field in order to let it be animated.

This quirk is brought up in the manual pages for actors (panda3d.org/manual/index.php … Animations). The page you were looking at is just a demonstration of how to do some simple things in panda, so it doesn’t mention everything.

I agree it’s a weird thing to need to do, but why don’t you want to keep a pointer to your actor class around? If you don’t have the pointer you can’t change anything.

Guess if this works:

from math import pi, sin, cos

from direct.showbase.ShowBase import ShowBase
from direct.task import Task
from direct.actor.Actor import Actor
 
class MyApp(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)
 
        # Load the environment model.
        self.environ = self.loader.loadModel("models/environment")
        # Reparent the model to render.
        self.environ.reparentTo(self.render)
        # Apply scale and position transforms on the model.
        self.environ.setScale(0.25, 0.25, 0.25)
        self.environ.setPos(-8, 42, 0)
 
        # Add the spinCameraTask procedure to the task manager.
        self.taskMgr.add(self.spinCameraTask, "SpinCameraTask")
 
        # Load and transform the panda actor.
        Attacher(self.render)
 
    # Define a procedure to move the camera.
    def spinCameraTask(self, task):
        
        angleDegrees = task.time * 6.0
        angleRadians = angleDegrees * (pi / 180.0)
        self.camera.setPos(20 * sin(angleRadians), -20.0 * cos(angleRadians), 3)
        self.camera.setHpr(angleDegrees, 0, 0)
        return Task.cont
 
 
 
class Attacher:
    def __init__(self, render):
        self.pandaActor = Actor("models/panda-model",
                               {"walk": "models/panda-walk4"})
        self.pandaActor.setScale(0.005, 0.005, 0.005)
        self.pandaActor.reparentTo(render)
        # Loop its animation.
        self.pandaActor.loop("walk")
        
app = MyApp()
app.run()

In all fairness, I imagine that in most cases – this has been my experience, at least – one will tend to keep a reference to the Actor in order to play or stop animations as desired.

Does your idea work? I’m inclined to guess that it doesn’t, because I would imagine that your “Attacher” instance likely gets garbage collected once the “init” method exits, and thus its stored Actor gets cleaned up too.

For cases in which you want to “fire and forget” Actors, perhaps it might be a better idea to put them into a list member of your main class (or some appropriate class). This also has the advantage of allowing you to specify when they are destroyed, such as at the end of a level.

The point is - if I want an animation to continue - I have to keep the object reference down the class hierarchy tree.
That is not what programming is about. Programming languages are designed to be explaining things in strict and predictable way, but this trick gives it all up.

Fair enough – although I doubt that you’ll likely find a “perfect” engine; I would expect to encounter at least some quirks, such as this one in this engine.

I’m not saying that the engine wouldn’t be improved if this were removed – I think that it would be – just that it doesn’t seem all that terrible to me.

As I think is mentioned in one of the pages linked-to above, it arises, I believe, as a result of the way that they handle NodePaths and Actors; I think that I recall some mention elsewhere of reworking how they approach Actors for 1.9.0 (although I think that that’s not likely to arrive at all soon).

Thank You for pointing for the tutorial pages and for telling about the “garbage collection” (indeed this shouldn’t be called garbage collection). I’ll probably use other game engine.

It’s not a feature of Panda, really, it’s a feature of Python (and most programming languages). If you want to preserve an object, you should keep a reference to it. Pretty much every other game engine uses that principle.

In this case, there’s a bit of a weird thing going on because the object that stores the geometry (the GeomNode) is implemented in C++ and stored in the scene graph, whereas the object that stores the animation info (the Actor) is implemented in Python and stored by you in the Python environment. So, if you let the Actor instance go out of scope, it will get cleaned up while the underlying GeomNode remains in the scene graph.

Still, it makes sense; how can you animate an object without being able to acquire a reference to control that animation? Since the Actor object is not stored in the scene graph, the only logical solution is that the animation disappears as soon as the reference to it goes out of scope.

I’m not sure why you have this strange objection to storing a reference to an object when you want it to continue existing; in fact, not creating a reference to an object will in most cases cause it to disappear entirely (with animations and all). It is only the fact that Panda stores the geometry in the scene graph that keeps the geometry from disappearing.

If it worked as you imagine, you’d create a memory leak; because you would not have any way to access the object or delete it from memory any more since you’d no longer be storing a reference to it.

If you still think it’s “stupid” that an object is deleted when there are no more references to it, you should go and relearn some of the basic concepts behind OOP programming languages, because you’ll be running into issues with any game library that you use.

Nice answer rdb =) I wished a “like” button.

I personally found it very annoying that kind of reasoning. “mimimi, I’ll use other engine”
And I guess it’s kinda a side effect of some of the way engines chose to work, although I don’t think it’s the engine’s fault.

The programmer should be able to understand how things works. How to code. And not just how some tools work with it’s 10000 abstractions. Although it’s important to optimize the process, it’s important to understand the basics.

The fire and forget feature alongside with the “Destroy(object)” type of thing is quite common in game development, and several tools (many visual/editor-based) chose to use it. I guess it’s ok the engine to handle that for you (even because you could have “instanced” it in the editor) and ask you to tell it when you want that object destroyed.

But I guess it’s not a reason to “any sober-minded, or at least thinking programmer” not understand basic concepts of scope and garbage collection. I mean… you could miss that and make a mistake as you were used to other style or whatever reason. Completely fine. But from there to “I’ll use other engine”, “That is not what programming is about” is kinda a long way…

Sorry for the rant, maybe the post was the trigger for some old thoughts and I might just misinterpreted it…


I didn’t make a personal attack on you, so that was quite uncalled for. If you have a good reason for disagreeing, you should share it. Resorting to expletives and personal attacks when you disagree with someone is never a mature or effective way to convince people.