GLU.java revision 843ef36f7b96cc19ea7d2996b7c8661b41ec3452
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
17package android.opengl;
18
19import javax.microedition.khronos.opengles.GL10;
20
21/**
22 * A set of GL utilities inspired by the OpenGL Utility Toolkit.
23 *
24 */
25
26public 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     */
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     */
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     */
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     */
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     */
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     */
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