Bug in BumpMapColorController.update(float) ?

More news from the bug tracking front: It seems there's a bug in the method updateWorldData(float) of SimpleLightNode. The method currently uses some Quaternion called lightRotate to compute the direction for DirectionalLights and SpotLights:


    public void updateWorldData(float time) {
        super.updateWorldData(time);
        if(light == null) {
            return;
        }
        lightRotate = worldRotation.mult(localRotation, lightRotate);

        switch (light.getType()) {
        case Light.LT_DIRECTIONAL:
            {
                DirectionalLight dLight = (DirectionalLight) light;
                dLight.setDirection(lightRotate.getRotationColumn(2,
                        dLight.getDirection()));
                break;
            }

        case Light.LT_POINT:
            {
                PointLight pLight = (PointLight) light;
                pLight.setLocation(worldTranslation);
                break;
            }

        case Light.LT_SPOT:
            {
                SpotLight sLight = (SpotLight) light;
                sLight.setLocation(worldTranslation);
                sLight.setDirection(lightRotate.getRotationColumn(2, sLight
                        .getDirection()));
                break;
            }

        default:
            break;
        }

    }



I had some strange results when using SimpleLightNode to point DirectionalLights and SpotLights in some direction. The direction calculated by SimpleLightNode seemed quite random, so I did some debugging again and noticed some completely weird values in the lights' direction vectors at the end of the method.
The method's intention seems to be to use the Z-Vector of the quaternion's rotation matrix as the direction, and as the node's world rotation is already being updated at the beginning of the method, I figured that simply using the worldRotation Quaternion instead of lightRotate and completely ignoring the latter might work. And... Tadaaah, it worked! :D
If I'm not completely wrong and have misunderstood the idea behind SimpleLightNode this is a bug...
Oh, and by the way, I think the call [pre]dLight.setDirection(lightRotate.getRotationColumn(2, dLight.getDirection()));[/pre] could be trimmed down to [pre]lightRotate.getRotationColumn(2, dLight.getDirection());[/pre]  :wink:


One more side note: As I tested positioning lights, I also tried using DirectionalLight, but this one seemed completely screwed up. For some directions it worked fine, for other directions the light pointed in a different direction than the one I specified and in some cases it almost completely disappeared. WTF? :|
I haven't figured out why that is yet, but as I currently don't need any DirectionalLights for the application I'm developing, I'll leave it to someone who knows more about that stuff than me to find out :wink:

EDIT: In this topic this problem (about the SimpleLightNode) has already been mentioned, and according to the replies, it should already have been fixed...?

EDIT 2: The problem with DirectionalLight does definitely NOT result from the problem with SimpleLightNode. I tested the directionalLight separately and the results were... different, but still wrong. ^^
Anyway, the issue with DirectionalLight might still result from something that I've misunderstood or implemented the wrong way, so any confirmation on this would be appreciated

EDIT 3: Changed the title, as I'm quite sure now that the bug is not in SimpleLightNode, but in BumpMapColorController (see second page).

Looking in CVS, the version of LightNode that's been current since July 2006 is the following (1.10):


    public void updateWorldData(float time) {
        super.updateWorldData(time);

        if(light == null) {
            return;
        }
        switch (light.getType()) {
        case Light.LT_DIRECTIONAL: {
            DirectionalLight dLight = (DirectionalLight) light;
            dLight.getDirection().set(worldTranslation).negateLocal();
            break;
        }

        case Light.LT_POINT: {
            PointLight pLight = (PointLight) light;
            pLight.getLocation().set(worldTranslation);
            break;
        }

        case Light.LT_SPOT: {
            SpotLight sLight = (SpotLight) light;
            sLight.getLocation().set(worldTranslation);
            worldRotation.getRotationColumn(2, sLight.getDirection());
            break;
        }

        default:
            break;
        }

    }



I don't know where yours is coming from. Are you using a branch of some sort?

Nope, I checked out CVS head last month… No idea why I got such an outdated version. But anyway, thanks for the hint, I'll check out again to get the latest version.

Hm, I just checked the CVS repository (HEAD revision) again, and the current version on the repository (version 1.10) is the one I posted. And I definitely am using the right repository, as the bug I posted here has just today been fixed by renanse, and the bugfix was on the repository…

Ah, I was looking at LightNode.java, not SimpleLightNode.java.



Which begs the question: Why is there a SimpleLightNode.java and a LightNode.java? The differences between the two are very minor, and neither is marked as deprecated.


I'll leave it to the developers to answer that question :wink:



But I'm still wondering about DirectionalLight… Has anyone else noticed the problems mentioned above?

I have had this forum post on my backlog for a bit now.  IRT directional lighting, what is the odd behavior you are seeing?  What you should be seeing is that light shines towards the origin from the world location of the light.  As for Simple and regular light nodes, I'm honestly not sure.  I think the SimpleLightNode version was added by cep21 a while back.

Er… from the world location of the light? I used DirectionalLight without a light node, and it still behaved strangely.



Okay, to illustrate it, I made some screenshots. The following shots show a Sphere with a radius of 6 at the world origin. The camera is placed at (0, 0, 50), looking at the origin (up vector (0, 1, 0)), unless stated otherwise.



First, a DirectionalLight, with a direction of (0, 0, -1):



Seems to point at about (0, -0.3, -1), I’d say…



Direction (-1, 0, 0):



This one looks okay.



Direction (1, 0, 0):



Also okay.



Direction (0, -1, 0):



:?



Same light direction, camera placed at (0, 0, -50), looking at the origin, up vector (0, 1, 0):





Admittedly, this time the light did not disappear for any direction, but still it seems bugged. It looks like the coordinate system for the light is rotated by about 30

Sorry, I was referring to the LightNode.



Looking further into this now.

Ok, so just throwing your described scene into a SimpleGame and running, I don't get the lighting issues you illustrate in your previous post.  Wild guess time… maybe your camera is setup oddly?  I'll try with the lightnode classes next.



Here's my test class:


import com.jme.app.AbstractGame;
import com.jme.app.SimpleGame;
import com.jme.bounding.BoundingBox;
import com.jme.light.DirectionalLight;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.shape.Sphere;

public class TestDirectionalLight extends SimpleGame {

    public static void main(String[] args) {
        TestDirectionalLight app = new TestDirectionalLight();
        app.setDialogBehaviour(AbstractGame.ALWAYS_SHOW_PROPS_DIALOG);
        app.start();
    }

    protected void simpleInitGame() {

        cam.setLocation(new Vector3f(0,0,50));
        cam.update();

        Sphere sp = new Sphere("sphere", 50, 50, 6);
        sp.setModelBound(new BoundingBox());
        sp.updateModelBound();
        rootNode.attachChild(sp);

        DirectionalLight dr = new DirectionalLight();
        dr.setDiffuse(new ColorRGBA(0.25f, 0.75f, 0.25f, 1.0f));
        dr.setDirection(new Vector3f(0, -1, 0));
        dr.setEnabled(true);

        lightState.detachAll();
        lightState.attach(dr);
        sp.setRenderState(lightState);
    }
}

So, this is one of the few differences between LightNode and SimpleLightNode. SimpleLightNode uses the orientation of the directional light. LightNode uses the position of the directional light, relative to the origin. I actually prefer the SimpleLightNode behavior in general, but either "ought" to work.



At this point, what I would do is put a breakpoint in updateWorldData() of SimpleLightNode, and trace through the values that get passed to the light. Then I would trace through the LightState applied to the world when rendering, to see what happens to the parameters applied in the LightNode. Pay careful attention to the actual values (and transforms) passed around, and you may find something.

Right, and if you look at SimpleLightNode it grabs the third column from a rotation matrix which makes me curious as to whether that will always be right.



fwiw, putting LightNode into the test and changing the node's position works fine for me. 

…now I'm totally confused. I just thought I had found the reason for the bug with DirectionalLight: I had set a rotation for my sphere (I wanted the "poles" of the sphere to be at the top and bottom instead of at the front and back), and when I removed the rotation, the lighting was okay. I thought it was my fault, and setting a transformation directly for the geometry would be causing the problem, so I used a node between the sphere and the scene root to set the rotation… And again, the lighting was as buggy as before!

Then I set a rotation for the sphere in your testing scene… And it worked! :? I don't get it.



The same thing happens when I use other primitives or custom TriMeshes. Honestly, I don't have the slightest idea what's going on here.

I think I'll just go to sleep for today… Maybe I can get this fixed tomorrow.



(@renanse: This implementation was part of the X3D loader I mailed you, so it's definitely bugged. As soon as I can fix it, I'll send you the update.)

Ok, no problem.

if you look at SimpleLightNode it grabs the third column from a rotation matrix which makes me curious as to whether that will always be right


Well, if it grabs the world rotation matrix third column, and what you want is a light that by default uses the Z axis, then that seems right to me.

Alright, I did some more testing on this and it seems that the BumpMapColorController is causing all the trouble. As it works perfectly for PointLight and SpotLight, it seems there's a bug with using the BumpMapColorController together with DirectionalLight, and I think I have already located it.

In the method update(float) of BumpMapColorController there are the following 3 lines (lines 194 to 196 in the source) after calculating the vector lVect from the geometry to the light source:


            if (l.getType() != Light.LT_DIRECTIONAL) {
                batch.getParentGeom().worldToLocal(lVect, lVect);
            }



I don't know why the transformation of world to local is not being performed for directional light, but when I remove the if clause so the worldToLocal is executed for any type of light, everything works perfectly, and the sphere is lit as it should be.

EDIT: And of course, in this case my X3D loader is not bugged. *yes* :D

Back from "vacation" and got this integrated now.  Looking for models to test with…

Just kicking this up, as it seems that the bug in BumpMapColorController (see [iurl=http://www.jmonkeyengine.com/jmeforum/index.php?topic=6618.msg52774#msg52774]this post[/iurl]) has not been fixed yet. If it is, in fact, not a bug, just tell me. But I'm quite sure it is, because after changing the passage in the code as described, there are no more problems when using directional light together with bump maps.