Is it possible to extract objects from a loader.loadmodel object as their own objects?

Yikes! I do apologize for asking so soon, but I did not expect to get stumped this soon, my problem now is, is it is possible to move objects created in blender3d that were loaded through the loader.loadmodel process away from the parent and to function like the parent?

Like a mesh just loaded through loader.loadmodel utilizing the polyset collisions it came in with?

For example lets say I created a playground scene and within that scene I created a ball object then loaded the whole scene into panda3d though the loader.loadmodel process, how would I make that ball already loaded into panda3d it’s own node separated from it’s parent?

I tired many things for hours like reparenting it to empty nodes, purely referencing it’s name through the find function, reparenting it directly to render itself, and even detaching it, but still I cannot get it to be transparent or even stash itself.

I give a big thanks for any response.

The solution is actually 2 posts by Thaumaturge, the post under this one, and the one I marked as the solution (the one that lead to the discovery), simply the fallow the one under this but add .getParent() after .find("**/ball")

Using “find” to acquire it and then reparenting to some other node it should work, I believe. Are you sure that “find” did, in fact, locate the element that you were looking for? (Noting for safety’s sake that “find” returns an empty node when it fails, rather than “None”, if I recall correctly.)

In order both to check myself and to serve as a working example, here’s a quick test that I put together:

To start with, in order to have a simple test to work with, I made a small “scene” in Blender. As shown below, it consists of only a plane and a sphere, the latter being named ball and a child of the plane. This “ball” will be the sub-model that we attempt to extract.
Screenshot from 2020-03-18 16-08-48

This is then loaded into the following program. The program first loads the model, then prints its content for reference. When the user presses the space-bar, the program looks for the ball sub-model, and if found, it separates it and moves it. That done, it once again prints the content of the main model, to check that the ball is indeed no longer attached there.

from direct.showbase.ShowBase import ShowBase

class Game(ShowBase):
    def __init__(self):

        self.accept("escape", base.userExit)

        self.model = loader.loadModel("testModel")
        self.model.setPos(0, 10, -1)

        self.accept("space", self.getBall)

    def getBall(self):
        self.ball = self.model.find("**/ball")
        if not self.ball.isEmpty():
            print ("Ball found!")
            self.ball.setPos(2, 10, 1)

app = Game()

On my machine, with this test-model, the above seems to work as expected: the ball is separated and moved, and the output of “ls” confirms that it’s no longer attached to the loaded model.

There is one caveat to doing this: if, prior to searching for your sub-model, you call “flattenStrong” on the loaded model (or perhaps “flattenMedium”; I’m not sure), then the sub-model that you’re attempting to extract may have been flattened into the rest of the model, and thus no longer be available.

All that said, if you’re not flattening your model and the above example and description doesn’t help, then perhaps it might be useful to see the relevant parts of your code.

So I just tried this, and the object just lost all it’s collision properties, other than that no transparency or stashing, thanks for the lead though, I,m going to continue to test this as I type.

Edit: maybe it has something to do with it’s collision node not porting?

How did you export your collision geometry? And if you view you model in PView and press “shift-c”, does the collision geometry show up?

[edit] I’m not sure about stashing, but if the transparency was applied to a node above the one that you’re removing, then it would indeed be lost.

I use blender3d game properties to add strings like “Collide - Polyset keep descend”

Ah–in that case, note that doing so (specifically, using the “keep” keyword) will, if I’m not much mistaken, create two sub-models: one for visible geometry, and one for collision geometry. Hence the extraction of one not also acquiring the other.

is there a way to port the collision geometry or is it lost in the transition?

Edit: I would imagine a collision node since polyset is a collision solid right?

I’m not sure of what you mean by “port”. The collision mesh should be there, just as the visible mesh is. They’re just two separate meshes.

Try loading your model and calling “ls” on it–something like this:

myModel = loader.loadModel(<your model file>)

That should tell you what the loaded model contains.

If I’m not much mistaken, “polyset” basically means “interpret this object as a polygonal collision model”; by contrast, you could instead have it generate another collision shape, like a sphere.

Whether you use “polyset” or another keyword there, you should end up with a collision node (inside a NodePath, as per usual), indeed.

sorry it meant move it with the geometry to render.

Edit: ls() is returning None.

That should be perfectly possible: just identify the collision-geometry and extract it as you did with the visible geometry.

The main trick is identifying it: I think that I recall that it won’t have the same name as the original node, with that name being used (presumably) by the visible geometry.

If you use “ls” as described above, you should be able to identify what name it has in this specific model–but I don’t know offhand whether there’s a reliable pattern to how the model is renamed, and if there is, what it might be.

You could also rework you model in Blender slightly such that the visible and collision geometry are generated by separate meshes (then dropping the “keep” in the “collide” tag, I imagine). That way you have control over the names of both.

[edit] Indeed, ls returns “None”–but it prints data to the terminal.

I don’t know if it is because I,m running in IDLE shell or not, but ls() outputs nothing (adding “print” gives a error), I imagine that the shell functions the same way as terminal because my analyze stats are being constantly printed there.

Hm. I’ve not seen that before! (I don’t use IDLE myself, so I’m not familiar with it. Perhaps it’s redirecting certain types of output automatically.)

Perhaps run your game directly from a terminal, then? That should give you your output.

I got the print function to work, it was bad syntax on my part, but yeah still nothing, I don’t know if my computer is setup to run panda3d from terminal.

Edit: okay it is printing something, it’s printing “None” I did not see it at first with my analyze stats on the shell.

As I said, “ls” returns “None”, which is why it’s printing that. Instead, “ls” internally prints to the terminal itself. If you’re not seeing that output, then try running your game directly from a terminal (i.e. not within IDLE, which might be redirecting some types of output).

1 Like

hmm, I will see if I can.

Edit: I did it, I fallowed the steps similar to packing the game for runtime, yes it displays some information, so what I,am looking for? the objects?

Edit: so it appears that there are collision nodes named as the objects I named in blender3d, maybe it needs to re-added to base.cTrav

Edit3: I think I see, yes the collision nodes named after the object in blender are now gone, but the PandaNode and GeomNode still remain, and I think the GeomNode is the appearance, but if that is true, then it begs the question, what happened the collision node? I reparented it to render so, it should still be there.

Edit4: getting the parent node worked! I marked your post as the solution because it ls() lead to this discovery.

1 Like

Ah, I’m glad that you got it working! :slight_smile:

By the way, for future reference you should, in general, be able to run your game in a terminal by just doing the following in said terminal:
(Presuming that the terminal is currently in the directory that holds your game’s main Python file.)

(Whether you use “python3” or “python”–or even “ppython”–may depend on your particular setup.)

1 Like

yeah, I did so, vary similar to running bdist_apps, but yeah, looking at the ls() results found that the command “find” finds the collision node of a unnamed panda node which also shares a geom node (the appearance) as well, getting that parent was the key, so a huge thank you to you man.

Not a problem; that all makes sense then, I believe! :slight_smile:

yeah, this should be useful to those who want to make part of a model transparent too.

It is indeed useful for that. :slight_smile:

1 Like