SceneView 0.10.0 업데이트에 대하여

·2023년 7월 3일
0

sceneView가 업데이트를 하면서 AR 관련해서 성능이 향상되고 기존 구글의 렌더링 엔진 오픈소스인 filament의 Engine가 ArModelNode의 매개변수로 추가되었다. 따라서 SceneView의 README.md에 적힌 것과 아주 살짝 사용법이 달라졌는데 README.md에 해당 변경사항이 반영되지 않는 것 같아 혹여나 헤매고 있을 이들을 위해 이 사실을 적기로 하였다.

시작하기 전에

기존의 SceneView 라이브러리도 filament 라이브러리를 사용하고 있었다. 다만, 업데이트 전까지 SceneView 라이브러리를 사용하는 프로그래머가 filament를 신경쓰지 않아도 자동으로 해주어 문제가 없었다면 이제는 우리가 Engine 클래스의 변수를 생성해 ArModelNode의 매개변수로 넘겨주어야 하는 것이다.

filament 라이브러리

filament 라이브러리 GitHub

우선 SceneView를 깊게 파지 않고 그냥 사용하는데에 해당 라이브러리에 대한 상세한 지식은 필요없다. ArModelNode 메소드를 살펴보면 Engine에 대한 내용도 볼 수 있어서 해당 코드에서 설명하는대로 따라하기만 하면 된다.

Android Studio에서는 클래스나 메소드를 Ctrl+클릭하면 해당 클래스나 메소드의 상세한 코드와 함께 개발자가 남겨둔 주석을 읽을 수 있다.

그러나 자세한 내용을 알고 싶은 이들을 위해서 GitHub 주소를 가져왔다. 해당 라이브러리는 다양한 운영체제 혹은 환경에서 사용될 수 있는 렌더링 엔진 라이브러리이지만, 안드로이드에서 특히나 적합한 형태를 취하고 있다고 공식적으로 밝힌 라이브러리이기도 하다.

Engine은 filament의 주 진입점으로 사용자가 생성한 모든 리소스를 추적하고 렌더링 스레드와 하드웨어 렌더러를 관리한다고 한다.

혹여나 filament와 SceneView가 무슨 차이가 있나 싶은 분들을 위해서 짧막하게 설명하자면 먼저 사용된 언어가 다르고 SceneView가 좀 더 간편한 렌더링을 위해서 만들어진 라이브러리라면 filament는 렌더링을 위해서 만들어진 라이브러리이다.

변경점

그래서 뭔데 싶을 것이다. 자고로 초보란 이론과 실습을 병행해야 겨우 이해하는 자들을 뜻하고 나 또한 엊그제부터 새로운 문제의 실마리를 얻고자 오늘 GitHub을 방문했다가 업데이트 공지를 봤을 때 filament가 뭔지도 몰라서 머리를 쥐어뜯으며 이해했기에 천천히 풀어나가고자 한다.

먼저 우리는 업데이트 공지를 읽을 필요가 있다. 내가 깨달은 게 있다면 괜히 남이 공부할 때까지 기다리지 말고 공식이 멀쩡하게 잘 업데이트하고 있으면 그거라도 따라가는 게 좋다는 것이다. 공식이 부지런하게 상세한 공지사항을 올릴 때 감지덕지하며 공식을 따라가야 한다.

공식 GitHub의 릴리즈 페이지에 가면 이런 화면이 우리를 기다린다.

참고로 최근 들어서 업데이트 주기는 1~2주인 듯 하다. 영어를 못하니 번역기에 의지해 영어와 한글을 왔다갔다하며 읽으면 여러 사실을 알 수 있다.

  1. 렌더링과 그에 관한 소비결과(?)는 이번 업데이트와 거의 상관이 없다. -> AR 모델이나 AR Point Cloud에서의 변경점이 있다.
  2. 기존의 SceneView에서는 fliament를 제대로 활용하지 못하는 문제가 있었다. -> 개선하여 성능을 향상시켰다. (덕분에 게임 엔진을 사용하는 것처럼 가벼워졌다고 합니다.)
  3. Lifecycle과 연결된 Activity 관련 문제에 대해 리펙토링을 통한 개선이 이루어졌다. -> Flutter에서 사용이 더 쉬워졌다.
  4. 3번의 영향으로 Node를 생성할 때 Engine을 매개변수로 사용해야 한다. -> 기존의 방식과 다르게 내부에 대한 계산같은 것(The whole transforms and parenting calculations)이 filament 라이브러리에게 위임됐기 때문이라고 합니다.
  5. SceneView/ARSceneView를 렌더링하기 전에 3D 항목을 미리 로드하고 View 범위 외부(ViewModel 내부 또는 원하는 위치)에 연결된 항목에 연결된 Filament 엔진을 관리할 수 있습니다. -> 이건 자세히 모르겠지만, 3D 모델 데이터를 렌더링 때 로딩하는 게 아니라 미리 준비시켜서 렌더링을 더 빨리 진행할 수 있다는 건가 싶습니다.

글 더미가 지나가면 변경사항에 대해 나열한 목록이 보이는데 이 글을 쓰는 이유인 두 번째 이유 ArModelNode hitPosition -> screenPosition라는 변경사항이 보인다.

대충 공지사항을 읽었으니 바로 READMD.md로 달려가보자 README.md에서는 ArModelNode 생성에 대해 이렇게하라고 나와있다.

ArModelNode(
    placementMode = PlacementMode.BEST_AVAILABLE, 
    hitPosition = Position(0.0f, 0.0f, -2.0f),
    followHitPosition = true,
    instantAnchor = false
)

하지만, 최신 버전에서 해당 코드로 실행하면 빨간 줄이 신나게 그어질 것이다. 먼저 필수인 Engine 매개변수가 없고 hitPosition은 screenPosition으로 바뀌었기 때문이다.

이전 포스팅을 보고 15분 간단 AR앱을 따라했다면 저 부분이 아마도 아래와 같은 형식 일 것이다.

 modelNode = ArModelNode().apply {
            placementMode = PlacementMode.BEST_AVAILABLE
            hitPosition = Position(0.0f, 0.0f, -10.0f)
            
            loadModelGlbAsync(
            	glbFileLocation = "models/bird_orange.glb",
            ){
                binding.sceneView.planeRenderer.isVisible = true
             }
             onAnchorChanged = {
                binding.place.isGone
            }
        }

일단 실행에는 성공한 이번 업데이트로 변경된 사항이 적용된 코드는 아래와 같다.

++ 2023.07.31
제대로 position도 먹히고 viewModel도 생성되는 코드를 알아냈다.


class MainActivity : AppCompatActivity() {
...
...
...
	//sceneview 0.10.0에서 추가. 기존 3D 렌더링 구글 오픈소스인 filament의 활용을 극대화시키기 위해 해당 라이브러리와의 endpoint인 Engine 사용을 도입
    //lifecycle과 관련된 문제 해결과 동시에 어느정도 성능 개선이 이루어짐. -> 렌더링이 부드러워졌고 기존의 문제(어느 View가 중복생성되거나 중복삭제되는 등의 문제)로 생긴 자원소모가 줄었다고 합니다.
    //filament는 그래픽을 렌더링해주는 엔진이라고 합니다.
    //Engine을 따로 만들지 않는다. SceneView 클래스 내부에 engine이 존재하는데 이 engine을 매개변수로 사용한다.

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

 	modelNode = ArModelNode(binding.sceneView.engine).apply {
    	        placementMode = PlacementMode.BEST_AVAILABLE
        	    screenPosition = Position(0.0f, 0.0f, -30.0f)
	
    	        lifecycleScope.launchWhenCreated {
        	        loadModelGlbAsync(
            	        glbFileLocation = "models/bird_orange.glb",
                	){
                    	binding.sceneView.planeRenderer.isVisible = true
               		}	
                	onAnchorChanged = {
                    	binding.place.isGone
                	}
            	}
        	}
            
...
...
...
}

위의 방식으로 ViewModel도 가능하다.

  ViewRenderable.builder()
                .setView(this@MainActivity, tapBinding.root)
                .setVerticalAlignment(ViewRenderable.VerticalAlignment.TOP)
                .setHorizontalAlignment(ViewRenderable.HorizontalAlignment.RIGHT)
                .build()
                .thenAccept {renderable: ViewRenderable ->
                    val viewNode = ViewNode(modelNode.engine)
                    viewNode.parent = modelNode
                    viewNode.setRenderable(renderable)
                    viewNode.position = Position(0.0f, 10.0f, 0.0f)
                }

요점은 생성하고자 하는 모델링의 상위 부모의 engine을 매개변수로 설정하는 것이라고 생각한다. (확신은 못 하고 아직은 더 살펴봐야 한다.)

+++ 매개변수로 주는 engine은 자신들의 내부 필드의 engine을 정의하기 위해 받아오는 값인 듯 하다. 딱히 상위 부모일 필요없고 sceneView의 engine을 가져와도 상관없을 것 같다.

profile
안드로이드 네이티브 앱 개발자를 지망하는 대학생입니다.

3개의 댓글

comment-user-thumbnail
2023년 7월 17일

Hey! I am a University student working on AR for my Final Year Project. When I build my application, the plane is rendered but the model is never rendered. Any idea how to resolve that. Any help will be greatly appreciated.

1개의 답글
comment-user-thumbnail
2023년 9월 6일

안녕하세요 현재 대학교 다니고 있는 학생입니다.
블로그 너무 잘보고 있습니다.!!
혹시, AR Model에 Text를 넣으려고 노력중에 있습니다.
블로그에서 사용하신 ViewRenderable를 사용하니깐 Text가 이동하긴 하지만, 검은색 ui element가 화면 가운데에 생기는 문제가 생기는데, 혹시 이런 문제 생긴적없으신가요?

답글 달기