ćwiczenie 4z - Robert Arsoba
Transkrypt
ćwiczenie 4z - Robert Arsoba
Zagadnienia uzupełniające programowanie w systemie Android dr inż. Robert Arsoba Ćwiczenie 4 Rysowanie obiektów trójwymiarowych Cel ćwiczenia Celem ćwiczenia jest praktyczne zapoznanie się z definiowaniem i rysowaniem obiektów trójwymiarowych przy użyciu biblioteki OpenGL ES. Omawiany jest przykład aplikacji, w której rysowany jest sześcian w reprezentacji krawędziowej. Zakres ćwiczenia obejmuje definiowanie reprezentacji punktowej, krawędziowej i wypełnianej wybranych brył oraz ich odrysowywanie na ekranie. Przygotowanie się do ćwiczenia Zapoznać się z wykładem „Grafika trójwymiarowa”. Zwrócić szczególną uwagę na opis reprezentacji punktowej, krawędziowej i wypełnianej obiektów trójwymiarowych. Przeanalizować opis tworzenia bufora wierzchołków i bufora indeksów. Zapoznać się z podstawowymi metodami API dotyczącymi rysowania. Na podstawie dokumentacji Android SDK: http://developer.android.com/reference/packages.html zapoznać się w podstawowym zakresie z klasami GLSurfaceView i GL10ES. Zapoznać się z przykładową aplikacją zamieszczoną w opisie ćwiczenia. Przeanalizować kod źródłowy aplikacji. Zwrócić uwagę na budowę klasy NaszRenderer. Przeanalizować definicję reprezentacji krawędziowej sześcianu. Zwrócić szczególną uwagę na metody dotyczące operacji rysowania i ustawień parametrów rysowania (metody o nazwach z przedrostkiem gl). Zwrócić szczególną uwagę na metodę onDrawFrame i zaprogramowany w niej fragment dotyczący rysowania sześcianu. Zadania do wykonania 1. Uruchomić przykładową aplikację zamieszczoną w opisie ćwiczenia i przetestować jej działanie. 2. Zmodyfikować fragment kodu źródłowego w metodzie onDrawFrame odpowiedzialny za rysowanie sześcianu. Wzorując się na ćwiczeniu 3, uzupełnić tę metodę o polecenia powodujące animację sześcianu (obrót wokół wybranej osi). 3. Wzorując się na reprezentacji krawędziowej sześcianu zaprogramowanej w metodzie definiuj_obiekt, zdefiniować w podobny sposób reprezentację krawędziową dla ostrosłupa. Odrysować tak zdefiniowany ostrosłup na ekranie. 4. Zdefiniować reprezentację wypełnianą wybranej bryły (np. sześcian lub ostrosłup) i odrysować ją na ekranie w taki sposób, aby każda ścianka miała inny kolor. Materiały przygotowano w ramach projektu „Inżynier pilnie poszukiwany” Strona 1 Zagadnienia uzupełniające programowanie w systemie Android dr inż. Robert Arsoba Przykładowa aplikacja – plik głównej aktywności OpenGLActivity.java Należy zwrócić uwagę na włączone ustawienie GLSurfaceView.RENDERMODE_WHEN_DIRTY. Powoduje ono, że w przypadku grafiki statycznej, zawartość powierzchni rysowania jest odrysowywana tylko w razie konieczności (po zmianie zawartości powierzchni). package org.przyklad; import android.app.Activity; import android.opengl.GLSurfaceView; import android.os.Bundle; public class OpenGLActivity extends Activity { private GLSurfaceView sv; // powierzchnia rysowania /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); sv = new GLSurfaceView(this); sv.setRenderer(new NaszRenderer()); // ustalenie obiektu kontrolującego rysowanie (tzw. renderer) // odrysowanie tylko w razie potrzeby (należy włączyć dla grafiki statycznej): sv.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); setContentView(sv); // zawartość widoku to powierzchnia rysowania } @Override public void onPause() { super.onPause(); sv.onPause(); } @Override public void onResume() { super.onResume(); sv.onResume(); } } Przykładowa aplikacja – plik NaszRenderer.java package org.przyklad; import import import import import import import import java.nio.ByteBuffer; java.nio.ByteOrder; java.nio.FloatBuffer; java.nio.ShortBuffer; javax.microedition.khronos.egl.EGLConfig; javax.microedition.khronos.opengles.GL10; android.opengl.GLSurfaceView; android.opengl.GLU; public class NaszRenderer implements GLSurfaceView.Renderer { private int VERTICES; // liczba wierzchołków private int INDEXES; // liczba indeksów private FloatBuffer vb; // bufor wierzchołków (vertex buffer) private ShortBuffer ib; // bufor indeksów (index buffer) Materiały przygotowano w ramach projektu „Inżynier pilnie poszukiwany” Strona 2 Zagadnienia uzupełniające programowanie w systemie Android dr inż. Robert Arsoba public void definiuj_obiekt() // definicja sześcianu { float punkty[] = // kolejność przeciwna do wskazówek zegara { // układ współrzędnych prawoskrętny // przednia ścianka (do obserwatora) -0.5f, 0.5f, 0.5f, // 0 LG 0 LG 2 PG 0.5f, -0.5f, 0.5f, // 1 PD 0.5f, 0.5f, 0.5f, // 2 PG 3 LD 1 PD -0.5f, -0.5f, 0.5f, // 3 LD // tylna ścianka (wgłąb ekranu) -0.5f, 0.5f, -0.5f, // 4 LG 4 LG 0.5f, -0.5f, -0.5f, // 5 PD 0.5f, 0.5f, -0.5f, // 6 PG 7 LD -0.5f, -0.5f, -0.5f // 7 LD 6 PG 5 PD }; short indeksy[] = { 0, 4, 0, 2, }; VERTICES = 8; INDEXES = 24; 3, 7, 4, 6, 3, 7, 3, 1, 1, 5, 7, 5 1, 5, // // 2, 2, 0, // przednia ścianka 6, 6, 4, // tylna ścianka lewa ścianka prawa ścianka // liczba wierzchołków // liczba indeksów ByteBuffer vbuf = ByteBuffer.allocateDirect(VERTICES*3*4); // 3 współrzędne * 4 bajty (float) vbuf.order(ByteOrder.nativeOrder()); vb = vbuf.asFloatBuffer(); // tworzenie bufora wierzchołków vb.put(punkty); // na podstawie tablicy wierzchołków vb.position(0); ByteBuffer ibuf = ByteBuffer.allocateDirect(INDEXES*2); // * 2 bajty (short) ibuf.order(ByteOrder.nativeOrder()); ib = ibuf.asShortBuffer(); // tworzenie bufora indeksów ib.put(indeksy); // na podstawie tablicy indeksów ib.position(0); } public void onSurfaceCreated(GL10 gl, EGLConfig eglConfig) { // metoda wywoływana tylko raz do utworzenia powierzchni rysowania gl.glClearColor(0.5f, 0.5f, 0.5f, 1.0f); // kolor tła szary (model koloru RGBA) definiuj_obiekt(); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); // włączone użycie bufora indeksów } public void onSurfaceChanged(GL10 gl, int szer, int wys) { // metoda wywoływana automat. po zmianie wymiarów pow. rysowania (np. zmiana orientacji urządzenia) gl.glViewport(0, 0, szer, wys); // parametry ekranu (płaszczyzny rzutowania) float aspekt = (float) szer/wys; // proporcje ekranu gl.glMatrixMode(GL10.GL_PROJECTION); // tryb macierzy rzutowania gl.glLoadIdentity(); // ustawienie macierzy jednostkowej (stan domyślny) gl.glFrustumf(-aspekt, aspekt, -1, 1, 3, 7); // macierz rzutowania } public void onDrawFrame(GL10 gl) { // metoda wywoływana automat. w przypadku konieczności odrysowania zawartości powierzchni rysowania gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); // wyczyszczenie pow. rysowania gl.glMatrixMode(GL10.GL_MODELVIEW); // tryb macierzy MODELVIEW gl.glLoadIdentity(); // ustawienie macierzy jednostkowej (stan domyślny) GLU.gluLookAt(gl, 0, 0, 5, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f); // parametry kamery gl.glColor4f(0.0f, 1.0f, 0.0f, 0.5f); // kolor rysowania zielony (model koloru RGBA) gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vb); // bufor wierzchołków gl.glDrawElements(GL10.GL_LINES, INDEXES, GL10.GL_UNSIGNED_SHORT, ib); // linie z bufora indeksów } } Materiały przygotowano w ramach projektu „Inżynier pilnie poszukiwany” Strona 3 Zagadnienia uzupełniające programowanie w systemie Android dr inż. Robert Arsoba Wygląd interfejsu użytkownika aplikacji Rysunek przedstawia wynik działania aplikacji – sześcian odrysowany w reprezentacji krawędziowej. Przykładowa aplikacja – plik strings.xml <?xml version="1.0" encoding="utf-8"?> <resources> <string name="hello">Hello World, OpenGLActivity!</string> <string name="app_name">Rysowanie 3D</string> </resources> Materiały przygotowano w ramach projektu „Inżynier pilnie poszukiwany” Strona 4