PDA

View Full Version : How to fix light position with rotating cube



yhbae
10-04-2011, 09:39 AM
This is the section of the code:


gl.glEnable(GL10.GL_LIGHTING);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

gl.glLoadIdentity();
gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, lightPositionBuffer);

gl.glTranslatef(0.0f, -1.2f, -10);And Into The Screen 6.0
gl.glRotatef(xrot, 1.0f, 0.0f, 0.0f);
gl.glRotatef(yrot, 0.0f, 1.0f, 0.0f);

model.draw(gl); // Draw the cube

With the above code, the surface shade continuously changes as the cube is being rotated but not the way I was expecting. As an example, the top surface continuously change the color from completel black to complete white gradually as the cube rotates on the y-axis.

If I move glLightfv() to just before draw(), then as expected, the surface doesn't change at all during rotation since the light position receives the same transformation as the scene itself.

What am I doing wrong?

thokra
10-04-2011, 10:01 AM
If you intend to keep the illumination of the cube constant (and I expect you do) then moving glLightfv() after the calls which (in this case) set up the view matrix (glTranslate() etc.) is correct.

The explanation for the variable illumination in you first scenario is simple: you're not transforming the light source position at all since right before invoking glLightfv you're setting the model-view matrix to identity. Therefore the light will be fixed in view space and the rest of the scene is transformed. As a result, the illumination of the cube changes.

HTH.

yhbae
10-04-2011, 10:06 AM
Thanks for the response. :)

Actually what I want to do eventually is to lit a room and have objects move around. The light will stay fixed in relation to the room. Cube here is one of the object. So in my case, I don't want to see the cube illumination stay constant as it moves around.

yhbae
10-04-2011, 10:15 AM
Here's another object in the scene. I have OBJ loader running and imported a sphere from Maya. The object has been triangulated as my app runs on Android which is a OpenGL ES.

I get strange bands of shades and if I continue to rotate the cube, I see this discontinuity as seen here:

https://picasaweb.google.com/103801513061140283133/Misc#5659686093013529666

Could normals imported from Maya been handled wrong?

thokra
10-04-2011, 10:18 AM
Hmm, that link doesn't work for me.

yhbae
10-04-2011, 10:30 AM
Looks like the permission was set wrong. Can you view it now?

thokra
10-04-2011, 10:50 AM
Nope, it reports: "Page not found!".

yhbae
10-04-2011, 11:19 AM
Doh... Lets try this:

https://lh5.googleusercontent.com/-2jYJI...0-04-130825.png (https://lh5.googleusercontent.com/-2jYJIaqH7CE/Tos-g-pKNEI/AAAAAAAAAZU/sWMQxwkRJL8/device-2011-10-04-130825.png)

thokra
10-04-2011, 11:43 AM
Well, that looks like faulty geometry to me. I guess you're rendering a sphere which is supposed to be lit smoothly? I've never worked with OpenGL on mobile devices, but isn't GLSL supported to some extent? If so, you could visualize the normals and discover discontinuities quite easily.

yhbae
10-04-2011, 12:11 PM
Actually the goal is to be able to use any objected created within Maya to be used within my app. This particular model was also created from Maya, exported into OBJ and parsed back into my app. In this OBJ file, all normals are already defined. I don't need to calculate normals manually.

I wrote the import code with some help from other samples.

Here's some more illustrations.

Here's the screen shot from Maya. It shows a model of a fish with normals displayed at each vertex.

https://lh4.googleusercontent.com/-QJ_HgKShm6U/TotZxKe80iI/AAAAAAAAAZs/RpFuFeUKYds/fish_maya.png

And this is the result on my Android phone:

https://lh3.googleusercontent.com/-pmLCB5ifV9E/TotZwpTZFpI/AAAAAAAAAZo/3Lcz34JIZwU/fish_android.png

I'm really puzzled by the vertical patterns shown on the body of the fish. Looking at those normal vectors on the fish, I don't think I should see any patterns on the body. Most normals point to the same direction.

BionicBytes
10-04-2011, 12:13 PM
Without seeing your draw code it's a bit difficult.
It could be that you have scaled the model?
This may also be scaling the normals. Try enabling GL_NORMALIZE to make all normals unit length.

thokra
10-04-2011, 12:24 PM
Good point. Deprecating and removing the fixed-function pipeline from my brain made me overlook this. ;)

yhbae
10-04-2011, 12:40 PM
Where should I enable GL_NORMALIZE? Is it ok to do it just before

gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);

? (That didn't work for me, by the way)

Thanks again. :)

thokra
10-04-2011, 12:47 PM
IIRC this would just be glEnable(GL_NORMALIZE)...

Normalization should then be done by th GL.

yhbae
10-04-2011, 01:03 PM
Sorry I wasn't clear on my question. I can do glEnable(GL_NORMALIZE), no problem there, but where? Should this be done just once at the beginning or per each frame draw?

Thanks. :)

thokra
10-04-2011, 01:17 PM
No, normally during initialization. There shouldn't be much reason to disable normalization.

yhbae
10-05-2011, 07:15 AM
Tried but that didn't help either.

Perhaps I am interpreting the normal vectors wrong.

For a cube object, this is the content produced directly by Maya:




# This file uses centimeters as units for non-parametric coordinates.

mtllib cube.mtl
g default
v -0.965940 0.000000 0.978742
v 0.991195 0.000000 0.978742
v -0.965940 1.651515 0.978742
v 0.991195 1.651515 0.978742
v -0.965940 1.651515 -0.968730
v 0.991195 1.651515 -0.968730
v -0.965940 0.000000 -0.968730
v 0.991195 0.000000 -0.968730
vt 0.375000 0.000000
vt 0.625000 0.000000
vt 0.375000 0.250000
vt 0.625000 0.250000
vt 0.375000 0.500000
vt 0.625000 0.500000
vt 0.375000 0.750000
vt 0.625000 0.750000
vt 0.375000 1.000000
vt 0.625000 1.000000
vt 0.875000 0.000000
vt 0.875000 0.250000
vt 0.125000 0.000000
vt 0.125000 0.250000
vn 0.000000 0.000000 1.000000
vn 0.000000 0.000000 1.000000
vn 0.000000 0.000000 1.000000
vn 0.000000 0.000000 1.000000
vn 0.000000 1.000000 0.000000
vn 0.000000 1.000000 0.000000
vn 0.000000 1.000000 0.000000
vn 0.000000 1.000000 0.000000
vn 0.000000 0.000000 -1.000000
vn 0.000000 0.000000 -1.000000
vn 0.000000 0.000000 -1.000000
vn 0.000000 0.000000 -1.000000
vn 0.000000 -1.000000 0.000000
vn 0.000000 -1.000000 0.000000
vn 0.000000 -1.000000 0.000000
vn 0.000000 -1.000000 0.000000
vn 1.000000 0.000000 0.000000
vn 1.000000 0.000000 0.000000
vn 1.000000 0.000000 0.000000
vn 1.000000 0.000000 0.000000
vn -1.000000 0.000000 0.000000
vn -1.000000 0.000000 0.000000
vn -1.000000 0.000000 0.000000
vn -1.000000 0.000000 0.000000
s 1
g pCube2
usemtl initialShadingGroup
f 1/1/1 2/2/2 3/3/3
f 3/3/3 2/2/2 4/4/4
s 2
f 3/3/5 4/4/6 5/5/7
f 5/5/7 4/4/6 6/6/8
s 3
f 5/5/9 6/6/10 7/7/11
f 7/7/11 6/6/10 8/8/12
s 4
f 7/7/13 8/8/14 1/9/15
f 1/9/15 8/8/14 2/10/16
s 5
f 2/2/17 8/11/18 4/4/19
f 4/4/19 8/11/18 6/12/20
s 6
f 7/13/21 1/1/22 5/14/23
f 5/14/23 1/1/22 3/3/24


What I've done is to feed vertex and normal values in the order you see here into corresponding arrays. As for the index buffer, I've used the first of the 3 values marked under 'f' fields. I currently don't use the second and third values from the 'f' fields.

The part that I am questioning right now is how does OpenGL figure out which normals belong to which surface/vertices. As you can see here, the index numbers for normals are not passed along, while vertex coordinates are, when surfaces are defined.

I've manually checked these values for the cube and they intuitively made sense so I don't think Maya is producing a bad set of data.

I appreciate some words of wisdom from anyone. :)

_arts_
10-05-2011, 08:24 AM
Don't Lightfv before your camera transformations, otherwise the light will move along with the camera. Do it after the transformations.

yhbae
10-05-2011, 08:31 AM
Don't Lightfv before your camera transformations, otherwise the light will move along with the camera. Do it after the transformations.

Makes sense but in this case, I do want the light to move along with the camera since I am simulating a room full of moving objects. Light should stay static in relation to the room, not the objects.

thokra
10-05-2011, 09:29 AM
Ah, now I see. :)

You cannot use an OBJ to setup a index buffer. The OBJ format does not define indexed geometry which can directly be used with OpenGL. You'll have to resort to using non-indexed geometry or rewrite your OBJ loader.

For example:

f 1/1/1 2/2/2 3/3/3
f 3/3/3 2/2/2 4/4/4

This is unproblematic, since every vertex index matches the normal and tex coord indices.

f 7/7/13 8/8/14 1/9/15
f 1/9/15 8/8/14 2/10/16

This, however, will alter the the values stored pointed to by index 1 and replace the normal and tex coord with index 1 with the ones identified by indices 15 and 9 respectively.

Remember: For each group of vertex attributes, OpenGL implementations maintain only a single, unique index.

Try to replace your indexed array with a non-indexed one and render using glDrawArrays().

_arts_
10-05-2011, 09:44 AM
Light should stay static in relation to the room, not the objects.

You want a light that moves with objects but not in the room ? I think I miss what you want to do.

yhbae
10-05-2011, 09:55 AM
Hi again,

Thanks for the tips. In fact, that's exactly what I tried and it worked! :)

Its surprising how many of these OBJ loaders for Android platform on the net are wrong. I had to do exactly what you mentioned here and it works now as expected.

Once again, your tips were much appreciated. :)

yhbae
10-05-2011, 09:57 AM
Light should stay static in relation to the room, not the objects.

You want a light that moves with objects but not in the room ? I think I miss what you want to do.

I simply want to simulate an aquarium tank for this particular project. Lots of fishes will be swimming around within the tank but the light source stays exactly where it is. If I place the light placement code right before draw, the lights will appear to be moving around with the fishes which isn't exactly what I want. In my case, the camera doesn't move at all.