Código de ejemplo: dibujo de un cubo en 3D
Puede utilizar la interfaz GL10 para dibujar un cubo en 3D.
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGL11;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.egl.EGLSurface;
import javax.microedition.khronos.opengles.GL10;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.container.FullScreen;
import net.rim.device.api.opengles.GLUtils;
class ThreeDCube extends FullScreen implements Runnable
{
private EGL11 _egl;
private EGLDisplay _eglDisplay;
private EGLConfig _eglConfig;
private EGLSurface _eglSurface;
private EGLContext _eglContext;
private GL10 _gl;
private Bitmap _offscreenBitmap;
private Graphics _offscreenGraphics;
private boolean _running;
private boolean _paused;
private FloatBuffer _cubeVertices, _cubeNormals, _cubeColors;
float _angle = 45f;
private int _vertexCount;
private static final float[] _vertices =
{
// front
-0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f,
0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f,
// right
0.5f, 0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, -0.5f,
0.5f, 0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f,
// back
0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f,
-0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f,
// left
-0.5f, 0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f, 0.5f,
-0.5f, 0.5f, 0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f,
// top
-0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f,
0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f,
// bottom
-0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f,
0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f
};
private static final float[] _normals =
{
/* front */ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1,
/* right */ 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0,
/* back */ 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1,
/* left */ -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0,
/* top */ 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0,
/* bottom */ 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0
};
private static final float[] _colors =
{
/* front – white */ 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1,
/* right – red */ 1,0,0,1, 1,0,0,1, 1,0,0,1, 1,0,0,1, 1,0,0,1, 1,0,0,1,
/* back – green */ 0,1,0,1, 0,1,0,1, 0,1,0,1, 0,1,0,1, 0,1,0,1, 0,1,0,1,
/* left – blue */ 0,0,1,1, 0,0,1,1, 0,0,1,1, 0,0,1,1, 0,0,1,1, 0,0,1,1,
/* top - yellow */ 1,1,0,1, 1,1,0,1, 1,1,0,1, 1,1,0,1, 1,1,0,1, 1,1,0,1,
/* bottom - magenta*/ 1,0,1,1, 1,0,1,1, 1,0,1,1, 1,0,1,1, 1,0,1,1, 1,0,1,1
};
ThreeDCube()
{
super(FullScreen.DEFAULT_MENU | FullScreen.DEFAULT_CLOSE);
}
private void initialize()
{
// Get EGL interface
_egl = (EGL11)EGLContext.getEGL();
// Get the EGL display
_eglDisplay = _egl.eglGetDisplay(EGL11.EGL_DEFAULT_DISPLAY);
// Initialize the display for EGL, pass null as the second argument
// because we don't need the version.
_egl.eglInitialize(_eglDisplay, null);
// Choose an EGL config
EGLConfig[] configs = new EGLConfig[1];
int[] numConfigs = new int[1];
int[] attrs =
{
EGL11.EGL_RED_SIZE, 5,
EGL11.EGL_GREEN_SIZE, 6,
EGL11.EGL_BLUE_SIZE, 5,
EGL11.EGL_NONE
};
_egl.eglChooseConfig(_eglDisplay, attrs, configs, 1, numConfigs);
_eglConfig = configs[0];
// Create an EGL window surface
_eglSurface = _egl.eglCreateWindowSurface
(_eglDisplay, _eglConfig, this, null);
// Create an EGL context
createEGLContext();
_cubeVertices = createVertexBuffer();
_cubeNormals = createNormalBuffer();
_cubeColors = createColorBuffer();
_vertexCount = _vertices.length / 3;
}
private FloatBuffer createVertexBuffer()
{
FloatBuffer buffer =
ByteBuffer.allocateDirect(_vertices.length * 4).asFloatBuffer();
buffer.put(_vertices);
buffer.rewind();
return buffer;
}
private FloatBuffer createNormalBuffer()
{
FloatBuffer buffer =
ByteBuffer.allocateDirect(_normals.length * 4).asFloatBuffer();
buffer.put(_normals);
buffer.rewind();
return buffer;
}
private FloatBuffer createColorBuffer()
{
FloatBuffer buffer =
ByteBuffer.allocateDirect(_colors.length * 4).asFloatBuffer();
buffer.put(_colors);
buffer.rewind();
return buffer;
}
private void createEGLContext()
{
// Create an EGL context
_eglContext = _egl.eglCreateContext
(_eglDisplay, _eglConfig, EGL10.EGL_NO_CONTEXT, null);
// Get the GL interface for our new context
_gl = (GL10)_eglContext.getGL();
// Make our new context current
_egl.eglMakeCurrent
(_eglDisplay, _eglSurface, _eglSurface, _eglContext);
}
private void destroyEGL()
{
_egl.eglMakeCurrent(_eglDisplay, EGL10.EGL_NO_SURFACE,
EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
_egl.eglDestroyContext(_eglDisplay, _eglContext);
_egl.eglDestroySurface(_eglDisplay, _eglSurface);
}
private void handleContextLost()
{
// Destroy our EGL context
_egl.eglMakeCurrent(_eglDisplay, EGL10.EGL_NO_SURFACE,
EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
_egl.eglDestroyContext(_eglDisplay, _eglContext);
_eglContext = EGL10.EGL_NO_CONTEXT;
// Re-create our EGL context
createEGLContext();
}
/***************************************************************************
* Main render loop.
***************************************************************************/
public void run()
{
initialize();
int throttle = 0;
while (_running)
{
throttle = (int)System.currentTimeMillis();
// Idle if in the background
if (_paused)
{
synchronized (this)
{
try
{
wait();
}
catch (InterruptedException x) { }
}
}
updateBackBuffer();
renderFrame();
++_angle;
if (_angle >= 360f)
{
_angle = 0f;
}
//Determine how long the frame took to render
throttle = (int)System.currentTimeMillis() - throttle;
//Throttle to 30 FPS to control CPU usage.
throttle = 33 - throttle;
if (throttle > 0)
{
// Throttle cpu usage
try
{
Thread.sleep(throttle);
}
catch (InterruptedException x) { }
}
}
destroyEGL();
}
private void renderFrame()
{
// Make our context and surface current and check for EGL_CONTEXT_LOST
if (!_egl.eglMakeCurrent(_eglDisplay, _eglSurface, _eglSurface, _eglContext))
{
if (_egl.eglGetError() == EGL11.EGL_CONTEXT_LOST)
handleContextLost();
}
// Signal that we are about to begin OpenGL rendering
_egl.eglWaitNative(EGL10.EGL_CORE_NATIVE_ENGINE, _offscreenGraphics);
render(_gl);
// Signal that OpenGL ES rendering is complete
_egl.eglWaitGL();
// Swap the window surface to the display
_egl.eglSwapBuffers(_eglDisplay, _eglSurface);
}
private void render(GL10 gl)
{
// Set our GL viewport
gl.glViewport(0, 0, getWidth(), getHeight());
// Clear the surface
gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
GLUtils.gluPerspective(gl, 45.0f, (float)getWidth()/(float)getHeight(),
0.15f, 100.0f);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
// Setup drawing state
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glEnable(GL10.GL_LIGHTING);
gl.glEnable(GL10.GL_LIGHT0);
gl.glEnable(GL10.GL_COLOR_MATERIAL);
// Draw our cube
gl.glTranslatef(0, 0, -3.5f);
gl.glRotatef(_angle, 1.0f, 1.0f, 0.0f);
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, _cubeVertices);
gl.glNormalPointer(GL10.GL_FLOAT, 0, _cubeNormals);
gl.glColorPointer(4, GL10.GL_FLOAT, 0, _cubeColors);
gl.glDrawArrays(GL10.GL_TRIANGLES, 0, _vertexCount);
}
/***************************************************************************
* Called by the UI system to paint the screen.
***************************************************************************/
protected void paint(Graphics g)
{
if (_offscreenBitmap != null)
g.drawBitmap(0, 0, _offscreenBitmap.getWidth(),
_offscreenBitmap.getHeight(), _offscreenBitmap, 0, 0);
}
/***************************************************************************
* Called when the visibility of our screen changes.
*
* The visible argument is true if our screen is being made visible,
* false if it's being hidden
***************************************************************************/
protected void onVisibilityChange(boolean visible)
{
if (visible)
{
resume();
}
else
{
pause();
}
}
/***************************************************************************
* Called when the screen is closing.
***************************************************************************/
public void close()
{
_running = false;
synchronized (this) { notifyAll(); }
super.close();
}
/***************************************************************************
* Keeps the back buffer in sync with the screen size.
***************************************************************************/
private void updateBackBuffer()
{
if (_offscreenBitmap != null)
{
if (_offscreenBitmap.getWidth() == getWidth() &&
_offscreenBitmap.getHeight() == getHeight())
return; // no change needed
}
_offscreenBitmap = new Bitmap(getWidth(), getHeight());
_offscreenGraphics = Graphics.create(_offscreenBitmap);
}
private void pause()
{
_paused = true;
}
private void resume()
{
if (_running)
{
// Pause the render loop
_paused = false;
synchronized (this) { notifyAll(); }
}
else
{
// Start the render thread.
_running = true;
new Thread(this).start();
}
}
}
Tema siguiente: Ejemplo de código: dibujo de un triángulo multicolor
Tema anterior: Ejemplo de código: compatibilidad de OpenGL ES
¿Le ha resultado útil esta información? Envíenos sus comentarios.