Program: 109227
Project: 109227
Buggy source:
/** 
 * More flexible method for dealing with camera(). <P> The actual call is like gluLookat. Here's the real skinny on what does what: <PRE> camera(); or camera(ex, ey, ez, cx, cy, cz, ux, uy, uz); </PRE> do not need to be called from with beginCamera();/endCamera(); That's because they always apply to the camera transformation, and they always totally replace it. That means that any coordinate transforms done before camera(); in draw() will be wiped out. It also means that camera() always operates in untransformed world coordinates. Therefore it is always redundant to call resetMatrix(); before camera(); This isn't technically true of gluLookat, but it's pretty much how it's used. <P> Now, beginCamera(); and endCamera(); are useful if you want to move the camera around using transforms like translate(), etc. They will wipe out any coordinate system transforms that occur before them in draw(), but they will not automatically wipe out the camera transform. This means that they should be at the top of draw(). It also means that the following: <PRE> beginCamera(); rotateY(PI / 8); endCamera(); </PRE> will result in a camera that spins without stopping. If you want to just rotate a small constant amount, try this: <PRE> beginCamera(); camera(); // sets up the default view rotateY(PI / 8); endCamera(); </PRE> That will rotate a little off of the default view. Note that this is entirely equivalent to <PRE> camera(); // sets up the default view beginCamera(); rotateY(PI / 8); endCamera(); </PRE> because camera() doesn't care whether or not it's inside a begin/end clause. Basically it's safe to use camera() or camera(ex, ey, ez, cx, cy, cz, ux, uy, uz) as naked calls because they do all the matrix resetting automatically.
 */
public void camera(float eyeX,float eyeY,float eyeZ,float centerX,float centerY,float centerZ,float upX,float upY,float upZ){
  eyeY=height - eyeY;
  centerY=height - centerY;
  float z0=eyeX - centerX;
  float z1=eyeY - centerY;
  float z2=eyeZ - centerZ;
  float mag=sqrt(z0 * z0 + z1 * z1 + z2 * z2);
  if (mag != 0) {
    z0/=mag;
    z1/=mag;
    z2/=mag;
  }
  float y0=upX;
  float y1=upY;
  float y2=upZ;
  float x0=y1 * z2 - y2 * z1;
  float x1=-y0 * z2 + y2 * z0;
  float x2=y0 * z1 - y1 * z0;
  y0=z1 * x2 - z2 * x1;
  y1=-z0 * x2 + z2 * x0;
  y2=z0 * x1 - z1 * x0;
  mag=sqrt(x0 * x0 + x1 * x1 + x2 * x2);
  if (mag != 0) {
    x0/=mag;
    x1/=mag;
    x2/=mag;
  }
  mag=sqrt(y0 * y0 + y1 * y1 + y2 * y2);
  if (mag != 0) {
    y0/=mag;
    y1/=mag;
    y2/=mag;
  }
  float[] m=glmodelview;
  m[0]=x0;
  m[1]=y0;
  m[2]=z0;
  m[3]=0.0f;
  m[4]=x1;
  m[5]=y1;
  m[6]=z1;
  m[7]=0.0f;
  m[8]=x2;
  m[9]=y2;
  m[10]=z2;
  m[11]=0;
  m[12]=0.0f;
  m[13]=0.0f;
  m[14]=0.0f;
  m[15]=1.0f;
  float tx=-eyeX;
  float ty=-eyeY + height;
  float tz=-eyeZ;
  m[12]+=tx * m[0] + ty * m[4] + tz * m[8];
  m[13]+=tx * m[1] + ty * m[5] + tz * m[9];
  m[14]+=tx * m[2] + ty * m[6] + tz * m[10];
  m[15]+=tx * m[3] + ty * m[7] + tz * m[11];
  m[4]=-m[4];
  m[5]=-m[5];
  m[6]=-m[6];
  m[7]=-m[7];
  gl.glMatrixMode(GL10.GL_MODELVIEW);
  gl.glLoadMatrixf(glmodelview,0);
  if (usingModelviewStack) {
    modelviewStack.set(glmodelview);
  }
  copyGLArrayToPMatrix(glmodelview,modelview);
  modelviewUpdated=true;
  calculateModelviewInvNoScaling();
  PApplet.arrayCopy(glmodelview,pcamera);
  PApplet.arrayCopy(glmodelviewInv,pcameraInv);
  copyGLArrayToPMatrix(pcamera,camera);
  copyGLArrayToPMatrix(pcameraInv,cameraInv);
}

Fixed version (ground truth):
/** 
 * More flexible method for dealing with camera(). <P> The actual call is like gluLookat. Here's the real skinny on what does what: <PRE> camera(); or camera(ex, ey, ez, cx, cy, cz, ux, uy, uz); </PRE> do not need to be called from with beginCamera();/endCamera(); That's because they always apply to the camera transformation, and they always totally replace it. That means that any coordinate transforms done before camera(); in draw() will be wiped out. It also means that camera() always operates in untransformed world coordinates. Therefore it is always redundant to call resetMatrix(); before camera(); This isn't technically true of gluLookat, but it's pretty much how it's used. <P> Now, beginCamera(); and endCamera(); are useful if you want to move the camera around using transforms like translate(), etc. They will wipe out any coordinate system transforms that occur before them in draw(), but they will not automatically wipe out the camera transform. This means that they should be at the top of draw(). It also means that the following: <PRE> beginCamera(); rotateY(PI / 8); endCamera(); </PRE> will result in a camera that spins without stopping. If you want to just rotate a small constant amount, try this: <PRE> beginCamera(); camera(); // sets up the default view rotateY(PI / 8); endCamera(); </PRE> That will rotate a little off of the default view. Note that this is entirely equivalent to <PRE> camera(); // sets up the default view beginCamera(); rotateY(PI / 8); endCamera(); </PRE> because camera() doesn't care whether or not it's inside a begin/end clause. Basically it's safe to use camera() or camera(ex, ey, ez, cx, cy, cz, ux, uy, uz) as naked calls because they do all the matrix resetting automatically.
 */
public void camera(float eyeX,float eyeY,float eyeZ,float centerX,float centerY,float centerZ,float upX,float upY,float upZ){
  eyeY=height - eyeY;
  centerY=height - centerY;
  currentEyeX=eyeX;
  currentCenterY=centerY;
  float z0=eyeX - centerX;
  float z1=eyeY - centerY;
  float z2=eyeZ - centerZ;
  float mag=sqrt(z0 * z0 + z1 * z1 + z2 * z2);
  if (mag != 0) {
    z0/=mag;
    z1/=mag;
    z2/=mag;
  }
  float y0=upX;
  float y1=upY;
  float y2=upZ;
  float x0=y1 * z2 - y2 * z1;
  float x1=-y0 * z2 + y2 * z0;
  float x2=y0 * z1 - y1 * z0;
  y0=z1 * x2 - z2 * x1;
  y1=-z0 * x2 + z2 * x0;
  y2=z0 * x1 - z1 * x0;
  mag=sqrt(x0 * x0 + x1 * x1 + x2 * x2);
  if (mag != 0) {
    x0/=mag;
    x1/=mag;
    x2/=mag;
  }
  mag=sqrt(y0 * y0 + y1 * y1 + y2 * y2);
  if (mag != 0) {
    y0/=mag;
    y1/=mag;
    y2/=mag;
  }
  float[] m=glmodelview;
  m[0]=x0;
  m[1]=y0;
  m[2]=z0;
  m[3]=0.0f;
  m[4]=x1;
  m[5]=y1;
  m[6]=z1;
  m[7]=0.0f;
  m[8]=x2;
  m[9]=y2;
  m[10]=z2;
  m[11]=0;
  m[12]=0.0f;
  m[13]=0.0f;
  m[14]=0.0f;
  m[15]=1.0f;
  float tx=-eyeX;
  float ty=-eyeY + height;
  float tz=-eyeZ;
  m[12]+=tx * m[0] + ty * m[4] + tz * m[8];
  m[13]+=tx * m[1] + ty * m[5] + tz * m[9];
  m[14]+=tx * m[2] + ty * m[6] + tz * m[10];
  m[15]+=tx * m[3] + ty * m[7] + tz * m[11];
  m[4]=-m[4];
  m[5]=-m[5];
  m[6]=-m[6];
  m[7]=-m[7];
  gl.glMatrixMode(GL10.GL_MODELVIEW);
  gl.glLoadMatrixf(glmodelview,0);
  if (usingModelviewStack) {
    modelviewStack.set(glmodelview);
  }
  copyGLArrayToPMatrix(glmodelview,modelview);
  modelviewUpdated=true;
  calculateModelviewInvNoScaling();
  PApplet.arrayCopy(glmodelview,pcamera);
  PApplet.arrayCopy(glmodelviewInv,pcameraInv);
  copyGLArrayToPMatrix(pcamera,camera);
  copyGLArrayToPMatrix(pcameraInv,cameraInv);
}