jPCT-AE(1) - main activity부터!

Programming/Graphics 2012. 6. 30. 21:46 by 빠재

오늘은 본격적으로 jPCT-AE을 개발하면서 포스팅을 해 보겠습니다.



시작이 반이라고, 어플리케이션 개발의 반은 프로젝트 세팅부터 시작됩니다.


프로젝트 개발을 어느 플랫폼에서 하느냐, 어느 엔진을 사용할 것이냐 등을 미리 결정해야 하기 때문에 처음 프로젝트를 만드는 일은 정말로 큰 부분을 차지합니다.


하지만 우리는 그렇게까지 고민할 필요는 없죠. 안드로이드 개발은 일반적으로 eclipse라는 IDE에서 이루어지고, 사용할 언어는 자바이며 그래픽 엔진은 jPCT를 사용할 것이기 때문이죠.



기본적으로 위 환경은 다 갖추어져 있다는 가정하에 시작하겠습니다.



1. 안드로이드 프로젝트 생성

프로젝트 세팅정도는 할 줄 안다 하시는 분이면 프로젝트 생성부분은 건너뛰어도 상관없습니다.



이클립스에서 File->New->Android Project 선택하고 다음과 같이 진행합니다.


1) 프로젝트 이름과 경로를 설정합니다. JPCT_Example라는 프로젝트 이름 입력. next

2) 개발 타겟이 될 안드로이드 버전을 정합니다. 여기서는 2.3.1(api level 9)로 정했습니다. next

3) 기본 패키지 이름을 정합니다. 여기서는 com.jpct.example라는 패키지명으로 사용하겠습니다. finish!



설정이 잘 되었으면 다음과 같이 구성된 프로젝트가 자동으로 생성됩니다.






2. 라이브러리 로드


프로젝트 폴더에 libs라는 폴더를 생성하고 그 밑에 jpct 홈페이지에서 구한 엔진 라이브러리 파일인 jpct-ae.jar파일을 넣습니다.


이클립스에서 추가된 jar파일을 오른쪽 클릭 후 Build Path->Add to Build Path 선택하면 jpct엔진이 라이브러리에 등록됩니다.



3. 메인 액티비티 코딩


http://www.jpct.net/wiki/index.php/Hello_World_for_Android 에 Hello_world 예제가 있으니 참고하셔도 됩니다. 


예제에서는 한 클래스 안에 내부 클래스를 또 선언하는 방식을 사용하였지만 저는 약간의 확장성(?)을 위해 내부 클래스들을 파일들로 분리하여 다시 만들어보았습니다.


1) JPCT_ExampleActivity.java

package com.jpct.example;

import java.lang.reflect.Field;

import android.app.Activity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;

import com.threed.jpct.Logger;

public class JPCT_ExampleActivity extends Activity {
	
	private static JPCT_ExampleActivity master = null;

	private GLSurfaceView glSurfaceView;
	private JPCT_Renderer renderer = null;
	
	public static JPCT_ExampleActivity getActivity() {
		return master;
	}

	private void copy(Object src) {
		try {
			Logger.log("Copying data from master Activity!");
			Field[] fs = src.getClass().getDeclaredFields();
			for (Field f : fs) {
				f.setAccessible(true);
				f.set(this, f.get(src));
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
    	// activity가 생성되었을 때의 동작
    	
        super.onCreate(savedInstanceState);
        if(master != null) {
        	copy(master);
        }
    	master = this;
        
    	// GLSurfaceView 생성
        glSurfaceView = new GLSurfaceView(getApplication());
        glSurfaceView.setEGLContextClientVersion(2);		// OpenGL ES 2.0을 사용함
        
        if(renderer == null)
        	renderer = new JPCT_Renderer();
        glSurfaceView.setRenderer(renderer);
        
        // 메인 view를 설정함
        setContentView(glSurfaceView);
    }
}



2) JPCT_Renderer.java

package com.jpct.example;

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

import com.threed.jpct.Camera;
import com.threed.jpct.FrameBuffer;
import com.threed.jpct.Light;
import com.threed.jpct.Logger;
import com.threed.jpct.Object3D;
import com.threed.jpct.Primitives;
import com.threed.jpct.RGBColor;
import com.threed.jpct.SimpleVector;
import com.threed.jpct.Texture;
import com.threed.jpct.TextureManager;
import com.threed.jpct.World;
import com.threed.jpct.util.MemoryHelper;

import android.opengl.GLSurfaceView.Renderer;

public class JPCT_Renderer implements Renderer {

	private World m_world;
	private Light m_light;
	private Camera m_cam;
	
	private FrameBuffer buffer = null;
	private RGBColor colBackground = new RGBColor(0x33, 0xcc, 0xcc);

	private Object3D m_cube;
	
	private long tick = 0;
	private int fps = 0;
	@Override
	public void onDrawFrame(GL10 gl) {
		
		// 화면 지움
		buffer.clear(colBackground);
		
		// 그리기
		m_world.renderScene(buffer);
		m_world.draw(buffer);
		
		// 그린 화면으로 갱신
		buffer.display();
		
		// FPS계산
		if(System.currentTimeMillis() - tick > 1000) {
			Logger.log("fps: " + fps);
			fps = 0;
			tick = System.currentTimeMillis();
		}
		else fps++;
	}

	@Override
	public void onSurfaceChanged(GL10 gl, int width, int height) {
		if(buffer == null) {
			// World 생성
			m_world = new World();
			
			// light 생성
			m_light = new Light(m_world);
			m_light.setIntensity(250, 250, 250);
			m_light.setPosition(new SimpleVector(50, -50, 50));
			
			// 주변광 설정(m_light와는 무관)
			m_world.setAmbientLight(100, 100, 100);
			
			// Texture 생성
			Texture t = new Texture(100, 100, new RGBColor(0, 0xff, 0, 0x7f));
			TextureManager.getInstance().addTexture("test", t);
			
			// 크기 10의 정육면체 객체 생성
			m_cube = Primitives.getBox(10, 1);	// cube 생성
			m_cube.calcTextureWrap();			// texture로 도형을 감싸도록 함
			m_cube.translate(0, -10, 0);		// 이동
			m_cube.setTexture("test");			// 아까 생성한 test texture으로 설정함
			m_cube.strip();
			m_cube.build();
			m_world.addObject(m_cube);			// World에 추가

			// camera 생성
			m_cam = m_world.getCamera();
			m_cam.setPosition(20, -20, 20);
			m_cam.lookAt(m_cube.getTransformedCenter());
		}
		
		if(buffer != null)
			buffer.dispose();
		buffer = new FrameBuffer(width, height);
		
		MemoryHelper.compact();
	}

	@Override
	public void onSurfaceCreated(GL10 gl, EGLConfig config) {
		// TODO Auto-generated method stub
	}
}


위와 같이 소스를 코딩하고 실행해 보면 다음과 같은 결과 화면을 얻을 수 있습니다.





Nav