001: /*
002: *
003: * Copyright (c) 2007, Sun Microsystems, Inc.
004: *
005: * All rights reserved.
006: *
007: * Redistribution and use in source and binary forms, with or without
008: * modification, are permitted provided that the following conditions
009: * are met:
010: *
011: * * Redistributions of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: * * Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in the
015: * documentation and/or other materials provided with the distribution.
016: * * Neither the name of Sun Microsystems nor the names of its contributors
017: * may be used to endorse or promote products derived from this software
018: * without specific prior written permission.
019: *
020: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
021: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
022: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
023: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
024: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
025: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
026: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
027: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
028: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
029: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
030: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
031: */
032: package com.sun.jsr239.wtksamples.cube;
033:
034: import java.nio.*;
035:
036: import javax.microedition.khronos.egl.*;
037: import javax.microedition.khronos.opengles.*;
038: import javax.microedition.lcdui.Command;
039: import javax.microedition.lcdui.CommandListener;
040: import javax.microedition.lcdui.Display;
041: import javax.microedition.lcdui.Displayable;
042: import javax.microedition.lcdui.Graphics;
043: import javax.microedition.lcdui.game.GameCanvas;
044: import javax.microedition.midlet.MIDlet;
045:
046: class CubeCanvas extends GameCanvas implements Runnable {
047: private static final byte[] s_cubeVertices = { -10, 10, 10, 10,
048: -10, 10, 10, 10, 10, -10, -10, 10,
049:
050: -10, 10, -10, 10, -10, -10, 10, 10, -10, -10, -10, -10,
051:
052: -10, -10, 10, 10, -10, -10, 10, -10, 10, -10, -10, -10,
053:
054: -10, 10, 10, 10, 10, -10, 10, 10, 10, -10, 10, -10,
055:
056: 10, -10, 10, 10, 10, -10, 10, 10, 10, 10, -10, -10,
057:
058: -10, -10, 10, -10, 10, -10, -10, 10, 10, -10, -10, -10 };
059: private static final byte[] s_cubeColors = { (byte) 40, (byte) 80,
060: (byte) 160, (byte) 255, (byte) 40, (byte) 80, (byte) 160,
061: (byte) 255, (byte) 40, (byte) 80, (byte) 160, (byte) 255,
062: (byte) 40, (byte) 80, (byte) 160, (byte) 255,
063:
064: (byte) 40, (byte) 80, (byte) 160, (byte) 255, (byte) 40,
065: (byte) 80, (byte) 160, (byte) 255, (byte) 40, (byte) 80,
066: (byte) 160, (byte) 255, (byte) 40, (byte) 80, (byte) 160,
067: (byte) 255,
068:
069: (byte) 128, (byte) 128, (byte) 128, (byte) 255, (byte) 128,
070: (byte) 128, (byte) 128, (byte) 255, (byte) 128, (byte) 128,
071: (byte) 128, (byte) 255, (byte) 128, (byte) 128, (byte) 128,
072: (byte) 255,
073:
074: (byte) 128, (byte) 128, (byte) 128, (byte) 255, (byte) 128,
075: (byte) 128, (byte) 128, (byte) 255, (byte) 128, (byte) 128,
076: (byte) 128, (byte) 255, (byte) 128, (byte) 128, (byte) 128,
077: (byte) 255,
078:
079: (byte) 255, (byte) 110, (byte) 10, (byte) 255, (byte) 255,
080: (byte) 110, (byte) 10, (byte) 255, (byte) 255, (byte) 110,
081: (byte) 10, (byte) 255, (byte) 255, (byte) 110, (byte) 10,
082: (byte) 255,
083:
084: (byte) 255, (byte) 70, (byte) 60, (byte) 255, (byte) 255,
085: (byte) 70, (byte) 60, (byte) 255, (byte) 255, (byte) 70,
086: (byte) 60, (byte) 255, (byte) 255, (byte) 70, (byte) 60,
087: (byte) 255 };
088: private static final byte[] s_cubeIndices = { 0, 3, 1, 2, 0, 1, /* front */
089: 6, 5, 4, 5, 7, 4, /* back */
090: 8, 11, 9, 10, 8, 9, /* top */
091: 15, 12, 13, 12, 14, 13, /* bottom */
092: 16, 19, 17, 18, 16, 17, /* right */
093: 23, 20, 21, 20, 22, 21 /* left */
094: };
095: private static final byte[] s_cubeNormals = { 0, 0, 127, 0, 0, 127,
096: 0, 0, 127, 0, 0, 127,
097:
098: 0, 0, -128, 0, 0, -128, 0, 0, -128, 0, 0, -128,
099:
100: 0, -128, 0, 0, -128, 0, 0, -128, 0, 0, -128, 0,
101:
102: 0, 127, 0, 0, 127, 0, 0, 127, 0, 0, 127, 0,
103:
104: 127, 0, 0, 127, 0, 0, 127, 0, 0, 127, 0, 0,
105:
106: -128, 0, 0, -128, 0, 0, -128, 0, 0, -128, 0, 0 };
107: boolean initialized = false;
108: int frame = 0;
109: float time = 0.0f;
110: Graphics g;
111: int width;
112: int height;
113: Cube cube;
114: EGL10 egl;
115: GL10 gl;
116: EGLConfig eglConfig;
117: EGLDisplay eglDisplay;
118: EGLSurface eglWindowSurface;
119: EGLContext eglContext;
120: ByteBuffer cubeVertices;
121: ByteBuffer cubeColors;
122: ByteBuffer cubeNormals;
123: ByteBuffer cubeIndices;
124:
125: public CubeCanvas(Cube cube) {
126: super (true);
127: this .cube = cube;
128: this .g = this .getGraphics();
129:
130: this .width = getWidth();
131: this .height = getHeight();
132: }
133:
134: private int getProperty(String propName, int def) {
135: String s = cube.getAppProperty(propName);
136: int val = (s == null) ? def : Integer.parseInt(s);
137:
138: return val;
139: }
140:
141: public void init() {
142: this .egl = (EGL10) EGLContext.getEGL();
143:
144: this .eglDisplay = egl.eglGetDisplay(egl.EGL_DEFAULT_DISPLAY);
145:
146: int[] major_minor = new int[2];
147: egl.eglInitialize(eglDisplay, major_minor);
148:
149: int[] num_config = new int[1];
150:
151: egl.eglGetConfigs(eglDisplay, null, 0, num_config);
152: System.out.println("num_config[0] = " + num_config[0]);
153:
154: int redSize = getProperty("jsr239.redSize", 8);
155: int greenSize = getProperty("jsr239.greenSize", 8);
156: int blueSize = getProperty("jsr239.blueSize", 8);
157: int alphaSize = getProperty("jsr239.alphaSize", 0);
158: int depthSize = getProperty("jsr239.depthSize", 32);
159: int stencilSize = getProperty("jsr239.stencilSize",
160: EGL10.EGL_DONT_CARE);
161:
162: int[] s_configAttribs = { EGL10.EGL_RED_SIZE, redSize,
163: EGL10.EGL_GREEN_SIZE, greenSize, EGL10.EGL_BLUE_SIZE,
164: blueSize, EGL10.EGL_ALPHA_SIZE, alphaSize,
165: EGL10.EGL_DEPTH_SIZE, depthSize,
166: EGL10.EGL_STENCIL_SIZE, stencilSize, EGL10.EGL_NONE };
167:
168: EGLConfig[] eglConfigs = new EGLConfig[num_config[0]];
169: egl.eglChooseConfig(eglDisplay, s_configAttribs, eglConfigs,
170: eglConfigs.length, num_config);
171: System.out.println("num_config[0] = " + num_config[0]);
172:
173: this .eglConfig = eglConfigs[0];
174:
175: this .eglContext = egl.eglCreateContext(eglDisplay, eglConfig,
176: EGL10.EGL_NO_CONTEXT, null);
177:
178: this .gl = (GL10) eglContext.getGL();
179:
180: this .eglWindowSurface = egl.eglCreateWindowSurface(eglDisplay,
181: eglConfig, g, null);
182:
183: // Initialize data Buffers
184: this .cubeVertices = ByteBuffer
185: .allocateDirect(s_cubeVertices.length);
186: cubeVertices.put(s_cubeVertices);
187: cubeVertices.rewind();
188:
189: this .cubeColors = ByteBuffer
190: .allocateDirect(s_cubeColors.length);
191: cubeColors.put(s_cubeColors);
192: cubeColors.rewind();
193:
194: this .cubeNormals = ByteBuffer
195: .allocateDirect(s_cubeNormals.length);
196: cubeNormals.put(s_cubeNormals);
197: cubeNormals.rewind();
198:
199: this .cubeIndices = ByteBuffer
200: .allocateDirect(s_cubeIndices.length);
201: cubeIndices.put(s_cubeIndices);
202: cubeIndices.rewind();
203:
204: this .initialized = true;
205: }
206:
207: private void perspective(float fovy, float aspect, float zNear,
208: float zFar) {
209: float xmin;
210: float xmax;
211: float ymin;
212: float ymax;
213:
214: ymax = zNear * (float) Math.tan((fovy * Math.PI) / 360.0);
215: ymin = -ymax;
216: xmin = ymin * aspect;
217: xmax = ymax * aspect;
218:
219: gl.glFrustumf(xmin, xmax, ymin, ymax, zNear, zFar);
220: }
221:
222: private void updateState(int width, int height) {
223: float[] light_position = { -50.f, 50.f, 50.f, 0.f };
224: float[] light_ambient = { 0.125f, 0.125f, 0.125f, 1.f };
225: float[] light_diffuse = { 1.0f, 1.0f, 1.0f, 1.f };
226: float[] material_spec = { 1.0f, 1.0f, 1.0f, 0.f };
227: float[] zero_vec4 = { 0.0f, 0.0f, 0.0f, 0.f };
228:
229: float aspect = (height != 0) ? ((float) width / (float) height)
230: : 1.0f;
231:
232: gl.glViewport(0, 0, width, height);
233: gl.glScissor(0, 0, width, height);
234:
235: gl.glMatrixMode(GL10.GL_MODELVIEW);
236: gl.glLoadIdentity();
237:
238: gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, light_position,
239: 0);
240: gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, light_ambient, 0);
241: gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, light_diffuse, 0);
242: gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_SPECULAR, zero_vec4, 0);
243: gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_SPECULAR,
244: material_spec, 0);
245:
246: gl.glEnable(GL10.GL_NORMALIZE);
247: gl.glEnable(GL10.GL_LIGHTING);
248: gl.glEnable(GL10.GL_LIGHT0);
249: gl.glEnable(GL10.GL_COLOR_MATERIAL);
250: gl.glEnable(GL10.GL_CULL_FACE);
251:
252: gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
253:
254: gl.glShadeModel(GL10.GL_SMOOTH);
255: gl.glDisable(GL10.GL_DITHER);
256:
257: // Clear background to blue
258: gl.glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
259:
260: gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
261: gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
262: gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
263:
264: gl.glMatrixMode(GL10.GL_PROJECTION);
265: gl.glLoadIdentity();
266:
267: perspective(90.f, aspect, 0.1f, 100.f);
268:
269: gl.glFinish();
270: }
271:
272: private void drawScene() {
273: // Make the context current on this thread
274: egl.eglMakeCurrent(eglDisplay, eglWindowSurface,
275: eglWindowSurface, eglContext);
276:
277: // Perform setup and clear background using GL
278: egl.eglWaitNative(EGL10.EGL_CORE_NATIVE_ENGINE, g);
279:
280: updateState(width, height);
281: gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
282: gl.glFinish();
283:
284: // Wait for GL to complete
285: egl.eglWaitGL();
286:
287: // Draw a green square using MIDP
288: g.setColor(0, 255, 0);
289: g.fillRect(20, 20, width - 40, height - 40);
290:
291: // Draw the scene using GL
292: egl.eglWaitNative(EGL10.EGL_CORE_NATIVE_ENGINE, g);
293:
294: gl.glMatrixMode(GL10.GL_MODELVIEW);
295: gl.glLoadIdentity();
296:
297: gl.glTranslatef(0.f, 0.f, -30.f);
298: gl.glRotatef((float) (time * 29.77f), 1.0f, 2.0f, 0.0f);
299: gl.glRotatef((float) (time * 22.311f), -0.1f, 0.0f, -5.0f);
300:
301: gl.glVertexPointer(3, GL10.GL_BYTE, 0, cubeVertices);
302: gl.glColorPointer(4, GL10.GL_UNSIGNED_BYTE, 0, cubeColors);
303: gl.glNormalPointer(GL10.GL_BYTE, 0, cubeNormals);
304:
305: gl.glDrawElements(GL10.GL_TRIANGLES, 6 * 6,
306: GL10.GL_UNSIGNED_BYTE, cubeIndices);
307: gl.glFinish();
308:
309: time += 0.1f;
310:
311: egl.eglWaitGL();
312:
313: // Release the context
314: egl.eglMakeCurrent(eglDisplay, EGL10.EGL_NO_SURFACE,
315: EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
316:
317: // Draw a red square using MIDP
318: g.setColor(255, 0, 0);
319: g.fillRect((width / 2) - 25, (height / 2) - 25, 50, 50);
320: }
321:
322: public void shutdown() {
323: egl.eglMakeCurrent(eglDisplay, EGL10.EGL_NO_SURFACE,
324: EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
325: egl.eglDestroyContext(eglDisplay, eglContext);
326: egl.eglDestroySurface(eglDisplay, eglWindowSurface);
327: egl.eglTerminate(eglDisplay);
328: }
329:
330: public void run() {
331: if (!initialized) {
332: init();
333: }
334:
335: try {
336: while (!cube.isFinished()) {
337: if (!cube.paused) {
338: Thread.sleep(2);
339: drawScene();
340: flushGraphics();
341: }
342: }
343: } catch (InterruptedException e) {
344: e.printStackTrace();
345: }
346:
347: shutdown();
348: }
349: }
350:
351: public class Cube extends MIDlet implements CommandListener {
352: private final Command exitCommand = new Command("Exit",
353: Command.EXIT, 1);
354: Display display;
355: CubeCanvas canvas;
356: boolean started = false;
357: boolean paused = false;
358: boolean finished = false;
359: Thread drawThread;
360:
361: public Cube() {
362: this .display = Display.getDisplay(this );
363: this .canvas = new CubeCanvas(this );
364: this .canvas.setCommandListener(this );
365: this .canvas.addCommand(exitCommand);
366: }
367:
368: public void startApp() {
369: if (!started) {
370: started = true;
371: display.setCurrent(canvas);
372: drawThread = new Thread(canvas);
373: drawThread.start();
374: }
375:
376: paused = finished = false;
377: }
378:
379: public void pauseApp() {
380: paused = true;
381: }
382:
383: public void destroyApp(boolean unconditional) {
384: // Wait for draw thread to die
385: setFinished();
386:
387: try {
388: drawThread.join();
389: } catch (InterruptedException e) {
390: e.printStackTrace();
391: }
392: }
393:
394: public void paint(Graphics g) {
395: }
396:
397: public void commandAction(Command cmd, Displayable disp) {
398: if (cmd == exitCommand) {
399: destroyApp(false);
400: notifyDestroyed();
401: }
402: }
403:
404: public synchronized boolean isFinished() {
405: return finished;
406: }
407:
408: public synchronized void setFinished() {
409: finished = true;
410: }
411: }
|