Weird effect of LocalRotation

I’m lost and need help! I’m trying to attach a few cylinders to the top end of main cylinder. All cylinders are randomly rotated.

Somehow this is what I see on the screen:



http://bp3.blogger.com/_lyvscL5tWXE/SAjV8TycWVI/AAAAAAAAABY/Y2iF-flOf5w/s1600-h/GrownBr.PNG



Here’s the code of main:


    protected void simpleInitGame()
    {
        lightState.setEnabled(false);
        AxisRods ar = new AxisRods("rods", true, 1f);
        rootNode.attachChild(ar);
        ar.setLocalTranslation(2f,0f,2f);
        Node tree=new Node("Tree");
        rootNode.attachChild(tree);
        GrownBranch trunk=new GrownBranch(tree,new Vector3f(5f,0,5f),1);
        Vector3f worldTrunkTop=trunk.getWorldCoordsOfTheTop();
        for(int i=2;i<4;i++)
        {
           new GrownBranch(tree,worldTrunkTop,i);
        }


And the code of GrownBranch:


public class GrownBranch
{
    protected Cylinder me;
    private static final Logger log=Logger.getLogger(GrownBranch.class.getName());
    public GrownBranch(Node tree, Vector3f attachToWorldCoords,int branchNum)
    {
        float seedlingLength= (float) (Math.random()*10f);
        float seedlingRadius=0.25f-0.05f*(float)(branchNum);
        me = new Cylinder("Branch:"+branchNum,10,10,seedlingRadius, seedlingLength);
        tree.attachChild(me);
        if(branchNum==1)
           me.setSolidColor(ColorRGBA.green);
        else
            if(branchNum==2)
                me.setSolidColor(ColorRGBA.blue);
            else
                if(branchNum=:3)
                    me.setSolidColor(ColorRGBA.cyan);
                else
                    if(branchNum==4)
                        me.setSolidColor(ColorRGBA.yellow);
                    else
                        if(branchNum==5)
                            me.setSolidColor(ColorRGBA.white);
                        else
                            if(branchNum==6)
                                me.setSolidColor(ColorRGBA.red);
                            else
                                me.setSolidColor(ColorRGBA.pink);
        Quaternion rotX = new Quaternion();
        rotX.fromAngleAxis((float)(Math.random()*Math.PI)/6f,new Vector3f(1.0f,0f,0f));
        Quaternion rotY = new Quaternion();
        rotY.fromAngleAxis((float)(Math.random()*Math.PI)/6f,new Vector3f(0f,1.0f,0f));
        Quaternion rotZ = new Quaternion();
        rotZ.fromAngleAxis((float)(Math.random()*Math.PI)/6f,new Vector3f(0f,0f,1.0f));
        me.setLocalRotation(rotX);
        /**
         * The middle after this is in the proper position
         */
        Vector3f localTrans=new Vector3f();
        me.worldToLocal(attachToWorldCoords,localTrans);
        log.info("Moving new branch to:"+localTrans);
        me.setLocalTranslation(localTrans);
        me.setModelBound(new BoundingBox());
        me.updateModelBound();
    }
    public Vector3f getWorldCoordsOfTheTop()
    {
        return me.localToWorld(new Vector3f(0f,0f,0.5f*me.getHeight()),null);
    }
}

Perhaps you could supply a simple sketch of what you expect it to look like. That would help alot.

Unfortunately, I'm not much of a painter and what passes for a mouse on my laptop just sucks, so I'll try to describe verbally. Hopefully, that helps.

I expect to see green cylinder and on top of it - blue and cyan cylinders, attached by the middles to the top of the green. Blue and cyan directions (i.e. their main axis) angled randomly in respect to the green's axis. Sort of like a palm tree. Ascii picture would look kind of like this:

 

      / - blue

      /| - cyan

      |

      | - green

      |

i would read the direction of the trunk and then move the branches along the direction.

attach the trunk and the branches to a node to be able to move them together around.



import java.util.Random;

import com.jme.app.SimpleGame;
import com.jme.bounding.BoundingBox;
import com.jme.math.FastMath;
import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.scene.Node;
import com.jme.scene.shape.Cylinder;

public class Palmtree extends SimpleGame {
    private static float trunkLength = 10;
    @Override
    protected void simpleInitGame() {
        Random rand = new Random();
       
        Node treeNode = new Node("tree");
        Cylinder trunk = new Cylinder("branch", 20, 20, 0.5f, trunkLength, true);
        trunk.setModelBound(new BoundingBox());
        trunk.updateModelBound();
        trunk.getLocalRotation().fromAngleAxis(FastMath.DEG_TO_RAD*-70, Vector3f.UNIT_X);
       
        treeNode.attachChild(trunk);
       
        // create 20 branches
        for (int i = 0; i < 20; i ++) {
            Cylinder branch = new Cylinder("trunk", 20, 20, 0.15f, 7, true);
            branch.setModelBound(new BoundingBox());
            branch.updateModelBound();
           
            // rotate the branch
            branch.getLocalRotation().fromAngleAxis(rand.nextFloat()*360, Vector3f.UNIT_X);
            branch.getLocalRotation().multLocal(new Quaternion().fromAngleAxis(rand.nextFloat()*360, Vector3f.UNIT_Y));
            branch.getLocalRotation().multLocal(new Quaternion().fromAngleAxis(rand.nextFloat()*360, Vector3f.UNIT_Z));
           
            treeNode.attachChild(branch);
           
            // move the branch up to the trunk's top
            // take the trunk's direction and multiply it with half of the trunks length
            Vector3f direction = trunk.getLocalRotation().getRotationColumn(2);
            direction.normalize();
            branch.getLocalTranslation().addLocal(direction.mult(trunkLength/2));
        }
       
        rootNode.attachChild(treeNode);

    }

    public static void main(String[] args) {
        new Palmtree().start();
    }
}

Your solution works, thank you! I was able to extend it to the use-case with the first cylinder (trunk) moved off (translated) its initial position.

Now I'd be the first to admit I haven't known anything about quaternions until a few days ago and I still don't know much, but what does getRotationColumn() do, physically speaking? The documentation is not very helpful. :frowning:

i don't know how quaternions work internally, i just know that this gives you the direction vector, maybe someone else can explain it in more detail :slight_smile: