1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.opengl; 18 19 import javax.microedition.khronos.opengles.GL10; 20 21 /** 22 * A set of GL utilities inspired by the OpenGL Utility Toolkit. 23 * 24 */ 25 26 public class GLU { 27 28 /** 29 * Return an error string from a GL or GLU error code. 30 * 31 * @param error - a GL or GLU error code. 32 * @return the error string for the input error code, or NULL if the input 33 * was not a valid GL or GLU error code. 34 */ gluErrorString(int error)35 public static String gluErrorString(int error) { 36 switch (error) { 37 case GL10.GL_NO_ERROR: 38 return "no error"; 39 case GL10.GL_INVALID_ENUM: 40 return "invalid enum"; 41 case GL10.GL_INVALID_VALUE: 42 return "invalid value"; 43 case GL10.GL_INVALID_OPERATION: 44 return "invalid operation"; 45 case GL10.GL_STACK_OVERFLOW: 46 return "stack overflow"; 47 case GL10.GL_STACK_UNDERFLOW: 48 return "stack underflow"; 49 case GL10.GL_OUT_OF_MEMORY: 50 return "out of memory"; 51 default: 52 return null; 53 } 54 } 55 56 /** 57 * Define a viewing transformation in terms of an eye point, a center of 58 * view, and an up vector. 59 * 60 * @param gl a GL10 interface 61 * @param eyeX eye point X 62 * @param eyeY eye point Y 63 * @param eyeZ eye point Z 64 * @param centerX center of view X 65 * @param centerY center of view Y 66 * @param centerZ center of view Z 67 * @param upX up vector X 68 * @param upY up vector Y 69 * @param upZ up vector Z 70 */ gluLookAt(GL10 gl, float eyeX, float eyeY, float eyeZ, float centerX, float centerY, float centerZ, float upX, float upY, float upZ)71 public static void gluLookAt(GL10 gl, float eyeX, float eyeY, float eyeZ, 72 float centerX, float centerY, float centerZ, float upX, float upY, 73 float upZ) { 74 75 // See the OpenGL GLUT documentation for gluLookAt for a description 76 // of the algorithm. We implement it in a straightforward way: 77 78 float fx = centerX - eyeX; 79 float fy = centerY - eyeY; 80 float fz = centerZ - eyeZ; 81 82 // Normalize f 83 float rlf = 1.0f / Matrix.length(fx, fy, fz); 84 fx *= rlf; 85 fy *= rlf; 86 fz *= rlf; 87 88 // compute s = f x up (x means "cross product") 89 float sx = fy * upZ - fz * upY; 90 float sy = fz * upX - fx * upZ; 91 float sz = fx * upY - fy * upX; 92 93 // and normalize s 94 float rls = 1.0f / Matrix.length(sx, sy, sz); 95 sx *= rls; 96 sy *= rls; 97 sz *= rls; 98 99 // compute u = s x f 100 float ux = sy * fz - sz * fy; 101 float uy = sz * fx - sx * fz; 102 float uz = sx * fy - sy * fx; 103 104 float[] scratch = sScratch; 105 synchronized(scratch) { 106 scratch[0] = sx; 107 scratch[1] = ux; 108 scratch[2] = -fx; 109 scratch[3] = 0.0f; 110 111 scratch[4] = sy; 112 scratch[5] = uy; 113 scratch[6] = -fy; 114 scratch[7] = 0.0f; 115 116 scratch[8] = sz; 117 scratch[9] = uz; 118 scratch[10] = -fz; 119 scratch[11] = 0.0f; 120 121 scratch[12] = 0.0f; 122 scratch[13] = 0.0f; 123 scratch[14] = 0.0f; 124 scratch[15] = 1.0f; 125 126 gl.glMultMatrixf(scratch, 0); 127 } 128 gl.glTranslatef(-eyeX, -eyeY, -eyeZ); 129 } 130 131 /** 132 * Set up a 2D orthographic projection matrix 133 * 134 * @param gl 135 * @param left 136 * @param right 137 * @param bottom 138 * @param top 139 */ gluOrtho2D(GL10 gl, float left, float right, float bottom, float top)140 public static void gluOrtho2D(GL10 gl, float left, float right, 141 float bottom, float top) { 142 gl.glOrthof(left, right, bottom, top, -1.0f, 1.0f); 143 } 144 145 /** 146 * Set up a perspective projection matrix 147 * 148 * @param gl a GL10 interface 149 * @param fovy specifies the field of view angle, in degrees, in the Y 150 * direction. 151 * @param aspect specifies the aspect ration that determins the field of 152 * view in the x direction. The aspect ratio is the ratio of x 153 * (width) to y (height). 154 * @param zNear specifies the distance from the viewer to the near clipping 155 * plane (always positive). 156 * @param zFar specifies the distance from the viewer to the far clipping 157 * plane (always positive). 158 */ gluPerspective(GL10 gl, float fovy, float aspect, float zNear, float zFar)159 public static void gluPerspective(GL10 gl, float fovy, float aspect, 160 float zNear, float zFar) { 161 float top = zNear * (float) Math.tan(fovy * (Math.PI / 360.0)); 162 float bottom = -top; 163 float left = bottom * aspect; 164 float right = top * aspect; 165 gl.glFrustumf(left, right, bottom, top, zNear, zFar); 166 } 167 168 /** 169 * Map object coordinates into window coordinates. gluProject transforms the 170 * specified object coordinates into window coordinates using model, proj, 171 * and view. The result is stored in win. 172 * <p> 173 * Note that you can use the OES_matrix_get extension, if present, to get 174 * the current modelView and projection matrices. 175 * 176 * @param objX object coordinates X 177 * @param objY object coordinates Y 178 * @param objZ object coordinates Z 179 * @param model the current modelview matrix 180 * @param modelOffset the offset into the model array where the modelview 181 * maxtrix data starts. 182 * @param project the current projection matrix 183 * @param projectOffset the offset into the project array where the project 184 * matrix data starts. 185 * @param view the current view, {x, y, width, height} 186 * @param viewOffset the offset into the view array where the view vector 187 * data starts. 188 * @param win the output vector {winX, winY, winZ}, that returns the 189 * computed window coordinates. 190 * @param winOffset the offset into the win array where the win vector data 191 * starts. 192 * @return A return value of GL_TRUE indicates success, a return value of 193 * GL_FALSE indicates failure. 194 */ gluProject(float objX, float objY, float objZ, float[] model, int modelOffset, float[] project, int projectOffset, int[] view, int viewOffset, float[] win, int winOffset)195 public static int gluProject(float objX, float objY, float objZ, 196 float[] model, int modelOffset, float[] project, int projectOffset, 197 int[] view, int viewOffset, float[] win, int winOffset) { 198 float[] scratch = sScratch; 199 synchronized(scratch) { 200 final int M_OFFSET = 0; // 0..15 201 final int V_OFFSET = 16; // 16..19 202 final int V2_OFFSET = 20; // 20..23 203 Matrix.multiplyMM(scratch, M_OFFSET, project, projectOffset, 204 model, modelOffset); 205 206 scratch[V_OFFSET + 0] = objX; 207 scratch[V_OFFSET + 1] = objY; 208 scratch[V_OFFSET + 2] = objZ; 209 scratch[V_OFFSET + 3] = 1.0f; 210 211 Matrix.multiplyMV(scratch, V2_OFFSET, 212 scratch, M_OFFSET, scratch, V_OFFSET); 213 214 float w = scratch[V2_OFFSET + 3]; 215 if (w == 0.0f) { 216 return GL10.GL_FALSE; 217 } 218 219 float rw = 1.0f / w; 220 221 win[winOffset] = 222 view[viewOffset] + view[viewOffset + 2] 223 * (scratch[V2_OFFSET + 0] * rw + 1.0f) 224 * 0.5f; 225 win[winOffset + 1] = 226 view[viewOffset + 1] + view[viewOffset + 3] 227 * (scratch[V2_OFFSET + 1] * rw + 1.0f) * 0.5f; 228 win[winOffset + 2] = (scratch[V2_OFFSET + 2] * rw + 1.0f) * 0.5f; 229 } 230 231 return GL10.GL_TRUE; 232 } 233 234 /** 235 * Map window coordinates to object coordinates. gluUnProject maps the 236 * specified window coordinates into object coordinates using model, proj, 237 * and view. The result is stored in obj. 238 * <p> 239 * Note that you can use the OES_matrix_get extension, if present, to get 240 * the current modelView and projection matrices. 241 * 242 * @param winX window coordinates X 243 * @param winY window coordinates Y 244 * @param winZ window coordinates Z 245 * @param model the current modelview matrix 246 * @param modelOffset the offset into the model array where the modelview 247 * maxtrix data starts. 248 * @param project the current projection matrix 249 * @param projectOffset the offset into the project array where the project 250 * matrix data starts. 251 * @param view the current view, {x, y, width, height} 252 * @param viewOffset the offset into the view array where the view vector 253 * data starts. 254 * @param obj the output vector {objX, objY, objZ}, that returns the 255 * computed object coordinates. 256 * @param objOffset the offset into the obj array where the obj vector data 257 * starts. 258 * @return A return value of GL10.GL_TRUE indicates success, a return value 259 * of GL10.GL_FALSE indicates failure. 260 */ gluUnProject(float winX, float winY, float winZ, float[] model, int modelOffset, float[] project, int projectOffset, int[] view, int viewOffset, float[] obj, int objOffset)261 public static int gluUnProject(float winX, float winY, float winZ, 262 float[] model, int modelOffset, float[] project, int projectOffset, 263 int[] view, int viewOffset, float[] obj, int objOffset) { 264 float[] scratch = sScratch; 265 synchronized(scratch) { 266 final int PM_OFFSET = 0; // 0..15 267 final int INVPM_OFFSET = 16; // 16..31 268 final int V_OFFSET = 0; // 0..3 Reuses PM_OFFSET space 269 Matrix.multiplyMM(scratch, PM_OFFSET, project, projectOffset, 270 model, modelOffset); 271 272 if (!Matrix.invertM(scratch, INVPM_OFFSET, scratch, PM_OFFSET)) { 273 return GL10.GL_FALSE; 274 } 275 276 scratch[V_OFFSET + 0] = 277 2.0f * (winX - view[viewOffset + 0]) / view[viewOffset + 2] 278 - 1.0f; 279 scratch[V_OFFSET + 1] = 280 2.0f * (winY - view[viewOffset + 1]) / view[viewOffset + 3] 281 - 1.0f; 282 scratch[V_OFFSET + 2] = 2.0f * winZ - 1.0f; 283 scratch[V_OFFSET + 3] = 1.0f; 284 285 Matrix.multiplyMV(obj, objOffset, scratch, INVPM_OFFSET, 286 scratch, V_OFFSET); 287 } 288 289 return GL10.GL_TRUE; 290 } 291 292 private static final float[] sScratch = new float[32]; 293 } 294