最近看到一则新闻,一个 1: 1 的自由高达落户在上海金桥。

作为高达爱好者的我一直想去现场感受一下高达真实的压迫感,无奈一直没机会去上海。不过这难不倒我,借助 AR 技术我自己动手做了一个1:1 的高达

怎么样,这效果不比上海金桥的差吧~

什么是 AR (Augemented Reality)


AR(增强现实)是近几年新兴的技术,他可以将3D模型等虚拟元素模拟仿真后应用到现实世界中,虚拟与现实,两种信息互为补充,从而实现对真实世界的“增强”。

不少人会将 AR(增强现实) 与 VR(虚拟现实)相混淆,两者的区别在于虚拟元素的占比:

  • VR:看到的场景和人物全是假的,是把你的意识代入一个虚拟的世界。
  • AR:看到的场景和人物一部分是真一部分是假,是把虚拟的信息带入到现实世界中。

VR 技术的研究已经有30多年的历史了,而 AR 则年轻得多,随着智能手机以及智能穿戴设备的普及而逐渐被人们熟知。相对于 VR,AR 的开发门槛低得多,只要有一台智能手机,借助 Google 提供的 ARCore,人人都可以开发出自己的 AR 应用。

ARCore 是 Google 提供的 AR 解决方案,为开发者提供 API,可以通过 Android , iOS 等手机平台感知周边环境,打造沉浸式的 AR 体验。

ARCore 为开发者提供了三大能力:

ARCore 能力 示意图
动作追踪
通过识别相机图像中的可视特征点来跟踪拍摄者的位置,从而决定虚拟元素的相对位置变化
环境理解
识别常见水平或垂直表面(如表格或墙壁)上的特征点群集,还可以确定平面边界,将虚拟对象放置在平面上
光线预测
预测当前场景的光照条件,可以使用此照明信息来照亮虚拟 AR 对象

ARCore 为 AR 提供了周边环境的感知能力,但一个完整的 AR 应用还需要处理 3D 模型的渲染,这要借助 OpenGL ES 来完成,学习成本很高。官方意识到这个问题,在 2017 年推出 ARCore 之后,紧跟着 2018 年的 IO 大会上推出了 Sceneform 这个在 Android 上的 3D 图像渲染库。

.obj , .fbx.gltf 等常见的 3D 模型文件格式,虽然可以在主流的 3D 软件中通用,但在 Android 中,我们只能通过 OpenGL 代码对其进行渲染。而 Sceneform 可以将这些格式的模型文件,连同所依赖的资源文件(.mtl, .bin, .png 等) 转换为 .sfb.sfb 格式。 后者是可供 Sceneform 渲染的二进制模型文件, 前者是具有可读性的摘要文件,用来描述后者。

相比于 OpenGL , Sceneform 的使用要简单得多,而且 sfb 还可以通过 Sceneform 提供的 AS 插件在 IDE 中进行模型预览。

接下来,通过 Sceneform 和 ARCore 来实现我的 1:1 高达

1. Gradle 添加依赖


新建 AndroidStudio 工程,在 root 的 build.gradle 中添加 Sceneform 插件

dependencies { classpath 'com.google.ar.sceneform:plugin:1.15.0'
}

接着在 app 的 build.gradle 中依赖 ARCore 和 Sceneform 的 aar

dependencies {...implementation 'com.google.ar:core:1.5.0'implementation 'com.google.ar.sceneform.ux:sceneform-ux:1.5.1'implementation 'com.google.ar.sceneform:core:1.5.1'
}

2. Manifest 申请权限



<uses-permission android:name="android.permission.CAMERA"/><!-- 此 App 在 GooglePlay 中只会对支持 ARCore 的设备可见 -->
<uses-feature android:name="android.hardware.camera.ar" android:required="true"/><application …>…<!-- 当安装 App 时,如果设备没有安装 ARCore,GooglePlay 会自动为其安装 --><meta-data android:name="com.google.ar.core" android:value="required" /></application>

3. 布局文件


ARFragment 可以用来承载 AR 场景、响应用户行为,Android 中显示虚拟元素的最简答的方法就是在布局中添加一个 ARFRagment :

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"><fragmentandroid:id="@+id/ux_fragment"android:name="com.google.ar.sceneform.ux.ArFragment"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="9" /></FrameLayout>

4. 制作 sfb 模型文件


3D 模型一般是通过 Maya 或 3D Max 等专业软件制作的,不少 3D 建模爱好者会将自己的作品上传到一些设计网站供大家免费或有偿下载。

模型下载网站:https://sketchfab.com/

我们可以在网站上下载常见格式的 3D 模型文件。以 .obj 为例,obj 文件中描述了多边形的顶点和片段信息等, 此外还有颜色、材质等信息存储在配套的 .mtl 文件中 , 我们将下载的 obj/mtl/png 等模型文件拷贝到非 assets 目录下,这样可以避免打入 apk。

例如 app/sampledata

我们在 build.gtadle 通过 sceneform.asset(...) 添加 obj > sfb 的配置如下

sceneform.asset('sampledata/msz-006_zeta_gundam/scene.obj','default','sampledata/msz-006_zeta_gundam/scene.sfa','src/main/assets/scene')

sampledata/msz-006_zeta_gundam/scene.obj 是 obj 源文件位置, src/main/assets/scene 是生成的 sfb 目标路径,我们将目标文件生成在 assets/ 中,打入 apk ,便于在运行时加载。

gradle 配置完后,sync 并 build 工程,build 过程中,会在 assets/ 中生成同名 sfb 文件

5. 加载 sfb 模型


//MainActivity.ktoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)arFragment = supportFragmentManager.findFragmentById(R.id.ux_fragment) as ArFragmentarFragment.setOnTapArPlaneListener { hitResult, plane, motionEvent ->if (plane.type != Plane.Type.HORIZONTAL_UPWARD_FACING ||state != AnchorState.NONE) {return@setOnTapArPlaneListener}val anchor = hitResult.createAnchor()placeObject(ux_fragment, anchor, Uri.parse("scene.sfb"))}}

ARFragment 能够响应在 AR 场景中的用户点击行为,在点击的位置中添加虚拟元素,
Uri.parse("scene.sfb") 用来获取 assets 中生成的模型文件。

    private fun placeObject(fragment: ArFragment, anchor: Anchor, model: Uri) {ModelRenderable.builder().setSource(fragment.context, model).build().thenAccept {addNodeToScene(fragment, anchor, it)}.exceptionally { throwable : Throwable ->Toast.makeText(arFragment.getContext(), "Error:$throwable.message", Toast.LENGTH_LONG).show();return@exceptionally null}}

Sceneform 提供 ModelRenderable 用于模型渲染。 通过 setSource 加载 sfb 模型文件

   private fun addNodeToScene(fragment: ArFragment, anchor: Anchor, renderable: Renderable) {val anchorNode = AnchorNode(anchor)val node = TransformableNode(fragment.transformationSystem)node.renderable = renderablenode.setParent(anchorNode)fragment.arSceneView.scene.addChild(anchorNode)node.select()}

ARSceneView 持有一个 Scene, Scene 是一个树形数据结构,作为 AR 场景的根节点,各种虚拟元素将作为其子节点被添加到场景中进行渲染

val node = TransformableNode(fragment.transformationSystem)
node.renderable = renderable
node.setParent(anchorNode)

所以,渲染 3D 模型,其实就是添加一个 Node 并为其设置 Renderable 的过程。

hitResult 是用户点击的位置信息,Anchor基于 hitResult 创建锚点,这个锚点作为子节点被添加到 Scene 根节点中,同时又作为 TransformableNode 的父节点。 TransformableNode 用来承载 3D 模型, 它可以接受手势进行拖拽或者放大缩小, 添加到 Archor 就相当于把 3D 模型放置到点击的位置上。

6. 完整代码


class MainActivity : AppCompatActivity() {lateinit var arFragment: ArFragmentoverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)if (!checkIsSupportedDeviceOrFinish(this)) returnsetContentView(R.layout.activity_main)arFragment = supportFragmentManager.findFragmentById(R.id.ux_fragment) as ArFragmentarFragment.setOnTapArPlaneListener { hitresult: HitResult, plane: Plane, motionevent: MotionEvent? ->if (plane.type != Plane.Type.HORIZONTAL_UPWARD_FACING)return@setOnTapArPlaneListenerval anchor = hitresult.createAnchor()placeObject(arFragment, anchor, R.raw.cube)}}private fun placeObject(arFragment: ArFragment, anchor: Anchor, uri: Int) {ModelRenderable.builder().setSource(arFragment.context, uri).build().thenAccept { modelRenderable: ModelRenderable -> addNodeToScene(arFragment, anchor, modelRenderable) }.exceptionally { throwable: Throwable ->Toast.makeText(arFragment.getContext(), "Error:$throwable.message", Toast.LENGTH_LONG).show();return@exceptionally null}}private fun addNodeToScene(arFragment: ArFragment, anchor: Anchor, renderable: Renderable) {val anchorNode = AnchorNode(anchor)val node = TransformableNode(arFragment.transformationSystem)node.renderable = renderablenode.setParent(anchorNode)arFragment.arSceneView.scene.addChild(anchorNode)node.select()}private fun checkIsSupportedDeviceOrFinish(activity: Activity): Boolean {if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {Toast.makeText(activity, "Sceneform requires Android N or later", Toast.LENGTH_LONG).show()activity.finish()return false}val openGlVersionString = (activity.getSystemService<Any>(Context.ACTIVITY_SERVICE) as ActivityManager).deviceConfigurationInfo.glEsVersionif (openGlVersionString.toDouble() < MIN_OPENGL_VERSION) {Toast.makeText(activity, "Sceneform requires OpenGL ES 3.0 or later", Toast.LENGTH_LONG).show()activity.finish()return false}return true}companion object {private const val MIN_OPENGL_VERSION = 3.0}
}

checkIsSupportedDeviceOrFinish 用来检测可运行环境,通过实现可知Sceneform 的运行条件是 AndroidN 以及 OpenGL 3.0 以上。

以上就是全部代码了,代码很少,效果很酷!

最后


Sceneform 配合 ARCore 可以快速搭建 AR 应用,除了加载静态的 3D 模型以外,Sceneform 也可以加载带动画的模型。随着 “元宇宙” 概念的兴起,Google,Facebook 等巨头必将加大在 AR 乃至 VR 技术上的研究投入,虚拟现实技术或将成为移动互联网之后的一个新的社交、娱乐场景,想象空间十分巨大。

今天就写到这里吧, 我要去跟我的虚拟女友玩耍了,

【Android】我用 ARCore 做了一个 1:1 的高达相关推荐

  1. 用Android Smart Image View做的一个网络图片浏览的Demo

    还是两种方式都写出来,也看看有多smart 1.传统方式从网络上获取图片并显示 首先新建Android Project顺便也在Manifest把网络权限加了 activity_main.xml布局如下 ...

  2. 做了一个系列的Android开发教程列表

    做了一个系列的Android开发教程列表.花了半天多的专题 里面包含了 4个系列的教程. 也包含了很多Android开发资料. 喜欢的人可以收藏哦:http://dev.apkbus.com/

  3. 【Android】最近做的一个Android平台下时间统计工具

    最近在完成实验室的项目之后花了一点时间弄了一个小应用.因为自己也算是手机重度手机依赖患者,平时虽然玩手机时间不长,但是很频繁,所以一直想要知道自己每天打开手机多少次,用了哪些应用,以及每个应用花了多少 ...

  4. android点击按钮弹出图片,用android做的一个简单的点击按钮显示图片的程序

    其实,在这之前我已经做了一个点击按钮的小程序,只不过它只是用来在界面上显示一些文字或者是用一个对话框来显示内容.按理说,做显示图片应该是不会有太大的问题了,可是问题还是来了.在我把这些个问题解决之后, ...

  5. Android等待对话框(做一个带动态效果的对话框)

    又到了动画总结的时间了,今天要总结的是一个对话框形式的动画效果,老样子gif图不太清晰,但是总体的效果是可以看的清楚的,一个动态的等待对话框,我只是简单的实现了一些动画,如果需要更复杂的需求,可以联系 ...

  6. android http通过post请求发送一个xml

    今天,简单讲讲android如何在网络请求时通过post方式发送xml数据. 其实也很简单,不过我之前对网络请求这一块不太熟悉,当需要做这个发送xml数据时,居然不知道怎么做.后来,在网上查找资料,最 ...

  7. android动画view上移,在Android开发中使用View制作一个引导动画

    在Android开发中使用View制作一个引导动画 发布时间:2020-11-20 16:46:16 来源:亿速云 阅读:98 作者:Leah 这篇文章将为大家详细讲解有关在Android开发中使用V ...

  8. 分享一个自己做的一个3DM手机客户端

    <script type="text/javascript" name="baidu-tc-cerfication" data-appid="4 ...

  9. linux i2c 端口 usb,做了一个电容屏的IIC接口转USB

    做了一个电容屏的IIC接口转USB [复制链接] 实现的功能:电容屏的触控芯片一般对外接口为IIC接口,无法在windows/linux等电脑主机上直接使用,通过增加一颗转接芯片实现IIC接口转免驱U ...

  10. android github 多页面程序,论一个APP从启动到主页面显示经历的过程?

    前言 (个人观点.不喜勿喷) 本部分内容是关于Android进阶的一些知识总结,涉及到的知识点比较杂,不过都 是面试中几乎常问的知识点,也是加分的点. 关于这部分内容,可能需要有一些具体的项目实践.在 ...

最新文章

  1. setting an array element with a sequence.
  2. oracle 查看并行数据库,Oracle数据库并行查询出错的解决方法
  3. 2017西安交大ACM小学期数据结构 [分块、二维矩阵]
  4. hdu 4961 Boring Sum(高效)
  5. 前端学习(1877)vue之电商管理系统电商系统之头部布局
  6. 遗传算法及其应用实现
  7. Mysql数据库常用命令,mysql速学实用教程。
  8. 蓝桥杯历届试题 地宫取宝 dp or 记忆化搜索
  9. UVA-10026 Shoemaker's Problem (贪心)
  10. java试卷_Java测试题及答案(Java干货完整试卷)
  11. OpenCL简单入门
  12. 生物信息学在疾病基础研究中的应用
  13. 无刷舵机、普通舵机等舵机的区别
  14. Java Web实现使用浏览器下载文件代码
  15. 上海交通大学计算机专业考研多少分进复试,2019考研:初试分数370+,有希望进上海交通大学么?...
  16. 什么是双机热备?双机热备软件介绍
  17. 手机怎么把图片制作成短视频,原来还有这种傻瓜式的操作,长知识了
  18. 第十七章 OAuth2集成——《跟我学Shiro》
  19. 纯CSS3写的10个不同的酷炫图片遮罩层效果【转】
  20. Christmas Gift圣诞创意衬线字体 for mac

热门文章

  1. HTML5 浏览器大小缩放到一定大小固定页面
  2. Unity导入免费的素材资源
  3. SIM800C的使用心得
  4. Linux编译安装iozone,Fedora下NFS的配置与iozone测试
  5. journalctl
  6. 历年被3.15晚会曝光的科技企业现状
  7. 红米10X/Pro/Note8Pro/Note9/K30U解账户锁详细刷机教程-可登小米账号
  8. 进制转换函数 Java
  9. python---字符串的拼接、去重、反转、字母花样排序、单词出现判断、统计文件特定单词频率lambda、硬盘容量、列表转字符串
  10. CV520国产兼容应用及说明