足不出户,一探古今,打造线上3D数字博物馆!
随着3D技术的不断革新,为了让更多的用户领略历史之美,越来越多的博物馆开始举办线上展览。通过模拟不同的环境、灯光投影、360°无死角放大缩小展品,观众可以享受到身临其境的沉浸体验。不仅如此,给展品加上BGM或者语音解说,帮助观众更加了解展品的详细背景,让演示场景更有代入感。
效果示意
看完如此逼真的效果展示,是不是想知道究竟是怎么实现的呢?
通过Android Studio的Kotlin工程实现 3D场景构建、物品展示以及声音播放功能,就可以做到。
一、准备3D模型
华为移动服务最新开放的3D物体建模服务(3D Modeling Kit),助力轻松建模。我们只需使用手机相机,通过拍摄物体的不同角度图像,便可实现物体的3D几何模型和纹理的自动化生成,为应用提供3D模型构建、预览等能力。具体操作指导可参考《5分钟给商品建立3D模型,我是如何做到的?》
二、制作3D物体视图
接下来我们将准备好的展品3D模型,通过华为图形引擎服务创建一个可交互的3D物体视图,如图所示:
↓↓↓
↓↓↓
集成华为图形引擎服务
软件要求:JDK1.7及以上版本
• minSdkVersion :设置为19或以上
• targetSdkVersion:设置为19或以上
• compileSdkVersion:设置为19或以上
• Gradle 3.5及以上版本
在build.gradle文件中配置以下内容:
buildscript { repositories { ... maven { url 'https://developer.huawei.com/repo/' } } ... } allprojects { repositories { ... maven { url 'https://developer.huawei.com/repo/' } } }
在应用级build.gradle文件中配置以下内容:
dependencies { ... implementation 'com.huawei.scenekit:full-sdk:5.1.0.300' } 示例工程使用了Kotlin的viewBinding功能从而略过了视图初始化样板代码。可在应用级build.gradle文件里加入如下代码来启用viewBinding功能: android { ... buildFeatures { viewBinding true } ... }
build.gradle文件同步完成后,就能在工程中使用图形引擎服务了。
本文中,我们仅需要使用该服务即可展示物品的3D图像,并且与之进行交互。如果还需要使用其他功能,可以参阅华为图形引擎服务官方文档。
创建3D视图
创建自定义视图的目的很简单,确保视图初始化完成后,第一个模型能自动加载到视图里。通过默认的SceneView手动实现模型加载,如下所示:
import android.content.Context import android.util.AttributeSet import android.view.SurfaceHolder import com.huawei.hms.scene.sdk.SceneView class CustomSceneView : SceneView { constructor(context: Context?) : super(context) constructor( context: Context?, attributeSet: AttributeSet? ) : super(context, attributeSet) override fun surfaceCreated(holder: SurfaceHolder) { super.surfaceCreated(holder) loadScene("qinghuaci/scene.gltf") loadSpecularEnvTexture("qinghuaci/specularEnvTexture.dds") loadDiffuseEnvTexture("qinghuaci/diffuseEnvTexture.dds") } }
展示物品需添加相关模型文件,打开工程文件夹,在“src/main”路径下创建“assets”文件夹,将3D模型文件保存,比如:
surfaceCreated中的loadScene()、loadSpecularEnvTexture()和loadDiffuseEnvTexture()方法用于加载物品。创建surface后,第一个物品将加载到surface中。 接下来,打开用于展示3D模型视图的XML文件,本工程中为activity_main.xml。在该文件中,创建刚才构造的CustomSceneView。下方代码使用了箭头图片用以在不同的物品模型间切换。
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <com.example.sceneaudiodemo.CustomSceneView android:id="@+id/csv_main" android:layout_width="match_parent" android:layout_height="match_parent"/> <ImageView android:id="@+id/iv_rightArrow" android:layout_width="32dp" android:layout_height="32dp" android:layout_margin="12dp" android:src="@drawable/ic_arrow" android:tint="@color/white" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" /> <ImageView android:id="@+id/iv_leftArrow" android:layout_width="32dp" android:layout_height="32dp" android:layout_margin="12dp" android:rotation="180" android:src="@drawable/ic_arrow" android:tint="@color/white" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
一切准备就绪,应用打开之后就能看到第一个展品:青花瓷花瓶了。
增加切换功能
现在,我们通过切换功能来查看多个展品3D模型。 在MainActivity中,配置如下信息:
private lateinit var binding: ActivityMainBinding private var selectedId = 0 private val modelSceneList = arrayListOf( "qinghuaci/scene.gltf", "tangyong/scene.gltf", ) private val modelSpecularList = arrayListOf( "qinghuaci/specularEnvTexture.dds", "tangyong/specularEnvTexture.dds", ) private val modelDiffList = arrayListOf( "qinghuaci/diffuseEnvTexture.dds", "tangyong/diffuseEnvTexture.dds", ) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) val view = binding.root setContentView(view) binding.ivRightArrow.setOnClickListener { if (modelSceneList.size == 0) return@setOnClickListener selectedId = (selectedId + 1) % modelSceneList.size // 确保ID处于模型列表的范围内。 loadImage() } binding.ivLeftArrow.setOnClickListener { if (modelSceneList.size == 0) return@setOnClickListener if (selectedId == 0) selectedId = modelSceneList.size - 1 // 确保ID处于模型列表的范围内。 else selectedId -= 1 loadImage() } } private fun loadImage() { binding.csvMain.loadScene(modelSceneList[selectedId]) binding.csvMain.loadSpecularEnvTexture(modelSpecularList[selectedId]) binding.csvMain.loadDiffuseEnvTexture(modelDiffList[selectedId]) }
在onCreate()中,创建了一个简单的逻辑,查看下一个/上一个模型。物品文件路径以字符串的形式保存于各个硬编码列表中。可以自行修改这个逻辑,使模型呈现更富动态。其中selectedId表示正在展示的物品模型ID。 这样,就实现了利用SceneView来展示3D模型,效果如下:
三、为展品增加讲解词
在加载不同的3D模型时,我们可以通过华为音频服务播放该展品对应的讲解词,为用户提供展品详细介绍。 集成华为音频服务
软件要求:
• JDK版本1.8.211及以上版本
• minSdkVersion:设置为21
• targetSdkVersion:设置为29
• compileSdkVersion:设置为29
• Gradle 4.6及以上版本
可以看到,音频服务相较于图形引擎服务软件要求更高,所以我们需要确保满足音频服务的使用要求。
首先,打开应用级build.gradle文件,添加音频服务的相关配置。
dependencies { ... implementation 'com.huawei.hms:audiokit-player:1.1.0.300' ... }
之前在配置图形引擎服务时,已经添加了必要的库,所以项目级build.gradle不需要改动。 在activity_main.xml文件中,添加一个简单的播放按钮。
<Button android:id="@+id/btn_playSound" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Play" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" />
这个按钮可以用来为展示中的物品播放声音。 然后,在MainActivity中添加以下配置:
private var mHwAudioManager: HwAudioManager? = null private var mHwAudioPlayerManager: HwAudioPlayerManager? = null override fun onCreate(savedInstanceState: Bundle?) { ... initPlayer(this) binding.btnPlaySound.setOnClickListener { mHwAudioPlayerManager?.play(selectedId) //创建播放列表实例。selectedId:播放曲目的参数。 } ... } private fun initPlayer(context: Context) { val hwAudioPlayerConfig = HwAudioPlayerConfig(context) HwAudioManagerFactory.createHwAudioManager(hwAudioPlayerConfig, object : HwAudioConfigCallBack { override fun onSuccess(hwAudioManager: HwAudioManager?) { try { mHwAudioManager = hwAudioManager mHwAudioPlayerManager = hwAudioManager?.playerManager mHwAudioPlayerManager?.playList(getPlaylist(), 0, 0) } catch (ex: Exception) { ex.printStackTrace() } } override fun onError(p0: Int) { Log.e("init:onError: ","$p0") } }) } fun getPlaylist(): List<HwAudioPlayItem>? { val playItemList: MutableList<HwAudioPlayItem> = ArrayList() val audioPlayItem1 = HwAudioPlayItem() val sound = Uri.parse("android.resource://yourpackagename/raw/soundfilename").toString() // soundfilename不包含文件扩展名。 audioPlayItem1.audioId = "1000" audioPlayItem1.singer = "Taoge" audioPlayItem1.onlinePath = "https://lfmusicservice.hwcloudtest.cn:18084/HMS/audio/Taoge-chengshilvren.mp3" //此处Demo使用歌曲示意 audioPlayItem1.setOnline(1) audioPlayItem1.audioTitle = "chengshilvren" playItemList.add(audioPlayItem1) val audioPlayItem2 = HwAudioPlayItem() audioPlayItem2.audioId = "1001" audioPlayItem2.singer = "Taoge" audioPlayItem2.onlinePath = "https://lfmusicservice.hwcloudtest.cn:18084/HMS/audio/Taoge-dayu.mp3"//此处Demo使用歌曲示意 audioPlayItem2.setOnline(1) audioPlayItem2.audioTitle = "dayu" playItemList.add(audioPlayItem2) return playItemList }
上述配置添加完成后,就能为展品播放讲解词了。本工程使用的声音音频为线上资源。如果需要播放本地音频,可以参考官网指导。这样,就能导入音频文件,为物品播放声音了。
至此,我们就可以创建一个360°可旋转、放大缩小、带有音效的展览场景了。
最后,除了3D文物展示等应用场景,我们还可以把这些能力应用到很多相关行业,比如:
线上社交领域中的脸萌、视频表情包、视频虚拟背景; 电商购物领域的3D商品展示、家装场景渲染、AR试穿; 影音领域的3D解锁屏保/手机主题、3D特效渲染、直播表情包; 教育领域的3D教学、3D书籍、VR远程教学。
欲了解更多详情,请参阅:
>>华为3D建模服务官网 、 开源仓库
>>华为图形引擎服务官网 、 开源仓库
>>华为音频服务官网 、 开源仓库
>>华为HMS Core官方论坛
>>解决集成问题请到Stack Overflow
点击关注,第一时间了解HMS Core最新技术~

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
怎样编写好的API?
本文分享自百度开发者中心怎样编写好的API? 本文首先阐述了 RESTful 风格 API 的基础理论知识以及 Richardson 成熟度模型,随后讨论了好的 API 应该具有哪些特征,最后对流行的 API 实现方式,即 GraphQL 和 RESTful,进行了对比。 现在,每个人都在关注 API。API 最早开始流行于大约 20 年前,2000 年,Roy Fielding 在他的博士论文中首次提出了 REST 这个术语。同年,Amazon、Salesforce 和 eBay 向全世界的开发者介绍了他们的 API,永远改变了我们构建软件的方式。 在 REST 之前,Roy Fielding 论文中的原则被称为“HTTP 对象模型”,随后你会明白这为何非常重要。 随着阅读的深入,你还会看到如何确定你的 API 是否成熟,好 API 的主要品质是什么以及为何在构建 API 的时候,要注重适应性。 1RESTful 架构基础 REST 代表表述性状态转移(Representational State Transfer),由 Roy Fielding 在他的博士论文中定义,长期以来,它就...
- 下一篇
Scorpio-CSharp v2.2.0 发布,Unity 游戏热更新脚本
Scorpio-CSharp v2.2.0 已经发布,Unity 游戏热更新脚本。 新增功能 支持多变量赋值 示例参考 暂不支持全局变量 Object 增加类函数 getHashCode Object 增加静态函数 referenceEquals 详情查看:https://gitee.com/qingfeng346/Scorpio-CSharp/releases/v2.2.0
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS8安装Docker,最新的服务器搭配容器使用
- CentOS7设置SWAP分区,小内存服务器的救世主
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- CentOS6,CentOS7官方镜像安装Oracle11G
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- SpringBoot2全家桶,快速入门学习开发网站教程