bab 4 viewing / camera -...

Post on 16-Mar-2019

230 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

300

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.

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]

Pusat Proyeksi pada titik tak terhingga

Bidang Proyeksi

B

C

D

A

B’

C’

D’

A’

301

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

302

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

303

……………………………………….. • 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.

304

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

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,

nxvu

initv

initvvadalahinitvvektorunitnnupupinitv

initn

initnnadalahinitnvektorunitrlainitn

_

_)(_,*_

_

_)(_,_

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:

110001

Pz

Py

Px

nrnnn

vrvvv

uruuu

Qn

Qv

Qu

zyx

zyx

zvx

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

305

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:

n

n

v

n

n

u

e

Q

Qv

e

Q

Qu

1

*,

1

*

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.

306

Jawab: Mencari sistem koordinat UVN:

)88.0,01.0,46.0())56.032.0(),2.019.0(),16.03.0((

)))8.0(*)7.0((

))6.0(*)53.0(()),38.0(*)53.0(())27.0(*)7.0((),27.0(*)6.0()38.0(*)8.0((

38.06.07.0

27.08.053.0

)38.0,6.0,7.0(

36.0

)23.0,36.0,42.0(

05.013.018.0

)23.0,36.0,42.0(

)23.0()36.0()42.0(

)23.0,36.0,42.0(

|_|

_

)23.0,36.0,42.0()23.0,64.0,42.0()0,1,0(_

))27.0(*8.0),8.0(*8.0),53.0(*8.0()0,1,0()27.0,8.0,53.0)(8.0()0,1,0(_

)27.0,8.0,53.0(*))27.0(*0)8.0(*1)53.0(*0()0,1,0(*)(_

)27.0,8.0,53.0(14

1,

14

3,

14

2

)1()3()2(

)1,3,2(

|_|

_

)1,3,2()1,3,2()0,0,0(_

222

222

u

u

kji

nvu

initv

initvv

initv

initv

nnupupinitv

initn

initnn

rlainitn

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

Vertex tX=p-r t

Y=p-r t

Z=p-r

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

Qu=t•u Q

v=t•v Q

n=t•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*):

307

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

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

v*

u*

308

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

309

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

310

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 {

311

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

312

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

313

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

314

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;

}

}

315

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;

}

316

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

317

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.

318

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

vertices

image

geometry pipeline

pixel pipeline

rasterizer

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

319

(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

320

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

321

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;

322

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

323

// 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( "Roboto-Regular.ttf", 14, 2, 2

); // Create Font (Height: 14 Pixels / X+Y Padding 2

Pixels)

324

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

}

325

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;

}

}

326

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

327

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

328

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

}

}

329

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

*/

330

@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

331

};

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

332

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

333

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;

334

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

335

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

336

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

337

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

338

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

}

}

339

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;

340

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

341

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

342

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

343

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-

344

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

}

345

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;

346

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

347

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

348

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

}

}

349

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

*/

350

@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

};

351

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

352

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;

353

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;

}

354

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

355

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

356

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

357

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

358

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

}

}

359

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

360

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

361

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

362

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

}

363

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

364

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

365

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

366

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

367

}

}

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;

368

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

}

369

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

370

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

371

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

372

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

373

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<FloatBuffer> mVertexBuffer = new

ArrayList<FloatBuffer>();

/** The vertices for the sphere. */

private final List<float[]> mVertices = new Ar-

rayList<float[]>();

/** Buffer holding the texture coordinates. */

private final List<FloatBuffer> mTextureBuffer = new

ArrayList<FloatBuffer>();

/** Mapping texture coordinates for the vertices. */

private final List<float[]> mTexture = new Ar-

rayList<float[]>();

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

374

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

375

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

}

376

/**

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

}

}

377

Gambar 5.11 Texture Mapping Pada Bola

378

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

379

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)

380

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)

381

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;

382

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

383

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

384

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

385

// 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() {

386

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;

387

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

388

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

389

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;

390

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

391

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

};

392

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]

393

= (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-

394

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

}));

395

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

396

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,

397

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

398

}

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

399

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

400

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

401

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

}

}

402

}

@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

403

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;

404

/**

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

405

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

406

}

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

407

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

408

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)

409

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

410

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

411

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;

412

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

413

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

414

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

415

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;

416

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

417

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<FloatBuffer> mVertexBuffer = new

ArrayList<FloatBuffer>();

/** The vertices for the sphere. */

private final List<float[]> mVertices = new Ar-

rayList<float[]>();

/** Buffer holding the texture coordinates. */

private final List<FloatBuffer> mTextureBuffer = new

ArrayList<FloatBuffer>();

/** Mapping texture coordinates for the vertices. */

private final List<float[]> mTexture = new Ar-

rayList<float[]>();

/** The texture pointer. */

private final int[] mTextures = new int[1];

418

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

419

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

420

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.

421

gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);

gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

}

}

Gambar 6.4 Blending Pada Bola

422

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.

423

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

424

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 Ө

Gambar 7.2 Normal Vector

Untuk mndefinisikan vektor normal, dapat menggunakan perintah sebagai berikut :

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

a

b

a x b

)()(

)()(

)()(

b x a

yxyx

zxzx

zyzy

zyx

zyx

abba

baab

abba

bbb

aaa

kji

425

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

426

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,

427

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,

428

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

429

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,

430

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

431

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

432

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

433

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

}

}

434

@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

435

//

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

436

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

437

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;

}

}

438

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

439

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

440

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

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

441

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-

442

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;

443

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)

444

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

445

(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

446

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-

447

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

448

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

}

449

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

450

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

}

}

451

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

452

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

453

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

454

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

455

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

456

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

457

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

458

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

459

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

460

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

461

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

462

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

463

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;

464

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

465

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

466

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

467

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

468

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

469

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

470

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

471

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;

472

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

473

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

474

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

475

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

476

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

};

477

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

478

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,

479

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

480

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;

481

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

482

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<FloatBuffer> mVertexBuffer = new

ArrayList<FloatBuffer>();

/** The vertices for the sphere. */

private final List<float[]> mVertices = new Ar-

rayList<float[]>();

/** Buffer holding the texture coordinates. */

private final List<FloatBuffer> mTextureBuffer = new

ArrayList<FloatBuffer>();

483

/** Mapping texture coordinates for the vertices. */

private final List<float[]> mTexture = new Ar-

rayList<float[]>();

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

484

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

485

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

486

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

487

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

488

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

489

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;

}

490

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

491

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

}

492

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

493

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

494

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

495

(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

496

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

497

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

498

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

499

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

}

500

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

501

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

502

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++) {

503

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

504

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

505

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

506

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

507

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

508

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

509

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

510

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

}));

511

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

512

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

513

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

514

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

}

}

515

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

516

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

517

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

518

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

519

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

520

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

521

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

522

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

523

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;

524

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

525

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

526

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-

527

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.

528

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

529

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

530

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

531

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

532

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

533

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;

534

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

535

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

536

}

//--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() {

537

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

538

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

539

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

540

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

541

? 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

542

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

543

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 Microsoft 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 Google 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.

544

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"),

545

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

546

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<String>(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(

547

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;

548

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;

549

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

550

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

551

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

552

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:

553

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 f(x) = a0 + a1x + a2x2, dengan a2 ≠ 0, adalah berupa parabola.

Grafik dari polinomial berderajat tiga f(x) = a0 + a1x + a2x2, + a3x3, dengan a3 ≠ 0, adalah berupa kurva pangkat 3.

Grafik dari polinomial berderajat dua atau lebih f(x) = a0 + a1x + a2x2 + ... + anxn , 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)

554

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:

555

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:

556

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 Iteratif (zn+1 = zn

2 + 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.

Contoh : f(zn+1)= zn2 + 2 dengan z0=0, maka urutan outputnya

adalah 2, 6, 38, 1446, …

Contoh Bentuk Set Julia :

Gambar 8.16 Kurva Set Julia 1

557

Gambar 8.17 Kurva Set Julia 2

Rumus Fractal Julia:

Misal diketahui Z0 = 0 , K = 0,1 + 0,6i, i2=-1

dan Iterasi Max = 3, maka

Z1=Z2+Z3 ?

Z1=Z02 + k

= 02+0,1+0,6i

= 0,1 +0,6i

Sehingga x,y = (0,1 ; 0,6)

Z2=Z12 + 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)

Z3=Z22 + 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)

top related