알쓸전컴(알아두면 쓸모있는 전자 컴퓨터)

ARcore 기초 개념 (2) android version Sceneform 본문

ARCore(google)

ARcore 기초 개념 (2) android version Sceneform

백곳 2018. 12. 13. 22:56


ARcore 기초 개념 (2) android version


ARCore 에는 Sceneform 가 존재 합니다.


제가 느낀 바로는 정말 AR 사용을 쉽게 해주는 라이브러리로 생각되었습니다.


여타저타 3D randering 에 대해서 잘 몰라도 AR을 사용할수 있게 해주는 강력한 라이브러리죠


사용법및 개념을 알아 보겠습니다.


일단 사용에 앞서 제일 좋은건 아래 내용과 같이 https://developers.google.com/ar/develop/java/sceneform/


공식 문서와 샘플 https://github.com/google-ar/sceneform-android-sdk/tree/master/samples/hellosceneform


해당 샘플 프로젝트를 같이 임포트 해서 해보시는게 가장 직관적으로 API 사용법을 알수 있지 않을까 싶습니다.


제가 설명 하는건 그저 공식 문서를 해석하고 시도해본 경험에 지나지 않습니다.


먼저 아래 처럼 공식 문서에서 다룬 데로 build.gradle 을 설정 합니다.

Configure your project's build.gradle files

  1. Make sure your project's build.gradle includes Google's Maven repository:

    allprojects {
        repositories
    {
            google
    ()
           

  2. Update your app's build.gradle to add the latest ARCore and Sceneform UX dependencies, and ensure that your project settings are compatible with both libraries.

    android {
       

        defaultConfig
    {
           
    // Sceneform requires minSdkVersion >= 24.
            minSdkVersion
    24
           

       
    }
       
    // Sceneform libraries use language constructs from Java 8.
       
    // Add these compile options if targeting minSdkVersion < 26.
        compileOptions
    {
            sourceCompatibility
    JavaVersion.VERSION_1_8
            targetCompatibility
    JavaVersion.VERSION_1_8
       
    }
    }

    dependencies
    {
       

       
    // Provides ARCore Session and related resources.
        implementation
    'com.google.ar:core:1.6.0'

       
    // Provides ArFragment, and other UX resources.
        implementation
    'com.google.ar.sceneform.ux:sceneform-ux:1.6.0'

       
    // Alternatively, use ArSceneView without the UX dependency.
        implementation
    'com.google.ar.sceneform:core:1.6.0'
    }

그리고 나서

AndroidManifest.xml 설정을 해줍니다.


<!-- Both "AR Optional" and "AR Required" apps require CAMERA permission. -->
<uses-permission android:name="android.permission.CAMERA" />

<!-- Indicates that app requires ARCore ("AR Required"). Ensures app is only
     visible in the Google Play Store on devices that support ARCore.
     For "AR Optional" apps remove this line. -->

<uses-feature android:name="android.hardware.camera.ar" />

<application>
    …
   
<!-- Indicates that app requires ARCore ("AR Required"). Causes Google
         Play Store to download and install ARCore along with the app.
         For an "AR Optional" app, specify "optional" instead of "required".
    -->

   
<meta-data android:name="com.google.ar.core" android:value="required" />
</application>

위와 같이 설정 하면 됩니다.


이건 제가 테스트한 코드 입니다.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.back.test.test">
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera.ar" android:required="true"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
tools:ignore="GoogleAppIndexingWarning">

<meta-data android:name="com.google.ar.core" android:value="required" />

<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>


샘플 프로젝트를 보고 작성 했습니다 .



그리고 안드로이드 ui 작성 xml 에

<fragment android:name="com.google.ar.sceneform.ux.ArFragment"
   
android:id="@+id/ux_fragment"
   
android:layout_width="match_parent"
   
android:layout_height="match_parent" />


위와 같이
fragment 작성 하라고 합니다.


그리고 저 fragement 는 Session 이라는 개념을 가지는데


AR 시스템 상태를 관리하고 세션 수명주기를 처리합니다. 이 클래스는 ARCore API의 주요 진입 점입니다. 이 클래스를 사용하면 세션을 만들고, 구성하고, 시작하거나 중지 할 수 있으며 가장 중요한 것은 카메라 이미지와 장치 포즈에 액세스 할 수있는 프레임을 수신 할 수 있습니다.

이라고 합니다 .
 
굉장히 중요 한 개념입니다. 앞으로 세션에 대해서 계속 나올테니까 말이죠.

그리고 이제 부터는 이해를 위해서


https://github.com/google-ar/sceneform-android-sdk/tree/master/samples/hellosceneform 소스를

git 에서 다운 받는게 좋습니다.

일단 먼저 샘플의

build.gradle  파일을 보면 아래와 같이 적혀 있습니다.



apply plugin: 'com.google.ar.sceneform.plugin'

sceneform
.asset('sampledata/models/andy.obj', // 'Source Asset Path' specified during import.
               
'default',                    // 'Material Path' specified during import.
               
'sampledata/models/andy.sfa', // '.sfa Output Path' specified during import.
               
'src/main/res/raw/andy')      // '.sfb Output Path' specified during import.

해당 부분은 ARCore는 obj를 직접적으로 3D 랜더링 파일로 사용 하지 않습니다.
Sfb 라는 파일로 바꿔서 사용 합니다.
sceneform.asset을 사용해 경로를 추가 해주고

apply plugin: 'com.google.ar.sceneform.plugin'

플러그인이 적용 되어 있다면 바로 sfb 파일로 컨버팅 해줍니다 .

그게 아니라면






참고: https://developers.google.com/ar/develop/java/sceneform/import-assets

위에 사이트 에서 특별한 플러그인 프로그램을 다운 받아서 변환 해줘야 합니다.



그럼 미리 APP에 추가된 3D 파일만 사용할수 있는가 ? 라는 의문이 듭니다.


그건 아닙니다.


다만 아래 사이트


참고 : https://developers.google.com/ar/reference/java/sceneform/reference/com/google/ar/sceneform/assets/RenderableSource.SourceType


public static final RenderableSource.SourceType GLB

public static final RenderableSource.SourceType GLTF2

위와 같은 2가지 타입만 자동으로 라이브러리 수준에서 sfb 로 바꿔서 랜더링 해줍니다 .


결국 obj->GLTF2 or GLF -> ARcore 라이브러리 함수 콜 -> 랜더링


순서가 됩니다.


obj->GLTF2 or GLF


이부분은


https://github.com/javagl/JglTF

 

java 라이브러리로 있어서 했지만 실패 했습니다. 


https://github.com/AnalyticalGraphicsInc/OBJ2GLTF  는 성공 했네요 


컨버팅 할때 obj와 mtl 이름이 같고 같은 폴더에 있으면 자동으로 mtl 찾아서 적용 시켜 주네요 . 







결국에 AR 랜더링 코드를 보면


    ModelRenderable.builder()
       
.setSource(this, R.raw.andy)
       
.build()
       
.thenAccept(renderable -> andyRenderable = renderable)
       
.exceptionally(
            throwable
-> {
           
Log.e(TAG, "Unable to load Renderable.", throwable);
           
return null;
       
});

해당 소스처럼 굉장히 간단한 코드로 실행 됩니다.

-> 문법은 java 람다 함수 문법 입니다.

아래는 제가 샘플을 보고 따라한 전체 소스 입니다.


package com.back.test.test;

import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.os.Build;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Gravity;
import android.view.MotionEvent;
import android.widget.Toast;

import com.google.ar.core.Anchor;
import com.google.ar.core.HitResult;
import com.google.ar.core.Plane;
import com.google.ar.sceneform.AnchorNode;
import com.google.ar.sceneform.rendering.ModelRenderable;
import com.google.ar.sceneform.ux.ArFragment;
import com.google.ar.sceneform.ux.TransformableNode;


public class MainActivity extends AppCompatActivity {

private static final String TAG = MainActivity.class.getSimpleName();
private static final double MIN_OPENGL_VERSION = 3.0;
private ArFragment arFragment;
private ModelRenderable andyRenderable;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (!checkIsSupportedDeviceOrFinish(this)) {
return;
}

setContentView(R.layout.activity_main);
arFragment = (ArFragment) getSupportFragmentManager().findFragmentById(R.id.ux_fragment);

ModelRenderable.builder()
.setSource(this, R.raw.andy)
.build()
.thenAccept(renderable -> andyRenderable = renderable)
.exceptionally(
throwable -> {
Toast toast =
Toast.makeText(this, "Unable to load andy renderable", Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER, 0, 0);
toast.show();
return null;
});

arFragment.setOnTapArPlaneListener(
(HitResult hitResult, Plane plane, MotionEvent motionEvent) -> {
if (andyRenderable == null) {
return;
}

// Create the Anchor.
Anchor anchor = hitResult.createAnchor();
AnchorNode anchorNode = new AnchorNode(anchor);
anchorNode.setParent(arFragment.getArSceneView().getScene());

// Create the transformable andy and add it to the anchor.
TransformableNode andy = new TransformableNode(arFragment.getTransformationSystem());
andy.setParent(anchorNode);
andy.setRenderable(andyRenderable);
andy.select();
});
}

public static boolean checkIsSupportedDeviceOrFinish(final Activity activity) {
if (Build.VERSION.SDK_INT < VERSION_CODES.N) {
Log.e(TAG, "Sceneform requires Android N or later");
Toast.makeText(activity, "Sceneform requires Android N or later", Toast.LENGTH_LONG).show();
activity.finish();
return false;
}
String openGlVersionString =
((ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE))
.getDeviceConfigurationInfo()
.getGlEsVersion();
if (Double.parseDouble(openGlVersionString) < MIN_OPENGL_VERSION) {
Log.e(TAG, "Sceneform requires OpenGL ES 3.0 later");
Toast.makeText(activity, "Sceneform requires OpenGL ES 3.0 or later", Toast.LENGTH_LONG)
.show();
activity.finish();
return false;
}
return true;
}
}


'ARCore(google)' 카테고리의 다른 글

unity arcore camera 이미지 얻기  (5) 2019.01.24
unity arcore get camera image 관련  (0) 2019.01.22
ARCore Draw 예제  (0) 2018.12.17
Java 에서 Java Script 사용하기  (0) 2018.12.14
ARcore 기초 개념 (1) android version  (0) 2018.12.13
Comments