GLU.java revision 9066cfe9886ac131c34d59ed0e2d287b0e3c0087
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[] m = new float[16];
105        m[0] = sx;
106        m[1] = ux;
107        m[2] = -fx;
108        m[3] = 0.0f;
109
110        m[4] = sy;
111        m[5] = uy;
112        m[6] = -fy;
113        m[7] = 0.0f;
114
115        m[8] = sz;
116        m[9] = uz;
117        m[10] = -fz;
118        m[11] = 0.0f;
119
120        m[12] = 0.0f;
121        m[13] = 0.0f;
122        m[14] = 0.0f;
123        m[15] = 1.0f;
124
125        gl.glMultMatrixf(m, 0);
126        gl.glTranslatef(-eyeX, -eyeY, -eyeZ);
127    }
128
129    /**
130     * Set up a 2D orthographic projection matrix
131     *
132     * @param gl
133     * @param left
134     * @param right
135     * @param bottom
136     * @param top
137     */
138    public static void gluOrtho2D(GL10 gl, float left, float right,
139            float bottom, float top) {
140        gl.glOrthof(left, right, bottom, top, -1.0f, 1.0f);
141    }
142
143    /**
144     * Set up a perspective projection matrix
145     *
146     * @param gl a GL10 interface
147     * @param fovy specifies the field of view angle, in degrees, in the Y
148     *        direction.
149     * @param aspect specifies the aspect ration that determins the field of
150     *        view in the x direction. The aspect ratio is the ratio of x
151     *        (width) to y (height).
152     * @param zNear specifies the distance from the viewer to the near clipping
153     *        plane (always positive).
154     * @param zFar specifies the distance from the viewer to the far clipping
155     *        plane (always positive).
156     */
157    public static void gluPerspective(GL10 gl, float fovy, float aspect,
158            float zNear, float zFar) {
159        float top = zNear * (float) Math.tan(fovy * (Math.PI / 360.0));
160        float bottom = -top;
161        float left = bottom * aspect;
162        float right = top * aspect;
163        gl.glFrustumf(left, right, bottom, top, zNear, zFar);
164    }
165
166    /**
167     * Map object coordinates into window coordinates. gluProject transforms the
168     * specified object coordinates into window coordinates using model, proj,
169     * and view. The result is stored in win.
170     * <p>
171     * Note that you can use the OES_matrix_get extension, if present, to get
172     * the current modelView and projection matrices.
173     *
174     * @param objX object coordinates X
175     * @param objY object coordinates Y
176     * @param objZ object coordinates Z
177     * @param model the current modelview matrix
178     * @param modelOffset the offset into the model array where the modelview
179     *        maxtrix data starts.
180     * @param project the current projection matrix
181     * @param projectOffset the offset into the project array where the project
182     *        matrix data starts.
183     * @param view the current view, {x, y, width, height}
184     * @param viewOffset the offset into the view array where the view vector
185     *        data starts.
186     * @param win the output vector {winX, winY, winZ}, that returns the
187     *        computed window coordinates.
188     * @param winOffset the offset into the win array where the win vector data
189     *        starts.
190     * @return A return value of GL_TRUE indicates success, a return value of
191     *         GL_FALSE indicates failure.
192     */
193    public static int gluProject(float objX, float objY, float objZ,
194            float[] model, int modelOffset, float[] project, int projectOffset,
195            int[] view, int viewOffset, float[] win, int winOffset) {
196        float[] m = new float[16];
197        Matrix.multiplyMM(m, 0, project, projectOffset, model, modelOffset);
198
199        float[] v = new float[4];
200
201        v[0] = objX;
202        v[1] = objY;
203        v[2] = objZ;
204        v[3] = 1.0f;
205
206        float[] v2 = new float[4];
207
208        Matrix.multiplyMV(v2, 0, m, 0, v, 0);
209
210        float w = v2[3];
211        if (w == 0.0f) {
212            return GL10.GL_FALSE;
213        }
214
215        float rw = 1.0f / w;
216
217        win[winOffset] =
218                view[viewOffset] + view[viewOffset + 2] * (v2[0] * rw + 1.0f)
219                        * 0.5f;
220        win[winOffset + 1] =
221                view[viewOffset + 1] + view[viewOffset + 3]
222                        * (v2[1] * rw + 1.0f) * 0.5f;
223        win[winOffset + 2] = (v2[2] * rw + 1.0f) * 0.5f;
224
225        return GL10.GL_TRUE;
226    }
227
228    /**
229     * Map window coordinates to object coordinates. gluUnProject maps the
230     * specified window coordinates into object coordinates using model, proj,
231     * and view. The result is stored in obj.
232     * <p>
233     * Note that you can use the OES_matrix_get extension, if present, to get
234     * the current modelView and projection matrices.
235     *
236     * @param winX window coordinates X
237     * @param winY window coordinates Y
238     * @param winZ window coordinates Z
239     * @param model the current modelview matrix
240     * @param modelOffset the offset into the model array where the modelview
241     *        maxtrix data starts.
242     * @param project the current projection matrix
243     * @param projectOffset the offset into the project array where the project
244     *        matrix data starts.
245     * @param view the current view, {x, y, width, height}
246     * @param viewOffset the offset into the view array where the view vector
247     *        data starts.
248     * @param obj the output vector {objX, objY, objZ}, that returns the
249     *        computed object coordinates.
250     * @param objOffset the offset into the obj array where the obj vector data
251     *        starts.
252     * @return A return value of GL10.GL_TRUE indicates success, a return value
253     *         of GL10.GL_FALSE indicates failure.
254     */
255    public static int gluUnProject(float winX, float winY, float winZ,
256            float[] model, int modelOffset, float[] project, int projectOffset,
257            int[] view, int viewOffset, float[] obj, int objOffset) {
258        float[] pm = new float[16];
259        Matrix.multiplyMM(pm, 0, project, projectOffset, model, modelOffset);
260
261        float[] invPM = new float[16];
262        if (!Matrix.invertM(invPM, 0, pm, 0)) {
263            return GL10.GL_FALSE;
264        }
265
266        float[] v = new float[4];
267
268        v[0] =
269                2.0f * (winX - view[viewOffset + 0]) / view[viewOffset + 2]
270                        - 1.0f;
271        v[1] =
272                2.0f * (winY - view[viewOffset + 1]) / view[viewOffset + 3]
273                        - 1.0f;
274        v[2] = 2.0f * winZ - 1.0f;
275        v[3] = 1.0f;
276
277        float[] v2 = new float[4];
278
279        Matrix.multiplyMV(v2, 0, invPM, 0, v, 0);
280
281        obj[objOffset] = v2[0];
282        obj[objOffset + 1] = v2[1];
283        obj[objOffset + 2] = v2[2];
284
285        return GL10.GL_TRUE;
286    }
287
288 }
289