Instancing question

Can I use instancing on a model, and set random scale and rotation, so that each instance has a different orientation and scale?

Sure. You can set any transform you like on different instances, otherwise it would kind of defeat the purpose.

To clarify: you can set the transform you like on the unique node above each instanced copy. The instances themselves must all have the same local transform (because they are all really the same node), but they will inherit their net transform from their parent.

David

Thanks, but I don’t quite understand. Could you help me adjust this code correctly?

What’s wrong with that ?
Use instanceUnderNode() to insert a unique parent between the instance and the desired parent.

grassPlacer = self.grassRow.instanceUnderNode(render, “name”)

Thanks
I’m trying, but I am not getting it right.
I tried this and some other methods, but now I only see the model, but no instances.

        self.grassRow = loader.loadModel("Models/blade01") 
        self.grassRow.setPosHprScale(-170,170,0.75,random()*360,0,0,random()*0.75,random()*0.75,random()*0.75)
        for i in range(50):
            grsssPlacer = render.attachNewNode("grassPlacer")
            grassPlacer = self.grassRow.instanceUnderNode(render, "grassPlacer")
            grsssPlacer.setPosHprScale(i*.025,0,0,i*random()*360,0,0,0.75,0.75,0.75)
            ## self.grassRow.instanceTo(grsssPlacer)

Where have I gone wrong in the code?

The code looks (mostly) right in principle, but you probably want to apply your initial transform to a common parent node, not to the node that’s getting repeatedly instanced. More like this:

self.grassRow = loader.loadModel("Models/blade01") 
grassParent = render.attachNewNode('grassParent')
grassParent.setPosHprScale(-170,170,0.75,
                           random()*360,0,0,
                           random()*0.75,random()*0.75,random()*0.75)
for i in range(50):
    grsssPlacer = grassParent.attachNewNode("grassPlacer")
    grassInstance = self.grassRow.instanceTo(grsssPlacer)
    grassInstance.setPosHprScale(i*.025,0,0,
                                 i*random()*360,0,0,
                                 0.75,0.75,0.75)

Note that instanceUnderNode() is just a shortcut for attachNewNode() followed by instanceTo(). You should use either one pattern or the other, but not both at the same time.

Note also that the return value of instanceTo() is the new instance, which is not the same thing as the parent node. (grsssPlacer is different from grassInstance).

David

Thanks, but something is still wrong somewhere. When I run that code, nothing is rendered (I see nothing). When I use this:

        self.grassRow = loader.loadModel("Models/blade01")
        grassParent = render.attachNewNode('grassParent')
        grassParent.setPosHprScale(-170,170,0.75,
                                random()*360,0,0,
                                random()*1.75,random()*1.75,random()*1.75)
        for i in range(50):
            grsssPlacer = grassParent.attachNewNode("grassPlacer")
            grassInstance = self.grassRow.instanceTo(grsssPlacer)
            grassInstance.setPos(i*.025,0,0)

…I see one blade of grass.
Is this code [ i*random()*360 ] correct? Am I missing something vital?

Are you sure the blades aren’t multiple, but they aren’t apart far enough? Try copyTo instead of instanceTo and see if that is working. If that still doesn’t work, its not related to the instancing code.

Oh, right. I screwed up. Use this instead:

        for i in range(50):
            grsssPlacer = grassParent.attachNewNode("grassPlacer")
            grassInstance = self.grassRow.instanceTo(grsssPlacer)
            grassPlacer.setPos(i*.025,0,0)

I made the same confusion I was counseling you against–I confused grassPlacer (the parent node, and unique to each instance) with grassInstance (the instanced node, common to each instance). You can’t set the transform on the instanced node, because each time you do you are changing all of the instances together. If you want the transform to be unique to each instance, you have to set it on the parent node.

David

Now I get an error.
NameError: global name ‘grassPlacer’ is not defined

You know panda3d instancing should not be confusing with new next gen hardware instancing on DX10 card? Panda3d instancing only helps for animations because they don’t have to be recomputed and resent for each instance. Id helps squat with standard solid objects like chairs, trees or grass.

Doesn’t it also help conserve memory?

Correct me if I misunderstand you.
The use of instancing is for animated objects, so it does not matter if I use instancing on static objects or not. Is that what you are saying, treeform?
I did think that instancing would cut down on cpu usage, but I also chose to use instancing to simplify things for me. I want to place realistic grass blades (polycount 7) on my terrain. Each blade would look different by altering the orientation and scale of each. I already have a code that does this, but it is going to be extremely lone and time consuming, so I figured that instancing would be the way to do it. Pro-rsoft said it can be done with instancing, so that’s what I want to do now. I just need some help on that. Thanks for replying, but I am hoping that I can get this code correct so that I can get past this. I’ve been on it a week now. I’d appreciate any more help on why the code is not working. Thanks

I’m sorry drwr. The code is working. I’m not sure why it returned the error the first time, but it’s working with this code:

# grass line 1
self.grassRow = loader.loadModel("Models/blade01")
grassParent = render.attachNewNode('grassParent')
grassParent.setPosHprScale(-170,170,0.75,0,0,0,0.35,0.35,0.35)
for i in range(50):
    grsssPlacer = grassParent.attachNewNode("grassPlacer")
    grassInstance = self.grassRow.instanceTo(grsssPlacer)
    ## grsssPlacer.setPos(i*0.75,0,0)
    grsssPlacer.setPosHprScale(i*.5,0,0, i*random()*360,0,0, i*random()*0.75,i*random()*0.75,i*random()*0.75)

Thank you very much for the help.
I have just one last question - I hope.
I get this:
:linmath(warning): Tried to invert singular LMatrix3.
in the DOS command window, and I believe it has something to do with i*random()0.75,irandom()0.75,irandom()*0.75). Can you tell me if the code is correct or is there another way to write this?

It means you’re setting a scale to 0 somewhere. Make sure the scale can’t reach zero (for example, by adding +0.1 or so)

Thanks
That’s fixed now.
Sorry to be such a pain on this, but there’s a major problem somewhere in the code. My grass blades aren’t restricted by scale. The first blade starts off tiny and randomly scales up to the last blade. If the random scale is say 0.3, it may restrict it to that till about the 25th blade, but then it keeps scaling up till the 50th blade. So what I get is a line of grass rising from the first to the last, just like a hill. What may be causing this?

        # grass line 1
        self.grassRow = loader.loadModel("Models/blade01")
        grassParent = render.attachNewNode('grassParent')
        grassParent.setPosHprScale(-170,170,0.75,0,0,0,random()*0.65,random()*0.65,random()*0.65)
        for i in range(50):
            self.grsssPlacer = grassParent.attachNewNode("grassPlacer")
            grassInstance = self.grassRow.instanceTo(self.grsssPlacer)
            self.grsssPlacer.setPos(i*.495,0,0)
            self.grsssPlacer.setHpr(i*random()*360,0,0)
            self.grsssPlacer.setScale(i*random()*0.2+0.1)
for i in range(50):
    self.grsssPlacer.setScale(i*random()*0.2+0.1)

Since i variable rises from 0 to 49, the result of the calculation tends to be greater and greater on each iteration.

What do I do to correct this?

Well, why multiply by i then?