/*
* Copyright (C) 2007 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Modifications
Copyright 2003-2004 Bytonic Software
Copyright 2010 Google Inc.
*/
package com.googlecode.gwtquake.shared.render;
/**
* A set of GL utilities inspired by the OpenGL Utility Toolkit.
*/
public class GLU {
/**
* Return an error string from a GL or GLU error code.
*
* @param error - a GL or GLU error code.
* @return the error string for the input error code, or NULL if the input
* was not a valid GL or GLU error code.
*/
public static String gluErrorString(int error) {
switch (error) {
case Gl1Context.GL_NO_ERROR:
return "no error";
case Gl1Context.GL_INVALID_ENUM:
return "invalid enum";
case Gl1Context.GL_INVALID_VALUE:
return "invalid value";
case Gl1Context.GL_INVALID_OPERATION:
return "invalid operation";
case Gl1Context.GL_STACK_OVERFLOW:
return "stack overflow";
case Gl1Context.GL_STACK_UNDERFLOW:
return "stack underflow";
case Gl1Context.GL_OUT_OF_MEMORY:
return "out of memory";
default:
return null;
}
}
// /**
// * Define a viewing transformation in terms of an eye point, a center of
// * view, and an up vector.
// *
// * @param gl a GLAdapter interface
// * @param eyeX eye point X
// * @param eyeY eye point Y
// * @param eyeZ eye point Z
// * @param centerX center of view X
// * @param centerY center of view Y
// * @param centerZ center of view Z
// * @param upX up vector X
// * @param upY up vector Y
// * @param upZ up vector Z
// */
// public static void gluLookAt(GLAdapter gl, float eyeX, float eyeY, float eyeZ,
// float centerX, float centerY, float centerZ, float upX, float upY,
// float upZ) {
//
// // See the OpenGL GLUT documentation for gluLookAt for a description
// // of the algorithm. We implement it in a straightforward way:
//
// float fx = centerX - eyeX;
// float fy = centerY - eyeY;
// float fz = centerZ - eyeZ;
//
// // Normalize f
// float rlf = 1.0f / Matrix.length(fx, fy, fz);
// fx *= rlf;
// fy *= rlf;
// fz *= rlf;
//
// // compute s = f x up (x means "cross product")
// float sx = fy * upZ - fz * upY;
// float sy = fz * upX - fx * upZ;
// float sz = fx * upY - fy * upX;
//
// // and normalize s
// float rls = 1.0f / Matrix.length(sx, sy, sz);
// sx *= rls;
// sy *= rls;
// sz *= rls;
//
// // compute u = s x f
// float ux = sy * fz - sz * fy;
// float uy = sz * fx - sx * fz;
// float uz = sx * fy - sy * fx;
//
// float[] m = new float[16];
// m[0] = sx;
// m[1] = ux;
// m[2] = -fx;
// m[3] = 0.0f;
//
// m[4] = sy;
// m[5] = uy;
// m[6] = -fy;
// m[7] = 0.0f;
//
// m[8] = sz;
// m[9] = uz;
// m[10] = -fz;
// m[11] = 0.0f;
//
// m[12] = 0.0f;
// m[13] = 0.0f;
// m[14] = 0.0f;
// m[15] = 1.0f;
//
// gl.glMultMatrixf(m, 0);
// gl.glTranslatef(-eyeX, -eyeY, -eyeZ);
// }
//
// /**
// * Set up a 2D orthographic projection matrix
// *
// * @param gl
// * @param left
// * @param right
// * @param bottom
// * @param top
// */
// public static void gluOrtho2D(GLAdapter gl, float left, float right,
// float bottom, float top) {
// gl.glOrthof(left, right, bottom, top, -1.0f, 1.0f);
// }
/**
* Set up a perspective projection matrix
*
* @param gl a GLAdapter interface
* @param fovy specifies the field of view angle, in degrees, in the Y
* direction.
* @param aspect specifies the aspect ration that determins the field of
* view in the x direction. The aspect ratio is the ratio of x
* (width) to y (height).
* @param zNear specifies the distance from the viewer to the near clipping
* plane (always positive).
* @param zFar specifies the distance from the viewer to the far clipping
* plane (always positive).
*/
public static void gluPerspective(Gl1Context gl, float fovy, float aspect,
float zNear, float zFar) {
float top = zNear * (float) Math.tan(fovy * (Math.PI / 360.0));
float bottom = -top;
float left = bottom * aspect;
float right = top * aspect;
gl.glFrustum(left, right, bottom, top, zNear, zFar);
}
/**
* Map object coordinates into window coordinates. gluProject transforms the
* specified object coordinates into window coordinates using model, proj,
* and view. The result is stored in win.
* <p>
* Note that you can use the OES_matrix_get extension, if present, to get
* the current modelView and projection matrices.
*
* @param objX object coordinates X
* @param objY object coordinates Y
* @param objZ object coordinates Z
* @param model the current modelview matrix
* @param modelOffset the offset into the model array where the modelview
* maxtrix data starts.
* @param project the current projection matrix
* @param projectOffset the offset into the project array where the project
* matrix data starts.
* @param view the current view, {x, y, width, height}
* @param viewOffset the offset into the view array where the view vector
* data starts.
* @param win the output vector {winX, winY, winZ}, that returns the
* computed window coordinates.
* @param winOffset the offset into the win array where the win vector data
* starts.
* @return A return value of GL_TRUE indicates success, a return value of
* GL_FALSE indicates failure.
*/
public static int gluProject(float objX, float objY, float objZ,
float[] model, int modelOffset, float[] project, int projectOffset,
int[] view, int viewOffset, float[] win, int winOffset) {
float[] m = new float[16];
Matrix.multiplyMM(m, 0, project, projectOffset, model, modelOffset);
float[] v = new float[4];
v[0] = objX;
v[1] = objY;
v[2] = objZ;
v[3] = 1.0f;
float[] v2 = new float[4];
Matrix.multiplyMV(v2, 0, m, 0, v, 0);
float w = v2[3];
if (w == 0.0f) {
return Gl1Context.GL_FALSE;
}
float rw = 1.0f / w;
win[winOffset] =
view[viewOffset] + view[viewOffset + 2] * (v2[0] * rw + 1.0f)
* 0.5f;
win[winOffset + 1] =
view[viewOffset + 1] + view[viewOffset + 3]
* (v2[1] * rw + 1.0f) * 0.5f;
win[winOffset + 2] = (v2[2] * rw + 1.0f) * 0.5f;
return Gl1Context.GL_TRUE;
}
/**
* Map window coordinates to object coordinates. gluUnProject maps the
* specified window coordinates into object coordinates using model, proj,
* and view. The result is stored in obj.
* <p>
* Note that you can use the OES_matrix_get extension, if present, to get
* the current modelView and projection matrices.
*
* @param winX window coordinates X
* @param winY window coordinates Y
* @param winZ window coordinates Z
* @param model the current modelview matrix
* @param modelOffset the offset into the model array where the modelview
* maxtrix data starts.
* @param project the current projection matrix
* @param projectOffset the offset into the project array where the project
* matrix data starts.
* @param view the current view, {x, y, width, height}
* @param viewOffset the offset into the view array where the view vector
* data starts.
* @param obj the output vector {objX, objY, objZ}, that returns the
* computed object coordinates.
* @param objOffset the offset into the obj array where the obj vector data
* starts.
* @return A return value of GLAdapter.GL_TRUE indicates success, a return value
* of GLAdapter.GL_FALSE indicates failure.
*/
public static int gluUnProject(float winX, float winY, float winZ,
float[] model, int modelOffset, float[] project, int projectOffset,
int[] view, int viewOffset, float[] obj, int objOffset) {
float[] pm = new float[16];
Matrix.multiplyMM(pm, 0, project, projectOffset, model, modelOffset);
float[] invPM = new float[16];
if (!Matrix.invertM(invPM, 0, pm, 0)) {
return Gl1Context.GL_FALSE;
}
float[] v = new float[4];
v[0] =
2.0f * (winX - view[viewOffset + 0]) / view[viewOffset + 2]
- 1.0f;
v[1] =
2.0f * (winY - view[viewOffset + 1]) / view[viewOffset + 3]
- 1.0f;
v[2] = 2.0f * winZ - 1.0f;
v[3] = 1.0f;
float[] v2 = new float[4];
Matrix.multiplyMV(v2, 0, invPM, 0, v, 0);
obj[objOffset] = v2[0];
obj[objOffset + 1] = v2[1];
obj[objOffset + 2] = v2[2];
return Gl1Context.GL_TRUE;
}
}