• Tidak ada hasil yang ditemukan

BAB 4 Viewing Camera - Part 2 of 3 dari Modul Ajar Grafika Komputer Pada Android v5

N/A
N/A
Protected

Academic year: 2018

Membagikan "BAB 4 Viewing Camera - Part 2 of 3 dari Modul Ajar Grafika Komputer Pada Android v5"

Copied!
258
0
0

Teks penuh

(1)

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’

(2)

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)

(3)

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,

ouble c_x, GLdouble c_y, GLdouble c_z, GLdouble u_x,

GLd-ouble u_y, GLdGLd-ouble 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();

(4)

………..

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

x

,n

y

,n

z

).

Sumbu v sebagai arah atas, sumbu u sebagai arah horisontal. (v

n), (u ∟ n) dan (u ∟ v)

(5)

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

x

, r

y

, r

z

), lookAt di titik la(la

x

, la

y

, la

z

) dan UpVector di titik up(up

x

,up

y

,up

z

). Sehingga,

n

x

v

u

init

v

init

v

v

adalah

init

v

vektor

unit

n

n

up

up

init

v

init

n

init

n

n

adalah

init

n

vektor

unit

r

la

init

n

_

_

)

(

_

,

*

_

_

_

)

(

_

,

_

Memindahkan titik koordinat dunia P(P

x

,P

y

,P

z

) ke koordinat

ka-mera sintetik Q(Q

u

,Q

v

,Q

n

). Titik Q dapat diperoleh melalui :

t(t

x

,t

y

,t

z

) = P - r

Q

u

= t

u, Q

v

= t

v dan Q

n

= t

n

Q

u

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

u

,Q

v

,Q

n

) yang

merupakan transformasi dari titik P(4,7,2) di koordinat dunia !

Jawab

:

t(t

x

,t

y

,t

z

) = P - r = (4-2,7-3,2-(-1)) =(2,4,3)

Q

u

= t • u =(2,4,3) • (

-1,0,0) = 2*(-1)+4*(0)+3*(0)=-2

Q

v

= t • v =(2,4,3) • (0,0.8,0.6) = 2*(0)+4*(0.8)+3*(0.6)=5

Q

n

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

1

1

0

0

0

1

Pz

Py

Px

n

r

n

n

n

v

r

v

v

v

u

r

u

u

u

Qn

Qv

Qu

z y x z y x z v x
(6)

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

Q

v

e

Q

Q

u

1

*

,

1

*

Mata/ eye terletak di (0, 0, e

n

), dengan syarat e

n

> n

z

dan e

n

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

(7)

Jawab:

Mencari sistem koordinat UVN:

) 88 . 0 , 01 . 0 , 46 . 0 ( )) 56 . 0 32 . 0 ( ), 2 . 0 19 . 0 ( ), 16 . 0 3 . 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 . 0 6 . 0 7 . 0 27 . 0 8 . 0 53 . 0 ) 38 . 0 , 6 . 0 , 7 . 0 ( 36 . 0 ) 23 . 0 , 36 . 0 , 42 . 0 ( 05 . 0 13 . 0 18 . 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 ( _ 2 2 2 2 2 2                                                                                                              u u k j i n v u init v init v v init v init v n n up up init v init n init n n r la init n

la = (0,0,0) dan r = (2,3,1)

n = (-0.53,-0.8,-0.27)

v = (-0.7,0.6,-0.38)

u = (0.46,-0.01,-0.88)

Transformasi vertex ke sistem UVN:

Vertex

t

X

=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

Q

u

=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

(8)

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*

(9)

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

(10)

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

(11)

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

(12)

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

(13)

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

(14)

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

(15)

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

(16)

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

(17)

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

}

(18)

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.

(19)

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

(20)

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

(21)

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

(22)

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

(23)

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

(24)

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

(25)

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

(26)

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

(27)

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

(28)

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

(29)

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

}

(30)

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

/**

(31)

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

(32)

};

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;

(33)

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

(34)

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;

(35)

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

(36)

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

}

(37)

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

(38)

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

(39)

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

(40)

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

(41)

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

(42)

gl.glPushMatrix();

gl.glLineWidth(1.0f);

gl.glEnable(GL10.GL_LINE_SMOOTH); //bounds.set(x - radius, y - radi-us, x + radiradi-us, 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 + radiradi-us, 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)

(43)

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

(44)

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

(45)

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;

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

(46)

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

(47)

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

(48)

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

(49)

(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

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

}

(50)

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

/**

(51)

@O

Gambar

Gambar synthetic camera dari vertex hasil transformasi perspek-tif (u*,v*):
Gambar 4.8 Ilustrasi Multiple View Object
Gambar 4.9 Multiple View Object
Gambar 5.1 Texture Mapping
+7

Referensi

Dokumen terkait