[Android] OpenGL ES에서 텍스쳐맵핑용 비트맵 생성

몇일전.. 안드로이드에서 OpenGL ES의 텍스쳐 맵핑을 살펴보고 실습을 해보면서.. 아무리 해도 텍스쳐가 맵핑되지 않았습니다.. 일단 OpenGL에서 텍스쳐맵핑을 위한 OpenGL의 API의 사용순서에 문제가 있겠거니.. 하며 문제를 파악해 나갔지만.. 도통 모르겠다 싶었구요.. 그러던중.. 문제를 해결.. ㅜㅜ

텍스쳐 맵핑을 하기위한 준비 과정으로 먼저 Bitmap 객체를 하나 생성해야 하는데.. 아래의 코드를 통해 Bitmap 객체를 생성했었습니다.

Bitmap bitmap = 
    BitmapFactory.decodeResource(context.getResources(), R.drawable.texture);

이 한줄로 비트맵을 포맷에 상관없이 읽을 수 있는 안드로이드의 API에 감탄을 했던것같은데.. 바로 문제는 여기에 있었습니다.. 이 코드를 아래 코드로 변경해야 텍스쳐가 맵핑됩니다.

Bitmap bitmap = null;
InputStream is = context.getResources().openRawResource(R.drawable.texture);
try {
    bitmap = BitmapFactory.decodeStream(is);
} finally {
    try {
        is.close();
        is = null;
    } catch(IOException e) {
        //.
    }
}

감탄했던 단 한줄의 코드 대신.. 원시 데이터로써 비트맵을 읽어 스트림을 만들고 이 스트림을 통해 비트맵을 만드는 제법 복잡다단한 방법이 바로 옳바른 방법이였습니다.. 아래는 그토록 보고 싶어라 했던 텍스쳐가 맵핑된 화면 결과…

사용자 삽입 이미지
흠…. 답답했던 때가 언제었냐는듯.. 눈이 맑아집니다.. ㅎㅎ 만약 첫번째 방식으로 하여 텍스쳐맵핑이 않되시는 분이 계시다면 두번째 방법으로 접근해 보시기 바랍니다.

[Android] 사용자 정의 이벤트 추가

자바에서 사용자 정의 이벤트를 추가하는 방법에 대한 글(자바에서 사용자정의 이벤트 추가하기)을 남긴 적이 있습니다. 그 글에서 소개한 사용자 정의 이벤트 추가 방식은 안드로이드에서는 추천하지 않는다는 글로 정리를 했습니다.

안드로이드에서는 어떤 식으로 사용자 정의 이벤트를 남기면 좋을까에 대한 것이 이 글의 주제입니다. 일반적인 자바에서 사용자 정의 이벤트는 이벤트 리스트에 여러개의 이벤트를 등록하게 됩니다. 예를 들어서 특정한 뷰에 대한 마우스 클릭에 대한 이벤트라면.. 여러개의 이벤트를 등록하게 하는 방식입니다. 하지만 안드로이드라는 환경은 한정된 리소스를 가지고 있음으로 해서.. 예로 든 특정 뷰에 대한 마우스 클릭에 대한 이벤트에 대해 ‘하나’만을 등록하는 방식이 더 적당하다고 할 수 있습니다. 물론… 필요하다면 자바에서 일반적인 사용자 정의 이벤트를 추가하는 방식을 안드로이드에서 사용해도 됩니다. 그럼.. 안드로이드에서 적합한 사용자 정의 이벤트를 추가하는 방식에 대해 정리해 보겠습니다.

먼저 새롭게 추가할 이벤트가 무엇인지 확인해 봅니다. 예를 들어 맵엔진 개발에 있어서 맵의 축척이 변경되었을때 발생하는 이벤트를 추가하는 예를 통해 살펴보겠습니다. 1개의 클래스와 또 다른 한개의 인터페이스를 추가해야 하는데.. 새롭게 추가할 클래스는 이벤트 객체에 대한 클래스이며 새롭게 추가할 인터페이스는 이벤트 리스너입니다. 이 둘은 일반적인 자바에서의 사용자 정의 이벤트에 대해서 동일한 내용입니다. 다른게 없습니다.

아래는 축척 변경 이벤트에 대한 이벤트 객체 클래스 소스입니다.

package geoservice.blackpoint.events;

import geoservice.blackpoint.XrMap;
import java.util.EventObject;

public class MapEvent extends EventObject {
    public MapEvent(Object source) {   
        super(source);   
    }   
 
    public XrMap getMap() {
        XrMap map = (XrMap)getSource(); 
        return map;
    }
}

이벤트 객체는 이벤트를 발생시킨 주체(getSource 매서드를 통해 반환됨)를 기본적인 내용으로 하며 그외 더 필요한 정보를 담을 수 있습니다. 다음으로 이벤트 리스너에 대한 인터페이스입니다.

package geoservice.blackpoint.events;

import java.util.EventListener;

public interface OnMapScaleChangedEventListener extends EventListener {
    void onMapScaleChanged(MapEvent event);
}

이벤트 리스너 인터페이스에는 여러개의 이벤트를 넣을 수 있는데.. 이 경우 맵축척 변경에 대한 이벤트만이 있습니다. 이제 축척 변경에 대한 이벤트에 필요한 클래스와 인터페이스가 준비되었습니다.

그럼 맵엔진 단에서 맵 축척이 변경되었을때 이벤트를 발생시키는 것에 대해 코드를 통해 살펴보겠습니다.

class XrMap {
    // 이벤트 코드에만 집중하자

    public OnTapUpEventListener onTapUpEventListener = null;    
    public void setOnTapUpListener(OnTapUpEventListener listener) {
        onTapUpEventListener = listener;
    }

    private void __맵축척을변경시키는부분__ {
        if(onMapScaleChangedEventListener != null) {
            MapEvent event = new MapEvent(this);
            onMapScaleChangedEventListener.onMapScaleChanged(event);
        }
    }

    // 이벤트 코드에만 집중하자
}

보시는 것처럼.. 이벤트 리스너에 대한 변수와 이 이벤트 리스너를 할당시키기 위한 매서드 끝으로 실제 이벤트가 발생될때 이벤트 리스너를 실행해 주는 코드로 구성되어 있습니다. 여기까지가 일반적으로 안드로이드에서 사용자 정의 이벤트를 만들어 주는 방식입니다. 그럼.. 이 맵축척이 변경되었을때 발생하는 이벤트에서 원하는 코드를 작성해보는 샘플 코드는 어떻게 될까.. 아래 코드를 통해 살펴보시기 바랍니다.

map.setOnMapScaleChangedListener(
    new OnMapScaleChangedEventListener() {
        public void onMapScaleChanged(MapEvent event) {
            Toast.makeText(
                XrMapTest.this, 
                "SCALE CHANGED", 
                Toast.LENGTH_SHORT).show();
       }
    }
);

map은 앞서 XrMap 클래스에 대한 변수입니다. 축척이 변경될때마다 화면에 SCALE CHANGED라는 메세지를 토스트를 통해 띠웁니다.. 끝으로 안드로이드에서 버튼을 클릭했을 때 이벤트를 할당하는 코드를 살펴보고.. 위의 맵축척 변경 이벤트 할당 코드와 비교해 보시기 바랍니다.

Button btnro= (Button)findViewById(R.id.ro);
btnro.setOnClickListener(
    new Button.OnClickListener() {
        public void onClick(View v) {
            CoordMapper cm = map.getRendererManager().getCoordMapper();
            cm.rotate(15);
            map.update();
        }
    }
);

보시는 것처럼.. 이벤트를 할당하는 두개의 구조가 모두 동일함을 알 수 있습니다. 이상으로 안드로이드에서 사용자 정의 이벤트를 할당하는 방법에 대한 정리를 마치도록 하겠습니다.