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