Object Stuck at (0, 0, 0) and Can't Be Moved After Creating Instances

I have created an object and am trying to create instances of it. However, whenever I do this, there is a copy at (0, 0, 0) despite me never putting one there. It seems that it can’t be moved, hidden, rotated, etc.

# The Object Class I'm Using
class Model():
    def __init__(self, path, pos, hpr, scale, parent):
        self.m = loader.loadModel(path)
        self.m.setPos(pos)
        self.m.setHpr(hpr)
        self.m.setScale(scale)
        self.m.reparentTo(parent)

    def setPos(self, pos):
        self.m.setPos(pos)

    def setHpr(self, hpr):
        self.m.setHpr(hpr)

    def reparentTo(self, parent):
        self.m.reparentTo(parent)

    def instanceTo(self, object):
        self.m.instanceTo(object)

    def setLight(self, light):
        self.m.setLight(light)

    def setTransparency(self, type):
        self.m.setTransparency(type)

# The Instancing Code
grassnodes = self.render.attachNewNode("grassnodes")
        grass = Model('Models/Grass.dae', (0, 0, 0), (0, 90, 180), 1, render)
        grass.setTransparency(TransparencyAttrib.MBinary)
        for i in range(100):
            placeholder = self.render.attachNewNode("Grass-Placeholder")
            placeholder.setHpr(-90, 0, 0)
            grass.instanceTo(placeholder)
            placeholder.setPos(random.randrange(0, 32) - 49, random.randrange(0, 50) - 25, 0.1 * random.randrange(-1, 1))
            placeholder.setHpr(random.randrange(0, 360), 0, random.randrange(-10, 10))
            placeholder.setScale(random.randrange(1, 3), random.randrange(1, 3), 1)

Well, when you construct your “Model” class, you do load the model and attach it to “render” (presumably with the default position of (0, 0, 0)). That, I imagine, is the copy that you’re seeing.

I’d suggest simply not reparenting your base model (i.e. “self.m”) to anything.

But, if I may ask… what is the purpose of so instancing? I’m not sure that it will gain you anything, as you’re loading a non-animated model (presumably)–and the benefit of this form of instancing, as far as I’m aware, is that it allows animations to be calculated just once for multiple objects.

If you want hardware geometry-instancing, then I don’t think that the form of instancing that you’re using will achieve that–although I stand to be corrected.

I am mainly trying to copy and past an object multiple times in different positions because I don’t want to place them individually. Is there a better way to do this?

Well, you have to make at least one method-call to spawn the model, so why not have that call be to “loadModel”?

That is, your code above would become something like this:

grassNodes = self.render.attachNewNode("grassNodes")
grassNodes.setTransparency(TransparencyAttrib.MBinary)
for i in range(100):
    grass = loader.loadModel("Models/Grass.dae")
    grass.reparentTo(grassNodes)
    grass.setPos(<your randomisation code here>)
    grass.setHpr(<your randomisation code here>)
    grass.setScale(<your randomisation code here>)

Note that Panda3D already has internal caching, so successive calls to “loadModel” with the same file won’t all read from disk, if I’m not much mistaken.

I didn’t realize you could do that, thanks! This actually makes what I’m trying to do much easier.

1 Like

Let me say that I still encounter features in Panda3D that amaze me. :slight_smile: