담당 Member: 이소담
flutter_cube패키지를 사용해 Flutter에서 3D 모델을 렌더링합니다.- 외부에서 가져온 귀여운 character 모델을 Flutter asset으로 연결합니다.
Cube,Scene,Object의 역할과 연결 구조를 정리합니다.- 슬라이더와 버튼으로 3D 모델의 회전과 크기를 제어합니다.
setState()와updateTransform()을 통해 UI 상태와 3D 상태가 어떻게 연결되는지 확인합니다.
이번 예제는 flutter_cube를 이용해 Flutter에서 외부 cat character 모델을 띄우고,
사용자 입력에 따라 모델의 회전과 크기가 바뀌는 흐름을 확인할 수 있도록 만든 실습용 예제 앱입니다.
이번 버전에서는 너무 단순한 기본 도형 대신, 외부 모델을 가져와 OBJ/MTL/PNG asset으로 연결하는 방식으로 구성했습니다. 또한 첫 화면에서 모델이 더 잘 보이도록 기본 카메라 거리와 초기 scale 값도 함께 조정했습니다.
프로젝트 목적은 다음과 같습니다.
- Flutter에서 3D asset을 로드하는 기본 흐름 이해하기
Cube -> Scene -> Object구조를 코드로 확인하기- 외부 모델 asset을 프로젝트에 포함하는 방법 정리하기
- 상태 변경이 3D 모델에 반영되는 과정을 직접 확인하기
이 프로젝트의 핵심 흐름은 아래처럼 보면 됩니다.
Flutter Widget -> Cube -> Scene -> Object -> Asset(.obj/.mtl/.png)
각 구성 요소의 역할은 다음과 같습니다.
Cube- Flutter 위젯입니다.
- 3D 장면을 화면에 렌더링하는 영역입니다.
Scene- 3D 공간 전체를 의미합니다.
- 카메라, 월드(
world), 조명 같은 요소를 포함합니다.
Object- 실제 3D 모델입니다.
.obj파일을 기반으로 생성됩니다.
assets- 앱 내부에서 읽을 3D 파일입니다.
- 이번 예제에서는
poly_pizza_cat.obj,poly_pizza_cat.mtl,Tex_Cat.png를 사용합니다.
상태 변경 흐름은 아래와 같습니다.
User Input -> setState() -> Object 값 변경 -> updateTransform() -> Scene 갱신
.
├─ assets/
│ └─ models/
│ ├─ poly_pizza_cat.glb
│ ├─ poly_pizza_cat.mtl
│ ├─ poly_pizza_cat.obj
│ └─ Tex_Cat.png
├─ lib/
│ ├─ app.dart
│ ├─ main.dart
│ └─ src/
│ ├─ controllers/
│ │ └─ model_viewer_controller.dart
│ ├─ pages/
│ │ └─ cube_demo_page.dart
│ └─ widgets/
│ └─ model_control_panel.dart
├─ test/
│ └─ widget_test.dart
└─ pubspec.yaml
flutter_cube: ^0.1.1의존성을 추가했습니다.- 모델 관련 파일을 한 번에 읽을 수 있도록
assets/models/디렉터리를 asset으로 등록했습니다.
dependencies:
flutter:
sdk: flutter
cupertino_icons: ^1.0.8
flutter_cube: ^0.1.1
flutter:
uses-material-design: true
assets:
- assets/models/앱의 시작점입니다.
CubeStudyApp을 실행하는 역할만 두어 진입 구조를 단순하게 유지했습니다.
import 'package:flutter/widgets.dart';
import 'app.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(const CubeStudyApp());
}앱 전체 테마와 MaterialApp 구성을 담당합니다.
현재 앱 타이틀은 Cat Character Viewer로 설정되어 있습니다.
3D 모델 제어 로직을 모아둔 파일입니다.
담당하는 역할은 다음과 같습니다.
Scene이 생성되면 카메라 위치 설정.obj모델을Object로 생성 후scene.world에 추가- 회전값과 크기값 변경
- 초기 상태로 리셋
updateTransform()호출로 실제 모델 변형 반영
핵심 코드는 아래 부분입니다.
void attachScene(cube.Scene scene) {
_scene = scene;
scene.camera.position.setValues(0, 0, 6);
scene.camera.target.setValues(0, 0, 0);
scene.camera.zoom = 1.2;
final model = cube.Object(
fileName: 'assets/models/poly_pizza_cat.obj',
isAsset: true,
lighting: true,
normalized: true,
name: 'poly-pizza-cat',
);
scene.world.add(model);
_model = model;
_applyTransform();
}void _applyTransform() {
final model = _model;
if (model == null) {
return;
}
model.rotation.setValues(rotationX, rotationY, 0);
model.scale.setValues(scale, scale, scale);
model.updateTransform();
_scene?.update();
}실제 메인 화면입니다.
포함된 내용은 다음과 같습니다.
- 앱 제목과 설명 문구
Cube기반 3D 뷰어 영역- 회전/크기/자동 회전/리셋 제어 UI
Cube,Scene,Object설명 카드- 더 친근한 캐릭터 느낌에 맞춘 색감과 레이아웃
제어용 UI만 따로 분리한 파일입니다.
이렇게 분리한 이유는 다음과 같습니다.
- 화면 레이아웃과 제어 위젯 코드를 분리하기 위해
- 팀원이 읽을 때 UI 코드와 로직 코드를 구분하기 쉽게 하기 위해
- 세션 자료로 사용할 때 구조를 명확하게 보여주기 위해
이번 예제는 외부 모델을 프로젝트 안으로 가져와, Flutter에서 바로 사용할 수 있도록 OBJ/MTL/PNG asset으로 구성했습니다.
- 외부 모델의 정점(vertex), 면(face), UV 정보가 포함된 OBJ 파일입니다.
flutter_cube가 실제로 읽는 메인 모델 파일입니다.
- 외부 모델의 재질과 텍스처 연결 정보를 담은 MTL 파일입니다.
map_Kd Tex_Cat.png설정을 통해 PNG 텍스처를 연결합니다.
- 외부 모델의 색 정보를 담는 텍스처 파일입니다.
- 단색 재질만 쓰는 대신 텍스처 기반으로 더 자연스러운 캐릭터 표현이 가능합니다.
- 외부에서 받은 원본 파일입니다.
- 현재 앱에서는 직접 읽지 않고, OBJ/MTL 변환용 원본으로 보관하고 있습니다.
- 모델명:
Cat - 제공처: Poly Pizza
- 제작자 표기: Poly by Google
- 라이선스: Creative Commons Attribution 3.0
- 모델 페이지: https://poly.pizza/m/6dM1J6f6pm9
이번 프로젝트에서는 원본 GLB 파일을 내려받은 뒤, Flutter에서 바로 사용할 수 있도록 OBJ/MTL/PNG asset으로 변환해 사용했습니다.
앱에서 제공하는 조작 기능은 다음과 같습니다.
- Y축 회전 슬라이더
- 모델 크기 슬라이더
-15°,+15°회전 버튼- 자동 회전 스위치
- Reset 버튼
이 기능들은 모두 ModelViewerController를 통해 3D 모델에 반영됩니다.
예를 들어 회전 슬라이더는 다음 흐름으로 동작합니다.
- 사용자가 슬라이더를 움직입니다.
setState()가 호출됩니다.- 컨트롤러의
setRotationY()가 실행됩니다. _applyTransform()이 실행됩니다.Object.rotation과Scene이 갱신됩니다.
프로젝트 루트에서 아래 명령을 실행하면 됩니다.
flutter pub get
flutter runWindows 환경에서 바로 확인하려면 아래 명령을 사용할 수 있습니다.
flutter run -d windows실행 파일까지 빌드하려면 아래 명령을 사용할 수 있습니다.
flutter build windows이번 프로젝트는 아래 환경에서 확인했습니다.
- Flutter
3.41.4 - Dart
3.11.1 flutter_cube^0.1.1
flutter_cube는 비교적 오래된 패키지지만,
현재 프로젝트 기준으로는 의존성 설치, 분석, 테스트, Windows 빌드까지 모두 통과했습니다.
아래 항목을 확인했습니다.
flutter pub getflutter analyzeflutter testflutter build windows
팀원들이 코드를 볼 때 특히 확인하면 좋은 부분은 아래와 같습니다.
Cube위젯이 생성되는 위치onSceneCreated에서Scene을 설정하는 흐름Object(fileName: ...)로 asset 기반 3D 모델을 읽는 부분updateTransform()과scene.update()가 함께 호출되는 이유- 외부 모델이 OBJ/MTL/PNG asset으로 연결되는 방식
- 초기 카메라 거리와 scale 값이 첫 화면 인상에 주는 영향
- UI 입력이 컨트롤러를 통해 3D 모델 상태로 연결되는 구조
