МІНІСТЕРСТВО ОСВІТИ ТА НАУКИ УКРАЇНИ
Національний університет «Львівська політехніка»
Кафедра САПР
Звіт
Про виконання лабораторної роботи №4
на тему:
Двовимірні побудови з використанням OpenGL
на платформі Java Micro Edition
З курсу:
«Геометричне моделювання в конструюванні інженерних об‘єктів та систем»
Мета роботи
Ознайомитися та практично освоїти можливості графінної бібліотеки OpenGL для робот из графікою на низькому рівні. Набути навичок програмування графіки для пристроїв з обмеженими ресурсами з платформою Java Micro Edition.
Короткі теоретичні відомості
OPENGL ES є мобільною підмножиною OPENGL , вони обидва розширювані, стандартизовані та cross-платформенні 3D API.
Пакет JSR 239 включає OPENGL ES, і є необов'язковим. Він може працювати на ряду платформ Java Micro Edition (Java ME), включаючи CLDC 1.1/MIDP 2.0, CDC 1.0/Personal Basis Profile, та CDC 1.0/Personal Profile, також і зворотньо сумісних версіях цих платформ.
OPENGL ES і EGL API визначені Khronos Group (www.khronos.org). OPENGL ES визначає два профілі: Common профіль (КПК, смартфони ітд) і Common-Lite профіль (для пристроїв з обмеженими ресурсами, типу мобільних телефонів). Common-Lite профіль - 32-бітний з фіксованою крапкою, тоді як Common профіль підтримує плаваючу крапку.
JSR 239 вимагає основний рідний графічний прискорювач, сертифікований Khronos, для комфортної роботи з OPENGL ES і EGL API. Цей прискорювач повинен підтримувати версію 1.0 OPENGL ES і EGL і всі основні розширення пов‘язані з ними API.
Індивідуальне завдання
Варіант №19
/
Текст програми
class HexaMidlet – головний клас мідлета
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Graphics;
import javax.microedition.midlet.MIDlet;
public class HexaMidlet extends MIDlet implements CommandListener {
private final Command exitCommand = new Command("Exit", Command.EXIT, 1);
Display display;
HexagonCanvas canvas;
boolean started = false;
boolean paused = false;
boolean finished = false;
Thread drawThread;
public HexaMidlet() {
this.display = Display.getDisplay(this);
this.canvas = new HexagonCanvas(this);
this.canvas.setCommandListener(this);
this.canvas.addCommand(exitCommand);
}
public void startApp() {
if (!started) {
started = true;
display.setCurrent(canvas);
drawThread = new Thread(canvas);
drawThread.start();
}
paused = finished = false;
}
public void pauseApp() {
paused = true;
}
public void destroyApp(boolean unconditional) {
// Wait for draw thread to die
setFinished();
try {
drawThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void commandAction(Command cmd, Displayable disp) {
if (cmd == exitCommand) {
destroyApp(false);
notifyDestroyed();
}
}
public synchronized boolean isFinished() {
return finished;
}
public synchronized void setFinished() {
finished = true;
}
}
HexagonCanvas – полотно для графіки
import java.nio.*;
import javax.microedition.khronos.egl.*;
import javax.microedition.khronos.opengles.*;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.game.GameCanvas;
public class HexagonCanvas extends GameCanvas implements Runnable {
private static byte l = 20;//radiys
private static float alfa = (float) (15 * Math.PI / 180);//angle
private static float speed = 3;//start speed
private static float acceleration = 9.8f;
private static float s = 2*l; // s < 4*l !!! way ahead
private static float h = (float) (l * Math.sin(Math.PI / 3));
private static float d = (float) (l * 0.5);
private static float hs = (float)(-h-(l*4+s)*Math.tan(alfa));
private static final byte[] m_groundVertices =
{
(byte)(-l*4), (byte)-h,
(byte)(l*4), (byte)(-h-8*l*Math.tan(alfa)),
(byte)(-l*4), (byte)(-h-8*l*Math.tan(alfa)),
(byte)(s), (byte) hs,
(byte)(l*4), (byte) hs
};
private static final byte[] m_groundIndices =
{
0, 1, 2,
3, 4, 1
};
private static final byte[] m_hexagonVertices =
{
(byte)-l, 0,
(byte)(-d), (byte)(h),
(byte)(d), (byte)(h),
(byte)l, 0,
(byte)(d), (byte)(-h),
(byte)(-d), (byte)(-h)
};
private static final byte[] m_hexagonIndices =
{
0, 1, 2,
3, 4, 5,
0, 3, 5,
2, 3, 0
};
boolean initialized = false;
float time = 0.0f;
Graphics g;
int width;
int height;
HexaMidlet midlet;
EGL10 egl;
GL10 gl;
EGLConfig eglConfig;
EGLDisplay eglDisplay;
EGLSurface eglWindowSurface;
EGLContext eglContext;
ByteBuffer hexagonVertices;
ByteBuffer hexagonIndices;
ByteBuffer groundVertices;
ByteBuffer groundIndices;
public HexagonCanvas(HexaMidlet cube) {
super(true);
this.midlet = cube;
this.g = this.getGraphics();
this.width = getWidth();
this.height = getHeight();
}
private int getProperty(String propName, int def) {
String s = midlet.getAppProperty(propName);
int val = (s == null) ? def : Integer.parseInt(s);
return val;
}
public void init() {
this.egl = (EGL10)EGLContext.getEGL();
this.eglDisplay = egl.eglGetDisplay(egl.EGL_DEFAULT_DISPLAY);
int[] major_minor = new int[2];
egl.eglInitialize(eglDisplay, major_minor);
int[] num_config = new int[1];
egl.eglGetConfigs(eglDisplay, null, 0, num_config);
System.out.println ("num_config[0] = " + num_config[0]);
int redSize = getProperty("jsr239.redSize", 8);
int greenSize = getProperty("jsr239.greenSize", 8);
int blueSize = getProperty("jsr239.blueSize", 8);
int alphaSize = getProperty("jsr239.alphaSize", 0);
int depthSize = getProperty("jsr239.depthSize", 32);
int stencilSize = getProperty("jsr239.stencilSize", EGL10.EGL_DONT_CARE);
int[] s_configAttribs =
{
EGL10.EGL_RED_SIZE, redSize, EGL10.EGL_GREEN_SIZE, greenSize, EGL10.EGL_BLUE_SIZE,
blueSize, EGL10.EGL_ALPHA_SIZE, alphaSize, EGL10.EGL_DEPTH_SIZE, depthSize,
EGL10.EGL_STENCIL_SIZE, stencilSize, EGL10.EGL_NONE
};
EGLConfig[] eglConfigs = new EGLConfig[num_config[0]];
egl.eglChooseConfig(eglDisplay, s_configAttribs, eglConfigs, eglConfigs.length, num_config);
this.eglConfig = eglConfigs[0];
this.eglContext = egl.eglCreateContext(eglDisplay, eglConfig, EGL10.EGL_NO_CONTEXT, null);
this.gl = (GL10)eglContext.getGL();
this.eglWindowSurface = egl.eglCreateWindowSurface(eglDisplay, eglConfig, g, null);
// Initialize data Buffers
this.groundVertices = ByteBuffer.allocateDirect(m_groundVertices.length);
groundVertices.put(m_groundVertices);
groundVertices.rewind();
this.groundIndices = ByteBuffer.allocateDirect(m_groundIndices.length);
groundIndices.put(m_groundIndices);
groundIndices.rewind();
this.hexagonVertices = ByteBuffer.allocateDirect(m_hexagonVertices.length);
hexagonVertices.put(m_hexagonVertices);
hexagonVertices.rewind();
this.hexagonIndices = ByteBuffer.allocateDirect(m_hexagonIndices.length);
hexagonIndices.put(m_hexagonIndices);
hexagonIndices.rewind();
this.initialized = true;
}
private void perspective(float fovy, float aspect, float zNear, float zFar) {
float xmin;
float xmax;
float ymin;
float ymax;
ymax = zNear * (float)Math.tan((fovy * Math.PI) / 360.0);
ymin = -ymax;
xmin = ymin * aspect;
xmax = ymax * aspect;
gl.glFrustumf(xmin, xmax, ymin, ymax, zNear, zFar);
}
private void updateState(int width, int height) {
float aspect = (height != 0) ? ((float)width / (float)height) : 1.0f;
gl.glViewport(0, 0, width, height);
gl.glScissor(0, 0, width, height);
// Clear background to blue
gl.glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
// Enable vertex array
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
perspective(90.f, aspect, 0.1f, 100.f);
gl.glFinish();
}
private void drawScene() {
// Make the context current on this thread
egl.eglMakeCurrent(eglDisplay, eglWindowSurface, eglWindowSurface, eglContext);
// Perform setup and clear background using GL
egl.eglWaitNative(EGL10.EGL_CORE_NATIVE_ENGINE, g);
updateState(width, height);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glFinish();
// Wait for GL to complete
egl.eglWaitGL();
// Draw the scene using GL
egl.eglWaitNative(EGL10.EGL_CORE_NATIVE_ENGINE, g);
//------------Ground-------------
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glTranslatef(0.f, 0.f, -100.f);
gl.glRotatef((0.f), 0.0f, 0.0f, 1.0f);
gl.glVertexPointer(2, GL10.GL_BYTE, 0, groundVertices);
gl.glColor4f((float)0.0, (float)1.0, (float)0.0, (float)1.0);
gl.glDrawElements(GL10.GL_TRIANGLES, m_groundIndices.length, GL10.GL_UNSIGNED_BYTE, groundIndices);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
float kyt = (float) ((speed + (acceleration * time) * Math.sin(alfa)) * time);
float dl = (float) ((l-h) * Math.sin(Math.PI *(kyt%60) / 60));
//phase corection
float dlx = (float) (dl * Math.sin(alfa));
float dly = (float) (dl * Math.cos(alfa));
//moving
float dx = (float) ((kyt/60)*l* Math.cos(alfa));
float dy = (float) ((kyt/60)*l* Math.sin(alfa));
//stop condition
if(!(-l*4+dlx+dx >= s && (dly-dy-h) <= hs)){
time += 0.1f;
}
gl.glTranslatef(-4*l+dlx+dx, dly-dy, -100.f);
gl.glRotatef((float) (-kyt - (180 * alfa / Math.PI)), 0.0f, 0.0f, 1.0f);
gl.glVertexPointer(2, GL10.GL_BYTE, 0, hexagonVertices);
gl.glColor4f((float)0.3, (float)0.3, (float)0.3, (float)1.0);
gl.glDrawElements(GL10.GL_TRIANGLES, m_hexagonIndices.length, GL10.GL_UNSIGNED_BYTE, hexagonIndices);
gl.glFinish();
egl.eglWaitGL();
// Release the context
egl.eglMakeCurrent(eglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE,
EGL10.EGL_NO_CONTEXT);
}
public void shutdown() {
egl.eglMakeCurrent(eglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE,
EGL10.EGL_NO_CONTEXT);
egl.eglDestroyContext(eglDisplay, eglContext);
egl.eglDestroySurface(eglDisplay, eglWindowSurface);
egl.eglTerminate(eglDisplay);
}
public void run() {
if (!initialized) {
init();
}
try {
while (!midlet.isFinished()) {
if (!midlet.paused) {
Thread.sleep(2);
drawScene();
flushGraphics();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
shutdown();
}
}
/
Висновок: на даній лабораторній роботі я ознайомився з можливостями платформи Java ME для створення графіки використовуючи бібліотеку OpenGL.