JOGL: Lighting the Inside of a Cube

Thedanisuar: thanks again for taking the time to play with my code. However, when I run your code, I still get the artifacts:

I’m still digesting basil_ and gouessej’s comments. I can tell you that I don’t really care what type of light I get: it doesn’t have to be directional, and the fact that it is directional was accidental. I just want a small working example that I can build off of.

I’ll try to play with keeping glFrustum() on the projection matrix, but any code samples you guys have to help me along are definitely appreciated.

KevinWorkman, please try to follow our recommendation, post your source code and then I’ll give it another look. If you don’t really know what to fix, let me know and I’ll tell you exactly what you have to modify. Maybe it won’t fix everything but it will eliminate a source of bugs.

Yes, I know. I wasn’t going to solve it entirely for you ;), there are issues with your camera/scene that are contributing to your lighting problems.

@basil_: “what is the light-position w-coordinate set to ? if it’s set to zero, light is treated as directional-light. not sure if that’s what you want”

Ah that’s right, I forgot that’s why it’s directional.

Okay, I’ve tried to incorporate everything you guys have said. I’ve set the light’s w to 1 so it’s not directional. I’ve made sure that glViewport() and glFrustrum() are called when the matrix mode is projection, and that everything else is called when the matrix mode is the modelview.

However, I’m still getting pretty much the same result. Updated code is below, and as always, if anybody can point out what I’m doing wrong, I’m all ears.


import java.awt.BorderLayout;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import javax.media.opengl.GL;
import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.awt.GLCanvas;
import javax.swing.JFrame;


import com.jogamp.opengl.util.FPSAnimator;

public class CameraTest implements GLEventListener {


	private final GLCanvas canvas = new GLCanvas();

	private final int worldX = -400;
	private final int worldY = -400;
	private final int worldWidth = 800;
	private final int worldHeight = 800;
	private final int worldZ = 100;
	private final int worldDepth = 800;

	public GL2 gl;

	private boolean upPressed = false;
	private boolean downPressed = false;
	private boolean leftPressed = false;
	private boolean rightPressed = false;
	private boolean pPressed = false;
	private boolean oPressed = false;

	double speed = 5;

	private double pitchAngle = 0;
	private double rollAngle = 210;

	Vector3D cameraPos = new Vector3D((worldX + worldWidth)/2, (worldY+worldHeight)/2, (worldZ + worldDepth)/2);

	Vector3D lightPos = new Vector3D((worldX + worldWidth)/2-10, (worldY+worldHeight)/2-10, (worldZ + worldDepth)/2+100);

	public CameraTest(){



		canvas.addGLEventListener(this);
		gl = (GL2) canvas.getGL();



		FPSAnimator animator = new FPSAnimator(canvas, 60);
		animator.start();

		canvas.addKeyListener(new KeyAdapter(){

			@Override
			public void keyReleased(KeyEvent e) {

				if(e.getKeyCode() == KeyEvent.VK_UP){
					upPressed = false;
				}
				else if(e.getKeyCode() == KeyEvent.VK_DOWN){
					downPressed = false;
				}
				else if(e.getKeyCode() == KeyEvent.VK_LEFT){
					leftPressed = false;
				}
				else if(e.getKeyCode() == KeyEvent.VK_RIGHT){
					rightPressed = false;
				}
				else if(e.getKeyCode() == KeyEvent.VK_P){
					pPressed = false;
				}
				else if(e.getKeyCode() == KeyEvent.VK_O){
					oPressed = false;
				}
			}

			@Override
			public void keyPressed(KeyEvent e) {


				if(e.getKeyCode() == KeyEvent.VK_UP){
					upPressed = true;
				}
				else if(e.getKeyCode() == KeyEvent.VK_DOWN){
					downPressed = true;
				}
				else if(e.getKeyCode() == KeyEvent.VK_LEFT){
					leftPressed = true;
				}
				else if(e.getKeyCode() == KeyEvent.VK_RIGHT){
					rightPressed = true;
				}
				else if(e.getKeyCode() == KeyEvent.VK_P){
					pPressed = true;
				}
				else if(e.getKeyCode() == KeyEvent.VK_O){
					oPressed = true;
				}

				else if(e.getKeyCode() == KeyEvent.VK_1){
					lightPos = lightPos.add(new Vector3D(-10, 0, 0));
				}
				else if(e.getKeyCode() == KeyEvent.VK_2){
					lightPos = lightPos.add(new Vector3D(10, 0, 0));
				}
				else if(e.getKeyCode() == KeyEvent.VK_3){
					lightPos = lightPos.add(new Vector3D(0, -10, 0));
				}
				else if(e.getKeyCode() == KeyEvent.VK_4){
					lightPos = lightPos.add(new Vector3D(0, 10, 0));
				}
				else if(e.getKeyCode() == KeyEvent.VK_5){
					lightPos = lightPos.add(new Vector3D(0, 0, -10));
				}
				else if(e.getKeyCode() == KeyEvent.VK_6){
					lightPos = lightPos.add(new Vector3D(0, 0, 10));
				}

				//System.out.println();
				System.out.println("Pos: " + lightPos.toString());
			}
		});

		JFrame frame = new JFrame("Camera Test");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.add(canvas, BorderLayout.CENTER);

		frame.setSize(500, 500);
		frame.setLocationRelativeTo(null);
		frame.setVisible(true);

		canvas.requestFocusInWindow();
	}


	public void init(GLAutoDrawable drawable) {

	}

	public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
		gl = (GL2) canvas.getGL();
		
		
		gl.glMatrixMode(GL2.GL_PROJECTION);
		gl.glLoadIdentity();
		gl.glViewport(0, 0, canvas.getWidth(), canvas.getHeight());
		gl.glFrustum(-1, 1, -1, 1, 1, 100000);
		
		
		gl.glMatrixMode(GL2.GL_MODELVIEW);
		gl.glEnable(GL.GL_CULL_FACE);
		gl.glCullFace(GL.GL_BACK);

		gl.glEnable(GL.GL_DEPTH_TEST);
		
		gl.glEnable(GL.GL_BLEND);

		gl.glEnable(GL2.GL_LIGHTING);
		gl.glEnable(GL2.GL_LIGHT0);

		gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_SPECULAR, new float[]{1f, 1f, 1f, 1}, 0);
		gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_EMISSION, new float[]{.1f, .1f, .1f, 1}, 0);
		gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_AMBIENT, new float[]{0f, 0f, 0f, 1}, 0);
		gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_DIFFUSE, new float[]{1f, 1f, 1f, 1}, 0);

		gl.glBlendFunc(GL.GL_SRC_ALPHA,  GL.GL_ONE_MINUS_SRC_ALPHA);

		gl.glLoadIdentity();

		gl.glClearColor(.25f, .25f, .25f, 1f);
	}


	public void display(GLAutoDrawable drawable){
		gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
		step();
		displayFromCamera(drawable);
	}

	private void step(){

		gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_POSITION, new float[]{(float)lightPos.x, (float)lightPos.y, (float)lightPos.z, 1}, 1);

		if(upPressed){
			pitchAngle+=1;
		}
		if(downPressed){
			pitchAngle-=1;
		}

		while(pitchAngle < 0){
			pitchAngle += 360;
		}
		while(pitchAngle > 360){
			pitchAngle -= 360;
		}

		if(leftPressed){
			if(pitchAngle < 270 && pitchAngle > 90){
				rollAngle+=1;
			}
			else{
				rollAngle-=1;
			}

		}
		if(rightPressed){
			if(pitchAngle < 270 && pitchAngle > 90){
				rollAngle-=1;
			}
			else{
				rollAngle+=1;
			}
		}
		
		if(pPressed){
			double newPosX = speed *  Math.sin(Math.toRadians(rollAngle)) * Math.cos(Math.toRadians(pitchAngle ));
			double newPosY = speed * -Math.sin(Math.toRadians(pitchAngle) );
			double newPosZ = speed *  Math.cos(Math.toRadians(rollAngle) ) * Math.cos(Math.toRadians(pitchAngle));

			cameraPos = cameraPos.add(new Vector3D(newPosX, newPosY, -newPosZ));
		}

		if(oPressed){
			double newPosX = speed *  Math.sin(Math.toRadians(rollAngle)) * Math.cos(Math.toRadians(pitchAngle ));
			double newPosY = speed * -Math.sin(Math.toRadians(pitchAngle) );
			double newPosZ = speed *  Math.cos(Math.toRadians(rollAngle) ) * Math.cos(Math.toRadians(pitchAngle));

			cameraPos = cameraPos.add(new Vector3D(-newPosX, -newPosY, newPosZ));
		}
	}

	public void displayFromCamera(GLAutoDrawable drawable){
		gl.glPushMatrix();

		gl.glLoadIdentity();
		
		gl.glRotated(pitchAngle, 1, 0, 0);
		gl.glRotated(rollAngle, 0, 1, 0);

		gl.glTranslated(-cameraPos.x, -cameraPos.y, -cameraPos.z);

		displayWholeScene(drawable, false);

		gl.glPopMatrix();
	}


	public void material(float r, float g, float b){

		float[] m = {r, g, b, 1};

		gl.glMaterialfv(GL.GL_FRONT, GL2.GL_SPECULAR, m,0);
		//   gl.glMaterialf(GL.GL_FRONT, GL.GL_SHININESS, 100.0f);
		gl.glMaterialfv(GL.GL_FRONT, GL2.GL_DIFFUSE, m, 0);
		//gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT, m, 0);
		//gl.glMaterialfv(GL.GL_FRONT, GL.GL_EMISSION, m, 0);
	}

	public void displayWholeScene(GLAutoDrawable drawable, boolean drawSnake){
		
		
		
		material(1, 1, 1);
        gl.glPointSize(1000/(cameraPos.distance(lightPos)+1));
        gl.glBegin(GL.GL_POINTS);
        gl.glVertex3d(lightPos.x, lightPos.y, lightPos.z);
        gl.glEnd();

		double w = (worldWidth)/10;
		double h = (worldHeight)/10;
		double d = worldDepth/10;

		for(double x = worldX; x < worldX+worldWidth; x+=w){
			for(double y = worldY; y < worldY+worldHeight; y+=h){

				gl.glBegin(GL2.GL_POLYGON);

				gl.glColor3f(0, 1, 0);
				material(0, .5f, 0);
				gl.glNormal3d(0, 0, -1);
				
				gl.glVertex3d(x, y+h, (worldZ+worldDepth));
				gl.glVertex3d(x+w, y+h, (worldZ+worldDepth));
				gl.glVertex3d(x+w, y, (worldZ+worldDepth));
				
				gl.glVertex3d(x, y, (worldZ+worldDepth));
				
				
				
				gl.glEnd();
			}
		}

		for(double z = worldZ; z < worldZ + worldDepth; z+=d){
			for(double y = worldY; y < worldY+worldHeight; y+=h){
				gl.glBegin(GL2.GL_POLYGON);
				gl.glColor3f(0, 0, 1);
				material(0, 0, .5f);
				gl.glNormal3d(1, 0, 0);
				
				
				
				gl.glVertex3d(worldX, y, (z+d));
				gl.glVertex3d(worldX, y, (z));
				gl.glVertex3d(worldX, y+h, (z));
				gl.glVertex3d(worldX, y+h, (z+d));

				gl.glEnd();
			}
		}


		//		gl.glBegin(GL2.GL_POLYGON);
		//		gl.glColor3f(0, 0, 1);
		//		material(0, 0, 1);
		//		gl.glNormal3d(-1, 0, 0);
		//		gl.glVertex3d(worldX, worldY+worldHeight, -(worldZ+worldDepth));
		//		gl.glVertex3d(worldX, worldY+worldHeight, -(worldZ));
		//		gl.glVertex3d(worldX, worldY, -(worldZ));
		//		gl.glVertex3d(worldX, worldY, -(worldZ+worldDepth));
		//		gl.glEnd();

	}

	public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {
	}


	private static class Vector3D{
		private final double x;
		private final double y;
		private final double z;

		public Vector3D(double x, double y, double z){
			this.x = x;
			this.y = y;
			this.z = z;
		}

		public float distance(Vector3D other) {
			return (float) Math.sqrt((x-other.x)*(x-other.x) + (y-other.y)*(y-other.y) + (z-other.z)*(z-other.z));
		}

		public Vector3D add(Vector3D delta) {
			return new Vector3D(x+delta.x, y+delta.y, z+delta.z);
		}

		public String toString(){
			return x + ", " + y + ", " + z;
		}

	}

	public static void main(String[] args) {
		new CameraTest();
	}


	@Override
	public void dispose(GLAutoDrawable arg0)
	{
		// TODO Auto-generated method stub

	}
}

another source of trouble with fixed pipeline can come from [icode]glShadeModel[/icode] when set to [icode]GL11.GL_FLAT[/icode], initial should be [icode]GL_SMOOTH[/icode] which is the right choice but maybe it’s worth to double check and just set to smooth.

https://www.opengl.org/sdk/docs/man2/xhtml/glShadeModel.xml

also worth playing with the possible settings for [icode]glLightModel[/icode] (hint GL_LIGHT_MODEL_LOCAL_VIEWER)

https://www.opengl.org/sdk/docs/man2/xhtml/glLightModel.xml

… besides [icode]GL_LIGHTING[/icode] and [icode]GL_LIGHTx[/icode] some states should be set like …

GL11.glLightModeli(GL11.GL_LIGHT_MODEL_LOCAL_VIEWER,GL11.GL_TRUE);
GL11.glLightModeli(GL11.GL_LIGHT_MODEL_TWO_SIDE,GL11.GL_TRUE);

GL11.glShadeModel(GL11.GL_SMOOTH);

// and ..

GL11.glEnable(GL11.GL_NORMALIZE);
GL11.glEnable(GL12.GL_RESCALE_NORMAL)

// and for the sake of completeness, tho' not sure if it's affecting fixed-pipe-lightning ..

GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT,GL11.GL_NICEST);

o/

I would like to take you up on this offer! It seems crazy that after a week and 4 people looking at it, nobody can tell me exactly what I’m doing wrong. I appreciate all the attempts at helping me so far, but it doesn’t seem like what I’m trying to do should be this complicated, right?

Anyway, I appreciate any help you can offer.

fixed pipe is painful. >:(

“public GL2 gl;” bad idea, never store a GL instance, it’s risky as you might use an invalid one, use GLContext.getCurrentGL().getGL2() instead.

Maybe setup your matrices correctly in init() too.

Avoid passing float arrays, use direct FloatBuffer objects, use Buffers.newDirectFloatBuffer().

Initialize your lights in init() too.

Maybe put your far plane less far, see glFrustum.

Why is there no ambient material?

gl.glNormal3d(1, 0, 0); ??? Are you sure your normals are correct???

Wait, are you not getting tons of popping with your current code? Light on then off and back on again? Also, you never answered which version of jogl you are using, NOT openGL version.

Yes, that’s exactly the current problem- the lights are “flickering” now. And I said I was originally using JOGL 1.1, but I have since switched to the latest version of JOGL as per gouessej’s suggestion. I would preferably be working in JOGL 1.1 since that’s what I’m going to have to translate this to anyway, but I’d be happy just to have something working at this point.

How can I use an invalid one, when I set the instance in the reshape() method? I’m not trying to argue, just trying to understand, as my code is based on code that my professor gave me.

Sorry if I’m being dumb, but what exactly do you mean by “setup your matrices correctly”? How am I setting them up incorrectly? What specifically looks wrong to you? What should I do instead?

Again, can I ask why? The code I’m using is taken mostly from examples the professor gave us, and he uses float arrays.

Will do. But why should this matter?

I can try this, but I want my view to basically be as large as the cube- why would making it smaller fix the problems I’m seeing?

Honestly, I don’t know. What kind of ambient material should I add?

That side of the cube is facing directly down the X axis, which is why the normal is also facing down the X axis- is that not correct?

Again, all I’m trying to get is a small “world” with a moving camera and a realistic-looking light source. I can go from there, I’m just not sure why it’s so difficult to get the very basics working. I appreciate all the help you guys have offered so far.

Sorry, your professor is wrong, he should have asked me to fix what he wrote in his book. The GL instance of a GLAutoDrawable can be invalidated at runtime, JOGL only guarantees that this invalidation can’t happen during the execution of a method in the GLEventListener, it means that the same GL instance is used during the execution of the method display(GLAutoDrawable) from the begin to the end but maybe another instance will be used in the next call. It’s better to avoid passing GL instances in order to avoid being tempted to store them.

At least do the same than what you already do in your reshape method. My reshape methods usually does a lot less except calling glViewport and setting the projection.

Each time you pass a float array, for each call, JOGL will have to create a direct NIO buffer under the hood if it is used to communicate with native OpenGL methods. Rather create your direct NIO buffers once for all even though JOGL is quite smart when managing them.

It should matter especially when you don’t pass into the reshape method. I don’t put tons of things in the reshape method…

Your view frustum is currently a lot bigger than your world.

I can’t check, my both graphics cards have a problem with light support, everything becomes black when I enable a light :s

Maybe I misread your code, sorry. Are your lights absolutely necessary? Maybe it would be better to make a first source code fully working without lights and adding them as a second step.

CameraTest, I cut out the methods without anything in them to retain some semblence of readability:

FYI: I feel like posting this much code is frowned upon so I will be hosting in the future, but for now…


public class CameraTest implements GLEventListener
{

	public GL2 gl;
	private GLU glu;
	private final GLCanvas canvas = new GLCanvas();

	private final int window_width = 500;
	private final int window_height = 500;
	private final int worldX = -400;
	private final int worldY = -400;
	private final int worldWidth = 800;
	private final int worldHeight = 800;
	private final int worldZ = 100;
	private final int worldDepth = 800;
	private final Keyboard keyboard;
	private final SimpleCamera camera;

	Vector3 light_pos = new Vector3((worldX + worldWidth) / 2 - 10,
			(worldY + worldHeight) / 2 - 10, (worldZ + worldDepth) / 2 + 100);

	public CameraTest()
	{

		keyboard = new Keyboard();
		camera = new SimpleCamera(new Vector3(0.0f, 5.0f, -5.0f));
		canvas.addGLEventListener(this);
		gl = (GL2) canvas.getGL();

		FPSAnimator animator = new FPSAnimator(canvas, 60);
		animator.start();

		canvas.addKeyListener(new KeyAdapter() {

			@Override
			public void keyReleased(KeyEvent e)
			{
				keyboard.keyUp(e);
			}

			@Override
			public void keyPressed(KeyEvent e)
			{
				keyboard.keyDown(e);
				if(keyboard.num1KeyDown()) light_pos.m_z -= 5.0f;
				if(keyboard.num2KeyDown()) light_pos.m_z += 5.0f;

				if(keyboard.num3KeyDown()) light_pos.m_x -= 5.0f;
				if(keyboard.num4KeyDown()) light_pos.m_x += 5.0f;

				if(keyboard.num5KeyDown()) light_pos.m_y -= 5.0f;
				if(keyboard.num6KeyDown()) light_pos.m_y += 5.0f;
			}
		});

		JFrame frame = new JFrame("Camera Test");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.add(canvas, BorderLayout.CENTER);

		frame.setSize(window_width, window_height);
		frame.setLocationRelativeTo(null);
		frame.setVisible(true);

		canvas.requestFocusInWindow();
	}

	public void reshape(GLAutoDrawable drawable, int x, int y, int width,
			int height)
	{
		gl = (GL2) canvas.getGL();
		glu = new GLU();
		
		gl.glEnable(GL.GL_DEPTH_TEST);
		
		gl.glEnable(GL2.GL_LIGHTING);
		gl.glEnable(GL2.GL_LIGHT0);

		gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_SPECULAR, new float[] { 1.0f, 1.0f, 1.0f, 1.0f }, 0);
		gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_EMISSION, new float[] { 0.1f, 0.1f, 0.1f, 1.0f }, 0);
		gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_AMBIENT, new float[] { 0.0f, 0.0f, 0.0f, 1.0f }, 0);
		gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_DIFFUSE, new float[] { 1.0f, 1.0f, 1.0f, 1.0f }, 0);
		gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_POSITION, new float[] { light_pos.m_x, light_pos.m_y, light_pos.m_z, 1.0f }, 0);
//		gl.glEnable(GL.GL_BLEND);
//		gl.glBlendFunc(GL.GL_SRC_ALPHA,  GL.GL_ONE_MINUS_SRC_ALPHA);
		gl.glClearColor(.25f, .25f, .25f, 1f);
	}

	public void display(GLAutoDrawable drawable)
	{
		gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
		
		//updates first
		gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_POSITION, new float[] { light_pos.m_x, light_pos.m_y, light_pos.m_z, 1.0f }, 0);
		camera.update(keyboard);
		//now draw
		camera.setPersp(gl, glu, window_width, window_height);
		displayWholeScene(gl);
	}
	public void displayWholeScene(GL2 drawable)
	{
		gl.glPointSize(5.0f);
		gl.glBegin(GL.GL_POINTS);
		gl.glVertex3d(light_pos.m_x, light_pos.m_y, light_pos.m_z);
		gl.glEnd();

		double w = (worldWidth) / 10;
		double h = (worldHeight) / 10;
		double d = worldDepth / 10;

		float[] m = { 0.5f, 0.5f, 1.0f, 1.0f };
		gl.glMaterialfv(GL.GL_FRONT, GL2.GL_SPECULAR, m, 0);
		gl.glMaterialfv(GL.GL_FRONT, GL2.GL_DIFFUSE, m, 0);
		
		for (double x = worldX; x < worldX + worldWidth; x += w)
		{
			for (double y = worldY; y < worldY + worldHeight; y += h)
			{

				gl.glBegin(GL2.GL_POLYGON);
				gl.glNormal3d(0, 0, -1);

				gl.glVertex3d(x, y + h, (worldZ + worldDepth));
				gl.glVertex3d(x + w, y + h, (worldZ + worldDepth));
				gl.glVertex3d(x + w, y, (worldZ + worldDepth));

				gl.glVertex3d(x, y, (worldZ + worldDepth));

				gl.glEnd();
			}
		}

		for (double z = worldZ; z < worldZ + worldDepth; z += d)
		{
			for (double y = worldY; y < worldY + worldHeight; y += h)
			{
				gl.glBegin(GL2.GL_POLYGON);
				gl.glNormal3d(1, 0, 0);

				gl.glVertex3d(worldX, y, (z + d));
				gl.glVertex3d(worldX, y, (z));
				gl.glVertex3d(worldX, y + h, (z));
				gl.glVertex3d(worldX, y + h, (z + d));

				gl.glEnd();
			}
		}

	}

	public static void main(String[] args)
	{
		new CameraTest();
	}
	
	public class Vector3
	{
		public float m_x; 
		public float m_y;
		public float m_z;
		
		public Vector3()
		{
			m_x = 0.0f;
			m_y = 0.0f;
			m_z = 0.0f;
		}
		
		public Vector3(float x, float y, float z)
		{
			m_x = x;
			m_y = y;
			m_z = z;
		}
	}
}

A Simple camera class:


import CameraTest.CameraTest.Vector3;

/**
 * @author Daniel DeFinis
 */
public class SimpleCamera
{
	private final static double m_pi = 3.1415926535;

	private float m_pitch;
	private float m_yaw;
	private float m_fov;
	private float m_z_near;
	private float m_z_far;
	private float m_mouse_vel;
	private float m_move_speed;

	private Vector3 m_eye;

	public SimpleCamera(Vector3 position)
	{
		m_pitch = -15.0f;
		m_yaw = 180.0f;
		m_fov = 90.0f;
		m_z_near = 0.1f;
		m_z_far = 10000.0f;
		m_mouse_vel = 1.0f;
		m_move_speed = 2.5f;
		
		m_eye = position;
	}

	private void lockCamera()
	{
		if(m_pitch > 90.0f) m_pitch = 90.0f;
		if(m_pitch < -90.0f) m_pitch = -90.0f;
		if(m_yaw > 360.0f) m_yaw -= 360.0f;
		if(m_yaw < 0.0f) m_yaw += 360.0f;
	}
	
	private void moveCameraStraff(float dist, float dir)
	{
		float rad = (float) ((m_yaw + dir) * m_pi / 180.0f);      
		m_eye.m_x -= Math.sin(rad) * dist * m_move_speed;    
		m_eye.m_z -= Math.cos(rad) * dist * m_move_speed;  
	}
	
	private void keyboardControl(Keyboard keyboard)
	{
		if(keyboard.wKeyDown())	moveCameraStraff(m_mouse_vel, 0.0f); //Move Camera FORWARD
		if(keyboard.sKeyDown())	moveCameraStraff(m_mouse_vel, 180.0f); //Move Camera REVERSE
		if(keyboard.aKeyDown())	moveCameraStraff(m_mouse_vel, 90.0f); //Move Camera LEFT
		if(keyboard.dKeyDown())	moveCameraStraff(m_mouse_vel, 270.0f); //Move Camera RIGHT
		if(keyboard.jKeyDown()) m_yaw+=0.5f;
		if(keyboard.lKeyDown()) m_yaw+=-0.5f;
		if(keyboard.iKeyDown()) m_pitch+=0.5f;
		if(keyboard.kKeyDown()) m_pitch+=-0.5f;
	}

	public void update(Keyboard keyboard)
	{
		keyboardControl(keyboard);
		lockCamera();
	}
	
	public void setPersp(GL2 gl, GLU glu, int window_width, int window_height)
	{
		//Make sure the camera is set to perspective so we can draw 3D stuff
		gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
		gl.glLoadIdentity();
		glu.gluPerspective(m_fov, (float)(window_width) / (float)(window_height), m_z_near, m_z_far);
		
		gl.glRotatef(-m_pitch, 1.0f, 0.0f, 0.0f);
		gl.glRotatef(-m_yaw, 0.0f, 1.0f, 0.0f);
		gl.glTranslatef(-m_eye.m_x, -m_eye.m_y, -m_eye.m_z);
	}
	
}

A keyboard class:


import java.awt.event.KeyEvent;

public class Keyboard 
{
	private boolean m_a_key_down;
	private boolean m_d_key_down;
	private boolean m_i_key_down;
	private boolean m_j_key_down;
	private boolean m_k_key_down;
	private boolean m_l_key_down;
	private boolean m_s_key_down;
	private boolean m_w_key_down;

	private boolean m_1_key_down;
	private boolean m_2_key_down;
	private boolean m_3_key_down;
	private boolean m_4_key_down;
	private boolean m_5_key_down;
	private boolean m_6_key_down;
	
	public Keyboard()
	{
		m_a_key_down = false;
		m_d_key_down = false;
		m_i_key_down = false;
		m_j_key_down = false;
		m_k_key_down = false;
		m_l_key_down = false;
		m_s_key_down = false;
		m_w_key_down = false;

		m_1_key_down = false;
		m_2_key_down = false;
		m_3_key_down = false;
		m_4_key_down = false;
		m_5_key_down = false;
		m_6_key_down = false;
	}
	public void keyDown(KeyEvent key)
	{		
		if(key.getKeyCode() == KeyEvent.VK_A)		m_a_key_down = true;
		if(key.getKeyCode() == KeyEvent.VK_D)		m_d_key_down = true;
		if(key.getKeyCode() == KeyEvent.VK_I)		m_i_key_down = true;
		if(key.getKeyCode() == KeyEvent.VK_J)		m_j_key_down = true;
		if(key.getKeyCode() == KeyEvent.VK_K)		m_k_key_down = true;
		if(key.getKeyCode() == KeyEvent.VK_L)		m_l_key_down = true;
		if(key.getKeyCode() == KeyEvent.VK_S)		m_s_key_down = true;
		if(key.getKeyCode() == KeyEvent.VK_W)		m_w_key_down = true;

		if(key.getKeyCode() == KeyEvent.VK_1)		m_1_key_down = true;
		if(key.getKeyCode() == KeyEvent.VK_2)		m_2_key_down = true;
		if(key.getKeyCode() == KeyEvent.VK_3)		m_3_key_down = true;
		if(key.getKeyCode() == KeyEvent.VK_4)		m_4_key_down = true;
		if(key.getKeyCode() == KeyEvent.VK_5)		m_5_key_down = true;
		if(key.getKeyCode() == KeyEvent.VK_6)		m_6_key_down = true;
		
	}
	public void keyUp(KeyEvent key)
	{		
		if(key.getKeyCode() == KeyEvent.VK_A)		m_a_key_down = false;
		if(key.getKeyCode() == KeyEvent.VK_D)		m_d_key_down = false;
		if(key.getKeyCode() == KeyEvent.VK_I)		m_i_key_down = false;
		if(key.getKeyCode() == KeyEvent.VK_J)		m_j_key_down = false;
		if(key.getKeyCode() == KeyEvent.VK_K)		m_k_key_down = false;
		if(key.getKeyCode() == KeyEvent.VK_L)		m_l_key_down = false;
		if(key.getKeyCode() == KeyEvent.VK_S)		m_s_key_down = false;
		if(key.getKeyCode() == KeyEvent.VK_W)		m_w_key_down = false;
		
		if(key.getKeyCode() == KeyEvent.VK_1)		m_1_key_down = false;
		if(key.getKeyCode() == KeyEvent.VK_2)		m_2_key_down = false;
		if(key.getKeyCode() == KeyEvent.VK_3)		m_3_key_down = false;
		if(key.getKeyCode() == KeyEvent.VK_4)		m_4_key_down = false;
		if(key.getKeyCode() == KeyEvent.VK_5)		m_5_key_down = false;
		if(key.getKeyCode() == KeyEvent.VK_6)		m_6_key_down = false;
	}

	/**@return - true if the a key is down*/
	public boolean aKeyDown() {return m_a_key_down;}
	
	/**@return - true if the d key is down*/
	public boolean dKeyDown() {return m_d_key_down;}

	/**@return - true if the i key is down*/
	public boolean iKeyDown() {return m_i_key_down;}

	/**@return - true if the j key is down*/
	public boolean jKeyDown() {return m_j_key_down;}

	/**@return - true if the k key is down*/
	public boolean kKeyDown() {return m_k_key_down;}

	/**@return - true if the l key is down*/
	public boolean lKeyDown() {return m_l_key_down;}
	
	/**@return - true if the s key is down*/
	public boolean sKeyDown() {return m_s_key_down;}

	/**@return - true if the w key is down*/
	public boolean wKeyDown() {return m_w_key_down;}

	/**@return - true if the 1 key is down*/
	public boolean num1KeyDown() {return m_1_key_down;}

	/**@return - true if the 2 key is down*/
	public boolean num2KeyDown() {return m_2_key_down;}
	
	/**@return - true if the 3 key is down*/
	public boolean num3KeyDown() {return m_3_key_down;}
	
	/**@return - true if the 4 key is down*/
	public boolean num4KeyDown() {return m_4_key_down;}

	/**@return - true if the 5 key is down*/
	public boolean num5KeyDown() {return m_5_key_down;}

	/**@return - true if the 6 key is down*/
	public boolean num6KeyDown() {return m_6_key_down;}
	
}

This is what you’re looking for, it’s only an alright example and you’ll have to change a lot of stuff(as well as optimize a ton, but that’s for later).

Also, you should really put all the code that’s in reshape into init(), because that’s what you’re doing initializing openGL.

Finally, your teacher is leading you down a very bad path. There is absolutely no reason you should be using jogl 1.1, openGL 1.0 to learn stuff? Fine. However, you should really be on the lastest verson of jogl. afaik it still has backwards compatability with openGL 1.0, but it’s all deprecated and not supported.

Thank you so much! This is exactly what I needed!

In response to goussej saying I should get something working without lights first, that’s exactly what I did. I have a fully working game, and I wanted to add lights to it, so I came up with the little example to try things out. The game (and the example) worked fine without the lights- well, I think it turns out that my camera logic was what was screwing everything up, so “working fine” is maybe not completely accurate. But now thanks to thedanisaur’s example, I have a base that I can use instead of my error-prone camera logic. I’m still not sure exactly what I was doing wrong, but oh well, I’m just thrilled to have some momentum again.

And I don’t want to badmouth my professor, so I won’t comment on the JOGL 1.1 issue. I’m sure it would be a lot of work to update the book and curriculum, and that’s probably why he sticks with JOGL 1.1. It hasn’t been too hard to translate between them, so I’m not super worried about it, but I’ll make sure to use JOGL 2+ in my own endeavors outside of class.

Thanks again for all the help you guys have given me, especially thedanisaur!

I suggested him to help him to port his code, he hasn’t yet replied. Porting code from JOGL 1.1 to JOGL 2 is quite straightforward, there are just a few imports to modify, BufferUtil must be replaced by Buffers, you have to use the profile and the GL subclasses… that’s all most of the time. I don’t blame your teacher because his book was released for the first time in 2008 and JOGL 2.0 was released several years later.

Big kudos to thedanisaur ;D

Edit.: He replied today (Sunday, November, 9th).

;D glad it’s working.

goussej, you better not get me in trouble…

My aim isn’t to get you in trouble, don’t worry. However, next time, please respect this instruction if you don’t want to get us in trouble.

Best regards.

Eh, you don’t have to “aim” to get me in trouble, to get me in trouble!

But I did post to the JOGL board originally, and only made this post after several days of crickets over there…