Rotating object by the Z axis

Hello all :wink:

First of all a little bit of code :

        self.tree = loader.loadModel("Tree/Tree")
        self.tree.setScale(0.25,0.25,0.25)
        self.tree.setPos(-12,-8,0)
        for i in range(4):
            self.treeTmp = render.attachNewNode("NewTree")
            self.treeTmp.setPos(i*8,0,0)
            self.treeTmp.setH(-i)
            self.tree.instanceTo(self.treeTmp)

By the previous code Iā€™m trying to do a simple rotation for each new tree following the z axis.
Still having some confusion to determine what are really the Yaw, Pitch and Roll. Tried to play a little bit with them, but I think that the center of the object is the root of the trunk and not the middle of the object itself!!!

Anywayā€¦ Tried many things and not getting the trickā€¦
Can anyone help ?

The center of rotation is the (0, 0, 0) point, which is only rarely the geometric center of the object. Since trees are usually modeled with (0, 0, 0) on the ground, it probably is the root of the trunk.

David

Ok but how rotate each new instance of the tree according to the Z axis of the tree itself ?

The purpose of this rotation is simple: giving a different shape for each instance. (well, the shape is the same but will look different for the viewer)

What about inserting a simple randomization of H and scale inside your cycle?
Something like:

import random
for i in range(4):
    self.treeTmp = render.attachNewNode("NewTree") 
    self.treeTmp.setPos(random.random()*10,random.random()*10,0) 
    self.treeTmp.setH(random.random()*360) 
    self.treeTmp.setScale(random.uniform(0.5, 1.5)#scale will be between 0.5 and 1.5 of the original
    self.tree.instanceTo(self.treeTmp)

Choose wisely the magic numbers
Remember that a cycle of this kind will always return a different tree disposition each time itā€™s executed.
But if you give the random module a seed, it will generate a determined disposition for your trees.

random.seed(1)#choose a number that works the way you like, experiment!

Thanks Ausir but I think that Iā€™m badly explaining my problem.
When Iā€™m using setH() on the instances, itā€™s like Iā€™m changing the positionning of the trees on the X and Y axis and not the rotation of the tree itself!!

Letā€™s take a bisc exemple of two trees and rotate them according to Z :
Here is what I want to do :

self.tree1.setPos(-6,-8,0)
self.tree2.setPos(-8,-8,0)
self.tree2.setH(90)
self.tree1.reparentTo(render)
self.tree2.reparentTo(render)

This is working very good and is the result desired
But for the instances, itā€™s not working the same way and I canā€™t understand why!

self.tree.setPos(-6,-8,0)
        for i in range(2):
            self.treeTmp = render.attachNewNode("NewTree")
            self.treeTmp.setPos(i*8,0,0)
            self.treeTmp.setH(90)
            self.tree.instanceTo(self.treeTmp)

Hope Iā€™m explaining it better this way.

I see your problem now.
My post was more of a ā€œstrategy to put things at randomā€ā€¦

The point is that NodePath.instanceTo() returns the new nodePath that is created.In your code, you create 4 trees as children of self.treeTmp, but you donā€™t access their properties.

So, try to go something like:

for i in range(10):
    self.tmp=self.tree.instanceTo(self.treeTmp)
    self.tmp.setH(random.random(360))#and so on

This way, all trees will be children of self.treeTmp.

Ok weā€™re getting closer :slight_smile:
But Iā€™m more confused now! You mean that for accessing the proprities of each instance, I need to create an other variable ?

Which will look something like this :

for i in range(2):
            self.treeTmp = render.attachNewNode("NewTree")
            self.tmp = self.tree.instanceTo(self.treeTmp)
            self.tmp.setPos(i*3,-2,0)
            self.tmp.setH(i*90)

That will not work.

Letā€™s take the example given in the manual :

dancer = Actor.Actor("chorus-line-dancer.egg", {"kick":"kick.egg"})
dancer.loop("kick")
dancer.setPos(0,0,0)
for i in range(50):
  placeholder = render.attachNewNode("Dancer-Placeholder")
  placeholder.setPos(i*5, 0, 0)
  dancer.instanceTo(placeholder)

The posistion of each new instance is being accessed by placeholder and it will be the same thing for the heading (seH())

I just tried some snippets, and your original (as well as my first snippet) definitely work.
So, you should make sure your tree model isnā€™t wrong.
To test with a ā€œneutralā€ model, replace

self.tree = loader.loadModel("Tree/Tree")

with

self.tree=loader.loadModel("smiley.egg")

and see for yourself the diferences in behaviour.

Also, thereā€™s no reason to use instanceTo here. Use copyTo instead, itā€™s much less likely to cause confusion, and just as efficient.

David

Finally found the problem :smiley:

It was not realted to my original files but the first setPos().

        #Load the tree
        self.tree = loader.loadModel("Tree/Tree.egg")
        self.tree.setScale(0.25,0.25,0.25)
        #self.tree.setPos(1,1,1)   #THIS WAS THE ANNOYING LINE
        for i in range(10):
            self.treeTmp = render.attachNewNode("NewTree")
            self.treeTmp.setPos(i*7,6,0)
            self.treeTmp.setH(i*80)
            self.tree.copyTo(self.treeTmp)

The code here is working perfectly and is want I wanted. Removing the comment on the line self.tree.setPos(1,1,1) and adding a modifiction on the heading after that was dispatching my trees in circle and not rotating them arround the z axis.

Understood that while I was playing with the smiley.egg and I didnā€™t know the command copyTo() yet.
Thanks to all for helping :wink: