我在 Android 上做了一个 1 : 1 高达

简介: 借助 Sceneform 和 ARCore,仅仅数行代码可以在 Android 上实现一个 1:1 的高达, 效果惊艳!

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

作为高达爱好者,我一直想去现场感受一下真实高达的压迫感,无奈一直没机会成行。不过这难不倒我,我决定自己动手做一个 1:1 高达来体验一番。

借助 AR 技术我实现了这个效果, 怎么样,不比上海金桥的差吧 ~

ezgif.com-gif-maker (9).gif

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

image.png

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

.obj , .fbx.gltf 等常见的 3D 模型文件格式,虽然可以在主流的 3D 软件中通用,但在 Android 中,我们只能通过 OpenGL 代码对其进行渲染。而 Sceneform 可以将这些格式的模型文件,连同所依赖的资源文件(.mtl, .bin, .png 等) 转换为 .sfa.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.17.1' 
}

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

dependencies {
    ...
    implementation 'com.google.ar:core:1.26.0'
    implementation 'com.google.ar.sceneform.ux:sceneform-ux:1.17.1'
    implementation 'com.google.ar.sceneform:core:1.17.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"?>
frameLabelStart--frameLabelEnd 

4. 制作 sfb 模型文件

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

sketchfab_gundam.gif

我们可以在网站上下载常见格式的 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. 加载、渲染模型

//MainActivity.kt

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        arFragment = supportFragmentManager.findFragmentById(R.id.ux_fragment) as ArFragment
        arFragment.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 = renderable
        node.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: ArFragment
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        if (!checkIsSupportedDeviceOrFinish(this)) return
        setContentView(R.layout.activity_main)
        
        arFragment = supportFragmentManager.findFragmentById(R.id.ux_fragment) as ArFragment
        arFragment.setOnTapArPlaneListener { hitresult: HitResult, plane: Plane, motionevent: MotionEvent? ->
            if (plane.type != Plane.Type.HORIZONTAL_UPWARD_FACING)
                return@setOnTapArPlaneListener
            val 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 = renderable
        node.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
                .glEsVersion
        if (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 以上。

以上就是全部代码了,虽然代码很少,效果很哇塞

Screen Shot 2021-09-08 at 6.55.16 AM.png

最后

Sceneform 配合 ARCore 可以快速搭建 AR 应用,除了加载静态的 3D 模型以外,Sceneform 还可以加载带动画的模型。

随着 “元宇宙” 概念的兴起,Google,Facebook 等巨头必将加大在 AR 乃至 VR 技术上的研究投入,虚拟现实技术或将成为移动互联网之后的新一代社交、娱乐场景,想象空间巨大。

今天就写到这里吧, 我要和刚认识的小姐姐玩耍去了 🙈

ezgif.com-gif-maker (11).gif

最后推荐一个网站,大家可以在那里下载一些有趣的 3D 模型 ~

https://sketchfab.com/

(完)


# 文末惊喜来了 !🎉🎉

衷心感谢各位读者大大的关注,欢迎大家就本文内容进行评论和吐槽!🙏🙏

本人将选取最热门的前两条评论用户,送出小礼品:掘金徽章一枚 🏅

  • 热门评论排序规则 :点赞数 + 评论数 (作者本人的评论除外)
  • 统计截止时间: 9月10日 24点

之后我将联系获奖用户寄送礼物,感谢掘金平台对本次活动的大力支持!

目录
相关文章
|
4月前
|
开发框架 前端开发 Android开发
安卓与iOS开发中的跨平台策略
在移动应用开发的战场上,安卓和iOS两大阵营各据一方。随着技术的演进,跨平台开发框架成为开发者的新宠,旨在实现一次编码、多平台部署的梦想。本文将探讨跨平台开发的优势与挑战,并分享实用的开发技巧,帮助开发者在安卓和iOS的世界中游刃有余。
|
27天前
|
JavaScript 搜索推荐 Android开发
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
65 8
【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
|
1月前
|
前端开发 Java Shell
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
179 20
【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
1月前
|
Dart 前端开发 Android开发
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
55 4
【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
|
2月前
|
缓存 前端开发 Android开发
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
111 12
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
|
23天前
|
安全 Android开发 iOS开发
escrcpy:【技术党必看】Android开发,Escrcpy 让你无线投屏新体验!图形界面掌控 Android,30-120fps 超流畅!🔥
escrcpy 是一款基于 Scrcpy 的开源项目,使用 Electron 构建,提供图形化界面来显示和控制 Android 设备。它支持 USB 和 Wi-Fi 连接,帧率可达 30-120fps,延迟低至 35-70ms,启动迅速且画质清晰。escrcpy 拥有丰富的功能,包括自动化任务、多设备管理、反向网络共享、批量操作等,无需注册账号或广告干扰。适用于游戏直播、办公协作和教育演示等多种场景,是一款轻量级、高性能的 Android 控制工具。
|
2月前
|
Dart 前端开发 Android开发
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
43 1
【02】写一个注册页面以及配置打包选项打包安卓apk测试—开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
3月前
|
搜索推荐 前端开发 API
探索安卓开发中的自定义视图:打造个性化用户界面
在安卓应用开发的广阔天地中,自定义视图是一块神奇的画布,让开发者能够突破标准控件的限制,绘制出独一无二的用户界面。本文将带你走进自定义视图的世界,从基础概念到实战技巧,逐步揭示如何在安卓平台上创建和运用自定义视图来提升用户体验。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开新的视野,让你的应用在众多同质化产品中脱颖而出。
85 19
|
3月前
|
JSON Java API
探索安卓开发:打造你的首个天气应用
在这篇技术指南中,我们将一起潜入安卓开发的海洋,学习如何从零开始构建一个简单的天气应用。通过这个实践项目,你将掌握安卓开发的核心概念、界面设计、网络编程以及数据解析等技能。无论你是初学者还是有一定基础的开发者,这篇文章都将为你提供一个清晰的路线图和实用的代码示例,帮助你在安卓开发的道路上迈出坚实的一步。让我们一起开始这段旅程,打造属于你自己的第一个安卓应用吧!
110 14
|
3月前
|
Java Linux 数据库
探索安卓开发:打造你的第一款应用
在数字时代的浪潮中,每个人都有机会成为创意的实现者。本文将带你走进安卓开发的奇妙世界,通过浅显易懂的语言和实际代码示例,引导你从零开始构建自己的第一款安卓应用。无论你是编程新手还是希望拓展技术的开发者,这篇文章都将为你打开一扇门,让你的创意和技术一起飞扬。

热门文章

最新文章

  • 1
    Android历史版本与APK文件结构
  • 2
    【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
  • 3
    【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
  • 4
    【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
  • 5
    【03】微信支付商户申请下户到配置完整流程-微信开放平台创建APP应用-填写上传基础资料-生成安卓证书-获取Apk签名-申请+配置完整流程-优雅草卓伊凡
  • 6
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
  • 7
    Cellebrite UFED 4PC 7.71 (Windows) - Android 和 iOS 移动设备取证软件
  • 8
    escrcpy:【技术党必看】Android开发,Escrcpy 让你无线投屏新体验!图形界面掌控 Android,30-120fps 超流畅!🔥
  • 9
    Android实战经验之Kotlin中快速实现MVI架构
  • 10
    即时通讯安全篇(一):正确地理解和使用Android端加密算法
  • 1
    【03】微信支付商户申请下户到配置完整流程-微信开放平台创建APP应用-填写上传基础资料-生成安卓证书-获取Apk签名-申请+配置完整流程-优雅草卓伊凡
    64
  • 2
    android FragmentManager 删除所有Fragment 重建
    25
  • 3
    Android实战经验之Kotlin中快速实现MVI架构
    41
  • 4
    即时通讯安全篇(一):正确地理解和使用Android端加密算法
    41
  • 5
    escrcpy:【技术党必看】Android开发,Escrcpy 让你无线投屏新体验!图形界面掌控 Android,30-120fps 超流畅!🔥
    46
  • 6
    【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
    156
  • 7
    Cellebrite UFED 4PC 7.71 (Windows) - Android 和 iOS 移动设备取证软件
    53
  • 8
    【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    73
  • 9
    Android历史版本与APK文件结构
    179
  • 10
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    54