Help With Redbook Example on Lighting

Started by PrintIn3DNow, February 22, 2012, 20:20:39

Previous topic - Next topic

PrintIn3DNow

Hi All, I'm hoping someone can help me. I've been trying to figure out lighting, and I'm having a heck of a time. I basically copy and pasted the Redbook's chapter 5 (example 5.1) code. Here is my translation: (NOTE: If you want to paste this into a class, that's fine, but it's not well behaved. You must disconnect the canvas before exiting)

import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JButton;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.GL11;
import org.lwjgl.util.glu.Sphere;
import java.awt.Canvas;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;

public class BasicGLTest {

	private JFrame frame;
	private Canvas rc;
	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					BasicGLTest window = new BasicGLTest();
					window.frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the application.
	 */
	public BasicGLTest() {
		initialize();
	}

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		frame = new JFrame();
		frame.setBounds(100, 100, 800, 600);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.getContentPane().setLayout(null);

		Canvas canvas = new Canvas();
		rc = canvas;
		canvas.setBounds(322, 62, 400, 400);
		frame.getContentPane().add(canvas);
		
		JButton btnMakeStuff = new JButton("Make Stuff");
		btnMakeStuff.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				try {
					Display.setParent(rc);
					Display.create();
					//GLfloat mat_specular[] = new float(){ 1.0, 1.0, 1.0, 1.0 };
					ByteBuffer mat_specular = ByteBuffer.allocateDirect(16);
					FloatBuffer ms = mat_specular.asFloatBuffer();
					ms.put(0,1.0f);ms.put(1,1.0f);ms.put(2,1.0f);ms.put(3,1.0f);
					//ms.flip();ms.rewind();
					//GLfloat mat_shininess[] = { 50.0 };
					ByteBuffer mat_shininess = ByteBuffer.allocateDirect(16);
					FloatBuffer msh = mat_shininess.asFloatBuffer();
					msh.put(0,50.0f);msh.put(1,0.0f);msh.put(2,0.0f);msh.put(3,0.0f);
					//msh.flip();msh.rewind();
					//GLfloat light_position[] = { 1.0, 1.0, 1.0, 0.0 };
					ByteBuffer light_position = ByteBuffer.allocateDirect(16);
					FloatBuffer lp = light_position.asFloatBuffer();
					lp.put(0,1.0f);lp.put(1,1.0f);lp.put(2,1.0f);lp.put(3,1.0f);
					//lp.flip();lp.rewind();
					GL11.glDisable(GL11.GL_CULL_FACE);
					GL11.glEnable(GL11.GL_TEXTURE_2D);
					GL11.glClearColor (0.0f, 0.0f, 0.0f, 0.0f);
					GL11.glShadeModel (GL11.GL_SMOOTH);

					GL11.glMaterial(GL11.GL_FRONT, GL11.GL_SPECULAR, ms);
					GL11.glMaterial(GL11.GL_FRONT, GL11.GL_SHININESS, msh);
					GL11.glLight(GL11.GL_LIGHT0, GL11.GL_POSITION, lp);

					GL11.glEnable(GL11.GL_LIGHTING);
					GL11.glEnable(GL11.GL_LIGHT0);
					GL11.glEnable(GL11.GL_DEPTH_TEST);
					GL11.glViewport (0, 0, rc.getWidth(), rc.getHeight());
					GL11.glMatrixMode (GL11.GL_PROJECTION);
					GL11.glLoadIdentity();
 				   	GL11.glOrtho (-1.5, 1.5, -1.5, 1.5, -10.0, 10.0);
 				    GL11.glMatrixMode(GL11.GL_MODELVIEW);
 				    GL11.glLoadIdentity();
 				   GL11.glClear (GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
 				   //GLU.glutSolidSphere (1.0, 20, 16);
 				   Sphere s = new Sphere();
 				   s.draw(1.0f, 20, 16);
 				   GL11.glFlush ();
 				   Display.update();

				} catch (LWJGLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				

			}
		});
		btnMakeStuff.setBounds(76, 98, 106, 23);
		frame.getContentPane().add(btnMakeStuff);
		
		JButton btnDisconnect = new JButton("Disconnect");
		btnDisconnect.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				Display.destroy();
			}
		});
		btnDisconnect.setBounds(76, 157, 106, 23);
		frame.getContentPane().add(btnDisconnect);
		
	}
}


I'm pretty sure I got it right, but the only thing that comes out is a dark black box with a very dark grey circle inside. No sphere. Any thoughts?
Thanks,
Dan

PrintIn3DNow

Hey Wait! I got it! But I don't understand why. I had a snippet like:
ByteBuffer mat_specular = ByteBuffer.allocateDirect(16);
FloatBuffer ms = mat_specular.asFloatBuffer();
ms.put(0,1.0f);ms.put(1,1.0f);ms.put(2,1.0f);ms.put(3,1.0f);
GL11.glMaterial(GL11.GL_FRONT, GL11.GL_SPECULAR, ms);


I saw someone using a different way of setting up the FloatBuffer:

float[] mat_specular = { 1.0f, 1.0f, 1.0f, 1.0f };
ByteBuffer temp = ByteBuffer.allocateDirect(16);
temp.order(ByteOrder.nativeOrder());
GL11.glMaterial(GL11.GL_FRONT, GL11.GL_SPECULAR, (FloatBuffer)temp.asFloatBuffer().put(mat_specular).flip());


When I substituted this everywhere, it suddenly worked perfectly! Can anyone explain why to me? Is it the flip? Or is it the nativeOrder? Thanks, DB

abcdef

When you set up a float buffer and put objects in it you are setting the position as you are going along so byt the time you have filled all your data the position marker is at the end. This in effect says there are no elements in the buffer from this point onwards.

To use the data you have just put in you need to reset this marker to the beginning of the buffer, a flip () or rewind() does this. Check out the api documentation for more details. The reason you need to do this is because the buffer allows you to have multiple sets of data in it and allows you to set the start marker to any point in the buffer

Fool Running

Quote from: abcdef on February 23, 2012, 10:48:20
When you set up a float buffer and put objects in it you are setting the position as you are going along so byt the time you have filled all your data the position marker is at the end. This in effect says there are no elements in the buffer from this point onwards.

To use the data you have just put in you need to reset this marker to the beginning of the buffer, a flip () or rewind() does this. Check out the api documentation for more details. The reason you need to do this is because the buffer allows you to have multiple sets of data in it and allows you to set the start marker to any point in the buffer
Although it is true that in most cases you want to do a flip() for the reasons abcdef mentioned, you were calling an overload of put() that does not have this behavior (i.e. inserting items at a particular index). Most likely your problem was not having the temp.order(ByteOrder.nativeOrder()) call. Otherwise you would have gotten an exception when the buffer was read.

Just FYI, there is a BufferUtils class (org.lwjgl.BufferUtils) that will do the creation of the buffer for you. ;D
Programmers will, one day, rule the world... and the world won't notice until its too late.Just testing the marquee option ;D

abcdef

The order shouldn't matter as you are writing and reading in the same order, the byte order is only generally an issue when you are reading from a different source (like a file).

put (myfloat) and put(1,myfloat) are the same essentially, one uses the next index and one uses the index given.

(Check out http://massapi.com/source/jdk1.6.0_17/src/java/nio/DirectByteBuffer.java.html)

Fool Running

Quote from: abcdef on February 23, 2012, 15:54:31
The order shouldn't matter as you are writing and reading in the same order, the byte order is only generally an issue when you are reading from a different source (like a file).
OpenGL always reads data in native order, thus you need to store them in native order.

Quote from: abcdef on February 23, 2012, 15:54:31
put (myfloat) and put(1,myfloat) are the same essentially, one uses the next index and one uses the index given.

(Check out http://massapi.com/source/jdk1.6.0_17/src/java/nio/DirectByteBuffer.java.html)
Quite right except that put(1,myfloat) does not change the buffer position, thus Flip() is not necessarily needed in his case since the position doesn't change.
Programmers will, one day, rule the world... and the world won't notice until its too late.Just testing the marquee option ;D