[commited] DirectionalLight attached to a LightNode, inherits wrong direction

http://www.jmonkeyengine.com/jmeforum/index.php?topic=9390.15



If a DirectionalLight is attached to a LightNode, its not inheriting its direction.

there seems to be a Bug in LightNode:


114       switch (light.getType()) {
115       case Directional: {
116            DirectionalLight dLight = (DirectionalLight) light;
117            dLight.getDirection().set(worldTranslation).negateLocal();
118            break;
119       }
120
121        case Point: {
122            PointLight pLight = (PointLight) light;
123            pLight.getLocation().set(worldTranslation);
124            break;
125        }



should be:


117            dLight.getDirection().set(worldRotation.getRotationColumn(2));



the following Test shows a pretty black screen without the fix, because the direction of the directional light will be (0,0,0)

import com.jme.app.SimpleGame;
import com.jme.bounding.BoundingSphere;
import com.jme.light.DirectionalLight;
import com.jme.light.LightNode;
import com.jme.math.FastMath;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.shape.Sphere;

public class TestLightNode extends SimpleGame {
    static final float worldsize = 40;//The size of the world

    public static void main(String[] args) {
       TestLightNode app = new TestLightNode();
        app.setConfigShowMode(ConfigShowMode.NeverShow);
        app.start();
    }
   
    void randomSphere(int i) {
        //Crate the big spheres and position it.
        Sphere newSphere = new Sphere("sp" + i, 8, 8, 2);
        newSphere.setModelBound(new BoundingSphere());
        newSphere.updateModelBound();
        newSphere.setLocalTranslation(new Vector3f(FastMath.rand.nextFloat()
                * worldsize * 2 - worldsize, FastMath.rand.nextFloat()
                * worldsize * 2 - worldsize, FastMath.rand.nextFloat()
                * worldsize * 2 - worldsize));
        rootNode.attachChild(newSphere);
    }

    protected void simpleInitGame() {
        this.lightState.detachAll();
       
        FastMath.rand.setSeed(1520);
       
        //Add the spheres.
        for (int i = 0; i < 60; i++) {
            this.randomSphere(i);
        }
       
       //Create a new DirectionalLight
      DirectionalLight dr = new DirectionalLight();
        dr.setEnabled(true);
        dr.setDiffuse(new ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f));
        dr.setAmbient(new ColorRGBA(0.2f, 0.2f, 0.2f, 1.0f));
        dr.setDirection(new Vector3f(0.5f, -0.5f, 0));
        dr.setShadowCaster(true);

        LightNode ln = new LightNode("drn");
        // let the light node look to the bottom right
        ln.lookAt(new Vector3f(5, -5, 0), Vector3f.UNIT_Y.clone());
        ln.setLight(dr);
        lightState.attach(dr);

        rootNode.attachChild(ln);
    }
}



there still seems to be a problem if the LightNode is rotated and translated at the same time though.

just keep in mind that directional light has always involved using the negative translation to control direction… the reason is you are basically setting where the light is (say the sun), therefore the directional light is the opposite direction.  Whether that is right or intuitive is up for discussion, but some people expect it to work that way.

hmmm ok, but then Line 117 still must be worldRotation.getRotationColumn(2).negateLocal() or else the light doesn't even show up at all.

also afaik, DirectionalLight does not and MUST NOT care about the translation, so you can ignore it when updating the DirectionalLight in the LightNode.

renanse said:

just keep in mind that directional light has always involved using the negative translation to control direction... the reason is you are basically setting where the light is (say the sun), therefore the directional light is the opposite direction.  Whether that is right or intuitive is up for discussion, but some people expect it to work that way.


ah ok, then it makes sense how it is implemented, but the javadoc is unclear about it.
Core-Dump said:

renanse said:

just keep in mind that directional light has always involved using the negative translation to control direction... the reason is you are basically setting where the light is (say the sun), therefore the directional light is the opposite direction.  Whether that is right or intuitive is up for discussion, but some people expect it to work that way.


ah ok, then it makes sense how it is implemented, but the javadoc is unclear about it.


Ah... agreed. I was also unclear about that.

So I guess the original code is correct after all: dLight.getDirection().set(worldTranslation).negateLocal(); Now I tried it out again and can manipulate the direction of the sunlight by changing the position of the lightnode. The directionalLight seems always to look at the zero point of the scene therfore determining the direction of the light. live & learn  :P

so we leave it as it is, but i will update the javadoc to make it more clear how the directional light behaves.

javadoc is fixed now