文章目录

  • 前言
  • 一、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模型方案总结相关推荐

  1. threejs加载3D模型例子

    加载3D模型 首先要引入ColladaLoader加载器,Collada是一个3D模型交换方案,即不同的3D模型可以通过Collada进行相互转换,言外之意,threejs可以使用Collada将3D ...

  2. Labview加载3D模型(.wrl)出现内存不足的解决方法

    Labview加载3D模型(.wrl)出现内存不足的解决方法 最近,由于项目的要求,需要做一个上位机,用于实时采集装备的状态信息.最终方案采用Labview数据流的方式构建应用程序.在加载wrl3D模 ...

  3. threejs加载3D模型

    加载3D模型 首先要引入ColladaLoader加载器,Collada是一个3D模型交换方案,即不同的3D模型可以通过Collada进行相互转换,言外之意,threejs可以使用Collada将3D ...

  4. 如何加载3D模型(odj文件和mtl文件)

    模型的加载 因为,在最近的项目模块中需要加载部分"模型".在加载模型在方面我从来的没有接触过,是通过同事告诉,慢慢摸索才完成的,其中是我遇到的问题和总结的一些的方法. 使用VUE加 ...

  5. Unity动态加载3D模型

    Unity动态加载3D模型 在Unity中创建游戏对象的方法有 3 种: 第一种是将物体模型资源由 Project 视图直接拖曳到 Hierarchy 面板中: 第二种是在 Unity 3D 菜单 G ...

  6. qt opengl 加载3d模型(obj格式)

    和一般c++程序加载3d模型一样,解读出数据内容,再用一个常规的着色程序就可以了. 我实现的效果如下,采用的免费模型 实现思路和前面的略有不同,就是把自己生成顶点.纹理.法线的过程变成从文件读取了. ...

  7. 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 ...

  8. Cesium.js 加载3D模型

    一.Cesuimjs介绍 Cesiunjs是一套GIS行业中进行地图渲染的js库,该库使用的WebGL进行地图渲染.并且结合HTML5进行相应,从而实现3D中渲染地图.本篇文章则介绍如何将后缀名为ma ...

  9. Qt Quick 3D系列(一):加载3d模型

    如果我们想在QML中使用3D且你之前没有三维程序开发的基础,使用Qt Quick 3D是个不错的选择,下面我介绍如何使用Qt Quick 3D加载3d模型.注意:Qt Quick 3D从Qt 5.15 ...

最新文章

  1. Android 侧划菜单
  2. 波士顿动力机器人齐秀舞姿,这是要成团出道?
  3. 补天白帽大会:无处不在的无线电攻击
  4. Starzhou:EOSIO1.0 版本环境搭建
  5. 【Qt】进程间通信之QSharedMemory示例
  6. LeetCode MySQL 1517. Find Users With Valid E-Mails(正则表达式)
  7. URAL1815 Farm in San Andreas(费马点,圆圆相交)
  8. 国内主流设计作品分享社区,用作品动世界
  9. 修改ECSHOP后台的商品列表里显示该商品品牌
  10. windows xp下Apache2.2.11整合Tomcat6.0.20
  11. 拓端tecdat|R语言逻辑回归(Logistic Regression)、回归决策树、随机森林信用卡违约分析信贷数据集
  12. Android GPS应用开发
  13. java 正则表达式 检测数学公式是否正确_java 正则表达式 检测数学公式是否正
  14. 计算机怎么把单元格内容水平居中,win10系统下怎样让Word中的表格内容居中
  15. 淘宝API 淘口令解析(POST)
  16. 3rd Batch请查收!您的问题解答清单
  17. 路易斯安那州立大学计算机科学,路易斯安那州立大学
  18. NER文献溯源-v2核心技术方法
  19. 数学符号归纳 常用数学符号名称中英文对照
  20. Logstash 时区问题

热门文章

  1. 实证研究的步骤_毕业论文怎么写?写作步骤是什么?方式可分为理论研究型、应用研究型和实证型三大类。理论研究型根据对现有理论的反思、研究【山西师范大学现代文理学院招生咨询吧】...
  2. 移门计算器地址,移门计算软件,免费移门计算器
  3. 如何取消keil中Bookmark标记
  4. 【算法竞赛入门练习题】判断给定的字符串中是否包含某个字符串
  5. Multi-Language 本地化插件 .NET and VB6
  6. 二氧化钛纳米片负载MIL100(Fe)|bmim][Tf2N]离子液体(IL)负载UiO-66-PEI(齐岳)
  7. 车头车尾识别(有待完善)
  8. 用python写一个豆瓣短评通用爬虫(登录、爬取、可视化)!
  9. 专业现场媒体编辑工具:QLab Pro
  10. 晚清五大臣出洋考察事件解密