Upload
youngbin-han
View
487
Download
10
Embed Size (px)
DESCRIPTION
Cardboard : Android 를 위한 저렴한 VR
Citation preview
CardboardAndroid 를 위한 저렴한 VR
Youngbin Han<[email protected]>
VR(Virtual Reality)?
http://blogs-images.forbes.com/danielnyegriffiths/files/2014/05/OculusRift1.jpg
https://s3.amazonaws.com/ksr/projects/476061/photo-main.jpg?1397812032
http://www.realareal.com/wp-content/uploads/2013/08/Oculus_VR_Immeractive_Haeva.jpg
$$$$$$$$
https://www.oculusvr.com/order/
g.co/cardboard
g.co/cardboard
http://www.dodocase.com/products/google-cardboard-vr-goggle-toolkit
Cardboard VR Toolkithttps://developers.google.com/cardboard/overview
Toolkit을 이용하면 다음을 포함한 많은 공통된 VR 개발을 단순화 할 수 있습니다.
● 렌즈 왜곡 보정● 머리 추적● 3D 교정● 양쪽에 나란히 렌더링● 입체 형상 구성● 사용자 입력 이벤트 처리
간단한 Cardboard 앱 만들기.
만들기 어려운 건 함정
https://developers.google.com/cardboard/get-started
준비할 것들...
...
프로젝트에 라이브러리 추가
https://github.com/googlesamples/cardboard/blob/master/CardboardSample/libs/cardboard.jar
권장되는 Manifest.xml 설정<manifest ... <uses-permission android:name="android.permission.NFC" /> <uses-permission android:name="android.permission.VIBRATE" /> ... <uses-sdk android:minSdkVersion="16"/> <uses-feature android:glEsVersion="0x00020000"android:required="true" /> <application ... <activity android:screenOrientation="landscape" ... </activity> </application></manifest>
가로 모드
Open GL ES 사용
NFC 및 진동 권한
Android 4.1 +
CardboardActivity 상속받기
public class CardboardActivityExample extends CardboardActivity { …
}
CardboardView.StereoRenderer 구현하기
public class CardboardActivityExample extends CardboardActivity implements CardboardView.StereoRenderer { …
}
CardboardView 초기화
private float[] mModelCube;private float[] mCamera;private float[] mView;private float[] mHeadView;private float[] mModelViewProjection;private float[] mModelView;private float[] mModelFloor;private Vibrator mVibrator;…
** * Sets the view to our CardboardView and initializes the transformation matrices we will use * to render our scene. * @param savedInstanceState */
…
@Overridepublic void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.common_ui); CardboardView cardboardView = (CardboardView) findViewById(R.id.common_paperscope_view); // Associate a CardboardView.StereoRenderer with cardboardView. cardboardView.setRenderer(this); // Associate the cardboardView with this activity. setCardboardView(cardboardView); mModelCube = new float[16]; mCamera = new float[16]; mView = new float[16]; mModelViewProjection = new float[16]; mModelView = new float[16]; mModelFloor = new float[16]; mHeadView = new float[16]; mVibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);…}
뷰 렌더링 하기CardboardView.StereoRenderer 를 통해 구현한,
onNewFrame(), onDrawEye() 사용.
onNewFrame() 구현하기private int mGlProgram = GLES20.glCreateProgram();private int mPositionParam;private int mNormalParam;private int mColorParam;private int mModelViewProjectionParam;private int mLightPosParam;private int mModelViewParam;private int mModelParam;private int mIsFloorParam;private float[] mHeadView;.../** * Prepares OpenGL ES before we draw a frame. * @param headTransform The head transformation in the new frame. */…
…@Overridepublic void onNewFrame(HeadTransform headTransform) { GLES20.glUseProgram(mGlProgram); mModelViewProjectionParam = GLES20.glGetUniformLocation(mGlProgram, "u_MVP"); mLightPosParam = GLES20.glGetUniformLocation(mGlProgram, "u_LightPos"); mModelViewParam = GLES20.glGetUniformLocation(mGlProgram, "u_MVMatrix"); mModelParam = GLES20.glGetUniformLocation(mGlProgram, "u_Model"); mIsFloorParam = GLES20.glGetUniformLocation(mGlProgram, "u_IsFloor"); // Build the Model part of the ModelView matrix. Matrix.rotateM(mModelCube, 0, TIME_DELTA, 0.5f, 0.5f, 1.0f); // Build the camera matrix and apply it to the ModelView. Matrix.setLookAtM(mCamera, 0, 0.0f, 0.0f, CAMERA_Z, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f); headTransform.getHeadView(mHeadView, 0); checkGLError("onReadyToDraw");}
onDrawEye() 구현하기private int mPositionParam;private int mNormalParam;private int mColorParam;// We keep the light always position just above the user.private final float[] mLightPosInEyeSpace = new float[] {0.0f, 2.0f, 0.0f, 1.0f};.../** * Draws a frame for an eye. The transformation for that eye (from the camera) is passed in as * a parameter. * @param transform The transformations to apply to render this eye. */…
@Overridepublic void onDrawEye(EyeTransform transform) { GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT); mPositionParam = GLES20.glGetAttribLocation(mGlProgram, "a_Position"); mNormalParam = GLES20.glGetAttribLocation(mGlProgram, "a_Normal"); mColorParam = GLES20.glGetAttribLocation(mGlProgram, "a_Color"); GLES20.glEnableVertexAttribArray(mPositionParam); GLES20.glEnableVertexAttribArray(mNormalParam); GLES20.glEnableVertexAttribArray(mColorParam); checkGLError("mColorParam"); // Apply the eye transformation to the camera. Matrix.multiplyMM(mView, 0, transform.getEyeView(), 0, mCamera, 0); // Set the position of the light Matrix.multiplyMV(mLightPosInEyeSpace, 0, mView, 0, mLightPosInWorldSpace, 0); GLES20.glUniform3f(mLightPosParam, mLightPosInEyeSpace[0], mLightPosInEyeSpace[1], mLightPosInEyeSpace[2]); // Build the ModelView and ModelViewProjection matrices // for calculating cube position and light. Matrix.multiplyMM(mModelView, 0, mView, 0, mModelCube, 0); Matrix.multiplyMM(mModelViewProjection, 0, transform.getPerspective(), 0, mModelView, 0); drawCube(); // Set mModelView for the floor, so we draw floor in the correct location Matrix.multiplyMM(mModelView, 0, mView, 0, mModelFloor, 0); Matrix.multiplyMM(mModelViewProjection, 0, transform.getPerspective(), 0, mModelView, 0); ...}
자석 버튼 누름 감지하기MagnetSensor.OnCardboardTriggerListener 사용
private Vibrator mVibrator;private CardboardOverlayView mOverlayView;.../** * Increment the score, hide the object, and give feedback if the user pulls the magnet while * looking at the object. Otherwise, remind the user what to do. */@Overridepublic void onCardboardTrigger() { if (isLookingAtObject()) { mScore++; mOverlayView.show3DToast("Found it! Look around for another one.\nScore = " + mScore); ... } else { mOverlayView.show3DToast("Look around to find the object!"); } // Always give user feedback mVibrator.vibrate(50);}
/** * Check if user is looking at object by calculating where the object is in eye-space. * @return */private boolean isLookingAtObject() { float[] initVec = {0, 0, 0, 1.0f}; float[] objPositionVec = new float[4];
// Convert object space to camera space. Use the headView from onNewFrame. Matrix.multiplyMM(mModelView, 0, mHeadView, 0, mModelCube, 0); Matrix.multiplyMV(objPositionVec, 0, mModelView, 0, initVec, 0);
float pitch = (float)Math.atan2(objPositionVec[1], -objPositionVec[2]); float yaw = (float)Math.atan2(objPositionVec[0], -objPositionVec[2]); ... return (Math.abs(pitch) < PITCH_LIMIT) && (Math.abs(yaw) < YAW_LIMIT);}
Cardboard 앱 시연(예제 앱) Treasure Hunt
Cardboard Demo 앱
참고자료
● https://developers.google.com/cardboard/get-started● g.co/cardboard● http://www.khronos.org/opengles/sdk/docs/man/
Thank You!