본문 바로가기
공허의 유산/표현의 자유

[Sceneform]#2. 기본 코드 입력

by 바른생활머시마 2020. 1. 13.
728x90
반응형

 지금까지 프로젝트의 공통적인 설정을 했다면, 이제부터는 구현하려는 프로젝트에 따라 달라질 수 있는 부분을 처리 해  보도록 하겠습니다.

 

 * android stuido의 update/ upgrade

 위와 같이, android studio의 update가 자주 있는데, 특별한 이유가 없다면 그 때 그 때 해 주도록 하겠습니다.  간혹 새 버젼 설치하면 작동에 문제가 되는 코드나 설정이 있을 수 있는데, 그런 문제 수정하면서 또 배워 볼 수 있으니~ Camera 사용 때문에 Emulator 사용에 대한 문서도 따로 있었던 것 같아요. 제가 사용하는 컴퓨터는 메인보드에서 무슨 설정이 맞지 않아 쓸 수 없는 상태라서 실제 장비를 연결해서 씁니다.

 

1. hellosceneform 참고

 hellosceneform을 참고해서 코드를 입력 해 보겠습니다. 그냥 복사해서 붙여 넣어도 상관 없을 것 같습니다.

https://github.com/google-ar/sceneform-android-sdk/blob/master/samples/hellosceneform/app/src/main/java/com/google/ar/sceneform/samples/hellosceneform/HelloSceneformActivity.java

 

google-ar/sceneform-android-sdk

Sceneform SDK for Android. Contribute to google-ar/sceneform-android-sdk development by creating an account on GitHub.

github.com

 

2. 코드 구성

 fragment로 구현 된 프로젝트이며, onCreate에서 필요한 조건이 갖춰져 있는지 확인합니다.

 arfragment와 renderable을 만든 후, fragment에 tap listener를 등록하며서 renderable을 연결해서 작동하도록 합니다.

 

 필요한 조건이란, 지원하는 OpenGL 버젼(3.0)이 적합한지, 그리고, android sdk 버젼(N)이 맞는지 확인하는 것입니다.

 별도 함수를 만들어 onCreate에서 가장 먼저 확인합니다.

    if (!checkIsSupportedDeviceOrFinish(this)) {
      return;
    }

 fragment를 사용하기 위해서, 정의한 layout은 아래와 같습니다. 자세한 내용은 차차 알아보도록 하고 일단 한번 띄워보는 것을 목적으로 하니, 똑같이 만들어 줍니다. (repository에서 가져와도 되고~) 이렇게 정의 된 layout을 setContentsView로 할당합니다.

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".HelloSceneformActivity">

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

</FrameLayout>

그 후, arfragment와 renderable을 각각 만들고 Listener에서 할당합니다.

이에 대한 상세한 코드는 이후에 따로 리뷰 해 보도록 하고, 일단 돌아가는 앱을 만들기 위해 기계적으로 따라 해 보겠습니다.

 

2. 사용 방법

앱을 구동하면, 단말기를 빙빙 돌리는 모습의 animation이 나옵니다. 단말기를 움직여서 (단말기 animation이 사라질 때까지)초기화를 한 후(바닥 인식 과정 같기도 하구요...), 화면을 탭 하면 andy가 바닥에 추가됩니다.

정말 간단하게 되죠???

이제 이 프로젝트 기반으로 sceneform의 다른 기능들을 리뷰 하면서 추가 해 보도록 하겠습니다.

 

 

 

 

3. 오류 처리

error: lambda expressions are not supported in -source 1.7
(use -source 8 or higher to enable lambda expressions)

 검색을 해 보니, 람다표현식을 쓰려면 android 지원 버젼 설정을 해줘야 하네요.

 아래 포스트에 잘 설명이 되어 있습니다.

https://fluorite94.tistory.com/85 

 

[Android / 안드로이드] lambda expressions are not supported at language level 에러 해결법

안드로이드에서 람다식을 사용하려는데 "lambda expressions are not supported at language level '1.7 " 에러가 발생하였습니다. 현재 자바 버전에서 람다식을 지원하지 않아 발생한 에러인데, 자바 버전을 올..

fluorite94.tistory.com

android studio 버젼에 따라 조금 달라질 수도 있는데, source compatibility 속성입니다.

Target도 같이 1.8로 변경 해 줍니다.

 

import android.support.v7.app.AppCompatActivity 에서 오류 발생

 일단 그냥 주석처리해도 상관 없는 것 같네요.

 샘플 코드를 그냥 전부 복사해서 붙여넣기 하면 android studio의 작성 당시의 상태와 맞지 않는 코드가 들어가는 것 같습니다. 그래서, 일단 import 구문은 복사해서 넣지 말고, 코드만 넣은 후, 필요한 것만 추가하는 것이 더 좋은 것 같습니다.  요즘은 워낙 자동으로 코드 보완이 잘 되어서 거의 다 되네요. 제가 직접 추가 해 준 것은 android.os.Build.VERSION_CODES 뿐이었어요.

 

 

hellosceneform project를 그대로 보시면 됩니다만, 제가 작성하는 코드도 따로 github에 정리해서 올립니다. 

위 내용까지는 2020.1.15 오전 버젼으로 커밋했습니다.

 

https://github.com/red112/sceneform.git

 

이번 포스트 내용과 비슷한 내용을 이전에 벌써 정리 해 두신 분도 계시네요.

https://idlecomputer.tistory.com/277

 

ARcore 기초 개념 (2) android version Sceneform

ARcore 기초 개념 (2) android version ARCore 에는 Sceneform 가 존재 합니다. 제가 느낀 바로는 정말 AR 사용을 쉽게 해주는 라이브러리로 생각되었습니다. 여타저타 3D randering 에 대해서 잘 몰라도 AR을 사..

idlecomputer.tistory.com

[MainActivity.java]

package com.wonil.arform;

import androidx.appcompat.app.AppCompatActivity;

import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.os.Build.VERSION_CODES;
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
    @SuppressWarnings({"AndroidApiChecker", "FutureReturnValueIgnored"})
    // CompletableFuture requires api level 24
    // FutureReturnValueIgnored is not valid
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (!checkIsSupportedDeviceOrFinish(this)) {
            return;
        }
        setContentView(R.layout.activity_ux);
        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;
    }
}

 

 

다음 시간에는 AR 공간에 그릴 모델을 원하는 것으로 바꿔 보도록 하겠습니다.

https://learn-and-give.tistory.com/4

 

[sceneform]#3. model 변경하기

ARCore 문서에 있는 다른 내용들을 해 보려고 하는데, 쉽지 않네요. 특히, lambda 표현식 때문에 샘플 코드들이 오히려 더 한 눈에 딱 들어오지 않네요. 타입 지정하지 않고 사용되는 변수들이 그 중

learn-and-give.tistory.com

 

728x90
반응형

댓글