렌더러 만들기

Renderable는 3D 모델이며 꼭짓점, 머티리얼, 텍스처 등으로 구성됩니다. Node에 연결하고 장면의 일부로 렌더링할 수 있습니다. 이 페이지에서는 Renderable을 만들고 수정하는 방법을 설명합니다.

Android 위젯에서 만들기

표준 Android 위젯에서 ViewRenderable를 만들 수 있습니다. 장면에서 플랫 카드로 렌더링됩니다.

새로 만들려면 다음 안내를 따르세요.

  1. res > layout에서 레이아웃 파일을 만듭니다. 예를 들면 다음과 같습니다.

    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
       android:id="@+id/planetInfoCard"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_weight="1"
       android:background="@drawable/rounded_bg"
       android:gravity="center"
       android:orientation="vertical"
       android:padding="6dp"
       android:text="Test"
       android:textAlignment="center" />
    
  2. ViewRenderable를 빌드합니다.

    ViewRenderable.builder()
        .setView(this, R.layout.test_view)
        .build()
        .thenAccept(renderable -> testViewRenderable = renderable);
    

    이 버전의 setView()는 확장되지 않은 레이아웃 파일의 리소스 ID를 사용합니다. setView(View)을 호출하여 프로그래매틱 방식으로 생성된 뷰에서 렌더러를 만들 수도 있습니다.

장면의 모든 build() 메서드는 CompletableFuture를 반환합니다. 객체는 별도의 스레드에 빌드되며 콜백 함수는 기본 스레드에서 실행됩니다.

렌더러의 크기는 View 객체의 크기를 기준으로 합니다. 기본적으로 뷰의 250dp는 렌더링 가능한 경우 1미터가 됩니다. setSizer(ViewSizer)을 사용하여 뷰 크기가 계산되는 방식을 변경합니다.

기본 뷰의 변경사항은 렌더러가 표시되는 방식에 영향을 줍니다. 뷰를 렌더링할 수 있는 노드가 연결된 노드는 뷰에 터치 이벤트를 전달하므로 예를 들어 버튼 누르기에 응답할 수 있습니다.

// update button text when the renderable's node is tapped
Button button = (Button) renderable.getView();
button.setOnClickListener((button) -> button.setText("clicked"));

3D 애셋에서 만들기

장면 양식은 3D 애셋 파일 (OBJ, AOSP, glTF)을 장면 양식 바이너리 애셋 (SFB)으로 변환하기 위한 도구와 플러그인을 제공합니다. 그러면 이 플러그인이 ModelRenderable에 빌드됩니다.

자세한 내용은 3D 애셋 가져오기 및 미리보기를 참고하세요.

런타임 시 간단한 형태 생성

정육면체, 구, 원통과 같은 간단한 모양을 만들려면 ShapeFactory를 사용하고 MaterialFactory를 사용하면 간단한 도형과 머티리얼로 렌더링 가능한 객체를 만들 수 있습니다.

빨간색 구를 만드는 방법은 다음과 같습니다.

MaterialFactory.makeOpaqueWithColor(this, new Color(android.graphics.Color.RED))
        .thenAccept(
            material -> {
              redSphereRenderable =
                  ShapeFactory.makeSphere(0.1f, new Vector3(0.0f, 0.15f, 0.0f), material); });

런타임 시 3D 모델 로드

glTF 또는 glb 파일로 저장된 3D 모델은 변환 없이 런타임에 로드할 수 있습니다. 이렇게 하면 애플리케이션에서 렌더링되는 모델의 유연성이 크게 개선되지만 런타임 시 모델을 읽어서 빌드 시간으로 sfb 변환에서 실행되는 최적화의 이점을 누릴 수 없다는 단점이 있습니다. 따라서 다양한 기기와 네트워크 조건에서 애플리케이션 및 3D 모델을 테스트하여 사용자에게 뛰어난 환경을 제공하는 것이 좋습니다.

런타임 애셋 로드를 사용하려면 app/build.gradle의 애셋 라이브러리에 종속 항목을 추가해야 합니다.

  dependencies {
     implementation 'com.google.ar.sceneform:assets:1.15.0'
  }

RenderableSource 클래스는 glTF 파일을 로드하고 렌더링 가능한 객체를 만드는 ModelRenderable.Builder의 소스 객체를 생성합니다.

예를 들어 인터넷에서 모델을 로드하는 코드는 다음과 같습니다.

 private static final String GLTF_ASSET =
   "https://github.com/KhronosGroup/glTF-Sample-Models/raw/master/2.0/Duck/glTF/Duck.gltf";

 /* When you build a Renderable, Sceneform loads model and related resources
 * in the background while returning a CompletableFuture.
 * Call thenAccept(), handle(), or check isDone() before calling get().
 */
 ModelRenderable.builder()
    .setSource(this, RenderableSource.builder().setSource(
            this,
            Uri.parse(GLTF_ASSET),
            RenderableSource.SourceType.GLTF2)
            .setScale(0.5f)  // Scale the original model to 50%.
            .setRecenterMode(RenderableSource.RecenterMode.ROOT)
            .build())
    .setRegistryId(GLTF_ASSET)
    .build()
    .thenAccept(renderable -> duckRenderable = renderable)
    .exceptionally(
        throwable -> {
          Toast toast =
              Toast.makeText(this, "Unable to load renderable " +
              GLTF_ASSET, Toast.LENGTH_LONG);
          toast.setGravity(Gravity.CENTER, 0, 0);
          toast.show();
          return null;
        });

참고: 원격으로 리소스에 액세스하려면 AndroidManifest.xml에 인터넷 권한을 포함해야 합니다.

    <manifest …>
      <!-- Needed to load a glTF from the internet. -->
        <uses-permission android:name="android.permission.INTERNET"/>

    </manifest>

런타임 시 렌더러 수정

여러 노드에서 렌더러를 사용할 경우 렌더러블의 변경사항은 모든 노드에 적용됩니다. 이러한 동작을 방지하려면 makeCopy()를 호출하여 별도의 렌더링 가능한 인스턴스를 만듭니다. 렌더러의 모든 머티리얼에서 makeCopy()도 호출합니다.

blueSphereRenderable = redSphereRenderable.makeCopy();
blueSphereRenderable.getMaterial().setFloat3(
                  MaterialFactory.MATERIAL_COLOR, new Color(android.graphics.Color.BLUE));