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’ C B A’ C’ 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, GLd- ouble c_x, GLdouble c_y, GLdouble c_z, GLdouble u_x, GLd- ouble u_y, GLdouble u_z) – e_x, e_y, and e_z menentukan sudut pandang yang di- inginkan (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 ter- letak 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 ber- dasarkan 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 pan- dang objek /center (lookAt) dan vektor atas (UpVector).

Synthetic Camera di OpenGL : gluLookAt(eye_x, eye_y, eye_z, cen- ter_x, center_y, center_z, up_x, up_y, up_z )

 n adalah vektor dari VRP menuju lookAt. Lalu vektor n dinormal- isasi. 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 n _ init  la  r, unitvektor n _ init adalah(n)  n _ init v _ init v _ init  up up n*n, unitvektor v _ init adalah(v)  v _ init u  v x n

 Memindahkan titik koordinat dunia P(Px,Py,Pz) ke koordinat ka- mera 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 uv u z  r uPx Qv v v v  r  vPy     x y z   Qn nx n y nz  r  nPz      1   0 0 0 1 1 

304

Setelah titik Q diketahui, maka langkah berikutnya adalah melakukan proyeksi perspektif terhadap titik Q, sehingga di- peroleh titik T(u*, v*). Proyeksi Q ke T dapat diperoleh dengan menggunakan rumus berikut: Q Q u*  u ,v*  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: (se- bagai informasi tentang vertex dan permukaan objek) Vertex X Y Z 0 0.0 -1.0 0.0 1 1.0 -1.0 0.0 2 1.0 -1.0 1.0 3 0.0 -1.0 1.0 4 0.5 0.5 0.5

Surface Index 0 1 4 1 2 4 2 3 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 syn- thetic camera apabila en=6.

305

Jawab: Mencari sistem koordinat UVN: n _ init  la  r  (0,0,0)  (2,3,1)  (2,3,1) n _ init (2,3,1)   2  3 1  n     , ,   (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 _ init (0.42,0.36,0.23) (0.42,0.36,0.23) (0.42,0.36,0.23) v     | v _ init | (0.42)2  (0.36)2  (0.23)2 0.18  0.13  0.05 0.36  (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 t =p-r t =p-r t =p-r X Y Z 0 0-2=-2 -1-3=-4 0-1=-1 1 -1 -4 -1 2 -1 -4 0 3 -2 -4 0 4 -1.5 -2.5 -0.5

Q =t•u Q =t•v Q =t•n u v n 0 -0.62 4.53 0.46 -1.32 4 -0.42 -1.7 3.73 -0.88 -1 4.26 -0.23 -0.26 2.93

Gambar synthetic camera dari vertex hasil transformasi perspek- tif (u*,v*):

306

Vertex u* v* 0 0 -2.53 1 1.38 -3.96 2 -1.11 -4.49 3 -3.03 -3.45 4 -0.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 ber- beda 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 TransPiramidaOb- ject(); }

@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 parame- ters CurrentAngle += AnimateStep; if (CurrentAngle > 360.0) { //CurrentAngle -= 360.0*Math.floor(CurrentAngle/360.0); CurrentAngle=0.0f; CurrentAngle += Ani- mateStep; } }

}

@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 as- pect 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); // Ena- bles 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); // Ena- ble 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 android.content.Context; import android.opengl.GLSurfaceView; import android.util.Log; import android.view.KeyEvent; import 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 GLSur- faceView 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)); esRen- der.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: // In- crease rightward speed Log.v("Test Action KEYCODE_DPAD_RIGHT", "action working"); Log.i("Test Action Nilai", ""+Math.abs(esRender.getAnimateStep())); esRen- der.setAnimateStep(esRender.getAnimateStep()+8.0f); requestRender(); //ballSpeedX++; break; case KeyEvent.KEYCODE_DPAD_LEFT: // In- crease leftward speed esRen- der.setAnimateStep(esRender.getAnimateStep()-8.0f); requestRender(); //ballSpeedX--; break; case KeyEvent.KEYCODE_DPAD_UP: // In- crease upward speed //ballSpeedY--; break; case KeyEvent.KEYCODE_DPAD_DOWN: // In- crease 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())); esRen- der.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())); esRen- der.setAnimateStep(esRender.getAnimateStep()-8.0f); requestRender(); //if (ballRadius > 20) { // Mini- mum radius // ballRadius *= 0.95; // De- crease radius by 5% //} break; } return true; // Event handled } }

MainActivity.java package com.camera_n_viewing_project; import android.opengl.GLSurfaceView; import android.os.Bundle; import android.app.Activity; import android.view.Menu; import android.view.Window; import android.view.WindowManager; public class MainActivity extends Activity {

/** The OpenGL view */

313

private GLSurfaceView glSurfaceView;

@Override protected void onCreate(Bundle savedInstanceS- tate) { super.onCreate(savedInstanceState); //setContentView(R.layout.activity_main);

// requesting to turn the title OFF requestWindowFeature(Window.FEATURE_NO_TITLE); // making it full screen getWin- dow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREE N, WindowManag- er.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. left- bottom-back 1.0f, -1.0f, -1.0f, // 1. right- bottom-back 1.0f, -1.0f, 1.0f, // 2. right- bottom-front -1.0f, -1.0f, 1.0f, // 3. left- bottom-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 = ByteBuff- er.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 = ByteBuff- er.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, in- dices.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 pipeline bertemu seperti diilustrasikan pada Gambar 5.2. Raster- isasi 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 ob- jek. 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 tex- ture dua dimensi [height][width]. Setiap pixel yang disebut dengan texel adalah terletak pada koordinat (s,t). Nilai s dan t bi- asanya 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*() un- tuk 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*() un- tuk 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*() un- tuk 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*() un- tuk 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 android.content.Context; import android.opengl.GLES20; import android.opengl.GLSurfaceView; import android.opengl.Matrix; import android.opengl.GLSurfaceView.Renderer; import android.opengl.GLU; import android.util.Log; import android.widget.TextView;

public class ESRender implements Renderer {

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

321

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 radius = 50.0f; // Ball's radius float x = radius; // Ball's center (x,y) float y = radius; float speedX = 5f; // Ball's speed (x,y) float 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 parame- ters 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 clear- value to farthest gl.glEnable(GL10.GL_DEPTH_TEST); // Ena- bles 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); // Ena- ble 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 + pad- ding), creates the texture // NOTE: after a successful call to this the font is ready for rendering! glText.load( "-Regular.ttf", 14, 2, 2 ); // Create Font (Height: 14 Pixels / X+Y Padding 2 Pixels)

323

//gl.glDisable(GL10.GL_DITHER); // Disa- ble dithering for better // performance

// Setup Texture, each time the surface is created (NEW) objectball_hole.loadBallTexture(gl, con- text,0); objectball1.loadBallTexture(gl, context,1);

objectball2.loadBallTexture(gl, context,0); objectball3.loadBallTexture(gl, context,1); gl.glEnable(GL10.GL_TEXTURE_2D); // Ena- ble 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); // Se- lect 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 < esRen- der.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 android.content.Context; import android.opengl.GLSurfaceView; import android.util.Log; import android.view.KeyEvent; import 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 GLSur- faceView 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 posi- tion changed.

float currentX = v.getX(); float currentY = v.getY(); float deltaX, deltaY;

//float scalingFactor = 0.50f / ((esRen- der.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()+ (del- taX/getWidth()));

//esRender.setspeedY(esRender.getspeedY()+ (del- taY/getHeight()));

esRen- der.setspeedX(esRender.getspeedX()+ deltaX/100);

327

esRen- 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) ){ esRen- der.setspeedX(esRender.getspeedX()- 0.05f); } if((esRender.getspeedX()- 0.05f <0) ){ esRender.setspeedX(0.0f); } if((esRender.getspeedY()- 0.05f >=0)){ esRen- der.setspeedY(esRender.getspeedY()- 0.05f); } if((esRender.getspeedY()- 0.05f <0) ){ esRender.setspeedY(0.0f); } Log.v("Test Action KEYCODE_A", "action working"); break; case KeyEvent.KEYCODE_Z: Log.v("Test Action KEYCODE_Z", "action working"); break; } return true; // Event handled } }

328

MainActivity.java

package com.texture_mapping;

import com.texture_mapping.R;

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

public class MainActivity extends Activity {

/** The OpenGL view */ private GLSurfaceView glSurfaceView;

@Override protected void onCreate(Bundle savedInstanceS- tate) { super.onCreate(savedInstanceState); //setContentView(R.layout.activity_main);

// requesting to turn the title OFF requestWindowFeature(Window.FEATURE_NO_TITLE); // making it full screen getWin- dow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCR EEN, WindowManag- er.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 */

329

@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; }

}

ObjectBall.java

package com.texture_mapping;

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 ja- vax.microedition.khronos.opengles.GL11ExtensionPack;

import com.texture_mapping.R;

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

public class ObjectBall {

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 -0.5f, -0.5f, 0.0f // V5

330

};

private float textCoord_Triagle[]={ 1.0f, 1.0f, 0.0f, // V3 0.0f, 1.0f, 0.0f, // V2 0.5f, 0.0f, 0.0f, // V1 - first vertex (x,y,z) };

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) };

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 };

private float vertices_circle[]={0.0f,0.0f,0.0f}; private float verti- ces_circle_color[]={0.0f,0.0f,0.0f,0.5f}; private float textCoord[],textCoord_hole[]; private float verti- ces_circle1[],vertices_circle1_hole[];

private int[] imageFileIDs = { // Image file IDs R.drawable.nature, R.drawable.mule};

int[] textures_indek = new int[1];

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; float teta, teta_hole; private int loop,loop_color;

public ObjectBall() {

331

// ======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; teta_hole=0; textCoord = new float[batas_sudut * 3]; textCoord_hole = new float[batas_sudut * 3]; for (int ii = 0; ii < batas_sudut * 3; ii += 3) { // membentuk textCoord untuk cir- cle color 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;

// membentuk textCoord untuk cir- cle hole textCoord_hole[ii] = (jari_jari*((float) Math.cos(-teta_hole)))+a; textCoord_hole[ii + 1] = (jari_jari*((float) Math.sin(-teta_hole)))+b; textCoord_hole[ii + 2] = 0.0f;

teta_hole += 15; }

// ======start to generate verti- ces to circle (Cara 1) ======//Inisialisasi jari_jari=50.0f;

// Titik Pusat a = 50.0f; b = 50.0f ;

teta=0; teta_hole=0; vertices_circle1 = new float[batas_sudut * 3]; vertices_circle1_hole = 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;

332

vertices_circle1[ii + 2] = 0.0f;

teta += Math.PI / 90;

// membentuk vertices_circle1 vertices_circle1_hole[ii] = (jari_jari*((float) Math.cos(teta_hole)))+a; vertices_circle1_hole[ii + 1] = (jari_jari*((float) Math.sin(teta_hole)))+b; vertices_circle1_hole[ii + 2] = 0.0f; teta_hole += 15; }

// ======start to generate verti- ces 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<=2*batas_sudut;teta+=step){ vertices_circle[loop] = (float) ((x- a)*Math.cos((teta/180)*(22/7)) - ((y- b)*Math.sin((teta/180)*(22/7))) + a); vertices_circle[loop+1] = (float) ((x- a)*Math.sin((teta/180)*(22/7)) - ((y- b)*Math.cos((teta/180)*(22/7))) + b); vertices_circle[loop+2]=0; loop+=3;

//mengenerate warna untuk setiap vertex

//vertices_circle_color[loop_color]=(float) ((x- a)*Math.cos((teta/180)*(22/7)) - ((y- b)*Math.sin((teta/180)*(22/7))) + a);

//vertices_circle_color[loop_color+1]=(float) ((x-a)*Math.sin((teta/180)*(22/7)) - ((y- b)*Math.cos((teta/180)*(22/7))) + b);

vertices_circle_color[loop_color]=(float) (Math.cos((teta/180)*(22/7)) ); verti- ces_circle_color[loop_color+1]=(float) (Math.sin((teta/180)*(22/7)));

vertices_circle_color[loop_color+2]=0.5f; vertices_circle_color[loop_color+3]=0.5f;

333

loop_color+=4; } // ======end for generate vertices to circle ======

}

// Point to our vertex buffer, return buffer holding the vertices public static FloatBuffer makeFloatBuffer(float[] arr){ ByteBuffer bb = ByteBuff- er.allocateDirect(arr.length * 4); bb.order(ByteOrder.nativeOrder()); FloatBuffer fb = bb.asFloatBuffer(); fb.put(arr); fb.position(0); return fb; }

// Setup index-array buffer. Indices in byte. public static ByteBuffer makeByteBuffer(byte[] arr){ ByteBuffer bb = ByteBuff- er.allocateDirect(arr.length); bb.put(arr); bb.position(0); return bb; }

/** The draw method for the primitive object with the GL context */ public void draw_circle(GL10 gl) {

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

// set the colour for the object circle //gl.glColor4f(0.0f, 0.0f, 1.0f, 1.0f);

//create VBO from buffer with glBuffer- Data() gl.glVertexPointer(3, GL10.GL_FLOAT, 0, make- FloatBuffer(vertices_circle));

//memetakan warna untuk setiap vertex gl.glColorPointer(4, GL10.GL_FLOAT, 0, make- FloatBuffer(vertices_circle_color));

//draw circle as filled shape //gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 1, (int) ((int) 2*batas_sudut/step));

//draw circle contours //gl.glDrawArrays(GL10.GL_LINES, 1, (int) ((int) 2*batas_sudut/step)); // membuat garis putus- putus pada tepi lingkaran

334

//gl.glDrawArrays(GL10.GL_LINES, 1, (int) ((int) 2*batas_sudut/step)); gl.glDrawArrays(GL10.GL_LINE_STRIP, 1, (int) ((int) 2*batas_sudut/step)); //gl.glDrawArrays(GL10.GL_POINTS, 1, (int) ((int) 2*batas_sudut/step));

//Disable the client state before leaving

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

gl.glDisableClientState(GL10.GL_COLOR_ARRAY); }

public void draw_circle_hole(GL10 gl) {

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

//create VBO from buffer with glBuffer- Data() gl.glVertexPointer(3, GL10.GL_FLOAT, 0, make- FloatBuffer(vertices_circle1_hole));

//menempelkan tekstur ke objek gl.glEnable(GL10.GL_TEXTURE_2D);

gl.glEnable(GL10.GL_BLEND); gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);

gl.glBindTexture(GL10.GL_TEXTURE_2D, tex- tures_indek[0]); // gl.glTexCoordPointer(3, GL10.GL_FLOAT, 0, makeFloatBuffer(textCoord_hole)); //

gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRA Y);

gl.glDrawArrays(GL10.GL_LINE_STRIP, 0, ba- tas_sudut);

//draw circle contours //gl.glDrawArrays(GL10.GL_LINES, 1, (int) ((int) 2*batas_sudut/step)); // membuat garis putus- putus pada tepi lingkaran //gl.glDrawArrays(GL10.GL_LINE_STRIP, 1, (int) ((int) 2*batas_sudut/step));

//Disable the client state before leaving

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisable( GL10.GL_BLEND ); // Disable Alpha Blend gl.glDisable( GL10.GL_TEXTURE_2D ); // Disable Texture Mapping }

public void draw_circle_color(GL10 gl) {

335

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

//create VBO from buffer with glBuffer- Data() gl.glVertexPointer(3, GL10.GL_FLOAT, 0, make- FloatBuffer(vertices_circle1));

//menempelkan tekstur ke objek gl.glEnable(GL10.GL_TEXTURE_2D);

gl.glEnable(GL10.GL_BLEND); gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);

gl.glBindTexture(GL10.GL_TEXTURE_2D, tex- tures_indek[0]); // gl.glTexCoordPointer(3, GL10.GL_FLOAT, 0, makeFloatBuffer(textCoord)); //

gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRA Y);

gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, ba- tas_sudut);

//draw circle contours //gl.glDrawArrays(GL10.GL_LINES, 1, (int) ((int) 2*batas_sudut/step)); // membuat garis putus- putus pada tepi lingkaran //gl.glDrawArrays(GL10.GL_LINE_STRIP, 1, (int) ((int) 2*batas_sudut/step));

//Disable the client state before leaving

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisable( GL10.GL_BLEND ); // Disable Alpha Blend gl.glDisable( GL10.GL_TEXTURE_2D ); // Disable Texture Mapping }

public void draw_kotak(GL10 gl) {

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

// 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);

336

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);

}

public void draw_segitiga(GL10 gl) { gl.glFrontFace(GL10.GL_CCW); // Front face in counter-clockwise

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

//gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

// set the colour for the triangle //gl.glColor4f(1.0f, 0.0f, 0.0f, 1.0f);

gl.glVertexPointer(3, GL10.GL_FLOAT, 0, makeFloatBuffer(new float [] {

1.0f, 1.0f, 0.0f, // V3 0.0f, 1.0f, 0.0f, // V2 0.5f, 0.0f, 0.0f, // V1 - first vertex (x,y,z) }));

// Draw the vertices as triangle //gl.glColorPointer(4, GL10.GL_FLOAT, 0, makeFloatBuffer(vertices_color));

//menempelkan tekstur ke objek gl.glEnable(GL10.GL_TEXTURE_2D);

gl.glEnable(GL10.GL_BLEND); gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);

gl.glBindTexture(GL10.GL_TEXTURE_2D, tex- tures_indek[0]); // gl.glTexCoordPointer(3, GL10.GL_FLOAT, 0, makeFloatBuffer(textCoord_Triagle)); //

gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRA Y);

gl.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 3); //Disable the client state before leaving

337

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

//gl.glDisableClientState(GL10.GL_COLOR_ARRAY); gl.glDisable( GL10.GL_BLEND ); // Disable Alpha Blend gl.glDisable( GL10.GL_TEXTURE_2D ); // Disable Texture Mapping

} public void loadBallTexture(GL10 gl, Context con- text,int index_Texture) { // Bitmap bitmap = BitmapFacto- ry.decodeResource(context.getResources(), // resource);

/*Bitmap bitmap = BitmapFacto- ry.decodeStream(context.getResources()

.openRawResource(R.drawable.nature));*/

Bitmap bitmap = BitmapFacto- ry.decodeStream(context.getResources()

.openRawResource(imageFileIDs[index_Texture]));

gl.glGenTextures(1, textures_indek, 0); gl.glBindTexture(GL10.GL_TEXTURE_2D, tex- tures_indek[0]);

//gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE ); //gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE );

gl.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); gl.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);

GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);

bitmap.recycle(); } }

338

Gambar 5.8 Texture Mapping Pada Segitiga 5.5 Texture Mapping Pada Lingkaran

Source Code 5.2 Code Texture Mapping Pada Lingkaran

ESRender.java

package com.texture_mapping;

import java.util.Formatter;

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

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

public class ESRender implements Renderer {

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

339

Context context;

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 radius = 50.0f; // Ball's radius float x = radius; // Ball's center (x,y) float y = radius; float speedX = 5f; // Ball's speed (x,y) float 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);

// menampilkan lingkaran only line with texture gl.glPushMatrix(); //gl.glScalef(150.0f, 150.0f, 150.0f); gl.glTranslatef(0.0f, 100.0f, 0.0f); gl.glLineWidth(1.0f); gl.glEnable(GL10.GL_LINE_SMOOTH); object- ball_hole.draw_circle_hole(gl); gl.glPopMatrix();

// menampilkan lingkaran dengan gradasi warna

340

gl.glPushMatrix();

gl.glLineWidth(1.0f); gl.glEnable(GL10.GL_LINE_SMOOTH); //bounds.set(x - radius, y - radi- us, x + radius, y + radius); gl.glTranslatef(x, y, 0.0f); //gl.glScalef(10.0f,10.0f,10.0f); //gl.glTranslatef(0.0f, 0.0f, - 5.0f); objectball2.draw_circle_color(gl); gl.glPopMatrix();

// menampilkan lingkaran dengan gradasi warna gl.glPushMatrix();

gl.glLineWidth(1.0f); gl.glEnable(GL10.GL_LINE_SMOOTH); //bounds.set(x - radius, y - radi- us, x + radius, y + radius); gl.glTranslatef(0, 200, 0.0f); //gl.glScalef(10.0f,10.0f,10.0f); //gl.glTranslatef(0.0f, 0.0f, - 5.0f); objectball3.draw_circle_color(gl); gl.glPopMatrix();

//render text gl.glPushMatrix(); // enable texture + alpha blending // NOTE: this is required for text rendering! we could incorporate it into // the GLText class, but then it would be called multiple times (which impacts perfor- mance). gl.glEnable( GL10.GL_TEXTURE_2D ); // Enable Texture Mapping gl.glEnable( GL10.GL_BLEND ); // Enable Alpha Blend gl.glBlendFunc( GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA ); // Set Alpha Blend Function

//Log.d(TAG, "Frames per second: " + fps + " (" + numFrames // + " frames in " + fpsE- lapsed + " ms)");

//}

glText.begin(1.0f, 1.0f, 1.0f, 1.0f); // Begin Text Rendering (Set Color WHITE) //glText.draw( "Posisi Bola : ("+ x + ","+y+")",150, 10); // Draw Test String

341

// Keep track of number of frames drawn numFrames++; long fpsElapsed = Sys- tem.currentTimeMillis() - fpsStartTime; //if (fpsElapsed > 1 * 1000) { // every 5 seconds float fps = (numFrames * 1000.0F) / fpsElapsed; // glText.draw( "Frames per second : "+ fps + " (" + numFrames + " frames in " + fpsElapsed + " ms)",150, 30); // Draw Test String fpsStartTime = Sys- tem.currentTimeMillis(); numFrames = 0; //}

glText.end(); // End Text Rendering

// disable texture + alpha gl.glDisable( GL10.GL_BLEND ); // Disable Alpha Blend gl.glDisable( GL10.GL_TEXTURE_2D ); // Disable Texture Mapping gl.glPopMatrix();

// // 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.glRotatef(mAngle, 0.0f, 1.0f, 0.0f); // gl.glTranslatef(-0.5f, -0.5f, 0.0f); // objectball1.draw_segitiga(gl);

// gl.glPopMatrix();

// update moveWithCollisionDetection(this); set((int)-radius, (int)-radius, mywidth, myheight);

// Update the rotational angle after each refresh if (RunMode==1) { // re-Calculate animation parame- ters mAngle += AnimateStep;

342

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 clear- value to farthest gl.glEnable(GL10.GL_DEPTH_TEST); // Ena- bles 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); // Ena- ble 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 + pad- ding), 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); // Disa- ble dithering for better // performance

// Setup Texture, each time the surface is created (NEW) objectball_hole.loadBallTexture(gl, con- text,0); objectball1.loadBallTexture(gl, context,1);

objectball2.loadBallTexture(gl, context,0); objectball3.loadBallTexture(gl, context,1); gl.glEnable(GL10.GL_TEXTURE_2D); // Ena-

343

ble 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;

mywidth=width; myheight=height;

// Set the viewport (display area) to cover the entire window gl.glViewport(0, 0, width, height);

// Setup perspective projection, with as- pect ratio matches viewport gl.glMatrixMode(GL10.GL_PROJECTION); // Select projection matrix gl.glLoadIdentity(); // Reset projection matrix

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); // Se- lect model-view matrix gl.glLoadIdentity(); // Reset

}

344

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 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;

345

y = esRender.getyMax() - radius; } else if (y - radius < esRen- der.getyMin()) { speedY = -speedY; y = esRender.getyMin() + radius; } }

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 android.content.Context; import android.opengl.GLSurfaceView; import android.util.Log; import android.view.KeyEvent; import 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 GLSur- faceView esRender = new ESRender(context); setRenderer(esRender);

// To enable keypad this.setFocusable(true); this.requestFocus();

346

// 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 posi- tion changed.

float currentX = v.getX(); float currentY = v.getY(); float deltaX, deltaY;

//float scalingFactor = 0.50f / ((esRen- der.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()+ (del-

347

taX/getWidth()));

//esRender.setspeedY(esRender.getspeedY()+ (del- taY/getHeight()));

esRen- der.setspeedX(esRender.getspeedX()+ deltaX/100); esRen- 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) ){ esRen- der.setspeedX(esRender.getspeedX()- 0.05f); } if((esRender.getspeedX()- 0.05f <0) ){ esRender.setspeedX(0.0f); } if((esRender.getspeedY()- 0.05f >=0)){ esRen- der.setspeedY(esRender.getspeedY()- 0.05f); } if((esRender.getspeedY()- 0.05f <0) ){ esRender.setspeedY(0.0f); } Log.v("Test Action KEYCODE_A", "action working"); break; case KeyEvent.KEYCODE_Z: Log.v("Test Action KEYCODE_Z", "action working"); break; } return true; // Event handled } }

348

MainActivity.java

package com.texture_mapping;

import com.texture_mapping.R;

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

public class MainActivity extends Activity {

/** The OpenGL view */ private GLSurfaceView glSurfaceView;

@Override protected void onCreate(Bundle savedInstanceS- tate) { super.onCreate(savedInstanceState); //setContentView(R.layout.activity_main);

// requesting to turn the title OFF requestWindowFeature(Window.FEATURE_NO_TITLE); // making it full screen getWin- dow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCR EEN, WindowManag- er.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 */

349

@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; }

}

ObjectBall.java

package com.texture_mapping;

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 ja- vax.microedition.khronos.opengles.GL11ExtensionPack;

import com.texture_mapping.R;

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

public class ObjectBall {

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 -0.5f, -0.5f, 0.0f // V5 };

350

private float textCoord_Triagle[]={ 1.0f, 1.0f, 0.0f, // V3 0.0f, 1.0f, 0.0f, // V2 0.5f, 0.0f, 0.0f, // V1 - first vertex (x,y,z) };

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) };

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 };

private float vertices_circle[]={0.0f,0.0f,0.0f}; private float verti- ces_circle_color[]={0.0f,0.0f,0.0f,0.5f}; private float textCoord[],textCoord_hole[]; private float verti- ces_circle1[],vertices_circle1_hole[];

private int[] imageFileIDs = { // Image file IDs R.drawable.nature, R.drawable.mule};

int[] textures_indek = new int[1];

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; float teta, teta_hole; private int loop,loop_color;

public ObjectBall() {

// ======start to generate stetch

351

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; teta_hole=0; textCoord = new float[batas_sudut * 3]; textCoord_hole = new float[batas_sudut * 3]; for (int ii = 0; ii < batas_sudut * 3; ii += 3) { // membentuk textCoord untuk cir- cle color 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;

// membentuk textCoord untuk cir- cle hole textCoord_hole[ii] = (jari_jari*((float) Math.cos(-teta_hole)))+a; textCoord_hole[ii + 1] = (jari_jari*((float) Math.sin(-teta_hole)))+b; textCoord_hole[ii + 2] = 0.0f;

teta_hole += 15; }

// ======start to generate verti- ces to circle (Cara 1) ======//Inisialisasi jari_jari=50.0f;

// Titik Pusat a = 50.0f; b = 50.0f ;

teta=0; teta_hole=0; vertices_circle1 = new float[batas_sudut * 3]; vertices_circle1_hole = 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;

352

teta += Math.PI / 90;

// membentuk vertices_circle1 vertices_circle1_hole[ii] = (jari_jari*((float) Math.cos(teta_hole)))+a; vertices_circle1_hole[ii + 1] = (jari_jari*((float) Math.sin(teta_hole)))+b; vertices_circle1_hole[ii + 2] = 0.0f; teta_hole += 15; }

// ======start to generate verti- ces 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<=2*batas_sudut;teta+=step){ vertices_circle[loop] = (float) ((x- a)*Math.cos((teta/180)*(22/7)) - ((y- b)*Math.sin((teta/180)*(22/7))) + a); vertices_circle[loop+1] = (float) ((x- a)*Math.sin((teta/180)*(22/7)) - ((y- b)*Math.cos((teta/180)*(22/7))) + b); vertices_circle[loop+2]=0; loop+=3;

//mengenerate warna untuk setiap vertex

//vertices_circle_color[loop_color]=(float) ((x- a)*Math.cos((teta/180)*(22/7)) - ((y- b)*Math.sin((teta/180)*(22/7))) + a);

//vertices_circle_color[loop_color+1]=(float) ((x-a)*Math.sin((teta/180)*(22/7)) - ((y- b)*Math.cos((teta/180)*(22/7))) + b);

vertices_circle_color[loop_color]=(float) (Math.cos((teta/180)*(22/7)) ); verti- ces_circle_color[loop_color+1]=(float) (Math.sin((teta/180)*(22/7)));

vertices_circle_color[loop_color+2]=0.5f; vertices_circle_color[loop_color+3]=0.5f; loop_color+=4; }

353

// ======end for generate vertices to circle ======

}

// Point to our vertex buffer, return buffer holding the vertices public static FloatBuffer makeFloatBuffer(float[] arr){ ByteBuffer bb = ByteBuff- er.allocateDirect(arr.length * 4); bb.order(ByteOrder.nativeOrder()); FloatBuffer fb = bb.asFloatBuffer(); fb.put(arr); fb.position(0); return fb; }

// Setup index-array buffer. Indices in byte. public static ByteBuffer makeByteBuffer(byte[] arr){ ByteBuffer bb = ByteBuff- er.allocateDirect(arr.length); bb.put(arr); bb.position(0); return bb; }

/** The draw method for the primitive object with the GL context */ public void draw_circle(GL10 gl) {

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

// set the colour for the object circle //gl.glColor4f(0.0f, 0.0f, 1.0f, 1.0f);

//create VBO from buffer with glBuffer- Data() gl.glVertexPointer(3, GL10.GL_FLOAT, 0, make- FloatBuffer(vertices_circle));

//memetakan warna untuk setiap vertex gl.glColorPointer(4, GL10.GL_FLOAT, 0, make- FloatBuffer(vertices_circle_color));

//draw circle as filled shape //gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 1, (int) ((int) 2*batas_sudut/step));

//draw circle contours //gl.glDrawArrays(GL10.GL_LINES, 1, (int) ((int) 2*batas_sudut/step)); // membuat garis putus- putus pada tepi lingkaran //gl.glDrawArrays(GL10.GL_LINES, 1, (int) ((int) 2*batas_sudut/step));

354

gl.glDrawArrays(GL10.GL_LINE_STRIP, 1, (int) ((int) 2*batas_sudut/step)); //gl.glDrawArrays(GL10.GL_POINTS, 1, (int) ((int) 2*batas_sudut/step));

//Disable the client state before leaving

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

gl.glDisableClientState(GL10.GL_COLOR_ARRAY); }

public void draw_circle_hole(GL10 gl) {

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

//create VBO from buffer with glBuffer- Data() gl.glVertexPointer(3, GL10.GL_FLOAT, 0, make- FloatBuffer(vertices_circle1_hole));

//menempelkan tekstur ke objek gl.glEnable(GL10.GL_TEXTURE_2D);

gl.glEnable(GL10.GL_BLEND); gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);

gl.glBindTexture(GL10.GL_TEXTURE_2D, tex- tures_indek[0]); // gl.glTexCoordPointer(3, GL10.GL_FLOAT, 0, makeFloatBuffer(textCoord_hole)); //

gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRA Y);

gl.glDrawArrays(GL10.GL_LINE_STRIP, 0, ba- tas_sudut);

//draw circle contours //gl.glDrawArrays(GL10.GL_LINES, 1, (int) ((int) 2*batas_sudut/step)); // membuat garis putus- putus pada tepi lingkaran //gl.glDrawArrays(GL10.GL_LINE_STRIP, 1, (int) ((int) 2*batas_sudut/step));

//Disable the client state before leaving

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisable( GL10.GL_BLEND ); // Disable Alpha Blend gl.glDisable( GL10.GL_TEXTURE_2D ); // Disable Texture Mapping }

public void draw_circle_color(GL10 gl) {

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

355

//create VBO from buffer with glBuffer- Data() gl.glVertexPointer(3, GL10.GL_FLOAT, 0, make- FloatBuffer(vertices_circle1));

//menempelkan tekstur ke objek gl.glEnable(GL10.GL_TEXTURE_2D);

gl.glEnable(GL10.GL_BLEND); gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);

gl.glBindTexture(GL10.GL_TEXTURE_2D, tex- tures_indek[0]); // gl.glTexCoordPointer(3, GL10.GL_FLOAT, 0, makeFloatBuffer(textCoord)); //

gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRA Y);

gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, ba- tas_sudut);

//draw circle contours //gl.glDrawArrays(GL10.GL_LINES, 1, (int) ((int) 2*batas_sudut/step)); // membuat garis putus- putus pada tepi lingkaran //gl.glDrawArrays(GL10.GL_LINE_STRIP, 1, (int) ((int) 2*batas_sudut/step));

//Disable the client state before leaving

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); gl.glDisable( GL10.GL_BLEND ); // Disable Alpha Blend gl.glDisable( GL10.GL_TEXTURE_2D ); // Disable Texture Mapping }

public void draw_kotak(GL10 gl) {

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

// 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));

356

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);

}

public void draw_segitiga(GL10 gl) { gl.glFrontFace(GL10.GL_CCW); // Front face in counter-clockwise

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

//gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

// set the colour for the triangle //gl.glColor4f(1.0f, 0.0f, 0.0f, 1.0f);

gl.glVertexPointer(3, GL10.GL_FLOAT, 0, makeFloatBuffer(new float [] {

1.0f, 1.0f, 0.0f, // V3 0.0f, 1.0f, 0.0f, // V2 0.5f, 0.0f, 0.0f, // V1 - first vertex (x,y,z)

}));

// Draw the vertices as triangle //gl.glColorPointer(4, GL10.GL_FLOAT, 0, makeFloatBuffer(vertices_color));

//menempelkan tekstur ke objek gl.glEnable(GL10.GL_TEXTURE_2D);

gl.glEnable(GL10.GL_BLEND); gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);

gl.glBindTexture(GL10.GL_TEXTURE_2D, tex- tures_indek[0]); // gl.glTexCoordPointer(3, GL10.GL_FLOAT, 0, makeFloatBuffer(textCoord_Triagle)); //

gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRA Y);

gl.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 3);

357

//Disable the client state before leaving

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

//gl.glDisableClientState(GL10.GL_COLOR_ARRAY); gl.glDisable( GL10.GL_BLEND ); // Disable Alpha Blend gl.glDisable( GL10.GL_TEXTURE_2D ); // Disable Texture Mapping

}

public void loadBallTexture(GL10 gl, Context con- text,int index_Texture) { // Bitmap bitmap = BitmapFacto- ry.decodeResource(context.getResources(), // resource);

/*Bitmap bitmap = BitmapFacto- ry.decodeStream(context.getResources()

.openRawResource(R.drawable.nature));*/

Bitmap bitmap = BitmapFacto- ry.decodeStream(context.getResources()

.openRawResource(imageFileIDs[index_Texture]));

gl.glGenTextures(1, textures_indek, 0); gl.glBindTexture(GL10.GL_TEXTURE_2D, tex- tures_indek[0]);

//gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE ); //gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE );

gl.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); gl.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);

GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);

bitmap.recycle(); } }

358

Gambar 5.9 Texture Mapping Pada Lingkaran 5.6 Texture Mapping Pada Kubus

Source Code 5.3 Code Texture Mapping Pada Kubus

ESRender.java

package com.wordpress.androidfreecode;

import java.io.IOException;

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

import android.content.Context; //import android.opengl.GLU; import android.opengl.GLSurfaceView.Renderer; import android.opengl.GLU;

public class ESRender implements Renderer {

private Context context; // Application context needed to read image (NEW) private TextureKubus kubus;

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

359

/** Constructor to set the handed over context */ public ESRender(Context context) { this.context = context; // Get the ap- plication context (NEW) kubus = new TextureKubus(); }

@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.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // set background dgn warna hitam

gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

// ----- Render the Kubus ----- gl.glPushMatrix(); gl.glTranslatef(0.0f, 0.9f, - 5.0f); //gl.glTranslatef(0.0f, 0.0f, - 6.0f); // Translate into the screen gl.glRotatef(CurrentAngle, 0.1f, 1.0f, 0.2f); // Rotate //gl.glRotatef(CurrentAngle, 1.0f, 1.0f, 1.0f ); gl.glTranslatef(-0.5f,-0.5f,- 0.5f); kubus.draw(gl); gl.glPopMatrix();

// Update the rotational angle after each refresh if (RunMode==1) { // re-Calculate animation parame- ters CurrentAngle += AnimateStep; if (CurrentAngle > 360.0) { //CurrentAngle -= 360.0*Math.floor(CurrentAngle/360.0); CurrentAngle=0.0f; CurrentAngle += Ani- mateStep; } }

}

@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;

360

// Set the viewport (display area) to cover the entire window gl.glViewport(0, 0, width, height);

// Setup perspective projection, with as- pect 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 gl.glClearDepthf(1.0f); // Set depth's clear-value to farthest gl.glEnable(GL10.GL_DEPTH_TEST); // Ena- bles 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); // Ena- ble smooth shading of color gl.glDisable(GL10.GL_DITHER); // Disable dithering for better // performance

// Setup Texture, each time the surface is created (NEW) kubus.loadTexture(gl, context); gl.glEnable(GL10.GL_TEXTURE_2D); // Ena- ble texture (NEW) }

public int getRunMode() { return RunMode; }

public void setRunMode(int mRunMode) {

361

RunMode = mRunMode; }

public float getAnimateStep() { return AnimateStep; }

public void setAnimateStep(float mAnimateStep) { AnimateStep = mAnimateStep; }

}

MainActivity.java

package com.wordpress.androidfreecode;

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

/** * Our OpenGL program's main activity */ public class MainActivity extends Activity { private GLSurfaceView glView; // Use GLSur- faceView // Call back when the activity is started, to in- itialize the view

@Override protected void onCreate(Bundle savedInstanceS- tate) { super.onCreate(savedInstanceState);

// requesting to turn the title OFF requestWindowFeature(Window.FEATURE_NO_TITLE); // making it full screen getWin- dow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCR EEN, WindowManag- er.LayoutParams.FLAG_FULLSCREEN);

glView = new GLSurfaceView(this); // Al- locate a GLSurfaceView glView.setRenderer(new ESRender(this)); // Use a custom renderer this.setContentView(glView); // This ac- tivity sets to GLSurfaceView }

362

// Call back when the activity is going into the background @Override protected void onPause() { super.onPause(); glView.onPause(); }

// Call back after onPause() @Override protected void onResume() { super.onResume(); glView.onResume(); }

}

TextureKubus.java

package com.wordpress.androidfreecode;

import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import javax.microedition.khronos.opengles.GL10;

import android.content.Context; import android.content.res.AssetManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import 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 TextureKubus { private FloatBuffer vertexBuffer; // Buffer for vertex-array private FloatBuffer texBuffer; // Buffer for tex- ture-coords-array (NEW) private float[] vertices = { // Vertices for a face -1.0f, -1.0f, 0.0f, // 0. left- bottom-front 1.0f, -1.0f, 0.0f, // 1. right-

363

bottom-front -1.0f, 1.0f, 0.0f, // 2. left-top- front 1.0f, 1.0f, 0.0f // 3. right-top- front }; 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 TextureKubus() { // Setup vertex-array buffer. Vertices in float. An float has 4 bytes ByteBuffer vbb = ByteBuff- er.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 vertexBuffer.position(0); // Rewind // Setup texture-coords-array buffer, in float. An float has 4 bytes // (NEW) ByteBuffer tbb = ByteBuff- er.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);

364

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();

// 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);

365

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, tex- tureIDs[0]); // Bind to texture

// ID // Set up texture filters 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);

// Construct an input stream to texture image "res\drawable\nature.png" //AssetManager assetManager = c.getAssets(); //InputStream istream = assetManag- er.open("nature.png"); InputStream istream = c.getResources().openRawResource(R.drawable.nature); Bitmap bitmap; try { // Read and decode input as bitmap bitmap = BitmapFacto- ry.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();

366

} }

Gambar 5.10 Texture Mapping Pada Kubus 5.7 Texture Mapping Pada Bola

Source Code 5.4 Code Texture Mapping Pada Bola

ESRender.java

package com.texture_mapping;

import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.content.Context; import android.opengl.GLSurfaceView; import android.opengl.GLSurfaceView.Renderer; import android.opengl.GLU;

public class ESRender implements Renderer {

/** Tilt the spheres a little. */ private static final int AXIAL_TILT_DEGRESS = 30;

/** Clear colour, alpha component. */ private static final float CLEAR_RED = 0.0f;

/** Clear colour, alpha component. */ private static final float CLEAR_GREEN = 0.0f;

/** Clear colour, alpha component. */ private static final float CLEAR_BLUE = 0.0f;

367

/** Clear colour, alpha component. */ private static final float CLEAR_ALPHA = 0.5f;

/** Perspective setup, field of view component. */ private static final float FOVY = 45.0f;

/** Perspective setup, near component. */ private static final float Z_NEAR = 0.1f;

/** Perspective setup, far component. */ private static final float Z_FAR = 100.0f;

/** Object distance on the screen. move it back a bit so we can see it! */ private static final float OBJECT_DISTANCE = - 15.0f;

/** The earth's sphere. */ private final MySphere mEarth;

/** The context. */ private final Context mContext;

/** The rotation angle, just to give the screen some action. */ private float mRotationAngle; /** * Constructor to set the handed over context. * @param context The context. */ public ESRender(final Context context) { this.mContext = context; //this.mEarth = new MySphere(3, 2); this.mEarth = new MySphere(5, 3); this.mRotationAngle = 0.0f; }

// Call back to draw the current frame. @Override public void onDrawFrame(GL10 gl) { // Clear color and depth buffers gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

gl.glLoadIdentity(); // ----- Render the Sphere ------gl.glPushMatrix(); gl.glTranslatef(0.0f, 0.0f, OBJECT_DISTANCE); gl.glRotatef(AXIAL_TILT_DEGRESS, 1, 0, 0); gl.glRotatef(this.mRotationAngle++, 0, 1, 0); this.mEarth.draw(gl); gl.glPopMatrix(); }

368

// Call back when the surface is first created or re-created. @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { this.mEarth.loadGLTexture(gl, this.mContext, R.drawable.earth); gl.glEnable(GL10.GL_TEXTURE_2D); gl.glShadeModel(GL10.GL_SMOOTH); gl.glClearColor(CLEAR_RED, CLEAR_GREEN, CLEAR_BLUE, CLEAR_ALPHA); gl.glClearDepthf(1.0f); gl.glEnable(GL10.GL_DEPTH_TEST); gl.glDepthFunc(GL10.GL_LEQUAL); gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST); }

// Call back after onSurfaceCreated() or whenever the window's size changes. @Override public void onSurfaceChanged(GL10 gl, int width, int height) {

final float aspectRatio = (float) width / (float) (height == 0 ? 1 : height);

// gl.glViewport(0, 0, width, height); //gl.glMatrixMode(GL10.GL_PROJECTION); // gl.glLoadIdentity();

/*if (height == 0) height = 1; // To prevent divide by zero float aspectRatio = (float) width / height;*/

// Set the viewport (display area) to cover the entire window gl.glViewport(0, 0, width, height);

// Setup perspective projection, with as- pect 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);

GLU.gluPerspective(gl, FOVY, aspectRatio, Z_NEAR, Z_FAR); gl.glMatrixMode(GL10.GL_MODELVIEW); //

369

Select model-view matrix gl.glLoadIdentity(); // Reset } }

MainActivity.java

package com.texture_mapping;

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

public class MainActivity extends Activity {

/** The OpenGL view. */ private GLSurfaceView glSurfaceView;

@Override protected void onCreate(final Bundle savedIn- stanceState) { super.onCreate(savedInstanceState);

this.requestWindowFeature(Window.FEATURE_NO_TITLE);

this.getWindow().setFlags(WindowManager.LayoutParams.F LAG_FULLSCREEN, WindowManag- er.LayoutParams.FLAG_FULLSCREEN); this.glSurfaceView = new GLSurfaceView(this); this.glSurfaceView.setRenderer(new ESRen- der(this)); this.setContentView(this.glSurfaceView); }

/** * Remember to resume the glSurface */ @Override protected void onResume() { super.onResume(); this.glSurfaceView.onResume(); }

/** * Also pause the glSurface */ @Override protected void onPause() {

370

super.onPause(); this.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.texture_mapping;

/** * @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;

/** 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

371

* 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 != 0) { if ((b & 1) != 0) { p *= powerN; } b >>>= 1; powerN = powerN * powerN; }

return p; } }

MySphere.java

package com.texture_mapping;

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

import javax.microedition.khronos.opengles.GL10;

import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import 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. */

372

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 Ar- rayList();

/** Buffer holding the texture coordinates. */ private final List mTextureBuffer = new ArrayList();

/** Mapping texture coordinates for the vertices. */ private final List mTexture = new Ar- rayList();

/** The texture pointer. */ private final int[] mTextures = new int[1];

/** Total number of strips for the given depth. */ private final int mTotalNumStrips;

/** * 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);

373

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 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 < numVertices- PerStrip; 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 - az- imuth / 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 - az- imuth / Maths.THREE_SIXTY_DEGREES); texturePoints[texturePos++] = (float) (1 - (altitude + Maths.NINETY_DEGREES) / Maths.ONE_EIGHTY_DEGREES);

374

azimuth += azimuthStepAngle; }

this.mVertices.add(vertices); this.mTexture.add(texturePoints);

ByteBuffer byteBuffer = ByteBuff- er.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);

// Setup texture. byteBuffer = ByteBuff- er.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 Con- text context, final int texture) { final Bitmap bitmap = BitmapFacto- ry.decodeResource(context.getResources(), texture);

// 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);

// Tidy up. bitmap.recycle(); }

375

/** * The draw method for the square with the GL con- text. * * @param gl Graphics handle. */ public void draw(final GL10 gl) { // 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_TEXTURE_COORD_ARRAY);

// Set the face rotation, clockwise in this case. gl.glFrontFace(GL10.GL_CW);

// 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.glTexCoordPointer(AMOUNT_OF_NUMBERS_PER_TEXTURE_POI NT, 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); } }

376

Gambar 5.11 Texture Mapping Pada Bola

377

BAB 6 Blending

6.1 Pengertian Blending

Blending merupakan fungsi yang menggabungkan nilai warna dari sumber (source) dan tujuan (destination/object), sehingga efek akhir scene terlihat transparan. Pencampuran dapat mengontrol berapa banyak warna yang dapat dikombinasikan. Dengan demikian untuk proses membuat terang fragmen dapat menggunakan alpha pencampuran. Warna pencampuran terletak pada teknik utama, seperti transparan, digital composite dan lukisan. Operasi campuran yaitu cara yang paling alami untuk mengetahui bahwa komponen RGB adalah suatu fragmen yang mewakili warna dan komponen alfa adalah suatu fragmen yang mewakili sifat tidak tembus cahaya. Dengan demikian, transparan mempunyai permukaan lebih rendah daripada yang buram. Dengan menggunakan glBlendFunc() untuk persediaan pada dua hal utama, yang pertama menentukan bagaimana faktor sumber dan tujuan harus dihitung dan yang kedua menunjukan bagaimana faktor sumber dan tujuan dihitung. Dan untuk proses pencampurannya harus ada faktor pengaktifannya menggunakan : glEnable (GL_BLEND). Menggunakan glDisable() dengan GL_BLEND untuk menonaktifkan Pencampuran dan menggunakan konstan GL_ONE(sumber) dan GL_ZERO(tujuan) memberikan hasil yang sama seperti ketika Pencampuran dinonaktifkan. Nilai-nilai ini bersifat default dengan void glBlendFunc(GLenum sfactor, GLenum dfactor). Teknik blending juga digunakan untuk ilusi dari cerminan sebuah objek pada Gambar 6.1.

Gambar 6.1 Teknik blending untuk mendapatkan efek pantulan

378

6.2 Source and Destination Factor Pada Blending

RGBA (Red, Green, Blue, Alpha) Alpha digunakan untuk mengatur tingkat opacity objek. a = 1 → tidak transparan a = 0 → transparan 0 < a < 1 → nilai untuk mengatur tingkat opacity Blending colors Source color : (Rs, Gs, Bs, As) Destination color : (Rd, Gd, Bd, Ad) Source factor : (Sr, Sg, Sb, Sa) Destination factor : (Dr, Dg, Db, Da) Blended RGBA = (RsSr+RdDr, GsSg+GdDg, BsSb+BdDb, As- Sa+AdDa) 6.3 Matematika Blending

Contoh soal blending : Biasanya, alasan mengapa seseorang menggunakan: glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); karena ingin menggunakan nilai alpha yang baru saja diberikan. Hal Ini digunakan untuk memperbanyak warna, dan kemudian menggu- nakan (1 - alpha) dan menggunakannya untuk memperbanyak warna buffer saat ini dalam koordinat. Oleh karena itu, jika melukis dengan quad glColor4f (1.0f, 1.0f, 1.0f, 0.6f) dan buffer diisi dengan glColor4f (1.0f, 0.0f, 0.0f, 1.0f), operasi akhirnya akan menjadi:

(1.0f, 1.0f, 1.0f) * ALPHA (1.0f, 0.0f, 0.0f) * (1 - ALPHA) (0.6f, 0.6f, 0.6f) (0.4f, 0.0f, 0.0f)

Jadi warna akhir adalah (1.0f, 0.6f, 0.6f)

379

Berikut contohnya : Objek ke 1 (biru) dengan RGBA (10, 20, 5, 0.2)

S Objek ke 2 (merah) dengan RGBA (30, 15, 6, 0.1)

D Gabungan objek satu dan objek 2

(R G B A) ?

GL_ONE_MINUS_SRC_ALPHA S/D (1,1,1,1) = (As,As,As,As) = (1, 1, 1, 1)(0.2, 0.2, 0.2, 0.2) = (0.8, 0.8, 0.8, 0.8)

380

Blended color Rblend = 0.8*10/S + 30*0.8/D = 8/S + 24/D = 32/SD Gblend = 0.8*20/S + 15*0.8/D = 16/S + 12/D = 24/SD Bblend = 0.8*5/S + 6*0.8/D = 4/S + 4.8/D = 8.8/SD Alphablend = 0.8*0.2/S + 0.1*0.8/D = 0.16/S + 0.08/D = 0.24/SD

RGBA adalah = (32, 24, 8.8, 0.24) 6.4 Blending Dua Segitiga

Source Code 6.1 Code Blending Dua Segitiga

ESRender.java

package com.blending;

import java.util.Formatter;

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

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

public class ESRender implements Renderer {

private ESText glText; private TextView textview;

381

private ObjectArena objectarena; // the primitive object to be drawn private ObjectBall objectball; private ObjectBall objectball2; private ObjectBall objectball3; private PrimitivesObject primob;

Context context; int Run_Mode=0; float CurrentAngle = 0.0f; // Angle in degrees float AnimateStep = 2.0f; // Rotation step per update

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

int xMin, xMax, yMin, yMax;

private int mywidth = 0; private int myheight = 0; private int jumlah_pantulan=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.objectball2 = new ObjectBall(); this.objectball3 = new ObjectBall(); this.primob = new PrimitivesObject(); }

@Override public void onDrawFrame(GL10 gl) {

// Draw background color gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

// segitiga merah gl.glPushMatrix(); gl.glColor4f(1.0f, 0.0f, 0.0f, 0.5f); 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); objectball.draw_segitiga(gl);

gl.glPopMatrix();

382

// segitiga hijau gl.glPushMatrix(); gl.glColor4f(0.0f, 0.0f, 1.0f, 0.5f); gl.glTranslatef(60.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); objectball.draw_segitiga(gl);

gl.glPopMatrix();

// update moveWithCollisionDetection(this); set((int)-radius, (int)-radius, mywidth, myheight);

// render text gl.glPushMatrix();

// gl.glScalef(10.0f, 10.0f, 10.0f);

// enable texture + alpha blending // NOTE: this is required for text ren- dering! we could incorporate it // into // the GLText class, but then it would be called multiple times (which // impacts performance). gl.glEnable(GL10.GL_TEXTURE_2D); // Ena- ble Texture Mapping gl.glEnable(GL10.GL_BLEND); // Enable Al- pha Blend gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA); // Set

// Alpha

// Blend

// Function

// disable texture + alpha gl.glDisable(GL10.GL_BLEND); // Disable Alpha Blend gl.glDisable(GL10.GL_TEXTURE_2D); // Dis- able Texture Mapping

gl.glPopMatrix();

383

// Update the rotational angle after each refresh // re-Calculate animation parame- ters CurrentAngle += AnimateStep; if (CurrentAngle > 360.0) { //CurrentAngle -= 360.0*Math.floor(CurrentAngle/360.0); CurrentAngle=0.0f; CurrentAngle += Ani- mateStep; }

}

@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); // Ena- bles 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); // Ena- ble smooth shading of color gl.glDisable(GL10.GL_DITHER); // Disable dithering for better // performance

// Create the GLText glText = new ESText(gl, con- text.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); // Disa- ble dithering for better // performance

// Setup Texture, each time the surface is created (NEW) objectball2.loadBallTexture(gl, context); gl.glEnable(GL10.GL_TEXTURE_2D); // Ena- ble 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 Ma- trix 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 < esRen- der.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 < esRen- der.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 android.content.Context; import android.opengl.GLSurfaceView; import android.util.Log; import android.view.KeyEvent; import 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 GLSur- faceView 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 posi- tion changed.

float currentX = v.getX(); float currentY = v.getY(); float deltaX, deltaY;

//float scalingFactor = 0.50f / ((esRen- der.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()+ (del- taX/getWidth()));

//esRender.setspeedY(esRender.getspeedY()+ (del- taY/getHeight()));

esRen- der.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) ){ esRen- der.setspeedX(esRender.getspeedX()- 0.05f); } if((esRender.getspeedX()- 0.05f <0) ){ esRender.setspeedX(0.0f); } if((esRender.getspeedY()- 0.05f >=0)){ esRen- der.setspeedY(esRender.getspeedY()- 0.05f); } if((esRender.getspeedY()- 0.05f <0) ){ esRender.setspeedY(0.0f); } Log.v("Test Action KEYCODE_A", "action working"); break; case KeyEvent.KEYCODE_Z: Log.v("Test Action KEYCODE_Z", "action working"); break; } return true; // Event handled } }

MainActivity.java

package com.blending;

389

import android.opengl.GLSurfaceView; import android.os.Bundle; import android.app.Activity; import android.view.Menu; import android.view.Window; import android.view.WindowManager; public class MainActivity extends Activity {

/** The OpenGL view */ private GLSurfaceView glSurfaceView;

@Override protected void onCreate(Bundle savedInstanceS- tate) { super.onCreate(savedInstanceState); //setContentView(R.layout.activity_main);

// requesting to turn the title OFF requestWindowFeature(Window.FEATURE_NO_TITLE); // making it full screen getWin- dow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCR EEN, WindowManag- er.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

390

the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; }

}

PrimitivesObject.java

package com.blending;

import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import javax.microedition.khronos.opengles.GL10; import 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 -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. right- bottom -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, 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 };

391

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 verti- ces 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 <= 2 * ba- tas_sudut; teta += step) { vertices_circle[loop] = (float) ((x - a) * Math.cos((teta / 180) * (22 / 7)) - ((y - b) * Math.sin((teta / 180) * (22 / 7))) + a); vertices_circle[loop + 1] = (float) ((x - a) * Math.sin((teta / 180) * (22 / 7)) - ((y - b) * Math.cos((teta / 180) * (22 / 7))) + b); vertices_circle[loop + 2] = 0; loop += 3;

// mengenerate warna untuk setiap vertex vertices_circle_color[loop_color]

392

= (float) ((x - a) * Math.cos((teta / 180) * (22 / 7)) - ((y - b) * Math.sin((teta / 180) * (22 / 7))) + a); vertices_circle_color[loop_color + 1] = (float) ((x - a) * Math.sin((teta / 180) * (22 / 7)) - ((y - b) * Math.cos((teta / 180) * (22 / 7))) + b); vertices_circle_color[loop_color + 2] = 0.5f; vertices_circle_color[loop_color + 3] = 0.5f; loop_color += 4; } // ======end for generate verti- ces to circle // ======

// ======start to generate verti- ces to line // ======x1 = -1.0f; y1 = -1.0f; x2 = 1.0f; y2 = 1.0f;

loop_line = 3; loop_line_color = 4; vertices_line = new float[(int) (2 * (x2 - x1) / step_line) * 3]; vertices_line_color = new float[(int) (2 * (x2 - x1) / step_line) * 4];

float m = (y2 - y1) / (x2 - x1); for (x = x1; x <= x2; x += step_line) { vertices_line[loop_line] = (float) (x); vertices_line[loop_line + 1] = (float) (m * (x - x1) + y1); vertices_line[loop_line + 2] = 0; loop_line += 3;

// mengenerate warna untuk setiap vertex verti- ces_line_color[loop_line_color] = (float) (0.5 * x); verti- ces_line_color[loop_line_color + 1] = (float) (0.5 * m * (x - x1) + y1); verti- ces_line_color[loop_line_color + 2] = 1.0f; verti- ces_line_color[loop_line_color + 3] = 1.0f; loop_line_color += 4; } // ======end for generate verti-

393

ces to line ======}

// Point to our vertex buffer, return buffer holding the vertices public static FloatBuffer makeFloatBuffer(float[] arr) { ByteBuffer bb = ByteBuff- er.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_points(GL10 gl) {

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

// set the colour for the points (pem- berian warna untuk titik) gl.glColor4f(0.0f, 0.0f, 1.0f, 1.0f);

// Point to our vertex buffer (mendata nilai lokasi/posisi titik) gl.glVertexPointer(3, GL10.GL_FLOAT, 0, makeFloatBuffer(new float[] { 1.0f, 1.0f, 0.0f, // V1 - first vertex (x,y,z) 1.0f, 0.8f, 0.0f, // V2 1.0f, 0.6f, 0.0f, // V3 1.0f, 0.4f, 0.0f, // V4 1.0f, 0.2f, 0.0f, // V5 1.0f, 0.0f, 0.0f, // V6 1.0f, -0.2f, 0.0f, // V7 1.0f, -0.4f, 0.0f, // V8 1.0f, -0.6f, 0.0f, // V9 1.0f, -0.8f, 0.0f, // V10 1.0f, -1.0f, 0.0f, // V11

0.8f, -1.0f, 0.0f, // V12 0.6f, -1.0f, 0.0f, // V13 0.4f, -1.0f, 0.0f, // V14 0.2f, -1.0f, 0.0f, // V15 0.0f, -1.0f, 0.0f, // V16 -0.2f, -1.0f, 0.0f, // V17 -0.4f, -1.0f, 0.0f, // V18 -0.6f, -1.0f, 0.0f, // V19 -0.7f, -1.0f, 0.0f, // V20 -0.8f, -1.0f, 0.0f, // V21 -1.0f, -1.0f, 0.0f, // V22 }));

394

// Draw the vertices as points (menggam- bar titik-titik) gl.glDrawArrays(GL10.GL_POINTS, 0, 22);

// Disable the client state before leav- ing

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); // gl.glDisableClientState(GL10.GL_COLOR_ARRAY);

}

public void draw_line(GL10 gl) {

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

// set the colour for the line (pemberian warna untuk garis) gl.glColor4f(0.0f, 0.0f, 1.0f, 1.0f);

// Point to our vertex buffer (mendata nilai lokasi/posisi titik yang // menyusun garis) gl.glVertexPointer(3, GL10.GL_FLOAT, 0, makeFloatBuffer(new float[] { 1.0f, 1.0f, 0.0f, // V1 - first vertex (x,y,z) -1.0f, -1.0f, 0.0f, // V2 - second vertex }));

// Draw the vertices as lines (menggambar garis dari titik-titik) gl.glDrawArrays(GL10.GL_LINES, 0, 2); /* * gl.glDrawElements(GL10.GL_LINES, 2, GL10.GL_UNSIGNED_SHORT, * makeFloatBuffer(new float [] { 1.0f, 1.0f, 0.0f, // V1 - first vertex * (x,y,z) -1.0f, -1.0f, 0.0f, // V2 - second vertex })); */

// Disable the client state before leav- ing

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); // gl.glDisableClientState(GL10.GL_COLOR_ARRAY);

}

public void draw_line_color(GL10 gl) {

395

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

// set the colour for the line (pemberian warna untuk garis) gl.glColor4f(0.0f, 0.0f, 1.0f, 1.0f);

// Point to our vertex buffer (mendata nilai lokasi/posisi titik yang // menyusun garis) gl.glVertexPointer(3, GL10.GL_FLOAT, 0, makeFloatBuffer(vertices_line));

// memetakan warna untuk setiap vertex gl.glColorPointer(4, GL10.GL_FLOAT, 0, makeFloatBuff- er(vertices_line_color));

// Draw the vertices as lines (menggambar garis dari titik-titik) gl.glDrawArrays(GL10.GL_LINE_STRIP, 0, (int) (2 * (x2 - x1) / step_line)); /* * gl.glDrawElements(GL10.GL_LINES, 2, GL10.GL_UNSIGNED_SHORT, * makeFloatBuffer(new float [] { 1.0f, 1.0f, 0.0f, // V1 - first vertex * (x,y,z) -1.0f, -1.0f, 0.0f, // V2 - second vertex })); */

// Disable the client state before leav- ing

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

gl.glDisableClientState(GL10.GL_COLOR_ARRAY);

}

public void draw_circle(GL10 gl) {

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

// set the colour for the object circle gl.glColor4f(1.0f, 0.0f, 0.0f, 1.0f);

// create VBO from buffer with glBuffer- Data() gl.glVertexPointer(3, GL10.GL_FLOAT, 0, makeFloatBuff- er(vertices_circle));

// draw circle as filled shape // gl.glDrawArrays(GL10.GL_TRIANGLE_FAN,

396

1, (int) ((int) // 2*batas_sudut/step));

// draw circle contours // gl.glDrawArrays(GL10.GL_LINES, 1, (int) ((int) 2*batas_sudut/step)); // // membuat garis putus-putus pada tepi lingkaran gl.glDrawArrays(GL10.GL_LINES, 1, (int) ((int) 2 * batas_sudut / step)); // gl.glDrawArrays(GL10.GL_LINE_STRIP, 1, (int) ((int) // 2*batas_sudut/step)); // gl.glDrawArrays(GL10.GL_POINTS, 1, (int) ((int) 2*batas_sudut/step));

// Disable the client state before leav- ing

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); // gl.glDisableClientState(GL10.GL_COLOR_ARRAY); }

public void draw_circle_color(GL10 gl) {

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

// set the colour edge for the object circle gl.glColor4f(0.0f, 0.0f, 1.0f, 1.0f);

// create VBO from buffer with glBuffer- Data() gl.glVertexPointer(3, GL10.GL_FLOAT, 0, makeFloatBuff- er(vertices_circle));

// memetakan warna untuk setiap vertex gl.glColorPointer(4, GL10.GL_FLOAT, 0, makeFloatBuff- er(vertices_circle_color));

// draw circle as filled shape // gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 1, (int) ((int) // 2*batas_sudut/step)); gl.glDrawArrays(GL10.GL_LINE_STRIP, 1, (int) ((int) 2 * ba- tas_sudut / step));

// Disable the client state before leav- ing

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

gl.glDisableClientState(GL10.GL_COLOR_ARRAY);

397

}

public void draw_kotak(GL10 gl) {

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

// 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 leav- ing

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

gl.glDisableClientState(GL10.GL_COLOR_ARRAY);

}

public void draw_segitiga(GL10 gl) {

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

// set the colour for the triangle gl.glColor4f(1.0f, 0.0f, 0.0f, 1.0f);

gl.glVertexPointer(3, GL10.GL_FLOAT, 0, makeFloatBuffer(new float[] { -0.5f, -0.5f, 0.0f, // V1 - first vertex (x,y,z) 0.5f, -0.5f, 0.0f, // V2 - second vertex 0.0f, 0.5f, 0.0f // V3 - third vertex

}));

// Draw the vertices as triangle gl.glColorPointer(4, GL10.GL_FLOAT, 0, makeFloatBuffer(vertices_color)); gl.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);

// Disable the client state before leav- ing

398

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

gl.glDisableClientState(GL10.GL_COLOR_ARRAY);

}

// Render the shape quad public void draw_quad(GL10 gl) { // Enable vertex-array and define its buffer

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, makeFloatBuffer(vertices_quad)); // Draw the primitives from the vertex- array directly gl.glPolygonOffset(0.0f, 1.0f); gl.glScalef(0.5f, 0.5f, 0.5f); gl.glColor4f(0.5f, 0.5f, 1.0f, 1.0f); // Set the current color (NEW) gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices_quad.length / 3); //gl.glDrawArrays(GL10.GL_TRIANGLES, 0, vertices_quad.length / 3); //gl.glDrawArrays(GL10.GL_LINES, 0, ver- tices_quad.length / 3);

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); }

}

Gambar 6.2 Blending Dua Segitiga

399

6.5 Blending Pada Kubus

Source Code 6.2 Code Blending Pada Kubus

ESRender.java

package com.blending;

import java.io.IOException;

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

import android.content.Context; //import android.opengl.GLU; import android.opengl.GLSurfaceView.Renderer; import android.opengl.GLU;

public class ESRender implements Renderer {

private Context context; // Application context needed to read image (NEW) private TextureKubus kubus;

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

// Lighting boolean lightingEnabled = false; private float[] lightAmbient = { 0.5f, 0.5f, 0.5f, 1.0f }; private float[] lightDiffuse = { 1.0f, 1.0f, 1.0f, 1.0f }; private float[] lightPosition = { 0.0f, 0.0f, 2.0f, 1.0f };

// Blending (NEW) boolean blendingEnabled = false; // Is blending on? (NEW)

/** Constructor to set the handed over context */ public ESRender(Context context) { this.context = context; // Get the appli- cation context (NEW) kubus = new TextureKubus(); }

@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

400

// gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // set background dgn warna // hitam gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

// Enable lighting? if (lightingEnabled) { gl.glEnable(GL10.GL_LIGHTING); } else { gl.glDisable(GL10.GL_LIGHTING); }

// Blending Enabled? (NEW) if (blendingEnabled) { gl.glEnable(GL10.GL_BLEND); // Turn blending on (NEW) gl.glDisable(GL10.GL_DEPTH_TEST); // Turn depth testing off (NEW) } else { gl.glDisable(GL10.GL_BLEND); // Turn blending off (NEW) gl.glEnable(GL10.GL_DEPTH_TEST); // Turn depth testing on (NEW) }

//gl.glLoadIdentity();

// ----- Render the Kubus ----- gl.glPushMatrix(); gl.glTranslatef(0.0f, 0.9f, - 5.0f); // gl.glTranslatef(0.0f, 0.0f, - 6.0f); // Translate into the screen gl.glRotatef(CurrentAngle, 0.1f, 1.0f, 0.2f); // Rotate // gl.glRotatef(CurrentAngle, 1.0f, 1.0f, 1.0f ); gl.glTranslatef(-0.5f, -0.5f, - 0.5f); //gl.glScalef(0.5f, 0.5f, 0.5f); kubus.draw(gl); gl.glPopMatrix();

// Update the rotational angle after each refresh if (RunMode == 1) { // re-Calculate animation parame- ters CurrentAngle += AnimateStep; if (CurrentAngle > 360.0) { // CurrentAngle -= 360.0*Math.floor(CurrentAngle/360.0); CurrentAngle = 0.0f; CurrentAngle += Ani- mateStep; } }

401

}

@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 as- pect 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 gl.glClearDepthf(1.0f); // Set depth's clear-value to farthest gl.glEnable(GL10.GL_DEPTH_TEST); // Ena- bles 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); // Ena- ble smooth shading of color gl.glDisable(GL10.GL_DITHER); // Disable dithering for better // performance

// Setup Texture, each time the surface

402

is created (NEW) kubus.loadTexture(gl, context); gl.glEnable(GL10.GL_TEXTURE_2D); // Ena- ble texture (NEW)

// Setup lighting GL_LIGHT1 with ambient and diffuse lights gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_AMBIENT, lightAmbient, 0); gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_DIFFUSE, lightDiffuse, 0); gl.glLightfv(GL10.GL_LIGHT1, GL10.GL_POSITION, lightPosition, 0); gl.glEnable(GL10.GL_LIGHT1); // Enable Light 1 gl.glEnable(GL10.GL_LIGHT0); // Enable the default Light 0

// 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 function (NEW) }

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.blending;

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

403

/** * 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;

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 // setRender- Mode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); }

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 = v.getX(); float y = v.getY();

switch (v.getAction()) {

case MotionEvent.ACTION_DOWN: Log.v("Test Action Down", "action down working"); break; // case MotionEvent.ACTION_POINTER_UP: // Log.v("Test Action ACTION_POINTER_UP", "action working"); // requestRender();

404

// 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: Log.v("Test Action move", "action down working"); float dx = (x - mPreviousX); float dy = (y - mPreviousY); mPreviousX = x; mPreviousY = y;

esRender.blendingEnabled = !esRen- der.blendingEnabled;

requestRender(); }

return true; }

// Key-up event handler @Override public boolean onKeyUp(int keyCode, KeyEvent event) { float x=getHeight();

switch (keyCode) { case KeyEvent.KEYCODE_DPAD_RIGHT: // In- crease rightward speed Log.v("Test Action KEYCODE_DPAD_RIGHT", "action working"); requestRender(); break; case KeyEvent.KEYCODE_DPAD_LEFT: // In- crease leftward speed requestRender(); break; case KeyEvent.KEYCODE_DPAD_UP: // In- crease upward speed break; case KeyEvent.KEYCODE_DPAD_DOWN: // In- crease downward speed break; case KeyEvent.KEYCODE_DPAD_CENTER: // Stop break; case KeyEvent.KEYCODE_B: // enable blend- ing Log.v("Test Action B", "action working"); esRender.blendingEnabled = !esRen- der.blendingEnabled; requestRender(); break;

405

} return true; // Event handled } }

MainActivity.java

package com.blending;

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

public class MainActivity extends Activity {

/** The OpenGL view */ private GLSurfaceView glSurfaceView;

@Override protected void onCreate(Bundle savedInstanceS- tate) { super.onCreate(savedInstanceState); //setContentView(R.layout.activity_main);

// requesting to turn the title OFF requestWindowFeature(Window.FEATURE_NO_TITLE); // making it full screen getWin- dow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCR EEN, WindowManag- er.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();

406

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; }

}

TextureKubus.java

package com.blending;

import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import javax.microedition.khronos.opengles.GL10; import android.content.Context; import android.content.res.AssetManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import 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 TextureKubus { private FloatBuffer vertexBuffer; // Buffer for vertex-array private FloatBuffer texBuffer; // Buffer for tex- ture-coords-array (NEW) private float[] vertices = { // Vertices for a

407

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 }; 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 TextureKubus() { // Setup vertex-array buffer. Vertices in float. An float has 4 bytes ByteBuffer vbb = ByteBuff- er.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 vertexBuffer.position(0); // Rewind // Setup texture-coords-array buffer, in float. An float has 4 bytes // (NEW) ByteBuffer tbb = ByteBuff- er.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); // Ena- ble cull face / disable transparan object gl.glCullFace(GL10.GL_BACK); // Cull the back face (don't display)

408

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();

// 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

409

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, tex- tureIDs[0]); // Bind to texture

// ID // Set up texture filters 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);

// Construct an input stream to texture image "res\drawable\nature.png" //AssetManager assetManager = c.getAssets(); //InputStream istream = assetManag- er.open("nature.png"); InputStream istream = c.getResources().openRawResource(R.drawable.nature); Bitmap bitmap; try { // Read and decode input as bitmap bitmap = BitmapFacto- ry.decodeStream(istream); } finally { try { istream.close(); } catch (IOException e) { } }

// Build Texture from loaded bitmap for

410

the currently-bind texture ID GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0); bitmap.recycle(); } }

Gambar 6.3 Blending Pada Kubus (Blending tidak terlihat jika belum ada gerakan sentuhan ke sembarang arah pada layarnya) 6.6 Blending Pada Bola

Source Code 6.3 Code Blending Pada Bola

ESRender.java

package com.blending;

import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import android.content.Context; import android.opengl.GLSurfaceView; import android.opengl.GLSurfaceView.Renderer; import android.opengl.GLU;

public class ESRender implements Renderer {

/** Tilt the spheres a little. */ private static final int AXIAL_TILT_DEGRESS = 30;

411

/** Clear colour, alpha component. */ private static final float CLEAR_RED = 0.0f;

/** Clear colour, alpha component. */ private static final float CLEAR_GREEN = 0.0f;

/** Clear colour, alpha component. */ private static final float CLEAR_BLUE = 0.0f;

/** Clear colour, alpha component. */ private static final float CLEAR_ALPHA = 0.5f;

/** Perspective setup, field of view component. */ private static final float FOVY = 45.0f;

/** Perspective setup, near component. */ private static final float Z_NEAR = 0.1f;

/** Perspective setup, far component. */ private static final float Z_FAR = 100.0f;

/** Object distance on the screen. move it back a bit so we can see it! */ private static final float OBJECT_DISTANCE = - 15.0f;

/** The earth's sphere. */ private final MySphere mEarth;

/** The context. */ private final Context mContext;

/** The rotation angle, just to give the screen some action. */ private float mRotationAngle;

/** * Constructor to set the handed over context. * @param context The context. */ public ESRender(final Context context) { this.mContext = context; //this.mEarth = new MySphere(3, 2); this.mEarth = new MySphere(5, 3); this.mRotationAngle = 0.0f; }

// Call back to draw the current frame. @Override public void onDrawFrame(GL10 gl) { // Clear color and depth buffers gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

gl.glEnable(GL10.GL_BLEND); // Turn blending on (NEW) gl.glDisable(GL10.GL_DEPTH_TEST); // Turn

412

depth testing off (NEW)

//gl.glLoadIdentity(); // ----- Render the Sphere ------gl.glPushMatrix(); gl.glTranslatef(0.0f, 0.0f, OBJECT_DISTANCE); gl.glRotatef(AXIAL_TILT_DEGRESS, 1, 0, 0); gl.glRotatef(this.mRotationAngle++, 0, 1, 0); this.mEarth.draw(gl); gl.glPopMatrix(); }

// Call back when the surface is first created or re-created. @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { this.mEarth.loadGLTexture(gl, this.mContext, R.drawable.earth); gl.glEnable(GL10.GL_TEXTURE_2D); gl.glShadeModel(GL10.GL_SMOOTH); gl.glClearColor(CLEAR_RED, CLEAR_GREEN, CLEAR_BLUE, CLEAR_ALPHA); gl.glClearDepthf(1.0f); gl.glEnable(GL10.GL_DEPTH_TEST); gl.glDepthFunc(GL10.GL_LEQUAL); gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);

// 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 function (NEW)

//gl.glBlendFunc(GL10.GL_ZERO, GL10.GL_ZERO); // Select blending function (NEW)

}

// Call back after onSurfaceCreated() or whenever the window's size changes. @Override public void onSurfaceChanged(GL10 gl, int width, int height) {

final float aspectRatio = (float) width / (float) (height == 0 ? 1 : height);

// gl.glViewport(0, 0, width, height); //gl.glMatrixMode(GL10.GL_PROJECTION); // gl.glLoadIdentity();

413

/*if (height == 0) height = 1; // To prevent divide by zero float aspectRatio = (float) width / height;*/

// Set the viewport (display area) to cover the entire window gl.glViewport(0, 0, width, height);

// Setup perspective projection, with as- pect 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);

GLU.gluPerspective(gl, FOVY, aspectRatio, Z_NEAR, Z_FAR); gl.glMatrixMode(GL10.GL_MODELVIEW); // Select model-view matrix gl.glLoadIdentity(); // Reset } }

MainActivity.java

package com.blending;

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

public class MainActivity extends Activity {

/** The OpenGL view. */ private GLSurfaceView glSurfaceView; @Override protected void onCreate(final Bundle savedIn- stanceState) { super.onCreate(savedInstanceState);

414

this.requestWindowFeature(Window.FEATURE_NO_TITLE);

this.getWindow().setFlags(WindowManager.LayoutParams.F LAG_FULLSCREEN, WindowManag- er.LayoutParams.FLAG_FULLSCREEN); this.glSurfaceView = new GLSurfaceView(this); this.glSurfaceView.setRenderer(new ESRen- der(this)); this.setContentView(this.glSurfaceView); } /** * Remember to resume the glSurface */ @Override protected void onResume() { super.onResume(); this.glSurfaceView.onResume(); }

/** * Also pause the glSurface */ @Override protected void onPause() { super.onPause(); this.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.blending;

/** * @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;

415

/** 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;

/** 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 != 0) { if ((b & 1) != 0) { p *= powerN; } b >>>= 1; powerN = powerN * powerN; }

return p; } }

MySphere.java

package com.blending;

import java.nio.ByteBuffer; import java.nio.ByteOrder;

416

import java.nio.FloatBuffer; import java.util.ArrayList; import java.util.List; import javax.microedition.khronos.opengles.GL10; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import 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 Ar- rayList();

/** Buffer holding the texture coordinates. */ private final List mTextureBuffer = new ArrayList();

/** Mapping texture coordinates for the vertices. */ private final List mTexture = new Ar- rayList();

/** The texture pointer. */ private final int[] mTextures = new int[1];

417

/** Total number of strips for the given depth. */ private final int mTotalNumStrips;

/** * 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 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 < numVertices- PerStrip; 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 - az-

418

imuth / 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 - az- imuth / 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 = ByteBuff- er.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);

// Setup texture. byteBuffer = ByteBuff- er.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 Con- text context, final int texture) {

419

final Bitmap bitmap = BitmapFacto- ry.decodeResource(context.getResources(), texture);

// 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);

// Tidy up. bitmap.recycle(); }

/** * The draw method for the square with the GL con- text. * * @param gl Graphics handle. */ public void draw(final GL10 gl) { // 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_TEXTURE_COORD_ARRAY);

// Set the face rotation, clockwise in this case. gl.glFrontFace(GL10.GL_CW);

// 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.glTexCoordPointer(AMOUNT_OF_NUMBERS_PER_TEXTURE_POI NT, 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.

420

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY); } }

Gambar 6.4 Blending Pada Bola

421

BAB 7 Lighting & Shading

7.1 Pengertian Lighting & Shading

Salah satu tujuan dari grafika komputer adalah menghasilkan tampilan yang senyata mungkin, dan karena pengaruh cahaya sangat besar terhadap hasil nyata maka dalam membuat tampilan akhir fac- tor pencahayaan harus diperhitungkan pula. Tetapi mengingat bahwa grafika computer adalah model matematika dari kehidupan nyata maka pencahayaan juga harus diubah menjadi model matematika. Model matematika itu harus memenuhi persyaratan sebagai berikut:  Menghasilkan efek seperti cahaya sungguhan  Dapat dihitung dengan cepat Model pencahayaan tiga dimensi yang realistik menyangkut dua elemen penting yang sangat berkaitan erat dengan shading model, yaitu:  Keakuratan dalam menggambarkan objek.  Teknik pencahayaan yang baik. Saat cahaya menimpa permukaan benda maka sebagian ca- haya akan dipantulkan dan sebagian lain diserap. Bergantung kepada frekuensi atau panjang gelombang yang dipantulkan dan diserap maka kita akan melihat warna. Mata kita selain sensitive terhadap warna juga sensitive terhadap intensitas cahaya (brightness). Secara awam kita menyebut intensitas cahaya sebagai kecerahan.

Gambar 7.1 Pencahayaan Sifat materi penyusun benda menentukan bagaimana cahaya bereaksi terhadap materi penyusun benda. Secara umum, cahaya yang menimpa sebuah permukaan akan dipantulkan oleh permukaan.

422

7.2 Proses dan Fungsi Pada Lighting float lightAmbient[] = new float[] { 0.2f, 0.3f, 0.6f, 1.0f }; float light_position[] = { 0.0f, 0.0f, 1.0f, 0.0f }; float white[] = new float[] { 1.0f, 1.0f, 1.0f, 1.0f };

1. gl.glPushMatrix(); 2. gl.glTranslatef(0.0f, 0.9f, -5.0f); 3. gl.glRotatef(CurrentAngle, 0.0f, 1.0f, 0.0f ); 4. gl.glMaterialf(GL10.GL_FRONT, GL10.GL_SHININESS, 256.0f); 5. gl.glLightfv(GL10.GL_LIGHT0,GL10.GL_POSITION,l ight_position,0); 6. gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, white, 0); 7. gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, lightAmbient, 0); 8. gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_SPECULAR, white, 0); 9. gl.glScalef(0.1f, 0.1f, 0.1f); 10. lampu.draw(gl); 11. gl.glPopMatrix();

Penjelasan :

1. Untuk membuka atau awalan dalam pembuatan desain dalam opengl 2. Untuk pengaturan posisi object yang kita inginkan 3. Untuk memutar object dengan sudut yang kita inginkan 4. Cahaya hanya berada dibagian depan , area yang mendapatkan cahaya sebesar “256.0f”. 5. Untuk pengaturan cahaya pada object dengan memanggil “light_position” (posisi cahaya) 6. Untuk pengaturan cahaya pada object dengan memanggil “white” (cahaya warna putih atau terang). 7. Untuk pengaturan cahaya pada object dengan memanggil “lightAmbient”(cahaya berasal dari segala arah).

423

8. Untuk pengaturan cahaya pada object dengan memanggil “white” (cahaya warna putih atau terang). 9. Untuk ukuran object ,misal kecil ,besar atau sedang. 10. Memanggil object yang akan kita gunakan. 11. Menutup pembuatan object pada opengl.

7.3 Normal Vektor Pada Lighting

Normal Vector adalah vector yang arahnya tegak lurus pada luasan (face). Normal Vector dapat diperoleh dari perkalian silang (cross-product) dari dua vector yang berada pada face. Besar dari Normal Vector tegantung pada hasil perkalian silangnya. Cara yang digunakan untuk menghitung vektor normal dari 3 vertex adalah : |axb|=|a||b|sin Ө

i j k (aybz )  (byaz )   a x b  ax ay az  (bxaz )  (axbz )   bx by bz (axby )  (bxay ) a x b

a

b

Gambar 7.2 Normal Vector

Untuk mndefinisikan vektor normal, dapat menggunakan perintah sebagai berikut :

 glNormal3f(fNormalX, fNormalY, fNormalZ) :  glVertex3f(fVert1, fVert2, fVert3) :

424

7.4 Lighting Pada Interior

Source Code 7.1 Code Lighting Pada Interior

ESRender.java

package com.ligthing;

import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.util.Formatter;

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

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

public class ESRender implements Renderer {

private ESText glText; private TextView textview; private ObjectArena objectarena; // the primitive object to be drawn private ObjectBall objectball; private ObjectBall objectball2; private ObjectBall objectball3; private PrimitivesObject primob; private TransObject transobject; private final MySphere mEarth, mEarth2, mEarth3;

private boolean isOn=true;

private PhotoKubus kotak; // (NEW) // private PhotoKubus tembok_blkng; private TextureKubus tembok; private Context context; private kubus kubus; private lukisan lukisan; private lukisan lukisan1; private pintu pintu;

private kubus_kecil kubus_kecil; private kaki_meja kaki_meja; private lampu lampu;

// Context context; int Run_Mode = 0; float CurrentAngle = 0.0f; // Angle in degrees

425

float AnimateStep = -2.0f; // Rotation step per update

float CurrentAngle1 = 0.0f; // Angle in degrees float AnimateStep1 = 2.0f; // Rotation step per update

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

int xMin, xMax, yMin, yMax;

private int mywidth = 0; private int myheight = 0; private int jumlah_pantulan = 0;

// posisi cahaya // base transformasi yang ada pada objek // gl.glTranslatef(600.0f, 200.0f, 0.0f); // gl.glScalef(25.0f, 25.0f, 25.0f); // gl.glTranslatef (0.0f, 0.0f, -5.0f);

// float[] position = { 0.0f, 0.0f, 1.5f, 1.0f }; // original float[] position = { ((0.0f) * 25.0f) + 600.0f, ((0.0f) * 25.0f) + 200.0f, ((1.5f - 5.0f) * 25.0f) + 0.0f, 1.0f }; float[] position41 = { ((0.0f) * 25.0f) + 800.0f, ((0.0f) * 25.0f) + 400.0f, ((1.5f - 5.0f) * 25.0f) + 0.0f, 1.0f }; float[] position42 = { ((0.0f) * 25.0f) + 800.0f, ((0.0f) * 25.0f) + 400.0f, ((-1.5f - 5.0f) * 25.0f) + 0.0f, 1.0f };

float[] position1 = { ((0.0f) * 25.0f) + 800.0f, ((0.0f) * 25.0f) + 200.0f, ((1.5f - 5.0f) * 25.0f) + 0.0f, 1.0f };

// float[] position2 = { 0.0f, 0.0f, -1.5f, 0.0f}; //{x,y,z,w} float[] position2 = { ((0.0f) * 25.0f) + 800.0f, ((0.0f) * 25.0f) + 200.0f, ((-1.5f - 5.0f) * 25.0f) + 0.0f, 1.0f }; float[] position3 = { ((0.0f) * 25.0f) + 800.0f, ((0.0f) * 25.0f) + 200.0f, ((-1.5f - 5.0f) * 25.0f) + 0.0f, 1.0f };

float black[] = new float[] { 0.0f, 0.0f, 0.0f, 1.0f }; float yellow[] = new float[] { 1.0f, 1.0f, 0.0f, 1.0f }; float cyan[] = new float[] { 0.0f, 1.0f, 1.0f,

426

1.0f }; float white[] = new float[] { 1.0f, 1.0f, 1.0f, 1.0f }; float orange[] = new float[] { 1.0f, 0.5f, 0.0f, 0.0f }; float diffuseMaterial[] = new float[] { 0.73f, 0.13f, 0.86f, 1.0f }; // set cahaya warna ungu float diffuseMaterial2[] = new float[] { 0.5f, 0.5f, 0.5f, 1.0f }; // set cahaya warna ungu float lightAmbient[] = new float[] { 0.2f, 0.3f, 0.6f, 1.0f };

float mat_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f }; float light_position[] = { -1.5f, 0.0f, 0.0f, 0.0f };

/** Constructor to set the handed over context */ public ESRender(Context context) { // super(); this.context = context; this.objectarena = new ObjectArena(); this.objectball = new ObjectBall(); this.objectball2 = new ObjectBall(); this.objectball3 = new ObjectBall(); this.primob = new PrimitivesObject(); this.mEarth = new MySphere(5, 3); this.mEarth2 = new MySphere(5, 3); this.mEarth3 = new MySphere(5, 3); this.transobject = new TransObject(); kotak = new PhotoKubus(context); // (NEW) // tembok_blkng = new PhotoKu- bus(context); tembok = new TextureKubus(context);

lukisan = new lukisan(context);// lukisan1 = new lukisan(context);//

// this.context = context; // Get the ap- plication context (NEW) kubus = new kubus(); pintu = new pintu(context); kubus_kecil = new kubus_kecil(context); kaki_meja = new kaki_meja(context); lampu = new lampu(context); }

@Override public void onDrawFrame(GL10 gl) {

// Draw background color gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); // gl.glClear(GL10.GL_COLOR_BUFFER_BIT); gl.glEnable(GL10.GL_DEPTH_TEST); gl.glEnable(GL10.GL_NORMALIZE);

// gl.glMaterialfv(GL10.GL_FRONT, GL10.GL_AMBIENT_AND_DIFFUSE,

427

// makeFloatBuffer(cyan));

gl.glMaterialfv(GL10.GL_FRONT, GL10.GL_SPECULAR, white, 0); gl.glMaterialfv(GL10.GL_FRONT, GL10.GL_SHININESS, white, 0); gl.glMaterialfv(GL10.GL_FRONT, GL10.GL_DIFFUSE, white, 0);

// gl.glMatrixMode( GL10.GL_MODELVIEW ); // Activate Model View Matrix // gl.glLoadIdentity(); // Load Identity Matrix if(isOn){ gl.glDisable(GL10.GL_LIGHTING); }

// bawah lantai gl.glPushMatrix(); // gl.glDisable(GL10.GL_LIGHTING); gl.glTranslatef(0.0f, 0.0f, -5.0f); // gl.glScalef(50.0f, 50.0f, 50.0f); gl.glRotatef(90, 1, 0, 0); kotak.draw(gl); // gl.glEnable(GL10.GL_LIGHTING); gl.glPopMatrix();

// atap gl.glPushMatrix(); // gl.glDisable(GL10.GL_LIGHTING); gl.glTranslatef(0.0f, 0.0f, -5.0f); gl.glRotatef(180, 1.0f, 0.0f, 0.0f); gl.glRotatef(90, 1.0f, 0.0f, 0.0f); // gl.glTranslatef(0.0f, 0.0f, -6.0f); // Translate into the screen // gl.glRotatef(CurrentAngle, 0.1f, 1.0f, 0.2f); // Rotate // gl.glRotatef(CurrentAngle, 1.0f, 1.0f, 1.0f ); // gl.glTranslatef(-0.5f,-0.5f,-0.5f); // gl.glScalef(2.0f, 2.0f, 2.0f); kotak.draw_atap(gl); // gl.glEnable(GL10.GL_LIGHTING); gl.glPopMatrix();

// tembok belakang gl.glPushMatrix(); // gl.glDisable(GL10.GL_LIGHTING); gl.glTranslatef(0.0f, 0.0f, -5.0f); gl.glRotatef(90, 1.0f, 0.0f, 0.0f); gl.glRotatef(90, 1.0f, 0.0f, 0.0f); kotak.draw_tembok_blk(gl); // gl.glEnable(GL10.GL_LIGHTING); gl.glPopMatrix();

// tembok samping kanan gl.glPushMatrix(); // gl.glDisable(GL10.GL_LIGHTING); gl.glTranslatef(1.0f, 0.0f, 0.0f);

428

gl.glTranslatef(0.0f, 0.0f, -5.0f); gl.glRotatef(180, 1.0f, 0.0f, 1.0f); tembok.draw_tembok_smp(gl); // gl.glEnable(GL10.GL_LIGHTING); gl.glPopMatrix();

// tembok samping kiri gl.glPushMatrix(); // gl.glDisable(GL10.GL_LIGHTING); gl.glTranslatef(-1.0f, 0.0f, -5.0f); // gl.glTranslatef(0.0f, 0.0f, -6.0f); // Translate into the screen // gl.glRotatef(CurrentAngle, 0.1f, 1.0f, 0.2f); // Rotate // gl.glRotatef(270, 0.0f, 0.0f, 1.0f); gl.glRotatef(90, 0.0f, 1.0f, 0.0f); gl.glRotatef(180, 1.0f, 0.0f, 0.0f); // gl.glTranslatef(-0.5f,-0.5f,-0.5f); // gl.glScalef(2.0f, 2.0f, 2.0f); tembok.draw_tembok_smp(gl); // gl.glEnable(GL10.GL_LIGHTING); gl.glPopMatrix();

// lukisan gl.glPushMatrix(); // gl.glDisable(GL10.GL_LIGHTING); gl.glTranslatef(1.5f, 0.0f, 0.0f); gl.glTranslatef(0.0f, 0.0f, -5.0f); gl.glRotatef(90, 0.0f, 1.0f, 0.0f); gl.glScalef(0.5f, 0.5f, 0.5f); // gl.glRotatef(CurrentAngle, 0.0f, 1.0f, 0.0f); lukisan.draw_lukisan(gl); // gl.glEnable(GL10.GL_LIGHTING); gl.glPopMatrix();

// lukisan2 gl.glPushMatrix(); // gl.glDisable(GL10.GL_LIGHTING); gl.glTranslatef(0.5f, 0.0f, 0.0f); gl.glTranslatef(0.0f, 0.0f, -5.5f); gl.glRotatef(180, 0.0f, 1.0f, 0.0f); gl.glScalef(0.3f, 0.5f, 0.1f); // gl.glRotatef(CurrentAngle, 0.0f, 1.0f, 0.0f); lukisan.draw_lukisan1(gl); // gl.glEnable(GL10.GL_LIGHTING); gl.glPopMatrix();

// PINTU gl.glPushMatrix(); // gl.glDisable(GL10.GL_LIGHTING); gl.glTranslatef(-1.3f, -0.2f, 0.0f); gl.glTranslatef(0.0f, 0.0f, -5.5f); gl.glRotatef(180, 0.0f, 1.0f, 0.0f); gl.glScalef(0.5f, 0.8f, 0.5f); // gl.glRotatef(CurrentAngle, 0.0f, 1.0f,

429

0.0f); pintu.draw_pintu(gl); // gl.glEnable(GL10.GL_LIGHTING); gl.glPopMatrix();

// // buat meja // gl.glPushMatrix(); // // gl.glTranslatef(0.0f, 0.0f, -5.0f); // gl.glScalef(0.5f, 0.5f, 0.5f); // gl.glRotatef(90, 1.0f, 0.0f, 0.0f); // kotak.draw_meja(gl); // gl.glPopMatrix();

// MEJA gl.glPushMatrix(); // gl.glDisable(GL10.GL_LIGHTING); gl.glTranslatef(1.5f, -0.6f, -5.0f); // gl.glScalef(0.4f, 0.05f, 1.0f); // gl.glTranslatef(0.0f, 0.0f, -6.0f); // Translate into the screen // gl.glRotatef(CurrentAngle, 0.0f, 1.0f, 0.0f); // Rotate gl.glRotatef(90, 1.0f, 0.0f, 0.0f); // gl.glRotatef(CurrentAngle, 1.0f, 1.0f, 1.0f ); // gl.glTranslatef(-0.5f,-0.5f,-0.5f); kaki_meja.draw(gl); // gl.glEnable(GL10.GL_LIGHTING); gl.glPopMatrix();

// KAKI MEJA gl.glPushMatrix(); // gl.glDisable(GL10.GL_LIGHTING); gl.glTranslatef(1.6f, -0.8f, -5.0f); gl.glScalef(0.05f, 0.17f, 0.05f); // gl.glTranslatef(0.0f, 0.0f, -6.0f); // Translate into the screen gl.glRotatef(90, 0.0f, 1.0f, 0.0f); // Rotate // gl.glRotatef(CurrentAngle, 1.0f, 1.0f, 1.0f ); // gl.glTranslatef(-0.5f,-0.5f,-0.5f); kaki_meja.draw(gl); // gl.glEnable(GL10.GL_LIGHTING); gl.glPopMatrix();

// Meja 2

gl.glPushMatrix(); // gl.glDisable(GL10.GL_LIGHTING); gl.glTranslatef(0.0f, -0.6f, -5.0f); // gl.glScalef(0.4f, 0.05f, 1.0f); // gl.glTranslatef(0.0f, 0.0f, -6.0f); // Translate into the screen // gl.glRotatef(CurrentAngle, 0.0f, 1.0f, 0.0f); // Rotate

430

gl.glRotatef(90, 1.0f, 0.0f, 0.0f); // gl.glRotatef(CurrentAngle, 1.0f, 1.0f, 1.0f ); // gl.glTranslatef(-0.5f,-0.5f,-0.5f); kaki_meja.draw(gl); // gl.glEnable(GL10.GL_LIGHTING); gl.glPopMatrix();

// KAKI MEJA gl.glPushMatrix(); // gl.glDisable(GL10.GL_LIGHTING); gl.glTranslatef(0.0f, -0.8f, -5.0f); gl.glScalef(0.05f, 0.17f, 0.05f); // gl.glTranslatef(0.0f, 0.0f, -6.0f); // Translate into the screen gl.glRotatef(90, 0.0f, 1.0f, 0.0f); // Rotate // gl.glRotatef(CurrentAngle, 1.0f, 1.0f, 1.0f ); // gl.glTranslatef(-0.5f,-0.5f,-0.5f); kaki_meja.draw(gl); // gl.glEnable(GL10.GL_LIGHTING); gl.glPopMatrix();

// kubus di atas meja gl.glPushMatrix(); // gl.glDisable(GL10.GL_LIGHTING); gl.glTranslatef(0.0f, -0.4f, -5.0f); gl.glScalef(0.1f, 0.1f, 0.1f); // gl.glTranslatef(0.0f, 0.0f, -6.0f); // Translate into the screen gl.glRotatef(CurrentAngle, 0.0f, 1.0f, 0.0f); // Rotate // gl.glRotatef(CurrentAngle, 1.0f, 1.0f, 1.0f ); // gl.glTranslatef(-0.5f,-0.5f,-0.5f); kubus_kecil.draw(gl); // gl.glEnable(GL10.GL_LIGHTING); gl.glPopMatrix();

// kubus di atas meja 2 gl.glPushMatrix(); // gl.glDisable(GL10.GL_LIGHTING); gl.glTranslatef(-0.1f, - 0.4f, -4.5f); gl.glScalef(0.1f, 0.1f, 0.1f); // gl.glTranslatef(0.0f, 0.0f, -6.0f); // Translate into the screen gl.glRotatef(45, 0.0f, 1.0f, 0.0f); // Rotate // gl.glRotatef(CurrentAngle, 1.0f, 1.0f, 1.0f ); // gl.glTranslatef(-0.5f,- 0.5f,-0.5f); kubus_kecil.draw(gl); // gl.glEnable(GL10.GL_LIGHTING);

431

gl.glPopMatrix();

// bola 1 gl.glPushMatrix(); // gl.glDisable(GL10.GL_LIGHTING); gl.glTranslatef(1.6f, -0.4f, -5.0f); gl.glScalef(0.05f, 0.05f, 0.05f); //gl.glRotatef(CurrentAngle, 0, 1, 0);

mEarth.draw(gl); // gl.glEnable(GL10.GL_LIGHTING); gl.glPopMatrix();

// bola 1 gl.glPushMatrix(); // gl.glDisable(GL10.GL_LIGHTING); gl.glTranslatef(1.0f, - 0.4f, -5.0f); gl.glScalef(0.05f, 0.05f, 0.05f); gl.glRotatef(CurrentAngle, 1.0f, 0.0f, 0.0f);

mEarth.draw(gl); // gl.glEnable(GL10.GL_LIGHTING); gl.glPopMatrix();

// LAMPU gl.glPushMatrix(); // gl.glDisable(GL10.GL_LIGHTING); gl.glTranslatef(0.0f, 0.7f, -5.0f); // gl.glRotatef(180, 0.0f, 0.0f, 1.0f); // Rotate

// gl.glTranslatef(0.0f, 0.0f, -6.0f); // Translate into the screen

// gl.glRotatef(0, 0.0f, 1.0f, 0.0f); // Ro- tate gl.glRotatef(CurrentAngle, 0.0f, 1.0f, 0.0f ); // gl.glTranslatef(-0.5f,-0.5f,-0.5f);

// gl.glPushMatrix(); // gl.glRotatef(180, 1.0f, 0.0f, 0.0f); gl.glMaterialf(GL10.GL_BACK, GL10.GL_SHININESS, 256.0f); gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_POSITION, light_position, 0); gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_DIFFUSE, white, 0); gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_AMBIENT, lightAmbient, 0); gl.glLightfv(GL10.GL_LIGHT0, GL10.GL_SPECULAR, white, 0); // gl.glTranslatef (0.0f, 0.0f, -0.5f);

432

// gl.glDisable (GL10.GL_LIGHTING);

// gl.glScalef(0.01f, 0.01f, 0.01f); // transob- ject.draw_kubus(gl); // gl.glEnable (GL10.GL_LIGHTING); // gl.glPopMatrix();

gl.glScalef(0.04f, 0.04f, 0.04f);

mEarth3.draw(gl); // gl.glEnable(GL10.GL_LIGHTING); gl.glPopMatrix();

// penyangga lampu gl.glPushMatrix(); // gl.glDisable(GL10.GL_LIGHTING); gl.glTranslatef(0.0f, 0.8f, -5.0f); gl.glScalef(0.03f, 0.2f, 0.05f); // gl.glTranslatef(0.0f, 0.0f, -6.0f); // Translate into the screen gl.glRotatef(90, 0.0f, 1.0f, 0.0f); // Rotate // gl.glRotatef(CurrentAngle, 1.0f, 1.0f, 1.0f ); // gl.glTranslatef(-0.5f,- 0.5f,-0.5f); kaki_meja.draw(gl); // gl.glEnable(GL10.GL_LIGHTING); gl.glPopMatrix();

if(isOn){ gl.glEnable(GL10.GL_LIGHTING); } // Update the rotational angle after each refresh // re-Calculate animation parameters CurrentAngle1 += AnimateStep1; if (CurrentAngle1 < -360.0) { // CurrentAngle -= 360.0*Math.floor(CurrentAngle/360.0); CurrentAngle1 = 0.0f; CurrentAngle1 += AnimateStep1; } CurrentAngle += AnimateStep; if (CurrentAngle > 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); // Ena- bles 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); // Ena- ble 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, con- text.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); // Disa- ble 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); // Ena- ble 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 Ma- trix // 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 < esRen- der.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 < esRen- der.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 android.content.Context; import android.opengl.GLSurfaceView; import android.util.Log; import android.view.KeyEvent; import 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 GLSur- faceView 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 / ((esRen- der.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()+ (del- taX/getWidth()));

//esRender.setspeedY(esRender.getspeedY()+ (del- taY/getHeight()));

esRen- der.setspeedX(esRender.getspeedX()+ deltaX/100); esRen- der.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) ){ esRen- der.setspeedX(esRender.getspeedX()- 0.05f); } if((esRender.getspeedX()- 0.05f <0) ){ esRender.setspeedX(0.0f); } if((esRender.getspeedY()- 0.05f >=0)){ esRen- der.setspeedY(esRender.getspeedY()- 0.05f); } if((esRender.getspeedY()- 0.05f <0) ){ esRender.setspeedY(0.0f); } Log.v("Test Action KEYCODE_A", "action working"); break; case KeyEvent.KEYCODE_Z: Log.v("Test Action KEYCODE_Z", "action working"); break; } return true; // Event handled } }

ESText.java

// This is a OpenGL ES 1.0 dynamic font rendering sys- tem. It loads actual font // , generates a font map (texture) from them, and allows rendering of // text strings. // // NOTE: the rendering portions of this class uses a sprite batcher in order // provide decent speed rendering. Also, rendering as- sumes a BOTTOM-LEFT // origin, and the (x,y) positions are relative to that,

440

as well as the // bottom-left of the string to render. package com.ligthing; import javax.microedition.khronos.opengles.GL10; import android.content.res.AssetManager; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Typeface; import android.opengl.GLUtils; public class ESText {

//--Constants--// public final static int CHAR_START = 32; // First Character (ASCII Code) public final static int CHAR_END = 126; // Last Character (ASCII Code) public final static int CHAR_CNT = ( ( ( CHAR_END - CHAR_START ) + 1 ) + 1 ); // Character Count (Including Character to use for Unknown)

public final static int CHAR_NONE = 32; // Character to Use for Unknown (ASCII Code) public final static int CHAR_UNKNOWN = ( CHAR_CNT - 1 ); // Index of the Unknown Character

public final static int FONT_SIZE_MIN = 6; // Minumum Font Size (Pixels) public final static int FONT_SIZE_MAX = 180; // Maximum Font Size (Pixels)

public final static int CHAR_BATCH_SIZE = 100; // Number of Characters to Render Per Batch

//--Members--// GL10 gl; // GL10 Instance AssetManager assets; // Asset Manager SpriteBatch batch; // Batch Renderer

int fontPadX, fontPadY; // Font Padding (Pixels; On Each Side, ie. Doubled on Both X+Y Axis)

float fontHeight; // Font Height (Actual; Pixels) float fontAscent; // Font Ascent (Above Baseline; Pixels) float fontDescent; // Font Descent (Below Baseline; Pixels)

int textureId; // Font Texture ID [NOTE: Public for Testing Purposes On-

441

ly!] int textureSize; // Texture Size for Font (Square) [NOTE: Public for Testing Purposes Only!] TextureRegion textureRgn; // Full Texture Region

float charWidthMax; // Character Width (Maximum; Pixels) float charHeight; // Character Height (Maximum; Pixels) final float[] charWidths; // Width of Each Character (Actual; Pixels) TextureRegion[] charRgn; // Region of Each Character (Texture Coordinates) int cellWidth, cellHeight; // Character Cell Width/Height int rowCnt, colCnt; // Number of Rows/Columns

float scaleX, scaleY; // Font Scale (X,Y Axis) float spaceX; // Additional (X,Y Axis) Spacing (Unscaled)

//--Constructor--// // D: save GL instance + asset manager, create ar- rays, and initialize the members // A: gl - OpenGL ES 10 Instance public ESText(GL10 gl, AssetManager assets) { this.gl = gl; // Save the GL10 Instance this.assets = assets; // Save the Asset Manager Instance

batch = new SpriteBatch( gl, CHAR_BATCH_SIZE ); // Create Sprite Batch (with Defined Size)

charWidths = new float[CHAR_CNT]; // Create the Array of Character Widths charRgn = new TextureRegion[CHAR_CNT]; // Create the Array of Character Regions

// initialize remaining members fontPadX = 0; fontPadY = 0;

fontHeight = 0.0f; fontAscent = 0.0f; fontDescent = 0.0f;

textureId = -1; textureSize = 0;

charWidthMax = 0; charHeight = 0;

cellWidth = 0;

442

cellHeight = 0; rowCnt = 0; colCnt = 0;

scaleX = 1.0f; // Default Scale = 1 (Unscaled) scaleY = 1.0f; // Default Scale = 1 (Unscaled) spaceX = 0.0f; }

//--Load Font--// // description // this will load the specified font file, create a texture for the defined // character range, and setup all required values used to render with it. // arguments: // file - Filename of the font (.ttf, .otf) to use. In 'Assets' folder. // size - Requested pixel size of font (height) // padX, padY - Extra padding per character (X+Y Axis); to prevent overlapping characters. public boolean load(String file, int size, int padX, int padY) {

// setup requested values fontPadX = padX; // Set Requested X Axis Padding fontPadY = padY; // Set Requested Y Axis Padding

// load the font and setup paint instance for drawing Typeface tf = Typeface.createFromAsset( assets, file ); // Create the Typeface from Font File Paint paint = new Paint(); // Create Android Paint Instance paint.setAntiAlias( true ); // Enable Anti Alias paint.setTextSize( size ); // Set Text Size paint.setColor( 0xffffffff ); // Set ARGB (White, Opaque) paint.setTypeface( tf ); // Set Typeface

// get font metrics Paint.FontMetrics fm = paint.getFontMetrics(); // Get Font Metrics fontHeight = (float)Math.ceil( Math.abs( fm.bottom ) + Math.abs( fm.top ) ); // Calculate Font Height fontAscent = (float)Math.ceil( Math.abs( fm.ascent ) ); // Save Font Ascent fontDescent = (float)Math.ceil( Math.abs( fm.descent ) ); // Save Font Descent

// determine the width of each character (includ- ing unknown character)

443

// also determine the maximum character width char[] s = new char[2]; // Create Character Array charWidthMax = charHeight = 0; // Reset Character Width/Height Maximums float[] w = new float[2]; // Working Width Value int cnt = 0; // Array Counter for ( char c = CHAR_START; c <= CHAR_END; c++ ) { // FOR Each Character s[0] = c; // Set Character paint.getTextWidths( s, 0, 1, w ); // Get Character Bounds charWidths[cnt] = w[0]; // Get Width if ( charWidths[cnt] > charWidthMax ) // IF Width Larger Than Max Width charWidthMax = charWidths[cnt]; // Save New Max Width cnt++; // Advance Array Counter } s[0] = CHAR_NONE; // Set Unknown Character paint.getTextWidths( s, 0, 1, w ); // Get Character Bounds charWidths[cnt] = w[0]; // Get Width if ( charWidths[cnt] > 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 de- fined characters. when // changing start/end characters

444

(CHAR_START/CHAR_END) this will need adjustment too! if ( maxSize <= 24 ) // IF Max Size is 18 or Less textureSize = 256; // Set 256 Texture Size else if ( maxSize <= 40 ) // ELSE IF Max Size is 40 or Less textureSize = 512; // Set 512 Texture Size else if ( maxSize <= 80 ) // ELSE IF Max Size is 80 or Less textureSize = 1024; // Set 1024 Texture Size else // ELSE IF Max Size is Larger Than 80 (and Less than FONT_SIZE_MAX) textureSize = 2048; // Set 2048 Texture Size

// create an empty bitmap (alpha only) Bitmap bitmap = Bitmap.createBitmap( textureSize, textureSize, Bitmap.Config.ALPHA_8 ); // Create Bitmap Canvas canvas = new Canvas( bitmap ); // Create Canvas for Rendering to Bitmap bitmap.eraseColor( 0x00000000 ); // Set Transparent Background (ARGB)

// calculate rows/columns // NOTE: while not required for anything, these may be useful to have :) colCnt = textureSize / cellWidth; // Calculate Number of Columns rowCnt = (int)Math.ceil( (float)CHAR_CNT / (float)colCnt ); // Calculate Number of Rows

// render each of the characters to the canvas (ie. build the font map) float x = fontPadX; // Set Start Position (X) float y = ( cellHeight - 1 ) - fontDescent - fontPadY; // Set Start Position (Y) for ( char c = CHAR_START; c <= CHAR_END; c++ ) { // FOR Each Character s[0] = c; // Set Character to Draw canvas.drawText( s, 0, 1, x, y, paint ); // Draw Character x += cellWidth; // Move to Next Character if ( ( x + cellWidth - fontPadX ) > textureSize ) { // IF End of Line Reached x = fontPadX; // Set X for New Row y += cellHeight; // Move Down a Row } } s[0] = CHAR_NONE; // Set Character to Use for NONE

445

canvas.drawText( s, 0, 1, x, y, paint ); // Draw Character

// generate a new texture int[] textureIds = new int[1]; // Array to Get Texture Id gl.glGenTextures( 1, textureIds, 0 ); // Generate New Texture textureId = textureIds[0]; // Save Texture Id

// setup filters for texture gl.glBindTexture( GL10.GL_TEXTURE_2D, textureId ); // Bind Texture gl.glTexParameterf( GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST ); // Set Minification Filter gl.glTexParameterf( GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR ); // Set Magnification Filter gl.glTexParameterf( GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE ); // Set U Wrapping gl.glTexParameterf( GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE ); // Set V Wrapping

// load the generated bitmap onto the texture GLUtils.texImage2D( GL10.GL_TEXTURE_2D, 0, bitmap, 0 ); // Load Bitmap to Texture gl.glBindTexture( GL10.GL_TEXTURE_2D, 0 ); // Unbind Texture

// release the bitmap bitmap.recycle(); // Release the Bitmap

// setup the array of character texture regions x = 0; // Initialize X y = 0; // Initialize Y for ( int c = 0; c < CHAR_CNT; c++ ) { // FOR Each Character (On Texture) charRgn[c] = new TextureRegion( textureSize, textureSize, x, y, cellWidth-1, cellHeight-1 ); // Cre- ate Region for Character x += cellWidth; // Move to Next Char (Cell) if ( x + cellWidth > textureSize ) { x = 0; // Reset X Position to Start y += cellHeight; // Move to Next Row (Cell) } }

// create full texture region textureRgn = new TextureRegion( textureSize, tex-

446

tureSize, 0, 0, textureSize, textureSize ); // Create Full Texture Region

// return success return true; // Return Success }

//--Begin/End Text Drawing--// // D: call these methods before/after (respectively all draw() calls using a text instance // NOTE: color is set on a per-batch basis, and fonts should be 8-bit alpha only!!! // A: red, green, blue - RGB values for font (default = 1.0) // alpha - optional alpha value for font (default = 1.0) // R: [none] public void begin() { begin( 1.0f, 1.0f, 1.0f, 1.0f ); // Begin with White Opaque } public void begin(float alpha) { begin( 1.0f, 1.0f, 1.0f, alpha ); // Begin with White (Explicit Alpha) } public void begin(float red, float green, float blue, float alpha) { gl.glColor4f( red, green, blue, alpha ); // Set Color+Alpha gl.glBindTexture( GL10.GL_TEXTURE_2D, textureId ); // Bind the Texture batch.beginBatch(); // Begin Batch } public void end() { batch.endBatch(); // End Batch gl.glColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); // Restore Default Color/Alpha }

//--Draw Text--// // D: draw text at the specified x,y position // A: text - the string to draw // x, y - the x,y position to draw text at (bottom left of text; including descent) // R: [none] public void draw(String text, float x, float y) { float chrHeight = cellHeight * scaleY; // Calculate Scaled Character Height float chrWidth = cellWidth * scaleX; // Calculate Scaled Character Width int len = text.length(); // Get String Length x += ( chrWidth / 2.0f ) - ( fontPadX * scaleX ); // Adjust Start X y += ( chrHeight / 2.0f ) - ( fontPadY * scaleY ); // Adjust Start Y

447

for ( int i = 0; i < len; i++ ) { // FOR Each Character in String int c = (int)text.charAt( i ) - CHAR_START; // Calculate Character Index (Offset by First Char in Font) if ( c < 0 || c >= CHAR_CNT ) // IF Character Not In Font c = CHAR_UNKNOWN; // Set to Unknown Character Index batch.drawSprite( x, y, chrWidth, chrHeight, charRgn[c] ); // Draw the Character x += ( charWidths[c] + spaceX ) * scaleX; // Advance X Position by Scaled Character Width } }

//--Draw Text Centered--// // D: draw text CENTERED at the specified x,y posi- tion // A: text - the string to draw // x, y - the x,y position to draw text at (bottom left of text) // R: the total width of the text that was drawn public float drawC(String text, float x, float y) { float len = getLength( text ); // Get Text Length draw( text, x - ( len / 2.0f ), y - ( getChar- Height() / 2.0f ) ); // Draw Text Centered return len; // Return Length } public float drawCX(String text, float x, float y) { float len = getLength( text ); // Get Text Length draw( text, x - ( len / 2.0f ), y ); // Draw Text Centered (X-Axis Only) return len; // Return Length } public void drawCY(String text, float x, float y) { draw( text, x, y - ( getCharHeight() / 2.0f ) ); // Draw Text Centered (Y-Axis Only) }

//--Set Scale--// // D: set the scaling to use for the font // A: scale - uniform scale for both x and y axis scaling // sx, sy - separate x and y axis scaling factors // R: [none] public void setScale(float scale) { scaleX = scaleY = scale; // Set Uniform Scale } public void setScale(float sx, float sy) { scaleX = sx; // Set X Scale scaleY = sy; // Set Y Scale }

448

//--Get Scale--// // D: get the current scaling used for the font // A: [none] // R: the x/y scale currently used for scale public float getScaleX() { return scaleX; // Return X Scale } public float getScaleY() { return scaleY; // Return Y Scale }

//--Set Space--// // D: set the spacing (unscaled; ie. pixel size) to use for the font // A: space - space for x axis spacing // R: [none] public void setSpace(float space) { spaceX = space; // Set Space }

//--Get Space--// // D: get the current spacing used for the font // A: [none] // R: the x/y space currently used for scale public float getSpace() { return spaceX; // Return X Space }

//--Get Length of a String--// // D: return the length of the specified string if rendered using current settings // A: text - the string to get length for // R: the length of the specified string (pixels) public float getLength(String text) { float len = 0.0f; // Working Length int strLen = text.length(); // Get String Length (Characters) for ( int i = 0; i < strLen; i++ ) { // For Each Character in String (Except Last int c = (int)text.charAt( i ) - CHAR_START; // Calculate Character Index (Offset by First Char in Font) len += ( charWidths[c] * scaleX ); // Add Scaled Character Width to Total Length } len += ( strLen > 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 ar- ea 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 - ( tex- tureSize / 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 = ByteBuff- er.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 <= 360.0f; theta += step) { co = (float)Math.cos(theta * Math.PI / 180.0); si = -(float)Math.sin(theta * Math.PI / 180.0);

v[n][0] = (r2 * co); v[n][1] = (h2); v[n][2] = (r2 * si); v[n + 1][0] = (r1 * co); v[n + 1][1] = (h1); v[n + 1][2] = (r1 * si);

vBuf.put(v[n]); vBuf.put(v[n + 1]);

n += 2;

if(n>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 java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import javax.microedition.khronos.opengles.GL10; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.opengl.GLUtils;

/* * A photo cube with 6 pictures (textures) on its 6 fac- es. */ public class item { private FloatBuffer vertexBuffer; // Vertex Buff- er 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 = ByteBuff- er.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] = BitmapFacto- ry.decodeStream(context.getResources()

.openRawResource(imageFileIDs[face])); int imgWidth = bit- map[face].getWidth(); int imgHeight = bit- map[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; 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

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. 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. left-bottom 1.0f, 1.0f, // B. right- bottom 0.0f, 0.0f, // C. left-top 1.0f, 0.0f // D. right-top }; ByteBuffer tbb = ByteBuff- er.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, tex- tureIDs[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, tex- tureIDs[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, tex- tureIDs[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, tex- tureIDs[face]);

457

// Build Texture from loaded bit- map 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);

GLU- tils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap[face], 0); bitmap[face].recycle(); } }

}

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

/* * A photo cube with 6 pictures (textures) on its 6 fac- es. */ public class kaki_meja { private FloatBuffer vertexBuffer; // Vertex Buff- er 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 = ByteBuff- er.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] = BitmapFacto- ry.decodeStream(context.getResources()

.openRawResource(imageFileIDs[face])); int imgWidth = bit- map[face].getWidth(); int imgHeight = bit- map[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; float faceTop = faceHeight / 2; float faceBottom = -faceTop;

// Define the vertices for this face // float[] vertices = { faceLeft, fa- ceBottom, 0.0f, // 0. //

// left-bottom-front // faceRight, faceBot- tom, 0.0f, // 1. right-bottom-front // faceLeft, faceTop, 0.0f, // 2. left-top-front

459

// 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. left- bottom 1.0f, 1.0f, // B. right- bottom 0.0f, 0.0f, // C. left-top 1.0f, 0.0f // D. right-top }; ByteBuffer tbb = ByteBuff- er.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, tex- tureIDs[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, tex- tureIDs[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, tex- tureIDs[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, tex- tureIDs[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, tex- tureIDs[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, tex- tureIDs[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, tex- tureIDs[face]); // Build Texture from loaded bit- map 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);

GLU- tils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap[face], 0); bitmap[face].recycle(); } } }

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

/* * A photo cube with 6 pictures (textures) on its 6 fac- es. */ public class kubus_kecil { private FloatBuffer vertexBuffer; // Vertex Buff- er

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 = ByteBuff- er.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] = BitmapFacto- ry.decodeStream(context.getResources()

.openRawResource(imageFileIDs[face])); int imgWidth = bit- map[face].getWidth(); int imgHeight = bit- map[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, fa- ceBottom, 0.0f, // 0. //

// left-bottom-front // faceRight, faceBot- tom, 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. left- bottom 1.0f, 1.0f, // B. right- bottom 0.0f, 0.0f, // C. left-top 1.0f, 0.0f // D. right-top }; ByteBuffer tbb = ByteBuff- er.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, tex- tureIDs[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, tex- tureIDs[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, tex- tureIDs[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, tex- tureIDs[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, tex- tureIDs[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, tex- tureIDs[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, tex- tureIDs[face]); // Build Texture from loaded bit- map 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);

GLU- tils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap[face], 0); bitmap[face].recycle(); } } }

kubus.java package com.ligthing;

466

import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import javax.microedition.khronos.opengles.GL10; import android.content.Context; import android.content.res.AssetManager; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import 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 tex- ture-coords-array (NEW) private 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 }; 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 = ByteBuff- er.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 = ByteBuff- er.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, tex- tureIDs[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 = assetManag- er.open("nature.png"); InputStream istream = c.getResources().openRawResource(R.drawable.atap); Bitmap bitmap; try { // Read and decode input as bitmap bitmap = BitmapFacto- ry.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 java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import javax.microedition.khronos.opengles.GL10; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.opengl.GLUtils;

/* * A photo cube with 6 pictures (textures) on its 6 fac- es. */ public class lampu { private FloatBuffer vertexBuffer; // Vertex Buff- er 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 = ByteBuff- er.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] = BitmapFacto- ry.decodeStream(context.getResources()

.openRawResource(imageFileIDs[face])); int imgWidth = bit- map[face].getWidth(); int imgHeight = bit- map[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, fa- ceBottom, 0.0f, // 0. //

// left-bottom-front // faceRight, faceBot- tom, 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. left- bottom 1.0f, 1.0f, // B. right- bottom 0.0f, 0.0f, // C. left-top 1.0f, 0.0f // D. right-top }; ByteBuffer tbb = ByteBuff- er.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, tex- tureIDs[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, tex- tureIDs[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, tex- tureIDs[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, tex- tureIDs[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, tex- tureIDs[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, tex- tureIDs[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, tex- tureIDs[face]); // Build Texture from loaded bit- map 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);

GLU- tils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap[face], 0); bitmap[face].recycle(); } } }

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

474

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

/* * A photo cube with 6 pictures (textures) on its 6 fac- es. */ public class lampu { private FloatBuffer vertexBuffer; // Vertex Buff- er 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 = ByteBuff- er.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] = BitmapFacto- ry.decodeStream(context.getResources()

.openRawResource(imageFileIDs[face]));

475

int imgWidth = bit- map[face].getWidth(); int imgHeight = bit- map[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; float faceTop = faceHeight / 2; float faceBottom = -faceTop;

// Define the vertices for this face // float[] vertices = { faceLeft, fa- ceBottom, 0.0f, // 0. //

// left-bottom-front // faceRight, faceBot- tom, 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. left- bottom 1.0f, 1.0f, // B. right- bottom 0.0f, 0.0f, // C. left-top 1.0f, 0.0f // D. right-top };

476

ByteBuffer tbb = ByteBuff- er.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, tex- tureIDs[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, tex- tureIDs[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, tex- tureIDs[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, tex- tureIDs[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, tex- tureIDs[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, tex- tureIDs[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, tex- tureIDs[face]); // Build Texture from loaded bit- map 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);

GLU- tils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap[face], 0); bitmap[face].recycle(); } } }

MainActivity.java package com.ligthing; import android.opengl.GLSurfaceView; import android.os.Bundle; import android.app.Activity; import android.view.Menu; import android.view.Window; import android.view.WindowManager; public class MainActivity extends Activity {

/** The OpenGL view */ private GLSurfaceView glSurfaceView;

@Override protected void onCreate(Bundle savedInstanceS- tate) { super.onCreate(savedInstanceState); //setContentView(R.layout.activity_main);

// requesting to turn the title OFF requestWindowFeature(Window.FEATURE_NO_TITLE); // making it full screen getWin- dow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREE N, WindowManag- er.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 != 0) { if ((b & 1) != 0) { p *= powerN; } b >>>= 1; powerN = powerN * powerN; }

return p; } }

481

MySphere.java package com.ligthing; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import java.util.ArrayList; import java.util.List; import javax.microedition.khronos.opengles.GL10; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Matrix; import 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 Ar- rayList();

/** Buffer holding the texture coordinates. */ private final List mTextureBuffer = new ArrayList();

482

/** Mapping texture coordinates for the vertices. */ private final List mTexture = new Ar- rayList();

/** 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 < numVertices- PerStrip; 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 - azi- muth / Maths.THREE_SIXTY_DEGREES); texturePoints[texturePos++] = (float) (1 - (al- titude + 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 - azi- muth / Maths.THREE_SIXTY_DEGREES); texturePoints[texturePos++] = (float) (1 - (al- titude + Maths.NINETY_DEGREES) / Maths.ONE_EIGHTY_DEGREES);

azimuth += azimuthStepAngle; }

this.mVertices.add(vertices); this.mTexture.add(texturePoints);

ByteBuffer byteBuffer = ByteBuff- er.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 = ByteBuff- er.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 Con- text context, final int texture) { // final Bitmap bitmap = BitmapFacto- ry.decodeResource(context.getResources(), texture);

final Bitmap bitmap = BitmapFacto- ry.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, // 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 -0.5f, -0.5f, 0.0f // V5 };

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 = ByteBuff- er.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 ja- vax.microedition.khronos.opengles.GL11ExtensionPack; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.opengl.GLES20; import android.opengl.GLUtils; import android.util.Log; public class ObjectBall { private float vertices_circle[]={0.0f,0.0f,0.0f}; private float verti- ces_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 verti- ces 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 verti- ces 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<=2*batas_sudut;teta+=step){ vertices_circle[loop] = (float) ((x- a)*Math.cos((teta/180)*(22/7)) - ((y- b)*Math.sin((teta/180)*(22/7))) + a); vertices_circle[loop+1] = (float) ((x- a)*Math.sin((teta/180)*(22/7)) - ((y- b)*Math.cos((teta/180)*(22/7))) + b); vertices_circle[loop+2]=0; loop+=3;

//mengenerate warna untuk setiap vertex

//vertices_circle_color[loop_color]=(float) ((x- a)*Math.cos((teta/180)*(22/7)) - ((y- b)*Math.sin((teta/180)*(22/7))) + a);

//vertices_circle_color[loop_color+1]=(float) ((x-a)*Math.sin((teta/180)*(22/7)) - ((y- b)*Math.cos((teta/180)*(22/7))) + b);

vertices_circle_color[loop_color]=(float) (Math.cos((teta/180)*(22/7)) ); verti- ces_circle_color[loop_color+1]=(float) (Math.sin((teta/180)*(22/7)));

vertices_circle_color[loop_color+2]=0.5f; vertices_circle_color[loop_color+3]=0.5f; loop_color+=4; } // ======end for generate vertices to circle ======

}

// Point to our vertex buffer, return buffer holding the vertices public static FloatBuffer makeFloatBuffer(float[] arr){ ByteBuffer bb = ByteBuff- er.allocateDirect(arr.length * 4); bb.order(ByteOrder.nativeOrder());

490

FloatBuffer fb = bb.asFloatBuffer(); fb.put(arr); fb.position(0); return fb; }

// Setup index-array buffer. Indices in byte. public static ByteBuffer makeByteBuffer(byte[] arr){ ByteBuffer bb = ByteBuff- er.allocateDirect(arr.length); bb.put(arr); bb.position(0); return bb; }

/** The draw method for the primitive object with the GL context */ public void draw_circle(GL10 gl) {

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

// set the colour for the object circle //gl.glColor4f(0.0f, 0.0f, 1.0f, 1.0f);

//create VBO from buffer with glBuffer- Data() gl.glVertexPointer(3, GL10.GL_FLOAT, 0, make- FloatBuffer(vertices_circle));

//memetakan warna untuk setiap vertex gl.glColorPointer(4, GL10.GL_FLOAT, 0, make- FloatBuffer(vertices_circle_color));

//draw circle as filled shape //gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 1, (int) ((int) 2*batas_sudut/step));

//draw circle contours //gl.glDrawArrays(GL10.GL_LINES, 1, (int) ((int) 2*batas_sudut/step)); // membuat garis putus- putus pada tepi lingkaran //gl.glDrawArrays(GL10.GL_LINES, 1, (int) ((int) 2*batas_sudut/step)); gl.glDrawArrays(GL10.GL_LINE_STRIP, 1, (int) ((int) 2*batas_sudut/step)); //gl.glDrawArrays(GL10.GL_POINTS, 1, (int) ((int) 2*batas_sudut/step));

//Disable the client state before leaving

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

gl.glDisableClientState(GL10.GL_COLOR_ARRAY); }

491

public void draw_circle_color(GL10 gl) {

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

//gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

// set the colour edge for the object circle //gl.glColor4f(0.0f, 0.0f, 1.0f, 1.0f);

//create VBO from buffer with glBuffer- Data() gl.glVertexPointer(3, GL10.GL_FLOAT, 0, make- FloatBuffer(vertices_circle1));

//memetakan warna untuk setiap vertex //gl.glColorPointer(4, GL10.GL_FLOAT, 0, makeFloatBuffer(vertices_circle_color));

//menempelkan tekstur ke objek gl.glEnable(GL10.GL_TEXTURE_2D);

gl.glEnable(GL10.GL_BLEND); gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);

gl.glBindTexture(GL10.GL_TEXTURE_2D, tex- tures_indek[0]); // 4 //gl.glTexCoordPointer(3, GL10.GL_FLOAT, 1, makeFloatBuffer(vertices_circle)); // 5 gl.glTexCoordPointer(3, GL10.GL_FLOAT, 0, makeFloatBuffer(textCoord)); // 5

gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRA Y);

//GL11ExtensionPack gl_ = (GL11ExtensionPack) gl; //GL11 gl11 = (GL11) gl; //gl.glBindTexture(GL10.GL_TEXTURE_2D, tex- tures_indek[0]);

// Set the face rotation //gl.glFrontFace(GL10.GL_CW);

//draw circle as filled shape //gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, (int) ((int) 2*batas_sudut/step)); //gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, (int) ((int) 2*batas_sudut/step)); gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, ba- tas_sudut); //gl.glDrawArrays(GL10.GL_LINE_STRIP, 0, (int) ((int) 2*batas_sudut/step)); //gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 1, 120);

492

//Log.i("Nilai 2*batas_sudut/step : ", ""+2*batas_sudut/step);

//gl.glDrawArrays(GL10.GL_LINE_STRIP, 1, (int) ((int) 2*batas_sudut/step)); //gl.glDrawElements(GL10.GL_TRIANGLES, (int) ((int) 2*batas_sudut/step), // GL10.GL_UNSIGNED_SHORT, makeFloatBuff- er(vertices_circle));

//draw circle contours //gl.glDrawArrays(GL10.GL_LINES, 1, (int) ((int) 2*batas_sudut/step)); // membuat garis putus- putus pada tepi lingkaran //gl.glDrawArrays(GL10.GL_LINE_STRIP, 1, (int) ((int) 2*batas_sudut/step)); //gl.glDrawArrays(GL10.GL_POINTS, 1, (int) ((int) 2*batas_sudut/step));

//Disable the client state before leaving

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

//gl.glDisableClientState(GL10.GL_COLOR_ARRAY); gl.glDisable( GL10.GL_BLEND ); // Disable Alpha Blend gl.glDisable( GL10.GL_TEXTURE_2D ); // Disable Texture Mapping }

public void draw_circle_color(GL10 gl,float red_in, float green_in,float blue_in, float alpha_in) {

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

//gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

// set the colour edge for the object circle gl.glColor4f(red_in, green_in, blue_in, 0.33f); //gl.glColor4f(red_in, green_in, blue_in, alpha_in);

//create VBO from buffer with glBuffer- Data() gl.glVertexPointer(3, GL10.GL_FLOAT, 0, make- FloatBuffer(vertices_circle1));

//memetakan warna untuk setiap vertex //gl.glColorPointer(4, GL10.GL_FLOAT, 0, makeFloatBuffer(vertices_circle_color));

//menempelkan tekstur ke objek //gl.glEnable(GL10.GL_TEXTURE_2D);

//gl.glEnable(GL10.GL_BLEND);

493

//gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);

//gl.glBindTexture(GL10.GL_TEXTURE_2D, textures_indek[0]); // 4 //gl.glTexCoordPointer(3, GL10.GL_FLOAT, 1, makeFloatBuffer(vertices_circle)); // 5 //gl.glTexCoordPointer(3, GL10.GL_FLOAT, 0, makeFloatBuffer(textCoord)); // 5

//gl.glEnableClientState(GL10.GL_TEXTURE_COORD_AR RAY);

//GL11ExtensionPack gl_ = (GL11ExtensionPack) gl; //GL11 gl11 = (GL11) gl; //gl.glBindTexture(GL10.GL_TEXTURE_2D, tex- tures_indek[0]);

// Set the face rotation //gl.glFrontFace(GL10.GL_CW);

gl.glEnable(GL10.GL_BLEND); gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);

//draw circle as filled shape //gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, (int) ((int) 2*batas_sudut/step));

gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, batas_sudut); //gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, (int) ((int) 2*batas_sudut/step)); //gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, batas_sudut); //gl.glDrawArrays(GL10.GL_LINE_STRIP, 0, (int) ((int) 2*batas_sudut/step)); //gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 1, 120); //Log.i("Nilai 2*batas_sudut/step : ", ""+2*batas_sudut/step);

//gl.glDrawArrays(GL10.GL_LINE_STRIP, 1, (int) ((int) 2*batas_sudut/step)); //gl.glDrawElements(GL10.GL_TRIANGLES, (int) ((int) 2*batas_sudut/step), // GL10.GL_UNSIGNED_SHORT, makeFloatBuff- er(vertices_circle));

//draw circle contours //gl.glDrawArrays(GL10.GL_LINES, 1, (int) ((int) 2*batas_sudut/step)); // membuat garis putus- putus pada tepi lingkaran //gl.glDrawArrays(GL10.GL_LINE_STRIP, 1,

494

(int) ((int) 2*batas_sudut/step)); //gl.glDrawArrays(GL10.GL_POINTS, 1, (int) ((int) 2*batas_sudut/step));

//Disable the client state before leaving

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

//gl.glDisableClientState(GL10.GL_COLOR_ARRAY); gl.glDisable( GL10.GL_BLEND ); // Disable Alpha Blend //gl.glDisable( GL10.GL_TEXTURE_2D ); // Disable Texture Mapping }

public void draw_segitiga(GL10 gl) { gl.glFrontFace(GL10.GL_CCW); // Front face in counter-clockwise

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

//gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

// set the colour for the triangle //gl.glColor4f(1.0f, 0.0f, 0.0f, 1.0f);

gl.glVertexPointer(3, GL10.GL_FLOAT, 0, makeFloatBuffer(new float [] {

1.0f, 1.0f, 0.0f, // V3 0.0f, 1.0f, 0.0f, // V2 0.5f, 0.0f, 0.0f, // V1 - first vertex (x,y,z) }));

// Draw the vertices as triangle //gl.glColorPointer(4, GL10.GL_FLOAT, 0, makeFloatBuffer(vertices_color));

//menempelkan tekstur ke objek //gl.glEnable(GL10.GL_TEXTURE_2D);

gl.glEnable(GL10.GL_BLEND); gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);

//gl.glEnableClientState(GL10.GL_TEXTURE_COORD_AR RAY);

gl.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 3);

//Disable the client state before leaving

495

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

//gl.glDisableClientState(GL10.GL_COLOR_ARRAY); gl.glDisable( GL10.GL_BLEND ); // Disable Alpha Blend

}

public void loadBallTexture(GL10 gl, Context con- text) { // Bitmap bitmap = BitmapFacto- ry.decodeResource(context.getResources(), // resource);

Bitmap bitmap = BitmapFacto- ry.decodeStream(context.getResources()

.openRawResource(R.drawable.nature));

gl.glGenTextures(1, textures_indek, 0); gl.glBindTexture(GL10.GL_TEXTURE_2D, tex- tures_indek[0]);

/*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); */

//gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE ); //gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE );

gl.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); gl.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);

//gl.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_REPEAT );

//gl.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_REPEAT );

///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);

GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);

496

bitmap.recycle(); } }

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

/* * A photo cube with 6 pictures (textures) on its 6 fac- es. */ public class PhotoKubus { private FloatBuffer vertexBuffer; // Vertex Buff- er private FloatBuffer texBuffer; // Texture Coords Buffer private int numFaces = 18; 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.lantai1, R.drawable.lumut, R.drawable.plapon, R.drawable.anyar }; private int[] textureIDs = new int[numFaces]; private Bitmap[] bitmap = new Bitmap[numFaces]; private float cubeHalfSize = 1.0f;

// Constructor - Set up the vertex buffer public PhotoKubus(Context context) { // Allocate vertex buffer. An float has 4 bytes

497

ByteBuffer vbb = ByteBuff- er.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] = BitmapFacto- ry.decodeStream(context.getResources()

.openRawResource(imageFileIDs[face])); int imgWidth = bit- map[face].getWidth(); int imgHeight = bit- map[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; float faceTop = faceHeight / 2; float faceBottom = -faceTop;

// Define the vertices for this face // float[] vertices = { faceLeft, fa- ceBottom, 0.0f, // 0. //

// left-bottom-front // faceRight, faceBot- tom, 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. left- bottom 1.0f, 1.0f, // B. right- bottom 0.0f, 0.0f, // C. left-top 1.0f, 0.0f // D. right-top }; ByteBuffer tbb = ByteBuff- er.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, tex- tureIDs[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, tex- tureIDs[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, tex- tureIDs[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, tex- tureIDs[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, tex- tureIDs[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, tex- tureIDs[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, tex- tureIDs[face]); // Build Texture from loaded bit- map 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);

GLU- tils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap[face], 0); bitmap[face].recycle(); } } }

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

/* * A photo cube with 6 pictures (textures) on its 6 fac- es. */ public class pintu { private FloatBuffer vertexBuffer; // Vertex Buff- er 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 = ByteBuff- er.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] = BitmapFacto- ry.decodeStream(context.getResources()

.openRawResource(imageFileIDs[face])); int imgWidth = bit- map[face].getWidth(); int imgHeight = bit- map[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; float faceTop = faceHeight / 2; float 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. left- bottom 1.0f, 1.0f, // B. right- bottom 0.0f, 0.0f, // C. left-top 1.0f, 0.0f // D. right-top }; ByteBuffer tbb = ByteBuff- er.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, tex- tureIDs[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, tex- tureIDs[face]); // Build Texture from loaded bit- map 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);

GLU- tils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap[face], 0); bitmap[face].recycle(); } } }

PrimitivesObject.java package com.ligthing; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import javax.microedition.khronos.opengles.GL10; import 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. right- bottom -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, 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 };

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 verti- ces 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 <= 2 * ba- tas_sudut; teta += step) { vertices_circle[loop] = (float) ((x - a) * Math.cos((teta / 180) * (22 / 7)) - ((y - b) * Math.sin((teta / 180) * (22 / 7))) + a); vertices_circle[loop + 1] = (float) ((x - a) * Math.sin((teta / 180) * (22 / 7)) - ((y - b) * Math.cos((teta / 180) * (22 / 7))) + b); vertices_circle[loop + 2] = 0; loop += 3;

// mengenerate warna untuk setiap vertex vertices_circle_color[loop_color] = (float) ((x - a) * Math.cos((teta / 180) * (22 / 7)) - ((y - b) * Math.sin((teta / 180) * (22 / 7))) + a); vertices_circle_color[loop_color + 1] = (float) ((x - a) * Math.sin((teta / 180) * (22 / 7)) - ((y - b) * Math.cos((teta / 180) * (22 / 7))) + b); vertices_circle_color[loop_color + 2] = 0.5f; vertices_circle_color[loop_color + 3] = 0.5f; loop_color += 4; } // ======end for generate verti- ces to circle // ======

// ======start to generate verti- ces to line // ======x1 = -1.0f; y1 = -1.0f; x2 = 1.0f; y2 = 1.0f;

loop_line = 3; loop_line_color = 4; vertices_line = new float[(int) (2 * (x2 - x1) / step_line) * 3]; vertices_line_color = new float[(int) (2

508

* (x2 - x1) / step_line) * 4];

float m = (y2 - y1) / (x2 - x1); for (x = x1; x <= x2; x += step_line) { vertices_line[loop_line] = (float) (x); vertices_line[loop_line + 1] = (float) (m * (x - x1) + y1); vertices_line[loop_line + 2] = 0; loop_line += 3;

// mengenerate warna untuk setiap vertex verti- ces_line_color[loop_line_color] = (float) (0.5 * x); verti- ces_line_color[loop_line_color + 1] = (float) (0.5 * m * (x - x1) + y1); verti- ces_line_color[loop_line_color + 2] = 1.0f; verti- ces_line_color[loop_line_color + 3] = 1.0f; loop_line_color += 4; } // ======end for generate verti- ces to line ======}

// Point to our vertex buffer, return buffer holding the vertices public static FloatBuffer makeFloatBuffer(float[] arr) { ByteBuffer bb = ByteBuff- er.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_points(GL10 gl) {

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

// set the colour for the points (pem- berian warna untuk titik) gl.glColor4f(0.0f, 0.0f, 1.0f, 1.0f);

// Point to our vertex buffer (mendata nilai lokasi/posisi titik) gl.glVertexPointer(3, GL10.GL_FLOAT, 0, makeFloatBuffer(new float[] { 1.0f, 1.0f, 0.0f, // V1 -

509

first vertex (x,y,z) 1.0f, 0.8f, 0.0f, // V2 1.0f, 0.6f, 0.0f, // V3 1.0f, 0.4f, 0.0f, // V4 1.0f, 0.2f, 0.0f, // V5 1.0f, 0.0f, 0.0f, // V6 1.0f, -0.2f, 0.0f, // V7 1.0f, -0.4f, 0.0f, // V8 1.0f, -0.6f, 0.0f, // V9 1.0f, -0.8f, 0.0f, // V10 1.0f, -1.0f, 0.0f, // V11

0.8f, -1.0f, 0.0f, // V12 0.6f, -1.0f, 0.0f, // V13 0.4f, -1.0f, 0.0f, // V14 0.2f, -1.0f, 0.0f, // V15 0.0f, -1.0f, 0.0f, // V16 -0.2f, -1.0f, 0.0f, // V17 -0.4f, -1.0f, 0.0f, // V18 -0.6f, -1.0f, 0.0f, // V19 -0.7f, -1.0f, 0.0f, // V20 -0.8f, -1.0f, 0.0f, // V21 -1.0f, -1.0f, 0.0f, // V22 }));

// Draw the vertices as points (menggam- bar titik-titik) gl.glDrawArrays(GL10.GL_POINTS, 0, 22);

// Disable the client state before leav- ing

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); // gl.glDisableClientState(GL10.GL_COLOR_ARRAY);

}

public void draw_line(GL10 gl) {

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

// set the colour for the line (pemberian warna untuk garis) gl.glColor4f(0.0f, 0.0f, 1.0f, 1.0f);

// Point to our vertex buffer (mendata nilai lokasi/posisi titik yang // menyusun garis) gl.glVertexPointer(3, GL10.GL_FLOAT, 0, makeFloatBuffer(new float[] { 1.0f, 1.0f, 0.0f, // V1 - first vertex (x,y,z) -1.0f, -1.0f, 0.0f, // V2 - second vertex }));

510

// Draw the vertices as lines (menggambar garis dari titik-titik) gl.glDrawArrays(GL10.GL_LINES, 0, 2); /* * gl.glDrawElements(GL10.GL_LINES, 2, GL10.GL_UNSIGNED_SHORT, * makeFloatBuffer(new float [] { 1.0f, 1.0f, 0.0f, // V1 - first vertex * (x,y,z) -1.0f, -1.0f, 0.0f, // V2 - second vertex })); */

// Disable the client state before leav- ing

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); // gl.glDisableClientState(GL10.GL_COLOR_ARRAY);

}

public void draw_line_color(GL10 gl) {

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

// set the colour for the line (pemberian warna untuk garis) gl.glColor4f(0.0f, 0.0f, 1.0f, 1.0f);

// Point to our vertex buffer (mendata nilai lokasi/posisi titik yang // menyusun garis) gl.glVertexPointer(3, GL10.GL_FLOAT, 0, makeFloatBuffer(vertices_line));

// memetakan warna untuk setiap vertex gl.glColorPointer(4, GL10.GL_FLOAT, 0, makeFloatBuff- er(vertices_line_color));

// Draw the vertices as lines (menggambar garis dari titik-titik) gl.glDrawArrays(GL10.GL_LINE_STRIP, 0, (int) (2 * (x2 - x1) / step_line)); /* * gl.glDrawElements(GL10.GL_LINES, 2, GL10.GL_UNSIGNED_SHORT, * makeFloatBuffer(new float [] { 1.0f, 1.0f, 0.0f, // V1 - first vertex * (x,y,z) -1.0f, -1.0f, 0.0f, // V2 - second vertex })); */

// Disable the client state before leav-

511

ing

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

gl.glDisableClientState(GL10.GL_COLOR_ARRAY);

}

public void draw_circle(GL10 gl) {

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

// set the colour for the object circle gl.glColor4f(1.0f, 0.0f, 0.0f, 1.0f);

// create VBO from buffer with glBuffer- Data() gl.glVertexPointer(3, GL10.GL_FLOAT, 0, makeFloatBuff- er(vertices_circle));

// draw circle as filled shape // gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 1, (int) ((int) // 2*batas_sudut/step));

// draw circle contours // gl.glDrawArrays(GL10.GL_LINES, 1, (int) ((int) 2*batas_sudut/step)); // // membuat garis putus-putus pada tepi lingkaran gl.glDrawArrays(GL10.GL_LINES, 1, (int) ((int) 2 * batas_sudut / step)); // gl.glDrawArrays(GL10.GL_LINE_STRIP, 1, (int) ((int) // 2*batas_sudut/step)); // gl.glDrawArrays(GL10.GL_POINTS, 1, (int) ((int) 2*batas_sudut/step));

// Disable the client state before leav- ing

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); // gl.glDisableClientState(GL10.GL_COLOR_ARRAY); }

public void draw_circle_color(GL10 gl) {

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

// set the colour edge for the object circle gl.glColor4f(0.0f, 0.0f, 1.0f, 1.0f);

512

// create VBO from buffer with glBuffer- Data() gl.glVertexPointer(3, GL10.GL_FLOAT, 0, makeFloatBuff- er(vertices_circle));

// memetakan warna untuk setiap vertex gl.glColorPointer(4, GL10.GL_FLOAT, 0, makeFloatBuff- er(vertices_circle_color));

// draw circle as filled shape // gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 1, (int) ((int) // 2*batas_sudut/step)); gl.glDrawArrays(GL10.GL_LINE_STRIP, 1, (int) ((int) 2 * ba- tas_sudut / step));

// Disable the client state before leav- ing

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

gl.glDisableClientState(GL10.GL_COLOR_ARRAY); }

public void draw_kotak(GL10 gl) {

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

// 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 leav- ing

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

gl.glDisableClientState(GL10.GL_COLOR_ARRAY);

}

public void draw_segitiga(GL10 gl) {

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

513

gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

// set the colour for the triangle gl.glColor4f(1.0f, 0.0f, 0.0f, 1.0f);

gl.glVertexPointer(3, GL10.GL_FLOAT, 0, makeFloatBuffer(new float[] { -0.5f, -0.5f, 0.0f, // V1 - first vertex (x,y,z) 0.5f, -0.5f, 0.0f, // V2 - second vertex 0.0f, 0.5f, 0.0f // V3 - third vertex

}));

// Draw the vertices as triangle gl.glColorPointer(4, GL10.GL_FLOAT, 0, makeFloatBuffer(vertices_color)); gl.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);

// Disable the client state before leav- ing

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

gl.glDisableClientState(GL10.GL_COLOR_ARRAY);

}

// Render the shape quad public void draw_quad(GL10 gl) { // Enable vertex-array and define its buffer

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, makeFloatBuffer(vertices_quad)); // Draw the primitives from the vertex- array directly gl.glPolygonOffset(0.0f, 1.0f); gl.glScalef(0.5f, 0.5f, 0.5f); gl.glColor4f(0.5f, 0.5f, 1.0f, 1.0f); // Set the current color (NEW) gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices_quad.length / 3); //gl.glDrawArrays(GL10.GL_TRIANGLES, 0, vertices_quad.length / 3); //gl.glDrawArrays(GL10.GL_LINES, 0, ver- tices_quad.length / 3);

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY); }

}

514

SpriteBatch.java package com.ligthing; import android.util.FloatMath; import javax.microedition.khronos.opengles.GL10; public class SpriteBatch {

//--Constants--// final static int VERTEX_SIZE = 4; // Vertex Size (in Components) ie. (X,Y,U,V) final static int VERTICES_PER_SPRITE = 4; // Vertices Per Sprite final static int INDICES_PER_SPRITE = 6; // Indices Per Sprite

//--Members--// GL10 gl; // GL Instance Vertices vertices; // Vertices Instance Used for Rendering float[] vertexBuffer; // Vertex Buffer int bufferIndex; // Vertex Buffer Start Index int maxSprites; // Maximum Sprites Allowed in Buffer int numSprites; // Number of Sprites Currently in Buffer

//--Constructor--// // D: prepare the sprite batcher for specified maxi- mum number of sprites // A: gl - the gl instance to use for rendering // maxSprites - the maximum allowed sprites per batch public SpriteBatch(GL10 gl, int maxSprites) { this.gl = gl; // Save GL Instance this.vertexBuffer = new float[maxSprites * VERTICES_PER_SPRITE * VERTEX_SIZE]; // Create Vertex Buffer this.vertices = new Vertices( gl, maxSprites * VERTICES_PER_SPRITE, maxSprites * INDICES_PER_SPRITE, false, true, false ); // Create Rendering Vertices this.bufferIndex = 0; // Reset Buffer Index this.maxSprites = maxSprites; // Save Maximum Sprites this.numSprites = 0; // Clear Sprite Counter

short[] indices = new short[maxSprites * INDICES_PER_SPRITE]; // Create Temp Index Buffer int len = indices.length; // Get Index Buffer Length

515

short j = 0; // Counter for ( int i = 0; i < len; i+= INDICES_PER_SPRITE, j += VERTICES_PER_SPRITE ) { // FOR Each Index Set (Per Sprite) indices[i + 0] = (short)( j + 0 ); // Calculate Index 0 indices[i + 1] = (short)( j + 1 ); // Calculate Index 1 indices[i + 2] = (short)( j + 2 ); // Calculate Index 2 indices[i + 3] = (short)( j + 2 ); // Calculate Index 3 indices[i + 4] = (short)( j + 3 ); // Calculate Index 4 indices[i + 5] = (short)( j + 0 ); // Calculate Index 5 } vertices.setIndices( indices, 0, len ); // Set Index Buffer for Rendering }

//--Begin Batch--// // D: signal the start of a batch. set the texture and clear buffer // NOTE: the overloaded (non-texture) version as- sumes that the texture is already bound! // A: textureId - the ID of the texture to use for the batch // R: [none] public void beginBatch(int textureId) { gl.glBindTexture( GL10.GL_TEXTURE_2D, textureId ); // Bind the Texture numSprites = 0; // Empty Sprite Counter bufferIndex = 0; // Reset Buffer Index (Empty) } public void beginBatch() { numSprites = 0; // Empty Sprite Counter bufferIndex = 0; // Reset Buffer Index (Empty) }

//--End Batch--// // D: signal the end of a batch. render the batched sprites // A: [none] // R: [none] public void endBatch() { if ( numSprites > 0 ) { // IF Any Sprites to Render vertices.setVertices( vertexBuffer, 0, buffer- Index ); // Set Vertices from Buffer vertices.bind(); // Bind Vertices vertices.draw( GL10.GL_TRIANGLES, 0, numSprites * INDICES_PER_SPRITE ); // Render Batched Sprites

516

vertices.unbind(); // Unbind Vertices } }

//--Draw Sprite to Batch--// // D: batch specified sprite to batch. adds vertices for sprite to vertex buffer // NOTE: MUST be called after beginBatch(), and before endBatch()! // NOTE: if the batch overflows, this will render the current batch, restart it, // and then batch this sprite. // A: x, y - the x,y position of the sprite (center) // width, height - the width and height of the sprite // region - the texture region to use for sprite // R: [none] public void drawSprite(float x, float y, float width, float height, TextureRegion region) { if ( numSprites == maxSprites ) { // IF Sprite Buffer is Full endBatch(); // End Batch // NOTE: leave current texture bound!! numSprites = 0; // Empty Sprite Counter bufferIndex = 0; // Reset Buffer Index (Empty) }

float halfWidth = width / 2.0f; // Calculate Half Width float halfHeight = height / 2.0f; // Calculate Half Height float x1 = x - halfWidth; // Calculate Left X float y1 = y - halfHeight; // Calculate Bottom Y float x2 = x + halfWidth; // Calculate Right X float y2 = y + halfHeight; // Calculate Top Y

vertexBuffer[bufferIndex++] = x1; // Add X for Vertex 0 vertexBuffer[bufferIndex++] = y1; // Add Y for Vertex 0 vertexBuffer[bufferIndex++] = region.u1; // Add U for Vertex 0 vertexBuffer[bufferIndex++] = region.v2; // Add V for Vertex 0

vertexBuffer[bufferIndex++] = x2; // Add X for Vertex 1 vertexBuffer[bufferIndex++] = y1; // Add Y for Vertex 1 vertexBuffer[bufferIndex++] = region.u2; // Add U for Vertex 1

517

vertexBuffer[bufferIndex++] = region.v2; // Add V for Vertex 1

vertexBuffer[bufferIndex++] = x2; // Add X for Vertex 2 vertexBuffer[bufferIndex++] = y2; // Add Y for Vertex 2 vertexBuffer[bufferIndex++] = region.u2; // Add U for Vertex 2 vertexBuffer[bufferIndex++] = region.v1; // Add V for Vertex 2

vertexBuffer[bufferIndex++] = x1; // Add X for Vertex 3 vertexBuffer[bufferIndex++] = y2; // Add Y for Vertex 3 vertexBuffer[bufferIndex++] = region.u1; // Add U for Vertex 3 vertexBuffer[bufferIndex++] = region.v1; // Add V for Vertex 3

numSprites++; // Increment Sprite Count } }

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

/* * A photo cube with 6 pictures (textures) on its 6 fac- es. */ public class TextureKubus { private FloatBuffer vertexBuffer; // Vertex Buff- er 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

518

R.drawable.lantai, // index 6 R.drawable.tembok, // index 7 R.drawable.anyar, // 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.lumut

}; private int[] textureIDs = new int[numFaces]; private Bitmap[] bitmap = new Bitmap[numFaces]; private float cubeHalfSize = 1.0f;

// Constructor - Set up the vertex buffer public TextureKubus(Context context) { // Allocate vertex buffer. An float has 4 bytes ByteBuffer vbb = ByteBuff- er.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] = BitmapFacto- ry.decodeStream(context.getResources()

.openRawResource(imageFileIDs[face])); int imgWidth = bit- map[face].getWidth(); int imgHeight = bit- map[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; 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, //

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. 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. left-bottom 1.0f, 1.0f, // B. right- bottom 0.0f, 0.0f, // C. left-top 1.0f, 0.0f // D. right-top }; ByteBuffer tbb = ByteBuff- er.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, tex- 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, tex- tureIDs[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, tex- tureIDs[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, tex- tureIDs[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 bit- map 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);

GLU- tils.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 java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.FloatBuffer; import javax.microedition.khronos.opengles.GL10; import android.opengl.GLES20; public class TransObject {

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 -0.5f, -0.5f, 0.0f // V5 };

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 indi- ces 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 verti- ces_circle_color[]={0.0f,0.0f,0.0f,0.5f}; private float vertices_line[]={0.0f,0.0f,0.0f}; private float verti- ces_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 verti- ces 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<=2*batas_sudut;teta+=step){ vertices_circle[loop] = (float) ((x- a)*Math.cos((teta/180)*(22/7)) - ((y- b)*Math.sin((teta/180)*(22/7))) + a); vertices_circle[loop+1] = (float) ((x- a)*Math.sin((teta/180)*(22/7)) - ((y- b)*Math.cos((teta/180)*(22/7))) + b); vertices_circle[loop+2]=0; loop+=3;

//mengenerate warna untuk setiap vertex vertices_circle_color[loop_color]=(float) ((x-a)*Math.cos((teta/180)*(22/7)) - ((y- b)*Math.sin((teta/180)*(22/7))) + a); verti- ces_circle_color[loop_color+1]=(float) ((x- a)*Math.sin((teta/180)*(22/7)) - ((y-

526

b)*Math.cos((teta/180)*(22/7))) + b); vertices_circle_color[loop_color+2]=0.5f; vertices_circle_color[loop_color+3]=0.5f; loop_color+=4; } // ======end for generate vertices to circle ======

// ======start to generate vertices to line ======x1 = -1.0f; y1 = -1.0f; x2= 1.0f; y2 = 1.0f;

loop_line=3; loop_line_color=4; vertices_line=new float[(int)(2*(x2- x1)/step_line)*3]; vertices_line_color=new float[(int)(2*(x2- x1)/step_line)*4];

float m = (y2-y1)/(x2-x1); for(x=x1;x<=x2;x+=step_line){ vertices_line[loop_line] = (float) (x); vertices_line[loop_line+1] = (float) (m*(x-x1)+y1); vertices_line[loop_line+2]=0; loop_line+=3;

//mengenerate warna untuk setiap vertex verti- ces_line_color[loop_line_color]=(float) (0.5*x); verti- ces_line_color[loop_line_color+1]=(float) (0.5*m*(x- x1)+y1); verti- ces_line_color[loop_line_color+2]=1.0f; verti- ces_line_color[loop_line_color+3]=1.0f; loop_line_color+=4; } // ======end for generate vertices to line ======}

// Point to our vertex buffer, return buffer holding the vertices public static FloatBuffer makeFloatBuffer(float[] arr){ ByteBuffer bb = ByteBuff- er.allocateDirect(arr.length * 4); bb.order(ByteOrder.nativeOrder()); FloatBuffer fb = bb.asFloatBuffer(); fb.put(arr); fb.position(0); return fb; }

// Setup index-array buffer. Indices in byte.

527

public static ByteBuffer makeByteBuffer(byte[] arr){ ByteBuffer bb = ByteBuff- er.allocateDirect(arr.length); bb.put(arr); bb.position(0); return bb; }

/** The draw method for the primitive object with the GL context */

public void draw_kubus(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_kubus));

gl.glEnableClientState(GL10.GL_COLOR_ARRAY); gl.glColorPointer(4, GL10.GL_FLOAT, 0, makeFloatBuffer(colors_kubus)); gl.glDrawElements(GL10.GL_TRIANGLES, in- dices_kubus.length, GL10.GL_UNSIGNED_BYTE, makeByteBuffer(indices_kubus)); //gl.glDrawElements(GL10.GL_LINE_STRIP, indices_kubus2.length, //GL10.GL_UNSIGNED_BYTE, makeByteBuffer(indices_kubus2));

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

gl.glDisableClientState(GL10.GL_COLOR_ARRAY); }

public void draw_points(GL10 gl) {

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

//gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

// set the colour for the points (pem- berian warna untuk titik) gl.glColor4f(0.0f, 0.0f, 1.0f, 1.0f);

// Point to our vertex buffer (mendata nilai lokasi/posisi titik) gl.glVertexPointer(3, GL10.GL_FLOAT, 0, makeFloatBuffer(new float [] { 1.0f, 1.0f, 0.0f, // V1 - first vertex (x,y,z) 1.0f, 0.8f, 0.0f, // V2

528

1.0f, 0.6f, 0.0f, // V3 1.0f, 0.4f, 0.0f, // V4 1.0f, 0.2f, 0.0f, // V5 1.0f, 0.0f, 0.0f, // V6 1.0f, -0.2f, 0.0f, // V7 1.0f, -0.4f, 0.0f, // V8 1.0f, -0.6f, 0.0f, // V9 1.0f, -0.8f, 0.0f, // V10 1.0f, -1.0f, 0.0f, // V11

0.8f, -1.0f, 0.0f, // V12 0.6f, -1.0f, 0.0f, // V13 0.4f, -1.0f, 0.0f, // V14 0.2f, -1.0f, 0.0f, // V15 0.0f, -1.0f, 0.0f, // V16 -0.2f, -1.0f, 0.0f, // V17 -0.4f, -1.0f, 0.0f, // V18 -0.6f, -1.0f, 0.0f, // V19 -0.7f, -1.0f, 0.0f, // V20 -0.8f, -1.0f, 0.0f, // V21 -1.0f, -1.0f, 0.0f, // V22 }));

// Draw the vertices as points (menggam- bar titik-titik) gl.glDrawArrays(GL10.GL_POINTS, 0, 22);

//Disable the client state before leaving

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

//gl.glDisableClientState(GL10.GL_COLOR_ARRAY);

} public void draw_line(GL10 gl) {

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

529

//gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

// set the colour for the line (pemberian warna untuk garis) gl.glColor4f(0.0f, 0.0f, 1.0f, 1.0f);

// Point to our vertex buffer (mendata nilai lokasi/posisi titik yang menyusun garis) gl.glVertexPointer(3, GL10.GL_FLOAT, 0, makeFloatBuffer(new float [] { 1.0f, 1.0f, 0.0f, // V1 - first vertex (x,y,z) -1.0f, -1.0f, 0.0f, // V2 - second vertex }));

// Draw the vertices as lines (menggambar garis dari titik-titik) gl.glDrawArrays(GL10.GL_LINES, 0, 2); /*gl.glDrawElements(GL10.GL_LINES, 2, GL10.GL_UNSIGNED_SHORT, makeFloatBuffer(new float [] { 1.0f, 1.0f, 0.0f, // V1 - first vertex (x,y,z) -1.0f, -1.0f, 0.0f, // V2 - second vertex }));*/

//Disable the client state before leaving

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

//gl.glDisableClientState(GL10.GL_COLOR_ARRAY);

}

public void draw_line_color(GL10 gl) {

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

// set the colour for the line (pemberian warna untuk garis) gl.glColor4f(0.0f, 0.0f, 1.0f, 1.0f);

// Point to our vertex buffer (mendata nilai lokasi/posisi titik yang menyusun garis) gl.glVertexPointer(3, GL10.GL_FLOAT, 0, makeFloatBuffer(vertices_line));

//memetakan warna untuk setiap vertex gl.glColorPointer(4, GL10.GL_FLOAT, 0, make- FloatBuffer(vertices_line_color));

// Draw the vertices as lines (menggambar garis dari titik-titik) gl.glDrawArrays(GL10.GL_LINE_STRIP, 0,

530

(int) (2*(x2-x1)/step_line)); /*gl.glDrawElements(GL10.GL_LINES, 2, GL10.GL_UNSIGNED_SHORT, makeFloatBuffer(new float [] { 1.0f, 1.0f, 0.0f, // V1 - first vertex (x,y,z) -1.0f, -1.0f, 0.0f, // V2 - second vertex }));*/

//Disable the client state before leaving

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

gl.glDisableClientState(GL10.GL_COLOR_ARRAY);

}

public void draw_circle(GL10 gl) {

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

//gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

// set the colour for the object circle gl.glColor4f(1.0f, 0.0f, 0.0f, 1.0f);

//create VBO from buffer with glBuffer- Data() gl.glVertexPointer(3, GL10.GL_FLOAT, 0, make- FloatBuffer(vertices_circle));

//draw circle as filled shape //gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 1, (int) ((int) 2*batas_sudut/step));

//draw circle contours //gl.glDrawArrays(GL10.GL_LINES, 1, (int) ((int) 2*batas_sudut/step)); // membuat garis putus- putus pada tepi lingkaran gl.glDrawArrays(GL10.GL_LINES, 1, (int) ((int) 2*batas_sudut/step)); //gl.glDrawArrays(GL10.GL_LINE_STRIP, 1, (int) ((int) 2*batas_sudut/step)); //gl.glDrawArrays(GL10.GL_POINTS, 1, (int) ((int) 2*batas_sudut/step));

//Disable the client state before leaving

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

//gl.glDisableClientState(GL10.GL_COLOR_ARRAY); }

public void draw_circle_color(GL10 gl) {

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

531

gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

// set the colour edge for the object circle gl.glColor4f(0.0f, 0.0f, 1.0f, 1.0f);

//create VBO from buffer with glBuffer- Data() gl.glVertexPointer(3, GL10.GL_FLOAT, 0, make- FloatBuffer(vertices_circle));

//memetakan warna untuk setiap vertex gl.glColorPointer(4, GL10.GL_FLOAT, 0, make- FloatBuffer(vertices_circle_color));

//draw circle as filled shape gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 1, (int) ((int) 2*batas_sudut/step)); //gl.glDrawArrays(GL10.GL_LINE_STRIP, 1, (int) ((int) 2*batas_sudut/step)); //gl.glDrawElements(GL10.GL_TRIANGLES, (int) ((int) 2*batas_sudut/step), // GL10.GL_UNSIGNED_SHORT, makeFloatBuff- er(vertices_circle));

//draw circle contours //gl.glDrawArrays(GL10.GL_LINES, 1, (int) ((int) 2*batas_sudut/step)); // membuat garis putus- putus pada tepi lingkaran //gl.glDrawArrays(GL10.GL_LINE_STRIP, 1, (int) ((int) 2*batas_sudut/step)); //gl.glDrawArrays(GL10.GL_POINTS, 1, (int) ((int) 2*batas_sudut/step));

//Disable the client state before leaving

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

gl.glDisableClientState(GL10.GL_COLOR_ARRAY); }

public void draw_kotak(GL10 gl) {

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

// 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);

532

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);

}

public void draw_segitiga(GL10 gl) {

gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);

gl.glEnableClientState(GL10.GL_COLOR_ARRAY);

// set the colour for the triangle gl.glColor4f(1.0f, 0.0f, 0.0f, 1.0f);

gl.glVertexPointer(3, GL10.GL_FLOAT, 0, makeFloatBuffer(new float [] { -0.5f, -0.5f, 0.0f, // V1 - first vertex (x,y,z) 0.5f, -0.5f, 0.0f, // V2 - second vertex 0.0f, 0.5f, 0.0f // V3 - third vertex

}));

// Draw the vertices as triangle gl.glColorPointer(4, GL10.GL_FLOAT, 0, makeFloatBuffer(vertices_color)); gl.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);

//Disable the client state before leaving

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

gl.glDisableClientState(GL10.GL_COLOR_ARRAY);

} }

Vertices.java package com.ligthing; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.IntBuffer; import java.nio.ShortBuffer;

533

import javax.microedition.khronos.opengles.GL10; public class Vertices {

//--Constants--// final static int POSITION_CNT_2D = 2; // Number of Components in Vertex Position for 2D final static int POSITION_CNT_3D = 3; // Number of Components in Vertex Position for 3D final static int COLOR_CNT = 4; // Number of Components in Vertex Color final static int TEXCOORD_CNT = 2; // Number of Components in Vertex Texture Coords final static int NORMAL_CNT = 3; // Number of Components in Vertex Normal

final static int INDEX_SIZE = Short.SIZE / 8; // Index Byte Size (Short.SIZE = bits)

//--Members--// // NOTE: all members are constant, and initialized in constructor! final GL10 gl; // GL Instance final boolean hasColor; // Use Color in Vertices final boolean hasTexCoords; // Use Texture Coords in Vertices final boolean hasNormals; // Use Normals in Vertices public final int positionCnt; // Number of Position Components (2=2D, 3=3D) public final int vertexStride; // Vertex Stride (Element Size of a Single Vertex) public final int vertexSize; // Bytesize of a Single Vertex final IntBuffer vertices; // Vertex Buffer final ShortBuffer indices; // Index Buffer public int numVertices; // Number of Vertices in Buffer public int numIndices; // Number of Indices in Buffer final int[] tmpBuffer; // Temp Buffer for Vertex Conversion

//--Constructor--// // D: create the vertices/indices as specified (for 2d/3d) // A: gl - the gl instance to use // maxVertices - maximum vertices allowed in buff- er // maxIndices - maximum indices allowed in buffer // hasColor - use color values in vertices // hasTexCoords - use texture coordinates in ver- tices // hasNormals - use normals in vertices

534

// use3D - (false, default) use 2d positions (ie. x/y only) // (true) use 3d positions (ie. x/y/z) public Vertices(GL10 gl, int maxVertices, int max- Indices, boolean hasColor, boolean hasTexCoords, boolean hasNormals) { this( gl, maxVertices, maxIndices, hasColor, hasT- exCoords, hasNormals, false ); // Call Overloaded Con- structor } public Vertices(GL10 gl, int maxVertices, int max- Indices, boolean hasColor, boolean hasTexCoords, boolean hasNormals, boolean use3D) { this.gl = gl; // Save GL Instance this.hasColor = hasColor; // Save Color Flag this.hasTexCoords = hasTexCoords; // Save Texture Coords Flag this.hasNormals = hasNormals; // Save Normals Flag this.positionCnt = use3D ? POSITION_CNT_3D : POSITION_CNT_2D; // Set Position Component Count this.vertexStride = this.positionCnt + ( hasColor ? COLOR_CNT : 0 ) + ( hasTexCoords ? TEXCOORD_CNT : 0 ) + ( hasNormals ? NORMAL_CNT : 0 ); // Calculate Vertex Stride this.vertexSize = this.vertexStride * 4; // Calculate Vertex Byte Size

ByteBuffer buffer = ByteBuffer.allocateDirect( maxVertices * vertexSize ); // Allocate Buffer for Ver- tices (Max) buffer.order( ByteOrder.nativeOrder() ); // Set Native Byte Order this.vertices = buffer.asIntBuffer(); // Save Vertex Buffer

if ( maxIndices > 0 ) { // IF Indices Required buffer = ByteBuffer.allocateDirect( maxIndices * INDEX_SIZE ); // Allocate Buffer for Indices (MAX) buffer.order( ByteOrder.nativeOrder() ); // Set Native Byte Order this.indices = buffer.asShortBuffer(); // Save Index Buffer } else // ELSE Indices Not Required indices = null; // No Index Buffer

numVertices = 0; // Zero Vertices in Buffer numIndices = 0; // Zero Indices in Buffer

this.tmpBuffer = new int[maxVertices * vertexSize / 4]; // Create Temp Buffer

535

}

//--Set Vertices--// // D: set the specified vertices in the vertex buffer // NOTE: optimized to use integer buffer! // A: vertices - array of vertices (floats) to set // offset - offset to first vertex in array // length - number of floats in the vertex array (total) // for easy setting use: vtx_cnt * (this.vertexSize / 4) // R: [none] public void setVertices(float[] vertices, int offset, int length) { this.vertices.clear(); // Remove Existing Vertices int last = offset + length; // Calculate Last Element for ( int i = offset, j = 0; i < last; i++, j++ ) // FOR Each Specified Vertex tmpBuffer[j] = Float.floatToRawIntBits( verti- ces[i] ); // Set Vertex as Raw Integer Bits in Buffer this.vertices.put( tmpBuffer, 0, length ); // Set New Vertices this.vertices.flip(); // Flip Vertex Buffer this.numVertices = length / this.vertexStride; // Save Number of Vertices //this.numVertices = length / ( this.vertexSize / 4 ); // Save Number of Vertices }

//--Set Indices--// // D: set the specified indices in the index buffer // A: indices - array of indices (shorts) to set // offset - offset to first index in array // length - number of indices in array (from off- set) // R: [none] public void setIndices(short[] indices, int offset, int length) { this.indices.clear(); // Clear Existing Indices this.indices.put( indices, offset, length ); // Set New Indices this.indices.flip(); // Flip Index Buffer this.numIndices = length; // Save Number of Indices }

//--Bind--// // D: perform all required binding/state changes be- fore rendering batches. // USAGE: call once before calling draw() multiple times for this buffer. // A: [none] // R: [none] public void bind() {

536

gl.glEnableClientState( GL10.GL_VERTEX_ARRAY ); // Enable Position in Vertices vertices.position( 0 ); // Set Vertex Buffer to Position gl.glVertexPointer( positionCnt, GL10.GL_FLOAT, vertexSize, vertices ); // Set Vertex Pointer

if ( hasColor ) { // IF Vertices Have Color gl.glEnableClientState( GL10.GL_COLOR_ARRAY ); // Enable Color in Vertices vertices.position( positionCnt ); // Set Vertex Buffer to Color gl.glColorPointer( COLOR_CNT, GL10.GL_FLOAT, vertexSize, vertices ); // Set Color Pointer }

if ( hasTexCoords ) { // IF Vertices Have Texture Coords gl.glEnableClientState( GL10.GL_TEXTURE_COORD_ARRAY ); // Enable Texture Coords in Vertices vertices.position( positionCnt + ( hasColor ? COLOR_CNT : 0 ) ); // Set Vertex Buffer to Texture Coords (NOTE: position based on whether color is also specified) gl.glTexCoordPointer( TEXCOORD_CNT, GL10.GL_FLOAT, vertexSize, vertices ); // Set Texture Coords Pointer }

if ( hasNormals ) { gl.glEnableClientState( GL10.GL_NORMAL_ARRAY ); // Enable Normals in Vertices vertices.position( positionCnt + ( hasColor ? COLOR_CNT : 0 ) + ( hasTexCoords ? TEXCOORD_CNT : 0 ) ); // Set Vertex Buffer to Normals (NOTE: position based on whether color/texcoords is also specified) gl.glNormalPointer( GL10.GL_FLOAT, vertexSize, vertices ); // Set Normals Pointer } }

//--Draw--// // D: draw the currently bound vertices in the ver- tex/index buffers // USAGE: can only be called after calling bind() for this buffer. // A: primitiveType - the type of primitive to draw // offset - the offset in the vertex/index buffer to start at // numVertices - the number of vertices (indices) to draw // R: [none] public void draw(int primitiveType, int offset, int numVertices) { if ( indices != null ) { // IF Indices Exist indices.position( offset ); //

537

Set Index Buffer to Specified Offset gl.glDrawElements( primitiveType, numVertices, GL10.GL_UNSIGNED_SHORT, indices ); // Draw Indexed } else { // ELSE No Indices Exist gl.glDrawArrays( primitiveType, offset, numVer- tices ); // Draw Direct (Array) } }

//--Unbind--// // D: clear binding states when done rendering batch- es. // USAGE: call once before calling draw() multiple times for this buffer. // A: [none] // R: [none] public void unbind() { if ( hasColor ) // IF Vertices Have Color gl.glDisableClientState( GL10.GL_COLOR_ARRAY ); // Clear Color State

if ( hasTexCoords ) // IF Vertices Have Texture Coords gl.glDisableClientState( GL10.GL_TEXTURE_COORD_ARRAY ); // Clear Texture Coords State

if ( hasNormals ) // IF Vertices Have Normals gl.glDisableClientState( GL10.GL_NORMAL_ARRAY ); // Clear Normals State }

//--Draw Full--// // D: draw the vertices in the vertex/index buffers // NOTE: unoptimized version! use bind()/draw()/unbind() for batches // A: primitiveType - the type of primitive to draw // offset - the offset in the vertex/index buffer to start at // numVertices - the number of vertices (indices) to draw // R: [none] public void drawFull(int primitiveType, int offset, int numVertices) { gl.glEnableClientState( GL10.GL_VERTEX_ARRAY ); // Enable Position in Vertices vertices.position( 0 ); // Set Vertex Buffer to Position gl.glVertexPointer( positionCnt, GL10.GL_FLOAT, vertexSize, vertices ); // Set Vertex Pointer

if ( hasColor ) { // IF Vertices Have Color gl.glEnableClientState( GL10.GL_COLOR_ARRAY ); // Enable Color in Vertices

538

vertices.position( positionCnt ); // Set Vertex Buffer to Color gl.glColorPointer( COLOR_CNT, GL10.GL_FLOAT, vertexSize, vertices ); // Set Color Pointer }

if ( hasTexCoords ) { // IF Vertices Have Texture Coords gl.glEnableClientState( GL10.GL_TEXTURE_COORD_ARRAY ); // Enable Texture Coords in Vertices vertices.position( positionCnt + ( hasColor ? COLOR_CNT : 0 ) ); // Set Vertex Buffer to Texture Coords (NOTE: position based on whether color is also specified) gl.glTexCoordPointer( TEXCOORD_CNT, GL10.GL_FLOAT, vertexSize, vertices ); // Set Texture Coords Pointer }

if ( indices != null ) { // IF Indices Exist indices.position( offset ); // Set Index Buffer to Specified Offset gl.glDrawElements( primitiveType, numVertices, GL10.GL_UNSIGNED_SHORT, indices ); // Draw Indexed } else { // ELSE No Indices Exist gl.glDrawArrays( primitiveType, offset, numVer- tices ); // Draw Direct (Array) }

if ( hasTexCoords ) // IF Vertices Have Texture Coords gl.glDisableClientState( GL10.GL_TEXTURE_COORD_ARRAY ); // Clear Texture Coords State

if ( hasColor ) // IF Vertices Have Color gl.glDisableClientState( GL10.GL_COLOR_ARRAY ); // Clear Color State }

//--Set Vertex Elements--// // D: use these methods to alter the values (posi- tion, color, textcoords, normals) for vertices // WARNING: these do NOT validate any values, en- sure that the index AND specified // elements EXIST before using!! // A: x, y, z - the x,y,z position to set in buffer // r, g, b, a - the r,g,b,a color to set in buffer // u, v - the u,v texture coords to set in buffer // nx, ny, nz - the x,y,z normal to set in buffer // R: [none] void setVtxPosition(int vtxIdx, float x, float y) { int index = vtxIdx * vertexStride; // Calculate Actual Index

539

vertices.put( index + 0, Float.floatToRawIntBits( x ) ); // Set X vertices.put( index + 1, Float.floatToRawIntBits( y ) ); // Set Y } void setVtxPosition(int vtxIdx, float x, float y, float z) { int index = vtxIdx * vertexStride; // Calculate Actual Index vertices.put( index + 0, Float.floatToRawIntBits( x ) ); // Set X vertices.put( index + 1, Float.floatToRawIntBits( y ) ); // Set Y vertices.put( index + 2, Float.floatToRawIntBits( z ) ); // Set Z } void setVtxColor(int vtxIdx, float r, float g, float b, float a) { int index = ( vtxIdx * vertexStride ) + posi- tionCnt; // Calculate Actual Index vertices.put( index + 0, Float.floatToRawIntBits( r ) ); // Set Red vertices.put( index + 1, Float.floatToRawIntBits( g ) ); // Set Green vertices.put( index + 2, Float.floatToRawIntBits( b ) ); // Set Blue vertices.put( index + 3, Float.floatToRawIntBits( a ) ); // Set Alpha } void setVtxColor(int vtxIdx, float r, float g, float b) { int index = ( vtxIdx * vertexStride ) + posi- tionCnt; // Calculate Actual Index vertices.put( index + 0, Float.floatToRawIntBits( r ) ); // Set Red vertices.put( index + 1, Float.floatToRawIntBits( g ) ); // Set Green vertices.put( index + 2, Float.floatToRawIntBits( b ) ); // Set Blue } void setVtxColor(int vtxIdx, float a) { int index = ( vtxIdx * vertexStride ) + posi- tionCnt; // Calculate Actual Index vertices.put( index + 3, Float.floatToRawIntBits( a ) ); // Set Alpha } void setVtxTexCoords(int vtxIdx, float u, float v) { int index = ( vtxIdx * vertexStride ) + posi- tionCnt + ( hasColor ? COLOR_CNT : 0 ); // Calculate Actual Index vertices.put( index + 0, Float.floatToRawIntBits( u ) ); // Set U vertices.put( index + 1, Float.floatToRawIntBits( v ) ); // Set V } void setVtxNormal(int vtxIdx, float x, float y, float z) { int index = ( vtxIdx * vertexStride ) + posi- tionCnt + ( hasColor ? COLOR_CNT : 0 ) + ( hasTexCoords

540

? TEXCOORD_CNT : 0 ); // Calculate Actual Index vertices.put( index + 0, Float.floatToRawIntBits( x ) ); // Set X vertices.put( index + 1, Float.floatToRawIntBits( y ) ); // Set Y vertices.put( index + 2, Float.floatToRawIntBits( z ) ); // Set Z } }

Gambar 7.3 Lighting Pada Interior

541

BAB 8 Model Loading & Curve

8.1 Pengertian Model Loading & Curve

Untuk membuat model, kita biasanya membuat dari awal. Tentu hali itu sangatlah merepotkan. Untuk itu diperkenalkan metode model loading, Model Loading merupakan teknik untuk loading/memuat dan merender sebuah gambar dengan format tertentu menggunakan OpenGL tanpa library gambar khusus dan juga termasuk kode yang dibutuhkan untuk melakukan loading data mentah dari gambar Untuk model loading, kita biasanya akan menggunakan format file OBJ, yang keduanya sangat sederhana dan sangat umum. Dan sekali lagi, untuk menjaga kesederhanaan, kita hanya akan berurusan dengan file OBJ yang memiliki 1 UV dan 1 Normal. • Beberapa Software untuk pembuatan model 3D : – Autodesk 3ds Max, Maya – Blender – SketchUp – Cinema4D

Gambar 8.1 Pembuatan Model 3D

Gambar 8.2 Aplikasi Blender

542

Macam OpenGL Model Loading  3DS Loader  MD2 Loader  OBJ Loader  PLY Loader  RAW Loader

8.2 Model Creator

Berikut adalah beberapa software yang digunakan untuk pem- buatan model 3D: 1. Autodesk 3ds Max Sebelumnya lebih dikenal dengan sebutan 3D Studio Max. Soft- ware ini dikembangkan oleh Autodesk Media and Entertainment. Software ini popular digunakan karena dapat digunakan pada platform Windows, kemampuan mengedit yang serba bisa, dan arsitektur plugin yang banyak. 2. Maya Software ini dibuat oleh Alias Systems Corporation yang kemudi- an diakuisisi oleh Autodesk, Inc. Maya digunakan dalam industry film dan TV, juga untuk permainan video computer. Kelebihan dari program ini adalah proses pembuatan animasi yang relatif lebih mudah dibandingkan perangkat 3D lainnya. 3. Blender Blender merupakan software grafis 3D yang gratis dan popular di kalangan desainer. Selain dapat digunakan untuk membuat ani- masi 3D, software ini juga memiliki fitur untuk membuat per- mainan. Blender tersedia untuk berbagai sistem operasi, seperti Microsoft Windows, Mac OS X, Linux, IRIX, Solaris, NetBSD, FreeBSD, dan OpenBSD. Software ini berlisensi GPL dan sum- bernya tersedia secara bebas dan dapat diambil siapa saja. 4. SketchUp Sebelumnya dikenal dengan Sketchup, merupakan soft- ware untuk membuat bentuk-bentuk arsitektural, desain interior, teknik sipil dan mesin, film, serta desain video game. Software ini memiliki dua versi. Versi freeware bernama SketchUp Make, dan versi berbayar merupakan SketchUp Pro. Software ini diklaim mudah digunakan. 5. Cinema4D Software ini dikembangkan oleh MAXON Computer GmbH.

543

8.3 Model Loading

Source Code 8.1 Code Model Loading

SplashActivity.java

package min3d.sampleProject1;

import android.app.ListActivity; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.text.util.Linkify; import android.view.ContextMenu; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ContextMenu.ContextMenuInfo; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.TextView; import an- droid.widget.AdapterView.AdapterContextMenuInfo;

/** * Main menu activity * * @author Lee */ public class SplashActivity extends ListActivity { private final int CONTEXTID_VIEWFILE = 0; private final int CONTEXTID_CANCEL = 1;

private String _baseSourcePath = "http://code.google.com/p/min3d/source/browse/trunk/samp lePro- jects/min3dSampleProject1/src/min3d/sampleProject1/"; class ItemVo { public String filename; public Class cls; public String label;

public ItemVo(String $label, Class $class, String $filename) { label = $label; cls = $class; filename = $filename; } } private ItemVo[] _items = { // new ItemVo("\"Hello, Jupiter\"", ExampleRotatingPlanets.class, "ExampleRotatingPlan- ets.java"),

544

// new ItemVo("Minimal example", Ex- ampleMostMinimal.class, "ExampleMostMinimal.java"), // new ItemVo("Vertex colors", Ex- ampleVertexColors.class, "ExampleVertexColors.java"), // new ItemVo("Texture", ExampleTex- tures.class, "ExampleTextures.java"), // new ItemVo("Usage of Vertices class", ExampleVerticesVariations.class, "ExampleVerti- cesVariations.java"), // new ItemVo("Triangles, lines, points", ExampleRenderType.class, "ExampleRender- Type.java"), // new ItemVo("Camera, frustum (trackball)", ExampleCamera.class, "ExampleCam- era.java"), // new ItemVo("Multiple lights", Ex- ampleMultipleLights.class, "ExampleMultiple- Lights.java"), // new ItemVo("Animating vertices", ExampleAnimatingVertices.class, "ExampleAnimatingVerti- ces.java"), // new ItemVo("Rendering subset of faces", ExampleSubsetOfFaces.class, "ExampleSubsetOfFac- es.java"), // new ItemVo("Assigning textures dy- namically", ExampleAssigningTexturesDynamically.class, "ExampleAssigningTexturesDynamically.java"), // new ItemVo("MIP Mapping (on vs. off)", ExampleMipMap.class, "ExampleMipMap.java"), // new ItemVo("Texture wrapping", Ex- ampleTextureWrap.class, "ExampleTextureWrap.java"), // new ItemVo("Multiple textures", ExampleMultiTexture.class, "ExampleMultiTexture.java"), // new ItemVo("Texture offset", Exam- pleTextureOffset.class, "ExampleTextureOffset.java"), // new ItemVo("3D inside layout", Ex- ampleInsideLayout.class, "ExampleInsideLayout.java"), // new ItemVo("Fog Example", Example- Fog.class, "ExampleFog.java"), // new ItemVo("Transparent GL Sur- face", ExampleTransparentGlSurface.class, "Transparen- tActivity.java"), // new ItemVo("Load model from .obj file", ExampleLoadObjFile.class, "Example- LoadObjFile.java"), // new ItemVo("Load multiple models from .obj file", ExampleLoadObjFileMultiple.class, "Ex- ampleLoadObjFileMultiple.java"), // new ItemVo("Load model from .3ds file", ExampleLoad3DSFile.class, "Example- Load3DSFile.java"), // new ItemVo("Load animated .md2 file", ExampleLoadMD2File.class, "Example- LoadMD2File.java"), // new ItemVo("Keyframe animation", ExampleKeyframeAnimation.class, "ExampleKeyframeAnima- tion.java"), // new ItemVo("Using the accelerome- ter", ExampleAccelerometer.class, "ExampleAccelerome-

545

ter.java") // new ItemVo("Tugas 3 GrafKom", Ex- ampleAccelerometer.class, "ExampleAccelerometer.java"), new ItemVo("Tugas 3 GrafKom", tu- gas.class, "tugas.java") }; @Override public void onCreate(Bundle savedInstanceState) { String[] strings = new String[_items.length]; for (int i = 0; i < _items.length; i++) { strings[i] = _items[i].label; } super.onCreate(savedInstanceState); setContentView(R.layout.splash_activity); setListAdapter(new ArrayAdapter(this, android.R.layout.simple_list_item_1, strings));

TextView tv = (TextView) this.findViewById(R.id.splashTitle); Linkify.addLinks(tv, 0x07); registerForContextMenu(getListView());

// TEST ONLY: // this.startActivity( new Intent(this, Exam- pleTransparentGlSurface.class ) ); } @Override public void onListItemClick(ListView parent, View v, int position, long id) { this.startActivity( new Intent(this, _items[position].cls ) ); } @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); int i = 0; menu.add(0, 0, i++, "project home"); menu.add(0, 1, i++, "author blog"); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { Intent i; switch (item.getItemId()) { case 0: i = new Intent(Intent.ACTION_VIEW); i.setData(Uri.parse( this.getResources().getString(R.string.projectUrl) )); startActivity(i); return true;

case 1: i = new Intent(Intent.ACTION_VIEW); i.setData(Uri.parse(

546

this.getResources().getString(R.string.myBlogUrl) )); startActivity(i); return true; } return false; } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menu- Info); menu.add(0, CONTEXTID_VIEWFILE, 0, "View source on Google Code"); menu.add(0, CONTEXTID_CANCEL, 0, "Can- cel"); } @Override public boolean onContextItemSelected(MenuItem item) { AdapterContextMenuInfo info = (Adapter- ContextMenuInfo) item.getMenuInfo();

switch (item.getItemId()) { case CONTEXTID_VIEWFILE: Intent i = new In- tent(Intent.ACTION_VIEW); String url = _baseSourcePath + _items[ (int)info.id ].filename; i.setData(Uri.parse(url)); startActivity(i); return true; case CONTEXTID_CANCEL: // do nothing return true;

default: return su- per.onContextItemSelected(item); } } }

tugas.java package com.ligthing; package min3d.sampleProject1; import min3d.core.Object3dContainer; import min3d.core.RendererActivity; import min3d.objectPrimitives.SkyBox; import min3d.parser.IParser; import min3d.parser.Parser; import min3d.vos.Light; import min3d.vos.Number3d; import android.content.pm.ActivityInfo; import android.hardware.Sensor;

547

import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.os.Bundle; public class tugas extends RendererActivity { // private final float FILTERING_FACTOR = .3f;

private SkyBox mSkyBox; private SensorManager mSensorManager; private Sensor mAccelerometer; private Number3d mAccVals; private Object3dContainer monster; private Object3dContainer pokemon; // @Override // public void onCreate(Bundle savedInstanceS- tate) { // super.onCreate(savedInstanceState); // setRequestedOrienta- tion(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); // mSensorManager = (SensorManager) getSystem- Service(SENSOR_SERVICE); // mAccelerometer = // mSensorManag- er.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); // mAccVals = new Number3d(); // }

public void initScene() { scene.lights().add(new Light()); mSkyBox = new SkyBox(5.0f, 2); // mSkyBox.addTexture(SkyBox.Face.North, R.drawable.wood_back, "north"); // mSkyBox.addTexture(SkyBox.Face.East, R.drawable.wood_right, "east"); // mSkyBox.addTexture(SkyBox.Face.South, R.drawable.wood_back, "south"); // mSkyBox.addTexture(SkyBox.Face.West, R.drawable.wood_left, "west"); // mSkyBox.addTexture(SkyBox.Face.Up, R.drawable.ceiling, "up"); // mSkyBox.addTexture(SkyBox.Face.Down, R.drawable.floor, "down");

mSkyBox.addTexture(SkyBox.Face.North, R.drawable.gambar_latar, "north"); mSkyBox.addTexture(SkyBox.Face.East, R.drawable.gambar_latar, "east"); mSkyBox.addTexture(SkyBox.Face.South, R.drawable.gambar_latar, "south"); mSkyBox.addTexture(SkyBox.Face.West, R.drawable.gambar_latar, "west"); mSkyBox.addTexture(SkyBox.Face.Up, R.drawable.malam, "up"); mSkyBox.addTexture(SkyBox.Face.Down, R.drawable.tanah, "down");

// mSkyBox.scale().y = 0.8f; // mSkyBox.scale().z = 2.0f;

548

mSkyBox.scale().y = 1.0f; mSkyBox.scale().z = 5.0f; scene.addChild(mSkyBox);

// yang sukses diload // groudon (pokemon) // frog // plant // capsule // rancor (monster) // cube

// Membuat objek pokemon IParser parser1 = Par- ser.createParser(Parser.Type.OBJ, getResources(),

"min3d.sampleProject1:raw/plant_obj", true); parser1.parse();

pokemon = parser1.getParsedObject(); pokemon.scale().x = pokemon.scale().y = pokemon.scale().z = 0.3f; pokemon.position().x = -1.0f; // pokemon.position().y = 0.5f; // pokemon.position().y = -2.5f; pokemon.position().y = -2.0f; pokemon.position().z = -3;

// pokemon.rotation().x = 90; scene.addChild(pokemon);

// Membuat objek MONSTER IParser parserx = Par- ser.createParser(Parser.Type.OBJ, getResources(),

"min3d.sampleProject1:raw/frog_obj", true); parserx.parse(); monster = parserx.getParsedObject(); monster.scale().x = monster.scale().y = monster.scale().z = 0.01f; monster.position().x = 1.5f; // monster.position().y = 0.5f; monster.position().y = -2.0f; // monster.position().y = -2.0f; monster.position().z = -3; scene.addChild(monster);

// mSensorManager.registerListener(this, mAccelerometer, // SensorManager.SENSOR_DELAY_UI); }

// @Override // public void onAccuracyChanged(Sensor sensor, int accuracy) { // // TODO Auto-generated method stub // } // // @Override

549

// public void onSensorChanged(SensorEvent event) { // if (event.sensor.getType() != Sen- sor.TYPE_ACCELEROMETER) // return; // // // low-pass filter to make the movement more stable // mAccVals.x = (float) (-event.values[1] * FILTERING_FACTOR + mAccVals.x * // (1.0 - FILTERING_FACTOR)); // mAccVals.y = (float) (event.values[0] * FILTERING_FACTOR + mAccVals.y * // (1.0 - FILTERING_FACTOR)); // // scene.camera().position.x = mAccVals.x * .2f; // scene.camera().position.y = mAccVals.y * .2f; // // scene.camera().target.x = - scene.camera().position.x; // scene.camera().target.y = - scene.camera().position.y; // }

@Override public void updateScene() { pokemon.rotation().y++; monster.rotation().y++; // objModel.rotation().z++; } }

Gambar 8.3 Model Loading (objek belum diberi texture)

550

8.4 Fractal Curve

Salah satu bentuk kurva adalah Kurva Fraktal, dimana merupakan sebuah objek dengan properti kesamaan diri yang dihasilkan oleh algoritma rekursif atau iteratif.Ini berarti citra fraktal dibuat dengan menyalin bagian kecil dari dirinya sendiri. Melukis objek menggunakan konsep fraktal dapat menghemat ukuran penyimpanan, jika dibandingkan dengan penyimpanan gambar dalam format bitmap. Objek tertentu juga dapat dibuat dengan pola yang tidak sama, misalkan pohon dengan panjang cabang-cabangnya dibuat bervariasi, dapat diatasi dengan pemberian unsur acak ke dalam algoritma fraktal, sehingga hasilnya lebih alami. Ini merupakan perpaduan seni dan matematika. Kelebihan penggunaan kurva fraktal dalam Grafika Komputer adalah karena banyak objek nyata dalam dunia tidak hanya dapat diwakili dengan prisma dan elips sederhana, misalnya kurva matematika yang tetap (sin, cos, etc).Walaupun kurva dapat menyatakan fenomena alam, namun jika didasarkan pada pembuatan kurva, maka objek yang dibuat bisa menjadi sangat komplek.Fraktal sangat berguna untuk mewakili bentuk alami seperti pohon, gunung, air, lapangan, awan dan lain-lain.Jenis Kurva: 1. Kurva Fraktal Koch Langkah-langkah dari Kurva Koch: a. Dimulai dengan sebuah garis lurus:

Gambar 8.4 Garis Lurus b. Membagi garis lurus menjadi 3 bagian:

Gambar 8.5 Garis Lurus yang telah dibagi menjadi 3 bagian c. Muncul bentuk segitiga garis dibagian tengah garis lurus yang sudah dibagi mejadi 3 bagian:

Gambar 8.6 Garis Lurus yang telah dibentuk segitiga di tengah bagiannya

551

Gambar 8.7 Kurva Fraktal Koch 2. Kurva Fraktal LindenMayer (L System)

Gambar 8.8 Kurva Fraktal LindenMayer (L System) 3. Kurva Fraktal Polinom Dalam matematika, polinomial atau suku banyak (juga ditulis sukubanyak) adalah pernyataan matematika yang melibatkan jumlahan perkalian pangkat dalam satu atau lebih variabel dengan koefisien. Sebuah polinomial dalam satu variabel dengan koefisien konstan memiliki bentuk seperti berikut:

552

Pangkat tertinggi pada suatu polinomial menunjukkan orde atau derajat dari polinomial tersebut.Sebuah fungsi polinomial dalam satu variabel real dapat dinyatakan dalam grafik fungsi antara lain:  Grafik dari polinomial nol f(x) = 0, adalah sumbu x.  Grafik dari polinomial berderajat nol f(x) = a0, dimana a0 ≠ 0, adalah garis horizontal dengan y memotong a0.  Grafik dari polinomial berderajat satu (atau fungsi linear) f(x) = a0 + a1x , dengan a1 ≠ 0, adalah berupa garis miring dengan y memotong di a0 dengan kemiringan sebesar a1.  Grafik dari polinomial berderajat dua 2 f(x) = a0 + a1x + a2x , dengan a2 ≠ 0, adalah berupa parabola.  Grafik dari polinomial berderajat tiga 2 3 f(x) = a0 + a1x + a2x , + a3x , dengan a3 ≠ 0, adalah berupa kurva pangkat 3.  Grafik dari polinomial berderajat dua atau lebih 2 n f(x) = a0 + a1x + a2x + ... + anx , dengan an ≠ 0 and n ≥ 2, adalah berupa kurva non-linear. Ilustrasi dari grafik-grafik tersebut adalah di bawah ini:

Gambar 8.9 Polinomial berderajat 2 Polinomial berderajat 2:

f(x) = x2 - x - 2 = (x+1)(x-2)

553

Gambar 8.10 Polinomial berderajat 3 Polinomial berderajat 3: f(x) = x3/4 + 3x2/4 - 3x/2 - 2 = 1/4 (x+4)(x+1)(x-2)

Gambar 8.11 Polinomial berderajat 4 Polinomial berderajat 4:

f(x) = 1/14 (9Fx+4)(x+1)(x-1)(x-3) + 0.5

Gambar 8.12 Polinomial berderajat 5 Polinomial berderajat 5:

554

f(x) = 1/20 (x+4)(x+2)(x+1)(x-1)(x-3) + 2

Gambar 8.13 Polinomial berderajat 6 Polinomial berderajat 6:

f(x) = 1/30 (x+3.5)(x+2)(x+1)(x-1)(x-3)(x-4) + 2

Gambar 8.14 Polinomial berderajat 7 Polinomial berderajat 7:

f(x) = (x-3)(x-2)(x-1)(x)(x+1)(x+2)(x+3)

4. Kurva Fraktal SetMandelBrot Fraktal Mandelbrot berarti sebuah objek dibagi menjadi kepingan-kepingan atau bagian-bagian yang tidak berketentuan.Ide ini muncul, karena objek awan tidaklah seperti bola, garis pantai tidaklah seperti tepian lingkaran, kulit kayu tidaklah licin, dan juga lintasan cahaya bukanlahmerupakan garis lurus.ContohBentuk MandelBrot:

555

Gambar 8.15 Kurva Fraktal Set MandelBrot 5. Kurva Fraktal SetJulia SetJulia merupakan bentuk lain dari fraktal yang kompleks. Perbedaan antara Mandelbrot Set dengan Julia Set dapat dilihat pada fungsi iteratifnya. Kalau pada Mandelbrot set, iterasi, dimulai dari z0 = 0 dan nilai konstanta k nya berbeda-beda. Pada Julia Set konstanta k tetap pada nilai tertentu dan nilai awal z0 berbeda-beda. Dengan demikian Mandelbrot Set berada pada bidang k sedangkan Julia Set berada pada bidang z. Fungsi 2 Iteratif (zn+1 = zn + k ):  Sistem menghasilkan masing-masing output dengan mengkuadratkan input dan menambahkan dengan k.  Orbit input menentukan bagaimana nilai digambarkan. Orbit adalah set nilai output sebagai fungsi yang diiterasi. 2  Contoh : f(zn+1)= zn + 2 dengan z0=0, maka urutan outputnya adalah 2, 6, 38, 1446, … Contoh Bentuk Set Julia :

Gambar 8.16 Kurva Set Julia 1

556

Gambar 8.17 Kurva Set Julia 2 Rumus Fractal Julia:

2 Misal diketahui Z0 = 0 , K = 0,1 + 0,6i, i =-1 dan Iterasi Max = 3, maka

Z1=Z2+Z3 ?

2 Z1=Z0 + k = 02+0,1+0,6i = 0,1 +0,6i Sehingga x,y = (0,1 ; 0,6)

2 Z2=Z1 + k = (0,1 +0,6i)2 +0,1+0,6i = 0.01+0.12i+0.36i2 + 0,1+0,6i = 0.11+0.72i+0.36i2 = -0.25+0.72i Sehingga x,y = (-0.25 ; 0.72)

2 Z3=Z2 + k = (-0.25+0.72i)2 +0,1+0,6i = 0.0625 - 0.36i + 0.5184i + 0.1+0.6i = -0.3559 + 0.24i Sehingga x,y = (-0.3559 ; 0,24)

557