Flutter 加载3D模型方案总结
文章目录
- 前言
- 一、flutter_cube
- 1.依赖
- 2.使用
- 二、model_viewer_plus
- 1.依赖
- 2.配置
- 2.使用
- 三、结合three.js
- 1. 配置three.js
- 下载资源
- 编写index.html
- 2. 导入Flutter项目
- 引入资源
- 声明资源
- 3. Flutter中使用
- 依赖
- 配置
- 使用
- 总结
前言
本文主要是对pub上的3D库使用总结及Flutter中结合three.js总结
一、flutter_cube
Flutter 3D 小部件,加载OBJ模型文件
支持Android,IOS,Window,Mac平台
1.依赖
flutter_cube: ^0.1.1
2.使用
import 'package:flutter/material.dart';
import 'package:flutter_cube/flutter_cube.dart';class Model3DViewer extends StatefulWidget {final String name;const Model3DViewer({Key? key, required this.name}) : super(key: key);@overrideState<Model3DViewer> createState() {return _Model3DViewerState();}
}class _Model3DViewerState extends State<Model3DViewer> {@overrideWidget build(BuildContext context) {return Cube(onSceneCreated: _onSceneCreated);}void _onSceneCreated(Scene scene) {scene.camera.position.z = 10;scene.camera.target.y = 2;final parent = widget.name.substring(0, widget.name.lastIndexOf('.'));scene.world.add(Object(scale: Vector3(10.0, 10.0, 10.0), fileName: 'assets/models/$parent/${widget.name}'));}
}
二、model_viewer_plus
Flutter 3D小部件,用于以 glTF 和 GLB 格式渲染交互式 3D 模型,继承自model viewer
支持Android,IOS,Web平台
1.依赖
model_viewer_plus: ^1.2.0
2.配置
Android清单文件中添加
<applicationandroid:label="flutter3d"android:name="${applicationName}"android:icon="@mipmap/ic_launcher"android:usesCleartextTraffic="true">
Android将 minSdkVersion 更改为 19以上
defaultConfig {applicationId "com.example.viewer.flutter3d"minSdkVersion 19targetSdkVersion 30versionCode flutterVersionCode.toInteger()versionName flutterVersionName}
Ios中ios/Runner/Info.plist中添加
<key>io.flutter.embedded_views_preview</key><string>YES</string>
web中index.html中添加
<head><script type="module" src="./assets/packages/model_viewer_plus/assets/model-viewer.min.js" defer></script>
</head>
2.使用
import 'package:flutter/material.dart';
import 'package:model_viewer_plus/model_viewer_plus.dart';class Model3DViewer extends StatefulWidget {final String name;const Model3DViewer({Key? key, required this.name}) : super(key: key);@overrideState<Model3DViewer> createState() {return _Model3DViewerState();}
}class _Model3DViewerState extends State<Model3DViewer> {@overrideWidget build(BuildContext context) {return ModelViewer(src: 'assets/models/${widget.name}',alt: "A 3D model of an astronaut",ar: true,autoRotate: true,cameraControls: true,);}
}
三、结合three.js
JavaScript编写的WebGL第三方库
实现在Android,IOS,Web平台使用
1. 配置three.js
下载资源
在官网下载所需文件
编写index.html
<!DOCTYPE html>
<html><head><title>Flutter 3D To ThreeJS</title><meta charset="utf-8" /><meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0"><style>body {margin: 0;padding: 0;width: 100%;height: 100%;-webkit-tap-highlight-color: rgba(0, 0, 0, 0);}</style>
</head><body><script async src="https://ga.jspm.io/npm:es-module-shims@1.5.4/dist/es-module-shims.js"></script><script type="importmap">{"imports": {"three": "./three.module.js"}}</script><script type="module">import * as THREE from 'three';import { GLTFLoader } from './GLTFLoader.js';import { RGBELoader } from './RGBELoader.js';import { OrbitControls } from './OrbitControls.js';let camera, scene, renderer, controls, object;let windowHalfX = window.innerWidth / 2;let windowHalfY = window.innerHeight / 2;init();animate();function init() {const container = document.createElement('div');document.body.appendChild(container);// 透视镜头 PerspectiveCameracamera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 2000);// 设置视角离原点的位置(眼睛距离模型的距离)camera.position.z = 3;scene = new THREE.Scene();// 环境光会均匀的照亮场景中的所有物体,环境光不能用来投射阴影,因为它没有方向。const ambientLight = new THREE.AmbientLight(0xcccccc, 1.5);scene.add(ambientLight);// 从一个点向各个方向发射的光源。一个常见的例子是模拟一个灯泡发出的光,该光源可以投射阴影。const pointLight = new THREE.PointLight(0xffffff, 0.01);camera.add(pointLight);scene.add(camera);// 加载进度监听const onProgress = function (xhr) {if (xhr.lengthComputable) {const percentComplete = xhr.loaded / xhr.total * 100;let progress = Math.round(percentComplete, 2)console.log(progress + '% downloaded');}};const onError = function (error) {console.log(error);}const params = new URLSearchParams(location.search);const name = params.get('name');new GLTFLoader().setPath("../models/").load(name, function (obj) {object = obj.scene;// 模型缩放// object.scale.set(0.3, 0.3, 0.3);// 改变模型的加载位置object.position.set(0, -1, 0);scene.add(object);}, onProgress, onError);// 渲染器设置 alpha: true 否则背景图不显示renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });renderer.outputEncoding = THREE.sRGBEncoding;renderer.setPixelRatio(window.devicePixelRatio);renderer.setSize(window.innerWidth, window.innerHeight);container.appendChild(renderer.domElement);// 轨道控制器,用于模型手势处理controls = new OrbitControls(camera, renderer.domElement);controls.listenToKeyEvents(window);controls.enableDamping = true;// 相机向内和向外移动不超过远近截面controls.maxDistance = 2000;controls.minDistance = 1;controls.enablePan = false;controls.enableRotate = true;controls.screenSpacePanning = false;controls.enableZoom = true;// // 禁用垂直旋转// controls.minPolarAngle = Math.PI / 2;// controls.maxPolarAngle = Math.PI / 2;// 包含由控件所使用的鼠标操作的引用controls.mouseButtons = {LEFT: THREE.MOUSE.ROTATE,MIDDLE: THREE.MOUSE.DOLLY,RIGHT: THREE.MOUSE.PAN}// 包含由控件所使用的触摸操作的引用controls.touches = {ONE: THREE.TOUCH.ROTATE,TWO: THREE.TOUCH.DOLLY_PAN}window.addEventListener('resize', onWindowResize);}function onWindowResize() {windowHalfX = window.innerWidth / 2;windowHalfY = window.innerHeight / 2;camera.aspect = window.innerWidth / window.innerHeight;camera.updateProjectionMatrix();renderer.setSize(window.innerWidth, window.innerHeight);}function animate() {requestAnimationFrame(animate);controls.update();render();}function render() {renderer.render(scene, camera);}</script>
</body></html>
2. 导入Flutter项目
引入资源
声明资源
assets:- assets/three3d/- assets/
3. Flutter中使用
依赖
webview_flutter: ^3.0.4local_assets_server: ^2.0.2+12
配置
Android清单文件中添加
<applicationandroid:label="flutter3d"android:name="${applicationName}"android:icon="@mipmap/ic_launcher"android:usesCleartextTraffic="true">
Android将 minSdkVersion 更改为 19以上
defaultConfig {applicationId "com.example.viewer.flutter3d"minSdkVersion 19targetSdkVersion 30versionCode flutterVersionCode.toInteger()versionName flutterVersionName}
Ios中ios/Runner/Info.plist中添加
<key>io.flutter.embedded_views_preview</key><string>YES</string>
使用
‘dart:ui’ 和dart:html 库是 web-only 的,没有把该方法允许外部调用,动态引入该方法。
// shim/dart_html_fake.dart
class IFrameElement {dynamic get style => null;dynamic src;
}
// shim/dart_ui_fake.dart
class platformViewRegistry {static void registerViewFactory(String viewTypeId, dynamic Function(int viewId) viewFactory,{bool isVisible = true}) {}
}
区分平台实现
import 'dart:io';import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:local_assets_server/local_assets_server.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'shim/dart_ui_fake.dart' if (dart.library.html) 'dart:ui' as ui;
import 'shim/dart_html_fake.dart' if (dart.library.html) 'dart:html';class Model3DViewer extends StatefulWidget {final String name;const Model3DViewer({Key? key, required this.name}) : super(key: key);@overrideState<Model3DViewer> createState() {return _Model3DViewerState();}
}class _Model3DViewerState extends State<Model3DViewer> {bool _isListening = false;String? _address;int? _port;final String _divID = DateTime.now().toIso8601String();@overridevoid initState() {if (kIsWeb) {ui.platformViewRegistry.registerViewFactory(_divID,(int viewId) => IFrameElement()..style.border = 'none'..src = 'assets/three3d/index.html?name=${widget.name}');} else {_startService();}super.initState();}/// 启动静态服务器,解决跨域问题和加载本地html_startService() async {final server = LocalAssetsServer(address: InternetAddress.loopbackIPv4,assetsBasePath: 'assets',logger: const DebugLogger());final netAddress = await server.serve();setState(() {_address = netAddress.address;_port = server.boundPort!;_isListening = true;print('http://$_address:$_port');});}@overrideWidget build(BuildContext context) {return Scaffold(body: LayoutBuilder(builder: (context, constraints) {if (kIsWeb) {return HtmlElementView(viewType: _divID);} else {return _isListening? WebView(debuggingEnabled: true,initialUrl: 'http://$_address:$_port/three3d/index.html?name=${widget.name}',javascriptMode: JavascriptMode.unrestricted): const Center(child: Text("加载中..."));}}),);}
}
总结
1、cube在Android和IOS上表现不错,而且是基于Flutter实现的
2、model_viewer_plus内部也是基于WebView实现的,所以简单展示模型推荐cube。
3、结合three.js看业务需求,若业务复杂推荐使用。
Flutter 加载3D模型方案总结相关推荐
- threejs加载3D模型例子
加载3D模型 首先要引入ColladaLoader加载器,Collada是一个3D模型交换方案,即不同的3D模型可以通过Collada进行相互转换,言外之意,threejs可以使用Collada将3D ...
- Labview加载3D模型(.wrl)出现内存不足的解决方法
Labview加载3D模型(.wrl)出现内存不足的解决方法 最近,由于项目的要求,需要做一个上位机,用于实时采集装备的状态信息.最终方案采用Labview数据流的方式构建应用程序.在加载wrl3D模 ...
- threejs加载3D模型
加载3D模型 首先要引入ColladaLoader加载器,Collada是一个3D模型交换方案,即不同的3D模型可以通过Collada进行相互转换,言外之意,threejs可以使用Collada将3D ...
- 如何加载3D模型(odj文件和mtl文件)
模型的加载 因为,在最近的项目模块中需要加载部分"模型".在加载模型在方面我从来的没有接触过,是通过同事告诉,慢慢摸索才完成的,其中是我遇到的问题和总结的一些的方法. 使用VUE加 ...
- Unity动态加载3D模型
Unity动态加载3D模型 在Unity中创建游戏对象的方法有 3 种: 第一种是将物体模型资源由 Project 视图直接拖曳到 Hierarchy 面板中: 第二种是在 Unity 3D 菜单 G ...
- qt opengl 加载3d模型(obj格式)
和一般c++程序加载3d模型一样,解读出数据内容,再用一个常规的着色程序就可以了. 我实现的效果如下,采用的免费模型 实现思路和前面的略有不同,就是把自己生成顶点.纹理.法线的过程变成从文件读取了. ...
- Qt和OpenGL:使用Open Asset Import Library(ASSIMP)加载3D模型
Qt和OpenGL:使用Open Asset Import Library(ASSIMP)加载3D模型 翻译自:https://www.ics.com/blog/qt-and-opengl-loadi ...
- Cesium.js 加载3D模型
一.Cesuimjs介绍 Cesiunjs是一套GIS行业中进行地图渲染的js库,该库使用的WebGL进行地图渲染.并且结合HTML5进行相应,从而实现3D中渲染地图.本篇文章则介绍如何将后缀名为ma ...
- Qt Quick 3D系列(一):加载3d模型
如果我们想在QML中使用3D且你之前没有三维程序开发的基础,使用Qt Quick 3D是个不错的选择,下面我介绍如何使用Qt Quick 3D加载3d模型.注意:Qt Quick 3D从Qt 5.15 ...
最新文章
- 美研究最新生物活性玻璃 可消灭致命的细菌
- NR 5G 移动性和状态变化
- python学习之- 内置函数
- 62.类文件结构(平台无关性、类文件结构)
- php zpo框架,Yii使用DeleteAll连表删除出现报错问题的解决方法
- Python 用hashlib求中文字符串的MD5值
- php析构函数使用,php析构函数__destruct()使用方法及实例讲解
- Python基础100题
- Linux命令格式及帮助命令详解
- 电子计算机说明文作文,关于电脑说明文作文(精选3篇)
- .NET框架怎样解决DLL Hell问题?
- matlab工作区显示的是什么,matlab工作区介绍
- 怎样在线分解gif图片?如何将gif拆分为静态图片?
- 如何完美清除被磁碟机感染的文件?
- ttl传输种过期_来自 202.112.36.253 的回复: TTL 传输中过期。解决思路
- 水溶性CdSe/ZnS量子点PL480nm--660nm(亲水配体包裹的核/壳型荧光纳米材料)
- Cannot copy param 0 weights from layer 'fc6'; shape mismatch.
- 腾讯云CentOS7 LAMP(linux的apache MariaDB php)yum方式部署
- ORB-SLAM2代码解析
- 基于ssm的万卷图书馆借阅管理平台#计算机毕业设计