Camera

BAB 4 Viewing / Camera 4.1 Pengertian Viewing / Camera Viewing camera adalah cara mengatur sudut pandang dari pergerakan kamera terhadap objek 2D maup...
Author: Clare Shelton
33 downloads 2 Views 4MB Size
BAB 4 Viewing / Camera 4.1 Pengertian Viewing / Camera Viewing camera adalah cara mengatur sudut pandang dari pergerakan kamera terhadap objek 2D maupun 3D, sehingga dapat memproyeksikan objek sehingga tampak riil.

4.1.1 Proyeksi Paralel Proyeksi paralel dapat dikategorikan menurut hubungan antara arah proyeksi dengan vektor normal dari bidang proyeksi, ke dalam dua macam proyeksi. Proyeksi yang di hasilkan belum membentuk object 3D yang tampak riil. Pusat proyeksi pada objek akan bertemu di titik yang tak terhingga.

D A

D’ A’

C’

C B

B’ Pusat Proyeksi pada titik tak terhingga Bidang Proyeksi

Gambar 4.1 Proyeksi paralel

4.1.2 Syntax Proyeksi Paralel Dalam OpenGL terdapat syntax untuk Parallel Projection. Salah satunya dapat menggunakan syntax:  glOrtho(-15.0, 20.0, -10.0, 15.0, -50.0, 70.0); Mendefinisikan besarnya sistem koordinat 3D: dengan range sumbu x adalah [-15,20], range untuk sumbu y adalah [-10,15], range untuk sumbu z adalah [-50,70]

300



gluOrtho2D(-100,100,-200,200); Mendefinisikan besarnya sistem koordinat 2D: dengan range sumbu x adalah [-100,100] dan range untuk sumbu y adalah [200,200].



4.1.3 Proyeksi Perspektif Perspective projection di gunakan untuk memodifikasi gambar 2D pada layar agar terlihat 3D seperti di dunia nyata, gambar terlihat semakin kecil di belakang, mempunyai pusat di satu titik, konsep ini seperti penglihatan di dunia nyata, ketika objek benda semakin jauh maka akan terlihat semakin kecil, ketika di lihat lebih dekat maka benda akan membesar secara konstan satu garis lurus. Untuk menciptakan pandangan perspektif, maka setting kamera perlu diubah dari glOrtho() menjadi gluPerspective(), gluLookAt(), dan glFrustum().

Gambar 4.2 Proyeksi Perspektif

4.1.4 Syntax Proyeksi Perspektif Dalam OpenGL terdapat syntax untuk Parallel Projection. Salah satunya dapat menggunakan syntax: • gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble near, GLdouble far) – Fovy adalah sudut di bidang pandang (dalam rentang dari [0.0, 180]) – Aspect adalah rasio aspek frustrum (lebar jendela di atas ketinggian jendela) – Near dan far adalah nilai antara sudut pandang dan pesawat dekat / jauh kliping

301

Gambar 4.3 gluPerspective() •

glFrustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near, GLdouble far) – left, right, top, and bottom mendefinisikan batas dari near. – near and far menentukan seberapa jauh dari sudut pandang clipping pane

Gambar 4.4 glFrustum() •

gluLookAt(GLdouble e_x, GLdouble e_y, GLdouble e_z, GLdouble c_x, GLdouble c_y, GLdouble c_z, GLdouble u_x, GLdouble u_y, GLdouble u_z) – e_x, e_y, and e_z menentukan sudut pandang yang diinginkan (mata) – c_x, c_y, c_z menentukan beberapa titik di sepanjang garis yang diinginkan sight (pusat) – u_x, u_y, and u_z mendifinisikan vector up dari camera kita (up)

Aktivasi Fungsi: • gluPerspective() ……………………… glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(AngleView, Aspek Rasio, Near, Far); 302

:



……………………………………….. gluLookAt() ……………………… glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(mata_x, mata_y, mata_z, lihat_x, lihat_y, lihat_z, atas_x, atas_y, atas_z); ………………………………………..

4.2 Matematika Synthetic Camera Cara kerja kamera sintetik:

Gambar 4.5 Cara Kerja Kamera Sintetik Objek terletak pada sistem koordinat dunia (x, y, z), lensa terletak pada sistem koordinat UVN atau kamera sintetik (u, v, n), dan film sebagai bidang proyeksi. Sistem koordinat kamera sintetik:

Gambar 4.6 Sistem koordinat kamera sintetik   

Sumbu n sebagai arah pandang kamera, dan ditentukan berdasarkan vektor normal (nx,ny,nz). Sumbu v sebagai arah atas, sumbu u sebagai arah horisontal. (v ∟ n), (u ∟ n) dan (u ∟ v) Titik tengah sumbu u,v,n disebut VRP (Viewing Reference Point), yang ditentukan oleh titik (rx,ry,rz) pada koordinat dunia. 303

Cara mendapatkan sumbu u, v, dan n: 

User menentukan titik tengah view/ eye (VRP), pusat titik pandang objek /center (lookAt) dan vektor atas (UpVector). Synthetic Camera di OpenGL : gluLookAt(eye_x, eye_y, eye_z, center_x, center_y, center_z, up_x, up_y, up_z )



n adalah vektor dari VRP menuju lookAt. Lalu vektor n dinormalisasi. Contoh : Diketahui VRP di titik r(rx , ry , rz), lookAt di titik la(lax , lay , laz) dan UpVector di titik up(upx,upy,upz). Sehingga,

n _ init  la  r , unit vektor n _ init adalah(n) 

n _ init n _ init

v _ init  up  up  n * n, unit vektor v _ init adalah(v) 

v _ init v _ init

u  v xn 

Memindahkan titik koordinat dunia P(Px,Py,Pz) ke koordinat kamera sintetik Q(Qu,Qv,Qn). Titik Q dapat diperoleh melalui : – t(tx,ty,tz) = P - r – Qu = t • u, Qv = t • v dan Qn = t • n Qu = (P-r) • u = (P • u)-(r • u) Contoh : Diketahui koordinat UVN dengan u=(-1,0,0), v=(0,0.8,0.6), n=(0,0.6,0.8) dan r = (2,3,-1). Hitunglah lokasi Q(Qu,Qv,Qn) yang merupakan transformasi dari titik P(4,7,2) di koordinat dunia ! Jawab : t(tx,ty,tz) = P - r = (4-2,7-3,2-(-1)) =(2,4,3) Qu = t • u =(2,4,3) • (-1,0,0) = 2*(-1)+4*(0)+3*(0)=-2 Qv = t • v =(2,4,3) • (0,0.8,0.6) = 2*(0)+4*(0.8)+3*(0.6)=5 Qn = t • n =(2,4,3) • (0,-0.6,0.8) = 2*(0)+4*(-0.6)+3*(0.8)=0 Jadi titik Q terletak di koordinat (-2,5,0) pada sistem koordinat UVN. Matrik transformasi dari koordinat dunia ke UVN: Qu  u x Qv   v   x Qn  n x    1   0

uv

uz

vy

vz

ny

nz

0

0

 r  u   Px  r  v   Py  r  n   Pz    1  1 

304

Setelah titik Q diketahui, maka langkah berikutnya adalah melakukan proyeksi perspektif terhadap titik Q, sehingga diperoleh titik T(u*, v*). Proyeksi Q ke T dapat diperoleh dengan menggunakan rumus berikut:

u* 

Qu Qv , v*  Q Q 1 n 1 n en en

Mata/ eye terletak di (0, 0, en), dengan syarat en > nz dan en != 0. Contoh: dengan menggunakan Tabel 4.1 dan 4.2 berikut: (sebagai informasi tentang vertex dan permukaan objek) Vertex 0 1 2 3 4

0

1

4

1

X 0.0 1.0 1.0 0.0 0.5

2

Y -1.0 -1.0 -1.0 -1.0 0.5

Surface Index 4 2 3

Z 0.0 0.0 1.0 1.0 0.5

4

3

0

4

Diketahui synthetic camera berada di (2, 3, 1) dan melihat kea rah (0, 0, 0). Arah atas didefinisikan melalui up=(0, 1, 0). Hitung dan gambarkan lokasi vertex-vertex seperti yang dilihat oleh synthetic camera apabila en=6.

305

Jawab: Mencari sistem koordinat UVN:

n _ init  la  r  (0,0,0)  (2,3,1)  (2,3,1) n

n _ init (2,3,1)   2  3 1    , ,   (0.53,0.8,0.27 ) | n _ init | (2) 2  (3) 2  (1) 2  14 14 14 

v _ init  up  (up  n) * n  (0,1,0)  (0 * (0.53)  1 * (0.8)  0 * (0.27 )) * (0.53,0.8,0.27 ) v _ init  (0,1,0)  (0.8)( 0.53,0.8,0.27 )  (0,1,0)  (0.8 * (0.53),0.8 * (0.8),0.8 * (0.27 )) v _ init  (0,1,0)  (0.42,0.64,0.23)  (0.42,0.36,0.23) v

v _ init (0.42,0.36,0.23) (0.42,0.36,0.23) (0.42,0.36,0.23)    | v _ init | 0.18  0.13  0.05 0.36 (0.42) 2  (0.36) 2  (0.23) 2

 (0.7,0.6,0.38) i

j

k

u  v  n   0.53  0.8  0.27  0.7

0.6

 0.38

u  (( 0.8) * (0.38)  (0.6) * (0.27 ), (( 0.7) * (0.27 ))  (( 0.53) * (0.38)), (( 0.53) * (0.6))  (( 0.7) * (0.8))) u  ((0.3  0.16), (0.19  0.2), (0.32  0.56))  (0.46,0.01,0.88)

la = (0,0,0) dan r = (2,3,1) n = (-0.53,-0.8,-0.27) v = (-0.7,0.6,-0.38) u = (0.46,-0.01,-0.88) Transformasi vertex ke sistem UVN: Vertex

tX=p-r

tY=p-r

tZ=p-r

0 1 2 3 4

0-2=-2 -1 -1 -2 -1.5

-1-3=-4 -4 -4 -4 -2.5

0-1=-1 -1 0 0 -0.5

Qu=t•u

Qv=t•v

Qn=t•n

0 0.46 -0.42 -0.88 -0.23

-0.62 -1.32 -1.7 -1 -0.26

4.53 4 3.73 4.26 2.93

Gambar synthetic camera dari vertex hasil transformasi perspektif (u*,v*):

306

Vertex 0 1 2 3 4

u* 0 1.38 -1.11 -3.03 -0.45

v* -2.53 -3.96 -4.49 -3.45 -0.51

v* u*

Gambar 4.7 Gambar synthetic camera dari vertex hasil trtasformasi perspektif (u*,v*)

4.3 Membuat Multiple View Object • • •

Satu objek yang dapat dilihat dengan posisi mata yang berbeda yaitu posisi mata kanan dan mata kiri. Didasarkan pada stereokopik alami dari sistem mata. Masing-masing mata melihat objek dari lokasi yang berbeda.

Gambar 4.8 Ilustrasi Multiple View Object 307

Source Code 4.1 Code Membuat Multiple View Object ESRender.java package com.camera_n_viewing_project; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; //import android.opengl.GLU; import android.opengl.GLSurfaceView.Renderer; import android.opengl.GLU;

public class ESRender implements Renderer { private TransObject transobject; // the primitive object to be drawn private TransPolarObject transpolarobject; private TransKubusObject kubus; private TransPiramidaObject piramida;

int RunMode=1; float CurrentAngle = 0.0f; Angle in degrees float AnimateStep = 2.0f; Rotation step per update

// //

/** Constructor to set the handed over context */ public ESRender() { this.piramida = new TransPiramidaObject(); } @Override public void onDrawFrame(GL10 gl) { // clear Screen and Depth Buffer //gl.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // set background dgn warna putih gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); // Reset the Modelview Matrix gl.glLoadIdentity();

// menampilkan piramida gl.glPushMatrix(); gl.glTranslatef(0.0f, 0.0f, 0.0f); // Rotate the object gl.glTranslatef(0.0f, 0.0f, 5.0f); gl.glScalef(0.5f, 0.5f, 0.5f); Scale down

308

//

gl.glRotatef( CurrentAngle, 0.1f, 1.0f, -0.1f ); piramida.draw(gl); gl.glPopMatrix();

// Update the rotational angle after each refresh if (RunMode==1) { // re-Calculate animation parameters CurrentAngle += AnimateStep; if (CurrentAngle > 360.0) { //CurrentAngle -= 360.0*Math.floor(CurrentAngle/360.0); CurrentAngle=0.0f; CurrentAngle += AnimateStep; } } } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { if (height == 0) height = 1; // To prevent divide by zero float aspect = (float) width / height; // Set the viewport (display area) to cover the entire window gl.glViewport(0, 0, width, height); // Setup perspective projection, with aspect ratio matches viewport gl.glMatrixMode(GL10.GL_PROJECTION); // Select projection matrix gl.glLoadIdentity(); // Reset projection matrix // Use perspective projection GLU.gluPerspective(gl, 45, aspect, 0.1f, 100.f); //gl.glOrthof(-3.0f, 3.0f, -3.0f, 3.0f, 3.0f, 3.0f); gl.glMatrixMode(GL10.GL_MODELVIEW); // Select model-view matrix gl.glLoadIdentity(); // Reset } @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set color's clear-value to black

309

gl.glClearDepthf(1.0f); // Set depth's clear-value to farthest gl.glEnable(GL10.GL_DEPTH_TEST); // Enables depth-buffer for hidden // surface removal gl.glDepthFunc(GL10.GL_LEQUAL); // The type of depth testing to do gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST); // nice // perspective // view gl.glShadeModel(GL10.GL_SMOOTH); // Enable smooth shading of color gl.glDisable(GL10.GL_DITHER); // Disable dithering for better // performance } public int getRunMode() { return RunMode; } public void setRunMode(int mRunMode) { RunMode = mRunMode; } public float getAnimateStep() { return AnimateStep; } public void setAnimateStep(float mAnimateStep) { AnimateStep = mAnimateStep; } }

ESSurfaceView.java package com.camera_n_viewing_project; import import import import import

android.content.Context; android.opengl.GLSurfaceView; android.util.Log; android.view.KeyEvent; android.view.MotionEvent;

/** * A view container where OpenGL ES graphics can be drawn on screen. * This view can also be used to capture touch events, such as a user * interacting with drawn objects. */ public class ESSurfaceView extends GLSurfaceView {

310

private final ESRender esRender; public ESSurfaceView(Context context) { super(context); // Set the Renderer for drawing on the GLSurfaceView esRender = new ESRender(); setRenderer(esRender); // To enable keypad this.setFocusable(true); this.requestFocus(); // To enable touch mode this.setFocusableInTouchMode(true); // Render the view only when there is a change in the drawing data // merender hanya ketika ada perubahan/ event //setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); } //private final float TOUCH_SCALE_FACTOR = 180.0f / 320; //private float mPreviousX; //private float mPreviousY; @Override public boolean onTouchEvent(MotionEvent v) { // MotionEvent reports input details from the touch screen // and other input controls. In this case, we are only // interested in events where the touch position changed. /*float x = e.getX(); float y = e.getY();*/ switch (v.getAction()) { case MotionEvent.ACTION_DOWN: Log.v("Test Action Down", "action down working"); Log.i("Test Action Nilai", ""+Math.abs(esRender.getRunMode()-1)); esRender.setRunMode(Math.abs(esRender.getRunMode()-1)); //break; requestRender(); //case MotionEvent.ACTION_POINTER_UP: //Log.v("Test Action ACTION_POINTER_UP", "action working"); //Log.i("Test Action Nilai", ""+Math.abs(esRender.getAnimateStep()));

311

//esRender.setAnimateStep(esRender.getAnimateStep ()+8.0f); //requestRender(); //case MotionEvent.ACTION_MOVE: //Log.v("Test Action ACTION_POINTER_DOWN", "action working"); //Log.i("Test Action Nilai", ""+Math.abs(esRender.getAnimateStep())); //esRender.setAnimateStep(esRender.getAnimateStep ()-8.0f); //requestRender(); //case MotionEvent.ACTION_UP: //Log.v("Test Action Up", "action up working"); //esRender.setRunMode(esRender.getRunMode()); //requestRender(); //case MotionEvent.ACTION_MOVE: //esRender.setRunMode(esRender.getRunMode()); //requestRender(); } //mPreviousX = x; // mPreviousY = y; return true; //break; } // Key-up event handler @Override public boolean onKeyUp(int keyCode, KeyEvent event) { switch (keyCode) { case KeyEvent.KEYCODE_DPAD_RIGHT: // Increase rightward speed Log.v("Test Action KEYCODE_DPAD_RIGHT", "action working"); Log.i("Test Action Nilai", ""+Math.abs(esRender.getAnimateStep())); esRender.setAnimateStep(esRender.getAnimateStep()+8.0f); requestRender(); //ballSpeedX++; break; case KeyEvent.KEYCODE_DPAD_LEFT: // Increase leftward speed esRender.setAnimateStep(esRender.getAnimateStep()-8.0f); requestRender(); //ballSpeedX--; break; case KeyEvent.KEYCODE_DPAD_UP: // Increase upward speed //ballSpeedY--; break; case KeyEvent.KEYCODE_DPAD_DOWN: // Increase downward speed

312

//ballSpeedY++; break; case KeyEvent.KEYCODE_DPAD_CENTER: // Stop //ballSpeedX = 0; //ballSpeedY = 0; break; case KeyEvent.KEYCODE_A: // Zoom in Log.v("Test Action KEYCODE_DPAD_RIGHT", "action working"); Log.i("Test Action Nilai", ""+Math.abs(esRender.getAnimateStep())); esRender.setAnimateStep(esRender.getAnimateStep()+8.0f); requestRender(); // Max radius is about 90% of half of the smaller dimension //float maxRadius = (xMax > yMax) ? yMax / 2 * 0.9f : xMax / 2 * 0.9f; //if (ballRadius < maxRadius) { //ballRadius *= 1.05; // Increase radius by 5% //} break; case KeyEvent.KEYCODE_Z: // Zoom out Log.v("Test Action KEYCODE_DPAD_RIGHT", "action working"); Log.i("Test Action Nilai", ""+Math.abs(esRender.getAnimateStep())); esRender.setAnimateStep(esRender.getAnimateStep()-8.0f); requestRender(); //if (ballRadius > 20) { // Minimum radius // ballRadius *= 0.95; // Decrease radius by 5% //} break; } return true; // Event handled } }

MainActivity.java package com.camera_n_viewing_project; import import import import import import

android.opengl.GLSurfaceView; android.os.Bundle; android.app.Activity; android.view.Menu; android.view.Window; android.view.WindowManager;

public class MainActivity extends Activity { /** The OpenGL view */

313

private GLSurfaceView glSurfaceView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //setContentView(R.layout.activity_main); // requesting to turn the title OFF requestWindowFeature(Window.FEATURE_NO_TITLE); // making it full screen getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREE N, WindowManager.LayoutParams.FLAG_FULLSCREEN); // Initiate the Open GL view and // create an instance with this activity glSurfaceView = new ESSurfaceView(this); // set our renderer to be the main renderer with // the current activity context //glSurfaceView.setRenderer(new ESRender()); setContentView(glSurfaceView); } /** * Remember to resume the glSurface */ @Override protected void onResume() { super.onResume(); glSurfaceView.onResume(); } /** * Also pause the glSurface */ @Override protected void onPause() { super.onPause(); glSurfaceView.onPause(); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }

314

TransPiramidaObject.java package com.camera_n_viewing_project; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import javax.microedition.khronos.opengles.GL10; public class TransPiramidaObject { private float[] vertices = { // 5 vertices of the pyramid in (x,y,z) -1.0f, -1.0f, -1.0f, // 0. leftbottom-back 1.0f, -1.0f, -1.0f, // 1. rightbottom-back 1.0f, -1.0f, 1.0f, // 2. rightbottom-front -1.0f, -1.0f, 1.0f, // 3. leftbottom-front 0.0f, 1.0f, 0.0f // 4. top }; private float[] colors = { // Colors of the 5 vertices in RGBA 0.0f, 0.0f, 1.0f, 1.0f, // 0. blue 0.0f, 1.0f, 0.0f, 1.0f, // 1. green 0.0f, 0.0f, 1.0f, 1.0f, // 2. blue 0.0f, 1.0f, 0.0f, 1.0f, // 3. green 1.0f, 0.0f, 0.0f, 1.0f // 4. red }; private byte[] indices = { // Vertex indices of the 4 Triangles 0, 1, 4, // back face 1, 2, 4, // right face 2, 3, 4, // front face (CCW) 3, 0, 4 // left face }; // Constructor - Set up the buffers public TransPiramidaObject() { } // Point to our vertex buffer, return buffer holding the vertices public static FloatBuffer makeFloatBuffer(float[] arr){ ByteBuffer bb = ByteBuffer.allocateDirect(arr.length * 4); bb.order(ByteOrder.nativeOrder()); FloatBuffer fb = bb.asFloatBuffer(); fb.put(arr); fb.position(0); return fb; }

315

// Setup index-array buffer. Indices in byte. public static ByteBuffer makeByteBuffer(byte[] arr){ ByteBuffer bb = ByteBuffer.allocateDirect(arr.length); bb.put(arr); bb.position(0); return bb; } // Draw the shape public void draw(GL10 gl) { gl.glFrontFace(GL10.GL_CCW); // Front face in counter-clockwise // orientation // Enable arrays and define their buffers gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, makeFloatBuffer(vertices)); gl.glEnableClientState(GL10.GL_COLOR_ARRAY); gl.glColorPointer(4, GL10.GL_FLOAT, 0, makeFloatBuffer(colors)); //gl.glDrawElements(GL10.GL_TRIANGLES, indices.length, //GL10.GL_UNSIGNED_BYTE, makeByteBuffer(indices)); gl.glDrawElements(GL10.GL_LINE_STRIP, indices.length, GL10.GL_UNSIGNED_BYTE, makeByteBuffer(indices)); gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_COLOR_ARRAY); } }

Gambar 4.9 Multiple View Object

316

BAB 5 Texture Mapping 5.1 Pengertian Texture Mapping Texture Mapping merupakan metode yang digunakan untuk menambah detail texture pada permukaan objek.

Gambar 5.1 Texture Mapping Texture merupakan data segi-empat sederhana yang berada pada bidang texture. Bidang texture diwakili oleh dua sumbu koordinat yaitu sumbu s dan sumbu t. Setiap texture akan memenuhi bidang koordinat (0.0,0.0) sd. (1.0,1.0). Nilai individual dari array texture biasanya dikenal dengan istilah texels (texture pixels).Yang membuat texture mapping sedikit rumit adalah bagaimana proses pemetaan antara bentuk segi empat texture ke polygon mengingat secara umum bentuk poligon biasanya non-rectangular. Beberapa contoh penggunaan texture mapping antara lain:  Mensimulasikan aspek visual dari material seperti tampakan kayu, batu bata, atau granit.  Mengurangi kompleksitas (jumlah polygon yang dibutuhkan) dari suatu obyek geometri.  Teknik pemrosesan citra seperti image wraping dan rectification, rotation, dan scaling.  Mensimulasikan berbagai efek permukaan seperti efek reflektif seperti cermin atau lantai yang telah digosok mengkilat, efek tonjolan, dan sebagainya.

317

Salah satu keuntungan dari texture mapping adalah bahwa detail visual itu berada di citra bukan di geometri. Dan sekompleks apapun citra, selama tidak merubah ukuran citra, tidak berpengaruh pada kinerja keseluruhan, yaitu kompleksitas dari citra tidak berpengaruh kepada pipeline geometric (transformasi, clipping) dari OpenGL. Texture ditambahkan saat rasterisasi ketika geometric pipeline dan pixel pipeline bertemu seperti diilustrasikan pada Gambar 5.2. Rasterisasi adalah mengubah gambar dari format vector ke format pixel atau titik. vertices

geometry pipeline rasterizer

image

pixel pipeline

Gambar 5.2 Ilustrasi Rasterisasi Ada dua cara untuk melakukan texture mapping:  Membuat extra polygon untuk membangun detail model pada objek. o Menambah kompleksitas scene sehingga memperlambat kecepatan rendering grafis. o Beberapa fitur grafis akan sulit untuk dimodelkan.  Membuat texture map pada permukaan (pendekatan yang lebih sering digunakan). Secara konseptual ada tiga langkah dalam melakukan texture mapping, yaitu: 1. Penentuan texture  Baca image dari file  Generate texture id untuk image tersebut glGenTextures(3, &texture[0]) 2. Pemberian koordinat texture ke vertex 3. Penentuan parameter texture (wrapping / filtering)

5.2 Representasi Texture Mapping 

Bitmap Texture Gambar dua dimensi yang direpresentasikan dengan array texture dua dimensi [height][width]. Setiap pixel yang disebut dengan texel adalah terletak pada koordinat (s,t). Nilai s dan t biasanya dinormalisasi dengan range [0,1]. Untuk setiap koordinat

318

(s,t) yang telah dinormalisasi, terdapat image value [red, green, blue].

Gambar 5.3 Bitmap Texture 

Procedural Texture Procedural texture adalah gambar yang dihasilkan computer yang dibuat dengan algoritma untuk menciptakan representasi realistis dari unsur-unsur alam seperti kayu, marmer, granit, logam, batu, dan sebagainya.

5.3 Parameter Texture Mapping Texture mapping diaktifkan dan di-non-aktifkan menggunakan glEnable() atau glDisable() dengan GL_TEXTURE_1D atau GL_TEXTURE_2D untuk menandakan satu atau dua dimensi. glTexParameter*() digunakan untuk mengatur texture. Berikut merupakan contoh penggunaan glTexParameter*() untuk melakukan magnification dan minification: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

Gambar 5.4 Magnification dan Minification

319

Berikut merupakan contoh penggunakan glTexParameter*() untuk melakukan repeating: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

Gambar 5.5 Repeating Texture Berikut merupakan contoh penggunakan glTexParameter*() untuk melakukan clamping: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

Gambar 5.6 Clamping Texture Berikut merupakan contoh penggunakan glTexParameter*() untuk melakukan repeating dan clamping: glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

320

Gambar 5.7 Repeating dan Clamping Texture

5.4 Texture Mapping Pada Segitiga Source Code 5.1 Code Texture Mapping Pada Segitiga ESRender.java

package com.texture_mapping; import java.util.Formatter; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import import import import import import import import

android.content.Context; android.opengl.GLES20; android.opengl.GLSurfaceView; android.opengl.Matrix; android.opengl.GLSurfaceView.Renderer; android.opengl.GLU; android.util.Log; android.widget.TextView;

public class ESRender implements Renderer {

private ESText glText; private TextView textview; private ObjectArena objectarena; primitive object to be drawn private ObjectBall objectball; private ObjectBall objectball_hole; private ObjectBall objectball1; private ObjectBall objectball2; private ObjectBall objectball3; Context context;

321

// the

private int RunMode=1; private float mAngle = 0.0f; Angle in degrees private float AnimateStep = 2.0f; // Rotation step per update

//

private long startTime; private long fpsStartTime; private long numFrames; float float float float float

radius = 50.0f; // Ball's radius x = radius; // Ball's center (x,y) y = radius; speedX = 5f; // Ball's speed (x,y) speedY = 3f;

int xMin, xMax, yMin, yMax; private int mywidth=0; private int myheight=0; /** Constructor to set the handed over context */ public ESRender(Context context) { //super(); this.context = context; this.objectarena = new ObjectArena(); this.objectball = new ObjectBall(); this.objectball_hole = new ObjectBall(); this.objectball1 = new ObjectBall(); this.objectball2 = new ObjectBall(); this.objectball3 = new ObjectBall(); } @Override public void onDrawFrame(GL10 gl) { // Draw background color gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

// segitiga gl.glPushMatrix(); //GLU.gluLookAt(gl, 0, 0, 0.01f, 0f, 0f, 0f, 0f, 1.0f, 0.0f); gl.glTranslatef(50.0f, 60.0f, 0.0f); gl.glScalef(80.0f, 80.0f, 0.0f); gl.glRotatef(180, 1.0f, 0.0f, 0.0f); gl.glTranslatef(5.0f, -3.5f, 0.0f); objectball1.draw_segitiga(gl); gl.glPopMatrix();

322

// update moveWithCollisionDetection(this); set((int)-radius, (int)-radius, mywidth, myheight); // Update the rotational angle after each refresh if (RunMode==1) { // re-Calculate animation parameters mAngle += AnimateStep; if (mAngle > 360.0) { //CurrentAngle -= 360.0*Math.floor(CurrentAngle/360.0); mAngle=0.0f; mAngle += AnimateStep; } } } @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { gl.glClearColor(0.5f, 0.5f, 0.5f, 1.0f); // Set color's clear-value to black gl.glClearDepthf(1.0f); // Set depth's clearvalue to farthest gl.glEnable(GL10.GL_DEPTH_TEST); // Enables depth-buffer for hidden // surface removal gl.glDepthFunc(GL10.GL_LEQUAL); // The type of depth testing to do gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST); // nice // perspective // view gl.glShadeModel(GL10.GL_SMOOTH); // Enable smooth shading of color gl.glDisable(GL10.GL_DITHER); // Disable dithering for better // performance // Create the GLText glText = new ESText( gl, context.getAssets() ); // Load the font from file (set size + padding), creates the texture // NOTE: after a successful call to this the font is ready for rendering! glText.load( "Roboto-Regular.ttf", 14, 2, 2 ); // Create Font (Height: 14 Pixels / X+Y Padding 2 Pixels)

323

//gl.glDisable(GL10.GL_DITHER); // Disable dithering for better // performance // Setup Texture, each time the surface is created (NEW) objectball_hole.loadBallTexture(gl, context,0); objectball1.loadBallTexture(gl, context,1); objectball2.loadBallTexture(gl, context,0); objectball3.loadBallTexture(gl, context,1); gl.glEnable(GL10.GL_TEXTURE_2D); // Enable texture (NEW)

} @Override public void onSurfaceChanged(GL10 gl, int width, int height) { mywidth=width; myheight=height;

gl.glViewport( 0, 0, width, height ); // Setup orthographic projection gl.glMatrixMode( GL10.GL_PROJECTION ); // Activate Projection Matrix gl.glLoadIdentity(); // Load Identity Matrix gl.glOrthof( // Set Ortho Projection (Left,Right,Bottom,Top,Front,Back) 0, width, 0, height, 1.0f, -10.0f ); // Save width and height //this.width = width; // Save Current Width //this.height = height; // Save Current Height gl.glMatrixMode(GL10.GL_MODELVIEW); // Select model-view matrix gl.glLoadIdentity(); // Reset } public float getxMax() { return xMax; } public void setxMax(int xmax) { xMax = xmax; }

324

public float getxMin() { return xMin; } public void setxMin(int xmin) { xMin = xmin; } public float getyMax() { return yMax; } public void setyMax(int ymax) { yMax = ymax; } public float getyMin() { return yMin; } public void setyMin(int ymin) { yMin = ymin; } public float getspeedX() { return speedX; } public void setspeedX(float speedX_) { speedX = speedX_; } public float getspeedY() { return speedY; } public void setspeedY(float speedY_) { speedY = speedY_; } public void moveWithCollisionDetection(ESRender esRender) { // Get new (x,y) position x += speedX; y += speedY; // Detect collision and react if (x + radius > esRender.getxMax()) { speedX = -speedX; x = esRender.getxMax() - radius; } else if (x - radius < esRender.getxMin()) { speedX = -speedX; x = esRender.getxMin() + radius; } if (y + radius > esRender.getyMax()) { speedY = -speedY; y = esRender.getyMax() - radius; } else if (y - radius < esRender.getyMin()) { speedY = -speedY; y = esRender.getyMin() + radius; } }

325

public void set(int x, int y, int width, int height) { xMin = x; //xMax = x + width - 1; xMax = x + width; yMin = y; //yMax = y + height - 1; yMax = y + height; } }

ESSurfaceView.java

package com.texture_mapping; import import import import import

android.content.Context; android.opengl.GLSurfaceView; android.util.Log; android.view.KeyEvent; android.view.MotionEvent;

/** * A view container where OpenGL ES graphics can be drawn on screen. * This view can also be used to capture touch events, such as a user * interacting with drawn objects. */ public class ESSurfaceView extends GLSurfaceView { private final ESRender esRender; private float previousX; private float previousY; public ESSurfaceView(Context context) { super(context); // Set the Renderer for drawing on the GLSurfaceView esRender = new ESRender(context); setRenderer(esRender); // To enable keypad this.setFocusable(true); this.requestFocus(); // To enable touch mode this.setFocusableInTouchMode(true); // Render the view only when there is a change in the drawing data // merender hanya ketika ada perubahan/ event

326

//setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); } //private final float TOUCH_SCALE_FACTOR = getWidth() / getHeight(); private float mPreviousX; private float mPreviousY; @Override public boolean onTouchEvent(MotionEvent v) { // MotionEvent reports input details from the touch screen // and other input controls. In this case, we are only // interested in events where the touch position changed. float currentX = v.getX(); float currentY = v.getY(); float deltaX, deltaY; //float scalingFactor = 0.50f / ((esRender.xMax > esRender.yMax) ? esRender.yMax //: esRender.xMax); switch (v.getAction()) { case MotionEvent.ACTION_DOWN: Log.v("Test Action Down", "action down working"); //break; requestRender(); //case MotionEvent.ACTION_POINTER_UP: //Log.v("Test Action ACTION_POINTER_UP", "action working"); //requestRender(); //case MotionEvent.ACTION_MOVE: //Log.v("Test Action ACTION_POINTER_DOWN", "action working"); //requestRender(); //case MotionEvent.ACTION_UP: //Log.v("Test Action Up", "action up working"); //requestRender(); case MotionEvent.ACTION_MOVE: // Modify rotational angles according to movement deltaX = currentX - previousX; deltaY = currentY - previousY;

//esRender.setspeedX(esRender.getspeedX()+ (deltaX/getWidth())); //esRender.setspeedY(esRender.getspeedY()+ (deltaY/getHeight())); esRender.setspeedX(esRender.getspeedX()+ deltaX/100);

327

esRender.setspeedY(esRender.getspeedY()+ deltaY/100); requestRender(); } // Save current x, y previousX = currentX; previousY = currentY; return true; // Event handled //break; } // Key-up event handler @Override public boolean onKeyUp(int keyCode, KeyEvent event) { switch (keyCode) { case KeyEvent.KEYCODE_A: // mengurangi kecepatan object if((esRender.getspeedX()- 0.05f >0) ){ esRender.setspeedX(esRender.getspeedX()- 0.05f); } if((esRender.getspeedX()- 0.05f =0)){ esRender.setspeedY(esRender.getspeedY()- 0.05f); } if((esRender.getspeedY()- 0.05f 360.0) { //CurrentAngle -= 360.0*Math.floor(CurrentAngle/360.0); CurrentAngle=0.0f; CurrentAngle += AnimateStep; } } @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { gl.glClearColor(0.5f, 0.5f, 0.5f, 1.0f); // Set color's clear-value to // black gl.glClearDepthf(1.0f); // Set depth's clear-value to farthest gl.glEnable(GL10.GL_DEPTH_TEST); // Enables depth-buffer for hidden // surface removal gl.glDepthFunc(GL10.GL_LEQUAL); // The type of depth testing to do gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST); // nice // perspective // view gl.glShadeModel(GL10.GL_SMOOTH); // Enable smooth shading of color gl.glDisable(GL10.GL_DITHER); // Disable dithering for better // performance // Create the GLText glText = new ESText(gl, context.getAssets()); // Load the font from file (set size + padding), creates the texture // NOTE: after a successful call to this the font is ready for // rendering! glText.load("Roboto-Regular.ttf", 14, 2, 2); // Create Font (Height: 14 // Pixels / X+Y Padding // 2 Pixels)

384

// gl.glDisable(GL10.GL_DITHER); // Disable dithering for better // performance // Setup Texture, each time the surface is created (NEW) objectball2.loadBallTexture(gl, context); gl.glEnable(GL10.GL_TEXTURE_2D); // Enable texture (NEW) } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { mywidth = width; myheight = height; gl.glViewport(0, 0, width, height); // Setup orthographic projection gl.glMatrixMode(GL10.GL_PROJECTION); // Activate Projection Matrix gl.glLoadIdentity(); // Load Identity Matrix gl.glOrthof( // Set Ortho Projection (Left,Right,Bottom,Top,Front,Back) 0, width, 0, height, 100.0f, -100.0f); // Save width and height // this.width = width; // Save Current Width // this.height = height; // Save Current Height gl.glMatrixMode(GL10.GL_MODELVIEW); // Select model-view matrix gl.glLoadIdentity(); // Reset } public float getxMax() { return xMax; } public void setxMax(int xmax) { xMax = xmax; } public float getxMin() { return xMin; } public void setxMin(int xmin) { xMin = xmin; } public float getyMax() {

385

return yMax; } public void setyMax(int ymax) { yMax = ymax; } public float getyMin() { return yMin; } public void setyMin(int ymin) { yMin = ymin; } public float getspeedX() { return speedX; } public void setspeedX(float speedX_) { speedX = speedX_; } public float getspeedY() { return speedY; } public void setspeedY(float speedY_) { speedY = speedY_; } public void moveWithCollisionDetection(ESRender esRender) { // Get new (x,y) position x += speedX; y += speedY; // Detect collision and react if (x + radius > esRender.getxMax()) { speedX = -speedX; x = esRender.getxMax() - radius; this.jumlah_pantulan+=1; } else if (x - radius < esRender.getxMin()) { speedX = -speedX; x = esRender.getxMin() + radius; this.jumlah_pantulan+=1; } if (y + radius > esRender.getyMax()) { speedY = -speedY; y = esRender.getyMax() - radius; this.jumlah_pantulan+=1; } else if (y - radius < esRender.getyMin()) { speedY = -speedY; y = esRender.getyMin() + radius; this.jumlah_pantulan+=1; } // pengkondisian penghitungan pantulan mulai dari nol if(Run_Mode==0){ this.jumlah_pantulan-=4;

386

this.Run_Mode=1; } } public void set(int x, int y, int width, int height) { xMin = x; // xMax = x + width - 1; xMax = x + width; yMin = y; // yMax = y + height - 1; yMax = y + height; } }

ESSurfaceView.java

package com.blending; import import import import import

android.content.Context; android.opengl.GLSurfaceView; android.util.Log; android.view.KeyEvent; android.view.MotionEvent;

/** * A view container where OpenGL ES graphics can be drawn on screen. * This view can also be used to capture touch events, such as a user * interacting with drawn objects. */ public class ESSurfaceView extends GLSurfaceView { private final ESRender esRender; private float previousX; private float previousY; public ESSurfaceView(Context context) { super(context); // Set the Renderer for drawing on the GLSurfaceView esRender = new ESRender(context); setRenderer(esRender); // To enable keypad this.setFocusable(true); this.requestFocus(); // To enable touch mode this.setFocusableInTouchMode(true); // Render the view only when there is a change in the drawing data // merender hanya ketika ada perubahan/ event

387

//setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); } //private final float TOUCH_SCALE_FACTOR = getWidth() / getHeight(); private float mPreviousX; private float mPreviousY; @Override public boolean onTouchEvent(MotionEvent v) { // MotionEvent reports input details from the touch screen // and other input controls. In this case, we are only // interested in events where the touch position changed. float currentX = v.getX(); float currentY = v.getY(); float deltaX, deltaY; //float scalingFactor = 0.50f / ((esRender.xMax > esRender.yMax) ? esRender.yMax //: esRender.xMax); switch (v.getAction()) { case MotionEvent.ACTION_DOWN: Log.v("Test Action Down", "action down working"); //break; requestRender(); //case MotionEvent.ACTION_POINTER_UP: //Log.v("Test Action ACTION_POINTER_UP", "action working"); //requestRender(); //case MotionEvent.ACTION_MOVE: //Log.v("Test Action ACTION_POINTER_DOWN", "action working"); //requestRender(); //case MotionEvent.ACTION_UP: //Log.v("Test Action Up", "action up working"); //requestRender(); case MotionEvent.ACTION_MOVE: // Modify rotational angles according to movement deltaX = currentX - previousX; deltaY = currentY - previousY;

//esRender.setspeedX(esRender.getspeedX()+ (deltaX/getWidth())); //esRender.setspeedY(esRender.getspeedY()+ (deltaY/getHeight())); esRender.setspeedX(esRender.getspeedX()+ deltaX/100); esRen-

388

der.setspeedY(esRender.getspeedY()+ deltaY/100); requestRender(); } // Save current x, y previousX = currentX; previousY = currentY; return true; // Event handled //break; } // Key-up event handler @Override public boolean onKeyUp(int keyCode, KeyEvent event) { switch (keyCode) { case KeyEvent.KEYCODE_A: // mengurangi kecepatan object if((esRender.getspeedX()- 0.05f >0) ){ esRender.setspeedX(esRender.getspeedX()- 0.05f); } if((esRender.getspeedX()- 0.05f =0)){ esRender.setspeedY(esRender.getspeedY()- 0.05f); } if((esRender.getspeedY()- 0.05f 360.0) { // CurrentAngle -= 360.0*Math.floor(CurrentAngle/360.0); CurrentAngle = 0.0f; CurrentAngle += AnimateStep; } }

433

@Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { gl.glClearColor(0.5f, 0.5f, 0.5f, 1.0f); // Set color's clear-value to // black gl.glClearDepthf(1.0f); // Set depth's clear-value to farthest gl.glEnable(GL10.GL_DEPTH_TEST); // Enables depth-buffer for hidden // surface removal gl.glDepthFunc(GL10.GL_LEQUAL); // The type of depth testing to do gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST); // nice // perspective // view gl.glShadeModel(GL10.GL_SMOOTH); // Enable smooth shading of color gl.glDisable(GL10.GL_DITHER); // Disable dithering for better // performance gl.glEnable(GL10.GL_LIGHTING); gl.glEnable(GL10.GL_LIGHT0); gl.glEnable(GL10.GL_LIGHT1); // Create the GLText glText = new ESText(gl, context.getAssets()); // Load the font from file (set size + padding), creates the texture // NOTE: after a successful call to this the font is ready for // rendering! glText.load("Roboto-Regular.ttf", 14, 2, 2); // Create Font (Height: 14 // Pixels / X+Y Padding // 2 Pixels) // gl.glDisable(GL10.GL_DITHER); // Disable dithering for better // performance // Setup Blending (NEW) gl.glColor4f(1.0f, 1.0f, 1.0f, 0.5f); // Full brightness, 50% alpha // (NEW) gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE); // Select blending

434

// function (NEW) // Setup Texture, each time the surface is created (NEW) objectball2.loadBallTexture(gl, context); mEarth.loadGLTexture(gl, context, 2); // mEarth2.loadGLTexture(gl, context,6); mEarth3.loadGLTexture(gl, context, 5); kotak.loadTexture(gl, context); // Load images into textures (NEW) tembok.loadTexture(gl, context); // kubus.loadTexture(gl, context); lukisan.loadTexture(gl, context); pintu.loadTexture(gl, context); kubus_kecil.loadTexture(gl, context); kaki_meja.loadTexture(gl, context); lampu.loadTexture(gl, context); gl.glEnable(GL10.GL_TEXTURE_2D); // Enable texture (NEW) } @Override public void onSurfaceChanged(GL10 gl, int width, int height) { // mywidth = width; // myheight = height; if (height == 0) height = 1; // To prevent divide by zero float aspect = (float) width / height; gl.glViewport(0, 0, width, height); // Setup orthographic projection gl.glMatrixMode(GL10.GL_PROJECTION); // Activate Projection Matrix gl.glLoadIdentity(); // Load Identity Matrix // gl.glOrthof( // Set Ortho Projection // (Left,Right,Bottom,Top,Front,Back) // 0, width, 0, height, 500.0f, -500.0f); // gl.glOrthof(arg0, arg1, arg2, arg3, arg4, arg5); // GLU.gluPerspective(gl, fovy, aspect, zNear, zFar); // Use perspective projection GLU.gluPerspective(gl, 45, aspect, 0.1f, 100.f); // GLU.gluPerspective(gl, 45, aspect, 500.0f, -500.f); // Save width and height // this.width = width; // Save Current

435

Width // this.height = height; // Save Current Height gl.glMatrixMode(GL10.GL_MODELVIEW); // Select model-view matrix gl.glLoadIdentity(); // Reset } public float getxMax() { return xMax; } public void setxMax(int xmax) { xMax = xmax; } public float getxMin() { return xMin; } public void setxMin(int xmin) { xMin = xmin; } public float getyMax() { return yMax; } public void setyMax(int ymax) { yMax = ymax; } public float getyMin() { return yMin; } public void setyMin(int ymin) { yMin = ymin; } public float getspeedX() { return speedX; } public void setspeedX(float speedX_) { speedX = speedX_; } public float getspeedY() { return speedY; } public void setspeedY(float speedY_) { speedY = speedY_; } public boolean getLamp(){

436

return isOn; } public boolean setOff(){ return isOn =false; } public boolean setOn(){ return isOn = true; } public void moveWithCollisionDetection(ESRender esRender) { // Get new (x,y) position x += speedX; y += speedY; // Detect collision and react if (x + radius > esRender.getxMax()) { speedX = -speedX; x = esRender.getxMax() - radius; this.jumlah_pantulan += 1; } else if (x - radius < esRender.getxMin()) { speedX = -speedX; x = esRender.getxMin() + radius; this.jumlah_pantulan += 1; } if (y + radius > esRender.getyMax()) { speedY = -speedY; y = esRender.getyMax() - radius; this.jumlah_pantulan += 1; } else if (y - radius < esRender.getyMin()) { speedY = -speedY; y = esRender.getyMin() + radius; this.jumlah_pantulan += 1; } // pengkondisian penghitungan pantulan mulai dari nol if (Run_Mode == 0) { this.jumlah_pantulan -= 4; this.Run_Mode = 1; } } public void set(int x, int y, int width, int height) { xMin = x; // xMax = x + width - 1; xMax = x + width; yMin = y; // yMax = y + height - 1; yMax = y + height; } }

437

ESSurfaceView.java package com.ligthing; import import import import import

android.content.Context; android.opengl.GLSurfaceView; android.util.Log; android.view.KeyEvent; android.view.MotionEvent;

/** * A view container where OpenGL ES graphics can be drawn on screen. * This view can also be used to capture touch events, such as a user * interacting with drawn objects. */ public class ESSurfaceView extends GLSurfaceView { private final ESRender esRender; private float previousX; private float previousY; private float saklar; public ESSurfaceView(Context context) { super(context); // Set the Renderer for drawing on the GLSurfaceView esRender = new ESRender(context); setRenderer(esRender); // To enable keypad this.setFocusable(true); this.requestFocus(); // To enable touch mode this.setFocusableInTouchMode(true); // Render the view only when there is a change in the drawing data // merender hanya ketika ada perubahan/ event //setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); } //private final float TOUCH_SCALE_FACTOR = getWidth() / getHeight(); private float mPreviousX; private float mPreviousY; @Override public boolean onTouchEvent(MotionEvent v) { // MotionEvent reports input details from the touch screen // and other input controls. In this case, we are only // interested in events where the touch position

438

changed. float currentX = v.getX(); float currentY = v.getY(); float deltaX, deltaY; //float scalingFactor = 0.50f / ((esRender.xMax > esRender.yMax) ? esRender.yMax //: esRender.xMax); switch (v.getAction()) { case MotionEvent.ACTION_DOWN: Log.v("Test Action Down", "action down working"); if(esRender.getLamp()){ esRender.setOff(); }else{ esRender.setOn(); } break; requestRender(); //case MotionEvent.ACTION_POINTER_UP: //Log.v("Test Action ACTION_POINTER_UP", "action working"); //requestRender(); //case MotionEvent.ACTION_MOVE: //Log.v("Test Action ACTION_POINTER_DOWN", "action working"); //requestRender(); //case MotionEvent.ACTION_UP: //Log.v("Test Action Up", "action up working"); //requestRender(); case MotionEvent.ACTION_MOVE: // Modify rotational angles according to movement deltaX = currentX - previousX; deltaY = currentY - previousY; //

//esRender.setspeedX(esRender.getspeedX()+ (deltaX/getWidth())); //esRender.setspeedY(esRender.getspeedY()+ (deltaY/getHeight())); esRender.setspeedX(esRender.getspeedX()+ deltaX/100); esRender.setspeedY(esRender.getspeedY()+ deltaY/100); requestRender();

} // Save current x, y

439

previousX = currentX; previousY = currentY; return true; // Event handled //break; } // Key-up event handler @Override public boolean onKeyUp(int keyCode, KeyEvent event) { switch (keyCode) { case KeyEvent.KEYCODE_A: // mengurangi kecepatan object if((esRender.getspeedX()- 0.05f >0) ){ esRender.setspeedX(esRender.getspeedX()- 0.05f); } if((esRender.getspeedX()- 0.05f =0)){ esRender.setspeedY(esRender.getspeedY()- 0.05f); } if((esRender.getspeedY()- 0.05f charWidthMax ) // IF Width Larger Than Max Width charWidthMax = charWidths[cnt]; // Save New Max Width cnt++; // Advance Array Counter // set character height to font height charHeight = fontHeight; Set Character Height

//

// find the maximum size, validate, and setup cell sizes cellWidth = (int)charWidthMax + ( 2 * fontPadX ); // Set Cell Width cellHeight = (int)charHeight + ( 2 * fontPadY ); // Set Cell Height int maxSize = cellWidth > cellHeight ? cellWidth : cellHeight; // Save Max Size (Width/Height) if ( maxSize < FONT_SIZE_MIN || maxSize > FONT_SIZE_MAX ) // IF Maximum Size Outside Valid Bounds return false; // Return Error // set texture size based on max font size (width or height) // NOTE: these values are fixed, based on the defined characters. when // changing start/end characters

444

(CHAR_START/CHAR_END) this will need adjustment too! if ( maxSize 1 ? ( ( strLen - 1 ) * spaceX ) * scaleX : 0 ); // Add Space Length return len; // Return Total Length } //--Get Width/Height of Character--// // D: return the scaled width/height of a character, or max character width

449

// NOTE: since all characters are the same height, no character index is required! // NOTE: excludes spacing!! // A: chr - the character to get width for // R: the requested character size (scaled) public float getCharWidth(char chr) { int c = chr - CHAR_START; // Calculate Character Index (Offset by First Char in Font) return ( charWidths[c] * scaleX ); // Return Scaled Character Width } public float getCharWidthMax() { return ( charWidthMax * scaleX ); // Return Scaled Max Character Width } public float getCharHeight() { return ( charHeight * scaleY ); // Return Scaled Character Height } //--Get Font Metrics--// // D: return the specified (scaled) font metric // A: [none] // R: the requested font metric (scaled) public float getAscent() { return ( fontAscent * scaleY ); Return Font Ascent } public float getDescent() { return ( fontDescent * scaleY ); Return Font Descent } public float getHeight() { return ( fontHeight * scaleY ); Return Font Height (Actual) }

//

//

//

//--Draw Font Texture--// // D: draw the entire font texture (NOTE: for testing purposes only) // A: width, height - the width and height of the area to draw to. this is used // to draw the texture to the top-left corner. public void drawTexture(int width, int height) { batch.beginBatch( textureId ); // Begin Batch (Bind Texture) batch.drawSprite( textureSize / 2, height - ( textureSize / 2 ), textureSize, textureSize, textureRgn ); // Draw batch.endBatch(); // End Batch }

}

450

FitObject.java package com.ligthing; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import javax.microedition.khronos.opengles.GL10;

public class FitObject { // Point to our vertex buffer, return buffer holding the vertices public static FloatBuffer makeFloatBuffer(float[] arr){ ByteBuffer bb = ByteBuffer.allocateDirect(arr.length * 4); bb.order(ByteOrder.nativeOrder()); FloatBuffer fb = bb.asFloatBuffer(); fb.put(arr); fb.position(0); return fb; } public void draw_bola(GL10 gl, float[] mat_diff, int shiness) { // mengaktifkan pencahayaan //float[] mat_amb = {0.2f * 1.0f, 0.2f * 0.4f, 0.2f * 0.4f, 1.0f,}; float[] mat_amb = {0.0f * 1.0f, 0.0f * 0.4f, 0.0f * 0.4f, 1.0f,}; //float[] mat_diff = {1.0f, 0.4f, 0.4f, 0.5f,}; //float[] mat_diff = {1.0f, 0.8f, 0.04f, 1.0f}; float[] mat_spec = {1.0f, 1.0f, 1.0f, 1.0f}; /*gl.glEnable(GL10.GL_DEPTH_TEST); gl.glEnable(GL10.GL_CULL_FACE); gl.glShadeModel(GL10.GL_SMOOTH); gl.glEnable(GL10.GL_LIGHTING); gl.glEnable(GL10.GL_LIGHT0); */ gl.glEnable(GL10.GL_LIGHTING); gl.glEnable(GL10.GL_LIGHT0); // set the colour edge for the object circle //gl.glColor4f(1.0f, 0.8f, 0.04f, 1.0f); gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_AMBIENT, makeFloatBuffer(mat_amb)); gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_DIFFUSE, makeFloatBuffer(mat_diff));

451

gl.glMaterialfv(GL10.GL_FRONT_AND_BACK, GL10.GL_SPECULAR, makeFloatBuffer(mat_spec)); gl.glMaterialf(GL10.GL_FRONT_AND_BACK, GL10.GL_SHININESS, shiness); //gl.glMaterialf(GL10.GL_FRONT_AND_BACK, GL10.GL_SHININESS, 128.0f); float theta, pai; float co, si; float r1, r2; float h1, h2; float step = 2.0f; float[][] v = new float[32][3]; ByteBuffer vbb; FloatBuffer vBuf; vbb = ByteBuffer.allocateDirect(v.length * v[0].length * 4); vbb.order(ByteOrder.nativeOrder()); vBuf = vbb.asFloatBuffer(); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_NORMAL_ARRAY); for (pai = -90.0f; pai < 90.0f; pai += step) { int n = 0; r1 = (float)Math.cos(pai * Math.PI / 180.0); r2 = (float)Math.cos((pai + step) * Math.PI / 180.0); h1 = (float)Math.sin(pai * Math.PI / 180.0); h2 = (float)Math.sin((pai + step) * Math.PI / 180.0); for (theta = 0.0f; theta 31){ vBuf.position(0); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vBuf);

452

gl.glNormalPointer(GL10.GL_FLOAT, 0, vBuf); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, n); n = 0; theta -= step; } } vBuf.position(0); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vBuf); gl.glNormalPointer(GL10.GL_FLOAT, 0, vBuf); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, n); } gl.glDisable(GL10.GL_LIGHTING); gl.glDisable(GL10.GL_LIGHT0); gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_NORMAL_ARRAY); } }

item.java package com.ligthing; import import import import import import import import

java.nio.ByteBuffer; java.nio.ByteOrder; java.nio.FloatBuffer; javax.microedition.khronos.opengles.GL10; android.content.Context; android.graphics.Bitmap; android.graphics.BitmapFactory; android.opengl.GLUtils;

/* * A photo cube with 6 pictures (textures) on its 6 faces. */ public class item { private FloatBuffer vertexBuffer; // Vertex Buffer private FloatBuffer texBuffer; // Texture Coords Buffer private int numFaces = 14; private int[] imageFileIDs = { // Image file IDs R.drawable.caldera, // index 0 R.drawable.candice, // index 1 R.drawable.mule, // index 2 R.drawable.glass, // index 3 R.drawable.leonardo, // index 4

453

R.drawable.tmsk, // index 5 R.drawable.lantai, // index 6 R.drawable.tembok, // index 7 R.drawable.tembokx, // index 8 R.drawable.atap, // index 9 R.drawable.meja,// index 10 R.drawable.imam, // index 11 R.drawable.pintux, // index 12 R.drawable.wallpaper // index 13 }; private int[] textureIDs = new int[numFaces]; private Bitmap[] bitmap = new Bitmap[numFaces]; private float cubeHalfSize = 1.0f; // Constructor - Set up the vertex buffer public item(Context context) { // Allocate vertex buffer. An float has 4 bytes ByteBuffer vbb = ByteBuffer.allocateDirect(12 * 4 * numFaces); vbb.order(ByteOrder.nativeOrder()); vertexBuffer = vbb.asFloatBuffer(); // Read images. Find the aspect ratio and adjust the vertices // accordingly. for (int face = 0; face < numFaces; face++) { bitmap[face] = BitmapFactory.decodeStream(context.getResources() .openRawResource(imageFileIDs[face])); int imgWidth = bitmap[face].getWidth(); int imgHeight = bitmap[face].getHeight(); float faceWidth = 2.0f; float faceHeight = 2.0f; // Adjust for aspect ratio if (imgWidth > imgHeight) { faceHeight = faceHeight * imgHeight / imgWidth; } else { faceWidth = faceWidth * imgWidth / imgHeight; } float float float float

faceLeft = -faceWidth / 2; faceRight = -faceLeft; faceTop = faceHeight / 2; faceBottom = -faceTop;

// Define the vertices for this face // float[] vertices = { faceLeft, faceBottom, 0.0f, // 0. // // left-bottom-front // faceRight, faceBottom, 0.0f, // 1. right-bottom-front

454

// faceLeft, faceTop, 0.0f, // 2. left-top-front // faceRight, faceTop, 0.0f, // 3. right-top-front // }; float[] vertices = { // Vertices for a face -1.0f, -1.0f, 0.0f, // 0. leftbottom-front 1.0f, -1.0f, 0.0f, // 1. right-bottom-front -1.0f, 1.0f, 0.0f, // 2. left-top-front 1.0f, 1.0f, 0.0f // 3. right-top-front }; vertexBuffer.put(vertices); // Populate } vertexBuffer.position(0); // Rewind // Allocate texture buffer. An float has 4 bytes. Repeat for 6 faces. float[] texCoords = { 0.0f, 1.0f, // A. left-bottom 1.0f, 1.0f, // B. rightbottom 0.0f, 0.0f, // C. left-top 1.0f, 0.0f // D. right-top }; ByteBuffer tbb = ByteBuffer.allocateDirect(texCoords.length * 4 * numFaces); tbb.order(ByteOrder.nativeOrder()); texBuffer = tbb.asFloatBuffer(); for (int face = 0; face < numFaces; face++) { texBuffer.put(texCoords); } texBuffer.position(0); // Rewind } // Render the shape (Buat lantai) public void draw(GL10 gl) { gl.glFrontFace(GL10.GL_CCW); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRA Y); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuffer); // lantai gl.glPushMatrix(); gl.glRotatef(90, 1.0f, 0.0f, 0.0f); gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, tex-

455

tureIDs[6]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); gl.glPopMatrix();

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARR AY); } // Render the shape (Buat tembok belakang) public void draw_tembok_blk(GL10 gl) { gl.glFrontFace(GL10.GL_CCW); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRA Y); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuffer); // tembok gl.glPushMatrix(); gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[7]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); gl.glPopMatrix();

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARR AY); } // Render the shape (Buat tembok samping) public void draw_tembok_smp(GL10 gl) { gl.glEnable(GL10.GL_TEXTURE_2D); gl.glFrontFace(GL10.GL_CCW);

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRA Y); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuffer); // tembok

456

gl.glPushMatrix(); gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[13]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); gl.glPopMatrix();

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARR AY); gl.glDisable(GL10.GL_TEXTURE_2D); } // Render the shape (Buat atap) public void draw_atap(GL10 gl) { gl.glFrontFace(GL10.GL_CCW); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRA Y); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuffer); // tembok gl.glPushMatrix(); gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[9]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); gl.glPopMatrix();

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARR AY); } // Load images into 6 GL textures public void loadTexture(GL10 gl, Context c) { gl.glGenTextures(14, textureIDs, 0); // Generate texture-ID array for 6 // IDs // Generate OpenGL texture images for (int face = 0; face < numFaces; face++) { gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[face]);

457

// Build Texture from loaded bitmap for the currently-bind texture // ID

gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap[face], 0); bitmap[face].recycle(); } } }

kaki_meja.java package com.ligthing; import import import import import import import import

java.nio.ByteBuffer; java.nio.ByteOrder; java.nio.FloatBuffer; javax.microedition.khronos.opengles.GL10; android.content.Context; android.graphics.Bitmap; android.graphics.BitmapFactory; android.opengl.GLUtils;

/* * A photo cube with 6 pictures (textures) on its 6 faces. */ public class kaki_meja { private FloatBuffer vertexBuffer; // Vertex Buffer private FloatBuffer texBuffer; // Texture Coords Buffer private int numFaces = 14; private int[] imageFileIDs = { // Image file IDs R.drawable.caldera, //index 0 R.drawable.candice, //index 1 R.drawable.mule, //index 2 R.drawable.glass, //index 3 R.drawable.leonardo, //index 4 R.drawable.tmsk, //index 5 R.drawable.lantai, //index 6 R.drawable.tembok, //index 7 R.drawable.tembokx, //index 8 R.drawable.atap, //index 9 R.drawable.meja,// index 10

458

R.drawable.imam, //index 11 R.drawable.pintux, // index 12 R.drawable.wallpaper // index 13 }; private int[] textureIDs = new int[numFaces]; private Bitmap[] bitmap = new Bitmap[numFaces]; private float cubeHalfSize = 1.0f; // Constructor - Set up the vertex buffer public kaki_meja(Context context) { // Allocate vertex buffer. An float has 4 bytes ByteBuffer vbb = ByteBuffer.allocateDirect(12 * 4 * numFaces); vbb.order(ByteOrder.nativeOrder()); vertexBuffer = vbb.asFloatBuffer();

// Read images. Find the aspect ratio and adjust the vertices // accordingly. for (int face = 0; face < numFaces; face++) { bitmap[face] = BitmapFactory.decodeStream(context.getResources() .openRawResource(imageFileIDs[face])); int imgWidth = bitmap[face].getWidth(); int imgHeight = bitmap[face].getHeight(); float faceWidth = 2.0f; float faceHeight = 2.0f; // Adjust for aspect ratio if (imgWidth > imgHeight) { faceHeight = faceHeight * imgHeight / imgWidth; } else { faceWidth = faceWidth * imgWidth / imgHeight; } float float float float

faceLeft = -faceWidth / 2; faceRight = -faceLeft; faceTop = faceHeight / 2; faceBottom = -faceTop;

// Define the vertices for this face // float[] vertices = { faceLeft, faceBottom, 0.0f, // 0. // // left-bottom-front // tom, 0.0f, // 1. right-bottom-front // 0.0f, // 2. left-top-front

459

faceRight, faceBotfaceLeft, faceTop,

// faceRight, faceTop, 0.0f, // 3. right-top-front // }; float[] vertices = { // Vertices for a face -1.0f, -1.0f, 0.0f, // 0. left-bottom-front 1.0f, -1.0f, 0.0f, // 1. right-bottom-front 1.0f, 1.0f, 0.0f, // 2. left-top-front 1.0f, 1.0f, 0.0f // 3. right-top-front }; vertexBuffer.put(vertices); // Populate } vertexBuffer.position(0); // Rewind // Allocate texture buffer. An float has 4 bytes. Repeat for 6 faces. float[] texCoords = { 0.0f, 1.0f, // A. leftbottom 1.0f, 1.0f, // B. rightbottom 0.0f, 0.0f, // C. left-top 1.0f, 0.0f // D. right-top }; ByteBuffer tbb = ByteBuffer.allocateDirect(texCoords.length * 4 * numFaces); tbb.order(ByteOrder.nativeOrder()); texBuffer = tbb.asFloatBuffer(); for (int face = 0; face < numFaces; face++) { texBuffer.put(texCoords); } texBuffer.position(0); // Rewind } // Render the shape public void draw(GL10 gl) { gl.glEnable(GL10.GL_TEXTURE_2D); gl.glFrontFace(GL10.GL_CCW); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRA Y); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuffer); // front gl.glPushMatrix(); gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[10]);

460

gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); gl.glPopMatrix(); // left gl.glPushMatrix(); gl.glRotatef(270.0f, 0f, 1f, 0f); gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[10]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 4, 4); gl.glPopMatrix(); // back gl.glPushMatrix(); gl.glRotatef(180.0f, 0f, 1f, 0f); gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[10]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 8, 4); gl.glPopMatrix(); // right gl.glPushMatrix(); gl.glRotatef(90.0f, 0f, 1f, 0f); gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[10]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 12, 4); gl.glPopMatrix(); // top gl.glPushMatrix(); gl.glRotatef(270.0f, 1f, 0f, 0f); gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[10]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 16, 4); gl.glPopMatrix(); // bottom gl.glPushMatrix(); gl.glRotatef(90.0f, 1f, 0f, 0f); gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[10]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 20, 4); gl.glPopMatrix();

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARR AY);

461

gl.glDisable(GL10.GL_TEXTURE_2D); } // Load images into 6 GL textures public void loadTexture(GL10 gl, Context c) { gl.glGenTextures(14, textureIDs, 0); // Generate texture-ID array for 6 // IDs // Generate OpenGL texture images for (int face = 0; face < numFaces; face++) { gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[face]); // Build Texture from loaded bitmap for the currently-bind texture // ID

gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap[face], 0); bitmap[face].recycle(); } } }

kubus_kecil.java package com.ligthing; import import import import import import import import

java.nio.ByteBuffer; java.nio.ByteOrder; java.nio.FloatBuffer; javax.microedition.khronos.opengles.GL10; android.content.Context; android.graphics.Bitmap; android.graphics.BitmapFactory; android.opengl.GLUtils;

/* * A photo cube with 6 pictures (textures) on its 6 faces. */ public class kubus_kecil { private FloatBuffer vertexBuffer; // Vertex Buffer

462

private FloatBuffer texBuffer; // Texture Coords Buffer private int numFaces = 14; private int[] imageFileIDs = { // Image file IDs R.drawable.caldera, //index 0 R.drawable.candice, //index 1 R.drawable.mule, //index 2 R.drawable.glass, //index 3 R.drawable.leonardo, //index 4 R.drawable.tmsk, //index 5 R.drawable.lantai, //index 6 R.drawable.tembok, //index 7 R.drawable.tembokx, //index 8 R.drawable.atap, //index 9 R.drawable.meja,// index 10 R.drawable.imam, //index 11 R.drawable.pintux, // index 12 R.drawable.wallpaper // index 13 }; private int[] textureIDs = new int[numFaces]; private Bitmap[] bitmap = new Bitmap[numFaces]; private float cubeHalfSize = 1.0f; // Constructor - Set up the vertex buffer public kubus_kecil(Context context) { // Allocate vertex buffer. An float has 4 bytes ByteBuffer vbb = ByteBuffer.allocateDirect(12 * 4 * numFaces); vbb.order(ByteOrder.nativeOrder()); vertexBuffer = vbb.asFloatBuffer();

// Read images. Find the aspect ratio and adjust the vertices // accordingly. for (int face = 0; face < numFaces; face++) { bitmap[face] = BitmapFactory.decodeStream(context.getResources() .openRawResource(imageFileIDs[face])); int imgWidth = bitmap[face].getWidth(); int imgHeight = bitmap[face].getHeight(); float faceWidth = 2.0f; float faceHeight = 2.0f; // Adjust for aspect ratio if (imgWidth > imgHeight) { faceHeight = faceHeight * imgHeight / imgWidth; } else { faceWidth = faceWidth * imgWidth / imgHeight; } float faceLeft = -faceWidth / 2;

463

float faceRight = -faceLeft; float faceTop = faceHeight / 2; float faceBottom = -faceTop; // Define the vertices for this face // float[] vertices = { faceLeft, faceBottom, 0.0f, // 0. // // left-bottom-front // faceRight, faceBottom, 0.0f, // 1. right-bottom-front // faceLeft, faceTop, 0.0f, // 2. left-top-front // faceRight, faceTop, 0.0f, // 3. right-top-front // }; float[] vertices = { // Vertices for a face -1.0f, -1.0f, 0.0f, // 0. left-bottom-front 1.0f, -1.0f, 0.0f, // 1. right-bottom-front 1.0f, 1.0f, 0.0f, // 2. left-top-front 1.0f, 1.0f, 0.0f // 3. right-top-front }; vertexBuffer.put(vertices); // Populate } vertexBuffer.position(0); // Rewind // Allocate texture buffer. An float has 4 bytes. Repeat for 6 faces. float[] texCoords = { 0.0f, 1.0f, // A. leftbottom 1.0f, 1.0f, // B. rightbottom 0.0f, 0.0f, // C. left-top 1.0f, 0.0f // D. right-top }; ByteBuffer tbb = ByteBuffer.allocateDirect(texCoords.length * 4 * numFaces); tbb.order(ByteOrder.nativeOrder()); texBuffer = tbb.asFloatBuffer(); for (int face = 0; face < numFaces; face++) { texBuffer.put(texCoords); } texBuffer.position(0); // Rewind } // Render the shape public void draw(GL10 gl) { gl.glEnable(GL10.GL_TEXTURE_2D); gl.glFrontFace(GL10.GL_CCW);

464

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRA Y); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuffer); // front gl.glPushMatrix(); gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[0]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); gl.glPopMatrix(); // left gl.glPushMatrix(); gl.glRotatef(270.0f, 0f, 1f, 0f); gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[1]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 4, 4); gl.glPopMatrix(); // back gl.glPushMatrix(); gl.glRotatef(180.0f, 0f, 1f, 0f); gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[2]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 8, 4); gl.glPopMatrix(); // right gl.glPushMatrix(); gl.glRotatef(90.0f, 0f, 1f, 0f); gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[3]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 12, 4); gl.glPopMatrix(); // top gl.glPushMatrix(); gl.glRotatef(270.0f, 1f, 0f, 0f); gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[4]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 16, 4); gl.glPopMatrix();

465

// bottom gl.glPushMatrix(); gl.glRotatef(90.0f, 1f, 0f, 0f); gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[5]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 20, 4); gl.glPopMatrix();

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARR AY); gl.glDisable(GL10.GL_TEXTURE_2D); } // Load images into 6 GL textures public void loadTexture(GL10 gl, Context c) { gl.glGenTextures(14, textureIDs, 0); // Generate texture-ID array for 6 // IDs // Generate OpenGL texture images for (int face = 0; face < numFaces; face++) { gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[face]); // Build Texture from loaded bitmap for the currently-bind texture // ID

gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap[face], 0); bitmap[face].recycle(); } } }

kubus.java package com.ligthing;

466

import import import import import import import import import import import

java.io.IOException; java.io.InputStream; java.nio.ByteBuffer; java.nio.ByteOrder; java.nio.FloatBuffer; javax.microedition.khronos.opengles.GL10; android.content.Context; android.content.res.AssetManager; android.graphics.Bitmap; android.graphics.BitmapFactory; android.opengl.GLUtils;

/* * A cube with texture. * Define the vertices for only one representative face. * * Render the cube by translating and rotating the face. */ public class kubus { private FloatBuffer vertexBuffer; // Buffer for vertex-array private FloatBuffer texBuffer; // Buffer for texture-coords-array (NEW) private float[] vertices = { // Vertices for a face -1.0f, -1.0f, 0.0f, // 0. leftbottom-front 1.0f, -1.0f, 0.0f, // 1. rightbottom-front -1.0f, 1.0f, 0.0f, // 2. left-topfront 1.0f, 1.0f, 0.0f // 3. right-topfront }; float[] texCoords = { // Texture coords for the above face (NEW) 0.0f, 1.0f, // A. left-bottom (NEW) 1.0f, 1.0f, // B. right-bottom (NEW) 0.0f, 0.0f, // C. left-top (NEW) 1.0f, 0.0f // D. right-top (NEW) }; int[] textureIDs = new int[1]; // Array for 1 texture-ID (NEW) // Constructor - Set up the buffers public kubus() { // Setup vertex-array buffer. Vertices in float. An float has 4 bytes ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4); vbb.order(ByteOrder.nativeOrder()); // Use native byte order vertexBuffer = vbb.asFloatBuffer(); // Convert from byte to float vertexBuffer.put(vertices); // Copy data into buffer

467

vertexBuffer.position(0); // Rewind // Setup texture-coords-array buffer, in float. An float has 4 bytes // (NEW) ByteBuffer tbb = ByteBuffer.allocateDirect(texCoords.length * 4); tbb.order(ByteOrder.nativeOrder()); texBuffer = tbb.asFloatBuffer(); texBuffer.put(texCoords); texBuffer.position(0);

} // Draw the shape public void draw(GL10 gl) { gl.glFrontFace(GL10.GL_CCW); // Front face in counter-clockwise // orientation gl.glEnable(GL10.GL_CULL_FACE); // Enable cull face gl.glCullFace(GL10.GL_BACK); // Cull the back face (don't display) gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRA Y); // Enable

// texture-coords-array

// (NEW) gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuffer); // Define

// texture-coords

// buffer (NEW) // front gl.glPushMatrix(); gl.glTranslatef(0.0f, 0.0f, 1.0f); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); gl.glPopMatrix(); // left gl.glPushMatrix(); gl.glRotatef(270.0f, 0.0f, 1.0f, 0.0f); gl.glTranslatef(0.0f, 0.0f, 1.0f); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); gl.glPopMatrix();

468

// back gl.glPushMatrix(); gl.glRotatef(180.0f, 0.0f, 1.0f, 0.0f); gl.glTranslatef(0.0f, 0.0f, 1.0f); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); gl.glPopMatrix(); // right gl.glPushMatrix(); gl.glRotatef(90.0f, 0.0f, 1.0f, 0.0f); gl.glTranslatef(0.0f, 0.0f, 1.0f); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); gl.glPopMatrix(); // top gl.glPushMatrix(); gl.glRotatef(270.0f, 1.0f, 0.0f, 0.0f); gl.glTranslatef(0.0f, 0.0f, 1.0f); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); gl.glPopMatrix(); // bottom gl.glPushMatrix(); gl.glRotatef(90.0f, 1.0f, 0.0f, 0.0f); gl.glTranslatef(0.0f, 0.0f, 1.0f); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); gl.glPopMatrix();

gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARR AY); // Disable

// texture-coords-array

// (NEW) gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisable(GL10.GL_CULL_FACE); } // Load an image into GL texture public void loadTexture(GL10 gl,Context c) { gl.glGenTextures(1, textureIDs, 0); // Generate texture-ID array gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[0]); // Bind to texture

// ID // Set up texture filters gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,

469

GL10.GL_NEAREST); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

// Construct an input stream to texture image "res\drawable\nature.png" //AssetManager assetManager = c.getAssets(); //InputStream istream = assetManager.open("nature.png"); InputStream istream = c.getResources().openRawResource(R.drawable.atap); Bitmap bitmap; try { // Read and decode input as bitmap bitmap = BitmapFactory.decodeStream(istream); } finally { try { istream.close(); } catch (IOException e) { } } // Build Texture from loaded bitmap for the currently-bind texture ID GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0); bitmap.recycle(); } }

lampu.java package com.ligthing; import import import import import import import import

java.nio.ByteBuffer; java.nio.ByteOrder; java.nio.FloatBuffer; javax.microedition.khronos.opengles.GL10; android.content.Context; android.graphics.Bitmap; android.graphics.BitmapFactory; android.opengl.GLUtils;

/* * A photo cube with 6 pictures (textures) on its 6 faces. */ public class lampu { private FloatBuffer vertexBuffer; // Vertex Buffer private FloatBuffer texBuffer; // Texture Coords Buffer

470

private int numFaces = 15; private int[] imageFileIDs = { // Image file IDs R.drawable.caldera, //index 0 R.drawable.candice, //index 1 R.drawable.mule, //index 2 R.drawable.glass, //index 3 R.drawable.leonardo, //index 4 R.drawable.tmsk, //index 5 R.drawable.lantai, //index 6 R.drawable.tembok, //index 7 R.drawable.tembokx, //index 8 R.drawable.atap, //index 9 R.drawable.meja,// index 10 R.drawable.imam, //index 11 R.drawable.pintux, // index 12 R.drawable.wallpaper, // index 13 R.drawable.lampux // index 14 }; private int[] textureIDs = new int[numFaces]; private Bitmap[] bitmap = new Bitmap[numFaces]; private float cubeHalfSize = 1.0f; // Constructor - Set up the vertex buffer public lampu(Context context) { // Allocate vertex buffer. An float has 4 bytes ByteBuffer vbb = ByteBuffer.allocateDirect(12 * 4 * numFaces); vbb.order(ByteOrder.nativeOrder()); vertexBuffer = vbb.asFloatBuffer();

// Read images. Find the aspect ratio and adjust the vertices // accordingly. for (int face = 0; face < numFaces; face++) { bitmap[face] = BitmapFactory.decodeStream(context.getResources() .openRawResource(imageFileIDs[face])); int imgWidth = bitmap[face].getWidth(); int imgHeight = bitmap[face].getHeight(); float faceWidth = 2.0f; float faceHeight = 2.0f; // Adjust for aspect ratio if (imgWidth > imgHeight) { faceHeight = faceHeight * imgHeight / imgWidth; } else { faceWidth = faceWidth * imgWidth / imgHeight; } float faceLeft = -faceWidth / 2; float faceRight = -faceLeft;

471

float faceTop = faceHeight / 2; float faceBottom = -faceTop; // Define the vertices for this face // float[] vertices = { faceLeft, faceBottom, 0.0f, // 0. // // left-bottom-front // faceRight, faceBottom, 0.0f, // 1. right-bottom-front // faceLeft, faceTop, 0.0f, // 2. left-top-front // faceRight, faceTop, 0.0f, // 3. right-top-front // }; float[] vertices = { // Vertices for a face -1.0f, -1.0f, 0.0f, // 0. left-bottom-front 1.0f, -1.0f, 0.0f, // 1. right-bottom-front 1.0f, 1.0f, 0.0f, // 2. left-top-front 1.0f, 1.0f, 0.0f // 3. right-top-front }; vertexBuffer.put(vertices); // Populate } vertexBuffer.position(0); // Rewind // Allocate texture buffer. An float has 4 bytes. Repeat for 6 faces. float[] texCoords = { 0.0f, 1.0f, // A. leftbottom 1.0f, 1.0f, // B. rightbottom 0.0f, 0.0f, // C. left-top 1.0f, 0.0f // D. right-top }; ByteBuffer tbb = ByteBuffer.allocateDirect(texCoords.length * 4 * numFaces); tbb.order(ByteOrder.nativeOrder()); texBuffer = tbb.asFloatBuffer(); for (int face = 0; face < numFaces; face++) { texBuffer.put(texCoords); } texBuffer.position(0); // Rewind } // Render the shape public void draw(GL10 gl) { gl.glEnable(GL10.GL_TEXTURE_2D); gl.glFrontFace(GL10.GL_CCW);

472

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRA Y); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuffer); // front gl.glPushMatrix(); gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[14]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); gl.glPopMatrix(); // left gl.glPushMatrix(); gl.glRotatef(270.0f, 0f, 1f, 0f); gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[14]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 4, 4); gl.glPopMatrix(); // back gl.glPushMatrix(); gl.glRotatef(180.0f, 0f, 1f, 0f); gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[14]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 8, 4); gl.glPopMatrix(); // right gl.glPushMatrix(); gl.glRotatef(90.0f, 0f, 1f, 0f); gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[14]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 12, 4); gl.glPopMatrix(); // top gl.glPushMatrix(); gl.glRotatef(270.0f, 1f, 0f, 0f); gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[14]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 16, 4); gl.glPopMatrix();

473

// bottom gl.glPushMatrix(); gl.glRotatef(90.0f, 1f, 0f, 0f); gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[14]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 20, 4); gl.glPopMatrix();

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARR AY); gl.glDisable(GL10.GL_TEXTURE_2D); } // Load images into 6 GL textures public void loadTexture(GL10 gl, Context c) { gl.glGenTextures(15, textureIDs, 0); // Generate texture-ID array for 6 // IDs // Generate OpenGL texture images for (int face = 0; face < numFaces; face++) { gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[face]); // Build Texture from loaded bitmap for the currently-bind texture // ID

gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap[face], 0); bitmap[face].recycle(); } } }

lukisan.java package com.ligthing; import java.nio.ByteBuffer;

474

import import import import import import import

java.nio.ByteOrder; java.nio.FloatBuffer; javax.microedition.khronos.opengles.GL10; android.content.Context; android.graphics.Bitmap; android.graphics.BitmapFactory; android.opengl.GLUtils;

/* * A photo cube with 6 pictures (textures) on its 6 faces. */ public class lampu { private FloatBuffer vertexBuffer; // Vertex Buffer private FloatBuffer texBuffer; // Texture Coords Buffer private int numFaces = 15; private int[] imageFileIDs = { // Image file IDs R.drawable.caldera, //index 0 R.drawable.candice, //index 1 R.drawable.mule, //index 2 R.drawable.glass, //index 3 R.drawable.leonardo, //index 4 R.drawable.tmsk, //index 5 R.drawable.lantai, //index 6 R.drawable.tembok, //index 7 R.drawable.tembokx, //index 8 R.drawable.atap, //index 9 R.drawable.meja,// index 10 R.drawable.imam, //index 11 R.drawable.pintux, // index 12 R.drawable.wallpaper, // index 13 R.drawable.lampux // index 14 }; private int[] textureIDs = new int[numFaces]; private Bitmap[] bitmap = new Bitmap[numFaces]; private float cubeHalfSize = 1.0f; // Constructor - Set up the vertex buffer public lampu(Context context) { // Allocate vertex buffer. An float has 4 bytes ByteBuffer vbb = ByteBuffer.allocateDirect(12 * 4 * numFaces); vbb.order(ByteOrder.nativeOrder()); vertexBuffer = vbb.asFloatBuffer();

// Read images. Find the aspect ratio and adjust the vertices // accordingly. for (int face = 0; face < numFaces; face++) { bitmap[face] = BitmapFactory.decodeStream(context.getResources() .openRawResource(imageFileIDs[face]));

475

int imgWidth = bitmap[face].getWidth(); int imgHeight = bitmap[face].getHeight(); float faceWidth = 2.0f; float faceHeight = 2.0f; // Adjust for aspect ratio if (imgWidth > imgHeight) { faceHeight = faceHeight * imgHeight / imgWidth; } else { faceWidth = faceWidth * imgWidth / imgHeight; } float float float float

faceLeft = -faceWidth / 2; faceRight = -faceLeft; faceTop = faceHeight / 2; faceBottom = -faceTop;

// Define the vertices for this face // float[] vertices = { faceLeft, faceBottom, 0.0f, // 0. // // left-bottom-front // faceRight, faceBottom, 0.0f, // 1. right-bottom-front // faceLeft, faceTop, 0.0f, // 2. left-top-front // faceRight, faceTop, 0.0f, // 3. right-top-front // }; float[] vertices = { // Vertices for a face -1.0f, -1.0f, 0.0f, // 0. left-bottom-front 1.0f, -1.0f, 0.0f, // 1. right-bottom-front 1.0f, 1.0f, 0.0f, // 2. left-top-front 1.0f, 1.0f, 0.0f // 3. right-top-front }; vertexBuffer.put(vertices); // Populate } vertexBuffer.position(0); // Rewind // Allocate texture buffer. An float has 4 bytes. Repeat for 6 faces. float[] texCoords = { 0.0f, 1.0f, // A. leftbottom 1.0f, 1.0f, // B. rightbottom 0.0f, 0.0f, // C. left-top 1.0f, 0.0f // D. right-top };

476

ByteBuffer tbb = ByteBuffer.allocateDirect(texCoords.length * 4 * numFaces); tbb.order(ByteOrder.nativeOrder()); texBuffer = tbb.asFloatBuffer(); for (int face = 0; face < numFaces; face++) { texBuffer.put(texCoords); } texBuffer.position(0); // Rewind } // Render the shape public void draw(GL10 gl) { gl.glEnable(GL10.GL_TEXTURE_2D); gl.glFrontFace(GL10.GL_CCW);

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRA Y); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuffer); // front gl.glPushMatrix(); gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[14]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); gl.glPopMatrix(); // left gl.glPushMatrix(); gl.glRotatef(270.0f, 0f, 1f, 0f); gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[14]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 4, 4); gl.glPopMatrix(); // back gl.glPushMatrix(); gl.glRotatef(180.0f, 0f, 1f, 0f); gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[14]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 8, 4); gl.glPopMatrix(); // right gl.glPushMatrix(); gl.glRotatef(90.0f, 0f, 1f, 0f);

477

gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[14]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 12, 4); gl.glPopMatrix(); // top gl.glPushMatrix(); gl.glRotatef(270.0f, 1f, 0f, 0f); gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[14]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 16, 4); gl.glPopMatrix(); // bottom gl.glPushMatrix(); gl.glRotatef(90.0f, 1f, 0f, 0f); gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[14]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 20, 4); gl.glPopMatrix();

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARR AY); gl.glDisable(GL10.GL_TEXTURE_2D); } // Load images into 6 GL textures public void loadTexture(GL10 gl, Context c) { gl.glGenTextures(15, textureIDs, 0); // Generate texture-ID array for 6 // IDs // Generate OpenGL texture images for (int face = 0; face < numFaces; face++) { gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[face]); // Build Texture from loaded bitmap for the currently-bind texture // ID

gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,

478

GL10.GL_LINEAR); GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap[face], 0); bitmap[face].recycle(); } } }

MainActivity.java package com.ligthing; import import import import import import

android.opengl.GLSurfaceView; android.os.Bundle; android.app.Activity; android.view.Menu; android.view.Window; android.view.WindowManager;

public class MainActivity extends Activity { /** The OpenGL view */ private GLSurfaceView glSurfaceView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //setContentView(R.layout.activity_main); // requesting to turn the title OFF requestWindowFeature(Window.FEATURE_NO_TITLE); // making it full screen getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREE N, WindowManager.LayoutParams.FLAG_FULLSCREEN); // Initiate the Open GL view and // create an instance with this activity glSurfaceView = new ESSurfaceView(this); // set our renderer to be the main renderer with // the current activity context //glSurfaceView.setRenderer(new ESRender()); setContentView(glSurfaceView); } /** * Remember to resume the glSurface */ @Override protected void onResume() { super.onResume();

479

glSurfaceView.onResume(); } /** * Also pause the glSurface */ @Override protected void onPause() { super.onPause(); glSurfaceView.onPause(); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }

Maths.java

package com.ligthing; /** * @author Jim Cornmell re-edit by XTech * */ public final class Maths { /** 180 in radians. */ public static final double ONE_EIGHTY_DEGREES = Math.PI; /** 360 in radians. */ public static final double THREE_SIXTY_DEGREES = ONE_EIGHTY_DEGREES * 2; /** 120 in radians. */ public static final double ONE_TWENTY_DEGREES = THREE_SIXTY_DEGREES / 3; /** 90 degrees, North pole. */ public static final double NINETY_DEGREES = Math.PI / 2; 480

/** Used by power. */ private static final long POWER_CLAMP = 0x00000000ffffffffL; /** * Constructor, although not used at the moment. */ private Maths() { } /** * Quick integer power function. * * @param base * number to raise. * @param raise * to this power. * @return base ^ raise. */ public static int power(final int base, final int raise) { int p = 1; long b = raise & POWER_CLAMP; // bits in b correspond to values of powerN // so start with p=1, and for each set bit in b, multiply corresponding // table entry long powerN = base; while (b if ((b p *= } b >>>= powerN }

!= 0) { & 1) != 0) { powerN; 1; = powerN * powerN;

return p; } }

481

MySphere.java package com.ligthing; import import import import import

java.nio.ByteBuffer; java.nio.ByteOrder; java.nio.FloatBuffer; java.util.ArrayList; java.util.List;

import javax.microedition.khronos.opengles.GL10; import import import import import

android.content.Context; android.graphics.Bitmap; android.graphics.BitmapFactory; android.graphics.Matrix; android.opengl.GLUtils;

/** * Render a sphere. * * @author Jim Cornmell re-edit by XTech * @since July 2013 */ public class MySphere { /** Maximum allowed depth. */ private static final int MAXIMUM_ALLOWED_DEPTH = 5; /** Used in vertex strip calculations, related to properties of a icosahedron. */ private static final int VERTEX_MAGIC_NUMBER = 5; /** Each vertex is a 2D coordinate. */ private static final int NUM_FLOATS_PER_VERTEX = 3; /** Each texture is a 2D coordinate. */ private static final int NUM_FLOATS_PER_TEXTURE = 2; /** Each vertex is made up of 3 points, x, y, z. */ private static final int AMOUNT_OF_NUMBERS_PER_VERTEX_POINT = 3; /** Each texture point is made up of 2 points, x, y (in reference to the texture being a 2D image). */ private static final int AMOUNT_OF_NUMBERS_PER_TEXTURE_POINT = 2; /** Buffer holding the vertices. */ private final List mVertexBuffer = new ArrayList(); /** The vertices for the sphere. */ private final List mVertices = new ArrayList(); /** Buffer holding the texture coordinates. */ private final List mTextureBuffer = new ArrayList();

482

/** Mapping texture coordinates for the vertices. */ private final List mTexture = new ArrayList(); /** The texture pointer. */ private final int[] mTextures = new int[1]; /** Total number of strips for the given depth. */ private final int mTotalNumStrips; private int[] imageFileIDs = { // Image file IDs R.drawable.nature, R.drawable.mule, R.drawable.earth, R.drawable.basketballcolor, R.drawable.soccerballadidas, R.drawable.ball1,R.drawable.ball2, R.drawable.ball3,R.drawable.ball4,R.drawable.ball 5, R.drawable.ball6,R.drawable.ball7,R.drawable.ball 8, R.drawable.ball9,R.drawable.ballcue }; /** * Sphere constructor. * @param depth integer representing the split of the sphere. * @param radius The spheres radius. */ public MySphere(final int depth, final float radius) { // Clamp depth to the range 1 to MAXIMUM_ALLOWED_DEPTH; final int d = Math.max(1, Math.min(MAXIMUM_ALLOWED_DEPTH, depth)); // Calculate basic values for the sphere. this.mTotalNumStrips = Maths.power(2, d - 1) * VERTEX_MAGIC_NUMBER; final int numVerticesPerStrip = Maths.power(2, d) * 3; final double altitudeStepAngle = Maths.ONE_TWENTY_DEGREES / Maths.power(2, d); final double azimuthStepAngle = Maths.THREE_SIXTY_DEGREES / this.mTotalNumStrips; double x, y, z, h, altitude, azimuth; for (int stripNum = 0; stripNum < this.mTotalNumStrips; stripNum++) { // Setup arrays to hold the points for this strip. final float[] vertices = new float[numVerticesPerStrip * NUM_FLOATS_PER_VERTEX]; // NOPMD final float[] texturePoints = new float[numVerticesPerStrip * NUM_FLOATS_PER_TEXTURE]; // NOPMD

483

int vertexPos = 0; int texturePos = 0; // Calculate position of the first vertex in this strip. altitude = Maths.NINETY_DEGREES; azimuth = stripNum * azimuthStepAngle; // Draw the rest of this strip. for (int vertexNum = 0; vertexNum < numVerticesPerStrip; vertexNum += 2) { // First point - Vertex. y = radius * Math.sin(altitude); h = radius * Math.cos(altitude); z = h * Math.sin(azimuth); x = h * Math.cos(azimuth); vertices[vertexPos++] = (float) x; vertices[vertexPos++] = (float) y; vertices[vertexPos++] = (float) z; // First point - Texture. texturePoints[texturePos++] = (float) (1 - azimuth / Maths.THREE_SIXTY_DEGREES); texturePoints[texturePos++] = (float) (1 - (altitude + Maths.NINETY_DEGREES) / Maths.ONE_EIGHTY_DEGREES); // Second point - Vertex. altitude -= altitudeStepAngle; azimuth -= azimuthStepAngle / 2.0; y = radius * Math.sin(altitude); h = radius * Math.cos(altitude); z = h * Math.sin(azimuth); x = h * Math.cos(azimuth); vertices[vertexPos++] = (float) x; vertices[vertexPos++] = (float) y; vertices[vertexPos++] = (float) z; // Second point - Texture. texturePoints[texturePos++] = (float) (1 - azimuth / Maths.THREE_SIXTY_DEGREES); texturePoints[texturePos++] = (float) (1 - (altitude + Maths.NINETY_DEGREES) / Maths.ONE_EIGHTY_DEGREES); azimuth += azimuthStepAngle; } this.mVertices.add(vertices); this.mTexture.add(texturePoints); ByteBuffer byteBuffer = ByteBuffer.allocateDirect(numVerticesPerStrip * NUM_FLOATS_PER_VERTEX * Float.SIZE); byteBuffer.order(ByteOrder.nativeOrder()); FloatBuffer fb = byteBuffer.asFloatBuffer(); fb.put(this.mVertices.get(stripNum)); fb.position(0); this.mVertexBuffer.add(fb);

484

// Setup texture. byteBuffer = ByteBuffer.allocateDirect(numVerticesPerStrip * NUM_FLOATS_PER_TEXTURE * Float.SIZE); byteBuffer.order(ByteOrder.nativeOrder()); fb = byteBuffer.asFloatBuffer(); fb.put(this.mTexture.get(stripNum)); fb.position(0); this.mTextureBuffer.add(fb); } } /** * Load the texture for the square. * * @param gl Handle. * @param context Handle. * @param texture Texture map for the sphere. */ public void loadGLTexture(final GL10 gl, final Context context, final int index_Texture) { //public void loadGLTexture(final GL10 gl, final Context context, final int texture) { // final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), texture); final Bitmap bitmap = BitmapFactory.decodeStream(context.getResources() .openRawResource(imageFileIDs[index_Texture])); // flip method, untuk membalik texture yang kurang sesuai Matrix flip = new Matrix(); flip.postScale(-1f, 1f); final Bitmap bmp = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), flip, true);

// Generate one texture pointer, and bind it to the texture array. gl.glGenTextures(1, this.mTextures, 0); gl.glBindTexture(GL10.GL_TEXTURE_2D, this.mTextures[0]); // Create nearest filtered texture. gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); // Use Android GLUtils to specify a two-dimensional texture image from our bitmap. //GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0); GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bmp, 0); // Tidy up.

485

//bitmap.recycle(); bmp.recycle(); } /** * The draw method for the square with the GL context. * * @param gl Graphics handle. */ public void draw(final GL10 gl) { //menempelkan tekstur ke objek gl.glEnable(GL10.GL_TEXTURE_2D); // bind the previously generated texture. gl.glBindTexture(GL10.GL_TEXTURE_2D, this.mTextures[0]); // Point to our buffers. gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_NORMAL_ARRAY); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); // Set the face rotation, clockwise in this case. gl.glFrontFace(GL10.GL_CCW); // Point to our vertex buffer. for (int i = 0; i < this.mTotalNumStrips; i++) { gl.glVertexPointer(AMOUNT_OF_NUMBERS_PER_VERTEX_POINT, GL10.GL_FLOAT, 0, this.mVertexBuffer.get(i)); gl.glNormalPointer(GL10.GL_FLOAT, 0, this.mVertexBuffer.get(i)); gl.glTexCoordPointer(AMOUNT_OF_NUMBERS_PER_TEXTURE_POINT , GL10.GL_FLOAT, 0, this.mTextureBuffer.get(i)); // Draw the vertices as triangle strip. gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, this.mVertices.get(i).length / AMOUNT_OF_NUMBERS_PER_VERTEX_POINT); } // Disable the client state before leaving. gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY); gl.glDisableClientState(GL10.GL_NORMAL_ARRAY); gl.glDisable( GL10.GL_TEXTURE_2D ); // Disable Texture Mapping } }

ObjectArena.java package com.ligthing;

486

import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import javax.microedition.khronos.opengles.GL10; import android.opengl.GLES20; public class ObjectArena { private float vertices[] = { -0.5f, -0.5f, 0.0f, first vertex (x,y,z) -0.5f, 0.5f, 0.0f, V2 0.5f, 0.5f, 0.0f, V3 0.5f, -0.5f, 0.0f, -0.5f, -0.5f, 0.0f V5 };

// V1 // // // V4

private float vertices_color[] = { 1.0f, 0.0f, 0.0f, 1.0f, CV1 - first color (red,green,blue) 0.0f, 1.0f, 0.0f, 1.0f, CV2 0.0f, 0.0f, 1.0f, 1.0f, CV3 0.0f, 1.0f, 0.0f, 1.0f, CV4 1.0f, 0.0f, 0.0f, 1.0f // CV5 };

//

// // // //

public ObjectArena() { } // Point to our vertex buffer, return buffer holding the vertices public static FloatBuffer makeFloatBuffer(float[] arr){ ByteBuffer bb = ByteBuffer.allocateDirect(arr.length * 4); bb.order(ByteOrder.nativeOrder()); FloatBuffer fb = bb.asFloatBuffer(); fb.put(arr); fb.position(0); return fb; } /** The draw method for the primitive object with the GL context */ public void draw_kotak(GL10 gl) {

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

487

// Point to our vertex buffer gl.glVertexPointer(3, GL10.GL_FLOAT, 0, makeFloatBuffer(vertices)); // Draw the vertices as square gl.glColorPointer(4, GL10.GL_FLOAT, 0, makeFloatBuffer(vertices_color)); gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3); gl.glColorPointer(4, GL10.GL_FLOAT, 0, makeFloatBuffer(vertices_color)); gl.glDrawArrays(GL10.GL_TRIANGLES, 2, 3);

//Disable the client state before leaving gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_COLOR_ARRAY); } }

ObjectBall.java package com.ligthing; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import javax.microedition.khronos.opengles.GL10; import javax.microedition.khronos.opengles.GL11; import javax.microedition.khronos.opengles.GL11ExtensionPack; import import import import import import

android.content.Context; android.graphics.Bitmap; android.graphics.BitmapFactory; android.opengl.GLES20; android.opengl.GLUtils; android.util.Log;

public class ObjectBall { private float vertices_circle[]={0.0f,0.0f,0.0f}; private float vertices_circle_color[]={0.0f,0.0f,0.0f,0.5f}; private float textCoord[]; private float vertices_circle1[];

int[] textures_indek = new int[1]; private int batas_sudut=360;

488

float jari_jari; float a,b; float x,y; float step=3.0f,step_line=0.2f; float x1,y1; float x2,y2; float teta; private int loop,loop_color; public ObjectBall() { // ============ start to generate stetch texture coordinat ========================== //Inisialisasi jari_jari=0.5f; // Titik Pusat a = 0.5f; b = 0.5f ; //x=a+jari_jari; y=b; teta = 0; // generate stretch texture coordinat teta=0; textCoord = new float[batas_sudut * 3]; for (int ii = 0; ii < batas_sudut * 3; ii += 3) { // membentuk textCoord textCoord[ii] = (jari_jari*((float) Math.cos(-teta)))+a; textCoord[ii + 1] = (jari_jari*((float) Math.sin(-teta)))+b; textCoord[ii + 2] = 0.0f; teta += Math.PI / 90; } // ============ start to generate vertices to circle (Cara 1) ========================== //Inisialisasi jari_jari=50.0f; // Titik Pusat a = 50.0f; b = 50.0f ; vertices_circle1 = new float[batas_sudut * 3]; for (int ii = 0; ii < batas_sudut * 3; ii += 3) { // membentuk vertices_circle1 vertices_circle1[ii] = (jari_jari*((float) Math.cos(teta)))+a; vertices_circle1[ii + 1] = (jari_jari*((float) Math.sin(teta)))+b; vertices_circle1[ii + 2] = 0.0f; teta += Math.PI / 90; }

489

// ============ start to generate vertices to circle (Cara 2) ========================== //Inisialisasi jari_jari=50.0f; // Titik Pusat a = 50.0f; b = 50.0f ; x=a+jari_jari; y=b; loop=0; loop_color=0; vertices_circle=new float[(int)(3*batas_sudut/step)*3]; vertices_circle_color=new float[(int)(3*batas_sudut/step)*4]; for(teta=0;teta imgHeight) { faceHeight = faceHeight * imgHeight / imgWidth; } else { faceWidth = faceWidth * imgWidth / imgHeight; } float float float float

faceLeft = -faceWidth / 2; faceRight = -faceLeft; faceTop = faceHeight / 2; faceBottom = -faceTop;

// Define the vertices for this face // float[] vertices = { faceLeft, faceBottom, 0.0f, // 0. // // left-bottom-front // faceRight, faceBottom, 0.0f, // 1. right-bottom-front // faceLeft, faceTop, 0.0f, // 2. left-top-front // faceRight, faceTop, 0.0f, // 3. right-top-front // }; float[] vertices = { // Vertices for a face -2.0f, -1.0f, 0.0f, // 0. left-bottom-front 2.0f, -1.0f, 0.0f, // 1. right-bottom-front 2.0f, 1.0f, 0.0f, // 2. left-top-front

498

2.0f, 1.0f, 0.0f // 3. right-top-front }; vertexBuffer.put(vertices); // Populate } vertexBuffer.position(0); // Rewind // Allocate texture buffer. An float has 4 bytes. Repeat for 6 faces. float[] texCoords = { 0.0f, 1.0f, // A. leftbottom 1.0f, 1.0f, // B. rightbottom 0.0f, 0.0f, // C. left-top 1.0f, 0.0f // D. right-top }; ByteBuffer tbb = ByteBuffer.allocateDirect(texCoords.length * 4 * numFaces); tbb.order(ByteOrder.nativeOrder()); texBuffer = tbb.asFloatBuffer(); for (int face = 0; face < numFaces; face++) { texBuffer.put(texCoords); } texBuffer.position(0); // Rewind } // Render the shape (Buat lantai) public void draw(GL10 gl) { gl.glEnable(GL10.GL_TEXTURE_2D); gl.glFrontFace(GL10.GL_CCW); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRA Y); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuffer); // lantai gl.glPushMatrix(); gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[14]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); gl.glPopMatrix();

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARR AY); gl.glDisable(GL10.GL_TEXTURE_2D); }

499

// Render the shape (Buat tembok belakang) public void draw_tembok_blk(GL10 gl) { gl.glEnable(GL10.GL_TEXTURE_2D); gl.glFrontFace(GL10.GL_CCW); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRA Y); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuffer); // tembok gl.glPushMatrix(); gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[17]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); gl.glPopMatrix();

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARR AY); gl.glDisable(GL10.GL_TEXTURE_2D); } // Render the shape (Buat tembok samping) public void draw_tembok_smp(GL10 gl) { gl.glFrontFace(GL10.GL_CCW); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRA Y); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuffer); // tembok gl.glPushMatrix(); gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[17]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); gl.glPopMatrix();

500

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARR AY); } // Render the shape (Buat atap) public void draw_atap(GL10 gl) { gl.glEnable(GL10.GL_TEXTURE_2D); gl.glFrontFace(GL10.GL_CCW); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRA Y); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuffer); // atap gl.glPushMatrix(); gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[16]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); gl.glPopMatrix();

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARR AY); gl.glDisable(GL10.GL_TEXTURE_2D); } public void draw_meja(GL10 gl) { gl.glFrontFace(GL10.GL_CCW); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRA Y); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuffer); // meja gl.glPushMatrix();

501

gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[10]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); gl.glPopMatrix();

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARR AY); } // buat kaki meja public void draw_kaki_meja(GL10 gl) { gl.glFrontFace(GL10.GL_CCW); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRA Y); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuffer); // kaki meja meja gl.glPushMatrix(); gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[10]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); gl.glPopMatrix();

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARR AY); } // Load images into 6 GL textures public void loadTexture(GL10 gl, Context c) { gl.glGenTextures(18, textureIDs, 0); // Generate texture-ID array for 6 // IDs // Generate OpenGL texture images for (int face = 0; face < numFaces; face++) {

502

gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[face]); // Build Texture from loaded bitmap for the currently-bind texture // ID

gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap[face], 0); bitmap[face].recycle(); } } }

pintu.java package com.ligthing; import import import import import import import import

java.nio.ByteBuffer; java.nio.ByteOrder; java.nio.FloatBuffer; javax.microedition.khronos.opengles.GL10; android.content.Context; android.graphics.Bitmap; android.graphics.BitmapFactory; android.opengl.GLUtils;

/* * A photo cube with 6 pictures (textures) on its 6 faces. */ public class pintu { private FloatBuffer vertexBuffer; // Vertex Buffer private FloatBuffer texBuffer; // Texture Coords Buffer private int numFaces = 14; private int[] imageFileIDs = { // Image file IDs R.drawable.caldera, //index 0 R.drawable.pintuku, //index 1 R.drawable.mule, //index 2 R.drawable.glass, //index 3 R.drawable.leonardo, //index 4 R.drawable.tmsk, //index 5 R.drawable.lantai, //index 6 R.drawable.tembok, //index 7 R.drawable.tembokx, //index 8 R.drawable.atap, //index 9

503

R.drawable.meja,// index 10 R.drawable.imam, //index 11 R.drawable.pintux, // index 12 R.drawable.wallpaper // index 13 }; private int[] textureIDs = new int[numFaces]; private Bitmap[] bitmap = new Bitmap[numFaces]; private float cubeHalfSize = 1.0f; // Constructor - Set up the vertex buffer public pintu(Context context) { // Allocate vertex buffer. An float has 4 bytes ByteBuffer vbb = ByteBuffer.allocateDirect(12 * 4 * numFaces); vbb.order(ByteOrder.nativeOrder()); vertexBuffer = vbb.asFloatBuffer();

// Read images. Find the aspect ratio and adjust the vertices // accordingly. for (int face = 0; face < numFaces; face++) { bitmap[face] = BitmapFactory.decodeStream(context.getResources() .openRawResource(imageFileIDs[face])); int imgWidth = bitmap[face].getWidth(); int imgHeight = bitmap[face].getHeight(); float faceWidth = 2.0f; float faceHeight = 2.0f; // Adjust for aspect ratio if (imgWidth > imgHeight) { faceHeight = faceHeight * imgHeight / imgWidth; } else { faceWidth = faceWidth * imgWidth / imgHeight; } float float float float

faceLeft = -faceWidth / 2; faceRight = -faceLeft; faceTop = faceHeight / 2; faceBottom = -faceTop;

float[] vertices = { // Vertices for a face -1.0f, -1.0f, 0.0f, // 0. left-bottom-front 1.0f, -1.0f, 0.0f, // 1. right-bottom-front 1.0f, 1.0f, 0.0f, // 2. left-top-front

504

1.0f, 1.0f, 0.0f // 3. right-top-front }; vertexBuffer.put(vertices); // Populate } vertexBuffer.position(0); // Rewind // Allocate texture buffer. An float has 4 bytes. Repeat for 6 faces. float[] texCoords = { 0.0f, 1.0f, // A. leftbottom 1.0f, 1.0f, // B. rightbottom 0.0f, 0.0f, // C. left-top 1.0f, 0.0f // D. right-top }; ByteBuffer tbb = ByteBuffer.allocateDirect(texCoords.length * 4 * numFaces); tbb.order(ByteOrder.nativeOrder()); texBuffer = tbb.asFloatBuffer(); for (int face = 0; face < numFaces; face++) { texBuffer.put(texCoords); } texBuffer.position(0); // Rewind } // Render the shape (Buat PINTU) public void draw_pintu(GL10 gl) { gl.glEnable(GL10.GL_TEXTURE_2D); gl.glFrontFace(GL10.GL_CCW); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRA Y); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuffer); // tembok gl.glPushMatrix(); gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[1]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); gl.glPopMatrix();

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARR AY);

505

gl.glDisable(GL10.GL_TEXTURE_2D); } // Load images into 6 GL textures public void loadTexture(GL10 gl, Context c) { gl.glGenTextures(14, textureIDs, 0); // Generate texture-ID array for 6 // IDs // Generate OpenGL texture images for (int face = 0; face < numFaces; face++) { gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[face]); // Build Texture from loaded bitmap for the currently-bind texture // ID

gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap[face], 0); bitmap[face].recycle(); } } }

PrimitivesObject.java package com.ligthing; import import import import import

java.nio.ByteBuffer; java.nio.ByteOrder; java.nio.FloatBuffer; javax.microedition.khronos.opengles.GL10; android.opengl.GLES20;

public class PrimitivesObject { private float vertices[] = { -0.5f, -0.5f, 0.0f, // V1 - first vertex // (x,y,z) -0.5f, 0.5f, 0.0f, // V2 0.5f, 0.5f, 0.0f, // V3 0.5f, -0.5f, 0.0f, // V4

506

-0.5f, -0.5f, 0.0f // V5 }; private float[] vertices_quad = { // Vertices for the square -1.0f, -1.0f, 0.0f, // 0. left-bottom 1.0f, -1.0f, 0.0f, // 1. rightbottom -1.0f, 1.0f, 0.0f, // 2. left-top 1.0f, 1.0f, 0.0f // 3. right-top }; private float vertices_color[] = { 1.0f, 0.0f, 0.0f, 1.0f, // CV1 - first

// color

// (red,green,blue) 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f,

0.0f, 1.0f, 0.0f, 0.0f,

1.0f, // CV2 1.0f, // CV3 1.0f, // CV4 1.0f // CV5

}; private float vertices_circle[] = { 0.0f, 0.0f, 0.0f }; private float vertices_circle_color[] = { 0.0f, 0.0f, 0.0f, 0.5f }; private float vertices_line[] = { 0.0f, 0.0f, 0.0f }; private float vertices_line_color[] = { 0.0f, 0.0f, 0.0f, 1.0f }; private int batas_sudut = 360; float jari_jari; float a, b; float x, y; float step = 3.0f, step_line = 0.2f; float x1, y1; float x2, y2; private int loop, loop_color, loop_line, loop_line_color; public PrimitivesObject() { // ============ start to generate vertices to circle // ========================== // Inisialisasi jari_jari = 1.0f; // Titik Pusat a = 0.0f; b = 0.0f; x = a + jari_jari; y = b; loop = 3;

507

loop_color = 4; vertices_circle = new float[(int) (3 * batas_sudut / step) * 3]; vertices_circle_color = new float[(int) (3 * batas_sudut / step) * 4]; for (float teta = 0; teta imgHeight) { faceHeight = faceHeight * imgHeight / imgWidth; } else { faceWidth = faceWidth * imgWidth / imgHeight; } float float float float

faceLeft = -faceWidth / 2; faceRight = -faceLeft; faceTop = faceHeight / 2; faceBottom = -faceTop;

// Define the vertices for this face // float[] vertices = { faceLeft, faceBottom, 0.0f, // 0. // // left-bottom-front // faceRight, faceBottom, 0.0f, //

519

1. right-bottom-front // faceLeft, faceTop, 0.0f, // 2. left-top-front // faceRight, faceTop, 0.0f, // 3. right-top-front // }; float[] vertices = { // Vertices for a face -1.0f, -1.0f, 0.0f, // 0. leftbottom-front 1.0f, -1.0f, 0.0f, // 1. right-bottom-front -1.0f, 1.0f, 0.0f, // 2. left-top-front 1.0f, 1.0f, 0.0f // 3. right-top-front }; vertexBuffer.put(vertices); // Populate } vertexBuffer.position(0); // Rewind // Allocate texture buffer. An float has 4 bytes. Repeat for 6 faces. float[] texCoords = { 0.0f, 1.0f, // A. left-bottom 1.0f, 1.0f, // B. rightbottom 0.0f, 0.0f, // C. left-top 1.0f, 0.0f // D. right-top }; ByteBuffer tbb = ByteBuffer.allocateDirect(texCoords.length * 4 * numFaces); tbb.order(ByteOrder.nativeOrder()); texBuffer = tbb.asFloatBuffer(); for (int face = 0; face < numFaces; face++) { texBuffer.put(texCoords); } texBuffer.position(0); // Rewind } // Render the shape (Buat lantai) public void draw(GL10 gl) { gl.glFrontFace(GL10.GL_CCW); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRA Y); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuffer); // lantai gl.glPushMatrix(); gl.glRotatef(90, 1.0f, 0.0f, 0.0f); gl.glTranslatef(0f, 0f, cubeHalfSize);

520

gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[6]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); gl.glPopMatrix();

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARR AY); } // Render the shape (Buat tembok belakang) public void draw_tembok_blk(GL10 gl) { gl.glFrontFace(GL10.GL_CCW); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRA Y); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuffer); // tembok gl.glPushMatrix(); gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[7]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); gl.glPopMatrix();

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARR AY); } // Render the shape (Buat tembok samping) public void draw_tembok_smp(GL10 gl) { gl.glEnable(GL10.GL_TEXTURE_2D); gl.glFrontFace(GL10.GL_CCW);

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRA Y); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuffer);

521

// tembok gl.glPushMatrix(); gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[8]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); gl.glPopMatrix();

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARR AY); gl.glDisable(GL10.GL_TEXTURE_2D); } // Render the shape (Buat atap) public void draw_atap(GL10 gl) { gl.glFrontFace(GL10.GL_CCW); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRA Y); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer); gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuffer); // tembok gl.glPushMatrix(); gl.glTranslatef(0f, 0f, cubeHalfSize); gl.glBindTexture(GL10.GL_TEXTURE_2D, textureIDs[14]); gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, 4); gl.glPopMatrix();

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARR AY); } // Load images into 6 GL textures public void loadTexture(GL10 gl, Context c) { gl.glGenTextures(15, textureIDs, 0); // Generate texture-ID array for 6 // IDs // Generate OpenGL texture images for (int face = 0; face < numFaces; face++) { gl.glBindTexture(GL10.GL_TEXTURE_2D, tex-

522

tureIDs[face]); // Build Texture from loaded bitmap for the currently-bind texture // ID

gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR); gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR); GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap[face], 0); bitmap[face].recycle(); } } }

TextureRegion.java

package com.ligthing; class TextureRegion { //--Members--// public float u1, v1; // Top/Left U,V Coordinates public float u2, v2; // Bottom/Right U,V Coordinates //--Constructor--// // D: calculate U,V coordinates from specified texture coordinates // A: texWidth, texHeight - the width and height of the texture the region is for // x, y - the top/left (x,y) of the region on the texture (in pixels) // width, height - the width and height of the region on the texture (in pixels) public TextureRegion(float texWidth, float texHeight, float x, float y, float width, float height) { this.u1 = x / texWidth; // Calculate U1 this.v1 = y / texHeight; 523

// Calculate V1 this.u2 = this.u1 + ( width / texWidth ); // Calculate U2 this.v2 = this.v1 + ( height / texHeight ); // Calculate V2 } }

TransObject.java package com.ligthing; import import import import import

java.nio.ByteBuffer; java.nio.ByteOrder; java.nio.FloatBuffer; javax.microedition.khronos.opengles.GL10; android.opengl.GLES20;

public class TransObject { private float vertices[] = { -0.5f, -0.5f, 0.0f, first vertex (x,y,z) -0.5f, 0.5f, 0.0f, V2 0.5f, 0.5f, 0.0f, V3 0.5f, -0.5f, 0.0f, -0.5f, -0.5f, 0.0f V5 };

// V1 // // // V4

private float vertices_color[] = { 1.0f, 0.0f, 0.0f, 1.0f, CV1 - first color (red,green,blue) 0.0f, 1.0f, 0.0f, 1.0f, CV2 0.0f, 0.0f, 1.0f, 1.0f, CV3 0.0f, 1.0f, 0.0f, 1.0f, CV4 1.0f, 0.0f, 0.0f, 1.0f // CV5 }; // list vertices kubus private float vertices_kubus[]= { 0.0f,0.0f,1.0f, 1.0f,0.0f,1.0f, 0.0f,1.0f,1.0f, 1.0f,1.0f,1.0f, 0.0f,0.0f,0.0f, 1.0f,0.0f,0.0f,

524

//

// // // //

0.0f,1.0f,0.0f, 1.0f,1.0f,0.0f }; // list color (kombinasi angka nol dan satu) private float colors_kubus[] = { 0.0f,0.0f,0.0f,1.0f, 1.0f,0.0f,0.0f,1.0f, 1.0f,1.0f,0.0f,1.0f, 0.0f,1.0f,0.0f,1.0f, 0.0f,0.0f,1.0f,1.0f, 1.0f,0.0f,1.0f,1.0f, 1.0f,1.0f,1.0f,1.0f, 0.0f,1.0f,1.0f,1.0f }; private byte[] indices_kubus = { 0,1,3, // depan 1 3,2,0, // depan 2 4,5,7, // belakang 1 7,6,4, // belakang 2 2,3,7, // atas 1 7,6,2, // atas 2 0,1,5, // bawah 1 5,4,0, // bawah 2 1,5,7, // kanan 1 7,3,1, // kanan 2 0,4,6, // kiri 1 6,4,0, // kiri 2 0,2,6, // kiri 3 6,2,0 // kiri 4 }; private byte[] indices_kubus2 = { // Vertex indices of the 6 kotak 0,1,3, // depan 1 3,2,0, // depan 2 4,5,7, // belakang 1 7,6,4, // belakang 2 2,3,7, // atas 1 7,6,2, // atas 2 0,1,5, // bawah 1 5,4,0, // bawah 2 1,5,7, // kanan 1 7,3,1, // kanan 2 0,4,6, // kiri 1 6,2,0, // kiri 3

525

4,6,2, 2,0,4

}; private ByteBuffer mIndexBuffer; // Buffer for index-array private float vertices_circle[]={0.0f,0.0f,0.0f}; private float vertices_circle_color[]={0.0f,0.0f,0.0f,0.5f}; private float vertices_line[]={0.0f,0.0f,0.0f}; private float vertices_line_color[]={0.0f,0.0f,0.0f,1.0f}; private int batas_sudut=360; float jari_jari; float a,b; float x,y; float step=3.0f,step_line=0.2f; float x1,y1; float x2,y2; private int loop,loop_color,loop_line,loop_line_color; public TransObject() { // ============ start to generate vertices to circle ========================== //Inisialisasi jari_jari=1.0f; // Titik Pusat a = 0.0f; b = 0.0f ; x=a+jari_jari; y=b; loop=3; loop_color=4; vertices_circle=new float[(int)(3*batas_sudut/step)*3]; vertices_circle_color=new float[(int)(3*batas_sudut/step)*4]; for(float teta=0;teta