HelloAnimation

I am new to jME and 3d programming in general. I am learning by going through the jME tutorials.



In the HelloAnimation tutorial a PointLight rotates around a sphere lighting areas of the sphere towards which it points at any given time during the rotation. I modified the program by introducing another, smaller, sphere which rotates around the PointLight as the PointLight rotates around the large sphere. The light does not seem to be cast on the proper area of the smaller sphere (see the screenshot below). Any idea as to what I’m doing wrong?







Following is the modifed code:



    protected void simpleInitGame() {
        Sphere s = new Sphere("My sphere", 30, 30, 5);
        Sphere s2 = new Sphere("sphere2", 30, 30, .5f);
       
        Node pivot = new Node("Pivot node");
        Node pivot2 = new Node("pivot2");
       
        PointLight pl = new PointLight();
        pl.setDiffuse(ColorRGBA.red);
        pl.setEnabled(true);
        this.lightState.detachAll();
        this.lightState.attach(pl);
       
        SimpleLightNode ln = new SimpleLightNode("pl node", pl);
        ln.setLocalTranslation(new Vector3f(0,10,0));
        pivot.attachChild(ln);
        pivot2.attachChild(s2);
        s2.setLocalTranslation(new Vector3f(0, 2, 0));
       
        Box b = new Box("Blarg",
                new Vector3f(-.3f, -.3f, -.3f),
                new Vector3f(.3f, .3f, .3f));
        ln.attachChild(b);
        ln.attachChild(pivot2);
       
        SpatialTransformer st = new SpatialTransformer(2);
        st.setObject(pivot, 0, -1);
        st.setObject(pivot2, 1, -1);
       
        Quaternion x0 = new Quaternion();
        x0.fromAngleAxis(0, new Vector3f(0,0,1));
        st.setRotation(0,0,x0);
        st.setRotation(1,0,x0);
       
        Quaternion x180 = new Quaternion();
        x180.fromAngleAxis(FastMath.DEG_TO_RAD * 180, new Vector3f(0,0,1));
        st.setRotation(0,4,x180);
        st.setRotation(1,4,x180);
       
        Quaternion x360 = new Quaternion();
        x360.fromAngleAxis(FastMath.DEG_TO_RAD * 360, new Vector3f(0,0,1));
        st.setRotation(0,8,x360);
        st.setRotation(1,8,x360);
       
        st.interpolateMissing();
        pivot.addController(st);
        pivot2.addController(st);
       
        rootNode.attachChild(pivot);
        rootNode.attachChild(s);
    }



Thanks.

I guess I just didn’t understand what you were meaning. Almost all the demos the lightnodes have a child. A child representing the light itself, simple cases it’s the box, the terrain lighting it’s the lensflare. By having the lightnode as a node, it allows you to easily represent the light with something tangible.

That’s fine. The move was one of efficence. And lights just seem to fit more as leaves than nodes. No biggie.

I don’t see any gain with this move.

While we’re on the subject, I think lights fit better as leaves than parents. Most uses of a light nodes will be as leaves in any game.



That means SceneLight should extend Spatial and work just like LightNode. This is a pretty strait forward move, if taken.

Yeap yeap. I also think that the light rotation for light node should simply be the world rotation as well…

I checked in SimpleLightNode with removal of lightTranslate.



I also think that we don’t really need SimpleLightNode and LightNode, so we can remove LightNode and rename SimpleLightNode.

I agree.

Multiple lights for multiple light nodes seems much more intuitive.



One light node should be just one light.

Ok, I think I tracked down what happened here… The code I was using allowed the user to specify a lights translation, rotation, etc relative to the light node.



We don’t allow that, so in our light node the light is always in the center of the node, and facing the same direction.



Therefore, Cep I believe you are correct.



Now, the reason you are allowed to set these values in the original code, is LightNode originally could hold multiple lights. Ours only holds the one, so rotating and positioning the node is how we control it.



Which, I think is the method I prefer. Anyone disagree? Would you rather you could add multiple lights to a single light node and orientate those individual lights? Or just add a single light to a LightNode and if you want something with multiple lights, add multiple LightNodes?

The add world translation may have been a copy/paste artifact from the local/world translation update lines in Spatial where it creates the worldTranslation by doing calculations and then adding the parent’s world rotation.

The “light” is at coord 0,0,0 of the LightNode’s coordinate system. So if you apply that coordinate to the formula you get



WorldScale * ( WorldRotation * (0,0,0) )+ WorldTranslation.



Because 0rotscal = 0, you can simplify it to just simply the world translation. At least I think.

Ok, closer:


lightTranslate = worldRotation.mult(localTranslation, lightTranslate)
               .multLocal(worldScale).addLocal(worldTranslation);



should be:

lightTranslate = worldRotation.mult(localTranslation, lightTranslate)
                .multLocal(worldScale);



The worldTranslation was adding to itself, this will give you the results you expect. I just need to figure out why that equation had world translation added to itself...

Once I figure out where the misunderstanding is, I'll fix the light nodes (Simple and regular).

It’s hard to say if it’s a problem with world position or not.



To calculate a nodes position, the equation:



t = wT + wS * (wR * lT)



or local translation times the world rotation times the world scale added to the world translation, gives the final translation.



There may be a problem with our ordering. Try a more simplified version of the equation:



lightTranslate = worldRotation.mult(lightTranslate).mult(worldScale).add(worldTranslation);



This will create excess objects, but might tell us if the problem lies with the translation or not.

Also, you can remove your line



pivot2.addController(st);



You don’t need to attach Controllers twice.

There’s some kind of problem with how light nodes calculate their absolute world position. Go inside



public void SimpleLightNode::updateWorldData(float time);



and change the top to:


        super.updateWorldData(time);
        lightRotate = worldRotation.mult(localRotation, lightRotate);
//        lightTranslate = worldRotation.mult(localTranslation, lightTranslate)
//                .multLocal(worldScale).addLocal(worldTranslation);
      lightTranslate.set(worldTranslation);




Notice I comment out the old calculation and just set it to the world translation. I'm not sure if that's the correct way. Give me a night and I'll think it through to make sure this is correct. It should solve your problem.