
在上一篇文章中,我已经解释了ARCore是什么以及它如何帮助开发人员在无需了解数学和OpenGL的情况下创建惊人的增强现实应用程序。
如果您还没有阅读它,我强烈建议您继续阅读本文,然后开始开发ARCore应用程序。
开始使用
要开始开发ARCore应用程序,您首先需要向项目添加ARCore支持。 这非常简单,因为我们将使用Android Studio和Sceneform SDK。 Sceneform自动执行两个主要操作:
- 检查ARCore。
- 请求使用相机的权限。
使用Sceneform SDK创建ARCore应用程序时,您无需担心这两个步骤。 您只需要将Sceneform SDK添加到您的项目中即可。
使用一个空的Activity创建一个新的Android Studio项目。
将以下依赖项添加到项目级别的build.gradle
文件中:
dependencies { classpath 'com.google.ar.sceneform:plugin:1.5.0' }
并将此依赖项添加到应用程序级别的build.gradle
文件中:
implementation "com.google.ar.sceneform.ux:sceneform-ux:1.5.0"
现在,将项目与Gradle文件同步,并等待构建完成。 因此,用于Android Studio的Sceneform SDK和Sceneform插件将添加到项目中。 这将允许您查看.sfb
,这些.sfb
是将在相机中渲染的3D模型,还可以帮助您导入,查看和创建3D资源。
创建您的第一个ARCore应用程序
现在,Android Studio设置已完成,并且已经安装了Sceneform SDK,我们可以开始创建第一个ARCore应用程序了。
首先,我们需要在场景中添加一个Sceneform片段。 这就是我们所有3D模型将被放置的所谓场景 。 该片段将负责初始化摄像机并自行处理权限。
转到主布局文件。 就我而言,这是activity_main.xml
文件。 并在其中添加Sceneform片段:
<?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"> <fragment android:name="com.google.ar.sceneform.ux.ArFragment" android:id="@+id/ux_fragment" android:layout_width="match_parent" android:layout_height="match_parent" /> </FrameLayout>
我设置match_parent
的宽度和高度,以使场景全屏显示。 您可以根据需要选择尺寸。
兼容性检查
这是您在布局文件中需要做的所有事情。 现在我们传递给Activity,在我的例子中是MainActivity
。 向活动添加方法:
public static boolean checkIsSupportedDeviceOrFinish(final Activity activity) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { Log.e(TAG, "Sceneform requires Android N or later"); Toast.makeText(activity, "Sceneform requires Android N or later", Toast.LENGTH_LONG).show(); activity.finish(); return false; } String openGlVersionString = ((ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE)) .getDeviceConfigurationInfo() .getGlEsVersion(); if (Double.parseDouble(openGlVersionString) < MIN_OPENGL_VERSION) { Log.e(TAG, "Sceneform requires OpenGL ES 3.0 later"); Toast.makeText(activity, "Sceneform requires OpenGL ES 3.0 or later", Toast.LENGTH_LONG) .show(); activity.finish(); return false; } return true; }
此方法检查您的设备是否支持Sceneform SDK。 该SDK需要Android API级别27或更高以及OpenGL ES 3.0或更高版本。 如果设备不支持这两个参数,则将不会加载场景,并且您的应用程序将显示黑屏。
但是,您仍然可以实现应用程序的所有其他功能,这些功能不需要Sceneform SDK。
检查兼容性后,我们可以创建3D模型并将其附加到场景。
添加资产
现在,您需要将3D模型添加到将在屏幕上显示的项目中。 如果您熟悉创建它们的过程,则可以自己创建这些模型。 或者,您可以转到Poly 。
在那里,您将找到可供选择的庞大3D资源库。 此外,它们可以免费下载。

在Android Studio中,在左窗格中打开您的应用程序文件夹。 您需要一个sampledata文件夹。 该文件夹将包含您的所有3D模型。 在此文件夹中,创建一个包含您的模型名称的文件夹。
在从Poly下载的档案中,您很可能会找到3个文件:
.mtl
文件.obj
文件.png
文件
这三个文件中最重要的是.obj
文件。 这是您的模型。 将所有3个文件放入sampledata->“您的模型文件夹”中 。

现在,右键单击.obj
文件。 第一个选项是Import Sceneform Asset 。 单击它,不更改默认设置,只需在下一个窗口中单击完成 。 之后,将项目与Gradle文件同步。
将在项目中使用的3D资源导入完成。 接下来,让我们在代码中使用3D模型并将其包含在场景中。
模型制作
将以下代码添加到您的活动中,我将逐行进行解释:
private static final String TAG = MainActivity.class.getSimpleName(); private static final double MIN_OPENGL_VERSION = 3.0; ArFragment arFragment; ModelRenderable lampPostRenderable; @Override @SuppressWarnings({"AndroidApiChecker", "FutureReturnValueIgnored"}) protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (!checkIsSupportedDeviceOrFinish(this)) { return; } setContentView(R.layout.activity_main); arFragment = (ArFragment) getSupportFragmentManager().findFragmentById(R.id.ux_fragment); ModelRenderable.builder() .setSource(this, Uri.parse("LampPost.sfb")) .build() .thenAccept(renderable -> lampPostRenderable = renderable) .exceptionally(throwable -> { Toast toast = Toast.makeText(this, "Unable to load andy renderable", Toast.LENGTH_LONG); toast.setGravity(Gravity.CENTER, 0, 0); toast.show(); return null; }); }
首先,我们找到arFragment
,我们先前已将其添加到布局中。 该片段负责场景的存储和操作。 您可以将其想象为我们场景的容器。
接下来,我们使用ModelRenderable
类构建模型。 使用setSource
方法setSource
我们从导入资源时生成的.sfb
文件加载模型。 thenAccept
方法在创建模型后获取模型,然后将加载的模型设置为变量lampPostRenderable
。
对于错误处理,我们有一个exceptionally
方法,如果发生异常,则调用该方法。
所有这些都是异步发生的,因此您不必担心多线程。
现在已经加载了模型并将其保存在lampPostRenderable
变量中,我们将其添加到场景中。
向场景添加模型
我们的场景位于arFragment
,它将接收用户触摸事件。 因此,我们需要为片段安装一个onTap
侦听器,以便处理触摸并将对象放置在需要的位置。 将以下代码添加到onCreate
方法:
arFragment.setOnTapArPlaneListener( (HitResult hitresult, Plane plane, MotionEvent motionevent) -> { if (lampPostRenderable == null){ return; } Anchor anchor = hitresult.createAnchor(); AnchorNode anchorNode = new AnchorNode(anchor); anchorNode.setParent(arFragment.getArSceneView().getScene()); TransformableNode lamp = new TransformableNode(arFragment.getTransformationSystem()); lamp.setParent(anchorNode); lamp.setRenderable(lampPostRenderable); lamp.select(); } );
我们为我们的AR片段设置了onTapArPlaneListener
侦听器。 以下语法用于lambda表达式。 如果您不熟悉它,请查看有关此主题的本小指南 。
首先,我们使用hitresult.createAnchor()
从HitResult
创建锚 ,并将其保存在Anchor
对象中。
然后,我们从该锚点创建一个节点 。 它将被称为AnchorNode
并将使用setParent
方法连接到场景。
接下来,我们创建一个TransformableNode
,它将成为我们的模型,并将其绑定到我们的节点。 TransformableNode
仍然没有任何有关它应显示的对象的信息。 我们将使用setRenderable
方法将此对象传递给它,该方法将ModelRenderable类型的对象作为参数(记住,我们得到了这样的对象并将其命名为lampPostRenderable
?)。 最后,我们调用lamp.select()
方法;
哦! 术语过多。 不用担心,我现在将解释所有内容:
场景 :这是将显示所有3D对象的地方。 该场景位于我们添加到布局的AR片段中。
HitResult :这是一条来自无限远的假想线(或射线),它给出了其与现实世界对象的交点。
锚点 :这是现实世界中的固定位置和方向。 可以理解为三维空间中的坐标(x,y,z)。 姿势是对象在舞台上的位置和方向。 它用于将对象的局部坐标空间转换为真实坐标空间。
锚点节点 :这是一个自动在现实世界中定位的节点。 这是检测到平面时安装的第一个节点。
TransformableNode :这是您可以与之交互的节点。 可以移动,缩放,旋转等。 在此示例中,我们可以缩放对象并旋转它。 因此,名称为可变形。
没有火箭科学。 这确实相对简单。 整个场景可以以图形的形式查看,其中父级为场景,子级为锚节点,然后将其分支为其他各种节点和对象,这些对象将在屏幕上显示。
因此,您的活动应如下所示:
package com.ayusch.arcorefirst; import android.app.Activity; import android.app.ActivityManager; import android.content.Context; import android.net.Uri; import android.os.Build; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.Gravity; import android.view.MotionEvent; import android.widget.Toast; import com.google.ar.core.Anchor; import com.google.ar.core.HitResult; import com.google.ar.core.Plane; import com.google.ar.sceneform.AnchorNode; import com.google.ar.sceneform.rendering.ModelRenderable; import com.google.ar.sceneform.ux.ArFragment; import com.google.ar.sceneform.ux.TransformableNode; public class MainActivity extends AppCompatActivity { private static final String TAG = MainActivity.class.getSimpleName(); private static final double MIN_OPENGL_VERSION = 3.0; ArFragment arFragment; ModelRenderable lampPostRenderable; @Override @SuppressWarnings({"AndroidApiChecker", "FutureReturnValueIgnored"}) protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (!checkIsSupportedDeviceOrFinish(this)) { return; } setContentView(R.layout.activity_main); arFragment = (ArFragment) getSupportFragmentManager().findFragmentById(R.id.ux_fragment); ModelRenderable.builder() .setSource(this, Uri.parse("LampPost.sfb")) .build() .thenAccept(renderable -> lampPostRenderable = renderable) .exceptionally(throwable -> { Toast toast = Toast.makeText(this, "Unable to load andy renderable", Toast.LENGTH_LONG); toast.setGravity(Gravity.CENTER, 0, 0); toast.show(); return null; }); arFragment.setOnTapArPlaneListener( (HitResult hitresult, Plane plane, MotionEvent motionevent) -> { if (lampPostRenderable == null){ return; } Anchor anchor = hitresult.createAnchor(); AnchorNode anchorNode = new AnchorNode(anchor); anchorNode.setParent(arFragment.getArSceneView().getScene()); TransformableNode lamp = new TransformableNode(arFragment.getTransformationSystem()); lamp.setParent(anchorNode); lamp.setRenderable(lampPostRenderable); lamp.select(); } ); } public static boolean checkIsSupportedDeviceOrFinish(final Activity activity) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { Log.e(TAG, "Sceneform requires Android N or later"); Toast.makeText(activity, "Sceneform requires Android N or later", Toast.LENGTH_LONG).show(); activity.finish(); return false; } String openGlVersionString = ((ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE)) .getDeviceConfigurationInfo() .getGlEsVersion(); if (Double.parseDouble(openGlVersionString) < MIN_OPENGL_VERSION) { Log.e(TAG, "Sceneform requires OpenGL ES 3.0 later"); Toast.makeText(activity, "Sceneform requires OpenGL ES 3.0 or later", Toast.LENGTH_LONG) .show(); activity.finish(); return false; } return true; } }
恭喜你! 您刚刚完成了第一个ARCore应用程序的创建。 开始向其中添加对象,您将看到它们如何开始在现实世界中栩栩如生。
这是您第一次了解如何在Android Studio中从头开始创建简单的ARCore应用程序。 在下一课中,我将深入研究ARCore,并为应用程序添加更多功能。